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, ®val);
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