Blame view

drivers/thermal/rockchip_thermal.c 38 KB
2025cf9e1   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
cbac8f639   Caesar Wang   thermal: rockchip...
2
  /*
678065d5b   Caesar Wang   thermal: rockchip...
3
   * Copyright (c) 2014-2016, Fuzhou Rockchip Electronics Co., Ltd
20f0af759   Caesar Wang   thermal: rockchip...
4
   * Caesar Wang <wxt@rock-chips.com>
cbac8f639   Caesar Wang   thermal: rockchip...
5
6
7
8
9
10
11
12
13
14
15
   */
  
  #include <linux/clk.h>
  #include <linux/delay.h>
  #include <linux/interrupt.h>
  #include <linux/io.h>
  #include <linux/module.h>
  #include <linux/of.h>
  #include <linux/of_address.h>
  #include <linux/of_irq.h>
  #include <linux/platform_device.h>
b94847632   Caesar Wang   thermal: rockchip...
16
  #include <linux/regmap.h>
cbac8f639   Caesar Wang   thermal: rockchip...
17
18
  #include <linux/reset.h>
  #include <linux/thermal.h>
b94847632   Caesar Wang   thermal: rockchip...
19
  #include <linux/mfd/syscon.h>
c970872e5   Caesar Wang   thermal: rockchip...
20
  #include <linux/pinctrl/consumer.h>
cbac8f639   Caesar Wang   thermal: rockchip...
21

66ec4bfcb   Amit Kucheria   thermal: rockchip...
22
  /*
cbac8f639   Caesar Wang   thermal: rockchip...
23
24
25
26
27
28
29
30
   * If the temperature over a period of time High,
   * the resulting TSHUT gave CRU module,let it reset the entire chip,
   * or via GPIO give PMIC.
   */
  enum tshut_mode {
  	TSHUT_MODE_CRU = 0,
  	TSHUT_MODE_GPIO,
  };
66ec4bfcb   Amit Kucheria   thermal: rockchip...
31
  /*
13c1cfda1   Caesar Wang   thermal: rockchip...
32
   * The system Temperature Sensors tshut(tshut) polarity
cbac8f639   Caesar Wang   thermal: rockchip...
33
34
35
36
37
38
39
   * the bit 8 is tshut polarity.
   * 0: low active, 1: high active
   */
  enum tshut_polarity {
  	TSHUT_LOW_ACTIVE = 0,
  	TSHUT_HIGH_ACTIVE,
  };
66ec4bfcb   Amit Kucheria   thermal: rockchip...
40
  /*
1d98b618c   Caesar Wang   thermal: rockchip...
41
42
   * The system has two Temperature Sensors.
   * sensor0 is for CPU, and sensor1 is for GPU.
cbac8f639   Caesar Wang   thermal: rockchip...
43
44
   */
  enum sensor_id {
1d98b618c   Caesar Wang   thermal: rockchip...
45
  	SENSOR_CPU = 0,
cbac8f639   Caesar Wang   thermal: rockchip...
46
47
  	SENSOR_GPU,
  };
66ec4bfcb   Amit Kucheria   thermal: rockchip...
48
  /*
13c1cfda1   Caesar Wang   thermal: rockchip...
49
   * The conversion table has the adc value and temperature.
952418a34   Caesar Wang   thermal: rockchip...
50
51
   * ADC_DECREMENT: the adc value is of diminishing.(e.g. rk3288_code_table)
   * ADC_INCREMENT: the adc value is incremental.(e.g. rk3368_code_table)
13c1cfda1   Caesar Wang   thermal: rockchip...
52
   */
020ba95db   Caesar Wang   thermal: rockchip...
53
54
55
56
  enum adc_sort_mode {
  	ADC_DECREMENT = 0,
  	ADC_INCREMENT,
  };
d27970b82   Stefan Schaeckeler   thermal: rockchip...
57
  #include "thermal_hwmon.h"
020ba95db   Caesar Wang   thermal: rockchip...
58
  /**
1d98b618c   Caesar Wang   thermal: rockchip...
59
60
61
62
   * The max sensors is two in rockchip SoCs.
   * Two sensors: CPU and GPU sensor.
   */
  #define SOC_MAX_SENSORS	2
13c1cfda1   Caesar Wang   thermal: rockchip...
63
  /**
678065d5b   Caesar Wang   thermal: rockchip...
64
   * struct chip_tsadc_table - hold information about chip-specific differences
13c1cfda1   Caesar Wang   thermal: rockchip...
65
66
67
68
69
   * @id: conversion table
   * @length: size of conversion table
   * @data_mask: mask to apply on data inputs
   * @mode: sort mode of this adc variant (incrementing or decrementing)
   */
ce74110d5   Caesar Wang   thermal: rockchip...
70
71
  struct chip_tsadc_table {
  	const struct tsadc_table *id;
ce74110d5   Caesar Wang   thermal: rockchip...
72
  	unsigned int length;
ce74110d5   Caesar Wang   thermal: rockchip...
73
  	u32 data_mask;
020ba95db   Caesar Wang   thermal: rockchip...
74
  	enum adc_sort_mode mode;
ce74110d5   Caesar Wang   thermal: rockchip...
75
  };
678065d5b   Caesar Wang   thermal: rockchip...
76
77
  /**
   * struct rockchip_tsadc_chip - hold the private data of tsadc chip
66ec4bfcb   Amit Kucheria   thermal: rockchip...
78
   * @chn_id: array of sensor ids of chip corresponding to the channel
678065d5b   Caesar Wang   thermal: rockchip...
79
80
81
82
83
84
   * @chn_num: the channel number of tsadc chip
   * @tshut_temp: the hardware-controlled shutdown temperature value
   * @tshut_mode: the hardware-controlled shutdown mode (0:CRU 1:GPIO)
   * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
   * @initialize: SoC special initialize tsadc controller method
   * @irq_ack: clear the interrupt
66ec4bfcb   Amit Kucheria   thermal: rockchip...
85
   * @control: enable/disable method for the tsadc controller
678065d5b   Caesar Wang   thermal: rockchip...
86
   * @get_temp: get the temperature
148485023   Caesar Wang   thermal: rockchip...
87
   * @set_alarm_temp: set the high temperature interrupt
678065d5b   Caesar Wang   thermal: rockchip...
88
89
90
91
   * @set_tshut_temp: set the hardware-controlled shutdown temperature
   * @set_tshut_mode: set the hardware-controlled shutdown mode
   * @table: the chip-specific conversion table
   */
cbac8f639   Caesar Wang   thermal: rockchip...
92
  struct rockchip_tsadc_chip {
1d98b618c   Caesar Wang   thermal: rockchip...
93
94
95
  	/* The sensor id of chip correspond to the ADC channel */
  	int chn_id[SOC_MAX_SENSORS];
  	int chn_num;
cbac8f639   Caesar Wang   thermal: rockchip...
96
  	/* The hardware-controlled tshut property */
437df2172   Caesar Wang   thermal: rockchip...
97
  	int tshut_temp;
cbac8f639   Caesar Wang   thermal: rockchip...
98
99
100
101
  	enum tshut_mode tshut_mode;
  	enum tshut_polarity tshut_polarity;
  
  	/* Chip-wide methods */
b94847632   Caesar Wang   thermal: rockchip...
102
103
  	void (*initialize)(struct regmap *grf,
  			   void __iomem *reg, enum tshut_polarity p);
cbac8f639   Caesar Wang   thermal: rockchip...
104
105
106
107
  	void (*irq_ack)(void __iomem *reg);
  	void (*control)(void __iomem *reg, bool on);
  
  	/* Per-sensor methods */
cdd8b3f7b   Brian Norris   thermal: rockchip...
108
  	int (*get_temp)(const struct chip_tsadc_table *table,
ce74110d5   Caesar Wang   thermal: rockchip...
109
  			int chn, void __iomem *reg, int *temp);
d3530497f   Caesar Wang   thermal: rockchip...
110
111
112
113
  	int (*set_alarm_temp)(const struct chip_tsadc_table *table,
  			      int chn, void __iomem *reg, int temp);
  	int (*set_tshut_temp)(const struct chip_tsadc_table *table,
  			      int chn, void __iomem *reg, int temp);
cbac8f639   Caesar Wang   thermal: rockchip...
114
  	void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
ce74110d5   Caesar Wang   thermal: rockchip...
115
116
117
  
  	/* Per-table methods */
  	struct chip_tsadc_table table;
cbac8f639   Caesar Wang   thermal: rockchip...
118
  };
678065d5b   Caesar Wang   thermal: rockchip...
119
120
121
122
123
124
  /**
   * struct rockchip_thermal_sensor - hold the information of thermal sensor
   * @thermal:  pointer to the platform/configuration data
   * @tzd: pointer to a thermal zone
   * @id: identifier of the thermal sensor
   */
cbac8f639   Caesar Wang   thermal: rockchip...
125
126
127
  struct rockchip_thermal_sensor {
  	struct rockchip_thermal_data *thermal;
  	struct thermal_zone_device *tzd;
1d98b618c   Caesar Wang   thermal: rockchip...
128
  	int id;
cbac8f639   Caesar Wang   thermal: rockchip...
129
  };
678065d5b   Caesar Wang   thermal: rockchip...
130
131
132
133
134
  /**
   * struct rockchip_thermal_data - hold the private data of thermal driver
   * @chip: pointer to the platform/configuration data
   * @pdev: platform device of thermal
   * @reset: the reset controller of tsadc
66ec4bfcb   Amit Kucheria   thermal: rockchip...
135
   * @sensors: array of thermal sensors
678065d5b   Caesar Wang   thermal: rockchip...
136
137
138
139
140
141
142
143
   * @clk: the controller clock is divided by the exteral 24MHz
   * @pclk: the advanced peripherals bus clock
   * @grf: the general register file will be used to do static set by software
   * @regs: the base address of tsadc controller
   * @tshut_temp: the hardware-controlled shutdown temperature value
   * @tshut_mode: the hardware-controlled shutdown mode (0:CRU 1:GPIO)
   * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
   */
