1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (c) 2015, The Linux Foundation. All rights reserved. |
4 | */ |
5 | |
6 | #include <linux/platform_device.h> |
7 | #include <linux/delay.h> |
8 | #include <linux/bitops.h> |
9 | #include <linux/regmap.h> |
10 | #include <linux/thermal.h> |
11 | #include "tsens.h" |
12 | |
13 | #define CONFIG_ADDR 0x3640 |
14 | #define CONFIG_ADDR_8660 0x3620 |
15 | /* CONFIG_ADDR bitmasks */ |
16 | #define CONFIG 0x9b |
17 | #define CONFIG_MASK 0xf |
18 | #define CONFIG_8660 1 |
19 | #define CONFIG_SHIFT_8660 28 |
20 | #define CONFIG_MASK_8660 (3 << CONFIG_SHIFT_8660) |
21 | |
22 | #define CNTL_ADDR 0x3620 |
23 | /* CNTL_ADDR bitmasks */ |
24 | #define EN BIT(0) |
25 | #define SW_RST BIT(1) |
26 | |
27 | #define MEASURE_PERIOD BIT(18) |
28 | #define SLP_CLK_ENA BIT(26) |
29 | #define SLP_CLK_ENA_8660 BIT(24) |
30 | #define SENSOR0_SHIFT 3 |
31 | |
32 | #define THRESHOLD_ADDR 0x3624 |
33 | |
34 | #define INT_STATUS_ADDR 0x363c |
35 | |
36 | #define S0_STATUS_OFF 0x3628 |
37 | #define S1_STATUS_OFF 0x362c |
38 | #define S2_STATUS_OFF 0x3630 |
39 | #define S3_STATUS_OFF 0x3634 |
40 | #define S4_STATUS_OFF 0x3638 |
41 | #define S5_STATUS_OFF 0x3664 /* Sensors 5-10 found on apq8064/msm8960 */ |
42 | #define S6_STATUS_OFF 0x3668 |
43 | #define S7_STATUS_OFF 0x366c |
44 | #define S8_STATUS_OFF 0x3670 |
45 | #define S9_STATUS_OFF 0x3674 |
46 | #define S10_STATUS_OFF 0x3678 |
47 | |
48 | /* Original slope - 350 to compensate mC to C inaccuracy */ |
49 | static u32 tsens_msm8960_slope[] = { |
50 | 826, 826, 804, 826, |
51 | 761, 782, 782, 849, |
52 | 782, 849, 782 |
53 | }; |
54 | |
55 | static int suspend_8960(struct tsens_priv *priv) |
56 | { |
57 | int ret; |
58 | unsigned int mask; |
59 | struct regmap *map = priv->tm_map; |
60 | |
61 | ret = regmap_read(map, THRESHOLD_ADDR, val: &priv->ctx.threshold); |
62 | if (ret) |
63 | return ret; |
64 | |
65 | ret = regmap_read(map, CNTL_ADDR, val: &priv->ctx.control); |
66 | if (ret) |
67 | return ret; |
68 | |
69 | if (priv->num_sensors > 1) |
70 | mask = SLP_CLK_ENA | EN; |
71 | else |
72 | mask = SLP_CLK_ENA_8660 | EN; |
73 | |
74 | ret = regmap_update_bits(map, CNTL_ADDR, mask, val: 0); |
75 | if (ret) |
76 | return ret; |
77 | |
78 | return 0; |
79 | } |
80 | |
81 | static int resume_8960(struct tsens_priv *priv) |
82 | { |
83 | int ret; |
84 | struct regmap *map = priv->tm_map; |
85 | |
86 | ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST); |
87 | if (ret) |
88 | return ret; |
89 | |
90 | /* |
91 | * Separate CONFIG restore is not needed only for 8660 as |
92 | * config is part of CTRL Addr and its restored as such |
93 | */ |
94 | if (priv->num_sensors > 1) { |
95 | ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG); |
96 | if (ret) |
97 | return ret; |
98 | } |
99 | |
100 | ret = regmap_write(map, THRESHOLD_ADDR, val: priv->ctx.threshold); |
101 | if (ret) |
102 | return ret; |
103 | |
104 | ret = regmap_write(map, CNTL_ADDR, val: priv->ctx.control); |
105 | if (ret) |
106 | return ret; |
107 | |
108 | return 0; |
109 | } |
110 | |
111 | static int enable_8960(struct tsens_priv *priv, int id) |
112 | { |
113 | int ret; |
114 | u32 reg, mask = BIT(id); |
115 | |
116 | ret = regmap_read(map: priv->tm_map, CNTL_ADDR, val: ®); |
117 | if (ret) |
118 | return ret; |
119 | |
120 | /* HARDWARE BUG: |
121 | * On platforms with more than 6 sensors, all remaining sensors |
122 | * must be enabled together, otherwise undefined results are expected. |
123 | * (Sensor 6-7 disabled, Sensor 3 disabled...) In the original driver, |
124 | * all the sensors are enabled in one step hence this bug is not |
125 | * triggered. |
126 | */ |
127 | if (id > 5) |
128 | mask = GENMASK(10, 6); |
129 | |
130 | mask <<= SENSOR0_SHIFT; |
131 | |
132 | /* Sensors already enabled. Skip. */ |
133 | if ((reg & mask) == mask) |
134 | return 0; |
135 | |
136 | ret = regmap_write(map: priv->tm_map, CNTL_ADDR, val: reg | SW_RST); |
137 | if (ret) |
138 | return ret; |
139 | |
140 | reg |= MEASURE_PERIOD; |
141 | |
142 | if (priv->num_sensors > 1) |
143 | reg |= mask | SLP_CLK_ENA | EN; |
144 | else |
145 | reg |= mask | SLP_CLK_ENA_8660 | EN; |
146 | |
147 | ret = regmap_write(map: priv->tm_map, CNTL_ADDR, val: reg); |
148 | if (ret) |
149 | return ret; |
150 | |
151 | return 0; |
152 | } |
153 | |
154 | static void disable_8960(struct tsens_priv *priv) |
155 | { |
156 | int ret; |
157 | u32 reg_cntl; |
158 | u32 mask; |
159 | |
160 | mask = GENMASK(priv->num_sensors - 1, 0); |
161 | mask <<= SENSOR0_SHIFT; |
162 | mask |= EN; |
163 | |
164 | ret = regmap_read(map: priv->tm_map, CNTL_ADDR, val: ®_cntl); |
165 | if (ret) |
166 | return; |
167 | |
168 | reg_cntl &= ~mask; |
169 | |
170 | if (priv->num_sensors > 1) |
171 | reg_cntl &= ~SLP_CLK_ENA; |
172 | else |
173 | reg_cntl &= ~SLP_CLK_ENA_8660; |
174 | |
175 | regmap_write(map: priv->tm_map, CNTL_ADDR, val: reg_cntl); |
176 | } |
177 | |
178 | static int calibrate_8960(struct tsens_priv *priv) |
179 | { |
180 | int i; |
181 | char *data; |
182 | u32 p1[11]; |
183 | |
184 | data = qfprom_read(dev: priv->dev, cname: "calib" ); |
185 | if (IS_ERR(ptr: data)) |
186 | data = qfprom_read(dev: priv->dev, cname: "calib_backup" ); |
187 | if (IS_ERR(ptr: data)) |
188 | return PTR_ERR(ptr: data); |
189 | |
190 | for (i = 0; i < priv->num_sensors; i++) { |
191 | p1[i] = data[i]; |
192 | priv->sensor[i].slope = tsens_msm8960_slope[i]; |
193 | } |
194 | |
195 | compute_intercept_slope(priv, pt1: p1, NULL, ONE_PT_CALIB); |
196 | |
197 | kfree(objp: data); |
198 | |
199 | return 0; |
200 | } |
201 | |
202 | static const struct reg_field tsens_8960_regfields[MAX_REGFIELDS] = { |
203 | /* ----- SROT ------ */ |
204 | /* No VERSION information */ |
205 | |
206 | /* CNTL */ |
207 | [TSENS_EN] = REG_FIELD(CNTL_ADDR, 0, 0), |
208 | [TSENS_SW_RST] = REG_FIELD(CNTL_ADDR, 1, 1), |
209 | /* 8960 has 5 sensors, 8660 has 11, we only handle 5 */ |
210 | [SENSOR_EN] = REG_FIELD(CNTL_ADDR, 3, 7), |
211 | |
212 | /* ----- TM ------ */ |
213 | /* INTERRUPT ENABLE */ |
214 | /* NO INTERRUPT ENABLE */ |
215 | |
216 | /* Single UPPER/LOWER TEMPERATURE THRESHOLD for all sensors */ |
217 | [LOW_THRESH_0] = REG_FIELD(THRESHOLD_ADDR, 0, 7), |
218 | [UP_THRESH_0] = REG_FIELD(THRESHOLD_ADDR, 8, 15), |
219 | /* MIN_THRESH_0 and MAX_THRESH_0 are not present in the regfield |
220 | * Recycle CRIT_THRESH_0 and 1 to set the required regs to hardcoded temp |
221 | * MIN_THRESH_0 -> CRIT_THRESH_1 |
222 | * MAX_THRESH_0 -> CRIT_THRESH_0 |
223 | */ |
224 | [CRIT_THRESH_1] = REG_FIELD(THRESHOLD_ADDR, 16, 23), |
225 | [CRIT_THRESH_0] = REG_FIELD(THRESHOLD_ADDR, 24, 31), |
226 | |
227 | /* UPPER/LOWER INTERRUPT [CLEAR/STATUS] */ |
228 | /* 1 == clear, 0 == normal operation */ |
229 | [LOW_INT_CLEAR_0] = REG_FIELD(CNTL_ADDR, 9, 9), |
230 | [UP_INT_CLEAR_0] = REG_FIELD(CNTL_ADDR, 10, 10), |
231 | |
232 | /* NO CRITICAL INTERRUPT SUPPORT on 8960 */ |
233 | |
234 | /* Sn_STATUS */ |
235 | [LAST_TEMP_0] = REG_FIELD(S0_STATUS_OFF, 0, 7), |
236 | [LAST_TEMP_1] = REG_FIELD(S1_STATUS_OFF, 0, 7), |
237 | [LAST_TEMP_2] = REG_FIELD(S2_STATUS_OFF, 0, 7), |
238 | [LAST_TEMP_3] = REG_FIELD(S3_STATUS_OFF, 0, 7), |
239 | [LAST_TEMP_4] = REG_FIELD(S4_STATUS_OFF, 0, 7), |
240 | [LAST_TEMP_5] = REG_FIELD(S5_STATUS_OFF, 0, 7), |
241 | [LAST_TEMP_6] = REG_FIELD(S6_STATUS_OFF, 0, 7), |
242 | [LAST_TEMP_7] = REG_FIELD(S7_STATUS_OFF, 0, 7), |
243 | [LAST_TEMP_8] = REG_FIELD(S8_STATUS_OFF, 0, 7), |
244 | [LAST_TEMP_9] = REG_FIELD(S9_STATUS_OFF, 0, 7), |
245 | [LAST_TEMP_10] = REG_FIELD(S10_STATUS_OFF, 0, 7), |
246 | |
247 | /* No VALID field on 8960 */ |
248 | /* TSENS_INT_STATUS bits: 1 == threshold violated */ |
249 | [MIN_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 0, 0), |
250 | [LOWER_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 1, 1), |
251 | [UPPER_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 2, 2), |
252 | /* No CRITICAL field on 8960 */ |
253 | [MAX_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 3, 3), |
254 | |
255 | /* TRDY: 1=ready, 0=in progress */ |
256 | [TRDY] = REG_FIELD(INT_STATUS_ADDR, 7, 7), |
257 | }; |
258 | |
259 | static const struct tsens_ops ops_8960 = { |
260 | .init = init_common, |
261 | .calibrate = calibrate_8960, |
262 | .get_temp = get_temp_common, |
263 | .enable = enable_8960, |
264 | .disable = disable_8960, |
265 | .suspend = suspend_8960, |
266 | .resume = resume_8960, |
267 | }; |
268 | |
269 | static struct tsens_features tsens_8960_feat = { |
270 | .ver_major = VER_0, |
271 | .crit_int = 0, |
272 | .combo_int = 0, |
273 | .adc = 1, |
274 | .srot_split = 0, |
275 | .max_sensors = 11, |
276 | .trip_min_temp = -40000, |
277 | .trip_max_temp = 120000, |
278 | }; |
279 | |
280 | struct tsens_plat_data data_8960 = { |
281 | .num_sensors = 11, |
282 | .ops = &ops_8960, |
283 | .feat = &tsens_8960_feat, |
284 | .fields = tsens_8960_regfields, |
285 | }; |
286 | |