4
4
* Copyright (c) 2018, Linaro Limited
5
5
*/
6
6
7
+ #include <linux/bitfield.h>
7
8
#include <linux/bitops.h>
9
+ #include <linux/nvmem-consumer.h>
8
10
#include <linux/regmap.h>
9
11
#include "tsens.h"
10
12
11
13
/* ----- SROT ------ */
12
14
#define SROT_HW_VER_OFF 0x0000
13
15
#define SROT_CTRL_OFF 0x0004
16
+ #define SROT_MEASURE_PERIOD 0x0008
17
+ #define SROT_Sn_CONVERSION 0x0060
18
+ #define V2_SHIFT_DEFAULT 0x0003
19
+ #define V2_SLOPE_DEFAULT 0x0cd0
20
+ #define V2_CZERO_DEFAULT 0x016a
21
+ #define ONE_PT_SLOPE 0x0cd0
22
+ #define TWO_PT_SHIFTED_GAIN 921600
23
+ #define ONE_PT_CZERO_CONST 94
24
+ #define SW_RST_DEASSERT 0x0
25
+ #define SW_RST_ASSERT 0x1
26
+ #define MEASURE_PERIOD_2mSEC 0x1
27
+ #define RESULT_FORMAT_TEMP 0x1
28
+ #define TSENS_ENABLE 0x1
29
+ #define SENSOR_CONVERSION (n ) (((n) * 4) + SROT_Sn_CONVERSION)
30
+ #define CONVERSION_SHIFT_MASK GENMASK(24, 23)
31
+ #define CONVERSION_SLOPE_MASK GENMASK(22, 10)
32
+ #define CONVERSION_CZERO_MASK GENMASK(9, 0)
14
33
15
34
/* ----- TM ------ */
16
35
#define TM_INT_EN_OFF 0x0004
@@ -50,6 +69,17 @@ static struct tsens_features ipq8074_feat = {
50
69
.trip_max_temp = 204000 ,
51
70
};
52
71
72
+ static struct tsens_features ipq5332_feat = {
73
+ .ver_major = VER_2_X_NO_RPM ,
74
+ .crit_int = 1 ,
75
+ .combo_int = 1 ,
76
+ .adc = 0 ,
77
+ .srot_split = 1 ,
78
+ .max_sensors = 16 ,
79
+ .trip_min_temp = 0 ,
80
+ .trip_max_temp = 204000 ,
81
+ };
82
+
53
83
static const struct reg_field tsens_v2_regfields [MAX_REGFIELDS ] = {
54
84
/* ----- SROT ------ */
55
85
/* VERSION */
@@ -59,6 +89,10 @@ static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
59
89
/* CTRL_OFF */
60
90
[TSENS_EN ] = REG_FIELD (SROT_CTRL_OFF , 0 , 0 ),
61
91
[TSENS_SW_RST ] = REG_FIELD (SROT_CTRL_OFF , 1 , 1 ),
92
+ [SENSOR_EN ] = REG_FIELD (SROT_CTRL_OFF , 3 , 18 ),
93
+ [CODE_OR_TEMP ] = REG_FIELD (SROT_CTRL_OFF , 21 , 21 ),
94
+
95
+ [MAIN_MEASURE_PERIOD ] = REG_FIELD (SROT_MEASURE_PERIOD , 0 , 7 ),
62
96
63
97
/* ----- TM ------ */
64
98
/* INTERRUPT ENABLE */
@@ -104,6 +138,128 @@ static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
104
138
[TRDY ] = REG_FIELD (TM_TRDY_OFF , 0 , 0 ),
105
139
};
106
140
141
+ static int tsens_v2_calibrate_sensor (struct device * dev , struct tsens_sensor * sensor ,
142
+ struct regmap * map , u32 mode , u32 base0 , u32 base1 )
143
+ {
144
+ u32 shift = V2_SHIFT_DEFAULT ;
145
+ u32 slope = V2_SLOPE_DEFAULT ;
146
+ u32 czero = V2_CZERO_DEFAULT ;
147
+ char name [20 ];
148
+ u32 val ;
149
+ int ret ;
150
+
151
+ /* Read offset value */
152
+ ret = snprintf (name , sizeof (name ), "tsens_sens%d_off" , sensor -> hw_id );
153
+ if (ret < 0 )
154
+ return ret ;
155
+
156
+ ret = nvmem_cell_read_variable_le_u32 (dev , name , & sensor -> offset );
157
+ if (ret )
158
+ return ret ;
159
+
160
+ /* Based on calib mode, program SHIFT, SLOPE and CZERO */
161
+ switch (mode ) {
162
+ case TWO_PT_CALIB :
163
+ slope = (TWO_PT_SHIFTED_GAIN / (base1 - base0 ));
164
+
165
+ czero = (base0 + sensor -> offset - ((base1 - base0 ) / 3 ));
166
+
167
+ break ;
168
+ case ONE_PT_CALIB2 :
169
+ czero = base0 + sensor -> offset - ONE_PT_CZERO_CONST ;
170
+
171
+ slope = ONE_PT_SLOPE ;
172
+
173
+ break ;
174
+ default :
175
+ dev_dbg (dev , "calibrationless mode\n" );
176
+ }
177
+
178
+ val = FIELD_PREP (CONVERSION_SHIFT_MASK , shift ) |
179
+ FIELD_PREP (CONVERSION_SLOPE_MASK , slope ) |
180
+ FIELD_PREP (CONVERSION_CZERO_MASK , czero );
181
+
182
+ regmap_write (map , SENSOR_CONVERSION (sensor -> hw_id ), val );
183
+
184
+ return 0 ;
185
+ }
186
+
187
+ static int tsens_v2_calibration (struct tsens_priv * priv )
188
+ {
189
+ struct device * dev = priv -> dev ;
190
+ u32 mode , base0 , base1 ;
191
+ int i , ret ;
192
+
193
+ if (priv -> num_sensors > MAX_SENSORS )
194
+ return - EINVAL ;
195
+
196
+ ret = nvmem_cell_read_variable_le_u32 (priv -> dev , "mode" , & mode );
197
+ if (ret == - ENOENT )
198
+ dev_warn (priv -> dev , "Calibration data not present in DT\n" );
199
+ if (ret < 0 )
200
+ return ret ;
201
+
202
+ dev_dbg (priv -> dev , "calibration mode is %d\n" , mode );
203
+
204
+ ret = nvmem_cell_read_variable_le_u32 (priv -> dev , "base0" , & base0 );
205
+ if (ret < 0 )
206
+ return ret ;
207
+
208
+ ret = nvmem_cell_read_variable_le_u32 (priv -> dev , "base1" , & base1 );
209
+ if (ret < 0 )
210
+ return ret ;
211
+
212
+ /* Calibrate each sensor */
213
+ for (i = 0 ; i < priv -> num_sensors ; i ++ ) {
214
+ ret = tsens_v2_calibrate_sensor (dev , & priv -> sensor [i ], priv -> srot_map ,
215
+ mode , base0 , base1 );
216
+ if (ret < 0 )
217
+ return ret ;
218
+ }
219
+
220
+ return 0 ;
221
+ }
222
+
223
+ static int __init init_tsens_v2_no_rpm (struct tsens_priv * priv )
224
+ {
225
+ struct device * dev = priv -> dev ;
226
+ int i , ret ;
227
+ u32 val = 0 ;
228
+
229
+ ret = init_common (priv );
230
+ if (ret < 0 )
231
+ return ret ;
232
+
233
+ priv -> rf [CODE_OR_TEMP ] = devm_regmap_field_alloc (dev , priv -> srot_map ,
234
+ priv -> fields [CODE_OR_TEMP ]);
235
+ if (IS_ERR (priv -> rf [CODE_OR_TEMP ]))
236
+ return PTR_ERR (priv -> rf [CODE_OR_TEMP ]);
237
+
238
+ priv -> rf [MAIN_MEASURE_PERIOD ] = devm_regmap_field_alloc (dev , priv -> srot_map ,
239
+ priv -> fields [MAIN_MEASURE_PERIOD ]);
240
+ if (IS_ERR (priv -> rf [MAIN_MEASURE_PERIOD ]))
241
+ return PTR_ERR (priv -> rf [MAIN_MEASURE_PERIOD ]);
242
+
243
+ regmap_field_write (priv -> rf [TSENS_SW_RST ], SW_RST_ASSERT );
244
+
245
+ regmap_field_write (priv -> rf [MAIN_MEASURE_PERIOD ], MEASURE_PERIOD_2mSEC );
246
+
247
+ /* Enable available sensors */
248
+ for (i = 0 ; i < priv -> num_sensors ; i ++ )
249
+ val |= 1 << priv -> sensor [i ].hw_id ;
250
+
251
+ regmap_field_write (priv -> rf [SENSOR_EN ], val );
252
+
253
+ /* Select temperature format, unit is deci-Celsius */
254
+ regmap_field_write (priv -> rf [CODE_OR_TEMP ], RESULT_FORMAT_TEMP );
255
+
256
+ regmap_field_write (priv -> rf [TSENS_SW_RST ], SW_RST_DEASSERT );
257
+
258
+ regmap_field_write (priv -> rf [TSENS_EN ], TSENS_ENABLE );
259
+
260
+ return 0 ;
261
+ }
262
+
107
263
static const struct tsens_ops ops_generic_v2 = {
108
264
.init = init_common ,
109
265
.get_temp = get_temp_tsens_valid ,
@@ -122,6 +278,28 @@ struct tsens_plat_data data_ipq8074 = {
122
278
.fields = tsens_v2_regfields ,
123
279
};
124
280
281
+ static const struct tsens_ops ops_ipq5332 = {
282
+ .init = init_tsens_v2_no_rpm ,
283
+ .get_temp = get_temp_tsens_valid ,
284
+ .calibrate = tsens_v2_calibration ,
285
+ };
286
+
287
+ const struct tsens_plat_data data_ipq5332 = {
288
+ .num_sensors = 5 ,
289
+ .ops = & ops_ipq5332 ,
290
+ .hw_ids = (unsigned int []){11 , 12 , 13 , 14 , 15 },
291
+ .feat = & ipq5332_feat ,
292
+ .fields = tsens_v2_regfields ,
293
+ };
294
+
295
+ const struct tsens_plat_data data_ipq5424 = {
296
+ .num_sensors = 7 ,
297
+ .ops = & ops_ipq5332 ,
298
+ .hw_ids = (unsigned int []){9 , 10 , 11 , 12 , 13 , 14 , 15 },
299
+ .feat = & ipq5332_feat ,
300
+ .fields = tsens_v2_regfields ,
301
+ };
302
+
125
303
/* Kept around for backward compatibility with old msm8996.dtsi */
126
304
struct tsens_plat_data data_8996 = {
127
305
.num_sensors = 13 ,
0 commit comments