Skip to contentSkip to conversation

iio: potentiometer: add driver for Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X

PATCH Superseded Slawomir Stepien 2 participants 3 messages Mar 22, 2016

Subsystems (2)

v4 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

PATCH v4 1/1 iio: potentiometer: add driver for Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X

The following functionalities are supported:
- write, read from volatile memory

Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf

---
Changes since v3:
- Added 'potentiometer' to subject
- Replaced mcp4131_exec with spi_write and mcp4131_read
- Narrowed mutex locking and unlocking places

Changes since v2:
- Removed unnecessary parentheses in MCP4131_WIPER_SHIFT macro
- Replaced the rx and tx SPI buffers with one buf that is ____cacheline_aligned
- Changed mutex locking position
- Replaced the devid with pointer to model configuration
- Removed positive ("Registered" & "Unregistered") dev_info prints
- Removed the mcp4131_remove callback

Changes since v1:
- One line summary changed
- Fixed module name and OF compatible
- Based code on Peter Rosin's code from mcp4531.c
- No additional sysfs attributes
- Deleted not used devid struct memeber
- Changed mcp4131_exec function arguments:
- write value is now u16
- no need to pass return buffer array - rx array from mcp4131_data is used
- Added missing new line characters to dev_info

---
 .../bindings/iio/potentiometer/mcp4131.txt         |  84 ++++
 drivers/iio/potentiometer/Kconfig                  |  18 +
 drivers/iio/potentiometer/Makefile                 |   1 +
 drivers/iio/potentiometer/mcp4131.c                | 492 +++++++++++++++++++++
 4 files changed, 595 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/potentiometer/mcp4131.txt
 create mode 100644 drivers/iio/potentiometer/mcp4131.c
Documentation/devicetree/bindings/iio/potentiometer/mcp4131.txt new file +84 -0
new file mode 100644
index 0000000..3ccba16
@@ -0,0 +1,84 @@
+* Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer
+  driver
+
+The node for this driver must be a child node of a SPI controller, hence
+all mandatory properties described in
+
+        Documentation/devicetree/bindings/spi/spi-bus.txt
+
+must be specified.
+
+Required properties:
+	- compatible:  	Must be one of the following, depending on the
+			model:
+			"microchip,mcp4131-502"
+			"microchip,mcp4131-103"
+			"microchip,mcp4131-503"
+			"microchip,mcp4131-104"
+			"microchip,mcp4132-502"
+			"microchip,mcp4132-103"
+			"microchip,mcp4132-503"
+			"microchip,mcp4132-104"
+			"microchip,mcp4141-502"
+			"microchip,mcp4141-103"
+			"microchip,mcp4141-503"
+			"microchip,mcp4141-104"
+			"microchip,mcp4142-502"
+			"microchip,mcp4142-103"
+			"microchip,mcp4142-503"
+			"microchip,mcp4142-104"
+			"microchip,mcp4151-502"
+			"microchip,mcp4151-103"
+			"microchip,mcp4151-503"
+			"microchip,mcp4151-104"
+			"microchip,mcp4152-502"
+			"microchip,mcp4152-103"
+			"microchip,mcp4152-503"
+			"microchip,mcp4152-104"
+			"microchip,mcp4161-502"
+			"microchip,mcp4161-103"
+			"microchip,mcp4161-503"
+			"microchip,mcp4161-104"
+			"microchip,mcp4162-502"
+			"microchip,mcp4162-103"
+			"microchip,mcp4162-503"
+			"microchip,mcp4162-104"
+			"microchip,mcp4231-502"
+			"microchip,mcp4231-103"
+			"microchip,mcp4231-503"
+			"microchip,mcp4231-104"
+			"microchip,mcp4232-502"
+			"microchip,mcp4232-103"
+			"microchip,mcp4232-503"
+			"microchip,mcp4232-104"
+			"microchip,mcp4241-502"
+			"microchip,mcp4241-103"
+			"microchip,mcp4241-503"
+			"microchip,mcp4241-104"
+			"microchip,mcp4242-502"
+			"microchip,mcp4242-103"
+			"microchip,mcp4242-503"
+			"microchip,mcp4242-104"
+			"microchip,mcp4251-502"
+			"microchip,mcp4251-103"
+			"microchip,mcp4251-503"
+			"microchip,mcp4251-104"
+			"microchip,mcp4252-502"
+			"microchip,mcp4252-103"
+			"microchip,mcp4252-503"
+			"microchip,mcp4252-104"
+			"microchip,mcp4261-502"
+			"microchip,mcp4261-103"
+			"microchip,mcp4261-503"
+			"microchip,mcp4261-104"
+			"microchip,mcp4262-502"
+			"microchip,mcp4262-103"
+			"microchip,mcp4262-503"
+			"microchip,mcp4262-104"
+
+Example:
+mcp4131: mcp4131@0 {
+	compatible = "mcp4131-502";
+	reg = <0>;
+	spi-max-frequency = <500000>;
+};
drivers/iio/potentiometer/Kconfig +18 -0
index fd75db7..5ef181a 100644
@@ -5,6 +5,24 @@
 
 menu "Digital potentiometers"
 
