44 * Copyright (c) 2018, Linaro Limited
55 */
66
7+ #include <linux/bitfield.h>
78#include <linux/bitops.h>
9+ #include <linux/nvmem-consumer.h>
810#include <linux/regmap.h>
911#include "tsens.h"
1012
1113/* ----- SROT ------ */
1214#define SROT_HW_VER_OFF 0x0000
1315#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)
1433
1534/* ----- TM ------ */
1635#define TM_INT_EN_OFF 0x0004
@@ -50,6 +69,17 @@ static struct tsens_features ipq8074_feat = {
5069 .trip_max_temp = 204000 ,
5170};
5271
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+
5383static const struct reg_field tsens_v2_regfields [MAX_REGFIELDS ] = {
5484 /* ----- SROT ------ */
5585 /* VERSION */
@@ -59,6 +89,10 @@ static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
5989 /* CTRL_OFF */
6090 [TSENS_EN ] = REG_FIELD (SROT_CTRL_OFF , 0 , 0 ),
6191 [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 ),
6296
6397 /* ----- TM ------ */
6498 /* INTERRUPT ENABLE */
@@ -104,6 +138,128 @@ static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
104138 [TRDY ] = REG_FIELD (TM_TRDY_OFF , 0 , 0 ),
105139};
106140
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+
107263static const struct tsens_ops ops_generic_v2 = {
108264 .init = init_common ,
109265 .get_temp = get_temp_tsens_valid ,
@@ -122,6 +278,28 @@ struct tsens_plat_data data_ipq8074 = {
122278 .fields = tsens_v2_regfields ,
123279};
124280
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+
125303/* Kept around for backward compatibility with old msm8996.dtsi */
126304struct tsens_plat_data data_8996 = {
127305 .num_sensors = 13 ,
0 commit comments