aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-11 15:26:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-11 15:26:08 -0400
commit8cbd0eefcaf8cc32ded2bf229f0fc379b2ad69f2 (patch)
tree08cc79685a888470509b969a2c079249ee28b69f /drivers
parent1466b77a7be75144dee1cb09839be3435854dd0b (diff)
parente8d39240d635ed9bcaddbec898b1c9f063c5dbb2 (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')
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/ti-soc-thermal/ti_soc_thermal.txt61
-rw-r--r--drivers/thermal/Kconfig15
-rw-r--r--drivers/thermal/Makefile3
-rw-r--r--drivers/thermal/armada_thermal.c3
-rw-r--r--drivers/thermal/cpu_cooling.c2
-rw-r--r--drivers/thermal/dove_thermal.c10
-rw-r--r--drivers/thermal/exynos_thermal.c3
-rw-r--r--drivers/thermal/kirkwood_thermal.c10
-rw-r--r--drivers/thermal/rcar_thermal.c10
-rw-r--r--drivers/thermal/spear_thermal.c20
-rw-r--r--drivers/thermal/thermal_core.c11
-rw-r--r--drivers/thermal/ti-soc-thermal/Kconfig (renamed from drivers/staging/ti-soc-thermal/Kconfig)12
-rw-r--r--drivers/thermal/ti-soc-thermal/Makefile (renamed from drivers/staging/ti-soc-thermal/Makefile)1
-rw-r--r--drivers/thermal/ti-soc-thermal/TODO (renamed from drivers/staging/ti-soc-thermal/TODO)0
-rw-r--r--drivers/thermal/ti-soc-thermal/dra752-bandgap.h280
-rw-r--r--drivers/thermal/ti-soc-thermal/dra752-thermal-data.c476
-rw-r--r--drivers/thermal/ti-soc-thermal/omap4-thermal-data.c (renamed from drivers/staging/ti-soc-thermal/omap4-thermal-data.c)0
-rw-r--r--drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h (renamed from drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h)0
-rw-r--r--drivers/thermal/ti-soc-thermal/omap5-thermal-data.c (renamed from drivers/staging/ti-soc-thermal/omap5-thermal-data.c)0
-rw-r--r--drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h (renamed from drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h)0
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.c (renamed from drivers/staging/ti-soc-thermal/ti-bandgap.c)36
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.h (renamed from drivers/staging/ti-soc-thermal/ti-bandgap.h)5
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-thermal-common.c (renamed from drivers/staging/ti-soc-thermal/ti-thermal-common.c)15
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-thermal.h (renamed from drivers/staging/ti-soc-thermal/ti-thermal.h)6
-rw-r--r--drivers/thermal/x86_pkg_temp_thermal.c642
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
121source "drivers/staging/csr/Kconfig" 121source "drivers/staging/csr/Kconfig"
122 122
123source "drivers/staging/ti-soc-thermal/Kconfig"
124
125source "drivers/staging/silicom/Kconfig" 123source "drivers/staging/silicom/Kconfig"
126 124
127source "drivers/staging/ced1401/Kconfig" 125source "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/
53obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ 53obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/
54obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/ 54obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/
55obj-$(CONFIG_CSR_WIFI) += csr/ 55obj-$(CONFIG_CSR_WIFI) += csr/
56obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
57obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/ 56obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/
58obj-$(CONFIG_CED1401) += ced1401/ 57obj-$(CONFIG_CED1401) += ced1401/
59obj-$(CONFIG_DRM_IMX) += imx-drm/ 58obj-$(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
3In the System Control Module, OMAP supplies a voltage reference
4and a temperature sensor feature that are gathered in the band
5gap voltage and temperature sensor (VBGAPTS) module. The band
6gap provides current and voltage reference for its internal
7circuits and other analog IP blocks. The analog-to-digital
8converter (ADC) produces an output value that is proportional
9to the silicon temperature.
10
11Required 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
18the talert signal is routed to;
19Specific:
20- ti,tshut-gpio : this entry should be used to inform which GPIO
21line the tshut signal is routed to;
22- regs : this entry must also be specified and it is specific
23to each bandgap version, because the mapping may change from
24soc to soc, apart of depending on available features.
25
26Example:
27OMAP4430:
28bandgap {
29 reg = <0x4a002260 0x4 0x4a00232C 0x4>;
30 compatible = "ti,omap4430-bandgap";
31};
32
33OMAP4460:
34bandgap {
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
43OMAP4470:
44bandgap {
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
53OMAP5430:
54bandgap {
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
172config 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
183menu "Texas Instruments thermal drivers"
184source "drivers/thermal/ti-soc-thermal/Kconfig"
185endmenu
186
172endif 187endif
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
23obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o 23obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
24obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o 24obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
25obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o 25obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
26 26obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
27obj-$(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;
999err_clk: 999err_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
50config 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 @@
1obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal.o 1obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal.o
2ti-soc-thermal-y := ti-bandgap.o 2ti-soc-thermal-y := ti-bandgap.o
3ti-soc-thermal-$(CONFIG_TI_THERMAL) += ti-thermal-common.o 3ti-soc-thermal-$(CONFIG_TI_THERMAL) += ti-thermal-common.o
4ti-soc-thermal-$(CONFIG_DRA752_THERMAL) += dra752-thermal-data.o
4ti-soc-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal-data.o 5ti-soc-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal-data.o
5ti-soc-thermal-$(CONFIG_OMAP5_THERMAL) += omap5-thermal-data.o 6ti-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 */
35static struct temp_sensor_registers
36dra752_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 */
70static struct temp_sensor_registers
71dra752_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 */
105static struct temp_sensor_registers
106dra752_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 */
140static struct temp_sensor_registers
141dra752_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 */
175static struct temp_sensor_registers
176dra752_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 */
208static 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 */
223static 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 */
238static 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 */
253static 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 */
268static 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 */
286static
287int 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 */
413const 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
1031unfreeze:
1032 RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0);
1033 spin_unlock(&bgp->lock);
1027exit: 1034exit:
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
404extern 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
46static int notify_delay_ms = PKG_TEMP_THERMAL_NOTIFY_DELAY;
47module_param(notify_delay_ms, int, 0644);
48MODULE_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
58struct 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 */
70static LIST_HEAD(phy_dev_list);
71static DEFINE_MUTEX(phy_dev_list_mutex);
72
73/* Interrupt to work function schedule queue */
74static DEFINE_PER_CPU(struct delayed_work, pkg_temp_thermal_threshold_work);
75
76/* To track if the work is already scheduled on a package */
77static u8 *pkg_work_scheduled;
78
79/* Spin lock to prevent races with pkg_work_scheduled */
80static spinlock_t pkg_work_lock;
81static u16 max_phy_id;
82
83/* Debug counters to show using debugfs */
84static struct dentry *debugfs;
85static unsigned int pkg_interrupt_cnt;
86static unsigned int pkg_work_cnt;
87
88static 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
108err_out:
109 debugfs_remove_recursive(debugfs);
110 return -ENOENT;
111}
112
113static 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*/
136static 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;
156err_ret:
157 *tj_max = 0;
158 return err;
159}
160
161static 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
179static 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
216int 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
261static 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 */
271static 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
278static bool pkg_temp_thermal_platform_thermal_rate_control(void)
279{
280 return true;
281}
282
283/* Enable threshold interrupt on local package/cpu */
284static 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 */
301static 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
310static 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
348static 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
377static 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
389static 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
458err_ret_free:
459 kfree(phy_dev_entry);
460err_ret_unlock:
461 mutex_unlock(&phy_dev_list_mutex);
462
463err_ret:
464 return err;
465}
466
467static 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
507static 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
534static 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
543static 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
560static struct notifier_block pkg_temp_thermal_notifier __refdata = {
561 .notifier_call = pkg_temp_thermal_cpu_callback,
562};
563
564static 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};
568MODULE_DEVICE_TABLE(x86cpu, pkg_temp_thermal_ids);
569
570static 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
594err_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
606static 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
637module_init(pkg_temp_thermal_init)
638module_exit(pkg_temp_thermal_exit)
639
640MODULE_DESCRIPTION("X86 PKG TEMP Thermal Driver");
641MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
642MODULE_LICENSE("GPL v2");