cbac8f639   Caesar Wang   thermal: rockchip...
144
145
146
147
  struct rockchip_thermal_data {
  	const struct rockchip_tsadc_chip *chip;
  	struct platform_device *pdev;
  	struct reset_control *reset;
1d98b618c   Caesar Wang   thermal: rockchip...
148
  	struct rockchip_thermal_sensor sensors[SOC_MAX_SENSORS];
cbac8f639   Caesar Wang   thermal: rockchip...
149
150
151
  
  	struct clk *clk;
  	struct clk *pclk;
b94847632   Caesar Wang   thermal: rockchip...
152
  	struct regmap *grf;
cbac8f639   Caesar Wang   thermal: rockchip...
153
  	void __iomem *regs;
437df2172   Caesar Wang   thermal: rockchip...
154
  	int tshut_temp;
cbac8f639   Caesar Wang   thermal: rockchip...
155
156
157
  	enum tshut_mode tshut_mode;
  	enum tshut_polarity tshut_polarity;
  };
952418a34   Caesar Wang   thermal: rockchip...
158
159
160
161
162
163
164
  /**
   * TSADC Sensor Register description:
   *
   * TSADCV2_* are used for RK3288 SoCs, the other chips can reuse it.
   * TSADCV3_* are used for newer SoCs than RK3288. (e.g: RK3228, RK3399)
   *
   */
b94847632   Caesar Wang   thermal: rockchip...
165
  #define TSADCV2_USER_CON			0x00
cbac8f639   Caesar Wang   thermal: rockchip...
166
167
168
169
  #define TSADCV2_AUTO_CON			0x04
  #define TSADCV2_INT_EN				0x08
  #define TSADCV2_INT_PD				0x0c
  #define TSADCV2_DATA(chn)			(0x20 + (chn) * 0x04)
148485023   Caesar Wang   thermal: rockchip...
170
  #define TSADCV2_COMP_INT(chn)		        (0x30 + (chn) * 0x04)
cbac8f639   Caesar Wang   thermal: rockchip...
171
172
173
174
175
176
177
  #define TSADCV2_COMP_SHUT(chn)		        (0x40 + (chn) * 0x04)
  #define TSADCV2_HIGHT_INT_DEBOUNCE		0x60
  #define TSADCV2_HIGHT_TSHUT_DEBOUNCE		0x64
  #define TSADCV2_AUTO_PERIOD			0x68
  #define TSADCV2_AUTO_PERIOD_HT			0x6c
  
  #define TSADCV2_AUTO_EN				BIT(0)
cbac8f639   Caesar Wang   thermal: rockchip...
178
179
  #define TSADCV2_AUTO_SRC_EN(chn)		BIT(4 + (chn))
  #define TSADCV2_AUTO_TSHUT_POLARITY_HIGH	BIT(8)
678065d5b   Caesar Wang   thermal: rockchip...
180

7ea38c6c3   Caesar Wang   thermal: rockchip...
181
  #define TSADCV3_AUTO_Q_SEL_EN			BIT(1)
cbac8f639   Caesar Wang   thermal: rockchip...
182
183
184
185
  
  #define TSADCV2_INT_SRC_EN(chn)			BIT(chn)
  #define TSADCV2_SHUT_2GPIO_SRC_EN(chn)		BIT(4 + (chn))
  #define TSADCV2_SHUT_2CRU_SRC_EN(chn)		BIT(8 + (chn))
452e01b3d   Dmitry Torokhov   thermal: rockhip:...
186
  #define TSADCV2_INT_PD_CLEAR_MASK		~BIT(8)
952418a34   Caesar Wang   thermal: rockchip...
187
  #define TSADCV3_INT_PD_CLEAR_MASK		~BIT(16)
cbac8f639   Caesar Wang   thermal: rockchip...
188
189
  
  #define TSADCV2_DATA_MASK			0xfff
20f0af759   Caesar Wang   thermal: rockchip...
190
  #define TSADCV3_DATA_MASK			0x3ff
cbac8f639   Caesar Wang   thermal: rockchip...
191
192
  #define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT	4
  #define TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT	4
466678790   Caesar Wang   thermal: rockchip...
193
194
  #define TSADCV2_AUTO_PERIOD_TIME		250 /* 250ms */
  #define TSADCV2_AUTO_PERIOD_HT_TIME		50  /* 50ms */
5ef62de75   Rocky Hao   thermal: rockchip...
195
196
  #define TSADCV3_AUTO_PERIOD_TIME		1875 /* 2.5ms */
  #define TSADCV3_AUTO_PERIOD_HT_TIME		1875 /* 2.5ms */
466678790   Caesar Wang   thermal: rockchip...
197

b94847632   Caesar Wang   thermal: rockchip...
198
199
200
201
202
  #define TSADCV2_USER_INTER_PD_SOC		0x340 /* 13 clocks */
  
  #define GRF_SARADC_TESTBIT			0x0e644
  #define GRF_TSADC_TESTBIT_L			0x0e648
  #define GRF_TSADC_TESTBIT_H			0x0e64c
ffd1b122d   Elaine Zhang   thermal: rockchip...
203
  #define PX30_GRF_SOC_CON2			0x0408
b94847632   Caesar Wang   thermal: rockchip...
204
205
  #define GRF_SARADC_TESTBIT_ON			(0x10001 << 2)
  #define GRF_TSADC_TESTBIT_H_ON			(0x10001 << 2)
23f75e489   Rocky Hao   thermal: rockchip...
206
207
  #define GRF_TSADC_VCM_EN_L			(0x10001 << 7)
  #define GRF_TSADC_VCM_EN_H			(0x10001 << 7)
cbac8f639   Caesar Wang   thermal: rockchip...
208

ffd1b122d   Elaine Zhang   thermal: rockchip...
209
  #define GRF_CON_TSADC_CH_INV			(0x10001 << 1)
7b02a5e78   Caesar Wang   thermal: rockchip...
210
  /**
678065d5b   Caesar Wang   thermal: rockchip...
211
212
213
   * struct tsadc_table - code to temperature conversion table
   * @code: the value of adc channel
   * @temp: the temperature
7b02a5e78   Caesar Wang   thermal: rockchip...
214
   * Note:
678065d5b   Caesar Wang   thermal: rockchip...
215
   * code to temperature mapping of the temperature sensor is a piece wise linear
7b02a5e78   Caesar Wang   thermal: rockchip...
216
217
   * curve.Any temperature, code faling between to 2 give temperatures can be
   * linearly interpolated.
678065d5b   Caesar Wang   thermal: rockchip...
218
   * Code to Temperature mapping should be updated based on manufacturer results.
7b02a5e78   Caesar Wang   thermal: rockchip...
219
   */
678065d5b   Caesar Wang   thermal: rockchip...
220
221
222
223
  struct tsadc_table {
  	u32 code;
  	int temp;
  };
4eca8cac2   Rocky Hao   thermal: rockchip...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
  static const struct tsadc_table rv1108_table[] = {
  	{0, -40000},
  	{374, -40000},
  	{382, -35000},
  	{389, -30000},
  	{397, -25000},
  	{405, -20000},
  	{413, -15000},
  	{421, -10000},
  	{429, -5000},
  	{436, 0},
  	{444, 5000},
  	{452, 10000},
  	{460, 15000},
  	{468, 20000},
  	{476, 25000},
  	{483, 30000},
  	{491, 35000},
  	{499, 40000},
  	{507, 45000},
  	{515, 50000},
  	{523, 55000},
  	{531, 60000},
  	{539, 65000},
  	{547, 70000},
  	{555, 75000},
  	{562, 80000},
  	{570, 85000},
  	{578, 90000},
  	{586, 95000},
  	{594, 100000},
  	{602, 105000},
  	{610, 110000},
  	{618, 115000},
  	{626, 120000},
  	{634, 125000},
  	{TSADCV2_DATA_MASK, 125000},
  };
952418a34   Caesar Wang   thermal: rockchip...
262
  static const struct tsadc_table rk3228_code_table[] = {
7ea38c6c3   Caesar Wang   thermal: rockchip...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
  	{0, -40000},
  	{588, -40000},
  	{593, -35000},
  	{598, -30000},
  	{603, -25000},
  	{608, -20000},
  	{613, -15000},
  	{618, -10000},
  	{623, -5000},
  	{629, 0},
  	{634, 5000},
  	{639, 10000},
  	{644, 15000},
  	{649, 20000},
  	{654, 25000},
  	{660, 30000},
  	{665, 35000},
  	{670, 40000},
  	{675, 45000},
  	{681, 50000},
  	{686, 55000},
  	{691, 60000},
  	{696, 65000},
  	{702, 70000},
  	{707, 75000},
  	{712, 80000},
  	{717, 85000},
  	{723, 90000},
  	{728, 95000},
  	{733, 100000},
  	{738, 105000},
  	{744, 110000},
  	{749, 115000},
  	{754, 120000},
  	{760, 125000},
  	{TSADCV2_DATA_MASK, 125000},
7b02a5e78   Caesar Wang   thermal: rockchip...
299
  };
