0001
0002
0003
0004
0005
0006
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
0029
0030
0031
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
0041
0042
0043
0044
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
0082
0083
0084
0085
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
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
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 = <c2632_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)<c2632_chip_info_tbl[ID_LTC2632L12] },
0388 { "ltc2632-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L10] },
0389 { "ltc2632-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L8] },
0390 { "ltc2632-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H12] },
0391 { "ltc2632-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H10] },
0392 { "ltc2632-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H8] },
0393 { "ltc2634-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L12] },
0394 { "ltc2634-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L10] },
0395 { "ltc2634-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L8] },
0396 { "ltc2634-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H12] },
0397 { "ltc2634-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H10] },
0398 { "ltc2634-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H8] },
0399 { "ltc2636-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L12] },
0400 { "ltc2636-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L10] },
0401 { "ltc2636-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L8] },
0402 { "ltc2636-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H12] },
0403 { "ltc2636-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H10] },
0404 { "ltc2636-h8", (kernel_ulong_t)<c2632_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 = <c2632_chip_info_tbl[ID_LTC2632L12]
0413 }, {
0414 .compatible = "lltc,ltc2632-l10",
0415 .data = <c2632_chip_info_tbl[ID_LTC2632L10]
0416 }, {
0417 .compatible = "lltc,ltc2632-l8",
0418 .data = <c2632_chip_info_tbl[ID_LTC2632L8]
0419 }, {
0420 .compatible = "lltc,ltc2632-h12",
0421 .data = <c2632_chip_info_tbl[ID_LTC2632H12]
0422 }, {
0423 .compatible = "lltc,ltc2632-h10",
0424 .data = <c2632_chip_info_tbl[ID_LTC2632H10]
0425 }, {
0426 .compatible = "lltc,ltc2632-h8",
0427 .data = <c2632_chip_info_tbl[ID_LTC2632H8]
0428 }, {
0429 .compatible = "lltc,ltc2634-l12",
0430 .data = <c2632_chip_info_tbl[ID_LTC2634L12]
0431 }, {
0432 .compatible = "lltc,ltc2634-l10",
0433 .data = <c2632_chip_info_tbl[ID_LTC2634L10]
0434 }, {
0435 .compatible = "lltc,ltc2634-l8",
0436 .data = <c2632_chip_info_tbl[ID_LTC2634L8]
0437 }, {
0438 .compatible = "lltc,ltc2634-h12",
0439 .data = <c2632_chip_info_tbl[ID_LTC2634H12]
0440 }, {
0441 .compatible = "lltc,ltc2634-h10",
0442 .data = <c2632_chip_info_tbl[ID_LTC2634H10]
0443 }, {
0444 .compatible = "lltc,ltc2634-h8",
0445 .data = <c2632_chip_info_tbl[ID_LTC2634H8]
0446 }, {
0447 .compatible = "lltc,ltc2636-l12",
0448 .data = <c2632_chip_info_tbl[ID_LTC2636L12]
0449 }, {
0450 .compatible = "lltc,ltc2636-l10",
0451 .data = <c2632_chip_info_tbl[ID_LTC2636L10]
0452 }, {
0453 .compatible = "lltc,ltc2636-l8",
0454 .data = <c2632_chip_info_tbl[ID_LTC2636L8]
0455 }, {
0456 .compatible = "lltc,ltc2636-h12",
0457 .data = <c2632_chip_info_tbl[ID_LTC2636H12]
0458 }, {
0459 .compatible = "lltc,ltc2636-h10",
0460 .data = <c2632_chip_info_tbl[ID_LTC2636H10]
0461 }, {
0462 .compatible = "lltc,ltc2636-h8",
0463 .data = <c2632_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");