xref: /linux/drivers/hwmon/ina238.c (revision e47a324d6f07c9ef252cfce1f14cfa5110cbed99)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Driver for Texas Instruments INA238 power monitor chip
4  * Datasheet: https://www.ti.com/product/ina238
5  *
6  * Copyright (C) 2021 Nathan Rossi <nathan.rossi@digi.com>
7  */
8 
9 #include <linux/err.h>
10 #include <linux/hwmon.h>
11 #include <linux/i2c.h>
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/of.h>
16 #include <linux/regmap.h>
17 
18 #include <linux/platform_data/ina2xx.h>
19 
20 /* INA238 register definitions */
21 #define INA238_CONFIG			0x0
22 #define INA238_ADC_CONFIG		0x1
23 #define INA238_SHUNT_CALIBRATION	0x2
24 #define SQ52206_SHUNT_TEMPCO		0x3
25 #define INA238_SHUNT_VOLTAGE		0x4
26 #define INA238_BUS_VOLTAGE		0x5
27 #define INA238_DIE_TEMP			0x6
28 #define INA238_CURRENT			0x7
29 #define INA238_POWER			0x8
30 #define SQ52206_ENERGY			0x9
31 #define SQ52206_CHARGE			0xa
32 #define INA238_DIAG_ALERT		0xb
33 #define INA238_SHUNT_OVER_VOLTAGE	0xc
34 #define INA238_SHUNT_UNDER_VOLTAGE	0xd
35 #define INA238_BUS_OVER_VOLTAGE		0xe
36 #define INA238_BUS_UNDER_VOLTAGE	0xf
37 #define INA238_TEMP_LIMIT		0x10
38 #define INA238_POWER_LIMIT		0x11
39 #define SQ52206_POWER_PEAK		0x20
40 #define INA238_DEVICE_ID		0x3f /* not available on INA237 */
41 
42 #define INA238_CONFIG_ADCRANGE		BIT(4)
43 #define SQ52206_CONFIG_ADCRANGE_HIGH	BIT(4)
44 #define SQ52206_CONFIG_ADCRANGE_LOW		BIT(3)
45 
46 #define INA238_DIAG_ALERT_TMPOL		BIT(7)
47 #define INA238_DIAG_ALERT_SHNTOL	BIT(6)
48 #define INA238_DIAG_ALERT_SHNTUL	BIT(5)
49 #define INA238_DIAG_ALERT_BUSOL		BIT(4)
50 #define INA238_DIAG_ALERT_BUSUL		BIT(3)
51 #define INA238_DIAG_ALERT_POL		BIT(2)
52 
53 #define INA238_REGISTERS		0x20
54 
55 #define INA238_RSHUNT_DEFAULT		10000 /* uOhm */
56 
57 /* Default configuration of device on reset. */
58 #define INA238_CONFIG_DEFAULT		0
59 #define SQ52206_CONFIG_DEFAULT		0x0005
60 /* 16 sample averaging, 1052us conversion time, continuous mode */
61 #define INA238_ADC_CONFIG_DEFAULT	0xfb6a
62 /* Configure alerts to be based on averaged value (SLOWALERT) */
63 #define INA238_DIAG_ALERT_DEFAULT	0x2000
64 /*
65  * This driver uses a fixed calibration value in order to scale current/power
66  * based on a fixed shunt resistor value. This allows for conversion within the
67  * device to avoid integer limits whilst current/power accuracy is scaled
68  * relative to the shunt resistor value within the driver. This is similar to
69  * how the ina2xx driver handles current/power scaling.
70  *
71  * The end result of this is that increasing shunt values (from a fixed 20 mOhm
72  * shunt) increase the effective current/power accuracy whilst limiting the
73  * range and decreasing shunt values decrease the effective accuracy but
74  * increase the range.
75  *
76  * The value of the Current register is calculated given the following:
77  *   Current (A) = (shunt voltage register * 5) * calibration / 81920
78  *
79  * The maximum shunt voltage is 163.835 mV (0x7fff, ADC_RANGE = 0, gain = 4).
80  * With the maximum current value of 0x7fff and a fixed shunt value results in
81  * a calibration value of 16384 (0x4000).
82  *
83  *   0x7fff = (0x7fff * 5) * calibration / 81920
84  *   calibration = 0x4000
85  *
86  * Equivalent calibration is applied for the Power register (maximum value for
87  * bus voltage is 102396.875 mV, 0x7fff), where the maximum power that can
88  * occur is ~16776192 uW (register value 0x147a8):
89  *
90  * This scaling means the resulting values for Current and Power registers need
91  * to be scaled by the difference between the fixed shunt resistor and the
92  * actual shunt resistor:
93  *
94  *  shunt = 0x4000 / (819.2 * 10^6) / 0.001 = 20000 uOhms (with 1mA/lsb)
95  *
96  *  Current (mA) = register value * 20000 / rshunt / 4 * gain
97  *  Power (mW) = 0.2 * register value * 20000 / rshunt / 4 * gain
98  *  (Specific for SQ52206)
99  *  Power (mW) = 0.24 * register value * 20000 / rshunt / 4 * gain
100  *  Energy (mJ) = 16 * 0.24 * register value * 20000 / rshunt / 4 * gain
101  */
102 #define INA238_CALIBRATION_VALUE	16384
103 #define INA238_FIXED_SHUNT		20000
104 
105 #define INA238_SHUNT_VOLTAGE_LSB	5 /* 5 uV/lsb */
106 #define INA238_BUS_VOLTAGE_LSB		3125 /* 3.125 mV/lsb */
107 #define INA238_DIE_TEMP_LSB			1250000 /* 125.0000 mC/lsb */
108 #define SQ52206_BUS_VOLTAGE_LSB		3750 /* 3.75 mV/lsb */
109 #define SQ52206_DIE_TEMP_LSB		78125 /* 7.8125 mC/lsb */
110 
111 static const struct regmap_config ina238_regmap_config = {
112 	.max_register = INA238_REGISTERS,
113 	.reg_bits = 8,
114 	.val_bits = 16,
115 };
116 
117 enum ina238_ids { ina238, ina237, sq52206 };
118 
119 struct ina238_config {
120 	bool has_power_highest;		/* chip detection power peak */
121 	bool has_energy;			/* chip detection energy */
122 	u8 temp_shift;				/* fixed parameters for temp calculate */
123 	u32 power_calculate_factor;	/* fixed parameters for power calculate */
124 	u16 config_default;			/* Power-on default state */
125 	int bus_voltage_lsb;		/* use for temperature calculate, uV/lsb */
126 	int temp_lsb;				/* use for temperature calculate */
127 };
128 
129 struct ina238_data {
130 	const struct ina238_config *config;
131 	struct i2c_client *client;
132 	struct mutex config_lock;
133 	struct regmap *regmap;
134 	u32 rshunt;
135 	int gain;
136 };
137 
138 static const struct ina238_config ina238_config[] = {
139 	[ina238] = {
140 		.has_energy = false,
141 		.has_power_highest = false,
142 		.temp_shift = 4,
143 		.power_calculate_factor = 20,
144 		.config_default = INA238_CONFIG_DEFAULT,
145 		.bus_voltage_lsb = INA238_BUS_VOLTAGE_LSB,
146 		.temp_lsb = INA238_DIE_TEMP_LSB,
147 	},
148 	[ina237] = {
149 		.has_energy = false,
150 		.has_power_highest = false,
151 		.temp_shift = 4,
152 		.power_calculate_factor = 20,
153 		.config_default = INA238_CONFIG_DEFAULT,
154 		.bus_voltage_lsb = INA238_BUS_VOLTAGE_LSB,
155 		.temp_lsb = INA238_DIE_TEMP_LSB,
156 	},
157 	[sq52206] = {
158 		.has_energy = true,
159 		.has_power_highest = true,
160 		.temp_shift = 0,
161 		.power_calculate_factor = 24,
162 		.config_default = SQ52206_CONFIG_DEFAULT,
163 		.bus_voltage_lsb = SQ52206_BUS_VOLTAGE_LSB,
164 		.temp_lsb = SQ52206_DIE_TEMP_LSB,
165 	},
166 };
167 
168 static int ina238_read_reg24(const struct i2c_client *client, u8 reg, u32 *val)
169 {
170 	u8 data[3];
171 	int err;
172 
173 	/* 24-bit register read */
174 	err = i2c_smbus_read_i2c_block_data(client, reg, 3, data);
175 	if (err < 0)
176 		return err;
177 	if (err != 3)
178 		return -EIO;
179 	*val = (data[0] << 16) | (data[1] << 8) | data[2];
180 
181 	return 0;
182 }
183 
184 static int ina238_read_reg40(const struct i2c_client *client, u8 reg, u64 *val)
185 {
186 	u8 data[5];
187 	u32 low;
188 	int err;
189 
190 	/* 40-bit register read */
191 	err = i2c_smbus_read_i2c_block_data(client, reg, 5, data);
192 	if (err < 0)
193 		return err;
194 	if (err != 5)
195 		return -EIO;
196 	low = (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4];
197 	*val = ((long long)data[0] << 32) | low;
198 
199 	return 0;
200 }
201 
202 static int ina238_read_in(struct device *dev, u32 attr, int channel,
203 			  long *val)
204 {
205 	struct ina238_data *data = dev_get_drvdata(dev);
206 	int reg, mask;
207 	int regval;
208 	int err;
209 
210 	switch (channel) {
211 	case 0:
212 		switch (attr) {
213 		case hwmon_in_input:
214 			reg = INA238_SHUNT_VOLTAGE;
215 			break;
216 		case hwmon_in_max:
217 			reg = INA238_SHUNT_OVER_VOLTAGE;
218 			break;
219 		case hwmon_in_min:
220 			reg = INA238_SHUNT_UNDER_VOLTAGE;
221 			break;
222 		case hwmon_in_max_alarm:
223 			reg = INA238_DIAG_ALERT;
224 			mask = INA238_DIAG_ALERT_SHNTOL;
225 			break;
226 		case hwmon_in_min_alarm:
227 			reg = INA238_DIAG_ALERT;
228 			mask = INA238_DIAG_ALERT_SHNTUL;
229 			break;
230 		default:
231 			return -EOPNOTSUPP;
232 		}
233 		break;
234 	case 1:
235 		switch (attr) {
236 		case hwmon_in_input:
237 			reg = INA238_BUS_VOLTAGE;
238 			break;
239 		case hwmon_in_max:
240 			reg = INA238_BUS_OVER_VOLTAGE;
241 			break;
242 		case hwmon_in_min:
243 			reg = INA238_BUS_UNDER_VOLTAGE;
244 			break;
245 		case hwmon_in_max_alarm:
246 			reg = INA238_DIAG_ALERT;
247 			mask = INA238_DIAG_ALERT_BUSOL;
248 			break;
249 		case hwmon_in_min_alarm:
250 			reg = INA238_DIAG_ALERT;
251 			mask = INA238_DIAG_ALERT_BUSUL;
252 			break;
253 		default:
254 			return -EOPNOTSUPP;
255 		}
256 		break;
257 	default:
258 		return -EOPNOTSUPP;
259 	}
260 
261 	err = regmap_read(data->regmap, reg, &regval);
262 	if (err < 0)
263 		return err;
264 
265 	switch (attr) {
266 	case hwmon_in_input:
267 	case hwmon_in_max:
268 	case hwmon_in_min:
269 		/* signed register, value in mV */
270 		regval = (s16)regval;
271 		if (channel == 0)
272 			/* gain of 1 -> LSB / 4 */
273 			*val = (regval * INA238_SHUNT_VOLTAGE_LSB) *
274 					data->gain / (1000 * 4);
275 		else
276 			*val = (regval * data->config->bus_voltage_lsb) / 1000;
277 		break;
278 	case hwmon_in_max_alarm:
279 	case hwmon_in_min_alarm:
280 		*val = !!(regval & mask);
281 		break;
282 	}
283 
284 	return 0;
285 }
286 
287 static int ina238_write_in(struct device *dev, u32 attr, int channel,
288 			   long val)
289 {
290 	struct ina238_data *data = dev_get_drvdata(dev);
291 	int regval;
292 
293 	if (attr != hwmon_in_max && attr != hwmon_in_min)
294 		return -EOPNOTSUPP;
295 
296 	/* convert decimal to register value */
297 	switch (channel) {
298 	case 0:
299 		/* signed value, clamp to max range +/-163 mV */
300 		regval = clamp_val(val, -163, 163);
301 		regval = (regval * 1000 * 4) /
302 			 (INA238_SHUNT_VOLTAGE_LSB * data->gain);
303 		regval = clamp_val(regval, S16_MIN, S16_MAX);
304 
305 		switch (attr) {
306 		case hwmon_in_max:
307 			return regmap_write(data->regmap,
308 					    INA238_SHUNT_OVER_VOLTAGE, regval);
309 		case hwmon_in_min:
310 			return regmap_write(data->regmap,
311 					    INA238_SHUNT_UNDER_VOLTAGE, regval);
312 		default:
313 			return -EOPNOTSUPP;
314 		}
315 	case 1:
316 		/* signed value, positive values only. Clamp to max 102.396 V */
317 		regval = clamp_val(val, 0, 102396);
318 		regval = (regval * 1000) / data->config->bus_voltage_lsb;
319 		regval = clamp_val(regval, 0, S16_MAX);
320 
321 		switch (attr) {
322 		case hwmon_in_max:
323 			return regmap_write(data->regmap,
324 					    INA238_BUS_OVER_VOLTAGE, regval);
325 		case hwmon_in_min:
326 			return regmap_write(data->regmap,
327 					    INA238_BUS_UNDER_VOLTAGE, regval);
328 		default:
329 			return -EOPNOTSUPP;
330 		}
331 	default:
332 		return -EOPNOTSUPP;
333 	}
334 }
335 
336 static int ina238_read_current(struct device *dev, u32 attr, long *val)
337 {
338 	struct ina238_data *data = dev_get_drvdata(dev);
339 	int regval;
340 	int err;
341 
342 	switch (attr) {
343 	case hwmon_curr_input:
344 		err = regmap_read(data->regmap, INA238_CURRENT, &regval);
345 		if (err < 0)
346 			return err;
347 
348 		/* Signed register, fixed 1mA current lsb. result in mA */
349 		*val = div_s64((s16)regval * INA238_FIXED_SHUNT * data->gain,
350 			       data->rshunt * 4);
351 		break;
352 	default:
353 		return -EOPNOTSUPP;
354 	}
355 
356 	return 0;
357 }
358 
359 static int ina238_read_power(struct device *dev, u32 attr, long *val)
360 {
361 	struct ina238_data *data = dev_get_drvdata(dev);
362 	long long power;
363 	int regval;
364 	int err;
365 
366 	switch (attr) {
367 	case hwmon_power_input:
368 		err = ina238_read_reg24(data->client, INA238_POWER, &regval);
369 		if (err)
370 			return err;
371 
372 		/* Fixed 1mA lsb, scaled by 1000000 to have result in uW */
373 		power = div_u64(regval * 1000ULL * INA238_FIXED_SHUNT *	data->gain *
374 				data->config->power_calculate_factor, 4 * 100 * data->rshunt);
375 		/* Clamp value to maximum value of long */
376 		*val = clamp_val(power, 0, LONG_MAX);
377 		break;
378 	case hwmon_power_input_highest:
379 		err = ina238_read_reg24(data->client, SQ52206_POWER_PEAK, &regval);
380 		if (err)
381 			return err;
382 
383 		/* Fixed 1mA lsb, scaled by 1000000 to have result in uW */
384 		power = div_u64(regval * 1000ULL * INA238_FIXED_SHUNT *	data->gain *
385 				data->config->power_calculate_factor, 4 * 100 * data->rshunt);
386 		/* Clamp value to maximum value of long */
387 		*val = clamp_val(power, 0, LONG_MAX);
388 		break;
389 	case hwmon_power_max:
390 		err = regmap_read(data->regmap, INA238_POWER_LIMIT, &regval);
391 		if (err)
392 			return err;
393 
394 		/*
395 		 * Truncated 24-bit compare register, lower 8-bits are
396 		 * truncated. Same conversion to/from uW as POWER register.
397 		 */
398 		power = div_u64((regval << 8) * 1000ULL * INA238_FIXED_SHUNT *	data->gain *
399 				data->config->power_calculate_factor, 4 * 100 * data->rshunt);
400 		/* Clamp value to maximum value of long */
401 		*val = clamp_val(power, 0, LONG_MAX);
402 		break;
403 	case hwmon_power_max_alarm:
404 		err = regmap_read(data->regmap, INA238_DIAG_ALERT, &regval);
405 		if (err)
406 			return err;
407 
408 		*val = !!(regval & INA238_DIAG_ALERT_POL);
409 		break;
410 	default:
411 		return -EOPNOTSUPP;
412 	}
413 
414 	return 0;
415 }
416 
417 static int ina238_write_power(struct device *dev, u32 attr, long val)
418 {
419 	struct ina238_data *data = dev_get_drvdata(dev);
420 	long regval;
421 
422 	if (attr != hwmon_power_max)
423 		return -EOPNOTSUPP;
424 
425 	/*
426 	 * Unsigned postive values. Compared against the 24-bit power register,
427 	 * lower 8-bits are truncated. Same conversion to/from uW as POWER
428 	 * register.
429 	 */
430 	regval = clamp_val(val, 0, LONG_MAX);
431 	regval = div_u64(val * 4 * 100 * data->rshunt, data->config->power_calculate_factor *
432 			1000ULL * INA238_FIXED_SHUNT * data->gain);
433 	regval = clamp_val(regval >> 8, 0, U16_MAX);
434 
435 	return regmap_write(data->regmap, INA238_POWER_LIMIT, regval);
436 }
437 
438 static int ina238_read_temp(struct device *dev, u32 attr, long *val)
439 {
440 	struct ina238_data *data = dev_get_drvdata(dev);
441 	int regval;
442 	int err;
443 
444 	switch (attr) {
445 	case hwmon_temp_input:
446 		err = regmap_read(data->regmap, INA238_DIE_TEMP, &regval);
447 		if (err)
448 			return err;
449 		/* Signed, result in mC */
450 		*val = div_s64(((s64)((s16)regval) >> data->config->temp_shift) *
451 						(s64)data->config->temp_lsb, 10000);
452 		break;
453 	case hwmon_temp_max:
454 		err = regmap_read(data->regmap, INA238_TEMP_LIMIT, &regval);
455 		if (err)
456 			return err;
457 		/* Signed, result in mC */
458 		*val = div_s64(((s64)((s16)regval) >> data->config->temp_shift) *
459 						(s64)data->config->temp_lsb, 10000);
460 		break;
461 	case hwmon_temp_max_alarm:
462 		err = regmap_read(data->regmap, INA238_DIAG_ALERT, &regval);
463 		if (err)
464 			return err;
465 
466 		*val = !!(regval & INA238_DIAG_ALERT_TMPOL);
467 		break;
468 	default:
469 		return -EOPNOTSUPP;
470 	}
471 
472 	return 0;
473 }
474 
475 static int ina238_write_temp(struct device *dev, u32 attr, long val)
476 {
477 	struct ina238_data *data = dev_get_drvdata(dev);
478 	int regval;
479 
480 	if (attr != hwmon_temp_max)
481 		return -EOPNOTSUPP;
482 
483 	/* Signed */
484 	regval = clamp_val(val, -40000, 125000);
485 	regval = div_s64(val * 10000, data->config->temp_lsb) << data->config->temp_shift;
486 	regval = clamp_val(regval, S16_MIN, S16_MAX) & (0xffff << data->config->temp_shift);
487 
488 	return regmap_write(data->regmap, INA238_TEMP_LIMIT, regval);
489 }
490 
491 static ssize_t energy1_input_show(struct device *dev,
492 				  struct device_attribute *da, char *buf)
493 {
494 	struct ina238_data *data = dev_get_drvdata(dev);
495 	int ret;
496 	u64 regval;
497 	u64 energy;
498 
499 	ret = ina238_read_reg40(data->client, SQ52206_ENERGY, &regval);
500 	if (ret)
501 		return ret;
502 
503 	/* result in mJ */
504 	energy = div_u64(regval * INA238_FIXED_SHUNT *	data->gain * 16 *
505 				data->config->power_calculate_factor, 4 * 100 * data->rshunt);
506 
507 	return sysfs_emit(buf, "%llu\n", energy);
508 }
509 
510 static int ina238_read(struct device *dev, enum hwmon_sensor_types type,
511 		       u32 attr, int channel, long *val)
512 {
513 	switch (type) {
514 	case hwmon_in:
515 		return ina238_read_in(dev, attr, channel, val);
516 	case hwmon_curr:
517 		return ina238_read_current(dev, attr, val);
518 	case hwmon_power:
519 		return ina238_read_power(dev, attr, val);
520 	case hwmon_temp:
521 		return ina238_read_temp(dev, attr, val);
522 	default:
523 		return -EOPNOTSUPP;
524 	}
525 	return 0;
526 }
527 
528 static int ina238_write(struct device *dev, enum hwmon_sensor_types type,
529 			u32 attr, int channel, long val)
530 {
531 	struct ina238_data *data = dev_get_drvdata(dev);
532 	int err;
533 
534 	mutex_lock(&data->config_lock);
535 
536 	switch (type) {
537 	case hwmon_in:
538 		err = ina238_write_in(dev, attr, channel, val);
539 		break;
540 	case hwmon_power:
541 		err = ina238_write_power(dev, attr, val);
542 		break;
543 	case hwmon_temp:
544 		err = ina238_write_temp(dev, attr, val);
545 		break;
546 	default:
547 		err = -EOPNOTSUPP;
548 		break;
549 	}
550 
551 	mutex_unlock(&data->config_lock);
552 	return err;
553 }
554 
555 static umode_t ina238_is_visible(const void *drvdata,
556 				 enum hwmon_sensor_types type,
557 				 u32 attr, int channel)
558 {
559 	const struct ina238_data *data = drvdata;
560 	bool has_power_highest = data->config->has_power_highest;
561 
562 	switch (type) {
563 	case hwmon_in:
564 		switch (attr) {
565 		case hwmon_in_input:
566 		case hwmon_in_max_alarm:
567 		case hwmon_in_min_alarm:
568 			return 0444;
569 		case hwmon_in_max:
570 		case hwmon_in_min:
571 			return 0644;
572 		default:
573 			return 0;
574 		}
575 	case hwmon_curr:
576 		switch (attr) {
577 		case hwmon_curr_input:
578 			return 0444;
579 		default:
580 			return 0;
581 		}
582 	case hwmon_power:
583 		switch (attr) {
584 		case hwmon_power_input:
585 		case hwmon_power_max_alarm:
586 			return 0444;
587 		case hwmon_power_max:
588 			return 0644;
589 		case hwmon_power_input_highest:
590 			if (has_power_highest)
591 				return 0444;
592 			return 0;
593 		default:
594 			return 0;
595 		}
596 	case hwmon_temp:
597 		switch (attr) {
598 		case hwmon_temp_input:
599 		case hwmon_temp_max_alarm:
600 			return 0444;
601 		case hwmon_temp_max:
602 			return 0644;
603 		default:
604 			return 0;
605 		}
606 	default:
607 		return 0;
608 	}
609 }
610 
611 #define INA238_HWMON_IN_CONFIG (HWMON_I_INPUT | \
612 				HWMON_I_MAX | HWMON_I_MAX_ALARM | \
613 				HWMON_I_MIN | HWMON_I_MIN_ALARM)
614 
615 static const struct hwmon_channel_info * const ina238_info[] = {
616 	HWMON_CHANNEL_INFO(in,
617 			   /* 0: shunt voltage */
618 			   INA238_HWMON_IN_CONFIG,
619 			   /* 1: bus voltage */
620 			   INA238_HWMON_IN_CONFIG),
621 	HWMON_CHANNEL_INFO(curr,
622 			   /* 0: current through shunt */
623 			   HWMON_C_INPUT),
624 	HWMON_CHANNEL_INFO(power,
625 			   /* 0: power */
626 			   HWMON_P_INPUT | HWMON_P_MAX |
627 			   HWMON_P_MAX_ALARM | HWMON_P_INPUT_HIGHEST),
628 	HWMON_CHANNEL_INFO(temp,
629 			   /* 0: die temperature */
630 			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_ALARM),
631 	NULL
632 };
633 
634 static const struct hwmon_ops ina238_hwmon_ops = {
635 	.is_visible = ina238_is_visible,
636 	.read = ina238_read,
637 	.write = ina238_write,
638 };
639 
640 static const struct hwmon_chip_info ina238_chip_info = {
641 	.ops = &ina238_hwmon_ops,
642 	.info = ina238_info,
643 };
644 
645 /* energy attributes are 5 bytes wide so we need u64 */
646 static DEVICE_ATTR_RO(energy1_input);
647 
648 static struct attribute *ina238_attrs[] = {
649 	&dev_attr_energy1_input.attr,
650 	NULL,
651 };
652 ATTRIBUTE_GROUPS(ina238);
653 
654 static int ina238_probe(struct i2c_client *client)
655 {
656 	struct ina2xx_platform_data *pdata = dev_get_platdata(&client->dev);
657 	struct device *dev = &client->dev;
658 	struct device *hwmon_dev;
659 	struct ina238_data *data;
660 	enum ina238_ids chip;
661 	int config;
662 	int ret;
663 
664 	chip = (uintptr_t)i2c_get_match_data(client);
665 
666 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
667 	if (!data)
668 		return -ENOMEM;
669 
670 	data->client = client;
671 	/* set the device type */
672 	data->config = &ina238_config[chip];
673 
674 	mutex_init(&data->config_lock);
675 
676 	data->regmap = devm_regmap_init_i2c(client, &ina238_regmap_config);
677 	if (IS_ERR(data->regmap)) {
678 		dev_err(dev, "failed to allocate register map\n");
679 		return PTR_ERR(data->regmap);
680 	}
681 
682 	/* load shunt value */
683 	data->rshunt = INA238_RSHUNT_DEFAULT;
684 	if (device_property_read_u32(dev, "shunt-resistor", &data->rshunt) < 0 && pdata)
685 		data->rshunt = pdata->shunt_uohms;
686 	if (data->rshunt == 0) {
687 		dev_err(dev, "invalid shunt resister value %u\n", data->rshunt);
688 		return -EINVAL;
689 	}
690 
691 	/* load shunt gain value */
692 	if (device_property_read_u32(dev, "ti,shunt-gain", &data->gain) < 0)
693 		data->gain = 4; /* Default of ADCRANGE = 0 */
694 	if (data->gain != 1 && data->gain != 2 && data->gain != 4) {
695 		dev_err(dev, "invalid shunt gain value %u\n", data->gain);
696 		return -EINVAL;
697 	}
698 
699 	/* Setup CONFIG register */
700 	config = data->config->config_default;
701 	if (chip == sq52206) {
702 		if (data->gain == 1)
703 			config |= SQ52206_CONFIG_ADCRANGE_HIGH; /* ADCRANGE = 10/11 is /1 */
704 		else if (data->gain == 2)
705 			config |= SQ52206_CONFIG_ADCRANGE_LOW; /* ADCRANGE = 01 is /2 */
706 	} else if (data->gain == 1) {
707 		config |= INA238_CONFIG_ADCRANGE; /* ADCRANGE = 1 is /1 */
708 	}
709 	ret = regmap_write(data->regmap, INA238_CONFIG, config);
710 	if (ret < 0) {
711 		dev_err(dev, "error configuring the device: %d\n", ret);
712 		return -ENODEV;
713 	}
714 
715 	/* Setup ADC_CONFIG register */
716 	ret = regmap_write(data->regmap, INA238_ADC_CONFIG,
717 			   INA238_ADC_CONFIG_DEFAULT);
718 	if (ret < 0) {
719 		dev_err(dev, "error configuring the device: %d\n", ret);
720 		return -ENODEV;
721 	}
722 
723 	/* Setup SHUNT_CALIBRATION register with fixed value */
724 	ret = regmap_write(data->regmap, INA238_SHUNT_CALIBRATION,
725 			   INA238_CALIBRATION_VALUE);
726 	if (ret < 0) {
727 		dev_err(dev, "error configuring the device: %d\n", ret);
728 		return -ENODEV;
729 	}
730 
731 	/* Setup alert/alarm configuration */
732 	ret = regmap_write(data->regmap, INA238_DIAG_ALERT,
733 			   INA238_DIAG_ALERT_DEFAULT);
734 	if (ret < 0) {
735 		dev_err(dev, "error configuring the device: %d\n", ret);
736 		return -ENODEV;
737 	}
738 
739 	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data,
740 							 &ina238_chip_info,
741 							 data->config->has_energy ?
742 								ina238_groups : NULL);
743 	if (IS_ERR(hwmon_dev))
744 		return PTR_ERR(hwmon_dev);
745 
746 	dev_info(dev, "power monitor %s (Rshunt = %u uOhm, gain = %u)\n",
747 		 client->name, data->rshunt, data->gain);
748 
749 	return 0;
750 }
751 
752 static const struct i2c_device_id ina238_id[] = {
753 	{ "ina237", ina237 },
754 	{ "ina238", ina238 },
755 	{ "sq52206", sq52206 },
756 	{ }
757 };
758 MODULE_DEVICE_TABLE(i2c, ina238_id);
759 
760 static const struct of_device_id __maybe_unused ina238_of_match[] = {
761 	{
762 		.compatible = "ti,ina237",
763 		.data = (void *)ina237
764 	},
765 	{
766 		.compatible = "ti,ina238",
767 		.data = (void *)ina238
768 	},
769 	{
770 		.compatible = "silergy,sq52206",
771 		.data = (void *)sq52206
772 	},
773 	{ }
774 };
775 MODULE_DEVICE_TABLE(of, ina238_of_match);
776 
777 static struct i2c_driver ina238_driver = {
778 	.driver = {
779 		.name	= "ina238",
780 		.of_match_table = of_match_ptr(ina238_of_match),
781 	},
782 	.probe		= ina238_probe,
783 	.id_table	= ina238_id,
784 };
785 
786 module_i2c_driver(ina238_driver);
787 
788 MODULE_AUTHOR("Nathan Rossi <nathan.rossi@digi.com>");
789 MODULE_DESCRIPTION("ina238 driver");
790 MODULE_LICENSE("GPL");
791