952418a34   Caesar Wang   thermal: rockchip...
300
  static const struct tsadc_table rk3288_code_table[] = {
cbac8f639   Caesar Wang   thermal: rockchip...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
  	{TSADCV2_DATA_MASK, -40000},
  	{3800, -40000},
  	{3792, -35000},
  	{3783, -30000},
  	{3774, -25000},
  	{3765, -20000},
  	{3756, -15000},
  	{3747, -10000},
  	{3737, -5000},
  	{3728, 0},
  	{3718, 5000},
  	{3708, 10000},
  	{3698, 15000},
  	{3688, 20000},
  	{3678, 25000},
  	{3667, 30000},
  	{3656, 35000},
  	{3645, 40000},
  	{3634, 45000},
  	{3623, 50000},
  	{3611, 55000},
  	{3600, 60000},
  	{3588, 65000},
  	{3575, 70000},
  	{3563, 75000},
  	{3550, 80000},
  	{3537, 85000},
  	{3524, 90000},
  	{3510, 95000},
  	{3496, 100000},
  	{3482, 105000},
  	{3467, 110000},
  	{3452, 115000},
  	{3437, 120000},
  	{3421, 125000},
cadf29dc2   Caesar Wang   thermal: rockchip...
336
  	{0, 125000},
cbac8f639   Caesar Wang   thermal: rockchip...
337
  };
eda519d5f   Rocky Hao   thermal: rockchip...
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
  static const struct tsadc_table rk3328_code_table[] = {
  	{0, -40000},
  	{296, -40000},
  	{304, -35000},
  	{313, -30000},
  	{331, -20000},
  	{340, -15000},
  	{349, -10000},
  	{359, -5000},
  	{368, 0},
  	{378, 5000},
  	{388, 10000},
  	{398, 15000},
  	{408, 20000},
  	{418, 25000},
  	{429, 30000},
  	{440, 35000},
  	{451, 40000},
  	{462, 45000},
  	{473, 50000},
  	{485, 55000},
  	{496, 60000},
  	{508, 65000},
  	{521, 70000},
  	{533, 75000},
  	{546, 80000},
  	{559, 85000},
  	{572, 90000},
  	{586, 95000},
  	{600, 100000},
  	{614, 105000},
  	{629, 110000},
  	{644, 115000},
  	{659, 120000},
  	{675, 125000},
  	{TSADCV2_DATA_MASK, 125000},
  };
952418a34   Caesar Wang   thermal: rockchip...
375
  static const struct tsadc_table rk3368_code_table[] = {
20f0af759   Caesar Wang   thermal: rockchip...
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
  	{0, -40000},
  	{106, -40000},
  	{108, -35000},
  	{110, -30000},
  	{112, -25000},
  	{114, -20000},
  	{116, -15000},
  	{118, -10000},
  	{120, -5000},
  	{122, 0},
  	{124, 5000},
  	{126, 10000},
  	{128, 15000},
  	{130, 20000},
  	{132, 25000},
  	{134, 30000},
  	{136, 35000},
  	{138, 40000},
  	{140, 45000},
  	{142, 50000},
  	{144, 55000},
  	{146, 60000},
  	{148, 65000},
  	{150, 70000},
  	{152, 75000},
  	{154, 80000},
  	{156, 85000},
  	{158, 90000},
  	{160, 95000},
  	{162, 100000},
  	{163, 105000},
  	{165, 110000},
  	{167, 115000},
  	{169, 120000},
  	{171, 125000},
  	{TSADCV3_DATA_MASK, 125000},
  };
952418a34   Caesar Wang   thermal: rockchip...
413
  static const struct tsadc_table rk3399_code_table[] = {
7ea38c6c3   Caesar Wang   thermal: rockchip...
414
  	{0, -40000},
f762a35d8   Caesar Wang   thermal: rockchip...
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
  	{402, -40000},
  	{410, -35000},
  	{419, -30000},
  	{427, -25000},
  	{436, -20000},
  	{444, -15000},
  	{453, -10000},
  	{461, -5000},
  	{470, 0},
  	{478, 5000},
  	{487, 10000},
  	{496, 15000},
  	{504, 20000},
  	{513, 25000},
  	{521, 30000},
  	{530, 35000},
  	{538, 40000},
  	{547, 45000},
  	{555, 50000},
  	{564, 55000},
  	{573, 60000},
  	{581, 65000},
  	{590, 70000},
  	{599, 75000},
  	{607, 80000},
  	{616, 85000},
  	{624, 90000},
  	{633, 95000},
  	{642, 100000},
  	{650, 105000},
  	{659, 110000},
  	{668, 115000},
  	{677, 120000},
  	{685, 125000},
7ea38c6c3   Caesar Wang   thermal: rockchip...
449
  	{TSADCV3_DATA_MASK, 125000},
b0d70338b   Caesar Wang   thermal: rockchip...
450
  };
cdd8b3f7b   Brian Norris   thermal: rockchip...
451
  static u32 rk_tsadcv2_temp_to_code(const struct chip_tsadc_table *table,
437df2172   Caesar Wang   thermal: rockchip...
452
  				   int temp)
cbac8f639   Caesar Wang   thermal: rockchip...
453
454
  {
  	int high, low, mid;
cadf29dc2   Caesar Wang   thermal: rockchip...
455
456
  	unsigned long num;
  	unsigned int denom;
d3530497f   Caesar Wang   thermal: rockchip...
457
  	u32 error = table->data_mask;
cbac8f639   Caesar Wang   thermal: rockchip...
458
459
  
  	low = 0;
cadf29dc2   Caesar Wang   thermal: rockchip...
460
  	high = (table->length - 1) - 1; /* ignore the last check for table */
cbac8f639   Caesar Wang   thermal: rockchip...
461
  	mid = (high + low) / 2;
1f09ba82f   Caesar Wang   thermal: rockchip...
462
  	/* Return mask code data when the temp is over table range */
d3530497f   Caesar Wang   thermal: rockchip...
463
  	if (temp < table->id[low].temp || temp > table->id[high].temp)
1f09ba82f   Caesar Wang   thermal: rockchip...
464
  		goto exit;
cbac8f639   Caesar Wang   thermal: rockchip...
465
466
  
  	while (low <= high) {
cdd8b3f7b   Brian Norris   thermal: rockchip...
467
468
469
  		if (temp == table->id[mid].temp)
  			return table->id[mid].code;
  		else if (temp < table->id[mid].temp)
cbac8f639   Caesar Wang   thermal: rockchip...
470
471
472
473
474
  			high = mid - 1;
  		else
  			low = mid + 1;
  		mid = (low + high) / 2;
  	}
cadf29dc2   Caesar Wang   thermal: rockchip...
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
  	/*
  	 * The conversion code granularity provided by the table. Let's
  	 * assume that the relationship between temperature and
  	 * analog value between 2 table entries is linear and interpolate
  	 * to produce less granular result.
  	 */
  	num = abs(table->id[mid + 1].code - table->id[mid].code);
  	num *= temp - table->id[mid].temp;
  	denom = table->id[mid + 1].temp - table->id[mid].temp;
  
  	switch (table->mode) {
  	case ADC_DECREMENT:
  		return table->id[mid].code - (num / denom);
  	case ADC_INCREMENT:
  		return table->id[mid].code + (num / denom);
  	default:
  		pr_err("%s: unknown table mode: %d
  ", __func__, table->mode);
  		return error;
  	}
1f09ba82f   Caesar Wang   thermal: rockchip...
495
  exit:
e6ed1b4ad   Brian Norris   thermal: rockchip...
496
497
498
  	pr_err("%s: invalid temperature, temp=%d error=%d
  ",
  	       __func__, temp, error);
1f09ba82f   Caesar Wang   thermal: rockchip...
499
  	return error;
cbac8f639   Caesar Wang   thermal: rockchip...
500
  }
cdd8b3f7b   Brian Norris   thermal: rockchip...
501
502
  static int rk_tsadcv2_code_to_temp(const struct chip_tsadc_table *table,
  				   u32 code, int *temp)
cbac8f639   Caesar Wang   thermal: rockchip...
503
  {
d9a241cbb   Dmitry Torokhov   thermal: rockchip...
504
  	unsigned int low = 1;
cdd8b3f7b   Brian Norris   thermal: rockchip...
505
  	unsigned int high = table->length - 1;
1e9a1aea7   Caesar Wang   thermal: rockchip...
506
507
508
  	unsigned int mid = (low + high) / 2;
  	unsigned int num;
  	unsigned long denom;
cdd8b3f7b   Brian Norris   thermal: rockchip...
509
  	WARN_ON(table->length < 2);
1e9a1aea7   Caesar Wang   thermal: rockchip...
510

cdd8b3f7b   Brian Norris   thermal: rockchip...
511
  	switch (table->mode) {
020ba95db   Caesar Wang   thermal: rockchip...
512
  	case ADC_DECREMENT:
cdd8b3f7b   Brian Norris   thermal: rockchip...
513
  		code &= table->data_mask;
db8318865   Caesar Wang   thermal: rockchip...
514
  		if (code <= table->id[high].code)
020ba95db   Caesar Wang   thermal: rockchip...
515
516
517
  			return -EAGAIN;		/* Incorrect reading */
  
  		while (low <= high) {
cdd8b3f7b   Brian Norris   thermal: rockchip...
518
519
  			if (code >= table->id[mid].code &&
  			    code < table->id[mid - 1].code)
020ba95db   Caesar Wang   thermal: rockchip...
520
  				break;
cdd8b3f7b   Brian Norris   thermal: rockchip...
521
  			else if (code < table->id[mid].code)
020ba95db   Caesar Wang   thermal: rockchip...
522
523
524
525
526
527
528
529
  				low = mid + 1;
  			else
  				high = mid - 1;
  
  			mid = (low + high) / 2;
  		}
  		break;
  	case ADC_INCREMENT:
cdd8b3f7b   Brian Norris   thermal: rockchip...
530
531
  		code &= table->data_mask;
  		if (code < table->id[low].code)
020ba95db   Caesar Wang   thermal: rockchip...
532
533
534
  			return -EAGAIN;		/* Incorrect reading */
  
  		while (low <= high) {
cdd8b3f7b   Brian Norris   thermal: rockchip...
535
536
  			if (code <= table->id[mid].code &&
  			    code > table->id[mid - 1].code)
020ba95db   Caesar Wang   thermal: rockchip...
537
  				break;
cdd8b3f7b   Brian Norris   thermal: rockchip...
538
  			else if (code > table->id[mid].code)
020ba95db   Caesar Wang   thermal: rockchip...
539
540
541
542
543
544
545
546
  				low = mid + 1;
  			else
  				high = mid - 1;
  
  			mid = (low + high) / 2;
  		}
  		break;
  	default:
cdd8b3f7b   Brian Norris   thermal: rockchip...
547
548
  		pr_err("%s: unknown table mode: %d
  ", __func__, table->mode);
e6ed1b4ad   Brian Norris   thermal: rockchip...
549
  		return -EINVAL;
cbac8f639   Caesar Wang   thermal: rockchip...
550
  	}
1e9a1aea7   Caesar Wang   thermal: rockchip...
551
552
553
554
555
556
  	/*
  	 * The 5C granularity provided by the table is too much. Let's
  	 * assume that the relationship between sensor readings and
  	 * temperature between 2 table entries is linear and interpolate
  	 * to produce less granular result.
  	 */
cdd8b3f7b   Brian Norris   thermal: rockchip...
557
558
559
560
  	num = table->id[mid].temp - table->id[mid - 1].temp;
  	num *= abs(table->id[mid - 1].code - code);
  	denom = abs(table->id[mid - 1].code - table->id[mid].code);
  	*temp = table->id[mid - 1].temp + (num / denom);
d9a241cbb   Dmitry Torokhov   thermal: rockchip...
561
562
  
  	return 0;
cbac8f639   Caesar Wang   thermal: rockchip...
563
564
565
  }
  
  /**
144c5565c   Caesar Wang   thermal: rockchip...
566
   * rk_tsadcv2_initialize - initialize TASDC Controller.
66ec4bfcb   Amit Kucheria   thermal: rockchip...
567
568
569
   * @grf: the general register file will be used to do static set by software
   * @regs: the base address of tsadc controller
   * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
144c5565c   Caesar Wang   thermal: rockchip...
570
571
572
573
574
575
576
577
578
579
580
581
   *
   * (1) Set TSADC_V2_AUTO_PERIOD:
   *     Configure the interleave between every two accessing of
   *     TSADC in normal operation.
   *
   * (2) Set TSADCV2_AUTO_PERIOD_HT:
   *     Configure the interleave between every two accessing of
   *     TSADC after the temperature is higher than COM_SHUT or COM_INT.
   *
   * (3) Set TSADCV2_HIGH_INT_DEBOUNCE and TSADC_HIGHT_TSHUT_DEBOUNCE:
   *     If the temperature is higher than COMP_INT or COMP_SHUT for
   *     "debounce" times, TSADC controller will generate interrupt or TSHUT.
cbac8f639   Caesar Wang   thermal: rockchip...
582
   */
b94847632   Caesar Wang   thermal: rockchip...
583
  static void rk_tsadcv2_initialize(struct regmap *grf, void __iomem *regs,
cbac8f639   Caesar Wang   thermal: rockchip...
584
585
586
  				  enum tshut_polarity tshut_polarity)
  {
  	if (tshut_polarity == TSHUT_HIGH_ACTIVE)
452e01b3d   Dmitry Torokhov   thermal: rockhip:...
587
  		writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
cbac8f639   Caesar Wang   thermal: rockchip...
588
589
  			       regs + TSADCV2_AUTO_CON);
  	else
452e01b3d   Dmitry Torokhov   thermal: rockhip:...
590
  		writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
cbac8f639   Caesar Wang   thermal: rockchip...
591
592
593
594
595
596
597
598
599
  			       regs + TSADCV2_AUTO_CON);
  
  	writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
  	writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
  		       regs + TSADCV2_HIGHT_INT_DEBOUNCE);
  	writel_relaxed(TSADCV2_AUTO_PERIOD_HT_TIME,
  		       regs + TSADCV2_AUTO_PERIOD_HT);
  	writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
  		       regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
