[PATCH 1/2] staging: iio: adc: ad7192: Add clock for external clock reference
This patch adds a clock to the state structure of ad7192 for getting the external clock frequency. This modifications is in accordance with clock framework dt bindings documentation. Signed-off-by: Mircea Caprioru --- drivers/staging/iio/adc/ad7192.c | 74 +--- drivers/staging/iio/adc/ad7192.h | 2 - 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index acdbc07fd259..8a4e6ede42b3 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -6,6 +6,7 @@ * Licensed under the GPL-2. */ +#include #include #include #include @@ -156,8 +157,9 @@ struct ad7192_state { struct regulator*avdd; struct regulator*dvdd; + struct clk *mclk; u16 int_vref_mv; - u32 mclk; + u32 fclk; u32 f_order; u32 mode; u32 conf; @@ -165,6 +167,7 @@ struct ad7192_state { u8 gpocon; u8 devid; struct mutexlock; /* protect sensor state */ + u8 clock_sel; struct ad_sigma_delta sd; }; @@ -250,28 +253,8 @@ static int ad7192_setup(struct ad7192_state *st, dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X)\n", id); - switch (pdata->clock_source_sel) { - case AD7192_CLK_INT: - case AD7192_CLK_INT_CO: - st->mclk = AD7192_INT_FREQ_MHZ; - break; - case AD7192_CLK_EXT_MCLK1_2: - case AD7192_CLK_EXT_MCLK2: - if (ad7192_valid_external_frequency(pdata->ext_clk_hz)) { - st->mclk = pdata->ext_clk_hz; - break; - } - dev_err(&st->sd.spi->dev, "Invalid frequency setting %u\n", - pdata->ext_clk_hz); - ret = -EINVAL; - goto out; - default: - ret = -EINVAL; - goto out; - } - st->mode = AD7192_MODE_SEL(AD7192_MODE_IDLE) | - AD7192_MODE_CLKSRC(pdata->clock_source_sel) | + AD7192_MODE_CLKSRC(st->clock_sel) | AD7192_MODE_RATE(480); st->conf = AD7192_CONF_GAIN(0); @@ -499,7 +482,7 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, *val -= 273 * ad7192_get_temp_scale(unipolar); return IIO_VAL_INT; case IIO_CHAN_INFO_SAMP_FREQ: - *val = st->mclk / + *val = st->fclk / (st->f_order * 1024 * AD7192_MODE_RATE(st->mode)); return IIO_VAL_INT; } @@ -546,7 +529,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, break; } - div = st->mclk / (val * st->f_order * 1024); + div = st->fclk / (val * st->f_order * 1024); if (div < 1 || div > 1023) { ret = -EINVAL; break; @@ -625,6 +608,42 @@ static const struct iio_chan_spec ad7193_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(14), }; +static int ad7192_clock_select(struct spi_device *spi, struct ad7192_state *st) +{ + int ret; + + st->clock_sel = AD7192_CLK_EXT_MCLK2; + st->mclk = devm_clk_get(&spi->dev, "clk"); + if (IS_ERR(st->mclk)) { + if (PTR_ERR(st->mclk) != -ENOENT) + return PTR_ERR(st->mclk); + + /* try xtal option */ + st->mclk = devm_clk_get(&spi->dev, "xtal"); + st->clock_sel = AD7192_CLK_EXT_MCLK1_2; + if (IS_ERR(st->mclk)) { + if (PTR_ERR(st->mclk) != -ENOENT) + return PTR_ERR(st->mclk); + + /* use internal clock */ + st->clock_sel = AD7192_CLK_INT; + st->fclk = AD7192_INT_FREQ_MHZ; + } + } + if (st->clock_sel == AD7192_CLK_EXT_MCLK2 || + st->clock_sel == AD7192_CLK_EXT_MCLK1_2) { + ret = clk_prepare_enable(st->mclk); + if (ret < 0) + return ret; + + st->fclk = clk_get_rate(st->mclk); + if (!ad7192_valid_external_frequency(st->fclk)) + return -EINVAL; + } + + return 0; +} + static int ad7192_probe(struct spi_device *spi) { const struct a
[PATCH 2/2] staging: iio: adc: ad7192: Add clock output option
When using the internal clock the device has an option in which the clock output is available on MCLK2 pin. This patch adds a dt binding for enabling this property. Signed-off-by: Mircea Caprioru --- drivers/staging/iio/adc/ad7192.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 8a4e6ede42b3..a11c8a82bb7c 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -611,6 +611,10 @@ static const struct iio_chan_spec ad7193_channels[] = { static int ad7192_clock_select(struct spi_device *spi, struct ad7192_state *st) { int ret; + bool clock_out_en; + + clock_out_en = of_property_read_bool(spi->dev.of_node, +"adi,int-clock-output-enable"); st->clock_sel = AD7192_CLK_EXT_MCLK2; st->mclk = devm_clk_get(&spi->dev, "clk"); @@ -626,7 +630,10 @@ static int ad7192_clock_select(struct spi_device *spi, struct ad7192_state *st) return PTR_ERR(st->mclk); /* use internal clock */ - st->clock_sel = AD7192_CLK_INT; + if (!clock_out_en) + st->clock_sel = AD7192_CLK_INT; + else + st->clock_sel = AD7192_CLK_INT_CO; st->fclk = AD7192_INT_FREQ_MHZ; } } -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] iio:dac:ad5686: Add AD5310R support
From: Stefan Popa The AD5310R is a single channel DAC with 10-bit precision, which is part of the same family as AD5311R, except that it uses the spi interface instead of i2c. The device has a built-in 2.5V reference which is enabled by default. Another important difference is that the SPI write command operation is 16 bits long. The first four bits represent the command, while the remaining 12 bits are for data. In the control reg, DB9 and DB10 are used for power-down modes, while DB8 is the REF bit. In order to accommodate this change, a new regmap type was defined and checked accordingly. Because AD5310R does not have a readback register, the read_raw operation will return "Operation is not supported". Datasheet: Link: http://www.analog.com/media/en/technical-documentation/data-sheets/AD5310R_5311R.pdf Signed-off-by: Stefan Popa Signed-off-by: Mircea Caprioru --- drivers/iio/dac/ad5686-spi.c | 21 ++--- drivers/iio/dac/ad5686.c | 16 drivers/iio/dac/ad5686.h | 7 +++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c index 1df9143f55e9..665fa6bd9ced 100644 --- a/drivers/iio/dac/ad5686-spi.c +++ b/drivers/iio/dac/ad5686-spi.c @@ -19,6 +19,12 @@ static int ad5686_spi_write(struct ad5686_state *st, u8 tx_len, *buf; switch (st->chip_info->regmap_type) { + case AD5310_REGMAP: + st->data[0].d16 = cpu_to_be16(AD5310_CMD(cmd) | + val); + buf = &st->data[0].d8[0]; + tx_len = 2; + break; case AD5683_REGMAP: st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | AD5683_DATA(val)); @@ -56,10 +62,18 @@ static int ad5686_spi_read(struct ad5686_state *st, u8 addr) u8 cmd = 0; int ret; - if (st->chip_info->regmap_type == AD5686_REGMAP) - cmd = AD5686_CMD_READBACK_ENABLE; - else if (st->chip_info->regmap_type == AD5683_REGMAP) + switch (st->chip_info->regmap_type) { + case AD5310_REGMAP: + return -ENOTSUPP; + case AD5683_REGMAP: cmd = AD5686_CMD_READBACK_ENABLE_V2; + break; + case AD5686_REGMAP: + cmd = AD5686_CMD_READBACK_ENABLE; + break; + default: + return -EINVAL; + } st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | AD5686_ADDR(addr)); @@ -86,6 +100,7 @@ static int ad5686_spi_remove(struct spi_device *spi) } static const struct spi_device_id ad5686_spi_id[] = { + {"ad5310r", ID_AD5310R}, {"ad5672r", ID_AD5672R}, {"ad5676", ID_AD5676}, {"ad5676r", ID_AD5676R}, diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 0e134b13967a..54ff76b93366 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -83,6 +83,10 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, st->pwr_down_mask &= ~(0x3 << (chan->channel * 2)); switch (st->chip_info->regmap_type) { + case AD5310_REGMAP: + shift = 9; + ref_bit_msk = AD5310_REF_BIT_MSK; + break; case AD5683_REGMAP: shift = 13; ref_bit_msk = AD5683_REF_BIT_MSK; @@ -221,6 +225,7 @@ static struct iio_chan_spec name[] = { \ AD5868_CHANNEL(7, 7, bits, _shift), \ } +DECLARE_AD5693_CHANNELS(ad5310r_channels, 10, 2); DECLARE_AD5693_CHANNELS(ad5311r_channels, 10, 6); DECLARE_AD5676_CHANNELS(ad5672_channels, 12, 4); DECLARE_AD5676_CHANNELS(ad5676_channels, 16, 0); @@ -232,6 +237,12 @@ DECLARE_AD5693_CHANNELS(ad5692r_channels, 14, 2); DECLARE_AD5693_CHANNELS(ad5691r_channels, 12, 4); static const struct ad5686_chip_info ad5686_chip_info_tbl[] = { + [ID_AD5310R] = { + .channels = ad5310r_channels, + .int_vref_mv = 2500, + .num_channels = 1, + .regmap_type = AD5310_REGMAP, + }, [ID_AD5311R] = { .channels = ad5311r_channels, .int_vref_mv = 2500, @@ -419,6 +430,11 @@ int ad5686_probe(struct device *dev, indio_dev->num_channels = st->chip_info->num_channels; switch (st->chip_info->regmap_type) { + case AD5310_REGMAP: + cmd = AD5686_CMD_CONTROL_REG; + ref_bit_msk = AD5310_REF_BIT_MSK; + st->use_internal_vref = !voltage_uv; + break; case AD5683_REGMAP: cmd = AD5686_CMD_CONTROL_REG; ref_bit_msk = AD5683_REF_BIT_MSK; diff --git a/drivers/iio/dac/ad5686.h b/drivers/iio/
[PATCH] iio: dac: ad5686: fix bit shift read register
This patch solves the register readback issue with the bit shift. When the dac resolution was lower than the register size (ex. 12 bits out of 16 bits) the readback value was not shifted with the difference in bits and the value was higher. Also a mask is applied on the read value in order to get the value relative to the actual bit size. Fixes: 0357e488b8 ("iio:dac:ad5686: Refactor the driver") Signed-off-by: Mircea Caprioru --- drivers/iio/dac/ad5686.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 54ff76b93366..a332b93ca2c4 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -128,7 +128,8 @@ static int ad5686_read_raw(struct iio_dev *indio_dev, mutex_unlock(&indio_dev->mlock); if (ret < 0) return ret; - *val = ret; + *val = (ret >> chan->scan_type.shift) & + GENMASK(chan->scan_type.realbits - 1, 0); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = st->vref_mv; -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel