aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhang Rui <rui.zhang@intel.com>2016-03-14 19:53:01 -0400
committerZhang Rui <rui.zhang@intel.com>2016-03-14 19:53:01 -0400
commit032f4a1e5a307c63b5ac27298ea82eb328f40ccc (patch)
tree3ba2d301d6408c6d3b11439076464f25c24b8cd5
parentccb361d2fdda8975c8bbc8a1749c31dbd62dd276 (diff)
parent61f846f37354fd294f3172845d9fec2c03f60a45 (diff)
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal into thermal-soc
-rw-r--r--Documentation/devicetree/bindings/thermal/mediatek-thermal.txt43
-rw-r--r--Documentation/thermal/sysfs-api.txt68
-rw-r--r--drivers/thermal/Kconfig9
-rw-r--r--drivers/thermal/Makefile1
-rw-r--r--drivers/thermal/mtk_thermal.c625
-rw-r--r--drivers/thermal/of-thermal.c81
-rw-r--r--include/linux/thermal.h18
7 files changed, 845 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
new file mode 100644
index 000000000000..81f9a512bc2a
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
@@ -0,0 +1,43 @@
1* Mediatek Thermal
2
3This describes the device tree binding for the Mediatek thermal controller
4which measures the on-SoC temperatures. This device does not have its own ADC,
5instead it directly controls the AUXADC via AHB bus accesses. For this reason
6this device needs phandles to the AUXADC. Also it controls a mux in the
7apmixedsys register space via AHB bus accesses, so a phandle to the APMIXEDSYS
8is also needed.
9
10Required properties:
11- compatible: "mediatek,mt8173-thermal"
12- reg: Address range of the thermal controller
13- interrupts: IRQ for the thermal controller
14- clocks, clock-names: Clocks needed for the thermal controller. required
15 clocks are:
16 "therm": Main clock needed for register access
17 "auxadc": The AUXADC clock
18- resets: Reference to the reset controller controlling the thermal controller.
19- mediatek,auxadc: A phandle to the AUXADC which the thermal controller uses
20- mediatek,apmixedsys: A phandle to the APMIXEDSYS controller.
21- #thermal-sensor-cells : Should be 0. See ./thermal.txt for a description.
22
23Optional properties:
24- nvmem-cells: A phandle to the calibration data provided by a nvmem device. If
25 unspecified default values shall be used.
26- nvmem-cell-names: Should be "calibration-data"
27
28Example:
29
30 thermal: thermal@1100b000 {
31 #thermal-sensor-cells = <1>;
32 compatible = "mediatek,mt8173-thermal";
33 reg = <0 0x1100b000 0 0x1000>;
34 interrupts = <0 70 IRQ_TYPE_LEVEL_LOW>;
35 clocks = <&pericfg CLK_PERI_THERM>, <&pericfg CLK_PERI_AUXADC>;
36 clock-names = "therm", "auxadc";
37 resets = <&pericfg MT8173_PERI_THERM_SW_RST>;
38 reset-names = "therm";
39 mediatek,auxadc = <&auxadc>;
40 mediatek,apmixedsys = <&apmixedsys>;
41 nvmem-cells = <&thermal_calibration_data>;
42 nvmem-cell-names = "calibration-data";
43 };
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index 8c745c8931da..ed419d6c8dec 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -72,6 +72,74 @@ temperature) and throttle appropriate devices.
72 It deletes the corresponding entry form /sys/class/thermal folder and 72 It deletes the corresponding entry form /sys/class/thermal folder and
73 unbind all the thermal cooling devices it uses. 73 unbind all the thermal cooling devices it uses.
74 74
751.1.3 struct thermal_zone_device *thermal_zone_of_sensor_register(
76 struct device *dev, int sensor_id, void *data,
77 const struct thermal_zone_of_device_ops *ops)
78
79 This interface adds a new sensor to a DT thermal zone.
80 This function will search the list of thermal zones described in
81 device tree and look for the zone that refer to the sensor device
82 pointed by dev->of_node as temperature providers. For the zone
83 pointing to the sensor node, the sensor will be added to the DT
84 thermal zone device.
85
86 The parameters for this interface are:
87 dev: Device node of sensor containing valid node pointer in
88 dev->of_node.
89 sensor_id: a sensor identifier, in case the sensor IP has more
90 than one sensors
91 data: a private pointer (owned by the caller) that will be
92 passed back, when a temperature reading is needed.
93 ops: struct thermal_zone_of_device_ops *.
94
95 get_temp: a pointer to a function that reads the
96 sensor temperature. This is mandatory
97 callback provided by sensor driver.
98 get_trend: a pointer to a function that reads the
99 sensor temperature trend.
100 set_emul_temp: a pointer to a function that sets
101 sensor emulated temperature.
102 The thermal zone temperature is provided by the get_temp() function
103 pointer of thermal_zone_of_device_ops. When called, it will
104 have the private pointer @data back.
105
106 It returns error pointer if fails otherwise valid thermal zone device
107 handle. Caller should check the return handle with IS_ERR() for finding
108 whether success or not.
109
1101.1.4 void thermal_zone_of_sensor_unregister(struct device *dev,
111 struct thermal_zone_device *tzd)
112
113 This interface unregisters a sensor from a DT thermal zone which was
114 successfully added by interface thermal_zone_of_sensor_register().
115 This function removes the sensor callbacks and private data from the
116 thermal zone device registered with thermal_zone_of_sensor_register()
117 interface. It will also silent the zone by remove the .get_temp() and
118 get_trend() thermal zone device callbacks.
119
1201.1.5 struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
121 struct device *dev, int sensor_id,
122 void *data, const struct thermal_zone_of_device_ops *ops)
123
124 This interface is resource managed version of
125 thermal_zone_of_sensor_register().
126 All details of thermal_zone_of_sensor_register() described in
127 section 1.1.3 is applicable here.
128 The benefit of using this interface to register sensor is that it
129 is not require to explicitly call thermal_zone_of_sensor_unregister()
130 in error path or during driver unbinding as this is done by driver
131 resource manager.
132
1331.1.6 void devm_thermal_zone_of_sensor_unregister(struct device *dev,
134 struct thermal_zone_device *tzd)
135
136 This interface is resource managed version of
137 thermal_zone_of_sensor_unregister().
138 All details of thermal_zone_of_sensor_unregister() described in
139 section 1.1.4 is applicable here.
140 Normally this function will not need to be called and the resource
141 management code will ensure that the resource is freed.
142
751.2 thermal cooling device interface 1431.2 thermal cooling device interface
761.2.1 struct thermal_cooling_device *thermal_cooling_device_register(char *name, 1441.2.1 struct thermal_cooling_device *thermal_cooling_device_register(char *name,
77 void *devdata, struct thermal_cooling_device_ops *) 145 void *devdata, struct thermal_cooling_device_ops *)
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index d1fd2e5d25e2..c37eedc35a24 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -372,6 +372,15 @@ config INTEL_PCH_THERMAL
372 Thermal reporting device will provide temperature reading, 372 Thermal reporting device will provide temperature reading,
373 programmable trip points and other information. 373 programmable trip points and other information.
374 374
375config MTK_THERMAL
376 tristate "Temperature sensor driver for mediatek SoCs"
377 depends on ARCH_MEDIATEK || COMPILE_TEST
378 depends on HAS_IOMEM
379 default y
380 help
381 Enable this option if you want to have support for thermal management
382 controller present in Mediatek SoCs
383
375menu "Texas Instruments thermal drivers" 384menu "Texas Instruments thermal drivers"
376depends on ARCH_HAS_BANDGAP || COMPILE_TEST 385depends on ARCH_HAS_BANDGAP || COMPILE_TEST
377depends on HAS_IOMEM 386depends on HAS_IOMEM
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index cfae6a654793..8e9cbc3b5679 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -48,3 +48,4 @@ obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
48obj-$(CONFIG_ST_THERMAL) += st/ 48obj-$(CONFIG_ST_THERMAL) += st/
49obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o 49obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o
50obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o 50obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
51obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
new file mode 100644
index 000000000000..3d93b1c07cee
--- /dev/null
+++ b/drivers/thermal/mtk_thermal.c
@@ -0,0 +1,625 @@
1/*
2 * Copyright (c) 2015 MediaTek Inc.
3 * Author: Hanyi Wu <hanyi.wu@mediatek.com>
4 * Sascha Hauer <s.hauer@pengutronix.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <linux/clk.h>
17#include <linux/delay.h>
18#include <linux/interrupt.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/nvmem-consumer.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
24#include <linux/platform_device.h>
25#include <linux/slab.h>
26#include <linux/io.h>
27#include <linux/thermal.h>
28#include <linux/reset.h>
29#include <linux/types.h>
30#include <linux/nvmem-consumer.h>
31
32/* AUXADC Registers */
33#define AUXADC_CON0_V 0x000
34#define AUXADC_CON1_V 0x004
35#define AUXADC_CON1_SET_V 0x008
36#define AUXADC_CON1_CLR_V 0x00c
37#define AUXADC_CON2_V 0x010
38#define AUXADC_DATA(channel) (0x14 + (channel) * 4)
39#define AUXADC_MISC_V 0x094
40
41#define AUXADC_CON1_CHANNEL(x) BIT(x)
42
43#define APMIXED_SYS_TS_CON1 0x604
44
45/* Thermal Controller Registers */
46#define TEMP_MONCTL0 0x000
47#define TEMP_MONCTL1 0x004
48#define TEMP_MONCTL2 0x008
49#define TEMP_MONIDET0 0x014
50#define TEMP_MONIDET1 0x018
51#define TEMP_MSRCTL0 0x038
52#define TEMP_AHBPOLL 0x040
53#define TEMP_AHBTO 0x044
54#define TEMP_ADCPNP0 0x048
55#define TEMP_ADCPNP1 0x04c
56#define TEMP_ADCPNP2 0x050
57#define TEMP_ADCPNP3 0x0b4
58
59#define TEMP_ADCMUX 0x054
60#define TEMP_ADCEN 0x060
61#define TEMP_PNPMUXADDR 0x064
62#define TEMP_ADCMUXADDR 0x068
63#define TEMP_ADCENADDR 0x074
64#define TEMP_ADCVALIDADDR 0x078
65#define TEMP_ADCVOLTADDR 0x07c
66#define TEMP_RDCTRL 0x080
67#define TEMP_ADCVALIDMASK 0x084
68#define TEMP_ADCVOLTAGESHIFT 0x088
69#define TEMP_ADCWRITECTRL 0x08c
70#define TEMP_MSR0 0x090
71#define TEMP_MSR1 0x094
72#define TEMP_MSR2 0x098
73#define TEMP_MSR3 0x0B8
74
75#define TEMP_SPARE0 0x0f0
76
77#define PTPCORESEL 0x400
78
79#define TEMP_MONCTL1_PERIOD_UNIT(x) ((x) & 0x3ff)
80
81#define TEMP_MONCTL2_FILTER_INTERVAL(x) (((x) & 0x3ff) << 16)
82#define TEMP_MONCTL2_SENSOR_INTERVAL(x) ((x) & 0x3ff)
83
84#define TEMP_AHBPOLL_ADC_POLL_INTERVAL(x) (x)
85
86#define TEMP_ADCWRITECTRL_ADC_PNP_WRITE BIT(0)
87#define TEMP_ADCWRITECTRL_ADC_MUX_WRITE BIT(1)
88
89#define TEMP_ADCVALIDMASK_VALID_HIGH BIT(5)
90#define TEMP_ADCVALIDMASK_VALID_POS(bit) (bit)
91
92#define MT8173_TS1 0
93#define MT8173_TS2 1
94#define MT8173_TS3 2
95#define MT8173_TS4 3
96#define MT8173_TSABB 4
97
98/* AUXADC channel 11 is used for the temperature sensors */
99#define MT8173_TEMP_AUXADC_CHANNEL 11
100
101/* The total number of temperature sensors in the MT8173 */
102#define MT8173_NUM_SENSORS 5
103
104/* The number of banks in the MT8173 */
105#define MT8173_NUM_ZONES 4
106
107/* The number of sensing points per bank */
108#define MT8173_NUM_SENSORS_PER_ZONE 4
109
110/* Layout of the fuses providing the calibration data */
111#define MT8173_CALIB_BUF0_VALID BIT(0)
112#define MT8173_CALIB_BUF1_ADC_GE(x) (((x) >> 22) & 0x3ff)
113#define MT8173_CALIB_BUF0_VTS_TS1(x) (((x) >> 17) & 0x1ff)
114#define MT8173_CALIB_BUF0_VTS_TS2(x) (((x) >> 8) & 0x1ff)
115#define MT8173_CALIB_BUF1_VTS_TS3(x) (((x) >> 0) & 0x1ff)
116#define MT8173_CALIB_BUF2_VTS_TS4(x) (((x) >> 23) & 0x1ff)
117#define MT8173_CALIB_BUF2_VTS_TSABB(x) (((x) >> 14) & 0x1ff)
118#define MT8173_CALIB_BUF0_DEGC_CALI(x) (((x) >> 1) & 0x3f)
119#define MT8173_CALIB_BUF0_O_SLOPE(x) (((x) >> 26) & 0x3f)
120
121#define THERMAL_NAME "mtk-thermal"
122
123struct mtk_thermal;
124
125struct mtk_thermal_bank {
126 struct mtk_thermal *mt;
127 int id;
128};
129
130struct mtk_thermal {
131 struct device *dev;
132 void __iomem *thermal_base;
133
134 struct clk *clk_peri_therm;
135 struct clk *clk_auxadc;
136
137 struct mtk_thermal_bank banks[MT8173_NUM_ZONES];
138
139 /* lock: for getting and putting banks */
140 struct mutex lock;
141
142 /* Calibration values */
143 s32 adc_ge;
144 s32 degc_cali;
145 s32 o_slope;
146 s32 vts[MT8173_NUM_SENSORS];
147
148 struct thermal_zone_device *tzd;
149};
150
151struct mtk_thermal_bank_cfg {
152 unsigned int num_sensors;
153 unsigned int sensors[MT8173_NUM_SENSORS_PER_ZONE];
154};
155
156static const int sensor_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 };
157
158/*
159 * The MT8173 thermal controller has four banks. Each bank can read up to
160 * four temperature sensors simultaneously. The MT8173 has a total of 5
161 * temperature sensors. We use each bank to measure a certain area of the
162 * SoC. Since TS2 is located centrally in the SoC it is influenced by multiple
163 * areas, hence is used in different banks.
164 *
165 * The thermal core only gets the maximum temperature of all banks, so
166 * the bank concept wouldn't be necessary here. However, the SVS (Smart
167 * Voltage Scaling) unit makes its decisions based on the same bank
168 * data, and this indeed needs the temperatures of the individual banks
169 * for making better decisions.
170 */
171static const struct mtk_thermal_bank_cfg bank_data[] = {
172 {
173 .num_sensors = 2,
174 .sensors = { MT8173_TS2, MT8173_TS3 },
175 }, {
176 .num_sensors = 2,
177 .sensors = { MT8173_TS2, MT8173_TS4 },
178 }, {
179 .num_sensors = 3,
180 .sensors = { MT8173_TS1, MT8173_TS2, MT8173_TSABB },
181 }, {
182 .num_sensors = 1,
183 .sensors = { MT8173_TS2 },
184 },
185};
186
187struct mtk_thermal_sense_point {
188 int msr;
189 int adcpnp;
190};
191
192static const struct mtk_thermal_sense_point
193 sensing_points[MT8173_NUM_SENSORS_PER_ZONE] = {
194 {
195 .msr = TEMP_MSR0,
196 .adcpnp = TEMP_ADCPNP0,
197 }, {
198 .msr = TEMP_MSR1,
199 .adcpnp = TEMP_ADCPNP1,
200 }, {
201 .msr = TEMP_MSR2,
202 .adcpnp = TEMP_ADCPNP2,
203 }, {
204 .msr = TEMP_MSR3,
205 .adcpnp = TEMP_ADCPNP3,
206 },
207};
208
209/**
210 * raw_to_mcelsius - convert a raw ADC value to mcelsius
211 * @mt: The thermal controller
212 * @raw: raw ADC value
213 *
214 * This converts the raw ADC value to mcelsius using the SoC specific
215 * calibration constants
216 */
217static int raw_to_mcelsius(struct mtk_thermal *mt, int sensno, s32 raw)
218{
219 s32 tmp;
220
221 raw &= 0xfff;
222
223 tmp = 203450520 << 3;
224 tmp /= 165 + mt->o_slope;
225 tmp /= 10000 + mt->adc_ge;
226 tmp *= raw - mt->vts[sensno] - 3350;
227 tmp >>= 3;
228
229 return mt->degc_cali * 500 - tmp;
230}
231
232/**
233 * mtk_thermal_get_bank - get bank
234 * @bank: The bank
235 *
236 * The bank registers are banked, we have to select a bank in the
237 * PTPCORESEL register to access it.
238 */
239static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank)
240{
241 struct mtk_thermal *mt = bank->mt;
242 u32 val;
243
244 mutex_lock(&mt->lock);
245
246 val = readl(mt->thermal_base + PTPCORESEL);
247 val &= ~0xf;
248 val |= bank->id;
249 writel(val, mt->thermal_base + PTPCORESEL);
250}
251
252/**
253 * mtk_thermal_put_bank - release bank
254 * @bank: The bank
255 *
256 * release a bank previously taken with mtk_thermal_get_bank,
257 */
258static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
259{
260 struct mtk_thermal *mt = bank->mt;
261
262 mutex_unlock(&mt->lock);
263}
264
265/**
266 * mtk_thermal_bank_temperature - get the temperature of a bank
267 * @bank: The bank
268 *
269 * The temperature of a bank is considered the maximum temperature of
270 * the sensors associated to the bank.
271 */
272static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
273{
274 struct mtk_thermal *mt = bank->mt;
275 int i, temp = INT_MIN, max = INT_MIN;
276 u32 raw;
277
278 for (i = 0; i < bank_data[bank->id].num_sensors; i++) {
279 raw = readl(mt->thermal_base + sensing_points[i].msr);
280
281 temp = raw_to_mcelsius(mt, bank_data[bank->id].sensors[i], raw);
282
283 /*
284 * The first read of a sensor often contains very high bogus
285 * temperature value. Filter these out so that the system does
286 * not immediately shut down.
287 */
288 if (temp > 200000)
289 temp = 0;
290
291 if (temp > max)
292 max = temp;
293 }
294
295 return max;
296}
297
298static int mtk_read_temp(void *data, int *temperature)
299{
300 struct mtk_thermal *mt = data;
301 int i;
302 int tempmax = INT_MIN;
303
304 for (i = 0; i < MT8173_NUM_ZONES; i++) {
305 struct mtk_thermal_bank *bank = &mt->banks[i];
306
307 mtk_thermal_get_bank(bank);
308
309 tempmax = max(tempmax, mtk_thermal_bank_temperature(bank));
310
311 mtk_thermal_put_bank(bank);
312 }
313
314 *temperature = tempmax;
315
316 return 0;
317}
318
319static const struct thermal_zone_of_device_ops mtk_thermal_ops = {
320 .get_temp = mtk_read_temp,
321};
322
323static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
324 u32 apmixed_phys_base, u32 auxadc_phys_base)
325{
326 struct mtk_thermal_bank *bank = &mt->banks[num];
327 const struct mtk_thermal_bank_cfg *cfg = &bank_data[num];
328 int i;
329
330 bank->id = num;
331 bank->mt = mt;
332
333 mtk_thermal_get_bank(bank);
334
335 /* bus clock 66M counting unit is 12 * 15.15ns * 256 = 46.540us */
336 writel(TEMP_MONCTL1_PERIOD_UNIT(12), mt->thermal_base + TEMP_MONCTL1);
337
338 /*
339 * filt interval is 1 * 46.540us = 46.54us,
340 * sen interval is 429 * 46.540us = 19.96ms
341 */
342 writel(TEMP_MONCTL2_FILTER_INTERVAL(1) |
343 TEMP_MONCTL2_SENSOR_INTERVAL(429),
344 mt->thermal_base + TEMP_MONCTL2);
345
346 /* poll is set to 10u */
347 writel(TEMP_AHBPOLL_ADC_POLL_INTERVAL(768),
348 mt->thermal_base + TEMP_AHBPOLL);
349
350 /* temperature sampling control, 1 sample */
351 writel(0x0, mt->thermal_base + TEMP_MSRCTL0);
352
353 /* exceed this polling time, IRQ would be inserted */
354 writel(0xffffffff, mt->thermal_base + TEMP_AHBTO);
355
356 /* number of interrupts per event, 1 is enough */
357 writel(0x0, mt->thermal_base + TEMP_MONIDET0);
358 writel(0x0, mt->thermal_base + TEMP_MONIDET1);
359
360 /*
361 * The MT8173 thermal controller does not have its own ADC. Instead it
362 * uses AHB bus accesses to control the AUXADC. To do this the thermal
363 * controller has to be programmed with the physical addresses of the
364 * AUXADC registers and with the various bit positions in the AUXADC.
365 * Also the thermal controller controls a mux in the APMIXEDSYS register
366 * space.
367 */
368
369 /*
370 * this value will be stored to TEMP_PNPMUXADDR (TEMP_SPARE0)
371 * automatically by hw
372 */
373 writel(BIT(MT8173_TEMP_AUXADC_CHANNEL), mt->thermal_base + TEMP_ADCMUX);
374
375 /* AHB address for auxadc mux selection */
376 writel(auxadc_phys_base + AUXADC_CON1_CLR_V,
377 mt->thermal_base + TEMP_ADCMUXADDR);
378
379 /* AHB address for pnp sensor mux selection */
380 writel(apmixed_phys_base + APMIXED_SYS_TS_CON1,
381 mt->thermal_base + TEMP_PNPMUXADDR);
382
383 /* AHB value for auxadc enable */
384 writel(BIT(MT8173_TEMP_AUXADC_CHANNEL), mt->thermal_base + TEMP_ADCEN);
385
386 /* AHB address for auxadc enable (channel 0 immediate mode selected) */
387 writel(auxadc_phys_base + AUXADC_CON1_SET_V,
388 mt->thermal_base + TEMP_ADCENADDR);
389
390 /* AHB address for auxadc valid bit */
391 writel(auxadc_phys_base + AUXADC_DATA(MT8173_TEMP_AUXADC_CHANNEL),
392 mt->thermal_base + TEMP_ADCVALIDADDR);
393
394 /* AHB address for auxadc voltage output */
395 writel(auxadc_phys_base + AUXADC_DATA(MT8173_TEMP_AUXADC_CHANNEL),
396 mt->thermal_base + TEMP_ADCVOLTADDR);
397
398 /* read valid & voltage are at the same register */
399 writel(0x0, mt->thermal_base + TEMP_RDCTRL);
400
401 /* indicate where the valid bit is */
402 writel(TEMP_ADCVALIDMASK_VALID_HIGH | TEMP_ADCVALIDMASK_VALID_POS(12),
403 mt->thermal_base + TEMP_ADCVALIDMASK);
404
405 /* no shift */
406 writel(0x0, mt->thermal_base + TEMP_ADCVOLTAGESHIFT);
407
408 /* enable auxadc mux write transaction */
409 writel(TEMP_ADCWRITECTRL_ADC_MUX_WRITE,
410 mt->thermal_base + TEMP_ADCWRITECTRL);
411
412 for (i = 0; i < cfg->num_sensors; i++)
413 writel(sensor_mux_values[cfg->sensors[i]],
414 mt->thermal_base + sensing_points[i].adcpnp);
415
416 writel((1 << cfg->num_sensors) - 1, mt->thermal_base + TEMP_MONCTL0);
417
418 writel(TEMP_ADCWRITECTRL_ADC_PNP_WRITE |
419 TEMP_ADCWRITECTRL_ADC_MUX_WRITE,
420 mt->thermal_base + TEMP_ADCWRITECTRL);
421
422 mtk_thermal_put_bank(bank);
423}
424
425static u64 of_get_phys_base(struct device_node *np)
426{
427 u64 size64;
428 const __be32 *regaddr_p;
429
430 regaddr_p = of_get_address(np, 0, &size64, NULL);
431 if (!regaddr_p)
432 return OF_BAD_ADDR;
433
434 return of_translate_address(np, regaddr_p);
435}
436
437static int mtk_thermal_get_calibration_data(struct device *dev,
438 struct mtk_thermal *mt)
439{
440 struct nvmem_cell *cell;
441 u32 *buf;
442 size_t len;
443 int i, ret = 0;
444
445 /* Start with default values */
446 mt->adc_ge = 512;
447 for (i = 0; i < MT8173_NUM_SENSORS; i++)
448 mt->vts[i] = 260;
449 mt->degc_cali = 40;
450 mt->o_slope = 0;
451
452 cell = nvmem_cell_get(dev, "calibration-data");
453 if (IS_ERR(cell)) {
454 if (PTR_ERR(cell) == -EPROBE_DEFER)
455 return PTR_ERR(cell);
456 return 0;
457 }
458
459 buf = (u32 *)nvmem_cell_read(cell, &len);
460
461 nvmem_cell_put(cell);
462
463 if (IS_ERR(buf))
464 return PTR_ERR(buf);
465
466 if (len < 3 * sizeof(u32)) {
467 dev_warn(dev, "invalid calibration data\n");
468 ret = -EINVAL;
469 goto out;
470 }
471
472 if (buf[0] & MT8173_CALIB_BUF0_VALID) {
473 mt->adc_ge = MT8173_CALIB_BUF1_ADC_GE(buf[1]);
474 mt->vts[MT8173_TS1] = MT8173_CALIB_BUF0_VTS_TS1(buf[0]);
475 mt->vts[MT8173_TS2] = MT8173_CALIB_BUF0_VTS_TS2(buf[0]);
476 mt->vts[MT8173_TS3] = MT8173_CALIB_BUF1_VTS_TS3(buf[1]);
477 mt->vts[MT8173_TS4] = MT8173_CALIB_BUF2_VTS_TS4(buf[2]);
478 mt->vts[MT8173_TSABB] = MT8173_CALIB_BUF2_VTS_TSABB(buf[2]);
479 mt->degc_cali = MT8173_CALIB_BUF0_DEGC_CALI(buf[0]);
480 mt->o_slope = MT8173_CALIB_BUF0_O_SLOPE(buf[0]);
481 } else {
482 dev_info(dev, "Device not calibrated, using default calibration values\n");
483 }
484
485out:
486 kfree(buf);
487
488 return ret;
489}
490
491static int mtk_thermal_probe(struct platform_device *pdev)
492{
493 int ret, i;
494 struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
495 struct mtk_thermal *mt;
496 struct resource *res;
497 u64 auxadc_phys_base, apmixed_phys_base;
498
499 mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
500 if (!mt)
501 return -ENOMEM;
502
503 mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm");
504 if (IS_ERR(mt->clk_peri_therm))
505 return PTR_ERR(mt->clk_peri_therm);
506
507 mt->clk_auxadc = devm_clk_get(&pdev->dev, "auxadc");
508 if (IS_ERR(mt->clk_auxadc))
509 return PTR_ERR(mt->clk_auxadc);
510
511 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
512 mt->thermal_base = devm_ioremap_resource(&pdev->dev, res);
513 if (IS_ERR(mt->thermal_base))
514 return PTR_ERR(mt->thermal_base);
515
516 ret = mtk_thermal_get_calibration_data(&pdev->dev, mt);
517 if (ret)
518 return ret;
519
520 mutex_init(&mt->lock);
521
522 mt->dev = &pdev->dev;
523
524 auxadc = of_parse_phandle(np, "mediatek,auxadc", 0);
525 if (!auxadc) {
526 dev_err(&pdev->dev, "missing auxadc node\n");
527 return -ENODEV;
528 }
529
530 auxadc_phys_base = of_get_phys_base(auxadc);
531
532 of_node_put(auxadc);
533
534 if (auxadc_phys_base == OF_BAD_ADDR) {
535 dev_err(&pdev->dev, "Can't get auxadc phys address\n");
536 return -EINVAL;
537 }
538
539 apmixedsys = of_parse_phandle(np, "mediatek,apmixedsys", 0);
540 if (!apmixedsys) {
541 dev_err(&pdev->dev, "missing apmixedsys node\n");
542 return -ENODEV;
543 }
544
545 apmixed_phys_base = of_get_phys_base(apmixedsys);
546
547 of_node_put(apmixedsys);
548
549 if (apmixed_phys_base == OF_BAD_ADDR) {
550 dev_err(&pdev->dev, "Can't get auxadc phys address\n");
551 return -EINVAL;
552 }
553
554 ret = clk_prepare_enable(mt->clk_auxadc);
555 if (ret) {
556 dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
557 return ret;
558 }
559
560 ret = device_reset(&pdev->dev);
561 if (ret)
562 goto err_disable_clk_auxadc;
563
564 ret = clk_prepare_enable(mt->clk_peri_therm);
565 if (ret) {
566 dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
567 goto err_disable_clk_auxadc;
568 }
569
570 for (i = 0; i < MT8173_NUM_ZONES; i++)
571 mtk_thermal_init_bank(mt, i, apmixed_phys_base,
572 auxadc_phys_base);
573
574 platform_set_drvdata(pdev, mt);
575
576 mt->tzd = thermal_zone_of_sensor_register(&pdev->dev, 0, mt,
577 &mtk_thermal_ops);
578 if (IS_ERR(mt->tzd))
579 goto err_register;
580
581 return 0;
582
583err_register:
584 clk_disable_unprepare(mt->clk_peri_therm);
585
586err_disable_clk_auxadc:
587 clk_disable_unprepare(mt->clk_auxadc);
588
589 return ret;
590}
591
592static int mtk_thermal_remove(struct platform_device *pdev)
593{
594 struct mtk_thermal *mt = platform_get_drvdata(pdev);
595
596 thermal_zone_of_sensor_unregister(&pdev->dev, mt->tzd);
597
598 clk_disable_unprepare(mt->clk_peri_therm);
599 clk_disable_unprepare(mt->clk_auxadc);
600
601 return 0;
602}
603
604static const struct of_device_id mtk_thermal_of_match[] = {
605 {
606 .compatible = "mediatek,mt8173-thermal",
607 }, {
608 },
609};
610
611static struct platform_driver mtk_thermal_driver = {
612 .probe = mtk_thermal_probe,
613 .remove = mtk_thermal_remove,
614 .driver = {
615 .name = THERMAL_NAME,
616 .of_match_table = mtk_thermal_of_match,
617 },
618};
619
620module_platform_driver(mtk_thermal_driver);
621
622MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
623MODULE_AUTHOR("Hanyi Wu <hanyi.wu@mediatek.com>");
624MODULE_DESCRIPTION("Mediatek thermal driver");
625MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index 9043f8f91852..49ac23d3e776 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -555,6 +555,87 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
555} 555}
556EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister); 556EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister);
557 557
558static void devm_thermal_zone_of_sensor_release(struct device *dev, void *res)
559{
560 thermal_zone_of_sensor_unregister(dev,
561 *(struct thermal_zone_device **)res);
562}
563
564static int devm_thermal_zone_of_sensor_match(struct device *dev, void *res,
565 void *data)
566{
567 struct thermal_zone_device **r = res;
568
569 if (WARN_ON(!r || !*r))
570 return 0;
571
572 return *r == data;
573}
574
575/**
576 * devm_thermal_zone_of_sensor_register - Resource managed version of
577 * thermal_zone_of_sensor_register()
578 * @dev: a valid struct device pointer of a sensor device. Must contain
579 * a valid .of_node, for the sensor node.
580 * @sensor_id: a sensor identifier, in case the sensor IP has more
581 * than one sensors
582 * @data: a private pointer (owned by the caller) that will be passed
583 * back, when a temperature reading is needed.
584 * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
585 *
586 * Refer thermal_zone_of_sensor_register() for more details.
587 *
588 * Return: On success returns a valid struct thermal_zone_device,
589 * otherwise, it returns a corresponding ERR_PTR(). Caller must
590 * check the return value with help of IS_ERR() helper.
591 * Registered hermal_zone_device device will automatically be
592 * released when device is unbounded.
593 */
594struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
595 struct device *dev, int sensor_id,
596 void *data, const struct thermal_zone_of_device_ops *ops)
597{
598 struct thermal_zone_device **ptr, *tzd;
599
600 ptr = devres_alloc(devm_thermal_zone_of_sensor_release, sizeof(*ptr),
601 GFP_KERNEL);
602 if (!ptr)
603 return ERR_PTR(-ENOMEM);
604
605 tzd = thermal_zone_of_sensor_register(dev, sensor_id, data, ops);
606 if (IS_ERR(tzd)) {
607 devres_free(ptr);
608 return tzd;
609 }
610
611 *ptr = tzd;
612 devres_add(dev, ptr);
613
614 return tzd;
615}
616EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_register);
617
618/**
619 * devm_thermal_zone_of_sensor_unregister - Resource managed version of
620 * thermal_zone_of_sensor_unregister().
621 * @dev: Device for which which resource was allocated.
622 * @tzd: a pointer to struct thermal_zone_device where the sensor is registered.
623 *
624 * This function removes the sensor callbacks and private data from the
625 * thermal zone device registered with devm_thermal_zone_of_sensor_register()
626 * API. It will also silent the zone by remove the .get_temp() and .get_trend()
627 * thermal zone device callbacks.
628 * Normally this function will not need to be called and the resource
629 * management code will ensure that the resource is freed.
630 */
631void devm_thermal_zone_of_sensor_unregister(struct device *dev,
632 struct thermal_zone_device *tzd)
633{
634 WARN_ON(devres_release(dev, devm_thermal_zone_of_sensor_release,
635 devm_thermal_zone_of_sensor_match, tzd));
636}
637EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_unregister);
638
558/*** functions parsing device tree nodes ***/ 639/*** functions parsing device tree nodes ***/
559 640
560/** 641/**
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index e13a1ace50e9..9c481991fdc7 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -362,6 +362,11 @@ thermal_zone_of_sensor_register(struct device *dev, int id, void *data,
362 const struct thermal_zone_of_device_ops *ops); 362 const struct thermal_zone_of_device_ops *ops);
363void thermal_zone_of_sensor_unregister(struct device *dev, 363void thermal_zone_of_sensor_unregister(struct device *dev,
364 struct thermal_zone_device *tz); 364 struct thermal_zone_device *tz);
365struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
366 struct device *dev, int id, void *data,
367 const struct thermal_zone_of_device_ops *ops);
368void devm_thermal_zone_of_sensor_unregister(struct device *dev,
369 struct thermal_zone_device *tz);
365#else 370#else
366static inline struct thermal_zone_device * 371static inline struct thermal_zone_device *
367thermal_zone_of_sensor_register(struct device *dev, int id, void *data, 372thermal_zone_of_sensor_register(struct device *dev, int id, void *data,
@@ -376,6 +381,19 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
376{ 381{
377} 382}
378 383
384static inline struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
385 struct device *dev, int id, void *data,
386 const struct thermal_zone_of_device_ops *ops)
387{
388 return ERR_PTR(-ENODEV);
389}
390
391static inline
392void devm_thermal_zone_of_sensor_unregister(struct device *dev,
393 struct thermal_zone_device *tz)
394{
395}
396
379#endif 397#endif
380 398
381#if IS_ENABLED(CONFIG_THERMAL) 399#if IS_ENABLED(CONFIG_THERMAL)