The ad7798 and ad7799 are similar to the ad7792 and ad7793 but are missing some features like the temperature sensor, being able to use an external clocksource and a few other things. This patch adds a new 'flags' fields to the chip_info struct which allows to specify which features a certain chip variant supports. The setup code will then ignore any platform data fields which are related to non supported features. Signed-off-by: Lars-Peter Clausen <lars@xxxxxxxxxx> --- drivers/iio/adc/ad7793.c | 116 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 14 deletions(-) diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index 8bcda5d..4a7ee0b 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -106,6 +106,8 @@ #define AD7793_ID 0xB #define AD7794_ID 0xF #define AD7795_ID 0xF +#define AD7798_ID 0x8 +#define AD7799_ID 0x9 #define AD7793_ID_MASK 0xF /* IO (Excitation Current Sources) Register Bit Designations (AD7793_REG_IO) */ @@ -130,10 +132,16 @@ * The DOUT/RDY output must also be wired to an interrupt capable GPIO. */ +#define AD7793_FLAG_HAS_CLKSEL BIT(0) +#define AD7793_FLAG_HAS_REFSEL BIT(1) +#define AD7793_FLAG_HAS_VBIAS BIT(2) +#define AD7793_HAS_EXITATION_CURRENT BIT(3) + struct ad7793_chip_info { unsigned int id; const struct iio_chan_spec *channels; unsigned int num_channels; + unsigned int flags; }; struct ad7793_state { @@ -154,6 +162,8 @@ enum ad7793_supported_device_ids { ID_AD7793, ID_AD7794, ID_AD7795, + ID_AD7798, + ID_AD7799, }; static struct ad7793_state *ad_sigma_delta_to_ad7793(struct ad_sigma_delta *sd) @@ -205,6 +215,34 @@ static int ad7793_calibrate_all(struct ad7793_state *st) ARRAY_SIZE(ad7793_calib_arr)); } +static int ad7793_check_platform_data(struct ad7793_state *st, + const struct ad7793_platform_data *pdata) +{ + if ((pdata->current_source_direction == AD7793_IEXEC1_IEXEC2_IOUT1 || + pdata->current_source_direction == AD7793_IEXEC1_IEXEC2_IOUT2) && + ((pdata->exitation_current != AD7793_IX_10uA) && + (pdata->exitation_current != AD7793_IX_210uA))) + return -EINVAL; + + if (!(st->chip_info->flags & AD7793_FLAG_HAS_CLKSEL) && + pdata->clock_src != AD7793_CLK_SRC_INT) + return -EINVAL; + + if (!(st->chip_info->flags & AD7793_FLAG_HAS_REFSEL) && + pdata->refsel != AD7793_REFSEL_REFIN1) + return -EINVAL; + + if (!(st->chip_info->flags & AD7793_FLAG_HAS_VBIAS) && + pdata->bias_voltage != AD7793_BIAS_VOLTAGE_DISABLED) + return -EINVAL; + + if (!(st->chip_info->flags & AD7793_HAS_EXITATION_CURRENT) && + pdata->exitation_current != AD7793_IX_DISABLED) + return -EINVAL; + + return 0; +} + static int ad7793_setup(struct iio_dev *indio_dev, const struct ad7793_platform_data *pdata, unsigned int vref_mv) @@ -214,11 +252,9 @@ static int ad7793_setup(struct iio_dev *indio_dev, unsigned long long scale_uv; u32 id; - if ((pdata->current_source_direction == AD7793_IEXEC1_IEXEC2_IOUT1 || - pdata->current_source_direction == AD7793_IEXEC1_IEXEC2_IOUT2) && - ((pdata->exitation_current != AD7793_IX_10uA) && - (pdata->exitation_current != AD7793_IX_210uA))) - return -EINVAL; + ret = ad7793_check_platform_data(st, pdata); + if (ret) + return ret; /* reset the serial interface */ ret = spi_write(st->sd.spi, (u8 *)&ret, sizeof(ret)); @@ -239,12 +275,18 @@ static int ad7793_setup(struct iio_dev *indio_dev, } st->mode = AD7793_MODE_RATE(1); - st->mode |= AD7793_MODE_CLKSRC(pdata->clock_src); - st->conf = AD7793_CONF_REFSEL(pdata->refsel); - st->conf |= AD7793_CONF_VBIAS(pdata->bias_voltage); + st->conf = 0; + + if (st->chip_info->flags & AD7793_FLAG_HAS_CLKSEL) + st->mode |= AD7793_MODE_CLKSRC(pdata->clock_src); + if (st->chip_info->flags & AD7793_FLAG_HAS_REFSEL) + st->conf |= AD7793_CONF_REFSEL(pdata->refsel); + if (st->chip_info->flags & AD7793_FLAG_HAS_VBIAS) + st->conf |= AD7793_CONF_VBIAS(pdata->bias_voltage); if (pdata->buffered) st->conf |= AD7793_CONF_BUF; - if (pdata->boost_enable) + if (pdata->boost_enable && + (st->chip_info->flags & AD7793_FLAG_HAS_VBIAS)) st->conf |= AD7793_CONF_BOOST; if (pdata->burnout_current) st->conf |= AD7793_CONF_BO_EN; @@ -259,11 +301,13 @@ static int ad7793_setup(struct iio_dev *indio_dev, if (ret) goto out; - ret = ad_sd_write_reg(&st->sd, AD7793_REG_IO, 1, - pdata->exitation_current | - (pdata->current_source_direction << 2)); - if (ret) - goto out; + if (st->chip_info->flags & AD7793_HAS_EXITATION_CURRENT) { + ret = ad_sd_write_reg(&st->sd, AD7793_REG_IO, 1, + pdata->exitation_current | + (pdata->current_source_direction << 2)); + if (ret) + goto out; + } ret = ad7793_calibrate_all(st); if (ret) @@ -525,37 +569,79 @@ const struct iio_chan_spec _name##_channels[] = { \ IIO_CHAN_SOFT_TIMESTAMP(9), \ } +#define DECLARE_AD7799_CHANNELS(_name, _b, _sb) \ +const struct iio_chan_spec _name##_channels[] = { \ + AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \ + AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \ + AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \ + AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \ + AD_SD_SUPPLY_CHANNEL(4, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \ + IIO_CHAN_SOFT_TIMESTAMP(5), \ +} + static DECLARE_AD7793_CHANNELS(ad7785, 20, 32, 4); static DECLARE_AD7793_CHANNELS(ad7792, 16, 32, 0); static DECLARE_AD7793_CHANNELS(ad7793, 24, 32, 0); static DECLARE_AD7795_CHANNELS(ad7794, 16, 32); static DECLARE_AD7795_CHANNELS(ad7795, 24, 32); +static DECLARE_AD7799_CHANNELS(ad7798, 16, 16); +static DECLARE_AD7799_CHANNELS(ad7799, 24, 32); static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { [ID_AD7785] = { .id = AD7785_ID, .channels = ad7785_channels, .num_channels = ARRAY_SIZE(ad7785_channels), + .flags = AD7793_FLAG_HAS_CLKSEL | + AD7793_FLAG_HAS_REFSEL | + AD7793_FLAG_HAS_VBIAS | + AD7793_HAS_EXITATION_CURRENT, }, [ID_AD7792] = { .id = AD7792_ID, .channels = ad7792_channels, .num_channels = ARRAY_SIZE(ad7792_channels), + .flags = AD7793_FLAG_HAS_CLKSEL | + AD7793_FLAG_HAS_REFSEL | + AD7793_FLAG_HAS_VBIAS | + AD7793_HAS_EXITATION_CURRENT, }, [ID_AD7793] = { .id = AD7793_ID, .channels = ad7793_channels, .num_channels = ARRAY_SIZE(ad7793_channels), + .flags = AD7793_FLAG_HAS_CLKSEL | + AD7793_FLAG_HAS_REFSEL | + AD7793_FLAG_HAS_VBIAS | + AD7793_HAS_EXITATION_CURRENT, }, [ID_AD7794] = { .id = AD7794_ID, .channels = ad7794_channels, .num_channels = ARRAY_SIZE(ad7794_channels), + .flags = AD7793_FLAG_HAS_CLKSEL | + AD7793_FLAG_HAS_REFSEL | + AD7793_FLAG_HAS_VBIAS | + AD7793_HAS_EXITATION_CURRENT, }, [ID_AD7795] = { .id = AD7795_ID, .channels = ad7795_channels, .num_channels = ARRAY_SIZE(ad7795_channels), + .flags = AD7793_FLAG_HAS_CLKSEL | + AD7793_FLAG_HAS_REFSEL | + AD7793_FLAG_HAS_VBIAS | + AD7793_HAS_EXITATION_CURRENT, + }, + [ID_AD7798] = { + .id = AD7798_ID, + .channels = ad7798_channels, + .num_channels = ARRAY_SIZE(ad7798_channels), + }, + [ID_AD7799] = { + .id = AD7799_ID, + .channels = ad7799_channels, + .num_channels = ARRAY_SIZE(ad7799_channels), }, }; @@ -671,6 +757,8 @@ static const struct spi_device_id ad7793_id[] = { {"ad7793", ID_AD7793}, {"ad7794", ID_AD7794}, {"ad7795", ID_AD7795}, + {"ad7798", ID_AD7798}, + {"ad7799", ID_AD7799}, {} }; MODULE_DEVICE_TABLE(spi, ad7793_id); -- 1.8.0 -- To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html