1*f52690c5SJanani Sunil // SPDX-License-Identifier: GPL-2.0 2*f52690c5SJanani Sunil /* 3*f52690c5SJanani Sunil * max22007.c - MAX22007 DAC driver 4*f52690c5SJanani Sunil * 5*f52690c5SJanani Sunil * Driver for Analog Devices MAX22007 Digital to Analog Converter. 6*f52690c5SJanani Sunil * 7*f52690c5SJanani Sunil * Copyright (c) 2026 Analog Devices Inc. 8*f52690c5SJanani Sunil */ 9*f52690c5SJanani Sunil 10*f52690c5SJanani Sunil #include <linux/bitfield.h> 11*f52690c5SJanani Sunil #include <linux/bits.h> 12*f52690c5SJanani Sunil #include <linux/crc8.h> 13*f52690c5SJanani Sunil #include <linux/delay.h> 14*f52690c5SJanani Sunil #include <linux/dev_printk.h> 15*f52690c5SJanani Sunil #include <linux/device/devres.h> 16*f52690c5SJanani Sunil #include <linux/err.h> 17*f52690c5SJanani Sunil #include <linux/errno.h> 18*f52690c5SJanani Sunil #include <linux/gpio/consumer.h> 19*f52690c5SJanani Sunil #include <linux/iio/iio.h> 20*f52690c5SJanani Sunil #include <linux/kstrtox.h> 21*f52690c5SJanani Sunil #include <linux/minmax.h> 22*f52690c5SJanani Sunil #include <linux/mod_devicetable.h> 23*f52690c5SJanani Sunil #include <linux/module.h> 24*f52690c5SJanani Sunil #include <linux/property.h> 25*f52690c5SJanani Sunil #include <linux/regmap.h> 26*f52690c5SJanani Sunil #include <linux/regulator/consumer.h> 27*f52690c5SJanani Sunil #include <linux/slab.h> 28*f52690c5SJanani Sunil #include <linux/spi/spi.h> 29*f52690c5SJanani Sunil #include <linux/string.h> 30*f52690c5SJanani Sunil #include <linux/sysfs.h> 31*f52690c5SJanani Sunil #include <linux/types.h> 32*f52690c5SJanani Sunil 33*f52690c5SJanani Sunil #include <dt-bindings/iio/addac/adi,ad74413r.h> 34*f52690c5SJanani Sunil struct device; 35*f52690c5SJanani Sunil 36*f52690c5SJanani Sunil #define MAX22007_NUM_CHANNELS 4 37*f52690c5SJanani Sunil #define MAX22007_REV_ID_REG 0x00 38*f52690c5SJanani Sunil #define MAX22007_STAT_INTR_REG 0x01 39*f52690c5SJanani Sunil #define MAX22007_INTERRUPT_EN_REG 0x02 40*f52690c5SJanani Sunil #define MAX22007_CONFIG_REG 0x03 41*f52690c5SJanani Sunil #define MAX22007_CONTROL_REG 0x04 42*f52690c5SJanani Sunil #define MAX22007_CHANNEL_MODE_REG 0x05 43*f52690c5SJanani Sunil #define MAX22007_SOFT_RESET_REG 0x06 44*f52690c5SJanani Sunil #define MAX22007_DAC_CHANNEL_REG(ch) (0x07 + (ch)) 45*f52690c5SJanani Sunil #define MAX22007_GPIO_CTRL_REG 0x0B 46*f52690c5SJanani Sunil #define MAX22007_GPIO_DATA_REG 0x0C 47*f52690c5SJanani Sunil #define MAX22007_GPI_EDGE_INT_CTRL_REG 0x0D 48*f52690c5SJanani Sunil #define MAX22007_GPI_INT_STATUS_REG 0x0E 49*f52690c5SJanani Sunil 50*f52690c5SJanani Sunil /* Channel mask definitions */ 51*f52690c5SJanani Sunil #define MAX22007_CH_MODE_CH_MASK(ch) BIT(12 + (ch)) 52*f52690c5SJanani Sunil #define MAX22007_CH_PWRON_CH_MASK(ch) BIT(8 + (ch)) 53*f52690c5SJanani Sunil #define MAX22007_DAC_LATCH_MODE_MASK(ch) BIT(12 + (ch)) 54*f52690c5SJanani Sunil #define MAX22007_LDAC_UPDATE_MASK(ch) BIT(12 + (ch)) 55*f52690c5SJanani Sunil #define MAX22007_SW_RST_MASK BIT(8) 56*f52690c5SJanani Sunil #define MAX22007_SW_CLR_MASK BIT(12) 57*f52690c5SJanani Sunil #define MAX22007_SOFT_RESET_BITS_MASK (MAX22007_SW_RST_MASK | \ 58*f52690c5SJanani Sunil MAX22007_SW_CLR_MASK) 59*f52690c5SJanani Sunil #define MAX22007_DAC_DATA_MASK GENMASK(15, 4) 60*f52690c5SJanani Sunil #define MAX22007_DAC_MAX_RAW GENMASK(11, 0) 61*f52690c5SJanani Sunil #define MAX22007_CRC8_POLYNOMIAL 0x8C 62*f52690c5SJanani Sunil #define MAX22007_CRC_EN_MASK BIT(0) 63*f52690c5SJanani Sunil #define MAX22007_RW_MASK BIT(0) 64*f52690c5SJanani Sunil #define MAX22007_CRC_OVERHEAD 1 65*f52690c5SJanani Sunil #define MAX22007_NUM_SUPPLIES 3 66*f52690c5SJanani Sunil #define MAX22007_REF_MV 2500 67*f52690c5SJanani Sunil 68*f52690c5SJanani Sunil /* Field value preparation macros with masking */ 69*f52690c5SJanani Sunil #define MAX22007_CH_PWR_VAL(ch, val) (((val) & 0x1) << (8 + (ch))) 70*f52690c5SJanani Sunil #define MAX22007_CH_MODE_VAL(ch, val) (((val) & 0x1) << (12 + (ch))) 71*f52690c5SJanani Sunil #define MAX22007_DAC_LATCH_MODE_VAL(ch, val) (((val) & 0x1) << (12 + (ch))) 72*f52690c5SJanani Sunil 73*f52690c5SJanani Sunil static u8 max22007_crc8_table[CRC8_TABLE_SIZE]; 74*f52690c5SJanani Sunil 75*f52690c5SJanani Sunil static const char * const max22007_supply_names[MAX22007_NUM_SUPPLIES] = { 76*f52690c5SJanani Sunil "vdd", 77*f52690c5SJanani Sunil "hvdd", 78*f52690c5SJanani Sunil "hvss", 79*f52690c5SJanani Sunil }; 80*f52690c5SJanani Sunil 81*f52690c5SJanani Sunil struct max22007_state { 82*f52690c5SJanani Sunil struct spi_device *spi; 83*f52690c5SJanani Sunil struct regmap *regmap; 84*f52690c5SJanani Sunil struct iio_chan_spec *iio_chans; 85*f52690c5SJanani Sunil u8 tx_buf[4] __aligned(IIO_DMA_MINALIGN); 86*f52690c5SJanani Sunil u8 rx_buf[4]; 87*f52690c5SJanani Sunil }; 88*f52690c5SJanani Sunil 89*f52690c5SJanani Sunil static int max22007_spi_read(void *context, const void *reg, size_t reg_size, 90*f52690c5SJanani Sunil void *val, size_t val_size) 91*f52690c5SJanani Sunil { 92*f52690c5SJanani Sunil struct max22007_state *st = context; 93*f52690c5SJanani Sunil u8 calculated_crc, received_crc; 94*f52690c5SJanani Sunil u8 rx_buf[4]; 95*f52690c5SJanani Sunil u8 reg_byte; 96*f52690c5SJanani Sunil int ret; 97*f52690c5SJanani Sunil 98*f52690c5SJanani Sunil if (reg_size != 1) 99*f52690c5SJanani Sunil return -EINVAL; 100*f52690c5SJanani Sunil 101*f52690c5SJanani Sunil if (val_size == 0 || val_size > 3) 102*f52690c5SJanani Sunil return -EINVAL; 103*f52690c5SJanani Sunil 104*f52690c5SJanani Sunil memcpy(®_byte, reg, 1); 105*f52690c5SJanani Sunil 106*f52690c5SJanani Sunil ret = spi_write_then_read(st->spi, ®_byte, 1, rx_buf, 107*f52690c5SJanani Sunil val_size + MAX22007_CRC_OVERHEAD); 108*f52690c5SJanani Sunil if (ret) { 109*f52690c5SJanani Sunil dev_err(&st->spi->dev, "SPI transfer failed: %d\n", ret); 110*f52690c5SJanani Sunil return ret; 111*f52690c5SJanani Sunil } 112*f52690c5SJanani Sunil 113*f52690c5SJanani Sunil calculated_crc = crc8(max22007_crc8_table, ®_byte, 1, 0x00); 114*f52690c5SJanani Sunil calculated_crc = crc8(max22007_crc8_table, rx_buf, 2, calculated_crc); 115*f52690c5SJanani Sunil received_crc = rx_buf[val_size]; 116*f52690c5SJanani Sunil 117*f52690c5SJanani Sunil if (calculated_crc != received_crc) { 118*f52690c5SJanani Sunil dev_err(&st->spi->dev, "CRC mismatch on read register %02x\n", reg_byte); 119*f52690c5SJanani Sunil return -EIO; 120*f52690c5SJanani Sunil } 121*f52690c5SJanani Sunil 122*f52690c5SJanani Sunil memcpy(val, rx_buf, val_size); 123*f52690c5SJanani Sunil 124*f52690c5SJanani Sunil return 0; 125*f52690c5SJanani Sunil } 126*f52690c5SJanani Sunil 127*f52690c5SJanani Sunil static int max22007_spi_write(void *context, const void *data, size_t count) 128*f52690c5SJanani Sunil { 129*f52690c5SJanani Sunil struct max22007_state *st = context; 130*f52690c5SJanani Sunil struct spi_transfer xfer = { 131*f52690c5SJanani Sunil .tx_buf = st->tx_buf, 132*f52690c5SJanani Sunil .rx_buf = st->rx_buf, 133*f52690c5SJanani Sunil }; 134*f52690c5SJanani Sunil 135*f52690c5SJanani Sunil if (count + MAX22007_CRC_OVERHEAD > sizeof(st->tx_buf)) 136*f52690c5SJanani Sunil return -EINVAL; 137*f52690c5SJanani Sunil 138*f52690c5SJanani Sunil memset(st->tx_buf, 0, sizeof(st->tx_buf)); 139*f52690c5SJanani Sunil 140*f52690c5SJanani Sunil xfer.len = count + MAX22007_CRC_OVERHEAD; 141*f52690c5SJanani Sunil 142*f52690c5SJanani Sunil memcpy(st->tx_buf, data, count); 143*f52690c5SJanani Sunil st->tx_buf[count] = crc8(max22007_crc8_table, st->tx_buf, 144*f52690c5SJanani Sunil sizeof(st->tx_buf) - 1, 0x00); 145*f52690c5SJanani Sunil 146*f52690c5SJanani Sunil return spi_sync_transfer(st->spi, &xfer, 1); 147*f52690c5SJanani Sunil } 148*f52690c5SJanani Sunil 149*f52690c5SJanani Sunil static bool max22007_reg_readable(struct device *dev, unsigned int reg) 150*f52690c5SJanani Sunil { 151*f52690c5SJanani Sunil switch (reg) { 152*f52690c5SJanani Sunil case MAX22007_REV_ID_REG: 153*f52690c5SJanani Sunil case MAX22007_STAT_INTR_REG: 154*f52690c5SJanani Sunil case MAX22007_CONFIG_REG: 155*f52690c5SJanani Sunil case MAX22007_CONTROL_REG: 156*f52690c5SJanani Sunil case MAX22007_CHANNEL_MODE_REG: 157*f52690c5SJanani Sunil case MAX22007_SOFT_RESET_REG: 158*f52690c5SJanani Sunil case MAX22007_GPIO_CTRL_REG: 159*f52690c5SJanani Sunil case MAX22007_GPIO_DATA_REG: 160*f52690c5SJanani Sunil case MAX22007_GPI_EDGE_INT_CTRL_REG: 161*f52690c5SJanani Sunil case MAX22007_GPI_INT_STATUS_REG: 162*f52690c5SJanani Sunil return true; 163*f52690c5SJanani Sunil case MAX22007_DAC_CHANNEL_REG(0) ... MAX22007_DAC_CHANNEL_REG(MAX22007_NUM_CHANNELS - 1): 164*f52690c5SJanani Sunil return true; 165*f52690c5SJanani Sunil default: 166*f52690c5SJanani Sunil return false; 167*f52690c5SJanani Sunil } 168*f52690c5SJanani Sunil } 169*f52690c5SJanani Sunil 170*f52690c5SJanani Sunil static bool max22007_reg_writable(struct device *dev, unsigned int reg) 171*f52690c5SJanani Sunil { 172*f52690c5SJanani Sunil switch (reg) { 173*f52690c5SJanani Sunil case MAX22007_CONFIG_REG: 174*f52690c5SJanani Sunil case MAX22007_CONTROL_REG: 175*f52690c5SJanani Sunil case MAX22007_CHANNEL_MODE_REG: 176*f52690c5SJanani Sunil case MAX22007_SOFT_RESET_REG: 177*f52690c5SJanani Sunil case MAX22007_GPIO_CTRL_REG: 178*f52690c5SJanani Sunil case MAX22007_GPIO_DATA_REG: 179*f52690c5SJanani Sunil case MAX22007_GPI_EDGE_INT_CTRL_REG: 180*f52690c5SJanani Sunil return true; 181*f52690c5SJanani Sunil case MAX22007_DAC_CHANNEL_REG(0) ... MAX22007_DAC_CHANNEL_REG(MAX22007_NUM_CHANNELS - 1): 182*f52690c5SJanani Sunil return true; 183*f52690c5SJanani Sunil default: 184*f52690c5SJanani Sunil return false; 185*f52690c5SJanani Sunil } 186*f52690c5SJanani Sunil } 187*f52690c5SJanani Sunil 188*f52690c5SJanani Sunil static const struct regmap_bus max22007_regmap_bus = { 189*f52690c5SJanani Sunil .read = max22007_spi_read, 190*f52690c5SJanani Sunil .write = max22007_spi_write, 191*f52690c5SJanani Sunil .read_flag_mask = MAX22007_RW_MASK, 192*f52690c5SJanani Sunil .reg_format_endian_default = REGMAP_ENDIAN_BIG, 193*f52690c5SJanani Sunil .val_format_endian_default = REGMAP_ENDIAN_BIG, 194*f52690c5SJanani Sunil }; 195*f52690c5SJanani Sunil 196*f52690c5SJanani Sunil static const struct regmap_config max22007_regmap_config = { 197*f52690c5SJanani Sunil .reg_bits = 8, 198*f52690c5SJanani Sunil .val_bits = 16, 199*f52690c5SJanani Sunil .reg_shift = -1, 200*f52690c5SJanani Sunil .readable_reg = max22007_reg_readable, 201*f52690c5SJanani Sunil .writeable_reg = max22007_reg_writable, 202*f52690c5SJanani Sunil .max_register = 0x0E, 203*f52690c5SJanani Sunil }; 204*f52690c5SJanani Sunil 205*f52690c5SJanani Sunil static int max22007_write_channel_data(struct max22007_state *st, 206*f52690c5SJanani Sunil unsigned int channel, int data) 207*f52690c5SJanani Sunil { 208*f52690c5SJanani Sunil unsigned int reg_val; 209*f52690c5SJanani Sunil 210*f52690c5SJanani Sunil if (data < 0 || data > MAX22007_DAC_MAX_RAW) 211*f52690c5SJanani Sunil return -EINVAL; 212*f52690c5SJanani Sunil 213*f52690c5SJanani Sunil reg_val = FIELD_PREP(MAX22007_DAC_DATA_MASK, data); 214*f52690c5SJanani Sunil 215*f52690c5SJanani Sunil return regmap_write(st->regmap, MAX22007_DAC_CHANNEL_REG(channel), reg_val); 216*f52690c5SJanani Sunil } 217*f52690c5SJanani Sunil 218*f52690c5SJanani Sunil static int max22007_read_channel_data(struct max22007_state *st, 219*f52690c5SJanani Sunil unsigned int channel, int *data) 220*f52690c5SJanani Sunil { 221*f52690c5SJanani Sunil unsigned int reg_val; 222*f52690c5SJanani Sunil int ret; 223*f52690c5SJanani Sunil 224*f52690c5SJanani Sunil ret = regmap_read(st->regmap, MAX22007_DAC_CHANNEL_REG(channel), ®_val); 225*f52690c5SJanani Sunil if (ret) 226*f52690c5SJanani Sunil return ret; 227*f52690c5SJanani Sunil 228*f52690c5SJanani Sunil *data = FIELD_GET(MAX22007_DAC_DATA_MASK, reg_val); 229*f52690c5SJanani Sunil 230*f52690c5SJanani Sunil return 0; 231*f52690c5SJanani Sunil } 232*f52690c5SJanani Sunil 233*f52690c5SJanani Sunil static int max22007_read_raw(struct iio_dev *indio_dev, 234*f52690c5SJanani Sunil struct iio_chan_spec const *chan, 235*f52690c5SJanani Sunil int *val, int *val2, long mask) 236*f52690c5SJanani Sunil { 237*f52690c5SJanani Sunil struct max22007_state *st = iio_priv(indio_dev); 238*f52690c5SJanani Sunil int ret; 239*f52690c5SJanani Sunil 240*f52690c5SJanani Sunil switch (mask) { 241*f52690c5SJanani Sunil case IIO_CHAN_INFO_RAW: 242*f52690c5SJanani Sunil ret = max22007_read_channel_data(st, chan->channel, val); 243*f52690c5SJanani Sunil if (ret) 244*f52690c5SJanani Sunil return ret; 245*f52690c5SJanani Sunil return IIO_VAL_INT; 246*f52690c5SJanani Sunil case IIO_CHAN_INFO_SCALE: 247*f52690c5SJanani Sunil if (chan->type == IIO_VOLTAGE) 248*f52690c5SJanani Sunil *val = 5 * MAX22007_REF_MV; /* 5 * Vref in mV */ 249*f52690c5SJanani Sunil else 250*f52690c5SJanani Sunil *val = 25; /* Vref / (2 * Rsense) = MAX22007_REF_MV / 100 */ 251*f52690c5SJanani Sunil *val2 = 12; /* 12-bit DAC resolution */ 252*f52690c5SJanani Sunil return IIO_VAL_FRACTIONAL_LOG2; 253*f52690c5SJanani Sunil default: 254*f52690c5SJanani Sunil return -EINVAL; 255*f52690c5SJanani Sunil } 256*f52690c5SJanani Sunil } 257*f52690c5SJanani Sunil 258*f52690c5SJanani Sunil static int max22007_write_raw(struct iio_dev *indio_dev, 259*f52690c5SJanani Sunil struct iio_chan_spec const *chan, 260*f52690c5SJanani Sunil int val, int val2, long mask) 261*f52690c5SJanani Sunil { 262*f52690c5SJanani Sunil struct max22007_state *st = iio_priv(indio_dev); 263*f52690c5SJanani Sunil 264*f52690c5SJanani Sunil switch (mask) { 265*f52690c5SJanani Sunil case IIO_CHAN_INFO_RAW: 266*f52690c5SJanani Sunil return max22007_write_channel_data(st, chan->channel, val); 267*f52690c5SJanani Sunil default: 268*f52690c5SJanani Sunil return -EINVAL; 269*f52690c5SJanani Sunil } 270*f52690c5SJanani Sunil } 271*f52690c5SJanani Sunil 272*f52690c5SJanani Sunil static const struct iio_info max22007_info = { 273*f52690c5SJanani Sunil .read_raw = max22007_read_raw, 274*f52690c5SJanani Sunil .write_raw = max22007_write_raw, 275*f52690c5SJanani Sunil }; 276*f52690c5SJanani Sunil 277*f52690c5SJanani Sunil static ssize_t max22007_read_dac_powerdown(struct iio_dev *indio_dev, 278*f52690c5SJanani Sunil uintptr_t private, 279*f52690c5SJanani Sunil const struct iio_chan_spec *chan, 280*f52690c5SJanani Sunil char *buf) 281*f52690c5SJanani Sunil { 282*f52690c5SJanani Sunil struct max22007_state *st = iio_priv(indio_dev); 283*f52690c5SJanani Sunil unsigned int reg_val; 284*f52690c5SJanani Sunil bool powerdown; 285*f52690c5SJanani Sunil int ret; 286*f52690c5SJanani Sunil 287*f52690c5SJanani Sunil ret = regmap_read(st->regmap, MAX22007_CHANNEL_MODE_REG, ®_val); 288*f52690c5SJanani Sunil if (ret) 289*f52690c5SJanani Sunil return ret; 290*f52690c5SJanani Sunil 291*f52690c5SJanani Sunil powerdown = !(reg_val & MAX22007_CH_PWRON_CH_MASK(chan->channel)); 292*f52690c5SJanani Sunil 293*f52690c5SJanani Sunil return sysfs_emit(buf, "%d\n", powerdown); 294*f52690c5SJanani Sunil } 295*f52690c5SJanani Sunil 296*f52690c5SJanani Sunil static ssize_t max22007_write_dac_powerdown(struct iio_dev *indio_dev, 297*f52690c5SJanani Sunil uintptr_t private, 298*f52690c5SJanani Sunil const struct iio_chan_spec *chan, 299*f52690c5SJanani Sunil const char *buf, size_t len) 300*f52690c5SJanani Sunil { 301*f52690c5SJanani Sunil struct max22007_state *st = iio_priv(indio_dev); 302*f52690c5SJanani Sunil bool powerdown; 303*f52690c5SJanani Sunil int ret; 304*f52690c5SJanani Sunil 305*f52690c5SJanani Sunil ret = kstrtobool(buf, &powerdown); 306*f52690c5SJanani Sunil if (ret) 307*f52690c5SJanani Sunil return ret; 308*f52690c5SJanani Sunil 309*f52690c5SJanani Sunil ret = regmap_update_bits(st->regmap, MAX22007_CHANNEL_MODE_REG, 310*f52690c5SJanani Sunil MAX22007_CH_PWRON_CH_MASK(chan->channel), 311*f52690c5SJanani Sunil MAX22007_CH_PWR_VAL(chan->channel, powerdown ? 0 : 1)); 312*f52690c5SJanani Sunil if (ret) 313*f52690c5SJanani Sunil return ret; 314*f52690c5SJanani Sunil 315*f52690c5SJanani Sunil return len; 316*f52690c5SJanani Sunil } 317*f52690c5SJanani Sunil 318*f52690c5SJanani Sunil static const struct iio_chan_spec_ext_info max22007_ext_info[] = { 319*f52690c5SJanani Sunil { 320*f52690c5SJanani Sunil .name = "powerdown", 321*f52690c5SJanani Sunil .read = max22007_read_dac_powerdown, 322*f52690c5SJanani Sunil .write = max22007_write_dac_powerdown, 323*f52690c5SJanani Sunil .shared = IIO_SEPARATE, 324*f52690c5SJanani Sunil }, 325*f52690c5SJanani Sunil { } 326*f52690c5SJanani Sunil }; 327*f52690c5SJanani Sunil 328*f52690c5SJanani Sunil static int max22007_parse_channel_cfg(struct max22007_state *st, u8 *num_channels) 329*f52690c5SJanani Sunil { 330*f52690c5SJanani Sunil struct device *dev = &st->spi->dev; 331*f52690c5SJanani Sunil int ret, num_chan; 332*f52690c5SJanani Sunil int i = 0; 333*f52690c5SJanani Sunil u32 reg; 334*f52690c5SJanani Sunil 335*f52690c5SJanani Sunil num_chan = device_get_child_node_count(dev); 336*f52690c5SJanani Sunil if (!num_chan) 337*f52690c5SJanani Sunil return dev_err_probe(dev, -ENODEV, "no channels configured\n"); 338*f52690c5SJanani Sunil 339*f52690c5SJanani Sunil st->iio_chans = devm_kcalloc(dev, num_chan, sizeof(*st->iio_chans), GFP_KERNEL); 340*f52690c5SJanani Sunil if (!st->iio_chans) 341*f52690c5SJanani Sunil return -ENOMEM; 342*f52690c5SJanani Sunil 343*f52690c5SJanani Sunil device_for_each_child_node_scoped(dev, child) { 344*f52690c5SJanani Sunil u32 ch_func; 345*f52690c5SJanani Sunil enum iio_chan_type chan_type; 346*f52690c5SJanani Sunil 347*f52690c5SJanani Sunil ret = fwnode_property_read_u32(child, "reg", ®); 348*f52690c5SJanani Sunil if (ret) 349*f52690c5SJanani Sunil return dev_err_probe(dev, ret, 350*f52690c5SJanani Sunil "failed to read reg property of %pfwP\n", child); 351*f52690c5SJanani Sunil 352*f52690c5SJanani Sunil if (reg >= MAX22007_NUM_CHANNELS) 353*f52690c5SJanani Sunil return dev_err_probe(dev, -EINVAL, 354*f52690c5SJanani Sunil "reg out of range in %pfwP\n", child); 355*f52690c5SJanani Sunil 356*f52690c5SJanani Sunil ret = fwnode_property_read_u32(child, "adi,ch-func", &ch_func); 357*f52690c5SJanani Sunil if (ret) 358*f52690c5SJanani Sunil return dev_err_probe(dev, ret, 359*f52690c5SJanani Sunil "missing adi,ch-func property for %pfwP\n", child); 360*f52690c5SJanani Sunil 361*f52690c5SJanani Sunil switch (ch_func) { 362*f52690c5SJanani Sunil case CH_FUNC_VOLTAGE_OUTPUT: 363*f52690c5SJanani Sunil chan_type = IIO_VOLTAGE; 364*f52690c5SJanani Sunil break; 365*f52690c5SJanani Sunil case CH_FUNC_CURRENT_OUTPUT: 366*f52690c5SJanani Sunil chan_type = IIO_CURRENT; 367*f52690c5SJanani Sunil break; 368*f52690c5SJanani Sunil default: 369*f52690c5SJanani Sunil return dev_err_probe(dev, -EINVAL, 370*f52690c5SJanani Sunil "invalid adi,ch-func %u for %pfwP\n", 371*f52690c5SJanani Sunil ch_func, child); 372*f52690c5SJanani Sunil } 373*f52690c5SJanani Sunil 374*f52690c5SJanani Sunil st->iio_chans[i++] = (struct iio_chan_spec) { 375*f52690c5SJanani Sunil .output = 1, 376*f52690c5SJanani Sunil .indexed = 1, 377*f52690c5SJanani Sunil .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 378*f52690c5SJanani Sunil BIT(IIO_CHAN_INFO_SCALE), 379*f52690c5SJanani Sunil .ext_info = max22007_ext_info, 380*f52690c5SJanani Sunil .channel = reg, 381*f52690c5SJanani Sunil .type = chan_type, 382*f52690c5SJanani Sunil }; 383*f52690c5SJanani Sunil 384*f52690c5SJanani Sunil ret = regmap_update_bits(st->regmap, MAX22007_CHANNEL_MODE_REG, 385*f52690c5SJanani Sunil MAX22007_CH_MODE_CH_MASK(reg), 386*f52690c5SJanani Sunil MAX22007_CH_MODE_VAL(reg, ch_func - 1)); 387*f52690c5SJanani Sunil if (ret) 388*f52690c5SJanani Sunil return ret; 389*f52690c5SJanani Sunil 390*f52690c5SJanani Sunil /* Set DAC to transparent mode (immediate update) */ 391*f52690c5SJanani Sunil ret = regmap_update_bits(st->regmap, MAX22007_CONFIG_REG, 392*f52690c5SJanani Sunil MAX22007_DAC_LATCH_MODE_MASK(reg), 393*f52690c5SJanani Sunil MAX22007_DAC_LATCH_MODE_VAL(reg, 1)); 394*f52690c5SJanani Sunil if (ret) 395*f52690c5SJanani Sunil return ret; 396*f52690c5SJanani Sunil } 397*f52690c5SJanani Sunil 398*f52690c5SJanani Sunil *num_channels = num_chan; 399*f52690c5SJanani Sunil 400*f52690c5SJanani Sunil return 0; 401*f52690c5SJanani Sunil } 402*f52690c5SJanani Sunil 403*f52690c5SJanani Sunil static int max22007_probe(struct spi_device *spi) 404*f52690c5SJanani Sunil { 405*f52690c5SJanani Sunil struct device *dev = &spi->dev; 406*f52690c5SJanani Sunil struct gpio_desc *reset_gpio; 407*f52690c5SJanani Sunil struct max22007_state *st; 408*f52690c5SJanani Sunil struct iio_dev *indio_dev; 409*f52690c5SJanani Sunil u8 num_channels; 410*f52690c5SJanani Sunil int ret; 411*f52690c5SJanani Sunil 412*f52690c5SJanani Sunil indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); 413*f52690c5SJanani Sunil if (!indio_dev) 414*f52690c5SJanani Sunil return -ENOMEM; 415*f52690c5SJanani Sunil 416*f52690c5SJanani Sunil st = iio_priv(indio_dev); 417*f52690c5SJanani Sunil st->spi = spi; 418*f52690c5SJanani Sunil 419*f52690c5SJanani Sunil crc8_populate_lsb(max22007_crc8_table, MAX22007_CRC8_POLYNOMIAL); 420*f52690c5SJanani Sunil 421*f52690c5SJanani Sunil st->regmap = devm_regmap_init(dev, &max22007_regmap_bus, st, 422*f52690c5SJanani Sunil &max22007_regmap_config); 423*f52690c5SJanani Sunil if (IS_ERR(st->regmap)) 424*f52690c5SJanani Sunil return dev_err_probe(dev, PTR_ERR(st->regmap), 425*f52690c5SJanani Sunil "Failed to initialize regmap\n"); 426*f52690c5SJanani Sunil 427*f52690c5SJanani Sunil ret = devm_regulator_bulk_get_enable(dev, MAX22007_NUM_SUPPLIES, 428*f52690c5SJanani Sunil max22007_supply_names); 429*f52690c5SJanani Sunil if (ret) 430*f52690c5SJanani Sunil return dev_err_probe(dev, ret, "Failed to get and enable regulators\n"); 431*f52690c5SJanani Sunil 432*f52690c5SJanani Sunil reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 433*f52690c5SJanani Sunil if (IS_ERR(reset_gpio)) 434*f52690c5SJanani Sunil return dev_err_probe(dev, PTR_ERR(reset_gpio), 435*f52690c5SJanani Sunil "Failed to get reset GPIO\n"); 436*f52690c5SJanani Sunil 437*f52690c5SJanani Sunil if (reset_gpio) { 438*f52690c5SJanani Sunil gpiod_set_value_cansleep(reset_gpio, 1); 439*f52690c5SJanani Sunil usleep_range(1000, 5000); 440*f52690c5SJanani Sunil gpiod_set_value_cansleep(reset_gpio, 0); 441*f52690c5SJanani Sunil usleep_range(1000, 5000); 442*f52690c5SJanani Sunil } else { 443*f52690c5SJanani Sunil ret = regmap_write(st->regmap, MAX22007_SOFT_RESET_REG, 444*f52690c5SJanani Sunil MAX22007_SOFT_RESET_BITS_MASK); 445*f52690c5SJanani Sunil if (ret) 446*f52690c5SJanani Sunil return ret; 447*f52690c5SJanani Sunil } 448*f52690c5SJanani Sunil 449*f52690c5SJanani Sunil ret = regmap_set_bits(st->regmap, MAX22007_CONFIG_REG, 450*f52690c5SJanani Sunil MAX22007_CRC_EN_MASK); 451*f52690c5SJanani Sunil if (ret) 452*f52690c5SJanani Sunil return ret; 453*f52690c5SJanani Sunil 454*f52690c5SJanani Sunil ret = max22007_parse_channel_cfg(st, &num_channels); 455*f52690c5SJanani Sunil if (ret) 456*f52690c5SJanani Sunil return ret; 457*f52690c5SJanani Sunil 458*f52690c5SJanani Sunil indio_dev->info = &max22007_info; 459*f52690c5SJanani Sunil indio_dev->modes = INDIO_DIRECT_MODE; 460*f52690c5SJanani Sunil indio_dev->channels = st->iio_chans; 461*f52690c5SJanani Sunil indio_dev->num_channels = num_channels; 462*f52690c5SJanani Sunil indio_dev->name = "max22007"; 463*f52690c5SJanani Sunil 464*f52690c5SJanani Sunil return devm_iio_device_register(dev, indio_dev); 465*f52690c5SJanani Sunil } 466*f52690c5SJanani Sunil 467*f52690c5SJanani Sunil static const struct spi_device_id max22007_id[] = { 468*f52690c5SJanani Sunil { "max22007" }, 469*f52690c5SJanani Sunil { } 470*f52690c5SJanani Sunil }; 471*f52690c5SJanani Sunil MODULE_DEVICE_TABLE(spi, max22007_id); 472*f52690c5SJanani Sunil 473*f52690c5SJanani Sunil static const struct of_device_id max22007_of_match[] = { 474*f52690c5SJanani Sunil { .compatible = "adi,max22007" }, 475*f52690c5SJanani Sunil { } 476*f52690c5SJanani Sunil }; 477*f52690c5SJanani Sunil MODULE_DEVICE_TABLE(of, max22007_of_match); 478*f52690c5SJanani Sunil 479*f52690c5SJanani Sunil static struct spi_driver max22007_driver = { 480*f52690c5SJanani Sunil .driver = { 481*f52690c5SJanani Sunil .name = "max22007", 482*f52690c5SJanani Sunil .of_match_table = max22007_of_match, 483*f52690c5SJanani Sunil }, 484*f52690c5SJanani Sunil .probe = max22007_probe, 485*f52690c5SJanani Sunil .id_table = max22007_id, 486*f52690c5SJanani Sunil }; 487*f52690c5SJanani Sunil module_spi_driver(max22007_driver); 488*f52690c5SJanani Sunil 489*f52690c5SJanani Sunil MODULE_AUTHOR("Janani Sunil <janani.sunil@analog.com>"); 490*f52690c5SJanani Sunil MODULE_DESCRIPTION("Analog Devices MAX22007 DAC"); 491*f52690c5SJanani Sunil MODULE_LICENSE("GPL"); 492