xref: /linux/drivers/hwmon/pmbus/sq24860.c (revision 7acf90feab8b009fde7def08ff2c622d0f10e99f)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Author: Ziming Zhu <ziming.zhu@silergycorp.com>
4  */
5 
6 #include <linux/bitfield.h>
7 #include <linux/err.h>
8 #include <linux/i2c.h>
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/math64.h>
13 
14 #include "pmbus.h"
15 
16 #define SQ24860_IIN_CAL_GAIN		0x38
17 #define SQ24860_READ_VAUX		0xd0
18 #define SQ24860_READ_VIN_MIN		0xd1
19 #define SQ24860_READ_VIN_PEAK		0xd2
20 #define SQ24860_READ_IIN_PEAK		0xd4
21 #define SQ24860_READ_PIN_PEAK		0xd5
22 #define SQ24860_READ_TEMP_AVG		0xd6
23 #define SQ24860_READ_TEMP_PEAK		0xd7
24 #define SQ24860_READ_VOUT_MIN		0xda
25 #define SQ24860_READ_VIN_AVG		0xdc
26 #define SQ24860_READ_VOUT_AVG		0xdd
27 #define SQ24860_READ_IIN_AVG		0xde
28 #define SQ24860_READ_PIN_AVG		0xdf
29 #define SQ24860_VIREF			0xe0
30 #define SQ24860_PK_MIN_AVG		0xea
31 #define PK_MIN_AVG_RST_PEAK		BIT(7)
32 #define PK_MIN_AVG_RST_AVG		BIT(6)
33 #define PK_MIN_AVG_RST_MIN		BIT(5)
34 #define PK_MIN_AVG_AVG_CNT		GENMASK(2, 0)
35 #define SQ24860_MFR_WRITE_PROTECT	0xf8
36 #define SQ24860_UNLOCKED		BIT(7)
37 
38 #define SQ24860_8B_SHIFT		2
39 #define SQ24860_IIN_OCF_NUM		1000000
40 #define SQ24860_IIN_OCF_DIV		129278
41 #define SQ24860_IIN_OCF_OFF		165
42 
43 #define PK_MIN_AVG_RST_MASK		(PK_MIN_AVG_RST_PEAK | \
44 					 PK_MIN_AVG_RST_AVG  | \
45 					 PK_MIN_AVG_RST_MIN)
46 #define SQ24860_MAX_SAMPLES		BIT(FIELD_MAX(PK_MIN_AVG_AVG_CNT))
47 /*
48  * Arbitrary default Rimon value: 1.6kOhm
49  */
50 #define SQ24860_DEFAULT_RIMON		1600000000
51 #define SQ24860_GIMON			18180
52 
53 #define SQ24860_VAUX_DIV		20
54 
55 static int sq24860_write_iin_cal_gain(struct i2c_client *client, u32 rimon)
56 {
57 	u64 temp = 6400ULL * 1000000000ULL * 1000ULL;
58 	u64 denom;
59 	u64 word;
60 
61 	if (!rimon)
62 		return -EINVAL;
63 
64 	denom = (u64)rimon * SQ24860_GIMON;
65 	word = div64_u64(temp, denom);
66 	if (!word || word > U16_MAX)
67 		return -EINVAL;
68 
69 	return i2c_smbus_write_word_data(client, SQ24860_IIN_CAL_GAIN,
70 					(u16)word);
71 }
72 
73 static int sq24860_mfr_write_protect_set(struct i2c_client *client,
74 					 u8 protect)
75 {
76 	u8 val;
77 
78 	switch (protect) {
79 	case 0:
80 		val = 0xa2;
81 		break;
82 	case PB_WP_ALL:
83 		val = 0x0;
84 		break;
85 	default:
86 		return -EINVAL;
87 	}
88 
89 	return pmbus_write_byte_data(client, -1, SQ24860_MFR_WRITE_PROTECT,
90 				     val);
91 }
92 
93 static int sq24860_mfr_write_protect_get(struct i2c_client *client)
94 {
95 	int ret = pmbus_read_byte_data(client, -1, SQ24860_MFR_WRITE_PROTECT);
96 
97 	if (ret < 0)
98 		return ret;
99 
100 	return (ret & SQ24860_UNLOCKED) ? 0 : PB_WP_ALL;
101 }
102 
103 static int sq24860_read_word_data(struct i2c_client *client,
104 				  int page, int phase, int reg)
105 {
106 	int ret;
107 
108 	switch (reg) {
109 	case PMBUS_VIRT_READ_VIN_MAX:
110 		ret = pmbus_read_word_data(client, page, phase,
111 					   SQ24860_READ_VIN_PEAK);
112 		break;
113 
114 	case PMBUS_VIRT_READ_VIN_MIN:
115 		ret = pmbus_read_word_data(client, page, phase,
116 					   SQ24860_READ_VIN_MIN);
117 		break;
118 
119 	case PMBUS_VIRT_READ_VIN_AVG:
120 		ret = pmbus_read_word_data(client, page, phase,
121 					   SQ24860_READ_VIN_AVG);
122 		break;
123 
124 	case PMBUS_VIRT_READ_VOUT_MIN:
125 		ret = pmbus_read_word_data(client, page, phase,
126 					   SQ24860_READ_VOUT_MIN);
127 		break;
128 
129 	case PMBUS_VIRT_READ_VOUT_AVG:
130 		ret = pmbus_read_word_data(client, page, phase,
131 					   SQ24860_READ_VOUT_AVG);
132 		break;
133 
134 	case PMBUS_VIRT_READ_IIN_AVG:
135 		ret = pmbus_read_word_data(client, page, phase,
136 					   SQ24860_READ_IIN_AVG);
137 		break;
138 
139 	case PMBUS_VIRT_READ_IIN_MAX:
140 		ret = pmbus_read_word_data(client, page, phase,
141 					   SQ24860_READ_IIN_PEAK);
142 		break;
143 
144 	case PMBUS_VIRT_READ_TEMP_AVG:
145 		ret = pmbus_read_word_data(client, page, phase,
146 					   SQ24860_READ_TEMP_AVG);
147 		break;
148 
149 	case PMBUS_VIRT_READ_TEMP_MAX:
150 		ret = pmbus_read_word_data(client, page, phase,
151 					   SQ24860_READ_TEMP_PEAK);
152 		break;
153 
154 	case PMBUS_VIRT_READ_PIN_AVG:
155 		ret = pmbus_read_word_data(client, page, phase,
156 					   SQ24860_READ_PIN_AVG);
157 		break;
158 
159 	case PMBUS_VIRT_READ_PIN_MAX:
160 		ret = pmbus_read_word_data(client, page, phase,
161 					   SQ24860_READ_PIN_PEAK);
162 		break;
163 
164 	case PMBUS_VIRT_READ_VMON:
165 		ret = pmbus_read_word_data(client, page, phase,
166 					   SQ24860_READ_VAUX);
167 		if (ret < 0)
168 			break;
169 		ret = DIV_ROUND_CLOSEST(ret, SQ24860_VAUX_DIV);
170 		break;
171 
172 	case PMBUS_VIN_UV_WARN_LIMIT:
173 	case PMBUS_VIN_UV_FAULT_LIMIT:
174 	case PMBUS_VIN_OV_WARN_LIMIT:
175 	case PMBUS_VIN_OV_FAULT_LIMIT:
176 	case PMBUS_VOUT_UV_WARN_LIMIT:
177 	case PMBUS_IIN_OC_WARN_LIMIT:
178 	case PMBUS_OT_WARN_LIMIT:
179 	case PMBUS_OT_FAULT_LIMIT:
180 	case PMBUS_PIN_OP_WARN_LIMIT:
181 		/*
182 		 * These registers provide an 8 bits value instead of a
183 		 * 10bits one. Just shifting twice the register value is
184 		 * enough to make the sensor type conversion work, even
185 		 * if the datasheet provides different m, b and R for
186 		 * those.
187 		 */
188 		ret = pmbus_read_word_data(client, page, phase, reg);
189 		if (ret < 0)
190 			break;
191 		ret <<= SQ24860_8B_SHIFT;
192 		break;
193 
194 	case PMBUS_IIN_OC_FAULT_LIMIT:
195 		/*
196 		 * VIREF directly sets the over-current limit at which the eFuse
197 		 * will turn the FET off and trigger a fault. Expose it through
198 		 * this generic property instead of a manufacturer specific one.
199 		 */
200 		ret = pmbus_read_byte_data(client, page, SQ24860_VIREF);
201 		if (ret < 0)
202 			break;
203 		ret = DIV_ROUND_CLOSEST(ret * SQ24860_IIN_OCF_NUM,
204 					SQ24860_IIN_OCF_DIV);
205 		ret += SQ24860_IIN_OCF_OFF;
206 		break;
207 
208 	case PMBUS_VIRT_SAMPLES:
209 		ret = pmbus_read_byte_data(client, page, SQ24860_PK_MIN_AVG);
210 		if (ret < 0)
211 			break;
212 		ret = BIT(FIELD_GET(PK_MIN_AVG_AVG_CNT, ret));
213 		break;
214 
215 	case PMBUS_VIRT_RESET_TEMP_HISTORY:
216 	case PMBUS_VIRT_RESET_VIN_HISTORY:
217 	case PMBUS_VIRT_RESET_IIN_HISTORY:
218 	case PMBUS_VIRT_RESET_PIN_HISTORY:
219 	case PMBUS_VIRT_RESET_VOUT_HISTORY:
220 		ret = 0;
221 		break;
222 
223 	default:
224 		ret = -ENODATA;
225 		break;
226 	}
227 
228 	return ret;
229 }
230 
231 static int sq24860_write_word_data(struct i2c_client *client,
232 				   int page, int reg, u16 value)
233 {
234 	int ret;
235 
236 	switch (reg) {
237 	case PMBUS_VIN_UV_WARN_LIMIT:
238 	case PMBUS_VIN_UV_FAULT_LIMIT:
239 	case PMBUS_VIN_OV_WARN_LIMIT:
240 	case PMBUS_VIN_OV_FAULT_LIMIT:
241 	case PMBUS_VOUT_UV_WARN_LIMIT:
242 	case PMBUS_IIN_OC_WARN_LIMIT:
243 	case PMBUS_OT_WARN_LIMIT:
244 	case PMBUS_OT_FAULT_LIMIT:
245 	case PMBUS_PIN_OP_WARN_LIMIT:
246 		value = max_t(s16, (s16)value, 0);
247 		value >>= SQ24860_8B_SHIFT;
248 		value = clamp_val(value, 0, 0xff);
249 		ret = pmbus_write_word_data(client, page, reg, value);
250 		break;
251 
252 	case PMBUS_IIN_OC_FAULT_LIMIT:
253 		value = max_t(s16, (s16)value, SQ24860_IIN_OCF_OFF);
254 		value -= SQ24860_IIN_OCF_OFF;
255 		value = DIV_ROUND_CLOSEST(((unsigned int)value) * SQ24860_IIN_OCF_DIV,
256 					  SQ24860_IIN_OCF_NUM);
257 		value = clamp_val(value, 0, 0x3f);
258 		ret = pmbus_write_byte_data(client, page, SQ24860_VIREF, value);
259 		break;
260 
261 	case PMBUS_VIRT_SAMPLES:
262 		value = clamp_val(value, 1, SQ24860_MAX_SAMPLES);
263 		value = ilog2(value);
264 		ret = pmbus_update_byte_data(client, page, SQ24860_PK_MIN_AVG,
265 					     PK_MIN_AVG_AVG_CNT,
266 					     FIELD_PREP(PK_MIN_AVG_AVG_CNT, value));
267 		break;
268 
269 	case PMBUS_VIRT_RESET_TEMP_HISTORY:
270 	case PMBUS_VIRT_RESET_VIN_HISTORY:
271 	case PMBUS_VIRT_RESET_IIN_HISTORY:
272 	case PMBUS_VIRT_RESET_PIN_HISTORY:
273 	case PMBUS_VIRT_RESET_VOUT_HISTORY:
274 		/*
275 		 * SQ24860 has history resets based on MIN/AVG/PEAK instead of per
276 		 * sensor type. Exposing this quirk in hwmon is not desirable so
277 		 * reset MIN, AVG and PEAK together. Even is there effectively only
278 		 * one reset, which resets everything, expose the 5 entries so
279 		 * userspace is not required map a sensor type to another to trigger
280 		 * a reset
281 		 */
282 		ret = pmbus_update_byte_data(client, 0, SQ24860_PK_MIN_AVG,
283 					     PK_MIN_AVG_RST_MASK,
284 					     PK_MIN_AVG_RST_MASK);
285 		break;
286 
287 	default:
288 		ret = -ENODATA;
289 		break;
290 	}
291 
292 	return ret;
293 }
294 
295 static int sq24860_read_byte_data(struct i2c_client *client,
296 				  int page, int reg)
297 {
298 	int ret;
299 
300 	switch (reg) {
301 	case PMBUS_WRITE_PROTECT:
302 		ret = sq24860_mfr_write_protect_get(client);
303 		break;
304 
305 	default:
306 		ret = -ENODATA;
307 		break;
308 	}
309 
310 	return ret;
311 }
312 
313 static int sq24860_write_byte_data(struct i2c_client *client,
314 				   int page, int reg, u8 byte)
315 {
316 	int ret;
317 
318 	switch (reg) {
319 	case PMBUS_WRITE_PROTECT:
320 		ret = sq24860_mfr_write_protect_set(client, byte);
321 		break;
322 
323 	default:
324 		ret = -ENODATA;
325 		break;
326 	}
327 
328 	return ret;
329 }
330 
331 #if IS_ENABLED(CONFIG_SENSORS_SQ24860_REGULATOR)
332 static const struct regulator_desc sq24860_reg_desc[] = {
333 	PMBUS_REGULATOR_ONE_NODE("vout"),
334 };
335 #endif
336 
337 static const struct pmbus_driver_info sq24860_base_info = {
338 	.pages = 1,
339 	.format[PSC_VOLTAGE_IN] = direct,
340 	.m[PSC_VOLTAGE_IN] = 64,
341 	.b[PSC_VOLTAGE_IN] = 0,
342 	.R[PSC_VOLTAGE_IN] = 0,
343 	.format[PSC_VOLTAGE_OUT] = direct,
344 	.m[PSC_VOLTAGE_OUT] = 64,
345 	.b[PSC_VOLTAGE_OUT] = 0,
346 	.R[PSC_VOLTAGE_OUT] = 0,
347 	.format[PSC_TEMPERATURE] = direct,
348 	.m[PSC_TEMPERATURE] = 1,
349 	.b[PSC_TEMPERATURE] = 0,
350 	.R[PSC_TEMPERATURE] = 0,
351 	/*
352 	 * Current and power measurements depend on the calibration gain
353 	 * programmed from the board-specific IMON resistor value.
354 	 */
355 	.format[PSC_CURRENT_IN] = direct,
356 	.m[PSC_CURRENT_IN] = 16,
357 	.b[PSC_CURRENT_IN] = 0,
358 	.R[PSC_CURRENT_IN] = 0,
359 	.format[PSC_POWER] = direct,
360 	.m[PSC_POWER] = 2,
361 	.b[PSC_POWER] = 0,
362 	.R[PSC_POWER] = 0,
363 	.func[0] = PMBUS_HAVE_VIN |
364 		   PMBUS_HAVE_VOUT |
365 		   PMBUS_HAVE_VMON |
366 		   PMBUS_HAVE_IIN |
367 		   PMBUS_HAVE_PIN |
368 		   PMBUS_HAVE_TEMP |
369 		   PMBUS_HAVE_STATUS_VOUT |
370 		   PMBUS_HAVE_STATUS_IOUT |
371 		   PMBUS_HAVE_STATUS_INPUT |
372 		   PMBUS_HAVE_STATUS_TEMP |
373 		   PMBUS_HAVE_SAMPLES,
374 	.read_word_data = sq24860_read_word_data,
375 	.write_word_data = sq24860_write_word_data,
376 	.read_byte_data = sq24860_read_byte_data,
377 	.write_byte_data = sq24860_write_byte_data,
378 
379 #if IS_ENABLED(CONFIG_SENSORS_SQ24860_REGULATOR)
380 	.reg_desc = sq24860_reg_desc,
381 	.num_regulators = ARRAY_SIZE(sq24860_reg_desc),
382 #endif
383 };
384 
385 static const struct i2c_device_id sq24860_i2c_id[] = {
386 	{ "sq24860" },
387 	{}
388 };
389 MODULE_DEVICE_TABLE(i2c, sq24860_i2c_id);
390 
391 static const struct of_device_id sq24860_of_match[] = {
392 	{ .compatible = "silergy,sq24860" },
393 	{}
394 };
395 MODULE_DEVICE_TABLE(of, sq24860_of_match);
396 
397 static int sq24860_probe(struct i2c_client *client)
398 {
399 	struct device *dev = &client->dev;
400 	struct pmbus_driver_info *info;
401 	u32 rimon;
402 	int ret;
403 
404 	if (device_property_read_u32(dev, "silergy,rimon-micro-ohms", &rimon))
405 		rimon = SQ24860_DEFAULT_RIMON;
406 	ret = sq24860_write_iin_cal_gain(client, rimon);
407 	if (ret < 0)
408 		return dev_err_probe(&client->dev, ret,
409 					     "Failed to set gain\n");
410 	info = devm_kmemdup(dev, &sq24860_base_info, sizeof(*info), GFP_KERNEL);
411 	if (!info)
412 		return -ENOMEM;
413 
414 	return pmbus_do_probe(client, info);
415 }
416 
417 static struct i2c_driver sq24860_driver = {
418 	.driver = {
419 		.name = "sq24860",
420 		.of_match_table = sq24860_of_match,
421 	},
422 	.probe = sq24860_probe,
423 	.id_table = sq24860_i2c_id,
424 };
425 module_i2c_driver(sq24860_driver);
426 
427 MODULE_AUTHOR("Ziming Zhu <ziming.zhu@silergycorp.com>");
428 MODULE_DESCRIPTION("PMBUS driver for SQ24860 eFuse");
429 MODULE_LICENSE("GPL");
430 MODULE_IMPORT_NS("PMBUS");
431