162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog 462306a36Sopenharmony_ci * Converter driver. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright 2012 Analog Devices Inc. 762306a36Sopenharmony_ci * Author: Lars-Peter Clausen <lars@metafoo.de> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/device.h> 1162306a36Sopenharmony_ci#include <linux/err.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/spi/spi.h> 1562306a36Sopenharmony_ci#include <linux/slab.h> 1662306a36Sopenharmony_ci#include <linux/sysfs.h> 1762306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1862306a36Sopenharmony_ci#include <asm/unaligned.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <linux/iio/iio.h> 2162306a36Sopenharmony_ci#include <linux/iio/sysfs.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include <linux/platform_data/ad5449.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define AD5449_MAX_CHANNELS 2 2662306a36Sopenharmony_ci#define AD5449_MAX_VREFS 2 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define AD5449_CMD_NOOP 0x0 2962306a36Sopenharmony_ci#define AD5449_CMD_LOAD_AND_UPDATE(x) (0x1 + (x) * 3) 3062306a36Sopenharmony_ci#define AD5449_CMD_READ(x) (0x2 + (x) * 3) 3162306a36Sopenharmony_ci#define AD5449_CMD_LOAD(x) (0x3 + (x) * 3) 3262306a36Sopenharmony_ci#define AD5449_CMD_CTRL 13 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define AD5449_CTRL_SDO_OFFSET 10 3562306a36Sopenharmony_ci#define AD5449_CTRL_DAISY_CHAIN BIT(9) 3662306a36Sopenharmony_ci#define AD5449_CTRL_HCLR_TO_MIDSCALE BIT(8) 3762306a36Sopenharmony_ci#define AD5449_CTRL_SAMPLE_RISING BIT(7) 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/** 4062306a36Sopenharmony_ci * struct ad5449_chip_info - chip specific information 4162306a36Sopenharmony_ci * @channels: Channel specification 4262306a36Sopenharmony_ci * @num_channels: Number of channels 4362306a36Sopenharmony_ci * @has_ctrl: Chip has a control register 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_cistruct ad5449_chip_info { 4662306a36Sopenharmony_ci const struct iio_chan_spec *channels; 4762306a36Sopenharmony_ci unsigned int num_channels; 4862306a36Sopenharmony_ci bool has_ctrl; 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/** 5262306a36Sopenharmony_ci * struct ad5449 - driver instance specific data 5362306a36Sopenharmony_ci * @spi: the SPI device for this driver instance 5462306a36Sopenharmony_ci * @chip_info: chip model specific constants, available modes etc 5562306a36Sopenharmony_ci * @vref_reg: vref supply regulators 5662306a36Sopenharmony_ci * @has_sdo: whether the SDO line is connected 5762306a36Sopenharmony_ci * @dac_cache: Cache for the DAC values 5862306a36Sopenharmony_ci * @data: spi transfer buffers 5962306a36Sopenharmony_ci * @lock: lock to protect the data buffer during SPI ops 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_cistruct ad5449 { 6262306a36Sopenharmony_ci struct spi_device *spi; 6362306a36Sopenharmony_ci const struct ad5449_chip_info *chip_info; 6462306a36Sopenharmony_ci struct regulator_bulk_data vref_reg[AD5449_MAX_VREFS]; 6562306a36Sopenharmony_ci struct mutex lock; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci bool has_sdo; 6862306a36Sopenharmony_ci uint16_t dac_cache[AD5449_MAX_CHANNELS]; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci /* 7162306a36Sopenharmony_ci * DMA (thus cache coherency maintenance) may require the 7262306a36Sopenharmony_ci * transfer buffers to live in their own cache lines. 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_ci __be16 data[2] __aligned(IIO_DMA_MINALIGN); 7562306a36Sopenharmony_ci}; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cienum ad5449_type { 7862306a36Sopenharmony_ci ID_AD5426, 7962306a36Sopenharmony_ci ID_AD5429, 8062306a36Sopenharmony_ci ID_AD5432, 8162306a36Sopenharmony_ci ID_AD5439, 8262306a36Sopenharmony_ci ID_AD5443, 8362306a36Sopenharmony_ci ID_AD5449, 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic int ad5449_write(struct iio_dev *indio_dev, unsigned int addr, 8762306a36Sopenharmony_ci unsigned int val) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci struct ad5449 *st = iio_priv(indio_dev); 9062306a36Sopenharmony_ci int ret; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci mutex_lock(&st->lock); 9362306a36Sopenharmony_ci st->data[0] = cpu_to_be16((addr << 12) | val); 9462306a36Sopenharmony_ci ret = spi_write(st->spi, st->data, 2); 9562306a36Sopenharmony_ci mutex_unlock(&st->lock); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci return ret; 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic int ad5449_read(struct iio_dev *indio_dev, unsigned int addr, 10162306a36Sopenharmony_ci unsigned int *val) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci struct ad5449 *st = iio_priv(indio_dev); 10462306a36Sopenharmony_ci int ret; 10562306a36Sopenharmony_ci struct spi_transfer t[] = { 10662306a36Sopenharmony_ci { 10762306a36Sopenharmony_ci .tx_buf = &st->data[0], 10862306a36Sopenharmony_ci .len = 2, 10962306a36Sopenharmony_ci .cs_change = 1, 11062306a36Sopenharmony_ci }, { 11162306a36Sopenharmony_ci .tx_buf = &st->data[1], 11262306a36Sopenharmony_ci .rx_buf = &st->data[1], 11362306a36Sopenharmony_ci .len = 2, 11462306a36Sopenharmony_ci }, 11562306a36Sopenharmony_ci }; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci mutex_lock(&st->lock); 11862306a36Sopenharmony_ci st->data[0] = cpu_to_be16(addr << 12); 11962306a36Sopenharmony_ci st->data[1] = cpu_to_be16(AD5449_CMD_NOOP); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); 12262306a36Sopenharmony_ci if (ret < 0) 12362306a36Sopenharmony_ci goto out_unlock; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci *val = be16_to_cpu(st->data[1]); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ciout_unlock: 12862306a36Sopenharmony_ci mutex_unlock(&st->lock); 12962306a36Sopenharmony_ci return ret; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic int ad5449_read_raw(struct iio_dev *indio_dev, 13362306a36Sopenharmony_ci struct iio_chan_spec const *chan, int *val, int *val2, long info) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci struct ad5449 *st = iio_priv(indio_dev); 13662306a36Sopenharmony_ci struct regulator_bulk_data *reg; 13762306a36Sopenharmony_ci int scale_uv; 13862306a36Sopenharmony_ci int ret; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci switch (info) { 14162306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 14262306a36Sopenharmony_ci if (st->has_sdo) { 14362306a36Sopenharmony_ci ret = ad5449_read(indio_dev, 14462306a36Sopenharmony_ci AD5449_CMD_READ(chan->address), val); 14562306a36Sopenharmony_ci if (ret) 14662306a36Sopenharmony_ci return ret; 14762306a36Sopenharmony_ci *val &= 0xfff; 14862306a36Sopenharmony_ci } else { 14962306a36Sopenharmony_ci *val = st->dac_cache[chan->address]; 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci return IIO_VAL_INT; 15362306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 15462306a36Sopenharmony_ci reg = &st->vref_reg[chan->channel]; 15562306a36Sopenharmony_ci scale_uv = regulator_get_voltage(reg->consumer); 15662306a36Sopenharmony_ci if (scale_uv < 0) 15762306a36Sopenharmony_ci return scale_uv; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci *val = scale_uv / 1000; 16062306a36Sopenharmony_ci *val2 = chan->scan_type.realbits; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL_LOG2; 16362306a36Sopenharmony_ci default: 16462306a36Sopenharmony_ci break; 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci return -EINVAL; 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic int ad5449_write_raw(struct iio_dev *indio_dev, 17162306a36Sopenharmony_ci struct iio_chan_spec const *chan, int val, int val2, long info) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci struct ad5449 *st = iio_priv(indio_dev); 17462306a36Sopenharmony_ci int ret; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci switch (info) { 17762306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 17862306a36Sopenharmony_ci if (val < 0 || val >= (1 << chan->scan_type.realbits)) 17962306a36Sopenharmony_ci return -EINVAL; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci ret = ad5449_write(indio_dev, 18262306a36Sopenharmony_ci AD5449_CMD_LOAD_AND_UPDATE(chan->address), 18362306a36Sopenharmony_ci val << chan->scan_type.shift); 18462306a36Sopenharmony_ci if (ret == 0) 18562306a36Sopenharmony_ci st->dac_cache[chan->address] = val; 18662306a36Sopenharmony_ci break; 18762306a36Sopenharmony_ci default: 18862306a36Sopenharmony_ci ret = -EINVAL; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return ret; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistatic const struct iio_info ad5449_info = { 19562306a36Sopenharmony_ci .read_raw = ad5449_read_raw, 19662306a36Sopenharmony_ci .write_raw = ad5449_write_raw, 19762306a36Sopenharmony_ci}; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci#define AD5449_CHANNEL(chan, bits) { \ 20062306a36Sopenharmony_ci .type = IIO_VOLTAGE, \ 20162306a36Sopenharmony_ci .indexed = 1, \ 20262306a36Sopenharmony_ci .output = 1, \ 20362306a36Sopenharmony_ci .channel = (chan), \ 20462306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 20562306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), \ 20662306a36Sopenharmony_ci .address = (chan), \ 20762306a36Sopenharmony_ci .scan_type = { \ 20862306a36Sopenharmony_ci .sign = 'u', \ 20962306a36Sopenharmony_ci .realbits = (bits), \ 21062306a36Sopenharmony_ci .storagebits = 16, \ 21162306a36Sopenharmony_ci .shift = 12 - (bits), \ 21262306a36Sopenharmony_ci }, \ 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci#define DECLARE_AD5449_CHANNELS(name, bits) \ 21662306a36Sopenharmony_ciconst struct iio_chan_spec name[] = { \ 21762306a36Sopenharmony_ci AD5449_CHANNEL(0, bits), \ 21862306a36Sopenharmony_ci AD5449_CHANNEL(1, bits), \ 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_cistatic DECLARE_AD5449_CHANNELS(ad5429_channels, 8); 22262306a36Sopenharmony_cistatic DECLARE_AD5449_CHANNELS(ad5439_channels, 10); 22362306a36Sopenharmony_cistatic DECLARE_AD5449_CHANNELS(ad5449_channels, 12); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic const struct ad5449_chip_info ad5449_chip_info[] = { 22662306a36Sopenharmony_ci [ID_AD5426] = { 22762306a36Sopenharmony_ci .channels = ad5429_channels, 22862306a36Sopenharmony_ci .num_channels = 1, 22962306a36Sopenharmony_ci .has_ctrl = false, 23062306a36Sopenharmony_ci }, 23162306a36Sopenharmony_ci [ID_AD5429] = { 23262306a36Sopenharmony_ci .channels = ad5429_channels, 23362306a36Sopenharmony_ci .num_channels = 2, 23462306a36Sopenharmony_ci .has_ctrl = true, 23562306a36Sopenharmony_ci }, 23662306a36Sopenharmony_ci [ID_AD5432] = { 23762306a36Sopenharmony_ci .channels = ad5439_channels, 23862306a36Sopenharmony_ci .num_channels = 1, 23962306a36Sopenharmony_ci .has_ctrl = false, 24062306a36Sopenharmony_ci }, 24162306a36Sopenharmony_ci [ID_AD5439] = { 24262306a36Sopenharmony_ci .channels = ad5439_channels, 24362306a36Sopenharmony_ci .num_channels = 2, 24462306a36Sopenharmony_ci .has_ctrl = true, 24562306a36Sopenharmony_ci }, 24662306a36Sopenharmony_ci [ID_AD5443] = { 24762306a36Sopenharmony_ci .channels = ad5449_channels, 24862306a36Sopenharmony_ci .num_channels = 1, 24962306a36Sopenharmony_ci .has_ctrl = false, 25062306a36Sopenharmony_ci }, 25162306a36Sopenharmony_ci [ID_AD5449] = { 25262306a36Sopenharmony_ci .channels = ad5449_channels, 25362306a36Sopenharmony_ci .num_channels = 2, 25462306a36Sopenharmony_ci .has_ctrl = true, 25562306a36Sopenharmony_ci }, 25662306a36Sopenharmony_ci}; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic const char *ad5449_vref_name(struct ad5449 *st, int n) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci if (st->chip_info->num_channels == 1) 26162306a36Sopenharmony_ci return "VREF"; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci if (n == 0) 26462306a36Sopenharmony_ci return "VREFA"; 26562306a36Sopenharmony_ci else 26662306a36Sopenharmony_ci return "VREFB"; 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistatic int ad5449_spi_probe(struct spi_device *spi) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci struct ad5449_platform_data *pdata = spi->dev.platform_data; 27262306a36Sopenharmony_ci const struct spi_device_id *id = spi_get_device_id(spi); 27362306a36Sopenharmony_ci struct iio_dev *indio_dev; 27462306a36Sopenharmony_ci struct ad5449 *st; 27562306a36Sopenharmony_ci unsigned int i; 27662306a36Sopenharmony_ci int ret; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 27962306a36Sopenharmony_ci if (indio_dev == NULL) 28062306a36Sopenharmony_ci return -ENOMEM; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci st = iio_priv(indio_dev); 28362306a36Sopenharmony_ci spi_set_drvdata(spi, indio_dev); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci st->chip_info = &ad5449_chip_info[id->driver_data]; 28662306a36Sopenharmony_ci st->spi = spi; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci for (i = 0; i < st->chip_info->num_channels; ++i) 28962306a36Sopenharmony_ci st->vref_reg[i].supply = ad5449_vref_name(st, i); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci ret = devm_regulator_bulk_get(&spi->dev, st->chip_info->num_channels, 29262306a36Sopenharmony_ci st->vref_reg); 29362306a36Sopenharmony_ci if (ret) 29462306a36Sopenharmony_ci return ret; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci ret = regulator_bulk_enable(st->chip_info->num_channels, st->vref_reg); 29762306a36Sopenharmony_ci if (ret) 29862306a36Sopenharmony_ci return ret; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci indio_dev->name = id->name; 30162306a36Sopenharmony_ci indio_dev->info = &ad5449_info; 30262306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 30362306a36Sopenharmony_ci indio_dev->channels = st->chip_info->channels; 30462306a36Sopenharmony_ci indio_dev->num_channels = st->chip_info->num_channels; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci mutex_init(&st->lock); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci if (st->chip_info->has_ctrl) { 30962306a36Sopenharmony_ci unsigned int ctrl = 0x00; 31062306a36Sopenharmony_ci if (pdata) { 31162306a36Sopenharmony_ci if (pdata->hardware_clear_to_midscale) 31262306a36Sopenharmony_ci ctrl |= AD5449_CTRL_HCLR_TO_MIDSCALE; 31362306a36Sopenharmony_ci ctrl |= pdata->sdo_mode << AD5449_CTRL_SDO_OFFSET; 31462306a36Sopenharmony_ci st->has_sdo = pdata->sdo_mode != AD5449_SDO_DISABLED; 31562306a36Sopenharmony_ci } else { 31662306a36Sopenharmony_ci st->has_sdo = true; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci ad5449_write(indio_dev, AD5449_CMD_CTRL, ctrl); 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci ret = iio_device_register(indio_dev); 32262306a36Sopenharmony_ci if (ret) 32362306a36Sopenharmony_ci goto error_disable_reg; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci return 0; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cierror_disable_reg: 32862306a36Sopenharmony_ci regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci return ret; 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cistatic void ad5449_spi_remove(struct spi_device *spi) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci struct iio_dev *indio_dev = spi_get_drvdata(spi); 33662306a36Sopenharmony_ci struct ad5449 *st = iio_priv(indio_dev); 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci iio_device_unregister(indio_dev); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); 34162306a36Sopenharmony_ci} 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_cistatic const struct spi_device_id ad5449_spi_ids[] = { 34462306a36Sopenharmony_ci { "ad5415", ID_AD5449 }, 34562306a36Sopenharmony_ci { "ad5426", ID_AD5426 }, 34662306a36Sopenharmony_ci { "ad5429", ID_AD5429 }, 34762306a36Sopenharmony_ci { "ad5432", ID_AD5432 }, 34862306a36Sopenharmony_ci { "ad5439", ID_AD5439 }, 34962306a36Sopenharmony_ci { "ad5443", ID_AD5443 }, 35062306a36Sopenharmony_ci { "ad5449", ID_AD5449 }, 35162306a36Sopenharmony_ci {} 35262306a36Sopenharmony_ci}; 35362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad5449_spi_ids); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic struct spi_driver ad5449_spi_driver = { 35662306a36Sopenharmony_ci .driver = { 35762306a36Sopenharmony_ci .name = "ad5449", 35862306a36Sopenharmony_ci }, 35962306a36Sopenharmony_ci .probe = ad5449_spi_probe, 36062306a36Sopenharmony_ci .remove = ad5449_spi_remove, 36162306a36Sopenharmony_ci .id_table = ad5449_spi_ids, 36262306a36Sopenharmony_ci}; 36362306a36Sopenharmony_cimodule_spi_driver(ad5449_spi_driver); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ciMODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 36662306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD5449 and similar DACs"); 36762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 368