Re: [PATCHv4] iio: adc: add driver for MCP3204/08 12-bit ADC
On 05/03/2013 11:00 AM, Lars-Peter Clausen wrote: > On 05/03/2013 11:58 AM, Oskar Andero wrote: >> This adds support for Microchip's 12 bit AD converters MCP3204 and >> MCP3208. These chips communicates over SPI and supports single-ended >> and pseudo-differential configurations. >> >> Cc: Jonathan Cameron >> Cc: Lars-Peter Clausen >> Signed-off-by: Oskar Andero > > Reviewed-by: Lars-Peter Clausen Nice driver. Thanks Oskar and thanks Lars-Peter for your review work on this. Applied to the togreg branch of iio.git. Note this branch will be rebased before I send Greg a pull request (nature of where we are in the cycle!). Jonathan > >> --- >> drivers/iio/adc/Kconfig | 10 ++ >> drivers/iio/adc/Makefile | 1 + >> drivers/iio/adc/mcp320x.c | 257 >> ++ >> 3 files changed, 268 insertions(+) >> create mode 100644 drivers/iio/adc/mcp320x.c >> >> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig >> index ab0767e6..93129ec 100644 >> --- a/drivers/iio/adc/Kconfig >> +++ b/drivers/iio/adc/Kconfig >> @@ -133,6 +133,16 @@ config MAX1363 >>max11646, max11647) Provides direct access via sysfs and buffered >>data via the iio dev interface. >> >> +config MCP320X >> +tristate "Microchip Technology MCP3204/08" >> +depends on SPI >> +help >> + Say yes here to build support for Microchip Technology's MCP3204 or >> + MCP3208 analog to digital converter. >> + >> + This driver can also be built as a module. If so, the module will be >> + called mcp320x. >> + >> config TI_ADC081C >> tristate "Texas Instruments ADC081C021/027" >> depends on I2C >> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile >> index 0a825be..8f475d3 100644 >> --- a/drivers/iio/adc/Makefile >> +++ b/drivers/iio/adc/Makefile >> @@ -14,6 +14,7 @@ obj-$(CONFIG_AT91_ADC) += at91_adc.o >> obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o >> obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o >> obj-$(CONFIG_MAX1363) += max1363.o >> +obj-$(CONFIG_MCP320X) += mcp320x.o >> obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o >> obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o >> obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o >> diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c >> new file mode 100644 >> index 000..ebc0159 >> --- /dev/null >> +++ b/drivers/iio/adc/mcp320x.c >> @@ -0,0 +1,257 @@ >> +/* >> + * Copyright (C) 2013 Oskar Andero >> + * >> + * Driver for Microchip Technology's MCP3204 and MCP3208 ADC chips. >> + * Datasheet can be found here: >> + * http://ww1.microchip.com/downloads/en/devicedoc/21298c.pdf >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License version 2 as >> + * published by the Free Software Foundation. >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#define MCP_SINGLE_ENDED(1 << 3) >> +#define MCP_START_BIT (1 << 4) >> + >> +enum { >> +mcp3204, >> +mcp3208, >> +}; >> + >> +struct mcp320x { >> +struct spi_device *spi; >> +struct spi_message msg; >> +struct spi_transfer transfer[2]; >> + >> +u8 tx_buf; >> +u8 rx_buf[2]; >> + >> +struct regulator *reg; >> +struct mutex lock; >> +}; >> + >> +static int mcp320x_adc_conversion(struct mcp320x *adc, u8 msg) >> +{ >> +int ret; >> + >> +adc->tx_buf = msg; >> +ret = spi_sync(adc->spi, >msg); >> +if (ret < 0) >> +return ret; >> + >> +return ((adc->rx_buf[0] & 0x3f) << 6) | >> +(adc->rx_buf[1] >> 2); >> +} >> + >> +static int mcp320x_read_raw(struct iio_dev *indio_dev, >> +struct iio_chan_spec const *channel, int *val, >> +int *val2, long mask) >> +{ >> +struct mcp320x *adc = iio_priv(indio_dev); >> +int ret = -EINVAL; >> + >> +mutex_lock(>lock); >> + >> +switch (mask) { >> +case IIO_CHAN_INFO_RAW: >> +if (channel->differential) >> +ret = mcp320x_adc_conversion(adc, >> +MCP_START_BIT | channel->address); >> +else >> +ret = mcp320x_adc_conversion(adc, >> +MCP_START_BIT | MCP_SINGLE_ENDED | >> +channel->address); >> +if (ret < 0) >> +goto out; >> + >> +*val = ret; >> +ret = IIO_VAL_INT; >> +break; >> + >> +case IIO_CHAN_INFO_SCALE: >> +/* Digital output code = (4096 * Vin) / Vref */ >> +ret = regulator_get_voltage(adc->reg); >> +if (ret < 0) >> +goto out; >> + >> +*val = ret / 1000; >> +*val2 = 12; >> +ret = IIO_VAL_FRACTIONAL_LOG2; >> +break; >> + >> +default: >> +break; >> +} >> + >> +out: >> +mutex_unlock(>lock); >> +
Re: [PATCHv4] iio: adc: add driver for MCP3204/08 12-bit ADC
On 05/03/2013 11:00 AM, Lars-Peter Clausen wrote: On 05/03/2013 11:58 AM, Oskar Andero wrote: This adds support for Microchip's 12 bit AD converters MCP3204 and MCP3208. These chips communicates over SPI and supports single-ended and pseudo-differential configurations. Cc: Jonathan Cameron ji...@cam.ac.uk Cc: Lars-Peter Clausen l...@metafoo.de Signed-off-by: Oskar Andero oskar.and...@gmail.com Reviewed-by: Lars-Peter Clausen l...@metafoo.de Nice driver. Thanks Oskar and thanks Lars-Peter for your review work on this. Applied to the togreg branch of iio.git. Note this branch will be rebased before I send Greg a pull request (nature of where we are in the cycle!). Jonathan --- drivers/iio/adc/Kconfig | 10 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/mcp320x.c | 257 ++ 3 files changed, 268 insertions(+) create mode 100644 drivers/iio/adc/mcp320x.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index ab0767e6..93129ec 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -133,6 +133,16 @@ config MAX1363 max11646, max11647) Provides direct access via sysfs and buffered data via the iio dev interface. +config MCP320X +tristate Microchip Technology MCP3204/08 +depends on SPI +help + Say yes here to build support for Microchip Technology's MCP3204 or + MCP3208 analog to digital converter. + + This driver can also be built as a module. If so, the module will be + called mcp320x. + config TI_ADC081C tristate Texas Instruments ADC081C021/027 depends on I2C diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 0a825be..8f475d3 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_MAX1363) += max1363.o +obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c new file mode 100644 index 000..ebc0159 --- /dev/null +++ b/drivers/iio/adc/mcp320x.c @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2013 Oskar Andero oskar.and...@gmail.com + * + * Driver for Microchip Technology's MCP3204 and MCP3208 ADC chips. + * Datasheet can be found here: + * http://ww1.microchip.com/downloads/en/devicedoc/21298c.pdf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include linux/err.h +#include linux/spi/spi.h +#include linux/module.h +#include linux/iio/iio.h +#include linux/regulator/consumer.h + +#define MCP_SINGLE_ENDED(1 3) +#define MCP_START_BIT (1 4) + +enum { +mcp3204, +mcp3208, +}; + +struct mcp320x { +struct spi_device *spi; +struct spi_message msg; +struct spi_transfer transfer[2]; + +u8 tx_buf; +u8 rx_buf[2]; + +struct regulator *reg; +struct mutex lock; +}; + +static int mcp320x_adc_conversion(struct mcp320x *adc, u8 msg) +{ +int ret; + +adc-tx_buf = msg; +ret = spi_sync(adc-spi, adc-msg); +if (ret 0) +return ret; + +return ((adc-rx_buf[0] 0x3f) 6) | +(adc-rx_buf[1] 2); +} + +static int mcp320x_read_raw(struct iio_dev *indio_dev, +struct iio_chan_spec const *channel, int *val, +int *val2, long mask) +{ +struct mcp320x *adc = iio_priv(indio_dev); +int ret = -EINVAL; + +mutex_lock(adc-lock); + +switch (mask) { +case IIO_CHAN_INFO_RAW: +if (channel-differential) +ret = mcp320x_adc_conversion(adc, +MCP_START_BIT | channel-address); +else +ret = mcp320x_adc_conversion(adc, +MCP_START_BIT | MCP_SINGLE_ENDED | +channel-address); +if (ret 0) +goto out; + +*val = ret; +ret = IIO_VAL_INT; +break; + +case IIO_CHAN_INFO_SCALE: +/* Digital output code = (4096 * Vin) / Vref */ +ret = regulator_get_voltage(adc-reg); +if (ret 0) +goto out; + +*val = ret / 1000; +*val2 = 12; +ret = IIO_VAL_FRACTIONAL_LOG2; +break; + +default: +break; +} + +out: +mutex_unlock(adc-lock); + +return ret; +} + +#define MCP320X_VOLTAGE_CHANNEL(num)\ +{
Re: [PATCHv4] iio: adc: add driver for MCP3204/08 12-bit ADC
On 05/03/2013 11:58 AM, Oskar Andero wrote: > This adds support for Microchip's 12 bit AD converters MCP3204 and > MCP3208. These chips communicates over SPI and supports single-ended > and pseudo-differential configurations. > > Cc: Jonathan Cameron > Cc: Lars-Peter Clausen > Signed-off-by: Oskar Andero Reviewed-by: Lars-Peter Clausen > --- > drivers/iio/adc/Kconfig | 10 ++ > drivers/iio/adc/Makefile | 1 + > drivers/iio/adc/mcp320x.c | 257 > ++ > 3 files changed, 268 insertions(+) > create mode 100644 drivers/iio/adc/mcp320x.c > > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig > index ab0767e6..93129ec 100644 > --- a/drivers/iio/adc/Kconfig > +++ b/drivers/iio/adc/Kconfig > @@ -133,6 +133,16 @@ config MAX1363 > max11646, max11647) Provides direct access via sysfs and buffered > data via the iio dev interface. > > +config MCP320X > + tristate "Microchip Technology MCP3204/08" > + depends on SPI > + help > + Say yes here to build support for Microchip Technology's MCP3204 or > + MCP3208 analog to digital converter. > + > + This driver can also be built as a module. If so, the module will be > + called mcp320x. > + > config TI_ADC081C > tristate "Texas Instruments ADC081C021/027" > depends on I2C > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile > index 0a825be..8f475d3 100644 > --- a/drivers/iio/adc/Makefile > +++ b/drivers/iio/adc/Makefile > @@ -14,6 +14,7 @@ obj-$(CONFIG_AT91_ADC) += at91_adc.o > obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o > obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o > obj-$(CONFIG_MAX1363) += max1363.o > +obj-$(CONFIG_MCP320X) += mcp320x.o > obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o > obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o > obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o > diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c > new file mode 100644 > index 000..ebc0159 > --- /dev/null > +++ b/drivers/iio/adc/mcp320x.c > @@ -0,0 +1,257 @@ > +/* > + * Copyright (C) 2013 Oskar Andero > + * > + * Driver for Microchip Technology's MCP3204 and MCP3208 ADC chips. > + * Datasheet can be found here: > + * http://ww1.microchip.com/downloads/en/devicedoc/21298c.pdf > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +#define MCP_SINGLE_ENDED (1 << 3) > +#define MCP_START_BIT(1 << 4) > + > +enum { > + mcp3204, > + mcp3208, > +}; > + > +struct mcp320x { > + struct spi_device *spi; > + struct spi_message msg; > + struct spi_transfer transfer[2]; > + > + u8 tx_buf; > + u8 rx_buf[2]; > + > + struct regulator *reg; > + struct mutex lock; > +}; > + > +static int mcp320x_adc_conversion(struct mcp320x *adc, u8 msg) > +{ > + int ret; > + > + adc->tx_buf = msg; > + ret = spi_sync(adc->spi, >msg); > + if (ret < 0) > + return ret; > + > + return ((adc->rx_buf[0] & 0x3f) << 6) | > + (adc->rx_buf[1] >> 2); > +} > + > +static int mcp320x_read_raw(struct iio_dev *indio_dev, > + struct iio_chan_spec const *channel, int *val, > + int *val2, long mask) > +{ > + struct mcp320x *adc = iio_priv(indio_dev); > + int ret = -EINVAL; > + > + mutex_lock(>lock); > + > + switch (mask) { > + case IIO_CHAN_INFO_RAW: > + if (channel->differential) > + ret = mcp320x_adc_conversion(adc, > + MCP_START_BIT | channel->address); > + else > + ret = mcp320x_adc_conversion(adc, > + MCP_START_BIT | MCP_SINGLE_ENDED | > + channel->address); > + if (ret < 0) > + goto out; > + > + *val = ret; > + ret = IIO_VAL_INT; > + break; > + > + case IIO_CHAN_INFO_SCALE: > + /* Digital output code = (4096 * Vin) / Vref */ > + ret = regulator_get_voltage(adc->reg); > + if (ret < 0) > + goto out; > + > + *val = ret / 1000; > + *val2 = 12; > + ret = IIO_VAL_FRACTIONAL_LOG2; > + break; > + > + default: > + break; > + } > + > +out: > + mutex_unlock(>lock); > + > + return ret; > +} > + > +#define MCP320X_VOLTAGE_CHANNEL(num) \ > + { \ > + .type = IIO_VOLTAGE,\ > + .indexed = 1, \ > + .channel = (num), \ > + .address
[PATCHv4] iio: adc: add driver for MCP3204/08 12-bit ADC
This adds support for Microchip's 12 bit AD converters MCP3204 and MCP3208. These chips communicates over SPI and supports single-ended and pseudo-differential configurations. Cc: Jonathan Cameron Cc: Lars-Peter Clausen Signed-off-by: Oskar Andero --- drivers/iio/adc/Kconfig | 10 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/mcp320x.c | 257 ++ 3 files changed, 268 insertions(+) create mode 100644 drivers/iio/adc/mcp320x.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index ab0767e6..93129ec 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -133,6 +133,16 @@ config MAX1363 max11646, max11647) Provides direct access via sysfs and buffered data via the iio dev interface. +config MCP320X + tristate "Microchip Technology MCP3204/08" + depends on SPI + help + Say yes here to build support for Microchip Technology's MCP3204 or + MCP3208 analog to digital converter. + + This driver can also be built as a module. If so, the module will be + called mcp320x. + config TI_ADC081C tristate "Texas Instruments ADC081C021/027" depends on I2C diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 0a825be..8f475d3 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_MAX1363) += max1363.o +obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c new file mode 100644 index 000..ebc0159 --- /dev/null +++ b/drivers/iio/adc/mcp320x.c @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2013 Oskar Andero + * + * Driver for Microchip Technology's MCP3204 and MCP3208 ADC chips. + * Datasheet can be found here: + * http://ww1.microchip.com/downloads/en/devicedoc/21298c.pdf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#define MCP_SINGLE_ENDED (1 << 3) +#define MCP_START_BIT (1 << 4) + +enum { + mcp3204, + mcp3208, +}; + +struct mcp320x { + struct spi_device *spi; + struct spi_message msg; + struct spi_transfer transfer[2]; + + u8 tx_buf; + u8 rx_buf[2]; + + struct regulator *reg; + struct mutex lock; +}; + +static int mcp320x_adc_conversion(struct mcp320x *adc, u8 msg) +{ + int ret; + + adc->tx_buf = msg; + ret = spi_sync(adc->spi, >msg); + if (ret < 0) + return ret; + + return ((adc->rx_buf[0] & 0x3f) << 6) | + (adc->rx_buf[1] >> 2); +} + +static int mcp320x_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *channel, int *val, + int *val2, long mask) +{ + struct mcp320x *adc = iio_priv(indio_dev); + int ret = -EINVAL; + + mutex_lock(>lock); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (channel->differential) + ret = mcp320x_adc_conversion(adc, + MCP_START_BIT | channel->address); + else + ret = mcp320x_adc_conversion(adc, + MCP_START_BIT | MCP_SINGLE_ENDED | + channel->address); + if (ret < 0) + goto out; + + *val = ret; + ret = IIO_VAL_INT; + break; + + case IIO_CHAN_INFO_SCALE: + /* Digital output code = (4096 * Vin) / Vref */ + ret = regulator_get_voltage(adc->reg); + if (ret < 0) + goto out; + + *val = ret / 1000; + *val2 = 12; + ret = IIO_VAL_FRACTIONAL_LOG2; + break; + + default: + break; + } + +out: + mutex_unlock(>lock); + + return ret; +} + +#define MCP320X_VOLTAGE_CHANNEL(num) \ + { \ + .type = IIO_VOLTAGE,\ + .indexed = 1, \ + .channel = (num), \ + .address = (num), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ + } + +#define MCP320X_VOLTAGE_CHANNEL_DIFF(num) \ + {
[PATCHv4] iio: adc: add driver for MCP3204/08 12-bit ADC
This adds support for Microchip's 12 bit AD converters MCP3204 and MCP3208. These chips communicates over SPI and supports single-ended and pseudo-differential configurations. Cc: Jonathan Cameron ji...@cam.ac.uk Cc: Lars-Peter Clausen l...@metafoo.de Signed-off-by: Oskar Andero oskar.and...@gmail.com --- drivers/iio/adc/Kconfig | 10 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/mcp320x.c | 257 ++ 3 files changed, 268 insertions(+) create mode 100644 drivers/iio/adc/mcp320x.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index ab0767e6..93129ec 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -133,6 +133,16 @@ config MAX1363 max11646, max11647) Provides direct access via sysfs and buffered data via the iio dev interface. +config MCP320X + tristate Microchip Technology MCP3204/08 + depends on SPI + help + Say yes here to build support for Microchip Technology's MCP3204 or + MCP3208 analog to digital converter. + + This driver can also be built as a module. If so, the module will be + called mcp320x. + config TI_ADC081C tristate Texas Instruments ADC081C021/027 depends on I2C diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 0a825be..8f475d3 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_MAX1363) += max1363.o +obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c new file mode 100644 index 000..ebc0159 --- /dev/null +++ b/drivers/iio/adc/mcp320x.c @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2013 Oskar Andero oskar.and...@gmail.com + * + * Driver for Microchip Technology's MCP3204 and MCP3208 ADC chips. + * Datasheet can be found here: + * http://ww1.microchip.com/downloads/en/devicedoc/21298c.pdf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include linux/err.h +#include linux/spi/spi.h +#include linux/module.h +#include linux/iio/iio.h +#include linux/regulator/consumer.h + +#define MCP_SINGLE_ENDED (1 3) +#define MCP_START_BIT (1 4) + +enum { + mcp3204, + mcp3208, +}; + +struct mcp320x { + struct spi_device *spi; + struct spi_message msg; + struct spi_transfer transfer[2]; + + u8 tx_buf; + u8 rx_buf[2]; + + struct regulator *reg; + struct mutex lock; +}; + +static int mcp320x_adc_conversion(struct mcp320x *adc, u8 msg) +{ + int ret; + + adc-tx_buf = msg; + ret = spi_sync(adc-spi, adc-msg); + if (ret 0) + return ret; + + return ((adc-rx_buf[0] 0x3f) 6) | + (adc-rx_buf[1] 2); +} + +static int mcp320x_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *channel, int *val, + int *val2, long mask) +{ + struct mcp320x *adc = iio_priv(indio_dev); + int ret = -EINVAL; + + mutex_lock(adc-lock); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (channel-differential) + ret = mcp320x_adc_conversion(adc, + MCP_START_BIT | channel-address); + else + ret = mcp320x_adc_conversion(adc, + MCP_START_BIT | MCP_SINGLE_ENDED | + channel-address); + if (ret 0) + goto out; + + *val = ret; + ret = IIO_VAL_INT; + break; + + case IIO_CHAN_INFO_SCALE: + /* Digital output code = (4096 * Vin) / Vref */ + ret = regulator_get_voltage(adc-reg); + if (ret 0) + goto out; + + *val = ret / 1000; + *val2 = 12; + ret = IIO_VAL_FRACTIONAL_LOG2; + break; + + default: + break; + } + +out: + mutex_unlock(adc-lock); + + return ret; +} + +#define MCP320X_VOLTAGE_CHANNEL(num) \ + { \ + .type = IIO_VOLTAGE,\ + .indexed = 1, \ + .channel = (num), \ + .address = (num), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ +
Re: [PATCHv4] iio: adc: add driver for MCP3204/08 12-bit ADC
On 05/03/2013 11:58 AM, Oskar Andero wrote: This adds support for Microchip's 12 bit AD converters MCP3204 and MCP3208. These chips communicates over SPI and supports single-ended and pseudo-differential configurations. Cc: Jonathan Cameron ji...@cam.ac.uk Cc: Lars-Peter Clausen l...@metafoo.de Signed-off-by: Oskar Andero oskar.and...@gmail.com Reviewed-by: Lars-Peter Clausen l...@metafoo.de --- drivers/iio/adc/Kconfig | 10 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/mcp320x.c | 257 ++ 3 files changed, 268 insertions(+) create mode 100644 drivers/iio/adc/mcp320x.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index ab0767e6..93129ec 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -133,6 +133,16 @@ config MAX1363 max11646, max11647) Provides direct access via sysfs and buffered data via the iio dev interface. +config MCP320X + tristate Microchip Technology MCP3204/08 + depends on SPI + help + Say yes here to build support for Microchip Technology's MCP3204 or + MCP3208 analog to digital converter. + + This driver can also be built as a module. If so, the module will be + called mcp320x. + config TI_ADC081C tristate Texas Instruments ADC081C021/027 depends on I2C diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 0a825be..8f475d3 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_MAX1363) += max1363.o +obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c new file mode 100644 index 000..ebc0159 --- /dev/null +++ b/drivers/iio/adc/mcp320x.c @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2013 Oskar Andero oskar.and...@gmail.com + * + * Driver for Microchip Technology's MCP3204 and MCP3208 ADC chips. + * Datasheet can be found here: + * http://ww1.microchip.com/downloads/en/devicedoc/21298c.pdf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include linux/err.h +#include linux/spi/spi.h +#include linux/module.h +#include linux/iio/iio.h +#include linux/regulator/consumer.h + +#define MCP_SINGLE_ENDED (1 3) +#define MCP_START_BIT(1 4) + +enum { + mcp3204, + mcp3208, +}; + +struct mcp320x { + struct spi_device *spi; + struct spi_message msg; + struct spi_transfer transfer[2]; + + u8 tx_buf; + u8 rx_buf[2]; + + struct regulator *reg; + struct mutex lock; +}; + +static int mcp320x_adc_conversion(struct mcp320x *adc, u8 msg) +{ + int ret; + + adc-tx_buf = msg; + ret = spi_sync(adc-spi, adc-msg); + if (ret 0) + return ret; + + return ((adc-rx_buf[0] 0x3f) 6) | + (adc-rx_buf[1] 2); +} + +static int mcp320x_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *channel, int *val, + int *val2, long mask) +{ + struct mcp320x *adc = iio_priv(indio_dev); + int ret = -EINVAL; + + mutex_lock(adc-lock); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (channel-differential) + ret = mcp320x_adc_conversion(adc, + MCP_START_BIT | channel-address); + else + ret = mcp320x_adc_conversion(adc, + MCP_START_BIT | MCP_SINGLE_ENDED | + channel-address); + if (ret 0) + goto out; + + *val = ret; + ret = IIO_VAL_INT; + break; + + case IIO_CHAN_INFO_SCALE: + /* Digital output code = (4096 * Vin) / Vref */ + ret = regulator_get_voltage(adc-reg); + if (ret 0) + goto out; + + *val = ret / 1000; + *val2 = 12; + ret = IIO_VAL_FRACTIONAL_LOG2; + break; + + default: + break; + } + +out: + mutex_unlock(adc-lock); + + return ret; +} + +#define MCP320X_VOLTAGE_CHANNEL(num) \ + { \ + .type = IIO_VOLTAGE,\ + .indexed = 1, \ + .channel = (num), \ + .address =