max77620_thermal.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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(struct thermal_zone_device *tz, int *temp)
  43. {
  44. struct max77620_therm_info *mtherm = thermal_zone_device_priv(tz);
  45. unsigned int val;
  46. int ret;
  47. ret = regmap_read(mtherm->rmap, MAX77620_REG_STATLBT, &val);
  48. if (ret < 0)
  49. return ret;
  50. if (val & MAX77620_IRQ_TJALRM2_MASK)
  51. *temp = MAX77620_TJALARM2_TEMP;
  52. else if (val & MAX77620_IRQ_TJALRM1_MASK)
  53. *temp = MAX77620_TJALARM1_TEMP;
  54. else
  55. *temp = MAX77620_NORMAL_OPERATING_TEMP;
  56. return 0;
  57. }
  58. static const struct thermal_zone_device_ops max77620_thermal_ops = {
  59. .get_temp = max77620_thermal_read_temp,
  60. };
  61. static irqreturn_t max77620_thermal_irq(int irq, void *data)
  62. {
  63. struct max77620_therm_info *mtherm = data;
  64. if (irq == mtherm->irq_tjalarm1)
  65. dev_warn(mtherm->dev, "Junction Temp Alarm1(120C) occurred\n");
  66. else if (irq == mtherm->irq_tjalarm2)
  67. dev_crit(mtherm->dev, "Junction Temp Alarm2(140C) occurred\n");
  68. thermal_zone_device_update(mtherm->tz_device,
  69. THERMAL_EVENT_UNSPECIFIED);
  70. return IRQ_HANDLED;
  71. }
  72. static int max77620_thermal_probe(struct platform_device *pdev)
  73. {
  74. struct max77620_therm_info *mtherm;
  75. int ret;
  76. mtherm = devm_kzalloc(&pdev->dev, sizeof(*mtherm), GFP_KERNEL);
  77. if (!mtherm)
  78. return -ENOMEM;
  79. mtherm->irq_tjalarm1 = platform_get_irq(pdev, 0);
  80. mtherm->irq_tjalarm2 = platform_get_irq(pdev, 1);
  81. if ((mtherm->irq_tjalarm1 < 0) || (mtherm->irq_tjalarm2 < 0)) {
  82. dev_err(&pdev->dev, "Alarm irq number not available\n");
  83. return -EINVAL;
  84. }
  85. mtherm->dev = &pdev->dev;
  86. mtherm->rmap = dev_get_regmap(pdev->dev.parent, NULL);
  87. if (!mtherm->rmap) {
  88. dev_err(&pdev->dev, "Failed to get parent regmap\n");
  89. return -ENODEV;
  90. }
  91. /*
  92. * The reference taken to the parent's node which will be balanced on
  93. * reprobe or on platform-device release.
  94. */
  95. device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
  96. mtherm->tz_device = devm_thermal_of_zone_register(&pdev->dev, 0,
  97. mtherm, &max77620_thermal_ops);
  98. if (IS_ERR(mtherm->tz_device))
  99. return PTR_ERR(mtherm->tz_device);
  100. ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm1, NULL,
  101. max77620_thermal_irq,
  102. IRQF_ONESHOT | IRQF_SHARED,
  103. dev_name(&pdev->dev), mtherm);
  104. if (ret < 0) {
  105. dev_err(&pdev->dev, "Failed to request irq1: %d\n", ret);
  106. return ret;
  107. }
  108. ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm2, NULL,
  109. max77620_thermal_irq,
  110. IRQF_ONESHOT | IRQF_SHARED,
  111. dev_name(&pdev->dev), mtherm);
  112. if (ret < 0) {
  113. dev_err(&pdev->dev, "Failed to request irq2: %d\n", ret);
  114. return ret;
  115. }
  116. return 0;
  117. }
  118. static struct platform_device_id max77620_thermal_devtype[] = {
  119. { .name = "max77620-thermal", },
  120. {},
  121. };
  122. MODULE_DEVICE_TABLE(platform, max77620_thermal_devtype);
  123. static struct platform_driver max77620_thermal_driver = {
  124. .driver = {
  125. .name = "max77620-thermal",
  126. },
  127. .probe = max77620_thermal_probe,
  128. .id_table = max77620_thermal_devtype,
  129. };
  130. module_platform_driver(max77620_thermal_driver);
  131. MODULE_DESCRIPTION("Max77620 Junction temperature Thermal driver");
  132. MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
  133. MODULE_AUTHOR("Mallikarjun Kasoju <mkasoju@nvidia.com>");
  134. MODULE_LICENSE("GPL v2");