1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2015, The Linux Foundation. All rights reserved.
4  */
5 
6 #include <linux/bitfield.h>
7 #include <linux/nvmem-consumer.h>
8 #include <linux/platform_device.h>
9 #include "tsens.h"
10 
11 /* ----- SROT ------ */
12 #define SROT_CTRL_OFF 0x0000
13 
14 /* ----- TM ------ */
15 #define TM_INT_EN_OFF				0x0000
16 #define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF	0x0004
17 #define TM_Sn_STATUS_OFF			0x0030
18 #define TM_TRDY_OFF				0x005c
19 
20 /* extra data for 8974 */
21 #define BKP_SEL			0x3
22 #define BKP_REDUN_SEL		0xe0000000
23 
24 #define BIT_APPEND		0x3
25 
26 struct tsens_legacy_calibration_format tsens_8916_nvmem = {
27 	.base_len = 7,
28 	.base_shift = 3,
29 	.sp_len = 5,
30 	.mode = { 0, 29, 1 },
31 	.invalid = { 0, 31, 1 },
32 	.base = { { 0, 0 }, { 1, 25 } },
33 	.sp = {
34 		{ { 0, 7 },  { 0, 12 } },
35 		{ { 0, 17 }, { 0, 22 } },
36 		{ { 0, 27 }, { 1, 0 } },
37 		{ { 1, 5 },  { 1, 10 } },
38 		{ { 1, 15 }, { 1, 20 } },
39 	},
40 };
41 
42 struct tsens_legacy_calibration_format tsens_8939_nvmem = {
43 	.base_len = 8,
44 	.base_shift = 2,
45 	.sp_len = 6,
46 	.mode = { 12, 0 },
47 	.invalid = { 12, 2 },
48 	.base = { { 0, 0 }, { 1, 24 } },
49 	.sp = {
50 		{ { 12, 3 },  { 12, 9 } },
51 		{ { 12, 15 }, { 12, 21 } },
52 		{ { 12, 27 }, { 13, 1 } },
53 		{ { 13, 7 },  { 13, 13 } },
54 		{ { 13, 19 }, { 13, 25 } },
55 		{ { 0, 8 },   { 0, 14 } },
56 		{ { 0, 20 },  { 0, 26 } },
57 		{ { 1, 0 },   { 1, 6 } },
58 		{ { 1, 12 },  { 1, 18 } },
59 	},
60 };
61 
62 struct tsens_legacy_calibration_format tsens_8974_nvmem = {
63 	.base_len = 8,
64 	.base_shift = 2,
65 	.sp_len = 6,
66 	.mode = { 1, 30 },
67 	.invalid = { 3, 30 },
68 	.base = { { 0, 0 }, { 2, 12 } },
69 	.sp = {
70 		{ { 0, 8 },  { 2, 20 } },
71 		{ { 0, 14 }, { 2, 26 } },
72 		{ { 0, 20 }, { 3, 0 } },
73 		{ { 0, 26 }, { 3, 6 } },
74 		{ { 1, 0 },  { 3, 12 } },
75 		{ { 1, 6 },  { 3, 18 } },
76 		{ { 1, 12 }, { 3, 24 } },
77 		{ { 1, 18 }, { 4, 0 } },
78 		{ { 1, 24 }, { 4, 6 } },
79 		{ { 2, 0 },  { 4, 12 } },
80 		{ { 2, 6 },  { 4, 18 } },
81 	},
82 };
83 
84 struct tsens_legacy_calibration_format tsens_8974_backup_nvmem = {
85 	.base_len = 8,
86 	.base_shift = 2,
87 	.sp_len = 6,
88 	.mode = { 4, 30, 1 },
89 	.invalid = { 5, 30, 1 },
90 	.base = { { 0, 0 }, { 2, 18 } },
91 	.sp = {
92 		{ { 0, 8 },  { 2, 26 } },
93 		{ { 0, 14 }, { 3, 0 } },
94 		{ { 0, 20 }, { 3, 6 } },
95 		{ { 0, 26 }, { 3, 12 } },
96 		{ { 1, 0 },  { 3, 18 } },
97 		{ { 1, 6 },  { 3, 24, 1 } },
98 		{ { 1, 12 }, { 4, 0, 1 } },
99 		{ { 1, 18 }, { 4, 6, 1 } },
100 		{ { 2, 0 },  { 4, 12, 1 } },
101 		{ { 2, 6 },  { 4, 18, 1 } },
102 		{ { 2, 12 }, { 4, 24, 1 } },
103 	},
104 };
105 
106 struct tsens_legacy_calibration_format tsens_9607_nvmem = {
107 	.base_len = 8,
108 	.base_shift = 2,
109 	.sp_len = 6,
110 	.mode = { 2, 20 },
111 	.invalid = { 2, 22 },
112 	.base = { { 0, 0 }, { 2, 12 } },
113 	.sp = {
114 		{ { 0, 8 },  { 0, 14 } },
115 		{ { 0, 20 }, { 0, 26 } },
116 		{ { 1, 0 },  { 1, 6 } },
117 		{ { 1, 12 }, { 1, 18 } },
118 		{ { 2, 0 },  { 2, 6 } },
119 	},
120 };
121 
122 static int calibrate_8916(struct tsens_priv *priv)
123 {
124 	u32 p1[5], p2[5];
125 	u32 *qfprom_cdata, *qfprom_csel;
126 	int mode, ret;
127 
128 	ret = tsens_calibrate_nvmem(priv, 3);
129 	if (!ret)
130 		return 0;
131 
132 	qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
133 	if (IS_ERR(qfprom_cdata))
134 		return PTR_ERR(qfprom_cdata);
135 
136 	qfprom_csel = (u32 *)qfprom_read(priv->dev, "calib_sel");
137 	if (IS_ERR(qfprom_csel)) {
138 		kfree(qfprom_cdata);
139 		return PTR_ERR(qfprom_csel);
140 	}
141 
142 	mode = tsens_read_calibration_legacy(priv, &tsens_8916_nvmem,
143 					     p1, p2,
144 					     qfprom_cdata, qfprom_csel);
145 
146 	compute_intercept_slope(priv, p1, p2, mode);
147 	kfree(qfprom_cdata);
148 	kfree(qfprom_csel);
149 
150 	return 0;
151 }
152 
153 static void fixup_8974_points(int mode, u32 *p1, u32 *p2)
154 {
155 	int i;
156 
157 	if (mode == NO_PT_CALIB) {
158 		p1[0] += 2;
159 		p1[1] += 9;
160 		p1[2] += 3;
161 		p1[3] += 9;
162 		p1[4] += 5;
163 		p1[5] += 9;
164 		p1[6] += 7;
165 		p1[7] += 10;
166 		p1[8] += 8;
167 		p1[9] += 9;
168 		p1[10] += 8;
169 	} else {
170 		for (i = 0; i < 11; i++) {
171 			/*
172 			 * ONE_PT_CALIB requires using addition here instead of
173 			 * using OR operation.
174 			 */
175 			p1[i] += BIT_APPEND;
176 			p2[i] += BIT_APPEND;
177 		}
178 	}
179 
180 }
181 
182 static int calibrate_8974_nvmem(struct tsens_priv *priv)
183 {
184 	u32 p1[11], p2[11];
185 	u32 backup;
186 	int ret, mode;
187 
188 	ret = nvmem_cell_read_variable_le_u32(priv->dev, "use_backup", &backup);
189 	if (ret == -ENOENT)
190 		dev_warn(priv->dev, "Please migrate to separate nvmem cells for calibration data\n");
191 	if (ret < 0)
192 		return ret;
193 
194 	mode = tsens_read_calibration(priv, 2, p1, p2, backup == BKP_SEL);
195 	if (mode < 0)
196 		return mode;
197 
198 	fixup_8974_points(mode, p1, p2);
199 
200 	compute_intercept_slope(priv, p1, p2, mode);
201 
202 	return 0;
203 }
204 
205 static int calibrate_8974(struct tsens_priv *priv)
206 {
207 	u32 p1[11], p2[11];
208 	u32 *calib, *bkp;
209 	u32 calib_redun_sel;
210 	int mode, ret;
211 
212 	ret = calibrate_8974_nvmem(priv);
213 	if (ret == 0)
214 		return 0;
215 
216 	calib = (u32 *)qfprom_read(priv->dev, "calib");
217 	if (IS_ERR(calib))
218 		return PTR_ERR(calib);
219 
220 	bkp = (u32 *)qfprom_read(priv->dev, "calib_backup");
221 	if (IS_ERR(bkp)) {
222 		kfree(calib);
223 		return PTR_ERR(bkp);
224 	}
225 
226 	calib_redun_sel = FIELD_GET(BKP_REDUN_SEL, bkp[1]);
227 
228 	if (calib_redun_sel == BKP_SEL)
229 		mode = tsens_read_calibration_legacy(priv, &tsens_8974_backup_nvmem,
230 						     p1, p2,
231 						     bkp, calib);
232 	else
233 		mode = tsens_read_calibration_legacy(priv, &tsens_8974_nvmem,
234 						     p1, p2,
235 						     calib, NULL);
236 
237 	fixup_8974_points(mode, p1, p2);
238 
239 	compute_intercept_slope(priv, p1, p2, mode);
240 	kfree(calib);
241 	kfree(bkp);
242 
243 	return 0;
244 }
245 
246 static int __init init_8939(struct tsens_priv *priv) {
247 	priv->sensor[0].slope = 2911;
248 	priv->sensor[1].slope = 2789;
249 	priv->sensor[2].slope = 2906;
250 	priv->sensor[3].slope = 2763;
251 	priv->sensor[4].slope = 2922;
252 	priv->sensor[5].slope = 2867;
253 	priv->sensor[6].slope = 2833;
254 	priv->sensor[7].slope = 2838;
255 	priv->sensor[8].slope = 2840;
256 	/* priv->sensor[9].slope = 2852; */
257 
258 	return init_common(priv);
259 }
260 
261 /* v0.1: 8916, 8939, 8974, 9607 */
262 
263 static struct tsens_features tsens_v0_1_feat = {
264 	.ver_major	= VER_0_1,
265 	.crit_int	= 0,
266 	.combo_int	= 0,
267 	.adc		= 1,
268 	.srot_split	= 1,
269 	.max_sensors	= 11,
270 	.trip_min_temp	= -40000,
271 	.trip_max_temp	= 120000,
272 };
273 
274 static const struct reg_field tsens_v0_1_regfields[MAX_REGFIELDS] = {
275 	/* ----- SROT ------ */
276 	/* No VERSION information */
277 
278 	/* CTRL_OFFSET */
279 	[TSENS_EN]     = REG_FIELD(SROT_CTRL_OFF, 0,  0),
280 	[TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1,  1),
281 
282 	/* ----- TM ------ */
283 	/* INTERRUPT ENABLE */
284 	[INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0),
285 
286 	/* UPPER/LOWER TEMPERATURE THRESHOLDS */
287 	REG_FIELD_FOR_EACH_SENSOR11(LOW_THRESH,    TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF,  0,  9),
288 	REG_FIELD_FOR_EACH_SENSOR11(UP_THRESH,     TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 10, 19),
289 
290 	/* UPPER/LOWER INTERRUPTS [CLEAR/STATUS] */
291 	REG_FIELD_FOR_EACH_SENSOR11(LOW_INT_CLEAR, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 20, 20),
292 	REG_FIELD_FOR_EACH_SENSOR11(UP_INT_CLEAR,  TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 21, 21),
293 
294 	/* NO CRITICAL INTERRUPT SUPPORT on v0.1 */
295 
296 	/* Sn_STATUS */
297 	REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP,    TM_Sn_STATUS_OFF,  0,  9),
298 	/* No VALID field on v0.1 */
299 	/* xxx_STATUS bits: 1 == threshold violated */
300 	REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS,   TM_Sn_STATUS_OFF, 10, 10),
301 	REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11),
302 	REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12),
303 	/* No CRITICAL field on v0.1 */
304 	REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS,   TM_Sn_STATUS_OFF, 13, 13),
305 
306 	/* TRDY: 1=ready, 0=in progress */
307 	[TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
308 };
309 
310 static const struct tsens_ops ops_v0_1 = {
311 	.init		= init_common,
312 	.calibrate	= tsens_calibrate_common,
313 	.get_temp	= get_temp_common,
314 };
315 
316 static const struct tsens_ops ops_8916 = {
317 	.init		= init_common,
318 	.calibrate	= calibrate_8916,
319 	.get_temp	= get_temp_common,
320 };
321 
322 struct tsens_plat_data data_8916 = {
323 	.num_sensors	= 5,
324 	.ops		= &ops_8916,
325 	.hw_ids		= (unsigned int []){0, 1, 2, 4, 5 },
326 
327 	.feat		= &tsens_v0_1_feat,
328 	.fields	= tsens_v0_1_regfields,
329 };
330 
331 static const struct tsens_ops ops_8939 = {
332 	.init		= init_8939,
333 	.calibrate	= tsens_calibrate_common,
334 	.get_temp	= get_temp_common,
335 };
336 
337 struct tsens_plat_data data_8939 = {
338 	.num_sensors	= 9,
339 	.ops		= &ops_8939,
340 	.hw_ids		= (unsigned int []){ 0, 1, 2, 3, 5, 6, 7, 8, 9, /* 10 */ },
341 
342 	.feat		= &tsens_v0_1_feat,
343 	.fields	= tsens_v0_1_regfields,
344 };
345 
346 static const struct tsens_ops ops_8974 = {
347 	.init		= init_common,
348 	.calibrate	= calibrate_8974,
349 	.get_temp	= get_temp_common,
350 };
351 
352 struct tsens_plat_data data_8974 = {
353 	.num_sensors	= 11,
354 	.ops		= &ops_8974,
355 	.feat		= &tsens_v0_1_feat,
356 	.fields	= tsens_v0_1_regfields,
357 };
358 
359 struct tsens_plat_data data_9607 = {
360 	.num_sensors	= 5,
361 	.ops		= &ops_v0_1,
362 	.feat		= &tsens_v0_1_feat,
363 	.fields	= tsens_v0_1_regfields,
364 };
365