aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal
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/thermal
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/thermal')
-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/Kconfig60
-rw-r--r--drivers/thermal/ti-soc-thermal/Makefile6
-rw-r--r--drivers/thermal/ti-soc-thermal/TODO12
-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.c267
-rw-r--r--drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h175
-rw-r--r--drivers/thermal/ti-soc-thermal/omap5-thermal-data.c359
-rw-r--r--drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h200
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.c1556
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.h408
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-thermal-common.c378
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-thermal.h123
-rw-r--r--drivers/thermal/x86_pkg_temp_thermal.c642
24 files changed, 4981 insertions, 48 deletions
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/thermal/ti-soc-thermal/Kconfig b/drivers/thermal/ti-soc-thermal/Kconfig
new file mode 100644
index 000000000000..bd4c7beba679
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/Kconfig
@@ -0,0 +1,60 @@
1config TI_SOC_THERMAL
2 tristate "Texas Instruments SoCs temperature sensor driver"
3 depends on THERMAL
4 depends on ARCH_HAS_BANDGAP
5 help
6 If you say yes here you get support for the Texas Instruments
7 OMAP4460+ on die bandgap temperature sensor support. The register
8 set is part of system control module.
9
10 This includes alert interrupts generation and also the TSHUT
11 support.
12
13config TI_THERMAL
14 bool "Texas Instruments SoCs thermal framework support"
15 depends on TI_SOC_THERMAL
16 depends on CPU_THERMAL
17 help
18 If you say yes here you want to get support for generic thermal
19 framework for the Texas Instruments on die bandgap temperature sensor.
20
21 This includes trip points definitions, extrapolation rules and
22 CPU cooling device bindings.
23
24config OMAP4_THERMAL
25 bool "Texas Instruments OMAP4 thermal support"
26 depends on TI_SOC_THERMAL
27 depends on ARCH_OMAP4
28 help
29 If you say yes here you get thermal support for the Texas Instruments
30 OMAP4 SoC family. The current chip supported are:
31 - OMAP4430
32 - OMAP4460
33 - OMAP4470
34
35 This includes alert interrupts generation and also the TSHUT
36 support.
37
38config OMAP5_THERMAL
39 bool "Texas Instruments OMAP5 thermal support"
40 depends on TI_SOC_THERMAL
41 depends on SOC_OMAP5
42 help
43 If you say yes here you get thermal support for the Texas Instruments
44 OMAP5 SoC family. The current chip supported are:
45 - OMAP5430
46
47 This includes alert interrupts generation and also the TSHUT
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/thermal/ti-soc-thermal/Makefile b/drivers/thermal/ti-soc-thermal/Makefile
new file mode 100644
index 000000000000..1226b2484e55
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/Makefile
@@ -0,0 +1,6 @@
1obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal.o
2ti-soc-thermal-y := ti-bandgap.o
3ti-soc-thermal-$(CONFIG_TI_THERMAL) += ti-thermal-common.o
4ti-soc-thermal-$(CONFIG_DRA752_THERMAL) += dra752-thermal-data.o
5ti-soc-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal-data.o
6ti-soc-thermal-$(CONFIG_OMAP5_THERMAL) += omap5-thermal-data.o
diff --git a/drivers/thermal/ti-soc-thermal/TODO b/drivers/thermal/ti-soc-thermal/TODO
new file mode 100644
index 000000000000..7da787d19241
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/TODO
@@ -0,0 +1,12 @@
1List of TODOs (by Eduardo Valentin)
2
3on ti-bandgap.c:
4- Revisit PM support
5
6on ti-thermal-common.c/ti-thermal.h:
7- Revisit need for locking
8
9generally:
10- make sure this code works on OMAP4430, OMAP4460 and OMAP5430
11
12Copy patches to Eduardo Valentin <eduardo.valentin@ti.com>
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/thermal/ti-soc-thermal/omap4-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
new file mode 100644
index 000000000000..d255d33da9eb
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
@@ -0,0 +1,267 @@
1/*
2 * OMAP4 thermal driver.
3 *
4 * Copyright (C) 2011-2012 Texas Instruments Inc.
5 * Contact:
6 * Eduardo Valentin <eduardo.valentin@ti.com>
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19#include "ti-thermal.h"
20#include "ti-bandgap.h"
21#include "omap4xxx-bandgap.h"
22
23/*
24 * OMAP4430 has one instance of thermal sensor for MPU
25 * need to describe the individual bit fields
26 */
27static struct temp_sensor_registers
28omap4430_mpu_temp_sensor_registers = {
29 .temp_sensor_ctrl = OMAP4430_TEMP_SENSOR_CTRL_OFFSET,
30 .bgap_tempsoff_mask = OMAP4430_BGAP_TEMPSOFF_MASK,
31 .bgap_soc_mask = OMAP4430_BGAP_TEMP_SENSOR_SOC_MASK,
32 .bgap_eocz_mask = OMAP4430_BGAP_TEMP_SENSOR_EOCZ_MASK,
33 .bgap_dtemp_mask = OMAP4430_BGAP_TEMP_SENSOR_DTEMP_MASK,
34
35 .bgap_mode_ctrl = OMAP4430_TEMP_SENSOR_CTRL_OFFSET,
36 .mode_ctrl_mask = OMAP4430_SINGLE_MODE_MASK,
37
38 .bgap_efuse = OMAP4430_FUSE_OPP_BGAP,
39};
40
41/* Thresholds and limits for OMAP4430 MPU temperature sensor */
42static struct temp_sensor_data omap4430_mpu_temp_sensor_data = {
43 .min_freq = OMAP4430_MIN_FREQ,
44 .max_freq = OMAP4430_MAX_FREQ,
45 .max_temp = OMAP4430_MAX_TEMP,
46 .min_temp = OMAP4430_MIN_TEMP,
47 .hyst_val = OMAP4430_HYST_VAL,
48};
49
50/*
51 * Temperature values in milli degree celsius
52 * ADC code values from 530 to 923
53 */
54static const int
55omap4430_adc_to_temp[OMAP4430_ADC_END_VALUE - OMAP4430_ADC_START_VALUE + 1] = {
56 -38000, -35000, -34000, -32000, -30000, -28000, -26000, -24000, -22000,
57 -20000, -18000, -17000, -15000, -13000, -12000, -10000, -8000, -6000,
58 -5000, -3000, -1000, 0, 2000, 3000, 5000, 6000, 8000, 10000, 12000,
59 13000, 15000, 17000, 19000, 21000, 23000, 25000, 27000, 28000, 30000,
60 32000, 33000, 35000, 37000, 38000, 40000, 42000, 43000, 45000, 47000,
61 48000, 50000, 52000, 53000, 55000, 57000, 58000, 60000, 62000, 64000,
62 66000, 68000, 70000, 71000, 73000, 75000, 77000, 78000, 80000, 82000,
63 83000, 85000, 87000, 88000, 90000, 92000, 93000, 95000, 97000, 98000,
64 100000, 102000, 103000, 105000, 107000, 109000, 111000, 113000, 115000,
65 117000, 118000, 120000, 122000, 123000,
66};
67
68/* OMAP4430 data */
69const struct ti_bandgap_data omap4430_data = {
70 .features = TI_BANDGAP_FEATURE_MODE_CONFIG |
71 TI_BANDGAP_FEATURE_CLK_CTRL |
72 TI_BANDGAP_FEATURE_POWER_SWITCH,
73 .fclock_name = "bandgap_fclk",
74 .div_ck_name = "bandgap_fclk",
75 .conv_table = omap4430_adc_to_temp,
76 .adc_start_val = OMAP4430_ADC_START_VALUE,
77 .adc_end_val = OMAP4430_ADC_END_VALUE,
78 .expose_sensor = ti_thermal_expose_sensor,
79 .remove_sensor = ti_thermal_remove_sensor,
80 .sensors = {
81 {
82 .registers = &omap4430_mpu_temp_sensor_registers,
83 .ts_data = &omap4430_mpu_temp_sensor_data,
84 .domain = "cpu",
85 .slope = OMAP_GRADIENT_SLOPE_4430,
86 .constant = OMAP_GRADIENT_CONST_4430,
87 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4430,
88 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4430,
89 .register_cooling = ti_thermal_register_cpu_cooling,
90 .unregister_cooling = ti_thermal_unregister_cpu_cooling,
91 },
92 },
93 .sensor_count = 1,
94};
95/*
96 * OMAP4460 has one instance of thermal sensor for MPU
97 * need to describe the individual bit fields
98 */
99static struct temp_sensor_registers
100omap4460_mpu_temp_sensor_registers = {
101 .temp_sensor_ctrl = OMAP4460_TEMP_SENSOR_CTRL_OFFSET,
102 .bgap_tempsoff_mask = OMAP4460_BGAP_TEMPSOFF_MASK,
103 .bgap_soc_mask = OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK,
104 .bgap_eocz_mask = OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK,
105 .bgap_dtemp_mask = OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK,
106
107 .bgap_mask_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
108 .mask_hot_mask = OMAP4460_MASK_HOT_MASK,
109 .mask_cold_mask = OMAP4460_MASK_COLD_MASK,
110
111 .bgap_mode_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
112 .mode_ctrl_mask = OMAP4460_SINGLE_MODE_MASK,
113
114 .bgap_counter = OMAP4460_BGAP_COUNTER_OFFSET,
115 .counter_mask = OMAP4460_COUNTER_MASK,
116
117 .bgap_threshold = OMAP4460_BGAP_THRESHOLD_OFFSET,
118 .threshold_thot_mask = OMAP4460_T_HOT_MASK,
119 .threshold_tcold_mask = OMAP4460_T_COLD_MASK,
120
121 .tshut_threshold = OMAP4460_BGAP_TSHUT_OFFSET,
122 .tshut_hot_mask = OMAP4460_TSHUT_HOT_MASK,
123 .tshut_cold_mask = OMAP4460_TSHUT_COLD_MASK,
124
125 .bgap_status = OMAP4460_BGAP_STATUS_OFFSET,
126 .status_clean_stop_mask = OMAP4460_CLEAN_STOP_MASK,
127 .status_bgap_alert_mask = OMAP4460_BGAP_ALERT_MASK,
128 .status_hot_mask = OMAP4460_HOT_FLAG_MASK,
129 .status_cold_mask = OMAP4460_COLD_FLAG_MASK,
130
131 .bgap_efuse = OMAP4460_FUSE_OPP_BGAP,
132};
133
134/* Thresholds and limits for OMAP4460 MPU temperature sensor */
135static struct temp_sensor_data omap4460_mpu_temp_sensor_data = {
136 .tshut_hot = OMAP4460_TSHUT_HOT,
137 .tshut_cold = OMAP4460_TSHUT_COLD,
138 .t_hot = OMAP4460_T_HOT,
139 .t_cold = OMAP4460_T_COLD,
140 .min_freq = OMAP4460_MIN_FREQ,
141 .max_freq = OMAP4460_MAX_FREQ,
142 .max_temp = OMAP4460_MAX_TEMP,
143 .min_temp = OMAP4460_MIN_TEMP,
144 .hyst_val = OMAP4460_HYST_VAL,
145 .update_int1 = 1000,
146 .update_int2 = 2000,
147};
148
149/*
150 * Temperature values in milli degree celsius
151 * ADC code values from 530 to 923
152 */
153static const int
154omap4460_adc_to_temp[OMAP4460_ADC_END_VALUE - OMAP4460_ADC_START_VALUE + 1] = {
155 -40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200,
156 -37800, -37300, -36800, -36400, -36000, -35600, -35200, -34800,
157 -34300, -33800, -33400, -33000, -32600, -32200, -31800, -31300,
158 -30800, -30400, -30000, -29600, -29200, -28700, -28200, -27800,
159 -27400, -27000, -26600, -26200, -25700, -25200, -24800, -24400,
160 -24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000,
161 -20600, -20200, -19700, -19200, -18800, -18400, -18000, -17600,
162 -17200, -16700, -16200, -15800, -15400, -15000, -14600, -14200,
163 -13700, -13200, -12800, -12400, -12000, -11600, -11200, -10700,
164 -10200, -9800, -9400, -9000, -8600, -8200, -7700, -7200, -6800,
165 -6400, -6000, -5600, -5200, -4800, -4300, -3800, -3400, -3000,
166 -2600, -2200, -1800, -1300, -800, -400, 0, 400, 800, 1200, 1600,
167 2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000, 6400,
168 6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10600, 11000,
169 11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800,
170 15300, 15800, 16200, 16600, 17000, 17400, 17800, 18200, 18700,
171 19200, 19600, 20000, 20400, 20800, 21200, 21600, 22100, 22600,
172 23000, 23400, 23800, 24200, 24600, 25000, 25400, 25900, 26400,
173 26800, 27200, 27600, 28000, 28400, 28800, 29300, 29800, 30200,
174 30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000,
175 34400, 34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800,
176 38200, 38600, 39000, 39400, 39800, 40200, 40600, 41100, 41600,
177 42000, 42400, 42800, 43200, 43600, 44000, 44400, 44800, 45300,
178 45800, 46200, 46600, 47000, 47400, 47800, 48200, 48600, 49000,
179 49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400, 52800,
180 53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600,
181 57000, 57400, 57800, 58200, 58700, 59200, 59600, 60000, 60400,
182 60800, 61200, 61600, 62000, 62400, 62800, 63300, 63800, 64200,
183 64600, 65000, 65400, 65800, 66200, 66600, 67000, 67400, 67800,
184 68200, 68700, 69200, 69600, 70000, 70400, 70800, 71200, 71600,
185 72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400,
186 75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000,
187 79400, 79800, 80300, 80800, 81200, 81600, 82000, 82400, 82800,
188 83200, 83600, 84000, 84400, 84800, 85200, 85600, 86000, 86400,
189 86800, 87300, 87800, 88200, 88600, 89000, 89400, 89800, 90200,
190 90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400, 93800,
191 94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600,
192 98000, 98400, 98800, 99200, 99600, 100000, 100400, 100800, 101200,
193 101600, 102000, 102400, 102800, 103200, 103600, 104000, 104400,
194 104800, 105200, 105600, 106100, 106600, 107000, 107400, 107800,
195 108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000,
196 111400, 111800, 112200, 112600, 113000, 113400, 113800, 114200,
197 114600, 115000, 115400, 115800, 116200, 116600, 117000, 117400,
198 117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600,
199 121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200,
200 124600, 124900, 125000, 125000, 125000, 125000
201};
202
203/* OMAP4460 data */
204const struct ti_bandgap_data omap4460_data = {
205 .features = TI_BANDGAP_FEATURE_TSHUT |
206 TI_BANDGAP_FEATURE_TSHUT_CONFIG |
207 TI_BANDGAP_FEATURE_TALERT |
208 TI_BANDGAP_FEATURE_MODE_CONFIG |
209 TI_BANDGAP_FEATURE_POWER_SWITCH |
210 TI_BANDGAP_FEATURE_CLK_CTRL |
211 TI_BANDGAP_FEATURE_COUNTER,
212 .fclock_name = "bandgap_ts_fclk",
213 .div_ck_name = "div_ts_ck",
214 .conv_table = omap4460_adc_to_temp,
215 .adc_start_val = OMAP4460_ADC_START_VALUE,
216 .adc_end_val = OMAP4460_ADC_END_VALUE,
217 .expose_sensor = ti_thermal_expose_sensor,
218 .remove_sensor = ti_thermal_remove_sensor,
219 .report_temperature = ti_thermal_report_sensor_temperature,
220 .sensors = {
221 {
222 .registers = &omap4460_mpu_temp_sensor_registers,
223 .ts_data = &omap4460_mpu_temp_sensor_data,
224 .domain = "cpu",
225 .slope = OMAP_GRADIENT_SLOPE_4460,
226 .constant = OMAP_GRADIENT_CONST_4460,
227 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4460,
228 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4460,
229 .register_cooling = ti_thermal_register_cpu_cooling,
230 .unregister_cooling = ti_thermal_unregister_cpu_cooling,
231 },
232 },
233 .sensor_count = 1,
234};
235
236/* OMAP4470 data */
237const struct ti_bandgap_data omap4470_data = {
238 .features = TI_BANDGAP_FEATURE_TSHUT |
239 TI_BANDGAP_FEATURE_TSHUT_CONFIG |
240 TI_BANDGAP_FEATURE_TALERT |
241 TI_BANDGAP_FEATURE_MODE_CONFIG |
242 TI_BANDGAP_FEATURE_POWER_SWITCH |
243 TI_BANDGAP_FEATURE_CLK_CTRL |
244 TI_BANDGAP_FEATURE_COUNTER,
245 .fclock_name = "bandgap_ts_fclk",
246 .div_ck_name = "div_ts_ck",
247 .conv_table = omap4460_adc_to_temp,
248 .adc_start_val = OMAP4460_ADC_START_VALUE,
249 .adc_end_val = OMAP4460_ADC_END_VALUE,
250 .expose_sensor = ti_thermal_expose_sensor,
251 .remove_sensor = ti_thermal_remove_sensor,
252 .report_temperature = ti_thermal_report_sensor_temperature,
253 .sensors = {
254 {
255 .registers = &omap4460_mpu_temp_sensor_registers,
256 .ts_data = &omap4460_mpu_temp_sensor_data,
257 .domain = "cpu",
258 .slope = OMAP_GRADIENT_SLOPE_4470,
259 .constant = OMAP_GRADIENT_CONST_4470,
260 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4470,
261 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4470,
262 .register_cooling = ti_thermal_register_cpu_cooling,
263 .unregister_cooling = ti_thermal_unregister_cpu_cooling,
264 },
265 },
266 .sensor_count = 1,
267};
diff --git a/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h b/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h
new file mode 100644
index 000000000000..6f2de3a3356d
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h
@@ -0,0 +1,175 @@
1/*
2 * OMAP4xxx 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 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23#ifndef __OMAP4XXX_BANDGAP_H
24#define __OMAP4XXX_BANDGAP_H
25
26/**
27 * *** OMAP4430 ***
28 *
29 * Below, in sequence, are the Register definitions,
30 * the bitfields and the temperature definitions for OMAP4430.
31 */
32
33/**
34 * OMAP4430 register definitions
35 *
36 * Registers are defined as offsets. The offsets are
37 * relative to FUSE_OPP_BGAP on 4430.
38 */
39
40/* OMAP4430.FUSE_OPP_BGAP */
41#define OMAP4430_FUSE_OPP_BGAP 0x0
42
43/* OMAP4430.TEMP_SENSOR */
44#define OMAP4430_TEMP_SENSOR_CTRL_OFFSET 0xCC
45
46/**
47 * Register and bit definitions for OMAP4430
48 *
49 * All the macros bellow define the required bits for
50 * controlling temperature on OMAP4430. Bit defines are
51 * grouped by register.
52 */
53
54/* OMAP4430.TEMP_SENSOR bits */
55#define OMAP4430_BGAP_TEMPSOFF_MASK BIT(12)
56#define OMAP4430_BGAP_TSHUT_MASK BIT(11)
57#define OMAP4430_SINGLE_MODE_MASK BIT(10)
58#define OMAP4430_BGAP_TEMP_SENSOR_SOC_MASK BIT(9)
59#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_MASK BIT(8)
60#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_MASK (0xff << 0)
61
62/**
63 * Temperature limits and thresholds for OMAP4430
64 *
65 * All the macros bellow are definitions for handling the
66 * ADC conversions and representation of temperature limits
67 * and thresholds for OMAP4430.
68 */
69
70/* ADC conversion table limits */
71#define OMAP4430_ADC_START_VALUE 0
72#define OMAP4430_ADC_END_VALUE 127
73/* bandgap clock limits (no control on 4430) */
74#define OMAP4430_MAX_FREQ 32768
75#define OMAP4430_MIN_FREQ 32768
76/* sensor limits */
77#define OMAP4430_MIN_TEMP -40000
78#define OMAP4430_MAX_TEMP 125000
79#define OMAP4430_HYST_VAL 5000
80
81/**
82 * *** OMAP4460 *** Applicable for OMAP4470
83 *
84 * Below, in sequence, are the Register definitions,
85 * the bitfields and the temperature definitions for OMAP4460.
86 */
87
88/**
89 * OMAP4460 register definitions
90 *
91 * Registers are defined as offsets. The offsets are
92 * relative to FUSE_OPP_BGAP on 4460.
93 */
94
95/* OMAP4460.FUSE_OPP_BGAP */
96#define OMAP4460_FUSE_OPP_BGAP 0x0
97
98/* OMAP4460.TEMP_SENSOR */
99#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET 0xCC
100
101/* OMAP4460.BANDGAP_CTRL */
102#define OMAP4460_BGAP_CTRL_OFFSET 0x118
103
104/* OMAP4460.BANDGAP_COUNTER */
105#define OMAP4460_BGAP_COUNTER_OFFSET 0x11C
106
107/* OMAP4460.BANDGAP_THRESHOLD */
108#define OMAP4460_BGAP_THRESHOLD_OFFSET 0x120
109
110/* OMAP4460.TSHUT_THRESHOLD */
111#define OMAP4460_BGAP_TSHUT_OFFSET 0x124
112
113/* OMAP4460.BANDGAP_STATUS */
114#define OMAP4460_BGAP_STATUS_OFFSET 0x128
115
116/**
117 * Register bitfields for OMAP4460
118 *
119 * All the macros bellow define the required bits for
120 * controlling temperature on OMAP4460. Bit defines are
121 * grouped by register.
122 */
123/* OMAP4460.TEMP_SENSOR bits */
124#define OMAP4460_BGAP_TEMPSOFF_MASK BIT(13)
125#define OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK BIT(11)
126#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK BIT(10)
127#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK (0x3ff << 0)
128
129/* OMAP4460.BANDGAP_CTRL bits */
130#define OMAP4460_SINGLE_MODE_MASK BIT(31)
131#define OMAP4460_MASK_HOT_MASK BIT(1)
132#define OMAP4460_MASK_COLD_MASK BIT(0)
133
134/* OMAP4460.BANDGAP_COUNTER bits */
135#define OMAP4460_COUNTER_MASK (0xffffff << 0)
136
137/* OMAP4460.BANDGAP_THRESHOLD bits */
138#define OMAP4460_T_HOT_MASK (0x3ff << 16)
139#define OMAP4460_T_COLD_MASK (0x3ff << 0)
140
141/* OMAP4460.TSHUT_THRESHOLD bits */
142#define OMAP4460_TSHUT_HOT_MASK (0x3ff << 16)
143#define OMAP4460_TSHUT_COLD_MASK (0x3ff << 0)
144
145/* OMAP4460.BANDGAP_STATUS bits */
146#define OMAP4460_CLEAN_STOP_MASK BIT(3)
147#define OMAP4460_BGAP_ALERT_MASK BIT(2)
148#define OMAP4460_HOT_FLAG_MASK BIT(1)
149#define OMAP4460_COLD_FLAG_MASK BIT(0)
150
151/**
152 * Temperature limits and thresholds for OMAP4460
153 *
154 * All the macros bellow are definitions for handling the
155 * ADC conversions and representation of temperature limits
156 * and thresholds for OMAP4460.
157 */
158
159/* ADC conversion table limits */
160#define OMAP4460_ADC_START_VALUE 530
161#define OMAP4460_ADC_END_VALUE 932
162/* bandgap clock limits */
163#define OMAP4460_MAX_FREQ 1500000
164#define OMAP4460_MIN_FREQ 1000000
165/* sensor limits */
166#define OMAP4460_MIN_TEMP -40000
167#define OMAP4460_MAX_TEMP 123000
168#define OMAP4460_HYST_VAL 5000
169/* interrupts thresholds */
170#define OMAP4460_TSHUT_HOT 900 /* 122 deg C */
171#define OMAP4460_TSHUT_COLD 895 /* 100 deg C */
172#define OMAP4460_T_HOT 800 /* 73 deg C */
173#define OMAP4460_T_COLD 795 /* 71 deg C */
174
175#endif /* __OMAP4XXX_BANDGAP_H */
diff --git a/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
new file mode 100644
index 000000000000..eff0c80fd4af
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
@@ -0,0 +1,359 @@
1/*
2 * OMAP5 thermal driver.
3 *
4 * Copyright (C) 2011-2012 Texas Instruments Inc.
5 * Contact:
6 * Eduardo Valentin <eduardo.valentin@ti.com>
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19#include "ti-thermal.h"
20#include "ti-bandgap.h"
21#include "omap5xxx-bandgap.h"
22
23/*
24 * OMAP5430 has three instances of thermal sensor for MPU, GPU & CORE,
25 * need to describe the individual registers and bit fields.
26 */
27
28/*
29 * OMAP5430 MPU thermal sensor register offset and bit-fields
30 */
31static struct temp_sensor_registers
32omap5430_mpu_temp_sensor_registers = {
33 .temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_MPU_OFFSET,
34 .bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
35 .bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
36 .bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
37
38 .bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
39 .mask_hot_mask = OMAP5430_MASK_HOT_MPU_MASK,
40 .mask_cold_mask = OMAP5430_MASK_COLD_MPU_MASK,
41 .mask_sidlemode_mask = OMAP5430_MASK_SIDLEMODE_MASK,
42 .mask_counter_delay_mask = OMAP5430_MASK_COUNTER_DELAY_MASK,
43 .mask_freeze_mask = OMAP5430_MASK_FREEZE_MPU_MASK,
44 .mask_clear_mask = OMAP5430_MASK_CLEAR_MPU_MASK,
45 .mask_clear_accum_mask = OMAP5430_MASK_CLEAR_ACCUM_MPU_MASK,
46
47
48 .bgap_counter = OMAP5430_BGAP_CTRL_OFFSET,
49 .counter_mask = OMAP5430_COUNTER_MASK,
50
51 .bgap_threshold = OMAP5430_BGAP_THRESHOLD_MPU_OFFSET,
52 .threshold_thot_mask = OMAP5430_T_HOT_MASK,
53 .threshold_tcold_mask = OMAP5430_T_COLD_MASK,
54
55 .tshut_threshold = OMAP5430_BGAP_TSHUT_MPU_OFFSET,
56 .tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
57 .tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
58
59 .bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
60 .status_clean_stop_mask = 0x0,
61 .status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
62 .status_hot_mask = OMAP5430_HOT_MPU_FLAG_MASK,
63 .status_cold_mask = OMAP5430_COLD_MPU_FLAG_MASK,
64
65 .bgap_cumul_dtemp = OMAP5430_BGAP_CUMUL_DTEMP_MPU_OFFSET,
66 .ctrl_dtemp_0 = OMAP5430_BGAP_DTEMP_MPU_0_OFFSET,
67 .ctrl_dtemp_1 = OMAP5430_BGAP_DTEMP_MPU_1_OFFSET,
68 .ctrl_dtemp_2 = OMAP5430_BGAP_DTEMP_MPU_2_OFFSET,
69 .ctrl_dtemp_3 = OMAP5430_BGAP_DTEMP_MPU_3_OFFSET,
70 .ctrl_dtemp_4 = OMAP5430_BGAP_DTEMP_MPU_4_OFFSET,
71 .bgap_efuse = OMAP5430_FUSE_OPP_BGAP_MPU,
72};
73
74/*
75 * OMAP5430 GPU thermal sensor register offset and bit-fields
76 */
77static struct temp_sensor_registers
78omap5430_gpu_temp_sensor_registers = {
79 .temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_GPU_OFFSET,
80 .bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
81 .bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
82 .bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
83
84 .bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
85 .mask_hot_mask = OMAP5430_MASK_HOT_GPU_MASK,
86 .mask_cold_mask = OMAP5430_MASK_COLD_GPU_MASK,
87 .mask_sidlemode_mask = OMAP5430_MASK_SIDLEMODE_MASK,
88 .mask_counter_delay_mask = OMAP5430_MASK_COUNTER_DELAY_MASK,
89 .mask_freeze_mask = OMAP5430_MASK_FREEZE_GPU_MASK,
90 .mask_clear_mask = OMAP5430_MASK_CLEAR_GPU_MASK,
91 .mask_clear_accum_mask = OMAP5430_MASK_CLEAR_ACCUM_GPU_MASK,
92
93 .bgap_counter = OMAP5430_BGAP_CTRL_OFFSET,
94 .counter_mask = OMAP5430_COUNTER_MASK,
95
96 .bgap_threshold = OMAP5430_BGAP_THRESHOLD_GPU_OFFSET,
97 .threshold_thot_mask = OMAP5430_T_HOT_MASK,
98 .threshold_tcold_mask = OMAP5430_T_COLD_MASK,
99
100 .tshut_threshold = OMAP5430_BGAP_TSHUT_GPU_OFFSET,
101 .tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
102 .tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
103
104 .bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
105 .status_clean_stop_mask = 0x0,
106 .status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
107 .status_hot_mask = OMAP5430_HOT_GPU_FLAG_MASK,
108 .status_cold_mask = OMAP5430_COLD_GPU_FLAG_MASK,
109
110 .bgap_cumul_dtemp = OMAP5430_BGAP_CUMUL_DTEMP_GPU_OFFSET,
111 .ctrl_dtemp_0 = OMAP5430_BGAP_DTEMP_GPU_0_OFFSET,
112 .ctrl_dtemp_1 = OMAP5430_BGAP_DTEMP_GPU_1_OFFSET,
113 .ctrl_dtemp_2 = OMAP5430_BGAP_DTEMP_GPU_2_OFFSET,
114 .ctrl_dtemp_3 = OMAP5430_BGAP_DTEMP_GPU_3_OFFSET,
115 .ctrl_dtemp_4 = OMAP5430_BGAP_DTEMP_GPU_4_OFFSET,
116
117 .bgap_efuse = OMAP5430_FUSE_OPP_BGAP_GPU,
118};
119
120/*
121 * OMAP5430 CORE thermal sensor register offset and bit-fields
122 */
123static struct temp_sensor_registers
124omap5430_core_temp_sensor_registers = {
125 .temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_CORE_OFFSET,
126 .bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
127 .bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
128 .bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
129
130 .bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
131 .mask_hot_mask = OMAP5430_MASK_HOT_CORE_MASK,
132 .mask_cold_mask = OMAP5430_MASK_COLD_CORE_MASK,
133 .mask_sidlemode_mask = OMAP5430_MASK_SIDLEMODE_MASK,
134 .mask_counter_delay_mask = OMAP5430_MASK_COUNTER_DELAY_MASK,
135 .mask_freeze_mask = OMAP5430_MASK_FREEZE_CORE_MASK,
136 .mask_clear_mask = OMAP5430_MASK_CLEAR_CORE_MASK,
137 .mask_clear_accum_mask = OMAP5430_MASK_CLEAR_ACCUM_CORE_MASK,
138
139 .bgap_counter = OMAP5430_BGAP_CTRL_OFFSET,
140 .counter_mask = OMAP5430_COUNTER_MASK,
141
142 .bgap_threshold = OMAP5430_BGAP_THRESHOLD_CORE_OFFSET,
143 .threshold_thot_mask = OMAP5430_T_HOT_MASK,
144 .threshold_tcold_mask = OMAP5430_T_COLD_MASK,
145
146 .tshut_threshold = OMAP5430_BGAP_TSHUT_CORE_OFFSET,
147 .tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
148 .tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
149
150 .bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
151 .status_clean_stop_mask = 0x0,
152 .status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
153 .status_hot_mask = OMAP5430_HOT_CORE_FLAG_MASK,
154 .status_cold_mask = OMAP5430_COLD_CORE_FLAG_MASK,
155
156 .bgap_cumul_dtemp = OMAP5430_BGAP_CUMUL_DTEMP_CORE_OFFSET,
157 .ctrl_dtemp_0 = OMAP5430_BGAP_DTEMP_CORE_0_OFFSET,
158 .ctrl_dtemp_1 = OMAP5430_BGAP_DTEMP_CORE_1_OFFSET,
159 .ctrl_dtemp_2 = OMAP5430_BGAP_DTEMP_CORE_2_OFFSET,
160 .ctrl_dtemp_3 = OMAP5430_BGAP_DTEMP_CORE_3_OFFSET,
161 .ctrl_dtemp_4 = OMAP5430_BGAP_DTEMP_CORE_4_OFFSET,
162
163 .bgap_efuse = OMAP5430_FUSE_OPP_BGAP_CORE,
164};
165
166/* Thresholds and limits for OMAP5430 MPU temperature sensor */
167static struct temp_sensor_data omap5430_mpu_temp_sensor_data = {
168 .tshut_hot = OMAP5430_MPU_TSHUT_HOT,
169 .tshut_cold = OMAP5430_MPU_TSHUT_COLD,
170 .t_hot = OMAP5430_MPU_T_HOT,
171 .t_cold = OMAP5430_MPU_T_COLD,
172 .min_freq = OMAP5430_MPU_MIN_FREQ,
173 .max_freq = OMAP5430_MPU_MAX_FREQ,
174 .max_temp = OMAP5430_MPU_MAX_TEMP,
175 .min_temp = OMAP5430_MPU_MIN_TEMP,
176 .hyst_val = OMAP5430_MPU_HYST_VAL,
177 .update_int1 = 1000,
178 .update_int2 = 2000,
179};
180
181/* Thresholds and limits for OMAP5430 GPU temperature sensor */
182static struct temp_sensor_data omap5430_gpu_temp_sensor_data = {
183 .tshut_hot = OMAP5430_GPU_TSHUT_HOT,
184 .tshut_cold = OMAP5430_GPU_TSHUT_COLD,
185 .t_hot = OMAP5430_GPU_T_HOT,
186 .t_cold = OMAP5430_GPU_T_COLD,
187 .min_freq = OMAP5430_GPU_MIN_FREQ,
188 .max_freq = OMAP5430_GPU_MAX_FREQ,
189 .max_temp = OMAP5430_GPU_MAX_TEMP,
190 .min_temp = OMAP5430_GPU_MIN_TEMP,
191 .hyst_val = OMAP5430_GPU_HYST_VAL,
192 .update_int1 = 1000,
193 .update_int2 = 2000,
194};
195
196/* Thresholds and limits for OMAP5430 CORE temperature sensor */
197static struct temp_sensor_data omap5430_core_temp_sensor_data = {
198 .tshut_hot = OMAP5430_CORE_TSHUT_HOT,
199 .tshut_cold = OMAP5430_CORE_TSHUT_COLD,
200 .t_hot = OMAP5430_CORE_T_HOT,
201 .t_cold = OMAP5430_CORE_T_COLD,
202 .min_freq = OMAP5430_CORE_MIN_FREQ,
203 .max_freq = OMAP5430_CORE_MAX_FREQ,
204 .max_temp = OMAP5430_CORE_MAX_TEMP,
205 .min_temp = OMAP5430_CORE_MIN_TEMP,
206 .hyst_val = OMAP5430_CORE_HYST_VAL,
207 .update_int1 = 1000,
208 .update_int2 = 2000,
209};
210
211/*
212 * OMAP54xx ES2.0 : Temperature values in milli degree celsius
213 * ADC code values from 540 to 945
214 */
215static int
216omap5430_adc_to_temp[
217 OMAP5430_ADC_END_VALUE - OMAP5430_ADC_START_VALUE + 1] = {
218 /* Index 540 - 549 */
219 -40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200,
220 -37800,
221 /* Index 550 - 559 */
222 -37400, -37000, -36600, -36200, -35800, -35300, -34700, -34200, -33800,
223 -33400,
224 /* Index 560 - 569 */
225 -33000, -32600, -32200, -31800, -31400, -31000, -30600, -30200, -29800,
226 -29400,
227 /* Index 570 - 579 */
228 -29000, -28600, -28200, -27700, -27100, -26600, -26200, -25800, -25400,
229 -25000,
230 /* Index 580 - 589 */
231 -24600, -24200, -23800, -23400, -23000, -22600, -22200, -21600, -21400,
232 -21000,
233 /* Index 590 - 599 */
234 -20500, -19900, -19400, -19000, -18600, -18200, -17800, -17400, -17000,
235 -16600,
236 /* Index 600 - 609 */
237 -16200, -15800, -15400, -15000, -14600, -14200, -13800, -13400, -13000,
238 -12500,
239 /* Index 610 - 619 */
240 -11900, -11400, -11000, -10600, -10200, -9800, -9400, -9000, -8600,
241 -8200,
242 /* Index 620 - 629 */
243 -7800, -7400, -7000, -6600, -6200, -5800, -5400, -5000, -4500, -3900,
244 /* Index 630 - 639 */
245 -3400, -3000, -2600, -2200, -1800, -1400, -1000, -600, -200, 200,
246 /* Index 640 - 649 */
247 600, 1000, 1400, 1800, 2200, 2600, 3000, 3400, 3900, 4500,
248 /* Index 650 - 659 */
249 5000, 5400, 5800, 6200, 6600, 7000, 7400, 7800, 8200, 8600,
250 /* Index 660 - 669 */
251 9000, 9400, 9800, 10200, 10600, 11000, 11400, 11800, 12200, 12700,
252 /* Index 670 - 679 */
253 13300, 13800, 14200, 14600, 15000, 15400, 15800, 16200, 16600, 17000,
254 /* Index 680 - 689 */
255 17400, 17800, 18200, 18600, 19000, 19400, 19800, 20200, 20600, 21100,
256 /* Index 690 - 699 */
257 21400, 21900, 22500, 23000, 23400, 23800, 24200, 24600, 25000, 25400,
258 /* Index 700 - 709 */
259 25800, 26200, 26600, 27000, 27400, 27800, 28200, 28600, 29000, 29400,
260 /* Index 710 - 719 */
261 29800, 30200, 30600, 31000, 31400, 31900, 32500, 33000, 33400, 33800,
262 /* Index 720 - 729 */
263 34200, 34600, 35000, 35400, 35800, 36200, 36600, 37000, 37400, 37800,
264 /* Index 730 - 739 */
265 38200, 38600, 39000, 39400, 39800, 40200, 40600, 41000, 41400, 41800,
266 /* Index 740 - 749 */
267 42200, 42600, 43100, 43700, 44200, 44600, 45000, 45400, 45800, 46200,
268 /* Index 750 - 759 */
269 46600, 47000, 47400, 47800, 48200, 48600, 49000, 49400, 49800, 50200,
270 /* Index 760 - 769 */
271 50600, 51000, 51400, 51800, 52200, 52600, 53000, 53400, 53800, 54200,
272 /* Index 770 - 779 */
273 54600, 55000, 55400, 55900, 56500, 57000, 57400, 57800, 58200, 58600,
274 /* Index 780 - 789 */
275 59000, 59400, 59800, 60200, 60600, 61000, 61400, 61800, 62200, 62600,
276 /* Index 790 - 799 */
277 63000, 63400, 63800, 64200, 64600, 65000, 65400, 65800, 66200, 66600,
278 /* Index 800 - 809 */
279 67000, 67400, 67800, 68200, 68600, 69000, 69400, 69800, 70200, 70600,
280 /* Index 810 - 819 */
281 71000, 71500, 72100, 72600, 73000, 73400, 73800, 74200, 74600, 75000,
282 /* Index 820 - 829 */
283 75400, 75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000,
284 /* Index 830 - 839 */
285 79400, 79800, 80200, 80600, 81000, 81400, 81800, 82200, 82600, 83000,
286 /* Index 840 - 849 */
287 83400, 83800, 84200, 84600, 85000, 85400, 85800, 86200, 86600, 87000,
288 /* Index 850 - 859 */
289 87400, 87800, 88200, 88600, 89000, 89400, 89800, 90200, 90600, 91000,
290 /* Index 860 - 869 */
291 91400, 91800, 92200, 92600, 93000, 93400, 93800, 94200, 94600, 95000,
292 /* Index 870 - 879 */
293 95400, 95800, 96200, 96600, 97000, 97500, 98100, 98600, 99000, 99400,
294 /* Index 880 - 889 */
295 99800, 100200, 100600, 101000, 101400, 101800, 102200, 102600, 103000,
296 103400,
297 /* Index 890 - 899 */
298 103800, 104200, 104600, 105000, 105400, 105800, 106200, 106600, 107000,
299 107400,
300 /* Index 900 - 909 */
301 107800, 108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000,
302 111400,
303 /* Index 910 - 919 */
304 111800, 112200, 112600, 113000, 113400, 113800, 114200, 114600, 115000,
305 115400,
306 /* Index 920 - 929 */
307 115800, 116200, 116600, 117000, 117400, 117800, 118200, 118600, 119000,
308 119400,
309 /* Index 930 - 939 */
310 119800, 120200, 120600, 121000, 121400, 121800, 122400, 122600, 123000,
311 123400,
312 /* Index 940 - 945 */
313 123800, 1242000, 124600, 124900, 125000, 125000,
314};
315
316/* OMAP54xx ES2.0 data */
317const struct ti_bandgap_data omap5430_data = {
318 .features = TI_BANDGAP_FEATURE_TSHUT_CONFIG |
319 TI_BANDGAP_FEATURE_FREEZE_BIT |
320 TI_BANDGAP_FEATURE_TALERT |
321 TI_BANDGAP_FEATURE_COUNTER_DELAY |
322 TI_BANDGAP_FEATURE_HISTORY_BUFFER,
323 .fclock_name = "l3instr_ts_gclk_div",
324 .div_ck_name = "l3instr_ts_gclk_div",
325 .conv_table = omap5430_adc_to_temp,
326 .adc_start_val = OMAP5430_ADC_START_VALUE,
327 .adc_end_val = OMAP5430_ADC_END_VALUE,
328 .expose_sensor = ti_thermal_expose_sensor,
329 .remove_sensor = ti_thermal_remove_sensor,
330 .report_temperature = ti_thermal_report_sensor_temperature,
331 .sensors = {
332 {
333 .registers = &omap5430_mpu_temp_sensor_registers,
334 .ts_data = &omap5430_mpu_temp_sensor_data,
335 .domain = "cpu",
336 .register_cooling = ti_thermal_register_cpu_cooling,
337 .unregister_cooling = ti_thermal_unregister_cpu_cooling,
338 .slope = OMAP_GRADIENT_SLOPE_5430_CPU,
339 .constant = OMAP_GRADIENT_CONST_5430_CPU,
340 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU,
341 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_CPU,
342 },
343 {
344 .registers = &omap5430_gpu_temp_sensor_registers,
345 .ts_data = &omap5430_gpu_temp_sensor_data,
346 .domain = "gpu",
347 .slope = OMAP_GRADIENT_SLOPE_5430_GPU,
348 .constant = OMAP_GRADIENT_CONST_5430_GPU,
349 .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU,
350 .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_GPU,
351 },
352 {
353 .registers = &omap5430_core_temp_sensor_registers,
354 .ts_data = &omap5430_core_temp_sensor_data,
355 .domain = "core",
356 },
357 },
358 .sensor_count = 3,
359};
diff --git a/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h b/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h
new file mode 100644
index 000000000000..400b55dffadd
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h
@@ -0,0 +1,200 @@
1/*
2 * OMAP5xxx 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 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23#ifndef __OMAP5XXX_BANDGAP_H
24#define __OMAP5XXX_BANDGAP_H
25
26/**
27 * *** OMAP5430 ***
28 *
29 * Below, in sequence, are the Register definitions,
30 * the bitfields and the temperature definitions for OMAP5430.
31 */
32
33/**
34 * OMAP5430 register definitions
35 *
36 * Registers are defined as offsets. The offsets are
37 * relative to FUSE_OPP_BGAP_GPU on 5430.
38 *
39 * Register below are grouped by domain (not necessarily in offset order)
40 */
41
42/* OMAP5430.GPU register offsets */
43#define OMAP5430_FUSE_OPP_BGAP_GPU 0x0
44#define OMAP5430_TEMP_SENSOR_GPU_OFFSET 0x150
45#define OMAP5430_BGAP_THRESHOLD_GPU_OFFSET 0x1A8
46#define OMAP5430_BGAP_TSHUT_GPU_OFFSET 0x1B4
47#define OMAP5430_BGAP_CUMUL_DTEMP_GPU_OFFSET 0x1C0
48#define OMAP5430_BGAP_DTEMP_GPU_0_OFFSET 0x1F4
49#define OMAP5430_BGAP_DTEMP_GPU_1_OFFSET 0x1F8
50#define OMAP5430_BGAP_DTEMP_GPU_2_OFFSET 0x1FC
51#define OMAP5430_BGAP_DTEMP_GPU_3_OFFSET 0x200
52#define OMAP5430_BGAP_DTEMP_GPU_4_OFFSET 0x204
53
54/* OMAP5430.MPU register offsets */
55#define OMAP5430_FUSE_OPP_BGAP_MPU 0x4
56#define OMAP5430_TEMP_SENSOR_MPU_OFFSET 0x14C
57#define OMAP5430_BGAP_THRESHOLD_MPU_OFFSET 0x1A4
58#define OMAP5430_BGAP_TSHUT_MPU_OFFSET 0x1B0
59#define OMAP5430_BGAP_CUMUL_DTEMP_MPU_OFFSET 0x1BC
60#define OMAP5430_BGAP_DTEMP_MPU_0_OFFSET 0x1E0
61#define OMAP5430_BGAP_DTEMP_MPU_1_OFFSET 0x1E4
62#define OMAP5430_BGAP_DTEMP_MPU_2_OFFSET 0x1E8
63#define OMAP5430_BGAP_DTEMP_MPU_3_OFFSET 0x1EC
64#define OMAP5430_BGAP_DTEMP_MPU_4_OFFSET 0x1F0
65
66/* OMAP5430.MPU register offsets */
67#define OMAP5430_FUSE_OPP_BGAP_CORE 0x8
68#define OMAP5430_TEMP_SENSOR_CORE_OFFSET 0x154
69#define OMAP5430_BGAP_THRESHOLD_CORE_OFFSET 0x1AC
70#define OMAP5430_BGAP_TSHUT_CORE_OFFSET 0x1B8
71#define OMAP5430_BGAP_CUMUL_DTEMP_CORE_OFFSET 0x1C4
72#define OMAP5430_BGAP_DTEMP_CORE_0_OFFSET 0x208
73#define OMAP5430_BGAP_DTEMP_CORE_1_OFFSET 0x20C
74#define OMAP5430_BGAP_DTEMP_CORE_2_OFFSET 0x210
75#define OMAP5430_BGAP_DTEMP_CORE_3_OFFSET 0x214
76#define OMAP5430_BGAP_DTEMP_CORE_4_OFFSET 0x218
77
78/* OMAP5430.common register offsets */
79#define OMAP5430_BGAP_CTRL_OFFSET 0x1A0
80#define OMAP5430_BGAP_STATUS_OFFSET 0x1C8
81
82/**
83 * Register bitfields for OMAP5430
84 *
85 * All the macros bellow define the required bits for
86 * controlling temperature on OMAP5430. Bit defines are
87 * grouped by register.
88 */
89
90/* OMAP5430.TEMP_SENSOR */
91#define OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK BIT(12)
92#define OMAP5430_BGAP_TEMPSOFF_MASK BIT(11)
93#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK BIT(10)
94#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK (0x3ff << 0)
95
96/* OMAP5430.BANDGAP_CTRL */
97#define OMAP5430_MASK_SIDLEMODE_MASK (0x3 << 30)
98#define OMAP5430_MASK_COUNTER_DELAY_MASK (0x7 << 27)
99#define OMAP5430_MASK_FREEZE_CORE_MASK BIT(23)
100#define OMAP5430_MASK_FREEZE_GPU_MASK BIT(22)
101#define OMAP5430_MASK_FREEZE_MPU_MASK BIT(21)
102#define OMAP5430_MASK_CLEAR_CORE_MASK BIT(20)
103#define OMAP5430_MASK_CLEAR_GPU_MASK BIT(19)
104#define OMAP5430_MASK_CLEAR_MPU_MASK BIT(18)
105#define OMAP5430_MASK_CLEAR_ACCUM_CORE_MASK BIT(17)
106#define OMAP5430_MASK_CLEAR_ACCUM_GPU_MASK BIT(16)
107#define OMAP5430_MASK_CLEAR_ACCUM_MPU_MASK BIT(15)
108#define OMAP5430_MASK_HOT_CORE_MASK BIT(5)
109#define OMAP5430_MASK_COLD_CORE_MASK BIT(4)
110#define OMAP5430_MASK_HOT_GPU_MASK BIT(3)
111#define OMAP5430_MASK_COLD_GPU_MASK BIT(2)
112#define OMAP5430_MASK_HOT_MPU_MASK BIT(1)
113#define OMAP5430_MASK_COLD_MPU_MASK BIT(0)
114
115/* OMAP5430.BANDGAP_COUNTER */
116#define OMAP5430_COUNTER_MASK (0xffffff << 0)
117
118/* OMAP5430.BANDGAP_THRESHOLD */
119#define OMAP5430_T_HOT_MASK (0x3ff << 16)
120#define OMAP5430_T_COLD_MASK (0x3ff << 0)
121
122/* OMAP5430.TSHUT_THRESHOLD */
123#define OMAP5430_TSHUT_HOT_MASK (0x3ff << 16)
124#define OMAP5430_TSHUT_COLD_MASK (0x3ff << 0)
125
126/* OMAP5430.BANDGAP_CUMUL_DTEMP_MPU */
127#define OMAP5430_CUMUL_DTEMP_MPU_MASK (0xffffffff << 0)
128
129/* OMAP5430.BANDGAP_CUMUL_DTEMP_GPU */
130#define OMAP5430_CUMUL_DTEMP_GPU_MASK (0xffffffff << 0)
131
132/* OMAP5430.BANDGAP_CUMUL_DTEMP_CORE */
133#define OMAP5430_CUMUL_DTEMP_CORE_MASK (0xffffffff << 0)
134
135/* OMAP5430.BANDGAP_STATUS */
136#define OMAP5430_BGAP_ALERT_MASK BIT(31)
137#define OMAP5430_HOT_CORE_FLAG_MASK BIT(5)
138#define OMAP5430_COLD_CORE_FLAG_MASK BIT(4)
139#define OMAP5430_HOT_GPU_FLAG_MASK BIT(3)
140#define OMAP5430_COLD_GPU_FLAG_MASK BIT(2)
141#define OMAP5430_HOT_MPU_FLAG_MASK BIT(1)
142#define OMAP5430_COLD_MPU_FLAG_MASK BIT(0)
143
144/**
145 * Temperature limits and thresholds for OMAP5430
146 *
147 * All the macros bellow are definitions for handling the
148 * ADC conversions and representation of temperature limits
149 * and thresholds for OMAP5430. Definitions are grouped
150 * by temperature domain.
151 */
152
153/* OMAP5430.common temperature definitions */
154/* ADC conversion table limits */
155#define OMAP5430_ADC_START_VALUE 540
156#define OMAP5430_ADC_END_VALUE 945
157
158/* OMAP5430.GPU temperature definitions */
159/* bandgap clock limits */
160#define OMAP5430_GPU_MAX_FREQ 1500000
161#define OMAP5430_GPU_MIN_FREQ 1000000
162/* sensor limits */
163#define OMAP5430_GPU_MIN_TEMP -40000
164#define OMAP5430_GPU_MAX_TEMP 125000
165#define OMAP5430_GPU_HYST_VAL 5000
166/* interrupts thresholds */
167#define OMAP5430_GPU_TSHUT_HOT 915
168#define OMAP5430_GPU_TSHUT_COLD 900
169#define OMAP5430_GPU_T_HOT 800
170#define OMAP5430_GPU_T_COLD 795
171
172/* OMAP5430.MPU temperature definitions */
173/* bandgap clock limits */
174#define OMAP5430_MPU_MAX_FREQ 1500000
175#define OMAP5430_MPU_MIN_FREQ 1000000
176/* sensor limits */
177#define OMAP5430_MPU_MIN_TEMP -40000
178#define OMAP5430_MPU_MAX_TEMP 125000
179#define OMAP5430_MPU_HYST_VAL 5000
180/* interrupts thresholds */
181#define OMAP5430_MPU_TSHUT_HOT 915
182#define OMAP5430_MPU_TSHUT_COLD 900
183#define OMAP5430_MPU_T_HOT 800
184#define OMAP5430_MPU_T_COLD 795
185
186/* OMAP5430.CORE temperature definitions */
187/* bandgap clock limits */
188#define OMAP5430_CORE_MAX_FREQ 1500000
189#define OMAP5430_CORE_MIN_FREQ 1000000
190/* sensor limits */
191#define OMAP5430_CORE_MIN_TEMP -40000
192#define OMAP5430_CORE_MAX_TEMP 125000
193#define OMAP5430_CORE_HYST_VAL 5000
194/* interrupts thresholds */
195#define OMAP5430_CORE_TSHUT_HOT 915
196#define OMAP5430_CORE_TSHUT_COLD 900
197#define OMAP5430_CORE_T_HOT 800
198#define OMAP5430_CORE_T_COLD 795
199
200#endif /* __OMAP5XXX_BANDGAP_H */
diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
new file mode 100644
index 000000000000..9dfd47196e63
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
@@ -0,0 +1,1556 @@
1/*
2 * TI Bandgap temperature sensor driver
3 *
4 * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
5 * Author: J Keerthy <j-keerthy@ti.com>
6 * Author: Moiz Sonasath <m-sonasath@ti.com>
7 * Couple of fixes, DT and MFD adaptation:
8 * Eduardo Valentin <eduardo.valentin@ti.com>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * version 2 as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 * 02110-1301 USA
23 *
24 */
25
26#include <linux/module.h>
27#include <linux/export.h>
28#include <linux/init.h>
29#include <linux/kernel.h>
30#include <linux/interrupt.h>
31#include <linux/clk.h>
32#include <linux/gpio.h>
33#include <linux/platform_device.h>
34#include <linux/err.h>
35#include <linux/types.h>
36#include <linux/spinlock.h>
37#include <linux/reboot.h>
38#include <linux/of_device.h>
39#include <linux/of_platform.h>
40#include <linux/of_irq.h>
41#include <linux/of_gpio.h>
42#include <linux/io.h>
43
44#include "ti-bandgap.h"
45
46/*** Helper functions to access registers and their bitfields ***/
47
48/**
49 * ti_bandgap_readl() - simple read helper function
50 * @bgp: pointer to ti_bandgap structure
51 * @reg: desired register (offset) to be read
52 *
53 * Helper function to read bandgap registers. It uses the io remapped area.
54 * Return: the register value.
55 */
56static u32 ti_bandgap_readl(struct ti_bandgap *bgp, u32 reg)
57{
58 return readl(bgp->base + reg);
59}
60
61/**
62 * ti_bandgap_writel() - simple write helper function
63 * @bgp: pointer to ti_bandgap structure
64 * @val: desired register value to be written
65 * @reg: desired register (offset) to be written
66 *
67 * Helper function to write bandgap registers. It uses the io remapped area.
68 */
69static void ti_bandgap_writel(struct ti_bandgap *bgp, u32 val, u32 reg)
70{
71 writel(val, bgp->base + reg);
72}
73
74/**
75 * DOC: macro to update bits.
76 *
77 * RMW_BITS() - used to read, modify and update bandgap bitfields.
78 * The value passed will be shifted.
79 */
80#define RMW_BITS(bgp, id, reg, mask, val) \
81do { \
82 struct temp_sensor_registers *t; \
83 u32 r; \
84 \
85 t = bgp->conf->sensors[(id)].registers; \
86 r = ti_bandgap_readl(bgp, t->reg); \
87 r &= ~t->mask; \
88 r |= (val) << __ffs(t->mask); \
89 ti_bandgap_writel(bgp, r, t->reg); \
90} while (0)
91
92/*** Basic helper functions ***/
93
94/**
95 * ti_bandgap_power() - controls the power state of a bandgap device
96 * @bgp: pointer to ti_bandgap structure
97 * @on: desired power state (1 - on, 0 - off)
98 *
99 * Used to power on/off a bandgap device instance. Only used on those
100 * that features tempsoff bit.
101 *
102 * Return: 0 on success, -ENOTSUPP if tempsoff is not supported.
103 */
104static int ti_bandgap_power(struct ti_bandgap *bgp, bool on)
105{
106 int i, ret = 0;
107
108 if (!TI_BANDGAP_HAS(bgp, POWER_SWITCH)) {
109 ret = -ENOTSUPP;
110 goto exit;
111 }
112
113 for (i = 0; i < bgp->conf->sensor_count; i++)
114 /* active on 0 */
115 RMW_BITS(bgp, i, temp_sensor_ctrl, bgap_tempsoff_mask, !on);
116
117exit:
118 return ret;
119}
120
121/**
122 * ti_bandgap_read_temp() - helper function to read sensor temperature
123 * @bgp: pointer to ti_bandgap structure
124 * @id: bandgap sensor id
125 *
126 * Function to concentrate the steps to read sensor temperature register.
127 * This function is desired because, depending on bandgap device version,
128 * it might be needed to freeze the bandgap state machine, before fetching
129 * the register value.
130 *
131 * Return: temperature in ADC values.
132 */
133static u32 ti_bandgap_read_temp(struct ti_bandgap *bgp, int id)
134{
135 struct temp_sensor_registers *tsr;
136 u32 temp, reg;
137
138 tsr = bgp->conf->sensors[id].registers;
139 reg = tsr->temp_sensor_ctrl;
140
141 if (TI_BANDGAP_HAS(bgp, FREEZE_BIT)) {
142 RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1);
143 /*
144 * In case we cannot read from cur_dtemp / dtemp_0,
145 * then we read from the last valid temp read
146 */
147 reg = tsr->ctrl_dtemp_1;
148 }
149
150 /* read temperature */
151 temp = ti_bandgap_readl(bgp, reg);
152 temp &= tsr->bgap_dtemp_mask;
153
154 if (TI_BANDGAP_HAS(bgp, FREEZE_BIT))
155 RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0);
156
157 return temp;
158}
159
160/*** IRQ handlers ***/
161
162/**
163 * ti_bandgap_talert_irq_handler() - handles Temperature alert IRQs
164 * @irq: IRQ number
165 * @data: private data (struct ti_bandgap *)
166 *
167 * This is the Talert handler. Use it only if bandgap device features
168 * HAS(TALERT). This handler goes over all sensors and checks their
169 * conditions and acts accordingly. In case there are events pending,
170 * it will reset the event mask to wait for the opposite event (next event).
171 * Every time there is a new event, it will be reported to thermal layer.
172 *
173 * Return: IRQ_HANDLED
174 */
175static irqreturn_t ti_bandgap_talert_irq_handler(int irq, void *data)
176{
177 struct ti_bandgap *bgp = data;
178 struct temp_sensor_registers *tsr;
179 u32 t_hot = 0, t_cold = 0, ctrl;
180 int i;
181
182 spin_lock(&bgp->lock);
183 for (i = 0; i < bgp->conf->sensor_count; i++) {
184 tsr = bgp->conf->sensors[i].registers;
185 ctrl = ti_bandgap_readl(bgp, tsr->bgap_status);
186
187 /* Read the status of t_hot */
188 t_hot = ctrl & tsr->status_hot_mask;
189
190 /* Read the status of t_cold */
191 t_cold = ctrl & tsr->status_cold_mask;
192
193 if (!t_cold && !t_hot)
194 continue;
195
196 ctrl = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
197 /*
198 * One TALERT interrupt: Two sources
199 * If the interrupt is due to t_hot then mask t_hot and
200 * and unmask t_cold else mask t_cold and unmask t_hot
201 */
202 if (t_hot) {
203 ctrl &= ~tsr->mask_hot_mask;
204 ctrl |= tsr->mask_cold_mask;
205 } else if (t_cold) {
206 ctrl &= ~tsr->mask_cold_mask;
207 ctrl |= tsr->mask_hot_mask;
208 }
209
210 ti_bandgap_writel(bgp, ctrl, tsr->bgap_mask_ctrl);
211
212 dev_dbg(bgp->dev,
213 "%s: IRQ from %s sensor: hotevent %d coldevent %d\n",
214 __func__, bgp->conf->sensors[i].domain,
215 t_hot, t_cold);
216
217 /* report temperature to whom may concern */
218 if (bgp->conf->report_temperature)
219 bgp->conf->report_temperature(bgp, i);
220 }
221 spin_unlock(&bgp->lock);
222
223 return IRQ_HANDLED;
224}
225
226/**
227 * ti_bandgap_tshut_irq_handler() - handles Temperature shutdown signal
228 * @irq: IRQ number
229 * @data: private data (unused)
230 *
231 * This is the Tshut handler. Use it only if bandgap device features
232 * HAS(TSHUT). If any sensor fires the Tshut signal, we simply shutdown
233 * the system.
234 *
235 * Return: IRQ_HANDLED
236 */
237static irqreturn_t ti_bandgap_tshut_irq_handler(int irq, void *data)
238{
239 pr_emerg("%s: TSHUT temperature reached. Needs shut down...\n",
240 __func__);
241
242 orderly_poweroff(true);
243
244 return IRQ_HANDLED;
245}
246
247/*** Helper functions which manipulate conversion ADC <-> mi Celsius ***/
248
249/**
250 * ti_bandgap_adc_to_mcelsius() - converts an ADC value to mCelsius scale
251 * @bgp: struct ti_bandgap pointer
252 * @adc_val: value in ADC representation
253 * @t: address where to write the resulting temperature in mCelsius
254 *
255 * Simple conversion from ADC representation to mCelsius. In case the ADC value
256 * is out of the ADC conv table range, it returns -ERANGE, 0 on success.
257 * The conversion table is indexed by the ADC values.
258 *
259 * Return: 0 if conversion was successful, else -ERANGE in case the @adc_val
260 * argument is out of the ADC conv table range.
261 */
262static
263int ti_bandgap_adc_to_mcelsius(struct ti_bandgap *bgp, int adc_val, int *t)
264{
265 const struct ti_bandgap_data *conf = bgp->conf;
266 int ret = 0;
267
268 /* look up for temperature in the table and return the temperature */
269 if (adc_val < conf->adc_start_val || adc_val > conf->adc_end_val) {
270 ret = -ERANGE;
271 goto exit;
272 }
273
274 *t = bgp->conf->conv_table[adc_val - conf->adc_start_val];
275
276exit:
277 return ret;
278}
279
280/**
281 * ti_bandgap_mcelsius_to_adc() - converts a mCelsius value to ADC scale
282 * @bgp: struct ti_bandgap pointer
283 * @temp: value in mCelsius
284 * @adc: address where to write the resulting temperature in ADC representation
285 *
286 * Simple conversion from mCelsius to ADC values. In case the temp value
287 * is out of the ADC conv table range, it returns -ERANGE, 0 on success.
288 * The conversion table is indexed by the ADC values.
289 *
290 * Return: 0 if conversion was successful, else -ERANGE in case the @temp
291 * argument is out of the ADC conv table range.
292 */
293static
294int ti_bandgap_mcelsius_to_adc(struct ti_bandgap *bgp, long temp, int *adc)
295{
296 const struct ti_bandgap_data *conf = bgp->conf;
297 const int *conv_table = bgp->conf->conv_table;
298 int high, low, mid, ret = 0;
299
300 low = 0;
301 high = conf->adc_end_val - conf->adc_start_val;
302 mid = (high + low) / 2;
303
304 if (temp < conv_table[low] || temp > conv_table[high]) {
305 ret = -ERANGE;
306 goto exit;
307 }
308
309 while (low < high) {
310 if (temp < conv_table[mid])
311 high = mid - 1;
312 else
313 low = mid + 1;
314 mid = (low + high) / 2;
315 }
316
317 *adc = conf->adc_start_val + low;
318
319exit:
320 return ret;
321}
322
323/**
324 * ti_bandgap_add_hyst() - add hysteresis (in mCelsius) to an ADC value
325 * @bgp: struct ti_bandgap pointer
326 * @adc_val: temperature value in ADC representation
327 * @hyst_val: hysteresis value in mCelsius
328 * @sum: address where to write the resulting temperature (in ADC scale)
329 *
330 * Adds an hysteresis value (in mCelsius) to a ADC temperature value.
331 *
332 * Return: 0 on success, -ERANGE otherwise.
333 */
334static
335int ti_bandgap_add_hyst(struct ti_bandgap *bgp, int adc_val, int hyst_val,
336 u32 *sum)
337{
338 int temp, ret;
339
340 /*
341 * Need to add in the mcelsius domain, so we have a temperature
342 * the conv_table range
343 */
344 ret = ti_bandgap_adc_to_mcelsius(bgp, adc_val, &temp);
345 if (ret < 0)
346 goto exit;
347
348 temp += hyst_val;
349
350 ret = ti_bandgap_mcelsius_to_adc(bgp, temp, sum);
351
352exit:
353 return ret;
354}
355
356/*** Helper functions handling device Alert/Shutdown signals ***/
357
358/**
359 * ti_bandgap_unmask_interrupts() - unmasks the events of thot & tcold
360 * @bgp: struct ti_bandgap pointer
361 * @id: bandgap sensor id
362 * @t_hot: hot temperature value to trigger alert signal
363 * @t_cold: cold temperature value to trigger alert signal
364 *
365 * Checks the requested t_hot and t_cold values and configures the IRQ event
366 * masks accordingly. Call this function only if bandgap features HAS(TALERT).
367 */
368static void ti_bandgap_unmask_interrupts(struct ti_bandgap *bgp, int id,
369 u32 t_hot, u32 t_cold)
370{
371 struct temp_sensor_registers *tsr;
372 u32 temp, reg_val;
373
374 /* Read the current on die temperature */
375 temp = ti_bandgap_read_temp(bgp, id);
376
377 tsr = bgp->conf->sensors[id].registers;
378 reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
379
380 if (temp < t_hot)
381 reg_val |= tsr->mask_hot_mask;
382 else
383 reg_val &= ~tsr->mask_hot_mask;
384
385 if (t_cold < temp)
386 reg_val |= tsr->mask_cold_mask;
387 else
388 reg_val &= ~tsr->mask_cold_mask;
389 ti_bandgap_writel(bgp, reg_val, tsr->bgap_mask_ctrl);
390}
391
392/**
393 * ti_bandgap_update_alert_threshold() - sequence to update thresholds
394 * @bgp: struct ti_bandgap pointer
395 * @id: bandgap sensor id
396 * @val: value (ADC) of a new threshold
397 * @hot: desired threshold to be updated. true if threshold hot, false if
398 * threshold cold
399 *
400 * It will program the required thresholds (hot and cold) for TALERT signal.
401 * This function can be used to update t_hot or t_cold, depending on @hot value.
402 * It checks the resulting t_hot and t_cold values, based on the new passed @val
403 * and configures the thresholds so that t_hot is always greater than t_cold.
404 * Call this function only if bandgap features HAS(TALERT).
405 *
406 * Return: 0 if no error, else corresponding error
407 */
408static int ti_bandgap_update_alert_threshold(struct ti_bandgap *bgp, int id,
409 int val, bool hot)
410{
411 struct temp_sensor_data *ts_data = bgp->conf->sensors[id].ts_data;
412 struct temp_sensor_registers *tsr;
413 u32 thresh_val, reg_val, t_hot, t_cold;
414 int err = 0;
415
416 tsr = bgp->conf->sensors[id].registers;
417
418 /* obtain the current value */
419 thresh_val = ti_bandgap_readl(bgp, tsr->bgap_threshold);
420 t_cold = (thresh_val & tsr->threshold_tcold_mask) >>
421 __ffs(tsr->threshold_tcold_mask);
422 t_hot = (thresh_val & tsr->threshold_thot_mask) >>
423 __ffs(tsr->threshold_thot_mask);
424 if (hot)
425 t_hot = val;
426 else
427 t_cold = val;
428
429 if (t_cold > t_hot) {
430 if (hot)
431 err = ti_bandgap_add_hyst(bgp, t_hot,
432 -ts_data->hyst_val,
433 &t_cold);
434 else
435 err = ti_bandgap_add_hyst(bgp, t_cold,
436 ts_data->hyst_val,
437 &t_hot);
438 }
439
440 /* write the new threshold values */
441 reg_val = thresh_val &
442 ~(tsr->threshold_thot_mask | tsr->threshold_tcold_mask);
443 reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask)) |
444 (t_cold << __ffs(tsr->threshold_tcold_mask));
445 ti_bandgap_writel(bgp, reg_val, tsr->bgap_threshold);
446
447 if (err) {
448 dev_err(bgp->dev, "failed to reprogram thot threshold\n");
449 err = -EIO;
450 goto exit;
451 }
452
453 ti_bandgap_unmask_interrupts(bgp, id, t_hot, t_cold);
454exit:
455 return err;
456}
457
458/**
459 * ti_bandgap_validate() - helper to check the sanity of a struct ti_bandgap
460 * @bgp: struct ti_bandgap pointer
461 * @id: bandgap sensor id
462 *
463 * Checks if the bandgap pointer is valid and if the sensor id is also
464 * applicable.
465 *
466 * Return: 0 if no errors, -EINVAL for invalid @bgp pointer or -ERANGE if
467 * @id cannot index @bgp sensors.
468 */
469static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id)
470{
471 int ret = 0;
472
473 if (!bgp || IS_ERR(bgp)) {
474 pr_err("%s: invalid bandgap pointer\n", __func__);
475 ret = -EINVAL;
476 goto exit;
477 }
478
479 if ((id < 0) || (id >= bgp->conf->sensor_count)) {
480 dev_err(bgp->dev, "%s: sensor id out of range (%d)\n",
481 __func__, id);
482 ret = -ERANGE;
483 }
484
485exit:
486 return ret;
487}
488
489/**
490 * _ti_bandgap_write_threshold() - helper to update TALERT t_cold or t_hot
491 * @bgp: struct ti_bandgap pointer
492 * @id: bandgap sensor id
493 * @val: value (mCelsius) of a new threshold
494 * @hot: desired threshold to be updated. true if threshold hot, false if
495 * threshold cold
496 *
497 * It will update the required thresholds (hot and cold) for TALERT signal.
498 * This function can be used to update t_hot or t_cold, depending on @hot value.
499 * Validates the mCelsius range and update the requested threshold.
500 * Call this function only if bandgap features HAS(TALERT).
501 *
502 * Return: 0 if no error, else corresponding error value.
503 */
504static int _ti_bandgap_write_threshold(struct ti_bandgap *bgp, int id, int val,
505 bool hot)
506{
507 struct temp_sensor_data *ts_data;
508 struct temp_sensor_registers *tsr;
509 u32 adc_val;
510 int ret;
511
512 ret = ti_bandgap_validate(bgp, id);
513 if (ret)
514 goto exit;
515
516 if (!TI_BANDGAP_HAS(bgp, TALERT)) {
517 ret = -ENOTSUPP;
518 goto exit;
519 }
520
521 ts_data = bgp->conf->sensors[id].ts_data;
522 tsr = bgp->conf->sensors[id].registers;
523 if (hot) {
524 if (val < ts_data->min_temp + ts_data->hyst_val)
525 ret = -EINVAL;
526 } else {
527 if (val > ts_data->max_temp + ts_data->hyst_val)
528 ret = -EINVAL;
529 }
530
531 if (ret)
532 goto exit;
533
534 ret = ti_bandgap_mcelsius_to_adc(bgp, val, &adc_val);
535 if (ret < 0)
536 goto exit;
537
538 spin_lock(&bgp->lock);
539 ret = ti_bandgap_update_alert_threshold(bgp, id, adc_val, hot);
540 spin_unlock(&bgp->lock);
541
542exit:
543 return ret;
544}
545
546/**
547 * _ti_bandgap_read_threshold() - helper to read TALERT t_cold or t_hot
548 * @bgp: struct ti_bandgap pointer
549 * @id: bandgap sensor id
550 * @val: value (mCelsius) of a threshold
551 * @hot: desired threshold to be read. true if threshold hot, false if
552 * threshold cold
553 *
554 * It will fetch the required thresholds (hot and cold) for TALERT signal.
555 * This function can be used to read t_hot or t_cold, depending on @hot value.
556 * Call this function only if bandgap features HAS(TALERT).
557 *
558 * Return: 0 if no error, -ENOTSUPP if it has no TALERT support, or the
559 * corresponding error value if some operation fails.
560 */
561static int _ti_bandgap_read_threshold(struct ti_bandgap *bgp, int id,
562 int *val, bool hot)
563{
564 struct temp_sensor_registers *tsr;
565 u32 temp, mask;
566 int ret = 0;
567
568 ret = ti_bandgap_validate(bgp, id);
569 if (ret)
570 goto exit;
571
572 if (!TI_BANDGAP_HAS(bgp, TALERT)) {
573 ret = -ENOTSUPP;
574 goto exit;
575 }
576
577 tsr = bgp->conf->sensors[id].registers;
578 if (hot)
579 mask = tsr->threshold_thot_mask;
580 else
581 mask = tsr->threshold_tcold_mask;
582
583 temp = ti_bandgap_readl(bgp, tsr->bgap_threshold);
584 temp = (temp & mask) >> __ffs(mask);
585 ret |= ti_bandgap_adc_to_mcelsius(bgp, temp, &temp);
586 if (ret) {
587 dev_err(bgp->dev, "failed to read thot\n");
588 ret = -EIO;
589 goto exit;
590 }
591
592 *val = temp;
593
594exit:
595 return ret;
596}
597
598/*** Exposed APIs ***/
599
600/**
601 * ti_bandgap_read_thot() - reads sensor current thot
602 * @bgp: pointer to bandgap instance
603 * @id: sensor id
604 * @thot: resulting current thot value
605 *
606 * Return: 0 on success or the proper error code
607 */
608int ti_bandgap_read_thot(struct ti_bandgap *bgp, int id, int *thot)
609{
610 return _ti_bandgap_read_threshold(bgp, id, thot, true);
611}
612
613/**
614 * ti_bandgap_write_thot() - sets sensor current thot
615 * @bgp: pointer to bandgap instance
616 * @id: sensor id
617 * @val: desired thot value
618 *
619 * Return: 0 on success or the proper error code
620 */
621int ti_bandgap_write_thot(struct ti_bandgap *bgp, int id, int val)
622{
623 return _ti_bandgap_write_threshold(bgp, id, val, true);
624}
625
626/**
627 * ti_bandgap_read_tcold() - reads sensor current tcold
628 * @bgp: pointer to bandgap instance
629 * @id: sensor id
630 * @tcold: resulting current tcold value
631 *
632 * Return: 0 on success or the proper error code
633 */
634int ti_bandgap_read_tcold(struct ti_bandgap *bgp, int id, int *tcold)
635{
636 return _ti_bandgap_read_threshold(bgp, id, tcold, false);
637}
638
639/**
640 * ti_bandgap_write_tcold() - sets the sensor tcold
641 * @bgp: pointer to bandgap instance
642 * @id: sensor id
643 * @val: desired tcold value
644 *
645 * Return: 0 on success or the proper error code
646 */
647int ti_bandgap_write_tcold(struct ti_bandgap *bgp, int id, int val)
648{
649 return _ti_bandgap_write_threshold(bgp, id, val, false);
650}
651
652/**
653 * ti_bandgap_read_counter() - read the sensor counter
654 * @bgp: pointer to bandgap instance
655 * @id: sensor id
656 * @interval: resulting update interval in miliseconds
657 */
658static void ti_bandgap_read_counter(struct ti_bandgap *bgp, int id,
659 int *interval)
660{
661 struct temp_sensor_registers *tsr;
662 int time;
663
664 tsr = bgp->conf->sensors[id].registers;
665 time = ti_bandgap_readl(bgp, tsr->bgap_counter);
666 time = (time & tsr->counter_mask) >>
667 __ffs(tsr->counter_mask);
668 time = time * 1000 / bgp->clk_rate;
669 *interval = time;
670}
671
672/**
673 * ti_bandgap_read_counter_delay() - read the sensor counter delay
674 * @bgp: pointer to bandgap instance
675 * @id: sensor id
676 * @interval: resulting update interval in miliseconds
677 */
678static void ti_bandgap_read_counter_delay(struct ti_bandgap *bgp, int id,
679 int *interval)
680{
681 struct temp_sensor_registers *tsr;
682 int reg_val;
683
684 tsr = bgp->conf->sensors[id].registers;
685
686 reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
687 reg_val = (reg_val & tsr->mask_counter_delay_mask) >>
688 __ffs(tsr->mask_counter_delay_mask);
689 switch (reg_val) {
690 case 0:
691 *interval = 0;
692 break;
693 case 1:
694 *interval = 1;
695 break;
696 case 2:
697 *interval = 10;
698 break;
699 case 3:
700 *interval = 100;
701 break;
702 case 4:
703 *interval = 250;
704 break;
705 case 5:
706 *interval = 500;
707 break;
708 default:
709 dev_warn(bgp->dev, "Wrong counter delay value read from register %X",
710 reg_val);
711 }
712}
713
714/**
715 * ti_bandgap_read_update_interval() - read the sensor update interval
716 * @bgp: pointer to bandgap instance
717 * @id: sensor id
718 * @interval: resulting update interval in miliseconds
719 *
720 * Return: 0 on success or the proper error code
721 */
722int ti_bandgap_read_update_interval(struct ti_bandgap *bgp, int id,
723 int *interval)
724{
725 int ret = 0;
726
727 ret = ti_bandgap_validate(bgp, id);
728 if (ret)
729 goto exit;
730
731 if (!TI_BANDGAP_HAS(bgp, COUNTER) &&
732 !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) {
733 ret = -ENOTSUPP;
734 goto exit;
735 }
736
737 if (TI_BANDGAP_HAS(bgp, COUNTER)) {
738 ti_bandgap_read_counter(bgp, id, interval);
739 goto exit;
740 }
741
742 ti_bandgap_read_counter_delay(bgp, id, interval);
743exit:
744 return ret;
745}
746
747/**
748 * ti_bandgap_write_counter_delay() - set the counter_delay
749 * @bgp: pointer to bandgap instance
750 * @id: sensor id
751 * @interval: desired update interval in miliseconds
752 *
753 * Return: 0 on success or the proper error code
754 */
755static int ti_bandgap_write_counter_delay(struct ti_bandgap *bgp, int id,
756 u32 interval)
757{
758 int rval;
759
760 switch (interval) {
761 case 0: /* Immediate conversion */
762 rval = 0x0;
763 break;
764 case 1: /* Conversion after ever 1ms */
765 rval = 0x1;
766 break;
767 case 10: /* Conversion after ever 10ms */
768 rval = 0x2;
769 break;
770 case 100: /* Conversion after ever 100ms */
771 rval = 0x3;
772 break;
773 case 250: /* Conversion after ever 250ms */
774 rval = 0x4;
775 break;
776 case 500: /* Conversion after ever 500ms */
777 rval = 0x5;
778 break;
779 default:
780 dev_warn(bgp->dev, "Delay %d ms is not supported\n", interval);
781 return -EINVAL;
782 }
783
784 spin_lock(&bgp->lock);
785 RMW_BITS(bgp, id, bgap_mask_ctrl, mask_counter_delay_mask, rval);
786 spin_unlock(&bgp->lock);
787
788 return 0;
789}
790
791/**
792 * ti_bandgap_write_counter() - set the bandgap sensor counter
793 * @bgp: pointer to bandgap instance
794 * @id: sensor id
795 * @interval: desired update interval in miliseconds
796 */
797static void ti_bandgap_write_counter(struct ti_bandgap *bgp, int id,
798 u32 interval)
799{
800 interval = interval * bgp->clk_rate / 1000;
801 spin_lock(&bgp->lock);
802 RMW_BITS(bgp, id, bgap_counter, counter_mask, interval);
803 spin_unlock(&bgp->lock);
804}
805
806/**
807 * ti_bandgap_write_update_interval() - set the update interval
808 * @bgp: pointer to bandgap instance
809 * @id: sensor id
810 * @interval: desired update interval in miliseconds
811 *
812 * Return: 0 on success or the proper error code
813 */
814int ti_bandgap_write_update_interval(struct ti_bandgap *bgp,
815 int id, u32 interval)
816{
817 int ret = ti_bandgap_validate(bgp, id);
818 if (ret)
819 goto exit;
820
821 if (!TI_BANDGAP_HAS(bgp, COUNTER) &&
822 !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) {
823 ret = -ENOTSUPP;
824 goto exit;
825 }
826
827 if (TI_BANDGAP_HAS(bgp, COUNTER)) {
828 ti_bandgap_write_counter(bgp, id, interval);
829 goto exit;
830 }
831
832 ret = ti_bandgap_write_counter_delay(bgp, id, interval);
833exit:
834 return ret;
835}
836
837/**
838 * ti_bandgap_read_temperature() - report current temperature
839 * @bgp: pointer to bandgap instance
840 * @id: sensor id
841 * @temperature: resulting temperature
842 *
843 * Return: 0 on success or the proper error code
844 */
845int ti_bandgap_read_temperature(struct ti_bandgap *bgp, int id,
846 int *temperature)
847{
848 u32 temp;
849 int ret;
850
851 ret = ti_bandgap_validate(bgp, id);
852 if (ret)
853 return ret;
854
855 spin_lock(&bgp->lock);
856 temp = ti_bandgap_read_temp(bgp, id);
857 spin_unlock(&bgp->lock);
858
859 ret |= ti_bandgap_adc_to_mcelsius(bgp, temp, &temp);
860 if (ret)
861 return -EIO;
862
863 *temperature = temp;
864
865 return 0;
866}
867
868/**
869 * ti_bandgap_set_sensor_data() - helper function to store thermal
870 * framework related data.
871 * @bgp: pointer to bandgap instance
872 * @id: sensor id
873 * @data: thermal framework related data to be stored
874 *
875 * Return: 0 on success or the proper error code
876 */
877int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data)
878{
879 int ret = ti_bandgap_validate(bgp, id);
880 if (ret)
881 return ret;
882
883 bgp->regval[id].data = data;
884
885 return 0;
886}
887
888/**
889 * ti_bandgap_get_sensor_data() - helper function to get thermal
890 * framework related data.
891 * @bgp: pointer to bandgap instance
892 * @id: sensor id
893 *
894 * Return: data stored by set function with sensor id on success or NULL
895 */
896void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id)
897{
898 int ret = ti_bandgap_validate(bgp, id);
899 if (ret)
900 return ERR_PTR(ret);
901
902 return bgp->regval[id].data;
903}
904
905/*** Helper functions used during device initialization ***/
906
907/**
908 * ti_bandgap_force_single_read() - executes 1 single ADC conversion
909 * @bgp: pointer to struct ti_bandgap
910 * @id: sensor id which it is desired to read 1 temperature
911 *
912 * Used to initialize the conversion state machine and set it to a valid
913 * state. Called during device initialization and context restore events.
914 *
915 * Return: 0
916 */
917static int
918ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id)
919{
920 u32 temp = 0, counter = 1000;
921
922 /* Select single conversion mode */
923 if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
924 RMW_BITS(bgp, id, bgap_mode_ctrl, mode_ctrl_mask, 0);
925
926 /* Start of Conversion = 1 */
927 RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 1);
928 /* Wait until DTEMP is updated */
929 temp = ti_bandgap_read_temp(bgp, id);
930
931 while ((temp == 0) && --counter)
932 temp = ti_bandgap_read_temp(bgp, id);
933 /* REVISIT: Check correct condition for end of conversion */
934
935 /* Start of Conversion = 0 */
936 RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 0);
937
938 return 0;
939}
940
941/**
942 * ti_bandgap_set_continous_mode() - One time enabling of continuous mode
943 * @bgp: pointer to struct ti_bandgap
944 *
945 * Call this function only if HAS(MODE_CONFIG) is set. As this driver may
946 * be used for junction temperature monitoring, it is desirable that the
947 * sensors are operational all the time, so that alerts are generated
948 * properly.
949 *
950 * Return: 0
951 */
952static int ti_bandgap_set_continuous_mode(struct ti_bandgap *bgp)
953{
954 int i;
955
956 for (i = 0; i < bgp->conf->sensor_count; i++) {
957 /* Perform a single read just before enabling continuous */
958 ti_bandgap_force_single_read(bgp, i);
959 RMW_BITS(bgp, i, bgap_mode_ctrl, mode_ctrl_mask, 1);
960 }
961
962 return 0;
963}
964
965/**
966 * ti_bandgap_get_trend() - To fetch the temperature trend of a sensor
967 * @bgp: pointer to struct ti_bandgap
968 * @id: id of the individual sensor
969 * @trend: Pointer to trend.
970 *
971 * This function needs to be called to fetch the temperature trend of a
972 * Particular sensor. The function computes the difference in temperature
973 * w.r.t time. For the bandgaps with built in history buffer the temperatures
974 * are read from the buffer and for those without the Buffer -ENOTSUPP is
975 * returned.
976 *
977 * Return: 0 if no error, else return corresponding error. If no
978 * error then the trend value is passed on to trend parameter
979 */
980int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend)
981{
982 struct temp_sensor_registers *tsr;
983 u32 temp1, temp2, reg1, reg2;
984 int t1, t2, interval, ret = 0;
985
986 ret = ti_bandgap_validate(bgp, id);
987 if (ret)
988 goto exit;
989
990 if (!TI_BANDGAP_HAS(bgp, HISTORY_BUFFER) ||
991 !TI_BANDGAP_HAS(bgp, FREEZE_BIT)) {
992 ret = -ENOTSUPP;
993 goto exit;
994 }
995
996 spin_lock(&bgp->lock);
997
998 tsr = bgp->conf->sensors[id].registers;
999
1000 /* Freeze and read the last 2 valid readings */
1001 RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1);
1002 reg1 = tsr->ctrl_dtemp_1;
1003 reg2 = tsr->ctrl_dtemp_2;
1004
1005 /* read temperature from history buffer */
1006 temp1 = ti_bandgap_readl(bgp, reg1);
1007 temp1 &= tsr->bgap_dtemp_mask;
1008
1009 temp2 = ti_bandgap_readl(bgp, reg2);
1010 temp2 &= tsr->bgap_dtemp_mask;
1011
1012 /* Convert from adc values to mCelsius temperature */
1013 ret = ti_bandgap_adc_to_mcelsius(bgp, temp1, &t1);
1014 if (ret)
1015 goto unfreeze;
1016
1017 ret = ti_bandgap_adc_to_mcelsius(bgp, temp2, &t2);
1018 if (ret)
1019 goto unfreeze;
1020
1021 /* Fetch the update interval */
1022 ret = ti_bandgap_read_update_interval(bgp, id, &interval);
1023 if (ret || !interval)
1024 goto unfreeze;
1025
1026 *trend = (t1 - t2) / interval;
1027
1028 dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n",
1029 t1, t2, *trend);
1030
1031unfreeze:
1032 RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0);
1033 spin_unlock(&bgp->lock);
1034exit:
1035 return ret;
1036}
1037
1038/**
1039 * ti_bandgap_tshut_init() - setup and initialize tshut handling
1040 * @bgp: pointer to struct ti_bandgap
1041 * @pdev: pointer to device struct platform_device
1042 *
1043 * Call this function only in case the bandgap features HAS(TSHUT).
1044 * In this case, the driver needs to handle the TSHUT signal as an IRQ.
1045 * The IRQ is wired as a GPIO, and for this purpose, it is required
1046 * to specify which GPIO line is used. TSHUT IRQ is fired anytime
1047 * one of the bandgap sensors violates the TSHUT high/hot threshold.
1048 * And in that case, the system must go off.
1049 *
1050 * Return: 0 if no error, else error status
1051 */
1052static int ti_bandgap_tshut_init(struct ti_bandgap *bgp,
1053 struct platform_device *pdev)
1054{
1055 int gpio_nr = bgp->tshut_gpio;
1056 int status;
1057
1058 /* Request for gpio_86 line */
1059 status = gpio_request(gpio_nr, "tshut");
1060 if (status < 0) {
1061 dev_err(bgp->dev, "Could not request for TSHUT GPIO:%i\n", 86);
1062 return status;
1063 }
1064 status = gpio_direction_input(gpio_nr);
1065 if (status) {
1066 dev_err(bgp->dev, "Cannot set input TSHUT GPIO %d\n", gpio_nr);
1067 return status;
1068 }
1069
1070 status = request_irq(gpio_to_irq(gpio_nr), ti_bandgap_tshut_irq_handler,
1071 IRQF_TRIGGER_RISING, "tshut", NULL);
1072 if (status) {
1073 gpio_free(gpio_nr);
1074 dev_err(bgp->dev, "request irq failed for TSHUT");
1075 }
1076
1077 return 0;
1078}
1079
1080/**
1081 * ti_bandgap_alert_init() - setup and initialize talert handling
1082 * @bgp: pointer to struct ti_bandgap
1083 * @pdev: pointer to device struct platform_device
1084 *
1085 * Call this function only in case the bandgap features HAS(TALERT).
1086 * In this case, the driver needs to handle the TALERT signals as an IRQs.
1087 * TALERT is a normal IRQ and it is fired any time thresholds (hot or cold)
1088 * are violated. In these situation, the driver must reprogram the thresholds,
1089 * accordingly to specified policy.
1090 *
1091 * Return: 0 if no error, else return corresponding error.
1092 */
1093static int ti_bandgap_talert_init(struct ti_bandgap *bgp,
1094 struct platform_device *pdev)
1095{
1096 int ret;
1097
1098 bgp->irq = platform_get_irq(pdev, 0);
1099 if (bgp->irq < 0) {
1100 dev_err(&pdev->dev, "get_irq failed\n");
1101 return bgp->irq;
1102 }
1103 ret = request_threaded_irq(bgp->irq, NULL,
1104 ti_bandgap_talert_irq_handler,
1105 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
1106 "talert", bgp);
1107 if (ret) {
1108 dev_err(&pdev->dev, "Request threaded irq failed.\n");
1109 return ret;
1110 }
1111
1112 return 0;
1113}
1114
1115static const struct of_device_id of_ti_bandgap_match[];
1116/**
1117 * ti_bandgap_build() - parse DT and setup a struct ti_bandgap
1118 * @pdev: pointer to device struct platform_device
1119 *
1120 * Used to read the device tree properties accordingly to the bandgap
1121 * matching version. Based on bandgap version and its capabilities it
1122 * will build a struct ti_bandgap out of the required DT entries.
1123 *
1124 * Return: valid bandgap structure if successful, else returns ERR_PTR
1125 * return value must be verified with IS_ERR.
1126 */
1127static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev)
1128{
1129 struct device_node *node = pdev->dev.of_node;
1130 const struct of_device_id *of_id;
1131 struct ti_bandgap *bgp;
1132 struct resource *res;
1133 int i;
1134
1135 /* just for the sake */
1136 if (!node) {
1137 dev_err(&pdev->dev, "no platform information available\n");
1138 return ERR_PTR(-EINVAL);
1139 }
1140
1141 bgp = devm_kzalloc(&pdev->dev, sizeof(*bgp), GFP_KERNEL);
1142 if (!bgp) {
1143 dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
1144 return ERR_PTR(-ENOMEM);
1145 }
1146
1147 of_id = of_match_device(of_ti_bandgap_match, &pdev->dev);
1148 if (of_id)
1149 bgp->conf = of_id->data;
1150
1151 /* register shadow for context save and restore */
1152 bgp->regval = devm_kzalloc(&pdev->dev, sizeof(*bgp->regval) *
1153 bgp->conf->sensor_count, GFP_KERNEL);
1154 if (!bgp) {
1155 dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
1156 return ERR_PTR(-ENOMEM);
1157 }
1158
1159 i = 0;
1160 do {
1161 void __iomem *chunk;
1162
1163 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
1164 if (!res)
1165 break;
1166 chunk = devm_ioremap_resource(&pdev->dev, res);
1167 if (i == 0)
1168 bgp->base = chunk;
1169 if (IS_ERR(chunk))
1170 return ERR_CAST(chunk);
1171
1172 i++;
1173 } while (res);
1174
1175 if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1176 bgp->tshut_gpio = of_get_gpio(node, 0);
1177 if (!gpio_is_valid(bgp->tshut_gpio)) {
1178 dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
1179 bgp->tshut_gpio);
1180 return ERR_PTR(-EINVAL);
1181 }
1182 }
1183
1184 return bgp;
1185}
1186
1187/*** Device driver call backs ***/
1188
1189static
1190int ti_bandgap_probe(struct platform_device *pdev)
1191{
1192 struct ti_bandgap *bgp;
1193 int clk_rate, ret = 0, i;
1194
1195 bgp = ti_bandgap_build(pdev);
1196 if (IS_ERR(bgp)) {
1197 dev_err(&pdev->dev, "failed to fetch platform data\n");
1198 return PTR_ERR(bgp);
1199 }
1200 bgp->dev = &pdev->dev;
1201
1202 if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1203 ret = ti_bandgap_tshut_init(bgp, pdev);
1204 if (ret) {
1205 dev_err(&pdev->dev,
1206 "failed to initialize system tshut IRQ\n");
1207 return ret;
1208 }
1209 }
1210
1211 bgp->fclock = clk_get(NULL, bgp->conf->fclock_name);
1212 ret = IS_ERR(bgp->fclock);
1213 if (ret) {
1214 dev_err(&pdev->dev, "failed to request fclock reference\n");
1215 ret = PTR_ERR(bgp->fclock);
1216 goto free_irqs;
1217 }
1218
1219 bgp->div_clk = clk_get(NULL, bgp->conf->div_ck_name);
1220 ret = IS_ERR(bgp->div_clk);
1221 if (ret) {
1222 dev_err(&pdev->dev,
1223 "failed to request div_ts_ck clock ref\n");
1224 ret = PTR_ERR(bgp->div_clk);
1225 goto free_irqs;
1226 }
1227
1228 for (i = 0; i < bgp->conf->sensor_count; i++) {
1229 struct temp_sensor_registers *tsr;
1230 u32 val;
1231
1232 tsr = bgp->conf->sensors[i].registers;
1233 /*
1234 * check if the efuse has a non-zero value if not
1235 * it is an untrimmed sample and the temperatures
1236 * may not be accurate
1237 */
1238 val = ti_bandgap_readl(bgp, tsr->bgap_efuse);
1239 if (ret || !val)
1240 dev_info(&pdev->dev,
1241 "Non-trimmed BGAP, Temp not accurate\n");
1242 }
1243
1244 clk_rate = clk_round_rate(bgp->div_clk,
1245 bgp->conf->sensors[0].ts_data->max_freq);
1246 if (clk_rate < bgp->conf->sensors[0].ts_data->min_freq ||
1247 clk_rate == 0xffffffff) {
1248 ret = -ENODEV;
1249 dev_err(&pdev->dev, "wrong clock rate (%d)\n", clk_rate);
1250 goto put_clks;
1251 }
1252
1253 ret = clk_set_rate(bgp->div_clk, clk_rate);
1254 if (ret)
1255 dev_err(&pdev->dev, "Cannot re-set clock rate. Continuing\n");
1256
1257 bgp->clk_rate = clk_rate;
1258 if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1259 clk_prepare_enable(bgp->fclock);
1260
1261
1262 spin_lock_init(&bgp->lock);
1263 bgp->dev = &pdev->dev;
1264 platform_set_drvdata(pdev, bgp);
1265
1266 ti_bandgap_power(bgp, true);
1267
1268 /* Set default counter to 1 for now */
1269 if (TI_BANDGAP_HAS(bgp, COUNTER))
1270 for (i = 0; i < bgp->conf->sensor_count; i++)
1271 RMW_BITS(bgp, i, bgap_counter, counter_mask, 1);
1272
1273 /* Set default thresholds for alert and shutdown */
1274 for (i = 0; i < bgp->conf->sensor_count; i++) {
1275 struct temp_sensor_data *ts_data;
1276
1277 ts_data = bgp->conf->sensors[i].ts_data;
1278
1279 if (TI_BANDGAP_HAS(bgp, TALERT)) {
1280 /* Set initial Talert thresholds */
1281 RMW_BITS(bgp, i, bgap_threshold,
1282 threshold_tcold_mask, ts_data->t_cold);
1283 RMW_BITS(bgp, i, bgap_threshold,
1284 threshold_thot_mask, ts_data->t_hot);
1285 /* Enable the alert events */
1286 RMW_BITS(bgp, i, bgap_mask_ctrl, mask_hot_mask, 1);
1287 RMW_BITS(bgp, i, bgap_mask_ctrl, mask_cold_mask, 1);
1288 }
1289
1290 if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG)) {
1291 /* Set initial Tshut thresholds */
1292 RMW_BITS(bgp, i, tshut_threshold,
1293 tshut_hot_mask, ts_data->tshut_hot);
1294 RMW_BITS(bgp, i, tshut_threshold,
1295 tshut_cold_mask, ts_data->tshut_cold);
1296 }
1297 }
1298
1299 if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
1300 ti_bandgap_set_continuous_mode(bgp);
1301
1302 /* Set .250 seconds time as default counter */
1303 if (TI_BANDGAP_HAS(bgp, COUNTER))
1304 for (i = 0; i < bgp->conf->sensor_count; i++)
1305 RMW_BITS(bgp, i, bgap_counter, counter_mask,
1306 bgp->clk_rate / 4);
1307
1308 /* Every thing is good? Then expose the sensors */
1309 for (i = 0; i < bgp->conf->sensor_count; i++) {
1310 char *domain;
1311
1312 if (bgp->conf->sensors[i].register_cooling) {
1313 ret = bgp->conf->sensors[i].register_cooling(bgp, i);
1314 if (ret)
1315 goto remove_sensors;
1316 }
1317
1318 if (bgp->conf->expose_sensor) {
1319 domain = bgp->conf->sensors[i].domain;
1320 ret = bgp->conf->expose_sensor(bgp, i, domain);
1321 if (ret)
1322 goto remove_last_cooling;
1323 }
1324 }
1325
1326 /*
1327 * Enable the Interrupts once everything is set. Otherwise irq handler
1328 * might be called as soon as it is enabled where as rest of framework
1329 * is still getting initialised.
1330 */
1331 if (TI_BANDGAP_HAS(bgp, TALERT)) {
1332 ret = ti_bandgap_talert_init(bgp, pdev);
1333 if (ret) {
1334 dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
1335 i = bgp->conf->sensor_count;
1336 goto disable_clk;
1337 }
1338 }
1339
1340 return 0;
1341
1342remove_last_cooling:
1343 if (bgp->conf->sensors[i].unregister_cooling)
1344 bgp->conf->sensors[i].unregister_cooling(bgp, i);
1345remove_sensors:
1346 for (i--; i >= 0; i--) {
1347 if (bgp->conf->sensors[i].unregister_cooling)
1348 bgp->conf->sensors[i].unregister_cooling(bgp, i);
1349 if (bgp->conf->remove_sensor)
1350 bgp->conf->remove_sensor(bgp, i);
1351 }
1352 ti_bandgap_power(bgp, false);
1353disable_clk:
1354 if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1355 clk_disable_unprepare(bgp->fclock);
1356put_clks:
1357 clk_put(bgp->fclock);
1358 clk_put(bgp->div_clk);
1359free_irqs:
1360 if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1361 free_irq(gpio_to_irq(bgp->tshut_gpio), NULL);
1362 gpio_free(bgp->tshut_gpio);
1363 }
1364
1365 return ret;
1366}
1367
1368static
1369int ti_bandgap_remove(struct platform_device *pdev)
1370{
1371 struct ti_bandgap *bgp = platform_get_drvdata(pdev);
1372 int i;
1373
1374 /* First thing is to remove sensor interfaces */
1375 for (i = 0; i < bgp->conf->sensor_count; i++) {
1376 if (bgp->conf->sensors[i].unregister_cooling)
1377 bgp->conf->sensors[i].unregister_cooling(bgp, i);
1378
1379 if (bgp->conf->remove_sensor)
1380 bgp->conf->remove_sensor(bgp, i);
1381 }
1382
1383 ti_bandgap_power(bgp, false);
1384
1385 if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1386 clk_disable_unprepare(bgp->fclock);
1387 clk_put(bgp->fclock);
1388 clk_put(bgp->div_clk);
1389
1390 if (TI_BANDGAP_HAS(bgp, TALERT))
1391 free_irq(bgp->irq, bgp);
1392
1393 if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1394 free_irq(gpio_to_irq(bgp->tshut_gpio), NULL);
1395 gpio_free(bgp->tshut_gpio);
1396 }
1397
1398 return 0;
1399}
1400
1401#ifdef CONFIG_PM
1402static int ti_bandgap_save_ctxt(struct ti_bandgap *bgp)
1403{
1404 int i;
1405
1406 for (i = 0; i < bgp->conf->sensor_count; i++) {
1407 struct temp_sensor_registers *tsr;
1408 struct temp_sensor_regval *rval;
1409
1410 rval = &bgp->regval[i];
1411 tsr = bgp->conf->sensors[i].registers;
1412
1413 if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
1414 rval->bg_mode_ctrl = ti_bandgap_readl(bgp,
1415 tsr->bgap_mode_ctrl);
1416 if (TI_BANDGAP_HAS(bgp, COUNTER))
1417 rval->bg_counter = ti_bandgap_readl(bgp,
1418 tsr->bgap_counter);
1419 if (TI_BANDGAP_HAS(bgp, TALERT)) {
1420 rval->bg_threshold = ti_bandgap_readl(bgp,
1421 tsr->bgap_threshold);
1422 rval->bg_ctrl = ti_bandgap_readl(bgp,
1423 tsr->bgap_mask_ctrl);
1424 }
1425
1426 if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG))
1427 rval->tshut_threshold = ti_bandgap_readl(bgp,
1428 tsr->tshut_threshold);
1429 }
1430
1431 return 0;
1432}
1433
1434static int ti_bandgap_restore_ctxt(struct ti_bandgap *bgp)
1435{
1436 int i;
1437
1438 for (i = 0; i < bgp->conf->sensor_count; i++) {
1439 struct temp_sensor_registers *tsr;
1440 struct temp_sensor_regval *rval;
1441 u32 val = 0;
1442
1443 rval = &bgp->regval[i];
1444 tsr = bgp->conf->sensors[i].registers;
1445
1446 if (TI_BANDGAP_HAS(bgp, COUNTER))
1447 val = ti_bandgap_readl(bgp, tsr->bgap_counter);
1448
1449 if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG))
1450 ti_bandgap_writel(bgp, rval->tshut_threshold,
1451 tsr->tshut_threshold);
1452 /* Force immediate temperature measurement and update
1453 * of the DTEMP field
1454 */
1455 ti_bandgap_force_single_read(bgp, i);
1456
1457 if (TI_BANDGAP_HAS(bgp, COUNTER))
1458 ti_bandgap_writel(bgp, rval->bg_counter,
1459 tsr->bgap_counter);
1460 if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
1461 ti_bandgap_writel(bgp, rval->bg_mode_ctrl,
1462 tsr->bgap_mode_ctrl);
1463 if (TI_BANDGAP_HAS(bgp, TALERT)) {
1464 ti_bandgap_writel(bgp, rval->bg_threshold,
1465 tsr->bgap_threshold);
1466 ti_bandgap_writel(bgp, rval->bg_ctrl,
1467 tsr->bgap_mask_ctrl);
1468 }
1469 }
1470
1471 return 0;
1472}
1473
1474static int ti_bandgap_suspend(struct device *dev)
1475{
1476 struct ti_bandgap *bgp = dev_get_drvdata(dev);
1477 int err;
1478
1479 err = ti_bandgap_save_ctxt(bgp);
1480 ti_bandgap_power(bgp, false);
1481
1482 if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1483 clk_disable_unprepare(bgp->fclock);
1484
1485 return err;
1486}
1487
1488static int ti_bandgap_resume(struct device *dev)
1489{
1490 struct ti_bandgap *bgp = dev_get_drvdata(dev);
1491
1492 if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1493 clk_prepare_enable(bgp->fclock);
1494
1495 ti_bandgap_power(bgp, true);
1496
1497 return ti_bandgap_restore_ctxt(bgp);
1498}
1499static const struct dev_pm_ops ti_bandgap_dev_pm_ops = {
1500 SET_SYSTEM_SLEEP_PM_OPS(ti_bandgap_suspend,
1501 ti_bandgap_resume)
1502};
1503
1504#define DEV_PM_OPS (&ti_bandgap_dev_pm_ops)
1505#else
1506#define DEV_PM_OPS NULL
1507#endif
1508
1509static const struct of_device_id of_ti_bandgap_match[] = {
1510#ifdef CONFIG_OMAP4_THERMAL
1511 {
1512 .compatible = "ti,omap4430-bandgap",
1513 .data = (void *)&omap4430_data,
1514 },
1515 {
1516 .compatible = "ti,omap4460-bandgap",
1517 .data = (void *)&omap4460_data,
1518 },
1519 {
1520 .compatible = "ti,omap4470-bandgap",
1521 .data = (void *)&omap4470_data,
1522 },
1523#endif
1524#ifdef CONFIG_OMAP5_THERMAL
1525 {
1526 .compatible = "ti,omap5430-bandgap",
1527 .data = (void *)&omap5430_data,
1528 },
1529#endif
1530#ifdef CONFIG_DRA752_THERMAL
1531 {
1532 .compatible = "ti,dra752-bandgap",
1533 .data = (void *)&dra752_data,
1534 },
1535#endif
1536 /* Sentinel */
1537 { },
1538};
1539MODULE_DEVICE_TABLE(of, of_ti_bandgap_match);
1540
1541static struct platform_driver ti_bandgap_sensor_driver = {
1542 .probe = ti_bandgap_probe,
1543 .remove = ti_bandgap_remove,
1544 .driver = {
1545 .name = "ti-soc-thermal",
1546 .pm = DEV_PM_OPS,
1547 .of_match_table = of_ti_bandgap_match,
1548 },
1549};
1550
1551module_platform_driver(ti_bandgap_sensor_driver);
1552
1553MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
1554MODULE_LICENSE("GPL v2");
1555MODULE_ALIAS("platform:ti-soc-thermal");
1556MODULE_AUTHOR("Texas Instrument Inc.");
diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.h b/drivers/thermal/ti-soc-thermal/ti-bandgap.h
new file mode 100644
index 000000000000..b3adf72f252d
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.h
@@ -0,0 +1,408 @@
1/*
2 * OMAP4 Bandgap temperature sensor driver
3 *
4 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
5 * Contact:
6 * Eduardo Valentin <eduardo.valentin@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23#ifndef __TI_BANDGAP_H
24#define __TI_BANDGAP_H
25
26#include <linux/spinlock.h>
27#include <linux/types.h>
28#include <linux/err.h>
29
30/**
31 * DOC: bandgap driver data structure
32 * ==================================
33 *
34 * +----------+----------------+
35 * | struct temp_sensor_regval |
36 * +---------------------------+
37 * * (Array of)
38 * |
39 * |
40 * +-------------------+ +-----------------+
41 * | struct ti_bandgap |-->| struct device * |
42 * +----------+--------+ +-----------------+
43 * |
44 * |
45 * V
46 * +------------------------+
47 * | struct ti_bandgap_data |
48 * +------------------------+
49 * |
50 * |
51 * * (Array of)
52 * +------------+------------------------------------------------------+
53 * | +----------+------------+ +-------------------------+ |
54 * | | struct ti_temp_sensor |-->| struct temp_sensor_data | |
55 * | +-----------------------+ +------------+------------+ |
56 * | | |
57 * | + |
58 * | V |
59 * | +----------+-------------------+ |
60 * | | struct temp_sensor_registers | |
61 * | +------------------------------+ |
62 * | |
63 * +-------------------------------------------------------------------+
64 *
65 * Above is a simple diagram describing how the data structure below
66 * are organized. For each bandgap device there should be a ti_bandgap_data
67 * containing the device instance configuration, as well as, an array of
68 * sensors, representing every sensor instance present in this bandgap.
69 */
70
71/**
72 * struct temp_sensor_registers - descriptor to access registers and bitfields
73 * @temp_sensor_ctrl: TEMP_SENSOR_CTRL register offset
74 * @bgap_tempsoff_mask: mask to temp_sensor_ctrl.tempsoff
75 * @bgap_soc_mask: mask to temp_sensor_ctrl.soc
76 * @bgap_eocz_mask: mask to temp_sensor_ctrl.eocz
77 * @bgap_dtemp_mask: mask to temp_sensor_ctrl.dtemp
78 * @bgap_mask_ctrl: BANDGAP_MASK_CTRL register offset
79 * @mask_hot_mask: mask to bandgap_mask_ctrl.mask_hot
80 * @mask_cold_mask: mask to bandgap_mask_ctrl.mask_cold
81 * @mask_sidlemode_mask: mask to bandgap_mask_ctrl.mask_sidlemode
82 * @mask_counter_delay_mask: mask to bandgap_mask_ctrl.mask_counter_delay
83 * @mask_freeze_mask: mask to bandgap_mask_ctrl.mask_free
84 * @mask_clear_mask: mask to bandgap_mask_ctrl.mask_clear
85 * @mask_clear_accum_mask: mask to bandgap_mask_ctrl.mask_clear_accum
86 * @bgap_mode_ctrl: BANDGAP_MODE_CTRL register offset
87 * @mode_ctrl_mask: mask to bandgap_mode_ctrl.mode_ctrl
88 * @bgap_counter: BANDGAP_COUNTER register offset
89 * @counter_mask: mask to bandgap_counter.counter
90 * @bgap_threshold: BANDGAP_THRESHOLD register offset (TALERT thresholds)
91 * @threshold_thot_mask: mask to bandgap_threhold.thot
92 * @threshold_tcold_mask: mask to bandgap_threhold.tcold
93 * @tshut_threshold: TSHUT_THRESHOLD register offset (TSHUT thresholds)
94 * @tshut_efuse_mask: mask to tshut_threshold.tshut_efuse
95 * @tshut_efuse_shift: shift to tshut_threshold.tshut_efuse
96 * @tshut_hot_mask: mask to tshut_threhold.thot
97 * @tshut_cold_mask: mask to tshut_threhold.thot
98 * @bgap_status: BANDGAP_STATUS register offset
99 * @status_clean_stop_mask: mask to bandgap_status.clean_stop
100 * @status_bgap_alert_mask: mask to bandgap_status.bandgap_alert
101 * @status_hot_mask: mask to bandgap_status.hot
102 * @status_cold_mask: mask to bandgap_status.cold
103 * @bgap_cumul_dtemp: BANDGAP_CUMUL_DTEMP register offset
104 * @ctrl_dtemp_0: CTRL_DTEMP0 register offset
105 * @ctrl_dtemp_1: CTRL_DTEMP1 register offset
106 * @ctrl_dtemp_2: CTRL_DTEMP2 register offset
107 * @ctrl_dtemp_3: CTRL_DTEMP3 register offset
108 * @ctrl_dtemp_4: CTRL_DTEMP4 register offset
109 * @bgap_efuse: BANDGAP_EFUSE register offset
110 *
111 * The register offsets and bitfields might change across
112 * OMAP and variants versions. Hence this struct serves as a
113 * descriptor map on how to access the registers and the bitfields.
114 *
115 * This descriptor contains registers of all versions of bandgap chips.
116 * Not all versions will use all registers, depending on the available
117 * features. Please read TRMs for descriptive explanation on each bitfield.
118 */
119
120struct temp_sensor_registers {
121 u32 temp_sensor_ctrl;
122 u32 bgap_tempsoff_mask;
123 u32 bgap_soc_mask;
124 u32 bgap_eocz_mask; /* not used: but needs revisit */
125 u32 bgap_dtemp_mask;
126
127 u32 bgap_mask_ctrl;
128 u32 mask_hot_mask;
129 u32 mask_cold_mask;
130 u32 mask_sidlemode_mask; /* not used: but may be needed for pm */
131 u32 mask_counter_delay_mask;
132 u32 mask_freeze_mask;
133 u32 mask_clear_mask; /* not used: but needed for trending */
134 u32 mask_clear_accum_mask; /* not used: but needed for trending */
135
136 u32 bgap_mode_ctrl;
137 u32 mode_ctrl_mask;
138
139 u32 bgap_counter;
140 u32 counter_mask;
141
142 u32 bgap_threshold;
143 u32 threshold_thot_mask;
144 u32 threshold_tcold_mask;
145
146 u32 tshut_threshold;
147 u32 tshut_efuse_mask; /* not used */
148 u32 tshut_efuse_shift; /* not used */
149 u32 tshut_hot_mask;
150 u32 tshut_cold_mask;
151
152 u32 bgap_status;
153 u32 status_clean_stop_mask; /* not used: but needed for trending */
154 u32 status_bgap_alert_mask; /* not used */
155 u32 status_hot_mask;
156 u32 status_cold_mask;
157
158 u32 bgap_cumul_dtemp; /* not used: but needed for trending */
159 u32 ctrl_dtemp_0; /* not used: but needed for trending */
160 u32 ctrl_dtemp_1; /* not used: but needed for trending */
161 u32 ctrl_dtemp_2; /* not used: but needed for trending */
162 u32 ctrl_dtemp_3; /* not used: but needed for trending */
163 u32 ctrl_dtemp_4; /* not used: but needed for trending */
164 u32 bgap_efuse;
165};
166
167/**
168 * struct temp_sensor_data - The thresholds and limits for temperature sensors.
169 * @tshut_hot: temperature to trigger a thermal reset (initial value)
170 * @tshut_cold: temp to get the plat out of reset due to thermal (init val)
171 * @t_hot: temperature to trigger a thermal alert (high initial value)
172 * @t_cold: temperature to trigger a thermal alert (low initial value)
173 * @min_freq: sensor minimum clock rate
174 * @max_freq: sensor maximum clock rate
175 * @max_temp: sensor maximum temperature
176 * @min_temp: sensor minimum temperature
177 * @hyst_val: temperature hysteresis considered while converting ADC values
178 * @update_int1: update interval
179 * @update_int2: update interval
180 *
181 * This data structure will hold the required thresholds and temperature limits
182 * for a specific temperature sensor, like shutdown temperature, alert
183 * temperature, clock / rate used, ADC conversion limits and update intervals
184 */
185struct temp_sensor_data {
186 u32 tshut_hot;
187 u32 tshut_cold;
188 u32 t_hot;
189 u32 t_cold;
190 u32 min_freq;
191 u32 max_freq;
192 int max_temp;
193 int min_temp;
194 int hyst_val;
195 u32 update_int1; /* not used */
196 u32 update_int2; /* not used */
197};
198
199struct ti_bandgap_data;
200
201/**
202 * struct temp_sensor_regval - temperature sensor register values and priv data
203 * @bg_mode_ctrl: temp sensor control register value
204 * @bg_ctrl: bandgap ctrl register value
205 * @bg_counter: bandgap counter value
206 * @bg_threshold: bandgap threshold register value
207 * @tshut_threshold: bandgap tshut register value
208 * @data: private data
209 *
210 * Data structure to save and restore bandgap register set context. Only
211 * required registers are shadowed, when needed.
212 */
213struct temp_sensor_regval {
214 u32 bg_mode_ctrl;
215 u32 bg_ctrl;
216 u32 bg_counter;
217 u32 bg_threshold;
218 u32 tshut_threshold;
219 void *data;
220};
221
222/**
223 * struct ti_bandgap - bandgap device structure
224 * @dev: struct device pointer
225 * @base: io memory base address
226 * @conf: struct with bandgap configuration set (# sensors, conv_table, etc)
227 * @regval: temperature sensor register values
228 * @fclock: pointer to functional clock of temperature sensor
229 * @div_clk: pointer to divider clock of temperature sensor fclk
230 * @lock: spinlock for ti_bandgap structure
231 * @irq: MPU IRQ number for thermal alert
232 * @tshut_gpio: GPIO where Tshut signal is routed
233 * @clk_rate: Holds current clock rate
234 *
235 * The bandgap device structure representing the bandgap device instance.
236 * It holds most of the dynamic stuff. Configurations and sensor specific
237 * entries are inside the @conf structure.
238 */
239struct ti_bandgap {
240 struct device *dev;
241 void __iomem *base;
242 const struct ti_bandgap_data *conf;
243 struct temp_sensor_regval *regval;
244 struct clk *fclock;
245 struct clk *div_clk;
246 spinlock_t lock; /* shields this struct */
247 int irq;
248 int tshut_gpio;
249 u32 clk_rate;
250};
251
252/**
253 * struct ti_temp_sensor - bandgap temperature sensor configuration data
254 * @ts_data: pointer to struct with thresholds, limits of temperature sensor
255 * @registers: pointer to the list of register offsets and bitfields
256 * @domain: the name of the domain where the sensor is located
257 * @slope: sensor gradient slope info for hotspot extrapolation equation
258 * @constant: sensor gradient const info for hotspot extrapolation equation
259 * @slope_pcb: sensor gradient slope info for hotspot extrapolation equation
260 * with no external influence
261 * @constant_pcb: sensor gradient const info for hotspot extrapolation equation
262 * with no external influence
263 * @register_cooling: function to describe how this sensor is going to be cooled
264 * @unregister_cooling: function to release cooling data
265 *
266 * Data structure to describe a temperature sensor handled by a bandgap device.
267 * It should provide configuration details on this sensor, such as how to
268 * access the registers affecting this sensor, shadow register buffer, how to
269 * assess the gradient from hotspot, how to cooldown the domain when sensor
270 * reports too hot temperature.
271 */
272struct ti_temp_sensor {
273 struct temp_sensor_data *ts_data;
274 struct temp_sensor_registers *registers;
275 char *domain;
276 /* for hotspot extrapolation */
277 const int slope;
278 const int constant;
279 const int slope_pcb;
280 const int constant_pcb;
281 int (*register_cooling)(struct ti_bandgap *bgp, int id);
282 int (*unregister_cooling)(struct ti_bandgap *bgp, int id);
283};
284
285/**
286 * DOC: ti bandgap feature types
287 *
288 * TI_BANDGAP_FEATURE_TSHUT - used when the thermal shutdown signal output
289 * of a bandgap device instance is routed to the processor. This means
290 * the system must react and perform the shutdown by itself (handle an
291 * IRQ, for instance).
292 *
293 * TI_BANDGAP_FEATURE_TSHUT_CONFIG - used when the bandgap device has control
294 * over the thermal shutdown configuration. This means that the thermal
295 * shutdown thresholds are programmable, for instance.
296 *
297 * TI_BANDGAP_FEATURE_TALERT - used when the bandgap device instance outputs
298 * a signal representing violation of programmable alert thresholds.
299 *
300 * TI_BANDGAP_FEATURE_MODE_CONFIG - used when it is possible to choose which
301 * mode, continuous or one shot, the bandgap device instance will operate.
302 *
303 * TI_BANDGAP_FEATURE_COUNTER - used when the bandgap device instance allows
304 * programming the update interval of its internal state machine.
305 *
306 * TI_BANDGAP_FEATURE_POWER_SWITCH - used when the bandgap device allows
307 * itself to be switched on/off.
308 *
309 * TI_BANDGAP_FEATURE_CLK_CTRL - used when the clocks feeding the bandgap
310 * device are gateable or not.
311 *
312 * TI_BANDGAP_FEATURE_FREEZE_BIT - used when the bandgap device features
313 * a history buffer that its update can be freezed/unfreezed.
314 *
315 * TI_BANDGAP_FEATURE_COUNTER_DELAY - used when the bandgap device features
316 * a delay programming based on distinct values.
317 *
318 * TI_BANDGAP_FEATURE_HISTORY_BUFFER - used when the bandgap device features
319 * a history buffer of temperatures.
320 *
321 * TI_BANDGAP_HAS(b, f) - macro to check if a bandgap device is capable of a
322 * specific feature (above) or not. Return non-zero, if yes.
323 */
324#define TI_BANDGAP_FEATURE_TSHUT BIT(0)
325#define TI_BANDGAP_FEATURE_TSHUT_CONFIG BIT(1)
326#define TI_BANDGAP_FEATURE_TALERT BIT(2)
327#define TI_BANDGAP_FEATURE_MODE_CONFIG BIT(3)
328#define TI_BANDGAP_FEATURE_COUNTER BIT(4)
329#define TI_BANDGAP_FEATURE_POWER_SWITCH BIT(5)
330#define TI_BANDGAP_FEATURE_CLK_CTRL BIT(6)
331#define TI_BANDGAP_FEATURE_FREEZE_BIT BIT(7)
332#define TI_BANDGAP_FEATURE_COUNTER_DELAY BIT(8)
333#define TI_BANDGAP_FEATURE_HISTORY_BUFFER BIT(9)
334#define TI_BANDGAP_HAS(b, f) \
335 ((b)->conf->features & TI_BANDGAP_FEATURE_ ## f)
336
337/**
338 * struct ti_bandgap_data - ti bandgap data configuration structure
339 * @features: a bitwise flag set to describe the device features
340 * @conv_table: Pointer to ADC to temperature conversion table
341 * @adc_start_val: ADC conversion table starting value
342 * @adc_end_val: ADC conversion table ending value
343 * @fclock_name: clock name of the functional clock
344 * @div_ck_name: clock name of the clock divisor
345 * @sensor_count: count of temperature sensor within this bandgap device
346 * @report_temperature: callback to report thermal alert to thermal API
347 * @expose_sensor: callback to export sensor to thermal API
348 * @remove_sensor: callback to destroy sensor from thermal API
349 * @sensors: array of sensors present in this bandgap instance
350 *
351 * This is a data structure which should hold most of the static configuration
352 * of a bandgap device instance. It should describe which features this instance
353 * is capable of, the clock names to feed this device, the amount of sensors and
354 * their configuration representation, and how to export and unexport them to
355 * a thermal API.
356 */
357struct ti_bandgap_data {
358 unsigned int features;
359 const int *conv_table;
360 u32 adc_start_val;
361 u32 adc_end_val;
362 char *fclock_name;
363 char *div_ck_name;
364 int sensor_count;
365 int (*report_temperature)(struct ti_bandgap *bgp, int id);
366 int (*expose_sensor)(struct ti_bandgap *bgp, int id, char *domain);
367 int (*remove_sensor)(struct ti_bandgap *bgp, int id);
368
369 /* this needs to be at the end */
370 struct ti_temp_sensor sensors[];
371};
372
373int ti_bandgap_read_thot(struct ti_bandgap *bgp, int id, int *thot);
374int ti_bandgap_write_thot(struct ti_bandgap *bgp, int id, int val);
375int ti_bandgap_read_tcold(struct ti_bandgap *bgp, int id, int *tcold);
376int ti_bandgap_write_tcold(struct ti_bandgap *bgp, int id, int val);
377int ti_bandgap_read_update_interval(struct ti_bandgap *bgp, int id,
378 int *interval);
379int ti_bandgap_write_update_interval(struct ti_bandgap *bgp, int id,
380 u32 interval);
381int ti_bandgap_read_temperature(struct ti_bandgap *bgp, int id,
382 int *temperature);
383int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data);
384void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id);
385int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend);
386
387#ifdef CONFIG_OMAP4_THERMAL
388extern const struct ti_bandgap_data omap4430_data;
389extern const struct ti_bandgap_data omap4460_data;
390extern const struct ti_bandgap_data omap4470_data;
391#else
392#define omap4430_data NULL
393#define omap4460_data NULL
394#define omap4470_data NULL
395#endif
396
397#ifdef CONFIG_OMAP5_THERMAL
398extern const struct ti_bandgap_data omap5430_data;
399#else
400#define omap5430_data NULL
401#endif
402
403#ifdef CONFIG_DRA752_THERMAL
404extern const struct ti_bandgap_data dra752_data;
405#else
406#define dra752_data NULL
407#endif
408#endif
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
new file mode 100644
index 000000000000..4c5f55c37349
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -0,0 +1,378 @@
1/*
2 * OMAP thermal driver interface
3 *
4 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
5 * Contact:
6 * Eduardo Valentin <eduardo.valentin@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/device.h>
25#include <linux/err.h>
26#include <linux/mutex.h>
27#include <linux/gfp.h>
28#include <linux/kernel.h>
29#include <linux/workqueue.h>
30#include <linux/thermal.h>
31#include <linux/cpufreq.h>
32#include <linux/cpumask.h>
33#include <linux/cpu_cooling.h>
34
35#include "ti-thermal.h"
36#include "ti-bandgap.h"
37
38/* common data structures */
39struct ti_thermal_data {
40 struct thermal_zone_device *ti_thermal;
41 struct thermal_zone_device *pcb_tz;
42 struct thermal_cooling_device *cool_dev;
43 struct ti_bandgap *bgp;
44 enum thermal_device_mode mode;
45 struct work_struct thermal_wq;
46 int sensor_id;
47};
48
49static void ti_thermal_work(struct work_struct *work)
50{
51 struct ti_thermal_data *data = container_of(work,
52 struct ti_thermal_data, thermal_wq);
53
54 thermal_zone_device_update(data->ti_thermal);
55
56 dev_dbg(&data->ti_thermal->device, "updated thermal zone %s\n",
57 data->ti_thermal->type);
58}
59
60/**
61 * ti_thermal_hotspot_temperature - returns sensor extrapolated temperature
62 * @t: omap sensor temperature
63 * @s: omap sensor slope value
64 * @c: omap sensor const value
65 */
66static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
67{
68 int delta = t * s / 1000 + c;
69
70 if (delta < 0)
71 delta = 0;
72
73 return t + delta;
74}
75
76/* thermal zone ops */
77/* Get temperature callback function for thermal zone*/
78static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
79 unsigned long *temp)
80{
81 struct thermal_zone_device *pcb_tz = NULL;
82 struct ti_thermal_data *data = thermal->devdata;
83 struct ti_bandgap *bgp;
84 const struct ti_temp_sensor *s;
85 int ret, tmp, slope, constant;
86 unsigned long pcb_temp;
87
88 if (!data)
89 return 0;
90
91 bgp = data->bgp;
92 s = &bgp->conf->sensors[data->sensor_id];
93
94 ret = ti_bandgap_read_temperature(bgp, data->sensor_id, &tmp);
95 if (ret)
96 return ret;
97
98 /* Default constants */
99 slope = s->slope;
100 constant = s->constant;
101
102 pcb_tz = data->pcb_tz;
103 /* In case pcb zone is available, use the extrapolation rule with it */
104 if (!IS_ERR(pcb_tz)) {
105 ret = thermal_zone_get_temp(pcb_tz, &pcb_temp);
106 if (!ret) {
107 tmp -= pcb_temp; /* got a valid PCB temp */
108 slope = s->slope_pcb;
109 constant = s->constant_pcb;
110 } else {
111 dev_err(bgp->dev,
112 "Failed to read PCB state. Using defaults\n");
113 }
114 }
115 *temp = ti_thermal_hotspot_temperature(tmp, slope, constant);
116
117 return ret;
118}
119
120/* Bind callback functions for thermal zone */
121static int ti_thermal_bind(struct thermal_zone_device *thermal,
122 struct thermal_cooling_device *cdev)
123{
124 struct ti_thermal_data *data = thermal->devdata;
125 int id;
126
127 if (!data || IS_ERR(data))
128 return -ENODEV;
129
130 /* check if this is the cooling device we registered */
131 if (data->cool_dev != cdev)
132 return 0;
133
134 id = data->sensor_id;
135
136 /* Simple thing, two trips, one passive another critical */
137 return thermal_zone_bind_cooling_device(thermal, 0, cdev,
138 /* bind with min and max states defined by cpu_cooling */
139 THERMAL_NO_LIMIT,
140 THERMAL_NO_LIMIT);
141}
142
143/* Unbind callback functions for thermal zone */
144static int ti_thermal_unbind(struct thermal_zone_device *thermal,
145 struct thermal_cooling_device *cdev)
146{
147 struct ti_thermal_data *data = thermal->devdata;
148
149 if (!data || IS_ERR(data))
150 return -ENODEV;
151
152 /* check if this is the cooling device we registered */
153 if (data->cool_dev != cdev)
154 return 0;
155
156 /* Simple thing, two trips, one passive another critical */
157 return thermal_zone_unbind_cooling_device(thermal, 0, cdev);
158}
159
160/* Get mode callback functions for thermal zone */
161static int ti_thermal_get_mode(struct thermal_zone_device *thermal,
162 enum thermal_device_mode *mode)
163{
164 struct ti_thermal_data *data = thermal->devdata;
165
166 if (data)
167 *mode = data->mode;
168
169 return 0;
170}
171
172/* Set mode callback functions for thermal zone */
173static int ti_thermal_set_mode(struct thermal_zone_device *thermal,
174 enum thermal_device_mode mode)
175{
176 struct ti_thermal_data *data = thermal->devdata;
177
178 if (!data->ti_thermal) {
179 dev_notice(&thermal->device, "thermal zone not registered\n");
180 return 0;
181 }
182
183 mutex_lock(&data->ti_thermal->lock);
184
185 if (mode == THERMAL_DEVICE_ENABLED)
186 data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
187 else
188 data->ti_thermal->polling_delay = 0;
189
190 mutex_unlock(&data->ti_thermal->lock);
191
192 data->mode = mode;
193 thermal_zone_device_update(data->ti_thermal);
194 dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n",
195 data->ti_thermal->polling_delay);
196
197 return 0;
198}
199
200/* Get trip type callback functions for thermal zone */
201static int ti_thermal_get_trip_type(struct thermal_zone_device *thermal,
202 int trip, enum thermal_trip_type *type)
203{
204 if (!ti_thermal_is_valid_trip(trip))
205 return -EINVAL;
206
207 if (trip + 1 == OMAP_TRIP_NUMBER)
208 *type = THERMAL_TRIP_CRITICAL;
209 else
210 *type = THERMAL_TRIP_PASSIVE;
211
212 return 0;
213}
214
215/* Get trip temperature callback functions for thermal zone */
216static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
217 int trip, unsigned long *temp)
218{
219 if (!ti_thermal_is_valid_trip(trip))
220 return -EINVAL;
221
222 *temp = ti_thermal_get_trip_value(trip);
223
224 return 0;
225}
226
227/* Get the temperature trend callback functions for thermal zone */
228static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
229 int trip, enum thermal_trend *trend)
230{
231 struct ti_thermal_data *data = thermal->devdata;
232 struct ti_bandgap *bgp;
233 int id, tr, ret = 0;
234
235 bgp = data->bgp;
236 id = data->sensor_id;
237
238 ret = ti_bandgap_get_trend(bgp, id, &tr);
239 if (ret)
240 return ret;
241
242 if (tr > 0)
243 *trend = THERMAL_TREND_RAISING;
244 else if (tr < 0)
245 *trend = THERMAL_TREND_DROPPING;
246 else
247 *trend = THERMAL_TREND_STABLE;
248
249 return 0;
250}
251
252/* Get critical temperature callback functions for thermal zone */
253static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
254 unsigned long *temp)
255{
256 /* shutdown zone */
257 return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
258}
259
260static struct thermal_zone_device_ops ti_thermal_ops = {
261 .get_temp = ti_thermal_get_temp,
262 .get_trend = ti_thermal_get_trend,
263 .bind = ti_thermal_bind,
264 .unbind = ti_thermal_unbind,
265 .get_mode = ti_thermal_get_mode,
266 .set_mode = ti_thermal_set_mode,
267 .get_trip_type = ti_thermal_get_trip_type,
268 .get_trip_temp = ti_thermal_get_trip_temp,
269 .get_crit_temp = ti_thermal_get_crit_temp,
270};
271
272static struct ti_thermal_data
273*ti_thermal_build_data(struct ti_bandgap *bgp, int id)
274{
275 struct ti_thermal_data *data;
276
277 data = devm_kzalloc(bgp->dev, sizeof(*data), GFP_KERNEL);
278 if (!data) {
279 dev_err(bgp->dev, "kzalloc fail\n");
280 return NULL;
281 }
282 data->sensor_id = id;
283 data->bgp = bgp;
284 data->mode = THERMAL_DEVICE_ENABLED;
285 /* pcb_tz will be either valid or PTR_ERR() */
286 data->pcb_tz = thermal_zone_get_zone_by_name("pcb");
287 INIT_WORK(&data->thermal_wq, ti_thermal_work);
288
289 return data;
290}
291
292int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
293 char *domain)
294{
295 struct ti_thermal_data *data;
296
297 data = ti_bandgap_get_sensor_data(bgp, id);
298
299 if (!data || IS_ERR(data))
300 data = ti_thermal_build_data(bgp, id);
301
302 if (!data)
303 return -EINVAL;
304
305 /* Create thermal zone */
306 data->ti_thermal = thermal_zone_device_register(domain,
307 OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
308 NULL, FAST_TEMP_MONITORING_RATE,
309 FAST_TEMP_MONITORING_RATE);
310 if (IS_ERR(data->ti_thermal)) {
311 dev_err(bgp->dev, "thermal zone device is NULL\n");
312 return PTR_ERR(data->ti_thermal);
313 }
314 data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
315 ti_bandgap_set_sensor_data(bgp, id, data);
316
317 return 0;
318}
319
320int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
321{
322 struct ti_thermal_data *data;
323
324 data = ti_bandgap_get_sensor_data(bgp, id);
325
326 thermal_zone_device_unregister(data->ti_thermal);
327
328 return 0;
329}
330
331int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id)
332{
333 struct ti_thermal_data *data;
334
335 data = ti_bandgap_get_sensor_data(bgp, id);
336
337 schedule_work(&data->thermal_wq);
338
339 return 0;
340}
341
342int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
343{
344 struct ti_thermal_data *data;
345
346 data = ti_bandgap_get_sensor_data(bgp, id);
347 if (!data || IS_ERR(data))
348 data = ti_thermal_build_data(bgp, id);
349
350 if (!data)
351 return -EINVAL;
352
353 if (!cpufreq_get_current_driver()) {
354 dev_dbg(bgp->dev, "no cpufreq driver yet\n");
355 return -EPROBE_DEFER;
356 }
357
358 /* Register cooling device */
359 data->cool_dev = cpufreq_cooling_register(cpu_present_mask);
360 if (IS_ERR(data->cool_dev)) {
361 dev_err(bgp->dev,
362 "Failed to register cpufreq cooling device\n");
363 return PTR_ERR(data->cool_dev);
364 }
365 ti_bandgap_set_sensor_data(bgp, id, data);
366
367 return 0;
368}
369
370int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
371{
372 struct ti_thermal_data *data;
373
374 data = ti_bandgap_get_sensor_data(bgp, id);
375 cpufreq_cooling_unregister(data->cool_dev);
376
377 return 0;
378}
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal.h b/drivers/thermal/ti-soc-thermal/ti-thermal.h
new file mode 100644
index 000000000000..f8b7ffea6194
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal.h
@@ -0,0 +1,123 @@
1/*
2 * OMAP thermal definitions
3 *
4 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
5 * Contact:
6 * Eduardo Valentin <eduardo.valentin@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23#ifndef __TI_THERMAL_H
24#define __TI_THERMAL_H
25
26#include "ti-bandgap.h"
27
28/* sensors gradient and offsets */
29#define OMAP_GRADIENT_SLOPE_4430 0
30#define OMAP_GRADIENT_CONST_4430 20000
31#define OMAP_GRADIENT_SLOPE_4460 348
32#define OMAP_GRADIENT_CONST_4460 -9301
33#define OMAP_GRADIENT_SLOPE_4470 308
34#define OMAP_GRADIENT_CONST_4470 -7896
35
36#define OMAP_GRADIENT_SLOPE_5430_CPU 65
37#define OMAP_GRADIENT_CONST_5430_CPU -1791
38#define OMAP_GRADIENT_SLOPE_5430_GPU 117
39#define OMAP_GRADIENT_CONST_5430_GPU -2992
40
41#define DRA752_GRADIENT_SLOPE 0
42#define DRA752_GRADIENT_CONST 2000
43
44/* PCB sensor calculation constants */
45#define OMAP_GRADIENT_SLOPE_W_PCB_4430 0
46#define OMAP_GRADIENT_CONST_W_PCB_4430 20000
47#define OMAP_GRADIENT_SLOPE_W_PCB_4460 1142
48#define OMAP_GRADIENT_CONST_W_PCB_4460 -393
49#define OMAP_GRADIENT_SLOPE_W_PCB_4470 1063
50#define OMAP_GRADIENT_CONST_W_PCB_4470 -477
51
52#define OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU 100
53#define OMAP_GRADIENT_CONST_W_PCB_5430_CPU 484
54#define OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU 464
55#define OMAP_GRADIENT_CONST_W_PCB_5430_GPU -5102
56
57#define DRA752_GRADIENT_SLOPE_W_PCB 0
58#define DRA752_GRADIENT_CONST_W_PCB 2000
59
60/* trip points of interest in milicelsius (at hotspot level) */
61#define OMAP_TRIP_COLD 100000
62#define OMAP_TRIP_HOT 110000
63#define OMAP_TRIP_SHUTDOWN 125000
64#define OMAP_TRIP_NUMBER 2
65#define OMAP_TRIP_STEP \
66 ((OMAP_TRIP_SHUTDOWN - OMAP_TRIP_HOT) / (OMAP_TRIP_NUMBER - 1))
67
68/* Update rates */
69#define FAST_TEMP_MONITORING_RATE 250
70
71/* helper macros */
72/**
73 * ti_thermal_get_trip_value - returns trip temperature based on index
74 * @i: trip index
75 */
76#define ti_thermal_get_trip_value(i) \
77 (OMAP_TRIP_HOT + ((i) * OMAP_TRIP_STEP))
78
79/**
80 * ti_thermal_is_valid_trip - check for trip index
81 * @i: trip index
82 */
83#define ti_thermal_is_valid_trip(trip) \
84 ((trip) >= 0 && (trip) < OMAP_TRIP_NUMBER)
85
86#ifdef CONFIG_TI_THERMAL
87int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, char *domain);
88int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id);
89int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id);
90int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id);
91int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id);
92#else
93static inline
94int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, char *domain)
95{
96 return 0;
97}
98
99static inline
100int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
101{
102 return 0;
103}
104
105static inline
106int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id)
107{
108 return 0;
109}
110
111static inline
112int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
113{
114 return 0;
115}
116
117static inline
118int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
119{
120 return 0;
121}
122#endif
123#endif
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");