Signed-off-by: Antony Pavlov <antonynpav...@gmail.com>
---
 .../devicetree/bindings/gpio/gpio_i2c.txt          | 32 +++++++++++++
 drivers/i2c/busses/i2c-gpio.c                      | 54 +++++++++++++++++++--
 include/of_gpio.h                                  | 55 ++++++++++++++++++++++
 3 files changed, 138 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpio/gpio_i2c.txt 
b/Documentation/devicetree/bindings/gpio/gpio_i2c.txt
new file mode 100644
index 0000000..4f8ec94
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio_i2c.txt
@@ -0,0 +1,32 @@
+Device-Tree bindings for i2c gpio driver
+
+Required properties:
+       - compatible = "i2c-gpio";
+       - gpios: sda and scl gpio
+
+
+Optional properties:
+       - i2c-gpio,sda-open-drain: sda as open drain
+       - i2c-gpio,scl-open-drain: scl as open drain
+       - i2c-gpio,scl-output-only: scl as output only
+       - i2c-gpio,delay-us: delay between GPIO operations (may depend on each 
platform)
+       - i2c-gpio,timeout-ms: timeout to get data
+
+Example nodes:
+
+i2c@0 {
+       compatible = "i2c-gpio";
+       gpios = <&pioA 23 0 /* sda */
+                &pioA 24 0 /* scl */
+               >;
+       i2c-gpio,sda-open-drain;
+       i2c-gpio,scl-open-drain;
+       i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       rv3029c2@56 {
+               compatible = "rv3029c2";
+               reg = <0x56>;
+       };
+};
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index 8b49c2c..29dc3d2 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -15,6 +15,7 @@
 #include <i2c/i2c-gpio.h>
 #include <init.h>
 #include <gpio.h>
+#include <of_gpio.h>
 
 struct i2c_gpio_private_data {
        struct i2c_adapter adap;
@@ -83,6 +84,38 @@ static int i2c_gpio_getscl(void *data)
        return gpio_get_value(pdata->scl_pin);
 }
 
+static int of_i2c_gpio_probe(struct device_node *np,
+                            struct i2c_gpio_platform_data *pdata)
+{
+       u32 reg;
+
+       if (of_gpio_count(np) < 2)
+               return -ENODEV;
+
+       pdata->sda_pin = of_get_gpio(np, 0);
+       pdata->scl_pin = of_get_gpio(np, 1);
+
+       if (!gpio_is_valid(pdata->sda_pin) || !gpio_is_valid(pdata->scl_pin)) {
+               pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n",
+                      np->full_name, pdata->sda_pin, pdata->scl_pin);
+               return -ENODEV;
+       }
+
+       of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay);
+
+       if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", &reg))
+               pdata->timeout_ms = reg;
+
+       pdata->sda_is_open_drain =
+               of_property_read_bool(np, "i2c-gpio,sda-open-drain");
+       pdata->scl_is_open_drain =
+               of_property_read_bool(np, "i2c-gpio,scl-open-drain");
+       pdata->scl_is_output_only =
+               of_property_read_bool(np, "i2c-gpio,scl-output-only");
+
+       return 0;
+}
+
 static int i2c_gpio_probe(struct device_d *dev)
 {
        struct i2c_gpio_private_data *priv;
@@ -97,9 +130,15 @@ static int i2c_gpio_probe(struct device_d *dev)
        bit_data = &priv->bit_data;
        pdata = &priv->pdata;
 
-       if (!dev->platform_data)
-               return -ENXIO;
-       memcpy(pdata, dev->platform_data, sizeof(*pdata));
+       if (dev->device_node) {
+               ret = of_i2c_gpio_probe(dev->device_node, pdata);
+               if (ret)
+                       return ret;
+       } else {
+               if (!dev->platform_data)
+                       return -ENXIO;
+               memcpy(pdata, dev->platform_data, sizeof(*pdata));
+       }
 
        ret = gpio_request(pdata->sda_pin, "sda");
        if (ret)
@@ -144,6 +183,7 @@ static int i2c_gpio_probe(struct device_d *dev)
 
        adap->algo_data = bit_data;
        adap->dev.parent = dev;
+       adap->dev.device_node = dev->device_node;
 
        adap->nr = dev->id;
        ret = i2c_bit_add_numbered_bus(adap);
@@ -165,8 +205,16 @@ err_request_sda:
        return ret;
 }
 
+#if defined(CONFIG_OFDEVICE)
+static struct of_device_id i2c_gpio_dt_ids[] = {
+       { .compatible = "i2c-gpio", },
+       { /* sentinel */ }
+};
+#endif
+
 static struct driver_d i2c_gpio_driver = {
        .name   = "i2c-gpio",
        .probe  = i2c_gpio_probe,
+       .of_compatible = DRV_OF_COMPAT(i2c_gpio_dt_ids),
 };
 device_platform_driver(i2c_gpio_driver);
diff --git a/include/of_gpio.h b/include/of_gpio.h
index d42b18e..95a454c 100644
--- a/include/of_gpio.h
+++ b/include/of_gpio.h
@@ -35,10 +35,65 @@ static inline int of_get_named_gpio_flags(struct 
device_node *np,
 
 #endif /* CONFIG_OF_GPIO */
 
+/**
+ * of_gpio_named_count() - Count GPIOs for a device
+ * @np:                device node to count GPIOs for
+ * @propname:  property name containing gpio specifier(s)
+ *
+ * The function returns the count of GPIOs specified for a node.
+ * Note that the empty GPIO specifiers count too. Returns either
+ *   Number of gpios defined in property,
+ *   -EINVAL for an incorrectly formed gpios property, or
+ *   -ENOENT for a missing gpios property
+ *
+ * Example:
+ * gpios = <0
+ *          &gpio1 1 2
+ *          0
+ *          &gpio2 3 4>;
+ *
+ * The above example defines four GPIOs, two of which are not specified.
+ * This function will return '4'
+ */
+static inline int of_gpio_named_count(struct device_node *np, const char* 
propname)
+{
+       return of_count_phandle_with_args(np, propname, "#gpio-cells");
+}
+
+/**
+ * of_gpio_count() - Count GPIOs for a device
+ * @np:                device node to count GPIOs for
+ *
+ * Same as of_gpio_named_count, but hard coded to use the 'gpios' property
+ */
+static inline int of_gpio_count(struct device_node *np)
+{
+       return of_gpio_named_count(np, "gpios");
+}
+
+static inline int of_get_gpio_flags(struct device_node *np, int index,
+                     enum of_gpio_flags *flags)
+{
+       return of_get_named_gpio_flags(np, "gpios", index, flags);
+}
+
 static inline int of_get_named_gpio(struct device_node *np,
                                const char *list_name, int index)
 {
        return of_get_named_gpio_flags(np, list_name, index, NULL);
 }
 
+/**
+ * of_get_gpio() - Get a GPIO number to use with GPIO API
+ * @np:                device node to get GPIO from
+ * @index:     index of the GPIO
+ *
+ * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
+ * value on the error condition.
+ */
+static inline int of_get_gpio(struct device_node *np, int index)
+{
+       return of_get_gpio_flags(np, index, NULL);
+}
+
 #endif
-- 
1.9.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

Reply via email to