diff options
| -rw-r--r-- | arch/arm/plat-omap/gpio.c | 154 |
1 files changed, 136 insertions, 18 deletions
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 037a4930ec61..ec0e2f18fdea 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c | |||
| @@ -117,8 +117,18 @@ struct gpio_bank { | |||
| 117 | u16 virtual_irq_start; | 117 | u16 virtual_irq_start; |
| 118 | int method; | 118 | int method; |
| 119 | u32 reserved_map; | 119 | u32 reserved_map; |
| 120 | #if defined (CONFIG_ARCH_OMAP16XX) || defined (CONFIG_ARCH_OMAP24XX) | ||
| 120 | u32 suspend_wakeup; | 121 | u32 suspend_wakeup; |
| 121 | u32 saved_wakeup; | 122 | u32 saved_wakeup; |
| 123 | #endif | ||
| 124 | #ifdef CONFIG_ARCH_OMAP24XX | ||
| 125 | u32 non_wakeup_gpios; | ||
| 126 | u32 enabled_non_wakeup_gpios; | ||
| 127 | |||
| 128 | u32 saved_datain; | ||
| 129 | u32 saved_fallingdetect; | ||
| 130 | u32 saved_risingdetect; | ||
| 131 | #endif | ||
| 122 | spinlock_t lock; | 132 | spinlock_t lock; |
| 123 | }; | 133 | }; |
| 124 | 134 | ||
| @@ -397,8 +407,10 @@ do { \ | |||
| 397 | __raw_writel(l, base + reg); \ | 407 | __raw_writel(l, base + reg); \ |
| 398 | } while(0) | 408 | } while(0) |
| 399 | 409 | ||
| 400 | static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int trigger) | 410 | #ifdef CONFIG_ARCH_OMAP24XX |
| 411 | static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | ||
| 401 | { | 412 | { |
| 413 | void __iomem *base = bank->base; | ||
| 402 | u32 gpio_bit = 1 << gpio; | 414 | u32 gpio_bit = 1 << gpio; |
| 403 | 415 | ||
| 404 | MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, | 416 | MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, |
| @@ -409,9 +421,21 @@ static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int tr | |||
| 409 | trigger & __IRQT_RISEDGE); | 421 | trigger & __IRQT_RISEDGE); |
| 410 | MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, | 422 | MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, |
| 411 | trigger & __IRQT_FALEDGE); | 423 | trigger & __IRQT_FALEDGE); |
| 424 | if (likely(!(bank->non_wakeup_gpios & gpio_bit))) { | ||
| 425 | if (trigger != 0) | ||
| 426 | __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_SETWKUENA); | ||
| 427 | else | ||
| 428 | __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_CLEARWKUENA); | ||
| 429 | } else { | ||
| 430 | if (trigger != 0) | ||
| 431 | bank->enabled_non_wakeup_gpios |= gpio_bit; | ||
| 432 | else | ||
| 433 | bank->enabled_non_wakeup_gpios &= ~gpio_bit; | ||
| 434 | } | ||
| 412 | /* FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only level | 435 | /* FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only level |
| 413 | * triggering requested. */ | 436 | * triggering requested. */ |
| 414 | } | 437 | } |
| 438 | #endif | ||
| 415 | 439 | ||
| 416 | static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | 440 | static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) |
| 417 | { | 441 | { |
| @@ -439,6 +463,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | |||
| 439 | else | 463 | else |
| 440 | goto bad; | 464 | goto bad; |
| 441 | break; | 465 | break; |
| 466 | #ifdef CONFIG_ARCH_OMAP16XX | ||
| 442 | case METHOD_GPIO_1610: | 467 | case METHOD_GPIO_1610: |
| 443 | if (gpio & 0x08) | 468 | if (gpio & 0x08) |
| 444 | reg += OMAP1610_GPIO_EDGE_CTRL2; | 469 | reg += OMAP1610_GPIO_EDGE_CTRL2; |
| @@ -454,7 +479,14 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | |||
| 454 | l |= 2 << (gpio << 1); | 479 | l |= 2 << (gpio << 1); |
| 455 | if (trigger & __IRQT_FALEDGE) | 480 | if (trigger & __IRQT_FALEDGE) |
| 456 | l |= 1 << (gpio << 1); | 481 | l |= 1 << (gpio << 1); |
| 482 | if (trigger) | ||
| 483 | /* Enable wake-up during idle for dynamic tick */ | ||
| 484 | __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_SET_WAKEUPENA); | ||
| 485 | else | ||
| 486 | __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA); | ||
| 457 | break; | 487 | break; |
| 488 | #endif | ||
| 489 | #ifdef CONFIG_ARCH_OMAP730 | ||
| 458 | case METHOD_GPIO_730: | 490 | case METHOD_GPIO_730: |
| 459 | reg += OMAP730_GPIO_INT_CONTROL; | 491 | reg += OMAP730_GPIO_INT_CONTROL; |
| 460 | l = __raw_readl(reg); | 492 | l = __raw_readl(reg); |
| @@ -465,9 +497,12 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | |||
| 465 | else | 497 | else |
| 466 | goto bad; | 498 | goto bad; |
| 467 | break; | 499 | break; |
| 500 | #endif | ||
| 501 | #ifdef CONFIG_ARCH_OMAP24XX | ||
| 468 | case METHOD_GPIO_24XX: | 502 | case METHOD_GPIO_24XX: |
| 469 | set_24xx_gpio_triggering(reg, gpio, trigger); | 503 | set_24xx_gpio_triggering(bank, gpio, trigger); |
| 470 | break; | 504 | break; |
| 505 | #endif | ||
| 471 | default: | 506 | default: |
| 472 | BUG(); | 507 | BUG(); |
| 473 | goto bad; | 508 | goto bad; |
| @@ -651,8 +686,8 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena | |||
| 651 | static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) | 686 | static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) |
| 652 | { | 687 | { |
| 653 | switch (bank->method) { | 688 | switch (bank->method) { |
| 689 | #ifdef CONFIG_ARCH_OMAP16XX | ||
| 654 | case METHOD_GPIO_1610: | 690 | case METHOD_GPIO_1610: |
| 655 | case METHOD_GPIO_24XX: | ||
| 656 | spin_lock(&bank->lock); | 691 | spin_lock(&bank->lock); |
| 657 | if (enable) | 692 | if (enable) |
| 658 | bank->suspend_wakeup |= (1 << gpio); | 693 | bank->suspend_wakeup |= (1 << gpio); |
| @@ -660,6 +695,24 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) | |||
| 660 | bank->suspend_wakeup &= ~(1 << gpio); | 695 | bank->suspend_wakeup &= ~(1 << gpio); |
| 661 | spin_unlock(&bank->lock); | 696 | spin_unlock(&bank->lock); |
| 662 | return 0; | 697 | return 0; |
| 698 | #endif | ||
| 699 | #ifdef CONFIG_ARCH_OMAP24XX | ||
| 700 | case METHOD_GPIO_24XX: | ||
| 701 | spin_lock(&bank->lock); | ||
| 702 | if (enable) { | ||
| 703 | if (bank->non_wakeup_gpios & (1 << gpio)) { | ||
| 704 | printk(KERN_ERR "Unable to enable wakeup on" | ||
| 705 | "non-wakeup GPIO%d\n", | ||
| 706 | (bank - gpio_bank) * 32 + gpio); | ||
| 707 | spin_unlock(&bank->lock); | ||
| 708 | return -EINVAL; | ||
| 709 | } | ||
| 710 | bank->suspend_wakeup |= (1 << gpio); | ||
| 711 | } else | ||
| 712 | bank->suspend_wakeup &= ~(1 << gpio); | ||
| 713 | spin_unlock(&bank->lock); | ||
| 714 | return 0; | ||
| 715 | #endif | ||
| 663 | default: | 716 | default: |
| 664 | printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n", | 717 | printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n", |
| 665 | bank->method); | 718 | bank->method); |
| @@ -721,20 +774,6 @@ int omap_request_gpio(int gpio) | |||
| 721 | __raw_writel(__raw_readl(reg) | (1 << get_gpio_index(gpio)), reg); | 774 | __raw_writel(__raw_readl(reg) | (1 << get_gpio_index(gpio)), reg); |
| 722 | } | 775 | } |
| 723 | #endif | 776 | #endif |
| 724 | #ifdef CONFIG_ARCH_OMAP16XX | ||
| 725 | if (bank->method == METHOD_GPIO_1610) { | ||
| 726 | /* Enable wake-up during idle for dynamic tick */ | ||
| 727 | void __iomem *reg = bank->base + OMAP1610_GPIO_SET_WAKEUPENA; | ||
| 728 | __raw_writel(1 << get_gpio_index(gpio), reg); | ||
| 729 | } | ||
| 730 | #endif | ||
| 731 | #ifdef CONFIG_ARCH_OMAP24XX | ||
| 732 | if (bank->method == METHOD_GPIO_24XX) { | ||
| 733 | /* Enable wake-up during idle for dynamic tick */ | ||
| 734 | void __iomem *reg = bank->base + OMAP24XX_GPIO_SETWKUENA; | ||
| 735 | __raw_writel(1 << get_gpio_index(gpio), reg); | ||
| 736 | } | ||
| 737 | #endif | ||
| 738 | spin_unlock(&bank->lock); | 777 | spin_unlock(&bank->lock); |
| 739 | 778 | ||
| 740 | return 0; | 779 | return 0; |
| @@ -1080,13 +1119,18 @@ static int __init _omap_gpio_init(void) | |||
| 1080 | #endif | 1119 | #endif |
| 1081 | #ifdef CONFIG_ARCH_OMAP24XX | 1120 | #ifdef CONFIG_ARCH_OMAP24XX |
| 1082 | if (bank->method == METHOD_GPIO_24XX) { | 1121 | if (bank->method == METHOD_GPIO_24XX) { |
| 1122 | static const u32 non_wakeup_gpios[] = { | ||
| 1123 | 0xe203ffc0, 0x08700040 | ||
| 1124 | }; | ||
| 1125 | |||
| 1083 | __raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_IRQENABLE1); | 1126 | __raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_IRQENABLE1); |
| 1084 | __raw_writel(0xffffffff, bank->base + OMAP24XX_GPIO_IRQSTATUS1); | 1127 | __raw_writel(0xffffffff, bank->base + OMAP24XX_GPIO_IRQSTATUS1); |
| 1085 | __raw_writew(0x0015, bank->base + OMAP24XX_GPIO_SYSCONFIG); | 1128 | __raw_writew(0x0015, bank->base + OMAP24XX_GPIO_SYSCONFIG); |
| 1086 | 1129 | ||
| 1087 | /* Initialize interface clock ungated, module enabled */ | 1130 | /* Initialize interface clock ungated, module enabled */ |
| 1088 | __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL); | 1131 | __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL); |
| 1089 | 1132 | if (i < ARRAY_SIZE(non_wakeup_gpios)) | |
| 1133 | bank->non_wakeup_gpios = non_wakeup_gpios[i]; | ||
| 1090 | gpio_count = 32; | 1134 | gpio_count = 32; |
| 1091 | } | 1135 | } |
| 1092 | #endif | 1136 | #endif |
| @@ -1200,6 +1244,80 @@ static struct sys_device omap_gpio_device = { | |||
| 1200 | .id = 0, | 1244 | .id = 0, |
| 1201 | .cls = &omap_gpio_sysclass, | 1245 | .cls = &omap_gpio_sysclass, |
| 1202 | }; | 1246 | }; |
| 1247 | |||
| 1248 | #endif | ||
| 1249 | |||
| 1250 | #ifdef CONFIG_ARCH_OMAP24XX | ||
| 1251 | |||
| 1252 | static int workaround_enabled; | ||
| 1253 | |||
| 1254 | void omap2_gpio_prepare_for_retention(void) | ||
| 1255 | { | ||
| 1256 | int i, c = 0; | ||
| 1257 | |||
| 1258 | /* Remove triggering for all non-wakeup GPIOs. Otherwise spurious | ||
| 1259 | * IRQs will be generated. See OMAP2420 Errata item 1.101. */ | ||
| 1260 | for (i = 0; i < gpio_bank_count; i++) { | ||
| 1261 | struct gpio_bank *bank = &gpio_bank[i]; | ||
| 1262 | u32 l1, l2; | ||
| 1263 | |||
| 1264 | if (!(bank->enabled_non_wakeup_gpios)) | ||
| 1265 | continue; | ||
| 1266 | bank->saved_datain = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN); | ||
| 1267 | l1 = __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); | ||
| 1268 | l2 = __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT); | ||
| 1269 | bank->saved_fallingdetect = l1; | ||
| 1270 | bank->saved_risingdetect = l2; | ||
| 1271 | l1 &= ~bank->enabled_non_wakeup_gpios; | ||
| 1272 | l2 &= ~bank->enabled_non_wakeup_gpios; | ||
| 1273 | __raw_writel(l1, bank->base + OMAP24XX_GPIO_FALLINGDETECT); | ||
| 1274 | __raw_writel(l2, bank->base + OMAP24XX_GPIO_RISINGDETECT); | ||
| 1275 | c++; | ||
| 1276 | } | ||
| 1277 | if (!c) { | ||
| 1278 | workaround_enabled = 0; | ||
| 1279 | return; | ||
| 1280 | } | ||
| 1281 | workaround_enabled = 1; | ||
| 1282 | } | ||
| 1283 | |||
| 1284 | void omap2_gpio_resume_after_retention(void) | ||
| 1285 | { | ||
| 1286 | int i; | ||
| 1287 | |||
| 1288 | if (!workaround_enabled) | ||
| 1289 | return; | ||
| 1290 | for (i = 0; i < gpio_bank_count; i++) { | ||
| 1291 | struct gpio_bank *bank = &gpio_bank[i]; | ||
| 1292 | u32 l; | ||
| 1293 | |||
| 1294 | if (!(bank->enabled_non_wakeup_gpios)) | ||
| 1295 | continue; | ||
| 1296 | __raw_writel(bank->saved_fallingdetect, | ||
| 1297 | bank->base + OMAP24XX_GPIO_FALLINGDETECT); | ||
| 1298 | __raw_writel(bank->saved_risingdetect, | ||
| 1299 | bank->base + OMAP24XX_GPIO_RISINGDETECT); | ||
| 1300 | /* Check if any of the non-wakeup interrupt GPIOs have changed | ||
| 1301 | * state. If so, generate an IRQ by software. This is | ||
| 1302 | * horribly racy, but it's the best we can do to work around | ||
| 1303 | * this silicon bug. */ | ||
| 1304 | l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN); | ||
| 1305 | l ^= bank->saved_datain; | ||
| 1306 | l &= bank->non_wakeup_gpios; | ||
| 1307 | if (l) { | ||
| 1308 | u32 old0, old1; | ||
| 1309 | |||
| 1310 | old0 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0); | ||
| 1311 | old1 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); | ||
| 1312 | __raw_writel(old0 | l, bank->base + OMAP24XX_GPIO_LEVELDETECT0); | ||
| 1313 | __raw_writel(old1 | l, bank->base + OMAP24XX_GPIO_LEVELDETECT1); | ||
| 1314 | __raw_writel(old0, bank->base + OMAP24XX_GPIO_LEVELDETECT0); | ||
| 1315 | __raw_writel(old1, bank->base + OMAP24XX_GPIO_LEVELDETECT1); | ||
| 1316 | } | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | } | ||
| 1320 | |||
| 1203 | #endif | 1321 | #endif |
| 1204 | 1322 | ||
| 1205 | /* | 1323 | /* |
