123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808 |
- /*
- * AD5755, AD5755-1, AD5757, AD5735, AD5737 Digital to analog converters driver
- *
- * Copyright 2012 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
- */
- #include <linux/device.h>
- #include <linux/err.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/spi/spi.h>
- #include <linux/slab.h>
- #include <linux/sysfs.h>
- #include <linux/delay.h>
- #include <linux/of.h>
- #include <linux/iio/iio.h>
- #include <linux/iio/sysfs.h>
- #include <linux/platform_data/ad5755.h>
- #define AD5755_NUM_CHANNELS 4
- #define AD5755_ADDR(x) ((x) << 16)
- #define AD5755_WRITE_REG_DATA(chan) (chan)
- #define AD5755_WRITE_REG_GAIN(chan) (0x08 | (chan))
- #define AD5755_WRITE_REG_OFFSET(chan) (0x10 | (chan))
- #define AD5755_WRITE_REG_CTRL(chan) (0x1c | (chan))
- #define AD5755_READ_REG_DATA(chan) (chan)
- #define AD5755_READ_REG_CTRL(chan) (0x4 | (chan))
- #define AD5755_READ_REG_GAIN(chan) (0x8 | (chan))
- #define AD5755_READ_REG_OFFSET(chan) (0xc | (chan))
- #define AD5755_READ_REG_CLEAR(chan) (0x10 | (chan))
- #define AD5755_READ_REG_SLEW(chan) (0x14 | (chan))
- #define AD5755_READ_REG_STATUS 0x18
- #define AD5755_READ_REG_MAIN 0x19
- #define AD5755_READ_REG_DC_DC 0x1a
- #define AD5755_CTRL_REG_SLEW 0x0
- #define AD5755_CTRL_REG_MAIN 0x1
- #define AD5755_CTRL_REG_DAC 0x2
- #define AD5755_CTRL_REG_DC_DC 0x3
- #define AD5755_CTRL_REG_SW 0x4
- #define AD5755_READ_FLAG 0x800000
- #define AD5755_NOOP 0x1CE000
- #define AD5755_DAC_INT_EN BIT(8)
- #define AD5755_DAC_CLR_EN BIT(7)
- #define AD5755_DAC_OUT_EN BIT(6)
- #define AD5755_DAC_INT_CURRENT_SENSE_RESISTOR BIT(5)
- #define AD5755_DAC_DC_DC_EN BIT(4)
- #define AD5755_DAC_VOLTAGE_OVERRANGE_EN BIT(3)
- #define AD5755_DC_DC_MAXV 0
- #define AD5755_DC_DC_FREQ_SHIFT 2
- #define AD5755_DC_DC_PHASE_SHIFT 4
- #define AD5755_EXT_DC_DC_COMP_RES BIT(6)
- #define AD5755_SLEW_STEP_SIZE_SHIFT 0
- #define AD5755_SLEW_RATE_SHIFT 3
- #define AD5755_SLEW_ENABLE BIT(12)
- /**
- * struct ad5755_chip_info - chip specific information
- * @channel_template: channel specification
- * @calib_shift: shift for the calibration data registers
- * @has_voltage_out: whether the chip has voltage outputs
- */
- struct ad5755_chip_info {
- const struct iio_chan_spec channel_template;
- unsigned int calib_shift;
- bool has_voltage_out;
- };
- /**
- * struct ad5755_state - driver instance specific data
- * @spi: spi device the driver is attached to
- * @chip_info: chip model specific constants, available modes etc
- * @pwr_down: bitmask which contains hether a channel is powered down or not
- * @ctrl: software shadow of the channel ctrl registers
- * @channels: iio channel spec for the device
- * @data: spi transfer buffers
- */
- struct ad5755_state {
- struct spi_device *spi;
- const struct ad5755_chip_info *chip_info;
- unsigned int pwr_down;
- unsigned int ctrl[AD5755_NUM_CHANNELS];
- struct iio_chan_spec channels[AD5755_NUM_CHANNELS];
- /*
- * DMA (thus cache coherency maintenance) requires the
- * transfer buffers to live in their own cache lines.
- */
- union {
- __be32 d32;
- u8 d8[4];
- } data[2] ____cacheline_aligned;
- };
- enum ad5755_type {
- ID_AD5755,
- ID_AD5757,
- ID_AD5735,
- ID_AD5737,
- };
- #ifdef CONFIG_OF
- static const int ad5755_dcdc_freq_table[][2] = {
- { 250000, AD5755_DC_DC_FREQ_250kHZ },
- { 410000, AD5755_DC_DC_FREQ_410kHZ },
- { 650000, AD5755_DC_DC_FREQ_650kHZ }
- };
- static const int ad5755_dcdc_maxv_table[][2] = {
- { 23000000, AD5755_DC_DC_MAXV_23V },
- { 24500000, AD5755_DC_DC_MAXV_24V5 },
- { 27000000, AD5755_DC_DC_MAXV_27V },
- { 29500000, AD5755_DC_DC_MAXV_29V5 },
- };
- static const int ad5755_slew_rate_table[][2] = {
- { 64000, AD5755_SLEW_RATE_64k },
- { 32000, AD5755_SLEW_RATE_32k },
- { 16000, AD5755_SLEW_RATE_16k },
- { 8000, AD5755_SLEW_RATE_8k },
- { 4000, AD5755_SLEW_RATE_4k },
- { 2000, AD5755_SLEW_RATE_2k },
- { 1000, AD5755_SLEW_RATE_1k },
- { 500, AD5755_SLEW_RATE_500 },
- { 250, AD5755_SLEW_RATE_250 },
- { 125, AD5755_SLEW_RATE_125 },
- { 64, AD5755_SLEW_RATE_64 },
- { 32, AD5755_SLEW_RATE_32 },
- { 16, AD5755_SLEW_RATE_16 },
- { 8, AD5755_SLEW_RATE_8 },
- { 4, AD5755_SLEW_RATE_4 },
- { 0, AD5755_SLEW_RATE_0_5 },
- };
- static const int ad5755_slew_step_table[][2] = {
- { 256, AD5755_SLEW_STEP_SIZE_256 },
- { 128, AD5755_SLEW_STEP_SIZE_128 },
- { 64, AD5755_SLEW_STEP_SIZE_64 },
- { 32, AD5755_SLEW_STEP_SIZE_32 },
- { 16, AD5755_SLEW_STEP_SIZE_16 },
- { 4, AD5755_SLEW_STEP_SIZE_4 },
- { 2, AD5755_SLEW_STEP_SIZE_2 },
- { 1, AD5755_SLEW_STEP_SIZE_1 },
- };
- #endif
- static int ad5755_write_unlocked(struct iio_dev *indio_dev,
- unsigned int reg, unsigned int val)
- {
- struct ad5755_state *st = iio_priv(indio_dev);
- st->data[0].d32 = cpu_to_be32((reg << 16) | val);
- return spi_write(st->spi, &st->data[0].d8[1], 3);
- }
- static int ad5755_write_ctrl_unlocked(struct iio_dev *indio_dev,
- unsigned int channel, unsigned int reg, unsigned int val)
- {
- return ad5755_write_unlocked(indio_dev,
- AD5755_WRITE_REG_CTRL(channel), (reg << 13) | val);
- }
- static int ad5755_write(struct iio_dev *indio_dev, unsigned int reg,
- unsigned int val)
- {
- int ret;
- mutex_lock(&indio_dev->mlock);
- ret = ad5755_write_unlocked(indio_dev, reg, val);
- mutex_unlock(&indio_dev->mlock);
- return ret;
- }
- static int ad5755_write_ctrl(struct iio_dev *indio_dev, unsigned int channel,
- unsigned int reg, unsigned int val)
- {
- int ret;
- mutex_lock(&indio_dev->mlock);
- ret = ad5755_write_ctrl_unlocked(indio_dev, channel, reg, val);
- mutex_unlock(&indio_dev->mlock);
- return ret;
- }
- static int ad5755_read(struct iio_dev *indio_dev, unsigned int addr)
- {
- struct ad5755_state *st = iio_priv(indio_dev);
- int ret;
- struct spi_transfer t[] = {
- {
- .tx_buf = &st->data[0].d8[1],
- .len = 3,
- .cs_change = 1,
- }, {
- .tx_buf = &st->data[1].d8[1],
- .rx_buf = &st->data[1].d8[1],
- .len = 3,
- },
- };
- mutex_lock(&indio_dev->mlock);
- st->data[0].d32 = cpu_to_be32(AD5755_READ_FLAG | (addr << 16));
- st->data[1].d32 = cpu_to_be32(AD5755_NOOP);
- ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
- if (ret >= 0)
- ret = be32_to_cpu(st->data[1].d32) & 0xffff;
- mutex_unlock(&indio_dev->mlock);
- return ret;
- }
- static int ad5755_update_dac_ctrl(struct iio_dev *indio_dev,
- unsigned int channel, unsigned int set, unsigned int clr)
- {
- struct ad5755_state *st = iio_priv(indio_dev);
- int ret;
- st->ctrl[channel] |= set;
- st->ctrl[channel] &= ~clr;
- ret = ad5755_write_ctrl_unlocked(indio_dev, channel,
- AD5755_CTRL_REG_DAC, st->ctrl[channel]);
- return ret;
- }
- static int ad5755_set_channel_pwr_down(struct iio_dev *indio_dev,
- unsigned int channel, bool pwr_down)
- {
- struct ad5755_state *st = iio_priv(indio_dev);
- unsigned int mask = BIT(channel);
- mutex_lock(&indio_dev->mlock);
- if ((bool)(st->pwr_down & mask) == pwr_down)
- goto out_unlock;
- if (!pwr_down) {
- st->pwr_down &= ~mask;
- ad5755_update_dac_ctrl(indio_dev, channel,
- AD5755_DAC_INT_EN | AD5755_DAC_DC_DC_EN, 0);
- udelay(200);
- ad5755_update_dac_ctrl(indio_dev, channel,
- AD5755_DAC_OUT_EN, 0);
- } else {
- st->pwr_down |= mask;
- ad5755_update_dac_ctrl(indio_dev, channel,
- 0, AD5755_DAC_INT_EN | AD5755_DAC_OUT_EN |
- AD5755_DAC_DC_DC_EN);
- }
- out_unlock:
- mutex_unlock(&indio_dev->mlock);
- return 0;
- }
- static const int ad5755_min_max_table[][2] = {
- [AD5755_MODE_VOLTAGE_0V_5V] = { 0, 5000 },
- [AD5755_MODE_VOLTAGE_0V_10V] = { 0, 10000 },
- [AD5755_MODE_VOLTAGE_PLUSMINUS_5V] = { -5000, 5000 },
- [AD5755_MODE_VOLTAGE_PLUSMINUS_10V] = { -10000, 10000 },
- [AD5755_MODE_CURRENT_4mA_20mA] = { 4, 20 },
- [AD5755_MODE_CURRENT_0mA_20mA] = { 0, 20 },
- [AD5755_MODE_CURRENT_0mA_24mA] = { 0, 24 },
- };
- static void ad5755_get_min_max(struct ad5755_state *st,
- struct iio_chan_spec const *chan, int *min, int *max)
- {
- enum ad5755_mode mode = st->ctrl[chan->channel] & 7;
- *min = ad5755_min_max_table[mode][0];
- *max = ad5755_min_max_table[mode][1];
- }
- static inline int ad5755_get_offset(struct ad5755_state *st,
- struct iio_chan_spec const *chan)
- {
- int min, max;
- ad5755_get_min_max(st, chan, &min, &max);
- return (min * (1 << chan->scan_type.realbits)) / (max - min);
- }
- static int ad5755_chan_reg_info(struct ad5755_state *st,
- struct iio_chan_spec const *chan, long info, bool write,
- unsigned int *reg, unsigned int *shift, unsigned int *offset)
- {
- switch (info) {
- case IIO_CHAN_INFO_RAW:
- if (write)
- *reg = AD5755_WRITE_REG_DATA(chan->address);
- else
- *reg = AD5755_READ_REG_DATA(chan->address);
- *shift = chan->scan_type.shift;
- *offset = 0;
- break;
- case IIO_CHAN_INFO_CALIBBIAS:
- if (write)
- *reg = AD5755_WRITE_REG_OFFSET(chan->address);
- else
- *reg = AD5755_READ_REG_OFFSET(chan->address);
- *shift = st->chip_info->calib_shift;
- *offset = 32768;
- break;
- case IIO_CHAN_INFO_CALIBSCALE:
- if (write)
- *reg = AD5755_WRITE_REG_GAIN(chan->address);
- else
- *reg = AD5755_READ_REG_GAIN(chan->address);
- *shift = st->chip_info->calib_shift;
- *offset = 0;
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
- static int ad5755_read_raw(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan, int *val, int *val2, long info)
- {
- struct ad5755_state *st = iio_priv(indio_dev);
- unsigned int reg, shift, offset;
- int min, max;
- int ret;
- switch (info) {
- case IIO_CHAN_INFO_SCALE:
- ad5755_get_min_max(st, chan, &min, &max);
- *val = max - min;
- *val2 = chan->scan_type.realbits;
- return IIO_VAL_FRACTIONAL_LOG2;
- case IIO_CHAN_INFO_OFFSET:
- *val = ad5755_get_offset(st, chan);
- return IIO_VAL_INT;
- default:
- ret = ad5755_chan_reg_info(st, chan, info, false,
- ®, &shift, &offset);
- if (ret)
- return ret;
- ret = ad5755_read(indio_dev, reg);
- if (ret < 0)
- return ret;
- *val = (ret - offset) >> shift;
- return IIO_VAL_INT;
- }
- return -EINVAL;
- }
- static int ad5755_write_raw(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan, int val, int val2, long info)
- {
- struct ad5755_state *st = iio_priv(indio_dev);
- unsigned int shift, reg, offset;
- int ret;
- ret = ad5755_chan_reg_info(st, chan, info, true,
- ®, &shift, &offset);
- if (ret)
- return ret;
- val <<= shift;
- val += offset;
- if (val < 0 || val > 0xffff)
- return -EINVAL;
- return ad5755_write(indio_dev, reg, val);
- }
- static ssize_t ad5755_read_powerdown(struct iio_dev *indio_dev, uintptr_t priv,
- const struct iio_chan_spec *chan, char *buf)
- {
- struct ad5755_state *st = iio_priv(indio_dev);
- return sprintf(buf, "%d\n",
- (bool)(st->pwr_down & (1 << chan->channel)));
- }
- static ssize_t ad5755_write_powerdown(struct iio_dev *indio_dev, uintptr_t priv,
- struct iio_chan_spec const *chan, const char *buf, size_t len)
- {
- bool pwr_down;
- int ret;
- ret = strtobool(buf, &pwr_down);
- if (ret)
- return ret;
- ret = ad5755_set_channel_pwr_down(indio_dev, chan->channel, pwr_down);
- return ret ? ret : len;
- }
- static const struct iio_info ad5755_info = {
- .read_raw = ad5755_read_raw,
- .write_raw = ad5755_write_raw,
- .driver_module = THIS_MODULE,
- };
- static const struct iio_chan_spec_ext_info ad5755_ext_info[] = {
- {
- .name = "powerdown",
- .read = ad5755_read_powerdown,
- .write = ad5755_write_powerdown,
- .shared = IIO_SEPARATE,
- },
- { },
- };
- #define AD5755_CHANNEL(_bits) { \
- .indexed = 1, \
- .output = 1, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
- BIT(IIO_CHAN_INFO_SCALE) | \
- BIT(IIO_CHAN_INFO_OFFSET) | \
- BIT(IIO_CHAN_INFO_CALIBSCALE) | \
- BIT(IIO_CHAN_INFO_CALIBBIAS), \
- .scan_type = { \
- .sign = 'u', \
- .realbits = (_bits), \
- .storagebits = 16, \
- .shift = 16 - (_bits), \
- }, \
- .ext_info = ad5755_ext_info, \
- }
- static const struct ad5755_chip_info ad5755_chip_info_tbl[] = {
- [ID_AD5735] = {
- .channel_template = AD5755_CHANNEL(14),
- .has_voltage_out = true,
- .calib_shift = 4,
- },
- [ID_AD5737] = {
- .channel_template = AD5755_CHANNEL(14),
- .has_voltage_out = false,
- .calib_shift = 4,
- },
- [ID_AD5755] = {
- .channel_template = AD5755_CHANNEL(16),
- .has_voltage_out = true,
- .calib_shift = 0,
- },
- [ID_AD5757] = {
- .channel_template = AD5755_CHANNEL(16),
- .has_voltage_out = false,
- .calib_shift = 0,
- },
- };
- static bool ad5755_is_valid_mode(struct ad5755_state *st, enum ad5755_mode mode)
- {
- switch (mode) {
- case AD5755_MODE_VOLTAGE_0V_5V:
- case AD5755_MODE_VOLTAGE_0V_10V:
- case AD5755_MODE_VOLTAGE_PLUSMINUS_5V:
- case AD5755_MODE_VOLTAGE_PLUSMINUS_10V:
- return st->chip_info->has_voltage_out;
- case AD5755_MODE_CURRENT_4mA_20mA:
- case AD5755_MODE_CURRENT_0mA_20mA:
- case AD5755_MODE_CURRENT_0mA_24mA:
- return true;
- default:
- return false;
- }
- }
- static int ad5755_setup_pdata(struct iio_dev *indio_dev,
- const struct ad5755_platform_data *pdata)
- {
- struct ad5755_state *st = iio_priv(indio_dev);
- unsigned int val;
- unsigned int i;
- int ret;
- if (pdata->dc_dc_phase > AD5755_DC_DC_PHASE_90_DEGREE ||
- pdata->dc_dc_freq > AD5755_DC_DC_FREQ_650kHZ ||
- pdata->dc_dc_maxv > AD5755_DC_DC_MAXV_29V5)
- return -EINVAL;
- val = pdata->dc_dc_maxv << AD5755_DC_DC_MAXV;
- val |= pdata->dc_dc_freq << AD5755_DC_DC_FREQ_SHIFT;
- val |= pdata->dc_dc_phase << AD5755_DC_DC_PHASE_SHIFT;
- if (pdata->ext_dc_dc_compenstation_resistor)
- val |= AD5755_EXT_DC_DC_COMP_RES;
- ret = ad5755_write_ctrl(indio_dev, 0, AD5755_CTRL_REG_DC_DC, val);
- if (ret < 0)
- return ret;
- for (i = 0; i < ARRAY_SIZE(pdata->dac); ++i) {
- val = pdata->dac[i].slew.step_size <<
- AD5755_SLEW_STEP_SIZE_SHIFT;
- val |= pdata->dac[i].slew.rate <<
- AD5755_SLEW_RATE_SHIFT;
- if (pdata->dac[i].slew.enable)
- val |= AD5755_SLEW_ENABLE;
- ret = ad5755_write_ctrl(indio_dev, i,
- AD5755_CTRL_REG_SLEW, val);
- if (ret < 0)
- return ret;
- }
- for (i = 0; i < ARRAY_SIZE(pdata->dac); ++i) {
- if (!ad5755_is_valid_mode(st, pdata->dac[i].mode))
- return -EINVAL;
- val = 0;
- if (!pdata->dac[i].ext_current_sense_resistor)
- val |= AD5755_DAC_INT_CURRENT_SENSE_RESISTOR;
- if (pdata->dac[i].enable_voltage_overrange)
- val |= AD5755_DAC_VOLTAGE_OVERRANGE_EN;
- val |= pdata->dac[i].mode;
- ret = ad5755_update_dac_ctrl(indio_dev, i, val, 0);
- if (ret < 0)
- return ret;
- }
- return 0;
- }
- static bool ad5755_is_voltage_mode(enum ad5755_mode mode)
- {
- switch (mode) {
- case AD5755_MODE_VOLTAGE_0V_5V:
- case AD5755_MODE_VOLTAGE_0V_10V:
- case AD5755_MODE_VOLTAGE_PLUSMINUS_5V:
- case AD5755_MODE_VOLTAGE_PLUSMINUS_10V:
- return true;
- default:
- return false;
- }
- }
- static int ad5755_init_channels(struct iio_dev *indio_dev,
- const struct ad5755_platform_data *pdata)
- {
- struct ad5755_state *st = iio_priv(indio_dev);
- struct iio_chan_spec *channels = st->channels;
- unsigned int i;
- for (i = 0; i < AD5755_NUM_CHANNELS; ++i) {
- channels[i] = st->chip_info->channel_template;
- channels[i].channel = i;
- channels[i].address = i;
- if (pdata && ad5755_is_voltage_mode(pdata->dac[i].mode))
- channels[i].type = IIO_VOLTAGE;
- else
- channels[i].type = IIO_CURRENT;
- }
- indio_dev->channels = channels;
- return 0;
- }
- #define AD5755_DEFAULT_DAC_PDATA { \
- .mode = AD5755_MODE_CURRENT_4mA_20mA, \
- .ext_current_sense_resistor = true, \
- .enable_voltage_overrange = false, \
- .slew = { \
- .enable = false, \
- .rate = AD5755_SLEW_RATE_64k, \
- .step_size = AD5755_SLEW_STEP_SIZE_1, \
- }, \
- }
- static const struct ad5755_platform_data ad5755_default_pdata = {
- .ext_dc_dc_compenstation_resistor = false,
- .dc_dc_phase = AD5755_DC_DC_PHASE_ALL_SAME_EDGE,
- .dc_dc_freq = AD5755_DC_DC_FREQ_410kHZ,
- .dc_dc_maxv = AD5755_DC_DC_MAXV_23V,
- .dac = {
- [0] = AD5755_DEFAULT_DAC_PDATA,
- [1] = AD5755_DEFAULT_DAC_PDATA,
- [2] = AD5755_DEFAULT_DAC_PDATA,
- [3] = AD5755_DEFAULT_DAC_PDATA,
- },
- };
- #ifdef CONFIG_OF
- static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
- {
- struct device_node *np = dev->of_node;
- struct device_node *pp;
- struct ad5755_platform_data *pdata;
- unsigned int tmp;
- unsigned int tmparray[3];
- int devnr, i;
- pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return NULL;
- pdata->ext_dc_dc_compenstation_resistor =
- of_property_read_bool(np, "adi,ext-dc-dc-compenstation-resistor");
- if (!of_property_read_u32(np, "adi,dc-dc-phase", &tmp))
- pdata->dc_dc_phase = tmp;
- else
- pdata->dc_dc_phase = AD5755_DC_DC_PHASE_ALL_SAME_EDGE;
- pdata->dc_dc_freq = AD5755_DC_DC_FREQ_410kHZ;
- if (!of_property_read_u32(np, "adi,dc-dc-freq-hz", &tmp)) {
- for (i = 0; i < ARRAY_SIZE(ad5755_dcdc_freq_table); i++) {
- if (tmp == ad5755_dcdc_freq_table[i][0]) {
- pdata->dc_dc_freq = ad5755_dcdc_freq_table[i][1];
- break;
- }
- }
- if (i == ARRAY_SIZE(ad5755_dcdc_freq_table)) {
- dev_err(dev,
- "adi,dc-dc-freq out of range selecting 410kHz");
- }
- }
- pdata->dc_dc_maxv = AD5755_DC_DC_MAXV_23V;
- if (!of_property_read_u32(np, "adi,dc-dc-max-microvolt", &tmp)) {
- for (i = 0; i < ARRAY_SIZE(ad5755_dcdc_maxv_table); i++) {
- if (tmp == ad5755_dcdc_maxv_table[i][0]) {
- pdata->dc_dc_maxv = ad5755_dcdc_maxv_table[i][1];
- break;
- }
- }
- if (i == ARRAY_SIZE(ad5755_dcdc_maxv_table)) {
- dev_err(dev,
- "adi,dc-dc-maxv out of range selecting 23V");
- }
- }
- devnr = 0;
- for_each_child_of_node(np, pp) {
- if (devnr >= AD5755_NUM_CHANNELS) {
- dev_err(dev,
- "There is to many channels defined in DT\n");
- goto error_out;
- }
- if (!of_property_read_u32(pp, "adi,mode", &tmp))
- pdata->dac[devnr].mode = tmp;
- else
- pdata->dac[devnr].mode = AD5755_MODE_CURRENT_4mA_20mA;
- pdata->dac[devnr].ext_current_sense_resistor =
- of_property_read_bool(pp, "adi,ext-current-sense-resistor");
- pdata->dac[devnr].enable_voltage_overrange =
- of_property_read_bool(pp, "adi,enable-voltage-overrange");
- if (!of_property_read_u32_array(pp, "adi,slew", tmparray, 3)) {
- pdata->dac[devnr].slew.enable = tmparray[0];
- pdata->dac[devnr].slew.rate = AD5755_SLEW_RATE_64k;
- for (i = 0; i < ARRAY_SIZE(ad5755_slew_rate_table); i++) {
- if (tmparray[1] == ad5755_slew_rate_table[i][0]) {
- pdata->dac[devnr].slew.rate =
- ad5755_slew_rate_table[i][1];
- break;
- }
- }
- if (i == ARRAY_SIZE(ad5755_slew_rate_table)) {
- dev_err(dev,
- "channel %d slew rate out of range selecting 64kHz",
- devnr);
- }
- pdata->dac[devnr].slew.step_size = AD5755_SLEW_STEP_SIZE_1;
- for (i = 0; i < ARRAY_SIZE(ad5755_slew_step_table); i++) {
- if (tmparray[2] == ad5755_slew_step_table[i][0]) {
- pdata->dac[devnr].slew.step_size =
- ad5755_slew_step_table[i][1];
- break;
- }
- }
- if (i == ARRAY_SIZE(ad5755_slew_step_table)) {
- dev_err(dev,
- "channel %d slew step size out of range selecting 1 LSB",
- devnr);
- }
- } else {
- pdata->dac[devnr].slew.enable = false;
- pdata->dac[devnr].slew.rate = AD5755_SLEW_RATE_64k;
- pdata->dac[devnr].slew.step_size =
- AD5755_SLEW_STEP_SIZE_1;
- }
- devnr++;
- }
- return pdata;
- error_out:
- devm_kfree(dev, pdata);
- return NULL;
- }
- #else
- static
- struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
- {
- return NULL;
- }
- #endif
- static int ad5755_probe(struct spi_device *spi)
- {
- enum ad5755_type type = spi_get_device_id(spi)->driver_data;
- const struct ad5755_platform_data *pdata = dev_get_platdata(&spi->dev);
- struct iio_dev *indio_dev;
- struct ad5755_state *st;
- int ret;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
- if (indio_dev == NULL) {
- dev_err(&spi->dev, "Failed to allocate iio device\n");
- return -ENOMEM;
- }
- st = iio_priv(indio_dev);
- spi_set_drvdata(spi, indio_dev);
- st->chip_info = &ad5755_chip_info_tbl[type];
- st->spi = spi;
- st->pwr_down = 0xf;
- indio_dev->dev.parent = &spi->dev;
- indio_dev->name = spi_get_device_id(spi)->name;
- indio_dev->info = &ad5755_info;
- indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->num_channels = AD5755_NUM_CHANNELS;
- if (spi->dev.of_node)
- pdata = ad5755_parse_dt(&spi->dev);
- else
- pdata = spi->dev.platform_data;
- if (!pdata) {
- dev_warn(&spi->dev, "no platform data? using default\n");
- pdata = &ad5755_default_pdata;
- }
- ret = ad5755_init_channels(indio_dev, pdata);
- if (ret)
- return ret;
- ret = ad5755_setup_pdata(indio_dev, pdata);
- if (ret)
- return ret;
- return devm_iio_device_register(&spi->dev, indio_dev);
- }
- static const struct spi_device_id ad5755_id[] = {
- { "ad5755", ID_AD5755 },
- { "ad5755-1", ID_AD5755 },
- { "ad5757", ID_AD5757 },
- { "ad5735", ID_AD5735 },
- { "ad5737", ID_AD5737 },
- {}
- };
- MODULE_DEVICE_TABLE(spi, ad5755_id);
- static const struct of_device_id ad5755_of_match[] = {
- { .compatible = "adi,ad5755" },
- { .compatible = "adi,ad5755-1" },
- { .compatible = "adi,ad5757" },
- { .compatible = "adi,ad5735" },
- { .compatible = "adi,ad5737" },
- { }
- };
- MODULE_DEVICE_TABLE(of, ad5755_of_match);
- static struct spi_driver ad5755_driver = {
- .driver = {
- .name = "ad5755",
- },
- .probe = ad5755_probe,
- .id_table = ad5755_id,
- };
- module_spi_driver(ad5755_driver);
- MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
- MODULE_DESCRIPTION("Analog Devices AD5755/55-1/57/35/37 DAC");
- MODULE_LICENSE("GPL v2");
|