b94847632   Caesar Wang   thermal: rockchip...
600
601
602
603
  }
  
  /**
   * rk_tsadcv3_initialize - initialize TASDC Controller.
66ec4bfcb   Amit Kucheria   thermal: rockchip...
604
605
606
   * @grf: the general register file will be used to do static set by software
   * @regs: the base address of tsadc controller
   * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
678065d5b   Caesar Wang   thermal: rockchip...
607
   *
b94847632   Caesar Wang   thermal: rockchip...
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
   * (1) The tsadc control power sequence.
   *
   * (2) Set TSADC_V2_AUTO_PERIOD:
   *     Configure the interleave between every two accessing of
   *     TSADC in normal operation.
   *
   * (2) Set TSADCV2_AUTO_PERIOD_HT:
   *     Configure the interleave between every two accessing of
   *     TSADC after the temperature is higher than COM_SHUT or COM_INT.
   *
   * (3) Set TSADCV2_HIGH_INT_DEBOUNCE and TSADC_HIGHT_TSHUT_DEBOUNCE:
   *     If the temperature is higher than COMP_INT or COMP_SHUT for
   *     "debounce" times, TSADC controller will generate interrupt or TSHUT.
   */
  static void rk_tsadcv3_initialize(struct regmap *grf, void __iomem *regs,
  				  enum tshut_polarity tshut_polarity)
  {
  	/* The tsadc control power sequence */
  	if (IS_ERR(grf)) {
  		/* Set interleave value to workround ic time sync issue */
  		writel_relaxed(TSADCV2_USER_INTER_PD_SOC, regs +
  			       TSADCV2_USER_CON);
466678790   Caesar Wang   thermal: rockchip...
630
631
632
633
634
635
636
637
638
  
  		writel_relaxed(TSADCV2_AUTO_PERIOD_TIME,
  			       regs + TSADCV2_AUTO_PERIOD);
  		writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
  			       regs + TSADCV2_HIGHT_INT_DEBOUNCE);
  		writel_relaxed(TSADCV2_AUTO_PERIOD_HT_TIME,
  			       regs + TSADCV2_AUTO_PERIOD_HT);
  		writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
  			       regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
b94847632   Caesar Wang   thermal: rockchip...
639
  	} else {
23f75e489   Rocky Hao   thermal: rockchip...
640
641
642
  		/* Enable the voltage common mode feature */
  		regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_VCM_EN_L);
  		regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_VCM_EN_H);
2fe5c1b04   Caesar Wang   thermal: rockchip...
643
  		usleep_range(15, 100); /* The spec note says at least 15 us */
b94847632   Caesar Wang   thermal: rockchip...
644
645
  		regmap_write(grf, GRF_SARADC_TESTBIT, GRF_SARADC_TESTBIT_ON);
  		regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_TESTBIT_H_ON);
2fe5c1b04   Caesar Wang   thermal: rockchip...
646
  		usleep_range(90, 200); /* The spec note says at least 90 us */
466678790   Caesar Wang   thermal: rockchip...
647
648
649
650
651
652
653
654
655
  
  		writel_relaxed(TSADCV3_AUTO_PERIOD_TIME,
  			       regs + TSADCV2_AUTO_PERIOD);
  		writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
  			       regs + TSADCV2_HIGHT_INT_DEBOUNCE);
  		writel_relaxed(TSADCV3_AUTO_PERIOD_HT_TIME,
  			       regs + TSADCV2_AUTO_PERIOD_HT);
  		writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
  			       regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
b94847632   Caesar Wang   thermal: rockchip...
656
657
658
659
660
661
662
663
  	}
  
  	if (tshut_polarity == TSHUT_HIGH_ACTIVE)
  		writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
  			       regs + TSADCV2_AUTO_CON);
  	else
  		writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
  			       regs + TSADCV2_AUTO_CON);
cbac8f639   Caesar Wang   thermal: rockchip...
664
  }
ffd1b122d   Elaine Zhang   thermal: rockchip...
665
666
667
668
669
670
  static void rk_tsadcv4_initialize(struct regmap *grf, void __iomem *regs,
  				  enum tshut_polarity tshut_polarity)
  {
  	rk_tsadcv2_initialize(grf, regs, tshut_polarity);
  	regmap_write(grf, PX30_GRF_SOC_CON2, GRF_CON_TSADC_CH_INV);
  }
952418a34   Caesar Wang   thermal: rockchip...
671
  static void rk_tsadcv2_irq_ack(void __iomem *regs)
7b02a5e78   Caesar Wang   thermal: rockchip...
672
673
674
675
  {
  	u32 val;
  
  	val = readl_relaxed(regs + TSADCV2_INT_PD);
952418a34   Caesar Wang   thermal: rockchip...
676
  	writel_relaxed(val & TSADCV2_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD);
7b02a5e78   Caesar Wang   thermal: rockchip...
677
  }
952418a34   Caesar Wang   thermal: rockchip...
678
  static void rk_tsadcv3_irq_ack(void __iomem *regs)
cbac8f639   Caesar Wang   thermal: rockchip...
679
680
681
682
  {
  	u32 val;
  
  	val = readl_relaxed(regs + TSADCV2_INT_PD);
952418a34   Caesar Wang   thermal: rockchip...
683
  	writel_relaxed(val & TSADCV3_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD);
cbac8f639   Caesar Wang   thermal: rockchip...
684
685
686
687
688
689
690
691
692
693
694
695
696
697
  }
  
  static void rk_tsadcv2_control(void __iomem *regs, bool enable)
  {
  	u32 val;
  
  	val = readl_relaxed(regs + TSADCV2_AUTO_CON);
  	if (enable)
  		val |= TSADCV2_AUTO_EN;
  	else
  		val &= ~TSADCV2_AUTO_EN;
  
  	writel_relaxed(val, regs + TSADCV2_AUTO_CON);
  }
