iio: potentiometer: add TI tpl0102 support
PATCH 1/1 iio: potentiometer: add TI tpl0102 support
Add support for the TI family of digital potentiometers.
--- drivers/iio/potentiometer/Kconfig | 11 +++ drivers/iio/potentiometer/Makefile | 1 + drivers/iio/potentiometer/tpl0102.c | 166 ++++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 drivers/iio/potentiometer/tpl0102.c
drivers/iio/potentiometer/Kconfig +11 -0
@@ -17,4 +17,15 @@ config MCP4531 To compile this driver as a module, choose M here: the module will be called mcp4531. +config TPL0102 + tristate "Texas Instruments digital potentiometer driver" + depends on I2C + help + Say yes here to build support for the Texas Instruments + TPL0102, TPL0402 + digital potentiometer chips. + + To compile this driver as a module, choose M here: the + module will be called tpl0102. + endmenu
drivers/iio/potentiometer/Makefile +1 -0
@@ -4,3 +4,4 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_MCP4531) += mcp4531.o +obj-$(CONFIG_TPL0102) += tpl0102.o
drivers/iio/potentiometer/tpl0102.c new file +166 -0
166 lines not on this page · raw message
Signature · 1 line
2.7.0
Quoted 3 lines · Matt Ranostay
Add support for the TI family of digital potentiometers.
Signed-off-by Matt Ranostay <[email protected]>
Various comments inline but basically a nice simple driver.
Jonathan
Quoted 14 lines
---
drivers/iio/potentiometer/Kconfig | 11 +++ drivers/iio/potentiometer/Makefile | 1 + drivers/iio/potentiometer/tpl0102.c | 166 ++++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+)create mode 100644
drivers/iio/potentiometer/tpl0102.cdrivers/iio/potentiometer/Kconfig +0
-0
drivers/iio/potentiometer/Kconfig config MCP4531 · line 22
Quoted 6 lines
drivers/iio/potentiometer/Kconfig +3
-0@@ -17,4 +17,15 @@ config MCP4531 To compile this driver as a module, choose M here: the module will be called mcp4531. +config TPL0102 + tristate "Texas Instruments digital potentiometer driver" + depends on I2C
Regmap depency as well.
Quoted 52 lines
drivers/iio/potentiometer/Kconfig +8
-0+ help + Say yes here to build support for the Texas Instruments + TPL0102, TPL0402 + digital potentiometer chips. + + To compile this driver as a module, choose M here: the + module will be called tpl0102. +endmenu
drivers/iio/potentiometer/Makefile +0
-0@@ -4,3 +4,4 @@ # When adding new entries keep the list in alphabetical orderobj-$(CONFIG_MCP4531) += mcp4531.o
drivers/iio/potentiometer/Makefile +1
-0+obj-$(CONFIG_TPL0102) += tpl0102.odrivers/iio/potentiometer/tpl0102.c new file +6
-0@@ -0,0 +1,166 @@ +/* +* tpl0102.c - Support for Texas Instruments digital potentiometers +* +* Copyright (C) 2016 Matt Ranostay <[email protected]> +* +* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * TODO: enable/disable hi-z output control
+ */drivers/iio/potentiometer/tpl0102.c new file +7
-0+ +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/regmap.h> +#include <linux/iio/iio.h> + +struct tpl0102_cfg {
drivers/iio/potentiometer/tpl0102.c line 34
Quoted 10 lines
drivers/iio/potentiometer/tpl0102.c new file +10
-0+int wipers; +int max_pos; +int kohms; +}; + +enum tpl0102_type { +TPL0102_104 , +TPL0401_103 , +CAT5140_503 , +CAT5140_104 ,
Numeric / alphabetical order preferred.
drivers/iio/potentiometer/tpl0102.c line 43
Quoted 9 lines
drivers/iio/potentiometer/tpl0102.c new file +9
-0+}; + +static const struct tpl0102_cfg tpl0102_cfg[] = { +/* ti parts */ + [TPL0102_104 ] = { .wipers =2 , .max_pos =256 , .kohms =100 }, + [TPL0401_103 ] = { .wipers =1 , .max_pos =128 , .kohms =10 , }, +/* on-semiconductor parts */ + [CAT5140_503 ] = { .wipers =1 , .max_pos =256 , .kohms =50 , }, + [CAT5140_104 ] = { .wipers =1 , .max_pos =256 , .kohms =100 , },
Alphabetical order would be a little better.
Quoted 27 lines
drivers/iio/potentiometer/tpl0102.c new file +27
-0+}; + +struct tpl0102_data { +struct regmap *regmap; +unsigned long devid; +}; + +static const struct regmap_config tpl0102_regmap_config = { + .reg_bits =8 , + .val_bits =8 , +}; + +#define TPL0102_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 tpl0102_channels[] = { +TPL0102_CHANNEL (0 ), +TPL0102_CHANNEL (1 ), +}; + +static int tpl0102_read_raw(struct iio_dev *indio_dev,
drivers/iio/potentiometer/tpl0102.c line 80
Quoted 10 lines
drivers/iio/potentiometer/tpl0102.c new file +10
-0+struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct tpl0102_data *data = iio_priv(indio_dev); + +switch (mask) { +case IIO_CHAN_INFO_RAW : { +return regmap_read (data->regmap, chan->channel, val) + ? -EIO :IIO_VAL_INT ; + }
Doesn't regmap_read return specific errors?
Quoted 12 lines
drivers/iio/potentiometer/tpl0102.c new file +12
-0+case IIO_CHAN_INFO_SCALE : + *val =1000 * tpl0102_cfg[data->devid].kohms; + *val2 = tpl0102_cfg[data->devid].max_pos; +return IIO_VAL_FRACTIONAL ; + } + +return -EINVAL ; +} + +static int tpl0102_write_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan, +int val,int val2,long mask)
drivers/iio/potentiometer/tpl0102.c line 102
Quoted 10 lines
drivers/iio/potentiometer/tpl0102.c new file +10
-0+{ +struct tpl0102_data *data =iio_priv (indio_dev); + +if (mask !=IIO_CHAN_INFO_RAW ) +return -EINVAL ; + +if (val >= tpl0102_cfg[data->devid].max_pos || val <0 ) +return -EINVAL ; + +return regmap_write (data->regmap, chan->channel, val &0xff );
Mask add anything given you have already checked the range?
drivers/iio/potentiometer/tpl0102.c line 114
Quoted 12 lines
drivers/iio/potentiometer/tpl0102.c new file +12
-0+} + +static const struct iio_info tpl0102_info = { + .read_raw = tpl0102_read_raw, + .write_raw = tpl0102_write_raw, + .driver_module =THIS_MODULE , +}; + +static int tpl0102_probe (struct i2c_client *client, +const struct i2c_device_id *id) +{ +struct device *dev = &client->dev;
Local dev variable doesn't add anything here and makes code slightly less obvious.
Quoted 5 lines
drivers/iio/potentiometer/tpl0102.c new file +5
-0+struct tpl0102_data *data; +long devid = id->driver_data; +struct iio_dev *indio_dev; + + if (!i2c_check_functionality(client->adapter,
drivers/iio/potentiometer/tpl0102.c line 129
Quoted 10 lines
drivers/iio/potentiometer/tpl0102.c new file +10
-0+ I2C_FUNC_SMBUS_WORD_DATA)) +return -ENOTSUPP ; + + indio_dev =devm_iio_device_alloc (dev,sizeof (*data)); +if (!indio_dev) +return -ENOMEM ; + data =iio_priv (indio_dev); +i2c_set_clientdata (client, indio_dev); + + data->devid = devid;
Why local devid variable?
drivers/iio/potentiometer/tpl0102.c line 142
Quoted 13 lines
drivers/iio/potentiometer/tpl0102.c new file +13
-0+ data->regmap =devm_regmap_init_i2c (client, &tpl0102_regmap_config); +if (IS_ERR (data->regmap)) { +dev_err (dev,"regmap initialization failed\n" ); +return PTR_ERR (data->regmap); + } + + indio_dev->dev.parent = dev; + indio_dev->info = &tpl0102_info; + indio_dev->channels = tpl0102_channels; + indio_dev->num_channels = tpl0102_cfg[devid].wipers; + indio_dev->name = client->name; + +return iio_device_register (indio_dev);
devm_ or you need to explicitly unregister in a remove function.
Quoted 25 lines
drivers/iio/potentiometer/tpl0102.c new file +24
-0+} + +static const struct i2c_device_id tpl0102_id[] = { + {"tpl0102-104" ,TPL0102_104 }, + {"tpl0401-103" ,TPL0401_103 }, + {"cat5140-503" ,CAT5140_503 }, + {"cat5140-104" ,CAT5140_104 }, + {} +}; +MODULE_DEVICE_TABLE (i2c, tpl0102_id); + +static struct i2c_driver tpl0102_driver = { + .driver = { + .name ="tpl0102" , + }, + .probe = tpl0102_probe, + .id_table = tpl0102_id, +}; + +module_i2c_driver (tpl0102_driver); + +MODULE_AUTHOR ("Matt Ranostay <[email protected]>" ); +MODULE_DESCRIPTION ("TPL0102 digital potentiometer" ); +MODULE_LICENSE ("GPL" );
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse my brevity.
Quoted 26 lines · Jonathan Cameron
Quoted 3 lines · Matt Ranostay
Add support for the TI family of digital potentiometers.
Signed-off-by Matt Ranostay <[email protected]>Various comments inline but basically a nice simple driver.
Jonathan
Quoted 17 lines
---
drivers/iio/potentiometer/Kconfig | 11 +++ drivers/iio/potentiometer/Makefile | 1 + drivers/iio/potentiometer/tpl0102.c | 166 ++++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+)create mode 100644
drivers/iio/potentiometer/tpl0102.cdrivers/iio/potentiometer/Kconfig +0
-0@@ -17,4 +17,15 @@ config MCP4531 To compile this driver as a module, choose M here: the module will be called mcp4531.
Quoted 4 lines
drivers/iio/potentiometer/Kconfig config MCP4531 · line 22
Quoted 3 lines
drivers/iio/potentiometer/Kconfig +3
-0+config TPL0102 + tristate "Texas Instruments digital potentiometer driver" + depends on I2CRegmap depency as well.
Noted
Quoted 55 lines
Quoted 55 lines
drivers/iio/potentiometer/Kconfig +8
-0+ help + Say yes here to build support for the Texas Instruments + TPL0102, TPL0402 + digital potentiometer chips. + + To compile this driver as a module, choose M here: the + module will be called tpl0102. +endmenu
drivers/iio/potentiometer/Makefile +0
-0@@ -4,3 +4,4 @@ # When adding new entries keep the list in alphabetical orderobj-$(CONFIG_MCP4531) += mcp4531.o
drivers/iio/potentiometer/Makefile +1
-0+obj-$(CONFIG_TPL0102) += tpl0102.odrivers/iio/potentiometer/tpl0102.c new file +6
-0@@ -0,0 +1,166 @@ +/* +* tpl0102.c - Support for Texas Instruments digital potentiometers +* +* Copyright (C) 2016 Matt Ranostay <[email protected]> +* +* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * TODO: enable/disable hi-z output control
+ */drivers/iio/potentiometer/tpl0102.c new file +10
-0+ +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/regmap.h> +#include <linux/iio/iio.h> + +struct tpl0102_cfg { +int wipers; +int max_pos; +int kohms;
Quoted 8 lines
drivers/iio/potentiometer/tpl0102.c line 34
Quoted 7 lines
drivers/iio/potentiometer/tpl0102.c new file +7
-0+}; + +enum tpl0102_type { +TPL0102_104 , +TPL0401_103 , +CAT5140_503 , +CAT5140_104 ,Numeric / alphabetical order preferred.
Ok.
Quoted 10 lines
drivers/iio/potentiometer/tpl0102.c line 43
Quoted 9 lines
drivers/iio/potentiometer/tpl0102.c new file +9
-0+}; + +static const struct tpl0102_cfg tpl0102_cfg[] = { +/* ti parts */ + [TPL0102_104 ] = { .wipers =2 , .max_pos =256 , .kohms =100 }, + [TPL0401_103 ] = { .wipers =1 , .max_pos =128 , .kohms =10 , }, +/* on-semiconductor parts */ + [CAT5140_503 ] = { .wipers =1 , .max_pos =256 , .kohms =50 , }, + [CAT5140_104 ] = { .wipers =1 , .max_pos =256 , .kohms =100 , },Alphabetical order would be a little better.
Ok
Quoted 53 lines
Quoted 27 lines
drivers/iio/potentiometer/tpl0102.c new file +27
-0+}; + +struct tpl0102_data { +struct regmap *regmap; +unsigned long devid; +}; + +static const struct regmap_config tpl0102_regmap_config = { + .reg_bits =8 , + .val_bits =8 , +}; + +#define TPL0102_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 tpl0102_channels[] = { +TPL0102_CHANNEL (0 ), +TPL0102_CHANNEL (1 ), +}; + +static int tpl0102_read_raw(struct iio_dev *indio_dev,drivers/iio/potentiometer/tpl0102.c line 80
Quoted 10 lines
drivers/iio/potentiometer/tpl0102.c new file +10
-0+struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct tpl0102_data *data = iio_priv(indio_dev); + +switch (mask) { +case IIO_CHAN_INFO_RAW : { +return regmap_read (data->regmap, chan->channel, val) + ? -EIO :IIO_VAL_INT ; + }Doesn't
regmap_readreturn specific errors?Quoted 15 lines
drivers/iio/potentiometer/tpl0102.c new file +15
-0+case IIO_CHAN_INFO_SCALE : + *val =1000 * tpl0102_cfg[data->devid].kohms; + *val2 = tpl0102_cfg[data->devid].max_pos; +return IIO_VAL_FRACTIONAL ; + } + +return -EINVAL ; +} + +static int tpl0102_write_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan, +int val,int val2,long mask) +{ +struct tpl0102_data *data =iio_priv (indio_dev); +
Quoted 8 lines
drivers/iio/potentiometer/tpl0102.c line 102
Quoted 7 lines
drivers/iio/potentiometer/tpl0102.c new file +7
-0+if (mask !=IIO_CHAN_INFO_RAW ) +return -EINVAL ; + +if (val >= tpl0102_cfg[data->devid].max_pos || val <0 ) +return -EINVAL ; + +return regmap_write (data->regmap, chan->channel, val &0xff );Mask add anything given you have already checked the range?
Paranoid I guess :). Will drop.
Quoted 13 lines
drivers/iio/potentiometer/tpl0102.c line 114
Quoted 12 lines
drivers/iio/potentiometer/tpl0102.c new file +12
-0+} + +static const struct iio_info tpl0102_info = { + .read_raw = tpl0102_read_raw, + .write_raw = tpl0102_write_raw, + .driver_module =THIS_MODULE , +}; + +static int tpl0102_probe (struct i2c_client *client, +const struct i2c_device_id *id) +{ +struct device *dev = &client->dev;Local dev variable doesn't add anything here and makes code slightly less obvious.
Quoted 16 lines
Quoted 5 lines
drivers/iio/potentiometer/tpl0102.c new file +5
-0+struct tpl0102_data *data; +long devid = id->driver_data; +struct iio_dev *indio_dev; + + if (!i2c_check_functionality(client->adapter,drivers/iio/potentiometer/tpl0102.c line 129
Quoted 10 lines
drivers/iio/potentiometer/tpl0102.c new file +10
-0+ I2C_FUNC_SMBUS_WORD_DATA)) +return -ENOTSUPP ; + + indio_dev =devm_iio_device_alloc (dev,sizeof (*data)); +if (!indio_dev) +return -ENOMEM ; + data =iio_priv (indio_dev); +i2c_set_clientdata (client, indio_dev); + + data->devid = devid;Why local devid variable?
Referenced below but seeing it is only used once it doesn't have to be local.
Quoted 6 lines
Quoted 6 lines
drivers/iio/potentiometer/tpl0102.c new file +6
-0+ data->regmap =devm_regmap_init_i2c (client, &tpl0102_regmap_config); +if (IS_ERR (data->regmap)) { +dev_err (dev,"regmap initialization failed\n" ); +return PTR_ERR (data->regmap); + } +
Quoted 8 lines
drivers/iio/potentiometer/tpl0102.c line 142
Quoted 7 lines
drivers/iio/potentiometer/tpl0102.c new file +7
-0+ indio_dev->dev.parent = dev; + indio_dev->info = &tpl0102_info; + indio_dev->channels = tpl0102_channels; + indio_dev->num_channels = tpl0102_cfg[devid].wipers; + indio_dev->name = client->name; + +return iio_device_register (indio_dev);
devm_or you need to explicitly unregister in a remove function.
Oops. Will fix in v2.
Quoted 29 lines
Quoted 16 lines
drivers/iio/potentiometer/tpl0102.c new file +14
-0+} + +static const struct i2c_device_id tpl0102_id[] = { + {"tpl0102-104" ,TPL0102_104 }, + {"tpl0401-103" ,TPL0401_103 }, + {"cat5140-503" ,CAT5140_503 }, + {"cat5140-104" ,CAT5140_104 }, + {} +}; +MODULE_DEVICE_TABLE (i2c, tpl0102_id); + +static struct i2c_driver tpl0102_driver = { + .driver = { + .name ="tpl0102" ,drivers/iio/potentiometer/tpl0102.c line 166
Quoted 10 lines
drivers/iio/potentiometer/tpl0102.c new file +10
-0+ }, + .probe = tpl0102_probe, + .id_table = tpl0102_id, +}; + +module_i2c_driver (tpl0102_driver); + +MODULE_AUTHOR ("Matt Ranostay <[email protected]>" ); +MODULE_DESCRIPTION ("TPL0102 digital potentiometer" ); +MODULE_LICENSE ("GPL" );--
Sent from my Android device with K-9 Mail. Please excuse my brevity.