max77620_thermal.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Junction temperature thermal driver for Maxim Max77620.
  4. *
  5. * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
  6. *
  7. * Author: Laxman Dewangan <ldewangan@nvidia.com>
  8. * Mallikarjun Kasoju <mkasoju@nvidia.com>
  9. */
  10. #include <linux/irq.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/mfd/max77620.h>
  13. #include <linux/module.h>
  14. #include <linux/of.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/regmap.h>
  17. #include <linux/slab.h>
  18. #include <linux/thermal.h>
  19. #define MAX77620_NORMAL_OPERATING_TEMP 100000
  20. #define MAX77620_TJALARM1_TEMP 120000
  21. #define MAX77620_TJALARM2_TEMP 140000
  22. struct max77620_therm_info {
  23. struct device *dev;
  24. struct regmap *rmap;
  25. struct thermal_zone_device *tz_device;
  26. int irq_tjalarm1;
  27. int irq_tjalarm2;
  28. };
  29. /**
  30. * max77620_thermal_read_temp: Read PMIC die temperatue.
  31. * @data: Device specific data.
  32. * @temp: Temperature in millidegrees Celsius
  33. *
  34. * The actual temperature of PMIC die is not available from PMIC.
  35. * PMIC only tells the status if it has crossed or not the threshold level
  36. * of 120degC or 140degC.
  37. * If threshold has not been crossed then assume die temperature as 100degC
  38. * else 120degC or 140deG based on the PMIC die temp threshold status.
  39. *
  40. * Return 0 on success otherwise error number to show reason of failure.
  41. */
  42. static int max77620_thermal_read_temp(void *data, int *temp)
  43. {
  44. struct max77620_therm_info *mtherm = data;
  45. unsigned int val;
  46. int ret;
  47. ret = regmap_read(mtherm->rmap, MAX77620_REG_STATLBT, &val);
  48. if (ret < 0) {
  49. dev_err(mtherm->dev, "Failed to read STATLBT: %d\n", ret);
  50. return ret;
  51. }
  52. if (val & MAX77620_IRQ_TJALRM2_MASK)
  53. *temp = MAX77620_TJALARM2_TEMP;
  54. else if (val & MAX77620_IRQ_TJALRM1_MASK)
  55. *temp = MAX77620_TJALARM1_TEMP;
  56. else
  57. *temp = MAX77620_NORMAL_OPERATING_TEMP;
  58. return 0;
  59. }
  60. static const struct thermal_zone_of_device_ops max77620_thermal_ops = {
  61. .get_temp = max77620_thermal_read_temp,
  62. };
  63. static irqreturn_t max77620_thermal_irq(int irq, void *data)
  64. {
  65. struct max77620_therm_info *mtherm = data;
  66. if (irq == mtherm->irq_tjalarm1)
  67. dev_warn(mtherm->dev, "Junction Temp Alarm1(120C) occurred\n");
  68. else if (irq == mtherm->irq_tjalarm2)
  69. dev_crit(mtherm->dev, "Junction Temp Alarm2(140C) occurred\n");
  70. thermal_zone_device_update(mtherm->tz_device,
  71. THERMAL_EVENT_UNSPECIFIED);
  72. return IRQ_HANDLED;
  73. }
  74. static int max77620_thermal_probe(struct platform_device *pdev)
  75. {
  76. struct max77620_therm_info *mtherm;
  77. int ret;
  78. mtherm = devm_kzalloc(&pdev->dev, sizeof(*mtherm), GFP_KERNEL);
  79. if (!mtherm)
  80. return -ENOMEM;
  81. mtherm->irq_tjalarm1 = platform_get_irq(pdev, 0);
  82. mtherm->irq_tjalarm2 = platform_get_irq(pdev, 1);
  83. if ((mtherm->irq_tjalarm1 < 0) || (mtherm->irq_tjalarm2 < 0)) {
  84. dev_err(&pdev->dev, "Alarm irq number not available\n");
  85. return -EINVAL;
  86. }
  87. mtherm->dev = &pdev->dev;
  88. mtherm->rmap = dev_get_regmap(pdev->dev.parent, NULL);
  89. if (!mtherm->rmap) {
  90. dev_err(&pdev->dev, "Failed to get parent regmap\n");
  91. return -ENODEV;
  92. }
  93. /*
  94. * The reference taken to the parent's node which will be balanced on
  95. * reprobe or on platform-device release.
  96. */
  97. device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
  98. mtherm->tz_device = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
  99. mtherm, &max77620_thermal_ops);
  100. if (IS_ERR(mtherm->tz_device)) {
  101. ret = PTR_ERR(mtherm->tz_device);
  102. dev_err(&pdev->dev, "Failed to register thermal zone: %d\n",
  103. ret);
  104. return ret;
  105. }
  106. ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm1, NULL,
  107. max77620_thermal_irq,
  108. IRQF_ONESHOT | IRQF_SHARED,
  109. dev_name(&pdev->dev), mtherm);
  110. if (ret < 0) {
  111. dev_err(&pdev->dev, "Failed to request irq1: %d\n", ret);
  112. return ret;
  113. }
  114. ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm2, NULL,
  115. max77620_thermal_irq,
  116. IRQF_ONESHOT | IRQF_SHARED,
  117. dev_name(&pdev->dev), mtherm);
  118. if (ret < 0) {
  119. dev_err(&pdev->dev, "Failed to request irq2: %d\n", ret);
  120. return ret;
  121. }
  122. platform_set_drvdata(pdev, mtherm);
  123. return 0;
  124. }
  125. static struct platform_device_id max77620_thermal_devtype[] = {
  126. { .name = "max77620-thermal", },
  127. {},
  128. };
  129. MODULE_DEVICE_TABLE(platform, max77620_thermal_devtype);
  130. static struct platform_driver max77620_thermal_driver = {
  131. .driver = {
  132. .name = "max77620-thermal",
  133. },
  134. .probe = max77620_thermal_probe,
  135. .id_table = max77620_thermal_devtype,
  136. };
  137. module_platform_driver(max77620_thermal_driver);
  138. MODULE_DESCRIPTION("Max77620 Junction temperature Thermal driver");
  139. MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
  140. MODULE_AUTHOR("Mallikarjun Kasoju <mkasoju@nvidia.com>");
  141. MODULE_LICENSE("GPL v2");