aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap/gpio.c')
-rw-r--r--arch/arm/plat-omap/gpio.c154
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
400static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int trigger) 410#ifdef CONFIG_ARCH_OMAP24XX
411static 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
416static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) 440static 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
651static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) 686static 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
1252static int workaround_enabled;
1253
1254void 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
1284void 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/*