7ea38c6c3   Caesar Wang   thermal: rockchip...
698
  /**
678065d5b   Caesar Wang   thermal: rockchip...
699
   * rk_tsadcv3_control - the tsadc controller is enabled or disabled.
66ec4bfcb   Amit Kucheria   thermal: rockchip...
700
701
   * @regs: the base address of tsadc controller
   * @enable: boolean flag to enable the controller
678065d5b   Caesar Wang   thermal: rockchip...
702
703
704
705
   *
   * NOTE: TSADC controller works at auto mode, and some SoCs need set the
   * tsadc_q_sel bit on TSADCV2_AUTO_CON[1]. The (1024 - tsadc_q) as output
   * adc value if setting this bit to enable.
7ea38c6c3   Caesar Wang   thermal: rockchip...
706
707
708
709
710
711
712
713
714
715
716
717
718
   */
  static void rk_tsadcv3_control(void __iomem *regs, bool enable)
  {
  	u32 val;
  
  	val = readl_relaxed(regs + TSADCV2_AUTO_CON);
  	if (enable)
  		val |= TSADCV2_AUTO_EN | TSADCV3_AUTO_Q_SEL_EN;
  	else
  		val &= ~TSADCV2_AUTO_EN;
  
  	writel_relaxed(val, regs + TSADCV2_AUTO_CON);
  }
cdd8b3f7b   Brian Norris   thermal: rockchip...
719
  static int rk_tsadcv2_get_temp(const struct chip_tsadc_table *table,
ce74110d5   Caesar Wang   thermal: rockchip...
720
  			       int chn, void __iomem *regs, int *temp)
cbac8f639   Caesar Wang   thermal: rockchip...
721
722
  {
  	u32 val;
cbac8f639   Caesar Wang   thermal: rockchip...
723
  	val = readl_relaxed(regs + TSADCV2_DATA(chn));
cbac8f639   Caesar Wang   thermal: rockchip...
724

ce74110d5   Caesar Wang   thermal: rockchip...
725
  	return rk_tsadcv2_code_to_temp(table, val, temp);
cbac8f639   Caesar Wang   thermal: rockchip...
726
  }
d3530497f   Caesar Wang   thermal: rockchip...
727
728
  static int rk_tsadcv2_alarm_temp(const struct chip_tsadc_table *table,
  				 int chn, void __iomem *regs, int temp)
148485023   Caesar Wang   thermal: rockchip...
729
  {
18591add4   Caesar Wang   thermal: rockchip...
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
  	u32 alarm_value;
  	u32 int_en, int_clr;
  
  	/*
  	 * In some cases, some sensors didn't need the trip points, the
  	 * set_trips will pass {-INT_MAX, INT_MAX} to trigger tsadc alarm
  	 * in the end, ignore this case and disable the high temperature
  	 * interrupt.
  	 */
  	if (temp == INT_MAX) {
  		int_clr = readl_relaxed(regs + TSADCV2_INT_EN);
  		int_clr &= ~TSADCV2_INT_SRC_EN(chn);
  		writel_relaxed(int_clr, regs + TSADCV2_INT_EN);
  		return 0;
  	}
148485023   Caesar Wang   thermal: rockchip...
745

1f09ba82f   Caesar Wang   thermal: rockchip...
746
  	/* Make sure the value is valid */
148485023   Caesar Wang   thermal: rockchip...
747
  	alarm_value = rk_tsadcv2_temp_to_code(table, temp);
cdd8b3f7b   Brian Norris   thermal: rockchip...
748
  	if (alarm_value == table->data_mask)
d3530497f   Caesar Wang   thermal: rockchip...
749
  		return -ERANGE;
1f09ba82f   Caesar Wang   thermal: rockchip...
750

cdd8b3f7b   Brian Norris   thermal: rockchip...
751
  	writel_relaxed(alarm_value & table->data_mask,
148485023   Caesar Wang   thermal: rockchip...
752
753
754
755
756
  		       regs + TSADCV2_COMP_INT(chn));
  
  	int_en = readl_relaxed(regs + TSADCV2_INT_EN);
  	int_en |= TSADCV2_INT_SRC_EN(chn);
  	writel_relaxed(int_en, regs + TSADCV2_INT_EN);
d3530497f   Caesar Wang   thermal: rockchip...
757
758
  
  	return 0;
148485023   Caesar Wang   thermal: rockchip...
759
  }
d3530497f   Caesar Wang   thermal: rockchip...
760
761
  static int rk_tsadcv2_tshut_temp(const struct chip_tsadc_table *table,
  				 int chn, void __iomem *regs, int temp)
cbac8f639   Caesar Wang   thermal: rockchip...
762
763
  {
  	u32 tshut_value, val;
1f09ba82f   Caesar Wang   thermal: rockchip...
764
  	/* Make sure the value is valid */
ce74110d5   Caesar Wang   thermal: rockchip...
765
  	tshut_value = rk_tsadcv2_temp_to_code(table, temp);
cdd8b3f7b   Brian Norris   thermal: rockchip...
766
  	if (tshut_value == table->data_mask)
d3530497f   Caesar Wang   thermal: rockchip...
767
  		return -ERANGE;
1f09ba82f   Caesar Wang   thermal: rockchip...
768

cbac8f639   Caesar Wang   thermal: rockchip...
769
770
771
772
773
  	writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn));
  
  	/* TSHUT will be valid */
  	val = readl_relaxed(regs + TSADCV2_AUTO_CON);
  	writel_relaxed(val | TSADCV2_AUTO_SRC_EN(chn), regs + TSADCV2_AUTO_CON);
d3530497f   Caesar Wang   thermal: rockchip...
774
775
  
  	return 0;
cbac8f639   Caesar Wang   thermal: rockchip...
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
  }
  
  static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs,
  				  enum tshut_mode mode)
  {
  	u32 val;
  
  	val = readl_relaxed(regs + TSADCV2_INT_EN);
  	if (mode == TSHUT_MODE_GPIO) {
  		val &= ~TSADCV2_SHUT_2CRU_SRC_EN(chn);
  		val |= TSADCV2_SHUT_2GPIO_SRC_EN(chn);
  	} else {
  		val &= ~TSADCV2_SHUT_2GPIO_SRC_EN(chn);
  		val |= TSADCV2_SHUT_2CRU_SRC_EN(chn);
  	}
  
  	writel_relaxed(val, regs + TSADCV2_INT_EN);
  }
ffd1b122d   Elaine Zhang   thermal: rockchip...
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
  static const struct rockchip_tsadc_chip px30_tsadc_data = {
  	.chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
  	.chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */
  	.chn_num = 2, /* 2 channels for tsadc */
  
  	.tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */
  	.tshut_temp = 95000,
  
  	.initialize = rk_tsadcv4_initialize,
  	.irq_ack = rk_tsadcv3_irq_ack,
  	.control = rk_tsadcv3_control,
  	.get_temp = rk_tsadcv2_get_temp,
  	.set_alarm_temp = rk_tsadcv2_alarm_temp,
  	.set_tshut_temp = rk_tsadcv2_tshut_temp,
  	.set_tshut_mode = rk_tsadcv2_tshut_mode,
  
  	.table = {
  		.id = rk3328_code_table,
  		.length = ARRAY_SIZE(rk3328_code_table),
  		.data_mask = TSADCV2_DATA_MASK,
  		.mode = ADC_INCREMENT,
  	},
  };
4eca8cac2   Rocky Hao   thermal: rockchip...
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
  static const struct rockchip_tsadc_chip rv1108_tsadc_data = {
  	.chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
  	.chn_num = 1, /* one channel for tsadc */
  
  	.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
  	.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
  	.tshut_temp = 95000,
  
  	.initialize = rk_tsadcv2_initialize,
  	.irq_ack = rk_tsadcv3_irq_ack,
  	.control = rk_tsadcv3_control,
  	.get_temp = rk_tsadcv2_get_temp,
  	.set_alarm_temp = rk_tsadcv2_alarm_temp,
  	.set_tshut_temp = rk_tsadcv2_tshut_temp,
  	.set_tshut_mode = rk_tsadcv2_tshut_mode,
  
  	.table = {
  		.id = rv1108_table,
  		.length = ARRAY_SIZE(rv1108_table),
  		.data_mask = TSADCV2_DATA_MASK,
  		.mode = ADC_INCREMENT,
  	},
  };
7b02a5e78   Caesar Wang   thermal: rockchip...
840
841
842
843
844
845
846
847
848
  static const struct rockchip_tsadc_chip rk3228_tsadc_data = {
  	.chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
  	.chn_num = 1, /* one channel for tsadc */
  
  	.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
  	.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
  	.tshut_temp = 95000,
  
  	.initialize = rk_tsadcv2_initialize,
952418a34   Caesar Wang   thermal: rockchip...
849
  	.irq_ack = rk_tsadcv3_irq_ack,
7ea38c6c3   Caesar Wang   thermal: rockchip...
850
  	.control = rk_tsadcv3_control,
7b02a5e78   Caesar Wang   thermal: rockchip...
851
  	.get_temp = rk_tsadcv2_get_temp,
148485023   Caesar Wang   thermal: rockchip...
852
  	.set_alarm_temp = rk_tsadcv2_alarm_temp,
7b02a5e78   Caesar Wang   thermal: rockchip...
853
854
855
856
  	.set_tshut_temp = rk_tsadcv2_tshut_temp,
  	.set_tshut_mode = rk_tsadcv2_tshut_mode,
  
  	.table = {
952418a34   Caesar Wang   thermal: rockchip...
857
858
  		.id = rk3228_code_table,
  		.length = ARRAY_SIZE(rk3228_code_table),
7b02a5e78   Caesar Wang   thermal: rockchip...
859
  		.data_mask = TSADCV3_DATA_MASK,
7ea38c6c3   Caesar Wang   thermal: rockchip...
860
  		.mode = ADC_INCREMENT,
7b02a5e78   Caesar Wang   thermal: rockchip...
861
862
  	},
  };
cbac8f639   Caesar Wang   thermal: rockchip...
863
  static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
