ltc2632.c (12724B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * LTC2632 Digital to analog convertors spi driver 4 * 5 * Copyright 2017 Maxime Roussin-BĂ©langer 6 * expanded by Silvan Murer <silvan.murer@gmail.com> 7 */ 8 9#include <linux/device.h> 10#include <linux/spi/spi.h> 11#include <linux/module.h> 12#include <linux/iio/iio.h> 13#include <linux/property.h> 14#include <linux/regulator/consumer.h> 15 16#include <asm/unaligned.h> 17 18#define LTC2632_CMD_WRITE_INPUT_N 0x0 19#define LTC2632_CMD_UPDATE_DAC_N 0x1 20#define LTC2632_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 21#define LTC2632_CMD_WRITE_INPUT_N_UPDATE_N 0x3 22#define LTC2632_CMD_POWERDOWN_DAC_N 0x4 23#define LTC2632_CMD_POWERDOWN_CHIP 0x5 24#define LTC2632_CMD_INTERNAL_REFER 0x6 25#define LTC2632_CMD_EXTERNAL_REFER 0x7 26 27/** 28 * struct ltc2632_chip_info - chip specific information 29 * @channels: channel spec for the DAC 30 * @num_channels: DAC channel count of the chip 31 * @vref_mv: internal reference voltage 32 */ 33struct ltc2632_chip_info { 34 const struct iio_chan_spec *channels; 35 const size_t num_channels; 36 const int vref_mv; 37}; 38 39/** 40 * struct ltc2632_state - driver instance specific data 41 * @spi_dev: pointer to the spi_device struct 42 * @powerdown_cache_mask: used to show current channel powerdown state 43 * @vref_mv: used reference voltage (internal or external) 44 * @vref_reg: regulator for the reference voltage 45 */ 46struct ltc2632_state { 47 struct spi_device *spi_dev; 48 unsigned int powerdown_cache_mask; 49 int vref_mv; 50 struct regulator *vref_reg; 51}; 52 53enum ltc2632_supported_device_ids { 54 ID_LTC2632L12, 55 ID_LTC2632L10, 56 ID_LTC2632L8, 57 ID_LTC2632H12, 58 ID_LTC2632H10, 59 ID_LTC2632H8, 60 ID_LTC2634L12, 61 ID_LTC2634L10, 62 ID_LTC2634L8, 63 ID_LTC2634H12, 64 ID_LTC2634H10, 65 ID_LTC2634H8, 66 ID_LTC2636L12, 67 ID_LTC2636L10, 68 ID_LTC2636L8, 69 ID_LTC2636H12, 70 ID_LTC2636H10, 71 ID_LTC2636H8, 72}; 73 74static int ltc2632_spi_write(struct spi_device *spi, 75 u8 cmd, u8 addr, u16 val, u8 shift) 76{ 77 u32 data; 78 u8 msg[3]; 79 80 /* 81 * The input shift register is 24 bits wide. 82 * The next four are the command bits, C3 to C0, 83 * followed by the 4-bit DAC address, A3 to A0, and then the 84 * 12-, 10-, 8-bit data-word. The data-word comprises the 12-, 85 * 10-, 8-bit input code followed by 4, 6, or 8 don't care bits. 86 */ 87 data = (cmd << 20) | (addr << 16) | (val << shift); 88 put_unaligned_be24(data, &msg[0]); 89 90 return spi_write(spi, msg, sizeof(msg)); 91} 92 93static int ltc2632_read_raw(struct iio_dev *indio_dev, 94 struct iio_chan_spec const *chan, 95 int *val, 96 int *val2, 97 long m) 98{ 99 const struct ltc2632_state *st = iio_priv(indio_dev); 100 101 switch (m) { 102 case IIO_CHAN_INFO_SCALE: 103 *val = st->vref_mv; 104 *val2 = chan->scan_type.realbits; 105 return IIO_VAL_FRACTIONAL_LOG2; 106 } 107 return -EINVAL; 108} 109 110static int ltc2632_write_raw(struct iio_dev *indio_dev, 111 struct iio_chan_spec const *chan, 112 int val, 113 int val2, 114 long mask) 115{ 116 struct ltc2632_state *st = iio_priv(indio_dev); 117 118 switch (mask) { 119 case IIO_CHAN_INFO_RAW: 120 if (val >= (1 << chan->scan_type.realbits) || val < 0) 121 return -EINVAL; 122 123 return ltc2632_spi_write(st->spi_dev, 124 LTC2632_CMD_WRITE_INPUT_N_UPDATE_N, 125 chan->address, val, 126 chan->scan_type.shift); 127 default: 128 return -EINVAL; 129 } 130} 131 132static ssize_t ltc2632_read_dac_powerdown(struct iio_dev *indio_dev, 133 uintptr_t private, 134 const struct iio_chan_spec *chan, 135 char *buf) 136{ 137 struct ltc2632_state *st = iio_priv(indio_dev); 138 139 return sysfs_emit(buf, "%d\n", 140 !!(st->powerdown_cache_mask & (1 << chan->channel))); 141} 142 143static ssize_t ltc2632_write_dac_powerdown(struct iio_dev *indio_dev, 144 uintptr_t private, 145 const struct iio_chan_spec *chan, 146 const char *buf, 147 size_t len) 148{ 149 bool pwr_down; 150 int ret; 151 struct ltc2632_state *st = iio_priv(indio_dev); 152 153 ret = kstrtobool(buf, &pwr_down); 154 if (ret) 155 return ret; 156 157 if (pwr_down) 158 st->powerdown_cache_mask |= (1 << chan->channel); 159 else 160 st->powerdown_cache_mask &= ~(1 << chan->channel); 161 162 ret = ltc2632_spi_write(st->spi_dev, 163 LTC2632_CMD_POWERDOWN_DAC_N, 164 chan->channel, 0, 0); 165 166 return ret ? ret : len; 167} 168 169static const struct iio_info ltc2632_info = { 170 .write_raw = ltc2632_write_raw, 171 .read_raw = ltc2632_read_raw, 172}; 173 174static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = { 175 { 176 .name = "powerdown", 177 .read = ltc2632_read_dac_powerdown, 178 .write = ltc2632_write_dac_powerdown, 179 .shared = IIO_SEPARATE, 180 }, 181 { }, 182}; 183 184#define LTC2632_CHANNEL(_chan, _bits) { \ 185 .type = IIO_VOLTAGE, \ 186 .indexed = 1, \ 187 .output = 1, \ 188 .channel = (_chan), \ 189 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 190 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 191 .address = (_chan), \ 192 .scan_type = { \ 193 .realbits = (_bits), \ 194 .shift = 16 - (_bits), \ 195 }, \ 196 .ext_info = ltc2632_ext_info, \ 197} 198 199#define DECLARE_LTC2632_CHANNELS(_name, _bits) \ 200 const struct iio_chan_spec _name ## _channels[] = { \ 201 LTC2632_CHANNEL(0, _bits), \ 202 LTC2632_CHANNEL(1, _bits), \ 203 LTC2632_CHANNEL(2, _bits), \ 204 LTC2632_CHANNEL(3, _bits), \ 205 LTC2632_CHANNEL(4, _bits), \ 206 LTC2632_CHANNEL(5, _bits), \ 207 LTC2632_CHANNEL(6, _bits), \ 208 LTC2632_CHANNEL(7, _bits), \ 209 } 210 211static DECLARE_LTC2632_CHANNELS(ltc2632x12, 12); 212static DECLARE_LTC2632_CHANNELS(ltc2632x10, 10); 213static DECLARE_LTC2632_CHANNELS(ltc2632x8, 8); 214 215static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = { 216 [ID_LTC2632L12] = { 217 .channels = ltc2632x12_channels, 218 .num_channels = 2, 219 .vref_mv = 2500, 220 }, 221 [ID_LTC2632L10] = { 222 .channels = ltc2632x10_channels, 223 .num_channels = 2, 224 .vref_mv = 2500, 225 }, 226 [ID_LTC2632L8] = { 227 .channels = ltc2632x8_channels, 228 .num_channels = 2, 229 .vref_mv = 2500, 230 }, 231 [ID_LTC2632H12] = { 232 .channels = ltc2632x12_channels, 233 .num_channels = 2, 234 .vref_mv = 4096, 235 }, 236 [ID_LTC2632H10] = { 237 .channels = ltc2632x10_channels, 238 .num_channels = 2, 239 .vref_mv = 4096, 240 }, 241 [ID_LTC2632H8] = { 242 .channels = ltc2632x8_channels, 243 .num_channels = 2, 244 .vref_mv = 4096, 245 }, 246 [ID_LTC2634L12] = { 247 .channels = ltc2632x12_channels, 248 .num_channels = 4, 249 .vref_mv = 2500, 250 }, 251 [ID_LTC2634L10] = { 252 .channels = ltc2632x10_channels, 253 .num_channels = 4, 254 .vref_mv = 2500, 255 }, 256 [ID_LTC2634L8] = { 257 .channels = ltc2632x8_channels, 258 .num_channels = 4, 259 .vref_mv = 2500, 260 }, 261 [ID_LTC2634H12] = { 262 .channels = ltc2632x12_channels, 263 .num_channels = 4, 264 .vref_mv = 4096, 265 }, 266 [ID_LTC2634H10] = { 267 .channels = ltc2632x10_channels, 268 .num_channels = 4, 269 .vref_mv = 4096, 270 }, 271 [ID_LTC2634H8] = { 272 .channels = ltc2632x8_channels, 273 .num_channels = 4, 274 .vref_mv = 4096, 275 }, 276 [ID_LTC2636L12] = { 277 .channels = ltc2632x12_channels, 278 .num_channels = 8, 279 .vref_mv = 2500, 280 }, 281 [ID_LTC2636L10] = { 282 .channels = ltc2632x10_channels, 283 .num_channels = 8, 284 .vref_mv = 2500, 285 }, 286 [ID_LTC2636L8] = { 287 .channels = ltc2632x8_channels, 288 .num_channels = 8, 289 .vref_mv = 2500, 290 }, 291 [ID_LTC2636H12] = { 292 .channels = ltc2632x12_channels, 293 .num_channels = 8, 294 .vref_mv = 4096, 295 }, 296 [ID_LTC2636H10] = { 297 .channels = ltc2632x10_channels, 298 .num_channels = 8, 299 .vref_mv = 4096, 300 }, 301 [ID_LTC2636H8] = { 302 .channels = ltc2632x8_channels, 303 .num_channels = 8, 304 .vref_mv = 4096, 305 }, 306}; 307 308static int ltc2632_probe(struct spi_device *spi) 309{ 310 struct ltc2632_state *st; 311 struct iio_dev *indio_dev; 312 struct ltc2632_chip_info *chip_info; 313 int ret; 314 315 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 316 if (!indio_dev) 317 return -ENOMEM; 318 319 st = iio_priv(indio_dev); 320 321 spi_set_drvdata(spi, indio_dev); 322 st->spi_dev = spi; 323 324 chip_info = (struct ltc2632_chip_info *) 325 spi_get_device_id(spi)->driver_data; 326 327 st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref"); 328 if (PTR_ERR(st->vref_reg) == -ENODEV) { 329 /* use internal reference voltage */ 330 st->vref_reg = NULL; 331 st->vref_mv = chip_info->vref_mv; 332 333 ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER, 334 0, 0, 0); 335 if (ret) { 336 dev_err(&spi->dev, 337 "Set internal reference command failed, %d\n", 338 ret); 339 return ret; 340 } 341 } else if (IS_ERR(st->vref_reg)) { 342 dev_err(&spi->dev, 343 "Error getting voltage reference regulator\n"); 344 return PTR_ERR(st->vref_reg); 345 } else { 346 /* use external reference voltage */ 347 ret = regulator_enable(st->vref_reg); 348 if (ret) { 349 dev_err(&spi->dev, 350 "enable reference regulator failed, %d\n", 351 ret); 352 return ret; 353 } 354 st->vref_mv = regulator_get_voltage(st->vref_reg) / 1000; 355 356 ret = ltc2632_spi_write(spi, LTC2632_CMD_EXTERNAL_REFER, 357 0, 0, 0); 358 if (ret) { 359 dev_err(&spi->dev, 360 "Set external reference command failed, %d\n", 361 ret); 362 return ret; 363 } 364 } 365 366 indio_dev->name = fwnode_get_name(dev_fwnode(&spi->dev)) ?: spi_get_device_id(spi)->name; 367 indio_dev->info = <c2632_info; 368 indio_dev->modes = INDIO_DIRECT_MODE; 369 indio_dev->channels = chip_info->channels; 370 indio_dev->num_channels = chip_info->num_channels; 371 372 return iio_device_register(indio_dev); 373} 374 375static void ltc2632_remove(struct spi_device *spi) 376{ 377 struct iio_dev *indio_dev = spi_get_drvdata(spi); 378 struct ltc2632_state *st = iio_priv(indio_dev); 379 380 iio_device_unregister(indio_dev); 381 382 if (st->vref_reg) 383 regulator_disable(st->vref_reg); 384} 385 386static const struct spi_device_id ltc2632_id[] = { 387 { "ltc2632-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L12] }, 388 { "ltc2632-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L10] }, 389 { "ltc2632-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L8] }, 390 { "ltc2632-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H12] }, 391 { "ltc2632-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H10] }, 392 { "ltc2632-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H8] }, 393 { "ltc2634-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L12] }, 394 { "ltc2634-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L10] }, 395 { "ltc2634-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L8] }, 396 { "ltc2634-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H12] }, 397 { "ltc2634-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H10] }, 398 { "ltc2634-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H8] }, 399 { "ltc2636-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L12] }, 400 { "ltc2636-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L10] }, 401 { "ltc2636-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L8] }, 402 { "ltc2636-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H12] }, 403 { "ltc2636-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H10] }, 404 { "ltc2636-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H8] }, 405 {} 406}; 407MODULE_DEVICE_TABLE(spi, ltc2632_id); 408 409static const struct of_device_id ltc2632_of_match[] = { 410 { 411 .compatible = "lltc,ltc2632-l12", 412 .data = <c2632_chip_info_tbl[ID_LTC2632L12] 413 }, { 414 .compatible = "lltc,ltc2632-l10", 415 .data = <c2632_chip_info_tbl[ID_LTC2632L10] 416 }, { 417 .compatible = "lltc,ltc2632-l8", 418 .data = <c2632_chip_info_tbl[ID_LTC2632L8] 419 }, { 420 .compatible = "lltc,ltc2632-h12", 421 .data = <c2632_chip_info_tbl[ID_LTC2632H12] 422 }, { 423 .compatible = "lltc,ltc2632-h10", 424 .data = <c2632_chip_info_tbl[ID_LTC2632H10] 425 }, { 426 .compatible = "lltc,ltc2632-h8", 427 .data = <c2632_chip_info_tbl[ID_LTC2632H8] 428 }, { 429 .compatible = "lltc,ltc2634-l12", 430 .data = <c2632_chip_info_tbl[ID_LTC2634L12] 431 }, { 432 .compatible = "lltc,ltc2634-l10", 433 .data = <c2632_chip_info_tbl[ID_LTC2634L10] 434 }, { 435 .compatible = "lltc,ltc2634-l8", 436 .data = <c2632_chip_info_tbl[ID_LTC2634L8] 437 }, { 438 .compatible = "lltc,ltc2634-h12", 439 .data = <c2632_chip_info_tbl[ID_LTC2634H12] 440 }, { 441 .compatible = "lltc,ltc2634-h10", 442 .data = <c2632_chip_info_tbl[ID_LTC2634H10] 443 }, { 444 .compatible = "lltc,ltc2634-h8", 445 .data = <c2632_chip_info_tbl[ID_LTC2634H8] 446 }, { 447 .compatible = "lltc,ltc2636-l12", 448 .data = <c2632_chip_info_tbl[ID_LTC2636L12] 449 }, { 450 .compatible = "lltc,ltc2636-l10", 451 .data = <c2632_chip_info_tbl[ID_LTC2636L10] 452 }, { 453 .compatible = "lltc,ltc2636-l8", 454 .data = <c2632_chip_info_tbl[ID_LTC2636L8] 455 }, { 456 .compatible = "lltc,ltc2636-h12", 457 .data = <c2632_chip_info_tbl[ID_LTC2636H12] 458 }, { 459 .compatible = "lltc,ltc2636-h10", 460 .data = <c2632_chip_info_tbl[ID_LTC2636H10] 461 }, { 462 .compatible = "lltc,ltc2636-h8", 463 .data = <c2632_chip_info_tbl[ID_LTC2636H8] 464 }, 465 {} 466}; 467MODULE_DEVICE_TABLE(of, ltc2632_of_match); 468 469static struct spi_driver ltc2632_driver = { 470 .driver = { 471 .name = "ltc2632", 472 .of_match_table = ltc2632_of_match, 473 }, 474 .probe = ltc2632_probe, 475 .remove = ltc2632_remove, 476 .id_table = ltc2632_id, 477}; 478module_spi_driver(ltc2632_driver); 479 480MODULE_AUTHOR("Maxime Roussin-Belanger <maxime.roussinbelanger@gmail.com>"); 481MODULE_DESCRIPTION("LTC2632 DAC SPI driver"); 482MODULE_LICENSE("GPL v2");