Loading arch/arm/mach-tegra/gpio.c +93 −11 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <linux/init.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/gpio.h> Loading Loading @@ -60,6 +61,13 @@ struct tegra_gpio_bank { int bank; int irq; spinlock_t lvl_lock[4]; #ifdef CONFIG_PM u32 cnf[4]; u32 out[4]; u32 oe[4]; u32 int_enb[4]; u32 int_lvl[4]; #endif }; Loading Loading @@ -131,7 +139,7 @@ static struct gpio_chip tegra_gpio_chip = { .direction_output = tegra_gpio_direction_output, .set = tegra_gpio_set, .base = 0, .ngpio = ARCH_NR_GPIOS, .ngpio = TEGRA_NR_GPIOS, }; static void tegra_gpio_irq_ack(unsigned int irq) Loading Loading @@ -244,6 +252,76 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) } #ifdef CONFIG_PM void tegra_gpio_resume(void) { unsigned long flags; int b, p, i; local_irq_save(flags); for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) { struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { unsigned int gpio = (b<<5) | (p<<3); __raw_writel(bank->cnf[p], GPIO_CNF(gpio)); __raw_writel(bank->out[p], GPIO_OUT(gpio)); __raw_writel(bank->oe[p], GPIO_OE(gpio)); __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio)); __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio)); } } local_irq_restore(flags); for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { struct irq_desc *desc = irq_to_desc(i); if (!desc || (desc->status & IRQ_WAKEUP)) continue; enable_irq(i); } } void tegra_gpio_suspend(void) { unsigned long flags; int b, p, i; for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { struct irq_desc *desc = irq_to_desc(i); if (!desc) continue; if (desc->status & IRQ_WAKEUP) { int gpio = i - INT_GPIO_BASE; pr_debug("gpio %d.%d is wakeup\n", gpio/8, gpio&7); continue; } disable_irq(i); } local_irq_save(flags); for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) { struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { unsigned int gpio = (b<<5) | (p<<3); bank->cnf[p] = __raw_readl(GPIO_CNF(gpio)); bank->out[p] = __raw_readl(GPIO_OUT(gpio)); bank->oe[p] = __raw_readl(GPIO_OE(gpio)); bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio)); bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio)); } } local_irq_restore(flags); } static int tegra_gpio_wake_enable(unsigned int irq, unsigned int enable) { struct tegra_gpio_bank *bank = get_irq_chip_data(irq); return set_irq_wake(bank->irq, enable); } #endif static struct irq_chip tegra_gpio_irq_chip = { .name = "GPIO", Loading @@ -251,6 +329,9 @@ static struct irq_chip tegra_gpio_irq_chip = { .mask = tegra_gpio_irq_mask, .unmask = tegra_gpio_irq_unmask, .set_type = tegra_gpio_irq_set_type, #ifdef CONFIG_PM .set_wake = tegra_gpio_wake_enable, #endif }; Loading @@ -274,7 +355,7 @@ static int __init tegra_gpio_init(void) gpiochip_add(&tegra_gpio_chip); for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + ARCH_NR_GPIOS); i++) { for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))]; lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class); Loading Loading @@ -312,7 +393,8 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) for (i = 0; i < 7; i++) { for (j = 0; j < 4; j++) { int gpio = tegra_gpio_compose(i, j, 0); seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", i, j, __raw_readl(GPIO_CNF(gpio)), __raw_readl(GPIO_OE(gpio)), Loading arch/arm/mach-tegra/include/mach/gpio.h +2 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ #include <mach/irqs.h> #define ARCH_NR_GPIOS INT_GPIO_NR #define TEGRA_NR_GPIOS INT_GPIO_NR #include <asm-generic/gpio.h> Loading @@ -35,7 +35,7 @@ static inline int gpio_to_irq(unsigned int gpio) { if (gpio < ARCH_NR_GPIOS) if (gpio < TEGRA_NR_GPIOS) return INT_GPIO_BASE + gpio; return -EINVAL; } Loading Loading
arch/arm/mach-tegra/gpio.c +93 −11 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <linux/init.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/gpio.h> Loading Loading @@ -60,6 +61,13 @@ struct tegra_gpio_bank { int bank; int irq; spinlock_t lvl_lock[4]; #ifdef CONFIG_PM u32 cnf[4]; u32 out[4]; u32 oe[4]; u32 int_enb[4]; u32 int_lvl[4]; #endif }; Loading Loading @@ -131,7 +139,7 @@ static struct gpio_chip tegra_gpio_chip = { .direction_output = tegra_gpio_direction_output, .set = tegra_gpio_set, .base = 0, .ngpio = ARCH_NR_GPIOS, .ngpio = TEGRA_NR_GPIOS, }; static void tegra_gpio_irq_ack(unsigned int irq) Loading Loading @@ -244,6 +252,76 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) } #ifdef CONFIG_PM void tegra_gpio_resume(void) { unsigned long flags; int b, p, i; local_irq_save(flags); for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) { struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { unsigned int gpio = (b<<5) | (p<<3); __raw_writel(bank->cnf[p], GPIO_CNF(gpio)); __raw_writel(bank->out[p], GPIO_OUT(gpio)); __raw_writel(bank->oe[p], GPIO_OE(gpio)); __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio)); __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio)); } } local_irq_restore(flags); for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { struct irq_desc *desc = irq_to_desc(i); if (!desc || (desc->status & IRQ_WAKEUP)) continue; enable_irq(i); } } void tegra_gpio_suspend(void) { unsigned long flags; int b, p, i; for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { struct irq_desc *desc = irq_to_desc(i); if (!desc) continue; if (desc->status & IRQ_WAKEUP) { int gpio = i - INT_GPIO_BASE; pr_debug("gpio %d.%d is wakeup\n", gpio/8, gpio&7); continue; } disable_irq(i); } local_irq_save(flags); for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) { struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { unsigned int gpio = (b<<5) | (p<<3); bank->cnf[p] = __raw_readl(GPIO_CNF(gpio)); bank->out[p] = __raw_readl(GPIO_OUT(gpio)); bank->oe[p] = __raw_readl(GPIO_OE(gpio)); bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio)); bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio)); } } local_irq_restore(flags); } static int tegra_gpio_wake_enable(unsigned int irq, unsigned int enable) { struct tegra_gpio_bank *bank = get_irq_chip_data(irq); return set_irq_wake(bank->irq, enable); } #endif static struct irq_chip tegra_gpio_irq_chip = { .name = "GPIO", Loading @@ -251,6 +329,9 @@ static struct irq_chip tegra_gpio_irq_chip = { .mask = tegra_gpio_irq_mask, .unmask = tegra_gpio_irq_unmask, .set_type = tegra_gpio_irq_set_type, #ifdef CONFIG_PM .set_wake = tegra_gpio_wake_enable, #endif }; Loading @@ -274,7 +355,7 @@ static int __init tegra_gpio_init(void) gpiochip_add(&tegra_gpio_chip); for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + ARCH_NR_GPIOS); i++) { for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))]; lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class); Loading Loading @@ -312,7 +393,8 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) for (i = 0; i < 7; i++) { for (j = 0; j < 4; j++) { int gpio = tegra_gpio_compose(i, j, 0); seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", i, j, __raw_readl(GPIO_CNF(gpio)), __raw_readl(GPIO_OE(gpio)), Loading
arch/arm/mach-tegra/include/mach/gpio.h +2 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ #include <mach/irqs.h> #define ARCH_NR_GPIOS INT_GPIO_NR #define TEGRA_NR_GPIOS INT_GPIO_NR #include <asm-generic/gpio.h> Loading @@ -35,7 +35,7 @@ static inline int gpio_to_irq(unsigned int gpio) { if (gpio < ARCH_NR_GPIOS) if (gpio < TEGRA_NR_GPIOS) return INT_GPIO_BASE + gpio; return -EINVAL; } Loading