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 15*8b26ab33SAndy Shevchenko #include <asm/unaligned.h> 16*8b26ab33SAndy Shevchenko 1702b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_WRITE_INPUT_N 0x0 1802b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_UPDATE_DAC_N 0x1 1902b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 2002b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_WRITE_INPUT_N_UPDATE_N 0x3 2102b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_POWERDOWN_DAC_N 0x4 2202b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_POWERDOWN_CHIP 0x5 2302b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_INTERNAL_REFER 0x6 2402b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_EXTERNAL_REFER 0x7 2502b829f9SMaxime Roussin-Belanger 2602b829f9SMaxime Roussin-Belanger /** 2702b829f9SMaxime Roussin-Belanger * struct ltc2632_chip_info - chip specific information 2802b829f9SMaxime Roussin-Belanger * @channels: channel spec for the DAC 299ff1d500SSilvan Murer * @vref_mv: internal reference voltage 3002b829f9SMaxime Roussin-Belanger */ 3102b829f9SMaxime Roussin-Belanger struct ltc2632_chip_info { 3202b829f9SMaxime Roussin-Belanger const struct iio_chan_spec *channels; 339f15a4a0SUwe Kleine-König const size_t num_channels; 3402b829f9SMaxime Roussin-Belanger const int vref_mv; 3502b829f9SMaxime Roussin-Belanger }; 3602b829f9SMaxime Roussin-Belanger 3702b829f9SMaxime Roussin-Belanger /** 3802b829f9SMaxime Roussin-Belanger * struct ltc2632_state - driver instance specific data 3902b829f9SMaxime Roussin-Belanger * @spi_dev: pointer to the spi_device struct 4002b829f9SMaxime Roussin-Belanger * @powerdown_cache_mask used to show current channel powerdown state 419ff1d500SSilvan Murer * @vref_mv used reference voltage (internal or external) 429ff1d500SSilvan Murer * @vref_reg regulator for the reference voltage 4302b829f9SMaxime Roussin-Belanger */ 4402b829f9SMaxime Roussin-Belanger struct ltc2632_state { 4502b829f9SMaxime Roussin-Belanger struct spi_device *spi_dev; 4602b829f9SMaxime Roussin-Belanger unsigned int powerdown_cache_mask; 479ff1d500SSilvan Murer int vref_mv; 489ff1d500SSilvan Murer struct regulator *vref_reg; 4902b829f9SMaxime Roussin-Belanger }; 5002b829f9SMaxime Roussin-Belanger 5102b829f9SMaxime Roussin-Belanger enum ltc2632_supported_device_ids { 5202b829f9SMaxime Roussin-Belanger ID_LTC2632L12, 5302b829f9SMaxime Roussin-Belanger ID_LTC2632L10, 5402b829f9SMaxime Roussin-Belanger ID_LTC2632L8, 5502b829f9SMaxime Roussin-Belanger ID_LTC2632H12, 5602b829f9SMaxime Roussin-Belanger ID_LTC2632H10, 5702b829f9SMaxime Roussin-Belanger ID_LTC2632H8, 589f15a4a0SUwe Kleine-König ID_LTC2636L12, 599f15a4a0SUwe Kleine-König ID_LTC2636L10, 609f15a4a0SUwe Kleine-König ID_LTC2636L8, 619f15a4a0SUwe Kleine-König ID_LTC2636H12, 629f15a4a0SUwe Kleine-König ID_LTC2636H10, 639f15a4a0SUwe Kleine-König ID_LTC2636H8, 6402b829f9SMaxime Roussin-Belanger }; 6502b829f9SMaxime Roussin-Belanger 6602b829f9SMaxime Roussin-Belanger static int ltc2632_spi_write(struct spi_device *spi, 6702b829f9SMaxime Roussin-Belanger u8 cmd, u8 addr, u16 val, u8 shift) 6802b829f9SMaxime Roussin-Belanger { 6902b829f9SMaxime Roussin-Belanger u32 data; 7002b829f9SMaxime Roussin-Belanger u8 msg[3]; 7102b829f9SMaxime Roussin-Belanger 7202b829f9SMaxime Roussin-Belanger /* 7302b829f9SMaxime Roussin-Belanger * The input shift register is 24 bits wide. 7402b829f9SMaxime Roussin-Belanger * The next four are the command bits, C3 to C0, 7502b829f9SMaxime Roussin-Belanger * followed by the 4-bit DAC address, A3 to A0, and then the 7602b829f9SMaxime Roussin-Belanger * 12-, 10-, 8-bit data-word. The data-word comprises the 12-, 7702b829f9SMaxime Roussin-Belanger * 10-, 8-bit input code followed by 4, 6, or 8 don't care bits. 7802b829f9SMaxime Roussin-Belanger */ 7902b829f9SMaxime Roussin-Belanger data = (cmd << 20) | (addr << 16) | (val << shift); 80*8b26ab33SAndy Shevchenko put_unaligned_be24(data, &msg[0]); 8102b829f9SMaxime Roussin-Belanger 8202b829f9SMaxime Roussin-Belanger return spi_write(spi, msg, sizeof(msg)); 8302b829f9SMaxime Roussin-Belanger } 8402b829f9SMaxime Roussin-Belanger 8502b829f9SMaxime Roussin-Belanger static int ltc2632_read_raw(struct iio_dev *indio_dev, 8602b829f9SMaxime Roussin-Belanger struct iio_chan_spec const *chan, 8702b829f9SMaxime Roussin-Belanger int *val, 8802b829f9SMaxime Roussin-Belanger int *val2, 8902b829f9SMaxime Roussin-Belanger long m) 9002b829f9SMaxime Roussin-Belanger { 9102b829f9SMaxime Roussin-Belanger const struct ltc2632_state *st = iio_priv(indio_dev); 9202b829f9SMaxime Roussin-Belanger 9302b829f9SMaxime Roussin-Belanger switch (m) { 9402b829f9SMaxime Roussin-Belanger case IIO_CHAN_INFO_SCALE: 959ff1d500SSilvan Murer *val = st->vref_mv; 9602b829f9SMaxime Roussin-Belanger *val2 = chan->scan_type.realbits; 9702b829f9SMaxime Roussin-Belanger return IIO_VAL_FRACTIONAL_LOG2; 9802b829f9SMaxime Roussin-Belanger } 9902b829f9SMaxime Roussin-Belanger return -EINVAL; 10002b829f9SMaxime Roussin-Belanger } 10102b829f9SMaxime Roussin-Belanger 10202b829f9SMaxime Roussin-Belanger static int ltc2632_write_raw(struct iio_dev *indio_dev, 10302b829f9SMaxime Roussin-Belanger struct iio_chan_spec const *chan, 10402b829f9SMaxime Roussin-Belanger int val, 10502b829f9SMaxime Roussin-Belanger int val2, 10602b829f9SMaxime Roussin-Belanger long mask) 10702b829f9SMaxime Roussin-Belanger { 10802b829f9SMaxime Roussin-Belanger struct ltc2632_state *st = iio_priv(indio_dev); 10902b829f9SMaxime Roussin-Belanger 11002b829f9SMaxime Roussin-Belanger switch (mask) { 11102b829f9SMaxime Roussin-Belanger case IIO_CHAN_INFO_RAW: 11202b829f9SMaxime Roussin-Belanger if (val >= (1 << chan->scan_type.realbits) || val < 0) 11302b829f9SMaxime Roussin-Belanger return -EINVAL; 11402b829f9SMaxime Roussin-Belanger 11502b829f9SMaxime Roussin-Belanger return ltc2632_spi_write(st->spi_dev, 11602b829f9SMaxime Roussin-Belanger LTC2632_CMD_WRITE_INPUT_N_UPDATE_N, 11702b829f9SMaxime Roussin-Belanger chan->address, val, 11802b829f9SMaxime Roussin-Belanger chan->scan_type.shift); 11902b829f9SMaxime Roussin-Belanger default: 12002b829f9SMaxime Roussin-Belanger return -EINVAL; 12102b829f9SMaxime Roussin-Belanger } 12202b829f9SMaxime Roussin-Belanger } 12302b829f9SMaxime Roussin-Belanger 12402b829f9SMaxime Roussin-Belanger static ssize_t ltc2632_read_dac_powerdown(struct iio_dev *indio_dev, 12502b829f9SMaxime Roussin-Belanger uintptr_t private, 12602b829f9SMaxime Roussin-Belanger const struct iio_chan_spec *chan, 12702b829f9SMaxime Roussin-Belanger char *buf) 12802b829f9SMaxime Roussin-Belanger { 12902b829f9SMaxime Roussin-Belanger struct ltc2632_state *st = iio_priv(indio_dev); 13002b829f9SMaxime Roussin-Belanger 13102b829f9SMaxime Roussin-Belanger return sprintf(buf, "%d\n", 13202b829f9SMaxime Roussin-Belanger !!(st->powerdown_cache_mask & (1 << chan->channel))); 13302b829f9SMaxime Roussin-Belanger } 13402b829f9SMaxime Roussin-Belanger 13502b829f9SMaxime Roussin-Belanger static ssize_t ltc2632_write_dac_powerdown(struct iio_dev *indio_dev, 13602b829f9SMaxime Roussin-Belanger uintptr_t private, 13702b829f9SMaxime Roussin-Belanger const struct iio_chan_spec *chan, 13802b829f9SMaxime Roussin-Belanger const char *buf, 13902b829f9SMaxime Roussin-Belanger size_t len) 14002b829f9SMaxime Roussin-Belanger { 14102b829f9SMaxime Roussin-Belanger bool pwr_down; 14202b829f9SMaxime Roussin-Belanger int ret; 14302b829f9SMaxime Roussin-Belanger struct ltc2632_state *st = iio_priv(indio_dev); 14402b829f9SMaxime Roussin-Belanger 14502b829f9SMaxime Roussin-Belanger ret = strtobool(buf, &pwr_down); 14602b829f9SMaxime Roussin-Belanger if (ret) 14702b829f9SMaxime Roussin-Belanger return ret; 14802b829f9SMaxime Roussin-Belanger 14902b829f9SMaxime Roussin-Belanger if (pwr_down) 15002b829f9SMaxime Roussin-Belanger st->powerdown_cache_mask |= (1 << chan->channel); 15102b829f9SMaxime Roussin-Belanger else 15202b829f9SMaxime Roussin-Belanger st->powerdown_cache_mask &= ~(1 << chan->channel); 15302b829f9SMaxime Roussin-Belanger 15402b829f9SMaxime Roussin-Belanger ret = ltc2632_spi_write(st->spi_dev, 15502b829f9SMaxime Roussin-Belanger LTC2632_CMD_POWERDOWN_DAC_N, 15602b829f9SMaxime Roussin-Belanger chan->channel, 0, 0); 15702b829f9SMaxime Roussin-Belanger 15802b829f9SMaxime Roussin-Belanger return ret ? ret : len; 15902b829f9SMaxime Roussin-Belanger } 16002b829f9SMaxime Roussin-Belanger 16102b829f9SMaxime Roussin-Belanger static const struct iio_info ltc2632_info = { 16202b829f9SMaxime Roussin-Belanger .write_raw = ltc2632_write_raw, 16302b829f9SMaxime Roussin-Belanger .read_raw = ltc2632_read_raw, 16402b829f9SMaxime Roussin-Belanger }; 16502b829f9SMaxime Roussin-Belanger 16602b829f9SMaxime Roussin-Belanger static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = { 16702b829f9SMaxime Roussin-Belanger { 16802b829f9SMaxime Roussin-Belanger .name = "powerdown", 16902b829f9SMaxime Roussin-Belanger .read = ltc2632_read_dac_powerdown, 17002b829f9SMaxime Roussin-Belanger .write = ltc2632_write_dac_powerdown, 17102b829f9SMaxime Roussin-Belanger .shared = IIO_SEPARATE, 17202b829f9SMaxime Roussin-Belanger }, 17302b829f9SMaxime Roussin-Belanger { }, 17402b829f9SMaxime Roussin-Belanger }; 17502b829f9SMaxime Roussin-Belanger 17602b829f9SMaxime Roussin-Belanger #define LTC2632_CHANNEL(_chan, _bits) { \ 17702b829f9SMaxime Roussin-Belanger .type = IIO_VOLTAGE, \ 17802b829f9SMaxime Roussin-Belanger .indexed = 1, \ 17902b829f9SMaxime Roussin-Belanger .output = 1, \ 18002b829f9SMaxime Roussin-Belanger .channel = (_chan), \ 18102b829f9SMaxime Roussin-Belanger .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 18202b829f9SMaxime Roussin-Belanger .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 18302b829f9SMaxime Roussin-Belanger .address = (_chan), \ 18402b829f9SMaxime Roussin-Belanger .scan_type = { \ 18502b829f9SMaxime Roussin-Belanger .realbits = (_bits), \ 18602b829f9SMaxime Roussin-Belanger .shift = 16 - (_bits), \ 18702b829f9SMaxime Roussin-Belanger }, \ 18802b829f9SMaxime Roussin-Belanger .ext_info = ltc2632_ext_info, \ 18902b829f9SMaxime Roussin-Belanger } 19002b829f9SMaxime Roussin-Belanger 19102b829f9SMaxime Roussin-Belanger #define DECLARE_LTC2632_CHANNELS(_name, _bits) \ 19202b829f9SMaxime Roussin-Belanger const struct iio_chan_spec _name ## _channels[] = { \ 19302b829f9SMaxime Roussin-Belanger LTC2632_CHANNEL(0, _bits), \ 19402b829f9SMaxime Roussin-Belanger LTC2632_CHANNEL(1, _bits), \ 1959f15a4a0SUwe Kleine-König LTC2632_CHANNEL(2, _bits), \ 1969f15a4a0SUwe Kleine-König LTC2632_CHANNEL(3, _bits), \ 1979f15a4a0SUwe Kleine-König LTC2632_CHANNEL(4, _bits), \ 1989f15a4a0SUwe Kleine-König LTC2632_CHANNEL(5, _bits), \ 1999f15a4a0SUwe Kleine-König LTC2632_CHANNEL(6, _bits), \ 2009f15a4a0SUwe Kleine-König LTC2632_CHANNEL(7, _bits), \ 20102b829f9SMaxime Roussin-Belanger } 20202b829f9SMaxime Roussin-Belanger 203f243d0f0SUwe Kleine-König static DECLARE_LTC2632_CHANNELS(ltc2632x12, 12); 204f243d0f0SUwe Kleine-König static DECLARE_LTC2632_CHANNELS(ltc2632x10, 10); 205f243d0f0SUwe Kleine-König static DECLARE_LTC2632_CHANNELS(ltc2632x8, 8); 20602b829f9SMaxime Roussin-Belanger 20702b829f9SMaxime Roussin-Belanger static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = { 20802b829f9SMaxime Roussin-Belanger [ID_LTC2632L12] = { 209f243d0f0SUwe Kleine-König .channels = ltc2632x12_channels, 2109f15a4a0SUwe Kleine-König .num_channels = 2, 21102b829f9SMaxime Roussin-Belanger .vref_mv = 2500, 21202b829f9SMaxime Roussin-Belanger }, 21302b829f9SMaxime Roussin-Belanger [ID_LTC2632L10] = { 214f243d0f0SUwe Kleine-König .channels = ltc2632x10_channels, 2159f15a4a0SUwe Kleine-König .num_channels = 2, 21602b829f9SMaxime Roussin-Belanger .vref_mv = 2500, 21702b829f9SMaxime Roussin-Belanger }, 21802b829f9SMaxime Roussin-Belanger [ID_LTC2632L8] = { 219f243d0f0SUwe Kleine-König .channels = ltc2632x8_channels, 2209f15a4a0SUwe Kleine-König .num_channels = 2, 22102b829f9SMaxime Roussin-Belanger .vref_mv = 2500, 22202b829f9SMaxime Roussin-Belanger }, 22302b829f9SMaxime Roussin-Belanger [ID_LTC2632H12] = { 224f243d0f0SUwe Kleine-König .channels = ltc2632x12_channels, 2259f15a4a0SUwe Kleine-König .num_channels = 2, 22602b829f9SMaxime Roussin-Belanger .vref_mv = 4096, 22702b829f9SMaxime Roussin-Belanger }, 22802b829f9SMaxime Roussin-Belanger [ID_LTC2632H10] = { 229f243d0f0SUwe Kleine-König .channels = ltc2632x10_channels, 2309f15a4a0SUwe Kleine-König .num_channels = 2, 23102b829f9SMaxime Roussin-Belanger .vref_mv = 4096, 23202b829f9SMaxime Roussin-Belanger }, 23302b829f9SMaxime Roussin-Belanger [ID_LTC2632H8] = { 234f243d0f0SUwe Kleine-König .channels = ltc2632x8_channels, 2359f15a4a0SUwe Kleine-König .num_channels = 2, 2369f15a4a0SUwe Kleine-König .vref_mv = 4096, 2379f15a4a0SUwe Kleine-König }, 2389f15a4a0SUwe Kleine-König [ID_LTC2636L12] = { 2399f15a4a0SUwe Kleine-König .channels = ltc2632x12_channels, 2409f15a4a0SUwe Kleine-König .num_channels = 8, 2419f15a4a0SUwe Kleine-König .vref_mv = 2500, 2429f15a4a0SUwe Kleine-König }, 2439f15a4a0SUwe Kleine-König [ID_LTC2636L10] = { 2449f15a4a0SUwe Kleine-König .channels = ltc2632x10_channels, 2459f15a4a0SUwe Kleine-König .num_channels = 8, 2469f15a4a0SUwe Kleine-König .vref_mv = 2500, 2479f15a4a0SUwe Kleine-König }, 2489f15a4a0SUwe Kleine-König [ID_LTC2636L8] = { 2499f15a4a0SUwe Kleine-König .channels = ltc2632x8_channels, 2509f15a4a0SUwe Kleine-König .num_channels = 8, 2519f15a4a0SUwe Kleine-König .vref_mv = 2500, 2529f15a4a0SUwe Kleine-König }, 2539f15a4a0SUwe Kleine-König [ID_LTC2636H12] = { 2549f15a4a0SUwe Kleine-König .channels = ltc2632x12_channels, 2559f15a4a0SUwe Kleine-König .num_channels = 8, 2569f15a4a0SUwe Kleine-König .vref_mv = 4096, 2579f15a4a0SUwe Kleine-König }, 2589f15a4a0SUwe Kleine-König [ID_LTC2636H10] = { 2599f15a4a0SUwe Kleine-König .channels = ltc2632x10_channels, 2609f15a4a0SUwe Kleine-König .num_channels = 8, 2619f15a4a0SUwe Kleine-König .vref_mv = 4096, 2629f15a4a0SUwe Kleine-König }, 2639f15a4a0SUwe Kleine-König [ID_LTC2636H8] = { 2649f15a4a0SUwe Kleine-König .channels = ltc2632x8_channels, 2659f15a4a0SUwe Kleine-König .num_channels = 8, 26602b829f9SMaxime Roussin-Belanger .vref_mv = 4096, 26702b829f9SMaxime Roussin-Belanger }, 26802b829f9SMaxime Roussin-Belanger }; 26902b829f9SMaxime Roussin-Belanger 27002b829f9SMaxime Roussin-Belanger static int ltc2632_probe(struct spi_device *spi) 27102b829f9SMaxime Roussin-Belanger { 27202b829f9SMaxime Roussin-Belanger struct ltc2632_state *st; 27302b829f9SMaxime Roussin-Belanger struct iio_dev *indio_dev; 27402b829f9SMaxime Roussin-Belanger struct ltc2632_chip_info *chip_info; 27502b829f9SMaxime Roussin-Belanger int ret; 27602b829f9SMaxime Roussin-Belanger 27702b829f9SMaxime Roussin-Belanger indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 27802b829f9SMaxime Roussin-Belanger if (!indio_dev) 27902b829f9SMaxime Roussin-Belanger return -ENOMEM; 28002b829f9SMaxime Roussin-Belanger 28102b829f9SMaxime Roussin-Belanger st = iio_priv(indio_dev); 28202b829f9SMaxime Roussin-Belanger 28302b829f9SMaxime Roussin-Belanger spi_set_drvdata(spi, indio_dev); 28402b829f9SMaxime Roussin-Belanger st->spi_dev = spi; 28502b829f9SMaxime Roussin-Belanger 28602b829f9SMaxime Roussin-Belanger chip_info = (struct ltc2632_chip_info *) 28702b829f9SMaxime Roussin-Belanger spi_get_device_id(spi)->driver_data; 28802b829f9SMaxime Roussin-Belanger 2899ff1d500SSilvan Murer st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref"); 2909ff1d500SSilvan Murer if (PTR_ERR(st->vref_reg) == -ENODEV) { 2919ff1d500SSilvan Murer /* use internal reference voltage */ 2929ff1d500SSilvan Murer st->vref_reg = NULL; 2939ff1d500SSilvan Murer st->vref_mv = chip_info->vref_mv; 2949ff1d500SSilvan Murer 2959ff1d500SSilvan Murer ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER, 2969ff1d500SSilvan Murer 0, 0, 0); 2979ff1d500SSilvan Murer if (ret) { 2989ff1d500SSilvan Murer dev_err(&spi->dev, 2999ff1d500SSilvan Murer "Set internal reference command failed, %d\n", 3009ff1d500SSilvan Murer ret); 3019ff1d500SSilvan Murer return ret; 3029ff1d500SSilvan Murer } 3039ff1d500SSilvan Murer } else if (IS_ERR(st->vref_reg)) { 3049ff1d500SSilvan Murer dev_err(&spi->dev, 3059ff1d500SSilvan Murer "Error getting voltage reference regulator\n"); 3069ff1d500SSilvan Murer return PTR_ERR(st->vref_reg); 3079ff1d500SSilvan Murer } else { 3089ff1d500SSilvan Murer /* use external reference voltage */ 3099ff1d500SSilvan Murer ret = regulator_enable(st->vref_reg); 3109ff1d500SSilvan Murer if (ret) { 3119ff1d500SSilvan Murer dev_err(&spi->dev, 3129ff1d500SSilvan Murer "enable reference regulator failed, %d\n", 3139ff1d500SSilvan Murer ret); 3149ff1d500SSilvan Murer return ret; 3159ff1d500SSilvan Murer } 3169ff1d500SSilvan Murer st->vref_mv = regulator_get_voltage(st->vref_reg) / 1000; 3179ff1d500SSilvan Murer 3189ff1d500SSilvan Murer ret = ltc2632_spi_write(spi, LTC2632_CMD_EXTERNAL_REFER, 3199ff1d500SSilvan Murer 0, 0, 0); 3209ff1d500SSilvan Murer if (ret) { 3219ff1d500SSilvan Murer dev_err(&spi->dev, 3229ff1d500SSilvan Murer "Set external reference command failed, %d\n", 3239ff1d500SSilvan Murer ret); 3249ff1d500SSilvan Murer return ret; 3259ff1d500SSilvan Murer } 3269ff1d500SSilvan Murer } 3279ff1d500SSilvan Murer 32802b829f9SMaxime Roussin-Belanger indio_dev->dev.parent = &spi->dev; 32902b829f9SMaxime Roussin-Belanger indio_dev->name = dev_of_node(&spi->dev) ? dev_of_node(&spi->dev)->name 33002b829f9SMaxime Roussin-Belanger : spi_get_device_id(spi)->name; 33102b829f9SMaxime Roussin-Belanger indio_dev->info = <c2632_info; 33202b829f9SMaxime Roussin-Belanger indio_dev->modes = INDIO_DIRECT_MODE; 33302b829f9SMaxime Roussin-Belanger indio_dev->channels = chip_info->channels; 3349f15a4a0SUwe Kleine-König indio_dev->num_channels = chip_info->num_channels; 33502b829f9SMaxime Roussin-Belanger 3369ff1d500SSilvan Murer return iio_device_register(indio_dev); 33702b829f9SMaxime Roussin-Belanger } 33802b829f9SMaxime Roussin-Belanger 3399ff1d500SSilvan Murer static int ltc2632_remove(struct spi_device *spi) 3409ff1d500SSilvan Murer { 3419ff1d500SSilvan Murer struct iio_dev *indio_dev = spi_get_drvdata(spi); 3429ff1d500SSilvan Murer struct ltc2632_state *st = iio_priv(indio_dev); 3439ff1d500SSilvan Murer 3449ff1d500SSilvan Murer iio_device_unregister(indio_dev); 3459ff1d500SSilvan Murer 3469ff1d500SSilvan Murer if (st->vref_reg) 3479ff1d500SSilvan Murer regulator_disable(st->vref_reg); 3489ff1d500SSilvan Murer 3499ff1d500SSilvan Murer return 0; 35002b829f9SMaxime Roussin-Belanger } 35102b829f9SMaxime Roussin-Belanger 35202b829f9SMaxime Roussin-Belanger static const struct spi_device_id ltc2632_id[] = { 35302b829f9SMaxime Roussin-Belanger { "ltc2632-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L12] }, 35402b829f9SMaxime Roussin-Belanger { "ltc2632-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L10] }, 35502b829f9SMaxime Roussin-Belanger { "ltc2632-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L8] }, 35602b829f9SMaxime Roussin-Belanger { "ltc2632-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H12] }, 35702b829f9SMaxime Roussin-Belanger { "ltc2632-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H10] }, 35802b829f9SMaxime Roussin-Belanger { "ltc2632-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H8] }, 3599f15a4a0SUwe Kleine-König { "ltc2636-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L12] }, 3609f15a4a0SUwe Kleine-König { "ltc2636-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L10] }, 3619f15a4a0SUwe Kleine-König { "ltc2636-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L8] }, 3629f15a4a0SUwe Kleine-König { "ltc2636-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H12] }, 3639f15a4a0SUwe Kleine-König { "ltc2636-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H10] }, 3649f15a4a0SUwe Kleine-König { "ltc2636-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H8] }, 36502b829f9SMaxime Roussin-Belanger {} 36602b829f9SMaxime Roussin-Belanger }; 36702b829f9SMaxime Roussin-Belanger MODULE_DEVICE_TABLE(spi, ltc2632_id); 36802b829f9SMaxime Roussin-Belanger 36902b829f9SMaxime Roussin-Belanger static const struct of_device_id ltc2632_of_match[] = { 37002b829f9SMaxime Roussin-Belanger { 37102b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-l12", 37202b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632L12] 37302b829f9SMaxime Roussin-Belanger }, { 37402b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-l10", 37502b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632L10] 37602b829f9SMaxime Roussin-Belanger }, { 37702b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-l8", 37802b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632L8] 37902b829f9SMaxime Roussin-Belanger }, { 38002b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-h12", 38102b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632H12] 38202b829f9SMaxime Roussin-Belanger }, { 38302b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-h10", 38402b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632H10] 38502b829f9SMaxime Roussin-Belanger }, { 38602b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-h8", 38702b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632H8] 3889f15a4a0SUwe Kleine-König }, { 3899f15a4a0SUwe Kleine-König .compatible = "lltc,ltc2636-l12", 3909f15a4a0SUwe Kleine-König .data = <c2632_chip_info_tbl[ID_LTC2636L12] 3919f15a4a0SUwe Kleine-König }, { 3929f15a4a0SUwe Kleine-König .compatible = "lltc,ltc2636-l10", 3939f15a4a0SUwe Kleine-König .data = <c2632_chip_info_tbl[ID_LTC2636L10] 3949f15a4a0SUwe Kleine-König }, { 3959f15a4a0SUwe Kleine-König .compatible = "lltc,ltc2636-l8", 3969f15a4a0SUwe Kleine-König .data = <c2632_chip_info_tbl[ID_LTC2636L8] 3979f15a4a0SUwe Kleine-König }, { 3989f15a4a0SUwe Kleine-König .compatible = "lltc,ltc2636-h12", 3999f15a4a0SUwe Kleine-König .data = <c2632_chip_info_tbl[ID_LTC2636H12] 4009f15a4a0SUwe Kleine-König }, { 4019f15a4a0SUwe Kleine-König .compatible = "lltc,ltc2636-h10", 4029f15a4a0SUwe Kleine-König .data = <c2632_chip_info_tbl[ID_LTC2636H10] 4039f15a4a0SUwe Kleine-König }, { 4049f15a4a0SUwe Kleine-König .compatible = "lltc,ltc2636-h8", 4059f15a4a0SUwe Kleine-König .data = <c2632_chip_info_tbl[ID_LTC2636H8] 40602b829f9SMaxime Roussin-Belanger }, 40702b829f9SMaxime Roussin-Belanger {} 40802b829f9SMaxime Roussin-Belanger }; 40902b829f9SMaxime Roussin-Belanger MODULE_DEVICE_TABLE(of, ltc2632_of_match); 41002b829f9SMaxime Roussin-Belanger 4110f6a2165SSilvan Murer static struct spi_driver ltc2632_driver = { 4120f6a2165SSilvan Murer .driver = { 4130f6a2165SSilvan Murer .name = "ltc2632", 4140f6a2165SSilvan Murer .of_match_table = of_match_ptr(ltc2632_of_match), 4150f6a2165SSilvan Murer }, 4160f6a2165SSilvan Murer .probe = ltc2632_probe, 4179ff1d500SSilvan Murer .remove = ltc2632_remove, 4180f6a2165SSilvan Murer .id_table = ltc2632_id, 4190f6a2165SSilvan Murer }; 4200f6a2165SSilvan Murer module_spi_driver(ltc2632_driver); 4210f6a2165SSilvan Murer 42202b829f9SMaxime Roussin-Belanger MODULE_AUTHOR("Maxime Roussin-Belanger <maxime.roussinbelanger@gmail.com>"); 42302b829f9SMaxime Roussin-Belanger MODULE_DESCRIPTION("LTC2632 DAC SPI driver"); 42402b829f9SMaxime Roussin-Belanger MODULE_LICENSE("GPL v2"); 425