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