summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAntony Pavlov <antonynpavlov@gmail.com>2014-06-24 01:21:11 +0400
committerSascha Hauer <s.hauer@pengutronix.de>2014-06-25 08:34:48 +0200
commit3ad9434f2faed97331670de1f5a6317df8c493b5 (patch)
treeb2a9c6686b01d1a756389f53610534e6b57463bf /drivers
parentf21744fba3eebb3eb90954c7397226047ecd0d98 (diff)
downloadbarebox-3ad9434f2faed97331670de1f5a6317df8c493b5.tar.gz
barebox-3ad9434f2faed97331670de1f5a6317df8c493b5.tar.xz
i2c: i2c_gpio: add devicetree support
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/busses/i2c-gpio.c55
1 files changed, 52 insertions, 3 deletions
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index 8b49c2c1bf..b4a0ecdb20 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,41 @@ 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 (!IS_ENABLED(CONFIG_OFDEVICE))
+ return -ENODEV;
+
+ 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 +133,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 +186,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 +208,14 @@ err_request_sda:
return ret;
}
+static struct of_device_id i2c_gpio_dt_ids[] = {
+ { .compatible = "i2c-gpio", },
+ { /* sentinel */ }
+};
+
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);