iio: potentiometer: add driver for Maxim Integrated DS1803
Subsystems (2)
PATCH 1/1 iio: potentiometer: add driver for Maxim Integrated DS1803
The following functions are supported:
- write, read potentiometer value
- potentiometer scale
Datasheet: https://datasheets.maximintegrated.com/en/ds/DS1803.pdf
--- .../bindings/iio/potentiometer/ds1803.txt | 21 +++ drivers/iio/potentiometer/Kconfig | 10 ++ drivers/iio/potentiometer/Makefile | 1 + drivers/iio/potentiometer/ds1803.c | 178 +++++++++++++++++++++ 4 files changed, 210 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/potentiometer/ds1803.txt create mode 100644 drivers/iio/potentiometer/ds1803.c
Documentation/devicetree/bindings/iio/potentiometer/ds1803.txt new file +21 -0
@@ -0,0 +1,21 @@ +* Maxim Integrated DS1803 digital potentiometer driver + +The node for this driver must be a child node of a I2C controller, hence +all mandatory properties for your controller must be specified. See directory: + + Documentation/devicetree/bindings/i2c + +for more details. + +Required properties: + - compatible: Must be one of the following, depending on the + model: + "maxim,ds1803-010", + "maxim,ds1803-050", + "maxim,ds1803-100" + +Example: +ds1803: ds1803@1 { + reg = <0x28>; + compatible = "maxim,ds1803-010"; +};
drivers/iio/potentiometer/Kconfig +10 -0
@@ -5,6 +5,16 @@ menu "Digital potentiometers" +config DS1803 + tristate "Maxim Integrated DS1803 Digital Potentiometer driver" + depends on I2C + help + Say yes here to build support for the Maxim Integrated DS1803 + digital potentiomenter chip. + + To compile this driver as a module, choose M here: the + module will be called ds1803. + config MCP4131 tristate "Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer driver" depends on SPI
drivers/iio/potentiometer/Makefile +1 -0
@@ -3,6 +3,7 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_DS1803) += ds1803.o obj-$(CONFIG_MCP4131) += mcp4131.o obj-$(CONFIG_MCP4531) += mcp4531.o obj-$(CONFIG_TPL0102) += tpl0102.o
drivers/iio/potentiometer/ds1803.c new file +178 -0
178 lines not on this page · raw message
Signature · 1 line
2.7.4
Quoted 4 lines
The following functions are supported:
- write, read potentiometer value
- potentiometer scale
minor comments below, nice driver
Quoted 83 lines
Datasheet: https://datasheets.maximintegrated.com/en/ds/DS1803.pdf
Signed-off-by Slawomir Stepien <[email protected]>--- .../bindings/iio/potentiometer/ds1803.txt | 21 +++ drivers/iio/potentiometer/Kconfig | 10 ++ drivers/iio/potentiometer/Makefile | 1 + drivers/iio/potentiometer/ds1803.c | 178 +++++++++++++++++++++ 4 files changed, 210 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/potentiometer/ds1803.txt create mode 100644 drivers/iio/potentiometer/ds1803.cDocumentation/devicetree/bindings/iio/potentiometer/ds1803.txt new file +21
-0@@ -0,0 +1,21 @@ +* Maxim Integrated DS1803 digital potentiometer driver + +The node for this driver must be a child node of a I2C controller, hence +all mandatory properties for your controller must be specified. See directory: + + Documentation/devicetree/bindings/i2c + +for more details. + +Required properties: + - compatible: Must be one of the following, depending on the + model: + "maxim,ds1803-010", + "maxim,ds1803-050", + "maxim,ds1803-100" + +Example: +ds1803: ds1803@1 { + reg = <0x28>; + compatible = "maxim,ds1803-010"; +};drivers/iio/potentiometer/Kconfig +10
-0@@ -5,6 +5,16 @@ menu "Digital potentiometers" +config DS1803 + tristate "Maxim Integrated DS1803 Digital Potentiometer driver" + depends on I2C + help + Say yes here to build support for the Maxim Integrated DS1803 + digital potentiomenter chip. + + To compile this driver as a module, choose M here: the + module will be called ds1803. + config MCP4131 tristate "Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer driver" depends on SPIdrivers/iio/potentiometer/Makefile +1
-0@@ -3,6 +3,7 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_DS1803) += ds1803.o obj-$(CONFIG_MCP4131) += mcp4131.o obj-$(CONFIG_MCP4531) += mcp4531.o obj-$(CONFIG_TPL0102) += tpl0102.odrivers/iio/potentiometer/ds1803.c new file +5
-0@@ -0,0 +1,178 @@ +/* +* Maxim Integrated DS1803 digital potentiometer driver +* Copyright (c) 2016 Slawomir Stepien +* +* Datasheet: https://datasheets.maximintegrated.com/en/ds/DS1803.pdf
drivers/iio/potentiometer/ds1803.c line 15
Quoted 10 lines
drivers/iio/potentiometer/ds1803.c new file +10
-0+* +* DEVID #Wipers #Positions Resistor Opts (kOhm) i2c address +* ds1803 2 256 10, 50, 100 0101xxx +* +* 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/cache.h>
for what is cache.h needed?
Quoted 47 lines
drivers/iio/potentiometer/ds1803.c new file +47
-0+#include <linux/err.h> +#include <linux/export.h> +#include <linux/i2c.h> +#include <linux/iio/iio.h> +#include <linux/module.h> +#include <linux/of.h> + +#define DS1803_NUM_WIPERS 2 +#define DS1803_MAX_POS 255 +#define DS1803_WRITE (n) (0xA8 | ((n) + 1)) + +enum ds1803_type { +DS1803_010 , +DS1803_050 , +DS1803_100 , +}; + +struct ds1803_cfg { +int kohms; +}; + +static const struct ds1803_cfg ds1803_cfg[] = { + [DS1803_010 ] = { .kohms =10 , }, + [DS1803_050 ] = { .kohms =50 , }, + [DS1803_100 ] = { .kohms =100 , }, +}; + +struct ds1803_data { +struct i2c_client *client; +const struct ds1803_cfg *cfg; +}; + +#define DS1803_CHANNEL (ch) { \ + .type = IIO_RESISTANCE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (ch), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +static const struct iio_chan_spec ds1803_channels[] = { +DS1803_CHANNEL (0 ), +DS1803_CHANNEL (1 ), +}; + +static int ds1803_read_raw(struct iio_dev *indio_dev,
drivers/iio/potentiometer/ds1803.c line 72
Quoted 10 lines
drivers/iio/potentiometer/ds1803.c new file +10
-0+struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct ds1803_data *data = iio_priv(indio_dev); +int pot = chan->channel; +s32 ret; + +switch (mask) { +case IIO_CHAN_INFO_RAW : + ret =i2c_smbus_read_word_swapped (data->client,0 );
maybe a #define to explain the name of register 0
drivers/iio/potentiometer/ds1803.c line 77
Quoted 5 lines
drivers/iio/potentiometer/ds1803.c new file +5
-0+if (ret <0 ) +return ret; + +/* Get bits for given pot */ + *val = (pot ==0 ? ret >>8 : ret &255 );
often 0xff is used to mask a byte
Quoted 11 lines
drivers/iio/potentiometer/ds1803.c new file +11
-0+return IIO_VAL_INT ; + +case IIO_CHAN_INFO_SCALE : + *val =1000 * data->cfg->kohms; + *val2 =DS1803_MAX_POS ; +return IIO_VAL_FRACTIONAL ; + } + +return -EINVAL ; +} +
drivers/iio/potentiometer/ds1803.c line 98
Quoted 10 lines
drivers/iio/potentiometer/ds1803.c new file +10
-0+static int ds1803_write_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan, +int val,int val2,long mask) +{ +struct ds1803_data *data =iio_priv (indio_dev); +int pot = chan->channel; + +switch (mask) { +case IIO_CHAN_INFO_RAW : +if (val >DS1803_MAX_POS || val <0 )
check that val2 is 0 or use .write_raw_get_fmt
Quoted 33 lines
drivers/iio/potentiometer/ds1803.c new file +33
-0+return -EINVAL ; +break ; +default : +return -EINVAL ; + } + +return i2c_smbus_write_byte_data (data->client,DS1803_WRITE (pot), val); +} + +static const struct iio_info ds1803_info = { + .read_raw = ds1803_read_raw, + .write_raw = ds1803_write_raw, + .driver_module =THIS_MODULE , +}; + +static int ds1803_probe (struct i2c_client *client, +const struct i2c_device_id *id) +{ +struct device *dev = &client->dev; +struct ds1803_data *data; +struct iio_dev *indio_dev; + +/* Value of two pots is read at the same time */ +if (!i2c_check_functionality (client->adapter, +I2C_FUNC_SMBUS_WORD_DATA )) { +dev_err (dev,"SMBUS Word Data not supported\n" ); +return -EOPNOTSUPP ; + } + + indio_dev =devm_iio_device_alloc (dev,sizeof (*data)); +if (!indio_dev) +return -ENOMEM ; +
drivers/iio/potentiometer/ds1803.c line 141
Quoted 10 lines
drivers/iio/potentiometer/ds1803.c new file +10
-0+i2c_set_clientdata (client, indio_dev); + + data =iio_priv (indio_dev); + data->client = client; + data->cfg = &ds1803_cfg[id->driver_data]; + + indio_dev->dev.parent = dev; + indio_dev->info = &ds1803_info; + indio_dev->channels = ds1803_channels; + indio_dev->num_channels =DS1803_NUM_WIPERS ;
ARRAY_SIZE(ds1803_channels)
Quoted 38 lines
drivers/iio/potentiometer/ds1803.c new file +37
-0+ indio_dev->name = client->name; + +return devm_iio_device_register (dev, indio_dev); +} + +#if defined(CONFIG_OF ) +static const struct of_device_id ds1803_dt_ids[] = { + { .compatible ="maxim,ds1803-010" , .data = &ds1803_cfg[DS1803_010 ] }, + { .compatible ="maxim,ds1803-050" , .data = &ds1803_cfg[DS1803_050 ] }, + { .compatible ="maxim,ds1803-100" , .data = &ds1803_cfg[DS1803_100 ] }, + {} +}; +MODULE_DEVICE_TABLE (of, ds1803_dt_ids); +#endif /* CONFIG_OF */ + +static const struct i2c_device_id ds1803_id[] = { + {"ds1803-010" ,DS1803_010 }, + {"ds1803-050" ,DS1803_050 }, + {"ds1803-100" ,DS1803_100 }, + {} +}; +MODULE_DEVICE_TABLE (i2c, ds1803_id); + +static struct i2c_driver ds1803_driver = { + .driver = { + .name ="ds1803" , + .of_match_table =of_match_ptr (ds1803_dt_ids), + }, + .probe = ds1803_probe, + .id_table = ds1803_id, +}; + +module_i2c_driver (ds1803_driver); + +MODULE_AUTHOR ("Slawomir Stepien <[email protected]>" ); +MODULE_DESCRIPTION ("DS1803 digital potentiometer" ); +MODULE_LICENSE ("GPL v2" );
Signature · 2 lines
Peter Meerwald-Stadler +43-664-2444418 (mobile)
Quoted 6 lines · Peter Meerwald-Stadler
Quoted 4 lines
The following functions are supported:
- write, read potentiometer value
- potentiometer scaleminor comments below, nice driver
Thank you for your comments!
Quoted 3 lines
Quoted 1 line
+#include <
linux/cache.h>for what is
cache.hneeded?
It is not needed here. I will delete it in v2.
Quoted 5 lines
Quoted 5 lines
drivers/iio/potentiometer/ds1803.c new file +5
-0+static int ds1803_read_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan, +int *val,int *val2,long mask) +{ +struct ds1803_data *data =iio_priv (indio_dev);
Quoted 8 lines
drivers/iio/potentiometer/ds1803.c line 72
Quoted 6 lines
drivers/iio/potentiometer/ds1803.c new file +6
-0+int pot = chan->channel; +s32 ret; + +switch (mask) { +case IIO_CHAN_INFO_RAW : + ret =i2c_smbus_read_word_swapped (data->client,0 );maybe a #define to explain the name of register 0
Well this zero is not register nor any kind of command that DS1803 needs to send back pots values.
DS1803 only requires the standard R/W bit to be set as read.
I used _word_ function series to get back a word (16 bits) as this poti returns 16 bits.
How should I named it?
#define NON_COMMAND 0
?
Or should I use different function? (2x i2c_smbus_read_byte?)
The i2c_smbus_read_byte() function also used 0 as command for its transfers...
Quoted 7 lines
drivers/iio/potentiometer/ds1803.c line 77
Quoted 5 lines
drivers/iio/potentiometer/ds1803.c new file +5
-0+if (ret <0 ) +return ret; + +/* Get bits for given pot */ + *val = (pot ==0 ? ret >>8 : ret &255 );often
0xffis used to mask a byte
OK.
Quoted 15 lines
Quoted 15 lines
drivers/iio/potentiometer/ds1803.c new file +15
-0+return IIO_VAL_INT ; + +case IIO_CHAN_INFO_SCALE : + *val =1000 * data->cfg->kohms; + *val2 =DS1803_MAX_POS ; +return IIO_VAL_FRACTIONAL ; + } + +return -EINVAL ; +} + +static int ds1803_write_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan, +int val,int val2,long mask) +{
Quoted 8 lines
drivers/iio/potentiometer/ds1803.c line 98
Quoted 6 lines
drivers/iio/potentiometer/ds1803.c new file +6
-0+struct ds1803_data *data =iio_priv (indio_dev); +int pot = chan->channel; + +switch (mask) { +case IIO_CHAN_INFO_RAW : +if (val >DS1803_MAX_POS || val <0 )check that val2 is 0 or use .write_raw_get_fmt
At this point I do not know why should I do it, but I will look into that.
Quoted 6 lines
drivers/iio/potentiometer/ds1803.c line 141
Quoted 4 lines
drivers/iio/potentiometer/ds1803.c new file +4
-0+ indio_dev->dev.parent = dev; + indio_dev->info = &ds1803_info; + indio_dev->channels = ds1803_channels; + indio_dev->num_channels =DS1803_NUM_WIPERS ;
ARRAY_SIZE(ds1803_channels)
Good point.
Signature · 1 line
Slawomir Stepien
Quoted 9 lines
Quoted 2 lines
maybe a #define to explain the name of register 0
Well this zero is not register nor any kind of command that DS1803 needs to send back pots values.
DS1803 only requires the standard R/W bit to be set as read.
I used _word_ function series to get back a word (16 bits) as this poti returns 16 bits.
Quoted 4 lines
How should I named it?
#define
NON_COMMAND0
?
maybe i2c_transfer() is more appropriate then
u8 databuf[2];
struct i2c_msg msgs[2] = {
{ .addr = client->addr, .len = sizeof(databuf), .buf = databuf,
.flags = I2C_M_RD } };
ret = i2c_transfer(client->adapter, msgs, 2);this does not send any data to the chip but only reads two bytes
Quoted 18 lines
Or should I use different function? (2x
i2c_smbus_read_byte?)The
i2c_smbus_read_byte()function also used 0 as command for its transfers...Quoted 4 lines
Quoted 4 lines
drivers/iio/potentiometer/ds1803.c new file +4
-0+static int ds1803_write_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan, +int val,int val2,long mask) +{Quoted 8 lines
drivers/iio/potentiometer/ds1803.c line 98
Quoted 6 lines
drivers/iio/potentiometer/ds1803.c new file +6
-0+struct ds1803_data *data =iio_priv (indio_dev); +int pot = chan->channel; + +switch (mask) { +case IIO_CHAN_INFO_RAW : +if (val >DS1803_MAX_POS || val <0 )check that val2 is 0 or use .write_raw_get_fmt
Quoted 1 line
At this point I do not know why should I do it, but I will look into that.
write_raw expects a VAL_INT_PLUS_MICROS per default, passed in val and val2
you can change that with .write_raw_get_fmt (e.g. to expect VAL_INT), or just make sure that the micros are 0
Signature · 2 lines
Peter Meerwald-Stadler +43-664-2444418 (mobile)
Quoted 16 lines · Peter Meerwald-Stadler
Quoted 9 lines
Quoted 2 lines
maybe a #define to explain the name of register 0
Well this zero is not register nor any kind of command that DS1803 needs to send back pots values.
DS1803 only requires the standard R/W bit to be set as read.
I used _word_ function series to get back a word (16 bits) as this poti returns 16 bits.Quoted 4 lines
How should I named it?
#define
NON_COMMAND0
?maybe
i2c_transfer()is more appropriate then
Quoted 7 lines
u8 databuf[2]; struct i2c_msg msgs[2] = { { .addr = client->addr, .len = sizeof(databuf), .buf = databuf, .flags = I2C_M_RD } }; ret = i2c_transfer(client->adapter, msgs, 2);this does not send any data to the chip but only reads two bytes
Good point. But maybe the better solution would be to use i2c_master_recv? Anyhow I will check both options ;)
Quoted 18 lines
Quoted 18 lines
Or should I use different function? (2x
i2c_smbus_read_byte?)The
i2c_smbus_read_byte()function also used 0 as command for its transfers...Quoted 12 lines
drivers/iio/potentiometer/ds1803.c line 98
Quoted 10 lines
drivers/iio/potentiometer/ds1803.c new file +10
-0+static int ds1803_write_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan, +int val,int val2,long mask) +{ +struct ds1803_data *data =iio_priv (indio_dev); +int pot = chan->channel; + +switch (mask) { +case IIO_CHAN_INFO_RAW : +if (val >DS1803_MAX_POS || val <0 )check that val2 is 0 or use .write_raw_get_fmt
Quoted 7 lines
Quoted 1 line
At this point I do not know why should I do it, but I will look into that.
write_rawexpects aVAL_INT_PLUS_MICROSper default, passed in val and val2you can change that with .write_raw_get_fmt (e.g. to expect
VAL_INT), or just make sure that the micros are 0
Thank you for the explanation.
Signature · 1 line
Slawomir Stepien