aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal/ti-soc-thermal
diff options
context:
space:
mode:
authorEduardo Valentin <eduardo.valentin@ti.com>2013-05-15 11:46:00 -0400
committerZhang Rui <rui.zhang@intel.com>2013-05-27 22:40:37 -0400
commiteb982001dbd8546f273f444868a1031cc78b4250 (patch)
tree08547bb02ed69dec61a69511b66e1ee6ac8e49d1 /drivers/thermal/ti-soc-thermal
parentc240a539df4e2d50f86e2f31813ff6b7334cd493 (diff)
thermal: introduce TI SoC thermal driver
This patch moves the ti-soc-thermal driver out of the staging tree to the thermal tree. Cc: Grant Likely <grant.likely@linaro.org> Cc: Rob Herring <rob.herring@calxeda.com> Cc: Rob Landley <rob@landley.net> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Zhang Rui <rui.zhang@intel.com> Cc: Eduardo Valentin <eduardo.valentin@ti.com> Cc: J Keerthy <j-keerthy@ti.com> Cc: Radhesh Fadnis <radhesh.fadnis@ti.com> Cc: Cyril Roelandt <tipecaml@gmail.com> Cc: devicetree-discuss@lists.ozlabs.org Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: devel@driverdev.osuosl.org Cc: linux-pm@vger.kernel.org Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Diffstat (limited to 'drivers/thermal/ti-soc-thermal')
-rw-r--r--drivers/thermal/ti-soc-thermal/Kconfig48
-rw-r--r--drivers/thermal/ti-soc-thermal/Makefile5
-rw-r--r--drivers/thermal/ti-soc-thermal/TODO12
-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.c1546
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.h403
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-thermal-common.c367
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-thermal.h117
11 files changed, 3499 insertions, 0 deletions
diff --git a/drivers/thermal/ti-soc-thermal/Kconfig b/drivers/thermal/ti-soc-thermal/Kconfig
new file mode 100644
index 000000000000..e81375fb2155
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/Kconfig
@@ -0,0 +1,48 @@
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.
diff --git a/drivers/thermal/ti-soc-thermal/Makefile b/drivers/thermal/ti-soc-thermal/Makefile
new file mode 100644
index 000000000000..0ca034fb419d
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/Makefile
@@ -0,0 +1,5 @@
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_OMAP4_THERMAL) += omap4-thermal-data.o
5ti-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/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..f20c1cfe9800
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
@@ -0,0 +1,1546 @@
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/io.h>
42
43#include "ti-bandgap.h"
44
45/*** Helper functions to access registers and their bitfields ***/
46
47/**
48 * ti_bandgap_readl() - simple read helper function
49 * @bgp: pointer to ti_bandgap structure
50 * @reg: desired register (offset) to be read
51 *
52 * Helper function to read bandgap registers. It uses the io remapped area.
53 * Return: the register value.
54 */
55static u32 ti_bandgap_readl(struct ti_bandgap *bgp, u32 reg)
56{
57 return readl(bgp->base + reg);
58}
59
60/**
61 * ti_bandgap_writel() - simple write helper function
62 * @bgp: pointer to ti_bandgap structure
63 * @val: desired register value to be written
64 * @reg: desired register (offset) to be written
65 *
66 * Helper function to write bandgap registers. It uses the io remapped area.
67 */
68static void ti_bandgap_writel(struct ti_bandgap *bgp, u32 val, u32 reg)
69{
70 writel(val, bgp->base + reg);
71}
72
73/**
74 * DOC: macro to update bits.
75 *
76 * RMW_BITS() - used to read, modify and update bandgap bitfields.
77 * The value passed will be shifted.
78 */
79#define RMW_BITS(bgp, id, reg, mask, val) \
80do { \
81 struct temp_sensor_registers *t; \
82 u32 r; \
83 \
84 t = bgp->conf->sensors[(id)].registers; \
85 r = ti_bandgap_readl(bgp, t->reg); \
86 r &= ~t->mask; \
87 r |= (val) << __ffs(t->mask); \
88 ti_bandgap_writel(bgp, r, t->reg); \
89} while (0)
90
91/*** Basic helper functions ***/
92
93/**
94 * ti_bandgap_power() - controls the power state of a bandgap device
95 * @bgp: pointer to ti_bandgap structure
96 * @on: desired power state (1 - on, 0 - off)
97 *
98 * Used to power on/off a bandgap device instance. Only used on those
99 * that features tempsoff bit.
100 *
101 * Return: 0 on success, -ENOTSUPP if tempsoff is not supported.
102 */
103static int ti_bandgap_power(struct ti_bandgap *bgp, bool on)
104{
105 int i, ret = 0;
106
107 if (!TI_BANDGAP_HAS(bgp, POWER_SWITCH)) {
108 ret = -ENOTSUPP;
109 goto exit;
110 }
111
112 for (i = 0; i < bgp->conf->sensor_count; i++)
113 /* active on 0 */
114 RMW_BITS(bgp, i, temp_sensor_ctrl, bgap_tempsoff_mask, !on);
115
116exit:
117 return ret;
118}
119
120/**
121 * ti_bandgap_read_temp() - helper function to read sensor temperature
122 * @bgp: pointer to ti_bandgap structure
123 * @id: bandgap sensor id
124 *
125 * Function to concentrate the steps to read sensor temperature register.
126 * This function is desired because, depending on bandgap device version,
127 * it might be needed to freeze the bandgap state machine, before fetching
128 * the register value.
129 *
130 * Return: temperature in ADC values.
131 */
132static u32 ti_bandgap_read_temp(struct ti_bandgap *bgp, int id)
133{
134 struct temp_sensor_registers *tsr;
135 u32 temp, reg;
136
137 tsr = bgp->conf->sensors[id].registers;
138 reg = tsr->temp_sensor_ctrl;
139
140 if (TI_BANDGAP_HAS(bgp, FREEZE_BIT)) {
141 RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1);
142 /*
143 * In case we cannot read from cur_dtemp / dtemp_0,
144 * then we read from the last valid temp read
145 */
146 reg = tsr->ctrl_dtemp_1;
147 }
148
149 /* read temperature */
150 temp = ti_bandgap_readl(bgp, reg);
151 temp &= tsr->bgap_dtemp_mask;
152
153 if (TI_BANDGAP_HAS(bgp, FREEZE_BIT))
154 RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0);
155
156 return temp;
157}
158
159/*** IRQ handlers ***/
160
161/**
162 * ti_bandgap_talert_irq_handler() - handles Temperature alert IRQs
163 * @irq: IRQ number
164 * @data: private data (struct ti_bandgap *)
165 *
166 * This is the Talert handler. Use it only if bandgap device features
167 * HAS(TALERT). This handler goes over all sensors and checks their
168 * conditions and acts accordingly. In case there are events pending,
169 * it will reset the event mask to wait for the opposite event (next event).
170 * Every time there is a new event, it will be reported to thermal layer.
171 *
172 * Return: IRQ_HANDLED
173 */
174static irqreturn_t ti_bandgap_talert_irq_handler(int irq, void *data)
175{
176 struct ti_bandgap *bgp = data;
177 struct temp_sensor_registers *tsr;
178 u32 t_hot = 0, t_cold = 0, ctrl;
179 int i;
180
181 spin_lock(&bgp->lock);
182 for (i = 0; i < bgp->conf->sensor_count; i++) {
183 tsr = bgp->conf->sensors[i].registers;
184 ctrl = ti_bandgap_readl(bgp, tsr->bgap_status);
185
186 /* Read the status of t_hot */
187 t_hot = ctrl & tsr->status_hot_mask;
188
189 /* Read the status of t_cold */
190 t_cold = ctrl & tsr->status_cold_mask;
191
192 if (!t_cold && !t_hot)
193 continue;
194
195 ctrl = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
196 /*
197 * One TALERT interrupt: Two sources
198 * If the interrupt is due to t_hot then mask t_hot and
199 * and unmask t_cold else mask t_cold and unmask t_hot
200 */
201 if (t_hot) {
202 ctrl &= ~tsr->mask_hot_mask;
203 ctrl |= tsr->mask_cold_mask;
204 } else if (t_cold) {
205 ctrl &= ~tsr->mask_cold_mask;
206 ctrl |= tsr->mask_hot_mask;
207 }
208
209 ti_bandgap_writel(bgp, ctrl, tsr->bgap_mask_ctrl);
210
211 dev_dbg(bgp->dev,
212 "%s: IRQ from %s sensor: hotevent %d coldevent %d\n",
213 __func__, bgp->conf->sensors[i].domain,
214 t_hot, t_cold);
215
216 /* report temperature to whom may concern */
217 if (bgp->conf->report_temperature)
218 bgp->conf->report_temperature(bgp, i);
219 }
220 spin_unlock(&bgp->lock);
221
222 return IRQ_HANDLED;
223}
224
225/**
226 * ti_bandgap_tshut_irq_handler() - handles Temperature shutdown signal
227 * @irq: IRQ number
228 * @data: private data (unused)
229 *
230 * This is the Tshut handler. Use it only if bandgap device features
231 * HAS(TSHUT). If any sensor fires the Tshut signal, we simply shutdown
232 * the system.
233 *
234 * Return: IRQ_HANDLED
235 */
236static irqreturn_t ti_bandgap_tshut_irq_handler(int irq, void *data)
237{
238 pr_emerg("%s: TSHUT temperature reached. Needs shut down...\n",
239 __func__);
240
241 orderly_poweroff(true);
242
243 return IRQ_HANDLED;
244}
245
246/*** Helper functions which manipulate conversion ADC <-> mi Celsius ***/
247
248/**
249 * ti_bandgap_adc_to_mcelsius() - converts an ADC value to mCelsius scale
250 * @bgp: struct ti_bandgap pointer
251 * @adc_val: value in ADC representation
252 * @t: address where to write the resulting temperature in mCelsius
253 *
254 * Simple conversion from ADC representation to mCelsius. In case the ADC value
255 * is out of the ADC conv table range, it returns -ERANGE, 0 on success.
256 * The conversion table is indexed by the ADC values.
257 *
258 * Return: 0 if conversion was successful, else -ERANGE in case the @adc_val
259 * argument is out of the ADC conv table range.
260 */
261static
262int ti_bandgap_adc_to_mcelsius(struct ti_bandgap *bgp, int adc_val, int *t)
263{
264 const struct ti_bandgap_data *conf = bgp->conf;
265 int ret = 0;
266
267 /* look up for temperature in the table and return the temperature */
268 if (adc_val < conf->adc_start_val || adc_val > conf->adc_end_val) {
269 ret = -ERANGE;
270 goto exit;
271 }
272
273 *t = bgp->conf->conv_table[adc_val - conf->adc_start_val];
274
275exit:
276 return ret;
277}
278
279/**
280 * ti_bandgap_mcelsius_to_adc() - converts a mCelsius value to ADC scale
281 * @bgp: struct ti_bandgap pointer
282 * @temp: value in mCelsius
283 * @adc: address where to write the resulting temperature in ADC representation
284 *
285 * Simple conversion from mCelsius to ADC values. In case the temp value
286 * is out of the ADC conv table range, it returns -ERANGE, 0 on success.
287 * The conversion table is indexed by the ADC values.
288 *
289 * Return: 0 if conversion was successful, else -ERANGE in case the @temp
290 * argument is out of the ADC conv table range.
291 */
292static
293int ti_bandgap_mcelsius_to_adc(struct ti_bandgap *bgp, long temp, int *adc)
294{
295 const struct ti_bandgap_data *conf = bgp->conf;
296 const int *conv_table = bgp->conf->conv_table;
297 int high, low, mid, ret = 0;
298
299 low = 0;
300 high = conf->adc_end_val - conf->adc_start_val;
301 mid = (high + low) / 2;
302
303 if (temp < conv_table[low] || temp > conv_table[high]) {
304 ret = -ERANGE;
305 goto exit;
306 }
307
308 while (low < high) {
309 if (temp < conv_table[mid])
310 high = mid - 1;
311 else
312 low = mid + 1;
313 mid = (low + high) / 2;
314 }
315
316 *adc = conf->adc_start_val + low;
317
318exit:
319 return ret;
320}
321
322/**
323 * ti_bandgap_add_hyst() - add hysteresis (in mCelsius) to an ADC value
324 * @bgp: struct ti_bandgap pointer
325 * @adc_val: temperature value in ADC representation
326 * @hyst_val: hysteresis value in mCelsius
327 * @sum: address where to write the resulting temperature (in ADC scale)
328 *
329 * Adds an hysteresis value (in mCelsius) to a ADC temperature value.
330 *
331 * Return: 0 on success, -ERANGE otherwise.
332 */
333static
334int ti_bandgap_add_hyst(struct ti_bandgap *bgp, int adc_val, int hyst_val,
335 u32 *sum)
336{
337 int temp, ret;
338
339 /*
340 * Need to add in the mcelsius domain, so we have a temperature
341 * the conv_table range
342 */
343 ret = ti_bandgap_adc_to_mcelsius(bgp, adc_val, &temp);
344 if (ret < 0)
345 goto exit;
346
347 temp += hyst_val;
348
349 ret = ti_bandgap_mcelsius_to_adc(bgp, temp, sum);
350
351exit:
352 return ret;
353}
354
355/*** Helper functions handling device Alert/Shutdown signals ***/
356
357/**
358 * ti_bandgap_unmask_interrupts() - unmasks the events of thot & tcold
359 * @bgp: struct ti_bandgap pointer
360 * @id: bandgap sensor id
361 * @t_hot: hot temperature value to trigger alert signal
362 * @t_cold: cold temperature value to trigger alert signal
363 *
364 * Checks the requested t_hot and t_cold values and configures the IRQ event
365 * masks accordingly. Call this function only if bandgap features HAS(TALERT).
366 */
367static void ti_bandgap_unmask_interrupts(struct ti_bandgap *bgp, int id,
368 u32 t_hot, u32 t_cold)
369{
370 struct temp_sensor_registers *tsr;
371 u32 temp, reg_val;
372
373 /* Read the current on die temperature */
374 temp = ti_bandgap_read_temp(bgp, id);
375
376 tsr = bgp->conf->sensors[id].registers;
377 reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
378
379 if (temp < t_hot)
380 reg_val |= tsr->mask_hot_mask;
381 else
382 reg_val &= ~tsr->mask_hot_mask;
383
384 if (t_cold < temp)
385 reg_val |= tsr->mask_cold_mask;
386 else
387 reg_val &= ~tsr->mask_cold_mask;
388 ti_bandgap_writel(bgp, reg_val, tsr->bgap_mask_ctrl);
389}
390
391/**
392 * ti_bandgap_update_alert_threshold() - sequence to update thresholds
393 * @bgp: struct ti_bandgap pointer
394 * @id: bandgap sensor id
395 * @val: value (ADC) of a new threshold
396 * @hot: desired threshold to be updated. true if threshold hot, false if
397 * threshold cold
398 *
399 * It will program the required thresholds (hot and cold) for TALERT signal.
400 * This function can be used to update t_hot or t_cold, depending on @hot value.
401 * It checks the resulting t_hot and t_cold values, based on the new passed @val
402 * and configures the thresholds so that t_hot is always greater than t_cold.
403 * Call this function only if bandgap features HAS(TALERT).
404 *
405 * Return: 0 if no error, else corresponding error
406 */
407static int ti_bandgap_update_alert_threshold(struct ti_bandgap *bgp, int id,
408 int val, bool hot)
409{
410 struct temp_sensor_data *ts_data = bgp->conf->sensors[id].ts_data;
411 struct temp_sensor_registers *tsr;
412 u32 thresh_val, reg_val, t_hot, t_cold;
413 int err = 0;
414
415 tsr = bgp->conf->sensors[id].registers;
416
417 /* obtain the current value */
418 thresh_val = ti_bandgap_readl(bgp, tsr->bgap_threshold);
419 t_cold = (thresh_val & tsr->threshold_tcold_mask) >>
420 __ffs(tsr->threshold_tcold_mask);
421 t_hot = (thresh_val & tsr->threshold_thot_mask) >>
422 __ffs(tsr->threshold_thot_mask);
423 if (hot)
424 t_hot = val;
425 else
426 t_cold = val;
427
428 if (t_cold > t_hot) {
429 if (hot)
430 err = ti_bandgap_add_hyst(bgp, t_hot,
431 -ts_data->hyst_val,
432 &t_cold);
433 else
434 err = ti_bandgap_add_hyst(bgp, t_cold,
435 ts_data->hyst_val,
436 &t_hot);
437 }
438
439 /* write the new threshold values */
440 reg_val = thresh_val &
441 ~(tsr->threshold_thot_mask | tsr->threshold_tcold_mask);
442 reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask)) |
443 (t_cold << __ffs(tsr->threshold_tcold_mask));
444 ti_bandgap_writel(bgp, reg_val, tsr->bgap_threshold);
445
446 if (err) {
447 dev_err(bgp->dev, "failed to reprogram thot threshold\n");
448 err = -EIO;
449 goto exit;
450 }
451
452 ti_bandgap_unmask_interrupts(bgp, id, t_hot, t_cold);
453exit:
454 return err;
455}
456
457/**
458 * ti_bandgap_validate() - helper to check the sanity of a struct ti_bandgap
459 * @bgp: struct ti_bandgap pointer
460 * @id: bandgap sensor id
461 *
462 * Checks if the bandgap pointer is valid and if the sensor id is also
463 * applicable.
464 *
465 * Return: 0 if no errors, -EINVAL for invalid @bgp pointer or -ERANGE if
466 * @id cannot index @bgp sensors.
467 */
468static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id)
469{
470 int ret = 0;
471
472 if (IS_ERR_OR_NULL(bgp)) {
473 pr_err("%s: invalid bandgap pointer\n", __func__);
474 ret = -EINVAL;
475 goto exit;
476 }
477
478 if ((id < 0) || (id >= bgp->conf->sensor_count)) {
479 dev_err(bgp->dev, "%s: sensor id out of range (%d)\n",
480 __func__, id);
481 ret = -ERANGE;
482 }
483
484exit:
485 return ret;
486}
487
488/**
489 * _ti_bandgap_write_threshold() - helper to update TALERT t_cold or t_hot
490 * @bgp: struct ti_bandgap pointer
491 * @id: bandgap sensor id
492 * @val: value (mCelsius) of a new threshold
493 * @hot: desired threshold to be updated. true if threshold hot, false if
494 * threshold cold
495 *
496 * It will update the required thresholds (hot and cold) for TALERT signal.
497 * This function can be used to update t_hot or t_cold, depending on @hot value.
498 * Validates the mCelsius range and update the requested threshold.
499 * Call this function only if bandgap features HAS(TALERT).
500 *
501 * Return: 0 if no error, else corresponding error value.
502 */
503static int _ti_bandgap_write_threshold(struct ti_bandgap *bgp, int id, int val,
504 bool hot)
505{
506 struct temp_sensor_data *ts_data;
507 struct temp_sensor_registers *tsr;
508 u32 adc_val;
509 int ret;
510
511 ret = ti_bandgap_validate(bgp, id);
512 if (ret)
513 goto exit;
514
515 if (!TI_BANDGAP_HAS(bgp, TALERT)) {
516 ret = -ENOTSUPP;
517 goto exit;
518 }
519
520 ts_data = bgp->conf->sensors[id].ts_data;
521 tsr = bgp->conf->sensors[id].registers;
522 if (hot) {
523 if (val < ts_data->min_temp + ts_data->hyst_val)
524 ret = -EINVAL;
525 } else {
526 if (val > ts_data->max_temp + ts_data->hyst_val)
527 ret = -EINVAL;
528 }
529
530 if (ret)
531 goto exit;
532
533 ret = ti_bandgap_mcelsius_to_adc(bgp, val, &adc_val);
534 if (ret < 0)
535 goto exit;
536
537 spin_lock(&bgp->lock);
538 ret = ti_bandgap_update_alert_threshold(bgp, id, adc_val, hot);
539 spin_unlock(&bgp->lock);
540
541exit:
542 return ret;
543}
544
545/**
546 * _ti_bandgap_read_threshold() - helper to read TALERT t_cold or t_hot
547 * @bgp: struct ti_bandgap pointer
548 * @id: bandgap sensor id
549 * @val: value (mCelsius) of a threshold
550 * @hot: desired threshold to be read. true if threshold hot, false if
551 * threshold cold
552 *
553 * It will fetch the required thresholds (hot and cold) for TALERT signal.
554 * This function can be used to read t_hot or t_cold, depending on @hot value.
555 * Call this function only if bandgap features HAS(TALERT).
556 *
557 * Return: 0 if no error, -ENOTSUPP if it has no TALERT support, or the
558 * corresponding error value if some operation fails.
559 */
560static int _ti_bandgap_read_threshold(struct ti_bandgap *bgp, int id,
561 int *val, bool hot)
562{
563 struct temp_sensor_registers *tsr;
564 u32 temp, mask;
565 int ret = 0;
566
567 ret = ti_bandgap_validate(bgp, id);
568 if (ret)
569 goto exit;
570
571 if (!TI_BANDGAP_HAS(bgp, TALERT)) {
572 ret = -ENOTSUPP;
573 goto exit;
574 }
575
576 tsr = bgp->conf->sensors[id].registers;
577 if (hot)
578 mask = tsr->threshold_thot_mask;
579 else
580 mask = tsr->threshold_tcold_mask;
581
582 temp = ti_bandgap_readl(bgp, tsr->bgap_threshold);
583 temp = (temp & mask) >> __ffs(mask);
584 ret |= ti_bandgap_adc_to_mcelsius(bgp, temp, &temp);
585 if (ret) {
586 dev_err(bgp->dev, "failed to read thot\n");
587 ret = -EIO;
588 goto exit;
589 }
590
591 *val = temp;
592
593exit:
594 return ret;
595}
596
597/*** Exposed APIs ***/
598
599/**
600 * ti_bandgap_read_thot() - reads sensor current thot
601 * @bgp: pointer to bandgap instance
602 * @id: sensor id
603 * @thot: resulting current thot value
604 *
605 * Return: 0 on success or the proper error code
606 */
607int ti_bandgap_read_thot(struct ti_bandgap *bgp, int id, int *thot)
608{
609 return _ti_bandgap_read_threshold(bgp, id, thot, true);
610}
611
612/**
613 * ti_bandgap_write_thot() - sets sensor current thot
614 * @bgp: pointer to bandgap instance
615 * @id: sensor id
616 * @val: desired thot value
617 *
618 * Return: 0 on success or the proper error code
619 */
620int ti_bandgap_write_thot(struct ti_bandgap *bgp, int id, int val)
621{
622 return _ti_bandgap_write_threshold(bgp, id, val, true);
623}
624
625/**
626 * ti_bandgap_read_tcold() - reads sensor current tcold
627 * @bgp: pointer to bandgap instance
628 * @id: sensor id
629 * @tcold: resulting current tcold value
630 *
631 * Return: 0 on success or the proper error code
632 */
633int ti_bandgap_read_tcold(struct ti_bandgap *bgp, int id, int *tcold)
634{
635 return _ti_bandgap_read_threshold(bgp, id, tcold, false);
636}
637
638/**
639 * ti_bandgap_write_tcold() - sets the sensor tcold
640 * @bgp: pointer to bandgap instance
641 * @id: sensor id
642 * @val: desired tcold value
643 *
644 * Return: 0 on success or the proper error code
645 */
646int ti_bandgap_write_tcold(struct ti_bandgap *bgp, int id, int val)
647{
648 return _ti_bandgap_write_threshold(bgp, id, val, false);
649}
650
651/**
652 * ti_bandgap_read_counter() - read the sensor counter
653 * @bgp: pointer to bandgap instance
654 * @id: sensor id
655 * @interval: resulting update interval in miliseconds
656 */
657static void ti_bandgap_read_counter(struct ti_bandgap *bgp, int id,
658 int *interval)
659{
660 struct temp_sensor_registers *tsr;
661 int time;
662
663 tsr = bgp->conf->sensors[id].registers;
664 time = ti_bandgap_readl(bgp, tsr->bgap_counter);
665 time = (time & tsr->counter_mask) >>
666 __ffs(tsr->counter_mask);
667 time = time * 1000 / bgp->clk_rate;
668 *interval = time;
669}
670
671/**
672 * ti_bandgap_read_counter_delay() - read the sensor counter delay
673 * @bgp: pointer to bandgap instance
674 * @id: sensor id
675 * @interval: resulting update interval in miliseconds
676 */
677static void ti_bandgap_read_counter_delay(struct ti_bandgap *bgp, int id,
678 int *interval)
679{
680 struct temp_sensor_registers *tsr;
681 int reg_val;
682
683 tsr = bgp->conf->sensors[id].registers;
684
685 reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
686 reg_val = (reg_val & tsr->mask_counter_delay_mask) >>
687 __ffs(tsr->mask_counter_delay_mask);
688 switch (reg_val) {
689 case 0:
690 *interval = 0;
691 break;
692 case 1:
693 *interval = 1;
694 break;
695 case 2:
696 *interval = 10;
697 break;
698 case 3:
699 *interval = 100;
700 break;
701 case 4:
702 *interval = 250;
703 break;
704 case 5:
705 *interval = 500;
706 break;
707 default:
708 dev_warn(bgp->dev, "Wrong counter delay value read from register %X",
709 reg_val);
710 }
711}
712
713/**
714 * ti_bandgap_read_update_interval() - read the sensor update interval
715 * @bgp: pointer to bandgap instance
716 * @id: sensor id
717 * @interval: resulting update interval in miliseconds
718 *
719 * Return: 0 on success or the proper error code
720 */
721int ti_bandgap_read_update_interval(struct ti_bandgap *bgp, int id,
722 int *interval)
723{
724 int ret = 0;
725
726 ret = ti_bandgap_validate(bgp, id);
727 if (ret)
728 goto exit;
729
730 if (!TI_BANDGAP_HAS(bgp, COUNTER) &&
731 !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) {
732 ret = -ENOTSUPP;
733 goto exit;
734 }
735
736 if (TI_BANDGAP_HAS(bgp, COUNTER)) {
737 ti_bandgap_read_counter(bgp, id, interval);
738 goto exit;
739 }
740
741 ti_bandgap_read_counter_delay(bgp, id, interval);
742exit:
743 return ret;
744}
745
746/**
747 * ti_bandgap_write_counter_delay() - set the counter_delay
748 * @bgp: pointer to bandgap instance
749 * @id: sensor id
750 * @interval: desired update interval in miliseconds
751 *
752 * Return: 0 on success or the proper error code
753 */
754static int ti_bandgap_write_counter_delay(struct ti_bandgap *bgp, int id,
755 u32 interval)
756{
757 int rval;
758
759 switch (interval) {
760 case 0: /* Immediate conversion */
761 rval = 0x0;
762 break;
763 case 1: /* Conversion after ever 1ms */
764 rval = 0x1;
765 break;
766 case 10: /* Conversion after ever 10ms */
767 rval = 0x2;
768 break;
769 case 100: /* Conversion after ever 100ms */
770 rval = 0x3;
771 break;
772 case 250: /* Conversion after ever 250ms */
773 rval = 0x4;
774 break;
775 case 500: /* Conversion after ever 500ms */
776 rval = 0x5;
777 break;
778 default:
779 dev_warn(bgp->dev, "Delay %d ms is not supported\n", interval);
780 return -EINVAL;
781 }
782
783 spin_lock(&bgp->lock);
784 RMW_BITS(bgp, id, bgap_mask_ctrl, mask_counter_delay_mask, rval);
785 spin_unlock(&bgp->lock);
786
787 return 0;
788}
789
790/**
791 * ti_bandgap_write_counter() - set the bandgap sensor counter
792 * @bgp: pointer to bandgap instance
793 * @id: sensor id
794 * @interval: desired update interval in miliseconds
795 */
796static void ti_bandgap_write_counter(struct ti_bandgap *bgp, int id,
797 u32 interval)
798{
799 interval = interval * bgp->clk_rate / 1000;
800 spin_lock(&bgp->lock);
801 RMW_BITS(bgp, id, bgap_counter, counter_mask, interval);
802 spin_unlock(&bgp->lock);
803}
804
805/**
806 * ti_bandgap_write_update_interval() - set the update interval
807 * @bgp: pointer to bandgap instance
808 * @id: sensor id
809 * @interval: desired update interval in miliseconds
810 *
811 * Return: 0 on success or the proper error code
812 */
813int ti_bandgap_write_update_interval(struct ti_bandgap *bgp,
814 int id, u32 interval)
815{
816 int ret = ti_bandgap_validate(bgp, id);
817 if (ret)
818 goto exit;
819
820 if (!TI_BANDGAP_HAS(bgp, COUNTER) &&
821 !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) {
822 ret = -ENOTSUPP;
823 goto exit;
824 }
825
826 if (TI_BANDGAP_HAS(bgp, COUNTER)) {
827 ti_bandgap_write_counter(bgp, id, interval);
828 goto exit;
829 }
830
831 ret = ti_bandgap_write_counter_delay(bgp, id, interval);
832exit:
833 return ret;
834}
835
836/**
837 * ti_bandgap_read_temperature() - report current temperature
838 * @bgp: pointer to bandgap instance
839 * @id: sensor id
840 * @temperature: resulting temperature
841 *
842 * Return: 0 on success or the proper error code
843 */
844int ti_bandgap_read_temperature(struct ti_bandgap *bgp, int id,
845 int *temperature)
846{
847 u32 temp;
848 int ret;
849
850 ret = ti_bandgap_validate(bgp, id);
851 if (ret)
852 return ret;
853
854 spin_lock(&bgp->lock);
855 temp = ti_bandgap_read_temp(bgp, id);
856 spin_unlock(&bgp->lock);
857
858 ret |= ti_bandgap_adc_to_mcelsius(bgp, temp, &temp);
859 if (ret)
860 return -EIO;
861
862 *temperature = temp;
863
864 return 0;
865}
866
867/**
868 * ti_bandgap_set_sensor_data() - helper function to store thermal
869 * framework related data.
870 * @bgp: pointer to bandgap instance
871 * @id: sensor id
872 * @data: thermal framework related data to be stored
873 *
874 * Return: 0 on success or the proper error code
875 */
876int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data)
877{
878 int ret = ti_bandgap_validate(bgp, id);
879 if (ret)
880 return ret;
881
882 bgp->regval[id].data = data;
883
884 return 0;
885}
886
887/**
888 * ti_bandgap_get_sensor_data() - helper function to get thermal
889 * framework related data.
890 * @bgp: pointer to bandgap instance
891 * @id: sensor id
892 *
893 * Return: data stored by set function with sensor id on success or NULL
894 */
895void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id)
896{
897 int ret = ti_bandgap_validate(bgp, id);
898 if (ret)
899 return ERR_PTR(ret);
900
901 return bgp->regval[id].data;
902}
903
904/*** Helper functions used during device initialization ***/
905
906/**
907 * ti_bandgap_force_single_read() - executes 1 single ADC conversion
908 * @bgp: pointer to struct ti_bandgap
909 * @id: sensor id which it is desired to read 1 temperature
910 *
911 * Used to initialize the conversion state machine and set it to a valid
912 * state. Called during device initialization and context restore events.
913 *
914 * Return: 0
915 */
916static int
917ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id)
918{
919 u32 temp = 0, counter = 1000;
920
921 /* Select single conversion mode */
922 if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
923 RMW_BITS(bgp, id, bgap_mode_ctrl, mode_ctrl_mask, 0);
924
925 /* Start of Conversion = 1 */
926 RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 1);
927 /* Wait until DTEMP is updated */
928 temp = ti_bandgap_read_temp(bgp, id);
929
930 while ((temp == 0) && --counter)
931 temp = ti_bandgap_read_temp(bgp, id);
932 /* REVISIT: Check correct condition for end of conversion */
933
934 /* Start of Conversion = 0 */
935 RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 0);
936
937 return 0;
938}
939
940/**
941 * ti_bandgap_set_continous_mode() - One time enabling of continuous mode
942 * @bgp: pointer to struct ti_bandgap
943 *
944 * Call this function only if HAS(MODE_CONFIG) is set. As this driver may
945 * be used for junction temperature monitoring, it is desirable that the
946 * sensors are operational all the time, so that alerts are generated
947 * properly.
948 *
949 * Return: 0
950 */
951static int ti_bandgap_set_continuous_mode(struct ti_bandgap *bgp)
952{
953 int i;
954
955 for (i = 0; i < bgp->conf->sensor_count; i++) {
956 /* Perform a single read just before enabling continuous */
957 ti_bandgap_force_single_read(bgp, i);
958 RMW_BITS(bgp, i, bgap_mode_ctrl, mode_ctrl_mask, 1);
959 }
960
961 return 0;
962}
963
964/**
965 * ti_bandgap_get_trend() - To fetch the temperature trend of a sensor
966 * @bgp: pointer to struct ti_bandgap
967 * @id: id of the individual sensor
968 * @trend: Pointer to trend.
969 *
970 * This function needs to be called to fetch the temperature trend of a
971 * Particular sensor. The function computes the difference in temperature
972 * w.r.t time. For the bandgaps with built in history buffer the temperatures
973 * are read from the buffer and for those without the Buffer -ENOTSUPP is
974 * returned.
975 *
976 * Return: 0 if no error, else return corresponding error. If no
977 * error then the trend value is passed on to trend parameter
978 */
979int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend)
980{
981 struct temp_sensor_registers *tsr;
982 u32 temp1, temp2, reg1, reg2;
983 int t1, t2, interval, ret = 0;
984
985 ret = ti_bandgap_validate(bgp, id);
986 if (ret)
987 goto exit;
988
989 if (!TI_BANDGAP_HAS(bgp, HISTORY_BUFFER) ||
990 !TI_BANDGAP_HAS(bgp, FREEZE_BIT)) {
991 ret = -ENOTSUPP;
992 goto exit;
993 }
994
995 tsr = bgp->conf->sensors[id].registers;
996
997 /* Freeze and read the last 2 valid readings */
998 reg1 = tsr->ctrl_dtemp_1;
999 reg2 = tsr->ctrl_dtemp_2;
1000
1001 /* read temperature from history buffer */
1002 temp1 = ti_bandgap_readl(bgp, reg1);
1003 temp1 &= tsr->bgap_dtemp_mask;
1004
1005 temp2 = ti_bandgap_readl(bgp, reg2);
1006 temp2 &= tsr->bgap_dtemp_mask;
1007
1008 /* Convert from adc values to mCelsius temperature */
1009 ret = ti_bandgap_adc_to_mcelsius(bgp, temp1, &t1);
1010 if (ret)
1011 goto exit;
1012
1013 ret = ti_bandgap_adc_to_mcelsius(bgp, temp2, &t2);
1014 if (ret)
1015 goto exit;
1016
1017 /* Fetch the update interval */
1018 ret = ti_bandgap_read_update_interval(bgp, id, &interval);
1019 if (ret || !interval)
1020 goto exit;
1021
1022 *trend = (t1 - t2) / interval;
1023
1024 dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n",
1025 t1, t2, *trend);
1026
1027exit:
1028 return ret;
1029}
1030
1031/**
1032 * ti_bandgap_tshut_init() - setup and initialize tshut handling
1033 * @bgp: pointer to struct ti_bandgap
1034 * @pdev: pointer to device struct platform_device
1035 *
1036 * Call this function only in case the bandgap features HAS(TSHUT).
1037 * In this case, the driver needs to handle the TSHUT signal as an IRQ.
1038 * The IRQ is wired as a GPIO, and for this purpose, it is required
1039 * to specify which GPIO line is used. TSHUT IRQ is fired anytime
1040 * one of the bandgap sensors violates the TSHUT high/hot threshold.
1041 * And in that case, the system must go off.
1042 *
1043 * Return: 0 if no error, else error status
1044 */
1045static int ti_bandgap_tshut_init(struct ti_bandgap *bgp,
1046 struct platform_device *pdev)
1047{
1048 int gpio_nr = bgp->tshut_gpio;
1049 int status;
1050
1051 /* Request for gpio_86 line */
1052 status = gpio_request(gpio_nr, "tshut");
1053 if (status < 0) {
1054 dev_err(bgp->dev, "Could not request for TSHUT GPIO:%i\n", 86);
1055 return status;
1056 }
1057 status = gpio_direction_input(gpio_nr);
1058 if (status) {
1059 dev_err(bgp->dev, "Cannot set input TSHUT GPIO %d\n", gpio_nr);
1060 return status;
1061 }
1062
1063 status = request_irq(gpio_to_irq(gpio_nr), ti_bandgap_tshut_irq_handler,
1064 IRQF_TRIGGER_RISING, "tshut", NULL);
1065 if (status) {
1066 gpio_free(gpio_nr);
1067 dev_err(bgp->dev, "request irq failed for TSHUT");
1068 }
1069
1070 return 0;
1071}
1072
1073/**
1074 * ti_bandgap_alert_init() - setup and initialize talert handling
1075 * @bgp: pointer to struct ti_bandgap
1076 * @pdev: pointer to device struct platform_device
1077 *
1078 * Call this function only in case the bandgap features HAS(TALERT).
1079 * In this case, the driver needs to handle the TALERT signals as an IRQs.
1080 * TALERT is a normal IRQ and it is fired any time thresholds (hot or cold)
1081 * are violated. In these situation, the driver must reprogram the thresholds,
1082 * accordingly to specified policy.
1083 *
1084 * Return: 0 if no error, else return corresponding error.
1085 */
1086static int ti_bandgap_talert_init(struct ti_bandgap *bgp,
1087 struct platform_device *pdev)
1088{
1089 int ret;
1090
1091 bgp->irq = platform_get_irq(pdev, 0);
1092 if (bgp->irq < 0) {
1093 dev_err(&pdev->dev, "get_irq failed\n");
1094 return bgp->irq;
1095 }
1096 ret = request_threaded_irq(bgp->irq, NULL,
1097 ti_bandgap_talert_irq_handler,
1098 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
1099 "talert", bgp);
1100 if (ret) {
1101 dev_err(&pdev->dev, "Request threaded irq failed.\n");
1102 return ret;
1103 }
1104
1105 return 0;
1106}
1107
1108static const struct of_device_id of_ti_bandgap_match[];
1109/**
1110 * ti_bandgap_build() - parse DT and setup a struct ti_bandgap
1111 * @pdev: pointer to device struct platform_device
1112 *
1113 * Used to read the device tree properties accordingly to the bandgap
1114 * matching version. Based on bandgap version and its capabilities it
1115 * will build a struct ti_bandgap out of the required DT entries.
1116 *
1117 * Return: valid bandgap structure if successful, else returns ERR_PTR
1118 * return value must be verified with IS_ERR.
1119 */
1120static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev)
1121{
1122 struct device_node *node = pdev->dev.of_node;
1123 const struct of_device_id *of_id;
1124 struct ti_bandgap *bgp;
1125 struct resource *res;
1126 u32 prop;
1127 int i;
1128
1129 /* just for the sake */
1130 if (!node) {
1131 dev_err(&pdev->dev, "no platform information available\n");
1132 return ERR_PTR(-EINVAL);
1133 }
1134
1135 bgp = devm_kzalloc(&pdev->dev, sizeof(*bgp), GFP_KERNEL);
1136 if (!bgp) {
1137 dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
1138 return ERR_PTR(-ENOMEM);
1139 }
1140
1141 of_id = of_match_device(of_ti_bandgap_match, &pdev->dev);
1142 if (of_id)
1143 bgp->conf = of_id->data;
1144
1145 /* register shadow for context save and restore */
1146 bgp->regval = devm_kzalloc(&pdev->dev, sizeof(*bgp->regval) *
1147 bgp->conf->sensor_count, GFP_KERNEL);
1148 if (!bgp) {
1149 dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
1150 return ERR_PTR(-ENOMEM);
1151 }
1152
1153 i = 0;
1154 do {
1155 void __iomem *chunk;
1156
1157 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
1158 if (!res)
1159 break;
1160 chunk = devm_ioremap_resource(&pdev->dev, res);
1161 if (i == 0)
1162 bgp->base = chunk;
1163 if (IS_ERR(chunk))
1164 return ERR_CAST(chunk);
1165
1166 i++;
1167 } while (res);
1168
1169 if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1170 if (of_property_read_u32(node, "ti,tshut-gpio", &prop) < 0) {
1171 dev_err(&pdev->dev, "missing tshut gpio in device tree\n");
1172 return ERR_PTR(-EINVAL);
1173 }
1174 bgp->tshut_gpio = prop;
1175 if (!gpio_is_valid(bgp->tshut_gpio)) {
1176 dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
1177 bgp->tshut_gpio);
1178 return ERR_PTR(-EINVAL);
1179 }
1180 }
1181
1182 return bgp;
1183}
1184
1185/*** Device driver call backs ***/
1186
1187static
1188int ti_bandgap_probe(struct platform_device *pdev)
1189{
1190 struct ti_bandgap *bgp;
1191 int clk_rate, ret = 0, i;
1192
1193 bgp = ti_bandgap_build(pdev);
1194 if (IS_ERR_OR_NULL(bgp)) {
1195 dev_err(&pdev->dev, "failed to fetch platform data\n");
1196 return PTR_ERR(bgp);
1197 }
1198 bgp->dev = &pdev->dev;
1199
1200 if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1201 ret = ti_bandgap_tshut_init(bgp, pdev);
1202 if (ret) {
1203 dev_err(&pdev->dev,
1204 "failed to initialize system tshut IRQ\n");
1205 return ret;
1206 }
1207 }
1208
1209 bgp->fclock = clk_get(NULL, bgp->conf->fclock_name);
1210 ret = IS_ERR_OR_NULL(bgp->fclock);
1211 if (ret) {
1212 dev_err(&pdev->dev, "failed to request fclock reference\n");
1213 goto free_irqs;
1214 }
1215
1216 bgp->div_clk = clk_get(NULL, bgp->conf->div_ck_name);
1217 ret = IS_ERR_OR_NULL(bgp->div_clk);
1218 if (ret) {
1219 dev_err(&pdev->dev,
1220 "failed to request div_ts_ck clock ref\n");
1221 goto free_irqs;
1222 }
1223
1224 for (i = 0; i < bgp->conf->sensor_count; i++) {
1225 struct temp_sensor_registers *tsr;
1226 u32 val;
1227
1228 tsr = bgp->conf->sensors[i].registers;
1229 /*
1230 * check if the efuse has a non-zero value if not
1231 * it is an untrimmed sample and the temperatures
1232 * may not be accurate
1233 */
1234 val = ti_bandgap_readl(bgp, tsr->bgap_efuse);
1235 if (ret || !val)
1236 dev_info(&pdev->dev,
1237 "Non-trimmed BGAP, Temp not accurate\n");
1238 }
1239
1240 clk_rate = clk_round_rate(bgp->div_clk,
1241 bgp->conf->sensors[0].ts_data->max_freq);
1242 if (clk_rate < bgp->conf->sensors[0].ts_data->min_freq ||
1243 clk_rate == 0xffffffff) {
1244 ret = -ENODEV;
1245 dev_err(&pdev->dev, "wrong clock rate (%d)\n", clk_rate);
1246 goto put_clks;
1247 }
1248
1249 ret = clk_set_rate(bgp->div_clk, clk_rate);
1250 if (ret)
1251 dev_err(&pdev->dev, "Cannot re-set clock rate. Continuing\n");
1252
1253 bgp->clk_rate = clk_rate;
1254 if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1255 clk_prepare_enable(bgp->fclock);
1256
1257
1258 spin_lock_init(&bgp->lock);
1259 bgp->dev = &pdev->dev;
1260 platform_set_drvdata(pdev, bgp);
1261
1262 ti_bandgap_power(bgp, true);
1263
1264 /* Set default counter to 1 for now */
1265 if (TI_BANDGAP_HAS(bgp, COUNTER))
1266 for (i = 0; i < bgp->conf->sensor_count; i++)
1267 RMW_BITS(bgp, i, bgap_counter, counter_mask, 1);
1268
1269 /* Set default thresholds for alert and shutdown */
1270 for (i = 0; i < bgp->conf->sensor_count; i++) {
1271 struct temp_sensor_data *ts_data;
1272
1273 ts_data = bgp->conf->sensors[i].ts_data;
1274
1275 if (TI_BANDGAP_HAS(bgp, TALERT)) {
1276 /* Set initial Talert thresholds */
1277 RMW_BITS(bgp, i, bgap_threshold,
1278 threshold_tcold_mask, ts_data->t_cold);
1279 RMW_BITS(bgp, i, bgap_threshold,
1280 threshold_thot_mask, ts_data->t_hot);
1281 /* Enable the alert events */
1282 RMW_BITS(bgp, i, bgap_mask_ctrl, mask_hot_mask, 1);
1283 RMW_BITS(bgp, i, bgap_mask_ctrl, mask_cold_mask, 1);
1284 }
1285
1286 if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG)) {
1287 /* Set initial Tshut thresholds */
1288 RMW_BITS(bgp, i, tshut_threshold,
1289 tshut_hot_mask, ts_data->tshut_hot);
1290 RMW_BITS(bgp, i, tshut_threshold,
1291 tshut_cold_mask, ts_data->tshut_cold);
1292 }
1293 }
1294
1295 if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
1296 ti_bandgap_set_continuous_mode(bgp);
1297
1298 /* Set .250 seconds time as default counter */
1299 if (TI_BANDGAP_HAS(bgp, COUNTER))
1300 for (i = 0; i < bgp->conf->sensor_count; i++)
1301 RMW_BITS(bgp, i, bgap_counter, counter_mask,
1302 bgp->clk_rate / 4);
1303
1304 /* Every thing is good? Then expose the sensors */
1305 for (i = 0; i < bgp->conf->sensor_count; i++) {
1306 char *domain;
1307
1308 if (bgp->conf->sensors[i].register_cooling) {
1309 ret = bgp->conf->sensors[i].register_cooling(bgp, i);
1310 if (ret)
1311 goto remove_sensors;
1312 }
1313
1314 if (bgp->conf->expose_sensor) {
1315 domain = bgp->conf->sensors[i].domain;
1316 ret = bgp->conf->expose_sensor(bgp, i, domain);
1317 if (ret)
1318 goto remove_last_cooling;
1319 }
1320 }
1321
1322 /*
1323 * Enable the Interrupts once everything is set. Otherwise irq handler
1324 * might be called as soon as it is enabled where as rest of framework
1325 * is still getting initialised.
1326 */
1327 if (TI_BANDGAP_HAS(bgp, TALERT)) {
1328 ret = ti_bandgap_talert_init(bgp, pdev);
1329 if (ret) {
1330 dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
1331 i = bgp->conf->sensor_count;
1332 goto disable_clk;
1333 }
1334 }
1335
1336 return 0;
1337
1338remove_last_cooling:
1339 if (bgp->conf->sensors[i].unregister_cooling)
1340 bgp->conf->sensors[i].unregister_cooling(bgp, i);
1341remove_sensors:
1342 for (i--; i >= 0; i--) {
1343 if (bgp->conf->sensors[i].unregister_cooling)
1344 bgp->conf->sensors[i].unregister_cooling(bgp, i);
1345 if (bgp->conf->remove_sensor)
1346 bgp->conf->remove_sensor(bgp, i);
1347 }
1348 ti_bandgap_power(bgp, false);
1349disable_clk:
1350 if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1351 clk_disable_unprepare(bgp->fclock);
1352put_clks:
1353 clk_put(bgp->fclock);
1354 clk_put(bgp->div_clk);
1355free_irqs:
1356 if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1357 free_irq(gpio_to_irq(bgp->tshut_gpio), NULL);
1358 gpio_free(bgp->tshut_gpio);
1359 }
1360
1361 return ret;
1362}
1363
1364static
1365int ti_bandgap_remove(struct platform_device *pdev)
1366{
1367 struct ti_bandgap *bgp = platform_get_drvdata(pdev);
1368 int i;
1369
1370 /* First thing is to remove sensor interfaces */
1371 for (i = 0; i < bgp->conf->sensor_count; i++) {
1372 if (bgp->conf->sensors[i].unregister_cooling)
1373 bgp->conf->sensors[i].unregister_cooling(bgp, i);
1374
1375 if (bgp->conf->remove_sensor)
1376 bgp->conf->remove_sensor(bgp, i);
1377 }
1378
1379 ti_bandgap_power(bgp, false);
1380
1381 if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1382 clk_disable_unprepare(bgp->fclock);
1383 clk_put(bgp->fclock);
1384 clk_put(bgp->div_clk);
1385
1386 if (TI_BANDGAP_HAS(bgp, TALERT))
1387 free_irq(bgp->irq, bgp);
1388
1389 if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1390 free_irq(gpio_to_irq(bgp->tshut_gpio), NULL);
1391 gpio_free(bgp->tshut_gpio);
1392 }
1393
1394 return 0;
1395}
1396
1397#ifdef CONFIG_PM
1398static int ti_bandgap_save_ctxt(struct ti_bandgap *bgp)
1399{
1400 int i;
1401
1402 for (i = 0; i < bgp->conf->sensor_count; i++) {
1403 struct temp_sensor_registers *tsr;
1404 struct temp_sensor_regval *rval;
1405
1406 rval = &bgp->regval[i];
1407 tsr = bgp->conf->sensors[i].registers;
1408
1409 if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
1410 rval->bg_mode_ctrl = ti_bandgap_readl(bgp,
1411 tsr->bgap_mode_ctrl);
1412 if (TI_BANDGAP_HAS(bgp, COUNTER))
1413 rval->bg_counter = ti_bandgap_readl(bgp,
1414 tsr->bgap_counter);
1415 if (TI_BANDGAP_HAS(bgp, TALERT)) {
1416 rval->bg_threshold = ti_bandgap_readl(bgp,
1417 tsr->bgap_threshold);
1418 rval->bg_ctrl = ti_bandgap_readl(bgp,
1419 tsr->bgap_mask_ctrl);
1420 }
1421
1422 if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG))
1423 rval->tshut_threshold = ti_bandgap_readl(bgp,
1424 tsr->tshut_threshold);
1425 }
1426
1427 return 0;
1428}
1429
1430static int ti_bandgap_restore_ctxt(struct ti_bandgap *bgp)
1431{
1432 int i;
1433
1434 for (i = 0; i < bgp->conf->sensor_count; i++) {
1435 struct temp_sensor_registers *tsr;
1436 struct temp_sensor_regval *rval;
1437 u32 val = 0;
1438
1439 rval = &bgp->regval[i];
1440 tsr = bgp->conf->sensors[i].registers;
1441
1442 if (TI_BANDGAP_HAS(bgp, COUNTER))
1443 val = ti_bandgap_readl(bgp, tsr->bgap_counter);
1444
1445 if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG))
1446 ti_bandgap_writel(bgp, rval->tshut_threshold,
1447 tsr->tshut_threshold);
1448 /* Force immediate temperature measurement and update
1449 * of the DTEMP field
1450 */
1451 ti_bandgap_force_single_read(bgp, i);
1452
1453 if (TI_BANDGAP_HAS(bgp, COUNTER))
1454 ti_bandgap_writel(bgp, rval->bg_counter,
1455 tsr->bgap_counter);
1456 if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
1457 ti_bandgap_writel(bgp, rval->bg_mode_ctrl,
1458 tsr->bgap_mode_ctrl);
1459 if (TI_BANDGAP_HAS(bgp, TALERT)) {
1460 ti_bandgap_writel(bgp, rval->bg_threshold,
1461 tsr->bgap_threshold);
1462 ti_bandgap_writel(bgp, rval->bg_ctrl,
1463 tsr->bgap_mask_ctrl);
1464 }
1465 }
1466
1467 return 0;
1468}
1469
1470static int ti_bandgap_suspend(struct device *dev)
1471{
1472 struct ti_bandgap *bgp = dev_get_drvdata(dev);
1473 int err;
1474
1475 err = ti_bandgap_save_ctxt(bgp);
1476 ti_bandgap_power(bgp, false);
1477
1478 if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1479 clk_disable_unprepare(bgp->fclock);
1480
1481 return err;
1482}
1483
1484static int ti_bandgap_resume(struct device *dev)
1485{
1486 struct ti_bandgap *bgp = dev_get_drvdata(dev);
1487
1488 if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1489 clk_prepare_enable(bgp->fclock);
1490
1491 ti_bandgap_power(bgp, true);
1492
1493 return ti_bandgap_restore_ctxt(bgp);
1494}
1495static const struct dev_pm_ops ti_bandgap_dev_pm_ops = {
1496 SET_SYSTEM_SLEEP_PM_OPS(ti_bandgap_suspend,
1497 ti_bandgap_resume)
1498};
1499
1500#define DEV_PM_OPS (&ti_bandgap_dev_pm_ops)
1501#else
1502#define DEV_PM_OPS NULL
1503#endif
1504
1505static const struct of_device_id of_ti_bandgap_match[] = {
1506#ifdef CONFIG_OMAP4_THERMAL
1507 {
1508 .compatible = "ti,omap4430-bandgap",
1509 .data = (void *)&omap4430_data,
1510 },
1511 {
1512 .compatible = "ti,omap4460-bandgap",
1513 .data = (void *)&omap4460_data,
1514 },
1515 {
1516 .compatible = "ti,omap4470-bandgap",
1517 .data = (void *)&omap4470_data,
1518 },
1519#endif
1520#ifdef CONFIG_OMAP5_THERMAL
1521 {
1522 .compatible = "ti,omap5430-bandgap",
1523 .data = (void *)&omap5430_data,
1524 },
1525#endif
1526 /* Sentinel */
1527 { },
1528};
1529MODULE_DEVICE_TABLE(of, of_ti_bandgap_match);
1530
1531static struct platform_driver ti_bandgap_sensor_driver = {
1532 .probe = ti_bandgap_probe,
1533 .remove = ti_bandgap_remove,
1534 .driver = {
1535 .name = "ti-soc-thermal",
1536 .pm = DEV_PM_OPS,
1537 .of_match_table = of_ti_bandgap_match,
1538 },
1539};
1540
1541module_platform_driver(ti_bandgap_sensor_driver);
1542
1543MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
1544MODULE_LICENSE("GPL v2");
1545MODULE_ALIAS("platform:ti-soc-thermal");
1546MODULE_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..5f4794abf583
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.h
@@ -0,0 +1,403 @@
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#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..e3c5e677eaa5
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -0,0 +1,367 @@
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_cooling_device *cool_dev;
42 struct ti_bandgap *bgp;
43 enum thermal_device_mode mode;
44 struct work_struct thermal_wq;
45 int sensor_id;
46};
47
48static void ti_thermal_work(struct work_struct *work)
49{
50 struct ti_thermal_data *data = container_of(work,
51 struct ti_thermal_data, thermal_wq);
52
53 thermal_zone_device_update(data->ti_thermal);
54
55 dev_dbg(&data->ti_thermal->device, "updated thermal zone %s\n",
56 data->ti_thermal->type);
57}
58
59/**
60 * ti_thermal_hotspot_temperature - returns sensor extrapolated temperature
61 * @t: omap sensor temperature
62 * @s: omap sensor slope value
63 * @c: omap sensor const value
64 */
65static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
66{
67 int delta = t * s / 1000 + c;
68
69 if (delta < 0)
70 delta = 0;
71
72 return t + delta;
73}
74
75/* thermal zone ops */
76/* Get temperature callback function for thermal zone*/
77static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
78 unsigned long *temp)
79{
80 struct ti_thermal_data *data = thermal->devdata;
81 struct ti_bandgap *bgp;
82 const struct ti_temp_sensor *s;
83 int ret, tmp, pcb_temp, slope, constant;
84
85 if (!data)
86 return 0;
87
88 bgp = data->bgp;
89 s = &bgp->conf->sensors[data->sensor_id];
90
91 ret = ti_bandgap_read_temperature(bgp, data->sensor_id, &tmp);
92 if (ret)
93 return ret;
94
95 pcb_temp = 0;
96 /* TODO: Introduce pcb temperature lookup */
97 /* In case pcb zone is available, use the extrapolation rule with it */
98 if (pcb_temp) {
99 tmp -= pcb_temp;
100 slope = s->slope_pcb;
101 constant = s->constant_pcb;
102 } else {
103 slope = s->slope;
104 constant = s->constant;
105 }
106 *temp = ti_thermal_hotspot_temperature(tmp, slope, constant);
107
108 return ret;
109}
110
111/* Bind callback functions for thermal zone */
112static int ti_thermal_bind(struct thermal_zone_device *thermal,
113 struct thermal_cooling_device *cdev)
114{
115 struct ti_thermal_data *data = thermal->devdata;
116 int id;
117
118 if (IS_ERR_OR_NULL(data))
119 return -ENODEV;
120
121 /* check if this is the cooling device we registered */
122 if (data->cool_dev != cdev)
123 return 0;
124
125 id = data->sensor_id;
126
127 /* Simple thing, two trips, one passive another critical */
128 return thermal_zone_bind_cooling_device(thermal, 0, cdev,
129 /* bind with min and max states defined by cpu_cooling */
130 THERMAL_NO_LIMIT,
131 THERMAL_NO_LIMIT);
132}
133
134/* Unbind callback functions for thermal zone */
135static int ti_thermal_unbind(struct thermal_zone_device *thermal,
136 struct thermal_cooling_device *cdev)
137{
138 struct ti_thermal_data *data = thermal->devdata;
139
140 if (IS_ERR_OR_NULL(data))
141 return -ENODEV;
142
143 /* check if this is the cooling device we registered */
144 if (data->cool_dev != cdev)
145 return 0;
146
147 /* Simple thing, two trips, one passive another critical */
148 return thermal_zone_unbind_cooling_device(thermal, 0, cdev);
149}
150
151/* Get mode callback functions for thermal zone */
152static int ti_thermal_get_mode(struct thermal_zone_device *thermal,
153 enum thermal_device_mode *mode)
154{
155 struct ti_thermal_data *data = thermal->devdata;
156
157 if (data)
158 *mode = data->mode;
159
160 return 0;
161}
162
163/* Set mode callback functions for thermal zone */
164static int ti_thermal_set_mode(struct thermal_zone_device *thermal,
165 enum thermal_device_mode mode)
166{
167 struct ti_thermal_data *data = thermal->devdata;
168
169 if (!data->ti_thermal) {
170 dev_notice(&thermal->device, "thermal zone not registered\n");
171 return 0;
172 }
173
174 mutex_lock(&data->ti_thermal->lock);
175
176 if (mode == THERMAL_DEVICE_ENABLED)
177 data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
178 else
179 data->ti_thermal->polling_delay = 0;
180
181 mutex_unlock(&data->ti_thermal->lock);
182
183 data->mode = mode;
184 thermal_zone_device_update(data->ti_thermal);
185 dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n",
186 data->ti_thermal->polling_delay);
187
188 return 0;
189}
190
191/* Get trip type callback functions for thermal zone */
192static int ti_thermal_get_trip_type(struct thermal_zone_device *thermal,
193 int trip, enum thermal_trip_type *type)
194{
195 if (!ti_thermal_is_valid_trip(trip))
196 return -EINVAL;
197
198 if (trip + 1 == OMAP_TRIP_NUMBER)
199 *type = THERMAL_TRIP_CRITICAL;
200 else
201 *type = THERMAL_TRIP_PASSIVE;
202
203 return 0;
204}
205
206/* Get trip temperature callback functions for thermal zone */
207static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
208 int trip, unsigned long *temp)
209{
210 if (!ti_thermal_is_valid_trip(trip))
211 return -EINVAL;
212
213 *temp = ti_thermal_get_trip_value(trip);
214
215 return 0;
216}
217
218/* Get the temperature trend callback functions for thermal zone */
219static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
220 int trip, enum thermal_trend *trend)
221{
222 struct ti_thermal_data *data = thermal->devdata;
223 struct ti_bandgap *bgp;
224 int id, tr, ret = 0;
225
226 bgp = data->bgp;
227 id = data->sensor_id;
228
229 ret = ti_bandgap_get_trend(bgp, id, &tr);
230 if (ret)
231 return ret;
232
233 if (tr > 0)
234 *trend = THERMAL_TREND_RAISING;
235 else if (tr < 0)
236 *trend = THERMAL_TREND_DROPPING;
237 else
238 *trend = THERMAL_TREND_STABLE;
239
240 return 0;
241}
242
243/* Get critical temperature callback functions for thermal zone */
244static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
245 unsigned long *temp)
246{
247 /* shutdown zone */
248 return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
249}
250
251static struct thermal_zone_device_ops ti_thermal_ops = {
252 .get_temp = ti_thermal_get_temp,
253 .get_trend = ti_thermal_get_trend,
254 .bind = ti_thermal_bind,
255 .unbind = ti_thermal_unbind,
256 .get_mode = ti_thermal_get_mode,
257 .set_mode = ti_thermal_set_mode,
258 .get_trip_type = ti_thermal_get_trip_type,
259 .get_trip_temp = ti_thermal_get_trip_temp,
260 .get_crit_temp = ti_thermal_get_crit_temp,
261};
262
263static struct ti_thermal_data
264*ti_thermal_build_data(struct ti_bandgap *bgp, int id)
265{
266 struct ti_thermal_data *data;
267
268 data = devm_kzalloc(bgp->dev, sizeof(*data), GFP_KERNEL);
269 if (!data) {
270 dev_err(bgp->dev, "kzalloc fail\n");
271 return NULL;
272 }
273 data->sensor_id = id;
274 data->bgp = bgp;
275 data->mode = THERMAL_DEVICE_ENABLED;
276 INIT_WORK(&data->thermal_wq, ti_thermal_work);
277
278 return data;
279}
280
281int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
282 char *domain)
283{
284 struct ti_thermal_data *data;
285
286 data = ti_bandgap_get_sensor_data(bgp, id);
287
288 if (IS_ERR_OR_NULL(data))
289 data = ti_thermal_build_data(bgp, id);
290
291 if (!data)
292 return -EINVAL;
293
294 /* Create thermal zone */
295 data->ti_thermal = thermal_zone_device_register(domain,
296 OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
297 NULL, FAST_TEMP_MONITORING_RATE,
298 FAST_TEMP_MONITORING_RATE);
299 if (IS_ERR_OR_NULL(data->ti_thermal)) {
300 dev_err(bgp->dev, "thermal zone device is NULL\n");
301 return PTR_ERR(data->ti_thermal);
302 }
303 data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
304 ti_bandgap_set_sensor_data(bgp, id, data);
305
306 return 0;
307}
308
309int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
310{
311 struct ti_thermal_data *data;
312
313 data = ti_bandgap_get_sensor_data(bgp, id);
314
315 thermal_zone_device_unregister(data->ti_thermal);
316
317 return 0;
318}
319
320int ti_thermal_report_sensor_temperature(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 schedule_work(&data->thermal_wq);
327
328 return 0;
329}
330
331int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
332{
333 struct ti_thermal_data *data;
334
335 data = ti_bandgap_get_sensor_data(bgp, id);
336 if (IS_ERR_OR_NULL(data))
337 data = ti_thermal_build_data(bgp, id);
338
339 if (!data)
340 return -EINVAL;
341
342 if (!cpufreq_get_current_driver()) {
343 dev_dbg(bgp->dev, "no cpufreq driver yet\n");
344 return -EPROBE_DEFER;
345 }
346
347 /* Register cooling device */
348 data->cool_dev = cpufreq_cooling_register(cpu_present_mask);
349 if (IS_ERR_OR_NULL(data->cool_dev)) {
350 dev_err(bgp->dev,
351 "Failed to register cpufreq cooling device\n");
352 return PTR_ERR(data->cool_dev);
353 }
354 ti_bandgap_set_sensor_data(bgp, id, data);
355
356 return 0;
357}
358
359int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
360{
361 struct ti_thermal_data *data;
362
363 data = ti_bandgap_get_sensor_data(bgp, id);
364 cpufreq_cooling_unregister(data->cool_dev);
365
366 return 0;
367}
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..5055777727cc
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal.h
@@ -0,0 +1,117 @@
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/* PCB sensor calculation constants */
42#define OMAP_GRADIENT_SLOPE_W_PCB_4430 0
43#define OMAP_GRADIENT_CONST_W_PCB_4430 20000
44#define OMAP_GRADIENT_SLOPE_W_PCB_4460 1142
45#define OMAP_GRADIENT_CONST_W_PCB_4460 -393
46#define OMAP_GRADIENT_SLOPE_W_PCB_4470 1063
47#define OMAP_GRADIENT_CONST_W_PCB_4470 -477
48
49#define OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU 100
50#define OMAP_GRADIENT_CONST_W_PCB_5430_CPU 484
51#define OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU 464
52#define OMAP_GRADIENT_CONST_W_PCB_5430_GPU -5102
53
54/* trip points of interest in milicelsius (at hotspot level) */
55#define OMAP_TRIP_COLD 100000
56#define OMAP_TRIP_HOT 110000
57#define OMAP_TRIP_SHUTDOWN 125000
58#define OMAP_TRIP_NUMBER 2
59#define OMAP_TRIP_STEP \
60 ((OMAP_TRIP_SHUTDOWN - OMAP_TRIP_HOT) / (OMAP_TRIP_NUMBER - 1))
61
62/* Update rates */
63#define FAST_TEMP_MONITORING_RATE 250
64
65/* helper macros */
66/**
67 * ti_thermal_get_trip_value - returns trip temperature based on index
68 * @i: trip index
69 */
70#define ti_thermal_get_trip_value(i) \
71 (OMAP_TRIP_HOT + ((i) * OMAP_TRIP_STEP))
72
73/**
74 * ti_thermal_is_valid_trip - check for trip index
75 * @i: trip index
76 */
77#define ti_thermal_is_valid_trip(trip) \
78 ((trip) >= 0 && (trip) < OMAP_TRIP_NUMBER)
79
80#ifdef CONFIG_TI_THERMAL
81int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, char *domain);
82int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id);
83int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id);
84int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id);
85int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id);
86#else
87static inline
88int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, char *domain)
89{
90 return 0;
91}
92
93static inline
94int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
95{
96 return 0;
97}
98
99static inline
100int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id)
101{
102 return 0;
103}
104
105static inline
106int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
107{
108 return 0;
109}
110
111static inline
112int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
113{
114 return 0;
115}
116#endif
117#endif