// SPDX-License-Identifier: GPL-2.0-only /* * AD5592R Digital <-> Analog converters driver * * Copyright 2014-2016 Analog Devices Inc. * Author: Paul Cercueil <paul.cercueil@analog.com>
*/
for (i = 0; i < st->num_channels; i++) { switch (st->channel_modes[i]) { case CH_MODE_DAC:
dac |= BIT(i); break;
case CH_MODE_ADC:
adc |= BIT(i); break;
case CH_MODE_DAC_AND_ADC:
dac |= BIT(i);
adc |= BIT(i); break;
case CH_MODE_GPIO:
st->gpio_map |= BIT(i);
st->gpio_in |= BIT(i); /* Default to input */ break;
case CH_MODE_UNUSED: default: switch (st->channel_offstate[i]) { case CH_OFFSTATE_OUT_TRISTATE:
tristate |= BIT(i); break;
case CH_OFFSTATE_OUT_LOW:
st->gpio_out |= BIT(i); break;
case CH_OFFSTATE_OUT_HIGH:
st->gpio_out |= BIT(i);
st->gpio_val |= BIT(i); break;
case CH_OFFSTATE_PULLDOWN: default:
pulldown |= BIT(i); break;
}
}
}
guard(mutex)(&st->lock);
/* Pull down unused pins to GND */
ret = ops->reg_write(st, AD5592R_REG_PULLDOWN, pulldown); if (ret) return ret;
ret = ops->reg_write(st, AD5592R_REG_TRISTATE, tristate); if (ret) return ret;
/* Configure pins that we use */
ret = ops->reg_write(st, AD5592R_REG_DAC_EN, dac); if (ret) return ret;
ret = ops->reg_write(st, AD5592R_REG_ADC_EN, adc); if (ret) return ret;
ret = ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); if (ret) return ret;
ret = ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out); if (ret) return ret;
ret = ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); if (ret) return ret;
/* Verify that we can read back at least one register */
ret = ops->reg_read(st, AD5592R_REG_ADC_EN, &read_back); if (!ret && (read_back & 0xff) != adc) return -EIO;
return 0;
}
staticint ad5592r_reset_channel_modes(struct ad5592r_state *st)
{ int i;
for (i = 0; i < ARRAY_SIZE(st->channel_modes); i++)
st->channel_modes[i] = CH_MODE_UNUSED;
return ad5592r_set_channel_modes(st);
}
staticint ad5592r_write_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
{ struct ad5592r_state *st = iio_priv(iio_dev); int ret = 0;
switch (mask) { case IIO_CHAN_INFO_RAW:
if (val >= (1 << chan->scan_type.realbits) || val < 0) return -EINVAL;
if (!chan->output) return -EINVAL;
scoped_guard(mutex, &st->lock) {
ret = st->ops->write_dac(st, chan->channel, val); if (!ret)
st->cached_dac[chan->channel] = val;
} return ret; case IIO_CHAN_INFO_SCALE: if (chan->type == IIO_VOLTAGE) { bool gain;
if (val == st->scale_avail[0][0] &&
val2 == st->scale_avail[0][1])
gain = false; elseif (val == st->scale_avail[1][0] &&
val2 == st->scale_avail[1][1])
gain = true; else return -EINVAL;
guard(mutex)(&st->lock);
ret = st->ops->reg_read(st, AD5592R_REG_CTRL,
&st->cached_gp_ctrl); if (ret < 0) return ret;
if (chan->output) { if (gain)
st->cached_gp_ctrl |=
AD5592R_REG_CTRL_DAC_RANGE; else
st->cached_gp_ctrl &=
~AD5592R_REG_CTRL_DAC_RANGE;
} else { if (gain)
st->cached_gp_ctrl |=
AD5592R_REG_CTRL_ADC_RANGE; else
st->cached_gp_ctrl &=
~AD5592R_REG_CTRL_ADC_RANGE;
}
staticint ad5592r_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long m)
{ struct ad5592r_state *st = iio_priv(iio_dev);
u16 read_val = 0; int ret = 0, mult = 0;
switch (m) { case IIO_CHAN_INFO_RAW: if (!chan->output) {
scoped_guard(mutex, &st->lock)
ret = st->ops->read_adc(st, chan->channel,
&read_val); if (ret) return ret;
for (i = 0; i < num_channels; i++) { switch (st->channel_modes[i]) { case CH_MODE_DAC:
ad5592r_setup_channel(iio_dev, &channels[curr_channel], true, i);
curr_channel++; break;
case CH_MODE_ADC:
ad5592r_setup_channel(iio_dev, &channels[curr_channel], false, i);
curr_channel++; break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.