Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux

Pull thermal management updates from Zhang Rui:
"There are not too many changes this time, except two new platform
thermal drivers, ti-soc-thermal driver and x86_pkg_temp_thermal
driver, and a couple of small fixes.

Highlights:

- move the ti-soc-thermal driver out of the staging tree to the
thermal tree.

- introduce the x86_pkg_temp_thermal driver. This driver registers
CPU digital temperature package level sensor as a thermal zone.

- small fixes/cleanups including removing redundant use of
platform_set_drvdata() and of_match_ptr for all platform thermal
drivers"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (34 commits)
thermal: cpu_cooling: fix stub function
thermal: ti-soc-thermal: use standard GPIO DT bindings
thermal: MAINTAINERS: Add git tree path for SoC specific updates
thermal: fix x86_pkg_temp_thermal.c build and Kconfig
Thermal: Documentation for x86 package temperature thermal driver
Thermal: CPU Package temperature thermal
thermal: consider emul_temperature while computing trend
thermal: ti-soc-thermal: add DT example for DRA752 chip
thermal: ti-soc-thermal: add dra752 chip to device table
thermal: ti-soc-thermal: add thermal data for DRA752 chips
thermal: ti-soc-thermal: remove usage of IS_ERR_OR_NULL
thermal: ti-soc-thermal: freeze FSM while computing trend
thermal: ti-soc-thermal: remove external heat while extrapolating hotspot
thermal: ti-soc-thermal: update DT reference for OMAP5430
x86, mcheck, therm_throt: Process package thresholds
thermal: cpu_cooling: fix 'descend' check in get_property()
Thermal: spear: Remove redundant use of of_match_ptr
Thermal: kirkwood: Remove redundant use of of_match_ptr
Thermal: dove: Remove redundant use of of_match_ptr
Thermal: armada: Remove redundant use of of_match_ptr
...

