policy_engine.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/module.h>
  7. #include <linux/platform_device.h>
  8. #include <linux/thermal.h>
  9. #include <linux/err.h>
  10. #include <linux/slab.h>
  11. #include <linux/of.h>
  12. #include <linux/of_address.h>
  13. #include <linux/interrupt.h>
  14. #include "thermal_zone_internal.h"
  15. #define PE_SENS_DRIVER "policy-engine-sensor"
  16. #define PE_INT_ENABLE_OFFSET 0x530
  17. #define PE_STATUS_OFFSET 0x590
  18. #define PE_INT_STATUS_OFFSET 0x620
  19. #define PE_INT_STATUS1_OFFSET 0x630
  20. #define PE_INTR_CFG 0x11000
  21. #define PE_INTR_CLEAR 0x11111
  22. #define PE_STS_CLEAR 0xFFFF
  23. #define PE_READ_MITIGATION_IDX(val) ((val >> 16) & 0x1F)
  24. struct pe_sensor_data {
  25. struct device *dev;
  26. struct thermal_zone_device *tz_dev;
  27. int32_t high_thresh;
  28. int32_t low_thresh;
  29. int32_t irq_num;
  30. void __iomem *regmap;
  31. struct mutex mutex;
  32. };
  33. static int pe_sensor_get_trend(void *data, int trip, enum thermal_trend *trend)
  34. {
  35. struct pe_sensor_data *pe_sens = (struct pe_sensor_data *)data;
  36. struct thermal_zone_device *tz = pe_sens->tz_dev;
  37. int value, last_value;
  38. if (!tz)
  39. return -EINVAL;
  40. value = READ_ONCE(tz->temperature);
  41. last_value = READ_ONCE(tz->last_temperature);
  42. if (!value)
  43. *trend = THERMAL_TREND_DROPPING;
  44. else if (value > last_value)
  45. *trend = THERMAL_TREND_RAISING;
  46. else if (value < last_value)
  47. *trend = THERMAL_TREND_DROPPING;
  48. else
  49. *trend = THERMAL_TREND_STABLE;
  50. return 0;
  51. }
  52. static int fetch_mitigation_table_idx(struct pe_sensor_data *pe_sens, int *temp)
  53. {
  54. u32 data = 0;
  55. data = readl_relaxed(pe_sens->regmap + PE_STATUS_OFFSET);
  56. *temp = PE_READ_MITIGATION_IDX(data);
  57. dev_dbg(pe_sens->dev, "PE data:%d index:%d\n", data, *temp);
  58. return 0;
  59. }
  60. static int pe_sensor_read(void *data, int *temp)
  61. {
  62. struct pe_sensor_data *pe_sens = (struct pe_sensor_data *)data;
  63. return fetch_mitigation_table_idx(pe_sens, temp);
  64. }
  65. static int pe_sensor_set_trips(void *data, int low, int high)
  66. {
  67. struct pe_sensor_data *pe_sens = (struct pe_sensor_data *)data;
  68. mutex_lock(&pe_sens->mutex);
  69. if (pe_sens->high_thresh == high &&
  70. pe_sens->low_thresh == low)
  71. goto unlock_exit;
  72. pe_sens->high_thresh = high;
  73. pe_sens->low_thresh = low;
  74. dev_dbg(pe_sens->dev, "PE rail set trip. high:%d low:%d\n",
  75. high, low);
  76. unlock_exit:
  77. mutex_unlock(&pe_sens->mutex);
  78. return 0;
  79. }
  80. static struct thermal_zone_of_device_ops pe_sensor_ops = {
  81. .get_temp = pe_sensor_read,
  82. .set_trips = pe_sensor_set_trips,
  83. .get_trend = pe_sensor_get_trend,
  84. };
  85. static irqreturn_t pe_handle_irq(int irq, void *data)
  86. {
  87. struct pe_sensor_data *pe_sens = (struct pe_sensor_data *)data;
  88. int val = 0, ret = 0;
  89. writel_relaxed(PE_INTR_CLEAR, pe_sens->regmap + PE_INT_STATUS_OFFSET);
  90. writel_relaxed(PE_STS_CLEAR, pe_sens->regmap + PE_INT_STATUS1_OFFSET);
  91. ret = fetch_mitigation_table_idx(pe_sens, &val);
  92. if (ret)
  93. return IRQ_HANDLED;
  94. mutex_lock(&pe_sens->mutex);
  95. dev_dbg(pe_sens->dev, "Policy Engine interrupt fired value:%d\n", val);
  96. if (pe_sens->tz_dev && (val >= pe_sens->high_thresh ||
  97. val <= pe_sens->low_thresh)) {
  98. mutex_unlock(&pe_sens->mutex);
  99. thermal_zone_device_update(pe_sens->tz_dev,
  100. THERMAL_TRIP_VIOLATED);
  101. } else
  102. mutex_unlock(&pe_sens->mutex);
  103. return IRQ_HANDLED;
  104. }
  105. static int pe_sens_device_probe(struct platform_device *pdev)
  106. {
  107. struct device *dev = &pdev->dev;
  108. int ret = 0;
  109. struct pe_sensor_data *pe_sens;
  110. struct resource *res;
  111. pe_sens = devm_kzalloc(dev, sizeof(*pe_sens), GFP_KERNEL);
  112. if (!pe_sens)
  113. return -ENOMEM;
  114. pe_sens->dev = dev;
  115. pe_sens->high_thresh = INT_MAX;
  116. pe_sens->low_thresh = INT_MIN;
  117. mutex_init(&pe_sens->mutex);
  118. dev_set_drvdata(dev, pe_sens);
  119. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  120. if (!res) {
  121. dev_err(dev, "Couldn't get MEM resource\n");
  122. return -EINVAL;
  123. }
  124. dev_dbg(dev, "pe@0x%x size:%d\n", res->start,
  125. resource_size(res));
  126. pe_sens->regmap = devm_ioremap_resource(dev, res);
  127. if (!pe_sens->regmap) {
  128. dev_err(dev, "Couldn't get regmap\n");
  129. return -EINVAL;
  130. }
  131. pe_sens->irq_num = platform_get_irq(pdev, 0);
  132. if (pe_sens->irq_num < 0) {
  133. dev_err(dev, "Couldn't get irq number\n");
  134. return pe_sens->irq_num;
  135. }
  136. pe_sens->tz_dev = devm_thermal_zone_of_sensor_register(
  137. dev, 0, pe_sens, &pe_sensor_ops);
  138. if (IS_ERR_OR_NULL(pe_sens->tz_dev)) {
  139. ret = PTR_ERR(pe_sens->tz_dev);
  140. if (ret != -ENODEV)
  141. dev_err(dev, "sensor register failed. ret:%d\n", ret);
  142. pe_sens->tz_dev = NULL;
  143. return ret;
  144. }
  145. qti_update_tz_ops(pe_sens->tz_dev, true);
  146. writel_relaxed(PE_INTR_CFG, pe_sens->regmap + PE_INT_ENABLE_OFFSET);
  147. writel_relaxed(PE_INTR_CLEAR, pe_sens->regmap + PE_INT_STATUS_OFFSET);
  148. writel_relaxed(PE_STS_CLEAR, pe_sens->regmap + PE_INT_STATUS1_OFFSET);
  149. ret = devm_request_threaded_irq(dev, pe_sens->irq_num, NULL,
  150. pe_handle_irq,
  151. IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
  152. dev_name(dev), pe_sens);
  153. if (ret) {
  154. dev_err(dev, "Couldn't get irq registered\n");
  155. thermal_zone_of_sensor_unregister(pe_sens->dev,
  156. pe_sens->tz_dev);
  157. return ret;
  158. }
  159. enable_irq_wake(pe_sens->irq_num);
  160. dev_dbg(dev, "PE sensor register success\n");
  161. return 0;
  162. }
  163. static int pe_sens_device_remove(struct platform_device *pdev)
  164. {
  165. struct pe_sensor_data *pe_sens =
  166. (struct pe_sensor_data *)dev_get_drvdata(&pdev->dev);
  167. thermal_zone_of_sensor_unregister(pe_sens->dev, pe_sens->tz_dev);
  168. qti_update_tz_ops(pe_sens->tz_dev, false);
  169. return 0;
  170. }
  171. static const struct of_device_id pe_sens_device_match[] = {
  172. {.compatible = "qcom,policy-engine"},
  173. {}
  174. };
  175. static struct platform_driver pe_sens_device_driver = {
  176. .probe = pe_sens_device_probe,
  177. .remove = pe_sens_device_remove,
  178. .driver = {
  179. .name = PE_SENS_DRIVER,
  180. .of_match_table = pe_sens_device_match,
  181. },
  182. };
  183. module_platform_driver(pe_sens_device_driver);
  184. MODULE_LICENSE("GPL");