xref: /openbmc/linux/drivers/iio/adc/max9611.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
12fa720b4SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0
269780a3bSJacopo Mondi /*
369780a3bSJacopo Mondi  * iio/adc/max9611.c
469780a3bSJacopo Mondi  *
569780a3bSJacopo Mondi  * Maxim max9611/max9612 high side current sense amplifier with
669780a3bSJacopo Mondi  * 12-bit ADC interface.
769780a3bSJacopo Mondi  *
869780a3bSJacopo Mondi  * Copyright (C) 2017 Jacopo Mondi
969780a3bSJacopo Mondi  */
1069780a3bSJacopo Mondi 
1169780a3bSJacopo Mondi /*
1269780a3bSJacopo Mondi  * This driver supports input common-mode voltage, current-sense
1369780a3bSJacopo Mondi  * amplifier with programmable gains and die temperature reading from
1469780a3bSJacopo Mondi  * Maxim max9611/max9612.
1569780a3bSJacopo Mondi  *
1669780a3bSJacopo Mondi  * Op-amp, analog comparator, and watchdog functionalities are not
1769780a3bSJacopo Mondi  * supported by this driver.
1869780a3bSJacopo Mondi  */
1969780a3bSJacopo Mondi 
2069780a3bSJacopo Mondi #include <linux/delay.h>
2169780a3bSJacopo Mondi #include <linux/i2c.h>
2269780a3bSJacopo Mondi #include <linux/iio/iio.h>
2369780a3bSJacopo Mondi #include <linux/iio/sysfs.h>
2469780a3bSJacopo Mondi #include <linux/module.h>
25c88eba5aSJonathan Cameron #include <linux/mod_devicetable.h>
26c88eba5aSJonathan Cameron #include <linux/property.h>
2769780a3bSJacopo Mondi 
2869780a3bSJacopo Mondi #define DRIVER_NAME			"max9611"
2969780a3bSJacopo Mondi 
3069780a3bSJacopo Mondi /* max9611 register addresses */
3169780a3bSJacopo Mondi #define MAX9611_REG_CSA_DATA		0x00
3269780a3bSJacopo Mondi #define MAX9611_REG_RS_DATA		0x02
3369780a3bSJacopo Mondi #define MAX9611_REG_TEMP_DATA		0x08
3469780a3bSJacopo Mondi #define MAX9611_REG_CTRL1		0x0a
3569780a3bSJacopo Mondi #define MAX9611_REG_CTRL2		0x0b
3669780a3bSJacopo Mondi 
3769780a3bSJacopo Mondi /* max9611 REG1 mux configuration options */
3869780a3bSJacopo Mondi #define MAX9611_MUX_MASK		GENMASK(3, 0)
3969780a3bSJacopo Mondi #define MAX9611_MUX_SENSE_1x		0x00
4069780a3bSJacopo Mondi #define MAX9611_MUX_SENSE_4x		0x01
4169780a3bSJacopo Mondi #define MAX9611_MUX_SENSE_8x		0x02
4269780a3bSJacopo Mondi #define MAX9611_INPUT_VOLT		0x03
4369780a3bSJacopo Mondi #define MAX9611_MUX_TEMP		0x06
4469780a3bSJacopo Mondi 
4569780a3bSJacopo Mondi /* max9611 voltage (both csa and input) helper macros */
4669780a3bSJacopo Mondi #define MAX9611_VOLTAGE_SHIFT		0x04
4769780a3bSJacopo Mondi #define MAX9611_VOLTAGE_RAW(_r)		((_r) >> MAX9611_VOLTAGE_SHIFT)
4869780a3bSJacopo Mondi 
4969780a3bSJacopo Mondi /*
5069780a3bSJacopo Mondi  * max9611 current sense amplifier voltage output:
5169780a3bSJacopo Mondi  * LSB and offset values depends on selected gain (1x, 4x, 8x)
5269780a3bSJacopo Mondi  *
5369780a3bSJacopo Mondi  * GAIN		LSB (nV)	OFFSET (LSB steps)
5469780a3bSJacopo Mondi  * 1x		107500		1
5569780a3bSJacopo Mondi  * 4x		26880		1
5669780a3bSJacopo Mondi  * 8x		13440		3
5769780a3bSJacopo Mondi  *
5869780a3bSJacopo Mondi  * The complete formula to calculate current sense voltage is:
5969780a3bSJacopo Mondi  *     (((adc_read >> 4) - offset) / ((1 / LSB) * 10^-3)
6069780a3bSJacopo Mondi  */
6169780a3bSJacopo Mondi #define MAX9611_CSA_1X_LSB_nV		107500
6269780a3bSJacopo Mondi #define MAX9611_CSA_4X_LSB_nV		26880
6369780a3bSJacopo Mondi #define MAX9611_CSA_8X_LSB_nV		13440
6469780a3bSJacopo Mondi 
6569780a3bSJacopo Mondi #define MAX9611_CSA_1X_OFFS_RAW		1
6669780a3bSJacopo Mondi #define MAX9611_CSA_4X_OFFS_RAW		1
6769780a3bSJacopo Mondi #define MAX9611_CSA_8X_OFFS_RAW		3
6869780a3bSJacopo Mondi 
6969780a3bSJacopo Mondi /*
7069780a3bSJacopo Mondi  * max9611 common input mode (CIM): LSB is 14mV, with 14mV offset at 25 C
7169780a3bSJacopo Mondi  *
7269780a3bSJacopo Mondi  * The complete formula to calculate input common voltage is:
7369780a3bSJacopo Mondi  *     (((adc_read >> 4) * 1000) - offset) / (1 / 14 * 1000)
7469780a3bSJacopo Mondi  */
7569780a3bSJacopo Mondi #define MAX9611_CIM_LSB_mV		14
7669780a3bSJacopo Mondi #define MAX9611_CIM_OFFSET_RAW		1
7769780a3bSJacopo Mondi 
7869780a3bSJacopo Mondi /*
7969780a3bSJacopo Mondi  * max9611 temperature reading: LSB is 480 milli degrees Celsius
8069780a3bSJacopo Mondi  *
8169780a3bSJacopo Mondi  * The complete formula to calculate temperature is:
8269780a3bSJacopo Mondi  *     ((adc_read >> 7) * 1000) / (1 / 480 * 1000)
8369780a3bSJacopo Mondi  */
8469780a3bSJacopo Mondi #define MAX9611_TEMP_MAX_POS		0x7f80
8569780a3bSJacopo Mondi #define MAX9611_TEMP_MAX_NEG		0xff80
8669780a3bSJacopo Mondi #define MAX9611_TEMP_MIN_NEG		0xd980
87ae8cc91aSJoe Perches #define MAX9611_TEMP_MASK		GENMASK(15, 7)
8869780a3bSJacopo Mondi #define MAX9611_TEMP_SHIFT		0x07
8969780a3bSJacopo Mondi #define MAX9611_TEMP_RAW(_r)		((_r) >> MAX9611_TEMP_SHIFT)
9069780a3bSJacopo Mondi #define MAX9611_TEMP_SCALE_NUM		1000000
9169780a3bSJacopo Mondi #define MAX9611_TEMP_SCALE_DIV		2083
9269780a3bSJacopo Mondi 
939fd229c4SGeert Uytterhoeven /*
949fd229c4SGeert Uytterhoeven  * Conversion time is 2 ms (typically) at Ta=25 degreeC
959fd229c4SGeert Uytterhoeven  * No maximum value is known, so play it safe.
969fd229c4SGeert Uytterhoeven  */
979fd229c4SGeert Uytterhoeven #define MAX9611_CONV_TIME_US_RANGE	3000, 3300
989fd229c4SGeert Uytterhoeven 
9969780a3bSJacopo Mondi struct max9611_dev {
10069780a3bSJacopo Mondi 	struct device *dev;
10169780a3bSJacopo Mondi 	struct i2c_client *i2c_client;
10269780a3bSJacopo Mondi 	struct mutex lock;
10369780a3bSJacopo Mondi 	unsigned int shunt_resistor_uohm;
10469780a3bSJacopo Mondi };
10569780a3bSJacopo Mondi 
10669780a3bSJacopo Mondi enum max9611_conf_ids {
10769780a3bSJacopo Mondi 	CONF_SENSE_1x,
10869780a3bSJacopo Mondi 	CONF_SENSE_4x,
10969780a3bSJacopo Mondi 	CONF_SENSE_8x,
11069780a3bSJacopo Mondi 	CONF_IN_VOLT,
11169780a3bSJacopo Mondi 	CONF_TEMP,
11269780a3bSJacopo Mondi };
11369780a3bSJacopo Mondi 
114922fdc19SLee Jones /*
11569780a3bSJacopo Mondi  * max9611_mux_conf - associate ADC mux configuration with register address
11669780a3bSJacopo Mondi  *		      where data shall be read from
11769780a3bSJacopo Mondi  */
11869780a3bSJacopo Mondi static const unsigned int max9611_mux_conf[][2] = {
119a33db947SGeert Uytterhoeven 	[CONF_SENSE_1x]	= { MAX9611_MUX_SENSE_1x, MAX9611_REG_CSA_DATA },
120a33db947SGeert Uytterhoeven 	[CONF_SENSE_4x]	= { MAX9611_MUX_SENSE_4x, MAX9611_REG_CSA_DATA },
121a33db947SGeert Uytterhoeven 	[CONF_SENSE_8x]	= { MAX9611_MUX_SENSE_8x, MAX9611_REG_CSA_DATA },
122a33db947SGeert Uytterhoeven 	[CONF_IN_VOLT]	= { MAX9611_INPUT_VOLT, MAX9611_REG_RS_DATA },
123a33db947SGeert Uytterhoeven 	[CONF_TEMP]	= { MAX9611_MUX_TEMP, MAX9611_REG_TEMP_DATA },
12469780a3bSJacopo Mondi };
12569780a3bSJacopo Mondi 
12669780a3bSJacopo Mondi enum max9611_csa_gain {
127a33db947SGeert Uytterhoeven 	CSA_GAIN_1x = CONF_SENSE_1x,
128a33db947SGeert Uytterhoeven 	CSA_GAIN_4x = CONF_SENSE_4x,
129a33db947SGeert Uytterhoeven 	CSA_GAIN_8x = CONF_SENSE_8x,
13069780a3bSJacopo Mondi };
13169780a3bSJacopo Mondi 
13269780a3bSJacopo Mondi enum max9611_csa_gain_params {
13369780a3bSJacopo Mondi 	CSA_GAIN_LSB_nV,
13469780a3bSJacopo Mondi 	CSA_GAIN_OFFS_RAW,
13569780a3bSJacopo Mondi };
13669780a3bSJacopo Mondi 
137922fdc19SLee Jones /*
13869780a3bSJacopo Mondi  * max9611_csa_gain_conf - associate gain multiplier with LSB and
13969780a3bSJacopo Mondi  *			   offset values.
14069780a3bSJacopo Mondi  *
14169780a3bSJacopo Mondi  * Group together parameters associated with configurable gain
14269780a3bSJacopo Mondi  * on current sense amplifier path to ADC interface.
14369780a3bSJacopo Mondi  * Current sense read routine adjusts gain until it gets a meaningful
14469780a3bSJacopo Mondi  * value; use this structure to retrieve the correct LSB and offset values.
14569780a3bSJacopo Mondi  */
14669780a3bSJacopo Mondi static const unsigned int max9611_gain_conf[][2] = {
147a33db947SGeert Uytterhoeven 	[CSA_GAIN_1x] = { MAX9611_CSA_1X_LSB_nV, MAX9611_CSA_1X_OFFS_RAW, },
148a33db947SGeert Uytterhoeven 	[CSA_GAIN_4x] = { MAX9611_CSA_4X_LSB_nV, MAX9611_CSA_4X_OFFS_RAW, },
149a33db947SGeert Uytterhoeven 	[CSA_GAIN_8x] = { MAX9611_CSA_8X_LSB_nV, MAX9611_CSA_8X_OFFS_RAW, },
15069780a3bSJacopo Mondi };
15169780a3bSJacopo Mondi 
15269780a3bSJacopo Mondi enum max9611_chan_addrs {
15369780a3bSJacopo Mondi 	MAX9611_CHAN_VOLTAGE_INPUT,
15469780a3bSJacopo Mondi 	MAX9611_CHAN_VOLTAGE_SENSE,
15569780a3bSJacopo Mondi 	MAX9611_CHAN_TEMPERATURE,
15669780a3bSJacopo Mondi 	MAX9611_CHAN_CURRENT_LOAD,
15769780a3bSJacopo Mondi 	MAX9611_CHAN_POWER_LOAD,
15869780a3bSJacopo Mondi };
15969780a3bSJacopo Mondi 
16069780a3bSJacopo Mondi static const struct iio_chan_spec max9611_channels[] = {
16169780a3bSJacopo Mondi 	{
16269780a3bSJacopo Mondi 	  .type			= IIO_TEMP,
16369780a3bSJacopo Mondi 	  .info_mask_separate	= BIT(IIO_CHAN_INFO_RAW) |
16469780a3bSJacopo Mondi 				  BIT(IIO_CHAN_INFO_SCALE),
16569780a3bSJacopo Mondi 	  .address		= MAX9611_CHAN_TEMPERATURE,
16669780a3bSJacopo Mondi 	},
16769780a3bSJacopo Mondi 	{
16869780a3bSJacopo Mondi 	  .type			= IIO_VOLTAGE,
16969780a3bSJacopo Mondi 	  .info_mask_separate	= BIT(IIO_CHAN_INFO_PROCESSED),
17069780a3bSJacopo Mondi 	  .address		= MAX9611_CHAN_VOLTAGE_SENSE,
17169780a3bSJacopo Mondi 	  .indexed		= 1,
17269780a3bSJacopo Mondi 	  .channel		= 0,
17369780a3bSJacopo Mondi 	},
17469780a3bSJacopo Mondi 	{
17569780a3bSJacopo Mondi 	  .type			= IIO_VOLTAGE,
17669780a3bSJacopo Mondi 	  .info_mask_separate	= BIT(IIO_CHAN_INFO_RAW)   |
17769780a3bSJacopo Mondi 				  BIT(IIO_CHAN_INFO_SCALE) |
17869780a3bSJacopo Mondi 				  BIT(IIO_CHAN_INFO_OFFSET),
17969780a3bSJacopo Mondi 	  .address		= MAX9611_CHAN_VOLTAGE_INPUT,
18069780a3bSJacopo Mondi 	  .indexed		= 1,
18169780a3bSJacopo Mondi 	  .channel		= 1,
18269780a3bSJacopo Mondi 	},
18369780a3bSJacopo Mondi 	{
18469780a3bSJacopo Mondi 	  .type			= IIO_CURRENT,
18569780a3bSJacopo Mondi 	  .info_mask_separate	= BIT(IIO_CHAN_INFO_PROCESSED),
18669780a3bSJacopo Mondi 	  .address		= MAX9611_CHAN_CURRENT_LOAD,
18769780a3bSJacopo Mondi 	},
18869780a3bSJacopo Mondi 	{
18969780a3bSJacopo Mondi 	  .type			= IIO_POWER,
19069780a3bSJacopo Mondi 	  .info_mask_separate	= BIT(IIO_CHAN_INFO_PROCESSED),
19169780a3bSJacopo Mondi 	  .address		= MAX9611_CHAN_POWER_LOAD
19269780a3bSJacopo Mondi 	},
19369780a3bSJacopo Mondi };
19469780a3bSJacopo Mondi 
19569780a3bSJacopo Mondi /**
19669780a3bSJacopo Mondi  * max9611_read_single() - read a single value from ADC interface
19769780a3bSJacopo Mondi  *
19869780a3bSJacopo Mondi  * Data registers are 16 bit long, spread between two 8 bit registers
19969780a3bSJacopo Mondi  * with consecutive addresses.
20069780a3bSJacopo Mondi  * Configure ADC mux first, then read register at address "reg_addr".
20169780a3bSJacopo Mondi  * The smbus_read_word routine asks for 16 bits and the ADC is kind enough
20269780a3bSJacopo Mondi  * to return values from "reg_addr" and "reg_addr + 1" consecutively.
20369780a3bSJacopo Mondi  * Data are transmitted with big-endian ordering: MSB arrives first.
20469780a3bSJacopo Mondi  *
20569780a3bSJacopo Mondi  * @max9611: max9611 device
20669780a3bSJacopo Mondi  * @selector: index for mux and register configuration
20769780a3bSJacopo Mondi  * @raw_val: the value returned from ADC
20869780a3bSJacopo Mondi  */
max9611_read_single(struct max9611_dev * max9611,enum max9611_conf_ids selector,u16 * raw_val)20969780a3bSJacopo Mondi static int max9611_read_single(struct max9611_dev *max9611,
21069780a3bSJacopo Mondi 			       enum max9611_conf_ids selector,
21169780a3bSJacopo Mondi 			       u16 *raw_val)
21269780a3bSJacopo Mondi {
21369780a3bSJacopo Mondi 	int ret;
21469780a3bSJacopo Mondi 
21569780a3bSJacopo Mondi 	u8 mux_conf = max9611_mux_conf[selector][0] & MAX9611_MUX_MASK;
21669780a3bSJacopo Mondi 	u8 reg_addr = max9611_mux_conf[selector][1];
21769780a3bSJacopo Mondi 
21869780a3bSJacopo Mondi 	/*
21969780a3bSJacopo Mondi 	 * Keep mutex lock held during read-write to avoid mux register
22069780a3bSJacopo Mondi 	 * (CTRL1) re-configuration.
22169780a3bSJacopo Mondi 	 */
22269780a3bSJacopo Mondi 	mutex_lock(&max9611->lock);
22369780a3bSJacopo Mondi 	ret = i2c_smbus_write_byte_data(max9611->i2c_client,
22469780a3bSJacopo Mondi 					MAX9611_REG_CTRL1, mux_conf);
22569780a3bSJacopo Mondi 	if (ret) {
22669780a3bSJacopo Mondi 		dev_err(max9611->dev, "i2c write byte failed: 0x%2x - 0x%2x\n",
22769780a3bSJacopo Mondi 			MAX9611_REG_CTRL1, mux_conf);
22869780a3bSJacopo Mondi 		mutex_unlock(&max9611->lock);
22969780a3bSJacopo Mondi 		return ret;
23069780a3bSJacopo Mondi 	}
23169780a3bSJacopo Mondi 
2329fd229c4SGeert Uytterhoeven 	/* need a delay here to make register configuration stabilize. */
2339fd229c4SGeert Uytterhoeven 
2349fd229c4SGeert Uytterhoeven 	usleep_range(MAX9611_CONV_TIME_US_RANGE);
23569780a3bSJacopo Mondi 
23669780a3bSJacopo Mondi 	ret = i2c_smbus_read_word_swapped(max9611->i2c_client, reg_addr);
23769780a3bSJacopo Mondi 	if (ret < 0) {
23869780a3bSJacopo Mondi 		dev_err(max9611->dev, "i2c read word from 0x%2x failed\n",
23969780a3bSJacopo Mondi 			reg_addr);
24069780a3bSJacopo Mondi 		mutex_unlock(&max9611->lock);
24169780a3bSJacopo Mondi 		return ret;
24269780a3bSJacopo Mondi 	}
24369780a3bSJacopo Mondi 
24469780a3bSJacopo Mondi 	*raw_val = ret;
24569780a3bSJacopo Mondi 	mutex_unlock(&max9611->lock);
24669780a3bSJacopo Mondi 
24769780a3bSJacopo Mondi 	return 0;
24869780a3bSJacopo Mondi }
24969780a3bSJacopo Mondi 
25069780a3bSJacopo Mondi /**
25169780a3bSJacopo Mondi  * max9611_read_csa_voltage() - read current sense amplifier output voltage
25269780a3bSJacopo Mondi  *
25369780a3bSJacopo Mondi  * Current sense amplifier output voltage is read through a configurable
25469780a3bSJacopo Mondi  * 1x, 4x or 8x gain.
25569780a3bSJacopo Mondi  * Start with plain 1x gain, and adjust gain control properly until a
25669780a3bSJacopo Mondi  * meaningful value is read from ADC output.
25769780a3bSJacopo Mondi  *
25869780a3bSJacopo Mondi  * @max9611: max9611 device
25969780a3bSJacopo Mondi  * @adc_raw: raw value read from ADC output
26069780a3bSJacopo Mondi  * @csa_gain: gain configuration option selector
26169780a3bSJacopo Mondi  */
max9611_read_csa_voltage(struct max9611_dev * max9611,u16 * adc_raw,enum max9611_csa_gain * csa_gain)26269780a3bSJacopo Mondi static int max9611_read_csa_voltage(struct max9611_dev *max9611,
26369780a3bSJacopo Mondi 				    u16 *adc_raw,
26469780a3bSJacopo Mondi 				    enum max9611_csa_gain *csa_gain)
26569780a3bSJacopo Mondi {
26669780a3bSJacopo Mondi 	enum max9611_conf_ids gain_selectors[] = {
26769780a3bSJacopo Mondi 		CONF_SENSE_1x,
26869780a3bSJacopo Mondi 		CONF_SENSE_4x,
26969780a3bSJacopo Mondi 		CONF_SENSE_8x
27069780a3bSJacopo Mondi 	};
27169780a3bSJacopo Mondi 	unsigned int i;
27269780a3bSJacopo Mondi 	int ret;
27369780a3bSJacopo Mondi 
27469780a3bSJacopo Mondi 	for (i = 0; i < ARRAY_SIZE(gain_selectors); ++i) {
27569780a3bSJacopo Mondi 		ret = max9611_read_single(max9611, gain_selectors[i], adc_raw);
27669780a3bSJacopo Mondi 		if (ret)
27769780a3bSJacopo Mondi 			return ret;
27869780a3bSJacopo Mondi 
27969780a3bSJacopo Mondi 		if (*adc_raw > 0) {
280b1ec0802SStefan Agner 			*csa_gain = (enum max9611_csa_gain)gain_selectors[i];
28169780a3bSJacopo Mondi 			return 0;
28269780a3bSJacopo Mondi 		}
28369780a3bSJacopo Mondi 	}
28469780a3bSJacopo Mondi 
28569780a3bSJacopo Mondi 	return -EIO;
28669780a3bSJacopo Mondi }
28769780a3bSJacopo Mondi 
max9611_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)28869780a3bSJacopo Mondi static int max9611_read_raw(struct iio_dev *indio_dev,
28969780a3bSJacopo Mondi 			    struct iio_chan_spec const *chan,
29069780a3bSJacopo Mondi 			    int *val, int *val2, long mask)
29169780a3bSJacopo Mondi {
29269780a3bSJacopo Mondi 	struct max9611_dev *dev = iio_priv(indio_dev);
29369780a3bSJacopo Mondi 	enum max9611_csa_gain gain_selector;
29469780a3bSJacopo Mondi 	const unsigned int *csa_gain;
29569780a3bSJacopo Mondi 	u16 adc_data;
29669780a3bSJacopo Mondi 	int ret;
29769780a3bSJacopo Mondi 
29869780a3bSJacopo Mondi 	switch (mask) {
29969780a3bSJacopo Mondi 	case IIO_CHAN_INFO_RAW:
30069780a3bSJacopo Mondi 
30169780a3bSJacopo Mondi 		switch (chan->address) {
30269780a3bSJacopo Mondi 		case MAX9611_CHAN_TEMPERATURE:
30369780a3bSJacopo Mondi 			ret = max9611_read_single(dev, CONF_TEMP,
30469780a3bSJacopo Mondi 						  &adc_data);
30569780a3bSJacopo Mondi 			if (ret)
30669780a3bSJacopo Mondi 				return -EINVAL;
30769780a3bSJacopo Mondi 
30869780a3bSJacopo Mondi 			*val = MAX9611_TEMP_RAW(adc_data);
30969780a3bSJacopo Mondi 			return IIO_VAL_INT;
31069780a3bSJacopo Mondi 
31169780a3bSJacopo Mondi 		case MAX9611_CHAN_VOLTAGE_INPUT:
31269780a3bSJacopo Mondi 			ret = max9611_read_single(dev, CONF_IN_VOLT,
31369780a3bSJacopo Mondi 						  &adc_data);
31469780a3bSJacopo Mondi 			if (ret)
31569780a3bSJacopo Mondi 				return -EINVAL;
31669780a3bSJacopo Mondi 
31769780a3bSJacopo Mondi 			*val = MAX9611_VOLTAGE_RAW(adc_data);
31869780a3bSJacopo Mondi 			return IIO_VAL_INT;
31969780a3bSJacopo Mondi 		}
32069780a3bSJacopo Mondi 
32169780a3bSJacopo Mondi 		break;
32269780a3bSJacopo Mondi 
32369780a3bSJacopo Mondi 	case IIO_CHAN_INFO_OFFSET:
32469780a3bSJacopo Mondi 		/* MAX9611_CHAN_VOLTAGE_INPUT */
32569780a3bSJacopo Mondi 		*val = MAX9611_CIM_OFFSET_RAW;
32669780a3bSJacopo Mondi 
32769780a3bSJacopo Mondi 		return IIO_VAL_INT;
32869780a3bSJacopo Mondi 
32969780a3bSJacopo Mondi 	case IIO_CHAN_INFO_SCALE:
33069780a3bSJacopo Mondi 
33169780a3bSJacopo Mondi 		switch (chan->address) {
33269780a3bSJacopo Mondi 		case MAX9611_CHAN_TEMPERATURE:
33369780a3bSJacopo Mondi 			*val = MAX9611_TEMP_SCALE_NUM;
33469780a3bSJacopo Mondi 			*val2 = MAX9611_TEMP_SCALE_DIV;
33569780a3bSJacopo Mondi 
33669780a3bSJacopo Mondi 			return IIO_VAL_FRACTIONAL;
33769780a3bSJacopo Mondi 
33869780a3bSJacopo Mondi 		case MAX9611_CHAN_VOLTAGE_INPUT:
33969780a3bSJacopo Mondi 			*val = MAX9611_CIM_LSB_mV;
34069780a3bSJacopo Mondi 
34169780a3bSJacopo Mondi 			return IIO_VAL_INT;
34269780a3bSJacopo Mondi 		}
34369780a3bSJacopo Mondi 
34469780a3bSJacopo Mondi 		break;
34569780a3bSJacopo Mondi 
34669780a3bSJacopo Mondi 	case IIO_CHAN_INFO_PROCESSED:
34769780a3bSJacopo Mondi 
34869780a3bSJacopo Mondi 		switch (chan->address) {
34969780a3bSJacopo Mondi 		case MAX9611_CHAN_VOLTAGE_SENSE:
35069780a3bSJacopo Mondi 			/*
35169780a3bSJacopo Mondi 			 * processed (mV): (raw - offset) * LSB (nV) / 10^6
35269780a3bSJacopo Mondi 			 *
35369780a3bSJacopo Mondi 			 * Even if max9611 can output raw csa voltage readings,
35469780a3bSJacopo Mondi 			 * use a produced value as scale depends on gain.
35569780a3bSJacopo Mondi 			 */
35669780a3bSJacopo Mondi 			ret = max9611_read_csa_voltage(dev, &adc_data,
35769780a3bSJacopo Mondi 						       &gain_selector);
35869780a3bSJacopo Mondi 			if (ret)
35969780a3bSJacopo Mondi 				return -EINVAL;
36069780a3bSJacopo Mondi 
36169780a3bSJacopo Mondi 			csa_gain = max9611_gain_conf[gain_selector];
36269780a3bSJacopo Mondi 
36369780a3bSJacopo Mondi 			adc_data -= csa_gain[CSA_GAIN_OFFS_RAW];
36469780a3bSJacopo Mondi 			*val = MAX9611_VOLTAGE_RAW(adc_data) *
36569780a3bSJacopo Mondi 			       csa_gain[CSA_GAIN_LSB_nV];
36669780a3bSJacopo Mondi 			*val2 = 1000000;
36769780a3bSJacopo Mondi 
36869780a3bSJacopo Mondi 			return IIO_VAL_FRACTIONAL;
36969780a3bSJacopo Mondi 
37069780a3bSJacopo Mondi 		case MAX9611_CHAN_CURRENT_LOAD:
37169780a3bSJacopo Mondi 			/* processed (mA): Vcsa (nV) / Rshunt (uOhm)  */
37269780a3bSJacopo Mondi 			ret = max9611_read_csa_voltage(dev, &adc_data,
37369780a3bSJacopo Mondi 						       &gain_selector);
37469780a3bSJacopo Mondi 			if (ret)
37569780a3bSJacopo Mondi 				return -EINVAL;
37669780a3bSJacopo Mondi 
37769780a3bSJacopo Mondi 			csa_gain = max9611_gain_conf[gain_selector];
37869780a3bSJacopo Mondi 
37969780a3bSJacopo Mondi 			adc_data -= csa_gain[CSA_GAIN_OFFS_RAW];
38069780a3bSJacopo Mondi 			*val = MAX9611_VOLTAGE_RAW(adc_data) *
38169780a3bSJacopo Mondi 			       csa_gain[CSA_GAIN_LSB_nV];
38269780a3bSJacopo Mondi 			*val2 = dev->shunt_resistor_uohm;
38369780a3bSJacopo Mondi 
38469780a3bSJacopo Mondi 			return IIO_VAL_FRACTIONAL;
38569780a3bSJacopo Mondi 
38669780a3bSJacopo Mondi 		case MAX9611_CHAN_POWER_LOAD:
38769780a3bSJacopo Mondi 			/*
38869780a3bSJacopo Mondi 			 * processed (mW): Vin (mV) * Vcsa (uV) /
38969780a3bSJacopo Mondi 			 *		   Rshunt (uOhm)
39069780a3bSJacopo Mondi 			 */
39169780a3bSJacopo Mondi 			ret = max9611_read_single(dev, CONF_IN_VOLT,
39269780a3bSJacopo Mondi 						  &adc_data);
39369780a3bSJacopo Mondi 			if (ret)
39469780a3bSJacopo Mondi 				return -EINVAL;
39569780a3bSJacopo Mondi 
39669780a3bSJacopo Mondi 			adc_data -= MAX9611_CIM_OFFSET_RAW;
39769780a3bSJacopo Mondi 			*val = MAX9611_VOLTAGE_RAW(adc_data) *
39869780a3bSJacopo Mondi 			       MAX9611_CIM_LSB_mV;
39969780a3bSJacopo Mondi 
40069780a3bSJacopo Mondi 			ret = max9611_read_csa_voltage(dev, &adc_data,
40169780a3bSJacopo Mondi 						       &gain_selector);
40269780a3bSJacopo Mondi 			if (ret)
40369780a3bSJacopo Mondi 				return -EINVAL;
40469780a3bSJacopo Mondi 
40569780a3bSJacopo Mondi 			csa_gain = max9611_gain_conf[gain_selector];
40669780a3bSJacopo Mondi 
40769780a3bSJacopo Mondi 			/* divide by 10^3 here to avoid 32bit overflow */
40869780a3bSJacopo Mondi 			adc_data -= csa_gain[CSA_GAIN_OFFS_RAW];
40969780a3bSJacopo Mondi 			*val *= MAX9611_VOLTAGE_RAW(adc_data) *
41069780a3bSJacopo Mondi 				csa_gain[CSA_GAIN_LSB_nV] / 1000;
41169780a3bSJacopo Mondi 			*val2 = dev->shunt_resistor_uohm;
41269780a3bSJacopo Mondi 
41369780a3bSJacopo Mondi 			return IIO_VAL_FRACTIONAL;
41469780a3bSJacopo Mondi 		}
41569780a3bSJacopo Mondi 
41669780a3bSJacopo Mondi 		break;
41769780a3bSJacopo Mondi 	}
41869780a3bSJacopo Mondi 
41969780a3bSJacopo Mondi 	return -EINVAL;
42069780a3bSJacopo Mondi }
42169780a3bSJacopo Mondi 
max9611_shunt_resistor_show(struct device * dev,struct device_attribute * attr,char * buf)42269780a3bSJacopo Mondi static ssize_t max9611_shunt_resistor_show(struct device *dev,
42369780a3bSJacopo Mondi 					   struct device_attribute *attr,
42469780a3bSJacopo Mondi 					   char *buf)
42569780a3bSJacopo Mondi {
42669780a3bSJacopo Mondi 	struct max9611_dev *max9611 = iio_priv(dev_to_iio_dev(dev));
42769780a3bSJacopo Mondi 	unsigned int i, r;
42869780a3bSJacopo Mondi 
429c5451719SJacopo Mondi 	i = max9611->shunt_resistor_uohm / 1000000;
430c5451719SJacopo Mondi 	r = max9611->shunt_resistor_uohm % 1000000;
43169780a3bSJacopo Mondi 
432d42b626dSLars-Peter Clausen 	return sysfs_emit(buf, "%u.%06u\n", i, r);
43369780a3bSJacopo Mondi }
43469780a3bSJacopo Mondi 
43569780a3bSJacopo Mondi static IIO_DEVICE_ATTR(in_power_shunt_resistor, 0444,
43669780a3bSJacopo Mondi 		       max9611_shunt_resistor_show, NULL, 0);
43769780a3bSJacopo Mondi static IIO_DEVICE_ATTR(in_current_shunt_resistor, 0444,
43869780a3bSJacopo Mondi 		       max9611_shunt_resistor_show, NULL, 0);
43969780a3bSJacopo Mondi 
44069780a3bSJacopo Mondi static struct attribute *max9611_attributes[] = {
44169780a3bSJacopo Mondi 	&iio_dev_attr_in_power_shunt_resistor.dev_attr.attr,
44269780a3bSJacopo Mondi 	&iio_dev_attr_in_current_shunt_resistor.dev_attr.attr,
44369780a3bSJacopo Mondi 	NULL,
44469780a3bSJacopo Mondi };
44569780a3bSJacopo Mondi 
44669780a3bSJacopo Mondi static const struct attribute_group max9611_attribute_group = {
44769780a3bSJacopo Mondi 	.attrs = max9611_attributes,
44869780a3bSJacopo Mondi };
44969780a3bSJacopo Mondi 
45069780a3bSJacopo Mondi static const struct iio_info indio_info = {
45169780a3bSJacopo Mondi 	.read_raw	= max9611_read_raw,
45269780a3bSJacopo Mondi 	.attrs		= &max9611_attribute_group,
45369780a3bSJacopo Mondi };
45469780a3bSJacopo Mondi 
max9611_init(struct max9611_dev * max9611)45569780a3bSJacopo Mondi static int max9611_init(struct max9611_dev *max9611)
45669780a3bSJacopo Mondi {
45769780a3bSJacopo Mondi 	struct i2c_client *client = max9611->i2c_client;
45869780a3bSJacopo Mondi 	u16 regval;
45969780a3bSJacopo Mondi 	int ret;
46069780a3bSJacopo Mondi 
46169780a3bSJacopo Mondi 	if (!i2c_check_functionality(client->adapter,
46269780a3bSJacopo Mondi 				     I2C_FUNC_SMBUS_WRITE_BYTE	|
46369780a3bSJacopo Mondi 				     I2C_FUNC_SMBUS_READ_WORD_DATA)) {
46469780a3bSJacopo Mondi 		dev_err(max9611->dev,
46569780a3bSJacopo Mondi 			"I2c adapter does not support smbus write_byte or read_word functionalities: aborting probe.\n");
46669780a3bSJacopo Mondi 		return -EINVAL;
46769780a3bSJacopo Mondi 	}
46869780a3bSJacopo Mondi 
46969780a3bSJacopo Mondi 	/* Make sure die temperature is in range to test communications. */
47069780a3bSJacopo Mondi 	ret = max9611_read_single(max9611, CONF_TEMP, &regval);
47169780a3bSJacopo Mondi 	if (ret)
47269780a3bSJacopo Mondi 		return ret;
47369780a3bSJacopo Mondi 
474b9ddd509SJacopo Mondi 	regval &= MAX9611_TEMP_MASK;
47569780a3bSJacopo Mondi 
47669780a3bSJacopo Mondi 	if ((regval > MAX9611_TEMP_MAX_POS &&
47769780a3bSJacopo Mondi 	     regval < MAX9611_TEMP_MIN_NEG) ||
47869780a3bSJacopo Mondi 	     regval > MAX9611_TEMP_MAX_NEG) {
47969780a3bSJacopo Mondi 		dev_err(max9611->dev,
48069780a3bSJacopo Mondi 			"Invalid value received from ADC 0x%4x: aborting\n",
48169780a3bSJacopo Mondi 			regval);
48269780a3bSJacopo Mondi 		return -EIO;
48369780a3bSJacopo Mondi 	}
48469780a3bSJacopo Mondi 
48569780a3bSJacopo Mondi 	/* Mux shall be zeroed back before applying other configurations */
48669780a3bSJacopo Mondi 	ret = i2c_smbus_write_byte_data(max9611->i2c_client,
48769780a3bSJacopo Mondi 					MAX9611_REG_CTRL1, 0);
48869780a3bSJacopo Mondi 	if (ret) {
48969780a3bSJacopo Mondi 		dev_err(max9611->dev, "i2c write byte failed: 0x%2x - 0x%2x\n",
49069780a3bSJacopo Mondi 			MAX9611_REG_CTRL1, 0);
49169780a3bSJacopo Mondi 		return ret;
49269780a3bSJacopo Mondi 	}
49369780a3bSJacopo Mondi 
49469780a3bSJacopo Mondi 	ret = i2c_smbus_write_byte_data(max9611->i2c_client,
49569780a3bSJacopo Mondi 					MAX9611_REG_CTRL2, 0);
49669780a3bSJacopo Mondi 	if (ret) {
49769780a3bSJacopo Mondi 		dev_err(max9611->dev, "i2c write byte failed: 0x%2x - 0x%2x\n",
49869780a3bSJacopo Mondi 			MAX9611_REG_CTRL2, 0);
49969780a3bSJacopo Mondi 		return ret;
50069780a3bSJacopo Mondi 	}
5019fd229c4SGeert Uytterhoeven 	usleep_range(MAX9611_CONV_TIME_US_RANGE);
50269780a3bSJacopo Mondi 
50369780a3bSJacopo Mondi 	return 0;
50469780a3bSJacopo Mondi }
50569780a3bSJacopo Mondi 
50669780a3bSJacopo Mondi static const struct of_device_id max9611_of_table[] = {
50769780a3bSJacopo Mondi 	{.compatible = "maxim,max9611", .data = "max9611"},
50869780a3bSJacopo Mondi 	{.compatible = "maxim,max9612", .data = "max9612"},
50969780a3bSJacopo Mondi 	{ },
51069780a3bSJacopo Mondi };
51169780a3bSJacopo Mondi 
51269780a3bSJacopo Mondi MODULE_DEVICE_TABLE(of, max9611_of_table);
max9611_probe(struct i2c_client * client)513d59ecbc4SUwe Kleine-König static int max9611_probe(struct i2c_client *client)
51469780a3bSJacopo Mondi {
51569780a3bSJacopo Mondi 	const char * const shunt_res_prop = "shunt-resistor-micro-ohms";
51669780a3bSJacopo Mondi 	struct max9611_dev *max9611;
51769780a3bSJacopo Mondi 	struct iio_dev *indio_dev;
518c88eba5aSJonathan Cameron 	struct device *dev = &client->dev;
51969780a3bSJacopo Mondi 	unsigned int of_shunt;
52069780a3bSJacopo Mondi 	int ret;
52169780a3bSJacopo Mondi 
52269780a3bSJacopo Mondi 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*max9611));
52335fa70dfSDan Carpenter 	if (!indio_dev)
52435fa70dfSDan Carpenter 		return -ENOMEM;
52569780a3bSJacopo Mondi 
52669780a3bSJacopo Mondi 	i2c_set_clientdata(client, indio_dev);
52769780a3bSJacopo Mondi 
52869780a3bSJacopo Mondi 	max9611			= iio_priv(indio_dev);
529c88eba5aSJonathan Cameron 	max9611->dev		= dev;
53069780a3bSJacopo Mondi 	max9611->i2c_client	= client;
53169780a3bSJacopo Mondi 	mutex_init(&max9611->lock);
53269780a3bSJacopo Mondi 
533c88eba5aSJonathan Cameron 	ret = device_property_read_u32(dev, shunt_res_prop, &of_shunt);
53469780a3bSJacopo Mondi 	if (ret) {
535c88eba5aSJonathan Cameron 		dev_err(dev, "Missing %s property for %pfw node\n",
536c88eba5aSJonathan Cameron 			shunt_res_prop, dev_fwnode(dev));
53769780a3bSJacopo Mondi 		return ret;
53869780a3bSJacopo Mondi 	}
53969780a3bSJacopo Mondi 	max9611->shunt_resistor_uohm = of_shunt;
54069780a3bSJacopo Mondi 
54169780a3bSJacopo Mondi 	ret = max9611_init(max9611);
54269780a3bSJacopo Mondi 	if (ret)
54369780a3bSJacopo Mondi 		return ret;
54469780a3bSJacopo Mondi 
545c88eba5aSJonathan Cameron 	indio_dev->name		= device_get_match_data(dev);
54669780a3bSJacopo Mondi 	indio_dev->modes	= INDIO_DIRECT_MODE;
54769780a3bSJacopo Mondi 	indio_dev->info		= &indio_info;
54869780a3bSJacopo Mondi 	indio_dev->channels	= max9611_channels;
54969780a3bSJacopo Mondi 	indio_dev->num_channels	= ARRAY_SIZE(max9611_channels);
55069780a3bSJacopo Mondi 
551c88eba5aSJonathan Cameron 	return devm_iio_device_register(dev, indio_dev);
55269780a3bSJacopo Mondi }
55369780a3bSJacopo Mondi 
55469780a3bSJacopo Mondi static struct i2c_driver max9611_driver = {
55569780a3bSJacopo Mondi 	.driver = {
55669780a3bSJacopo Mondi 		   .name = DRIVER_NAME,
55769780a3bSJacopo Mondi 		   .of_match_table = max9611_of_table,
55869780a3bSJacopo Mondi 	},
559*7cf15f42SUwe Kleine-König 	.probe = max9611_probe,
56069780a3bSJacopo Mondi };
56169780a3bSJacopo Mondi module_i2c_driver(max9611_driver);
56269780a3bSJacopo Mondi 
56369780a3bSJacopo Mondi MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org>");
56469780a3bSJacopo Mondi MODULE_DESCRIPTION("Maxim max9611/12 current sense amplifier with 12bit ADC");
56569780a3bSJacopo Mondi MODULE_LICENSE("GPL v2");
566