diff options
Diffstat (limited to 'drivers/gpio/gpio-pxa.c')
-rw-r--r-- | drivers/gpio/gpio-pxa.c | 161 |
1 files changed, 102 insertions, 59 deletions
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 9cc108d2b77..d7a5c9d7552 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -19,6 +19,7 @@ #include <linux/init.h> #include <linux/irq.h> #include <linux/irqdomain.h> +#include <linux/irqchip/chained_irq.h> #include <linux/io.h> #include <linux/of.h> #include <linux/of_device.h> @@ -26,8 +27,6 @@ #include <linux/syscore_ops.h> #include <linux/slab.h> -#include <asm/mach/irq.h> - #include <mach/irqs.h> /* @@ -86,20 +85,61 @@ struct pxa_gpio_chip { #endif }; -enum { +enum pxa_gpio_type { PXA25X_GPIO = 0, PXA26X_GPIO, PXA27X_GPIO, PXA3XX_GPIO, PXA93X_GPIO, MMP_GPIO = 0x10, + MMP2_GPIO, +}; + +struct pxa_gpio_id { + enum pxa_gpio_type type; + int gpio_nums; }; static DEFINE_SPINLOCK(gpio_lock); static struct pxa_gpio_chip *pxa_gpio_chips; -static int gpio_type; +static enum pxa_gpio_type gpio_type; static void __iomem *gpio_reg_base; +static struct pxa_gpio_id pxa25x_id = { + .type = PXA25X_GPIO, + .gpio_nums = 85, +}; + +static struct pxa_gpio_id pxa26x_id = { + .type = PXA26X_GPIO, + .gpio_nums = 90, +}; + +static struct pxa_gpio_id pxa27x_id = { + .type = PXA27X_GPIO, + .gpio_nums = 121, +}; + +static struct pxa_gpio_id pxa3xx_id = { + .type = PXA3XX_GPIO, + .gpio_nums = 128, +}; + +static struct pxa_gpio_id pxa93x_id = { + .type = PXA93X_GPIO, + .gpio_nums = 192, +}; + +static struct pxa_gpio_id mmp_id = { + .type = MMP_GPIO, + .gpio_nums = 128, +}; + +static struct pxa_gpio_id mmp2_id = { + .type = MMP2_GPIO, + .gpio_nums = 192, +}; + #define for_each_gpio_chip(i, c) \ for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) @@ -432,47 +472,39 @@ static struct irq_chip pxa_muxed_gpio_chip = { .irq_set_wake = pxa_gpio_set_wake, }; -static int pxa_gpio_nums(void) +static int pxa_gpio_nums(struct platform_device *pdev) { + const struct platform_device_id *id = platform_get_device_id(pdev); + struct pxa_gpio_id *pxa_id = (struct pxa_gpio_id *)id->driver_data; int count = 0; -#ifdef CONFIG_ARCH_PXA - if (cpu_is_pxa25x()) { -#ifdef CONFIG_CPU_PXA26x - count = 89; - gpio_type = PXA26X_GPIO; -#elif defined(CONFIG_PXA25x) - count = 84; - gpio_type = PXA26X_GPIO; -#endif /* CONFIG_CPU_PXA26x */ - } else if (cpu_is_pxa27x()) { - count = 120; - gpio_type = PXA27X_GPIO; - } else if (cpu_is_pxa93x()) { - count = 191; - gpio_type = PXA93X_GPIO; - } else if (cpu_is_pxa3xx()) { - count = 127; - gpio_type = PXA3XX_GPIO; - } -#endif /* CONFIG_ARCH_PXA */ - -#ifdef CONFIG_ARCH_MMP - if (cpu_is_pxa168() || cpu_is_pxa910()) { - count = 127; - gpio_type = MMP_GPIO; - } else if (cpu_is_mmp2()) { - count = 191; - gpio_type = MMP_GPIO; + switch (pxa_id->type) { + case PXA25X_GPIO: + case PXA26X_GPIO: + case PXA27X_GPIO: + case PXA3XX_GPIO: + case PXA93X_GPIO: + case MMP_GPIO: + case MMP2_GPIO: + gpio_type = pxa_id->type; + count = pxa_id->gpio_nums - 1; + break; + default: + count = -EINVAL; + break; } -#endif /* CONFIG_ARCH_MMP */ return count; } #ifdef CONFIG_OF static struct of_device_id pxa_gpio_dt_ids[] = { - { .compatible = "mrvl,pxa-gpio" }, - { .compatible = "mrvl,mmp-gpio", .data = (void *)MMP_GPIO }, + { .compatible = "intel,pxa25x-gpio", .data = &pxa25x_id, }, + { .compatible = "intel,pxa26x-gpio", .data = &pxa26x_id, }, + { .compatible = "intel,pxa27x-gpio", .data = &pxa27x_id, }, + { .compatible = "intel,pxa3xx-gpio", .data = &pxa3xx_id, }, + { .compatible = "marvell,pxa93x-gpio", .data = &pxa93x_id, }, + { .compatible = "marvell,mmp-gpio", .data = &mmp_id, }, + { .compatible = "marvell,mmp2-gpio", .data = &mmp2_id, }, {} }; @@ -492,16 +524,18 @@ const struct irq_domain_ops pxa_irq_domain_ops = { static int pxa_gpio_probe_dt(struct platform_device *pdev) { - int ret, nr_banks, nr_gpios; + int ret, nr_gpios; struct device_node *prev, *next, *np = pdev->dev.of_node; const struct of_device_id *of_id = of_match_device(pxa_gpio_dt_ids, &pdev->dev); + const struct pxa_gpio_id *gpio_id; - if (!of_id) { + if (!of_id || !of_id->data) { dev_err(&pdev->dev, "Failed to find gpio controller\n"); return -EFAULT; } - gpio_type = (int)of_id->data; + gpio_id = of_id->data; + gpio_type = gpio_id->type; next = of_get_next_child(np, NULL); prev = next; @@ -510,14 +544,8 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev) ret = -EINVAL; goto err; } - for (nr_banks = 1; ; nr_banks++) { - next = of_get_next_child(np, prev); - if (!next) - break; - prev = next; - } of_node_put(prev); - nr_gpios = nr_banks << 5; + nr_gpios = gpio_id->gpio_nums; pxa_last_gpio = nr_gpios - 1; irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0); @@ -546,19 +574,18 @@ static int pxa_gpio_probe(struct platform_device *pdev) int gpio, irq, ret, use_of = 0; int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; - ret = pxa_gpio_probe_dt(pdev); - if (ret < 0) { - pxa_last_gpio = pxa_gpio_nums(); -#ifdef CONFIG_ARCH_PXA - if (gpio_is_pxa_type(gpio_type)) - irq_base = PXA_GPIO_TO_IRQ(0); -#endif -#ifdef CONFIG_ARCH_MMP - if (gpio_is_mmp_type(gpio_type)) - irq_base = MMP_GPIO_TO_IRQ(0); -#endif + info = dev_get_platdata(&pdev->dev); + if (info) { + irq_base = info->irq_base; + if (irq_base <= 0) + return -EINVAL; + pxa_last_gpio = pxa_gpio_nums(pdev); } else { + irq_base = 0; use_of = 1; + ret = pxa_gpio_probe_dt(pdev); + if (ret < 0) + return -EINVAL; } if (!pxa_last_gpio) @@ -595,7 +622,6 @@ static int pxa_gpio_probe(struct platform_device *pdev) } /* Initialize GPIO chips */ - info = dev_get_platdata(&pdev->dev); pxa_init_gpio_chip(pxa_last_gpio, info ? info->gpio_set_wake : NULL); /* clear all GPIO edge detects */ @@ -635,14 +661,31 @@ static int pxa_gpio_probe(struct platform_device *pdev) return 0; } +static const struct platform_device_id gpio_id_table[] = { + { "pxa25x-gpio", (unsigned long)&pxa25x_id }, + { "pxa26x-gpio", (unsigned long)&pxa26x_id }, + { "pxa27x-gpio", (unsigned long)&pxa27x_id }, + { "pxa3xx-gpio", (unsigned long)&pxa3xx_id }, + { "pxa93x-gpio", (unsigned long)&pxa93x_id }, + { "mmp-gpio", (unsigned long)&mmp_id }, + { "mmp2-gpio", (unsigned long)&mmp2_id }, + { }, +}; + static struct platform_driver pxa_gpio_driver = { .probe = pxa_gpio_probe, .driver = { .name = "pxa-gpio", .of_match_table = of_match_ptr(pxa_gpio_dt_ids), }, + .id_table = gpio_id_table, }; -module_platform_driver(pxa_gpio_driver); + +static int __init pxa_gpio_init(void) +{ + return platform_driver_register(&pxa_gpio_driver); +} +postcore_initcall(pxa_gpio_init); #ifdef CONFIG_PM static int pxa_gpio_suspend(void) |