aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2006-12-06 20:13:53 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-05-05 05:54:23 -0400
commitb9772a220a0d1b1d83b770ed131fa8b090af3681 (patch)
tree0411d07d9d054e81bc5e56856293ddada02b448e /arch
parent3ac4fa99291a60329e9c9424ac3e67bb4f9564f5 (diff)
ARM: OMAP: /sys/kernel/debug/omap_gpio
Add some GPIO debug support: /sys/kernel/debug/omap_gpio dumps the state of all GPIOs that have been claimed, including basic IRQ info if relevant. Tested on 24xx, 16xx. Includes minor bugfixes: recording IRQ trigger mode (this should probably be a genirq patch), adding missing space to non-wakeup warning Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> 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.c130
1 files changed, 129 insertions, 1 deletions
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index ec0e2f18fdea..0059f19185a7 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -535,6 +535,10 @@ static int gpio_irq_type(unsigned irq, unsigned type)
535 bank = get_gpio_bank(gpio); 535 bank = get_gpio_bank(gpio);
536 spin_lock(&bank->lock); 536 spin_lock(&bank->lock);
537 retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type); 537 retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
538 if (retval == 0) {
539 irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
540 irq_desc[irq].status |= type;
541 }
538 spin_unlock(&bank->lock); 542 spin_unlock(&bank->lock);
539 return retval; 543 return retval;
540} 544}
@@ -701,7 +705,7 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
701 spin_lock(&bank->lock); 705 spin_lock(&bank->lock);
702 if (enable) { 706 if (enable) {
703 if (bank->non_wakeup_gpios & (1 << gpio)) { 707 if (bank->non_wakeup_gpios & (1 << gpio)) {
704 printk(KERN_ERR "Unable to enable wakeup on" 708 printk(KERN_ERR "Unable to enable wakeup on "
705 "non-wakeup GPIO%d\n", 709 "non-wakeup GPIO%d\n",
706 (bank - gpio_bank) * 32 + gpio); 710 (bank - gpio_bank) * 32 + gpio);
707 spin_unlock(&bank->lock); 711 spin_unlock(&bank->lock);
@@ -1359,3 +1363,127 @@ EXPORT_SYMBOL(omap_set_gpio_dataout);
1359EXPORT_SYMBOL(omap_get_gpio_datain); 1363EXPORT_SYMBOL(omap_get_gpio_datain);
1360 1364
1361arch_initcall(omap_gpio_sysinit); 1365arch_initcall(omap_gpio_sysinit);
1366
1367
1368#ifdef CONFIG_DEBUG_FS
1369
1370#include <linux/debugfs.h>
1371#include <linux/seq_file.h>
1372
1373static int gpio_is_input(struct gpio_bank *bank, int mask)
1374{
1375 void __iomem *reg = bank->base;
1376
1377 switch (bank->method) {
1378 case METHOD_MPUIO:
1379 reg += OMAP_MPUIO_IO_CNTL;
1380 break;
1381 case METHOD_GPIO_1510:
1382 reg += OMAP1510_GPIO_DIR_CONTROL;
1383 break;
1384 case METHOD_GPIO_1610:
1385 reg += OMAP1610_GPIO_DIRECTION;
1386 break;
1387 case METHOD_GPIO_730:
1388 reg += OMAP730_GPIO_DIR_CONTROL;
1389 break;
1390 case METHOD_GPIO_24XX:
1391 reg += OMAP24XX_GPIO_OE;
1392 break;
1393 }
1394 return __raw_readl(reg) & mask;
1395}
1396
1397
1398static int dbg_gpio_show(struct seq_file *s, void *unused)
1399{
1400 unsigned i, j, gpio;
1401
1402 for (i = 0, gpio = 0; i < gpio_bank_count; i++) {
1403 struct gpio_bank *bank = gpio_bank + i;
1404 unsigned bankwidth = 16;
1405 u32 mask = 1;
1406
1407 if (!cpu_is_omap24xx() && bank->method == METHOD_MPUIO)
1408 gpio = OMAP_MPUIO(0);
1409 else if (cpu_is_omap24xx() || cpu_is_omap730())
1410 bankwidth = 32;
1411
1412 for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) {
1413 unsigned irq, value, is_in, irqstat;
1414
1415 if (!(bank->reserved_map & mask))
1416 continue;
1417
1418 irq = bank->virtual_irq_start + j;
1419 value = omap_get_gpio_datain(gpio);
1420 is_in = gpio_is_input(bank, mask);
1421
1422 if (!cpu_is_omap24xx() && bank->method == METHOD_MPUIO)
1423 seq_printf(s, "MPUIO %2d: ", j);
1424 else
1425 seq_printf(s, "GPIO %3d: ", gpio);
1426 seq_printf(s, "%s %s",
1427 is_in ? "in " : "out",
1428 value ? "hi" : "lo");
1429
1430 irqstat = irq_desc[irq].status;
1431 if (is_in && ((bank->suspend_wakeup & mask)
1432 || irqstat & IRQ_TYPE_SENSE_MASK)) {
1433 char *trigger = NULL;
1434
1435 switch (irqstat & IRQ_TYPE_SENSE_MASK) {
1436 case IRQ_TYPE_EDGE_FALLING:
1437 trigger = "falling";
1438 break;
1439 case IRQ_TYPE_EDGE_RISING:
1440 trigger = "rising";
1441 break;
1442 case IRQ_TYPE_EDGE_BOTH:
1443 trigger = "bothedge";
1444 break;
1445 case IRQ_TYPE_LEVEL_LOW:
1446 trigger = "low";
1447 break;
1448 case IRQ_TYPE_LEVEL_HIGH:
1449 trigger = "high";
1450 break;
1451 case IRQ_TYPE_NONE:
1452 trigger = "(unspecified)";
1453 break;
1454 }
1455 seq_printf(s, ", irq-%d %s%s",
1456 irq, trigger,
1457 (bank->suspend_wakeup & mask)
1458 ? " wakeup" : "");
1459 }
1460 seq_printf(s, "\n");
1461 }
1462
1463 if (!cpu_is_omap24xx() && bank->method == METHOD_MPUIO) {
1464 seq_printf(s, "\n");
1465 gpio = 0;
1466 }
1467 }
1468 return 0;
1469}
1470
1471static int dbg_gpio_open(struct inode *inode, struct file *file)
1472{
1473 return single_open(file, dbg_gpio_show, inode->u.generic_ip/*i_private*/);
1474}
1475
1476static const struct file_operations debug_fops = {
1477 .open = dbg_gpio_open,
1478 .read = seq_read,
1479 .llseek = seq_lseek,
1480 .release = single_release,
1481};
1482
1483static int __init omap_gpio_debuginit(void)
1484{
1485 (void) debugfs_create_file("omap_gpio", S_IRUGO, NULL, NULL, &debug_fops);
1486 return 0;
1487}
1488late_initcall(omap_gpio_debuginit);
1489#endif