1d98b618c   Caesar Wang   thermal: rockchip...
864
865
866
  	.chn_id[SENSOR_CPU] = 1, /* cpu sensor is channel 1 */
  	.chn_id[SENSOR_GPU] = 2, /* gpu sensor is channel 2 */
  	.chn_num = 2, /* two channels for tsadc */
cbac8f639   Caesar Wang   thermal: rockchip...
867
868
869
870
871
872
873
874
  	.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
  	.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
  	.tshut_temp = 95000,
  
  	.initialize = rk_tsadcv2_initialize,
  	.irq_ack = rk_tsadcv2_irq_ack,
  	.control = rk_tsadcv2_control,
  	.get_temp = rk_tsadcv2_get_temp,
148485023   Caesar Wang   thermal: rockchip...
875
  	.set_alarm_temp = rk_tsadcv2_alarm_temp,
cbac8f639   Caesar Wang   thermal: rockchip...
876
877
  	.set_tshut_temp = rk_tsadcv2_tshut_temp,
  	.set_tshut_mode = rk_tsadcv2_tshut_mode,
ce74110d5   Caesar Wang   thermal: rockchip...
878
879
  
  	.table = {
952418a34   Caesar Wang   thermal: rockchip...
880
881
  		.id = rk3288_code_table,
  		.length = ARRAY_SIZE(rk3288_code_table),
ce74110d5   Caesar Wang   thermal: rockchip...
882
  		.data_mask = TSADCV2_DATA_MASK,
020ba95db   Caesar Wang   thermal: rockchip...
883
  		.mode = ADC_DECREMENT,
ce74110d5   Caesar Wang   thermal: rockchip...
884
  	},
cbac8f639   Caesar Wang   thermal: rockchip...
885
  };
eda519d5f   Rocky Hao   thermal: rockchip...
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
  static const struct rockchip_tsadc_chip rk3328_tsadc_data = {
  	.chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
  	.chn_num = 1, /* one channels for tsadc */
  
  	.tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */
  	.tshut_temp = 95000,
  
  	.initialize = rk_tsadcv2_initialize,
  	.irq_ack = rk_tsadcv3_irq_ack,
  	.control = rk_tsadcv3_control,
  	.get_temp = rk_tsadcv2_get_temp,
  	.set_alarm_temp = rk_tsadcv2_alarm_temp,
  	.set_tshut_temp = rk_tsadcv2_tshut_temp,
  	.set_tshut_mode = rk_tsadcv2_tshut_mode,
  
  	.table = {
  		.id = rk3328_code_table,
  		.length = ARRAY_SIZE(rk3328_code_table),
  		.data_mask = TSADCV2_DATA_MASK,
  		.mode = ADC_INCREMENT,
  	},
  };
1cd602693   Elaine Zhang   thermal: rockchip...
908
909
910
911
912
913
914
915
916
917
918
919
920
  static const struct rockchip_tsadc_chip rk3366_tsadc_data = {
  	.chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
  	.chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */
  	.chn_num = 2, /* two channels for tsadc */
  
  	.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
  	.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
  	.tshut_temp = 95000,
  
  	.initialize = rk_tsadcv3_initialize,
  	.irq_ack = rk_tsadcv3_irq_ack,
  	.control = rk_tsadcv3_control,
  	.get_temp = rk_tsadcv2_get_temp,
148485023   Caesar Wang   thermal: rockchip...
921
  	.set_alarm_temp = rk_tsadcv2_alarm_temp,
1cd602693   Elaine Zhang   thermal: rockchip...
922
923
924
925
926
927
928
929
930
931
  	.set_tshut_temp = rk_tsadcv2_tshut_temp,
  	.set_tshut_mode = rk_tsadcv2_tshut_mode,
  
  	.table = {
  		.id = rk3228_code_table,
  		.length = ARRAY_SIZE(rk3228_code_table),
  		.data_mask = TSADCV3_DATA_MASK,
  		.mode = ADC_INCREMENT,
  	},
  };
20f0af759   Caesar Wang   thermal: rockchip...
932
933
934
935
936
937
938
939
940
941
942
943
944
  static const struct rockchip_tsadc_chip rk3368_tsadc_data = {
  	.chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
  	.chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */
  	.chn_num = 2, /* two channels for tsadc */
  
  	.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
  	.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
  	.tshut_temp = 95000,
  
  	.initialize = rk_tsadcv2_initialize,
  	.irq_ack = rk_tsadcv2_irq_ack,
  	.control = rk_tsadcv2_control,
  	.get_temp = rk_tsadcv2_get_temp,
148485023   Caesar Wang   thermal: rockchip...
945
  	.set_alarm_temp = rk_tsadcv2_alarm_temp,
20f0af759   Caesar Wang   thermal: rockchip...
946
947
948
949
  	.set_tshut_temp = rk_tsadcv2_tshut_temp,
  	.set_tshut_mode = rk_tsadcv2_tshut_mode,
  
  	.table = {
952418a34   Caesar Wang   thermal: rockchip...
950
951
  		.id = rk3368_code_table,
  		.length = ARRAY_SIZE(rk3368_code_table),
20f0af759   Caesar Wang   thermal: rockchip...
952
953
954
955
  		.data_mask = TSADCV3_DATA_MASK,
  		.mode = ADC_INCREMENT,
  	},
  };
b0d70338b   Caesar Wang   thermal: rockchip...
956
957
958
959
960
961
962
963
  static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
  	.chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
  	.chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */
  	.chn_num = 2, /* two channels for tsadc */
  
  	.tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
  	.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
  	.tshut_temp = 95000,
b94847632   Caesar Wang   thermal: rockchip...
964
  	.initialize = rk_tsadcv3_initialize,
952418a34   Caesar Wang   thermal: rockchip...
965
  	.irq_ack = rk_tsadcv3_irq_ack,
7ea38c6c3   Caesar Wang   thermal: rockchip...
966
  	.control = rk_tsadcv3_control,
b0d70338b   Caesar Wang   thermal: rockchip...
967
  	.get_temp = rk_tsadcv2_get_temp,
148485023   Caesar Wang   thermal: rockchip...
968
  	.set_alarm_temp = rk_tsadcv2_alarm_temp,
b0d70338b   Caesar Wang   thermal: rockchip...
969
970
971
972
  	.set_tshut_temp = rk_tsadcv2_tshut_temp,
  	.set_tshut_mode = rk_tsadcv2_tshut_mode,
  
  	.table = {
952418a34   Caesar Wang   thermal: rockchip...
973
974
  		.id = rk3399_code_table,
  		.length = ARRAY_SIZE(rk3399_code_table),
b0d70338b   Caesar Wang   thermal: rockchip...
975
  		.data_mask = TSADCV3_DATA_MASK,
7ea38c6c3   Caesar Wang   thermal: rockchip...
976
  		.mode = ADC_INCREMENT,
b0d70338b   Caesar Wang   thermal: rockchip...
977
978
  	},
  };
cbac8f639   Caesar Wang   thermal: rockchip...
979
  static const struct of_device_id of_rockchip_thermal_match[] = {
ffd1b122d   Elaine Zhang   thermal: rockchip...
980
981
982
  	{	.compatible = "rockchip,px30-tsadc",
  		.data = (void *)&px30_tsadc_data,
  	},
cbac8f639   Caesar Wang   thermal: rockchip...
983
  	{
4eca8cac2   Rocky Hao   thermal: rockchip...
984
985
986
987
  		.compatible = "rockchip,rv1108-tsadc",
  		.data = (void *)&rv1108_tsadc_data,
  	},
  	{
7b02a5e78   Caesar Wang   thermal: rockchip...
988
989
990
991
  		.compatible = "rockchip,rk3228-tsadc",
  		.data = (void *)&rk3228_tsadc_data,
  	},
  	{
cbac8f639   Caesar Wang   thermal: rockchip...
992
993
994
  		.compatible = "rockchip,rk3288-tsadc",
  		.data = (void *)&rk3288_tsadc_data,
  	},
20f0af759   Caesar Wang   thermal: rockchip...
995
  	{
eda519d5f   Rocky Hao   thermal: rockchip...
996
997
998
999
  		.compatible = "rockchip,rk3328-tsadc",
  		.data = (void *)&rk3328_tsadc_data,
  	},
  	{
1cd602693   Elaine Zhang   thermal: rockchip...
1000
1001
1002
1003
  		.compatible = "rockchip,rk3366-tsadc",
  		.data = (void *)&rk3366_tsadc_data,
  	},
  	{
20f0af759   Caesar Wang   thermal: rockchip...
1004
1005
1006
  		.compatible = "rockchip,rk3368-tsadc",
  		.data = (void *)&rk3368_tsadc_data,
  	},
b0d70338b   Caesar Wang   thermal: rockchip...
1007
1008
1009
1010
  	{
  		.compatible = "rockchip,rk3399-tsadc",
  		.data = (void *)&rk3399_tsadc_data,
  	},
cbac8f639   Caesar Wang   thermal: rockchip...
1011
1012
1013
1014
1015
1016
1017
1018
  	{ /* end */ },
  };
  MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match);
  
  static void
  rockchip_thermal_toggle_sensor(struct rockchip_thermal_sensor *sensor, bool on)
  {
  	struct thermal_zone_device *tzd = sensor->tzd;
7f4957be0   Andrzej Pietrasiewicz   thermal: Use mode...
1019
1020
1021
1022
  	if (on)
  		thermal_zone_device_enable(tzd);
  	else
  		thermal_zone_device_disable(tzd);
cbac8f639   Caesar Wang   thermal: rockchip...
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
  }
  
  static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
  {
  	struct rockchip_thermal_data *thermal = dev;
  	int i;
  
  	dev_dbg(&thermal->pdev->dev, "thermal alarm
  ");
  
  	thermal->chip->irq_ack(thermal->regs);
1d98b618c   Caesar Wang   thermal: rockchip...
1034
  	for (i = 0; i < thermal->chip->chn_num; i++)
0e70f466f   Srinivas Pandruvada   thermal: Enhance ...
1035
1036
  		thermal_zone_device_update(thermal->sensors[i].tzd,
  					   THERMAL_EVENT_UNSPECIFIED);
cbac8f639   Caesar Wang   thermal: rockchip...
1037
1038
1039
  
  	return IRQ_HANDLED;
  }
148485023   Caesar Wang   thermal: rockchip...
1040
1041
1042
1043
1044
1045
1046
1047
1048
  static int rockchip_thermal_set_trips(void *_sensor, int low, int high)
  {
  	struct rockchip_thermal_sensor *sensor = _sensor;
  	struct rockchip_thermal_data *thermal = sensor->thermal;
  	const struct rockchip_tsadc_chip *tsadc = thermal->chip;
  
  	dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d
  ",
  		__func__, sensor->id, low, high);
d3530497f   Caesar Wang   thermal: rockchip...
1049
1050
  	return tsadc->set_alarm_temp(&tsadc->table,
  				     sensor->id, thermal->regs, high);
148485023   Caesar Wang   thermal: rockchip...
1051
  }
