Add DT support while keeping legacy support.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
---
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index 16f6115..9792783 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -61,6 +61,9 @@ o        `                     ~~~~\___/~~~~    ` controller 
in FPGA is ,.`
 #include <linux/platform_device.h>
 #include <linux/mod_devicetable.h>
 #include <linux/basic_mmio_gpio.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 
 static void bgpio_write8(void __iomem *reg, unsigned long data)
 {
@@ -488,8 +491,58 @@ static void __iomem *bgpio_map(struct platform_device 
*pdev,
        return ret;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id bgpio_dt_ids[] = {
+       { .compatible = "basic-mmio-gpio" },
+};
+MODULE_DEVICE_TABLE(of, bgpio_dt_ids);
+
+static int bgpio_probe_dt(struct platform_device *pdev)
+{
+       u32 tmp;
+       struct bgpio_pdata *pdata;
+       struct device_node *np;
+
+       np = pdev->dev.of_node;
+       if (!np)
+               return 0;
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+
+       pdata->label = dev_name(&pdev->dev);
+       pdata->base = -1;
+       if (of_find_property(np, "byte-be", NULL)) {
+               pdata->flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;
+       }
+       if (of_find_property(np, "bit-be", NULL)) {
+               pdata->flags |= BGPIOF_BIG_ENDIAN;
+       }
+       if (of_find_property(np, "regset-nr", NULL)) {
+               pdata->flags |= BGPIOF_UNREADABLE_REG_SET;
+       }
+       if (of_find_property(np, "regdir-nr", NULL)) {
+               pdata->flags |= BGPIOF_UNREADABLE_REG_DIR;
+       }
+       if (!of_property_read_u32(np, "num-gpios", &tmp)) {
+               pdata->ngpio = tmp;
+       }
+
+       pdev->dev.platform_data = pdata;
+
+       return 1;
+}
+#else
+static inline int bgpio_probe_dt(struct platform_device *pdev)
+{
+       return 0;
+}
+#endif
+
 static int bgpio_pdev_probe(struct platform_device *pdev)
 {
+       int status;
        struct device *dev = &pdev->dev;
        struct resource *r;
        void __iomem *dat;
@@ -498,10 +551,24 @@ 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;
        int err;
        struct bgpio_chip *bgc;
-       struct bgpio_pdata *pdata = dev_get_platdata(dev);
+       struct bgpio_pdata *pdata;
+       bool use_of = 0;
+
+       status = bgpio_probe_dt(pdev);
+       if (status < 0)
+               return status;
+       if (status > 0)
+               use_of = 1;
+
+       pdata = dev_get_platdata(dev);
+
+       if (!use_of)
+               flags = pdev->id_entry->driver_data;
+       else if (pdata)
+               flags = pdata->flags;
 
        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
        if (!r)
@@ -547,6 +614,9 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, bgc);
 
+       if (use_of)
+               of_gpiochip_add(&bgc->gc);
+
        return gpiochip_add(&bgc->gc);
 }
 
@@ -572,6 +642,7 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table);
 static struct platform_driver bgpio_driver = {
        .driver = {
                .name = "basic-mmio-gpio",
+               .of_match_table = bgpio_dt_ids,
        },
        .id_table = bgpio_id_table,
        .probe = bgpio_pdev_probe,
diff --git a/include/linux/basic_mmio_gpio.h b/include/linux/basic_mmio_gpio.h
index 0e97856..a35dffd 100644
--- a/include/linux/basic_mmio_gpio.h
+++ b/include/linux/basic_mmio_gpio.h
@@ -22,6 +22,7 @@ struct bgpio_pdata {
        const char *label;
        int base;
        int ngpio;
+       unsigned long flags;
 };
 
 struct device;
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to