12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2cbac8f63SCaesar Wang /*
3678065d5SCaesar Wang * Copyright (c) 2014-2016, Fuzhou Rockchip Electronics Co., Ltd
420f0af75SCaesar Wang * Caesar Wang <wxt@rock-chips.com>
5cbac8f63SCaesar Wang */
6cbac8f63SCaesar Wang
7cbac8f63SCaesar Wang #include <linux/clk.h>
8cbac8f63SCaesar Wang #include <linux/delay.h>
9cbac8f63SCaesar Wang #include <linux/interrupt.h>
10cbac8f63SCaesar Wang #include <linux/io.h>
11cbac8f63SCaesar Wang #include <linux/module.h>
12cbac8f63SCaesar Wang #include <linux/of.h>
13cbac8f63SCaesar Wang #include <linux/of_address.h>
14cbac8f63SCaesar Wang #include <linux/of_irq.h>
15cbac8f63SCaesar Wang #include <linux/platform_device.h>
16b9484763SCaesar Wang #include <linux/regmap.h>
17cbac8f63SCaesar Wang #include <linux/reset.h>
18cbac8f63SCaesar Wang #include <linux/thermal.h>
19b9484763SCaesar Wang #include <linux/mfd/syscon.h>
20c970872eSCaesar Wang #include <linux/pinctrl/consumer.h>
21cbac8f63SCaesar Wang
2266ec4bfcSAmit Kucheria /*
23cbac8f63SCaesar Wang * If the temperature over a period of time High,
24cbac8f63SCaesar Wang * the resulting TSHUT gave CRU module,let it reset the entire chip,
25cbac8f63SCaesar Wang * or via GPIO give PMIC.
26cbac8f63SCaesar Wang */
27cbac8f63SCaesar Wang enum tshut_mode {
28cbac8f63SCaesar Wang TSHUT_MODE_CRU = 0,
29cbac8f63SCaesar Wang TSHUT_MODE_GPIO,
30cbac8f63SCaesar Wang };
31cbac8f63SCaesar Wang
3266ec4bfcSAmit Kucheria /*
3313c1cfdaSCaesar Wang * The system Temperature Sensors tshut(tshut) polarity
34cbac8f63SCaesar Wang * the bit 8 is tshut polarity.
35cbac8f63SCaesar Wang * 0: low active, 1: high active
36cbac8f63SCaesar Wang */
37cbac8f63SCaesar Wang enum tshut_polarity {
38cbac8f63SCaesar Wang TSHUT_LOW_ACTIVE = 0,
39cbac8f63SCaesar Wang TSHUT_HIGH_ACTIVE,
40cbac8f63SCaesar Wang };
41cbac8f63SCaesar Wang
4266ec4bfcSAmit Kucheria /*
43020ba95dSCaesar Wang * The conversion table has the adc value and temperature.
44952418a3SCaesar Wang * ADC_DECREMENT: the adc value is of diminishing.(e.g. rk3288_code_table)
45952418a3SCaesar Wang * ADC_INCREMENT: the adc value is incremental.(e.g. rk3368_code_table)
46020ba95dSCaesar Wang */
47020ba95dSCaesar Wang enum adc_sort_mode {
48020ba95dSCaesar Wang ADC_DECREMENT = 0,
49020ba95dSCaesar Wang ADC_INCREMENT,
50020ba95dSCaesar Wang };
51020ba95dSCaesar Wang
52d27970b8SStefan Schaeckeler #include "thermal_hwmon.h"
53d27970b8SStefan Schaeckeler
5413c1cfdaSCaesar Wang /**
55678065d5SCaesar Wang * struct chip_tsadc_table - hold information about chip-specific differences
5613c1cfdaSCaesar Wang * @id: conversion table
5713c1cfdaSCaesar Wang * @length: size of conversion table
5813c1cfdaSCaesar Wang * @data_mask: mask to apply on data inputs
5913c1cfdaSCaesar Wang * @mode: sort mode of this adc variant (incrementing or decrementing)
6013c1cfdaSCaesar Wang */
61ce74110dSCaesar Wang struct chip_tsadc_table {
62ce74110dSCaesar Wang const struct tsadc_table *id;
63ce74110dSCaesar Wang unsigned int length;
64ce74110dSCaesar Wang u32 data_mask;
65020ba95dSCaesar Wang enum adc_sort_mode mode;
66ce74110dSCaesar Wang };
67ce74110dSCaesar Wang
68678065d5SCaesar Wang /**
69678065d5SCaesar Wang * struct rockchip_tsadc_chip - hold the private data of tsadc chip
70f7cef1b7SSebastian Reichel * @chn_offset: the channel offset of the first channel
71678065d5SCaesar Wang * @chn_num: the channel number of tsadc chip
72678065d5SCaesar Wang * @tshut_temp: the hardware-controlled shutdown temperature value
73678065d5SCaesar Wang * @tshut_mode: the hardware-controlled shutdown mode (0:CRU 1:GPIO)
74678065d5SCaesar Wang * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
75678065d5SCaesar Wang * @initialize: SoC special initialize tsadc controller method
76678065d5SCaesar Wang * @irq_ack: clear the interrupt
7766ec4bfcSAmit Kucheria * @control: enable/disable method for the tsadc controller
78678065d5SCaesar Wang * @get_temp: get the temperature
7914848502SCaesar Wang * @set_alarm_temp: set the high temperature interrupt
80678065d5SCaesar Wang * @set_tshut_temp: set the hardware-controlled shutdown temperature
81678065d5SCaesar Wang * @set_tshut_mode: set the hardware-controlled shutdown mode
82678065d5SCaesar Wang * @table: the chip-specific conversion table
83678065d5SCaesar Wang */
84cbac8f63SCaesar Wang struct rockchip_tsadc_chip {
851d98b618SCaesar Wang /* The sensor id of chip correspond to the ADC channel */
86f7cef1b7SSebastian Reichel int chn_offset;
871d98b618SCaesar Wang int chn_num;
881d98b618SCaesar Wang
89cbac8f63SCaesar Wang /* The hardware-controlled tshut property */
90437df217SCaesar Wang int tshut_temp;
91cbac8f63SCaesar Wang enum tshut_mode tshut_mode;
92cbac8f63SCaesar Wang enum tshut_polarity tshut_polarity;
93cbac8f63SCaesar Wang
94cbac8f63SCaesar Wang /* Chip-wide methods */
95b9484763SCaesar Wang void (*initialize)(struct regmap *grf,
96b9484763SCaesar Wang void __iomem *reg, enum tshut_polarity p);
97cbac8f63SCaesar Wang void (*irq_ack)(void __iomem *reg);
98cbac8f63SCaesar Wang void (*control)(void __iomem *reg, bool on);
99cbac8f63SCaesar Wang
100cbac8f63SCaesar Wang /* Per-sensor methods */
101cdd8b3f7SBrian Norris int (*get_temp)(const struct chip_tsadc_table *table,
102ce74110dSCaesar Wang int chn, void __iomem *reg, int *temp);
103d3530497SCaesar Wang int (*set_alarm_temp)(const struct chip_tsadc_table *table,
10414848502SCaesar Wang int chn, void __iomem *reg, int temp);
105d3530497SCaesar Wang int (*set_tshut_temp)(const struct chip_tsadc_table *table,
106437df217SCaesar Wang int chn, void __iomem *reg, int temp);
107cbac8f63SCaesar Wang void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
108ce74110dSCaesar Wang
109ce74110dSCaesar Wang /* Per-table methods */
110ce74110dSCaesar Wang struct chip_tsadc_table table;
111cbac8f63SCaesar Wang };
112cbac8f63SCaesar Wang
113678065d5SCaesar Wang /**
114678065d5SCaesar Wang * struct rockchip_thermal_sensor - hold the information of thermal sensor
115678065d5SCaesar Wang * @thermal: pointer to the platform/configuration data
116678065d5SCaesar Wang * @tzd: pointer to a thermal zone
117678065d5SCaesar Wang * @id: identifier of the thermal sensor
118678065d5SCaesar Wang */
119cbac8f63SCaesar Wang struct rockchip_thermal_sensor {
120cbac8f63SCaesar Wang struct rockchip_thermal_data *thermal;
121cbac8f63SCaesar Wang struct thermal_zone_device *tzd;
1221d98b618SCaesar Wang int id;
123cbac8f63SCaesar Wang };
124cbac8f63SCaesar Wang
125678065d5SCaesar Wang /**
126678065d5SCaesar Wang * struct rockchip_thermal_data - hold the private data of thermal driver
127678065d5SCaesar Wang * @chip: pointer to the platform/configuration data
128678065d5SCaesar Wang * @pdev: platform device of thermal
129678065d5SCaesar Wang * @reset: the reset controller of tsadc
13066ec4bfcSAmit Kucheria * @sensors: array of thermal sensors
131678065d5SCaesar Wang * @clk: the controller clock is divided by the exteral 24MHz
132678065d5SCaesar Wang * @pclk: the advanced peripherals bus clock
133678065d5SCaesar Wang * @grf: the general register file will be used to do static set by software
134678065d5SCaesar Wang * @regs: the base address of tsadc controller
135678065d5SCaesar Wang * @tshut_temp: the hardware-controlled shutdown temperature value
136678065d5SCaesar Wang * @tshut_mode: the hardware-controlled shutdown mode (0:CRU 1:GPIO)
137678065d5SCaesar Wang * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
138678065d5SCaesar Wang */
139cbac8f63SCaesar Wang struct rockchip_thermal_data {
140cbac8f63SCaesar Wang const struct rockchip_tsadc_chip *chip;
141cbac8f63SCaesar Wang struct platform_device *pdev;
142cbac8f63SCaesar Wang struct reset_control *reset;
143cbac8f63SCaesar Wang
144267f5965SSebastian Reichel struct rockchip_thermal_sensor *sensors;
145cbac8f63SCaesar Wang
146cbac8f63SCaesar Wang struct clk *clk;
147cbac8f63SCaesar Wang struct clk *pclk;
148cbac8f63SCaesar Wang
149b9484763SCaesar Wang struct regmap *grf;
150cbac8f63SCaesar Wang void __iomem *regs;
151cbac8f63SCaesar Wang
152437df217SCaesar Wang int tshut_temp;
153cbac8f63SCaesar Wang enum tshut_mode tshut_mode;
154cbac8f63SCaesar Wang enum tshut_polarity tshut_polarity;
155cbac8f63SCaesar Wang };
156cbac8f63SCaesar Wang
1576d5dad7bSRandy Dunlap /*
158952418a3SCaesar Wang * TSADC Sensor Register description:
159952418a3SCaesar Wang *
160952418a3SCaesar Wang * TSADCV2_* are used for RK3288 SoCs, the other chips can reuse it.
161952418a3SCaesar Wang * TSADCV3_* are used for newer SoCs than RK3288. (e.g: RK3228, RK3399)
162952418a3SCaesar Wang *
163952418a3SCaesar Wang */
164b9484763SCaesar Wang #define TSADCV2_USER_CON 0x00
165cbac8f63SCaesar Wang #define TSADCV2_AUTO_CON 0x04
166cbac8f63SCaesar Wang #define TSADCV2_INT_EN 0x08
167cbac8f63SCaesar Wang #define TSADCV2_INT_PD 0x0c
16845d7b386SFinley Xiao #define TSADCV3_AUTO_SRC_CON 0x0c
16945d7b386SFinley Xiao #define TSADCV3_HT_INT_EN 0x14
17045d7b386SFinley Xiao #define TSADCV3_HSHUT_GPIO_INT_EN 0x18
17145d7b386SFinley Xiao #define TSADCV3_HSHUT_CRU_INT_EN 0x1c
17245d7b386SFinley Xiao #define TSADCV3_INT_PD 0x24
17345d7b386SFinley Xiao #define TSADCV3_HSHUT_PD 0x28
174cbac8f63SCaesar Wang #define TSADCV2_DATA(chn) (0x20 + (chn) * 0x04)
17514848502SCaesar Wang #define TSADCV2_COMP_INT(chn) (0x30 + (chn) * 0x04)
176cbac8f63SCaesar Wang #define TSADCV2_COMP_SHUT(chn) (0x40 + (chn) * 0x04)
17745d7b386SFinley Xiao #define TSADCV3_DATA(chn) (0x2c + (chn) * 0x04)
17845d7b386SFinley Xiao #define TSADCV3_COMP_INT(chn) (0x6c + (chn) * 0x04)
17945d7b386SFinley Xiao #define TSADCV3_COMP_SHUT(chn) (0x10c + (chn) * 0x04)
180cbac8f63SCaesar Wang #define TSADCV2_HIGHT_INT_DEBOUNCE 0x60
181cbac8f63SCaesar Wang #define TSADCV2_HIGHT_TSHUT_DEBOUNCE 0x64
18245d7b386SFinley Xiao #define TSADCV3_HIGHT_INT_DEBOUNCE 0x14c
18345d7b386SFinley Xiao #define TSADCV3_HIGHT_TSHUT_DEBOUNCE 0x150
184cbac8f63SCaesar Wang #define TSADCV2_AUTO_PERIOD 0x68
185cbac8f63SCaesar Wang #define TSADCV2_AUTO_PERIOD_HT 0x6c
18645d7b386SFinley Xiao #define TSADCV3_AUTO_PERIOD 0x154
18745d7b386SFinley Xiao #define TSADCV3_AUTO_PERIOD_HT 0x158
188cbac8f63SCaesar Wang
189cbac8f63SCaesar Wang #define TSADCV2_AUTO_EN BIT(0)
19045d7b386SFinley Xiao #define TSADCV2_AUTO_EN_MASK BIT(16)
191cbac8f63SCaesar Wang #define TSADCV2_AUTO_SRC_EN(chn) BIT(4 + (chn))
19245d7b386SFinley Xiao #define TSADCV3_AUTO_SRC_EN(chn) BIT(chn)
19345d7b386SFinley Xiao #define TSADCV3_AUTO_SRC_EN_MASK(chn) BIT(16 + chn)
194cbac8f63SCaesar Wang #define TSADCV2_AUTO_TSHUT_POLARITY_HIGH BIT(8)
19545d7b386SFinley Xiao #define TSADCV2_AUTO_TSHUT_POLARITY_MASK BIT(24)
196678065d5SCaesar Wang
1977ea38c6cSCaesar Wang #define TSADCV3_AUTO_Q_SEL_EN BIT(1)
198cbac8f63SCaesar Wang
199cbac8f63SCaesar Wang #define TSADCV2_INT_SRC_EN(chn) BIT(chn)
20045d7b386SFinley Xiao #define TSADCV2_INT_SRC_EN_MASK(chn) BIT(16 + (chn))
201cbac8f63SCaesar Wang #define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn))
202cbac8f63SCaesar Wang #define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn))
203cbac8f63SCaesar Wang
204452e01b3SDmitry Torokhov #define TSADCV2_INT_PD_CLEAR_MASK ~BIT(8)
205952418a3SCaesar Wang #define TSADCV3_INT_PD_CLEAR_MASK ~BIT(16)
20645d7b386SFinley Xiao #define TSADCV4_INT_PD_CLEAR_MASK 0xffffffff
207cbac8f63SCaesar Wang
208cbac8f63SCaesar Wang #define TSADCV2_DATA_MASK 0xfff
20920f0af75SCaesar Wang #define TSADCV3_DATA_MASK 0x3ff
21045d7b386SFinley Xiao #define TSADCV4_DATA_MASK 0x1ff
21120f0af75SCaesar Wang
212cbac8f63SCaesar Wang #define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT 4
213cbac8f63SCaesar Wang #define TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT 4
21446667879SCaesar Wang #define TSADCV2_AUTO_PERIOD_TIME 250 /* 250ms */
21546667879SCaesar Wang #define TSADCV2_AUTO_PERIOD_HT_TIME 50 /* 50ms */
2165ef62de7SRocky Hao #define TSADCV3_AUTO_PERIOD_TIME 1875 /* 2.5ms */
2175ef62de7SRocky Hao #define TSADCV3_AUTO_PERIOD_HT_TIME 1875 /* 2.5ms */
21846667879SCaesar Wang
21916bee043SFinley Xiao #define TSADCV5_AUTO_PERIOD_TIME 1622 /* 2.5ms */
22016bee043SFinley Xiao #define TSADCV5_AUTO_PERIOD_HT_TIME 1622 /* 2.5ms */
22145d7b386SFinley Xiao #define TSADCV6_AUTO_PERIOD_TIME 5000 /* 2.5ms */
22245d7b386SFinley Xiao #define TSADCV6_AUTO_PERIOD_HT_TIME 5000 /* 2.5ms */
22316bee043SFinley Xiao
224b9484763SCaesar Wang #define TSADCV2_USER_INTER_PD_SOC 0x340 /* 13 clocks */
22516bee043SFinley Xiao #define TSADCV5_USER_INTER_PD_SOC 0xfc0 /* 97us, at least 90us */
226b9484763SCaesar Wang
227b9484763SCaesar Wang #define GRF_SARADC_TESTBIT 0x0e644
228b9484763SCaesar Wang #define GRF_TSADC_TESTBIT_L 0x0e648
229b9484763SCaesar Wang #define GRF_TSADC_TESTBIT_H 0x0e64c
230b9484763SCaesar Wang
231ffd1b122SElaine Zhang #define PX30_GRF_SOC_CON2 0x0408
232ffd1b122SElaine Zhang
23316bee043SFinley Xiao #define RK3568_GRF_TSADC_CON 0x0600
23416bee043SFinley Xiao #define RK3568_GRF_TSADC_ANA_REG0 (0x10001 << 0)
23516bee043SFinley Xiao #define RK3568_GRF_TSADC_ANA_REG1 (0x10001 << 1)
23616bee043SFinley Xiao #define RK3568_GRF_TSADC_ANA_REG2 (0x10001 << 2)
23716bee043SFinley Xiao #define RK3568_GRF_TSADC_TSEN (0x10001 << 8)
23816bee043SFinley Xiao
23945d7b386SFinley Xiao #define RK3588_GRF0_TSADC_CON 0x0100
24045d7b386SFinley Xiao
24145d7b386SFinley Xiao #define RK3588_GRF0_TSADC_TRM (0xff0077 << 0)
24245d7b386SFinley Xiao #define RK3588_GRF0_TSADC_SHUT_2CRU (0x30003 << 10)
24345d7b386SFinley Xiao #define RK3588_GRF0_TSADC_SHUT_2GPIO (0x70007 << 12)
24445d7b386SFinley Xiao
245b9484763SCaesar Wang #define GRF_SARADC_TESTBIT_ON (0x10001 << 2)
246b9484763SCaesar Wang #define GRF_TSADC_TESTBIT_H_ON (0x10001 << 2)
24723f75e48SRocky Hao #define GRF_TSADC_VCM_EN_L (0x10001 << 7)
24823f75e48SRocky Hao #define GRF_TSADC_VCM_EN_H (0x10001 << 7)
249cbac8f63SCaesar Wang
250ffd1b122SElaine Zhang #define GRF_CON_TSADC_CH_INV (0x10001 << 1)
251ffd1b122SElaine Zhang
252678065d5SCaesar Wang /**
253678065d5SCaesar Wang * struct tsadc_table - code to temperature conversion table
254678065d5SCaesar Wang * @code: the value of adc channel
255678065d5SCaesar Wang * @temp: the temperature
256678065d5SCaesar Wang * Note:
257678065d5SCaesar Wang * code to temperature mapping of the temperature sensor is a piece wise linear
258678065d5SCaesar Wang * curve.Any temperature, code faling between to 2 give temperatures can be
259678065d5SCaesar Wang * linearly interpolated.
260678065d5SCaesar Wang * Code to Temperature mapping should be updated based on manufacturer results.
261678065d5SCaesar Wang */
262cbac8f63SCaesar Wang struct tsadc_table {
263d9a241cbSDmitry Torokhov u32 code;
264437df217SCaesar Wang int temp;
265cbac8f63SCaesar Wang };
266cbac8f63SCaesar Wang
2674eca8cacSRocky Hao static const struct tsadc_table rv1108_table[] = {
2684eca8cacSRocky Hao {0, -40000},
2694eca8cacSRocky Hao {374, -40000},
2704eca8cacSRocky Hao {382, -35000},
2714eca8cacSRocky Hao {389, -30000},
2724eca8cacSRocky Hao {397, -25000},
2734eca8cacSRocky Hao {405, -20000},
2744eca8cacSRocky Hao {413, -15000},
2754eca8cacSRocky Hao {421, -10000},
2764eca8cacSRocky Hao {429, -5000},
2774eca8cacSRocky Hao {436, 0},
2784eca8cacSRocky Hao {444, 5000},
2794eca8cacSRocky Hao {452, 10000},
2804eca8cacSRocky Hao {460, 15000},
2814eca8cacSRocky Hao {468, 20000},
2824eca8cacSRocky Hao {476, 25000},
2834eca8cacSRocky Hao {483, 30000},
2844eca8cacSRocky Hao {491, 35000},
2854eca8cacSRocky Hao {499, 40000},
2864eca8cacSRocky Hao {507, 45000},
2874eca8cacSRocky Hao {515, 50000},
2884eca8cacSRocky Hao {523, 55000},
2894eca8cacSRocky Hao {531, 60000},
2904eca8cacSRocky Hao {539, 65000},
2914eca8cacSRocky Hao {547, 70000},
2924eca8cacSRocky Hao {555, 75000},
2934eca8cacSRocky Hao {562, 80000},
2944eca8cacSRocky Hao {570, 85000},
2954eca8cacSRocky Hao {578, 90000},
2964eca8cacSRocky Hao {586, 95000},
2974eca8cacSRocky Hao {594, 100000},
2984eca8cacSRocky Hao {602, 105000},
2994eca8cacSRocky Hao {610, 110000},
3004eca8cacSRocky Hao {618, 115000},
3014eca8cacSRocky Hao {626, 120000},
3024eca8cacSRocky Hao {634, 125000},
3034eca8cacSRocky Hao {TSADCV2_DATA_MASK, 125000},
3044eca8cacSRocky Hao };
3054eca8cacSRocky Hao
306952418a3SCaesar Wang static const struct tsadc_table rk3228_code_table[] = {
3077ea38c6cSCaesar Wang {0, -40000},
3087ea38c6cSCaesar Wang {588, -40000},
3097ea38c6cSCaesar Wang {593, -35000},
3107ea38c6cSCaesar Wang {598, -30000},
3117ea38c6cSCaesar Wang {603, -25000},
3127ea38c6cSCaesar Wang {608, -20000},
3137ea38c6cSCaesar Wang {613, -15000},
3147ea38c6cSCaesar Wang {618, -10000},
3157ea38c6cSCaesar Wang {623, -5000},
3167ea38c6cSCaesar Wang {629, 0},
3177ea38c6cSCaesar Wang {634, 5000},
3187ea38c6cSCaesar Wang {639, 10000},
3197ea38c6cSCaesar Wang {644, 15000},
3207ea38c6cSCaesar Wang {649, 20000},
3217ea38c6cSCaesar Wang {654, 25000},
3227ea38c6cSCaesar Wang {660, 30000},
3237ea38c6cSCaesar Wang {665, 35000},
3247ea38c6cSCaesar Wang {670, 40000},
3257ea38c6cSCaesar Wang {675, 45000},
3267ea38c6cSCaesar Wang {681, 50000},
3277ea38c6cSCaesar Wang {686, 55000},
3287ea38c6cSCaesar Wang {691, 60000},
3297ea38c6cSCaesar Wang {696, 65000},
3307ea38c6cSCaesar Wang {702, 70000},
3317ea38c6cSCaesar Wang {707, 75000},
3327ea38c6cSCaesar Wang {712, 80000},
3337ea38c6cSCaesar Wang {717, 85000},
3347ea38c6cSCaesar Wang {723, 90000},
3357ea38c6cSCaesar Wang {728, 95000},
3367ea38c6cSCaesar Wang {733, 100000},
3377ea38c6cSCaesar Wang {738, 105000},
3387ea38c6cSCaesar Wang {744, 110000},
3397ea38c6cSCaesar Wang {749, 115000},
3407ea38c6cSCaesar Wang {754, 120000},
3417ea38c6cSCaesar Wang {760, 125000},
3427ea38c6cSCaesar Wang {TSADCV2_DATA_MASK, 125000},
3437b02a5e7SCaesar Wang };
3447b02a5e7SCaesar Wang
345952418a3SCaesar Wang static const struct tsadc_table rk3288_code_table[] = {
346cbac8f63SCaesar Wang {TSADCV2_DATA_MASK, -40000},
347cbac8f63SCaesar Wang {3800, -40000},
348cbac8f63SCaesar Wang {3792, -35000},
349cbac8f63SCaesar Wang {3783, -30000},
350cbac8f63SCaesar Wang {3774, -25000},
351cbac8f63SCaesar Wang {3765, -20000},
352cbac8f63SCaesar Wang {3756, -15000},
353cbac8f63SCaesar Wang {3747, -10000},
354cbac8f63SCaesar Wang {3737, -5000},
355cbac8f63SCaesar Wang {3728, 0},
356cbac8f63SCaesar Wang {3718, 5000},
357cbac8f63SCaesar Wang {3708, 10000},
358cbac8f63SCaesar Wang {3698, 15000},
359cbac8f63SCaesar Wang {3688, 20000},
360cbac8f63SCaesar Wang {3678, 25000},
361cbac8f63SCaesar Wang {3667, 30000},
362cbac8f63SCaesar Wang {3656, 35000},
363cbac8f63SCaesar Wang {3645, 40000},
364cbac8f63SCaesar Wang {3634, 45000},
365cbac8f63SCaesar Wang {3623, 50000},
366cbac8f63SCaesar Wang {3611, 55000},
367cbac8f63SCaesar Wang {3600, 60000},
368cbac8f63SCaesar Wang {3588, 65000},
369cbac8f63SCaesar Wang {3575, 70000},
370cbac8f63SCaesar Wang {3563, 75000},
371cbac8f63SCaesar Wang {3550, 80000},
372cbac8f63SCaesar Wang {3537, 85000},
373cbac8f63SCaesar Wang {3524, 90000},
374cbac8f63SCaesar Wang {3510, 95000},
375cbac8f63SCaesar Wang {3496, 100000},
376cbac8f63SCaesar Wang {3482, 105000},
377cbac8f63SCaesar Wang {3467, 110000},
378cbac8f63SCaesar Wang {3452, 115000},
379cbac8f63SCaesar Wang {3437, 120000},
380cbac8f63SCaesar Wang {3421, 125000},
381cadf29dcSCaesar Wang {0, 125000},
382cbac8f63SCaesar Wang };
383cbac8f63SCaesar Wang
384eda519d5SRocky Hao static const struct tsadc_table rk3328_code_table[] = {
385eda519d5SRocky Hao {0, -40000},
386eda519d5SRocky Hao {296, -40000},
387eda519d5SRocky Hao {304, -35000},
388eda519d5SRocky Hao {313, -30000},
389eda519d5SRocky Hao {331, -20000},
390eda519d5SRocky Hao {340, -15000},
391eda519d5SRocky Hao {349, -10000},
392eda519d5SRocky Hao {359, -5000},
393eda519d5SRocky Hao {368, 0},
394eda519d5SRocky Hao {378, 5000},
395eda519d5SRocky Hao {388, 10000},
396eda519d5SRocky Hao {398, 15000},
397eda519d5SRocky Hao {408, 20000},
398eda519d5SRocky Hao {418, 25000},
399eda519d5SRocky Hao {429, 30000},
400eda519d5SRocky Hao {440, 35000},
401eda519d5SRocky Hao {451, 40000},
402eda519d5SRocky Hao {462, 45000},
403eda519d5SRocky Hao {473, 50000},
404eda519d5SRocky Hao {485, 55000},
405eda519d5SRocky Hao {496, 60000},
406eda519d5SRocky Hao {508, 65000},
407eda519d5SRocky Hao {521, 70000},
408eda519d5SRocky Hao {533, 75000},
409eda519d5SRocky Hao {546, 80000},
410eda519d5SRocky Hao {559, 85000},
411eda519d5SRocky Hao {572, 90000},
412eda519d5SRocky Hao {586, 95000},
413eda519d5SRocky Hao {600, 100000},
414eda519d5SRocky Hao {614, 105000},
415eda519d5SRocky Hao {629, 110000},
416eda519d5SRocky Hao {644, 115000},
417eda519d5SRocky Hao {659, 120000},
418eda519d5SRocky Hao {675, 125000},
419eda519d5SRocky Hao {TSADCV2_DATA_MASK, 125000},
420eda519d5SRocky Hao };
421eda519d5SRocky Hao
422952418a3SCaesar Wang static const struct tsadc_table rk3368_code_table[] = {
42320f0af75SCaesar Wang {0, -40000},
42420f0af75SCaesar Wang {106, -40000},
42520f0af75SCaesar Wang {108, -35000},
42620f0af75SCaesar Wang {110, -30000},
42720f0af75SCaesar Wang {112, -25000},
42820f0af75SCaesar Wang {114, -20000},
42920f0af75SCaesar Wang {116, -15000},
43020f0af75SCaesar Wang {118, -10000},
43120f0af75SCaesar Wang {120, -5000},
43220f0af75SCaesar Wang {122, 0},
43320f0af75SCaesar Wang {124, 5000},
43420f0af75SCaesar Wang {126, 10000},
43520f0af75SCaesar Wang {128, 15000},
43620f0af75SCaesar Wang {130, 20000},
43720f0af75SCaesar Wang {132, 25000},
43820f0af75SCaesar Wang {134, 30000},
43920f0af75SCaesar Wang {136, 35000},
44020f0af75SCaesar Wang {138, 40000},
44120f0af75SCaesar Wang {140, 45000},
44220f0af75SCaesar Wang {142, 50000},
44320f0af75SCaesar Wang {144, 55000},
44420f0af75SCaesar Wang {146, 60000},
44520f0af75SCaesar Wang {148, 65000},
44620f0af75SCaesar Wang {150, 70000},
44720f0af75SCaesar Wang {152, 75000},
44820f0af75SCaesar Wang {154, 80000},
44920f0af75SCaesar Wang {156, 85000},
45020f0af75SCaesar Wang {158, 90000},
45120f0af75SCaesar Wang {160, 95000},
45220f0af75SCaesar Wang {162, 100000},
45320f0af75SCaesar Wang {163, 105000},
45420f0af75SCaesar Wang {165, 110000},
45520f0af75SCaesar Wang {167, 115000},
45620f0af75SCaesar Wang {169, 120000},
45720f0af75SCaesar Wang {171, 125000},
45820f0af75SCaesar Wang {TSADCV3_DATA_MASK, 125000},
45920f0af75SCaesar Wang };
46020f0af75SCaesar Wang
461952418a3SCaesar Wang static const struct tsadc_table rk3399_code_table[] = {
4627ea38c6cSCaesar Wang {0, -40000},
463f762a35dSCaesar Wang {402, -40000},
464f762a35dSCaesar Wang {410, -35000},
465f762a35dSCaesar Wang {419, -30000},
466f762a35dSCaesar Wang {427, -25000},
467f762a35dSCaesar Wang {436, -20000},
468f762a35dSCaesar Wang {444, -15000},
469f762a35dSCaesar Wang {453, -10000},
470f762a35dSCaesar Wang {461, -5000},
471f762a35dSCaesar Wang {470, 0},
472f762a35dSCaesar Wang {478, 5000},
473f762a35dSCaesar Wang {487, 10000},
474f762a35dSCaesar Wang {496, 15000},
475f762a35dSCaesar Wang {504, 20000},
476f762a35dSCaesar Wang {513, 25000},
477f762a35dSCaesar Wang {521, 30000},
478f762a35dSCaesar Wang {530, 35000},
479f762a35dSCaesar Wang {538, 40000},
480f762a35dSCaesar Wang {547, 45000},
481f762a35dSCaesar Wang {555, 50000},
482f762a35dSCaesar Wang {564, 55000},
483f762a35dSCaesar Wang {573, 60000},
484f762a35dSCaesar Wang {581, 65000},
485f762a35dSCaesar Wang {590, 70000},
486f762a35dSCaesar Wang {599, 75000},
487f762a35dSCaesar Wang {607, 80000},
488f762a35dSCaesar Wang {616, 85000},
489f762a35dSCaesar Wang {624, 90000},
490f762a35dSCaesar Wang {633, 95000},
491f762a35dSCaesar Wang {642, 100000},
492f762a35dSCaesar Wang {650, 105000},
493f762a35dSCaesar Wang {659, 110000},
494f762a35dSCaesar Wang {668, 115000},
495f762a35dSCaesar Wang {677, 120000},
496f762a35dSCaesar Wang {685, 125000},
4977ea38c6cSCaesar Wang {TSADCV3_DATA_MASK, 125000},
498b0d70338SCaesar Wang };
499b0d70338SCaesar Wang
50016bee043SFinley Xiao static const struct tsadc_table rk3568_code_table[] = {
50116bee043SFinley Xiao {0, -40000},
50216bee043SFinley Xiao {1584, -40000},
50316bee043SFinley Xiao {1620, -35000},
50416bee043SFinley Xiao {1652, -30000},
50516bee043SFinley Xiao {1688, -25000},
50616bee043SFinley Xiao {1720, -20000},
50716bee043SFinley Xiao {1756, -15000},
50816bee043SFinley Xiao {1788, -10000},
50916bee043SFinley Xiao {1824, -5000},
51016bee043SFinley Xiao {1856, 0},
51116bee043SFinley Xiao {1892, 5000},
51216bee043SFinley Xiao {1924, 10000},
51316bee043SFinley Xiao {1956, 15000},
51416bee043SFinley Xiao {1992, 20000},
51516bee043SFinley Xiao {2024, 25000},
51616bee043SFinley Xiao {2060, 30000},
51716bee043SFinley Xiao {2092, 35000},
51816bee043SFinley Xiao {2128, 40000},
51916bee043SFinley Xiao {2160, 45000},
52016bee043SFinley Xiao {2196, 50000},
52116bee043SFinley Xiao {2228, 55000},
52216bee043SFinley Xiao {2264, 60000},
52316bee043SFinley Xiao {2300, 65000},
52416bee043SFinley Xiao {2332, 70000},
52516bee043SFinley Xiao {2368, 75000},
52616bee043SFinley Xiao {2400, 80000},
52716bee043SFinley Xiao {2436, 85000},
52816bee043SFinley Xiao {2468, 90000},
52916bee043SFinley Xiao {2500, 95000},
53016bee043SFinley Xiao {2536, 100000},
53116bee043SFinley Xiao {2572, 105000},
53216bee043SFinley Xiao {2604, 110000},
53316bee043SFinley Xiao {2636, 115000},
53416bee043SFinley Xiao {2672, 120000},
53516bee043SFinley Xiao {2704, 125000},
53616bee043SFinley Xiao {TSADCV2_DATA_MASK, 125000},
53716bee043SFinley Xiao };
53816bee043SFinley Xiao
53945d7b386SFinley Xiao static const struct tsadc_table rk3588_code_table[] = {
54045d7b386SFinley Xiao {0, -40000},
54145d7b386SFinley Xiao {215, -40000},
54245d7b386SFinley Xiao {285, 25000},
54345d7b386SFinley Xiao {350, 85000},
54445d7b386SFinley Xiao {395, 125000},
54545d7b386SFinley Xiao {TSADCV4_DATA_MASK, 125000},
54645d7b386SFinley Xiao };
54745d7b386SFinley Xiao
rk_tsadcv2_temp_to_code(const struct chip_tsadc_table * table,int temp)548cdd8b3f7SBrian Norris static u32 rk_tsadcv2_temp_to_code(const struct chip_tsadc_table *table,
549437df217SCaesar Wang int temp)
550cbac8f63SCaesar Wang {
551cbac8f63SCaesar Wang int high, low, mid;
552cadf29dcSCaesar Wang unsigned long num;
553cadf29dcSCaesar Wang unsigned int denom;
554d3530497SCaesar Wang u32 error = table->data_mask;
555cbac8f63SCaesar Wang
556cbac8f63SCaesar Wang low = 0;
557cadf29dcSCaesar Wang high = (table->length - 1) - 1; /* ignore the last check for table */
558cbac8f63SCaesar Wang mid = (high + low) / 2;
559cbac8f63SCaesar Wang
5601f09ba82SCaesar Wang /* Return mask code data when the temp is over table range */
561d3530497SCaesar Wang if (temp < table->id[low].temp || temp > table->id[high].temp)
5621f09ba82SCaesar Wang goto exit;
563cbac8f63SCaesar Wang
564cbac8f63SCaesar Wang while (low <= high) {
565cdd8b3f7SBrian Norris if (temp == table->id[mid].temp)
566cdd8b3f7SBrian Norris return table->id[mid].code;
567cdd8b3f7SBrian Norris else if (temp < table->id[mid].temp)
568cbac8f63SCaesar Wang high = mid - 1;
569cbac8f63SCaesar Wang else
570cbac8f63SCaesar Wang low = mid + 1;
571cbac8f63SCaesar Wang mid = (low + high) / 2;
572cbac8f63SCaesar Wang }
573cbac8f63SCaesar Wang
574cadf29dcSCaesar Wang /*
575cadf29dcSCaesar Wang * The conversion code granularity provided by the table. Let's
576cadf29dcSCaesar Wang * assume that the relationship between temperature and
577cadf29dcSCaesar Wang * analog value between 2 table entries is linear and interpolate
578cadf29dcSCaesar Wang * to produce less granular result.
579cadf29dcSCaesar Wang */
580cadf29dcSCaesar Wang num = abs(table->id[mid + 1].code - table->id[mid].code);
581cadf29dcSCaesar Wang num *= temp - table->id[mid].temp;
582cadf29dcSCaesar Wang denom = table->id[mid + 1].temp - table->id[mid].temp;
583cadf29dcSCaesar Wang
584cadf29dcSCaesar Wang switch (table->mode) {
585cadf29dcSCaesar Wang case ADC_DECREMENT:
586cadf29dcSCaesar Wang return table->id[mid].code - (num / denom);
587cadf29dcSCaesar Wang case ADC_INCREMENT:
588cadf29dcSCaesar Wang return table->id[mid].code + (num / denom);
589cadf29dcSCaesar Wang default:
590cadf29dcSCaesar Wang pr_err("%s: unknown table mode: %d\n", __func__, table->mode);
591cadf29dcSCaesar Wang return error;
592cadf29dcSCaesar Wang }
593cadf29dcSCaesar Wang
5941f09ba82SCaesar Wang exit:
595e6ed1b4aSBrian Norris pr_err("%s: invalid temperature, temp=%d error=%d\n",
596e6ed1b4aSBrian Norris __func__, temp, error);
5971f09ba82SCaesar Wang return error;
598cbac8f63SCaesar Wang }
599cbac8f63SCaesar Wang
rk_tsadcv2_code_to_temp(const struct chip_tsadc_table * table,u32 code,int * temp)600cdd8b3f7SBrian Norris static int rk_tsadcv2_code_to_temp(const struct chip_tsadc_table *table,
601cdd8b3f7SBrian Norris u32 code, int *temp)
602cbac8f63SCaesar Wang {
603d9a241cbSDmitry Torokhov unsigned int low = 1;
604cdd8b3f7SBrian Norris unsigned int high = table->length - 1;
6051e9a1aeaSCaesar Wang unsigned int mid = (low + high) / 2;
6061e9a1aeaSCaesar Wang unsigned int num;
6071e9a1aeaSCaesar Wang unsigned long denom;
608cbac8f63SCaesar Wang
609cdd8b3f7SBrian Norris WARN_ON(table->length < 2);
610cbac8f63SCaesar Wang
611cdd8b3f7SBrian Norris switch (table->mode) {
612020ba95dSCaesar Wang case ADC_DECREMENT:
613cdd8b3f7SBrian Norris code &= table->data_mask;
614db831886SCaesar Wang if (code <= table->id[high].code)
615d9a241cbSDmitry Torokhov return -EAGAIN; /* Incorrect reading */
616d9a241cbSDmitry Torokhov
617d9a241cbSDmitry Torokhov while (low <= high) {
618cdd8b3f7SBrian Norris if (code >= table->id[mid].code &&
619cdd8b3f7SBrian Norris code < table->id[mid - 1].code)
6201e9a1aeaSCaesar Wang break;
621cdd8b3f7SBrian Norris else if (code < table->id[mid].code)
622cbac8f63SCaesar Wang low = mid + 1;
623cbac8f63SCaesar Wang else
624cbac8f63SCaesar Wang high = mid - 1;
625020ba95dSCaesar Wang
626cbac8f63SCaesar Wang mid = (low + high) / 2;
627cbac8f63SCaesar Wang }
628020ba95dSCaesar Wang break;
629020ba95dSCaesar Wang case ADC_INCREMENT:
630cdd8b3f7SBrian Norris code &= table->data_mask;
631cdd8b3f7SBrian Norris if (code < table->id[low].code)
632020ba95dSCaesar Wang return -EAGAIN; /* Incorrect reading */
633020ba95dSCaesar Wang
634020ba95dSCaesar Wang while (low <= high) {
635cdd8b3f7SBrian Norris if (code <= table->id[mid].code &&
636cdd8b3f7SBrian Norris code > table->id[mid - 1].code)
637020ba95dSCaesar Wang break;
638cdd8b3f7SBrian Norris else if (code > table->id[mid].code)
639020ba95dSCaesar Wang low = mid + 1;
640020ba95dSCaesar Wang else
641020ba95dSCaesar Wang high = mid - 1;
642020ba95dSCaesar Wang
643020ba95dSCaesar Wang mid = (low + high) / 2;
644020ba95dSCaesar Wang }
645020ba95dSCaesar Wang break;
646020ba95dSCaesar Wang default:
647cdd8b3f7SBrian Norris pr_err("%s: unknown table mode: %d\n", __func__, table->mode);
648e6ed1b4aSBrian Norris return -EINVAL;
649020ba95dSCaesar Wang }
650cbac8f63SCaesar Wang
6511e9a1aeaSCaesar Wang /*
6521e9a1aeaSCaesar Wang * The 5C granularity provided by the table is too much. Let's
6531e9a1aeaSCaesar Wang * assume that the relationship between sensor readings and
6541e9a1aeaSCaesar Wang * temperature between 2 table entries is linear and interpolate
6551e9a1aeaSCaesar Wang * to produce less granular result.
6561e9a1aeaSCaesar Wang */
657cdd8b3f7SBrian Norris num = table->id[mid].temp - table->id[mid - 1].temp;
658cdd8b3f7SBrian Norris num *= abs(table->id[mid - 1].code - code);
659cdd8b3f7SBrian Norris denom = abs(table->id[mid - 1].code - table->id[mid].code);
660cdd8b3f7SBrian Norris *temp = table->id[mid - 1].temp + (num / denom);
661d9a241cbSDmitry Torokhov
662d9a241cbSDmitry Torokhov return 0;
663cbac8f63SCaesar Wang }
664cbac8f63SCaesar Wang
665cbac8f63SCaesar Wang /**
666144c5565SCaesar Wang * rk_tsadcv2_initialize - initialize TASDC Controller.
66766ec4bfcSAmit Kucheria * @grf: the general register file will be used to do static set by software
66866ec4bfcSAmit Kucheria * @regs: the base address of tsadc controller
66966ec4bfcSAmit Kucheria * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
670144c5565SCaesar Wang *
671144c5565SCaesar Wang * (1) Set TSADC_V2_AUTO_PERIOD:
672144c5565SCaesar Wang * Configure the interleave between every two accessing of
673144c5565SCaesar Wang * TSADC in normal operation.
674144c5565SCaesar Wang *
675144c5565SCaesar Wang * (2) Set TSADCV2_AUTO_PERIOD_HT:
676144c5565SCaesar Wang * Configure the interleave between every two accessing of
677144c5565SCaesar Wang * TSADC after the temperature is higher than COM_SHUT or COM_INT.
678144c5565SCaesar Wang *
679144c5565SCaesar Wang * (3) Set TSADCV2_HIGH_INT_DEBOUNCE and TSADC_HIGHT_TSHUT_DEBOUNCE:
680144c5565SCaesar Wang * If the temperature is higher than COMP_INT or COMP_SHUT for
681cbac8f63SCaesar Wang * "debounce" times, TSADC controller will generate interrupt or TSHUT.
682cbac8f63SCaesar Wang */
rk_tsadcv2_initialize(struct regmap * grf,void __iomem * regs,enum tshut_polarity tshut_polarity)683b9484763SCaesar Wang static void rk_tsadcv2_initialize(struct regmap *grf, void __iomem *regs,
684cbac8f63SCaesar Wang enum tshut_polarity tshut_polarity)
685cbac8f63SCaesar Wang {
686cbac8f63SCaesar Wang if (tshut_polarity == TSHUT_HIGH_ACTIVE)
687452e01b3SDmitry Torokhov writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
688cbac8f63SCaesar Wang regs + TSADCV2_AUTO_CON);
689cbac8f63SCaesar Wang else
690452e01b3SDmitry Torokhov writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
691cbac8f63SCaesar Wang regs + TSADCV2_AUTO_CON);
692cbac8f63SCaesar Wang
693cbac8f63SCaesar Wang writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
694cbac8f63SCaesar Wang writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
695cbac8f63SCaesar Wang regs + TSADCV2_HIGHT_INT_DEBOUNCE);
696cbac8f63SCaesar Wang writel_relaxed(TSADCV2_AUTO_PERIOD_HT_TIME,
697cbac8f63SCaesar Wang regs + TSADCV2_AUTO_PERIOD_HT);
698cbac8f63SCaesar Wang writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
699cbac8f63SCaesar Wang regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
700b9484763SCaesar Wang }
701b9484763SCaesar Wang
702b9484763SCaesar Wang /**
703b9484763SCaesar Wang * rk_tsadcv3_initialize - initialize TASDC Controller.
70466ec4bfcSAmit Kucheria * @grf: the general register file will be used to do static set by software
70566ec4bfcSAmit Kucheria * @regs: the base address of tsadc controller
70666ec4bfcSAmit Kucheria * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
707678065d5SCaesar Wang *
708b9484763SCaesar Wang * (1) The tsadc control power sequence.
709b9484763SCaesar Wang *
710b9484763SCaesar Wang * (2) Set TSADC_V2_AUTO_PERIOD:
711b9484763SCaesar Wang * Configure the interleave between every two accessing of
712b9484763SCaesar Wang * TSADC in normal operation.
713b9484763SCaesar Wang *
714b9484763SCaesar Wang * (2) Set TSADCV2_AUTO_PERIOD_HT:
715b9484763SCaesar Wang * Configure the interleave between every two accessing of
716b9484763SCaesar Wang * TSADC after the temperature is higher than COM_SHUT or COM_INT.
717b9484763SCaesar Wang *
718b9484763SCaesar Wang * (3) Set TSADCV2_HIGH_INT_DEBOUNCE and TSADC_HIGHT_TSHUT_DEBOUNCE:
719b9484763SCaesar Wang * If the temperature is higher than COMP_INT or COMP_SHUT for
720b9484763SCaesar Wang * "debounce" times, TSADC controller will generate interrupt or TSHUT.
721b9484763SCaesar Wang */
rk_tsadcv3_initialize(struct regmap * grf,void __iomem * regs,enum tshut_polarity tshut_polarity)722b9484763SCaesar Wang static void rk_tsadcv3_initialize(struct regmap *grf, void __iomem *regs,
723b9484763SCaesar Wang enum tshut_polarity tshut_polarity)
724b9484763SCaesar Wang {
725b9484763SCaesar Wang /* The tsadc control power sequence */
726b9484763SCaesar Wang if (IS_ERR(grf)) {
727b9484763SCaesar Wang /* Set interleave value to workround ic time sync issue */
728b9484763SCaesar Wang writel_relaxed(TSADCV2_USER_INTER_PD_SOC, regs +
729b9484763SCaesar Wang TSADCV2_USER_CON);
73046667879SCaesar Wang
73146667879SCaesar Wang writel_relaxed(TSADCV2_AUTO_PERIOD_TIME,
73246667879SCaesar Wang regs + TSADCV2_AUTO_PERIOD);
73346667879SCaesar Wang writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
73446667879SCaesar Wang regs + TSADCV2_HIGHT_INT_DEBOUNCE);
73546667879SCaesar Wang writel_relaxed(TSADCV2_AUTO_PERIOD_HT_TIME,
73646667879SCaesar Wang regs + TSADCV2_AUTO_PERIOD_HT);
73746667879SCaesar Wang writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
73846667879SCaesar Wang regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
73946667879SCaesar Wang
740b9484763SCaesar Wang } else {
74123f75e48SRocky Hao /* Enable the voltage common mode feature */
74223f75e48SRocky Hao regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_VCM_EN_L);
74323f75e48SRocky Hao regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_VCM_EN_H);
74423f75e48SRocky Hao
7452fe5c1b0SCaesar Wang usleep_range(15, 100); /* The spec note says at least 15 us */
746b9484763SCaesar Wang regmap_write(grf, GRF_SARADC_TESTBIT, GRF_SARADC_TESTBIT_ON);
747b9484763SCaesar Wang regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_TESTBIT_H_ON);
7482fe5c1b0SCaesar Wang usleep_range(90, 200); /* The spec note says at least 90 us */
74946667879SCaesar Wang
75046667879SCaesar Wang writel_relaxed(TSADCV3_AUTO_PERIOD_TIME,
75146667879SCaesar Wang regs + TSADCV2_AUTO_PERIOD);
75246667879SCaesar Wang writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
75346667879SCaesar Wang regs + TSADCV2_HIGHT_INT_DEBOUNCE);
75446667879SCaesar Wang writel_relaxed(TSADCV3_AUTO_PERIOD_HT_TIME,
75546667879SCaesar Wang regs + TSADCV2_AUTO_PERIOD_HT);
75646667879SCaesar Wang writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
75746667879SCaesar Wang regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
758b9484763SCaesar Wang }
759b9484763SCaesar Wang
760b9484763SCaesar Wang if (tshut_polarity == TSHUT_HIGH_ACTIVE)
761b9484763SCaesar Wang writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
762b9484763SCaesar Wang regs + TSADCV2_AUTO_CON);
763b9484763SCaesar Wang else
764b9484763SCaesar Wang writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
765b9484763SCaesar Wang regs + TSADCV2_AUTO_CON);
766cbac8f63SCaesar Wang }
767cbac8f63SCaesar Wang
rk_tsadcv4_initialize(struct regmap * grf,void __iomem * regs,enum tshut_polarity tshut_polarity)768ffd1b122SElaine Zhang static void rk_tsadcv4_initialize(struct regmap *grf, void __iomem *regs,
769ffd1b122SElaine Zhang enum tshut_polarity tshut_polarity)
770ffd1b122SElaine Zhang {
771ffd1b122SElaine Zhang rk_tsadcv2_initialize(grf, regs, tshut_polarity);
772ffd1b122SElaine Zhang regmap_write(grf, PX30_GRF_SOC_CON2, GRF_CON_TSADC_CH_INV);
773ffd1b122SElaine Zhang }
774ffd1b122SElaine Zhang
rk_tsadcv7_initialize(struct regmap * grf,void __iomem * regs,enum tshut_polarity tshut_polarity)77516bee043SFinley Xiao static void rk_tsadcv7_initialize(struct regmap *grf, void __iomem *regs,
77616bee043SFinley Xiao enum tshut_polarity tshut_polarity)
77716bee043SFinley Xiao {
77816bee043SFinley Xiao writel_relaxed(TSADCV5_USER_INTER_PD_SOC, regs + TSADCV2_USER_CON);
77916bee043SFinley Xiao writel_relaxed(TSADCV5_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
78016bee043SFinley Xiao writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
78116bee043SFinley Xiao regs + TSADCV2_HIGHT_INT_DEBOUNCE);
78216bee043SFinley Xiao writel_relaxed(TSADCV5_AUTO_PERIOD_HT_TIME,
78316bee043SFinley Xiao regs + TSADCV2_AUTO_PERIOD_HT);
78416bee043SFinley Xiao writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
78516bee043SFinley Xiao regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
78616bee043SFinley Xiao
78716bee043SFinley Xiao if (tshut_polarity == TSHUT_HIGH_ACTIVE)
78816bee043SFinley Xiao writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
78916bee043SFinley Xiao regs + TSADCV2_AUTO_CON);
79016bee043SFinley Xiao else
79116bee043SFinley Xiao writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
79216bee043SFinley Xiao regs + TSADCV2_AUTO_CON);
79316bee043SFinley Xiao
79416bee043SFinley Xiao /*
79516bee043SFinley Xiao * The general register file will is optional
79616bee043SFinley Xiao * and might not be available.
79716bee043SFinley Xiao */
79816bee043SFinley Xiao if (!IS_ERR(grf)) {
79916bee043SFinley Xiao regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_TSEN);
80016bee043SFinley Xiao /*
80116bee043SFinley Xiao * RK3568 TRM, section 18.5. requires a delay no less
80216bee043SFinley Xiao * than 10us between the rising edge of tsadc_tsen_en
80316bee043SFinley Xiao * and the rising edge of tsadc_ana_reg_0/1/2.
80416bee043SFinley Xiao */
80516bee043SFinley Xiao udelay(15);
80616bee043SFinley Xiao regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG0);
80716bee043SFinley Xiao regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG1);
80816bee043SFinley Xiao regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG2);
80916bee043SFinley Xiao
81016bee043SFinley Xiao /*
81116bee043SFinley Xiao * RK3568 TRM, section 18.5. requires a delay no less
81216bee043SFinley Xiao * than 90us after the rising edge of tsadc_ana_reg_0/1/2.
81316bee043SFinley Xiao */
81416bee043SFinley Xiao usleep_range(100, 200);
81516bee043SFinley Xiao }
81616bee043SFinley Xiao }
81716bee043SFinley Xiao
rk_tsadcv8_initialize(struct regmap * grf,void __iomem * regs,enum tshut_polarity tshut_polarity)81845d7b386SFinley Xiao static void rk_tsadcv8_initialize(struct regmap *grf, void __iomem *regs,
81945d7b386SFinley Xiao enum tshut_polarity tshut_polarity)
82045d7b386SFinley Xiao {
82145d7b386SFinley Xiao writel_relaxed(TSADCV6_AUTO_PERIOD_TIME, regs + TSADCV3_AUTO_PERIOD);
82245d7b386SFinley Xiao writel_relaxed(TSADCV6_AUTO_PERIOD_HT_TIME,
82345d7b386SFinley Xiao regs + TSADCV3_AUTO_PERIOD_HT);
82445d7b386SFinley Xiao writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
82545d7b386SFinley Xiao regs + TSADCV3_HIGHT_INT_DEBOUNCE);
82645d7b386SFinley Xiao writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
82745d7b386SFinley Xiao regs + TSADCV3_HIGHT_TSHUT_DEBOUNCE);
82845d7b386SFinley Xiao if (tshut_polarity == TSHUT_HIGH_ACTIVE)
82945d7b386SFinley Xiao writel_relaxed(TSADCV2_AUTO_TSHUT_POLARITY_HIGH |
83045d7b386SFinley Xiao TSADCV2_AUTO_TSHUT_POLARITY_MASK,
83145d7b386SFinley Xiao regs + TSADCV2_AUTO_CON);
83245d7b386SFinley Xiao else
83345d7b386SFinley Xiao writel_relaxed(TSADCV2_AUTO_TSHUT_POLARITY_MASK,
83445d7b386SFinley Xiao regs + TSADCV2_AUTO_CON);
83545d7b386SFinley Xiao }
83645d7b386SFinley Xiao
rk_tsadcv2_irq_ack(void __iomem * regs)837cbac8f63SCaesar Wang static void rk_tsadcv2_irq_ack(void __iomem *regs)
838cbac8f63SCaesar Wang {
839cbac8f63SCaesar Wang u32 val;
840cbac8f63SCaesar Wang
841cbac8f63SCaesar Wang val = readl_relaxed(regs + TSADCV2_INT_PD);
842452e01b3SDmitry Torokhov writel_relaxed(val & TSADCV2_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD);
843cbac8f63SCaesar Wang }
844cbac8f63SCaesar Wang
rk_tsadcv3_irq_ack(void __iomem * regs)845952418a3SCaesar Wang static void rk_tsadcv3_irq_ack(void __iomem *regs)
846952418a3SCaesar Wang {
847952418a3SCaesar Wang u32 val;
848952418a3SCaesar Wang
849952418a3SCaesar Wang val = readl_relaxed(regs + TSADCV2_INT_PD);
850952418a3SCaesar Wang writel_relaxed(val & TSADCV3_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD);
851952418a3SCaesar Wang }
852952418a3SCaesar Wang
rk_tsadcv4_irq_ack(void __iomem * regs)85345d7b386SFinley Xiao static void rk_tsadcv4_irq_ack(void __iomem *regs)
85445d7b386SFinley Xiao {
85545d7b386SFinley Xiao u32 val;
85645d7b386SFinley Xiao
85745d7b386SFinley Xiao val = readl_relaxed(regs + TSADCV3_INT_PD);
85845d7b386SFinley Xiao writel_relaxed(val & TSADCV4_INT_PD_CLEAR_MASK, regs + TSADCV3_INT_PD);
85945d7b386SFinley Xiao val = readl_relaxed(regs + TSADCV3_HSHUT_PD);
86045d7b386SFinley Xiao writel_relaxed(val & TSADCV3_INT_PD_CLEAR_MASK,
86145d7b386SFinley Xiao regs + TSADCV3_HSHUT_PD);
86245d7b386SFinley Xiao }
86345d7b386SFinley Xiao
rk_tsadcv2_control(void __iomem * regs,bool enable)864cbac8f63SCaesar Wang static void rk_tsadcv2_control(void __iomem *regs, bool enable)
865cbac8f63SCaesar Wang {
866cbac8f63SCaesar Wang u32 val;
867cbac8f63SCaesar Wang
868cbac8f63SCaesar Wang val = readl_relaxed(regs + TSADCV2_AUTO_CON);
869cbac8f63SCaesar Wang if (enable)
870cbac8f63SCaesar Wang val |= TSADCV2_AUTO_EN;
871cbac8f63SCaesar Wang else
872cbac8f63SCaesar Wang val &= ~TSADCV2_AUTO_EN;
873cbac8f63SCaesar Wang
874cbac8f63SCaesar Wang writel_relaxed(val, regs + TSADCV2_AUTO_CON);
875cbac8f63SCaesar Wang }
876cbac8f63SCaesar Wang
8777ea38c6cSCaesar Wang /**
878678065d5SCaesar Wang * rk_tsadcv3_control - the tsadc controller is enabled or disabled.
87966ec4bfcSAmit Kucheria * @regs: the base address of tsadc controller
88066ec4bfcSAmit Kucheria * @enable: boolean flag to enable the controller
881678065d5SCaesar Wang *
882678065d5SCaesar Wang * NOTE: TSADC controller works at auto mode, and some SoCs need set the
883678065d5SCaesar Wang * tsadc_q_sel bit on TSADCV2_AUTO_CON[1]. The (1024 - tsadc_q) as output
884678065d5SCaesar Wang * adc value if setting this bit to enable.
8857ea38c6cSCaesar Wang */
rk_tsadcv3_control(void __iomem * regs,bool enable)8867ea38c6cSCaesar Wang static void rk_tsadcv3_control(void __iomem *regs, bool enable)
8877ea38c6cSCaesar Wang {
8887ea38c6cSCaesar Wang u32 val;
8897ea38c6cSCaesar Wang
8907ea38c6cSCaesar Wang val = readl_relaxed(regs + TSADCV2_AUTO_CON);
8917ea38c6cSCaesar Wang if (enable)
8927ea38c6cSCaesar Wang val |= TSADCV2_AUTO_EN | TSADCV3_AUTO_Q_SEL_EN;
8937ea38c6cSCaesar Wang else
8947ea38c6cSCaesar Wang val &= ~TSADCV2_AUTO_EN;
8957ea38c6cSCaesar Wang
8967ea38c6cSCaesar Wang writel_relaxed(val, regs + TSADCV2_AUTO_CON);
8977ea38c6cSCaesar Wang }
8987ea38c6cSCaesar Wang
rk_tsadcv4_control(void __iomem * regs,bool enable)89945d7b386SFinley Xiao static void rk_tsadcv4_control(void __iomem *regs, bool enable)
90045d7b386SFinley Xiao {
90145d7b386SFinley Xiao u32 val;
90245d7b386SFinley Xiao
90345d7b386SFinley Xiao if (enable)
90445d7b386SFinley Xiao val = TSADCV2_AUTO_EN | TSADCV2_AUTO_EN_MASK;
90545d7b386SFinley Xiao else
90645d7b386SFinley Xiao val = TSADCV2_AUTO_EN_MASK;
90745d7b386SFinley Xiao
90845d7b386SFinley Xiao writel_relaxed(val, regs + TSADCV2_AUTO_CON);
90945d7b386SFinley Xiao }
91045d7b386SFinley Xiao
rk_tsadcv2_get_temp(const struct chip_tsadc_table * table,int chn,void __iomem * regs,int * temp)911cdd8b3f7SBrian Norris static int rk_tsadcv2_get_temp(const struct chip_tsadc_table *table,
912ce74110dSCaesar Wang int chn, void __iomem *regs, int *temp)
913cbac8f63SCaesar Wang {
914cbac8f63SCaesar Wang u32 val;
915cbac8f63SCaesar Wang
916cbac8f63SCaesar Wang val = readl_relaxed(regs + TSADCV2_DATA(chn));
917cbac8f63SCaesar Wang
918ce74110dSCaesar Wang return rk_tsadcv2_code_to_temp(table, val, temp);
919cbac8f63SCaesar Wang }
920cbac8f63SCaesar Wang
rk_tsadcv4_get_temp(const struct chip_tsadc_table * table,int chn,void __iomem * regs,int * temp)92145d7b386SFinley Xiao static int rk_tsadcv4_get_temp(const struct chip_tsadc_table *table,
92245d7b386SFinley Xiao int chn, void __iomem *regs, int *temp)
92345d7b386SFinley Xiao {
92445d7b386SFinley Xiao u32 val;
92545d7b386SFinley Xiao
92645d7b386SFinley Xiao val = readl_relaxed(regs + TSADCV3_DATA(chn));
92745d7b386SFinley Xiao
92845d7b386SFinley Xiao return rk_tsadcv2_code_to_temp(table, val, temp);
92945d7b386SFinley Xiao }
93045d7b386SFinley Xiao
rk_tsadcv2_alarm_temp(const struct chip_tsadc_table * table,int chn,void __iomem * regs,int temp)931d3530497SCaesar Wang static int rk_tsadcv2_alarm_temp(const struct chip_tsadc_table *table,
93214848502SCaesar Wang int chn, void __iomem *regs, int temp)
93314848502SCaesar Wang {
93418591addSCaesar Wang u32 alarm_value;
93518591addSCaesar Wang u32 int_en, int_clr;
93618591addSCaesar Wang
93718591addSCaesar Wang /*
93818591addSCaesar Wang * In some cases, some sensors didn't need the trip points, the
93918591addSCaesar Wang * set_trips will pass {-INT_MAX, INT_MAX} to trigger tsadc alarm
94018591addSCaesar Wang * in the end, ignore this case and disable the high temperature
94118591addSCaesar Wang * interrupt.
94218591addSCaesar Wang */
94318591addSCaesar Wang if (temp == INT_MAX) {
94418591addSCaesar Wang int_clr = readl_relaxed(regs + TSADCV2_INT_EN);
94518591addSCaesar Wang int_clr &= ~TSADCV2_INT_SRC_EN(chn);
94618591addSCaesar Wang writel_relaxed(int_clr, regs + TSADCV2_INT_EN);
94718591addSCaesar Wang return 0;
94818591addSCaesar Wang }
94914848502SCaesar Wang
9501f09ba82SCaesar Wang /* Make sure the value is valid */
95114848502SCaesar Wang alarm_value = rk_tsadcv2_temp_to_code(table, temp);
952cdd8b3f7SBrian Norris if (alarm_value == table->data_mask)
953d3530497SCaesar Wang return -ERANGE;
9541f09ba82SCaesar Wang
955cdd8b3f7SBrian Norris writel_relaxed(alarm_value & table->data_mask,
95614848502SCaesar Wang regs + TSADCV2_COMP_INT(chn));
95714848502SCaesar Wang
95814848502SCaesar Wang int_en = readl_relaxed(regs + TSADCV2_INT_EN);
95914848502SCaesar Wang int_en |= TSADCV2_INT_SRC_EN(chn);
96014848502SCaesar Wang writel_relaxed(int_en, regs + TSADCV2_INT_EN);
961d3530497SCaesar Wang
962d3530497SCaesar Wang return 0;
96314848502SCaesar Wang }
96414848502SCaesar Wang
rk_tsadcv3_alarm_temp(const struct chip_tsadc_table * table,int chn,void __iomem * regs,int temp)96545d7b386SFinley Xiao static int rk_tsadcv3_alarm_temp(const struct chip_tsadc_table *table,
96645d7b386SFinley Xiao int chn, void __iomem *regs, int temp)
96745d7b386SFinley Xiao {
96845d7b386SFinley Xiao u32 alarm_value;
96945d7b386SFinley Xiao
97045d7b386SFinley Xiao /*
97145d7b386SFinley Xiao * In some cases, some sensors didn't need the trip points, the
97245d7b386SFinley Xiao * set_trips will pass {-INT_MAX, INT_MAX} to trigger tsadc alarm
97345d7b386SFinley Xiao * in the end, ignore this case and disable the high temperature
97445d7b386SFinley Xiao * interrupt.
97545d7b386SFinley Xiao */
97645d7b386SFinley Xiao if (temp == INT_MAX) {
97745d7b386SFinley Xiao writel_relaxed(TSADCV2_INT_SRC_EN_MASK(chn),
97845d7b386SFinley Xiao regs + TSADCV3_HT_INT_EN);
97945d7b386SFinley Xiao return 0;
98045d7b386SFinley Xiao }
98145d7b386SFinley Xiao /* Make sure the value is valid */
98245d7b386SFinley Xiao alarm_value = rk_tsadcv2_temp_to_code(table, temp);
98345d7b386SFinley Xiao if (alarm_value == table->data_mask)
98445d7b386SFinley Xiao return -ERANGE;
98545d7b386SFinley Xiao writel_relaxed(alarm_value & table->data_mask,
98645d7b386SFinley Xiao regs + TSADCV3_COMP_INT(chn));
98745d7b386SFinley Xiao writel_relaxed(TSADCV2_INT_SRC_EN(chn) | TSADCV2_INT_SRC_EN_MASK(chn),
98845d7b386SFinley Xiao regs + TSADCV3_HT_INT_EN);
98945d7b386SFinley Xiao return 0;
99045d7b386SFinley Xiao }
99145d7b386SFinley Xiao
rk_tsadcv2_tshut_temp(const struct chip_tsadc_table * table,int chn,void __iomem * regs,int temp)992d3530497SCaesar Wang static int rk_tsadcv2_tshut_temp(const struct chip_tsadc_table *table,
993437df217SCaesar Wang int chn, void __iomem *regs, int temp)
994cbac8f63SCaesar Wang {
995cbac8f63SCaesar Wang u32 tshut_value, val;
996cbac8f63SCaesar Wang
9971f09ba82SCaesar Wang /* Make sure the value is valid */
998ce74110dSCaesar Wang tshut_value = rk_tsadcv2_temp_to_code(table, temp);
999cdd8b3f7SBrian Norris if (tshut_value == table->data_mask)
1000d3530497SCaesar Wang return -ERANGE;
10011f09ba82SCaesar Wang
1002cbac8f63SCaesar Wang writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn));
1003cbac8f63SCaesar Wang
1004cbac8f63SCaesar Wang /* TSHUT will be valid */
1005cbac8f63SCaesar Wang val = readl_relaxed(regs + TSADCV2_AUTO_CON);
1006cbac8f63SCaesar Wang writel_relaxed(val | TSADCV2_AUTO_SRC_EN(chn), regs + TSADCV2_AUTO_CON);
1007d3530497SCaesar Wang
1008d3530497SCaesar Wang return 0;
1009cbac8f63SCaesar Wang }
1010cbac8f63SCaesar Wang
rk_tsadcv3_tshut_temp(const struct chip_tsadc_table * table,int chn,void __iomem * regs,int temp)101145d7b386SFinley Xiao static int rk_tsadcv3_tshut_temp(const struct chip_tsadc_table *table,
101245d7b386SFinley Xiao int chn, void __iomem *regs, int temp)
101345d7b386SFinley Xiao {
101445d7b386SFinley Xiao u32 tshut_value;
101545d7b386SFinley Xiao
101645d7b386SFinley Xiao /* Make sure the value is valid */
101745d7b386SFinley Xiao tshut_value = rk_tsadcv2_temp_to_code(table, temp);
101845d7b386SFinley Xiao if (tshut_value == table->data_mask)
101945d7b386SFinley Xiao return -ERANGE;
102045d7b386SFinley Xiao
102145d7b386SFinley Xiao writel_relaxed(tshut_value, regs + TSADCV3_COMP_SHUT(chn));
102245d7b386SFinley Xiao
102345d7b386SFinley Xiao /* TSHUT will be valid */
102445d7b386SFinley Xiao writel_relaxed(TSADCV3_AUTO_SRC_EN(chn) | TSADCV3_AUTO_SRC_EN_MASK(chn),
102545d7b386SFinley Xiao regs + TSADCV3_AUTO_SRC_CON);
102645d7b386SFinley Xiao
102745d7b386SFinley Xiao return 0;
102845d7b386SFinley Xiao }
102945d7b386SFinley Xiao
rk_tsadcv2_tshut_mode(int chn,void __iomem * regs,enum tshut_mode mode)1030cbac8f63SCaesar Wang static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs,
1031cbac8f63SCaesar Wang enum tshut_mode mode)
1032cbac8f63SCaesar Wang {
1033cbac8f63SCaesar Wang u32 val;
1034cbac8f63SCaesar Wang
1035cbac8f63SCaesar Wang val = readl_relaxed(regs + TSADCV2_INT_EN);
1036cbac8f63SCaesar Wang if (mode == TSHUT_MODE_GPIO) {
1037cbac8f63SCaesar Wang val &= ~TSADCV2_SHUT_2CRU_SRC_EN(chn);
1038cbac8f63SCaesar Wang val |= TSADCV2_SHUT_2GPIO_SRC_EN(chn);
1039cbac8f63SCaesar Wang } else {
1040cbac8f63SCaesar Wang val &= ~TSADCV2_SHUT_2GPIO_SRC_EN(chn);
1041cbac8f63SCaesar Wang val |= TSADCV2_SHUT_2CRU_SRC_EN(chn);
1042cbac8f63SCaesar Wang }
1043cbac8f63SCaesar Wang
1044cbac8f63SCaesar Wang writel_relaxed(val, regs + TSADCV2_INT_EN);
1045cbac8f63SCaesar Wang }
1046cbac8f63SCaesar Wang
rk_tsadcv3_tshut_mode(int chn,void __iomem * regs,enum tshut_mode mode)104745d7b386SFinley Xiao static void rk_tsadcv3_tshut_mode(int chn, void __iomem *regs,
104845d7b386SFinley Xiao enum tshut_mode mode)
104945d7b386SFinley Xiao {
105045d7b386SFinley Xiao u32 val_gpio, val_cru;
105145d7b386SFinley Xiao
105245d7b386SFinley Xiao if (mode == TSHUT_MODE_GPIO) {
105345d7b386SFinley Xiao val_gpio = TSADCV2_INT_SRC_EN(chn) | TSADCV2_INT_SRC_EN_MASK(chn);
105445d7b386SFinley Xiao val_cru = TSADCV2_INT_SRC_EN_MASK(chn);
105545d7b386SFinley Xiao } else {
105645d7b386SFinley Xiao val_cru = TSADCV2_INT_SRC_EN(chn) | TSADCV2_INT_SRC_EN_MASK(chn);
105745d7b386SFinley Xiao val_gpio = TSADCV2_INT_SRC_EN_MASK(chn);
105845d7b386SFinley Xiao }
105945d7b386SFinley Xiao writel_relaxed(val_gpio, regs + TSADCV3_HSHUT_GPIO_INT_EN);
106045d7b386SFinley Xiao writel_relaxed(val_cru, regs + TSADCV3_HSHUT_CRU_INT_EN);
106145d7b386SFinley Xiao }
106245d7b386SFinley Xiao
1063ffd1b122SElaine Zhang static const struct rockchip_tsadc_chip px30_tsadc_data = {
1064f7cef1b7SSebastian Reichel /* cpu, gpu */
1065f7cef1b7SSebastian Reichel .chn_offset = 0,
1066ffd1b122SElaine Zhang .chn_num = 2, /* 2 channels for tsadc */
1067ffd1b122SElaine Zhang
1068ffd1b122SElaine Zhang .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */
1069ffd1b122SElaine Zhang .tshut_temp = 95000,
1070ffd1b122SElaine Zhang
1071ffd1b122SElaine Zhang .initialize = rk_tsadcv4_initialize,
1072ffd1b122SElaine Zhang .irq_ack = rk_tsadcv3_irq_ack,
1073ffd1b122SElaine Zhang .control = rk_tsadcv3_control,
1074ffd1b122SElaine Zhang .get_temp = rk_tsadcv2_get_temp,
1075ffd1b122SElaine Zhang .set_alarm_temp = rk_tsadcv2_alarm_temp,
1076ffd1b122SElaine Zhang .set_tshut_temp = rk_tsadcv2_tshut_temp,
1077ffd1b122SElaine Zhang .set_tshut_mode = rk_tsadcv2_tshut_mode,
1078ffd1b122SElaine Zhang
1079ffd1b122SElaine Zhang .table = {
1080ffd1b122SElaine Zhang .id = rk3328_code_table,
1081ffd1b122SElaine Zhang .length = ARRAY_SIZE(rk3328_code_table),
1082ffd1b122SElaine Zhang .data_mask = TSADCV2_DATA_MASK,
1083ffd1b122SElaine Zhang .mode = ADC_INCREMENT,
1084ffd1b122SElaine Zhang },
1085ffd1b122SElaine Zhang };
1086ffd1b122SElaine Zhang
10874eca8cacSRocky Hao static const struct rockchip_tsadc_chip rv1108_tsadc_data = {
1088f7cef1b7SSebastian Reichel /* cpu */
1089f7cef1b7SSebastian Reichel .chn_offset = 0,
10904eca8cacSRocky Hao .chn_num = 1, /* one channel for tsadc */
10914eca8cacSRocky Hao
10924eca8cacSRocky Hao .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
10934eca8cacSRocky Hao .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
10944eca8cacSRocky Hao .tshut_temp = 95000,
10954eca8cacSRocky Hao
10964eca8cacSRocky Hao .initialize = rk_tsadcv2_initialize,
10974eca8cacSRocky Hao .irq_ack = rk_tsadcv3_irq_ack,
10984eca8cacSRocky Hao .control = rk_tsadcv3_control,
10994eca8cacSRocky Hao .get_temp = rk_tsadcv2_get_temp,
11004eca8cacSRocky Hao .set_alarm_temp = rk_tsadcv2_alarm_temp,
11014eca8cacSRocky Hao .set_tshut_temp = rk_tsadcv2_tshut_temp,
11024eca8cacSRocky Hao .set_tshut_mode = rk_tsadcv2_tshut_mode,
11034eca8cacSRocky Hao
11044eca8cacSRocky Hao .table = {
11054eca8cacSRocky Hao .id = rv1108_table,
11064eca8cacSRocky Hao .length = ARRAY_SIZE(rv1108_table),
11074eca8cacSRocky Hao .data_mask = TSADCV2_DATA_MASK,
11084eca8cacSRocky Hao .mode = ADC_INCREMENT,
11094eca8cacSRocky Hao },
11104eca8cacSRocky Hao };
11114eca8cacSRocky Hao
11127b02a5e7SCaesar Wang static const struct rockchip_tsadc_chip rk3228_tsadc_data = {
1113f7cef1b7SSebastian Reichel /* cpu */
1114f7cef1b7SSebastian Reichel .chn_offset = 0,
11157b02a5e7SCaesar Wang .chn_num = 1, /* one channel for tsadc */
11167b02a5e7SCaesar Wang
11177b02a5e7SCaesar Wang .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
11187b02a5e7SCaesar Wang .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
11197b02a5e7SCaesar Wang .tshut_temp = 95000,
11207b02a5e7SCaesar Wang
11217b02a5e7SCaesar Wang .initialize = rk_tsadcv2_initialize,
1122952418a3SCaesar Wang .irq_ack = rk_tsadcv3_irq_ack,
11237ea38c6cSCaesar Wang .control = rk_tsadcv3_control,
11247b02a5e7SCaesar Wang .get_temp = rk_tsadcv2_get_temp,
112514848502SCaesar Wang .set_alarm_temp = rk_tsadcv2_alarm_temp,
11267b02a5e7SCaesar Wang .set_tshut_temp = rk_tsadcv2_tshut_temp,
11277b02a5e7SCaesar Wang .set_tshut_mode = rk_tsadcv2_tshut_mode,
11287b02a5e7SCaesar Wang
11297b02a5e7SCaesar Wang .table = {
1130952418a3SCaesar Wang .id = rk3228_code_table,
1131952418a3SCaesar Wang .length = ARRAY_SIZE(rk3228_code_table),
11327b02a5e7SCaesar Wang .data_mask = TSADCV3_DATA_MASK,
11337ea38c6cSCaesar Wang .mode = ADC_INCREMENT,
11347b02a5e7SCaesar Wang },
11357b02a5e7SCaesar Wang };
11367b02a5e7SCaesar Wang
1137cbac8f63SCaesar Wang static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
1138f7cef1b7SSebastian Reichel /* cpu, gpu */
1139f7cef1b7SSebastian Reichel .chn_offset = 1,
11401d98b618SCaesar Wang .chn_num = 2, /* two channels for tsadc */
11411d98b618SCaesar Wang
1142cbac8f63SCaesar Wang .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
1143cbac8f63SCaesar Wang .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
1144cbac8f63SCaesar Wang .tshut_temp = 95000,
1145cbac8f63SCaesar Wang
1146cbac8f63SCaesar Wang .initialize = rk_tsadcv2_initialize,
1147cbac8f63SCaesar Wang .irq_ack = rk_tsadcv2_irq_ack,
1148cbac8f63SCaesar Wang .control = rk_tsadcv2_control,
1149cbac8f63SCaesar Wang .get_temp = rk_tsadcv2_get_temp,
115014848502SCaesar Wang .set_alarm_temp = rk_tsadcv2_alarm_temp,
1151cbac8f63SCaesar Wang .set_tshut_temp = rk_tsadcv2_tshut_temp,
1152cbac8f63SCaesar Wang .set_tshut_mode = rk_tsadcv2_tshut_mode,
1153ce74110dSCaesar Wang
1154ce74110dSCaesar Wang .table = {
1155952418a3SCaesar Wang .id = rk3288_code_table,
1156952418a3SCaesar Wang .length = ARRAY_SIZE(rk3288_code_table),
1157ce74110dSCaesar Wang .data_mask = TSADCV2_DATA_MASK,
1158020ba95dSCaesar Wang .mode = ADC_DECREMENT,
1159ce74110dSCaesar Wang },
1160cbac8f63SCaesar Wang };
1161cbac8f63SCaesar Wang
1162eda519d5SRocky Hao static const struct rockchip_tsadc_chip rk3328_tsadc_data = {
1163f7cef1b7SSebastian Reichel /* cpu */
1164f7cef1b7SSebastian Reichel .chn_offset = 0,
1165eda519d5SRocky Hao .chn_num = 1, /* one channels for tsadc */
1166eda519d5SRocky Hao
1167eda519d5SRocky Hao .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */
1168eda519d5SRocky Hao .tshut_temp = 95000,
1169eda519d5SRocky Hao
1170eda519d5SRocky Hao .initialize = rk_tsadcv2_initialize,
1171eda519d5SRocky Hao .irq_ack = rk_tsadcv3_irq_ack,
1172eda519d5SRocky Hao .control = rk_tsadcv3_control,
1173eda519d5SRocky Hao .get_temp = rk_tsadcv2_get_temp,
1174eda519d5SRocky Hao .set_alarm_temp = rk_tsadcv2_alarm_temp,
1175eda519d5SRocky Hao .set_tshut_temp = rk_tsadcv2_tshut_temp,
1176eda519d5SRocky Hao .set_tshut_mode = rk_tsadcv2_tshut_mode,
1177eda519d5SRocky Hao
1178eda519d5SRocky Hao .table = {
1179eda519d5SRocky Hao .id = rk3328_code_table,
1180eda519d5SRocky Hao .length = ARRAY_SIZE(rk3328_code_table),
1181eda519d5SRocky Hao .data_mask = TSADCV2_DATA_MASK,
1182eda519d5SRocky Hao .mode = ADC_INCREMENT,
1183eda519d5SRocky Hao },
1184eda519d5SRocky Hao };
1185eda519d5SRocky Hao
11861cd60269SElaine Zhang static const struct rockchip_tsadc_chip rk3366_tsadc_data = {
1187f7cef1b7SSebastian Reichel /* cpu, gpu */
1188f7cef1b7SSebastian Reichel .chn_offset = 0,
11891cd60269SElaine Zhang .chn_num = 2, /* two channels for tsadc */
11901cd60269SElaine Zhang
11911cd60269SElaine Zhang .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
11921cd60269SElaine Zhang .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
11931cd60269SElaine Zhang .tshut_temp = 95000,
11941cd60269SElaine Zhang
11951cd60269SElaine Zhang .initialize = rk_tsadcv3_initialize,
11961cd60269SElaine Zhang .irq_ack = rk_tsadcv3_irq_ack,
11971cd60269SElaine Zhang .control = rk_tsadcv3_control,
11981cd60269SElaine Zhang .get_temp = rk_tsadcv2_get_temp,
119914848502SCaesar Wang .set_alarm_temp = rk_tsadcv2_alarm_temp,
12001cd60269SElaine Zhang .set_tshut_temp = rk_tsadcv2_tshut_temp,
12011cd60269SElaine Zhang .set_tshut_mode = rk_tsadcv2_tshut_mode,
12021cd60269SElaine Zhang
12031cd60269SElaine Zhang .table = {
12041cd60269SElaine Zhang .id = rk3228_code_table,
12051cd60269SElaine Zhang .length = ARRAY_SIZE(rk3228_code_table),
12061cd60269SElaine Zhang .data_mask = TSADCV3_DATA_MASK,
12071cd60269SElaine Zhang .mode = ADC_INCREMENT,
12081cd60269SElaine Zhang },
12091cd60269SElaine Zhang };
12101cd60269SElaine Zhang
121120f0af75SCaesar Wang static const struct rockchip_tsadc_chip rk3368_tsadc_data = {
1212f7cef1b7SSebastian Reichel /* cpu, gpu */
1213f7cef1b7SSebastian Reichel .chn_offset = 0,
121420f0af75SCaesar Wang .chn_num = 2, /* two channels for tsadc */
121520f0af75SCaesar Wang
121620f0af75SCaesar Wang .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
121720f0af75SCaesar Wang .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
121820f0af75SCaesar Wang .tshut_temp = 95000,
121920f0af75SCaesar Wang
122020f0af75SCaesar Wang .initialize = rk_tsadcv2_initialize,
122120f0af75SCaesar Wang .irq_ack = rk_tsadcv2_irq_ack,
122220f0af75SCaesar Wang .control = rk_tsadcv2_control,
122320f0af75SCaesar Wang .get_temp = rk_tsadcv2_get_temp,
122414848502SCaesar Wang .set_alarm_temp = rk_tsadcv2_alarm_temp,
122520f0af75SCaesar Wang .set_tshut_temp = rk_tsadcv2_tshut_temp,
122620f0af75SCaesar Wang .set_tshut_mode = rk_tsadcv2_tshut_mode,
122720f0af75SCaesar Wang
122820f0af75SCaesar Wang .table = {
1229952418a3SCaesar Wang .id = rk3368_code_table,
1230952418a3SCaesar Wang .length = ARRAY_SIZE(rk3368_code_table),
123120f0af75SCaesar Wang .data_mask = TSADCV3_DATA_MASK,
123220f0af75SCaesar Wang .mode = ADC_INCREMENT,
123320f0af75SCaesar Wang },
123420f0af75SCaesar Wang };
123520f0af75SCaesar Wang
1236b0d70338SCaesar Wang static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
1237f7cef1b7SSebastian Reichel /* cpu, gpu */
1238f7cef1b7SSebastian Reichel .chn_offset = 0,
1239b0d70338SCaesar Wang .chn_num = 2, /* two channels for tsadc */
1240b0d70338SCaesar Wang
1241b0d70338SCaesar Wang .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
1242b0d70338SCaesar Wang .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
1243b0d70338SCaesar Wang .tshut_temp = 95000,
1244b0d70338SCaesar Wang
1245b9484763SCaesar Wang .initialize = rk_tsadcv3_initialize,
1246952418a3SCaesar Wang .irq_ack = rk_tsadcv3_irq_ack,
12477ea38c6cSCaesar Wang .control = rk_tsadcv3_control,
1248b0d70338SCaesar Wang .get_temp = rk_tsadcv2_get_temp,
124914848502SCaesar Wang .set_alarm_temp = rk_tsadcv2_alarm_temp,
1250b0d70338SCaesar Wang .set_tshut_temp = rk_tsadcv2_tshut_temp,
1251b0d70338SCaesar Wang .set_tshut_mode = rk_tsadcv2_tshut_mode,
1252b0d70338SCaesar Wang
1253b0d70338SCaesar Wang .table = {
1254952418a3SCaesar Wang .id = rk3399_code_table,
1255952418a3SCaesar Wang .length = ARRAY_SIZE(rk3399_code_table),
1256b0d70338SCaesar Wang .data_mask = TSADCV3_DATA_MASK,
12577ea38c6cSCaesar Wang .mode = ADC_INCREMENT,
1258b0d70338SCaesar Wang },
1259b0d70338SCaesar Wang };
1260b0d70338SCaesar Wang
126116bee043SFinley Xiao static const struct rockchip_tsadc_chip rk3568_tsadc_data = {
1262f7cef1b7SSebastian Reichel /* cpu, gpu */
1263f7cef1b7SSebastian Reichel .chn_offset = 0,
126416bee043SFinley Xiao .chn_num = 2, /* two channels for tsadc */
126516bee043SFinley Xiao
126616bee043SFinley Xiao .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
126716bee043SFinley Xiao .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
126816bee043SFinley Xiao .tshut_temp = 95000,
126916bee043SFinley Xiao
127016bee043SFinley Xiao .initialize = rk_tsadcv7_initialize,
127116bee043SFinley Xiao .irq_ack = rk_tsadcv3_irq_ack,
127216bee043SFinley Xiao .control = rk_tsadcv3_control,
127316bee043SFinley Xiao .get_temp = rk_tsadcv2_get_temp,
127416bee043SFinley Xiao .set_alarm_temp = rk_tsadcv2_alarm_temp,
127516bee043SFinley Xiao .set_tshut_temp = rk_tsadcv2_tshut_temp,
127616bee043SFinley Xiao .set_tshut_mode = rk_tsadcv2_tshut_mode,
127716bee043SFinley Xiao
127816bee043SFinley Xiao .table = {
127916bee043SFinley Xiao .id = rk3568_code_table,
128016bee043SFinley Xiao .length = ARRAY_SIZE(rk3568_code_table),
128116bee043SFinley Xiao .data_mask = TSADCV2_DATA_MASK,
128216bee043SFinley Xiao .mode = ADC_INCREMENT,
128316bee043SFinley Xiao },
128416bee043SFinley Xiao };
128516bee043SFinley Xiao
128645d7b386SFinley Xiao static const struct rockchip_tsadc_chip rk3588_tsadc_data = {
128745d7b386SFinley Xiao /* top, big_core0, big_core1, little_core, center, gpu, npu */
128845d7b386SFinley Xiao .chn_offset = 0,
128945d7b386SFinley Xiao .chn_num = 7, /* seven channels for tsadc */
129045d7b386SFinley Xiao .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
129145d7b386SFinley Xiao .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
129245d7b386SFinley Xiao .tshut_temp = 95000,
129345d7b386SFinley Xiao .initialize = rk_tsadcv8_initialize,
129445d7b386SFinley Xiao .irq_ack = rk_tsadcv4_irq_ack,
129545d7b386SFinley Xiao .control = rk_tsadcv4_control,
129645d7b386SFinley Xiao .get_temp = rk_tsadcv4_get_temp,
129745d7b386SFinley Xiao .set_alarm_temp = rk_tsadcv3_alarm_temp,
129845d7b386SFinley Xiao .set_tshut_temp = rk_tsadcv3_tshut_temp,
129945d7b386SFinley Xiao .set_tshut_mode = rk_tsadcv3_tshut_mode,
130045d7b386SFinley Xiao .table = {
130145d7b386SFinley Xiao .id = rk3588_code_table,
130245d7b386SFinley Xiao .length = ARRAY_SIZE(rk3588_code_table),
130345d7b386SFinley Xiao .data_mask = TSADCV4_DATA_MASK,
130445d7b386SFinley Xiao .mode = ADC_INCREMENT,
130545d7b386SFinley Xiao },
130645d7b386SFinley Xiao };
130745d7b386SFinley Xiao
1308cbac8f63SCaesar Wang static const struct of_device_id of_rockchip_thermal_match[] = {
1309ffd1b122SElaine Zhang { .compatible = "rockchip,px30-tsadc",
1310ffd1b122SElaine Zhang .data = (void *)&px30_tsadc_data,
1311ffd1b122SElaine Zhang },
1312cbac8f63SCaesar Wang {
13134eca8cacSRocky Hao .compatible = "rockchip,rv1108-tsadc",
13144eca8cacSRocky Hao .data = (void *)&rv1108_tsadc_data,
13154eca8cacSRocky Hao },
13164eca8cacSRocky Hao {
13177b02a5e7SCaesar Wang .compatible = "rockchip,rk3228-tsadc",
13187b02a5e7SCaesar Wang .data = (void *)&rk3228_tsadc_data,
13197b02a5e7SCaesar Wang },
13207b02a5e7SCaesar Wang {
1321cbac8f63SCaesar Wang .compatible = "rockchip,rk3288-tsadc",
1322cbac8f63SCaesar Wang .data = (void *)&rk3288_tsadc_data,
1323cbac8f63SCaesar Wang },
132420f0af75SCaesar Wang {
1325eda519d5SRocky Hao .compatible = "rockchip,rk3328-tsadc",
1326eda519d5SRocky Hao .data = (void *)&rk3328_tsadc_data,
1327eda519d5SRocky Hao },
1328eda519d5SRocky Hao {
13291cd60269SElaine Zhang .compatible = "rockchip,rk3366-tsadc",
13301cd60269SElaine Zhang .data = (void *)&rk3366_tsadc_data,
13311cd60269SElaine Zhang },
13321cd60269SElaine Zhang {
133320f0af75SCaesar Wang .compatible = "rockchip,rk3368-tsadc",
133420f0af75SCaesar Wang .data = (void *)&rk3368_tsadc_data,
133520f0af75SCaesar Wang },
1336b0d70338SCaesar Wang {
1337b0d70338SCaesar Wang .compatible = "rockchip,rk3399-tsadc",
1338b0d70338SCaesar Wang .data = (void *)&rk3399_tsadc_data,
1339b0d70338SCaesar Wang },
134016bee043SFinley Xiao {
134116bee043SFinley Xiao .compatible = "rockchip,rk3568-tsadc",
134216bee043SFinley Xiao .data = (void *)&rk3568_tsadc_data,
134316bee043SFinley Xiao },
134445d7b386SFinley Xiao {
134545d7b386SFinley Xiao .compatible = "rockchip,rk3588-tsadc",
134645d7b386SFinley Xiao .data = (void *)&rk3588_tsadc_data,
134745d7b386SFinley Xiao },
1348cbac8f63SCaesar Wang { /* end */ },
1349cbac8f63SCaesar Wang };
1350cbac8f63SCaesar Wang MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match);
1351cbac8f63SCaesar Wang
1352cbac8f63SCaesar Wang static void
rockchip_thermal_toggle_sensor(struct rockchip_thermal_sensor * sensor,bool on)1353cbac8f63SCaesar Wang rockchip_thermal_toggle_sensor(struct rockchip_thermal_sensor *sensor, bool on)
1354cbac8f63SCaesar Wang {
1355cbac8f63SCaesar Wang struct thermal_zone_device *tzd = sensor->tzd;
1356cbac8f63SCaesar Wang
13577f4957beSAndrzej Pietrasiewicz if (on)
13587f4957beSAndrzej Pietrasiewicz thermal_zone_device_enable(tzd);
13597f4957beSAndrzej Pietrasiewicz else
13607f4957beSAndrzej Pietrasiewicz thermal_zone_device_disable(tzd);
1361cbac8f63SCaesar Wang }
1362cbac8f63SCaesar Wang
rockchip_thermal_alarm_irq_thread(int irq,void * dev)1363cbac8f63SCaesar Wang static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
1364cbac8f63SCaesar Wang {
1365cbac8f63SCaesar Wang struct rockchip_thermal_data *thermal = dev;
1366cbac8f63SCaesar Wang int i;
1367cbac8f63SCaesar Wang
1368cbac8f63SCaesar Wang dev_dbg(&thermal->pdev->dev, "thermal alarm\n");
1369cbac8f63SCaesar Wang
1370cbac8f63SCaesar Wang thermal->chip->irq_ack(thermal->regs);
1371cbac8f63SCaesar Wang
13721d98b618SCaesar Wang for (i = 0; i < thermal->chip->chn_num; i++)
13730e70f466SSrinivas Pandruvada thermal_zone_device_update(thermal->sensors[i].tzd,
13740e70f466SSrinivas Pandruvada THERMAL_EVENT_UNSPECIFIED);
1375cbac8f63SCaesar Wang
1376cbac8f63SCaesar Wang return IRQ_HANDLED;
1377cbac8f63SCaesar Wang }
1378cbac8f63SCaesar Wang
rockchip_thermal_set_trips(struct thermal_zone_device * tz,int low,int high)137990b2ca02SDaniel Lezcano static int rockchip_thermal_set_trips(struct thermal_zone_device *tz, int low, int high)
138014848502SCaesar Wang {
13815f68d078SDaniel Lezcano struct rockchip_thermal_sensor *sensor = thermal_zone_device_priv(tz);
138214848502SCaesar Wang struct rockchip_thermal_data *thermal = sensor->thermal;
138314848502SCaesar Wang const struct rockchip_tsadc_chip *tsadc = thermal->chip;
138414848502SCaesar Wang
138514848502SCaesar Wang dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n",
138614848502SCaesar Wang __func__, sensor->id, low, high);
138714848502SCaesar Wang
1388d3530497SCaesar Wang return tsadc->set_alarm_temp(&tsadc->table,
138914848502SCaesar Wang sensor->id, thermal->regs, high);
139014848502SCaesar Wang }
139114848502SCaesar Wang
rockchip_thermal_get_temp(struct thermal_zone_device * tz,int * out_temp)139290b2ca02SDaniel Lezcano static int rockchip_thermal_get_temp(struct thermal_zone_device *tz, int *out_temp)
1393cbac8f63SCaesar Wang {
13945f68d078SDaniel Lezcano struct rockchip_thermal_sensor *sensor = thermal_zone_device_priv(tz);
1395cbac8f63SCaesar Wang struct rockchip_thermal_data *thermal = sensor->thermal;
1396cbac8f63SCaesar Wang const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip;
1397cbac8f63SCaesar Wang int retval;
1398cbac8f63SCaesar Wang
1399cdd8b3f7SBrian Norris retval = tsadc->get_temp(&tsadc->table,
1400ce74110dSCaesar Wang sensor->id, thermal->regs, out_temp);
1401cbac8f63SCaesar Wang return retval;
1402cbac8f63SCaesar Wang }
1403cbac8f63SCaesar Wang
140490b2ca02SDaniel Lezcano static const struct thermal_zone_device_ops rockchip_of_thermal_ops = {
1405cbac8f63SCaesar Wang .get_temp = rockchip_thermal_get_temp,
140614848502SCaesar Wang .set_trips = rockchip_thermal_set_trips,
1407cbac8f63SCaesar Wang };
1408cbac8f63SCaesar Wang
rockchip_configure_from_dt(struct device * dev,struct device_node * np,struct rockchip_thermal_data * thermal)1409cbac8f63SCaesar Wang static int rockchip_configure_from_dt(struct device *dev,
1410cbac8f63SCaesar Wang struct device_node *np,
1411cbac8f63SCaesar Wang struct rockchip_thermal_data *thermal)
1412cbac8f63SCaesar Wang {
1413cbac8f63SCaesar Wang u32 shut_temp, tshut_mode, tshut_polarity;
1414cbac8f63SCaesar Wang
1415cbac8f63SCaesar Wang if (of_property_read_u32(np, "rockchip,hw-tshut-temp", &shut_temp)) {
1416cbac8f63SCaesar Wang dev_warn(dev,
1417437df217SCaesar Wang "Missing tshut temp property, using default %d\n",
1418cbac8f63SCaesar Wang thermal->chip->tshut_temp);
1419cbac8f63SCaesar Wang thermal->tshut_temp = thermal->chip->tshut_temp;
1420cbac8f63SCaesar Wang } else {
142143b4eb9fSCaesar Wang if (shut_temp > INT_MAX) {
1422437df217SCaesar Wang dev_err(dev, "Invalid tshut temperature specified: %d\n",
142343b4eb9fSCaesar Wang shut_temp);
1424cbac8f63SCaesar Wang return -ERANGE;
1425cbac8f63SCaesar Wang }
142643b4eb9fSCaesar Wang thermal->tshut_temp = shut_temp;
142743b4eb9fSCaesar Wang }
1428cbac8f63SCaesar Wang
1429cbac8f63SCaesar Wang if (of_property_read_u32(np, "rockchip,hw-tshut-mode", &tshut_mode)) {
1430cbac8f63SCaesar Wang dev_warn(dev,
1431cbac8f63SCaesar Wang "Missing tshut mode property, using default (%s)\n",
1432cbac8f63SCaesar Wang thermal->chip->tshut_mode == TSHUT_MODE_GPIO ?
1433cbac8f63SCaesar Wang "gpio" : "cru");
1434cbac8f63SCaesar Wang thermal->tshut_mode = thermal->chip->tshut_mode;
1435cbac8f63SCaesar Wang } else {
1436cbac8f63SCaesar Wang thermal->tshut_mode = tshut_mode;
1437cbac8f63SCaesar Wang }
1438cbac8f63SCaesar Wang
1439cbac8f63SCaesar Wang if (thermal->tshut_mode > 1) {
1440cbac8f63SCaesar Wang dev_err(dev, "Invalid tshut mode specified: %d\n",
1441cbac8f63SCaesar Wang thermal->tshut_mode);
1442cbac8f63SCaesar Wang return -EINVAL;
1443cbac8f63SCaesar Wang }
1444cbac8f63SCaesar Wang
1445cbac8f63SCaesar Wang if (of_property_read_u32(np, "rockchip,hw-tshut-polarity",
1446cbac8f63SCaesar Wang &tshut_polarity)) {
1447cbac8f63SCaesar Wang dev_warn(dev,
1448cbac8f63SCaesar Wang "Missing tshut-polarity property, using default (%s)\n",
1449cbac8f63SCaesar Wang thermal->chip->tshut_polarity == TSHUT_LOW_ACTIVE ?
1450cbac8f63SCaesar Wang "low" : "high");
1451cbac8f63SCaesar Wang thermal->tshut_polarity = thermal->chip->tshut_polarity;
1452cbac8f63SCaesar Wang } else {
1453cbac8f63SCaesar Wang thermal->tshut_polarity = tshut_polarity;
1454cbac8f63SCaesar Wang }
1455cbac8f63SCaesar Wang
1456cbac8f63SCaesar Wang if (thermal->tshut_polarity > 1) {
1457cbac8f63SCaesar Wang dev_err(dev, "Invalid tshut-polarity specified: %d\n",
1458cbac8f63SCaesar Wang thermal->tshut_polarity);
1459cbac8f63SCaesar Wang return -EINVAL;
1460cbac8f63SCaesar Wang }
1461cbac8f63SCaesar Wang
1462b9484763SCaesar Wang /* The tsadc wont to handle the error in here since some SoCs didn't
1463b9484763SCaesar Wang * need this property.
1464b9484763SCaesar Wang */
1465b9484763SCaesar Wang thermal->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
1466ce62abaeSShawn Lin if (IS_ERR(thermal->grf))
1467ce62abaeSShawn Lin dev_warn(dev, "Missing rockchip,grf property\n");
1468b9484763SCaesar Wang
1469cbac8f63SCaesar Wang return 0;
1470cbac8f63SCaesar Wang }
1471cbac8f63SCaesar Wang
1472cbac8f63SCaesar Wang static int
rockchip_thermal_register_sensor(struct platform_device * pdev,struct rockchip_thermal_data * thermal,struct rockchip_thermal_sensor * sensor,int id)1473cbac8f63SCaesar Wang rockchip_thermal_register_sensor(struct platform_device *pdev,
1474cbac8f63SCaesar Wang struct rockchip_thermal_data *thermal,
1475cbac8f63SCaesar Wang struct rockchip_thermal_sensor *sensor,
14761d98b618SCaesar Wang int id)
1477cbac8f63SCaesar Wang {
1478cbac8f63SCaesar Wang const struct rockchip_tsadc_chip *tsadc = thermal->chip;
1479cbac8f63SCaesar Wang int error;
1480cbac8f63SCaesar Wang
1481cbac8f63SCaesar Wang tsadc->set_tshut_mode(id, thermal->regs, thermal->tshut_mode);
1482d3530497SCaesar Wang
1483d3530497SCaesar Wang error = tsadc->set_tshut_temp(&tsadc->table, id, thermal->regs,
1484ce74110dSCaesar Wang thermal->tshut_temp);
1485d3530497SCaesar Wang if (error)
1486d3530497SCaesar Wang dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n",
1487d3530497SCaesar Wang __func__, thermal->tshut_temp, error);
1488cbac8f63SCaesar Wang
1489cbac8f63SCaesar Wang sensor->thermal = thermal;
1490cbac8f63SCaesar Wang sensor->id = id;
149190b2ca02SDaniel Lezcano sensor->tzd = devm_thermal_of_zone_register(&pdev->dev, id, sensor,
149290b2ca02SDaniel Lezcano &rockchip_of_thermal_ops);
1493cbac8f63SCaesar Wang if (IS_ERR(sensor->tzd)) {
1494cbac8f63SCaesar Wang error = PTR_ERR(sensor->tzd);
1495cbac8f63SCaesar Wang dev_err(&pdev->dev, "failed to register sensor %d: %d\n",
1496cbac8f63SCaesar Wang id, error);
1497cbac8f63SCaesar Wang return error;
1498cbac8f63SCaesar Wang }
1499cbac8f63SCaesar Wang
1500cbac8f63SCaesar Wang return 0;
1501cbac8f63SCaesar Wang }
1502cbac8f63SCaesar Wang
150313c1cfdaSCaesar Wang /**
15046d5dad7bSRandy Dunlap * rockchip_thermal_reset_controller - Reset TSADC Controller, reset all tsadc registers.
150566ec4bfcSAmit Kucheria * @reset: the reset controller of tsadc
1506cbac8f63SCaesar Wang */
rockchip_thermal_reset_controller(struct reset_control * reset)1507cbac8f63SCaesar Wang static void rockchip_thermal_reset_controller(struct reset_control *reset)
1508cbac8f63SCaesar Wang {
1509cbac8f63SCaesar Wang reset_control_assert(reset);
1510cbac8f63SCaesar Wang usleep_range(10, 20);
1511cbac8f63SCaesar Wang reset_control_deassert(reset);
1512cbac8f63SCaesar Wang }
1513cbac8f63SCaesar Wang
rockchip_thermal_probe(struct platform_device * pdev)1514cbac8f63SCaesar Wang static int rockchip_thermal_probe(struct platform_device *pdev)
1515cbac8f63SCaesar Wang {
1516cbac8f63SCaesar Wang struct device_node *np = pdev->dev.of_node;
1517cbac8f63SCaesar Wang struct rockchip_thermal_data *thermal;
1518cbac8f63SCaesar Wang int irq;
15192633ad19SEduardo Valentin int i;
1520cbac8f63SCaesar Wang int error;
1521cbac8f63SCaesar Wang
1522cbac8f63SCaesar Wang irq = platform_get_irq(pdev, 0);
15238cb775bbSMarkus Elfring if (irq < 0)
1524cbac8f63SCaesar Wang return -EINVAL;
1525cbac8f63SCaesar Wang
1526cbac8f63SCaesar Wang thermal = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_thermal_data),
1527cbac8f63SCaesar Wang GFP_KERNEL);
1528cbac8f63SCaesar Wang if (!thermal)
1529cbac8f63SCaesar Wang return -ENOMEM;
1530cbac8f63SCaesar Wang
1531cbac8f63SCaesar Wang thermal->pdev = pdev;
1532cbac8f63SCaesar Wang
1533f1d2427cSSebastian Reichel thermal->chip = device_get_match_data(&pdev->dev);
1534cbac8f63SCaesar Wang if (!thermal->chip)
1535cbac8f63SCaesar Wang return -EINVAL;
1536cbac8f63SCaesar Wang
1537267f5965SSebastian Reichel thermal->sensors = devm_kcalloc(&pdev->dev, thermal->chip->chn_num,
1538267f5965SSebastian Reichel sizeof(*thermal->sensors), GFP_KERNEL);
1539267f5965SSebastian Reichel if (!thermal->sensors)
1540267f5965SSebastian Reichel return -ENOMEM;
1541267f5965SSebastian Reichel
15422484b632Sye xingchen thermal->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
1543cbac8f63SCaesar Wang if (IS_ERR(thermal->regs))
1544cbac8f63SCaesar Wang return PTR_ERR(thermal->regs);
1545cbac8f63SCaesar Wang
1546*fee5caecSYe Xingchen thermal->reset = devm_reset_control_array_get_exclusive(&pdev->dev);
1547cb71c5f9SSebastian Reichel if (IS_ERR(thermal->reset))
1548cb71c5f9SSebastian Reichel return dev_err_probe(&pdev->dev, PTR_ERR(thermal->reset),
1549cb71c5f9SSebastian Reichel "failed to get tsadc reset.\n");
1550cbac8f63SCaesar Wang
15512f6916f1SSebastian Reichel thermal->clk = devm_clk_get_enabled(&pdev->dev, "tsadc");
1552cb71c5f9SSebastian Reichel if (IS_ERR(thermal->clk))
1553cb71c5f9SSebastian Reichel return dev_err_probe(&pdev->dev, PTR_ERR(thermal->clk),
1554cb71c5f9SSebastian Reichel "failed to get tsadc clock.\n");
1555cbac8f63SCaesar Wang
15562f6916f1SSebastian Reichel thermal->pclk = devm_clk_get_enabled(&pdev->dev, "apb_pclk");
1557cb71c5f9SSebastian Reichel if (IS_ERR(thermal->pclk))
1558cb71c5f9SSebastian Reichel return dev_err_probe(&pdev->dev, PTR_ERR(thermal->pclk),
1559cb71c5f9SSebastian Reichel "failed to get apb_pclk clock.\n");
1560cbac8f63SCaesar Wang
1561cbac8f63SCaesar Wang rockchip_thermal_reset_controller(thermal->reset);
1562cbac8f63SCaesar Wang
1563cbac8f63SCaesar Wang error = rockchip_configure_from_dt(&pdev->dev, np, thermal);
1564cb71c5f9SSebastian Reichel if (error)
1565cb71c5f9SSebastian Reichel return dev_err_probe(&pdev->dev, error,
1566cb71c5f9SSebastian Reichel "failed to parse device tree data\n");
1567cbac8f63SCaesar Wang
1568b9484763SCaesar Wang thermal->chip->initialize(thermal->grf, thermal->regs,
1569b9484763SCaesar Wang thermal->tshut_polarity);
1570cbac8f63SCaesar Wang
15711d98b618SCaesar Wang for (i = 0; i < thermal->chip->chn_num; i++) {
1572cbac8f63SCaesar Wang error = rockchip_thermal_register_sensor(pdev, thermal,
15731d98b618SCaesar Wang &thermal->sensors[i],
1574f7cef1b7SSebastian Reichel thermal->chip->chn_offset + i);
1575cb71c5f9SSebastian Reichel if (error)
1576cb71c5f9SSebastian Reichel return dev_err_probe(&pdev->dev, error,
1577cb71c5f9SSebastian Reichel "failed to register sensor[%d].\n", i);
1578cbac8f63SCaesar Wang }
1579cbac8f63SCaesar Wang
1580cbac8f63SCaesar Wang error = devm_request_threaded_irq(&pdev->dev, irq, NULL,
1581cbac8f63SCaesar Wang &rockchip_thermal_alarm_irq_thread,
1582cbac8f63SCaesar Wang IRQF_ONESHOT,
1583cbac8f63SCaesar Wang "rockchip_thermal", thermal);
1584cb71c5f9SSebastian Reichel if (error)
1585cb71c5f9SSebastian Reichel return dev_err_probe(&pdev->dev, error,
1586cb71c5f9SSebastian Reichel "failed to request tsadc irq.\n");
1587cbac8f63SCaesar Wang
1588cbac8f63SCaesar Wang thermal->chip->control(thermal->regs, true);
1589cbac8f63SCaesar Wang
1590d27970b8SStefan Schaeckeler for (i = 0; i < thermal->chip->chn_num; i++) {
1591cbac8f63SCaesar Wang rockchip_thermal_toggle_sensor(&thermal->sensors[i], true);
1592d27970b8SStefan Schaeckeler error = thermal_add_hwmon_sysfs(thermal->sensors[i].tzd);
1593d27970b8SStefan Schaeckeler if (error)
1594d27970b8SStefan Schaeckeler dev_warn(&pdev->dev,
1595d27970b8SStefan Schaeckeler "failed to register sensor %d with hwmon: %d\n",
1596d27970b8SStefan Schaeckeler i, error);
1597d27970b8SStefan Schaeckeler }
1598cbac8f63SCaesar Wang
1599cbac8f63SCaesar Wang platform_set_drvdata(pdev, thermal);
1600cbac8f63SCaesar Wang
1601cbac8f63SCaesar Wang return 0;
1602cbac8f63SCaesar Wang }
1603cbac8f63SCaesar Wang
rockchip_thermal_remove(struct platform_device * pdev)1604cbac8f63SCaesar Wang static int rockchip_thermal_remove(struct platform_device *pdev)
1605cbac8f63SCaesar Wang {
1606cbac8f63SCaesar Wang struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev);
1607cbac8f63SCaesar Wang int i;
1608cbac8f63SCaesar Wang
16091d98b618SCaesar Wang for (i = 0; i < thermal->chip->chn_num; i++) {
1610cbac8f63SCaesar Wang struct rockchip_thermal_sensor *sensor = &thermal->sensors[i];
1611cbac8f63SCaesar Wang
1612d27970b8SStefan Schaeckeler thermal_remove_hwmon_sysfs(sensor->tzd);
1613cbac8f63SCaesar Wang rockchip_thermal_toggle_sensor(sensor, false);
1614cbac8f63SCaesar Wang }
1615cbac8f63SCaesar Wang
1616cbac8f63SCaesar Wang thermal->chip->control(thermal->regs, false);
1617cbac8f63SCaesar Wang
1618cbac8f63SCaesar Wang return 0;
1619cbac8f63SCaesar Wang }
1620cbac8f63SCaesar Wang
rockchip_thermal_suspend(struct device * dev)1621cbac8f63SCaesar Wang static int __maybe_unused rockchip_thermal_suspend(struct device *dev)
1622cbac8f63SCaesar Wang {
162326d84c27SWolfram Sang struct rockchip_thermal_data *thermal = dev_get_drvdata(dev);
1624cbac8f63SCaesar Wang int i;
1625cbac8f63SCaesar Wang
16261d98b618SCaesar Wang for (i = 0; i < thermal->chip->chn_num; i++)
1627cbac8f63SCaesar Wang rockchip_thermal_toggle_sensor(&thermal->sensors[i], false);
1628cbac8f63SCaesar Wang
1629cbac8f63SCaesar Wang thermal->chip->control(thermal->regs, false);
1630cbac8f63SCaesar Wang
1631cbac8f63SCaesar Wang clk_disable(thermal->pclk);
1632cbac8f63SCaesar Wang clk_disable(thermal->clk);
16330f5ee062SHeiko Stuebner
16340f5ee062SHeiko Stuebner pinctrl_pm_select_sleep_state(dev);
16357e38a5b1SCaesar Wang
1636cbac8f63SCaesar Wang return 0;
1637cbac8f63SCaesar Wang }
1638cbac8f63SCaesar Wang
rockchip_thermal_resume(struct device * dev)1639cbac8f63SCaesar Wang static int __maybe_unused rockchip_thermal_resume(struct device *dev)
1640cbac8f63SCaesar Wang {
164126d84c27SWolfram Sang struct rockchip_thermal_data *thermal = dev_get_drvdata(dev);
1642cbac8f63SCaesar Wang int i;
1643cbac8f63SCaesar Wang int error;
1644cbac8f63SCaesar Wang
1645cbac8f63SCaesar Wang error = clk_enable(thermal->clk);
1646cbac8f63SCaesar Wang if (error)
1647cbac8f63SCaesar Wang return error;
1648cbac8f63SCaesar Wang
1649cbac8f63SCaesar Wang error = clk_enable(thermal->pclk);
1650ab5b52f1SShawn Lin if (error) {
1651ab5b52f1SShawn Lin clk_disable(thermal->clk);
1652cbac8f63SCaesar Wang return error;
1653ab5b52f1SShawn Lin }
1654cbac8f63SCaesar Wang
1655cbac8f63SCaesar Wang rockchip_thermal_reset_controller(thermal->reset);
1656cbac8f63SCaesar Wang
1657b9484763SCaesar Wang thermal->chip->initialize(thermal->grf, thermal->regs,
1658b9484763SCaesar Wang thermal->tshut_polarity);
1659cbac8f63SCaesar Wang
16601d98b618SCaesar Wang for (i = 0; i < thermal->chip->chn_num; i++) {
16611d98b618SCaesar Wang int id = thermal->sensors[i].id;
1662cbac8f63SCaesar Wang
1663cbac8f63SCaesar Wang thermal->chip->set_tshut_mode(id, thermal->regs,
1664cbac8f63SCaesar Wang thermal->tshut_mode);
1665d3530497SCaesar Wang
1666d3530497SCaesar Wang error = thermal->chip->set_tshut_temp(&thermal->chip->table,
1667ce74110dSCaesar Wang id, thermal->regs,
1668cbac8f63SCaesar Wang thermal->tshut_temp);
1669d3530497SCaesar Wang if (error)
167026d84c27SWolfram Sang dev_err(dev, "%s: invalid tshut=%d, error=%d\n",
1671d3530497SCaesar Wang __func__, thermal->tshut_temp, error);
1672cbac8f63SCaesar Wang }
1673cbac8f63SCaesar Wang
1674cbac8f63SCaesar Wang thermal->chip->control(thermal->regs, true);
1675cbac8f63SCaesar Wang
16761d98b618SCaesar Wang for (i = 0; i < thermal->chip->chn_num; i++)
1677cbac8f63SCaesar Wang rockchip_thermal_toggle_sensor(&thermal->sensors[i], true);
1678cbac8f63SCaesar Wang
16790f5ee062SHeiko Stuebner pinctrl_pm_select_default_state(dev);
16807e38a5b1SCaesar Wang
1681cbac8f63SCaesar Wang return 0;
1682cbac8f63SCaesar Wang }
1683cbac8f63SCaesar Wang
1684cbac8f63SCaesar Wang static SIMPLE_DEV_PM_OPS(rockchip_thermal_pm_ops,
1685cbac8f63SCaesar Wang rockchip_thermal_suspend, rockchip_thermal_resume);
1686cbac8f63SCaesar Wang
1687cbac8f63SCaesar Wang static struct platform_driver rockchip_thermal_driver = {
1688cbac8f63SCaesar Wang .driver = {
1689cbac8f63SCaesar Wang .name = "rockchip-thermal",
1690cbac8f63SCaesar Wang .pm = &rockchip_thermal_pm_ops,
1691cbac8f63SCaesar Wang .of_match_table = of_rockchip_thermal_match,
1692cbac8f63SCaesar Wang },
1693cbac8f63SCaesar Wang .probe = rockchip_thermal_probe,
1694cbac8f63SCaesar Wang .remove = rockchip_thermal_remove,
1695cbac8f63SCaesar Wang };
1696cbac8f63SCaesar Wang
1697cbac8f63SCaesar Wang module_platform_driver(rockchip_thermal_driver);
1698cbac8f63SCaesar Wang
1699cbac8f63SCaesar Wang MODULE_DESCRIPTION("ROCKCHIP THERMAL Driver");
1700cbac8f63SCaesar Wang MODULE_AUTHOR("Rockchip, Inc.");
1701cbac8f63SCaesar Wang MODULE_LICENSE("GPL v2");
1702cbac8f63SCaesar Wang MODULE_ALIAS("platform:rockchip-thermal");
1703