From: Jiang Lu <[email protected]>

Since the PPC LSI ACP34xx board implements 2 pl061 gpio controller,
Update driver register interface to support ppc of-platform style
driver register interface.

The patch abstract the common code of probe routine between
ARM_AMBA style driver and of-platform driver, then fork a new drivers
for ppc of-platform.

The OF style driver extract device information from device-tree, including
gpio base, io address & irq.

Signed-off-by: Jiang Lu <[email protected]>
---
 drivers/gpio/Kconfig      |   2 +-
 drivers/gpio/gpio-pl061.c | 110 ++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 97 insertions(+), 15 deletions(-)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index eb80ba3..91c4f21 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -144,7 +144,7 @@ config GPIO_MXS
 
 config GPIO_PL061
        bool "PrimeCell PL061 GPIO support"
-       depends on ARM_AMBA
+       depends on ARM_AMBA || ACP
        select GENERIC_IRQ_CHIP
        help
          Say yes here to support the PrimeCell PL061 GPIO device
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index b4b5da4..a87b4d4 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -19,11 +19,16 @@
 #include <linux/workqueue.h>
 #include <linux/gpio.h>
 #include <linux/device.h>
+#ifdef CONFIG_ARM_AMBA
 #include <linux/amba/bus.h>
+#include <asm/mach/irq.h>
+#else
+#include <linux/of_platform.h>
+#include <linux/of.h>
+#endif
 #include <linux/amba/pl061.h>
 #include <linux/slab.h>
 #include <linux/pm.h>
-#include <asm/mach/irq.h>
 
 #define GPIODIR 0x400
 #define GPIOIS  0x404
@@ -47,6 +52,18 @@ struct pl061_context_save_regs {
 };
 #endif
 
+#ifdef CONFIG_PPC
+static inline void chained_irq_enter(struct irq_chip *chip,
+                                       struct irq_desc *desc) {}
+
+static inline void chained_irq_exit(struct irq_chip *chip,
+                                       struct irq_desc *desc)
+{
+       if (chip->irq_eoi)
+               chip->irq_eoi(&desc->irq_data);
+}
+#endif
+
 struct pl061_gpio {
        /* Each of the two spinlocks protects a different set of hardware
         * regiters and data structurs. This decouples the code of the IRQ from
@@ -216,21 +233,22 @@ static void __init pl061_init_gc(struct pl061_gpio *chip, 
int irq_base)
                               IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
 }
 
-static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
+static int __devinit pl061_probe(struct device *dev,
+       struct resource *res, int irq, struct pl061_gpio **retchip)
 {
        struct pl061_platform_data *pdata;
        struct pl061_gpio *chip;
-       int ret, irq, i;
+       int ret, i;
 
        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
 
-       pdata = dev->dev.platform_data;
+       pdata = dev->platform_data;
        if (pdata) {
                chip->gc.base = pdata->gpio_base;
                chip->irq_base = pdata->irq_base;
-       } else if (dev->dev.of_node) {
+       } else if (dev->of_node) {
                chip->gc.base = -1;
                chip->irq_base = 0;
        } else {
@@ -238,13 +256,13 @@ static int pl061_probe(struct amba_device *dev, const 
struct amba_id *id)
                goto free_mem;
        }
 
-       if (!request_mem_region(dev->res.start,
-                               resource_size(&dev->res), "pl061")) {
+       if (!request_mem_region(res->start,
+                               resource_size(res), "pl061")) {
                ret = -EBUSY;
                goto free_mem;
        }
 
-       chip->base = ioremap(dev->res.start, resource_size(&dev->res));
+       chip->base = ioremap(res->start, resource_size(res));
        if (chip->base == NULL) {
                ret = -ENOMEM;
                goto release_region;
@@ -258,14 +276,17 @@ static int pl061_probe(struct amba_device *dev, const 
struct amba_id *id)
        chip->gc.set = pl061_set_value;
        chip->gc.to_irq = pl061_to_irq;
        chip->gc.ngpio = PL061_GPIO_NR;
-       chip->gc.label = dev_name(&dev->dev);
-       chip->gc.dev = &dev->dev;
+       chip->gc.label = dev_name(dev);
+       chip->gc.dev = dev;
        chip->gc.owner = THIS_MODULE;
 
        ret = gpiochip_add(&chip->gc);
        if (ret)
                goto iounmap;
 
+       if (retchip)
+               *retchip = chip;
+
        /*
         * irq_chip support
         */
@@ -276,7 +297,6 @@ static int pl061_probe(struct amba_device *dev, const 
struct amba_id *id)
        pl061_init_gc(chip, chip->irq_base);
 
        writeb(0, chip->base + GPIOIE); /* disable irqs */
-       irq = dev->irq[0];
        if (irq < 0) {
                ret = -ENODEV;
                goto iounmap;
@@ -294,17 +314,19 @@ static int pl061_probe(struct amba_device *dev, const 
struct amba_id *id)
                }
        }
 
