summaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-pxa.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-pxa.c')
-rw-r--r--drivers/gpio/gpio-pxa.c161
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)