102b829f9SMaxime Roussin-Belanger /* 202b829f9SMaxime Roussin-Belanger * LTC2632 Digital to analog convertors spi driver 302b829f9SMaxime Roussin-Belanger * 4*3723c632SArnd Bergmann * Copyright 2017 Maxime Roussin-Bélanger 59ff1d500SSilvan Murer * expanded by Silvan Murer <silvan.murer@gmail.com> 602b829f9SMaxime Roussin-Belanger * 702b829f9SMaxime Roussin-Belanger * Licensed under the GPL-2. 802b829f9SMaxime Roussin-Belanger */ 902b829f9SMaxime Roussin-Belanger 1002b829f9SMaxime Roussin-Belanger #include <linux/device.h> 1102b829f9SMaxime Roussin-Belanger #include <linux/spi/spi.h> 1202b829f9SMaxime Roussin-Belanger #include <linux/module.h> 1302b829f9SMaxime Roussin-Belanger #include <linux/iio/iio.h> 149ff1d500SSilvan Murer #include <linux/regulator/consumer.h> 1502b829f9SMaxime Roussin-Belanger 1602b829f9SMaxime Roussin-Belanger #define LTC2632_DAC_CHANNELS 2 1702b829f9SMaxime Roussin-Belanger 1802b829f9SMaxime Roussin-Belanger #define LTC2632_ADDR_DAC0 0x0 1902b829f9SMaxime Roussin-Belanger #define LTC2632_ADDR_DAC1 0x1 2002b829f9SMaxime Roussin-Belanger 2102b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_WRITE_INPUT_N 0x0 2202b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_UPDATE_DAC_N 0x1 2302b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 2402b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_WRITE_INPUT_N_UPDATE_N 0x3 2502b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_POWERDOWN_DAC_N 0x4 2602b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_POWERDOWN_CHIP 0x5 2702b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_INTERNAL_REFER 0x6 2802b829f9SMaxime Roussin-Belanger #define LTC2632_CMD_EXTERNAL_REFER 0x7 2902b829f9SMaxime Roussin-Belanger 3002b829f9SMaxime Roussin-Belanger /** 3102b829f9SMaxime Roussin-Belanger * struct ltc2632_chip_info - chip specific information 3202b829f9SMaxime Roussin-Belanger * @channels: channel spec for the DAC 339ff1d500SSilvan Murer * @vref_mv: internal reference voltage 3402b829f9SMaxime Roussin-Belanger */ 3502b829f9SMaxime Roussin-Belanger struct ltc2632_chip_info { 3602b829f9SMaxime Roussin-Belanger const struct iio_chan_spec *channels; 3702b829f9SMaxime Roussin-Belanger const int vref_mv; 3802b829f9SMaxime Roussin-Belanger }; 3902b829f9SMaxime Roussin-Belanger 4002b829f9SMaxime Roussin-Belanger /** 4102b829f9SMaxime Roussin-Belanger * struct ltc2632_state - driver instance specific data 4202b829f9SMaxime Roussin-Belanger * @spi_dev: pointer to the spi_device struct 4302b829f9SMaxime Roussin-Belanger * @powerdown_cache_mask used to show current channel powerdown state 449ff1d500SSilvan Murer * @vref_mv used reference voltage (internal or external) 459ff1d500SSilvan Murer * @vref_reg regulator for the reference voltage 4602b829f9SMaxime Roussin-Belanger */ 4702b829f9SMaxime Roussin-Belanger struct ltc2632_state { 4802b829f9SMaxime Roussin-Belanger struct spi_device *spi_dev; 4902b829f9SMaxime Roussin-Belanger unsigned int powerdown_cache_mask; 509ff1d500SSilvan Murer int vref_mv; 519ff1d500SSilvan Murer struct regulator *vref_reg; 5202b829f9SMaxime Roussin-Belanger }; 5302b829f9SMaxime Roussin-Belanger 5402b829f9SMaxime Roussin-Belanger enum ltc2632_supported_device_ids { 5502b829f9SMaxime Roussin-Belanger ID_LTC2632L12, 5602b829f9SMaxime Roussin-Belanger ID_LTC2632L10, 5702b829f9SMaxime Roussin-Belanger ID_LTC2632L8, 5802b829f9SMaxime Roussin-Belanger ID_LTC2632H12, 5902b829f9SMaxime Roussin-Belanger ID_LTC2632H10, 6002b829f9SMaxime Roussin-Belanger ID_LTC2632H8, 6102b829f9SMaxime Roussin-Belanger }; 6202b829f9SMaxime Roussin-Belanger 6302b829f9SMaxime Roussin-Belanger static int ltc2632_spi_write(struct spi_device *spi, 6402b829f9SMaxime Roussin-Belanger u8 cmd, u8 addr, u16 val, u8 shift) 6502b829f9SMaxime Roussin-Belanger { 6602b829f9SMaxime Roussin-Belanger u32 data; 6702b829f9SMaxime Roussin-Belanger u8 msg[3]; 6802b829f9SMaxime Roussin-Belanger 6902b829f9SMaxime Roussin-Belanger /* 7002b829f9SMaxime Roussin-Belanger * The input shift register is 24 bits wide. 7102b829f9SMaxime Roussin-Belanger * The next four are the command bits, C3 to C0, 7202b829f9SMaxime Roussin-Belanger * followed by the 4-bit DAC address, A3 to A0, and then the 7302b829f9SMaxime Roussin-Belanger * 12-, 10-, 8-bit data-word. The data-word comprises the 12-, 7402b829f9SMaxime Roussin-Belanger * 10-, 8-bit input code followed by 4, 6, or 8 don't care bits. 7502b829f9SMaxime Roussin-Belanger */ 7602b829f9SMaxime Roussin-Belanger data = (cmd << 20) | (addr << 16) | (val << shift); 7702b829f9SMaxime Roussin-Belanger msg[0] = data >> 16; 7802b829f9SMaxime Roussin-Belanger msg[1] = data >> 8; 7902b829f9SMaxime Roussin-Belanger msg[2] = data; 8002b829f9SMaxime Roussin-Belanger 8102b829f9SMaxime Roussin-Belanger return spi_write(spi, msg, sizeof(msg)); 8202b829f9SMaxime Roussin-Belanger } 8302b829f9SMaxime Roussin-Belanger 8402b829f9SMaxime Roussin-Belanger static int ltc2632_read_raw(struct iio_dev *indio_dev, 8502b829f9SMaxime Roussin-Belanger struct iio_chan_spec const *chan, 8602b829f9SMaxime Roussin-Belanger int *val, 8702b829f9SMaxime Roussin-Belanger int *val2, 8802b829f9SMaxime Roussin-Belanger long m) 8902b829f9SMaxime Roussin-Belanger { 9002b829f9SMaxime Roussin-Belanger const struct ltc2632_state *st = iio_priv(indio_dev); 9102b829f9SMaxime Roussin-Belanger 9202b829f9SMaxime Roussin-Belanger switch (m) { 9302b829f9SMaxime Roussin-Belanger case IIO_CHAN_INFO_SCALE: 949ff1d500SSilvan Murer *val = st->vref_mv; 9502b829f9SMaxime Roussin-Belanger *val2 = chan->scan_type.realbits; 9602b829f9SMaxime Roussin-Belanger return IIO_VAL_FRACTIONAL_LOG2; 9702b829f9SMaxime Roussin-Belanger } 9802b829f9SMaxime Roussin-Belanger return -EINVAL; 9902b829f9SMaxime Roussin-Belanger } 10002b829f9SMaxime Roussin-Belanger 10102b829f9SMaxime Roussin-Belanger static int ltc2632_write_raw(struct iio_dev *indio_dev, 10202b829f9SMaxime Roussin-Belanger struct iio_chan_spec const *chan, 10302b829f9SMaxime Roussin-Belanger int val, 10402b829f9SMaxime Roussin-Belanger int val2, 10502b829f9SMaxime Roussin-Belanger long mask) 10602b829f9SMaxime Roussin-Belanger { 10702b829f9SMaxime Roussin-Belanger struct ltc2632_state *st = iio_priv(indio_dev); 10802b829f9SMaxime Roussin-Belanger 10902b829f9SMaxime Roussin-Belanger switch (mask) { 11002b829f9SMaxime Roussin-Belanger case IIO_CHAN_INFO_RAW: 11102b829f9SMaxime Roussin-Belanger if (val >= (1 << chan->scan_type.realbits) || val < 0) 11202b829f9SMaxime Roussin-Belanger return -EINVAL; 11302b829f9SMaxime Roussin-Belanger 11402b829f9SMaxime Roussin-Belanger return ltc2632_spi_write(st->spi_dev, 11502b829f9SMaxime Roussin-Belanger LTC2632_CMD_WRITE_INPUT_N_UPDATE_N, 11602b829f9SMaxime Roussin-Belanger chan->address, val, 11702b829f9SMaxime Roussin-Belanger chan->scan_type.shift); 11802b829f9SMaxime Roussin-Belanger default: 11902b829f9SMaxime Roussin-Belanger return -EINVAL; 12002b829f9SMaxime Roussin-Belanger } 12102b829f9SMaxime Roussin-Belanger } 12202b829f9SMaxime Roussin-Belanger 12302b829f9SMaxime Roussin-Belanger static ssize_t ltc2632_read_dac_powerdown(struct iio_dev *indio_dev, 12402b829f9SMaxime Roussin-Belanger uintptr_t private, 12502b829f9SMaxime Roussin-Belanger const struct iio_chan_spec *chan, 12602b829f9SMaxime Roussin-Belanger char *buf) 12702b829f9SMaxime Roussin-Belanger { 12802b829f9SMaxime Roussin-Belanger struct ltc2632_state *st = iio_priv(indio_dev); 12902b829f9SMaxime Roussin-Belanger 13002b829f9SMaxime Roussin-Belanger return sprintf(buf, "%d\n", 13102b829f9SMaxime Roussin-Belanger !!(st->powerdown_cache_mask & (1 << chan->channel))); 13202b829f9SMaxime Roussin-Belanger } 13302b829f9SMaxime Roussin-Belanger 13402b829f9SMaxime Roussin-Belanger static ssize_t ltc2632_write_dac_powerdown(struct iio_dev *indio_dev, 13502b829f9SMaxime Roussin-Belanger uintptr_t private, 13602b829f9SMaxime Roussin-Belanger const struct iio_chan_spec *chan, 13702b829f9SMaxime Roussin-Belanger const char *buf, 13802b829f9SMaxime Roussin-Belanger size_t len) 13902b829f9SMaxime Roussin-Belanger { 14002b829f9SMaxime Roussin-Belanger bool pwr_down; 14102b829f9SMaxime Roussin-Belanger int ret; 14202b829f9SMaxime Roussin-Belanger struct ltc2632_state *st = iio_priv(indio_dev); 14302b829f9SMaxime Roussin-Belanger 14402b829f9SMaxime Roussin-Belanger ret = strtobool(buf, &pwr_down); 14502b829f9SMaxime Roussin-Belanger if (ret) 14602b829f9SMaxime Roussin-Belanger return ret; 14702b829f9SMaxime Roussin-Belanger 14802b829f9SMaxime Roussin-Belanger if (pwr_down) 14902b829f9SMaxime Roussin-Belanger st->powerdown_cache_mask |= (1 << chan->channel); 15002b829f9SMaxime Roussin-Belanger else 15102b829f9SMaxime Roussin-Belanger st->powerdown_cache_mask &= ~(1 << chan->channel); 15202b829f9SMaxime Roussin-Belanger 15302b829f9SMaxime Roussin-Belanger ret = ltc2632_spi_write(st->spi_dev, 15402b829f9SMaxime Roussin-Belanger LTC2632_CMD_POWERDOWN_DAC_N, 15502b829f9SMaxime Roussin-Belanger chan->channel, 0, 0); 15602b829f9SMaxime Roussin-Belanger 15702b829f9SMaxime Roussin-Belanger return ret ? ret : len; 15802b829f9SMaxime Roussin-Belanger } 15902b829f9SMaxime Roussin-Belanger 16002b829f9SMaxime Roussin-Belanger static const struct iio_info ltc2632_info = { 16102b829f9SMaxime Roussin-Belanger .write_raw = ltc2632_write_raw, 16202b829f9SMaxime Roussin-Belanger .read_raw = ltc2632_read_raw, 16302b829f9SMaxime Roussin-Belanger }; 16402b829f9SMaxime Roussin-Belanger 16502b829f9SMaxime Roussin-Belanger static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = { 16602b829f9SMaxime Roussin-Belanger { 16702b829f9SMaxime Roussin-Belanger .name = "powerdown", 16802b829f9SMaxime Roussin-Belanger .read = ltc2632_read_dac_powerdown, 16902b829f9SMaxime Roussin-Belanger .write = ltc2632_write_dac_powerdown, 17002b829f9SMaxime Roussin-Belanger .shared = IIO_SEPARATE, 17102b829f9SMaxime Roussin-Belanger }, 17202b829f9SMaxime Roussin-Belanger { }, 17302b829f9SMaxime Roussin-Belanger }; 17402b829f9SMaxime Roussin-Belanger 17502b829f9SMaxime Roussin-Belanger #define LTC2632_CHANNEL(_chan, _bits) { \ 17602b829f9SMaxime Roussin-Belanger .type = IIO_VOLTAGE, \ 17702b829f9SMaxime Roussin-Belanger .indexed = 1, \ 17802b829f9SMaxime Roussin-Belanger .output = 1, \ 17902b829f9SMaxime Roussin-Belanger .channel = (_chan), \ 18002b829f9SMaxime Roussin-Belanger .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 18102b829f9SMaxime Roussin-Belanger .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 18202b829f9SMaxime Roussin-Belanger .address = (_chan), \ 18302b829f9SMaxime Roussin-Belanger .scan_type = { \ 18402b829f9SMaxime Roussin-Belanger .realbits = (_bits), \ 18502b829f9SMaxime Roussin-Belanger .shift = 16 - (_bits), \ 18602b829f9SMaxime Roussin-Belanger }, \ 18702b829f9SMaxime Roussin-Belanger .ext_info = ltc2632_ext_info, \ 18802b829f9SMaxime Roussin-Belanger } 18902b829f9SMaxime Roussin-Belanger 19002b829f9SMaxime Roussin-Belanger #define DECLARE_LTC2632_CHANNELS(_name, _bits) \ 19102b829f9SMaxime Roussin-Belanger const struct iio_chan_spec _name ## _channels[] = { \ 19202b829f9SMaxime Roussin-Belanger LTC2632_CHANNEL(0, _bits), \ 19302b829f9SMaxime Roussin-Belanger LTC2632_CHANNEL(1, _bits), \ 19402b829f9SMaxime Roussin-Belanger } 19502b829f9SMaxime Roussin-Belanger 19602b829f9SMaxime Roussin-Belanger static DECLARE_LTC2632_CHANNELS(ltc2632l12, 12); 19702b829f9SMaxime Roussin-Belanger static DECLARE_LTC2632_CHANNELS(ltc2632l10, 10); 19802b829f9SMaxime Roussin-Belanger static DECLARE_LTC2632_CHANNELS(ltc2632l8, 8); 19902b829f9SMaxime Roussin-Belanger 20002b829f9SMaxime Roussin-Belanger static DECLARE_LTC2632_CHANNELS(ltc2632h12, 12); 20102b829f9SMaxime Roussin-Belanger static DECLARE_LTC2632_CHANNELS(ltc2632h10, 10); 20202b829f9SMaxime Roussin-Belanger static DECLARE_LTC2632_CHANNELS(ltc2632h8, 8); 20302b829f9SMaxime Roussin-Belanger 20402b829f9SMaxime Roussin-Belanger static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = { 20502b829f9SMaxime Roussin-Belanger [ID_LTC2632L12] = { 20602b829f9SMaxime Roussin-Belanger .channels = ltc2632l12_channels, 20702b829f9SMaxime Roussin-Belanger .vref_mv = 2500, 20802b829f9SMaxime Roussin-Belanger }, 20902b829f9SMaxime Roussin-Belanger [ID_LTC2632L10] = { 21002b829f9SMaxime Roussin-Belanger .channels = ltc2632l10_channels, 21102b829f9SMaxime Roussin-Belanger .vref_mv = 2500, 21202b829f9SMaxime Roussin-Belanger }, 21302b829f9SMaxime Roussin-Belanger [ID_LTC2632L8] = { 21402b829f9SMaxime Roussin-Belanger .channels = ltc2632l8_channels, 21502b829f9SMaxime Roussin-Belanger .vref_mv = 2500, 21602b829f9SMaxime Roussin-Belanger }, 21702b829f9SMaxime Roussin-Belanger [ID_LTC2632H12] = { 21802b829f9SMaxime Roussin-Belanger .channels = ltc2632h12_channels, 21902b829f9SMaxime Roussin-Belanger .vref_mv = 4096, 22002b829f9SMaxime Roussin-Belanger }, 22102b829f9SMaxime Roussin-Belanger [ID_LTC2632H10] = { 22202b829f9SMaxime Roussin-Belanger .channels = ltc2632h10_channels, 22302b829f9SMaxime Roussin-Belanger .vref_mv = 4096, 22402b829f9SMaxime Roussin-Belanger }, 22502b829f9SMaxime Roussin-Belanger [ID_LTC2632H8] = { 22602b829f9SMaxime Roussin-Belanger .channels = ltc2632h8_channels, 22702b829f9SMaxime Roussin-Belanger .vref_mv = 4096, 22802b829f9SMaxime Roussin-Belanger }, 22902b829f9SMaxime Roussin-Belanger }; 23002b829f9SMaxime Roussin-Belanger 23102b829f9SMaxime Roussin-Belanger static int ltc2632_probe(struct spi_device *spi) 23202b829f9SMaxime Roussin-Belanger { 23302b829f9SMaxime Roussin-Belanger struct ltc2632_state *st; 23402b829f9SMaxime Roussin-Belanger struct iio_dev *indio_dev; 23502b829f9SMaxime Roussin-Belanger struct ltc2632_chip_info *chip_info; 23602b829f9SMaxime Roussin-Belanger int ret; 23702b829f9SMaxime Roussin-Belanger 23802b829f9SMaxime Roussin-Belanger indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 23902b829f9SMaxime Roussin-Belanger if (!indio_dev) 24002b829f9SMaxime Roussin-Belanger return -ENOMEM; 24102b829f9SMaxime Roussin-Belanger 24202b829f9SMaxime Roussin-Belanger st = iio_priv(indio_dev); 24302b829f9SMaxime Roussin-Belanger 24402b829f9SMaxime Roussin-Belanger spi_set_drvdata(spi, indio_dev); 24502b829f9SMaxime Roussin-Belanger st->spi_dev = spi; 24602b829f9SMaxime Roussin-Belanger 24702b829f9SMaxime Roussin-Belanger chip_info = (struct ltc2632_chip_info *) 24802b829f9SMaxime Roussin-Belanger spi_get_device_id(spi)->driver_data; 24902b829f9SMaxime Roussin-Belanger 2509ff1d500SSilvan Murer st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref"); 2519ff1d500SSilvan Murer if (PTR_ERR(st->vref_reg) == -ENODEV) { 2529ff1d500SSilvan Murer /* use internal reference voltage */ 2539ff1d500SSilvan Murer st->vref_reg = NULL; 2549ff1d500SSilvan Murer st->vref_mv = chip_info->vref_mv; 2559ff1d500SSilvan Murer 2569ff1d500SSilvan Murer ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER, 2579ff1d500SSilvan Murer 0, 0, 0); 2589ff1d500SSilvan Murer if (ret) { 2599ff1d500SSilvan Murer dev_err(&spi->dev, 2609ff1d500SSilvan Murer "Set internal reference command failed, %d\n", 2619ff1d500SSilvan Murer ret); 2629ff1d500SSilvan Murer return ret; 2639ff1d500SSilvan Murer } 2649ff1d500SSilvan Murer } else if (IS_ERR(st->vref_reg)) { 2659ff1d500SSilvan Murer dev_err(&spi->dev, 2669ff1d500SSilvan Murer "Error getting voltage reference regulator\n"); 2679ff1d500SSilvan Murer return PTR_ERR(st->vref_reg); 2689ff1d500SSilvan Murer } else { 2699ff1d500SSilvan Murer /* use external reference voltage */ 2709ff1d500SSilvan Murer ret = regulator_enable(st->vref_reg); 2719ff1d500SSilvan Murer if (ret) { 2729ff1d500SSilvan Murer dev_err(&spi->dev, 2739ff1d500SSilvan Murer "enable reference regulator failed, %d\n", 2749ff1d500SSilvan Murer ret); 2759ff1d500SSilvan Murer return ret; 2769ff1d500SSilvan Murer } 2779ff1d500SSilvan Murer st->vref_mv = regulator_get_voltage(st->vref_reg) / 1000; 2789ff1d500SSilvan Murer 2799ff1d500SSilvan Murer ret = ltc2632_spi_write(spi, LTC2632_CMD_EXTERNAL_REFER, 2809ff1d500SSilvan Murer 0, 0, 0); 2819ff1d500SSilvan Murer if (ret) { 2829ff1d500SSilvan Murer dev_err(&spi->dev, 2839ff1d500SSilvan Murer "Set external reference command failed, %d\n", 2849ff1d500SSilvan Murer ret); 2859ff1d500SSilvan Murer return ret; 2869ff1d500SSilvan Murer } 2879ff1d500SSilvan Murer } 2889ff1d500SSilvan Murer 28902b829f9SMaxime Roussin-Belanger indio_dev->dev.parent = &spi->dev; 29002b829f9SMaxime Roussin-Belanger indio_dev->name = dev_of_node(&spi->dev) ? dev_of_node(&spi->dev)->name 29102b829f9SMaxime Roussin-Belanger : spi_get_device_id(spi)->name; 29202b829f9SMaxime Roussin-Belanger indio_dev->info = <c2632_info; 29302b829f9SMaxime Roussin-Belanger indio_dev->modes = INDIO_DIRECT_MODE; 29402b829f9SMaxime Roussin-Belanger indio_dev->channels = chip_info->channels; 29502b829f9SMaxime Roussin-Belanger indio_dev->num_channels = LTC2632_DAC_CHANNELS; 29602b829f9SMaxime Roussin-Belanger 2979ff1d500SSilvan Murer return iio_device_register(indio_dev); 29802b829f9SMaxime Roussin-Belanger } 29902b829f9SMaxime Roussin-Belanger 3009ff1d500SSilvan Murer static int ltc2632_remove(struct spi_device *spi) 3019ff1d500SSilvan Murer { 3029ff1d500SSilvan Murer struct iio_dev *indio_dev = spi_get_drvdata(spi); 3039ff1d500SSilvan Murer struct ltc2632_state *st = iio_priv(indio_dev); 3049ff1d500SSilvan Murer 3059ff1d500SSilvan Murer iio_device_unregister(indio_dev); 3069ff1d500SSilvan Murer 3079ff1d500SSilvan Murer if (st->vref_reg) 3089ff1d500SSilvan Murer regulator_disable(st->vref_reg); 3099ff1d500SSilvan Murer 3109ff1d500SSilvan Murer return 0; 31102b829f9SMaxime Roussin-Belanger } 31202b829f9SMaxime Roussin-Belanger 31302b829f9SMaxime Roussin-Belanger static const struct spi_device_id ltc2632_id[] = { 31402b829f9SMaxime Roussin-Belanger { "ltc2632-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L12] }, 31502b829f9SMaxime Roussin-Belanger { "ltc2632-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L10] }, 31602b829f9SMaxime Roussin-Belanger { "ltc2632-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L8] }, 31702b829f9SMaxime Roussin-Belanger { "ltc2632-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H12] }, 31802b829f9SMaxime Roussin-Belanger { "ltc2632-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H10] }, 31902b829f9SMaxime Roussin-Belanger { "ltc2632-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H8] }, 32002b829f9SMaxime Roussin-Belanger {} 32102b829f9SMaxime Roussin-Belanger }; 32202b829f9SMaxime Roussin-Belanger MODULE_DEVICE_TABLE(spi, ltc2632_id); 32302b829f9SMaxime Roussin-Belanger 32402b829f9SMaxime Roussin-Belanger static const struct of_device_id ltc2632_of_match[] = { 32502b829f9SMaxime Roussin-Belanger { 32602b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-l12", 32702b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632L12] 32802b829f9SMaxime Roussin-Belanger }, { 32902b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-l10", 33002b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632L10] 33102b829f9SMaxime Roussin-Belanger }, { 33202b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-l8", 33302b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632L8] 33402b829f9SMaxime Roussin-Belanger }, { 33502b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-h12", 33602b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632H12] 33702b829f9SMaxime Roussin-Belanger }, { 33802b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-h10", 33902b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632H10] 34002b829f9SMaxime Roussin-Belanger }, { 34102b829f9SMaxime Roussin-Belanger .compatible = "lltc,ltc2632-h8", 34202b829f9SMaxime Roussin-Belanger .data = <c2632_chip_info_tbl[ID_LTC2632H8] 34302b829f9SMaxime Roussin-Belanger }, 34402b829f9SMaxime Roussin-Belanger {} 34502b829f9SMaxime Roussin-Belanger }; 34602b829f9SMaxime Roussin-Belanger MODULE_DEVICE_TABLE(of, ltc2632_of_match); 34702b829f9SMaxime Roussin-Belanger 3480f6a2165SSilvan Murer static struct spi_driver ltc2632_driver = { 3490f6a2165SSilvan Murer .driver = { 3500f6a2165SSilvan Murer .name = "ltc2632", 3510f6a2165SSilvan Murer .of_match_table = of_match_ptr(ltc2632_of_match), 3520f6a2165SSilvan Murer }, 3530f6a2165SSilvan Murer .probe = ltc2632_probe, 3549ff1d500SSilvan Murer .remove = ltc2632_remove, 3550f6a2165SSilvan Murer .id_table = ltc2632_id, 3560f6a2165SSilvan Murer }; 3570f6a2165SSilvan Murer module_spi_driver(ltc2632_driver); 3580f6a2165SSilvan Murer 35902b829f9SMaxime Roussin-Belanger MODULE_AUTHOR("Maxime Roussin-Belanger <maxime.roussinbelanger@gmail.com>"); 36002b829f9SMaxime Roussin-Belanger MODULE_DESCRIPTION("LTC2632 DAC SPI driver"); 36102b829f9SMaxime Roussin-Belanger MODULE_LICENSE("GPL v2"); 362