diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 8b49c2c1b..b4a0ecdb2 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -15,6 +15,7 @@ #include #include #include +#include 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", ®)) + 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); diff --git a/include/of_gpio.h b/include/of_gpio.h index d42b18e63..95a454c68 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