Commit | Line | Data |
---|---|---|
2d71d8de | 1 | // SPDX-License-Identifier: GPL-2.0 |
840a5bd3 RN |
2 | /* |
3 | * Copyright (c) 2015, The Linux Foundation. All rights reserved. | |
840a5bd3 RN |
4 | */ |
5 | ||
6 | #include <linux/platform_device.h> | |
7 | #include "tsens.h" | |
8 | ||
c1997054 AK |
9 | /* ----- SROT ------ */ |
10 | #define SROT_CTRL_OFF 0x0000 | |
11 | ||
12 | /* ----- TM ------ */ | |
13 | #define TM_INT_EN_OFF 0x0000 | |
14 | #define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004 | |
15 | #define TM_Sn_STATUS_OFF 0x0030 | |
16 | #define TM_TRDY_OFF 0x005c | |
17 | ||
840a5bd3 | 18 | /* eeprom layout data for 8916 */ |
774ccb08 AK |
19 | #define MSM8916_BASE0_MASK 0x0000007f |
20 | #define MSM8916_BASE1_MASK 0xfe000000 | |
21 | #define MSM8916_BASE0_SHIFT 0 | |
22 | #define MSM8916_BASE1_SHIFT 25 | |
23 | ||
24 | #define MSM8916_S0_P1_MASK 0x00000f80 | |
25 | #define MSM8916_S1_P1_MASK 0x003e0000 | |
26 | #define MSM8916_S2_P1_MASK 0xf8000000 | |
27 | #define MSM8916_S3_P1_MASK 0x000003e0 | |
28 | #define MSM8916_S4_P1_MASK 0x000f8000 | |
29 | ||
30 | #define MSM8916_S0_P2_MASK 0x0001f000 | |
31 | #define MSM8916_S1_P2_MASK 0x07c00000 | |
32 | #define MSM8916_S2_P2_MASK 0x0000001f | |
33 | #define MSM8916_S3_P2_MASK 0x00007c00 | |
34 | #define MSM8916_S4_P2_MASK 0x01f00000 | |
35 | ||
36 | #define MSM8916_S0_P1_SHIFT 7 | |
37 | #define MSM8916_S1_P1_SHIFT 17 | |
38 | #define MSM8916_S2_P1_SHIFT 27 | |
39 | #define MSM8916_S3_P1_SHIFT 5 | |
40 | #define MSM8916_S4_P1_SHIFT 15 | |
41 | ||
42 | #define MSM8916_S0_P2_SHIFT 12 | |
43 | #define MSM8916_S1_P2_SHIFT 22 | |
44 | #define MSM8916_S2_P2_SHIFT 0 | |
45 | #define MSM8916_S3_P2_SHIFT 10 | |
46 | #define MSM8916_S4_P2_SHIFT 20 | |
47 | ||
48 | #define MSM8916_CAL_SEL_MASK 0xe0000000 | |
49 | #define MSM8916_CAL_SEL_SHIFT 29 | |
840a5bd3 | 50 | |
582a0c41 AK |
51 | /* eeprom layout data for 8974 */ |
52 | #define BASE1_MASK 0xff | |
53 | #define S0_P1_MASK 0x3f00 | |
54 | #define S1_P1_MASK 0xfc000 | |
55 | #define S2_P1_MASK 0x3f00000 | |
56 | #define S3_P1_MASK 0xfc000000 | |
57 | #define S4_P1_MASK 0x3f | |
58 | #define S5_P1_MASK 0xfc0 | |
59 | #define S6_P1_MASK 0x3f000 | |
60 | #define S7_P1_MASK 0xfc0000 | |
61 | #define S8_P1_MASK 0x3f000000 | |
62 | #define S8_P1_MASK_BKP 0x3f | |
63 | #define S9_P1_MASK 0x3f | |
64 | #define S9_P1_MASK_BKP 0xfc0 | |
65 | #define S10_P1_MASK 0xfc0 | |
66 | #define S10_P1_MASK_BKP 0x3f000 | |
67 | #define CAL_SEL_0_1 0xc0000000 | |
68 | #define CAL_SEL_2 0x40000000 | |
69 | #define CAL_SEL_SHIFT 30 | |
70 | #define CAL_SEL_SHIFT_2 28 | |
71 | ||
72 | #define S0_P1_SHIFT 8 | |
73 | #define S1_P1_SHIFT 14 | |
74 | #define S2_P1_SHIFT 20 | |
75 | #define S3_P1_SHIFT 26 | |
76 | #define S5_P1_SHIFT 6 | |
77 | #define S6_P1_SHIFT 12 | |
78 | #define S7_P1_SHIFT 18 | |
79 | #define S8_P1_SHIFT 24 | |
80 | #define S9_P1_BKP_SHIFT 6 | |
81 | #define S10_P1_SHIFT 6 | |
82 | #define S10_P1_BKP_SHIFT 12 | |
83 | ||
84 | #define BASE2_SHIFT 12 | |
85 | #define BASE2_BKP_SHIFT 18 | |
86 | #define S0_P2_SHIFT 20 | |
87 | #define S0_P2_BKP_SHIFT 26 | |
88 | #define S1_P2_SHIFT 26 | |
89 | #define S2_P2_BKP_SHIFT 6 | |
90 | #define S3_P2_SHIFT 6 | |
91 | #define S3_P2_BKP_SHIFT 12 | |
92 | #define S4_P2_SHIFT 12 | |
93 | #define S4_P2_BKP_SHIFT 18 | |
94 | #define S5_P2_SHIFT 18 | |
95 | #define S5_P2_BKP_SHIFT 24 | |
96 | #define S6_P2_SHIFT 24 | |
97 | #define S7_P2_BKP_SHIFT 6 | |
98 | #define S8_P2_SHIFT 6 | |
99 | #define S8_P2_BKP_SHIFT 12 | |
100 | #define S9_P2_SHIFT 12 | |
101 | #define S9_P2_BKP_SHIFT 18 | |
102 | #define S10_P2_SHIFT 18 | |
103 | #define S10_P2_BKP_SHIFT 24 | |
104 | ||
105 | #define BASE2_MASK 0xff000 | |
106 | #define BASE2_BKP_MASK 0xfc0000 | |
107 | #define S0_P2_MASK 0x3f00000 | |
108 | #define S0_P2_BKP_MASK 0xfc000000 | |
109 | #define S1_P2_MASK 0xfc000000 | |
110 | #define S1_P2_BKP_MASK 0x3f | |
111 | #define S2_P2_MASK 0x3f | |
112 | #define S2_P2_BKP_MASK 0xfc0 | |
113 | #define S3_P2_MASK 0xfc0 | |
114 | #define S3_P2_BKP_MASK 0x3f000 | |
115 | #define S4_P2_MASK 0x3f000 | |
116 | #define S4_P2_BKP_MASK 0xfc0000 | |
117 | #define S5_P2_MASK 0xfc0000 | |
118 | #define S5_P2_BKP_MASK 0x3f000000 | |
119 | #define S6_P2_MASK 0x3f000000 | |
120 | #define S6_P2_BKP_MASK 0x3f | |
121 | #define S7_P2_MASK 0x3f | |
122 | #define S7_P2_BKP_MASK 0xfc0 | |
123 | #define S8_P2_MASK 0xfc0 | |
124 | #define S8_P2_BKP_MASK 0x3f000 | |
125 | #define S9_P2_MASK 0x3f000 | |
126 | #define S9_P2_BKP_MASK 0xfc0000 | |
127 | #define S10_P2_MASK 0xfc0000 | |
128 | #define S10_P2_BKP_MASK 0x3f000000 | |
129 | ||
130 | #define BKP_SEL 0x3 | |
131 | #define BKP_REDUN_SEL 0xe0000000 | |
132 | #define BKP_REDUN_SHIFT 29 | |
133 | ||
134 | #define BIT_APPEND 0x3 | |
135 | ||
69b628ac | 136 | static int calibrate_8916(struct tsens_priv *priv) |
840a5bd3 RN |
137 | { |
138 | int base0 = 0, base1 = 0, i; | |
139 | u32 p1[5], p2[5]; | |
140 | int mode = 0; | |
141 | u32 *qfprom_cdata, *qfprom_csel; | |
142 | ||
69b628ac | 143 | qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); |
840a5bd3 RN |
144 | if (IS_ERR(qfprom_cdata)) |
145 | return PTR_ERR(qfprom_cdata); | |
146 | ||
69b628ac | 147 | qfprom_csel = (u32 *)qfprom_read(priv->dev, "calib_sel"); |
6b8249ab SK |
148 | if (IS_ERR(qfprom_csel)) { |
149 | kfree(qfprom_cdata); | |
840a5bd3 | 150 | return PTR_ERR(qfprom_csel); |
6b8249ab | 151 | } |
840a5bd3 | 152 | |
774ccb08 | 153 | mode = (qfprom_csel[0] & MSM8916_CAL_SEL_MASK) >> MSM8916_CAL_SEL_SHIFT; |
69b628ac | 154 | dev_dbg(priv->dev, "calibration mode is %d\n", mode); |
840a5bd3 RN |
155 | |
156 | switch (mode) { | |
157 | case TWO_PT_CALIB: | |
774ccb08 AK |
158 | base1 = (qfprom_cdata[1] & MSM8916_BASE1_MASK) >> MSM8916_BASE1_SHIFT; |
159 | p2[0] = (qfprom_cdata[0] & MSM8916_S0_P2_MASK) >> MSM8916_S0_P2_SHIFT; | |
160 | p2[1] = (qfprom_cdata[0] & MSM8916_S1_P2_MASK) >> MSM8916_S1_P2_SHIFT; | |
161 | p2[2] = (qfprom_cdata[1] & MSM8916_S2_P2_MASK) >> MSM8916_S2_P2_SHIFT; | |
162 | p2[3] = (qfprom_cdata[1] & MSM8916_S3_P2_MASK) >> MSM8916_S3_P2_SHIFT; | |
163 | p2[4] = (qfprom_cdata[1] & MSM8916_S4_P2_MASK) >> MSM8916_S4_P2_SHIFT; | |
69b628ac | 164 | for (i = 0; i < priv->num_sensors; i++) |
840a5bd3 RN |
165 | p2[i] = ((base1 + p2[i]) << 3); |
166 | /* Fall through */ | |
167 | case ONE_PT_CALIB2: | |
774ccb08 AK |
168 | base0 = (qfprom_cdata[0] & MSM8916_BASE0_MASK); |
169 | p1[0] = (qfprom_cdata[0] & MSM8916_S0_P1_MASK) >> MSM8916_S0_P1_SHIFT; | |
170 | p1[1] = (qfprom_cdata[0] & MSM8916_S1_P1_MASK) >> MSM8916_S1_P1_SHIFT; | |
171 | p1[2] = (qfprom_cdata[0] & MSM8916_S2_P1_MASK) >> MSM8916_S2_P1_SHIFT; | |
172 | p1[3] = (qfprom_cdata[1] & MSM8916_S3_P1_MASK) >> MSM8916_S3_P1_SHIFT; | |
173 | p1[4] = (qfprom_cdata[1] & MSM8916_S4_P1_MASK) >> MSM8916_S4_P1_SHIFT; | |
69b628ac | 174 | for (i = 0; i < priv->num_sensors; i++) |
840a5bd3 RN |
175 | p1[i] = (((base0) + p1[i]) << 3); |
176 | break; | |
177 | default: | |
69b628ac | 178 | for (i = 0; i < priv->num_sensors; i++) { |
840a5bd3 RN |
179 | p1[i] = 500; |
180 | p2[i] = 780; | |
181 | } | |
182 | break; | |
183 | } | |
184 | ||
69b628ac | 185 | compute_intercept_slope(priv, p1, p2, mode); |
6b8249ab SK |
186 | kfree(qfprom_cdata); |
187 | kfree(qfprom_csel); | |
840a5bd3 RN |
188 | |
189 | return 0; | |
190 | } | |
191 | ||
582a0c41 AK |
192 | static int calibrate_8974(struct tsens_priv *priv) |
193 | { | |
194 | int base1 = 0, base2 = 0, i; | |
195 | u32 p1[11], p2[11]; | |
196 | int mode = 0; | |
197 | u32 *calib, *bkp; | |
198 | u32 calib_redun_sel; | |
199 | ||
200 | calib = (u32 *)qfprom_read(priv->dev, "calib"); | |
201 | if (IS_ERR(calib)) | |
202 | return PTR_ERR(calib); | |
203 | ||
204 | bkp = (u32 *)qfprom_read(priv->dev, "calib_backup"); | |
6b8249ab SK |
205 | if (IS_ERR(bkp)) { |
206 | kfree(calib); | |
582a0c41 | 207 | return PTR_ERR(bkp); |
6b8249ab | 208 | } |
582a0c41 AK |
209 | |
210 | calib_redun_sel = bkp[1] & BKP_REDUN_SEL; | |
211 | calib_redun_sel >>= BKP_REDUN_SHIFT; | |
212 | ||
213 | if (calib_redun_sel == BKP_SEL) { | |
214 | mode = (calib[4] & CAL_SEL_0_1) >> CAL_SEL_SHIFT; | |
215 | mode |= (calib[5] & CAL_SEL_2) >> CAL_SEL_SHIFT_2; | |
216 | ||
217 | switch (mode) { | |
218 | case TWO_PT_CALIB: | |
219 | base2 = (bkp[2] & BASE2_BKP_MASK) >> BASE2_BKP_SHIFT; | |
220 | p2[0] = (bkp[2] & S0_P2_BKP_MASK) >> S0_P2_BKP_SHIFT; | |
221 | p2[1] = (bkp[3] & S1_P2_BKP_MASK); | |
222 | p2[2] = (bkp[3] & S2_P2_BKP_MASK) >> S2_P2_BKP_SHIFT; | |
223 | p2[3] = (bkp[3] & S3_P2_BKP_MASK) >> S3_P2_BKP_SHIFT; | |
224 | p2[4] = (bkp[3] & S4_P2_BKP_MASK) >> S4_P2_BKP_SHIFT; | |
225 | p2[5] = (calib[4] & S5_P2_BKP_MASK) >> S5_P2_BKP_SHIFT; | |
226 | p2[6] = (calib[5] & S6_P2_BKP_MASK); | |
227 | p2[7] = (calib[5] & S7_P2_BKP_MASK) >> S7_P2_BKP_SHIFT; | |
228 | p2[8] = (calib[5] & S8_P2_BKP_MASK) >> S8_P2_BKP_SHIFT; | |
229 | p2[9] = (calib[5] & S9_P2_BKP_MASK) >> S9_P2_BKP_SHIFT; | |
230 | p2[10] = (calib[5] & S10_P2_BKP_MASK) >> S10_P2_BKP_SHIFT; | |
231 | /* Fall through */ | |
232 | case ONE_PT_CALIB: | |
233 | case ONE_PT_CALIB2: | |
234 | base1 = bkp[0] & BASE1_MASK; | |
235 | p1[0] = (bkp[0] & S0_P1_MASK) >> S0_P1_SHIFT; | |
236 | p1[1] = (bkp[0] & S1_P1_MASK) >> S1_P1_SHIFT; | |
237 | p1[2] = (bkp[0] & S2_P1_MASK) >> S2_P1_SHIFT; | |
238 | p1[3] = (bkp[0] & S3_P1_MASK) >> S3_P1_SHIFT; | |
239 | p1[4] = (bkp[1] & S4_P1_MASK); | |
240 | p1[5] = (bkp[1] & S5_P1_MASK) >> S5_P1_SHIFT; | |
241 | p1[6] = (bkp[1] & S6_P1_MASK) >> S6_P1_SHIFT; | |
242 | p1[7] = (bkp[1] & S7_P1_MASK) >> S7_P1_SHIFT; | |
243 | p1[8] = (bkp[2] & S8_P1_MASK_BKP) >> S8_P1_SHIFT; | |
244 | p1[9] = (bkp[2] & S9_P1_MASK_BKP) >> S9_P1_BKP_SHIFT; | |
245 | p1[10] = (bkp[2] & S10_P1_MASK_BKP) >> S10_P1_BKP_SHIFT; | |
246 | break; | |
247 | } | |
248 | } else { | |
249 | mode = (calib[1] & CAL_SEL_0_1) >> CAL_SEL_SHIFT; | |
250 | mode |= (calib[3] & CAL_SEL_2) >> CAL_SEL_SHIFT_2; | |
251 | ||
252 | switch (mode) { | |
253 | case TWO_PT_CALIB: | |
254 | base2 = (calib[2] & BASE2_MASK) >> BASE2_SHIFT; | |
255 | p2[0] = (calib[2] & S0_P2_MASK) >> S0_P2_SHIFT; | |
256 | p2[1] = (calib[2] & S1_P2_MASK) >> S1_P2_SHIFT; | |
257 | p2[2] = (calib[3] & S2_P2_MASK); | |
258 | p2[3] = (calib[3] & S3_P2_MASK) >> S3_P2_SHIFT; | |
259 | p2[4] = (calib[3] & S4_P2_MASK) >> S4_P2_SHIFT; | |
260 | p2[5] = (calib[3] & S5_P2_MASK) >> S5_P2_SHIFT; | |
261 | p2[6] = (calib[3] & S6_P2_MASK) >> S6_P2_SHIFT; | |
262 | p2[7] = (calib[4] & S7_P2_MASK); | |
263 | p2[8] = (calib[4] & S8_P2_MASK) >> S8_P2_SHIFT; | |
264 | p2[9] = (calib[4] & S9_P2_MASK) >> S9_P2_SHIFT; | |
265 | p2[10] = (calib[4] & S10_P2_MASK) >> S10_P2_SHIFT; | |
266 | /* Fall through */ | |
267 | case ONE_PT_CALIB: | |
268 | case ONE_PT_CALIB2: | |
269 | base1 = calib[0] & BASE1_MASK; | |
270 | p1[0] = (calib[0] & S0_P1_MASK) >> S0_P1_SHIFT; | |
271 | p1[1] = (calib[0] & S1_P1_MASK) >> S1_P1_SHIFT; | |
272 | p1[2] = (calib[0] & S2_P1_MASK) >> S2_P1_SHIFT; | |
273 | p1[3] = (calib[0] & S3_P1_MASK) >> S3_P1_SHIFT; | |
274 | p1[4] = (calib[1] & S4_P1_MASK); | |
275 | p1[5] = (calib[1] & S5_P1_MASK) >> S5_P1_SHIFT; | |
276 | p1[6] = (calib[1] & S6_P1_MASK) >> S6_P1_SHIFT; | |
277 | p1[7] = (calib[1] & S7_P1_MASK) >> S7_P1_SHIFT; | |
278 | p1[8] = (calib[1] & S8_P1_MASK) >> S8_P1_SHIFT; | |
279 | p1[9] = (calib[2] & S9_P1_MASK); | |
280 | p1[10] = (calib[2] & S10_P1_MASK) >> S10_P1_SHIFT; | |
281 | break; | |
282 | } | |
283 | } | |
284 | ||
285 | switch (mode) { | |
286 | case ONE_PT_CALIB: | |
287 | for (i = 0; i < priv->num_sensors; i++) | |
288 | p1[i] += (base1 << 2) | BIT_APPEND; | |
289 | break; | |
290 | case TWO_PT_CALIB: | |
291 | for (i = 0; i < priv->num_sensors; i++) { | |
292 | p2[i] += base2; | |
293 | p2[i] <<= 2; | |
294 | p2[i] |= BIT_APPEND; | |
295 | } | |
296 | /* Fall through */ | |
297 | case ONE_PT_CALIB2: | |
298 | for (i = 0; i < priv->num_sensors; i++) { | |
299 | p1[i] += base1; | |
300 | p1[i] <<= 2; | |
301 | p1[i] |= BIT_APPEND; | |
302 | } | |
303 | break; | |
304 | default: | |
305 | for (i = 0; i < priv->num_sensors; i++) | |
306 | p2[i] = 780; | |
307 | p1[0] = 502; | |
308 | p1[1] = 509; | |
309 | p1[2] = 503; | |
310 | p1[3] = 509; | |
311 | p1[4] = 505; | |
312 | p1[5] = 509; | |
313 | p1[6] = 507; | |
314 | p1[7] = 510; | |
315 | p1[8] = 508; | |
316 | p1[9] = 509; | |
317 | p1[10] = 508; | |
318 | break; | |
319 | } | |
320 | ||
321 | compute_intercept_slope(priv, p1, p2, mode); | |
6b8249ab SK |
322 | kfree(calib); |
323 | kfree(bkp); | |
582a0c41 AK |
324 | |
325 | return 0; | |
326 | } | |
327 | ||
c1997054 AK |
328 | /* v0.1: 8916, 8974 */ |
329 | ||
330 | static const struct tsens_features tsens_v0_1_feat = { | |
331 | .ver_major = VER_0_1, | |
332 | .crit_int = 0, | |
333 | .adc = 1, | |
334 | .srot_split = 1, | |
1b6e3e51 | 335 | .max_sensors = 11, |
c1997054 AK |
336 | }; |
337 | ||
338 | static const struct reg_field tsens_v0_1_regfields[MAX_REGFIELDS] = { | |
339 | /* ----- SROT ------ */ | |
340 | /* No VERSION information */ | |
341 | ||
342 | /* CTRL_OFFSET */ | |
343 | [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0), | |
344 | [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1), | |
345 | ||
346 | /* ----- TM ------ */ | |
347 | /* INTERRUPT ENABLE */ | |
348 | [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0), | |
349 | ||
350 | /* Sn_STATUS */ | |
351 | REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 9), | |
352 | /* No VALID field on v0.1 */ | |
353 | REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS, TM_Sn_STATUS_OFF, 10, 10), | |
354 | REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11), | |
355 | REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12), | |
356 | /* No CRITICAL field on v0.1 */ | |
357 | REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS, TM_Sn_STATUS_OFF, 13, 13), | |
358 | ||
359 | /* TRDY: 1=ready, 0=in progress */ | |
360 | [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), | |
361 | }; | |
362 | ||
032d4057 | 363 | static const struct tsens_ops ops_8916 = { |
840a5bd3 RN |
364 | .init = init_common, |
365 | .calibrate = calibrate_8916, | |
366 | .get_temp = get_temp_common, | |
367 | }; | |
368 | ||
3c040ce0 | 369 | const struct tsens_plat_data data_8916 = { |
840a5bd3 RN |
370 | .num_sensors = 5, |
371 | .ops = &ops_8916, | |
372 | .hw_ids = (unsigned int []){0, 1, 2, 4, 5 }, | |
c1997054 AK |
373 | |
374 | .feat = &tsens_v0_1_feat, | |
375 | .fields = tsens_v0_1_regfields, | |
840a5bd3 | 376 | }; |
582a0c41 AK |
377 | |
378 | static const struct tsens_ops ops_8974 = { | |
379 | .init = init_common, | |
380 | .calibrate = calibrate_8974, | |
381 | .get_temp = get_temp_common, | |
382 | }; | |
383 | ||
384 | const struct tsens_plat_data data_8974 = { | |
385 | .num_sensors = 11, | |
386 | .ops = &ops_8974, | |
c1997054 AK |
387 | .feat = &tsens_v0_1_feat, |
388 | .fields = tsens_v0_1_regfields, | |
582a0c41 | 389 | }; |