Commit d6511322 authored by Ludovic Desroches's avatar Ludovic Desroches Committed by Jonathan Cameron

iio:adc:at91-sama5d2: add support for differential conversions

Add signed differential channels and update the voltage scale for
differential conversions.
Signed-off-by: default avatarLudovic Desroches <ludovic.desroches@atmel.com>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent 94b24230
...@@ -113,8 +113,11 @@ ...@@ -113,8 +113,11 @@
#define AT91_SAMA5D2_CWR 0x44 #define AT91_SAMA5D2_CWR 0x44
/* Channel Gain Register */ /* Channel Gain Register */
#define AT91_SAMA5D2_CGR 0x48 #define AT91_SAMA5D2_CGR 0x48
/* Channel Offset Register */ /* Channel Offset Register */
#define AT91_SAMA5D2_COR 0x4c #define AT91_SAMA5D2_COR 0x4c
#define AT91_SAMA5D2_COR_DIFF_OFFSET 16
/* Channel Data Register 0 */ /* Channel Data Register 0 */
#define AT91_SAMA5D2_CDR0 0x50 #define AT91_SAMA5D2_CDR0 0x50
/* Analog Control Register */ /* Analog Control Register */
...@@ -142,7 +145,7 @@ ...@@ -142,7 +145,7 @@
/* Version Register */ /* Version Register */
#define AT91_SAMA5D2_VERSION 0xfc #define AT91_SAMA5D2_VERSION 0xfc
#define AT91_SAMA5D2_CHAN(num, addr) \ #define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
{ \ { \
.type = IIO_VOLTAGE, \ .type = IIO_VOLTAGE, \
.channel = num, \ .channel = num, \
...@@ -158,6 +161,24 @@ ...@@ -158,6 +161,24 @@
.indexed = 1, \ .indexed = 1, \
} }
#define AT91_SAMA5D2_CHAN_DIFF(num, num2, addr) \
{ \
.type = IIO_VOLTAGE, \
.differential = 1, \
.channel = num, \
.channel2 = num2, \
.address = addr, \
.scan_type = { \
.sign = 's', \
.realbits = 12, \
}, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
.datasheet_name = "CH"#num"-CH"#num2, \
.indexed = 1, \
}
#define at91_adc_readl(st, reg) readl_relaxed(st->base + reg) #define at91_adc_readl(st, reg) readl_relaxed(st->base + reg)
#define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg) #define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg)
...@@ -187,18 +208,24 @@ struct at91_adc_state { ...@@ -187,18 +208,24 @@ struct at91_adc_state {
}; };
static const struct iio_chan_spec at91_adc_channels[] = { static const struct iio_chan_spec at91_adc_channels[] = {
AT91_SAMA5D2_CHAN(0, 0x50), AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
AT91_SAMA5D2_CHAN(1, 0x54), AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
AT91_SAMA5D2_CHAN(2, 0x58), AT91_SAMA5D2_CHAN_SINGLE(2, 0x58),
AT91_SAMA5D2_CHAN(3, 0x5c), AT91_SAMA5D2_CHAN_SINGLE(3, 0x5c),
AT91_SAMA5D2_CHAN(4, 0x60), AT91_SAMA5D2_CHAN_SINGLE(4, 0x60),
AT91_SAMA5D2_CHAN(5, 0x64), AT91_SAMA5D2_CHAN_SINGLE(5, 0x64),
AT91_SAMA5D2_CHAN(6, 0x68), AT91_SAMA5D2_CHAN_SINGLE(6, 0x68),
AT91_SAMA5D2_CHAN(7, 0x6c), AT91_SAMA5D2_CHAN_SINGLE(7, 0x6c),
AT91_SAMA5D2_CHAN(8, 0x70), AT91_SAMA5D2_CHAN_SINGLE(8, 0x70),
AT91_SAMA5D2_CHAN(9, 0x74), AT91_SAMA5D2_CHAN_SINGLE(9, 0x74),
AT91_SAMA5D2_CHAN(10, 0x78), AT91_SAMA5D2_CHAN_SINGLE(10, 0x78),
AT91_SAMA5D2_CHAN(11, 0x7c), AT91_SAMA5D2_CHAN_SINGLE(11, 0x7c),
AT91_SAMA5D2_CHAN_DIFF(0, 1, 0x50),
AT91_SAMA5D2_CHAN_DIFF(2, 3, 0x58),
AT91_SAMA5D2_CHAN_DIFF(4, 5, 0x60),
AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
}; };
static unsigned at91_adc_startup_time(unsigned startup_time_min, static unsigned at91_adc_startup_time(unsigned startup_time_min,
...@@ -281,6 +308,7 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, ...@@ -281,6 +308,7 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask) int *val, int *val2, long mask)
{ {
struct at91_adc_state *st = iio_priv(indio_dev); struct at91_adc_state *st = iio_priv(indio_dev);
u32 cor = 0;
int ret; int ret;
switch (mask) { switch (mask) {
...@@ -289,6 +317,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, ...@@ -289,6 +317,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
st->chan = chan; st->chan = chan;
if (chan->differential)
cor = (BIT(chan->channel) | BIT(chan->channel2)) <<
AT91_SAMA5D2_COR_DIFF_OFFSET;
at91_adc_writel(st, AT91_SAMA5D2_COR, cor);
at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel)); at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel));
at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel)); at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel));
at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START); at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START);
...@@ -301,6 +334,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, ...@@ -301,6 +334,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
if (ret > 0) { if (ret > 0) {
*val = st->conversion_value; *val = st->conversion_value;
if (chan->scan_type.sign == 's')
*val = sign_extend32(*val, 11);
ret = IIO_VAL_INT; ret = IIO_VAL_INT;
st->conversion_done = false; st->conversion_done = false;
} }
...@@ -313,6 +348,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, ...@@ -313,6 +348,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
*val = st->vref_uv / 1000; *val = st->vref_uv / 1000;
if (chan->differential)
*val *= 2;
*val2 = chan->scan_type.realbits; *val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2; return IIO_VAL_FRACTIONAL_LOG2;
...@@ -447,8 +484,12 @@ static int at91_adc_probe(struct platform_device *pdev) ...@@ -447,8 +484,12 @@ static int at91_adc_probe(struct platform_device *pdev)
at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST);
at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff); at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff);
/* Transfer field must be set to 2 according to the datasheet. */ /*
at91_adc_writel(st, AT91_SAMA5D2_MR, AT91_SAMA5D2_MR_TRANSFER(2)); * Transfer field must be set to 2 according to the datasheet and
* allows different analog settings for each channel.
*/
at91_adc_writel(st, AT91_SAMA5D2_MR,
AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH);
at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate); at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment