From 59b6367c0155e4785926f6890a5f5e0ea2ad72d3 Mon Sep 17 00:00:00 2001 From: Greg Meiste Date: Mon, 26 Jul 2010 14:39:57 -0500 Subject: [PATCH] mfd: cpcap-irq: Add debugfs file for CPCAP IRQ data This change will add the file cpcap-irq to the debug fs directory. The file will provide data for each of the cpcap interrupts. The data includes the interrupt name, if the interrupt is enabled/disabled, if a handler has been registered with the interrupt, and the number of times the interrupt has been generated. Signed-off-by: Greg Meiste --- drivers/mfd/cpcap-irq.c | 150 +++++++++++++++++++++++++++++++++++----- 1 file changed, 134 insertions(+), 16 deletions(-) diff --git a/drivers/mfd/cpcap-irq.c b/drivers/mfd/cpcap-irq.c index e010e0dda74d..9c133be68126 100644 --- a/drivers/mfd/cpcap-irq.c +++ b/drivers/mfd/cpcap-irq.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, Motorola, All Rights Reserved. + * Copyright (C) 2009 - 2010, Motorola, All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -27,6 +27,7 @@ #include #include #include +#include #define NUM_INT_REGS 5 #define NUM_INTS_PER_REG 16 @@ -42,14 +43,19 @@ struct cpcap_event_handler { void *data; }; +struct cpcap_irq_info { + uint8_t registered; + uint8_t enabled; + uint32_t count; +}; + struct cpcap_irqdata { struct mutex lock; struct work_struct work; struct workqueue_struct *workqueue; struct cpcap_device *cpcap; struct cpcap_event_handler event_handler[CPCAP_IRQ__NUM]; - uint64_t registered; - uint64_t enabled; + struct cpcap_irq_info irq_info[CPCAP_IRQ__NUM]; struct wake_lock wake_lock; }; @@ -293,6 +299,8 @@ static void irq_work_func(struct work_struct *work) if (event_handler->func) event_handler->func(index, event_handler->data); + + data->irq_info[index].count++; } } error: @@ -300,12 +308,125 @@ error: wake_unlock(&data->wake_lock); } +#ifdef CONFIG_DEBUG_FS +static int cpcap_dbg_irq_show(struct seq_file *s, void *data) +{ + static const char *irq_name[] = { + [CPCAP_IRQ_HSCLK] = "HSCLK", + [CPCAP_IRQ_PRIMAC] = "PRIMAC", + [CPCAP_IRQ_SECMAC] = "SECMAC", + [CPCAP_IRQ_LOWBPL] = "LOWBPL", + [CPCAP_IRQ_SEC2PRI] = "SEC2PRI", + [CPCAP_IRQ_LOWBPH] = "LOWBPH", + [CPCAP_IRQ_EOL] = "EOL", + [CPCAP_IRQ_TS] = "TS", + [CPCAP_IRQ_ADCDONE] = "ADCDONE", + [CPCAP_IRQ_HS] = "HS", + [CPCAP_IRQ_MB2] = "MB2", + [CPCAP_IRQ_VBUSOV] = "VBUSOV", + [CPCAP_IRQ_RVRS_CHRG] = "RVRS_CHRG", + [CPCAP_IRQ_CHRG_DET] = "CHRG_DET", + [CPCAP_IRQ_IDFLOAT] = "IDFLOAT", + [CPCAP_IRQ_IDGND] = "IDGND", + + [CPCAP_IRQ_SE1] = "SE1", + [CPCAP_IRQ_SESSEND] = "SESSEND", + [CPCAP_IRQ_SESSVLD] = "SESSVLD", + [CPCAP_IRQ_VBUSVLD] = "VBUSVLD", + [CPCAP_IRQ_CHRG_CURR1] = "CHRG_CURR1", + [CPCAP_IRQ_CHRG_CURR2] = "CHRG_CURR2", + [CPCAP_IRQ_RVRS_MODE] = "RVRS_MODE", + [CPCAP_IRQ_ON] = "ON", + [CPCAP_IRQ_ON2] = "ON2", + [CPCAP_IRQ_CLK] = "CLK", + [CPCAP_IRQ_1HZ] = "1HZ", + [CPCAP_IRQ_PTT] = "PTT", + [CPCAP_IRQ_SE0CONN] = "SE0CONN", + [CPCAP_IRQ_CHRG_SE1B] = "CHRG_SE1B", + [CPCAP_IRQ_UART_ECHO_OVERRUN] = "UART_ECHO_OVERRUN", + [CPCAP_IRQ_EXTMEMHD] = "EXTMEMHD", + + [CPCAP_IRQ_WARM] = "WARM", + [CPCAP_IRQ_SYSRSTR] = "SYSRSTR", + [CPCAP_IRQ_SOFTRST] = "SOFTRST", + [CPCAP_IRQ_DIEPWRDWN] = "DIEPWRDWN", + [CPCAP_IRQ_DIETEMPH] = "DIETEMPH", + [CPCAP_IRQ_PC] = "PC", + [CPCAP_IRQ_OFLOWSW] = "OFLOWSW", + [CPCAP_IRQ_TODA] = "TODA", + [CPCAP_IRQ_OPT_SEL_DTCH] = "OPT_SEL_DTCH", + [CPCAP_IRQ_OPT_SEL_STATE] = "OPT_SEL_STATE", + [CPCAP_IRQ_ONEWIRE1] = "ONEWIRE1", + [CPCAP_IRQ_ONEWIRE2] = "ONEWIRE2", + [CPCAP_IRQ_ONEWIRE3] = "ONEWIRE3", + [CPCAP_IRQ_UCRESET] = "UCRESET", + [CPCAP_IRQ_PWRGOOD] = "PWRGOOD", + [CPCAP_IRQ_USBDPLLCLK] = "USBDPLLCLK", + + [CPCAP_IRQ_DPI] = "DPI", + [CPCAP_IRQ_DMI] = "DMI", + [CPCAP_IRQ_UCBUSY] = "UCBUSY", + [CPCAP_IRQ_GCAI_CURR1] = "GCAI_CURR1", + [CPCAP_IRQ_GCAI_CURR2] = "GCAI_CURR2", + [CPCAP_IRQ_SB_MAX_RETRANSMIT_ERR] = "SB_MAX_RETRANSMIT_ERR", + [CPCAP_IRQ_BATTDETB] = "BATTDETB", + [CPCAP_IRQ_PRIHALT] = "PRIHALT", + [CPCAP_IRQ_SECHALT] = "SECHALT", + [CPCAP_IRQ_CC_CAL] = "CC_CAL", + + [CPCAP_IRQ_UC_PRIROMR] = "UC_PRIROMR", + [CPCAP_IRQ_UC_PRIRAMW] = "UC_PRIRAMW", + [CPCAP_IRQ_UC_PRIRAMR] = "UC_PRIRAMR", + [CPCAP_IRQ_UC_USEROFF] = "UC_USEROFF", + [CPCAP_IRQ_UC_PRIMACRO_4] = "UC_PRIMACRO_4", + [CPCAP_IRQ_UC_PRIMACRO_5] = "UC_PRIMACRO_5", + [CPCAP_IRQ_UC_PRIMACRO_6] = "UC_PRIMACRO_6", + [CPCAP_IRQ_UC_PRIMACRO_7] = "UC_PRIMACRO_7", + [CPCAP_IRQ_UC_PRIMACRO_8] = "UC_PRIMACRO_8", + [CPCAP_IRQ_UC_PRIMACRO_9] = "UC_PRIMACRO_9", + [CPCAP_IRQ_UC_PRIMACRO_10] = "UC_PRIMACRO_10", + [CPCAP_IRQ_UC_PRIMACRO_11] = "UC_PRIMACRO_11", + [CPCAP_IRQ_UC_PRIMACRO_12] = "UC_PRIMACRO_12", + [CPCAP_IRQ_UC_PRIMACRO_13] = "UC_PRIMACRO_13", + [CPCAP_IRQ_UC_PRIMACRO_14] = "UC_PRIMACRO_14", + [CPCAP_IRQ_UC_PRIMACRO_15] = "UC_PRIMACRO_15", + }; + unsigned int i; + struct cpcap_irqdata *irqdata = s->private; + + seq_printf(s, "%21s%9s%12s%10s\n", + "CPCAP IRQ", "Enabled", "Registered", "Count"); + + for (i = 0; i < CPCAP_IRQ__NUM; i++) { + if ((i <= CPCAP_IRQ_CC_CAL) || (i >= CPCAP_IRQ_UC_PRIROMR)) { + seq_printf(s, "%21s%9d%12d%10d\n", + irq_name[i], + irqdata->irq_info[i].enabled, + irqdata->irq_info[i].registered, + irqdata->irq_info[i].count); + } + } + return 0; +} + +static int cpcap_dbg_irq_open(struct inode *inode, struct file *file) +{ + return single_open(file, cpcap_dbg_irq_show, inode->i_private); +} + +static const struct file_operations debug_fops = { + .open = cpcap_dbg_irq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + int cpcap_irq_init(struct cpcap_device *cpcap) { int retval; struct spi_device *spi = cpcap->spi; struct cpcap_irqdata *data; - struct dentry *debug_dir; data = kzalloc(sizeof(struct cpcap_irqdata), GFP_KERNEL); if (!data) @@ -334,13 +455,10 @@ int cpcap_irq_init(struct cpcap_device *cpcap) printk(KERN_ERR "cpcap_irq: Failed initializing pwrkey.\n"); goto error; } - - debug_dir = debugfs_create_dir("cpcap-irq", NULL); - debugfs_create_u64("registered", S_IRUGO, debug_dir, - &data->registered); - debugfs_create_u64("enabled", S_IRUGO, debug_dir, - &data->enabled); - +#ifdef CONFIG_DEBUG_FS + (void)debugfs_create_file("cpcap-irq", S_IRUGO, NULL, data, + &debug_fops); +#endif return 0; error: @@ -376,7 +494,7 @@ int cpcap_irq_register(struct cpcap_device *cpcap, mutex_lock(&irqdata->lock); if (irqdata->event_handler[irq].func == NULL) { - irqdata->registered |= 1 << irq; + irqdata->irq_info[irq].registered = 1; cpcap_irq_unmask(cpcap, irq); irqdata->event_handler[irq].func = cb_func; irqdata->event_handler[irq].data = data; @@ -401,7 +519,7 @@ int cpcap_irq_free(struct cpcap_device *cpcap, enum cpcap_irqs irq) retval = cpcap_irq_mask(cpcap, irq); data->event_handler[irq].func = NULL; data->event_handler[irq].data = NULL; - data->registered &= ~(1 << irq); + data->irq_info[irq].registered = 0; mutex_unlock(&data->lock); return retval; @@ -448,7 +566,7 @@ int cpcap_irq_mask(struct cpcap_device *cpcap, int retval = -EINVAL; if ((irq < CPCAP_IRQ__NUM) && (irq != CPCAP_IRQ_SECMAC)) { - data->enabled &= ~(1 << irq); + data->irq_info[irq].enabled = 0; retval = cpcap_regacc_write(cpcap, get_mask_reg(irq), EVENT_MASK(irq), @@ -466,7 +584,7 @@ int cpcap_irq_unmask(struct cpcap_device *cpcap, int retval = -EINVAL; if ((irq < CPCAP_IRQ__NUM) && (irq != CPCAP_IRQ_SECMAC)) { - data->enabled |= 1 << irq; + data->irq_info[irq].enabled = 1; retval = cpcap_regacc_write(cpcap, get_mask_reg(irq), 0, @@ -484,7 +602,7 @@ int cpcap_irq_mask_get(struct cpcap_device *cpcap, int retval = -EINVAL; if ((irq < CPCAP_IRQ__NUM) && (irq != CPCAP_IRQ_SECMAC)) - return (data->enabled & (1 << irq)) ? 0 : 1; + return data->irq_info[irq].enabled; return retval; } -- 2.34.1