mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 20:53:53 +08:00
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>
This commit is contained in:
parent
3ac4fa9929
commit
b9772a220a
@ -535,6 +535,10 @@ static int gpio_irq_type(unsigned irq, unsigned type)
|
||||
bank = get_gpio_bank(gpio);
|
||||
spin_lock(&bank->lock);
|
||||
retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
|
||||
if (retval == 0) {
|
||||
irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
|
||||
irq_desc[irq].status |= type;
|
||||
}
|
||||
spin_unlock(&bank->lock);
|
||||
return retval;
|
||||
}
|
||||
@ -701,7 +705,7 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
|
||||
spin_lock(&bank->lock);
|
||||
if (enable) {
|
||||
if (bank->non_wakeup_gpios & (1 << gpio)) {
|
||||
printk(KERN_ERR "Unable to enable wakeup on"
|
||||
printk(KERN_ERR "Unable to enable wakeup on "
|
||||
"non-wakeup GPIO%d\n",
|
||||
(bank - gpio_bank) * 32 + gpio);
|
||||
spin_unlock(&bank->lock);
|
||||
@ -1359,3 +1363,127 @@ EXPORT_SYMBOL(omap_set_gpio_dataout);
|
||||
EXPORT_SYMBOL(omap_get_gpio_datain);
|
||||
|
||||
arch_initcall(omap_gpio_sysinit);
|
||||
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
static int gpio_is_input(struct gpio_bank *bank, int mask)
|
||||
{
|
||||
void __iomem *reg = bank->base;
|
||||
|
||||
switch (bank->method) {
|
||||
case METHOD_MPUIO:
|
||||
reg += OMAP_MPUIO_IO_CNTL;
|
||||
break;
|
||||
case METHOD_GPIO_1510:
|
||||
reg += OMAP1510_GPIO_DIR_CONTROL;
|
||||
break;
|
||||
case METHOD_GPIO_1610:
|
||||
reg += OMAP1610_GPIO_DIRECTION;
|
||||
break;
|
||||
case METHOD_GPIO_730:
|
||||
reg += OMAP730_GPIO_DIR_CONTROL;
|
||||
break;
|
||||
case METHOD_GPIO_24XX:
|
||||
reg += OMAP24XX_GPIO_OE;
|
||||
break;
|
||||
}
|
||||
return __raw_readl(reg) & mask;
|
||||
}
|
||||
|
||||
|
||||
static int dbg_gpio_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
unsigned i, j, gpio;
|
||||
|
||||
for (i = 0, gpio = 0; i < gpio_bank_count; i++) {
|
||||
struct gpio_bank *bank = gpio_bank + i;
|
||||
unsigned bankwidth = 16;
|
||||
u32 mask = 1;
|
||||
|
||||
if (!cpu_is_omap24xx() && bank->method == METHOD_MPUIO)
|
||||
gpio = OMAP_MPUIO(0);
|
||||
else if (cpu_is_omap24xx() || cpu_is_omap730())
|
||||
bankwidth = 32;
|
||||
|
||||
for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) {
|
||||
unsigned irq, value, is_in, irqstat;
|
||||
|
||||
if (!(bank->reserved_map & mask))
|
||||
continue;
|
||||
|
||||
irq = bank->virtual_irq_start + j;
|
||||
value = omap_get_gpio_datain(gpio);
|
||||
is_in = gpio_is_input(bank, mask);
|
||||
|
||||
if (!cpu_is_omap24xx() && bank->method == METHOD_MPUIO)
|
||||
seq_printf(s, "MPUIO %2d: ", j);
|
||||
else
|
||||
seq_printf(s, "GPIO %3d: ", gpio);
|
||||
seq_printf(s, "%s %s",
|
||||
is_in ? "in " : "out",
|
||||
value ? "hi" : "lo");
|
||||
|
||||
irqstat = irq_desc[irq].status;
|
||||
if (is_in && ((bank->suspend_wakeup & mask)
|
||||
|| irqstat & IRQ_TYPE_SENSE_MASK)) {
|
||||
char *trigger = NULL;
|
||||
|
||||
switch (irqstat & IRQ_TYPE_SENSE_MASK) {
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
trigger = "falling";
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
trigger = "rising";
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
trigger = "bothedge";
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
trigger = "low";
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
trigger = "high";
|
||||
break;
|
||||
case IRQ_TYPE_NONE:
|
||||
trigger = "(unspecified)";
|
||||
break;
|
||||
}
|
||||
seq_printf(s, ", irq-%d %s%s",
|
||||
irq, trigger,
|
||||
(bank->suspend_wakeup & mask)
|
||||
? " wakeup" : "");
|
||||
}
|
||||
seq_printf(s, "\n");
|
||||
}
|
||||
|
||||
if (!cpu_is_omap24xx() && bank->method == METHOD_MPUIO) {
|
||||
seq_printf(s, "\n");
|
||||
gpio = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dbg_gpio_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, dbg_gpio_show, inode->u.generic_ip/*i_private*/);
|
||||
}
|
||||
|
||||
static const struct file_operations debug_fops = {
|
||||
.open = dbg_gpio_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int __init omap_gpio_debuginit(void)
|
||||
{
|
||||
(void) debugfs_create_file("omap_gpio", S_IRUGO, NULL, NULL, &debug_fops);
|
||||
return 0;
|
||||
}
|
||||
late_initcall(omap_gpio_debuginit);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user