Maxim MAX1241 driver
Subsystems (2)
v5 cover Maxim MAX1241 driver
Hello again,
Here's version 5 of a patch series which adds support for the Maxim MAX1241, a 12-bit, single-channel, SPI-connected ADC.
Changelog so far:
v5:
* Add vdd supply binding
* Reorder include headers -- one of them had escaped the long mechanized hand of the Alphabetron
* Drop scan_index and scan_type from channel spec, as the driver doesn't support buffered modes
* Drop a useless initialization of a local variable in probe function
* Revise dt-bindings patch subject line, revise maintainer and copyright to match the Signed-off: string, drop reference to driver from bindings description
* Various readability/cosmetic fixes
v4:
* Dropped explicit documentation of SPI reg property
* Reordered patch series so that dt bindings come first
v3:
* Fixed silly copy-paste error in Kconfig description
v2:
* Removed useeless header includes
* Dropped needlessly verbose stuff in _read and _probe functions
* Dropped useless GPL notice
* Lowered log level of shdn pin status in probe function, now it's dev_dbg
* Added proper error checking for the GPIO shutdown pin
* remove now always returns zero (man, I've been wrong about this for *years* now...)
* Added regulator disable action, cleanup is now handled via devm
* Drop delay_usecs, use delay.value, delay.unit
* Drop config_of, of_match_ptr call
* Dropped IIO_BUFFER, IIO_TRIGGERED_BUFFER dependencies, set SPI_MASTER as dependency, fix indenting.
* DT binding: use correct id, add reg description (looks pretty standard), dropped spi-max-frequency, fixed dt_binding_check complaints (oops!)
Thanks,
Alex
Alexandru Lazar (2):
dt-bindings: iio: adc: Add MAX1241 bindings
iio: adc: Add MAX1241 driver
.../bindings/iio/adc/maxim,max1241.yaml | 65 ++++++ drivers/iio/adc/Kconfig | 10 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/max1241.c | 213 ++++++++++++++++++ 4 files changed, 289 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/maxim,max1241.yaml create mode 100644 drivers/iio/adc/max1241.c
Signature · 1 line
2.25.2
PATCH v5 1/2 dt-bindings: iio: adc: Add MAX1241 bindings
Add device-tree bindings documentation for the MAX1241 device driver.
--- .../bindings/iio/adc/maxim,max1241.yaml | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/maxim,max1241.yaml
Documentation/devicetree/bindings/iio/adc/maxim,max1241.yaml new file +65 -0
@@ -0,0 +1,65 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright 2020 Alexandru Lazar +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/maxim,max1241.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX1241 12-bit, single-channel analog to digital converter + +maintainers: + - Alexandru Lazar <[email protected]> + +description: | + Bindings for the max1241 12-bit, single-channel ADC device. Datasheet + can be found at: + https://datasheets.maximintegrated.com/en/ds/MAX1240-MAX1241.pdf + +properties: + compatible: + enum: + - maxim,max1241 + + reg: + maxItems: 1 + + vdd-supply: + description: + Device tree identifier of the regulator that powers the ADC. + maxItems: 1 + + vref-supply: + description: + Device tree identifier of the regulator that provides the external + reference voltage. + maxItems: 1 + + shdn-gpios: + description: + GPIO spec for the GPIO pin connected to the ADC's /SHDN pin. If + specified, the /SHDN pin will be asserted between conversions, + thus enabling power-down mode. + maxItems: 1 + +required: + - compatible + - reg + - vdd-supply + - vref-supply + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + spi0 { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "maxim,max1241"; + reg = <0>; + vdd-supply = <&adc_vdd>; + vref-supply = <&adc_vref>; + spi-max-frequency = <1000000>; + shdn-gpios = <&gpio 26 1>; + }; + };
Signature · 1 line
2.25.2
PATCH v5 2/2 iio: adc: Add MAX1241 driver
In reply to Alexandru LazarAdd driver for the Maxim MAX1241 12-bit, single-channel ADC.
--- drivers/iio/adc/Kconfig | 10 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/max1241.c | 213 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 drivers/iio/adc/max1241.c
drivers/iio/adc/Kconfig +10 -0
@@ -566,6 +566,16 @@ config MAX1118 To compile this driver as a module, choose M here: the module will be called max1118. +config MAX1241 + tristate "Maxim max1241 ADC driver" + depends on SPI_MASTER + help + Say yes here to build support for Maxim max1241 12-bit, single-channel + ADC. + + To compile this driver as a module, choose M here: the module will be + called max1241. + config MAX1363 tristate "Maxim max1363 ADC driver" depends on I2C
drivers/iio/adc/Makefile +1 -0
@@ -54,6 +54,7 @@ obj-$(CONFIG_LTC2497) += ltc2497.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX11100) += max11100.o obj-$(CONFIG_MAX1118) += max1118.o +obj-$(CONFIG_MAX1241) += max1241.o obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MAX9611) += max9611.o obj-$(CONFIG_MCP320X) += mcp320x.o
drivers/iio/adc/max1241.c new file +213 -0
213 lines not on this page · raw message
Signature · 1 line
2.25.2
Jonathan Cameron
maintainerRe: [PATCH v5 2/2] iio: adc: Add MAX1241 driver
Quoted 4 lines · On Sun, 22 Mar 2020 16:02:37 +0200 Alexandru Lazar <[email protected]> wrote:
Add driver for the Maxim MAX1241 12-bit, single-channel ADC.
Reviewed-by Alexandru Ardelean <[email protected]>Signed-off-by Alexandru Lazar <[email protected]>
Minor issue inline. I can fix that up when applying. However, I'd like to give more time for Rob to take a look at the dt binding. I've made too many mistakes on those recently :(
Reality is we've missed the coming merge window with this anyway so we have plenty of time.
Thanks,
Jonathan
Quoted 192 lines
--- drivers/iio/adc/Kconfig | 10 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/max1241.c | 213 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 drivers/iio/adc/max1241.cdrivers/iio/adc/Kconfig +10
-0@@ -566,6 +566,16 @@ config MAX1118 To compile this driver as a module, choose M here: the module will be called max1118. +config MAX1241 + tristate "Maxim max1241 ADC driver" + depends on SPI_MASTER + help + Say yes here to build support for Maxim max1241 12-bit, single-channel + ADC. + + To compile this driver as a module, choose M here: the module will be + called max1241. + config MAX1363 tristate "Maxim max1363 ADC driver" depends on I2Cdrivers/iio/adc/Makefile +1
-0@@ -54,6 +54,7 @@ obj-$(CONFIG_LTC2497) += ltc2497.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX11100) += max11100.o obj-$(CONFIG_MAX1118) += max1118.o +obj-$(CONFIG_MAX1241) += max1241.o obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MAX9611) += max9611.o obj-$(CONFIG_MCP320X) += mcp320x.odrivers/iio/adc/max1241.c new file +146
-0@@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* MAX1241 low-power, 12-bit serial ADC +* +* Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX1240-MAX1241.pdf +*/ + +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/iio/iio.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> +#include <linux/spi/spi.h> + +#define MAX1241_VAL_MASK GENMASK(11, 0) +#define MAX1241_SHDN_DELAY_USEC 4 + +enum max1241_id { + max1241, +}; + +struct max1241 { +struct spi_device *spi; +struct mutex lock; +struct regulator *vdd; +struct regulator *vref; +struct gpio_desc *shdn; + +__be16 data____cacheline_aligned ; +}; + +static const struct iio_chan_spec max1241_channels[] = { + { + .type =IIO_VOLTAGE , + .indexed =1 , + .channel =0 , + .info_mask_separate =BIT (IIO_CHAN_INFO_RAW ) | +BIT (IIO_CHAN_INFO_SCALE ), + }, +}; + +static int max1241_read (struct max1241 *adc) +{ +struct spi_transfer xfers[] = { +/* +* Begin conversion by bringing /CS low for at least +* tconv us. +*/ + { + .len =0 , + .delay.value =8 , + .delay.unit =SPI_DELAY_UNIT_USECS , + }, +/* +* Then read two bytes of data in our RX buffer. +*/ + { + .rx_buf = &adc->data, + .len =2 , + }, + }; + +return spi_sync_transfer (adc->spi, xfers,ARRAY_SIZE (xfers)); +} + +static int max1241_read_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan, +int *val,int *val2,long mask) +{ +int ret, vref_uV; +struct max1241 *adc =iio_priv (indio_dev); + +switch (mask) { +case IIO_CHAN_INFO_RAW : +mutex_lock (&adc->lock); + +if (adc->shdn) { +gpiod_set_value (adc->shdn,0 ); +udelay (MAX1241_SHDN_DELAY_USEC ); + ret =max1241_read (adc); +gpiod_set_value (adc->shdn,1 ); + }else + ret =max1241_read (adc); + +if (ret) { +mutex_unlock (&adc->lock); +return ret; + } + + *val = (be16_to_cpu (adc->data) >>3 ) &MAX1241_VAL_MASK ; + +mutex_unlock (&adc->lock); +return IIO_VAL_INT ; +case IIO_CHAN_INFO_SCALE : + vref_uV =regulator_get_voltage (adc->vref); + +if (vref_uV <0 ) +return vref_uV; + + *val = vref_uV /1000 ; + *val2 =12 ; + +return IIO_VAL_FRACTIONAL_LOG2 ; +default : +return -EINVAL ; + } +} + +static const struct iio_info max1241_info = { + .read_raw = max1241_read_raw, +}; + +static void max1241_disable_reg_action (void *data) +{ +struct max1241 *adc = data; +struct device *dev = &adc->spi->dev; +int err; + + err =regulator_disable (adc->vref); +if (err) +dev_err (dev,"could not disable vref regulator.\n" ); + + err =regulator_disable (adc->vdd); +if (err) +dev_err (dev,"could not disable vdd regulator.\n" ); +} + +static int max1241_probe (struct spi_device *spi) +{ +struct device *dev = &spi->dev; +struct iio_dev *indio_dev; +struct max1241 *adc; +int ret; + + indio_dev =devm_iio_device_alloc (dev,sizeof (*adc)); +if (!indio_dev) +return -ENOMEM ; + + adc =iio_priv (indio_dev); + adc->spi = spi; +mutex_init (&adc->lock); + +spi_set_drvdata (spi, indio_dev); + + adc->vdd =devm_regulator_get (dev,"vdd" ); +if (IS_ERR (adc->vdd)) {
drivers/iio/adc/max1241.c line 156
Quoted 10 lines
drivers/iio/adc/max1241.c new file +10
-0+dev_err (dev,"failed to get vdd regulator\n" ); +return PTR_ERR (adc->vdd); + } + + ret =regulator_enable (adc->vdd); +if (ret) +return ret; + + adc->vref =devm_regulator_get (dev,"vref" ); +if (IS_ERR (adc->vref)) {
If this returns an error you have left the vref regulator on.
Unfortunately to keep things simple you'll need to have two separate callbacks for devm_add_action_or_reset, one for each of the regulators.
Quoted 57 lines
drivers/iio/adc/max1241.c new file +57
-0+dev_err (dev,"failed to get vref regulator\n" ); +return PTR_ERR (adc->vref); + } + + ret =regulator_enable (adc->vref); +if (ret) +return ret; + + ret =devm_add_action_or_reset (dev, max1241_disable_reg_action, adc); +if (ret) { +dev_err (dev,"could not set up regulator cleanup action!\n" ); +return ret; + } + + adc->shdn =devm_gpiod_get_optional (dev,"shdn" ,GPIOD_OUT_HIGH ); +if (IS_ERR (adc->shdn)) +return PTR_ERR (adc->shdn); + +if (adc->shdn) +dev_dbg (dev,"shdn pin passed, low-power mode enabled" ); +else +dev_dbg (dev,"no shdn pin passed, low-power mode disabled" ); + + indio_dev->name =spi_get_device_id (spi)->name; + indio_dev->dev.parent = dev; + indio_dev->info = &max1241_info; + indio_dev->modes =INDIO_DIRECT_MODE ; + indio_dev->channels = max1241_channels; + indio_dev->num_channels =ARRAY_SIZE (max1241_channels); + +return devm_iio_device_register (dev, indio_dev); +} + +static const struct spi_device_id max1241_id[] = { + {"max1241" , max1241 }, + {} +}; + +static const struct of_device_id max1241_dt_ids[] = { + { .compatible ="maxim,max1241" }, + {} +}; +MODULE_DEVICE_TABLE (of, max1241_dt_ids); + +static struct spi_driver max1241_spi_driver = { + .driver = { + .name ="max1241" , + .of_match_table = max1241_dt_ids, + }, + .probe = max1241_probe, + .id_table = max1241_id, +}; +module_spi_driver (max1241_spi_driver); + +MODULE_AUTHOR ("Alexandru Lazar <[email protected]>" ); +MODULE_DESCRIPTION ("MAX1241 ADC driver" ); +MODULE_LICENSE ("GPL v2" );
Re: [PATCH v5 2/2] iio: adc: Add MAX1241 driver
Quoted 3 lines
Minor issue inline. I can fix that up when applying. However, I'd like to give more time for Rob to take a look at the dt binding. I've made too many mistakes on those recently :(
Ooh, yes! Right! Sorry, my brain is still not wired correctly for these fancy new callback thingies.
It's actually less minor than it looks because disable_reg_action actually tries to turn *both* regulators off. No way that's gonna go well, and I'm not sure why I my alarm didn't go off when I tested the damn thing, either.
I'll fix it on Monday and post a v6, don't worry about it, you've got a whole tree to tend to. We got plenty of time anyway (and, like I said, I'm really in no rush at all :-) ).
Thanks,
Alex
Quoted 275 lines
Reality is we've missed the coming merge window with this anyway so we have plenty of time.
Thanks,
Jonathan
Quoted 192 lines
--- drivers/iio/adc/Kconfig | 10 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/max1241.c | 213 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 drivers/iio/adc/max1241.cdrivers/iio/adc/Kconfig +10
-0@@ -566,6 +566,16 @@ config MAX1118 To compile this driver as a module, choose M here: the module will be called max1118. +config MAX1241 + tristate "Maxim max1241 ADC driver" + depends on SPI_MASTER + help + Say yes here to build support for Maxim max1241 12-bit, single-channel + ADC. + + To compile this driver as a module, choose M here: the module will be + called max1241. + config MAX1363 tristate "Maxim max1363 ADC driver" depends on I2Cdrivers/iio/adc/Makefile +1
-0@@ -54,6 +54,7 @@ obj-$(CONFIG_LTC2497) += ltc2497.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX11100) += max11100.o obj-$(CONFIG_MAX1118) += max1118.o +obj-$(CONFIG_MAX1241) += max1241.o obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MAX9611) += max9611.o obj-$(CONFIG_MCP320X) += mcp320x.odrivers/iio/adc/max1241.c new file +146
-0@@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* MAX1241 low-power, 12-bit serial ADC +* +* Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX1240-MAX1241.pdf +*/ + +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/iio/iio.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> +#include <linux/spi/spi.h> + +#define MAX1241_VAL_MASK GENMASK(11, 0) +#define MAX1241_SHDN_DELAY_USEC 4 + +enum max1241_id { + max1241, +}; + +struct max1241 { +struct spi_device *spi; +struct mutex lock; +struct regulator *vdd; +struct regulator *vref; +struct gpio_desc *shdn; + +__be16 data____cacheline_aligned ; +}; + +static const struct iio_chan_spec max1241_channels[] = { + { + .type =IIO_VOLTAGE , + .indexed =1 , + .channel =0 , + .info_mask_separate =BIT (IIO_CHAN_INFO_RAW ) | +BIT (IIO_CHAN_INFO_SCALE ), + }, +}; + +static int max1241_read (struct max1241 *adc) +{ +struct spi_transfer xfers[] = { +/* +* Begin conversion by bringing /CS low for at least +* tconv us. +*/ + { + .len =0 , + .delay.value =8 , + .delay.unit =SPI_DELAY_UNIT_USECS , + }, +/* +* Then read two bytes of data in our RX buffer. +*/ + { + .rx_buf = &adc->data, + .len =2 , + }, + }; + +return spi_sync_transfer (adc->spi, xfers,ARRAY_SIZE (xfers)); +} + +static int max1241_read_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan, +int *val,int *val2,long mask) +{ +int ret, vref_uV; +struct max1241 *adc =iio_priv (indio_dev); + +switch (mask) { +case IIO_CHAN_INFO_RAW : +mutex_lock (&adc->lock); + +if (adc->shdn) { +gpiod_set_value (adc->shdn,0 ); +udelay (MAX1241_SHDN_DELAY_USEC ); + ret =max1241_read (adc); +gpiod_set_value (adc->shdn,1 ); + }else + ret =max1241_read (adc); + +if (ret) { +mutex_unlock (&adc->lock); +return ret; + } + + *val = (be16_to_cpu (adc->data) >>3 ) &MAX1241_VAL_MASK ; + +mutex_unlock (&adc->lock); +return IIO_VAL_INT ; +case IIO_CHAN_INFO_SCALE : + vref_uV =regulator_get_voltage (adc->vref); + +if (vref_uV <0 ) +return vref_uV; + + *val = vref_uV /1000 ; + *val2 =12 ; + +return IIO_VAL_FRACTIONAL_LOG2 ; +default : +return -EINVAL ; + } +} + +static const struct iio_info max1241_info = { + .read_raw = max1241_read_raw, +}; + +static void max1241_disable_reg_action (void *data) +{ +struct max1241 *adc = data; +struct device *dev = &adc->spi->dev; +int err; + + err =regulator_disable (adc->vref); +if (err) +dev_err (dev,"could not disable vref regulator.\n" ); + + err =regulator_disable (adc->vdd); +if (err) +dev_err (dev,"could not disable vdd regulator.\n" ); +} + +static int max1241_probe (struct spi_device *spi) +{ +struct device *dev = &spi->dev; +struct iio_dev *indio_dev; +struct max1241 *adc; +int ret; + + indio_dev =devm_iio_device_alloc (dev,sizeof (*adc)); +if (!indio_dev) +return -ENOMEM ; + + adc =iio_priv (indio_dev); + adc->spi = spi; +mutex_init (&adc->lock); + +spi_set_drvdata (spi, indio_dev); + + adc->vdd =devm_regulator_get (dev,"vdd" ); +if (IS_ERR (adc->vdd)) {drivers/iio/adc/max1241.c line 156
Quoted 10 lines
drivers/iio/adc/max1241.c new file +10
-0+dev_err (dev,"failed to get vdd regulator\n" ); +return PTR_ERR (adc->vdd); + } + + ret =regulator_enable (adc->vdd); +if (ret) +return ret; + + adc->vref =devm_regulator_get (dev,"vref" ); +if (IS_ERR (adc->vref)) {If this returns an error you have left the vref regulator on.
Unfortunately to keep things simple you'll need to have two separate callbacks for
devm_add_action_or_reset, one for each of the regulators.Quoted 57 lines
drivers/iio/adc/max1241.c new file +57
-0+dev_err (dev,"failed to get vref regulator\n" ); +return PTR_ERR (adc->vref); + } + + ret =regulator_enable (adc->vref); +if (ret) +return ret; + + ret =devm_add_action_or_reset (dev, max1241_disable_reg_action, adc); +if (ret) { +dev_err (dev,"could not set up regulator cleanup action!\n" ); +return ret; + } + + adc->shdn =devm_gpiod_get_optional (dev,"shdn" ,GPIOD_OUT_HIGH ); +if (IS_ERR (adc->shdn)) +return PTR_ERR (adc->shdn); + +if (adc->shdn) +dev_dbg (dev,"shdn pin passed, low-power mode enabled" ); +else +dev_dbg (dev,"no shdn pin passed, low-power mode disabled" ); + + indio_dev->name =spi_get_device_id (spi)->name; + indio_dev->dev.parent = dev; + indio_dev->info = &max1241_info; + indio_dev->modes =INDIO_DIRECT_MODE ; + indio_dev->channels = max1241_channels; + indio_dev->num_channels =ARRAY_SIZE (max1241_channels); + +return devm_iio_device_register (dev, indio_dev); +} + +static const struct spi_device_id max1241_id[] = { + {"max1241" , max1241 }, + {} +}; + +static const struct of_device_id max1241_dt_ids[] = { + { .compatible ="maxim,max1241" }, + {} +}; +MODULE_DEVICE_TABLE (of, max1241_dt_ids); + +static struct spi_driver max1241_spi_driver = { + .driver = { + .name ="max1241" , + .of_match_table = max1241_dt_ids, + }, + .probe = max1241_probe, + .id_table = max1241_id, +}; +module_spi_driver (max1241_spi_driver); + +MODULE_AUTHOR ("Alexandru Lazar <[email protected]>" ); +MODULE_DESCRIPTION ("MAX1241 ADC driver" ); +MODULE_LICENSE ("GPL v2" );
Quoted 4 lines · Alexandru Lazar
Hello again,
Here's version 5 of a patch series which adds support for the Maxim MAX1241, a 12-bit, single-channel, SPI-connected ADC.
*poke*
No rush here, just wanna make sure this doesn't go off-radar.
Thanks,
Alex
Quoted 9 lines · Alexandru Lazar
Quoted 4 lines · Alexandru Lazar
Hello again,
Here's version 5 of a patch series which adds support for the Maxim MAX1241, a 12-bit, single-channel, SPI-connected ADC.
*poke*
No rush here, just wanna make sure this doesn't go off-radar.
No reply is good news! Means nobody has anything to complain :)
Johnathan usually picks up patches during the weekend (For which I think we can not thank him enough!).
- Lars