Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * LTC2632 Digital to analog convertors spi driver
0004  *
0005  * Copyright 2017 Maxime Roussin-Bélanger
0006  * expanded by Silvan Murer <silvan.murer@gmail.com>
0007  */
0008 
0009 #include <linux/device.h>
0010 #include <linux/spi/spi.h>
0011 #include <linux/module.h>
0012 #include <linux/iio/iio.h>
0013 #include <linux/property.h>
0014 #include <linux/regulator/consumer.h>
0015 
0016 #include <asm/unaligned.h>
0017 
0018 #define LTC2632_CMD_WRITE_INPUT_N               0x0
0019 #define LTC2632_CMD_UPDATE_DAC_N                0x1
0020 #define LTC2632_CMD_WRITE_INPUT_N_UPDATE_ALL    0x2
0021 #define LTC2632_CMD_WRITE_INPUT_N_UPDATE_N      0x3
0022 #define LTC2632_CMD_POWERDOWN_DAC_N             0x4
0023 #define LTC2632_CMD_POWERDOWN_CHIP              0x5
0024 #define LTC2632_CMD_INTERNAL_REFER              0x6
0025 #define LTC2632_CMD_EXTERNAL_REFER              0x7
0026 
0027 /**
0028  * struct ltc2632_chip_info - chip specific information
0029  * @channels:       channel spec for the DAC
0030  * @num_channels:   DAC channel count of the chip
0031  * @vref_mv:        internal reference voltage
0032  */
0033 struct ltc2632_chip_info {
0034     const struct iio_chan_spec *channels;
0035     const size_t num_channels;
0036     const int vref_mv;
0037 };
0038 
0039 /**
0040  * struct ltc2632_state - driver instance specific data
0041  * @spi_dev:            pointer to the spi_device struct
0042  * @powerdown_cache_mask:   used to show current channel powerdown state
0043  * @vref_mv:            used reference voltage (internal or external)
0044  * @vref_reg:       regulator for the reference voltage
0045  */
0046 struct ltc2632_state {
0047     struct spi_device *spi_dev;
0048     unsigned int powerdown_cache_mask;
0049     int vref_mv;
0050     struct regulator *vref_reg;
0051 };
0052 
0053 enum ltc2632_supported_device_ids {
0054     ID_LTC2632L12,
0055     ID_LTC2632L10,
0056     ID_LTC2632L8,
0057     ID_LTC2632H12,
0058     ID_LTC2632H10,
0059     ID_LTC2632H8,
0060     ID_LTC2634L12,
0061     ID_LTC2634L10,
0062     ID_LTC2634L8,
0063     ID_LTC2634H12,
0064     ID_LTC2634H10,
0065     ID_LTC2634H8,
0066     ID_LTC2636L12,
0067     ID_LTC2636L10,
0068     ID_LTC2636L8,
0069     ID_LTC2636H12,
0070     ID_LTC2636H10,
0071     ID_LTC2636H8,
0072 };
0073 
0074 static int ltc2632_spi_write(struct spi_device *spi,
0075                  u8 cmd, u8 addr, u16 val, u8 shift)
0076 {
0077     u32 data;
0078     u8 msg[3];
0079 
0080     /*
0081      * The input shift register is 24 bits wide.
0082      * The next four are the command bits, C3 to C0,
0083      * followed by the 4-bit DAC address, A3 to A0, and then the
0084      * 12-, 10-, 8-bit data-word. The data-word comprises the 12-,
0085      * 10-, 8-bit input code followed by 4, 6, or 8 don't care bits.
0086      */
0087     data = (cmd << 20) | (addr << 16) | (val << shift);
0088     put_unaligned_be24(data, &msg[0]);
0089 
0090     return spi_write(spi, msg, sizeof(msg));
0091 }
0092 
0093 static int ltc2632_read_raw(struct iio_dev *indio_dev,
0094                 struct iio_chan_spec const *chan,
0095                 int *val,
0096                 int *val2,
0097                 long m)
0098 {
0099     const struct ltc2632_state *st = iio_priv(indio_dev);
0100 
0101     switch (m) {
0102     case IIO_CHAN_INFO_SCALE:
0103         *val = st->vref_mv;
0104         *val2 = chan->scan_type.realbits;
0105         return IIO_VAL_FRACTIONAL_LOG2;
0106     }
0107     return -EINVAL;
0108 }
0109 
0110 static int ltc2632_write_raw(struct iio_dev *indio_dev,
0111                  struct iio_chan_spec const *chan,
0112                  int val,
0113                  int val2,
0114                  long mask)
0115 {
0116     struct ltc2632_state *st = iio_priv(indio_dev);
0117 
0118     switch (mask) {
0119     case IIO_CHAN_INFO_RAW:
0120         if (val >= (1 << chan->scan_type.realbits) || val < 0)
0121             return -EINVAL;
0122 
0123         return ltc2632_spi_write(st->spi_dev,
0124                      LTC2632_CMD_WRITE_INPUT_N_UPDATE_N,
0125                      chan->address, val,
0126                      chan->scan_type.shift);
0127     default:
0128         return -EINVAL;
0129     }
0130 }
0131 
0132 static ssize_t ltc2632_read_dac_powerdown(struct iio_dev *indio_dev,
0133                       uintptr_t private,
0134                       const struct iio_chan_spec *chan,
0135                       char *buf)
0136 {
0137     struct ltc2632_state *st = iio_priv(indio_dev);
0138 
0139     return sysfs_emit(buf, "%d\n",
0140               !!(st->powerdown_cache_mask & (1 << chan->channel)));
0141 }
0142 
0143 static ssize_t ltc2632_write_dac_powerdown(struct iio_dev *indio_dev,
0144                        uintptr_t private,
0145                        const struct iio_chan_spec *chan,
0146                        const char *buf,
0147                        size_t len)
0148 {
0149     bool pwr_down;
0150     int ret;
0151     struct ltc2632_state *st = iio_priv(indio_dev);
0152 
0153     ret = kstrtobool(buf, &pwr_down);
0154     if (ret)
0155         return ret;
0156 
0157     if (pwr_down)
0158         st->powerdown_cache_mask |= (1 << chan->channel);
0159     else
0160         st->powerdown_cache_mask &= ~(1 << chan->channel);
0161 
0162     ret = ltc2632_spi_write(st->spi_dev,
0163                 LTC2632_CMD_POWERDOWN_DAC_N,
0164                 chan->channel, 0, 0);
0165 
0166     return ret ? ret : len;
0167 }
0168 
0169 static const struct iio_info ltc2632_info = {
0170     .write_raw  = ltc2632_write_raw,
0171     .read_raw   = ltc2632_read_raw,
0172 };
0173 
0174 static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = {
0175     {
0176         .name = "powerdown",
0177         .read = ltc2632_read_dac_powerdown,
0178         .write = ltc2632_write_dac_powerdown,
0179         .shared = IIO_SEPARATE,
0180     },
0181     { },
0182 };
0183 
0184 #define LTC2632_CHANNEL(_chan, _bits) { \
0185         .type = IIO_VOLTAGE, \
0186         .indexed = 1, \
0187         .output = 1, \
0188         .channel = (_chan), \
0189         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
0190         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
0191         .address = (_chan), \
0192         .scan_type = { \
0193             .realbits   = (_bits), \
0194             .shift      = 16 - (_bits), \
0195         }, \
0196         .ext_info = ltc2632_ext_info, \
0197 }
0198 
0199 #define DECLARE_LTC2632_CHANNELS(_name, _bits) \
0200     const struct iio_chan_spec _name ## _channels[] = { \
0201         LTC2632_CHANNEL(0, _bits), \
0202         LTC2632_CHANNEL(1, _bits), \
0203         LTC2632_CHANNEL(2, _bits), \
0204         LTC2632_CHANNEL(3, _bits), \
0205         LTC2632_CHANNEL(4, _bits), \
0206         LTC2632_CHANNEL(5, _bits), \
0207         LTC2632_CHANNEL(6, _bits), \
0208         LTC2632_CHANNEL(7, _bits), \
0209     }
0210 
0211 static DECLARE_LTC2632_CHANNELS(ltc2632x12, 12);
0212 static DECLARE_LTC2632_CHANNELS(ltc2632x10, 10);
0213 static DECLARE_LTC2632_CHANNELS(ltc2632x8, 8);
0214 
0215 static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = {
0216     [ID_LTC2632L12] = {
0217         .channels   = ltc2632x12_channels,
0218         .num_channels   = 2,
0219         .vref_mv    = 2500,
0220     },
0221     [ID_LTC2632L10] = {
0222         .channels   = ltc2632x10_channels,
0223         .num_channels   = 2,
0224         .vref_mv    = 2500,
0225     },
0226     [ID_LTC2632L8] =  {
0227         .channels   = ltc2632x8_channels,
0228         .num_channels   = 2,
0229         .vref_mv    = 2500,
0230     },
0231     [ID_LTC2632H12] = {
0232         .channels   = ltc2632x12_channels,
0233         .num_channels   = 2,
0234         .vref_mv    = 4096,
0235     },
0236     [ID_LTC2632H10] = {
0237         .channels   = ltc2632x10_channels,
0238         .num_channels   = 2,
0239         .vref_mv    = 4096,
0240     },
0241     [ID_LTC2632H8] =  {
0242         .channels   = ltc2632x8_channels,
0243         .num_channels   = 2,
0244         .vref_mv    = 4096,
0245     },
0246     [ID_LTC2634L12] = {
0247         .channels   = ltc2632x12_channels,
0248         .num_channels   = 4,
0249         .vref_mv    = 2500,
0250     },
0251     [ID_LTC2634L10] = {
0252         .channels   = ltc2632x10_channels,
0253         .num_channels   = 4,
0254         .vref_mv    = 2500,
0255     },
0256     [ID_LTC2634L8] =  {
0257         .channels   = ltc2632x8_channels,
0258         .num_channels   = 4,
0259         .vref_mv    = 2500,
0260     },
0261     [ID_LTC2634H12] = {
0262         .channels   = ltc2632x12_channels,
0263         .num_channels   = 4,
0264         .vref_mv    = 4096,
0265     },
0266     [ID_LTC2634H10] = {
0267         .channels   = ltc2632x10_channels,
0268         .num_channels   = 4,
0269         .vref_mv    = 4096,
0270     },
0271     [ID_LTC2634H8] =  {
0272         .channels   = ltc2632x8_channels,
0273         .num_channels   = 4,
0274         .vref_mv    = 4096,
0275     },
0276     [ID_LTC2636L12] = {
0277         .channels   = ltc2632x12_channels,
0278         .num_channels   = 8,
0279         .vref_mv    = 2500,
0280     },
0281     [ID_LTC2636L10] = {
0282         .channels   = ltc2632x10_channels,
0283         .num_channels   = 8,
0284         .vref_mv    = 2500,
0285     },
0286     [ID_LTC2636L8] =  {
0287         .channels   = ltc2632x8_channels,
0288         .num_channels   = 8,
0289         .vref_mv    = 2500,
0290     },
0291     [ID_LTC2636H12] = {
0292         .channels   = ltc2632x12_channels,
0293         .num_channels   = 8,
0294         .vref_mv    = 4096,
0295     },
0296     [ID_LTC2636H10] = {
0297         .channels   = ltc2632x10_channels,
0298         .num_channels   = 8,
0299         .vref_mv    = 4096,
0300     },
0301     [ID_LTC2636H8] =  {
0302         .channels   = ltc2632x8_channels,
0303         .num_channels   = 8,
0304         .vref_mv    = 4096,
0305     },
0306 };
0307 
0308 static int ltc2632_probe(struct spi_device *spi)
0309 {
0310     struct ltc2632_state *st;
0311     struct iio_dev *indio_dev;
0312     struct ltc2632_chip_info *chip_info;
0313     int ret;
0314 
0315     indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
0316     if (!indio_dev)
0317         return -ENOMEM;
0318 
0319     st = iio_priv(indio_dev);
0320 
0321     spi_set_drvdata(spi, indio_dev);
0322     st->spi_dev = spi;
0323 
0324     chip_info = (struct ltc2632_chip_info *)
0325             spi_get_device_id(spi)->driver_data;
0326 
0327     st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref");
0328     if (PTR_ERR(st->vref_reg) == -ENODEV) {
0329         /* use internal reference voltage */
0330         st->vref_reg = NULL;
0331         st->vref_mv = chip_info->vref_mv;
0332 
0333         ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER,
0334                 0, 0, 0);
0335         if (ret) {
0336             dev_err(&spi->dev,
0337                 "Set internal reference command failed, %d\n",
0338                 ret);
0339             return ret;
0340         }
0341     } else if (IS_ERR(st->vref_reg)) {
0342         dev_err(&spi->dev,
0343                 "Error getting voltage reference regulator\n");
0344         return PTR_ERR(st->vref_reg);
0345     } else {
0346         /* use external reference voltage */
0347         ret = regulator_enable(st->vref_reg);
0348         if (ret) {
0349             dev_err(&spi->dev,
0350                 "enable reference regulator failed, %d\n",
0351                 ret);
0352             return ret;
0353         }
0354         st->vref_mv = regulator_get_voltage(st->vref_reg) / 1000;
0355 
0356         ret = ltc2632_spi_write(spi, LTC2632_CMD_EXTERNAL_REFER,
0357                 0, 0, 0);
0358         if (ret) {
0359             dev_err(&spi->dev,
0360                 "Set external reference command failed, %d\n",
0361                 ret);
0362             return ret;
0363         }
0364     }
0365 
0366     indio_dev->name = fwnode_get_name(dev_fwnode(&spi->dev)) ?: spi_get_device_id(spi)->name;
0367     indio_dev->info = &ltc2632_info;
0368     indio_dev->modes = INDIO_DIRECT_MODE;
0369     indio_dev->channels = chip_info->channels;
0370     indio_dev->num_channels = chip_info->num_channels;
0371 
0372     return iio_device_register(indio_dev);
0373 }
0374 
0375 static void ltc2632_remove(struct spi_device *spi)
0376 {
0377     struct iio_dev *indio_dev = spi_get_drvdata(spi);
0378     struct ltc2632_state *st = iio_priv(indio_dev);
0379 
0380     iio_device_unregister(indio_dev);
0381 
0382     if (st->vref_reg)
0383         regulator_disable(st->vref_reg);
0384 }
0385 
0386 static const struct spi_device_id ltc2632_id[] = {
0387     { "ltc2632-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L12] },
0388     { "ltc2632-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L10] },
0389     { "ltc2632-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L8] },
0390     { "ltc2632-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H12] },
0391     { "ltc2632-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H10] },
0392     { "ltc2632-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H8] },
0393     { "ltc2634-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L12] },
0394     { "ltc2634-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L10] },
0395     { "ltc2634-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L8] },
0396     { "ltc2634-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H12] },
0397     { "ltc2634-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H10] },
0398     { "ltc2634-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H8] },
0399     { "ltc2636-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L12] },
0400     { "ltc2636-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L10] },
0401     { "ltc2636-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L8] },
0402     { "ltc2636-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636H12] },
0403     { "ltc2636-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636H10] },
0404     { "ltc2636-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636H8] },
0405     {}
0406 };
0407 MODULE_DEVICE_TABLE(spi, ltc2632_id);
0408 
0409 static const struct of_device_id ltc2632_of_match[] = {
0410     {
0411         .compatible = "lltc,ltc2632-l12",
0412         .data = &ltc2632_chip_info_tbl[ID_LTC2632L12]
0413     }, {
0414         .compatible = "lltc,ltc2632-l10",
0415         .data = &ltc2632_chip_info_tbl[ID_LTC2632L10]
0416     }, {
0417         .compatible = "lltc,ltc2632-l8",
0418         .data = &ltc2632_chip_info_tbl[ID_LTC2632L8]
0419     }, {
0420         .compatible = "lltc,ltc2632-h12",
0421         .data = &ltc2632_chip_info_tbl[ID_LTC2632H12]
0422     }, {
0423         .compatible = "lltc,ltc2632-h10",
0424         .data = &ltc2632_chip_info_tbl[ID_LTC2632H10]
0425     }, {
0426         .compatible = "lltc,ltc2632-h8",
0427         .data = &ltc2632_chip_info_tbl[ID_LTC2632H8]
0428     }, {
0429         .compatible = "lltc,ltc2634-l12",
0430         .data = &ltc2632_chip_info_tbl[ID_LTC2634L12]
0431     }, {
0432         .compatible = "lltc,ltc2634-l10",
0433         .data = &ltc2632_chip_info_tbl[ID_LTC2634L10]
0434     }, {
0435         .compatible = "lltc,ltc2634-l8",
0436         .data = &ltc2632_chip_info_tbl[ID_LTC2634L8]
0437     }, {
0438         .compatible = "lltc,ltc2634-h12",
0439         .data = &ltc2632_chip_info_tbl[ID_LTC2634H12]
0440     }, {
0441         .compatible = "lltc,ltc2634-h10",
0442         .data = &ltc2632_chip_info_tbl[ID_LTC2634H10]
0443     }, {
0444         .compatible = "lltc,ltc2634-h8",
0445         .data = &ltc2632_chip_info_tbl[ID_LTC2634H8]
0446     }, {
0447         .compatible = "lltc,ltc2636-l12",
0448         .data = &ltc2632_chip_info_tbl[ID_LTC2636L12]
0449     }, {
0450         .compatible = "lltc,ltc2636-l10",
0451         .data = &ltc2632_chip_info_tbl[ID_LTC2636L10]
0452     }, {
0453         .compatible = "lltc,ltc2636-l8",
0454         .data = &ltc2632_chip_info_tbl[ID_LTC2636L8]
0455     }, {
0456         .compatible = "lltc,ltc2636-h12",
0457         .data = &ltc2632_chip_info_tbl[ID_LTC2636H12]
0458     }, {
0459         .compatible = "lltc,ltc2636-h10",
0460         .data = &ltc2632_chip_info_tbl[ID_LTC2636H10]
0461     }, {
0462         .compatible = "lltc,ltc2636-h8",
0463         .data = &ltc2632_chip_info_tbl[ID_LTC2636H8]
0464     },
0465     {}
0466 };
0467 MODULE_DEVICE_TABLE(of, ltc2632_of_match);
0468 
0469 static struct spi_driver ltc2632_driver = {
0470     .driver     = {
0471         .name   = "ltc2632",
0472         .of_match_table = ltc2632_of_match,
0473     },
0474     .probe      = ltc2632_probe,
0475     .remove     = ltc2632_remove,
0476     .id_table   = ltc2632_id,
0477 };
0478 module_spi_driver(ltc2632_driver);
0479 
0480 MODULE_AUTHOR("Maxime Roussin-Belanger <maxime.roussinbelanger@gmail.com>");
0481 MODULE_DESCRIPTION("LTC2632 DAC SPI driver");
0482 MODULE_LICENSE("GPL v2");