1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2019, Linaro Limited
4 */
5
6 #include <linux/bitops.h>
7 #include <linux/regmap.h>
8 #include <linux/delay.h>
9 #include "tsens.h"
10
11 /* ----- SROT ------ */
12 #define SROT_HW_VER_OFF 0x0000
13 #define SROT_CTRL_OFF 0x0004
14
15 /* ----- TM ------ */
16 #define TM_INT_EN_OFF 0x0000
17 #define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004
18 #define TM_Sn_STATUS_OFF 0x0044
19 #define TM_TRDY_OFF 0x0084
20
21 /* eeprom layout data for qcs404/405 (v1) */
22 #define BASE0_MASK 0x000007f8
23 #define BASE1_MASK 0x0007f800
24 #define BASE0_SHIFT 3
25 #define BASE1_SHIFT 11
26
27 #define S0_P1_MASK 0x0000003f
28 #define S1_P1_MASK 0x0003f000
29 #define S2_P1_MASK 0x3f000000
30 #define S3_P1_MASK 0x000003f0
31 #define S4_P1_MASK 0x003f0000
32 #define S5_P1_MASK 0x0000003f
33 #define S6_P1_MASK 0x0003f000
34 #define S7_P1_MASK 0x3f000000
35 #define S8_P1_MASK 0x000003f0
36 #define S9_P1_MASK 0x003f0000
37
38 #define S0_P2_MASK 0x00000fc0
39 #define S1_P2_MASK 0x00fc0000
40 #define S2_P2_MASK_1_0 0xc0000000
41 #define S2_P2_MASK_5_2 0x0000000f
42 #define S3_P2_MASK 0x0000fc00
43 #define S4_P2_MASK 0x0fc00000
44 #define S5_P2_MASK 0x00000fc0
45 #define S6_P2_MASK 0x00fc0000
46 #define S7_P2_MASK_1_0 0xc0000000
47 #define S7_P2_MASK_5_2 0x0000000f
48 #define S8_P2_MASK 0x0000fc00
49 #define S9_P2_MASK 0x0fc00000
50
51 #define S0_P1_SHIFT 0
52 #define S0_P2_SHIFT 6
53 #define S1_P1_SHIFT 12
54 #define S1_P2_SHIFT 18
55 #define S2_P1_SHIFT 24
56 #define S2_P2_SHIFT_1_0 30
57
58 #define S2_P2_SHIFT_5_2 0
59 #define S3_P1_SHIFT 4
60 #define S3_P2_SHIFT 10
61 #define S4_P1_SHIFT 16
62 #define S4_P2_SHIFT 22
63
64 #define S5_P1_SHIFT 0
65 #define S5_P2_SHIFT 6
66 #define S6_P1_SHIFT 12
67 #define S6_P2_SHIFT 18
68 #define S7_P1_SHIFT 24
69 #define S7_P2_SHIFT_1_0 30
70
71 #define S7_P2_SHIFT_5_2 0
72 #define S8_P1_SHIFT 4
73 #define S8_P2_SHIFT 10
74 #define S9_P1_SHIFT 16
75 #define S9_P2_SHIFT 22
76
77 #define CAL_SEL_MASK 7
78 #define CAL_SEL_SHIFT 0
79
calibrate_v1(struct tsens_priv * priv)80 static int calibrate_v1(struct tsens_priv *priv)
81 {
82 u32 base0 = 0, base1 = 0;
83 u32 p1[10], p2[10];
84 u32 mode = 0, lsb = 0, msb = 0;
85 u32 *qfprom_cdata;
86 int i;
87
88 qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
89 if (IS_ERR(qfprom_cdata))
90 return PTR_ERR(qfprom_cdata);
91
92 mode = (qfprom_cdata[4] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
93 dev_dbg(priv->dev, "calibration mode is %d\n", mode);
94
95 switch (mode) {
96 case TWO_PT_CALIB:
97 base1 = (qfprom_cdata[4] & BASE1_MASK) >> BASE1_SHIFT;
98 p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
99 p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
100 /* This value is split over two registers, 2 bits and 4 bits */
101 lsb = (qfprom_cdata[0] & S2_P2_MASK_1_0) >> S2_P2_SHIFT_1_0;
102 msb = (qfprom_cdata[1] & S2_P2_MASK_5_2) >> S2_P2_SHIFT_5_2;
103 p2[2] = msb << 2 | lsb;
104 p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
105 p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
106 p2[5] = (qfprom_cdata[2] & S5_P2_MASK) >> S5_P2_SHIFT;
107 p2[6] = (qfprom_cdata[2] & S6_P2_MASK) >> S6_P2_SHIFT;
108 /* This value is split over two registers, 2 bits and 4 bits */
109 lsb = (qfprom_cdata[2] & S7_P2_MASK_1_0) >> S7_P2_SHIFT_1_0;
110 msb = (qfprom_cdata[3] & S7_P2_MASK_5_2) >> S7_P2_SHIFT_5_2;
111 p2[7] = msb << 2 | lsb;
112 p2[8] = (qfprom_cdata[3] & S8_P2_MASK) >> S8_P2_SHIFT;
113 p2[9] = (qfprom_cdata[3] & S9_P2_MASK) >> S9_P2_SHIFT;
114 for (i = 0; i < priv->num_sensors; i++)
115 p2[i] = ((base1 + p2[i]) << 2);
116 /* Fall through */
117 case ONE_PT_CALIB2:
118 base0 = (qfprom_cdata[4] & BASE0_MASK) >> BASE0_SHIFT;
119 p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
120 p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
121 p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
122 p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
123 p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
124 p1[5] = (qfprom_cdata[2] & S5_P1_MASK) >> S5_P1_SHIFT;
125 p1[6] = (qfprom_cdata[2] & S6_P1_MASK) >> S6_P1_SHIFT;
126 p1[7] = (qfprom_cdata[2] & S7_P1_MASK) >> S7_P1_SHIFT;
127 p1[8] = (qfprom_cdata[3] & S8_P1_MASK) >> S8_P1_SHIFT;
128 p1[9] = (qfprom_cdata[3] & S9_P1_MASK) >> S9_P1_SHIFT;
129 for (i = 0; i < priv->num_sensors; i++)
130 p1[i] = (((base0) + p1[i]) << 2);
131 break;
132 default:
133 for (i = 0; i < priv->num_sensors; i++) {
134 p1[i] = 500;
135 p2[i] = 780;
136 }
137 break;
138 }
139
140 compute_intercept_slope(priv, p1, p2, mode);
141 kfree(qfprom_cdata);
142
143 return 0;
144 }
145
146 /* v1.x: qcs404,405 */
147
148 static const struct tsens_features tsens_v1_feat = {
149 .ver_major = VER_1_X,
150 .crit_int = 0,
151 .adc = 1,
152 .srot_split = 1,
153 .max_sensors = 11,
154 };
155
156 static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = {
157 /* ----- SROT ------ */
158 /* VERSION */
159 [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31),
160 [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27),
161 [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15),
162 /* CTRL_OFFSET */
163 [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),
164 [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),
165 [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 13),
166
167 /* ----- TM ------ */
168 /* INTERRUPT ENABLE */
169 [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0),
170
171 /* Sn_STATUS */
172 REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 9),
173 REG_FIELD_FOR_EACH_SENSOR11(VALID, TM_Sn_STATUS_OFF, 14, 14),
174 REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS, TM_Sn_STATUS_OFF, 10, 10),
175 REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11),
176 REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12),
177 /* No CRITICAL field on v1.x */
178 REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS, TM_Sn_STATUS_OFF, 13, 13),
179
180 /* TRDY: 1=ready, 0=in progress */
181 [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
182 };
183
184 static const struct tsens_ops ops_generic_v1 = {
185 .init = init_common,
186 .calibrate = calibrate_v1,
187 .get_temp = get_temp_tsens_valid,
188 };
189
190 const struct tsens_plat_data data_tsens_v1 = {
191 .ops = &ops_generic_v1,
192 .feat = &tsens_v1_feat,
193 .fields = tsens_v1_regfields,
194 };
195