Merge branch 'for-linus' of git://git.open-osd.org/linux-open-osd
[deliverable/linux.git] / drivers / gpio / gpio-tegra.c
index bdc2937915906fa7a7589b02e258daccb7b024f7..32de6707e3c456a19750e33dd21923bde2fcd41e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
+#include <linux/irqdomain.h>
 
 #include <asm/mach/irq.h>
 
@@ -74,9 +75,10 @@ struct tegra_gpio_bank {
 #endif
 };
 
-
+static struct irq_domain *irq_domain;
 static void __iomem *regs;
-static struct tegra_gpio_bank tegra_gpio_banks[7];
+static u32 tegra_gpio_bank_count;
+static struct tegra_gpio_bank *tegra_gpio_banks;
 
 static inline void tegra_gpio_writel(u32 val, u32 reg)
 {
@@ -107,11 +109,13 @@ void tegra_gpio_enable(int gpio)
 {
        tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
 }
+EXPORT_SYMBOL_GPL(tegra_gpio_enable);
 
 void tegra_gpio_disable(int gpio)
 {
        tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
 }
+EXPORT_SYMBOL_GPL(tegra_gpio_disable);
 
 static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
@@ -139,7 +143,7 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 
 static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
-       return TEGRA_GPIO_TO_IRQ(offset);
+       return irq_find_mapping(irq_domain, offset);
 }
 
 static struct gpio_chip tegra_gpio_chip = {
@@ -155,28 +159,28 @@ static struct gpio_chip tegra_gpio_chip = {
 
 static void tegra_gpio_irq_ack(struct irq_data *d)
 {
-       int gpio = d->irq - INT_GPIO_BASE;
+       int gpio = d->hwirq;
 
        tegra_gpio_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
 }
 
 static void tegra_gpio_irq_mask(struct irq_data *d)
 {
-       int gpio = d->irq - INT_GPIO_BASE;
+       int gpio = d->hwirq;
 
        tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0);
 }
 
 static void tegra_gpio_irq_unmask(struct irq_data *d)
 {
-       int gpio = d->irq - INT_GPIO_BASE;
+       int gpio = d->hwirq;
 
        tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1);
 }
 
 static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
-       int gpio = d->irq - INT_GPIO_BASE;
+       int gpio = d->hwirq;
        struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
        int port = GPIO_PORT(gpio);
        int lvl_type;
@@ -273,7 +277,7 @@ void tegra_gpio_resume(void)
 
        local_irq_save(flags);
 
-       for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
+       for (b = 0; b < tegra_gpio_bank_count; b++) {
                struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
 
                for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
@@ -296,7 +300,7 @@ void tegra_gpio_suspend(void)
        int p;
 
        local_irq_save(flags);
-       for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
+       for (b = 0; b < tegra_gpio_bank_count; b++) {
                struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
 
                for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
@@ -337,13 +341,44 @@ static struct lock_class_key gpio_lock_class;
 
 static int __devinit tegra_gpio_probe(struct platform_device *pdev)
 {
+       int irq_base;
        struct resource *res;
        struct tegra_gpio_bank *bank;
        int gpio;
        int i;
        int j;
 
-       for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
+       for (;;) {
+               res = platform_get_resource(pdev, IORESOURCE_IRQ, tegra_gpio_bank_count);
+               if (!res)
+                       break;
+               tegra_gpio_bank_count++;
+       }
+       if (!tegra_gpio_bank_count) {
+               dev_err(&pdev->dev, "Missing IRQ resource\n");
+               return -ENODEV;
+       }
+
+       tegra_gpio_chip.ngpio = tegra_gpio_bank_count * 32;
+
+       tegra_gpio_banks = devm_kzalloc(&pdev->dev,
+                       tegra_gpio_bank_count * sizeof(*tegra_gpio_banks),
+                       GFP_KERNEL);
+       if (!tegra_gpio_banks) {
+               dev_err(&pdev->dev, "Couldn't allocate bank structure\n");
+               return -ENODEV;
+       }
+
+       irq_base = irq_alloc_descs(-1, 0, tegra_gpio_chip.ngpio, 0);
+       if (irq_base < 0) {
+               dev_err(&pdev->dev, "Couldn't allocate IRQ numbers\n");
+               return -ENODEV;
+       }
+       irq_domain = irq_domain_add_legacy(pdev->dev.of_node,
+                                          tegra_gpio_chip.ngpio, irq_base, 0,
+                                          &irq_domain_simple_ops, NULL);
+
+       for (i = 0; i < tegra_gpio_bank_count; i++) {
                res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
                if (!res) {
                        dev_err(&pdev->dev, "Missing IRQ resource\n");
@@ -380,8 +415,8 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
 
        gpiochip_add(&tegra_gpio_chip);
 
-       for (gpio = 0; gpio < TEGRA_NR_GPIOS; gpio++) {
-               int irq = TEGRA_GPIO_TO_IRQ(gpio);
+       for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) {
+               int irq = irq_find_mapping(irq_domain, gpio);
                /* No validity check; all Tegra GPIOs are valid IRQs */
 
                bank = &tegra_gpio_banks[GPIO_BANK(gpio)];
@@ -393,7 +428,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
                set_irq_flags(irq, IRQF_VALID);
        }
 
-       for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
+       for (i = 0; i < tegra_gpio_bank_count; i++) {
                bank = &tegra_gpio_banks[i];
 
                irq_set_chained_handler(bank->irq, tegra_gpio_irq_handler);
@@ -426,7 +461,7 @@ static int __init tegra_gpio_init(void)
 }
 postcore_initcall(tegra_gpio_init);
 
-void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
+void tegra_gpio_config(struct tegra_gpio_table *table, int num)
 {
        int i;
 
This page took 0.03787 seconds and 5 git commands to generate.