xref: /openbmc/linux/drivers/thermal/qcom/tsens-v1.c (revision b9df3997)
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 
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