diff options
Diffstat (limited to 'arch/arm/mach-tegra/gpio.c')
| -rw-r--r-- | arch/arm/mach-tegra/gpio.c | 104 |
1 files changed, 93 insertions, 11 deletions
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c index fe78fba25f3c..0775265e69f5 100644 --- a/arch/arm/mach-tegra/gpio.c +++ b/arch/arm/mach-tegra/gpio.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| 21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
| 22 | #include <linux/interrupt.h> | ||
| 22 | 23 | ||
| 23 | #include <linux/io.h> | 24 | #include <linux/io.h> |
| 24 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
| @@ -60,6 +61,13 @@ struct tegra_gpio_bank { | |||
| 60 | int bank; | 61 | int bank; |
| 61 | int irq; | 62 | int irq; |
| 62 | spinlock_t lvl_lock[4]; | 63 | spinlock_t lvl_lock[4]; |
| 64 | #ifdef CONFIG_PM | ||
| 65 | u32 cnf[4]; | ||
| 66 | u32 out[4]; | ||
| 67 | u32 oe[4]; | ||
| 68 | u32 int_enb[4]; | ||
| 69 | u32 int_lvl[4]; | ||
| 70 | #endif | ||
| 63 | }; | 71 | }; |
| 64 | 72 | ||
| 65 | 73 | ||
| @@ -131,7 +139,7 @@ static struct gpio_chip tegra_gpio_chip = { | |||
| 131 | .direction_output = tegra_gpio_direction_output, | 139 | .direction_output = tegra_gpio_direction_output, |
| 132 | .set = tegra_gpio_set, | 140 | .set = tegra_gpio_set, |
| 133 | .base = 0, | 141 | .base = 0, |
| 134 | .ngpio = ARCH_NR_GPIOS, | 142 | .ngpio = TEGRA_NR_GPIOS, |
| 135 | }; | 143 | }; |
| 136 | 144 | ||
| 137 | static void tegra_gpio_irq_ack(unsigned int irq) | 145 | static void tegra_gpio_irq_ack(unsigned int irq) |
| @@ -244,6 +252,76 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
| 244 | 252 | ||
| 245 | } | 253 | } |
| 246 | 254 | ||
| 255 | #ifdef CONFIG_PM | ||
| 256 | void tegra_gpio_resume(void) | ||
| 257 | { | ||
| 258 | unsigned long flags; | ||
| 259 | int b, p, i; | ||
| 260 | |||
| 261 | local_irq_save(flags); | ||
| 262 | |||
| 263 | for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) { | ||
| 264 | struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; | ||
| 265 | |||
| 266 | for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { | ||
| 267 | unsigned int gpio = (b<<5) | (p<<3); | ||
| 268 | __raw_writel(bank->cnf[p], GPIO_CNF(gpio)); | ||
| 269 | __raw_writel(bank->out[p], GPIO_OUT(gpio)); | ||
| 270 | __raw_writel(bank->oe[p], GPIO_OE(gpio)); | ||
| 271 | __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio)); | ||
| 272 | __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio)); | ||
| 273 | } | ||
| 274 | } | ||
| 275 | |||
| 276 | local_irq_restore(flags); | ||
| 277 | |||
| 278 | for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { | ||
| 279 | struct irq_desc *desc = irq_to_desc(i); | ||
| 280 | if (!desc || (desc->status & IRQ_WAKEUP)) | ||
| 281 | continue; | ||
| 282 | enable_irq(i); | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | void tegra_gpio_suspend(void) | ||
| 287 | { | ||
| 288 | unsigned long flags; | ||
| 289 | int b, p, i; | ||
| 290 | |||
| 291 | for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { | ||
| 292 | struct irq_desc *desc = irq_to_desc(i); | ||
| 293 | if (!desc) | ||
| 294 | continue; | ||
| 295 | if (desc->status & IRQ_WAKEUP) { | ||
| 296 | int gpio = i - INT_GPIO_BASE; | ||
| 297 | pr_debug("gpio %d.%d is wakeup\n", gpio/8, gpio&7); | ||
| 298 | continue; | ||
| 299 | } | ||
| 300 | disable_irq(i); | ||
| 301 | } | ||
| 302 | |||
| 303 | local_irq_save(flags); | ||
| 304 | for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) { | ||
| 305 | struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; | ||
| 306 | |||
| 307 | for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { | ||
| 308 | unsigned int gpio = (b<<5) | (p<<3); | ||
| 309 | bank->cnf[p] = __raw_readl(GPIO_CNF(gpio)); | ||
| 310 | bank->out[p] = __raw_readl(GPIO_OUT(gpio)); | ||
| 311 | bank->oe[p] = __raw_readl(GPIO_OE(gpio)); | ||
| 312 | bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio)); | ||
| 313 | bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio)); | ||
| 314 | } | ||
| 315 | } | ||
| 316 | local_irq_restore(flags); | ||
| 317 | } | ||
| 318 | |||
| 319 | static int tegra_gpio_wake_enable(unsigned int irq, unsigned int enable) | ||
| 320 | { | ||
| 321 | struct tegra_gpio_bank *bank = get_irq_chip_data(irq); | ||
| 322 | return set_irq_wake(bank->irq, enable); | ||
| 323 | } | ||
| 324 | #endif | ||
| 247 | 325 | ||
| 248 | static struct irq_chip tegra_gpio_irq_chip = { | 326 | static struct irq_chip tegra_gpio_irq_chip = { |
| 249 | .name = "GPIO", | 327 | .name = "GPIO", |
| @@ -251,6 +329,9 @@ static struct irq_chip tegra_gpio_irq_chip = { | |||
| 251 | .mask = tegra_gpio_irq_mask, | 329 | .mask = tegra_gpio_irq_mask, |
| 252 | .unmask = tegra_gpio_irq_unmask, | 330 | .unmask = tegra_gpio_irq_unmask, |
| 253 | .set_type = tegra_gpio_irq_set_type, | 331 | .set_type = tegra_gpio_irq_set_type, |
| 332 | #ifdef CONFIG_PM | ||
| 333 | .set_wake = tegra_gpio_wake_enable, | ||
| 334 | #endif | ||
| 254 | }; | 335 | }; |
| 255 | 336 | ||
| 256 | 337 | ||
| @@ -274,7 +355,7 @@ static int __init tegra_gpio_init(void) | |||
| 274 | 355 | ||
| 275 | gpiochip_add(&tegra_gpio_chip); | 356 | gpiochip_add(&tegra_gpio_chip); |
| 276 | 357 | ||
| 277 | for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + ARCH_NR_GPIOS); i++) { | 358 | for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { |
| 278 | bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))]; | 359 | bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))]; |
| 279 | 360 | ||
| 280 | lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class); | 361 | lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class); |
| @@ -312,15 +393,16 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) | |||
| 312 | for (i = 0; i < 7; i++) { | 393 | for (i = 0; i < 7; i++) { |
| 313 | for (j = 0; j < 4; j++) { | 394 | for (j = 0; j < 4; j++) { |
| 314 | int gpio = tegra_gpio_compose(i, j, 0); | 395 | int gpio = tegra_gpio_compose(i, j, 0); |
| 315 | seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", | 396 | seq_printf(s, |
| 316 | i, j, | 397 | "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", |
| 317 | __raw_readl(GPIO_CNF(gpio)), | 398 | i, j, |
| 318 | __raw_readl(GPIO_OE(gpio)), | 399 | __raw_readl(GPIO_CNF(gpio)), |
| 319 | __raw_readl(GPIO_OUT(gpio)), | 400 | __raw_readl(GPIO_OE(gpio)), |
| 320 | __raw_readl(GPIO_IN(gpio)), | 401 | __raw_readl(GPIO_OUT(gpio)), |
| 321 | __raw_readl(GPIO_INT_STA(gpio)), | 402 | __raw_readl(GPIO_IN(gpio)), |
| 322 | __raw_readl(GPIO_INT_ENB(gpio)), | 403 | __raw_readl(GPIO_INT_STA(gpio)), |
| 323 | __raw_readl(GPIO_INT_LVL(gpio))); | 404 | __raw_readl(GPIO_INT_ENB(gpio)), |
| 405 | __raw_readl(GPIO_INT_LVL(gpio))); | ||
| 324 | } | 406 | } |
| 325 | } | 407 | } |
| 326 | return 0; | 408 | return 0; |