17e8351a7   Sascha Hauer   thermal: consiste...
1052
  static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
cbac8f639   Caesar Wang   thermal: rockchip...
1053
1054
1055
1056
1057
  {
  	struct rockchip_thermal_sensor *sensor = _sensor;
  	struct rockchip_thermal_data *thermal = sensor->thermal;
  	const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip;
  	int retval;
cdd8b3f7b   Brian Norris   thermal: rockchip...
1058
  	retval = tsadc->get_temp(&tsadc->table,
ce74110d5   Caesar Wang   thermal: rockchip...
1059
  				 sensor->id, thermal->regs, out_temp);
17e8351a7   Sascha Hauer   thermal: consiste...
1060
1061
  	dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d
  ",
cbac8f639   Caesar Wang   thermal: rockchip...
1062
1063
1064
1065
1066
1067
1068
  		sensor->id, *out_temp, retval);
  
  	return retval;
  }
  
  static const struct thermal_zone_of_device_ops rockchip_of_thermal_ops = {
  	.get_temp = rockchip_thermal_get_temp,
148485023   Caesar Wang   thermal: rockchip...
1069
  	.set_trips = rockchip_thermal_set_trips,
cbac8f639   Caesar Wang   thermal: rockchip...
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
  };
  
  static int rockchip_configure_from_dt(struct device *dev,
  				      struct device_node *np,
  				      struct rockchip_thermal_data *thermal)
  {
  	u32 shut_temp, tshut_mode, tshut_polarity;
  
  	if (of_property_read_u32(np, "rockchip,hw-tshut-temp", &shut_temp)) {
  		dev_warn(dev,
437df2172   Caesar Wang   thermal: rockchip...
1080
1081
  			 "Missing tshut temp property, using default %d
  ",
cbac8f639   Caesar Wang   thermal: rockchip...
1082
1083
1084
  			 thermal->chip->tshut_temp);
  		thermal->tshut_temp = thermal->chip->tshut_temp;
  	} else {
43b4eb9fe   Caesar Wang   thermal: rockchip...
1085
1086
1087
1088
1089
1090
  		if (shut_temp > INT_MAX) {
  			dev_err(dev, "Invalid tshut temperature specified: %d
  ",
  				shut_temp);
  			return -ERANGE;
  		}
cbac8f639   Caesar Wang   thermal: rockchip...
1091
1092
  		thermal->tshut_temp = shut_temp;
  	}
cbac8f639   Caesar Wang   thermal: rockchip...
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
  	if (of_property_read_u32(np, "rockchip,hw-tshut-mode", &tshut_mode)) {
  		dev_warn(dev,
  			 "Missing tshut mode property, using default (%s)
  ",
  			 thermal->chip->tshut_mode == TSHUT_MODE_GPIO ?
  				"gpio" : "cru");
  		thermal->tshut_mode = thermal->chip->tshut_mode;
  	} else {
  		thermal->tshut_mode = tshut_mode;
  	}
  
  	if (thermal->tshut_mode > 1) {
  		dev_err(dev, "Invalid tshut mode specified: %d
  ",
  			thermal->tshut_mode);
  		return -EINVAL;
  	}
  
  	if (of_property_read_u32(np, "rockchip,hw-tshut-polarity",
  				 &tshut_polarity)) {
  		dev_warn(dev,
  			 "Missing tshut-polarity property, using default (%s)
  ",
  			 thermal->chip->tshut_polarity == TSHUT_LOW_ACTIVE ?
  				"low" : "high");
  		thermal->tshut_polarity = thermal->chip->tshut_polarity;
  	} else {
  		thermal->tshut_polarity = tshut_polarity;
  	}
  
  	if (thermal->tshut_polarity > 1) {
  		dev_err(dev, "Invalid tshut-polarity specified: %d
  ",
  			thermal->tshut_polarity);
  		return -EINVAL;
  	}
b94847632   Caesar Wang   thermal: rockchip...
1129
1130
1131
1132
  	/* The tsadc wont to handle the error in here since some SoCs didn't
  	 * need this property.
  	 */
  	thermal->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
ce62abaeb   Shawn Lin   thermal: rockchip...
1133
1134
1135
  	if (IS_ERR(thermal->grf))
  		dev_warn(dev, "Missing rockchip,grf property
  ");
b94847632   Caesar Wang   thermal: rockchip...
1136

cbac8f639   Caesar Wang   thermal: rockchip...
1137
1138
1139
1140
1141
1142
1143
  	return 0;
  }
  
  static int
  rockchip_thermal_register_sensor(struct platform_device *pdev,
  				 struct rockchip_thermal_data *thermal,
  				 struct rockchip_thermal_sensor *sensor,
1d98b618c   Caesar Wang   thermal: rockchip...
1144
  				 int id)
cbac8f639   Caesar Wang   thermal: rockchip...
1145
1146
1147
1148
1149
  {
  	const struct rockchip_tsadc_chip *tsadc = thermal->chip;
  	int error;
  
  	tsadc->set_tshut_mode(id, thermal->regs, thermal->tshut_mode);
d3530497f   Caesar Wang   thermal: rockchip...
1150
1151
  
  	error = tsadc->set_tshut_temp(&tsadc->table, id, thermal->regs,
ce74110d5   Caesar Wang   thermal: rockchip...
1152
  			      thermal->tshut_temp);
d3530497f   Caesar Wang   thermal: rockchip...
1153
1154
1155
1156
  	if (error)
  		dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d
  ",
  			__func__, thermal->tshut_temp, error);
cbac8f639   Caesar Wang   thermal: rockchip...
1157
1158
1159
  
  	sensor->thermal = thermal;
  	sensor->id = id;
2633ad191   Eduardo Valentin   thermal: convert ...
1160
1161
  	sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, id,
  					sensor, &rockchip_of_thermal_ops);
cbac8f639   Caesar Wang   thermal: rockchip...
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
  	if (IS_ERR(sensor->tzd)) {
  		error = PTR_ERR(sensor->tzd);
  		dev_err(&pdev->dev, "failed to register sensor %d: %d
  ",
  			id, error);
  		return error;
  	}
  
  	return 0;
  }