+config MCP4131
+	tristate "Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer driver"
+	depends on SPI
+	help
+	  Say yes here to build support for the Microchip
+	  MCP4131, MCP4132,
+	  MCP4141, MCP4142,
+	  MCP4151, MCP4152,
+	  MCP4161, MCP4162,
+	  MCP4231, MCP4232,
+	  MCP4241, MCP4242,
+	  MCP4251, MCP4252,
+	  MCP4261, MCP4262,
+	  digital potentiomenter chips.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mcp4131.
+
 config MCP4531
 	tristate "Microchip MCP45xx/MCP46xx Digital Potentiometer driver"
 	depends on I2C
drivers/iio/potentiometer/Makefile +1 -0
index 8afe492..cd5c80b 100644
@@ -3,4 +3,5 @@
 #
 
 # When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_MCP4131) += mcp4131.o
 obj-$(CONFIG_MCP4531) += mcp4531.o
drivers/iio/potentiometer/mcp4131.c new file +492 -0

492 lines not on this page · raw message

Signature · 1 line
2.7.4
#1 lore raw

Hi Slawomir,

drivers/iio/potentiometer/mcp4131.c line 41

Quoted 13 lines · Slawomir Stepien

The following functionalities are supported:
- write, read from volatile memory

Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf

---

drivers/iio/potentiometer/mcp4131.c new file +5 -0
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+
+#include <linux/iio/iio.h>

Give that you use that you have a some OF stuff in your driver you should also include <linux/of.h>. Same goes for <linux/mutex.h>. I am sure this builds fine without those includes, but you should explicitly include stuff that you use.

While you're at it you could also put the includes in alphabetic order.