-       amba_set_drvdata(dev, chip);
+       dev_set_drvdata(dev, chip);
 
        return 0;
 
 iounmap:
        iounmap(chip->base);
 release_region:
-       release_mem_region(dev->res.start, resource_size(&dev->res));
+       release_mem_region(res->start, resource_size(res));
 free_mem:
        kfree(chip);
 
+       if (retchip)
+               *retchip = NULL;
        return ret;
 }
 
@@ -360,6 +382,12 @@ static const struct dev_pm_ops pl061_dev_pm_ops = {
 };
 #endif
 
+#ifdef CONFIG_ARM_AMBA
+static int __init pl061_amba_probe(struct amba_device *dev, struct amba_id *id)
+{
+       return pl061_probe(&dev->dev, &dev->res, dev->irq[0], NULL);
+}
+
 static struct amba_id pl061_ids[] = {
        {
                .id     = 0x00041061,
@@ -378,12 +406,66 @@ static struct amba_driver pl061_gpio_driver = {
 #endif
        },
        .id_table       = pl061_ids,
-       .probe          = pl061_probe,
+       .probe          = pl061_amba_probe,
 };
+#else
+static int __devinit pl061_of_probe(struct platform_device *ofdev)
+{
+       struct resource r_mem;
+       struct pl061_platform_data pl061_data = {0};
+       int irq;
+       const u32 *prop;
+       int len;
+       struct pl061_gpio *chip = NULL;
+       int ret;
+
+       if (of_address_to_resource(ofdev->dev.of_node, 0, &r_mem))
+               return -ENODEV;
+
+       pl061_data.gpio_base = 0;
+       prop = of_get_property(ofdev->dev.of_node, "cell-index", &len);
+       if (!prop || len < sizeof(*prop))
+               dev_warn(&ofdev->dev, "no 'cell-index' property\n");
+       else
+               pl061_data.gpio_base = *prop;
+
+       irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL);
+       pl061_data.irq_base = irq;
+       if (irq == NO_IRQ)
+               pl061_data.irq_base = (unsigned) -1;
+
+       ofdev->dev.platform_data = &pl061_data;
+
+       ret = pl061_probe(&ofdev->dev, &r_mem, irq, &chip);
+
+       if (ret < 0)
+               return ret;
+       return 0;
+}
+
+static struct of_device_id pl061_match[] = {
+       {
+               .compatible = "amba_pl061",
+       },
+       { /* end of list */ },
+};
+
+static struct platform_driver pl061_gpio_driver = {
+       .driver = {
+               .name = "gpio-pl061",
+               .of_match_table = pl061_match,
+       },
+       .probe = pl061_of_probe,
+};
+#endif
 
 static int __init pl061_gpio_init(void)
 {
+#ifdef CONFIG_ARM_AMBA
        return amba_driver_register(&pl061_gpio_driver);
+#else
+       return platform_driver_register(&pl061_gpio_driver);
+#endif
 }
 subsys_initcall(pl061_gpio_init);
 
-- 
1.8.3

_______________________________________________
linux-yocto mailing list
[email protected]
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to