xref: /linux/drivers/thermal/qcom/tsens-8960.c (revision 8c994eff8fcfe8ecb1f1dbebed25b4d7bb75be12)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2015, The Linux Foundation. All rights reserved.
4  */
5 
6 #include <linux/platform_device.h>
7 #include <linux/delay.h>
8 #include <linux/bitops.h>
9 #include <linux/regmap.h>
10 #include <linux/thermal.h>
11 #include "tsens.h"
12 
13 #define CONFIG_ADDR		0x3640
14 #define CONFIG_ADDR_8660	0x3620
15 /* CONFIG_ADDR bitmasks */
16 #define CONFIG			0x9b
17 #define CONFIG_MASK		0xf
18 #define CONFIG_8660		1
19 #define CONFIG_SHIFT_8660	28
20 #define CONFIG_MASK_8660	(3 << CONFIG_SHIFT_8660)
21 
22 #define CNTL_ADDR		0x3620
23 /* CNTL_ADDR bitmasks */
24 #define EN			BIT(0)
25 #define SW_RST			BIT(1)
26 
27 #define MEASURE_PERIOD		BIT(18)
28 #define SLP_CLK_ENA		BIT(26)
29 #define SLP_CLK_ENA_8660	BIT(24)
30 #define SENSOR0_SHIFT		3
31 
32 #define THRESHOLD_ADDR		0x3624
33 
34 #define INT_STATUS_ADDR		0x363c
35 
36 #define S0_STATUS_OFF		0x3628
37 #define S1_STATUS_OFF		0x362c
38 #define S2_STATUS_OFF		0x3630
39 #define S3_STATUS_OFF		0x3634
40 #define S4_STATUS_OFF		0x3638
41 #define S5_STATUS_OFF		0x3664  /* Sensors 5-10 found on apq8064/msm8960 */
42 #define S6_STATUS_OFF		0x3668
43 #define S7_STATUS_OFF		0x366c
44 #define S8_STATUS_OFF		0x3670
45 #define S9_STATUS_OFF		0x3674
46 #define S10_STATUS_OFF		0x3678
47 
48 /* Original slope - 350 to compensate mC to C inaccuracy */
49 static u32 tsens_msm8960_slope[] = {
50 			826, 826, 804, 826,
51 			761, 782, 782, 849,
52 			782, 849, 782
53 			};
54 
55 static int suspend_8960(struct tsens_priv *priv)
56 {
57 	int ret;
58 	unsigned int mask;
59 	struct regmap *map = priv->tm_map;
60 
61 	ret = regmap_read(map, THRESHOLD_ADDR, &priv->ctx.threshold);
62 	if (ret)
63 		return ret;
64 
65 	ret = regmap_read(map, CNTL_ADDR, &priv->ctx.control);
66 	if (ret)
67 		return ret;
68 
69 	if (priv->num_sensors > 1)
70 		mask = SLP_CLK_ENA | EN;
71 	else
72 		mask = SLP_CLK_ENA_8660 | EN;
73 
74 	ret = regmap_update_bits(map, CNTL_ADDR, mask, 0);
75 	if (ret)
76 		return ret;
77 
78 	return 0;
79 }
80 
81 static int resume_8960(struct tsens_priv *priv)
82 {
83 	int ret;
84 	struct regmap *map = priv->tm_map;
85 
86 	ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
87 	if (ret)
88 		return ret;
89 
90 	/*
91 	 * Separate CONFIG restore is not needed only for 8660 as
92 	 * config is part of CTRL Addr and its restored as such
93 	 */
94 	if (priv->num_sensors > 1) {
95 		ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
96 		if (ret)
97 			return ret;
98 	}
99 
100 	ret = regmap_write(map, THRESHOLD_ADDR, priv->ctx.threshold);
101 	if (ret)
102 		return ret;
103 
104 	ret = regmap_write(map, CNTL_ADDR, priv->ctx.control);
105 	if (ret)
106 		return ret;
107 
108 	return 0;
109 }
110 
111 static int enable_8960(struct tsens_priv *priv, int id)
112 {
113 	int ret;
114 	u32 reg, mask = BIT(id);
115 
116 	ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg);
117 	if (ret)
118 		return ret;
119 
120 	/* HARDWARE BUG:
121 	 * On platforms with more than 6 sensors, all remaining sensors
122 	 * must be enabled together, otherwise undefined results are expected.
123 	 * (Sensor 6-7 disabled, Sensor 3 disabled...) In the original driver,
124 	 * all the sensors are enabled in one step hence this bug is not
125 	 * triggered.
126 	 */
127 	if (id > 5)
128 		mask = GENMASK(10, 6);
129 
130 	mask <<= SENSOR0_SHIFT;
131 
132 	/* Sensors already enabled. Skip. */
133 	if ((reg & mask) == mask)
134 		return 0;
135 
136 	ret = regmap_write(priv->tm_map, CNTL_ADDR, reg | SW_RST);
137 	if (ret)
138 		return ret;
139 
140 	reg |= MEASURE_PERIOD;
141 
142 	if (priv->num_sensors > 1)
143 		reg |= mask | SLP_CLK_ENA | EN;
144 	else
145 		reg |= mask | SLP_CLK_ENA_8660 | EN;
146 
147 	ret = regmap_write(priv->tm_map, CNTL_ADDR, reg);
148 	if (ret)
149 		return ret;
150 
151 	return 0;
152 }
153 
154 static void disable_8960(struct tsens_priv *priv)
155 {
156 	int ret;
157 	u32 reg_cntl;
158 	u32 mask;
159 
160 	mask = GENMASK(priv->num_sensors - 1, 0);
161 	mask <<= SENSOR0_SHIFT;
162 	mask |= EN;
163 
164 	ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg_cntl);
165 	if (ret)
166 		return;
167 
168 	reg_cntl &= ~mask;
169 
170 	if (priv->num_sensors > 1)
171 		reg_cntl &= ~SLP_CLK_ENA;
172 	else
173 		reg_cntl &= ~SLP_CLK_ENA_8660;
174 
175 	regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
176 }
177 
178 static int calibrate_8960(struct tsens_priv *priv)
179 {
180 	int i;
181 	char *data;
182 	u32 p1[11];
183 
184 	data = qfprom_read(priv->dev, "calib");
185 	if (IS_ERR(data))
186 		data = qfprom_read(priv->dev, "calib_backup");
187 	if (IS_ERR(data))
188 		return PTR_ERR(data);
189 
190 	for (i = 0; i < priv->num_sensors; i++) {
191 		p1[i] = data[i];
192 		priv->sensor[i].slope = tsens_msm8960_slope[i];
193 	}
194 
195 	compute_intercept_slope(priv, p1, NULL, ONE_PT_CALIB);
196 
197 	kfree(data);
198 
199 	return 0;
200 }
201 
202 static const struct reg_field tsens_8960_regfields[MAX_REGFIELDS] = {
203 	/* ----- SROT ------ */
204 	/* No VERSION information */
205 
206 	/* CNTL */
207 	[TSENS_EN]     = REG_FIELD(CNTL_ADDR,  0, 0),
208 	[TSENS_SW_RST] = REG_FIELD(CNTL_ADDR,  1, 1),
209 	/* 8960 has 5 sensors, 8660 has 11, we only handle 5 */
210 	[SENSOR_EN]    = REG_FIELD(CNTL_ADDR,  3, 7),
211 
212 	/* ----- TM ------ */
213 	/* INTERRUPT ENABLE */
214 	/* NO INTERRUPT ENABLE */
215 
216 	/* Single UPPER/LOWER TEMPERATURE THRESHOLD for all sensors */
217 	[LOW_THRESH_0]   = REG_FIELD(THRESHOLD_ADDR,  0,  7),
218 	[UP_THRESH_0]    = REG_FIELD(THRESHOLD_ADDR,  8, 15),
219 	/* MIN_THRESH_0 and MAX_THRESH_0 are not present in the regfield
220 	 * Recycle CRIT_THRESH_0 and 1 to set the required regs to hardcoded temp
221 	 * MIN_THRESH_0 -> CRIT_THRESH_1
222 	 * MAX_THRESH_0 -> CRIT_THRESH_0
223 	 */
224 	[CRIT_THRESH_1]   = REG_FIELD(THRESHOLD_ADDR, 16, 23),
225 	[CRIT_THRESH_0]   = REG_FIELD(THRESHOLD_ADDR, 24, 31),
226 
227 	/* UPPER/LOWER INTERRUPT [CLEAR/STATUS] */
228 	/* 1 == clear, 0 == normal operation */
229 	[LOW_INT_CLEAR_0]   = REG_FIELD(CNTL_ADDR,  9,  9),
230 	[UP_INT_CLEAR_0]    = REG_FIELD(CNTL_ADDR, 10, 10),
231 
232 	/* NO CRITICAL INTERRUPT SUPPORT on 8960 */
233 
234 	/* Sn_STATUS */
235 	[LAST_TEMP_0]  = REG_FIELD(S0_STATUS_OFF,  0,  7),
236 	[LAST_TEMP_1]  = REG_FIELD(S1_STATUS_OFF,  0,  7),
237 	[LAST_TEMP_2]  = REG_FIELD(S2_STATUS_OFF,  0,  7),
238 	[LAST_TEMP_3]  = REG_FIELD(S3_STATUS_OFF,  0,  7),
239 	[LAST_TEMP_4]  = REG_FIELD(S4_STATUS_OFF,  0,  7),
240 	[LAST_TEMP_5]  = REG_FIELD(S5_STATUS_OFF,  0,  7),
241 	[LAST_TEMP_6]  = REG_FIELD(S6_STATUS_OFF,  0,  7),
242 	[LAST_TEMP_7]  = REG_FIELD(S7_STATUS_OFF,  0,  7),
243 	[LAST_TEMP_8]  = REG_FIELD(S8_STATUS_OFF,  0,  7),
244 	[LAST_TEMP_9]  = REG_FIELD(S9_STATUS_OFF,  0,  7),
245 	[LAST_TEMP_10] = REG_FIELD(S10_STATUS_OFF, 0,  7),
246 
247 	/* No VALID field on 8960 */
248 	/* TSENS_INT_STATUS bits: 1 == threshold violated */
249 	[MIN_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 0, 0),
250 	[LOWER_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 1, 1),
251 	[UPPER_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 2, 2),
252 	/* No CRITICAL field on 8960 */
253 	[MAX_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 3, 3),
254 
255 	/* TRDY: 1=ready, 0=in progress */
256 	[TRDY] = REG_FIELD(INT_STATUS_ADDR, 7, 7),
257 };
258 
259 static const struct tsens_ops ops_8960 = {
260 	.init		= init_common,
261 	.calibrate	= calibrate_8960,
262 	.get_temp	= get_temp_common,
263 	.enable		= enable_8960,
264 	.disable	= disable_8960,
265 	.suspend	= suspend_8960,
266 	.resume		= resume_8960,
267 };
268 
269 static struct tsens_features tsens_8960_feat = {
270 	.ver_major	= VER_0,
271 	.crit_int	= 0,
272 	.combo_int	= 0,
273 	.adc		= 1,
274 	.srot_split	= 0,
275 	.max_sensors	= 11,
276 	.trip_min_temp	= -40000,
277 	.trip_max_temp	= 120000,
278 };
279 
280 struct tsens_plat_data data_8960 = {
281 	.num_sensors	= 11,
282 	.ops		= &ops_8960,
283 	.feat		= &tsens_8960_feat,
284 	.fields		= tsens_8960_regfields,
285 };
286