13c1cfda1   Caesar Wang   thermal: rockchip...
1172
  /**
cbac8f639   Caesar Wang   thermal: rockchip...
1173
   * Reset TSADC Controller, reset all tsadc registers.
66ec4bfcb   Amit Kucheria   thermal: rockchip...
1174
   * @reset: the reset controller of tsadc
cbac8f639   Caesar Wang   thermal: rockchip...
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
   */
  static void rockchip_thermal_reset_controller(struct reset_control *reset)
  {
  	reset_control_assert(reset);
  	usleep_range(10, 20);
  	reset_control_deassert(reset);
  }
  
  static int rockchip_thermal_probe(struct platform_device *pdev)
  {
  	struct device_node *np = pdev->dev.of_node;
  	struct rockchip_thermal_data *thermal;
  	const struct of_device_id *match;
  	struct resource *res;
  	int irq;
2633ad191   Eduardo Valentin   thermal: convert ...
1190
  	int i;
cbac8f639   Caesar Wang   thermal: rockchip...
1191
1192
1193
1194
1195
1196
1197
  	int error;
  
  	match = of_match_node(of_rockchip_thermal_match, np);
  	if (!match)
  		return -ENXIO;
  
  	irq = platform_get_irq(pdev, 0);
8cb775bb0   Markus Elfring   thermal: Delete a...
1198
  	if (irq < 0)
cbac8f639   Caesar Wang   thermal: rockchip...
1199
  		return -EINVAL;
cbac8f639   Caesar Wang   thermal: rockchip...
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
  
  	thermal = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_thermal_data),
  			       GFP_KERNEL);
  	if (!thermal)
  		return -ENOMEM;
  
  	thermal->pdev = pdev;
  
  	thermal->chip = (const struct rockchip_tsadc_chip *)match->data;
  	if (!thermal->chip)
  		return -EINVAL;
  
  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	thermal->regs = devm_ioremap_resource(&pdev->dev, res);
  	if (IS_ERR(thermal->regs))
  		return PTR_ERR(thermal->regs);
  
  	thermal->reset = devm_reset_control_get(&pdev->dev, "tsadc-apb");
  	if (IS_ERR(thermal->reset)) {
  		error = PTR_ERR(thermal->reset);
  		dev_err(&pdev->dev, "failed to get tsadc reset: %d
  ", error);
  		return error;
  	}
  
  	thermal->clk = devm_clk_get(&pdev->dev, "tsadc");
  	if (IS_ERR(thermal->clk)) {
  		error = PTR_ERR(thermal->clk);
  		dev_err(&pdev->dev, "failed to get tsadc clock: %d
  ", error);
  		return error;
  	}
  
  	thermal->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
  	if (IS_ERR(thermal->pclk)) {
0d0a2bf6e   Dan Carpenter   thermal: rockchip...
1235
  		error = PTR_ERR(thermal->pclk);
cbac8f639   Caesar Wang   thermal: rockchip...
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
  		dev_err(&pdev->dev, "failed to get apb_pclk clock: %d
  ",
  			error);
  		return error;
  	}
  
  	error = clk_prepare_enable(thermal->clk);
  	if (error) {
  		dev_err(&pdev->dev, "failed to enable converter clock: %d
  ",
  			error);
  		return error;
  	}
  
  	error = clk_prepare_enable(thermal->pclk);
  	if (error) {
  		dev_err(&pdev->dev, "failed to enable pclk: %d
  ", error);
  		goto err_disable_clk;
  	}
  
  	rockchip_thermal_reset_controller(thermal->reset);
  
  	error = rockchip_configure_from_dt(&pdev->dev, np, thermal);
  	if (error) {
  		dev_err(&pdev->dev, "failed to parse device tree data: %d
  ",
  			error);
  		goto err_disable_pclk;
  	}
b94847632   Caesar Wang   thermal: rockchip...
1266
1267
  	thermal->chip->initialize(thermal->grf, thermal->regs,
  				  thermal->tshut_polarity);
cbac8f639   Caesar Wang   thermal: rockchip...
1268

1d98b618c   Caesar Wang   thermal: rockchip...
1269
1270
1271
1272
1273
1274
1275
1276
1277
  	for (i = 0; i < thermal->chip->chn_num; i++) {
  		error = rockchip_thermal_register_sensor(pdev, thermal,
  						&thermal->sensors[i],
  						thermal->chip->chn_id[i]);
  		if (error) {
  			dev_err(&pdev->dev,
  				"failed to register sensor[%d] : error = %d
  ",
  				i, error);
1d98b618c   Caesar Wang   thermal: rockchip...
1278
1279
  			goto err_disable_pclk;
  		}
cbac8f639   Caesar Wang   thermal: rockchip...
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
  	}
  
  	error = devm_request_threaded_irq(&pdev->dev, irq, NULL,
  					  &rockchip_thermal_alarm_irq_thread,
  					  IRQF_ONESHOT,
  					  "rockchip_thermal", thermal);
  	if (error) {
  		dev_err(&pdev->dev,
  			"failed to request tsadc irq: %d
  ", error);
2633ad191   Eduardo Valentin   thermal: convert ...
1290
  		goto err_disable_pclk;
cbac8f639   Caesar Wang   thermal: rockchip...
1291
1292
1293
  	}
  
  	thermal->chip->control(thermal->regs, true);
d27970b82   Stefan Schaeckeler   thermal: rockchip...
1294
  	for (i = 0; i < thermal->chip->chn_num; i++) {
cbac8f639   Caesar Wang   thermal: rockchip...
1295
  		rockchip_thermal_toggle_sensor(&thermal->sensors[i], true);
d27970b82   Stefan Schaeckeler   thermal: rockchip...
1296
1297
1298
1299
1300
1301
1302
1303
  		thermal->sensors[i].tzd->tzp->no_hwmon = false;
  		error = thermal_add_hwmon_sysfs(thermal->sensors[i].tzd);
  		if (error)
  			dev_warn(&pdev->dev,
  				 "failed to register sensor %d with hwmon: %d
  ",
  				 i, error);
  	}
cbac8f639   Caesar Wang   thermal: rockchip...
1304
1305
1306
1307
  
  	platform_set_drvdata(pdev, thermal);
  
  	return 0;
cbac8f639   Caesar Wang   thermal: rockchip...
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
  err_disable_pclk:
  	clk_disable_unprepare(thermal->pclk);
  err_disable_clk:
  	clk_disable_unprepare(thermal->clk);
  
  	return error;
  }
  
  static int rockchip_thermal_remove(struct platform_device *pdev)
  {
  	struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev);
  	int i;
1d98b618c   Caesar Wang   thermal: rockchip...
1320
  	for (i = 0; i < thermal->chip->chn_num; i++) {
cbac8f639   Caesar Wang   thermal: rockchip...
1321
  		struct rockchip_thermal_sensor *sensor = &thermal->sensors[i];
d27970b82   Stefan Schaeckeler   thermal: rockchip...
1322
  		thermal_remove_hwmon_sysfs(sensor->tzd);
cbac8f639   Caesar Wang   thermal: rockchip...
1323
  		rockchip_thermal_toggle_sensor(sensor, false);
cbac8f639   Caesar Wang   thermal: rockchip...
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
  	}
  
  	thermal->chip->control(thermal->regs, false);
  
  	clk_disable_unprepare(thermal->pclk);
  	clk_disable_unprepare(thermal->clk);
  
  	return 0;
  }
  
  static int __maybe_unused rockchip_thermal_suspend(struct device *dev)
  {
26d84c276   Wolfram Sang   thermal: rockchip...
1336
  	struct rockchip_thermal_data *thermal = dev_get_drvdata(dev);
cbac8f639   Caesar Wang   thermal: rockchip...
1337
  	int i;
1d98b618c   Caesar Wang   thermal: rockchip...
1338
  	for (i = 0; i < thermal->chip->chn_num; i++)
cbac8f639   Caesar Wang   thermal: rockchip...
1339
1340
1341
1342
1343
1344
  		rockchip_thermal_toggle_sensor(&thermal->sensors[i], false);
  
  	thermal->chip->control(thermal->regs, false);
  
  	clk_disable(thermal->pclk);
  	clk_disable(thermal->clk);
0f5ee062d   Heiko Stuebner   Revert "thermal: ...
1345
1346
  
  	pinctrl_pm_select_sleep_state(dev);
7e38a5b1d   Caesar Wang   thermal: rockchip...
1347

cbac8f639   Caesar Wang   thermal: rockchip...
1348
1349
1350
1351
1352
  	return 0;
  }
  
  static int __maybe_unused rockchip_thermal_resume(struct device *dev)
  {
26d84c276   Wolfram Sang   thermal: rockchip...
1353
  	struct rockchip_thermal_data *thermal = dev_get_drvdata(dev);
cbac8f639   Caesar Wang   thermal: rockchip...
1354
1355
1356
1357
1358
1359
1360
1361
  	int i;
  	int error;
  
  	error = clk_enable(thermal->clk);
  	if (error)
  		return error;
  
  	error = clk_enable(thermal->pclk);
ab5b52f16   Shawn Lin   thermal: rockchip...
1362
1363
  	if (error) {
  		clk_disable(thermal->clk);
cbac8f639   Caesar Wang   thermal: rockchip...
1364
  		return error;
ab5b52f16   Shawn Lin   thermal: rockchip...
1365
  	}
cbac8f639   Caesar Wang   thermal: rockchip...
1366
1367
  
  	rockchip_thermal_reset_controller(thermal->reset);
b94847632   Caesar Wang   thermal: rockchip...
1368
1369
  	thermal->chip->initialize(thermal->grf, thermal->regs,
  				  thermal->tshut_polarity);
cbac8f639   Caesar Wang   thermal: rockchip...
1370

1d98b618c   Caesar Wang   thermal: rockchip...
1371
1372
  	for (i = 0; i < thermal->chip->chn_num; i++) {
  		int id = thermal->sensors[i].id;
cbac8f639   Caesar Wang   thermal: rockchip...
1373
1374
1375
  
  		thermal->chip->set_tshut_mode(id, thermal->regs,
  					      thermal->tshut_mode);
d3530497f   Caesar Wang   thermal: rockchip...
1376
1377
  
  		error = thermal->chip->set_tshut_temp(&thermal->chip->table,
ce74110d5   Caesar Wang   thermal: rockchip...
1378
  					      id, thermal->regs,
cbac8f639   Caesar Wang   thermal: rockchip...
1379
  					      thermal->tshut_temp);
d3530497f   Caesar Wang   thermal: rockchip...
1380
  		if (error)
26d84c276   Wolfram Sang   thermal: rockchip...
1381
1382
  			dev_err(dev, "%s: invalid tshut=%d, error=%d
  ",
d3530497f   Caesar Wang   thermal: rockchip...
1383
  				__func__, thermal->tshut_temp, error);
cbac8f639   Caesar Wang   thermal: rockchip...
1384
1385
1386
  	}
  
  	thermal->chip->control(thermal->regs, true);
1d98b618c   Caesar Wang   thermal: rockchip...
1387
  	for (i = 0; i < thermal->chip->chn_num; i++)
cbac8f639   Caesar Wang   thermal: rockchip...
1388
  		rockchip_thermal_toggle_sensor(&thermal->sensors[i], true);
0f5ee062d   Heiko Stuebner   Revert "thermal: ...
1389
  	pinctrl_pm_select_default_state(dev);
7e38a5b1d   Caesar Wang   thermal: rockchip...
1390

cbac8f639   Caesar Wang   thermal: rockchip...
1391
1392
1393
1394
1395
1396
1397
1398
1399
  	return 0;
  }
  
  static SIMPLE_DEV_PM_OPS(rockchip_thermal_pm_ops,
  			 rockchip_thermal_suspend, rockchip_thermal_resume);
  
  static struct platform_driver rockchip_thermal_driver = {
  	.driver = {
  		.name = "rockchip-thermal",
cbac8f639   Caesar Wang   thermal: rockchip...
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
  		.pm = &rockchip_thermal_pm_ops,
  		.of_match_table = of_rockchip_thermal_match,
  	},
  	.probe = rockchip_thermal_probe,
  	.remove = rockchip_thermal_remove,
  };
  
  module_platform_driver(rockchip_thermal_driver);
  
  MODULE_DESCRIPTION("ROCKCHIP THERMAL Driver");
  MODULE_AUTHOR("Rockchip, Inc.");
  MODULE_LICENSE("GPL v2");
  MODULE_ALIAS("platform:rockchip-thermal");