#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,
}
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);
.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,
},
};
/* 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)
{"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},
{}
};
*
* 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 */
#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;
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_ */