1fda8d26eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 202b829f9SMaxime Roussin-Belanger /* 302b829f9SMaxime Roussin-Belanger * LTC2632 Digital to analog convertors spi driver 402b829f9SMaxime Roussin-Belanger * 53723c632SArnd Bergmann * Copyright 2017 Maxime Roussin-Bélanger 69ff1d500SSilvan Murer * expanded by Silvan Murer <silvan.murer@gmail.com> 702b829f9SMaxime Roussin-Belanger */ 802b829f9SMaxime Roussin-Belanger 902b829f9SMaxime Roussin-Belanger #include <linux/device.h> 1002b829f9SMaxime Roussin-Belanger #include <linux/spi/spi.h> 1102b829f9SMaxime Roussin-Belanger #include <linux/module.h> 1202b829f9SMaxime Roussin-Belanger #include <linux/iio/iio.h> 139ff1d500SSilvan Murer #include <linux/regulator/consumer.h> 1402b829f9SMaxime Roussin-Belanger 1502b829f9SMaxime Roussin-Belanger #define LTC2632_ADDR_DAC0 0x0 1602b829f9SMaxime Roussin-Belanger #define LTC2632_ADDR_DAC1 0x1 1702b829f9SMaxime Roussin-Belanger 1802b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_WRITE_INPUT_N 0x0 1902b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_UPDATE_DAC_N 0x1 2002b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 2102b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_WRITE_INPUT_N_UPDATE_N 0x3 2202b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_POWERDOWN_DAC_N 0x4 2302b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_POWERDOWN_CHIP 0x5 2402b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_INTERNAL_REFER 0x6 2502b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_EXTERNAL_REFER 0x7 2602b829f9SMaxime Roussin-Belanger 2702b829f9SMaxime Roussin-Belanger /** 2802b829f9SMaxime Roussin-Belanger * struct ltc2632_chip_info - chip specific information 2902b829f9SMaxime Roussin-Belanger * @channels: channel spec for the DAC 309ff1d500SSilvan Murer * @vref_mv: internal reference voltage 3102b829f9SMaxime Roussin-Belanger */ 3202b829f9SMaxime Roussin-Belanger struct ltc2632_chip_info { 3302b829f9SMaxime Roussin-Belanger const struct iio_chan_spec *channels; 34*9f15a4a0SUwe Kleine-König const size_t num_channels; 3502b829f9SMaxime Roussin-Belanger const int vref_mv; 3602b829f9SMaxime Roussin-Belanger }; 3702b829f9SMaxime Roussin-Belanger 3802b829f9SMaxime Roussin-Belanger /** 3902b829f9SMaxime Roussin-Belanger * struct ltc2632_state - driver instance specific data 4002b829f9SMaxime Roussin-Belanger * @spi_dev: pointer to the spi_device struct 4102b829f9SMaxime Roussin-Belanger * @powerdown_cache_mask used to show current channel powerdown state 429ff1d500SSilvan Murer * @vref_mv used reference voltage (internal or external) 439ff1d500SSilvan Murer * @vref_reg regulator for the reference voltage 4402b829f9SMaxime Roussin-Belanger */ 4502b829f9SMaxime Roussin-Belanger struct ltc2632_state { 4602b829f9SMaxime Roussin-Belanger struct spi_device *spi_dev; 4702b829f9SMaxime Roussin-Belanger unsigned int powerdown_cache_mask; 489ff1d500SSilvan Murer int vref_mv; 499ff1d500SSilvan Murer struct regulator *vref_reg; 5002b829f9SMaxime Roussin-Belanger }; 5102b829f9SMaxime Roussin-Belanger 5202b829f9SMaxime Roussin-Belanger enum ltc2632_supported_device_ids { 5302b829f9SMaxime Roussin-Belanger ID_LTC2632L12, 5402b829f9SMaxime Roussin-Belanger ID_LTC2632L10, 5502b829f9SMaxime Roussin-Belanger ID_LTC2632L8, 5602b829f9SMaxime Roussin-Belanger ID_LTC2632H12, 5702b829f9SMaxime Roussin-Belanger ID_LTC2632H10, 5802b829f9SMaxime Roussin-Belanger ID_LTC2632H8, 59*9f15a4a0SUwe Kleine-König ID_LTC2636L12, 60*9f15a4a0SUwe Kleine-König ID_LTC2636L10, 61*9f15a4a0SUwe Kleine-König ID_LTC2636L8, 62*9f15a4a0SUwe Kleine-König ID_LTC2636H12, 63*9f15a4a0SUwe Kleine-König ID_LTC2636H10, 64*9f15a4a0SUwe Kleine-König ID_LTC2636H8, 6502b829f9SMaxime Roussin-Belanger }; 6602b829f9SMaxime Roussin-Belanger 6702b829f9SMaxime Roussin-Belanger static int ltc2632_spi_write(struct spi_device *spi, 6802b829f9SMaxime Roussin-Belanger u8 cmd, u8 addr, u16 val, u8 shift) 6902b829f9SMaxime Roussin-Belanger { 7002b829f9SMaxime Roussin-Belanger u32 data; 7102b829f9SMaxime Roussin-Belanger u8 msg[3]; 7202b829f9SMaxime Roussin-Belanger 7302b829f9SMaxime Roussin-Belanger /* 7402b829f9SMaxime Roussin-Belanger * The input shift register is 24 bits wide. 7502b829f9SMaxime Roussin-Belanger * The next four are the command bits, C3 to C0, 7602b829f9SMaxime Roussin-Belanger * followed by the 4-bit DAC address, A3 to A0, and then the 7702b829f9SMaxime Roussin-Belanger * 12-, 10-, 8-bit data-word. The data-word comprises the 12-, 7802b829f9SMaxime Roussin-Belanger * 10-, 8-bit input code followed by 4, 6, or 8 don't care bits. 7902b829f9SMaxime Roussin-Belanger */ 8002b829f9SMaxime Roussin-Belanger data = (cmd << 20) | (addr << 16) | (val << shift); 8102b829f9SMaxime Roussin-Belanger msg[0] = data >> 16; 8202b829f9SMaxime Roussin-Belanger msg[1] = data >> 8; 8302b829f9SMaxime Roussin-Belanger msg[2] = data; 8402b829f9SMaxime Roussin-Belanger 8502b829f9SMaxime Roussin-Belanger return spi_write(spi, msg, sizeof(msg)); 8602b829f9SMaxime Roussin-Belanger } 8702b829f9SMaxime Roussin-Belanger 8802b829f9SMaxime Roussin-Belanger static int ltc2632_read_raw(struct iio_dev *indio_dev, 8902b829f9SMaxime Roussin-Belanger struct iio_chan_spec const *chan, 9002b829f9SMaxime Roussin-Belanger int *val, 9102b829f9SMaxime Roussin-Belanger int *val2, 9202b829f9SMaxime Roussin-Belanger long m) 9302b829f9SMaxime Roussin-Belanger { 9402b829f9SMaxime Roussin-Belanger const struct ltc2632_state *st = iio_priv(indio_dev); 9502b829f9SMaxime Roussin-Belanger 9602b829f9SMaxime Roussin-Belanger switch (m) { 9702b829f9SMaxime Roussin-Belanger case IIO_CHAN_INFO_SCALE: 989ff1d500SSilvan Murer *val = st->vref_mv; 9902b829f9SMaxime Roussin-Belanger *val2 = chan->scan_type.realbits; 10002b829f9SMaxime Roussin-Belanger return IIO_VAL_FRACTIONAL_LOG2; 10102b829f9SMaxime Roussin-Belanger } 10202b829f9SMaxime Roussin-Belanger return -EINVAL; 10302b829f9SMaxime Roussin-Belanger } 10402b829f9SMaxime Roussin-Belanger 10502b829f9SMaxime Roussin-Belanger static int ltc2632_write_raw(struct iio_dev *indio_dev, 10602b829f9SMaxime Roussin-Belanger struct iio_chan_spec const *chan, 10702b829f9SMaxime Roussin-Belanger int val, 10802b829f9SMaxime Roussin-Belanger int val2, 10902b829f9SMaxime Roussin-Belanger long mask) 11002b829f9SMaxime Roussin-Belanger { 11102b829f9SMaxime Roussin-Belanger struct ltc2632_state *st = iio_priv(indio_dev); 11202b829f9SMaxime Roussin-Belanger 11302b829f9SMaxime Roussin-Belanger switch (mask) { 11402b829f9SMaxime Roussin-Belanger case IIO_CHAN_INFO_RAW: 11502b829f9SMaxime Roussin-Belanger if (val >= (1 << chan->scan_type.realbits) || val < 0) 11602b829f9SMaxime Roussin-Belanger return -EINVAL; 11702b829f9SMaxime Roussin-Belanger 11802b829f9SMaxime Roussin-Belanger return ltc2632_spi_write(st->spi_dev, 11902b829f9SMaxime Roussin-Belanger LTC2632_CMD_WRITE_INPUT_N_UPDATE_N, 12002b829f9SMaxime Roussin-Belanger chan->address, val, 12102b829f9SMaxime Roussin-Belanger chan->scan_type.shift); 12202b829f9SMaxime Roussin-Belanger default: 12302b829f9SMaxime Roussin-Belanger return -EINVAL; 12402b829f9SMaxime Roussin-Belanger } 12502b829f9SMaxime Roussin-Belanger } 12602b829f9SMaxime Roussin-Belanger 12702b829f9SMaxime Roussin-Belanger static ssize_t ltc2632_read_dac_powerdown(struct iio_dev *indio_dev, 12802b829f9SMaxime Roussin-Belanger uintptr_t private, 12902b829f9SMaxime Roussin-Belanger const struct iio_chan_spec *chan, 13002b829f9SMaxime Roussin-Belanger char *buf) 13102b829f9SMaxime Roussin-Belanger { 13202b829f9SMaxime Roussin-Belanger struct ltc2632_state *st = iio_priv(indio_dev); 13302b829f9SMaxime Roussin-Belanger 13402b829f9SMaxime Roussin-Belanger return sprintf(buf, "%d\n", 13502b829f9SMaxime Roussin-Belanger !!(st->powerdown_cache_mask & (1 << chan->channel))); 13602b829f9SMaxime Roussin-Belanger } 13702b829f9SMaxime Roussin-Belanger 13802b829f9SMaxime Roussin-Belanger static ssize_t ltc2632_write_dac_powerdown(struct iio_dev *indio_dev, 13902b829f9SMaxime Roussin-Belanger uintptr_t private, 14002b829f9SMaxime Roussin-Belanger const struct iio_chan_spec *chan, 14102b829f9SMaxime Roussin-Belanger const char *buf, 14202b829f9SMaxime Roussin-Belanger size_t len) 14302b829f9SMaxime Roussin-Belanger { 14402b829f9SMaxime Roussin-Belanger bool pwr_down; 14502b829f9SMaxime Roussin-Belanger int ret; 14602b829f9SMaxime Roussin-Belanger struct ltc2632_state *st = iio_priv(indio_dev); 14702b829f9SMaxime Roussin-Belanger 14802b829f9SMaxime Roussin-Belanger ret = strtobool(buf, &pwr_down); 14902b829f9SMaxime Roussin-Belanger if (ret) 15002b829f9SMaxime Roussin-Belanger return ret; 15102b829f9SMaxime Roussin-Belanger 15202b829f9SMaxime Roussin-Belanger if (pwr_down) 15302b829f9SMaxime Roussin-Belanger st->powerdown_cache_mask |= (1 << chan->channel); 15402b829f9SMaxime Roussin-Belanger else 15502b829f9SMaxime Roussin-Belanger st->powerdown_cache_mask &= ~(1 << chan->channel); 15602b829f9SMaxime Roussin-Belanger 15702b829f9SMaxime Roussin-Belanger ret = ltc2632_spi_write(st->spi_dev, 15802b829f9SMaxime Roussin-Belanger LTC2632_CMD_POWERDOWN_DAC_N, 15902b829f9SMaxime Roussin-Belanger chan->channel, 0, 0); 16002b829f9SMaxime Roussin-Belanger 16102b829f9SMaxime Roussin-Belanger return ret ? ret : len; 16202b829f9SMaxime Roussin-Belanger } 16302b829f9SMaxime Roussin-Belanger 16402b829f9SMaxime Roussin-Belanger static const struct iio_info ltc2632_info = { 16502b829f9SMaxime Roussin-Belanger .write_raw = ltc2632_write_raw, 16602b829f9SMaxime Roussin-Belanger .read_raw = ltc2632_read_raw, 16702b829f9SMaxime Roussin-Belanger }; 16802b829f9SMaxime Roussin-Belanger 16902b829f9SMaxime Roussin-Belanger static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = { 17002b829f9SMaxime Roussin-Belanger { 17102b829f9SMaxime Roussin-Belanger .name = "powerdown", 17202b829f9SMaxime Roussin-Belanger .read = ltc2632_read_dac_powerdown, 17302b829f9SMaxime Roussin-Belanger .write = ltc2632_write_dac_powerdown, 17402b829f9SMaxime Roussin-Belanger .shared = IIO_SEPARATE, 17502b829f9SMaxime Roussin-Belanger }, 17602b829f9SMaxime Roussin-Belanger { }, 17702b829f9SMaxime Roussin-Belanger }; 17802b829f9SMaxime Roussin-Belanger 17902b829f9SMaxime Roussin-Belanger #define LTC2632_CHANNEL(_chan, _bits) { \ 18002b829f9SMaxime Roussin-Belanger .type = IIO_VOLTAGE, \ 18102b829f9SMaxime Roussin-Belanger .indexed = 1, \ 18202b829f9SMaxime Roussin-Belanger .output = 1, \ 18302b829f9SMaxime Roussin-Belanger .channel = (_chan), \ 18402b829f9SMaxime Roussin-Belanger .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 18502b829f9SMaxime Roussin-Belanger .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 18602b829f9SMaxime Roussin-Belanger .address = (_chan), \ 18702b829f9SMaxime Roussin-Belanger .scan_type = { \ 18802b829f9SMaxime Roussin-Belanger .realbits = (_bits), \ 18902b829f9SMaxime Roussin-Belanger .shift = 16 - (_bits), \ 19002b829f9SMaxime Roussin-Belanger }, \ 19102b829f9SMaxime Roussin-Belanger .ext_info = ltc2632_ext_info, \ 19202b829f9SMaxime Roussin-Belanger } 19302b829f9SMaxime Roussin-Belanger 19402b829f9SMaxime Roussin-Belanger #define DECLARE_LTC2632_CHANNELS(_name, _bits) \ 19502b829f9SMaxime Roussin-Belanger const struct iio_chan_spec _name ## _channels[] = { \ 19602b829f9SMaxime Roussin-Belanger LTC2632_CHANNEL(0, _bits), \ 19702b829f9SMaxime Roussin-Belanger LTC2632_CHANNEL(1, _bits), \ 198*9f15a4a0SUwe Kleine-König LTC2632_CHANNEL(2, _bits), \ 199*9f15a4a0SUwe Kleine-König LTC2632_CHANNEL(3, _bits), \ 200*9f15a4a0SUwe Kleine-König LTC2632_CHANNEL(4, _bits), \ 201*9f15a4a0SUwe Kleine-König LTC2632_CHANNEL(5, _bits), \ 202*9f15a4a0SUwe Kleine-König LTC2632_CHANNEL(6, _bits), \ 203*9f15a4a0SUwe Kleine-König LTC2632_CHANNEL(7, _bits), \ 20402b829f9SMaxime Roussin-Belanger } 20502b829f9SMaxime Roussin-Belanger 206f243d0f0SUwe Kleine-König static DECLARE_LTC2632_CHANNELS(ltc2632x12, 12); 207f243d0f0SUwe Kleine-König static DECLARE_LTC2632_CHANNELS(ltc2632x10, 10); 208f243d0f0SUwe Kleine-König static DECLARE_LTC2632_CHANNELS(ltc2632x8, 8); 20902b829f9SMaxime Roussin-Belanger 21002b829f9SMaxime Roussin-Belanger static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = { 21102b829f9SMaxime Roussin-Belanger [ID_LTC2632L12] = { 212f243d0f0SUwe Kleine-König .channels = ltc2632x12_channels, 213*9f15a4a0SUwe Kleine-König .num_channels = 2, 21402b829f9SMaxime Roussin-Belanger .vref_mv = 2500, 21502b829f9SMaxime Roussin-Belanger }, 21602b829f9SMaxime Roussin-Belanger [ID_LTC2632L10] = { 217f243d0f0SUwe Kleine-König .channels = ltc2632x10_channels, 218*9f15a4a0SUwe Kleine-König .num_channels = 2, 21902b829f9SMaxime Roussin-Belanger .vref_mv = 2500, 22002b829f9SMaxime Roussin-Belanger }, 22102b829f9SMaxime Roussin-Belanger [ID_LTC2632L8] = { 222f243d0f0SUwe Kleine-König .channels = ltc2632x8_channels, 223*9f15a4a0SUwe Kleine-König .num_channels = 2, 22402b829f9SMaxime Roussin-Belanger .vref_mv = 2500, 22502b829f9SMaxime Roussin-Belanger }, 22602b829f9SMaxime Roussin-Belanger [ID_LTC2632H12] = { 227f243d0f0SUwe Kleine-König .channels = ltc2632x12_channels, 228*9f15a4a0SUwe Kleine-König .num_channels = 2, 22902b829f9SMaxime Roussin-Belanger .vref_mv = 4096, 23002b829f9SMaxime Roussin-Belanger }, 23102b829f9SMaxime Roussin-Belanger [ID_LTC2632H10] = { 232f243d0f0SUwe Kleine-König .channels = ltc2632x10_channels, 233*9f15a4a0SUwe Kleine-König .num_channels = 2, 23402b829f9SMaxime Roussin-Belanger .vref_mv = 4096, 23502b829f9SMaxime Roussin-Belanger }, 23602b829f9SMaxime Roussin-Belanger [ID_LTC2632H8] = { 237f243d0f0SUwe Kleine-König .channels = ltc2632x8_channels, 238*9f15a4a0SUwe Kleine-König .num_channels = 2, 239*9f15a4a0SUwe Kleine-König .vref_mv = 4096, 240*9f15a4a0SUwe Kleine-König }, 241*9f15a4a0SUwe Kleine-König [ID_LTC2636L12] = { 242*9f15a4a0SUwe Kleine-König .channels = ltc2632x12_channels, 243*9f15a4a0SUwe Kleine-König .num_channels = 8, 244*9f15a4a0SUwe Kleine-König .vref_mv = 2500, 245*9f15a4a0SUwe Kleine-König }, 246*9f15a4a0SUwe Kleine-König [ID_LTC2636L10] = { 247*9f15a4a0SUwe Kleine-König .channels = ltc2632x10_channels, 248*9f15a4a0SUwe Kleine-König .num_channels = 8, 249*9f15a4a0SUwe Kleine-König .vref_mv = 2500, 250*9f15a4a0SUwe Kleine-König }, 251*9f15a4a0SUwe Kleine-König [ID_LTC2636L8] = { 252*9f15a4a0SUwe Kleine-König .channels = ltc2632x8_channels, 253*9f15a4a0SUwe Kleine-König .num_channels = 8, 254*9f15a4a0SUwe Kleine-König .vref_mv = 2500, 255*9f15a4a0SUwe Kleine-König }, 256*9f15a4a0SUwe Kleine-König [ID_LTC2636H12] = { 257*9f15a4a0SUwe Kleine-König .channels = ltc2632x12_channels, 258*9f15a4a0SUwe Kleine-König .num_channels = 8, 259*9f15a4a0SUwe Kleine-König .vref_mv = 4096, 260*9f15a4a0SUwe Kleine-König }, 261*9f15a4a0SUwe Kleine-König [ID_LTC2636H10] = { 262*9f15a4a0SUwe Kleine-König .channels = ltc2632x10_channels, 263*9f15a4a0SUwe Kleine-König .num_channels = 8, 264*9f15a4a0SUwe Kleine-König .vref_mv = 4096, 265*9f15a4a0SUwe Kleine-König }, 266*9f15a4a0SUwe Kleine-König [ID_LTC2636H8] = { 267*9f15a4a0SUwe Kleine-König .channels = ltc2632x8_channels, 268*9f15a4a0SUwe Kleine-König .num_channels = 8, 26902b829f9SMaxime Roussin-Belanger .vref_mv = 4096, 27002b829f9SMaxime Roussin-Belanger }, 27102b829f9SMaxime Roussin-Belanger }; 27202b829f9SMaxime Roussin-Belanger 27302b829f9SMaxime Roussin-Belanger static int ltc2632_probe(struct spi_device *spi) 27402b829f9SMaxime Roussin-Belanger { 27502b829f9SMaxime Roussin-Belanger struct ltc2632_state *st; 27602b829f9SMaxime Roussin-Belanger struct iio_dev *indio_dev; 27702b829f9SMaxime Roussin-Belanger struct ltc2632_chip_info *chip_info; 27802b829f9SMaxime Roussin-Belanger int ret; 27902b829f9SMaxime Roussin-Belanger 28002b829f9SMaxime Roussin-Belanger indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 28102b829f9SMaxime Roussin-Belanger if (!indio_dev) 28202b829f9SMaxime Roussin-Belanger return -ENOMEM; 28302b829f9SMaxime Roussin-Belanger 28402b829f9SMaxime Roussin-Belanger st = iio_priv(indio_dev); 28502b829f9SMaxime Roussin-Belanger 28602b829f9SMaxime Roussin-Belanger spi_set_drvdata(spi, indio_dev); 28702b829f9SMaxime Roussin-Belanger st->spi_dev = spi; 28802b829f9SMaxime Roussin-Belanger 28902b829f9SMaxime Roussin-Belanger chip_info = (struct ltc2632_chip_info *) 29002b829f9SMaxime Roussin-Belanger spi_get_device_id(spi)->driver_data; 29102b829f9SMaxime Roussin-Belanger 2929ff1d500SSilvan Murer st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref"); 2939ff1d500SSilvan Murer if (PTR_ERR(st->vref_reg) == -ENODEV) { 2949ff1d500SSilvan Murer /* use internal reference voltage */ 2959ff1d500SSilvan Murer st->vref_reg = NULL; 2969ff1d500SSilvan Murer st->vref_mv = chip_info->vref_mv; 2979ff1d500SSilvan Murer 2989ff1d500SSilvan Murer ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER, 2999ff1d500SSilvan Murer 0, 0, 0); 3009ff1d500SSilvan Murer if (ret) { 3019ff1d500SSilvan Murer dev_err(&spi->dev, 3029ff1d500SSilvan Murer "Set internal reference command failed, %d\n", 3039ff1d500SSilvan Murer ret); 3049ff1d500SSilvan Murer return ret; 3059ff1d500SSilvan Murer } 3069ff1d500SSilvan Murer } else if (IS_ERR(st->vref_reg)) { 3079ff1d500SSilvan Murer dev_err(&spi->dev, 3089ff1d500SSilvan Murer "Error getting voltage reference regulator\n"); 3099ff1d500SSilvan Murer return PTR_ERR(st->vref_reg); 3109ff1d500SSilvan Murer } else { 3119ff1d500SSilvan Murer /* use external reference voltage */ 3129ff1d500SSilvan Murer ret = regulator_enable(st->vref_reg); 3139ff1d500SSilvan Murer if (ret) { 3149ff1d500SSilvan Murer dev_err(&spi->dev, 3159ff1d500SSilvan Murer "enable reference regulator failed, %d\n", 3169ff1d500SSilvan Murer ret); 3179ff1d500SSilvan Murer return ret; 3189ff1d500SSilvan Murer } 3199ff1d500SSilvan Murer st->vref_mv = regulator_get_voltage(st->vref_reg) / 1000; 3209ff1d500SSilvan Murer 3219ff1d500SSilvan Murer ret = ltc2632_spi_write(spi, LTC2632_CMD_EXTERNAL_REFER, 3229ff1d500SSilvan Murer 0, 0, 0); 3239ff1d500SSilvan Murer if (ret) { 3249ff1d500SSilvan Murer dev_err(&spi->dev, 3259ff1d500SSilvan Murer "Set external reference command failed, %d\n", 3269ff1d500SSilvan Murer ret); 3279ff1d500SSilvan Murer return ret; 3289ff1d500SSilvan Murer } 3299ff1d500SSilvan Murer } 3309ff1d500SSilvan Murer 33102b829f9SMaxime Roussin-Belanger indio_dev->dev.parent = &spi->dev; 33202b829f9SMaxime Roussin-Belanger indio_dev->name = dev_of_node(&spi->dev) ? dev_of_node(&spi->dev)->name 33302b829f9SMaxime Roussin-Belanger : spi_get_device_id(spi)->name; 33402b829f9SMaxime Roussin-Belanger indio_dev->info = <c2632_info; 33502b829f9SMaxime Roussin-Belanger indio_dev->modes = INDIO_DIRECT_MODE; 33602b829f9SMaxime Roussin-Belanger indio_dev->channels = chip_info->channels; 337*9f15a4a0SUwe Kleine-König indio_dev->num_channels = chip_info->num_channels; 33802b829f9SMaxime Roussin-Belanger 3399ff1d500SSilvan Murer return iio_device_register(indio_dev); 34002b829f9SMaxime Roussin-Belanger } 34102b829f9SMaxime Roussin-Belanger 3429ff1d500SSilvan Murer static int ltc2632_remove(struct spi_device *spi) 3439ff1d500SSilvan Murer { 3449ff1d500SSilvan Murer struct iio_dev *indio_dev = spi_get_drvdata(spi); 3459ff1d500SSilvan Murer struct ltc2632_state *st = iio_priv(indio_dev); 3469ff1d500SSilvan Murer 3479ff1d500SSilvan Murer iio_device_unregister(indio_dev); 3489ff1d500SSilvan Murer 3499ff1d500SSilvan Murer if (st->vref_reg) 3509ff1d500SSilvan Murer regulator_disable(st->vref_reg); 3519ff1d500SSilvan Murer 3529ff1d500SSilvan Murer return 0; 35302b829f9SMaxime Roussin-Belanger } 35402b829f9SMaxime Roussin-Belanger 35502b829f9SMaxime Roussin-Belanger static const struct spi_device_id ltc2632_id[] = { 35602b829f9SMaxime Roussin-Belanger { "ltc2632-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L12] }, 35702b829f9SMaxime Roussin-Belanger { "ltc2632-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L10] }, 35802b829f9SMaxime Roussin-Belanger { "ltc2632-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L8] }, 35902b829f9SMaxime Roussin-Belanger { "ltc2632-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H12] }, 36002b829f9SMaxime Roussin-Belanger { "ltc2632-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H10] }, 36102b829f9SMaxime Roussin-Belanger { "ltc2632-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H8] }, 362*9f15a4a0SUwe Kleine-König { "ltc2636-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L12] }, 363*9f15a4a0SUwe Kleine-König { "ltc2636-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L10] }, 364*9f15a4a0SUwe Kleine-König { "ltc2636-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L8] }, 365*9f15a4a0SUwe Kleine-König { "ltc2636-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H12] }, 366*9f15a4a0SUwe Kleine-König { "ltc2636-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H10] }, 367*9f15a4a0SUwe Kleine-König { "ltc2636-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H8] }, 36802b829f9SMaxime Roussin-Belanger {} 36902b829f9SMaxime Roussin-Belanger }; 37002b829f9SMaxime Roussin-Belanger MODULE_DEVICE_TABLE(spi, ltc2632_id); 37102b829f9SMaxime Roussin-Belanger 37202b829f9SMaxime Roussin-Belanger static const struct of_device_id ltc2632_of_match[] = { 37302b829f9SMaxime Roussin-Belanger { 37402b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-l12", 37502b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632L12] 37602b829f9SMaxime Roussin-Belanger }, { 37702b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-l10", 37802b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632L10] 37902b829f9SMaxime Roussin-Belanger }, { 38002b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-l8", 38102b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632L8] 38202b829f9SMaxime Roussin-Belanger }, { 38302b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-h12", 38402b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632H12] 38502b829f9SMaxime Roussin-Belanger }, { 38602b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-h10", 38702b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632H10] 38802b829f9SMaxime Roussin-Belanger }, { 38902b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-h8", 39002b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632H8] 391*9f15a4a0SUwe Kleine-König }, { 392*9f15a4a0SUwe Kleine-König .compatible = "lltc,ltc2636-l12", 393*9f15a4a0SUwe Kleine-König .data = <c2632_chip_info_tbl[ID_LTC2636L12] 394*9f15a4a0SUwe Kleine-König }, { 395*9f15a4a0SUwe Kleine-König .compatible = "lltc,ltc2636-l10", 396*9f15a4a0SUwe Kleine-König .data = <c2632_chip_info_tbl[ID_LTC2636L10] 397*9f15a4a0SUwe Kleine-König }, { 398*9f15a4a0SUwe Kleine-König .compatible = "lltc,ltc2636-l8", 399*9f15a4a0SUwe Kleine-König .data = <c2632_chip_info_tbl[ID_LTC2636L8] 400*9f15a4a0SUwe Kleine-König }, { 401*9f15a4a0SUwe Kleine-König .compatible = "lltc,ltc2636-h12", 402*9f15a4a0SUwe Kleine-König .data = <c2632_chip_info_tbl[ID_LTC2636H12] 403*9f15a4a0SUwe Kleine-König }, { 404*9f15a4a0SUwe Kleine-König .compatible = "lltc,ltc2636-h10", 405*9f15a4a0SUwe Kleine-König .data = <c2632_chip_info_tbl[ID_LTC2636H10] 406*9f15a4a0SUwe Kleine-König }, { 407*9f15a4a0SUwe Kleine-König .compatible = "lltc,ltc2636-h8", 408*9f15a4a0SUwe Kleine-König .data = <c2632_chip_info_tbl[ID_LTC2636H8] 40902b829f9SMaxime Roussin-Belanger }, 41002b829f9SMaxime Roussin-Belanger {} 41102b829f9SMaxime Roussin-Belanger }; 41202b829f9SMaxime Roussin-Belanger MODULE_DEVICE_TABLE(of, ltc2632_of_match); 41302b829f9SMaxime Roussin-Belanger 4140f6a2165SSilvan Murer static struct spi_driver ltc2632_driver = { 4150f6a2165SSilvan Murer .driver = { 4160f6a2165SSilvan Murer .name = "ltc2632", 4170f6a2165SSilvan Murer .of_match_table = of_match_ptr(ltc2632_of_match), 4180f6a2165SSilvan Murer }, 4190f6a2165SSilvan Murer .probe = ltc2632_probe, 4209ff1d500SSilvan Murer .remove = ltc2632_remove, 4210f6a2165SSilvan Murer .id_table = ltc2632_id, 4220f6a2165SSilvan Murer }; 4230f6a2165SSilvan Murer module_spi_driver(ltc2632_driver); 4240f6a2165SSilvan Murer 42502b829f9SMaxime Roussin-Belanger MODULE_AUTHOR("Maxime Roussin-Belanger <maxime.roussinbelanger@gmail.com>"); 42602b829f9SMaxime Roussin-Belanger MODULE_DESCRIPTION("LTC2632 DAC SPI driver"); 42702b829f9SMaxime Roussin-Belanger MODULE_LICENSE("GPL v2"); 428