intel_soc_dts_iosf.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * intel_soc_dts_iosf.c
  4. * Copyright (c) 2015, Intel Corporation.
  5. */
  6. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  7. #include <linux/bitops.h>
  8. #include <linux/intel_tcc.h>
  9. #include <linux/module.h>
  10. #include <linux/slab.h>
  11. #include <linux/interrupt.h>
  12. #include <asm/iosf_mbi.h>
  13. #include "intel_soc_dts_iosf.h"
  14. #define SOC_DTS_OFFSET_ENABLE 0xB0
  15. #define SOC_DTS_OFFSET_TEMP 0xB1
  16. #define SOC_DTS_OFFSET_PTPS 0xB2
  17. #define SOC_DTS_OFFSET_PTTS 0xB3
  18. #define SOC_DTS_OFFSET_PTTSS 0xB4
  19. #define SOC_DTS_OFFSET_PTMC 0x80
  20. #define SOC_DTS_TE_AUX0 0xB5
  21. #define SOC_DTS_TE_AUX1 0xB6
  22. #define SOC_DTS_AUX0_ENABLE_BIT BIT(0)
  23. #define SOC_DTS_AUX1_ENABLE_BIT BIT(1)
  24. #define SOC_DTS_CPU_MODULE0_ENABLE_BIT BIT(16)
  25. #define SOC_DTS_CPU_MODULE1_ENABLE_BIT BIT(17)
  26. #define SOC_DTS_TE_SCI_ENABLE BIT(9)
  27. #define SOC_DTS_TE_SMI_ENABLE BIT(10)
  28. #define SOC_DTS_TE_MSI_ENABLE BIT(11)
  29. #define SOC_DTS_TE_APICA_ENABLE BIT(14)
  30. #define SOC_DTS_PTMC_APIC_DEASSERT_BIT BIT(4)
  31. /* DTS encoding for TJ MAX temperature */
  32. #define SOC_DTS_TJMAX_ENCODING 0x7F
  33. /* Mask for two trips in status bits */
  34. #define SOC_DTS_TRIP_MASK 0x03
  35. static int update_trip_temp(struct intel_soc_dts_sensors *sensors,
  36. int thres_index, int temp)
  37. {
  38. int status;
  39. u32 temp_out;
  40. u32 out;
  41. unsigned long update_ptps;
  42. u32 store_ptps;
  43. u32 store_ptmc;
  44. u32 store_te_out;
  45. u32 te_out;
  46. u32 int_enable_bit = SOC_DTS_TE_APICA_ENABLE;
  47. if (sensors->intr_type == INTEL_SOC_DTS_INTERRUPT_MSI)
  48. int_enable_bit |= SOC_DTS_TE_MSI_ENABLE;
  49. temp_out = (sensors->tj_max - temp) / 1000;
  50. status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
  51. SOC_DTS_OFFSET_PTPS, &store_ptps);
  52. if (status)
  53. return status;
  54. update_ptps = store_ptps;
  55. bitmap_set_value8(&update_ptps, temp_out & 0xFF, thres_index * 8);
  56. out = update_ptps;
  57. status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
  58. SOC_DTS_OFFSET_PTPS, out);
  59. if (status)
  60. return status;
  61. pr_debug("update_trip_temp PTPS = %x\n", out);
  62. status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
  63. SOC_DTS_OFFSET_PTMC, &out);
  64. if (status)
  65. goto err_restore_ptps;
  66. store_ptmc = out;
  67. status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
  68. SOC_DTS_TE_AUX0 + thres_index,
  69. &te_out);
  70. if (status)
  71. goto err_restore_ptmc;
  72. store_te_out = te_out;
  73. /* Enable for CPU module 0 and module 1 */
  74. out |= (SOC_DTS_CPU_MODULE0_ENABLE_BIT |
  75. SOC_DTS_CPU_MODULE1_ENABLE_BIT);
  76. if (temp) {
  77. if (thres_index)
  78. out |= SOC_DTS_AUX1_ENABLE_BIT;
  79. else
  80. out |= SOC_DTS_AUX0_ENABLE_BIT;
  81. te_out |= int_enable_bit;
  82. } else {
  83. if (thres_index)
  84. out &= ~SOC_DTS_AUX1_ENABLE_BIT;
  85. else
  86. out &= ~SOC_DTS_AUX0_ENABLE_BIT;
  87. te_out &= ~int_enable_bit;
  88. }
  89. status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
  90. SOC_DTS_OFFSET_PTMC, out);
  91. if (status)
  92. goto err_restore_te_out;
  93. status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
  94. SOC_DTS_TE_AUX0 + thres_index,
  95. te_out);
  96. if (status)
  97. goto err_restore_te_out;
  98. return 0;
  99. err_restore_te_out:
  100. iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
  101. SOC_DTS_OFFSET_PTMC, store_te_out);
  102. err_restore_ptmc:
  103. iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
  104. SOC_DTS_OFFSET_PTMC, store_ptmc);
  105. err_restore_ptps:
  106. iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
  107. SOC_DTS_OFFSET_PTPS, store_ptps);
  108. /* Nothing we can do if restore fails */
  109. return status;
  110. }
  111. static int sys_set_trip_temp(struct thermal_zone_device *tzd,
  112. const struct thermal_trip *trip,
  113. int temp)
  114. {
  115. struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd);
  116. struct intel_soc_dts_sensors *sensors = dts->sensors;
  117. unsigned int trip_index = THERMAL_TRIP_PRIV_TO_INT(trip->priv);
  118. int status;
  119. if (temp > sensors->tj_max)
  120. return -EINVAL;
  121. mutex_lock(&sensors->dts_update_lock);
  122. status = update_trip_temp(sensors, trip_index, temp);
  123. mutex_unlock(&sensors->dts_update_lock);
  124. return status;
  125. }
  126. static int sys_get_curr_temp(struct thermal_zone_device *tzd,
  127. int *temp)
  128. {
  129. int status;
  130. u32 out;
  131. struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd);
  132. struct intel_soc_dts_sensors *sensors;
  133. unsigned long raw;
  134. sensors = dts->sensors;
  135. status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
  136. SOC_DTS_OFFSET_TEMP, &out);
  137. if (status)
  138. return status;
  139. raw = out;
  140. out = bitmap_get_value8(&raw, dts->id * 8) - SOC_DTS_TJMAX_ENCODING;
  141. *temp = sensors->tj_max - out * 1000;
  142. return 0;
  143. }
  144. static const struct thermal_zone_device_ops tzone_ops = {
  145. .get_temp = sys_get_curr_temp,
  146. .set_trip_temp = sys_set_trip_temp,
  147. };
  148. static int soc_dts_enable(int id)
  149. {
  150. u32 out;
  151. int ret;
  152. ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
  153. SOC_DTS_OFFSET_ENABLE, &out);
  154. if (ret)
  155. return ret;
  156. if (!(out & BIT(id))) {
  157. out |= BIT(id);
  158. ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
  159. SOC_DTS_OFFSET_ENABLE, out);
  160. if (ret)
  161. return ret;
  162. }
  163. return ret;
  164. }
  165. static void remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry *dts)
  166. {
  167. iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
  168. SOC_DTS_OFFSET_ENABLE, dts->store_status);
  169. thermal_zone_device_unregister(dts->tzone);
  170. }
  171. static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts,
  172. struct thermal_trip *trips)
  173. {
  174. char name[10];
  175. u32 store_ptps;
  176. int ret;
  177. /* Store status to restor on exit */
  178. ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
  179. SOC_DTS_OFFSET_ENABLE, &dts->store_status);
  180. if (ret)
  181. goto err_ret;
  182. dts->id = id;
  183. /* Check if the writable trip we provide is not used by BIOS */
  184. ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
  185. SOC_DTS_OFFSET_PTPS, &store_ptps);
  186. if (!ret) {
  187. int i;
  188. for (i = 0; i <= 1; i++) {
  189. if (store_ptps & (0xFFU << i * 8))
  190. trips[i].flags &= ~THERMAL_TRIP_FLAG_RW_TEMP;
  191. }
  192. }
  193. snprintf(name, sizeof(name), "soc_dts%d", id);
  194. dts->tzone = thermal_zone_device_register_with_trips(name, trips,
  195. SOC_MAX_DTS_TRIPS,
  196. dts, &tzone_ops,
  197. NULL, 0, 0);
  198. if (IS_ERR(dts->tzone)) {
  199. ret = PTR_ERR(dts->tzone);
  200. goto err_ret;
  201. }
  202. ret = thermal_zone_device_enable(dts->tzone);
  203. if (ret)
  204. goto err_enable;
  205. ret = soc_dts_enable(id);
  206. if (ret)
  207. goto err_enable;
  208. return 0;
  209. err_enable:
  210. thermal_zone_device_unregister(dts->tzone);
  211. err_ret:
  212. return ret;
  213. }
  214. void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors)
  215. {
  216. u32 sticky_out;
  217. int status;
  218. u32 ptmc_out;
  219. unsigned long flags;
  220. spin_lock_irqsave(&sensors->intr_notify_lock, flags);
  221. status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
  222. SOC_DTS_OFFSET_PTMC, &ptmc_out);
  223. ptmc_out |= SOC_DTS_PTMC_APIC_DEASSERT_BIT;
  224. status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
  225. SOC_DTS_OFFSET_PTMC, ptmc_out);
  226. status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
  227. SOC_DTS_OFFSET_PTTSS, &sticky_out);
  228. pr_debug("status %d PTTSS %x\n", status, sticky_out);
  229. if (sticky_out & SOC_DTS_TRIP_MASK) {
  230. int i;
  231. /* reset sticky bit */
  232. status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
  233. SOC_DTS_OFFSET_PTTSS, sticky_out);
  234. spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
  235. for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
  236. pr_debug("TZD update for zone %d\n", i);
  237. thermal_zone_device_update(sensors->soc_dts[i].tzone,
  238. THERMAL_EVENT_UNSPECIFIED);
  239. }
  240. } else
  241. spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
  242. }
  243. EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_interrupt_handler);
  244. static void dts_trips_reset(struct intel_soc_dts_sensors *sensors, int dts_index)
  245. {
  246. update_trip_temp(sensors, 0, 0);
  247. update_trip_temp(sensors, 1, 0);
  248. }
  249. static void set_trip(struct thermal_trip *trip, enum thermal_trip_type type,
  250. u8 flags, int temp, unsigned int index)
  251. {
  252. trip->type = type;
  253. trip->flags = flags;
  254. trip->temperature = temp;
  255. trip->priv = THERMAL_INT_TO_TRIP_PRIV(index);
  256. }
  257. struct intel_soc_dts_sensors *
  258. intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type,
  259. bool critical_trip, int crit_offset)
  260. {
  261. struct thermal_trip trips[SOC_MAX_DTS_SENSORS][SOC_MAX_DTS_TRIPS] = { 0 };
  262. struct intel_soc_dts_sensors *sensors;
  263. int tj_max;
  264. int ret;
  265. int i;
  266. if (!iosf_mbi_available())
  267. return ERR_PTR(-ENODEV);
  268. tj_max = intel_tcc_get_tjmax(-1);
  269. if (tj_max < 0)
  270. return ERR_PTR(tj_max);
  271. sensors = kzalloc_obj(*sensors);
  272. if (!sensors)
  273. return ERR_PTR(-ENOMEM);
  274. spin_lock_init(&sensors->intr_notify_lock);
  275. mutex_init(&sensors->dts_update_lock);
  276. sensors->intr_type = intr_type;
  277. sensors->tj_max = tj_max * 1000;
  278. for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
  279. int temp;
  280. sensors->soc_dts[i].sensors = sensors;
  281. set_trip(&trips[i][0], THERMAL_TRIP_PASSIVE,
  282. THERMAL_TRIP_FLAG_RW_TEMP, 0, 0);
  283. ret = update_trip_temp(sensors, 0, 0);
  284. if (ret)
  285. goto err_reset_trips;
  286. if (critical_trip) {
  287. temp = sensors->tj_max - crit_offset;
  288. set_trip(&trips[i][1], THERMAL_TRIP_CRITICAL, 0, temp, 1);
  289. } else {
  290. set_trip(&trips[i][1], THERMAL_TRIP_PASSIVE,
  291. THERMAL_TRIP_FLAG_RW_TEMP, 0, 1);
  292. temp = 0;
  293. }
  294. ret = update_trip_temp(sensors, 1, temp);
  295. if (ret)
  296. goto err_reset_trips;
  297. }
  298. for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
  299. ret = add_dts_thermal_zone(i, &sensors->soc_dts[i], trips[i]);
  300. if (ret)
  301. goto err_remove_zone;
  302. }
  303. return sensors;
  304. err_remove_zone:
  305. for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i)
  306. remove_dts_thermal_zone(&sensors->soc_dts[i]);
  307. err_reset_trips:
  308. for (i = 0; i < SOC_MAX_DTS_SENSORS; i++)
  309. dts_trips_reset(sensors, i);
  310. kfree(sensors);
  311. return ERR_PTR(ret);
  312. }
  313. EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_init);
  314. void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors)
  315. {
  316. int i;
  317. for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
  318. remove_dts_thermal_zone(&sensors->soc_dts[i]);
  319. dts_trips_reset(sensors, i);
  320. }
  321. kfree(sensors);
  322. }
  323. EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit);
  324. MODULE_IMPORT_NS("INTEL_TCC");
  325. MODULE_LICENSE("GPL v2");
  326. MODULE_DESCRIPTION("SoC DTS driver using side band interface");