+1627 -83
+47
Documentation/thermal/x86_pkg_temperature_thermal
··· 1 + Kernel driver: x86_pkg_temp_thermal 2 + =================== 3 + 4 + Supported chips: 5 + * x86: with package level thermal management 6 + (Verify using: CPUID.06H:EAX[bit 6] =1) 7 + 8 + Authors: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> 9 + 10 + Reference 11 + --- 12 + Intel® 64 and IA-32 Architectures Software Developer’s Manual (Jan, 2013): 13 + Chapter 14.6: PACKAGE LEVEL THERMAL MANAGEMENT 14 + 15 + Description 16 + --------- 17 + 18 + This driver register CPU digital temperature package level sensor as a thermal 19 + zone with maximum two user mode configurable trip points. Number of trip points 20 + depends on the capability of the package. Once the trip point is violated, 21 + user mode can receive notification via thermal notification mechanism and can 22 + take any action to control temperature. 23 + 24 + 25 + Threshold management 26 + -------------------- 27 + Each package will register as a thermal zone under /sys/class/thermal. 28 + Example: 29 + /sys/class/thermal/thermal_zone1 30 + 31 + This contains two trip points: 32 + - trip_point_0_temp 33 + - trip_point_1_temp 34 + 35 + User can set any temperature between 0 to TJ-Max temperature. Temperature units 36 + are in milli-degree Celsius. Refer to "Documentation/thermal/sysfs-api.txt" for 37 + thermal sys-fs details. 38 + 39 + Any value other than 0 in these trip points, can trigger thermal notifications. 40 + Setting 0, stops sending thermal notifications. 41 + 42 + Thermal notifications: To get kobject-uevent notifications, set the thermal zone 43 + policy to "user_space". For example: echo -n "user_space" > policy 44 + 45 + 46 + 47 +
+3 -2
MAINTAINERS
··· 8159 8159 M: Eduardo Valentin <eduardo.valentin@ti.com> 8160 8160 L: linux-pm@vger.kernel.org 8161 8161 T: git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git 8162 + T: git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git 8162 8163 Q: https://patchwork.kernel.org/project/linux-pm/list/ 8163 8164 S: Supported 8164 8165 F: drivers/thermal/ ··· 8184 8183 TI BANDGAP AND THERMAL DRIVER 8185 8184 M: Eduardo Valentin <eduardo.valentin@ti.com> 8186 8185 L: linux-pm@vger.kernel.org 8187 - S: Maintained 8188 - F: drivers/staging/omap-thermal/ 8186 + S: Supported 8187 + F: drivers/thermal/ti-soc-thermal/ 8189 8188 8190 8189 TI FLASH MEDIA INTERFACE DRIVER 8191 8190 M: Alex Dubov <oakad@yahoo.com>
+7
arch/x86/include/asm/mce.h
··· 214 214 /* Interrupt Handler for core thermal thresholds */ 215 215 extern int (*platform_thermal_notify)(__u64 msr_val); 216 216 217 + /* Interrupt Handler for package thermal thresholds */ 218 + extern int (*platform_thermal_package_notify)(__u64 msr_val); 219 + 220 + /* Callback support of rate control, return true, if 221 + * callback has rate control */ 222 + extern bool (*platform_thermal_package_rate_control)(void); 223 + 217 224 #ifdef CONFIG_X86_THERMAL_VECTOR 218 225 extern void mcheck_intel_therm_init(void); 219 226 #else
+59 -4
arch/x86/kernel/cpu/mcheck/therm_throt.c
··· 55 55 struct _thermal_state package_power_limit; 56 56 struct _thermal_state core_thresh0; 57 57 struct _thermal_state core_thresh1; 58 + struct _thermal_state pkg_thresh0; 59 + struct _thermal_state pkg_thresh1; 58 60 }; 59 61 60 62 /* Callback to handle core threshold interrupts */ 61 63 int (*platform_thermal_notify)(__u64 msr_val); 62 64 EXPORT_SYMBOL(platform_thermal_notify); 65 + 66 + /* Callback to handle core package threshold_interrupts */ 67 + int (*platform_thermal_package_notify)(__u64 msr_val); 68 + EXPORT_SYMBOL_GPL(platform_thermal_package_notify); 69 + 70 + /* Callback support of rate control, return true, if 71 + * callback has rate control */ 72 + bool (*platform_thermal_package_rate_control)(void); 73 + EXPORT_SYMBOL_GPL(platform_thermal_package_rate_control); 74 + 63 75 64 76 static DEFINE_PER_CPU(struct thermal_state, thermal_state); 65 77 ··· 207 195 return 0; 208 196 } 209 197 210 - static int thresh_event_valid(int event) 198 + static int thresh_event_valid(int level, int event) 211 199 { 212 200 struct _thermal_state *state; 213 201 unsigned int this_cpu = smp_processor_id(); 214 202 struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu); 215 203 u64 now = get_jiffies_64(); 216 204 217 - state = (event == 0) ? &pstate->core_thresh0 : &pstate->core_thresh1; 205 + if (level == PACKAGE_LEVEL) 206 + state = (event == 0) ? &pstate->pkg_thresh0 : 207 + &pstate->pkg_thresh1; 208 + else 209 + state = (event == 0) ? &pstate->core_thresh0 : 210 + &pstate->core_thresh1; 218 211 219 212 if (time_before64(now, state->next_check)) 220 213 return 0; 221 214 222 215 state->next_check = now + CHECK_INTERVAL; 216 + 223 217 return 1; 224 218 } 225 219 ··· 340 322 341 323 #endif /* CONFIG_SYSFS */ 342 324 325 + static void notify_package_thresholds(__u64 msr_val) 326 + { 327 + bool notify_thres_0 = false; 328 + bool notify_thres_1 = false; 329 + 330 + if (!platform_thermal_package_notify) 331 + return; 332 + 333 + /* lower threshold check */ 334 + if (msr_val & THERM_LOG_THRESHOLD0) 335 + notify_thres_0 = true; 336 + /* higher threshold check */ 337 + if (msr_val & THERM_LOG_THRESHOLD1) 338 + notify_thres_1 = true; 339 + 340 + if (!notify_thres_0 && !notify_thres_1) 341 + return; 342 + 343 + if (platform_thermal_package_rate_control && 344 + platform_thermal_package_rate_control()) { 345 + /* Rate control is implemented in callback */ 346 + platform_thermal_package_notify(msr_val); 347 + return; 348 + } 349 + 350 + /* lower threshold reached */ 351 + if (notify_thres_0 && thresh_event_valid(PACKAGE_LEVEL, 0)) 352 + platform_thermal_package_notify(msr_val); 353 + /* higher threshold reached */ 354 + if (notify_thres_1 && thresh_event_valid(PACKAGE_LEVEL, 1)) 355 + platform_thermal_package_notify(msr_val); 356 + } 357 + 343 358 static void notify_thresholds(__u64 msr_val) 344 359 { 345 360 /* check whether the interrupt handler is defined; ··· 382 331 return; 383 332 384 333 /* lower threshold reached */ 385 - if ((msr_val & THERM_LOG_THRESHOLD0) && thresh_event_valid(0)) 334 + if ((msr_val & THERM_LOG_THRESHOLD0) && 335 + thresh_event_valid(CORE_LEVEL, 0)) 386 336 platform_thermal_notify(msr_val); 387 337 /* higher threshold reached */ 388 - if ((msr_val & THERM_LOG_THRESHOLD1) && thresh_event_valid(1)) 338 + if ((msr_val & THERM_LOG_THRESHOLD1) && 339 + thresh_event_valid(CORE_LEVEL, 1)) 389 340 platform_thermal_notify(msr_val); 390 341 } 391 342 ··· 413 360 414 361 if (this_cpu_has(X86_FEATURE_PTS)) { 415 362 rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val); 363 + /* check violations of package thermal thresholds */ 364 + notify_package_thresholds(msr_val); 416 365 therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT, 417 366 THERMAL_THROTTLING_EVENT, 418 367 PACKAGE_LEVEL);
-2
drivers/staging/Kconfig
··· 120 120 121 121 source "drivers/staging/csr/Kconfig" 122 122 123 - source "drivers/staging/ti-soc-thermal/Kconfig" 124 - 125 123 source "drivers/staging/silicom/Kconfig" 126 124 127 125 source "drivers/staging/ced1401/Kconfig"
-1
drivers/staging/Makefile
··· 53 53 obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ 54 54 obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/ 55 55 obj-$(CONFIG_CSR_WIFI) += csr/ 56 - obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ 57 56 obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/ 58 57 obj-$(CONFIG_CED1401) += ced1401/ 59 58 obj-$(CONFIG_DRM_IMX) += imx-drm/
+12
drivers/staging/ti-soc-thermal/Kconfig drivers/thermal/ti-soc-thermal/Kconfig
··· 46 46 47 47 This includes alert interrupts generation and also the TSHUT 48 48 support. 49 + 50 + config DRA752_THERMAL 51 + bool "Texas Instruments DRA752 thermal support" 52 + depends on TI_SOC_THERMAL 53 + depends on SOC_DRA7XX 54 + help 55 + If you say yes here you get thermal support for the Texas Instruments 56 + DRA752 SoC family. The current chip supported are: 57 + - DRA752 58 + 59 + This includes alert interrupts generation and also the TSHUT 60 + support.
+1
drivers/staging/ti-soc-thermal/Makefile drivers/thermal/ti-soc-thermal/Makefile
··· 1 1 obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal.o 2 2 ti-soc-thermal-y := ti-bandgap.o 3 3 ti-soc-thermal-$(CONFIG_TI_THERMAL) += ti-thermal-common.o 4 + ti-soc-thermal-$(CONFIG_DRA752_THERMAL) += dra752-thermal-data.o 4 5 ti-soc-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal-data.o 5 6 ti-soc-thermal-$(CONFIG_OMAP5_THERMAL) += omap5-thermal-data.o
drivers/staging/ti-soc-thermal/TODO drivers/thermal/ti-soc-thermal/TODO
drivers/staging/ti-soc-thermal/omap4-thermal-data.c drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h
drivers/staging/ti-soc-thermal/omap5-thermal-data.c drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h
+23 -13
drivers/staging/ti-soc-thermal/ti-bandgap.c drivers/thermal/ti-soc-thermal/ti-bandgap.c
··· 38 38 #include <linux/of_device.h> 39 39 #include <linux/of_platform.h> 40 40 #include <linux/of_irq.h> 41 + #include <linux/of_gpio.h> 41 42 #include <linux/io.h> 42 43 43 44 #include "ti-bandgap.h" ··· 470 469 { 471 470 int ret = 0; 472 471 473 - if (IS_ERR_OR_NULL(bgp)) { 472 + if (!bgp || IS_ERR(bgp)) { 474 473 pr_err("%s: invalid bandgap pointer\n", __func__); 475 474 ret = -EINVAL; 476 475 goto exit; ··· 993 992 goto exit; 994 993 } 995 994 995 + spin_lock(&bgp->lock); 996 + 996 997 tsr = bgp->conf->sensors[id].registers; 997 998 998 999 /* Freeze and read the last 2 valid readings */ 1000 + RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1); 999 1001 reg1 = tsr->ctrl_dtemp_1; 1000 1002 reg2 = tsr->ctrl_dtemp_2; 1001 1003 ··· 1012 1008 /* Convert from adc values to mCelsius temperature */ 1013 1009 ret = ti_bandgap_adc_to_mcelsius(bgp, temp1, &t1); 1014 1010 if (ret) 1015 - goto exit; 1011 + goto unfreeze; 1016 1012 1017 1013 ret = ti_bandgap_adc_to_mcelsius(bgp, temp2, &t2); 1018 1014 if (ret) 1019 - goto exit; 1015 + goto unfreeze; 1020 1016 1021 1017 /* Fetch the update interval */ 1022 1018 ret = ti_bandgap_read_update_interval(bgp, id, &interval); 1023 1019 if (ret || !interval) 1024 - goto exit; 1020 + goto unfreeze; 1025 1021 1026 1022 *trend = (t1 - t2) / interval; 1027 1023 1028 1024 dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n", 1029 1025 t1, t2, *trend); 1030 1026 1027 + unfreeze: 1028 + RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0); 1029 + spin_unlock(&bgp->lock); 1031 1030 exit: 1032 1031 return ret; 1033 1032 } ··· 1130 1123 const struct of_device_id *of_id; 1131 1124 struct ti_bandgap *bgp; 1132 1125 struct resource *res; 1133 - u32 prop; 1134 1126 int i; 1135 1127 1136 1128 /* just for the sake */ ··· 1173 1167 } while (res); 1174 1168 1175 1169 if (TI_BANDGAP_HAS(bgp, TSHUT)) { 1176 - if (of_property_read_u32(node, "ti,tshut-gpio", &prop) < 0) { 1177 - dev_err(&pdev->dev, "missing tshut gpio in device tree\n"); 1178 - return ERR_PTR(-EINVAL); 1179 - } 1180 - bgp->tshut_gpio = prop; 1170 + bgp->tshut_gpio = of_get_gpio(node, 0); 1181 1171 if (!gpio_is_valid(bgp->tshut_gpio)) { 1182 1172 dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n", 1183 1173 bgp->tshut_gpio); ··· 1193 1191 int clk_rate, ret = 0, i; 1194 1192 1195 1193 bgp = ti_bandgap_build(pdev); 1196 - if (IS_ERR_OR_NULL(bgp)) { 1194 + if (IS_ERR(bgp)) { 1197 1195 dev_err(&pdev->dev, "failed to fetch platform data\n"); 1198 1196 return PTR_ERR(bgp); 1199 1197 } ··· 1209 1207 } 1210 1208 1211 1209 bgp->fclock = clk_get(NULL, bgp->conf->fclock_name); 1212 - ret = IS_ERR_OR_NULL(bgp->fclock); 1210 + ret = IS_ERR(bgp->fclock); 1213 1211 if (ret) { 1214 1212 dev_err(&pdev->dev, "failed to request fclock reference\n"); 1213 + ret = PTR_ERR(bgp->fclock); 1215 1214 goto free_irqs; 1216 1215 } 1217 1216 1218 1217 bgp->div_clk = clk_get(NULL, bgp->conf->div_ck_name); 1219 - ret = IS_ERR_OR_NULL(bgp->div_clk); 1218 + ret = IS_ERR(bgp->div_clk); 1220 1219 if (ret) { 1221 1220 dev_err(&pdev->dev, 1222 1221 "failed to request div_ts_ck clock ref\n"); 1222 + ret = PTR_ERR(bgp->div_clk); 1223 1223 goto free_irqs; 1224 1224 } 1225 1225 ··· 1525 1521 { 1526 1522 .compatible = "ti,omap5430-bandgap", 1527 1523 .data = (void *)&omap5430_data, 1524 + }, 1525 + #endif 1526 + #ifdef CONFIG_DRA752_THERMAL 1527 + { 1528 + .compatible = "ti,dra752-bandgap", 1529 + .data = (void *)&dra752_data, 1528 1530 }, 1529 1531 #endif 1530 1532 /* Sentinel */
+5
drivers/staging/ti-soc-thermal/ti-bandgap.h drivers/thermal/ti-soc-thermal/ti-bandgap.h
··· 400 400 #define omap5430_data NULL 401 401 #endif 402 402 403 + #ifdef CONFIG_DRA752_THERMAL 404 + extern const struct ti_bandgap_data dra752_data; 405 + #else 406 + #define dra752_data NULL 407 + #endif 403 408 #endif
+8 -7
drivers/staging/ti-soc-thermal/ti-thermal-common.c drivers/thermal/ti-soc-thermal/ti-thermal-common.c
··· 101 101 102 102 pcb_tz = data->pcb_tz; 103 103 /* In case pcb zone is available, use the extrapolation rule with it */ 104 - if (!IS_ERR_OR_NULL(pcb_tz)) { 104 + if (!IS_ERR(pcb_tz)) { 105 105 ret = thermal_zone_get_temp(pcb_tz, &pcb_temp); 106 106 if (!ret) { 107 107 tmp -= pcb_temp; /* got a valid PCB temp */ ··· 124 124 struct ti_thermal_data *data = thermal->devdata; 125 125 int id; 126 126 127 - if (IS_ERR_OR_NULL(data)) 127 + if (!data || IS_ERR(data)) 128 128 return -ENODEV; 129 129 130 130 /* check if this is the cooling device we registered */ ··· 146 146 { 147 147 struct ti_thermal_data *data = thermal->devdata; 148 148 149 - if (IS_ERR_OR_NULL(data)) 149 + if (!data || IS_ERR(data)) 150 150 return -ENODEV; 151 151 152 152 /* check if this is the cooling device we registered */ ··· 282 282 data->sensor_id = id; 283 283 data->bgp = bgp; 284 284 data->mode = THERMAL_DEVICE_ENABLED; 285 + /* pcb_tz will be either valid or PTR_ERR() */ 285 286 data->pcb_tz = thermal_zone_get_zone_by_name("pcb"); 286 287 INIT_WORK(&data->thermal_wq, ti_thermal_work); 287 288 ··· 296 295 297 296 data = ti_bandgap_get_sensor_data(bgp, id); 298 297 299 - if (IS_ERR_OR_NULL(data)) 298 + if (!data || IS_ERR(data)) 300 299 data = ti_thermal_build_data(bgp, id); 301 300 302 301 if (!data) ··· 307 306 OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops, 308 307 NULL, FAST_TEMP_MONITORING_RATE, 309 308 FAST_TEMP_MONITORING_RATE); 310 - if (IS_ERR_OR_NULL(data->ti_thermal)) { 309 + if (IS_ERR(data->ti_thermal)) { 311 310 dev_err(bgp->dev, "thermal zone device is NULL\n"); 312 311 return PTR_ERR(data->ti_thermal); 313 312 } ··· 344 343 struct ti_thermal_data *data; 345 344 346 345 data = ti_bandgap_get_sensor_data(bgp, id); 347 - if (IS_ERR_OR_NULL(data)) 346 + if (!data || IS_ERR(data)) 348 347 data = ti_thermal_build_data(bgp, id); 349 348 350 349 if (!data) ··· 357 356 358 357 /* Register cooling device */ 359 358 data->cool_dev = cpufreq_cooling_register(cpu_present_mask); 360 - if (IS_ERR_OR_NULL(data->cool_dev)) { 359 + if (IS_ERR(data->cool_dev)) { 361 360 dev_err(bgp->dev, 362 361 "Failed to register cpufreq cooling device\n"); 363 362 return PTR_ERR(data->cool_dev);
+6
drivers/staging/ti-soc-thermal/ti-thermal.h drivers/thermal/ti-soc-thermal/ti-thermal.h
··· 38 38 #define OMAP_GRADIENT_SLOPE_5430_GPU 117 39 39 #define OMAP_GRADIENT_CONST_5430_GPU -2992 40 40 41 + #define DRA752_GRADIENT_SLOPE 0 42 + #define DRA752_GRADIENT_CONST 2000 43 + 41 44 /* PCB sensor calculation constants */ 42 45 #define OMAP_GRADIENT_SLOPE_W_PCB_4430 0 43 46 #define OMAP_GRADIENT_CONST_W_PCB_4430 20000 ··· 53 50 #define OMAP_GRADIENT_CONST_W_PCB_5430_CPU 484 54 51 #define OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU 464 55 52 #define OMAP_GRADIENT_CONST_W_PCB_5430_GPU -5102 53 + 54 + #define DRA752_GRADIENT_SLOPE_W_PCB 0 55 + #define DRA752_GRADIENT_CONST_W_PCB 2000 56 56 57 57 /* trip points of interest in milicelsius (at hotspot level) */ 58 58 #define OMAP_TRIP_COLD 100000
+17 -4
drivers/staging/ti-soc-thermal/ti_soc_thermal.txt Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt
··· 17 17 - interrupts : this entry should indicate which interrupt line 18 18 the talert signal is routed to; 19 19 Specific: 20 - - ti,tshut-gpio : this entry should be used to inform which GPIO 21 - line the tshut signal is routed to; 20 + - gpios : this entry should be used to inform which GPIO 21 + line the tshut signal is routed to. The informed GPIO will 22 + be treated as an IRQ; 22 23 - regs : this entry must also be specified and it is specific 23 24 to each bandgap version, because the mapping may change from 24 25 soc to soc, apart of depending on available features. ··· 38 37 0x4a002378 0x18>; 39 38 compatible = "ti,omap4460-bandgap"; 40 39 interrupts = <0 126 4>; /* talert */ 41 - ti,tshut-gpio = <86>; 40 + gpios = <&gpio3 22 0>; /* tshut */ 42 41 }; 43 42 44 43 OMAP4470: ··· 48 47 0x4a002378 0x18>; 49 48 compatible = "ti,omap4470-bandgap"; 50 49 interrupts = <0 126 4>; /* talert */ 51 - ti,tshut-gpio = <86>; 50 + gpios = <&gpio3 22 0>; /* tshut */ 52 51 }; 53 52 54 53 OMAP5430: ··· 58 57 0x4a002380 0x2c 59 58 0x4a0023C0 0x3c>; 60 59 compatible = "ti,omap5430-bandgap"; 60 + interrupts = <0 126 4>; /* talert */ 61 + }; 62 + 63 + DRA752: 64 + bandgap { 65 + reg = <0x4a0021e0 0xc 66 + 0x4a00232c 0xc 67 + 0x4a002380 0x2c 68 + 0x4a0023C0 0x3c 69 + 0x4a002564 0x8 70 + 0x4a002574 0x50>; 71 + compatible = "ti,dra752-bandgap"; 61 72 interrupts = <0 126 4>; /* talert */ 62 73 };
+15
drivers/thermal/Kconfig
··· 169 169 enforce idle time which results in more package C-state residency. The 170 170 user interface is exposed via generic thermal framework. 171 171 172 + config X86_PKG_TEMP_THERMAL 173 + tristate "X86 package temperature thermal driver" 174 + depends on X86_THERMAL_VECTOR 175 + select THERMAL_GOV_USER_SPACE 176 + default m 177 + help 178 + Enable this to register CPU digital sensor for package temperature as 179 + thermal zone. Each package will have its own thermal zone. There are 180 + two trip points which can be set by user to get notifications via thermal 181 + notification methods. 182 + 183 + menu "Texas Instruments thermal drivers" 184 + source "drivers/thermal/ti-soc-thermal/Kconfig" 185 + endmenu 186 + 172 187 endif
+2 -1
drivers/thermal/Makefile
··· 23 23 obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o 24 24 obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o 25 25 obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o 26 - 26 + obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o 27 + obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
+1 -2
drivers/thermal/armada_thermal.c
··· 200 200 platform_get_drvdata(pdev); 201 201 202 202 thermal_zone_device_unregister(armada_thermal); 203 - platform_set_drvdata(pdev, NULL); 204 203 205 204 return 0; 206 205 } ··· 210 211 .driver = { 211 212 .name = "armada_thermal", 212 213 .owner = THIS_MODULE, 213 - .of_match_table = of_match_ptr(armada_thermal_id_table), 214 + .of_match_table = armada_thermal_id_table, 214 215 }, 215 216 }; 216 217
+1 -1
drivers/thermal/cpu_cooling.c
··· 167 167 continue; 168 168 169 169 /* get the frequency order */ 170 - if (freq != CPUFREQ_ENTRY_INVALID && descend != -1) 170 + if (freq != CPUFREQ_ENTRY_INVALID && descend == -1) 171 171 descend = !!(freq > table[i].frequency); 172 172 173 173 freq = table[i].frequency;
+2 -8
drivers/thermal/dove_thermal.c
··· 134 134 struct resource *res; 135 135 int ret; 136 136 137 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 138 - if (!res) { 139 - dev_err(&pdev->dev, "Failed to get platform resource\n"); 140 - return -ENODEV; 141 - } 142 - 143 137 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 144 138 if (!priv) 145 139 return -ENOMEM; 146 140 141 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 147 142 priv->sensor = devm_ioremap_resource(&pdev->dev, res); 148 143 if (IS_ERR(priv->sensor)) 149 144 return PTR_ERR(priv->sensor); ··· 173 178 platform_get_drvdata(pdev); 174 179 175 180 thermal_zone_device_unregister(dove_thermal); 176 - platform_set_drvdata(pdev, NULL); 177 181 178 182 return 0; 179 183 } ··· 185 191 .driver = { 186 192 .name = "dove_thermal", 187 193 .owner = THIS_MODULE, 188 - .of_match_table = of_match_ptr(dove_thermal_id_table), 194 + .of_match_table = dove_thermal_id_table, 189 195 }, 190 196 }; 191 197
-3
drivers/thermal/exynos_thermal.c
··· 997 997 998 998 return 0; 999 999 err_clk: 1000 - platform_set_drvdata(pdev, NULL); 1001 1000 clk_unprepare(data->clk); 1002 1001 return ret; 1003 1002 } ··· 1010 1011 exynos_unregister_thermal(); 1011 1012 1012 1013 clk_unprepare(data->clk); 1013 - 1014 - platform_set_drvdata(pdev, NULL); 1015 1014 1016 1015 return 0; 1017 1016 }
+2 -8
drivers/thermal/kirkwood_thermal.c
··· 75 75 struct kirkwood_thermal_priv *priv; 76 76 struct resource *res; 77 77 78 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 79 - if (!res) { 80 - dev_err(&pdev->dev, "Failed to get platform resource\n"); 81 - return -ENODEV; 82 - } 83 - 84 78 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 85 79 if (!priv) 86 80 return -ENOMEM; 87 81 82 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 88 83 priv->sensor = devm_ioremap_resource(&pdev->dev, res); 89 84 if (IS_ERR(priv->sensor)) 90 85 return PTR_ERR(priv->sensor); ··· 103 108 platform_get_drvdata(pdev); 104 109 105 110 thermal_zone_device_unregister(kirkwood_thermal); 106 - platform_set_drvdata(pdev, NULL); 107 111 108 112 return 0; 109 113 } ··· 115 121 .driver = { 116 122 .name = "kirkwood_thermal", 117 123 .owner = THIS_MODULE, 118 - .of_match_table = of_match_ptr(kirkwood_thermal_id_table), 124 + .of_match_table = kirkwood_thermal_id_table, 119 125 }, 120 126 }; 121 127
+2 -8
drivers/thermal/rcar_thermal.c
··· 389 389 * platform has IRQ support. 390 390 * Then, drier use common register 391 391 */ 392 - res = platform_get_resource(pdev, IORESOURCE_MEM, mres++); 393 - if (!res) { 394 - dev_err(dev, "Could not get platform resource\n"); 395 - return -ENODEV; 396 - } 397 392 398 393 ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0, 399 394 dev_name(dev), common); ··· 400 405 /* 401 406 * rcar_has_irq_support() will be enabled 402 407 */ 408 + res = platform_get_resource(pdev, IORESOURCE_MEM, mres++); 403 409 common->base = devm_ioremap_resource(dev, res); 404 410 if (IS_ERR(common->base)) 405 411 return PTR_ERR(common->base); ··· 454 458 455 459 platform_set_drvdata(pdev, common); 456 460 457 - dev_info(dev, "%d sensor proved\n", i); 461 + dev_info(dev, "%d sensor probed\n", i); 458 462 459 463 return 0; 460 464 ··· 482 486 if (rcar_has_irq_support(priv)) 483 487 rcar_thermal_irq_disable(priv); 484 488 } 485 - 486 - platform_set_drvdata(pdev, NULL); 487 489 488 490 pm_runtime_put_sync(dev); 489 491 pm_runtime_disable(dev);
+6 -14
drivers/thermal/spear_thermal.c
··· 104 104 struct thermal_zone_device *spear_thermal = NULL; 105 105 struct spear_thermal_dev *stdev; 106 106 struct device_node *np = pdev->dev.of_node; 107 - struct resource *stres = platform_get_resource(pdev, IORESOURCE_MEM, 0); 107 + struct resource *res; 108 108 int ret = 0, val; 109 109 110 110 if (!np || !of_property_read_u32(np, "st,thermal-flags", &val)) { 111 111 dev_err(&pdev->dev, "Failed: DT Pdata not passed\n"); 112 112 return -EINVAL; 113 - } 114 - 115 - if (!stres) { 116 - dev_err(&pdev->dev, "memory resource missing\n"); 117 - return -ENODEV; 118 113 } 119 114 120 115 stdev = devm_kzalloc(&pdev->dev, sizeof(*stdev), GFP_KERNEL); ··· 119 124 } 120 125 121 126 /* Enable thermal sensor */ 122 - stdev->thermal_base = devm_ioremap(&pdev->dev, stres->start, 123 - resource_size(stres)); 124 - if (!stdev->thermal_base) { 125 - dev_err(&pdev->dev, "ioremap failed\n"); 126 - return -ENOMEM; 127 - } 127 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 128 + stdev->thermal_base = devm_ioremap_resource(&pdev->dev, res); 129 + if (IS_ERR(stdev->thermal_base)) 130 + return PTR_ERR(stdev->thermal_base); 128 131 129 132 stdev->clk = devm_clk_get(&pdev->dev, NULL); 130 133 if (IS_ERR(stdev->clk)) { ··· 167 174 struct spear_thermal_dev *stdev = spear_thermal->devdata; 168 175 169 176 thermal_zone_device_unregister(spear_thermal); 170 - platform_set_drvdata(pdev, NULL); 171 177 172 178 /* Disable SPEAr Thermal Sensor */ 173 179 actual_mask = readl_relaxed(stdev->thermal_base); ··· 190 198 .name = "spear_thermal", 191 199 .owner = THIS_MODULE, 192 200 .pm = &spear_thermal_pm_ops, 193 - .of_match_table = of_match_ptr(spear_thermal_id_table), 201 + .of_match_table = spear_thermal_id_table, 194 202 }, 195 203 }; 196 204
+8 -3
drivers/thermal/thermal_core.c
··· 33 33 #include <linux/idr.h> 34 34 #include <linux/thermal.h> 35 35 #include <linux/reboot.h> 36 + #include <linux/string.h> 36 37 #include <net/netlink.h> 37 38 #include <net/genetlink.h> 38 39 ··· 156 155 { 157 156 enum thermal_trend trend; 158 157 159 - if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) { 158 + if (tz->emul_temperature || !tz->ops->get_trend || 159 + tz->ops->get_trend(tz, trip, &trend)) { 160 160 if (tz->temperature > tz->last_temperature) 161 161 trend = THERMAL_TREND_RAISING; 162 162 else if (tz->temperature < tz->last_temperature) ··· 715 713 int ret = -EINVAL; 716 714 struct thermal_zone_device *tz = to_thermal_zone(dev); 717 715 struct thermal_governor *gov; 716 + char name[THERMAL_NAME_LENGTH]; 717 + 718 + snprintf(name, sizeof(name), "%s", buf); 718 719 719 720 mutex_lock(&thermal_governor_lock); 720 721 721 - gov = __find_governor(buf); 722 + gov = __find_governor(strim(name)); 722 723 if (!gov) 723 724 goto exit; 724 725 ··· 1629 1624 if (!ops || !ops->get_temp) 1630 1625 return ERR_PTR(-EINVAL); 1631 1626 1632 - if (trips > 0 && !ops->get_trip_type) 1627 + if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp)) 1633 1628 return ERR_PTR(-EINVAL); 1634 1629 1635 1630 tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL);
+280
drivers/thermal/ti-soc-thermal/dra752-bandgap.h
··· 1 + /* 2 + * DRA752 bandgap registers, bitfields and temperature definitions 3 + * 4 + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ 5 + * Contact: 6 + * Eduardo Valentin <eduardo.valentin@ti.com> 7 + * Tero Kristo <t-kristo@ti.com> 8 + * 9 + * This is an auto generated file. 10 + * 11 + * This program is free software; you can redistribute it and/or 12 + * modify it under the terms of the GNU General Public License 13 + * version 2 as published by the Free Software Foundation. 14 + * 15 + * This program is distributed in the hope that it will be useful, but 16 + * WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 + * General Public License for more details. 19 + * 20 + * You should have received a copy of the GNU General Public License 21 + * along with this program; if not, write to the Free Software 22 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 23 + * 02110-1301 USA 24 + * 25 + */ 26 + #ifndef __DRA752_BANDGAP_H 27 + #define __DRA752_BANDGAP_H 28 + 29 + /** 30 + * *** DRA752 *** 31 + * 32 + * Below, in sequence, are the Register definitions, 33 + * the bitfields and the temperature definitions for DRA752. 34 + */ 35 + 36 + /** 37 + * DRA752 register definitions 38 + * 39 + * Registers are defined as offsets. The offsets are 40 + * relative to FUSE_OPP_BGAP_GPU on DRA752. 41 + * DRA752_BANDGAP_BASE 0x4a0021e0 42 + * 43 + * Register below are grouped by domain (not necessarily in offset order) 44 + */ 45 + 46 + 47 + /* DRA752.common register offsets */ 48 + #define DRA752_BANDGAP_CTRL_1_OFFSET 0x1a0 49 + #define DRA752_BANDGAP_STATUS_1_OFFSET 0x1c8 50 + #define DRA752_BANDGAP_CTRL_2_OFFSET 0x39c 51 + #define DRA752_BANDGAP_STATUS_2_OFFSET 0x3b8 52 + 53 + /* DRA752.core register offsets */ 54 + #define DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET 0x8 55 + #define DRA752_TEMP_SENSOR_CORE_OFFSET 0x154 56 + #define DRA752_BANDGAP_THRESHOLD_CORE_OFFSET 0x1ac 57 + #define DRA752_BANDGAP_TSHUT_CORE_OFFSET 0x1b8 58 + #define DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET 0x1c4 59 + #define DRA752_DTEMP_CORE_0_OFFSET 0x208 60 + #define DRA752_DTEMP_CORE_1_OFFSET 0x20c 61 + #define DRA752_DTEMP_CORE_2_OFFSET 0x210 62 + #define DRA752_DTEMP_CORE_3_OFFSET 0x214 63 + #define DRA752_DTEMP_CORE_4_OFFSET 0x218 64 + 65 + /* DRA752.iva register offsets */ 66 + #define DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET 0x388 67 + #define DRA752_TEMP_SENSOR_IVA_OFFSET 0x398 68 + #define DRA752_BANDGAP_THRESHOLD_IVA_OFFSET 0x3a4 69 + #define DRA752_BANDGAP_TSHUT_IVA_OFFSET 0x3ac 70 + #define DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET 0x3b4 71 + #define DRA752_DTEMP_IVA_0_OFFSET 0x3d0 72 + #define DRA752_DTEMP_IVA_1_OFFSET 0x3d4 73 + #define DRA752_DTEMP_IVA_2_OFFSET 0x3d8 74 + #define DRA752_DTEMP_IVA_3_OFFSET 0x3dc 75 + #define DRA752_DTEMP_IVA_4_OFFSET 0x3e0 76 + 77 + /* DRA752.mpu register offsets */ 78 + #define DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET 0x4 79 + #define DRA752_TEMP_SENSOR_MPU_OFFSET 0x14c 80 + #define DRA752_BANDGAP_THRESHOLD_MPU_OFFSET 0x1a4 81 + #define DRA752_BANDGAP_TSHUT_MPU_OFFSET 0x1b0 82 + #define DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET 0x1bc 83 + #define DRA752_DTEMP_MPU_0_OFFSET 0x1e0 84 + #define DRA752_DTEMP_MPU_1_OFFSET 0x1e4 85 + #define DRA752_DTEMP_MPU_2_OFFSET 0x1e8 86 + #define DRA752_DTEMP_MPU_3_OFFSET 0x1ec 87 + #define DRA752_DTEMP_MPU_4_OFFSET 0x1f0 88 + 89 + /* DRA752.dspeve register offsets */ 90 + #define DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET 0x384 91 + #define DRA752_TEMP_SENSOR_DSPEVE_OFFSET 0x394 92 + #define DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET 0x3a0 93 + #define DRA752_BANDGAP_TSHUT_DSPEVE_OFFSET 0x3a8 94 + #define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET 0x3b0 95 + #define DRA752_DTEMP_DSPEVE_0_OFFSET 0x3bc 96 + #define DRA752_DTEMP_DSPEVE_1_OFFSET 0x3c0 97 + #define DRA752_DTEMP_DSPEVE_2_OFFSET 0x3c4 98 + #define DRA752_DTEMP_DSPEVE_3_OFFSET 0x3c8 99 + #define DRA752_DTEMP_DSPEVE_4_OFFSET 0x3cc 100 + 101 + /* DRA752.gpu register offsets */ 102 + #define DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET 0x0 103 + #define DRA752_TEMP_SENSOR_GPU_OFFSET 0x150 104 + #define DRA752_BANDGAP_THRESHOLD_GPU_OFFSET 0x1a8 105 + #define DRA752_BANDGAP_TSHUT_GPU_OFFSET 0x1b4 106 + #define DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET 0x1c0 107 + #define DRA752_DTEMP_GPU_0_OFFSET 0x1f4 108 + #define DRA752_DTEMP_GPU_1_OFFSET 0x1f8 109 + #define DRA752_DTEMP_GPU_2_OFFSET 0x1fc 110 + #define DRA752_DTEMP_GPU_3_OFFSET 0x200 111 + #define DRA752_DTEMP_GPU_4_OFFSET 0x204 112 + 113 + /** 114 + * Register bitfields for DRA752 115 + * 116 + * All the macros bellow define the required bits for 117 + * controlling temperature on DRA752. Bit defines are 118 + * grouped by register. 119 + */ 120 + 121 + /* DRA752.BANDGAP_STATUS_1 */ 122 + #define DRA752_BANDGAP_STATUS_1_ALERT_MASK BIT(31) 123 + #define DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK BIT(5) 124 + #define DRA752_BANDGAP_STATUS_1_COLD_CORE_MASK BIT(4) 125 + #define DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK BIT(3) 126 + #define DRA752_BANDGAP_STATUS_1_COLD_GPU_MASK BIT(2) 127 + #define DRA752_BANDGAP_STATUS_1_HOT_MPU_MASK BIT(1) 128 + #define DRA752_BANDGAP_STATUS_1_COLD_MPU_MASK BIT(0) 129 + 130 + /* DRA752.BANDGAP_CTRL_2 */ 131 + #define DRA752_BANDGAP_CTRL_2_FREEZE_IVA_MASK BIT(22) 132 + #define DRA752_BANDGAP_CTRL_2_FREEZE_DSPEVE_MASK BIT(21) 133 + #define DRA752_BANDGAP_CTRL_2_CLEAR_IVA_MASK BIT(19) 134 + #define DRA752_BANDGAP_CTRL_2_CLEAR_DSPEVE_MASK BIT(18) 135 + #define DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_IVA_MASK BIT(16) 136 + #define DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_DSPEVE_MASK BIT(15) 137 + #define DRA752_BANDGAP_CTRL_2_MASK_HOT_IVA_MASK BIT(3) 138 + #define DRA752_BANDGAP_CTRL_2_MASK_COLD_IVA_MASK BIT(2) 139 + #define DRA752_BANDGAP_CTRL_2_MASK_HOT_DSPEVE_MASK BIT(1) 140 + #define DRA752_BANDGAP_CTRL_2_MASK_COLD_DSPEVE_MASK BIT(0) 141 + 142 + /* DRA752.BANDGAP_STATUS_2 */ 143 + #define DRA752_BANDGAP_STATUS_2_HOT_IVA_MASK BIT(3) 144 + #define DRA752_BANDGAP_STATUS_2_COLD_IVA_MASK BIT(2) 145 + #define DRA752_BANDGAP_STATUS_2_HOT_DSPEVE_MASK BIT(1) 146 + #define DRA752_BANDGAP_STATUS_2_COLD_DSPEVE_MASK BIT(0) 147 + 148 + /* DRA752.BANDGAP_CTRL_1 */ 149 + #define DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK (0x3 << 30) 150 + #define DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK (0x7 << 27) 151 + #define DRA752_BANDGAP_CTRL_1_FREEZE_CORE_MASK BIT(23) 152 + #define DRA752_BANDGAP_CTRL_1_FREEZE_GPU_MASK BIT(22) 153 + #define DRA752_BANDGAP_CTRL_1_FREEZE_MPU_MASK BIT(21) 154 + #define DRA752_BANDGAP_CTRL_1_CLEAR_CORE_MASK BIT(20) 155 + #define DRA752_BANDGAP_CTRL_1_CLEAR_GPU_MASK BIT(19) 156 + #define DRA752_BANDGAP_CTRL_1_CLEAR_MPU_MASK BIT(18) 157 + #define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_CORE_MASK BIT(17) 158 + #define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_GPU_MASK BIT(16) 159 + #define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_MPU_MASK BIT(15) 160 + #define DRA752_BANDGAP_CTRL_1_MASK_HOT_CORE_MASK BIT(5) 161 + #define DRA752_BANDGAP_CTRL_1_MASK_COLD_CORE_MASK BIT(4) 162 + #define DRA752_BANDGAP_CTRL_1_MASK_HOT_GPU_MASK BIT(3) 163 + #define DRA752_BANDGAP_CTRL_1_MASK_COLD_GPU_MASK BIT(2) 164 + #define DRA752_BANDGAP_CTRL_1_MASK_HOT_MPU_MASK BIT(1) 165 + #define DRA752_BANDGAP_CTRL_1_MASK_COLD_MPU_MASK BIT(0) 166 + 167 + /* DRA752.TEMP_SENSOR */ 168 + #define DRA752_TEMP_SENSOR_TMPSOFF_MASK BIT(11) 169 + #define DRA752_TEMP_SENSOR_EOCZ_MASK BIT(10) 170 + #define DRA752_TEMP_SENSOR_DTEMP_MASK (0x3ff << 0) 171 + 172 + /* DRA752.BANDGAP_THRESHOLD */ 173 + #define DRA752_BANDGAP_THRESHOLD_HOT_MASK (0x3ff << 16) 174 + #define DRA752_BANDGAP_THRESHOLD_COLD_MASK (0x3ff << 0) 175 + 176 + /* DRA752.TSHUT_THRESHOLD */ 177 + #define DRA752_TSHUT_THRESHOLD_MUXCTRL_MASK BIT(31) 178 + #define DRA752_TSHUT_THRESHOLD_HOT_MASK (0x3ff << 16) 179 + #define DRA752_TSHUT_THRESHOLD_COLD_MASK (0x3ff << 0) 180 + 181 + /* DRA752.BANDGAP_CUMUL_DTEMP_CORE */ 182 + #define DRA752_BANDGAP_CUMUL_DTEMP_CORE_MASK (0xffffffff << 0) 183 + 184 + /* DRA752.BANDGAP_CUMUL_DTEMP_IVA */ 185 + #define DRA752_BANDGAP_CUMUL_DTEMP_IVA_MASK (0xffffffff << 0) 186 + 187 + /* DRA752.BANDGAP_CUMUL_DTEMP_MPU */ 188 + #define DRA752_BANDGAP_CUMUL_DTEMP_MPU_MASK (0xffffffff << 0) 189 + 190 + /* DRA752.BANDGAP_CUMUL_DTEMP_DSPEVE */ 191 + #define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_MASK (0xffffffff << 0) 192 + 193 + /* DRA752.BANDGAP_CUMUL_DTEMP_GPU */ 194 + #define DRA752_BANDGAP_CUMUL_DTEMP_GPU_MASK (0xffffffff << 0) 195 + 196 + /** 197 + * Temperature limits and thresholds for DRA752 198 + * 199 + * All the macros bellow are definitions for handling the 200 + * ADC conversions and representation of temperature limits 201 + * and thresholds for DRA752. Definitions are grouped 202 + * by temperature domain. 203 + */ 204 + 205 + /* DRA752.common temperature definitions */ 206 + /* ADC conversion table limits */ 207 + #define DRA752_ADC_START_VALUE 540 208 + #define DRA752_ADC_END_VALUE 945 209 + 210 + /* DRA752.GPU temperature definitions */ 211 + /* bandgap clock limits */ 212 + #define DRA752_GPU_MAX_FREQ 1500000 213 + #define DRA752_GPU_MIN_FREQ 1000000 214 + /* sensor limits */ 215 + #define DRA752_GPU_MIN_TEMP -40000 216 + #define DRA752_GPU_MAX_TEMP 125000 217 + #define DRA752_GPU_HYST_VAL 5000 218 + /* interrupts thresholds */ 219 + #define DRA752_GPU_TSHUT_HOT 915 220 + #define DRA752_GPU_TSHUT_COLD 900 221 + #define DRA752_GPU_T_HOT 800 222 + #define DRA752_GPU_T_COLD 795 223 + 224 + /* DRA752.MPU temperature definitions */ 225 + /* bandgap clock limits */ 226 + #define DRA752_MPU_MAX_FREQ 1500000 227 + #define DRA752_MPU_MIN_FREQ 1000000 228 + /* sensor limits */ 229 + #define DRA752_MPU_MIN_TEMP -40000 230 + #define DRA752_MPU_MAX_TEMP 125000 231 + #define DRA752_MPU_HYST_VAL 5000 232 + /* interrupts thresholds */ 233 + #define DRA752_MPU_TSHUT_HOT 915 234 + #define DRA752_MPU_TSHUT_COLD 900 235 + #define DRA752_MPU_T_HOT 800 236 + #define DRA752_MPU_T_COLD 795 237 + 238 + /* DRA752.CORE temperature definitions */ 239 + /* bandgap clock limits */ 240 + #define DRA752_CORE_MAX_FREQ 1500000 241 + #define DRA752_CORE_MIN_FREQ 1000000 242 + /* sensor limits */ 243 + #define DRA752_CORE_MIN_TEMP -40000 244 + #define DRA752_CORE_MAX_TEMP 125000 245 + #define DRA752_CORE_HYST_VAL 5000 246 + /* interrupts thresholds */ 247 + #define DRA752_CORE_TSHUT_HOT 915 248 + #define DRA752_CORE_TSHUT_COLD 900 249 + #define DRA752_CORE_T_HOT 800 250 + #define DRA752_CORE_T_COLD 795 251 + 252 + /* DRA752.DSPEVE temperature definitions */ 253 + /* bandgap clock limits */ 254 + #define DRA752_DSPEVE_MAX_FREQ 1500000 255 + #define DRA752_DSPEVE_MIN_FREQ 1000000 256 + /* sensor limits */ 257 + #define DRA752_DSPEVE_MIN_TEMP -40000 258 + #define DRA752_DSPEVE_MAX_TEMP 125000 259 + #define DRA752_DSPEVE_HYST_VAL 5000 260 + /* interrupts thresholds */ 261 + #define DRA752_DSPEVE_TSHUT_HOT 915 262 + #define DRA752_DSPEVE_TSHUT_COLD 900 263 + #define DRA752_DSPEVE_T_HOT 800 264 + #define DRA752_DSPEVE_T_COLD 795 265 + 266 + /* DRA752.IVA temperature definitions */ 267 + /* bandgap clock limits */ 268 + #define DRA752_IVA_MAX_FREQ 1500000 269 + #define DRA752_IVA_MIN_FREQ 1000000 270 + /* sensor limits */ 271 + #define DRA752_IVA_MIN_TEMP -40000 272 + #define DRA752_IVA_MAX_TEMP 125000 273 + #define DRA752_IVA_HYST_VAL 5000 274 + /* interrupts thresholds */ 275 + #define DRA752_IVA_TSHUT_HOT 915 276 + #define DRA752_IVA_TSHUT_COLD 900 277 + #define DRA752_IVA_T_HOT 800 278 + #define DRA752_IVA_T_COLD 795 279 + 280 + #endif /* __DRA752_BANDGAP_H */
+476
drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
··· 1 + /* 2 + * DRA752 thermal data. 3 + * 4 + * Copyright (C) 2013 Texas Instruments Inc. 5 + * Contact: 6 + * Eduardo Valentin <eduardo.valentin@ti.com> 7 + * Tero Kristo <t-kristo@ti.com> 8 + * 9 + * This file is partially autogenerated. 10 + * 11 + * This software is licensed under the terms of the GNU General Public 12 + * License version 2, as published by the Free Software Foundation, and 13 + * may be copied, distributed, and modified under those terms. 14 + * 15 + * This program is distributed in the hope that it will be useful, 16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 + * GNU General Public License for more details. 19 + * 20 + */ 21 + 22 + #include "ti-thermal.h" 23 + #include "ti-bandgap.h" 24 + #include "dra752-bandgap.h" 25 + 26 + /* 27 + * DRA752 has five instances of thermal sensor: MPU, GPU, CORE, 28 + * IVA and DSPEVE need to describe the individual registers and 29 + * bit fields. 30 + */ 31 + 32 + /* 33 + * DRA752 CORE thermal sensor register offsets and bit-fields 34 + */ 35 + static struct temp_sensor_registers 36 + dra752_core_temp_sensor_registers = { 37 + .temp_sensor_ctrl = DRA752_TEMP_SENSOR_CORE_OFFSET, 38 + .bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK, 39 + .bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK, 40 + .bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK, 41 + .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET, 42 + .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_CORE_MASK, 43 + .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_CORE_MASK, 44 + .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, 45 + .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_CORE_MASK, 46 + .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_CORE_MASK, 47 + .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_CORE_MASK, 48 + .bgap_threshold = DRA752_BANDGAP_THRESHOLD_CORE_OFFSET, 49 + .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, 50 + .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, 51 + .tshut_threshold = DRA752_BANDGAP_TSHUT_CORE_OFFSET, 52 + .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, 53 + .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, 54 + .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, 55 + .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, 56 + .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK, 57 + .status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_CORE_MASK, 58 + .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET, 59 + .ctrl_dtemp_0 = DRA752_DTEMP_CORE_0_OFFSET, 60 + .ctrl_dtemp_1 = DRA752_DTEMP_CORE_1_OFFSET, 61 + .ctrl_dtemp_2 = DRA752_DTEMP_CORE_2_OFFSET, 62 + .ctrl_dtemp_3 = DRA752_DTEMP_CORE_3_OFFSET, 63 + .ctrl_dtemp_4 = DRA752_DTEMP_CORE_4_OFFSET, 64 + .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET, 65 + }; 66 + 67 + /* 68 + * DRA752 IVA thermal sensor register offsets and bit-fields 69 + */ 70 + static struct temp_sensor_registers 71 + dra752_iva_temp_sensor_registers = { 72 + .temp_sensor_ctrl = DRA752_TEMP_SENSOR_IVA_OFFSET, 73 + .bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK, 74 + .bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK, 75 + .bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK, 76 + .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_2_OFFSET, 77 + .mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_IVA_MASK, 78 + .mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_IVA_MASK, 79 + .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, 80 + .mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_IVA_MASK, 81 + .mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_IVA_MASK, 82 + .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_IVA_MASK, 83 + .bgap_threshold = DRA752_BANDGAP_THRESHOLD_IVA_OFFSET, 84 + .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, 85 + .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, 86 + .tshut_threshold = DRA752_BANDGAP_TSHUT_IVA_OFFSET, 87 + .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, 88 + .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, 89 + .bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET, 90 + .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, 91 + .status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_IVA_MASK, 92 + .status_cold_mask = DRA752_BANDGAP_STATUS_2_COLD_IVA_MASK, 93 + .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET, 94 + .ctrl_dtemp_0 = DRA752_DTEMP_IVA_0_OFFSET, 95 + .ctrl_dtemp_1 = DRA752_DTEMP_IVA_1_OFFSET, 96 + .ctrl_dtemp_2 = DRA752_DTEMP_IVA_2_OFFSET, 97 + .ctrl_dtemp_3 = DRA752_DTEMP_IVA_3_OFFSET, 98 + .ctrl_dtemp_4 = DRA752_DTEMP_IVA_4_OFFSET, 99 + .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET, 100 + }; 101 + 102 + /* 103 + * DRA752 MPU thermal sensor register offsets and bit-fields 104 + */ 105 + static struct temp_sensor_registers 106 + dra752_mpu_temp_sensor_registers = { 107 + .temp_sensor_ctrl = DRA752_TEMP_SENSOR_MPU_OFFSET, 108 + .bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK, 109 + .bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK, 110 + .bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK, 111 + .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET, 112 + .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_MPU_MASK, 113 + .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_MPU_MASK, 114 + .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, 115 + .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_MPU_MASK, 116 + .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_MPU_MASK, 117 + .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_MPU_MASK, 118 + .bgap_threshold = DRA752_BANDGAP_THRESHOLD_MPU_OFFSET, 119 + .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, 120 + .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, 121 + .tshut_threshold = DRA752_BANDGAP_TSHUT_MPU_OFFSET, 122 + .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, 123 + .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, 124 + .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, 125 + .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, 126 + .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_MPU_MASK, 127 + .status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_MPU_MASK, 128 + .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET, 129 + .ctrl_dtemp_0 = DRA752_DTEMP_MPU_0_OFFSET, 130 + .ctrl_dtemp_1 = DRA752_DTEMP_MPU_1_OFFSET, 131 + .ctrl_dtemp_2 = DRA752_DTEMP_MPU_2_OFFSET, 132 + .ctrl_dtemp_3 = DRA752_DTEMP_MPU_3_OFFSET, 133 + .ctrl_dtemp_4 = DRA752_DTEMP_MPU_4_OFFSET, 134 + .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET, 135 + }; 136 + 137 + /* 138 + * DRA752 DSPEVE thermal sensor register offsets and bit-fields 139 + */ 140 + static struct temp_sensor_registers 141 + dra752_dspeve_temp_sensor_registers = { 142 + .temp_sensor_ctrl = DRA752_TEMP_SENSOR_DSPEVE_OFFSET, 143 + .bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK, 144 + .bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK, 145 + .bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK, 146 + .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_2_OFFSET, 147 + .mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_DSPEVE_MASK, 148 + .mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_DSPEVE_MASK, 149 + .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, 150 + .mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_DSPEVE_MASK, 151 + .mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_DSPEVE_MASK, 152 + .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_DSPEVE_MASK, 153 + .bgap_threshold = DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET, 154 + .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, 155 + .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, 156 + .tshut_threshold = DRA752_BANDGAP_TSHUT_DSPEVE_OFFSET, 157 + .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, 158 + .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, 159 + .bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET, 160 + .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, 161 + .status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_DSPEVE_MASK, 162 + .status_cold_mask = DRA752_BANDGAP_STATUS_2_COLD_DSPEVE_MASK, 163 + .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET, 164 + .ctrl_dtemp_0 = DRA752_DTEMP_DSPEVE_0_OFFSET, 165 + .ctrl_dtemp_1 = DRA752_DTEMP_DSPEVE_1_OFFSET, 166 + .ctrl_dtemp_2 = DRA752_DTEMP_DSPEVE_2_OFFSET, 167 + .ctrl_dtemp_3 = DRA752_DTEMP_DSPEVE_3_OFFSET, 168 + .ctrl_dtemp_4 = DRA752_DTEMP_DSPEVE_4_OFFSET, 169 + .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET, 170 + }; 171 + 172 + /* 173 + * DRA752 GPU thermal sensor register offsets and bit-fields 174 + */ 175 + static struct temp_sensor_registers 176 + dra752_gpu_temp_sensor_registers = { 177 + .temp_sensor_ctrl = DRA752_TEMP_SENSOR_GPU_OFFSET, 178 + .bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK, 179 + .bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK, 180 + .bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK, 181 + .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET, 182 + .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_GPU_MASK, 183 + .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_GPU_MASK, 184 + .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, 185 + .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_GPU_MASK, 186 + .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_GPU_MASK, 187 + .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_GPU_MASK, 188 + .bgap_threshold = DRA752_BANDGAP_THRESHOLD_GPU_OFFSET, 189 + .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, 190 + .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, 191 + .tshut_threshold = DRA752_BANDGAP_TSHUT_GPU_OFFSET, 192 + .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, 193 + .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, 194 + .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, 195 + .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, 196 + .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK, 197 + .status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_GPU_MASK, 198 + .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET, 199 + .ctrl_dtemp_0 = DRA752_DTEMP_GPU_0_OFFSET, 200 + .ctrl_dtemp_1 = DRA752_DTEMP_GPU_1_OFFSET, 201 + .ctrl_dtemp_2 = DRA752_DTEMP_GPU_2_OFFSET, 202 + .ctrl_dtemp_3 = DRA752_DTEMP_GPU_3_OFFSET, 203 + .ctrl_dtemp_4 = DRA752_DTEMP_GPU_4_OFFSET, 204 + .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET, 205 + }; 206 + 207 + /* Thresholds and limits for DRA752 MPU temperature sensor */ 208 + static struct temp_sensor_data dra752_mpu_temp_sensor_data = { 209 + .tshut_hot = DRA752_MPU_TSHUT_HOT, 210 + .tshut_cold = DRA752_MPU_TSHUT_COLD, 211 + .t_hot = DRA752_MPU_T_HOT, 212 + .t_cold = DRA752_MPU_T_COLD, 213 + .min_freq = DRA752_MPU_MIN_FREQ, 214 + .max_freq = DRA752_MPU_MAX_FREQ, 215 + .max_temp = DRA752_MPU_MAX_TEMP, 216 + .min_temp = DRA752_MPU_MIN_TEMP, 217 + .hyst_val = DRA752_MPU_HYST_VAL, 218 + .update_int1 = 1000, 219 + .update_int2 = 2000, 220 + }; 221 + 222 + /* Thresholds and limits for DRA752 GPU temperature sensor */ 223 + static struct temp_sensor_data dra752_gpu_temp_sensor_data = { 224 + .tshut_hot = DRA752_GPU_TSHUT_HOT, 225 + .tshut_cold = DRA752_GPU_TSHUT_COLD, 226 + .t_hot = DRA752_GPU_T_HOT, 227 + .t_cold = DRA752_GPU_T_COLD, 228 + .min_freq = DRA752_GPU_MIN_FREQ, 229 + .max_freq = DRA752_GPU_MAX_FREQ, 230 + .max_temp = DRA752_GPU_MAX_TEMP, 231 + .min_temp = DRA752_GPU_MIN_TEMP, 232 + .hyst_val = DRA752_GPU_HYST_VAL, 233 + .update_int1 = 1000, 234 + .update_int2 = 2000, 235 + }; 236 + 237 + /* Thresholds and limits for DRA752 CORE temperature sensor */ 238 + static struct temp_sensor_data dra752_core_temp_sensor_data = { 239 + .tshut_hot = DRA752_CORE_TSHUT_HOT, 240 + .tshut_cold = DRA752_CORE_TSHUT_COLD, 241 + .t_hot = DRA752_CORE_T_HOT, 242 + .t_cold = DRA752_CORE_T_COLD, 243 + .min_freq = DRA752_CORE_MIN_FREQ, 244 + .max_freq = DRA752_CORE_MAX_FREQ, 245 + .max_temp = DRA752_CORE_MAX_TEMP, 246 + .min_temp = DRA752_CORE_MIN_TEMP, 247 + .hyst_val = DRA752_CORE_HYST_VAL, 248 + .update_int1 = 1000, 249 + .update_int2 = 2000, 250 + }; 251 + 252 + /* Thresholds and limits for DRA752 DSPEVE temperature sensor */ 253 + static struct temp_sensor_data dra752_dspeve_temp_sensor_data = { 254 + .tshut_hot = DRA752_DSPEVE_TSHUT_HOT, 255 + .tshut_cold = DRA752_DSPEVE_TSHUT_COLD, 256 + .t_hot = DRA752_DSPEVE_T_HOT, 257 + .t_cold = DRA752_DSPEVE_T_COLD, 258 + .min_freq = DRA752_DSPEVE_MIN_FREQ, 259 + .max_freq = DRA752_DSPEVE_MAX_FREQ, 260 + .max_temp = DRA752_DSPEVE_MAX_TEMP, 261 + .min_temp = DRA752_DSPEVE_MIN_TEMP, 262 + .hyst_val = DRA752_DSPEVE_HYST_VAL, 263 + .update_int1 = 1000, 264 + .update_int2 = 2000, 265 + }; 266 + 267 + /* Thresholds and limits for DRA752 IVA temperature sensor */ 268 + static struct temp_sensor_data dra752_iva_temp_sensor_data = { 269 + .tshut_hot = DRA752_IVA_TSHUT_HOT, 270 + .tshut_cold = DRA752_IVA_TSHUT_COLD, 271 + .t_hot = DRA752_IVA_T_HOT, 272 + .t_cold = DRA752_IVA_T_COLD, 273 + .min_freq = DRA752_IVA_MIN_FREQ, 274 + .max_freq = DRA752_IVA_MAX_FREQ, 275 + .max_temp = DRA752_IVA_MAX_TEMP, 276 + .min_temp = DRA752_IVA_MIN_TEMP, 277 + .hyst_val = DRA752_IVA_HYST_VAL, 278 + .update_int1 = 1000, 279 + .update_int2 = 2000, 280 + }; 281 + 282 + /* 283 + * DRA752 : Temperature values in milli degree celsius 284 + * ADC code values from 540 to 945 285 + */ 286 + static 287 + int dra752_adc_to_temp[DRA752_ADC_END_VALUE - DRA752_ADC_START_VALUE + 1] = { 288 + /* Index 540 - 549 */ 289 + -40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200, 290 + -37800, 291 + /* Index 550 - 559 */ 292 + -37400, -37000, -36600, -36200, -35800, -35300, -34700, -34200, -33800, 293 + -33400, 294 + /* Index 560 - 569 */ 295 + -33000, -32600, -32200, -31800, -31400, -31000, -30600, -30200, -29800, 296 + -29400, 297 + /* Index 570 - 579 */ 298 + -29000, -28600, -28200, -27700, -27100, -26600, -26200, -25800, -25400, 299 + -25000, 300 + /* Index 580 - 589 */ 301 + -24600, -24200, -23800, -23400, -23000, -22600, -22200, -21800, -21400, 302 + -21000, 303 + /* Index 590 - 599 */ 304 + -20500, -19900, -19400, -19000, -18600, -18200, -17800, -17400, -17000, 305 + -16600, 306 + /* Index 600 - 609 */ 307 + -16200, -15800, -15400, -15000, -14600, -14200, -13800, -13400, -13000, 308 + -12500, 309 + /* Index 610 - 619 */ 310 + -11900, -11400, -11000, -10600, -10200, -9800, -9400, -9000, -8600, 311 + -8200, 312 + /* Index 620 - 629 */ 313 + -7800, -7400, -7000, -6600, -6200, -5800, -5400, -5000, -4500, 314 + -3900, 315 + /* Index 630 - 639 */ 316 + -3400, -3000, -2600, -2200, -1800, -1400, -1000, -600, -200, 317 + 200, 318 + /* Index 640 - 649 */ 319 + 600, 1000, 1400, 1800, 2200, 2600, 3000, 3400, 3900, 320 + 4500, 321 + /* Index 650 - 659 */ 322 + 5000, 5400, 5800, 6200, 6600, 7000, 7400, 7800, 8200, 323 + 8600, 324 + /* Index 660 - 669 */ 325 + 9000, 9400, 9800, 10200, 10600, 11000, 11400, 11800, 12200, 326 + 12700, 327 + /* Index 670 - 679 */ 328 + 13300, 13800, 14200, 14600, 15000, 15400, 15800, 16200, 16600, 329 + 17000, 330 + /* Index 680 - 689 */ 331 + 17400, 17800, 18200, 18600, 19000, 19400, 19800, 20200, 20600, 332 + 21000, 333 + /* Index 690 - 699 */ 334 + 21400, 21900, 22500, 23000, 23400, 23800, 24200, 24600, 25000, 335 + 25400, 336 + /* Index 700 - 709 */ 337 + 25800, 26200, 26600, 27000, 27400, 27800, 28200, 28600, 29000, 338 + 29400, 339 + /* Index 710 - 719 */ 340 + 29800, 30200, 30600, 31000, 31400, 31900, 32500, 33000, 33400, 341 + 33800, 342 + /* Index 720 - 729 */ 343 + 34200, 34600, 35000, 35400, 35800, 36200, 36600, 37000, 37400, 344 + 37800, 345 + /* Index 730 - 739 */ 346 + 38200, 38600, 39000, 39400, 39800, 40200, 40600, 41000, 41400, 347 + 41800, 348 + /* Index 740 - 749 */ 349 + 42200, 42600, 43100, 43700, 44200, 44600, 45000, 45400, 45800, 350 + 46200, 351 + /* Index 750 - 759 */ 352 + 46600, 47000, 47400, 47800, 48200, 48600, 49000, 49400, 49800, 353 + 50200, 354 + /* Index 760 - 769 */ 355 + 50600, 51000, 51400, 51800, 52200, 52600, 53000, 53400, 53800, 356 + 54200, 357 + /* Index 770 - 779 */ 358 + 54600, 55000, 55400, 55900, 56500, 57000, 57400, 57800, 58200, 359 + 58600, 360 + /* Index 780 - 789 */ 361 + 59000, 59400, 59800, 60200, 60600, 61000, 61400, 61800, 62200, 362 + 62600, 363 + /* Index 790 - 799 */ 364 + 63000, 63400, 63800, 64200, 64600, 65000, 65400, 65800, 66200, 365 + 66600, 366 + /* Index 800 - 809 */ 367 + 67000, 67400, 67800, 68200, 68600, 69000, 69400, 69800, 70200, 368 + 70600, 369 + /* Index 810 - 819 */ 370 + 71000, 71500, 72100, 72600, 73000, 73400, 73800, 74200, 74600, 371 + 75000, 372 + /* Index 820 - 829 */ 373 + 75400, 75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600, 374 + 79000, 375 + /* Index 830 - 839 */ 376 + 79400, 79800, 80200, 80600, 81000, 81400, 81800, 82200, 82600, 377 + 83000, 378 + /* Index 840 - 849 */ 379 + 83400, 83800, 84200, 84600, 85000, 85400, 85800, 86200, 86600, 380 + 87000, 381 + /* Index 850 - 859 */ 382 + 87400, 87800, 88200, 88600, 89000, 89400, 89800, 90200, 90600, 383 + 91000, 384 + /* Index 860 - 869 */ 385 + 91400, 91800, 92200, 92600, 93000, 93400, 93800, 94200, 94600, 386 + 95000, 387 + /* Index 870 - 879 */ 388 + 95400, 95800, 96200, 96600, 97000, 97500, 98100, 98600, 99000, 389 + 99400, 390 + /* Index 880 - 889 */ 391 + 99800, 100200, 100600, 101000, 101400, 101800, 102200, 102600, 103000, 392 + 103400, 393 + /* Index 890 - 899 */ 394 + 103800, 104200, 104600, 105000, 105400, 105800, 106200, 106600, 107000, 395 + 107400, 396 + /* Index 900 - 909 */ 397 + 107800, 108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000, 398 + 111400, 399 + /* Index 910 - 919 */ 400 + 111800, 112200, 112600, 113000, 113400, 113800, 114200, 114600, 115000, 401 + 115400, 402 + /* Index 920 - 929 */ 403 + 115800, 116200, 116600, 117000, 117400, 117800, 118200, 118600, 119000, 404 + 119400, 405 + /* Index 930 - 939 */ 406 + 119800, 120200, 120600, 121000, 121400, 121800, 122200, 122600, 123000, 407 + 123400, 408 + /* Index 940 - 945 */ 409 + 123800, 124200, 124600, 124900, 125000, 125000, 410 + }; 411 + 412 + /* DRA752 data */ 413 + const struct ti_bandgap_data dra752_data = { 414 + .features = TI_BANDGAP_FEATURE_TSHUT_CONFIG | 415 + TI_BANDGAP_FEATURE_FREEZE_BIT | 416 + TI_BANDGAP_FEATURE_TALERT | 417 + TI_BANDGAP_FEATURE_COUNTER_DELAY | 418 + TI_BANDGAP_FEATURE_HISTORY_BUFFER, 419 + .fclock_name = "l3instr_ts_gclk_div", 420 + .div_ck_name = "l3instr_ts_gclk_div", 421 + .conv_table = dra752_adc_to_temp, 422 + .adc_start_val = DRA752_ADC_START_VALUE, 423 + .adc_end_val = DRA752_ADC_END_VALUE, 424 + .expose_sensor = ti_thermal_expose_sensor, 425 + .remove_sensor = ti_thermal_remove_sensor, 426 + .sensors = { 427 + { 428 + .registers = &dra752_mpu_temp_sensor_registers, 429 + .ts_data = &dra752_mpu_temp_sensor_data, 430 + .domain = "cpu", 431 + .register_cooling = ti_thermal_register_cpu_cooling, 432 + .unregister_cooling = ti_thermal_unregister_cpu_cooling, 433 + .slope = DRA752_GRADIENT_SLOPE, 434 + .constant = DRA752_GRADIENT_CONST, 435 + .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 436 + .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 437 + }, 438 + { 439 + .registers = &dra752_gpu_temp_sensor_registers, 440 + .ts_data = &dra752_gpu_temp_sensor_data, 441 + .domain = "gpu", 442 + .slope = DRA752_GRADIENT_SLOPE, 443 + .constant = DRA752_GRADIENT_CONST, 444 + .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 445 + .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 446 + }, 447 + { 448 + .registers = &dra752_core_temp_sensor_registers, 449 + .ts_data = &dra752_core_temp_sensor_data, 450 + .domain = "core", 451 + .slope = DRA752_GRADIENT_SLOPE, 452 + .constant = DRA752_GRADIENT_CONST, 453 + .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 454 + .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 455 + }, 456 + { 457 + .registers = &dra752_dspeve_temp_sensor_registers, 458 + .ts_data = &dra752_dspeve_temp_sensor_data, 459 + .domain = "dspeve", 460 + .slope = DRA752_GRADIENT_SLOPE, 461 + .constant = DRA752_GRADIENT_CONST, 462 + .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 463 + .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 464 + }, 465 + { 466 + .registers = &dra752_iva_temp_sensor_registers, 467 + .ts_data = &dra752_iva_temp_sensor_data, 468 + .domain = "iva", 469 + .slope = DRA752_GRADIENT_SLOPE, 470 + .constant = DRA752_GRADIENT_CONST, 471 + .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, 472 + .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, 473 + }, 474 + }, 475 + .sensor_count = 5, 476 + };
+642
drivers/thermal/x86_pkg_temp_thermal.c
··· 1 + /* 2 + * x86_pkg_temp_thermal driver 3 + * Copyright (c) 2013, Intel Corporation. 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms and conditions of the GNU General Public License, 7 + * version 2, as published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope it will be useful, but WITHOUT 10 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 + * more details. 13 + * 14 + * You should have received a copy of the GNU General Public License along with 15 + * this program; if not, write to the Free Software Foundation, Inc. 16 + * 17 + */ 18 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 19 + 20 + #include <linux/module.h> 21 + #include <linux/init.h> 22 + #include <linux/err.h> 23 + #include <linux/param.h> 24 + #include <linux/device.h> 25 + #include <linux/platform_device.h> 26 + #include <linux/cpu.h> 27 + #include <linux/smp.h> 28 + #include <linux/slab.h> 29 + #include <linux/pm.h> 30 + #include <linux/thermal.h> 31 + #include <linux/debugfs.h> 32 + #include <asm/cpu_device_id.h> 33 + #include <asm/mce.h> 34 + 35 + /* 36 + * Rate control delay: Idea is to introduce denounce effect 37 + * This should be long enough to avoid reduce events, when 38 + * threshold is set to a temperature, which is constantly 39 + * violated, but at the short enough to take any action. 40 + * The action can be remove threshold or change it to next 41 + * interesting setting. Based on experiments, in around 42 + * every 5 seconds under load will give us a significant 43 + * temperature change. 44 + */ 45 + #define PKG_TEMP_THERMAL_NOTIFY_DELAY 5000 46 + static int notify_delay_ms = PKG_TEMP_THERMAL_NOTIFY_DELAY; 47 + module_param(notify_delay_ms, int, 0644); 48 + MODULE_PARM_DESC(notify_delay_ms, 49 + "User space notification delay in milli seconds."); 50 + 51 + /* Number of trip points in thermal zone. Currently it can't 52 + * be more than 2. MSR can allow setting and getting notifications 53 + * for only 2 thresholds. This define enforces this, if there 54 + * is some wrong values returned by cpuid for number of thresholds. 55 + */ 56 + #define MAX_NUMBER_OF_TRIPS 2 57 + 58 + struct phy_dev_entry { 59 + struct list_head list; 60 + u16 phys_proc_id; 61 + u16 first_cpu; 62 + u32 tj_max; 63 + int ref_cnt; 64 + u32 start_pkg_therm_low; 65 + u32 start_pkg_therm_high; 66 + struct thermal_zone_device *tzone; 67 + }; 68 + 69 + /* List maintaining number of package instances */ 70 + static LIST_HEAD(phy_dev_list); 71 + static DEFINE_MUTEX(phy_dev_list_mutex); 72 + 73 + /* Interrupt to work function schedule queue */ 74 + static DEFINE_PER_CPU(struct delayed_work, pkg_temp_thermal_threshold_work); 75 + 76 + /* To track if the work is already scheduled on a package */ 77 + static u8 *pkg_work_scheduled; 78 + 79 + /* Spin lock to prevent races with pkg_work_scheduled */ 80 + static spinlock_t pkg_work_lock; 81 + static u16 max_phy_id; 82 + 83 + /* Debug counters to show using debugfs */ 84 + static struct dentry *debugfs; 85 + static unsigned int pkg_interrupt_cnt; 86 + static unsigned int pkg_work_cnt; 87 + 88 + static int pkg_temp_debugfs_init(void) 89 + { 90 + struct dentry *d; 91 + 92 + debugfs = debugfs_create_dir("pkg_temp_thermal", NULL); 93 + if (!debugfs) 94 + return -ENOENT; 95 + 96 + d = debugfs_create_u32("pkg_thres_interrupt", S_IRUGO, debugfs, 97 + (u32 *)&pkg_interrupt_cnt); 98 + if (!d) 99 + goto err_out; 100 + 101 + d = debugfs_create_u32("pkg_thres_work", S_IRUGO, debugfs, 102 + (u32 *)&pkg_work_cnt); 103 + if (!d) 104 + goto err_out; 105 + 106 + return 0; 107 + 108 + err_out: 109 + debugfs_remove_recursive(debugfs); 110 + return -ENOENT; 111 + } 112 + 113 + static struct phy_dev_entry 114 + *pkg_temp_thermal_get_phy_entry(unsigned int cpu) 115 + { 116 + u16 phys_proc_id = topology_physical_package_id(cpu); 117 + struct phy_dev_entry *phy_ptr; 118 + 119 + mutex_lock(&phy_dev_list_mutex); 120 + 121 + list_for_each_entry(phy_ptr, &phy_dev_list, list) 122 + if (phy_ptr->phys_proc_id == phys_proc_id) { 123 + mutex_unlock(&phy_dev_list_mutex); 124 + return phy_ptr; 125 + } 126 + 127 + mutex_unlock(&phy_dev_list_mutex); 128 + 129 + return NULL; 130 + } 131 + 132 + /* 133 + * tj-max is is interesting because threshold is set relative to this 134 + * temperature. 135 + */ 136 + static int get_tj_max(int cpu, u32 *tj_max) 137 + { 138 + u32 eax, edx; 139 + u32 val; 140 + int err; 141 + 142 + err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); 143 + if (err) 144 + goto err_ret; 145 + else { 146 + val = (eax >> 16) & 0xff; 147 + if (val) 148 + *tj_max = val * 1000; 149 + else { 150 + err = -EINVAL; 151 + goto err_ret; 152 + } 153 + } 154 + 155 + return 0; 156 + err_ret: 157 + *tj_max = 0; 158 + return err; 159 + } 160 + 161 + static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp) 162 + { 163 + u32 eax, edx; 164 + struct phy_dev_entry *phy_dev_entry; 165 + 166 + phy_dev_entry = tzd->devdata; 167 + rdmsr_on_cpu(phy_dev_entry->first_cpu, MSR_IA32_PACKAGE_THERM_STATUS, 168 + &eax, &edx); 169 + if (eax & 0x80000000) { 170 + *temp = phy_dev_entry->tj_max - 171 + ((eax >> 16) & 0x7f) * 1000; 172 + pr_debug("sys_get_curr_temp %ld\n", *temp); 173 + return 0; 174 + } 175 + 176 + return -EINVAL; 177 + } 178 + 179 + static int sys_get_trip_temp(struct thermal_zone_device *tzd, 180 + int trip, unsigned long *temp) 181 + { 182 + u32 eax, edx; 183 + struct phy_dev_entry *phy_dev_entry; 184 + u32 mask, shift; 185 + unsigned long thres_reg_value; 186 + int ret; 187 + 188 + if (trip >= MAX_NUMBER_OF_TRIPS) 189 + return -EINVAL; 190 + 191 + phy_dev_entry = tzd->devdata; 192 + 193 + if (trip) { 194 + mask = THERM_MASK_THRESHOLD1; 195 + shift = THERM_SHIFT_THRESHOLD1; 196 + } else { 197 + mask = THERM_MASK_THRESHOLD0; 198 + shift = THERM_SHIFT_THRESHOLD0; 199 + } 200 + 201 + ret = rdmsr_on_cpu(phy_dev_entry->first_cpu, 202 + MSR_IA32_PACKAGE_THERM_INTERRUPT, &eax, &edx); 203 + if (ret < 0) 204 + return -EINVAL; 205 + 206 + thres_reg_value = (eax & mask) >> shift; 207 + if (thres_reg_value) 208 + *temp = phy_dev_entry->tj_max - thres_reg_value * 1000; 209 + else 210 + *temp = 0; 211 + pr_debug("sys_get_trip_temp %ld\n", *temp); 212 + 213 + return 0; 214 + } 215 + 216 + int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, 217 + unsigned long temp) 218 + { 219 + u32 l, h; 220 + struct phy_dev_entry *phy_dev_entry; 221 + u32 mask, shift, intr; 222 + int ret; 223 + 224 + phy_dev_entry = tzd->devdata; 225 + 226 + if (trip >= MAX_NUMBER_OF_TRIPS || temp >= phy_dev_entry->tj_max) 227 + return -EINVAL; 228 + 229 + ret = rdmsr_on_cpu(phy_dev_entry->first_cpu, 230 + MSR_IA32_PACKAGE_THERM_INTERRUPT, 231 + &l, &h); 232 + if (ret < 0) 233 + return -EINVAL; 234 + 235 + if (trip) { 236 + mask = THERM_MASK_THRESHOLD1; 237 + shift = THERM_SHIFT_THRESHOLD1; 238 + intr = THERM_INT_THRESHOLD1_ENABLE; 239 + } else { 240 + mask = THERM_MASK_THRESHOLD0; 241 + shift = THERM_SHIFT_THRESHOLD0; 242 + intr = THERM_INT_THRESHOLD0_ENABLE; 243 + } 244 + l &= ~mask; 245 + /* 246 + * When users space sets a trip temperature == 0, which is indication 247 + * that, it is no longer interested in receiving notifications. 248 + */ 249 + if (!temp) 250 + l &= ~intr; 251 + else { 252 + l |= (phy_dev_entry->tj_max - temp)/1000 << shift; 253 + l |= intr; 254 + } 255 + 256 + return wrmsr_on_cpu(phy_dev_entry->first_cpu, 257 + MSR_IA32_PACKAGE_THERM_INTERRUPT, 258 + l, h); 259 + } 260 + 261 + static int sys_get_trip_type(struct thermal_zone_device *thermal, 262 + int trip, enum thermal_trip_type *type) 263 + { 264 + 265 + *type = THERMAL_TRIP_PASSIVE; 266 + 267 + return 0; 268 + } 269 + 270 + /* Thermal zone callback registry */ 271 + static struct thermal_zone_device_ops tzone_ops = { 272 + .get_temp = sys_get_curr_temp, 273 + .get_trip_temp = sys_get_trip_temp, 274 + .get_trip_type = sys_get_trip_type, 275 + .set_trip_temp = sys_set_trip_temp, 276 + }; 277 + 278 + static bool pkg_temp_thermal_platform_thermal_rate_control(void) 279 + { 280 + return true; 281 + } 282 + 283 + /* Enable threshold interrupt on local package/cpu */ 284 + static inline void enable_pkg_thres_interrupt(void) 285 + { 286 + u32 l, h; 287 + u8 thres_0, thres_1; 288 + 289 + rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h); 290 + /* only enable/disable if it had valid threshold value */ 291 + thres_0 = (l & THERM_MASK_THRESHOLD0) >> THERM_SHIFT_THRESHOLD0; 292 + thres_1 = (l & THERM_MASK_THRESHOLD1) >> THERM_SHIFT_THRESHOLD1; 293 + if (thres_0) 294 + l |= THERM_INT_THRESHOLD0_ENABLE; 295 + if (thres_1) 296 + l |= THERM_INT_THRESHOLD1_ENABLE; 297 + wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h); 298 + } 299 + 300 + /* Disable threshold interrupt on local package/cpu */ 301 + static inline void disable_pkg_thres_interrupt(void) 302 + { 303 + u32 l, h; 304 + rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h); 305 + wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, 306 + l & (~THERM_INT_THRESHOLD0_ENABLE) & 307 + (~THERM_INT_THRESHOLD1_ENABLE), h); 308 + } 309 + 310 + static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work) 311 + { 312 + __u64 msr_val; 313 + int cpu = smp_processor_id(); 314 + int phy_id = topology_physical_package_id(cpu); 315 + struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu); 316 + bool notify = false; 317 + 318 + if (!phdev) 319 + return; 320 + 321 + spin_lock(&pkg_work_lock); 322 + ++pkg_work_cnt; 323 + if (unlikely(phy_id > max_phy_id)) { 324 + spin_unlock(&pkg_work_lock); 325 + return; 326 + } 327 + pkg_work_scheduled[phy_id] = 0; 328 + spin_unlock(&pkg_work_lock); 329 + 330 + enable_pkg_thres_interrupt(); 331 + rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val); 332 + if (msr_val & THERM_LOG_THRESHOLD0) { 333 + wrmsrl(MSR_IA32_PACKAGE_THERM_STATUS, 334 + msr_val & ~THERM_LOG_THRESHOLD0); 335 + notify = true; 336 + } 337 + if (msr_val & THERM_LOG_THRESHOLD1) { 338 + wrmsrl(MSR_IA32_PACKAGE_THERM_STATUS, 339 + msr_val & ~THERM_LOG_THRESHOLD1); 340 + notify = true; 341 + } 342 + if (notify) { 343 + pr_debug("thermal_zone_device_update\n"); 344 + thermal_zone_device_update(phdev->tzone); 345 + } 346 + } 347 + 348 + static int pkg_temp_thermal_platform_thermal_notify(__u64 msr_val) 349 + { 350 + unsigned long flags; 351 + int cpu = smp_processor_id(); 352 + int phy_id = topology_physical_package_id(cpu); 353 + 354 + /* 355 + * When a package is in interrupted state, all CPU's in that package 356 + * are in the same interrupt state. So scheduling on any one CPU in 357 + * the package is enough and simply return for others. 358 + */ 359 + spin_lock_irqsave(&pkg_work_lock, flags); 360 + ++pkg_interrupt_cnt; 361 + if (unlikely(phy_id > max_phy_id) || unlikely(!pkg_work_scheduled) || 362 + pkg_work_scheduled[phy_id]) { 363 + disable_pkg_thres_interrupt(); 364 + spin_unlock_irqrestore(&pkg_work_lock, flags); 365 + return -EINVAL; 366 + } 367 + pkg_work_scheduled[phy_id] = 1; 368 + spin_unlock_irqrestore(&pkg_work_lock, flags); 369 + 370 + disable_pkg_thres_interrupt(); 371 + schedule_delayed_work_on(cpu, 372 + &per_cpu(pkg_temp_thermal_threshold_work, cpu), 373 + msecs_to_jiffies(notify_delay_ms)); 374 + return 0; 375 + } 376 + 377 + static int find_siblings_cpu(int cpu) 378 + { 379 + int i; 380 + int id = topology_physical_package_id(cpu); 381 + 382 + for_each_online_cpu(i) 383 + if (i != cpu && topology_physical_package_id(i) == id) 384 + return i; 385 + 386 + return 0; 387 + } 388 + 389 + static int pkg_temp_thermal_device_add(unsigned int cpu) 390 + { 391 + int err; 392 + u32 tj_max; 393 + struct phy_dev_entry *phy_dev_entry; 394 + char buffer[30]; 395 + int thres_count; 396 + u32 eax, ebx, ecx, edx; 397 + 398 + cpuid(6, &eax, &ebx, &ecx, &edx); 399 + thres_count = ebx & 0x07; 400 + if (!thres_count) 401 + return -ENODEV; 402 + 403 + thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS); 404 + 405 + err = get_tj_max(cpu, &tj_max); 406 + if (err) 407 + goto err_ret; 408 + 409 + mutex_lock(&phy_dev_list_mutex); 410 + 411 + phy_dev_entry = kzalloc(sizeof(*phy_dev_entry), GFP_KERNEL); 412 + if (!phy_dev_entry) { 413 + err = -ENOMEM; 414 + goto err_ret_unlock; 415 + } 416 + 417 + spin_lock(&pkg_work_lock); 418 + if (topology_physical_package_id(cpu) > max_phy_id) 419 + max_phy_id = topology_physical_package_id(cpu); 420 + pkg_work_scheduled = krealloc(pkg_work_scheduled, 421 + (max_phy_id+1) * sizeof(u8), GFP_ATOMIC); 422 + if (!pkg_work_scheduled) { 423 + spin_unlock(&pkg_work_lock); 424 + err = -ENOMEM; 425 + goto err_ret_free; 426 + } 427 + pkg_work_scheduled[topology_physical_package_id(cpu)] = 0; 428 + spin_unlock(&pkg_work_lock); 429 + 430 + phy_dev_entry->phys_proc_id = topology_physical_package_id(cpu); 431 + phy_dev_entry->first_cpu = cpu; 432 + phy_dev_entry->tj_max = tj_max; 433 + phy_dev_entry->ref_cnt = 1; 434 + snprintf(buffer, sizeof(buffer), "pkg-temp-%d\n", 435 + phy_dev_entry->phys_proc_id); 436 + phy_dev_entry->tzone = thermal_zone_device_register(buffer, 437 + thres_count, 438 + (thres_count == MAX_NUMBER_OF_TRIPS) ? 439 + 0x03 : 0x01, 440 + phy_dev_entry, &tzone_ops, NULL, 0, 0); 441 + if (IS_ERR(phy_dev_entry->tzone)) { 442 + err = PTR_ERR(phy_dev_entry->tzone); 443 + goto err_ret_free; 444 + } 445 + /* Store MSR value for package thermal interrupt, to restore at exit */ 446 + rdmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, 447 + &phy_dev_entry->start_pkg_therm_low, 448 + &phy_dev_entry->start_pkg_therm_high); 449 + 450 + list_add_tail(&phy_dev_entry->list, &phy_dev_list); 451 + pr_debug("pkg_temp_thermal_device_add :phy_id %d cpu %d\n", 452 + phy_dev_entry->phys_proc_id, cpu); 453 + 454 + mutex_unlock(&phy_dev_list_mutex); 455 + 456 + return 0; 457 + 458 + err_ret_free: 459 + kfree(phy_dev_entry); 460 + err_ret_unlock: 461 + mutex_unlock(&phy_dev_list_mutex); 462 + 463 + err_ret: 464 + return err; 465 + } 466 + 467 + static int pkg_temp_thermal_device_remove(unsigned int cpu) 468 + { 469 + struct phy_dev_entry *n; 470 + u16 phys_proc_id = topology_physical_package_id(cpu); 471 + struct phy_dev_entry *phdev = 472 + pkg_temp_thermal_get_phy_entry(cpu); 473 + 474 + if (!phdev) 475 + return -ENODEV; 476 + 477 + mutex_lock(&phy_dev_list_mutex); 478 + /* If we are loosing the first cpu for this package, we need change */ 479 + if (phdev->first_cpu == cpu) { 480 + phdev->first_cpu = find_siblings_cpu(cpu); 481 + pr_debug("thermal_device_remove: first cpu switched %d\n", 482 + phdev->first_cpu); 483 + } 484 + /* 485 + * It is possible that no siblings left as this was the last cpu 486 + * going offline. We don't need to worry about this assignment 487 + * as the phydev entry will be removed in this case and 488 + * thermal zone is removed. 489 + */ 490 + --phdev->ref_cnt; 491 + pr_debug("thermal_device_remove: pkg: %d cpu %d ref_cnt %d\n", 492 + phys_proc_id, cpu, phdev->ref_cnt); 493 + if (!phdev->ref_cnt) 494 + list_for_each_entry_safe(phdev, n, &phy_dev_list, list) { 495 + if (phdev->phys_proc_id == phys_proc_id) { 496 + thermal_zone_device_unregister(phdev->tzone); 497 + list_del(&phdev->list); 498 + kfree(phdev); 499 + break; 500 + } 501 + } 502 + mutex_unlock(&phy_dev_list_mutex); 503 + 504 + return 0; 505 + } 506 + 507 + static int get_core_online(unsigned int cpu) 508 + { 509 + struct cpuinfo_x86 *c = &cpu_data(cpu); 510 + struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu); 511 + 512 + /* Check if there is already an instance for this package */ 513 + if (!phdev) { 514 + if (!cpu_has(c, X86_FEATURE_DTHERM) && 515 + !cpu_has(c, X86_FEATURE_PTS)) 516 + return -ENODEV; 517 + if (pkg_temp_thermal_device_add(cpu)) 518 + return -ENODEV; 519 + } else { 520 + mutex_lock(&phy_dev_list_mutex); 521 + ++phdev->ref_cnt; 522 + pr_debug("get_core_online: cpu %d ref_cnt %d\n", 523 + cpu, phdev->ref_cnt); 524 + mutex_unlock(&phy_dev_list_mutex); 525 + } 526 + INIT_DELAYED_WORK(&per_cpu(pkg_temp_thermal_threshold_work, cpu), 527 + pkg_temp_thermal_threshold_work_fn); 528 + 529 + pr_debug("get_core_online: cpu %d successful\n", cpu); 530 + 531 + return 0; 532 + } 533 + 534 + static void put_core_offline(unsigned int cpu) 535 + { 536 + if (!pkg_temp_thermal_device_remove(cpu)) 537 + cancel_delayed_work_sync( 538 + &per_cpu(pkg_temp_thermal_threshold_work, cpu)); 539 + 540 + pr_debug("put_core_offline: cpu %d\n", cpu); 541 + } 542 + 543 + static int pkg_temp_thermal_cpu_callback(struct notifier_block *nfb, 544 + unsigned long action, void *hcpu) 545 + { 546 + unsigned int cpu = (unsigned long) hcpu; 547 + 548 + switch (action) { 549 + case CPU_ONLINE: 550 + case CPU_DOWN_FAILED: 551 + get_core_online(cpu); 552 + break; 553 + case CPU_DOWN_PREPARE: 554 + put_core_offline(cpu); 555 + break; 556 + } 557 + return NOTIFY_OK; 558 + } 559 + 560 + static struct notifier_block pkg_temp_thermal_notifier __refdata = { 561 + .notifier_call = pkg_temp_thermal_cpu_callback, 562 + }; 563 + 564 + static const struct x86_cpu_id __initconst pkg_temp_thermal_ids[] = { 565 + { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM }, 566 + {} 567 + }; 568 + MODULE_DEVICE_TABLE(x86cpu, pkg_temp_thermal_ids); 569 + 570 + static int __init pkg_temp_thermal_init(void) 571 + { 572 + int i; 573 + 574 + if (!x86_match_cpu(pkg_temp_thermal_ids)) 575 + return -ENODEV; 576 + 577 + spin_lock_init(&pkg_work_lock); 578 + platform_thermal_package_notify = 579 + pkg_temp_thermal_platform_thermal_notify; 580 + platform_thermal_package_rate_control = 581 + pkg_temp_thermal_platform_thermal_rate_control; 582 + 583 + get_online_cpus(); 584 + for_each_online_cpu(i) 585 + if (get_core_online(i)) 586 + goto err_ret; 587 + register_hotcpu_notifier(&pkg_temp_thermal_notifier); 588 + put_online_cpus(); 589 + 590 + pkg_temp_debugfs_init(); /* Don't care if fails */ 591 + 592 + return 0; 593 + 594 + err_ret: 595 + get_online_cpus(); 596 + for_each_online_cpu(i) 597 + put_core_offline(i); 598 + put_online_cpus(); 599 + kfree(pkg_work_scheduled); 600 + platform_thermal_package_notify = NULL; 601 + platform_thermal_package_rate_control = NULL; 602 + 603 + return -ENODEV; 604 + } 605 + 606 + static void __exit pkg_temp_thermal_exit(void) 607 + { 608 + struct phy_dev_entry *phdev, *n; 609 + int i; 610 + 611 + get_online_cpus(); 612 + unregister_hotcpu_notifier(&pkg_temp_thermal_notifier); 613 + mutex_lock(&phy_dev_list_mutex); 614 + list_for_each_entry_safe(phdev, n, &phy_dev_list, list) { 615 + /* Retore old MSR value for package thermal interrupt */ 616 + wrmsr_on_cpu(phdev->first_cpu, 617 + MSR_IA32_PACKAGE_THERM_INTERRUPT, 618 + phdev->start_pkg_therm_low, 619 + phdev->start_pkg_therm_high); 620 + thermal_zone_device_unregister(phdev->tzone); 621 + list_del(&phdev->list); 622 + kfree(phdev); 623 + } 624 + mutex_unlock(&phy_dev_list_mutex); 625 + platform_thermal_package_notify = NULL; 626 + platform_thermal_package_rate_control = NULL; 627 + for_each_online_cpu(i) 628 + cancel_delayed_work_sync( 629 + &per_cpu(pkg_temp_thermal_threshold_work, i)); 630 + put_online_cpus(); 631 + 632 + kfree(pkg_work_scheduled); 633 + 634 + debugfs_remove_recursive(debugfs); 635 + } 636 + 637 + module_init(pkg_temp_thermal_init) 638 + module_exit(pkg_temp_thermal_exit) 639 + 640 + MODULE_DESCRIPTION("X86 PKG TEMP Thermal Driver"); 641 + MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 642 + MODULE_LICENSE("GPL v2");
+2 -2
include/linux/cpu_cooling.h
··· 41 41 */ 42 42 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev); 43 43 44 - unsigned long cpufreq_cooling_get_level(unsigned int, unsigned int); 44 + unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq); 45 45 #else /* !CONFIG_CPU_THERMAL */ 46 46 static inline struct thermal_cooling_device * 47 47 cpufreq_cooling_register(const struct cpumask *clip_cpus) ··· 54 54 return; 55 55 } 56 56 static inline 57 - unsigned long cpufreq_cooling_get_level(unsigned int, unsigned int) 57 + unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq) 58 58 { 59 59 return THERMAL_CSTATE_INVALID; 60 60 }