Thread (1 message) 1 message, 1 author, 2013-08-27
STALE4722d

[RESEND PATCH v2] gpio: Enable pcf857x GPIO expander for Device Tree

From: Archit Taneja <hidden>
Date: 2013-08-27 05:27:03
Also in: linux-arm-kernel, linux-omap
Subsystem: gpio subsystem, open firmware and flattened device tree bindings, the rest · Maintainers: Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Torvalds

Add code to parse the GPIO expander Device Tree node and extract platform data
out of it, and populate the struct 'pcf857x_platform_data' maintained by the
driver. This enables devices to reference the gpio expander from Device Tree.

Add DT binding info in Documentation.

Signed-off-by: Archit Taneja <redacted>
---
- v2 posted after quite a while, sorry for the delay!

Changes in v2:
- second gpeio-cell description corrected in Documentation
- interrupt controller description removed for now, will be added in a follow
  up patch
- n_latch description updated

 .../devicetree/bindings/gpio/gpio-pcf857x.txt      | 41 ++++++++++++++++
 drivers/gpio/gpio-pcf857x.c                        | 57 ++++++++++++++++++++--
 2 files changed, 94 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt
diff --git a/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt b/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt
new file mode 100644
index 0000000..504d114
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt
@@ -0,0 +1,41 @@
+PCF857x I2C based GPIO controller bindings
+
+Required properties:
+- compatible:
+  - "nxp,pca9670" for NXP PCA9670 8 bit I/O expander
+  - "nxp,pca9672" for NXP PCA9672 8 bit I/O expander with interrupt
+  - "nxp,pca9674" for NXP PCA9672 8 bit I/O expander with interrupt
+  - "nxp,pca8574" for NXP PCA8574 8 bit I/O expander with interrupt
+  - "nxp,pca8575" for NXP PCA8575 16 bit I/O expander with interrupt
+  - "nxp,pca9671" for NXP PCA9671 16 bit I/O expander
+  - "nxp,pca9673" for NXP PCA9673 16 bit I/O expander with interrupt
+  - "nxp,pca9675" for NXP PCA9675 16 bit I/O expander with interrupt
+  - "ti,pcf8574"  for TI PCF8574 8 bit I/O expander with interrupt
+  - "ti,pcf8574a" for TI PCF8574A 8 bit I/O expander with interrupt
+  - "ti,pcf8575"  for TI PCF8575 16 bit I/O expander with interrupt
+  - "ti,tca9554"  for TI TCA9554 8 bit I/O expander with interrupt
+  - "maxim,max7328" for MAXIM MAX7328 8 bit I/O expander with interrupt
+  - "maxim,max7329" for MAXIM MAX7329 8 bit I/O expander with interrupt
+- gpio-controller : Marks the device node as a GPIO controller.
+- #gpio-cells : Should be two.
+  - first cell is the pin number.
+  - second cell is used to specify optional parameters (currently unused, but
+    needed by gpiolib).
+- reg: I2C address of the chip.
+
+Device speific properties:
+- n_latch:		optional bit-inverse of initial register value; if
+			you leave this initialized to zero the driver will act
+			like the chip was just reset. If it is a non-zero
+			value, the driver will program the inverted value of
+			n_latch as the initial state of the gpios.
+
+Example:
+
+pcf8575: pcf8575 {
+	compatible = "ti,pcf8575";
+	gpio-controller;
+	#gpio-cells = <2>;
+	reg = <0x20>;
+	n_latch = <0x0>;
+};
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index e8faf53..3435790 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pcf857x.h>
 #include <linux/interrupt.h>
@@ -255,17 +256,42 @@ fail:
 
 /*-------------------------------------------------------------------------*/
 
+static struct pcf857x_platform_data *of_gpio_pcf857x(struct device *dev)
+{
+	struct pcf857x_platform_data *pdata;
+	int r;
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return NULL;
+
+	pdata->gpio_base = -1;
+
+	r = of_property_read_u32(dev->of_node, "n_latch", &pdata->n_latch);
+	if (r) {
+		dev_dbg(dev, "couldn't find n-latch, use default\n");
+		pdata->n_latch = 0;
+	}
+
+	return pdata;
+}
+
 static int pcf857x_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct pcf857x_platform_data	*pdata;
+	struct device_node		*node;
 	struct pcf857x			*gpio;
 	int				status;
 
 	pdata = client->dev.platform_data;
-	if (!pdata) {
+	node = client->dev.of_node;
+
+	if (!pdata && node)
+		pdata = of_gpio_pcf857x(&client->dev);
+
+	if (!pdata)
 		dev_dbg(&client->dev, "no platform data\n");
-	}
 
 	/* Allocate, initialize, and register this gpio_chip. */
 	gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL);
@@ -420,10 +446,33 @@ static int pcf857x_remove(struct i2c_client *client)
 	return status;
 }
 
+static const struct of_device_id pcf857x_dt_ids[] = {
+	{ .compatible = "nxp,pca9670", },
+	{ .compatible = "nxp,pca9672", },
+	{ .compatible = "nxp,pca9674", },
+	{ .compatible = "nxp,pca8574", },
+	{ .compatible = "nxp,pca8575", },
+	{ .compatible = "nxp,pca9671", },
+	{ .compatible = "nxp,pca9673", },
+	{ .compatible = "nxp,pca9675", },
+
+	{ .compatible = "ti,pcf8574", },
+	{ .compatible = "ti,pcf8574a", },
+	{ .compatible = "ti,pcf8575", },
+	{ .compatible = "ti,tca9554", },
+
+	{ .compatible = "maxim,max7328", },
+	{ .compatible = "maxim,max7329", },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, pcf857x_dt_ids);
+
 static struct i2c_driver pcf857x_driver = {
 	.driver = {
-		.name	= "pcf857x",
-		.owner	= THIS_MODULE,
+		.name		= "pcf857x",
+		.owner		= THIS_MODULE,
+		.of_match_table	= pcf857x_dt_ids,
 	},
 	.probe	= pcf857x_probe,
 	.remove	= pcf857x_remove,
-- 
1.8.1.2
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help