diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-11 15:26:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-11 15:26:08 -0400 |
commit | 8cbd0eefcaf8cc32ded2bf229f0fc379b2ad69f2 (patch) | |
tree | 08cc79685a888470509b969a2c079249ee28b69f /drivers | |
parent | 1466b77a7be75144dee1cb09839be3435854dd0b (diff) | |
parent | e8d39240d635ed9bcaddbec898b1c9f063c5dbb2 (diff) |
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
...
Diffstat (limited to 'drivers')
27 files changed, 1492 insertions, 132 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index f64b662c74db..3227ebeae3f1 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -120,8 +120,6 @@ source "drivers/staging/gdm72xx/Kconfig" | |||
120 | 120 | ||
121 | source "drivers/staging/csr/Kconfig" | 121 | source "drivers/staging/csr/Kconfig" |
122 | 122 | ||
123 | source "drivers/staging/ti-soc-thermal/Kconfig" | ||
124 | |||
125 | source "drivers/staging/silicom/Kconfig" | 123 | source "drivers/staging/silicom/Kconfig" |
126 | 124 | ||
127 | source "drivers/staging/ced1401/Kconfig" | 125 | source "drivers/staging/ced1401/Kconfig" |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 1fb58a1562cb..4d79ebe2de06 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
@@ -53,7 +53,6 @@ obj-$(CONFIG_ANDROID) += android/ | |||
53 | obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ | 53 | obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ |
54 | obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/ | 54 | obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/ |
55 | obj-$(CONFIG_CSR_WIFI) += csr/ | 55 | obj-$(CONFIG_CSR_WIFI) += csr/ |
56 | obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ | ||
57 | obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/ | 56 | obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/ |
58 | obj-$(CONFIG_CED1401) += ced1401/ | 57 | obj-$(CONFIG_CED1401) += ced1401/ |
59 | obj-$(CONFIG_DRM_IMX) += imx-drm/ | 58 | obj-$(CONFIG_DRM_IMX) += imx-drm/ |
diff --git a/drivers/staging/ti-soc-thermal/ti_soc_thermal.txt b/drivers/staging/ti-soc-thermal/ti_soc_thermal.txt deleted file mode 100644 index 1629652372b6..000000000000 --- a/drivers/staging/ti-soc-thermal/ti_soc_thermal.txt +++ /dev/null | |||
@@ -1,61 +0,0 @@ | |||
1 | * Texas Instrument OMAP SCM bandgap bindings | ||
2 | |||
3 | In the System Control Module, OMAP supplies a voltage reference | ||
4 | and a temperature sensor feature that are gathered in the band | ||
5 | gap voltage and temperature sensor (VBGAPTS) module. The band | ||
6 | gap provides current and voltage reference for its internal | ||
7 | circuits and other analog IP blocks. The analog-to-digital | ||
8 | converter (ADC) produces an output value that is proportional | ||
9 | to the silicon temperature. | ||
10 | |||
11 | Required properties: | ||
12 | - compatible : Should be: | ||
13 | - "ti,omap4430-bandgap" : for OMAP4430 bandgap | ||
14 | - "ti,omap4460-bandgap" : for OMAP4460 bandgap | ||
15 | - "ti,omap4470-bandgap" : for OMAP4470 bandgap | ||
16 | - "ti,omap5430-bandgap" : for OMAP5430 bandgap | ||
17 | - interrupts : this entry should indicate which interrupt line | ||
18 | the talert signal is routed to; | ||
19 | Specific: | ||
20 | - ti,tshut-gpio : this entry should be used to inform which GPIO | ||
21 | line the tshut signal is routed to; | ||
22 | - regs : this entry must also be specified and it is specific | ||
23 | to each bandgap version, because the mapping may change from | ||
24 | soc to soc, apart of depending on available features. | ||
25 | |||
26 | Example: | ||
27 | OMAP4430: | ||
28 | bandgap { | ||
29 | reg = <0x4a002260 0x4 0x4a00232C 0x4>; | ||
30 | compatible = "ti,omap4430-bandgap"; | ||
31 | }; | ||
32 | |||
33 | OMAP4460: | ||
34 | bandgap { | ||
35 | reg = <0x4a002260 0x4 | ||
36 | 0x4a00232C 0x4 | ||
37 | 0x4a002378 0x18>; | ||
38 | compatible = "ti,omap4460-bandgap"; | ||
39 | interrupts = <0 126 4>; /* talert */ | ||
40 | ti,tshut-gpio = <86>; | ||
41 | }; | ||
42 | |||
43 | OMAP4470: | ||
44 | bandgap { | ||
45 | reg = <0x4a002260 0x4 | ||
46 | 0x4a00232C 0x4 | ||
47 | 0x4a002378 0x18>; | ||
48 | compatible = "ti,omap4470-bandgap"; | ||
49 | interrupts = <0 126 4>; /* talert */ | ||
50 | ti,tshut-gpio = <86>; | ||
51 | }; | ||
52 | |||
53 | OMAP5430: | ||
54 | bandgap { | ||
55 | reg = <0x4a0021e0 0xc | ||
56 | 0x4a00232c 0xc | ||
57 | 0x4a002380 0x2c | ||
58 | 0x4a0023C0 0x3c>; | ||
59 | compatible = "ti,omap5430-bandgap"; | ||
60 | interrupts = <0 126 4>; /* talert */ | ||
61 | }; | ||
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 5e3c02554d99..e988c81d763c 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig | |||
@@ -169,4 +169,19 @@ config INTEL_POWERCLAMP | |||
169 | enforce idle time which results in more package C-state residency. The | 169 | enforce idle time which results in more package C-state residency. The |
170 | user interface is exposed via generic thermal framework. | 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 | endif | 187 | endif |
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index c054d410ac3f..67184a293e3f 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile | |||
@@ -23,4 +23,5 @@ obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o | |||
23 | obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o | 23 | obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o |
24 | obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o | 24 | obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o |
25 | obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o | 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/ | ||
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 54ffd64ca3f7..5e53212b984f 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c | |||
@@ -200,7 +200,6 @@ static int armada_thermal_exit(struct platform_device *pdev) | |||
200 | platform_get_drvdata(pdev); | 200 | platform_get_drvdata(pdev); |
201 | 201 | ||
202 | thermal_zone_device_unregister(armada_thermal); | 202 | thermal_zone_device_unregister(armada_thermal); |
203 | platform_set_drvdata(pdev, NULL); | ||
204 | 203 | ||
205 | return 0; | 204 | return 0; |
206 | } | 205 | } |
@@ -211,7 +210,7 @@ static struct platform_driver armada_thermal_driver = { | |||
211 | .driver = { | 210 | .driver = { |
212 | .name = "armada_thermal", | 211 | .name = "armada_thermal", |
213 | .owner = THIS_MODULE, | 212 | .owner = THIS_MODULE, |
214 | .of_match_table = of_match_ptr(armada_thermal_id_table), | 213 | .of_match_table = armada_thermal_id_table, |
215 | }, | 214 | }, |
216 | }; | 215 | }; |
217 | 216 | ||
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index c94bf2e5de62..82e15dbb3ac7 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c | |||
@@ -167,7 +167,7 @@ static int get_property(unsigned int cpu, unsigned long input, | |||
167 | continue; | 167 | continue; |
168 | 168 | ||
169 | /* get the frequency order */ | 169 | /* get the frequency order */ |
170 | if (freq != CPUFREQ_ENTRY_INVALID && descend != -1) | 170 | if (freq != CPUFREQ_ENTRY_INVALID && descend == -1) |
171 | descend = !!(freq > table[i].frequency); | 171 | descend = !!(freq > table[i].frequency); |
172 | 172 | ||
173 | freq = table[i].frequency; | 173 | freq = table[i].frequency; |
diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c index a088d1365ca5..828f5e345c30 100644 --- a/drivers/thermal/dove_thermal.c +++ b/drivers/thermal/dove_thermal.c | |||
@@ -134,16 +134,11 @@ static int dove_thermal_probe(struct platform_device *pdev) | |||
134 | struct resource *res; | 134 | struct resource *res; |
135 | int ret; | 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 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | 137 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
144 | if (!priv) | 138 | if (!priv) |
145 | return -ENOMEM; | 139 | return -ENOMEM; |
146 | 140 | ||
141 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
147 | priv->sensor = devm_ioremap_resource(&pdev->dev, res); | 142 | priv->sensor = devm_ioremap_resource(&pdev->dev, res); |
148 | if (IS_ERR(priv->sensor)) | 143 | if (IS_ERR(priv->sensor)) |
149 | return PTR_ERR(priv->sensor); | 144 | return PTR_ERR(priv->sensor); |
@@ -178,7 +173,6 @@ static int dove_thermal_exit(struct platform_device *pdev) | |||
178 | platform_get_drvdata(pdev); | 173 | platform_get_drvdata(pdev); |
179 | 174 | ||
180 | thermal_zone_device_unregister(dove_thermal); | 175 | thermal_zone_device_unregister(dove_thermal); |
181 | platform_set_drvdata(pdev, NULL); | ||
182 | 176 | ||
183 | return 0; | 177 | return 0; |
184 | } | 178 | } |
@@ -191,7 +185,7 @@ static struct platform_driver dove_thermal_driver = { | |||
191 | .driver = { | 185 | .driver = { |
192 | .name = "dove_thermal", | 186 | .name = "dove_thermal", |
193 | .owner = THIS_MODULE, | 187 | .owner = THIS_MODULE, |
194 | .of_match_table = of_match_ptr(dove_thermal_id_table), | 188 | .of_match_table = dove_thermal_id_table, |
195 | }, | 189 | }, |
196 | }; | 190 | }; |
197 | 191 | ||
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c index 4cbe3eea6deb..9af4b93c9f86 100644 --- a/drivers/thermal/exynos_thermal.c +++ b/drivers/thermal/exynos_thermal.c | |||
@@ -997,7 +997,6 @@ static int exynos_tmu_probe(struct platform_device *pdev) | |||
997 | 997 | ||
998 | return 0; | 998 | return 0; |
999 | err_clk: | 999 | err_clk: |
1000 | platform_set_drvdata(pdev, NULL); | ||
1001 | clk_unprepare(data->clk); | 1000 | clk_unprepare(data->clk); |
1002 | return ret; | 1001 | return ret; |
1003 | } | 1002 | } |
@@ -1012,8 +1011,6 @@ static int exynos_tmu_remove(struct platform_device *pdev) | |||
1012 | 1011 | ||
1013 | clk_unprepare(data->clk); | 1012 | clk_unprepare(data->clk); |
1014 | 1013 | ||
1015 | platform_set_drvdata(pdev, NULL); | ||
1016 | |||
1017 | return 0; | 1014 | return 0; |
1018 | } | 1015 | } |
1019 | 1016 | ||
diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c index dfeceaffbc03..3b034a0dfc94 100644 --- a/drivers/thermal/kirkwood_thermal.c +++ b/drivers/thermal/kirkwood_thermal.c | |||
@@ -75,16 +75,11 @@ static int kirkwood_thermal_probe(struct platform_device *pdev) | |||
75 | struct kirkwood_thermal_priv *priv; | 75 | struct kirkwood_thermal_priv *priv; |
76 | struct resource *res; | 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 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | 78 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
85 | if (!priv) | 79 | if (!priv) |
86 | return -ENOMEM; | 80 | return -ENOMEM; |
87 | 81 | ||
82 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
88 | priv->sensor = devm_ioremap_resource(&pdev->dev, res); | 83 | priv->sensor = devm_ioremap_resource(&pdev->dev, res); |
89 | if (IS_ERR(priv->sensor)) | 84 | if (IS_ERR(priv->sensor)) |
90 | return PTR_ERR(priv->sensor); | 85 | return PTR_ERR(priv->sensor); |
@@ -108,7 +103,6 @@ static int kirkwood_thermal_exit(struct platform_device *pdev) | |||
108 | platform_get_drvdata(pdev); | 103 | platform_get_drvdata(pdev); |
109 | 104 | ||
110 | thermal_zone_device_unregister(kirkwood_thermal); | 105 | thermal_zone_device_unregister(kirkwood_thermal); |
111 | platform_set_drvdata(pdev, NULL); | ||
112 | 106 | ||
113 | return 0; | 107 | return 0; |
114 | } | 108 | } |
@@ -121,7 +115,7 @@ static struct platform_driver kirkwood_thermal_driver = { | |||
121 | .driver = { | 115 | .driver = { |
122 | .name = "kirkwood_thermal", | 116 | .name = "kirkwood_thermal", |
123 | .owner = THIS_MODULE, | 117 | .owner = THIS_MODULE, |
124 | .of_match_table = of_match_ptr(kirkwood_thermal_id_table), | 118 | .of_match_table = kirkwood_thermal_id_table, |
125 | }, | 119 | }, |
126 | }; | 120 | }; |
127 | 121 | ||
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 8d7edd4c8228..88f92e1a9944 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c | |||
@@ -389,11 +389,6 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
389 | * platform has IRQ support. | 389 | * platform has IRQ support. |
390 | * Then, drier use common register | 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 | ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0, | 393 | ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0, |
399 | dev_name(dev), common); | 394 | dev_name(dev), common); |
@@ -405,6 +400,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
405 | /* | 400 | /* |
406 | * rcar_has_irq_support() will be enabled | 401 | * rcar_has_irq_support() will be enabled |
407 | */ | 402 | */ |
403 | res = platform_get_resource(pdev, IORESOURCE_MEM, mres++); | ||
408 | common->base = devm_ioremap_resource(dev, res); | 404 | common->base = devm_ioremap_resource(dev, res); |
409 | if (IS_ERR(common->base)) | 405 | if (IS_ERR(common->base)) |
410 | return PTR_ERR(common->base); | 406 | return PTR_ERR(common->base); |
@@ -458,7 +454,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
458 | 454 | ||
459 | platform_set_drvdata(pdev, common); | 455 | platform_set_drvdata(pdev, common); |
460 | 456 | ||
461 | dev_info(dev, "%d sensor proved\n", i); | 457 | dev_info(dev, "%d sensor probed\n", i); |
462 | 458 | ||
463 | return 0; | 459 | return 0; |
464 | 460 | ||
@@ -487,8 +483,6 @@ static int rcar_thermal_remove(struct platform_device *pdev) | |||
487 | rcar_thermal_irq_disable(priv); | 483 | rcar_thermal_irq_disable(priv); |
488 | } | 484 | } |
489 | 485 | ||
490 | platform_set_drvdata(pdev, NULL); | ||
491 | |||
492 | pm_runtime_put_sync(dev); | 486 | pm_runtime_put_sync(dev); |
493 | pm_runtime_disable(dev); | 487 | pm_runtime_disable(dev); |
494 | 488 | ||
diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c index 3c5ee5607977..ab79ea4701d9 100644 --- a/drivers/thermal/spear_thermal.c +++ b/drivers/thermal/spear_thermal.c | |||
@@ -104,7 +104,7 @@ static int spear_thermal_probe(struct platform_device *pdev) | |||
104 | struct thermal_zone_device *spear_thermal = NULL; | 104 | struct thermal_zone_device *spear_thermal = NULL; |
105 | struct spear_thermal_dev *stdev; | 105 | struct spear_thermal_dev *stdev; |
106 | struct device_node *np = pdev->dev.of_node; | 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 | int ret = 0, val; | 108 | int ret = 0, val; |
109 | 109 | ||
110 | if (!np || !of_property_read_u32(np, "st,thermal-flags", &val)) { | 110 | if (!np || !of_property_read_u32(np, "st,thermal-flags", &val)) { |
@@ -112,11 +112,6 @@ static int spear_thermal_probe(struct platform_device *pdev) | |||
112 | return -EINVAL; | 112 | return -EINVAL; |
113 | } | 113 | } |
114 | 114 | ||
115 | if (!stres) { | ||
116 | dev_err(&pdev->dev, "memory resource missing\n"); | ||
117 | return -ENODEV; | ||
118 | } | ||
119 | |||
120 | stdev = devm_kzalloc(&pdev->dev, sizeof(*stdev), GFP_KERNEL); | 115 | stdev = devm_kzalloc(&pdev->dev, sizeof(*stdev), GFP_KERNEL); |
121 | if (!stdev) { | 116 | if (!stdev) { |
122 | dev_err(&pdev->dev, "kzalloc fail\n"); | 117 | dev_err(&pdev->dev, "kzalloc fail\n"); |
@@ -124,12 +119,10 @@ static int spear_thermal_probe(struct platform_device *pdev) | |||
124 | } | 119 | } |
125 | 120 | ||
126 | /* Enable thermal sensor */ | 121 | /* Enable thermal sensor */ |
127 | stdev->thermal_base = devm_ioremap(&pdev->dev, stres->start, | 122 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
128 | resource_size(stres)); | 123 | stdev->thermal_base = devm_ioremap_resource(&pdev->dev, res); |
129 | if (!stdev->thermal_base) { | 124 | if (IS_ERR(stdev->thermal_base)) |
130 | dev_err(&pdev->dev, "ioremap failed\n"); | 125 | return PTR_ERR(stdev->thermal_base); |
131 | return -ENOMEM; | ||
132 | } | ||
133 | 126 | ||
134 | stdev->clk = devm_clk_get(&pdev->dev, NULL); | 127 | stdev->clk = devm_clk_get(&pdev->dev, NULL); |
135 | if (IS_ERR(stdev->clk)) { | 128 | if (IS_ERR(stdev->clk)) { |
@@ -174,7 +167,6 @@ static int spear_thermal_exit(struct platform_device *pdev) | |||
174 | struct spear_thermal_dev *stdev = spear_thermal->devdata; | 167 | struct spear_thermal_dev *stdev = spear_thermal->devdata; |
175 | 168 | ||
176 | thermal_zone_device_unregister(spear_thermal); | 169 | thermal_zone_device_unregister(spear_thermal); |
177 | platform_set_drvdata(pdev, NULL); | ||
178 | 170 | ||
179 | /* Disable SPEAr Thermal Sensor */ | 171 | /* Disable SPEAr Thermal Sensor */ |
180 | actual_mask = readl_relaxed(stdev->thermal_base); | 172 | actual_mask = readl_relaxed(stdev->thermal_base); |
@@ -198,7 +190,7 @@ static struct platform_driver spear_thermal_driver = { | |||
198 | .name = "spear_thermal", | 190 | .name = "spear_thermal", |
199 | .owner = THIS_MODULE, | 191 | .owner = THIS_MODULE, |
200 | .pm = &spear_thermal_pm_ops, | 192 | .pm = &spear_thermal_pm_ops, |
201 | .of_match_table = of_match_ptr(spear_thermal_id_table), | 193 | .of_match_table = spear_thermal_id_table, |
202 | }, | 194 | }, |
203 | }; | 195 | }; |
204 | 196 | ||
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index d755440791b7..1f02e8edb45c 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/idr.h> | 33 | #include <linux/idr.h> |
34 | #include <linux/thermal.h> | 34 | #include <linux/thermal.h> |
35 | #include <linux/reboot.h> | 35 | #include <linux/reboot.h> |
36 | #include <linux/string.h> | ||
36 | #include <net/netlink.h> | 37 | #include <net/netlink.h> |
37 | #include <net/genetlink.h> | 38 | #include <net/genetlink.h> |
38 | 39 | ||
@@ -155,7 +156,8 @@ int get_tz_trend(struct thermal_zone_device *tz, int trip) | |||
155 | { | 156 | { |
156 | enum thermal_trend trend; | 157 | enum thermal_trend trend; |
157 | 158 | ||
158 | if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) { | 159 | if (tz->emul_temperature || !tz->ops->get_trend || |
160 | tz->ops->get_trend(tz, trip, &trend)) { | ||
159 | if (tz->temperature > tz->last_temperature) | 161 | if (tz->temperature > tz->last_temperature) |
160 | trend = THERMAL_TREND_RAISING; | 162 | trend = THERMAL_TREND_RAISING; |
161 | else if (tz->temperature < tz->last_temperature) | 163 | else if (tz->temperature < tz->last_temperature) |
@@ -713,10 +715,13 @@ policy_store(struct device *dev, struct device_attribute *attr, | |||
713 | int ret = -EINVAL; | 715 | int ret = -EINVAL; |
714 | struct thermal_zone_device *tz = to_thermal_zone(dev); | 716 | struct thermal_zone_device *tz = to_thermal_zone(dev); |
715 | struct thermal_governor *gov; | 717 | struct thermal_governor *gov; |
718 | char name[THERMAL_NAME_LENGTH]; | ||
719 | |||
720 | snprintf(name, sizeof(name), "%s", buf); | ||
716 | 721 | ||
717 | mutex_lock(&thermal_governor_lock); | 722 | mutex_lock(&thermal_governor_lock); |
718 | 723 | ||
719 | gov = __find_governor(buf); | 724 | gov = __find_governor(strim(name)); |
720 | if (!gov) | 725 | if (!gov) |
721 | goto exit; | 726 | goto exit; |
722 | 727 | ||
@@ -1624,7 +1629,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, | |||
1624 | if (!ops || !ops->get_temp) | 1629 | if (!ops || !ops->get_temp) |
1625 | return ERR_PTR(-EINVAL); | 1630 | return ERR_PTR(-EINVAL); |
1626 | 1631 | ||
1627 | if (trips > 0 && !ops->get_trip_type) | 1632 | if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp)) |
1628 | return ERR_PTR(-EINVAL); | 1633 | return ERR_PTR(-EINVAL); |
1629 | 1634 | ||
1630 | tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL); | 1635 | tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL); |
diff --git a/drivers/staging/ti-soc-thermal/Kconfig b/drivers/thermal/ti-soc-thermal/Kconfig index e81375fb2155..bd4c7beba679 100644 --- a/drivers/staging/ti-soc-thermal/Kconfig +++ b/drivers/thermal/ti-soc-thermal/Kconfig | |||
@@ -46,3 +46,15 @@ config OMAP5_THERMAL | |||
46 | 46 | ||
47 | This includes alert interrupts generation and also the TSHUT | 47 | This includes alert interrupts generation and also the TSHUT |
48 | support. | 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. | ||
diff --git a/drivers/staging/ti-soc-thermal/Makefile b/drivers/thermal/ti-soc-thermal/Makefile index 0ca034fb419d..1226b2484e55 100644 --- a/drivers/staging/ti-soc-thermal/Makefile +++ b/drivers/thermal/ti-soc-thermal/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal.o | 1 | obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal.o |
2 | ti-soc-thermal-y := ti-bandgap.o | 2 | ti-soc-thermal-y := ti-bandgap.o |
3 | ti-soc-thermal-$(CONFIG_TI_THERMAL) += ti-thermal-common.o | 3 | ti-soc-thermal-$(CONFIG_TI_THERMAL) += ti-thermal-common.o |
4 | ti-soc-thermal-$(CONFIG_DRA752_THERMAL) += dra752-thermal-data.o | ||
4 | ti-soc-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal-data.o | 5 | ti-soc-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal-data.o |
5 | ti-soc-thermal-$(CONFIG_OMAP5_THERMAL) += omap5-thermal-data.o | 6 | ti-soc-thermal-$(CONFIG_OMAP5_THERMAL) += omap5-thermal-data.o |
diff --git a/drivers/staging/ti-soc-thermal/TODO b/drivers/thermal/ti-soc-thermal/TODO index 7da787d19241..7da787d19241 100644 --- a/drivers/staging/ti-soc-thermal/TODO +++ b/drivers/thermal/ti-soc-thermal/TODO | |||
diff --git a/drivers/thermal/ti-soc-thermal/dra752-bandgap.h b/drivers/thermal/ti-soc-thermal/dra752-bandgap.h new file mode 100644 index 000000000000..6b0f2b1160f7 --- /dev/null +++ b/drivers/thermal/ti-soc-thermal/dra752-bandgap.h | |||
@@ -0,0 +1,280 @@ | |||
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 */ | ||
diff --git a/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c new file mode 100644 index 000000000000..e5d8326a54d6 --- /dev/null +++ b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c | |||
@@ -0,0 +1,476 @@ | |||
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 | }; | ||
diff --git a/drivers/staging/ti-soc-thermal/omap4-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c index d255d33da9eb..d255d33da9eb 100644 --- a/drivers/staging/ti-soc-thermal/omap4-thermal-data.c +++ b/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c | |||
diff --git a/drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h b/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h index 6f2de3a3356d..6f2de3a3356d 100644 --- a/drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h | |||
diff --git a/drivers/staging/ti-soc-thermal/omap5-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c index eff0c80fd4af..eff0c80fd4af 100644 --- a/drivers/staging/ti-soc-thermal/omap5-thermal-data.c +++ b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c | |||
diff --git a/drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h b/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h index 400b55dffadd..400b55dffadd 100644 --- a/drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h | |||
diff --git a/drivers/staging/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index f20c1cfe9800..9dfd47196e63 100644 --- a/drivers/staging/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/of_device.h> | 38 | #include <linux/of_device.h> |
39 | #include <linux/of_platform.h> | 39 | #include <linux/of_platform.h> |
40 | #include <linux/of_irq.h> | 40 | #include <linux/of_irq.h> |
41 | #include <linux/of_gpio.h> | ||
41 | #include <linux/io.h> | 42 | #include <linux/io.h> |
42 | 43 | ||
43 | #include "ti-bandgap.h" | 44 | #include "ti-bandgap.h" |
@@ -469,7 +470,7 @@ static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id) | |||
469 | { | 470 | { |
470 | int ret = 0; | 471 | int ret = 0; |
471 | 472 | ||
472 | if (IS_ERR_OR_NULL(bgp)) { | 473 | if (!bgp || IS_ERR(bgp)) { |
473 | pr_err("%s: invalid bandgap pointer\n", __func__); | 474 | pr_err("%s: invalid bandgap pointer\n", __func__); |
474 | ret = -EINVAL; | 475 | ret = -EINVAL; |
475 | goto exit; | 476 | goto exit; |
@@ -992,9 +993,12 @@ int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend) | |||
992 | goto exit; | 993 | goto exit; |
993 | } | 994 | } |
994 | 995 | ||
996 | spin_lock(&bgp->lock); | ||
997 | |||
995 | tsr = bgp->conf->sensors[id].registers; | 998 | tsr = bgp->conf->sensors[id].registers; |
996 | 999 | ||
997 | /* Freeze and read the last 2 valid readings */ | 1000 | /* Freeze and read the last 2 valid readings */ |
1001 | RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1); | ||
998 | reg1 = tsr->ctrl_dtemp_1; | 1002 | reg1 = tsr->ctrl_dtemp_1; |
999 | reg2 = tsr->ctrl_dtemp_2; | 1003 | reg2 = tsr->ctrl_dtemp_2; |
1000 | 1004 | ||
@@ -1008,22 +1012,25 @@ int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend) | |||
1008 | /* Convert from adc values to mCelsius temperature */ | 1012 | /* Convert from adc values to mCelsius temperature */ |
1009 | ret = ti_bandgap_adc_to_mcelsius(bgp, temp1, &t1); | 1013 | ret = ti_bandgap_adc_to_mcelsius(bgp, temp1, &t1); |
1010 | if (ret) | 1014 | if (ret) |
1011 | goto exit; | 1015 | goto unfreeze; |
1012 | 1016 | ||
1013 | ret = ti_bandgap_adc_to_mcelsius(bgp, temp2, &t2); | 1017 | ret = ti_bandgap_adc_to_mcelsius(bgp, temp2, &t2); |
1014 | if (ret) | 1018 | if (ret) |
1015 | goto exit; | 1019 | goto unfreeze; |
1016 | 1020 | ||
1017 | /* Fetch the update interval */ | 1021 | /* Fetch the update interval */ |
1018 | ret = ti_bandgap_read_update_interval(bgp, id, &interval); | 1022 | ret = ti_bandgap_read_update_interval(bgp, id, &interval); |
1019 | if (ret || !interval) | 1023 | if (ret || !interval) |
1020 | goto exit; | 1024 | goto unfreeze; |
1021 | 1025 | ||
1022 | *trend = (t1 - t2) / interval; | 1026 | *trend = (t1 - t2) / interval; |
1023 | 1027 | ||
1024 | dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n", | 1028 | dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n", |
1025 | t1, t2, *trend); | 1029 | t1, t2, *trend); |
1026 | 1030 | ||
1031 | unfreeze: | ||
1032 | RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0); | ||
1033 | spin_unlock(&bgp->lock); | ||
1027 | exit: | 1034 | exit: |
1028 | return ret; | 1035 | return ret; |
1029 | } | 1036 | } |
@@ -1123,7 +1130,6 @@ static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev) | |||
1123 | const struct of_device_id *of_id; | 1130 | const struct of_device_id *of_id; |
1124 | struct ti_bandgap *bgp; | 1131 | struct ti_bandgap *bgp; |
1125 | struct resource *res; | 1132 | struct resource *res; |
1126 | u32 prop; | ||
1127 | int i; | 1133 | int i; |
1128 | 1134 | ||
1129 | /* just for the sake */ | 1135 | /* just for the sake */ |
@@ -1167,11 +1173,7 @@ static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev) | |||
1167 | } while (res); | 1173 | } while (res); |
1168 | 1174 | ||
1169 | if (TI_BANDGAP_HAS(bgp, TSHUT)) { | 1175 | if (TI_BANDGAP_HAS(bgp, TSHUT)) { |
1170 | if (of_property_read_u32(node, "ti,tshut-gpio", &prop) < 0) { | 1176 | bgp->tshut_gpio = of_get_gpio(node, 0); |
1171 | dev_err(&pdev->dev, "missing tshut gpio in device tree\n"); | ||
1172 | return ERR_PTR(-EINVAL); | ||
1173 | } | ||
1174 | bgp->tshut_gpio = prop; | ||
1175 | if (!gpio_is_valid(bgp->tshut_gpio)) { | 1177 | if (!gpio_is_valid(bgp->tshut_gpio)) { |
1176 | dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n", | 1178 | dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n", |
1177 | bgp->tshut_gpio); | 1179 | bgp->tshut_gpio); |
@@ -1191,7 +1193,7 @@ int ti_bandgap_probe(struct platform_device *pdev) | |||
1191 | int clk_rate, ret = 0, i; | 1193 | int clk_rate, ret = 0, i; |
1192 | 1194 | ||
1193 | bgp = ti_bandgap_build(pdev); | 1195 | bgp = ti_bandgap_build(pdev); |
1194 | if (IS_ERR_OR_NULL(bgp)) { | 1196 | if (IS_ERR(bgp)) { |
1195 | dev_err(&pdev->dev, "failed to fetch platform data\n"); | 1197 | dev_err(&pdev->dev, "failed to fetch platform data\n"); |
1196 | return PTR_ERR(bgp); | 1198 | return PTR_ERR(bgp); |
1197 | } | 1199 | } |
@@ -1207,17 +1209,19 @@ int ti_bandgap_probe(struct platform_device *pdev) | |||
1207 | } | 1209 | } |
1208 | 1210 | ||
1209 | bgp->fclock = clk_get(NULL, bgp->conf->fclock_name); | 1211 | bgp->fclock = clk_get(NULL, bgp->conf->fclock_name); |
1210 | ret = IS_ERR_OR_NULL(bgp->fclock); | 1212 | ret = IS_ERR(bgp->fclock); |
1211 | if (ret) { | 1213 | if (ret) { |
1212 | dev_err(&pdev->dev, "failed to request fclock reference\n"); | 1214 | dev_err(&pdev->dev, "failed to request fclock reference\n"); |
1215 | ret = PTR_ERR(bgp->fclock); | ||
1213 | goto free_irqs; | 1216 | goto free_irqs; |
1214 | } | 1217 | } |
1215 | 1218 | ||
1216 | bgp->div_clk = clk_get(NULL, bgp->conf->div_ck_name); | 1219 | bgp->div_clk = clk_get(NULL, bgp->conf->div_ck_name); |
1217 | ret = IS_ERR_OR_NULL(bgp->div_clk); | 1220 | ret = IS_ERR(bgp->div_clk); |
1218 | if (ret) { | 1221 | if (ret) { |
1219 | dev_err(&pdev->dev, | 1222 | dev_err(&pdev->dev, |
1220 | "failed to request div_ts_ck clock ref\n"); | 1223 | "failed to request div_ts_ck clock ref\n"); |
1224 | ret = PTR_ERR(bgp->div_clk); | ||
1221 | goto free_irqs; | 1225 | goto free_irqs; |
1222 | } | 1226 | } |
1223 | 1227 | ||
@@ -1523,6 +1527,12 @@ static const struct of_device_id of_ti_bandgap_match[] = { | |||
1523 | .data = (void *)&omap5430_data, | 1527 | .data = (void *)&omap5430_data, |
1524 | }, | 1528 | }, |
1525 | #endif | 1529 | #endif |
1530 | #ifdef CONFIG_DRA752_THERMAL | ||
1531 | { | ||
1532 | .compatible = "ti,dra752-bandgap", | ||
1533 | .data = (void *)&dra752_data, | ||
1534 | }, | ||
1535 | #endif | ||
1526 | /* Sentinel */ | 1536 | /* Sentinel */ |
1527 | { }, | 1537 | { }, |
1528 | }; | 1538 | }; |
diff --git a/drivers/staging/ti-soc-thermal/ti-bandgap.h b/drivers/thermal/ti-soc-thermal/ti-bandgap.h index 5f4794abf583..b3adf72f252d 100644 --- a/drivers/staging/ti-soc-thermal/ti-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.h | |||
@@ -400,4 +400,9 @@ extern const struct ti_bandgap_data omap5430_data; | |||
400 | #define omap5430_data NULL | 400 | #define omap5430_data NULL |
401 | #endif | 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 | #endif | 408 | #endif |
diff --git a/drivers/staging/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index 8e67ebf98404..4c5f55c37349 100644 --- a/drivers/staging/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c | |||
@@ -101,7 +101,7 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, | |||
101 | 101 | ||
102 | pcb_tz = data->pcb_tz; | 102 | pcb_tz = data->pcb_tz; |
103 | /* In case pcb zone is available, use the extrapolation rule with it */ | 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 | ret = thermal_zone_get_temp(pcb_tz, &pcb_temp); | 105 | ret = thermal_zone_get_temp(pcb_tz, &pcb_temp); |
106 | if (!ret) { | 106 | if (!ret) { |
107 | tmp -= pcb_temp; /* got a valid PCB temp */ | 107 | tmp -= pcb_temp; /* got a valid PCB temp */ |
@@ -124,7 +124,7 @@ static int ti_thermal_bind(struct thermal_zone_device *thermal, | |||
124 | struct ti_thermal_data *data = thermal->devdata; | 124 | struct ti_thermal_data *data = thermal->devdata; |
125 | int id; | 125 | int id; |
126 | 126 | ||
127 | if (IS_ERR_OR_NULL(data)) | 127 | if (!data || IS_ERR(data)) |
128 | return -ENODEV; | 128 | return -ENODEV; |
129 | 129 | ||
130 | /* check if this is the cooling device we registered */ | 130 | /* check if this is the cooling device we registered */ |
@@ -146,7 +146,7 @@ static int ti_thermal_unbind(struct thermal_zone_device *thermal, | |||
146 | { | 146 | { |
147 | struct ti_thermal_data *data = thermal->devdata; | 147 | struct ti_thermal_data *data = thermal->devdata; |
148 | 148 | ||
149 | if (IS_ERR_OR_NULL(data)) | 149 | if (!data || IS_ERR(data)) |
150 | return -ENODEV; | 150 | return -ENODEV; |
151 | 151 | ||
152 | /* check if this is the cooling device we registered */ | 152 | /* check if this is the cooling device we registered */ |
@@ -282,6 +282,7 @@ static struct ti_thermal_data | |||
282 | data->sensor_id = id; | 282 | data->sensor_id = id; |
283 | data->bgp = bgp; | 283 | data->bgp = bgp; |
284 | data->mode = THERMAL_DEVICE_ENABLED; | 284 | data->mode = THERMAL_DEVICE_ENABLED; |
285 | /* pcb_tz will be either valid or PTR_ERR() */ | ||
285 | data->pcb_tz = thermal_zone_get_zone_by_name("pcb"); | 286 | data->pcb_tz = thermal_zone_get_zone_by_name("pcb"); |
286 | INIT_WORK(&data->thermal_wq, ti_thermal_work); | 287 | INIT_WORK(&data->thermal_wq, ti_thermal_work); |
287 | 288 | ||
@@ -295,7 +296,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, | |||
295 | 296 | ||
296 | data = ti_bandgap_get_sensor_data(bgp, id); | 297 | data = ti_bandgap_get_sensor_data(bgp, id); |
297 | 298 | ||
298 | if (IS_ERR_OR_NULL(data)) | 299 | if (!data || IS_ERR(data)) |
299 | data = ti_thermal_build_data(bgp, id); | 300 | data = ti_thermal_build_data(bgp, id); |
300 | 301 | ||
301 | if (!data) | 302 | if (!data) |
@@ -306,7 +307,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, | |||
306 | OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops, | 307 | OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops, |
307 | NULL, FAST_TEMP_MONITORING_RATE, | 308 | NULL, FAST_TEMP_MONITORING_RATE, |
308 | FAST_TEMP_MONITORING_RATE); | 309 | FAST_TEMP_MONITORING_RATE); |
309 | if (IS_ERR_OR_NULL(data->ti_thermal)) { | 310 | if (IS_ERR(data->ti_thermal)) { |
310 | dev_err(bgp->dev, "thermal zone device is NULL\n"); | 311 | dev_err(bgp->dev, "thermal zone device is NULL\n"); |
311 | return PTR_ERR(data->ti_thermal); | 312 | return PTR_ERR(data->ti_thermal); |
312 | } | 313 | } |
@@ -343,7 +344,7 @@ int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id) | |||
343 | struct ti_thermal_data *data; | 344 | struct ti_thermal_data *data; |
344 | 345 | ||
345 | data = ti_bandgap_get_sensor_data(bgp, id); | 346 | data = ti_bandgap_get_sensor_data(bgp, id); |
346 | if (IS_ERR_OR_NULL(data)) | 347 | if (!data || IS_ERR(data)) |
347 | data = ti_thermal_build_data(bgp, id); | 348 | data = ti_thermal_build_data(bgp, id); |
348 | 349 | ||
349 | if (!data) | 350 | if (!data) |
@@ -356,7 +357,7 @@ int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id) | |||
356 | 357 | ||
357 | /* Register cooling device */ | 358 | /* Register cooling device */ |
358 | data->cool_dev = cpufreq_cooling_register(cpu_present_mask); | 359 | data->cool_dev = cpufreq_cooling_register(cpu_present_mask); |
359 | if (IS_ERR_OR_NULL(data->cool_dev)) { | 360 | if (IS_ERR(data->cool_dev)) { |
360 | dev_err(bgp->dev, | 361 | dev_err(bgp->dev, |
361 | "Failed to register cpufreq cooling device\n"); | 362 | "Failed to register cpufreq cooling device\n"); |
362 | return PTR_ERR(data->cool_dev); | 363 | return PTR_ERR(data->cool_dev); |
diff --git a/drivers/staging/ti-soc-thermal/ti-thermal.h b/drivers/thermal/ti-soc-thermal/ti-thermal.h index 5055777727cc..f8b7ffea6194 100644 --- a/drivers/staging/ti-soc-thermal/ti-thermal.h +++ b/drivers/thermal/ti-soc-thermal/ti-thermal.h | |||
@@ -38,6 +38,9 @@ | |||
38 | #define OMAP_GRADIENT_SLOPE_5430_GPU 117 | 38 | #define OMAP_GRADIENT_SLOPE_5430_GPU 117 |
39 | #define OMAP_GRADIENT_CONST_5430_GPU -2992 | 39 | #define OMAP_GRADIENT_CONST_5430_GPU -2992 |
40 | 40 | ||
41 | #define DRA752_GRADIENT_SLOPE 0 | ||
42 | #define DRA752_GRADIENT_CONST 2000 | ||
43 | |||
41 | /* PCB sensor calculation constants */ | 44 | /* PCB sensor calculation constants */ |
42 | #define OMAP_GRADIENT_SLOPE_W_PCB_4430 0 | 45 | #define OMAP_GRADIENT_SLOPE_W_PCB_4430 0 |
43 | #define OMAP_GRADIENT_CONST_W_PCB_4430 20000 | 46 | #define OMAP_GRADIENT_CONST_W_PCB_4430 20000 |
@@ -51,6 +54,9 @@ | |||
51 | #define OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU 464 | 54 | #define OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU 464 |
52 | #define OMAP_GRADIENT_CONST_W_PCB_5430_GPU -5102 | 55 | #define OMAP_GRADIENT_CONST_W_PCB_5430_GPU -5102 |
53 | 56 | ||
57 | #define DRA752_GRADIENT_SLOPE_W_PCB 0 | ||
58 | #define DRA752_GRADIENT_CONST_W_PCB 2000 | ||
59 | |||
54 | /* trip points of interest in milicelsius (at hotspot level) */ | 60 | /* trip points of interest in milicelsius (at hotspot level) */ |
55 | #define OMAP_TRIP_COLD 100000 | 61 | #define OMAP_TRIP_COLD 100000 |
56 | #define OMAP_TRIP_HOT 110000 | 62 | #define OMAP_TRIP_HOT 110000 |
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c new file mode 100644 index 000000000000..5de56f671a9d --- /dev/null +++ b/drivers/thermal/x86_pkg_temp_thermal.c | |||
@@ -0,0 +1,642 @@ | |||
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"); | ||