aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJuha Yrjola <juha.yrjola@solidboot.com>2006-12-06 20:13:52 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-05-05 05:54:07 -0400
commit3ac4fa99291a60329e9c9424ac3e67bb4f9564f5 (patch)
tree0db75aefeb5c39e1c842f9d44b59f65e6d81753a /arch
parent14f1c3bf51b78d916a6aff9c9b5e6689e3e006e7 (diff)
ARM: OMAP: Implement workaround for GPIO wakeup bug in OMAP2420 silicon
Some GPIOs on OMAP2420 do not have wakeup capabilities. If these GPIOs are configured as IRQ sources, spurious interrupts will be generated each time the core domain enters retention. Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-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/*