From: Álvaro Fernández Rojas <noltari@xxxxxxxxx> This patch adds support for defining basic memory-mapped GPIOs within the device tree framework. Signed-off-by: Álvaro Fernández Rojas <noltari@xxxxxxxxx> Signed-off-by: Christian Lamparter <chunkeey@xxxxxxxxxxxxxx> --- drivers/gpio/gpio-generic.c | 70 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c index 54cddfa..f535299 100644 --- a/drivers/gpio/gpio-generic.c +++ b/drivers/gpio/gpio-generic.c @@ -61,6 +61,8 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` #include <linux/bitops.h> #include <linux/platform_device.h> #include <linux/mod_devicetable.h> +#include <linux/of.h> +#include <linux/of_device.h> static void bgpio_write8(void __iomem *reg, unsigned long data) { @@ -569,6 +571,59 @@ static void __iomem *bgpio_map(struct platform_device *pdev, return devm_ioremap_resource(&pdev->dev, r); } +#ifdef CONFIG_OF +static const struct of_device_id bgpio_of_match[] = { + { .compatible = "basic-mmio-gpio" }, + { } +}; +MODULE_DEVICE_TABLE(of, bgpio_of_match); + +static struct bgpio_pdata *bgpio_parse_dt(struct device *dev, + unsigned long *flags) +{ + struct bgpio_pdata *pdata; + int err; + + if (!of_match_node(bgpio_of_match, dev->of_node)) + return NULL; + + pdata = devm_kzalloc(dev, sizeof(struct bgpio_pdata), + GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + err = of_property_read_u32(dev->of_node, "ngpio", &pdata->ngpio); + if (err && err != -EINVAL) + return ERR_PTR(err); + + if (of_device_is_big_endian(dev->of_node)) + *flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER; + + if (of_property_read_bool(dev->of_node, "unreadable-reg-set")) + *flags |= BGPIOF_UNREADABLE_REG_SET; + + if (of_property_read_bool(dev->of_node, "unreadable-reg-dir")) + *flags |= BGPIOF_UNREADABLE_REG_DIR; + + if (of_property_read_bool(dev->of_node, "big-endian-byte-order")) + *flags |= BGPIOF_BIG_ENDIAN; + + if (of_property_read_bool(dev->of_node, "read-output-reg-set")) + *flags |= BGPIOF_READ_OUTPUT_REG_SET; + + if (of_property_read_bool(dev->of_node, "no-output")) + *flags |= BGPIOF_NO_OUTPUT; + + return pdata; +} +#else +static struct bgpio_data *bgpio_parse_dt(struct device *dev, + unsigned long *flags) +{ + return NULL; +} +#endif /* CONFIG_OF */ + static int bgpio_pdev_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -579,10 +634,18 @@ static int bgpio_pdev_probe(struct platform_device *pdev) void __iomem *dirout; void __iomem *dirin; unsigned long sz; - unsigned long flags = pdev->id_entry->driver_data; + unsigned long flags = 0; int err; struct gpio_chip *gc; - struct bgpio_pdata *pdata = dev_get_platdata(dev); + struct bgpio_pdata *pdata; + + pdata = bgpio_parse_dt(dev, &flags); + if (IS_ERR(pdata)) { + return PTR_ERR(pdata); + } else if (!pdata) { + pdata = dev_get_platdata(dev); + flags = pdev->id_entry->driver_data; + } r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); if (!r) @@ -646,6 +709,9 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table); static struct platform_driver bgpio_driver = { .driver = { .name = "basic-mmio-gpio", +#ifdef CONFIG_OF + .of_match_table = of_match_ptr(bgpio_of_match), +#endif }, .id_table = bgpio_id_table, .probe = bgpio_pdev_probe, -- 2.8.1 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html