Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
[firefly-linux-kernel-4.4.55.git] / drivers / gpio / gpio-tegra.c
index 414ad912232f9ecc1558c42e865d289920375dfc..da4cb5b0cb87612fed241b9a4ebc6245716377cd 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/pm.h>
 
-#include <asm/mach/irq.h>
-
 #define GPIO_BANK(x)           ((x) >> 5)
 #define GPIO_PORT(x)           (((x) >> 3) & 0x3)
 #define GPIO_BIT(x)            ((x) & 0x7)
@@ -72,6 +71,7 @@ struct tegra_gpio_bank {
        u32 oe[4];
        u32 int_enb[4];
        u32 int_lvl[4];
+       u32 wake_enb[4];
 #endif
 };
 
@@ -333,15 +333,31 @@ static int tegra_gpio_suspend(struct device *dev)
                        bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
                        bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
                        bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
+
+                       /* Enable gpio irq for wake up source */
+                       tegra_gpio_writel(bank->wake_enb[p],
+                                         GPIO_INT_ENB(gpio));
                }
        }
        local_irq_restore(flags);
        return 0;
 }
 
-static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
+static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable)
 {
        struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       int gpio = d->hwirq;
+       u32 port, bit, mask;
+
+       port = GPIO_PORT(gpio);
+       bit = GPIO_BIT(gpio);
+       mask = BIT(bit);
+
+       if (enable)
+               bank->wake_enb[port] |= mask;
+       else
+               bank->wake_enb[port] &= ~mask;
+
        return irq_set_irq_wake(bank->irq, enable);
 }
 #endif
@@ -353,7 +369,7 @@ static struct irq_chip tegra_gpio_irq_chip = {
        .irq_unmask     = tegra_gpio_irq_unmask,
        .irq_set_type   = tegra_gpio_irq_set_type,
 #ifdef CONFIG_PM_SLEEP
-       .irq_set_wake   = tegra_gpio_wake_enable,
+       .irq_set_wake   = tegra_gpio_irq_set_wake,
 #endif
 };
 
@@ -398,10 +414,11 @@ static int tegra_gpio_probe(struct platform_device *pdev)
        int j;
 
        match = of_match_device(tegra_gpio_of_match, &pdev->dev);
-       if (match)
-               config = (struct tegra_gpio_soc_config *)match->data;
-       else
-               config = &tegra20_gpio_config;
+       if (!match) {
+               dev_err(&pdev->dev, "Error: No device match found\n");
+               return -ENODEV;
+       }
+       config = (struct tegra_gpio_soc_config *)match->data;
 
        tegra_gpio_bank_stride = config->bank_stride;
        tegra_gpio_upper_offset = config->upper_offset;
@@ -462,9 +479,7 @@ static int tegra_gpio_probe(struct platform_device *pdev)
                }
        }
 
-#ifdef CONFIG_OF_GPIO
        tegra_gpio_chip.of_node = pdev->dev.of_node;
-#endif
 
        gpiochip_add(&tegra_gpio_chip);