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 INA238_SHUNT_VOLTAGE		0x4
25#define INA238_BUS_VOLTAGE		0x5
26#define INA238_DIE_TEMP			0x6
27#define INA238_CURRENT			0x7
28#define INA238_POWER			0x8
29#define INA238_DIAG_ALERT		0xb
30#define INA238_SHUNT_OVER_VOLTAGE	0xc
31#define INA238_SHUNT_UNDER_VOLTAGE	0xd
32#define INA238_BUS_OVER_VOLTAGE		0xe
33#define INA238_BUS_UNDER_VOLTAGE	0xf
34#define INA238_TEMP_LIMIT		0x10
35#define INA238_POWER_LIMIT		0x11
36#define INA238_DEVICE_ID		0x3f /* not available on INA237 */
37
38#define INA238_CONFIG_ADCRANGE		BIT(4)
39
40#define INA238_DIAG_ALERT_TMPOL		BIT(7)
41#define INA238_DIAG_ALERT_SHNTOL	BIT(6)
42#define INA238_DIAG_ALERT_SHNTUL	BIT(5)
43#define INA238_DIAG_ALERT_BUSOL		BIT(4)
44#define INA238_DIAG_ALERT_BUSUL		BIT(3)
45#define INA238_DIAG_ALERT_POL		BIT(2)
46
47#define INA238_REGISTERS		0x11
48
49#define INA238_RSHUNT_DEFAULT		10000 /* uOhm */
50
51/* Default configuration of device on reset. */
52#define INA238_CONFIG_DEFAULT		0
53/* 16 sample averaging, 1052us conversion time, continuous mode */
54#define INA238_ADC_CONFIG_DEFAULT	0xfb6a
55/* Configure alerts to be based on averaged value (SLOWALERT) */
56#define INA238_DIAG_ALERT_DEFAULT	0x2000
57/*
58 * This driver uses a fixed calibration value in order to scale current/power
59 * based on a fixed shunt resistor value. This allows for conversion within the
60 * device to avoid integer limits whilst current/power accuracy is scaled
61 * relative to the shunt resistor value within the driver. This is similar to
62 * how the ina2xx driver handles current/power scaling.
63 *
64 * The end result of this is that increasing shunt values (from a fixed 20 mOhm
65 * shunt) increase the effective current/power accuracy whilst limiting the
66 * range and decreasing shunt values decrease the effective accuracy but
67 * increase the range.
68 *
69 * The value of the Current register is calculated given the following:
70 *   Current (A) = (shunt voltage register * 5) * calibration / 81920
71 *
72 * The maximum shunt voltage is 163.835 mV (0x7fff, ADC_RANGE = 0, gain = 4).
73 * With the maximum current value of 0x7fff and a fixed shunt value results in
74 * a calibration value of 16384 (0x4000).
75 *
76 *   0x7fff = (0x7fff * 5) * calibration / 81920
77 *   calibration = 0x4000
78 *
79 * Equivalent calibration is applied for the Power register (maximum value for
80 * bus voltage is 102396.875 mV, 0x7fff), where the maximum power that can
81 * occur is ~16776192 uW (register value 0x147a8):
82 *
83 * This scaling means the resulting values for Current and Power registers need
84 * to be scaled by the difference between the fixed shunt resistor and the
85 * actual shunt resistor:
86 *
87 *  shunt = 0x4000 / (819.2 * 10^6) / 0.001 = 20000 uOhms (with 1mA/lsb)
88 *
89 *  Current (mA) = register value * 20000 / rshunt / 4 * gain
90 *  Power (W) = 0.2 * register value * 20000 / rshunt / 4 * gain
91 */
92#define INA238_CALIBRATION_VALUE	16384
93#define INA238_FIXED_SHUNT		20000
94
95#define INA238_SHUNT_VOLTAGE_LSB	5 /* 5 uV/lsb */
96#define INA238_BUS_VOLTAGE_LSB		3125 /* 3.125 mV/lsb */
97#define INA238_DIE_TEMP_LSB		125 /* 125 mC/lsb */
98
99static struct regmap_config ina238_regmap_config = {
100	.max_register = INA238_REGISTERS,
101	.reg_bits = 8,
102	.val_bits = 16,
103};
104
105struct ina238_data {
106	struct i2c_client *client;
107	struct mutex config_lock;
108	struct regmap *regmap;
109	u32 rshunt;
110	int gain;
111};
112
113static int ina238_read_reg24(const struct i2c_client *client, u8 reg, u32 *val)
114{
115	u8 data[3];
116	int err;
117
118	/* 24-bit register read */
119	err = i2c_smbus_read_i2c_block_data(client, reg, 3, data);
120	if (err < 0)
121		return err;
122	if (err != 3)
123		return -EIO;
124	*val = (data[0] << 16) | (data[1] << 8) | data[2];
125
126	return 0;
127}
128
129static int ina238_read_in(struct device *dev, u32 attr, int channel,
130			  long *val)
131{
132	struct ina238_data *data = dev_get_drvdata(dev);
133	int reg, mask;
134	int regval;
135	int err;
136
137	switch (channel) {
138	case 0:
139		switch (attr) {
140		case hwmon_in_input:
141			reg = INA238_SHUNT_VOLTAGE;
142			break;
143		case hwmon_in_max:
144			reg = INA238_SHUNT_OVER_VOLTAGE;
145			break;
146		case hwmon_in_min:
147			reg = INA238_SHUNT_UNDER_VOLTAGE;
148			break;
149		case hwmon_in_max_alarm:
150			reg = INA238_DIAG_ALERT;
151			mask = INA238_DIAG_ALERT_SHNTOL;
152			break;
153		case hwmon_in_min_alarm:
154			reg = INA238_DIAG_ALERT;
155			mask = INA238_DIAG_ALERT_SHNTUL;
156			break;
157		default:
158			return -EOPNOTSUPP;
159		}
160		break;
161	case 1:
162		switch (attr) {
163		case hwmon_in_input:
164			reg = INA238_BUS_VOLTAGE;
165			break;
166		case hwmon_in_max:
167			reg = INA238_BUS_OVER_VOLTAGE;
168			break;
169		case hwmon_in_min:
170			reg = INA238_BUS_UNDER_VOLTAGE;
171			break;
172		case hwmon_in_max_alarm:
173			reg = INA238_DIAG_ALERT;
174			mask = INA238_DIAG_ALERT_BUSOL;
175			break;
176		case hwmon_in_min_alarm:
177			reg = INA238_DIAG_ALERT;
178			mask = INA238_DIAG_ALERT_BUSUL;
179			break;
180		default:
181			return -EOPNOTSUPP;
182		}
183		break;
184	default:
185		return -EOPNOTSUPP;
186	}
187
188	err = regmap_read(data->regmap, reg, &regval);
189	if (err < 0)
190		return err;
191
192	switch (attr) {
193	case hwmon_in_input:
194	case hwmon_in_max:
195	case hwmon_in_min:
196		/* signed register, value in mV */
197		regval = (s16)regval;
198		if (channel == 0)
199			/* gain of 1 -> LSB / 4 */
200			*val = (regval * INA238_SHUNT_VOLTAGE_LSB) /
201			       (1000 * (4 - data->gain + 1));
202		else
203			*val = (regval * INA238_BUS_VOLTAGE_LSB) / 1000;
204		break;
205	case hwmon_in_max_alarm:
206	case hwmon_in_min_alarm:
207		*val = !!(regval & mask);
208		break;
209	}
210
211	return 0;
212}
213
214static int ina238_write_in(struct device *dev, u32 attr, int channel,
215			   long val)
216{
217	struct ina238_data *data = dev_get_drvdata(dev);
218	int regval;
219
220	if (attr != hwmon_in_max && attr != hwmon_in_min)
221		return -EOPNOTSUPP;
222
223	/* convert decimal to register value */
224	switch (channel) {
225	case 0:
226		/* signed value, clamp to max range +/-163 mV */
227		regval = clamp_val(val, -163, 163);
228		regval = (regval * 1000 * (4 - data->gain + 1)) /
229			 INA238_SHUNT_VOLTAGE_LSB;
230		regval = clamp_val(regval, S16_MIN, S16_MAX);
231
232		switch (attr) {
233		case hwmon_in_max:
234			return regmap_write(data->regmap,
235					    INA238_SHUNT_OVER_VOLTAGE, regval);
236		case hwmon_in_min:
237			return regmap_write(data->regmap,
238					    INA238_SHUNT_UNDER_VOLTAGE, regval);
239		default:
240			return -EOPNOTSUPP;
241		}
242	case 1:
243		/* signed value, positive values only. Clamp to max 102.396 V */
244		regval = clamp_val(val, 0, 102396);
245		regval = (regval * 1000) / INA238_BUS_VOLTAGE_LSB;
246		regval = clamp_val(regval, 0, S16_MAX);
247
248		switch (attr) {
249		case hwmon_in_max:
250			return regmap_write(data->regmap,
251					    INA238_BUS_OVER_VOLTAGE, regval);
252		case hwmon_in_min:
253			return regmap_write(data->regmap,
254					    INA238_BUS_UNDER_VOLTAGE, regval);
255		default:
256			return -EOPNOTSUPP;
257		}
258	default:
259		return -EOPNOTSUPP;
260	}
261}
262
263static int ina238_read_current(struct device *dev, u32 attr, long *val)
264{
265	struct ina238_data *data = dev_get_drvdata(dev);
266	int regval;
267	int err;
268
269	switch (attr) {
270	case hwmon_curr_input:
271		err = regmap_read(data->regmap, INA238_CURRENT, &regval);
272		if (err < 0)
273			return err;
274
275		/* Signed register, fixed 1mA current lsb. result in mA */
276		*val = div_s64((s16)regval * INA238_FIXED_SHUNT * data->gain,
277			       data->rshunt * 4);
278		break;
279	default:
280		return -EOPNOTSUPP;
281	}
282
283	return 0;
284}
285
286static int ina238_read_power(struct device *dev, u32 attr, long *val)
287{
288	struct ina238_data *data = dev_get_drvdata(dev);
289	long long power;
290	int regval;
291	int err;
292
293	switch (attr) {
294	case hwmon_power_input:
295		err = ina238_read_reg24(data->client, INA238_POWER, &regval);
296		if (err)
297			return err;
298
299		/* Fixed 1mA lsb, scaled by 1000000 to have result in uW */
300		power = div_u64(regval * 1000ULL * INA238_FIXED_SHUNT *
301				data->gain, 20 * data->rshunt);
302		/* Clamp value to maximum value of long */
303		*val = clamp_val(power, 0, LONG_MAX);
304		break;
305	case hwmon_power_max:
306		err = regmap_read(data->regmap, INA238_POWER_LIMIT, &regval);
307		if (err)
308			return err;
309
310		/*
311		 * Truncated 24-bit compare register, lower 8-bits are
312		 * truncated. Same conversion to/from uW as POWER register.
313		 */
314		power = div_u64((regval << 8) * 1000ULL * INA238_FIXED_SHUNT *
315			       data->gain, 20 * data->rshunt);
316		/* Clamp value to maximum value of long */
317		*val = clamp_val(power, 0, LONG_MAX);
318		break;
319	case hwmon_power_max_alarm:
320		err = regmap_read(data->regmap, INA238_DIAG_ALERT, &regval);
321		if (err)
322			return err;
323
324		*val = !!(regval & INA238_DIAG_ALERT_POL);
325		break;
326	default:
327		return -EOPNOTSUPP;
328	}
329
330	return 0;
331}
332
333static int ina238_write_power(struct device *dev, u32 attr, long val)
334{
335	struct ina238_data *data = dev_get_drvdata(dev);
336	long regval;
337
338	if (attr != hwmon_power_max)
339		return -EOPNOTSUPP;
340
341	/*
342	 * Unsigned postive values. Compared against the 24-bit power register,
343	 * lower 8-bits are truncated. Same conversion to/from uW as POWER
344	 * register.
345	 */
346	regval = clamp_val(val, 0, LONG_MAX);
347	regval = div_u64(val * 20ULL * data->rshunt,
348			 1000ULL * INA238_FIXED_SHUNT * data->gain);
349	regval = clamp_val(regval >> 8, 0, U16_MAX);
350
351	return regmap_write(data->regmap, INA238_POWER_LIMIT, regval);
352}
353
354static int ina238_read_temp(struct device *dev, u32 attr, long *val)
355{
356	struct ina238_data *data = dev_get_drvdata(dev);
357	int regval;
358	int err;
359
360	switch (attr) {
361	case hwmon_temp_input:
362		err = regmap_read(data->regmap, INA238_DIE_TEMP, &regval);
363		if (err)
364			return err;
365
366		/* Signed, bits 15-4 of register, result in mC */
367		*val = ((s16)regval >> 4) * INA238_DIE_TEMP_LSB;
368		break;
369	case hwmon_temp_max:
370		err = regmap_read(data->regmap, INA238_TEMP_LIMIT, &regval);
371		if (err)
372			return err;
373
374		/* Signed, bits 15-4 of register, result in mC */
375		*val = ((s16)regval >> 4) * INA238_DIE_TEMP_LSB;
376		break;
377	case hwmon_temp_max_alarm:
378		err = regmap_read(data->regmap, INA238_DIAG_ALERT, &regval);
379		if (err)
380			return err;
381
382		*val = !!(regval & INA238_DIAG_ALERT_TMPOL);
383		break;
384	default:
385		return -EOPNOTSUPP;
386	}
387
388	return 0;
389}
390
391static int ina238_write_temp(struct device *dev, u32 attr, long val)
392{
393	struct ina238_data *data = dev_get_drvdata(dev);
394	int regval;
395
396	if (attr != hwmon_temp_max)
397		return -EOPNOTSUPP;
398
399	/* Signed, bits 15-4 of register */
400	regval = (val / INA238_DIE_TEMP_LSB) << 4;
401	regval = clamp_val(regval, S16_MIN, S16_MAX) & 0xfff0;
402
403	return regmap_write(data->regmap, INA238_TEMP_LIMIT, regval);
404}
405
406static int ina238_read(struct device *dev, enum hwmon_sensor_types type,
407		       u32 attr, int channel, long *val)
408{
409	switch (type) {
410	case hwmon_in:
411		return ina238_read_in(dev, attr, channel, val);
412	case hwmon_curr:
413		return ina238_read_current(dev, attr, val);
414	case hwmon_power:
415		return ina238_read_power(dev, attr, val);
416	case hwmon_temp:
417		return ina238_read_temp(dev, attr, val);
418	default:
419		return -EOPNOTSUPP;
420	}
421	return 0;
422}
423
424static int ina238_write(struct device *dev, enum hwmon_sensor_types type,
425		       u32 attr, int channel, long val)
426{
427	struct ina238_data *data = dev_get_drvdata(dev);
428	int err;
429
430	mutex_lock(&data->config_lock);
431
432	switch (type) {
433	case hwmon_in:
434		err = ina238_write_in(dev, attr, channel, val);
435		break;
436	case hwmon_power:
437		err = ina238_write_power(dev, attr, val);
438		break;
439	case hwmon_temp:
440		err = ina238_write_temp(dev, attr, val);
441		break;
442	default:
443		err = -EOPNOTSUPP;
444		break;
445	}
446
447	mutex_unlock(&data->config_lock);
448	return err;
449}
450
451static umode_t ina238_is_visible(const void *drvdata,
452				 enum hwmon_sensor_types type,
453				 u32 attr, int channel)
454{
455	switch (type) {
456	case hwmon_in:
457		switch (attr) {
458		case hwmon_in_input:
459		case hwmon_in_max_alarm:
460		case hwmon_in_min_alarm:
461			return 0444;
462		case hwmon_in_max:
463		case hwmon_in_min:
464			return 0644;
465		default:
466			return 0;
467		}
468	case hwmon_curr:
469		switch (attr) {
470		case hwmon_curr_input:
471			return 0444;
472		default:
473			return 0;
474		}
475	case hwmon_power:
476		switch (attr) {
477		case hwmon_power_input:
478		case hwmon_power_max_alarm:
479			return 0444;
480		case hwmon_power_max:
481			return 0644;
482		default:
483			return 0;
484		}
485	case hwmon_temp:
486		switch (attr) {
487		case hwmon_temp_input:
488		case hwmon_temp_max_alarm:
489			return 0444;
490		case hwmon_temp_max:
491			return 0644;
492		default:
493			return 0;
494		}
495	default:
496		return 0;
497	}
498}
499
500#define INA238_HWMON_IN_CONFIG (HWMON_I_INPUT | \
501				HWMON_I_MAX | HWMON_I_MAX_ALARM | \
502				HWMON_I_MIN | HWMON_I_MIN_ALARM)
503
504static const struct hwmon_channel_info * const ina238_info[] = {
505	HWMON_CHANNEL_INFO(in,
506			   /* 0: shunt voltage */
507			   INA238_HWMON_IN_CONFIG,
508			   /* 1: bus voltage */
509			   INA238_HWMON_IN_CONFIG),
510	HWMON_CHANNEL_INFO(curr,
511			   /* 0: current through shunt */
512			   HWMON_C_INPUT),
513	HWMON_CHANNEL_INFO(power,
514			   /* 0: power */
515			   HWMON_P_INPUT | HWMON_P_MAX | HWMON_P_MAX_ALARM),
516	HWMON_CHANNEL_INFO(temp,
517			   /* 0: die temperature */
518			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_ALARM),
519	NULL
520};
521
522static const struct hwmon_ops ina238_hwmon_ops = {
523	.is_visible = ina238_is_visible,
524	.read = ina238_read,
525	.write = ina238_write,
526};
527
528static const struct hwmon_chip_info ina238_chip_info = {
529	.ops = &ina238_hwmon_ops,
530	.info = ina238_info,
531};
532
533static int ina238_probe(struct i2c_client *client)
534{
535	struct ina2xx_platform_data *pdata = dev_get_platdata(&client->dev);
536	struct device *dev = &client->dev;
537	struct device *hwmon_dev;
538	struct ina238_data *data;
539	int config;
540	int ret;
541
542	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
543	if (!data)
544		return -ENOMEM;
545
546	data->client = client;
547	mutex_init(&data->config_lock);
548
549	data->regmap = devm_regmap_init_i2c(client, &ina238_regmap_config);
550	if (IS_ERR(data->regmap)) {
551		dev_err(dev, "failed to allocate register map\n");
552		return PTR_ERR(data->regmap);
553	}
554
555	/* load shunt value */
556	data->rshunt = INA238_RSHUNT_DEFAULT;
557	if (device_property_read_u32(dev, "shunt-resistor", &data->rshunt) < 0 && pdata)
558		data->rshunt = pdata->shunt_uohms;
559	if (data->rshunt == 0) {
560		dev_err(dev, "invalid shunt resister value %u\n", data->rshunt);
561		return -EINVAL;
562	}
563
564	/* load shunt gain value */
565	if (device_property_read_u32(dev, "ti,shunt-gain", &data->gain) < 0)
566		data->gain = 4; /* Default of ADCRANGE = 0 */
567	if (data->gain != 1 && data->gain != 4) {
568		dev_err(dev, "invalid shunt gain value %u\n", data->gain);
569		return -EINVAL;
570	}
571
572	/* Setup CONFIG register */
573	config = INA238_CONFIG_DEFAULT;
574	if (data->gain == 1)
575		config |= INA238_CONFIG_ADCRANGE; /* ADCRANGE = 1 is /1 */
576	ret = regmap_write(data->regmap, INA238_CONFIG, config);
577	if (ret < 0) {
578		dev_err(dev, "error configuring the device: %d\n", ret);
579		return -ENODEV;
580	}
581
582	/* Setup ADC_CONFIG register */
583	ret = regmap_write(data->regmap, INA238_ADC_CONFIG,
584			   INA238_ADC_CONFIG_DEFAULT);
585	if (ret < 0) {
586		dev_err(dev, "error configuring the device: %d\n", ret);
587		return -ENODEV;
588	}
589
590	/* Setup SHUNT_CALIBRATION register with fixed value */
591	ret = regmap_write(data->regmap, INA238_SHUNT_CALIBRATION,
592			   INA238_CALIBRATION_VALUE);
593	if (ret < 0) {
594		dev_err(dev, "error configuring the device: %d\n", ret);
595		return -ENODEV;
596	}
597
598	/* Setup alert/alarm configuration */
599	ret = regmap_write(data->regmap, INA238_DIAG_ALERT,
600			   INA238_DIAG_ALERT_DEFAULT);
601	if (ret < 0) {
602		dev_err(dev, "error configuring the device: %d\n", ret);
603		return -ENODEV;
604	}
605
606	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data,
607							 &ina238_chip_info,
608							 NULL);
609	if (IS_ERR(hwmon_dev))
610		return PTR_ERR(hwmon_dev);
611
612	dev_info(dev, "power monitor %s (Rshunt = %u uOhm, gain = %u)\n",
613		 client->name, data->rshunt, data->gain);
614
615	return 0;
616}
617
618static const struct i2c_device_id ina238_id[] = {
619	{ "ina238", 0 },
620	{ }
621};
622MODULE_DEVICE_TABLE(i2c, ina238_id);
623
624static const struct of_device_id __maybe_unused ina238_of_match[] = {
625	{ .compatible = "ti,ina237" },
626	{ .compatible = "ti,ina238" },
627	{ },
628};
629MODULE_DEVICE_TABLE(of, ina238_of_match);
630
631static struct i2c_driver ina238_driver = {
632	.driver = {
633		.name	= "ina238",
634		.of_match_table = of_match_ptr(ina238_of_match),
635	},
636	.probe		= ina238_probe,
637	.id_table	= ina238_id,
638};
639
640module_i2c_driver(ina238_driver);
641
642MODULE_AUTHOR("Nathan Rossi <nathan.rossi@digi.com>");
643MODULE_DESCRIPTION("ina238 driver");
644MODULE_LICENSE("GPL");
645