Quoted 14 lines
drivers/iio/potentiometer/mcp4131.c new file +14 -0
+static int mcp4131_read_raw(struct iio_dev *indio_dev,
+                           struct iio_chan_spec const *chan,
+                           int *val, int *val2, long mask)
+{
+       int err;
+       struct mcp4131_data *data = iio_priv(indio_dev);
+       int address = chan->channel;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               mutex_lock(&data->lock);
+
+               data->buf[0] = (address << MCP4131_WIPER_SHIFT) | MCP4131_READ;
+               data->buf[1] = 0;

drivers/iio/potentiometer/mcp4131.c line 185

Quoted 10 lines
drivers/iio/potentiometer/mcp4131.c new file +10 -0
+
+               err = mcp4131_read(data->spi, data->buf, 2);
+               if (err) {
+                       mutex_unlock(&data->lock);
+                       return err;
+               }
+
+               /* Error, bad address/command combination */
+               if (!MCP4131_CMDERR(data->buf))
+                       return -EIO;

Missing mutex unlock here.

Quoted 37 lines
drivers/iio/potentiometer/mcp4131.c new file +37 -0
+
+               *val = MCP4131_RAW(data->buf);
+               mutex_unlock(&data->lock);
+
+               return IIO_VAL_INT;
+
+       case IIO_CHAN_INFO_SCALE:
+               *val = 1000 * data->cfg->kohms;
+               *val2 = data->cfg->max_pos;
+               return IIO_VAL_FRACTIONAL;
+       }
+
+       return -EINVAL;
+}
+
+static int mcp4131_write_raw(struct iio_dev *indio_dev,
+                            struct iio_chan_spec const *chan,
+                            int val, int val2, long mask)
+{
+       int err;
+       struct mcp4131_data *data = iio_priv(indio_dev);
+       int address = chan->channel << MCP4131_WIPER_SHIFT;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               if (val > data->cfg->max_pos || val < 0)
+                       return -EINVAL;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       mutex_lock(&data->lock);
+
+       data->buf[0] = address << MCP4131_WIPER_SHIFT;
+       data->buf[0] |= MCP4131_WRITE | (val >> 8);

drivers/iio/potentiometer/mcp4131.c line 232

Quoted 10 lines
drivers/iio/potentiometer/mcp4131.c new file +10 -0
+       data->buf[1] = val & 0xFF; /* 8 bits here */
+
+       err = spi_write(data->spi, data->buf, 2);
+       if (err) {
+               mutex_unlock(&data->lock);
+               return err;
+       }
+       mutex_unlock(&data->lock);
+
+       return 0;

This last part could be written as:
err = spi_write(data->spi, data->buf, 2);
mutex_unlock(&data->lock);

return err;

Other than the things I noted driver looks good to me.

regards,
Joachim Eastwood

#2 lore raw
Quoted 11 lines · Joachim Eastwood

Hi Slawomir,

Quoted 7 lines · Slawomir Stepien

The following functionalities are supported:
- write, read from volatile memory

Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf

---

Quoted 10 lines

drivers/iio/potentiometer/mcp4131.c line 41

Quoted 5 lines
drivers/iio/potentiometer/mcp4131.c new file +5 -0
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+
+#include <linux/iio/iio.h>

Give that you use that you have a some OF stuff in your driver you should also include <linux/of.h>. Same goes for <linux/mutex.h>. I am sure this builds fine without those includes, but you should explicitly include stuff that you use.

Oh yes that's true.

Quoted 1 line

While you're at it you could also put the includes in alphabetic order.

OK

Quoted 18 lines
Quoted 18 lines
drivers/iio/potentiometer/mcp4131.c new file +18 -0
+static int mcp4131_read_raw(struct iio_dev *indio_dev,
+                           struct iio_chan_spec const *chan,
+                           int *val, int *val2, long mask)
+{
+       int err;
+       struct mcp4131_data *data = iio_priv(indio_dev);
+       int address = chan->channel;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               mutex_lock(&data->lock);
+
+               data->buf[0] = (address << MCP4131_WIPER_SHIFT) | MCP4131_READ;
+               data->buf[1] = 0;
+
+               err = mcp4131_read(data->spi, data->buf, 2);
+               if (err) {
+                       mutex_unlock(&data->lock);
Quoted 8 lines

drivers/iio/potentiometer/mcp4131.c line 185

Quoted 6 lines
drivers/iio/potentiometer/mcp4131.c new file +6 -0
+                       return err;
+               }
+
+               /* Error, bad address/command combination */
+               if (!MCP4131_CMDERR(data->buf))
+                       return -EIO;

Missing mutex unlock here.

Oh ;) I'll fix that.

Quoted 52 lines
Quoted 37 lines
drivers/iio/potentiometer/mcp4131.c new file +37 -0
+
+               *val = MCP4131_RAW(data->buf);
+               mutex_unlock(&data->lock);
+
+               return IIO_VAL_INT;
+
+       case IIO_CHAN_INFO_SCALE:
+               *val = 1000 * data->cfg->kohms;
+               *val2 = data->cfg->max_pos;
+               return IIO_VAL_FRACTIONAL;
+       }
+
+       return -EINVAL;
+}
+
+static int mcp4131_write_raw(struct iio_dev *indio_dev,
+                            struct iio_chan_spec const *chan,
+                            int val, int val2, long mask)
+{
+       int err;
+       struct mcp4131_data *data = iio_priv(indio_dev);
+       int address = chan->channel << MCP4131_WIPER_SHIFT;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               if (val > data->cfg->max_pos || val < 0)
+                       return -EINVAL;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       mutex_lock(&data->lock);
+
+       data->buf[0] = address << MCP4131_WIPER_SHIFT;
+       data->buf[0] |= MCP4131_WRITE | (val >> 8);

drivers/iio/potentiometer/mcp4131.c line 232

Quoted 10 lines
drivers/iio/potentiometer/mcp4131.c new file +10 -0
+       data->buf[1] = val & 0xFF; /* 8 bits here */
+
+       err = spi_write(data->spi, data->buf, 2);
+       if (err) {
+               mutex_unlock(&data->lock);
+               return err;
+       }
+       mutex_unlock(&data->lock);
+
+       return 0;

This last part could be written as:
err = spi_write(data->spi, data->buf, 2);
mutex_unlock(&data->lock);

Quoted 1 line

return err;

OK

Quoted 5 lines

Other than the things I noted driver looks good to me.

regards,
Joachim Eastwood

Signature · 1 line
Slawomir Stepien