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
