mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 08:44:21 +08:00
staging: iio: dac: ad5446: Enable driver support for AD5620/AD5640/AD5660 DA converters
Initial support for single channel, 12-/14-/16-Bit nanoDAC with On-Chip Reference staging: iio: dac: ad5446: Fix according to review feedback Review feedback by Jonathan Cameron: Use kernel doc style to document headers. Turn data into a union Add some comments for clarity Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Acked-by: Jonathan Cameron <jic23@cam.ac.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
f386caa3cd
commit
d846263da4
@ -11,11 +11,11 @@ config AD5624R_SPI
|
||||
AD5664R convertors (DAC). This driver uses the common SPI interface.
|
||||
|
||||
config AD5446
|
||||
tristate "Analog Devices AD5444, AD5446 and AD5541A, AD5512A DAC SPI driver"
|
||||
tristate "Analog Devices AD5444/6, AD5620/40/60 and AD5541A/12A DAC SPI driver"
|
||||
depends on SPI
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD5444, AD5446
|
||||
and AD5541A, AD5512A DACs.
|
||||
Say yes here to build support for Analog Devices AD5444, AD5446,
|
||||
AD5620, AD5640, AD5660 and AD5541A, AD5512A DACs.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad5446.
|
||||
|
@ -23,6 +23,31 @@
|
||||
|
||||
#include "ad5446.h"
|
||||
|
||||
static void ad5446_store_sample(struct ad5446_state *st, unsigned val)
|
||||
{
|
||||
st->data.d16 = cpu_to_be16(AD5446_LOAD |
|
||||
(val << st->chip_info->left_shift));
|
||||
}
|
||||
|
||||
static void ad5542_store_sample(struct ad5446_state *st, unsigned val)
|
||||
{
|
||||
st->data.d16 = cpu_to_be16(val << st->chip_info->left_shift);
|
||||
}
|
||||
|
||||
static void ad5620_store_sample(struct ad5446_state *st, unsigned val)
|
||||
{
|
||||
st->data.d16 = cpu_to_be16(AD5620_LOAD |
|
||||
(val << st->chip_info->left_shift));
|
||||
}
|
||||
|
||||
static void ad5660_store_sample(struct ad5446_state *st, unsigned val)
|
||||
{
|
||||
val |= AD5660_LOAD;
|
||||
st->data.d24[0] = (val >> 16) & 0xFF;
|
||||
st->data.d24[1] = (val >> 8) & 0xFF;
|
||||
st->data.d24[2] = val & 0xFF;
|
||||
}
|
||||
|
||||
static ssize_t ad5446_write(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
@ -43,18 +68,7 @@ static ssize_t ad5446_write(struct device *dev,
|
||||
}
|
||||
|
||||
mutex_lock(&dev_info->mlock);
|
||||
switch (spi_get_device_id(st->spi)->driver_data) {
|
||||
case ID_AD5444:
|
||||
case ID_AD5446:
|
||||
st->data = cpu_to_be16(AD5446_LOAD |
|
||||
(val << st->chip_info->left_shift));
|
||||
break;
|
||||
case ID_AD5542A:
|
||||
case ID_AD5512A:
|
||||
st->data = cpu_to_be16(val << st->chip_info->left_shift);
|
||||
break;
|
||||
}
|
||||
|
||||
st->chip_info->store_sample(st, val);
|
||||
ret = spi_sync(st->spi, &st->msg);
|
||||
mutex_unlock(&dev_info->mlock);
|
||||
|
||||
@ -105,24 +119,76 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
|
||||
.storagebits = 16,
|
||||
.left_shift = 2,
|
||||
.sign = 'u', /* IIO_SCAN_EL_TYPE_UNSIGNED */
|
||||
.store_sample = ad5446_store_sample,
|
||||
},
|
||||
[ID_AD5446] = {
|
||||
.bits = 14,
|
||||
.storagebits = 16,
|
||||
.left_shift = 0,
|
||||
.sign = 'u', /* IIO_SCAN_EL_TYPE_UNSIGNED */
|
||||
.store_sample = ad5446_store_sample,
|
||||
},
|
||||
[ID_AD5542A] = {
|
||||
.bits = 16,
|
||||
.storagebits = 16,
|
||||
.left_shift = 0,
|
||||
.sign = 'u', /* IIO_SCAN_EL_TYPE_UNSIGNED */
|
||||
.store_sample = ad5542_store_sample,
|
||||
},
|
||||
[ID_AD5512A] = {
|
||||
.bits = 12,
|
||||
.storagebits = 16,
|
||||
.left_shift = 4,
|
||||
.sign = 'u', /* IIO_SCAN_EL_TYPE_UNSIGNED */
|
||||
.store_sample = ad5542_store_sample,
|
||||
},
|
||||
[ID_AD5620_2500] = {
|
||||
.bits = 12,
|
||||
.storagebits = 16,
|
||||
.left_shift = 2,
|
||||
.sign = 'u', /* IIO_SCAN_EL_TYPE_UNSIGNED */
|
||||
.int_vref_mv = 2500,
|
||||
.store_sample = ad5620_store_sample,
|
||||
},
|
||||
[ID_AD5620_1250] = {
|
||||
.bits = 12,
|
||||
.storagebits = 16,
|
||||
.left_shift = 2,
|
||||
.sign = 'u', /* IIO_SCAN_EL_TYPE_UNSIGNED */
|
||||
.int_vref_mv = 1250,
|
||||
.store_sample = ad5620_store_sample,
|
||||
},
|
||||
[ID_AD5640_2500] = {
|
||||
.bits = 14,
|
||||
.storagebits = 16,
|
||||
.left_shift = 0,
|
||||
.sign = 'u', /* IIO_SCAN_EL_TYPE_UNSIGNED */
|
||||
.int_vref_mv = 2500,
|
||||
.store_sample = ad5620_store_sample,
|
||||
},
|
||||
[ID_AD5640_1250] = {
|
||||
.bits = 14,
|
||||
.storagebits = 16,
|
||||
.left_shift = 0,
|
||||
.sign = 'u', /* IIO_SCAN_EL_TYPE_UNSIGNED */
|
||||
.int_vref_mv = 1250,
|
||||
.store_sample = ad5620_store_sample,
|
||||
},
|
||||
[ID_AD5660_2500] = {
|
||||
.bits = 16,
|
||||
.storagebits = 24,
|
||||
.left_shift = 0,
|
||||
.sign = 'u', /* IIO_SCAN_EL_TYPE_UNSIGNED */
|
||||
.int_vref_mv = 2500,
|
||||
.store_sample = ad5660_store_sample,
|
||||
},
|
||||
[ID_AD5660_1250] = {
|
||||
.bits = 16,
|
||||
.storagebits = 24,
|
||||
.left_shift = 0,
|
||||
.sign = 'u', /* IIO_SCAN_EL_TYPE_UNSIGNED */
|
||||
.int_vref_mv = 1250,
|
||||
.store_sample = ad5660_store_sample,
|
||||
},
|
||||
};
|
||||
|
||||
@ -168,16 +234,28 @@ static int __devinit ad5446_probe(struct spi_device *spi)
|
||||
|
||||
/* Setup default message */
|
||||
|
||||
st->xfer.tx_buf = &st->data,
|
||||
st->xfer.len = 2,
|
||||
st->xfer.tx_buf = &st->data;
|
||||
st->xfer.len = st->chip_info->storagebits / 8;
|
||||
|
||||
spi_message_init(&st->msg);
|
||||
spi_message_add_tail(&st->xfer, &st->msg);
|
||||
|
||||
if (voltage_uv)
|
||||
st->vref_mv = voltage_uv / 1000;
|
||||
else
|
||||
dev_warn(&spi->dev, "reference voltage unspecified\n");
|
||||
switch (spi_get_device_id(spi)->driver_data) {
|
||||
case ID_AD5620_2500:
|
||||
case ID_AD5620_1250:
|
||||
case ID_AD5640_2500:
|
||||
case ID_AD5640_1250:
|
||||
case ID_AD5660_2500:
|
||||
case ID_AD5660_1250:
|
||||
st->vref_mv = st->chip_info->int_vref_mv;
|
||||
break;
|
||||
default:
|
||||
if (voltage_uv)
|
||||
st->vref_mv = voltage_uv / 1000;
|
||||
else
|
||||
dev_warn(&spi->dev,
|
||||
"reference voltage unspecified\n");
|
||||
}
|
||||
|
||||
ret = iio_device_register(st->indio_dev);
|
||||
if (ret)
|
||||
@ -217,6 +295,12 @@ static const struct spi_device_id ad5446_id[] = {
|
||||
{"ad5446", ID_AD5446},
|
||||
{"ad5542a", ID_AD5542A},
|
||||
{"ad5512a", ID_AD5512A},
|
||||
{"ad5620-2500", ID_AD5620_2500}, /* AD5620/40/60: */
|
||||
{"ad5620-1250", ID_AD5620_1250}, /* part numbers may look differently */
|
||||
{"ad5640-2500", ID_AD5640_2500},
|
||||
{"ad5640-1250", ID_AD5640_1250},
|
||||
{"ad5660-2500", ID_AD5660_2500},
|
||||
{"ad5660-1250", ID_AD5660_1250},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
*
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
#ifndef IIO_ADC_AD5446_H_
|
||||
#define IIO_ADC_AD5446_H_
|
||||
#ifndef IIO_DAC_AD5446_H_
|
||||
#define IIO_DAC_AD5446_H_
|
||||
|
||||
/* DAC Control Bits */
|
||||
|
||||
@ -15,14 +15,30 @@
|
||||
#define AD5446_NOP (0x2 << 14) /* No operation */
|
||||
#define AD5446_CLK_RISING (0x3 << 14) /* Clock data on rising edge */
|
||||
|
||||
#define AD5620_LOAD (0x0 << 14) /* Load and update Norm Operation*/
|
||||
#define AD5620_PWRDWN_1k (0x1 << 14) /* Power-down: 1kOhm to GND */
|
||||
#define AD5620_PWRDWN_100k (0x2 << 14) /* Power-down: 100kOhm to GND */
|
||||
#define AD5620_PWRDWN_TRISTATE (0x3 << 14) /* Power-down: Three-state */
|
||||
|
||||
#define AD5660_LOAD (0x0 << 16) /* Load and update Norm Operation*/
|
||||
#define AD5660_PWRDWN_1k (0x1 << 16) /* Power-down: 1kOhm to GND */
|
||||
#define AD5660_PWRDWN_100k (0x2 << 16) /* Power-down: 100kOhm to GND */
|
||||
#define AD5660_PWRDWN_TRISTATE (0x3 << 16) /* Power-down: Three-state */
|
||||
|
||||
#define RES_MASK(bits) ((1 << (bits)) - 1)
|
||||
|
||||
struct ad5446_chip_info {
|
||||
u8 bits; /* number of DAC bits */
|
||||
u8 storagebits; /* number of bits written to the DAC */
|
||||
u8 left_shift; /* number of bits the datum must be shifted */
|
||||
char sign; /* [s]igned or [u]nsigned */
|
||||
};
|
||||
/**
|
||||
* struct ad5446_state - driver instance specific data
|
||||
* @indio_dev: the industrial I/O device
|
||||
* @spi: spi_device
|
||||
* @chip_info: chip model specific constants, available modes etc
|
||||
* @reg: supply regulator
|
||||
* @poll_work: bottom half of polling interrupt handler
|
||||
* @vref_mv: actual reference voltage used
|
||||
* @xfer: default spi transfer
|
||||
* @msg: default spi message
|
||||
* @data: spi transmit buffer
|
||||
*/
|
||||
|
||||
struct ad5446_state {
|
||||
struct iio_dev *indio_dev;
|
||||
@ -33,14 +49,50 @@ struct ad5446_state {
|
||||
unsigned short vref_mv;
|
||||
struct spi_transfer xfer;
|
||||
struct spi_message msg;
|
||||
unsigned short data;
|
||||
union {
|
||||
unsigned short d16;
|
||||
unsigned char d24[3];
|
||||
} data;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ad5446_chip_info - chip specifc information
|
||||
* @bits: accuracy of the DAC in bits
|
||||
* @storagebits: number of bits written to the DAC
|
||||
* @left_shift: number of bits the datum must be shifted
|
||||
* @sign: data representation [s]igned or [u]nsigned
|
||||
* @int_vref_mv: AD5620/40/60: the internal reference voltage
|
||||
* @store_sample: chip specifc helper function to store the datum
|
||||
*/
|
||||
|
||||
struct ad5446_chip_info {
|
||||
u8 bits;
|
||||
u8 storagebits;
|
||||
u8 left_shift;
|
||||
char sign;
|
||||
u16 int_vref_mv;
|
||||
void (*store_sample) (struct ad5446_state *st, unsigned val);
|
||||
};
|
||||
|
||||
/**
|
||||
* ad5446_supported_device_ids:
|
||||
* The AD5620/40/60 parts are available in different fixed internal reference
|
||||
* voltage options. The actual part numbers may look differently
|
||||
* (and a bit cryptic), however this style is used to make clear which
|
||||
* parts are supported here.
|
||||
*/
|
||||
|
||||
enum ad5446_supported_device_ids {
|
||||
ID_AD5444,
|
||||
ID_AD5446,
|
||||
ID_AD5542A,
|
||||
ID_AD5512A,
|
||||
ID_AD5620_2500,
|
||||
ID_AD5620_1250,
|
||||
ID_AD5640_2500,
|
||||
ID_AD5640_1250,
|
||||
ID_AD5660_2500,
|
||||
ID_AD5660_1250,
|
||||
};
|
||||
|
||||
#endif /* IIO_ADC_AD5446_H_ */
|
||||
#endif /* IIO_DAC_AD5446_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user