aboutsummaryrefslogtreecommitdiff
path: root/drivers/i2c/busses/i2c-gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-gpio.c')
-rw-r--r--drivers/i2c/busses/i2c-gpio.c87
1 files changed, 51 insertions, 36 deletions
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index f3fa4332bbd..71a45b210a2 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -15,8 +15,8 @@
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
+#include <linux/of.h>
#include <linux/of_gpio.h>
-#include <linux/of_i2c.h>
struct i2c_gpio_private_data {
struct i2c_adapter adap;
@@ -85,23 +85,32 @@ 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)
+static int of_i2c_gpio_get_pins(struct device_node *np,
+ unsigned int *sda_pin, unsigned int *scl_pin)
{
- 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);
+ *sda_pin = of_get_gpio(np, 0);
+ *scl_pin = of_get_gpio(np, 1);
- if (!gpio_is_valid(pdata->sda_pin) || !gpio_is_valid(pdata->scl_pin)) {
+ if (*sda_pin == -EPROBE_DEFER || *scl_pin == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) {
pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n",
- np->full_name, pdata->sda_pin, pdata->scl_pin);
+ np->full_name, *sda_pin, *scl_pin);
return -ENODEV;
}
+ return 0;
+}
+
+static void of_i2c_gpio_get_props(struct device_node *np,
+ struct i2c_gpio_platform_data *pdata)
+{
+ u32 reg;
+
of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay);
if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", &reg))
@@ -113,8 +122,6 @@ static int of_i2c_gpio_probe(struct device_node *np,
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 platform_device *pdev)
@@ -123,8 +130,36 @@ static int i2c_gpio_probe(struct platform_device *pdev)
struct i2c_gpio_platform_data *pdata;
struct i2c_algo_bit_data *bit_data;
struct i2c_adapter *adap;
+ unsigned int sda_pin, scl_pin;
int ret;
+ /* First get the GPIO pins; if it fails, we'll defer the probe. */
+ if (pdev->dev.of_node) {
+ ret = of_i2c_gpio_get_pins(pdev->dev.of_node,
+ &sda_pin, &scl_pin);
+ if (ret)
+ return ret;
+ } else {
+ if (!dev_get_platdata(&pdev->dev))
+ return -ENXIO;
+ pdata = dev_get_platdata(&pdev->dev);
+ sda_pin = pdata->sda_pin;
+ scl_pin = pdata->scl_pin;
+ }
+
+ ret = devm_gpio_request(&pdev->dev, sda_pin, "sda");
+ if (ret) {
+ if (ret == -EINVAL)
+ ret = -EPROBE_DEFER; /* Try again later */
+ return ret;
+ }
+ ret = devm_gpio_request(&pdev->dev, scl_pin, "scl");
+ if (ret) {
+ if (ret == -EINVAL)
+ ret = -EPROBE_DEFER; /* Try again later */
+ return ret;
+ }
+
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -133,22 +168,13 @@ static int i2c_gpio_probe(struct platform_device *pdev)
pdata = &priv->pdata;
if (pdev->dev.of_node) {
- ret = of_i2c_gpio_probe(pdev->dev.of_node, pdata);
- if (ret)
- return ret;
+ pdata->sda_pin = sda_pin;
+ pdata->scl_pin = scl_pin;
+ of_i2c_gpio_get_props(pdev->dev.of_node, pdata);
} else {
- if (!pdev->dev.platform_data)
- return -ENXIO;
- memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
+ memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata));
}
- ret = gpio_request(pdata->sda_pin, "sda");
- if (ret)
- goto err_request_sda;
- ret = gpio_request(pdata->scl_pin, "scl");
- if (ret)
- goto err_request_scl;
-
if (pdata->sda_is_open_drain) {
gpio_direction_output(pdata->sda_pin, 1);
bit_data->setsda = i2c_gpio_setsda_val;
@@ -197,9 +223,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)
adap->nr = pdev->id;
ret = i2c_bit_add_numbered_bus(adap);
if (ret)
- goto err_add_bus;
-
- of_i2c_register_devices(adap);
+ return ret;
platform_set_drvdata(pdev, priv);
@@ -209,13 +233,6 @@ static int i2c_gpio_probe(struct platform_device *pdev)
? ", no clock stretching" : "");
return 0;
-
-err_add_bus:
- gpio_free(pdata->scl_pin);
-err_request_scl:
- gpio_free(pdata->sda_pin);
-err_request_sda:
- return ret;
}
static int i2c_gpio_remove(struct platform_device *pdev)
@@ -229,8 +246,6 @@ static int i2c_gpio_remove(struct platform_device *pdev)
pdata = &priv->pdata;
i2c_del_adapter(adap);
- gpio_free(pdata->scl_pin);
- gpio_free(pdata->sda_pin);
return 0;
}