i2c: i2c_gpio: add devicetree support
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
f21744fba3
commit
3ad9434f2f
|
@ -15,6 +15,7 @@
|
||||||
#include <i2c/i2c-gpio.h>
|
#include <i2c/i2c-gpio.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include <gpio.h>
|
#include <gpio.h>
|
||||||
|
#include <of_gpio.h>
|
||||||
|
|
||||||
struct i2c_gpio_private_data {
|
struct i2c_gpio_private_data {
|
||||||
struct i2c_adapter adap;
|
struct i2c_adapter adap;
|
||||||
|
@ -83,6 +84,41 @@ static int i2c_gpio_getscl(void *data)
|
||||||
return gpio_get_value(pdata->scl_pin);
|
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)
|
static int i2c_gpio_probe(struct device_d *dev)
|
||||||
{
|
{
|
||||||
struct i2c_gpio_private_data *priv;
|
struct i2c_gpio_private_data *priv;
|
||||||
|
@ -97,9 +133,15 @@ static int i2c_gpio_probe(struct device_d *dev)
|
||||||
bit_data = &priv->bit_data;
|
bit_data = &priv->bit_data;
|
||||||
pdata = &priv->pdata;
|
pdata = &priv->pdata;
|
||||||
|
|
||||||
if (!dev->platform_data)
|
if (dev->device_node) {
|
||||||
return -ENXIO;
|
ret = of_i2c_gpio_probe(dev->device_node, pdata);
|
||||||
memcpy(pdata, dev->platform_data, sizeof(*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");
|
ret = gpio_request(pdata->sda_pin, "sda");
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -144,6 +186,7 @@ static int i2c_gpio_probe(struct device_d *dev)
|
||||||
|
|
||||||
adap->algo_data = bit_data;
|
adap->algo_data = bit_data;
|
||||||
adap->dev.parent = dev;
|
adap->dev.parent = dev;
|
||||||
|
adap->dev.device_node = dev->device_node;
|
||||||
|
|
||||||
adap->nr = dev->id;
|
adap->nr = dev->id;
|
||||||
ret = i2c_bit_add_numbered_bus(adap);
|
ret = i2c_bit_add_numbered_bus(adap);
|
||||||
|
@ -165,8 +208,14 @@ err_request_sda:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct of_device_id i2c_gpio_dt_ids[] = {
|
||||||
|
{ .compatible = "i2c-gpio", },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
|
||||||
static struct driver_d i2c_gpio_driver = {
|
static struct driver_d i2c_gpio_driver = {
|
||||||
.name = "i2c-gpio",
|
.name = "i2c-gpio",
|
||||||
.probe = i2c_gpio_probe,
|
.probe = i2c_gpio_probe,
|
||||||
|
.of_compatible = DRV_OF_COMPAT(i2c_gpio_dt_ids),
|
||||||
};
|
};
|
||||||
device_platform_driver(i2c_gpio_driver);
|
device_platform_driver(i2c_gpio_driver);
|
||||||
|
|
|
@ -35,10 +35,65 @@ static inline int of_get_named_gpio_flags(struct device_node *np,
|
||||||
|
|
||||||
#endif /* CONFIG_OF_GPIO */
|
#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,
|
static inline int of_get_named_gpio(struct device_node *np,
|
||||||
const char *list_name, int index)
|
const char *list_name, int index)
|
||||||
{
|
{
|
||||||
return of_get_named_gpio_flags(np, list_name, index, NULL);
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue