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