Re: [PATCH v2 1/3] iio: adc: add support for mcp3911
Hi Jonathan, Sorry for the delay, I've been away from keyboard for a few days. On Sun, Jul 29, 2018 at 12:44:22PM +0100, Jonathan Cameron wrote: > On Tue, 24 Jul 2018 20:30:02 +0200 > Marcus Folkesson wrote: > > > MCP3911 is a dual channel Analog Front End (AFE) containing two > > synchronous sampling delta-sigma Analog-to-Digital Converters (ADC). > > > > Signed-off-by: Marcus Folkesson > > Signed-off-by: Kent Gustavsson > Hi > > I think you missed cleaning up the clock enable in the remove. > If it is safe to not do so it should also be safe in the error path > of probe. I've actually noticed this and had it prepared in v4 :-) > > A couple of trivial other things jumped out at me whilst reading. Thank you so much, I will fix these. > > Thanks, > > Jonathan > > --- > > > > Notes: > > v2: > > - cleanups and bugfixes (thanks Peter Meerwald-Stadler) > > - drop hardware gain > > - use the presence or lack of regulator to indicate if we go > > for internal or external voltage reference > > - do not store device node in private struct > > - drop support to set width in devicetree > > - use the presence or lack of clock to indicate if we go for > > internal or external clock > > > > drivers/iio/adc/Kconfig | 10 ++ > > drivers/iio/adc/Makefile | 1 + > > drivers/iio/adc/mcp3911.c | 366 > > ++ > > 3 files changed, 377 insertions(+) > > create mode 100644 drivers/iio/adc/mcp3911.c > > > > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig > > index 15606f237480..f9a41fa96fcc 100644 > > --- a/drivers/iio/adc/Kconfig > > +++ b/drivers/iio/adc/Kconfig > > @@ -501,6 +501,16 @@ config MCP3422 > > This driver can also be built as a module. If so, the module will be > > called mcp3422. > > > > +config MCP3911 > > + tristate "Microchip Technology MCP3911 driver" > > + depends on SPI > > + help > > + Say yes here to build support for Microchip Technology's MCP3911 > > + analog to digital converter. > > + > > + This driver can also be built as a module. If so, the module will be > > + called mcp3911. > > + > > config MEDIATEK_MT6577_AUXADC > > tristate "MediaTek AUXADC driver" > > depends on ARCH_MEDIATEK || COMPILE_TEST > > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile > > index 28a9423997f3..3cfebfff7d26 100644 > > --- a/drivers/iio/adc/Makefile > > +++ b/drivers/iio/adc/Makefile > > @@ -47,6 +47,7 @@ obj-$(CONFIG_MAX1363) += max1363.o > > obj-$(CONFIG_MAX9611) += max9611.o > > obj-$(CONFIG_MCP320X) += mcp320x.o > > obj-$(CONFIG_MCP3422) += mcp3422.o > > +obj-$(CONFIG_MCP3911) += mcp3911.o > > obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o > > obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o > > obj-$(CONFIG_MESON_SARADC) += meson_saradc.o > > diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c > > new file mode 100644 > > index ..29aa39930ead > > --- /dev/null > > +++ b/drivers/iio/adc/mcp3911.c > > @@ -0,0 +1,366 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Driver for Microchip MCP3911, Two-channel Analog Front End > > + * > > + * Copyright (C) 2018 Marcus Folkesson > > + * Copyright (C) 2018 Kent Gustavsson > > + * > > + */ > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define MCP3911_REG_CHANNEL0 0x00 > > +#define MCP3911_REG_CHANNEL1 0x03 > > +#define MCP3911_REG_MOD0x06 > > +#define MCP3911_REG_PHASE 0x07 > > +#define MCP3911_REG_GAIN 0x09 > > + > > +#define MCP3911_REG_STATUSCOM 0x0a > > +#define MCP3911_STATUSCOM_CH1_24WIDTH BIT(4) > > +#define MCP3911_STATUSCOM_CH0_24WIDTH BIT(3) > > +#define MCP3911_STATUSCOM_EN_OFFCALBIT(2) > > +#define MCP3911_STATUSCOM_EN_GAINCAL BIT(1) > > + > > +#define MCP3911_REG_CONFIG 0x0c > > +#define MCP3911_CONFIG_CLKEXT BIT(1) > > +#define MCP3911_CONFIG_VREFEXT BIT(2) > > + > > +#define MCP3911_REG_OFFCAL_CH0 0x0e > > +#define MCP3911_REG_GAINCAL_CH00x11 > > +#define MCP3911_REG_OFFCAL_CH1 0x14 > > +#define MCP3911_REG_GAINCAL_CH10x17 > > +#define MCP3911_REG_VREFCAL0x1a > > + > > +#define MCP3911_CHANNEL(x) (MCP3911_REG_CHANNEL0 + x * 3) > > +#define MCP3911_OFFCAL(x) (MCP3911_REG_OFFCAL_CH0 + x * 6) > > + > > +/* Internal voltage reference in uV */ > > +#define MCP3911_INT_VREF_UV120 > > + > > +#define MCP3911_REG_READ(reg, id) reg) << 1) | ((id) << 5) | (1 << > > 0)) & 0xff) > > +#define MCP3911_REG_WRITE(reg, id) reg) << 1) | ((id) << 5) | (0 << > > 0)) & 0xff) > > + > > +#define MCP3911_NUM_CHANNELS 2 > > + > > +struct mcp3911 { > > + struct spi_device *spi; > >
Re: [PATCH v2 1/3] iio: adc: add support for mcp3911
Hi Jonathan, Sorry for the delay, I've been away from keyboard for a few days. On Sun, Jul 29, 2018 at 12:44:22PM +0100, Jonathan Cameron wrote: > On Tue, 24 Jul 2018 20:30:02 +0200 > Marcus Folkesson wrote: > > > MCP3911 is a dual channel Analog Front End (AFE) containing two > > synchronous sampling delta-sigma Analog-to-Digital Converters (ADC). > > > > Signed-off-by: Marcus Folkesson > > Signed-off-by: Kent Gustavsson > Hi > > I think you missed cleaning up the clock enable in the remove. > If it is safe to not do so it should also be safe in the error path > of probe. I've actually noticed this and had it prepared in v4 :-) > > A couple of trivial other things jumped out at me whilst reading. Thank you so much, I will fix these. > > Thanks, > > Jonathan > > --- > > > > Notes: > > v2: > > - cleanups and bugfixes (thanks Peter Meerwald-Stadler) > > - drop hardware gain > > - use the presence or lack of regulator to indicate if we go > > for internal or external voltage reference > > - do not store device node in private struct > > - drop support to set width in devicetree > > - use the presence or lack of clock to indicate if we go for > > internal or external clock > > > > drivers/iio/adc/Kconfig | 10 ++ > > drivers/iio/adc/Makefile | 1 + > > drivers/iio/adc/mcp3911.c | 366 > > ++ > > 3 files changed, 377 insertions(+) > > create mode 100644 drivers/iio/adc/mcp3911.c > > > > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig > > index 15606f237480..f9a41fa96fcc 100644 > > --- a/drivers/iio/adc/Kconfig > > +++ b/drivers/iio/adc/Kconfig > > @@ -501,6 +501,16 @@ config MCP3422 > > This driver can also be built as a module. If so, the module will be > > called mcp3422. > > > > +config MCP3911 > > + tristate "Microchip Technology MCP3911 driver" > > + depends on SPI > > + help > > + Say yes here to build support for Microchip Technology's MCP3911 > > + analog to digital converter. > > + > > + This driver can also be built as a module. If so, the module will be > > + called mcp3911. > > + > > config MEDIATEK_MT6577_AUXADC > > tristate "MediaTek AUXADC driver" > > depends on ARCH_MEDIATEK || COMPILE_TEST > > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile > > index 28a9423997f3..3cfebfff7d26 100644 > > --- a/drivers/iio/adc/Makefile > > +++ b/drivers/iio/adc/Makefile > > @@ -47,6 +47,7 @@ obj-$(CONFIG_MAX1363) += max1363.o > > obj-$(CONFIG_MAX9611) += max9611.o > > obj-$(CONFIG_MCP320X) += mcp320x.o > > obj-$(CONFIG_MCP3422) += mcp3422.o > > +obj-$(CONFIG_MCP3911) += mcp3911.o > > obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o > > obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o > > obj-$(CONFIG_MESON_SARADC) += meson_saradc.o > > diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c > > new file mode 100644 > > index ..29aa39930ead > > --- /dev/null > > +++ b/drivers/iio/adc/mcp3911.c > > @@ -0,0 +1,366 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Driver for Microchip MCP3911, Two-channel Analog Front End > > + * > > + * Copyright (C) 2018 Marcus Folkesson > > + * Copyright (C) 2018 Kent Gustavsson > > + * > > + */ > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define MCP3911_REG_CHANNEL0 0x00 > > +#define MCP3911_REG_CHANNEL1 0x03 > > +#define MCP3911_REG_MOD0x06 > > +#define MCP3911_REG_PHASE 0x07 > > +#define MCP3911_REG_GAIN 0x09 > > + > > +#define MCP3911_REG_STATUSCOM 0x0a > > +#define MCP3911_STATUSCOM_CH1_24WIDTH BIT(4) > > +#define MCP3911_STATUSCOM_CH0_24WIDTH BIT(3) > > +#define MCP3911_STATUSCOM_EN_OFFCALBIT(2) > > +#define MCP3911_STATUSCOM_EN_GAINCAL BIT(1) > > + > > +#define MCP3911_REG_CONFIG 0x0c > > +#define MCP3911_CONFIG_CLKEXT BIT(1) > > +#define MCP3911_CONFIG_VREFEXT BIT(2) > > + > > +#define MCP3911_REG_OFFCAL_CH0 0x0e > > +#define MCP3911_REG_GAINCAL_CH00x11 > > +#define MCP3911_REG_OFFCAL_CH1 0x14 > > +#define MCP3911_REG_GAINCAL_CH10x17 > > +#define MCP3911_REG_VREFCAL0x1a > > + > > +#define MCP3911_CHANNEL(x) (MCP3911_REG_CHANNEL0 + x * 3) > > +#define MCP3911_OFFCAL(x) (MCP3911_REG_OFFCAL_CH0 + x * 6) > > + > > +/* Internal voltage reference in uV */ > > +#define MCP3911_INT_VREF_UV120 > > + > > +#define MCP3911_REG_READ(reg, id) reg) << 1) | ((id) << 5) | (1 << > > 0)) & 0xff) > > +#define MCP3911_REG_WRITE(reg, id) reg) << 1) | ((id) << 5) | (0 << > > 0)) & 0xff) > > + > > +#define MCP3911_NUM_CHANNELS 2 > > + > > +struct mcp3911 { > > + struct spi_device *spi; > >
Re: [PATCH v2 1/3] iio: adc: add support for mcp3911
On Tue, 24 Jul 2018 20:30:02 +0200 Marcus Folkesson wrote: > MCP3911 is a dual channel Analog Front End (AFE) containing two > synchronous sampling delta-sigma Analog-to-Digital Converters (ADC). > > Signed-off-by: Marcus Folkesson > Signed-off-by: Kent Gustavsson Hi I think you missed cleaning up the clock enable in the remove. If it is safe to not do so it should also be safe in the error path of probe. A couple of trivial other things jumped out at me whilst reading. Thanks, Jonathan > --- > > Notes: > v2: > - cleanups and bugfixes (thanks Peter Meerwald-Stadler) > - drop hardware gain > - use the presence or lack of regulator to indicate if we go for > internal or external voltage reference > - do not store device node in private struct > - drop support to set width in devicetree > - use the presence or lack of clock to indicate if we go for internal > or external clock > > drivers/iio/adc/Kconfig | 10 ++ > drivers/iio/adc/Makefile | 1 + > drivers/iio/adc/mcp3911.c | 366 > ++ > 3 files changed, 377 insertions(+) > create mode 100644 drivers/iio/adc/mcp3911.c > > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig > index 15606f237480..f9a41fa96fcc 100644 > --- a/drivers/iio/adc/Kconfig > +++ b/drivers/iio/adc/Kconfig > @@ -501,6 +501,16 @@ config MCP3422 > This driver can also be built as a module. If so, the module will be > called mcp3422. > > +config MCP3911 > + tristate "Microchip Technology MCP3911 driver" > + depends on SPI > + help > + Say yes here to build support for Microchip Technology's MCP3911 > + analog to digital converter. > + > + This driver can also be built as a module. If so, the module will be > + called mcp3911. > + > config MEDIATEK_MT6577_AUXADC > tristate "MediaTek AUXADC driver" > depends on ARCH_MEDIATEK || COMPILE_TEST > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile > index 28a9423997f3..3cfebfff7d26 100644 > --- a/drivers/iio/adc/Makefile > +++ b/drivers/iio/adc/Makefile > @@ -47,6 +47,7 @@ obj-$(CONFIG_MAX1363) += max1363.o > obj-$(CONFIG_MAX9611) += max9611.o > obj-$(CONFIG_MCP320X) += mcp320x.o > obj-$(CONFIG_MCP3422) += mcp3422.o > +obj-$(CONFIG_MCP3911) += mcp3911.o > obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o > obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o > obj-$(CONFIG_MESON_SARADC) += meson_saradc.o > diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c > new file mode 100644 > index ..29aa39930ead > --- /dev/null > +++ b/drivers/iio/adc/mcp3911.c > @@ -0,0 +1,366 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Driver for Microchip MCP3911, Two-channel Analog Front End > + * > + * Copyright (C) 2018 Marcus Folkesson > + * Copyright (C) 2018 Kent Gustavsson > + * > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define MCP3911_REG_CHANNEL0 0x00 > +#define MCP3911_REG_CHANNEL1 0x03 > +#define MCP3911_REG_MOD 0x06 > +#define MCP3911_REG_PHASE0x07 > +#define MCP3911_REG_GAIN 0x09 > + > +#define MCP3911_REG_STATUSCOM0x0a > +#define MCP3911_STATUSCOM_CH1_24WIDTHBIT(4) > +#define MCP3911_STATUSCOM_CH0_24WIDTHBIT(3) > +#define MCP3911_STATUSCOM_EN_OFFCAL BIT(2) > +#define MCP3911_STATUSCOM_EN_GAINCAL BIT(1) > + > +#define MCP3911_REG_CONFIG 0x0c > +#define MCP3911_CONFIG_CLKEXTBIT(1) > +#define MCP3911_CONFIG_VREFEXT BIT(2) > + > +#define MCP3911_REG_OFFCAL_CH0 0x0e > +#define MCP3911_REG_GAINCAL_CH0 0x11 > +#define MCP3911_REG_OFFCAL_CH1 0x14 > +#define MCP3911_REG_GAINCAL_CH1 0x17 > +#define MCP3911_REG_VREFCAL 0x1a > + > +#define MCP3911_CHANNEL(x) (MCP3911_REG_CHANNEL0 + x * 3) > +#define MCP3911_OFFCAL(x)(MCP3911_REG_OFFCAL_CH0 + x * 6) > + > +/* Internal voltage reference in uV */ > +#define MCP3911_INT_VREF_UV 120 > + > +#define MCP3911_REG_READ(reg, id)reg) << 1) | ((id) << 5) | (1 << > 0)) & 0xff) > +#define MCP3911_REG_WRITE(reg, id) reg) << 1) | ((id) << 5) | (0 << > 0)) & 0xff) > + > +#define MCP3911_NUM_CHANNELS 2 > + > +struct mcp3911 { > + struct spi_device *spi; > + struct mutex lock; > + struct regulator *vref; > + struct clk *adc_clk; > + u32 dev_addr; > +}; > + > +static int mcp3911_read(struct mcp3911 *adc, u8 reg, u32 *val, u8 len) > +{ > + int ret; > + > + reg = MCP3911_REG_READ(reg, adc->dev_addr); > + ret = spi_write_then_read(adc->spi, , 1, val, len); > + if (ret < 0) > + return ret; > + > + be32_to_cpus(val); > + *val >>= ((4 - len) * 8); > + dev_dbg(>spi->dev, "reading 0x%x from register 0x%x\n", *val, > +
Re: [PATCH v2 1/3] iio: adc: add support for mcp3911
On Tue, 24 Jul 2018 20:30:02 +0200 Marcus Folkesson wrote: > MCP3911 is a dual channel Analog Front End (AFE) containing two > synchronous sampling delta-sigma Analog-to-Digital Converters (ADC). > > Signed-off-by: Marcus Folkesson > Signed-off-by: Kent Gustavsson Hi I think you missed cleaning up the clock enable in the remove. If it is safe to not do so it should also be safe in the error path of probe. A couple of trivial other things jumped out at me whilst reading. Thanks, Jonathan > --- > > Notes: > v2: > - cleanups and bugfixes (thanks Peter Meerwald-Stadler) > - drop hardware gain > - use the presence or lack of regulator to indicate if we go for > internal or external voltage reference > - do not store device node in private struct > - drop support to set width in devicetree > - use the presence or lack of clock to indicate if we go for internal > or external clock > > drivers/iio/adc/Kconfig | 10 ++ > drivers/iio/adc/Makefile | 1 + > drivers/iio/adc/mcp3911.c | 366 > ++ > 3 files changed, 377 insertions(+) > create mode 100644 drivers/iio/adc/mcp3911.c > > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig > index 15606f237480..f9a41fa96fcc 100644 > --- a/drivers/iio/adc/Kconfig > +++ b/drivers/iio/adc/Kconfig > @@ -501,6 +501,16 @@ config MCP3422 > This driver can also be built as a module. If so, the module will be > called mcp3422. > > +config MCP3911 > + tristate "Microchip Technology MCP3911 driver" > + depends on SPI > + help > + Say yes here to build support for Microchip Technology's MCP3911 > + analog to digital converter. > + > + This driver can also be built as a module. If so, the module will be > + called mcp3911. > + > config MEDIATEK_MT6577_AUXADC > tristate "MediaTek AUXADC driver" > depends on ARCH_MEDIATEK || COMPILE_TEST > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile > index 28a9423997f3..3cfebfff7d26 100644 > --- a/drivers/iio/adc/Makefile > +++ b/drivers/iio/adc/Makefile > @@ -47,6 +47,7 @@ obj-$(CONFIG_MAX1363) += max1363.o > obj-$(CONFIG_MAX9611) += max9611.o > obj-$(CONFIG_MCP320X) += mcp320x.o > obj-$(CONFIG_MCP3422) += mcp3422.o > +obj-$(CONFIG_MCP3911) += mcp3911.o > obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o > obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o > obj-$(CONFIG_MESON_SARADC) += meson_saradc.o > diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c > new file mode 100644 > index ..29aa39930ead > --- /dev/null > +++ b/drivers/iio/adc/mcp3911.c > @@ -0,0 +1,366 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Driver for Microchip MCP3911, Two-channel Analog Front End > + * > + * Copyright (C) 2018 Marcus Folkesson > + * Copyright (C) 2018 Kent Gustavsson > + * > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define MCP3911_REG_CHANNEL0 0x00 > +#define MCP3911_REG_CHANNEL1 0x03 > +#define MCP3911_REG_MOD 0x06 > +#define MCP3911_REG_PHASE0x07 > +#define MCP3911_REG_GAIN 0x09 > + > +#define MCP3911_REG_STATUSCOM0x0a > +#define MCP3911_STATUSCOM_CH1_24WIDTHBIT(4) > +#define MCP3911_STATUSCOM_CH0_24WIDTHBIT(3) > +#define MCP3911_STATUSCOM_EN_OFFCAL BIT(2) > +#define MCP3911_STATUSCOM_EN_GAINCAL BIT(1) > + > +#define MCP3911_REG_CONFIG 0x0c > +#define MCP3911_CONFIG_CLKEXTBIT(1) > +#define MCP3911_CONFIG_VREFEXT BIT(2) > + > +#define MCP3911_REG_OFFCAL_CH0 0x0e > +#define MCP3911_REG_GAINCAL_CH0 0x11 > +#define MCP3911_REG_OFFCAL_CH1 0x14 > +#define MCP3911_REG_GAINCAL_CH1 0x17 > +#define MCP3911_REG_VREFCAL 0x1a > + > +#define MCP3911_CHANNEL(x) (MCP3911_REG_CHANNEL0 + x * 3) > +#define MCP3911_OFFCAL(x)(MCP3911_REG_OFFCAL_CH0 + x * 6) > + > +/* Internal voltage reference in uV */ > +#define MCP3911_INT_VREF_UV 120 > + > +#define MCP3911_REG_READ(reg, id)reg) << 1) | ((id) << 5) | (1 << > 0)) & 0xff) > +#define MCP3911_REG_WRITE(reg, id) reg) << 1) | ((id) << 5) | (0 << > 0)) & 0xff) > + > +#define MCP3911_NUM_CHANNELS 2 > + > +struct mcp3911 { > + struct spi_device *spi; > + struct mutex lock; > + struct regulator *vref; > + struct clk *adc_clk; > + u32 dev_addr; > +}; > + > +static int mcp3911_read(struct mcp3911 *adc, u8 reg, u32 *val, u8 len) > +{ > + int ret; > + > + reg = MCP3911_REG_READ(reg, adc->dev_addr); > + ret = spi_write_then_read(adc->spi, , 1, val, len); > + if (ret < 0) > + return ret; > + > + be32_to_cpus(val); > + *val >>= ((4 - len) * 8); > + dev_dbg(>spi->dev, "reading 0x%x from register 0x%x\n", *val, > +
[PATCH v2 1/3] iio: adc: add support for mcp3911
MCP3911 is a dual channel Analog Front End (AFE) containing two synchronous sampling delta-sigma Analog-to-Digital Converters (ADC). Signed-off-by: Marcus Folkesson Signed-off-by: Kent Gustavsson --- Notes: v2: - cleanups and bugfixes (thanks Peter Meerwald-Stadler) - drop hardware gain - use the presence or lack of regulator to indicate if we go for internal or external voltage reference - do not store device node in private struct - drop support to set width in devicetree - use the presence or lack of clock to indicate if we go for internal or external clock drivers/iio/adc/Kconfig | 10 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/mcp3911.c | 366 ++ 3 files changed, 377 insertions(+) create mode 100644 drivers/iio/adc/mcp3911.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 15606f237480..f9a41fa96fcc 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -501,6 +501,16 @@ config MCP3422 This driver can also be built as a module. If so, the module will be called mcp3422. +config MCP3911 + tristate "Microchip Technology MCP3911 driver" + depends on SPI + help + Say yes here to build support for Microchip Technology's MCP3911 + analog to digital converter. + + This driver can also be built as a module. If so, the module will be + called mcp3911. + config MEDIATEK_MT6577_AUXADC tristate "MediaTek AUXADC driver" depends on ARCH_MEDIATEK || COMPILE_TEST diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 28a9423997f3..3cfebfff7d26 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MAX9611) += max9611.o obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_MCP3422) += mcp3422.o +obj-$(CONFIG_MCP3911) += mcp3911.o obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o obj-$(CONFIG_MESON_SARADC) += meson_saradc.o diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c new file mode 100644 index ..29aa39930ead --- /dev/null +++ b/drivers/iio/adc/mcp3911.c @@ -0,0 +1,366 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Microchip MCP3911, Two-channel Analog Front End + * + * Copyright (C) 2018 Marcus Folkesson + * Copyright (C) 2018 Kent Gustavsson + * + */ +#include +#include +#include +#include +#include +#include +#include + +#define MCP3911_REG_CHANNEL0 0x00 +#define MCP3911_REG_CHANNEL1 0x03 +#define MCP3911_REG_MOD0x06 +#define MCP3911_REG_PHASE 0x07 +#define MCP3911_REG_GAIN 0x09 + +#define MCP3911_REG_STATUSCOM 0x0a +#define MCP3911_STATUSCOM_CH1_24WIDTH BIT(4) +#define MCP3911_STATUSCOM_CH0_24WIDTH BIT(3) +#define MCP3911_STATUSCOM_EN_OFFCALBIT(2) +#define MCP3911_STATUSCOM_EN_GAINCAL BIT(1) + +#define MCP3911_REG_CONFIG 0x0c +#define MCP3911_CONFIG_CLKEXT BIT(1) +#define MCP3911_CONFIG_VREFEXT BIT(2) + +#define MCP3911_REG_OFFCAL_CH0 0x0e +#define MCP3911_REG_GAINCAL_CH00x11 +#define MCP3911_REG_OFFCAL_CH1 0x14 +#define MCP3911_REG_GAINCAL_CH10x17 +#define MCP3911_REG_VREFCAL0x1a + +#define MCP3911_CHANNEL(x) (MCP3911_REG_CHANNEL0 + x * 3) +#define MCP3911_OFFCAL(x) (MCP3911_REG_OFFCAL_CH0 + x * 6) + +/* Internal voltage reference in uV */ +#define MCP3911_INT_VREF_UV120 + +#define MCP3911_REG_READ(reg, id) reg) << 1) | ((id) << 5) | (1 << 0)) & 0xff) +#define MCP3911_REG_WRITE(reg, id) reg) << 1) | ((id) << 5) | (0 << 0)) & 0xff) + +#define MCP3911_NUM_CHANNELS 2 + +struct mcp3911 { + struct spi_device *spi; + struct mutex lock; + struct regulator *vref; + struct clk *adc_clk; + u32 dev_addr; +}; + +static int mcp3911_read(struct mcp3911 *adc, u8 reg, u32 *val, u8 len) +{ + int ret; + + reg = MCP3911_REG_READ(reg, adc->dev_addr); + ret = spi_write_then_read(adc->spi, , 1, val, len); + if (ret < 0) + return ret; + + be32_to_cpus(val); + *val >>= ((4 - len) * 8); + dev_dbg(>spi->dev, "reading 0x%x from register 0x%x\n", *val, + reg>>1); + return ret; +} + +static int mcp3911_write(struct mcp3911 *adc, u8 reg, u32 val, u8 len) +{ + dev_dbg(>spi->dev, "writing 0x%x to register 0x%x\n", val, reg); + + val <<= (3 - len) * 8; + cpu_to_be32s(); + val |= MCP3911_REG_WRITE(reg, adc->dev_addr); + + return spi_write(adc->spi, , len+1); +} + +static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask, + u32 val, u8 len) +{ + u32 tmp; + int ret; + + ret =
[PATCH v2 1/3] iio: adc: add support for mcp3911
MCP3911 is a dual channel Analog Front End (AFE) containing two synchronous sampling delta-sigma Analog-to-Digital Converters (ADC). Signed-off-by: Marcus Folkesson Signed-off-by: Kent Gustavsson --- Notes: v2: - cleanups and bugfixes (thanks Peter Meerwald-Stadler) - drop hardware gain - use the presence or lack of regulator to indicate if we go for internal or external voltage reference - do not store device node in private struct - drop support to set width in devicetree - use the presence or lack of clock to indicate if we go for internal or external clock drivers/iio/adc/Kconfig | 10 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/mcp3911.c | 366 ++ 3 files changed, 377 insertions(+) create mode 100644 drivers/iio/adc/mcp3911.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 15606f237480..f9a41fa96fcc 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -501,6 +501,16 @@ config MCP3422 This driver can also be built as a module. If so, the module will be called mcp3422. +config MCP3911 + tristate "Microchip Technology MCP3911 driver" + depends on SPI + help + Say yes here to build support for Microchip Technology's MCP3911 + analog to digital converter. + + This driver can also be built as a module. If so, the module will be + called mcp3911. + config MEDIATEK_MT6577_AUXADC tristate "MediaTek AUXADC driver" depends on ARCH_MEDIATEK || COMPILE_TEST diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 28a9423997f3..3cfebfff7d26 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MAX9611) += max9611.o obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_MCP3422) += mcp3422.o +obj-$(CONFIG_MCP3911) += mcp3911.o obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o obj-$(CONFIG_MESON_SARADC) += meson_saradc.o diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c new file mode 100644 index ..29aa39930ead --- /dev/null +++ b/drivers/iio/adc/mcp3911.c @@ -0,0 +1,366 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Microchip MCP3911, Two-channel Analog Front End + * + * Copyright (C) 2018 Marcus Folkesson + * Copyright (C) 2018 Kent Gustavsson + * + */ +#include +#include +#include +#include +#include +#include +#include + +#define MCP3911_REG_CHANNEL0 0x00 +#define MCP3911_REG_CHANNEL1 0x03 +#define MCP3911_REG_MOD0x06 +#define MCP3911_REG_PHASE 0x07 +#define MCP3911_REG_GAIN 0x09 + +#define MCP3911_REG_STATUSCOM 0x0a +#define MCP3911_STATUSCOM_CH1_24WIDTH BIT(4) +#define MCP3911_STATUSCOM_CH0_24WIDTH BIT(3) +#define MCP3911_STATUSCOM_EN_OFFCALBIT(2) +#define MCP3911_STATUSCOM_EN_GAINCAL BIT(1) + +#define MCP3911_REG_CONFIG 0x0c +#define MCP3911_CONFIG_CLKEXT BIT(1) +#define MCP3911_CONFIG_VREFEXT BIT(2) + +#define MCP3911_REG_OFFCAL_CH0 0x0e +#define MCP3911_REG_GAINCAL_CH00x11 +#define MCP3911_REG_OFFCAL_CH1 0x14 +#define MCP3911_REG_GAINCAL_CH10x17 +#define MCP3911_REG_VREFCAL0x1a + +#define MCP3911_CHANNEL(x) (MCP3911_REG_CHANNEL0 + x * 3) +#define MCP3911_OFFCAL(x) (MCP3911_REG_OFFCAL_CH0 + x * 6) + +/* Internal voltage reference in uV */ +#define MCP3911_INT_VREF_UV120 + +#define MCP3911_REG_READ(reg, id) reg) << 1) | ((id) << 5) | (1 << 0)) & 0xff) +#define MCP3911_REG_WRITE(reg, id) reg) << 1) | ((id) << 5) | (0 << 0)) & 0xff) + +#define MCP3911_NUM_CHANNELS 2 + +struct mcp3911 { + struct spi_device *spi; + struct mutex lock; + struct regulator *vref; + struct clk *adc_clk; + u32 dev_addr; +}; + +static int mcp3911_read(struct mcp3911 *adc, u8 reg, u32 *val, u8 len) +{ + int ret; + + reg = MCP3911_REG_READ(reg, adc->dev_addr); + ret = spi_write_then_read(adc->spi, , 1, val, len); + if (ret < 0) + return ret; + + be32_to_cpus(val); + *val >>= ((4 - len) * 8); + dev_dbg(>spi->dev, "reading 0x%x from register 0x%x\n", *val, + reg>>1); + return ret; +} + +static int mcp3911_write(struct mcp3911 *adc, u8 reg, u32 val, u8 len) +{ + dev_dbg(>spi->dev, "writing 0x%x to register 0x%x\n", val, reg); + + val <<= (3 - len) * 8; + cpu_to_be32s(); + val |= MCP3911_REG_WRITE(reg, adc->dev_addr); + + return spi_write(adc->spi, , len+1); +} + +static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask, + u32 val, u8 len) +{ + u32 tmp; + int ret; + + ret =