[linux-yocto] [PATCH 51/70] GPIO:pl061: Update driver to support of-platform drivers
Paul Butler
butler.paul at gmail.com
Mon Jun 10 18:46:14 PDT 2013
From: Jiang Lu <lu.jiang at windriver.com>
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 <lu.jiang at windriver.com>
---
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
More information about the linux-yocto
mailing list