#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bus.h" #include "irq.h" #define MAP_KEY_IRQ (0x02) #define MAP_1MS_IRQ (0x03) #define PROC_NAME ("fpga_irq") enum IRQ_TYPE_NAME { MRS_KEY_IRQ = 0, MRS_1MS_IRQ = 1, }; typedef struct __EXT_IRQ_INFO__ { int irqId; int irqMap; enum IRQ_TYPE_NAME irqType; char irqName[32]; } EXT_IRQ_INFO, *PEXT_IRQ_INFO; typedef int (*PEXT_1MSTIMER_RUNTIME)(void*); typedef int (*PEXT_KEY_RUNTIME)(void*); struct irq_hook { PEXT_1MSTIMER_RUNTIME hook; void* data; }; static EXT_IRQ_INFO g_IrqInfo[2]; static unsigned int g_IrqCnt = 0; static unsigned int g_KeyCnt = 0; static unsigned int* g_pIrqRegBase = NULL; static struct irq_hook g_1MSIrqHooks[32]; static volatile unsigned int g_1MSPoolMap = 0xFFFFFFFF; static struct irq_hook g_KeyIrqHooks[32]; static volatile unsigned int g_KeyPoolMap = 0xFFFFFFFF; static unsigned int g_FPGAINfoOption = 0; static struct tm g_LastKeyTime; int register_ext_timer_irq(PEXT_1MSTIMER_RUNTIME phooks, void* data) { int ret = -ENOSPC; int idx = 0; if((idx = fls(g_1MSPoolMap) - 1) >= 0) { g_1MSPoolMap &= ~(1 << idx); g_1MSIrqHooks[idx].hook = phooks; g_1MSIrqHooks[idx].data = data; ret = idx; printk("ext_irq_poll_register %x\n", ret); } return ret; } EXPORT_SYMBOL(register_ext_timer_irq); int unregister_ext_timer_irq(int idx) { int ret = -EINVAL; printk("ext_irq_poll_unregister %x\n", idx); if(!(g_1MSPoolMap & (1 << idx))) { g_1MSPoolMap |= (1 << idx); } return ret; } EXPORT_SYMBOL(unregister_ext_timer_irq); int register_key_timer_irq(PEXT_KEY_RUNTIME phooks, void* data) { int ret = -ENOSPC; int idx = 0; if((idx = fls(g_KeyPoolMap) - 1) >= 0) { g_KeyPoolMap &= ~(1 << idx); g_KeyIrqHooks[idx].hook = phooks; g_KeyIrqHooks[idx].data = data; ret = idx; printk("key_irq_poll_register %x\n", ret); } return ret; } EXPORT_SYMBOL(register_key_timer_irq); int unregister_key_timer_irq(int idx) { int ret = -EINVAL; printk("key_irq_poll_unregister %x\n", idx); if(!(g_KeyPoolMap & (1 << idx))) { g_KeyPoolMap |= (1 << idx); } return ret; } EXPORT_SYMBOL(unregister_key_timer_irq); /** disable interrput **/ static void fpga_disable_irq(unsigned short irq) { unsigned short reg; reg = read_fpga16(FPGA_INT_MASK_REG_OFFSET); reg &= ~irq; write_fpga16(FPGA_INT_MASK_REG_OFFSET, reg); reg = read_fpga16(FPGA_INT_MASK_REG_OFFSET); } /** enable interrput **/ static void fpga_enable_irq(unsigned short irq) { unsigned short reg; reg = read_fpga16(FPGA_INT_MASK_REG_OFFSET); reg |= irq; write_fpga16(FPGA_INT_MASK_REG_OFFSET, reg); reg = read_fpga16(FPGA_INT_MASK_REG_OFFSET); } static unsigned short fpga_irq_clr(void) { unsigned short value; value = read_fpga16(FPGA_INT_STATUS_REG_OFFSET); value &= FPGA_INT_REG_MASK; return value; } static void clr_int_status_bit(unsigned short value) { unsigned short reg; reg = read_fpga16(FPGA_INT_STATUS_REG_OFFSET); reg &= ~value; write_fpga16(FPGA_INT_STATUS_REG_OFFSET, reg); } static unsigned short get_int_status_bit(void) { unsigned short value; value = read_fpga16(FPGA_INT_STATUS_REG_OFFSET); value &= FPGA_INT_REG_MASK; return value; } static unsigned short get_gpio_data(void) { unsigned short value; value = read_fpga16(FPGA_GPIO_DATA_OFFSET); return value; } static irqreturn_t ext1ms_irq_handler(int irq, void* dev_id) { int i = -1; unsigned int bits; bits = ~g_1MSPoolMap; while((i = fls(bits) - 1) >= 0) { bits &= ~(1 << i); g_1MSIrqHooks[i].hook(g_1MSIrqHooks[i].data); } g_IrqCnt++; // Reset Irq in_be32((const volatile unsigned int*)&g_pIrqRegBase[MPIC_IACK_OFFSET]); out_be32((volatile unsigned int*)&g_pIrqRegBase[MPIC_EOI_OFFSET], MPIC_EOI_VALUE); return IRQ_HANDLED; } static irqreturn_t key_irq_handler(int irq, void* dev_id) { unsigned short status, data; int i = -1; unsigned int bits; struct timeval tv; status = get_int_status_bit(); fpga_disable_irq(FPGA_INT_REG_MASK); if(status & (FPGA_GPIO_STOP_BIT)) { //ndelay(10000000); data = get_gpio_data(); if(data & (FPGA_GPIO_STOP_BIT)) { //printk("key stop detect\n"); do_gettimeofday(&tv); time_to_tm(tv.tv_sec, 0, &g_LastKeyTime); g_LastKeyTime.tm_yday = tv.tv_usec / 1000; g_KeyCnt++; bits = ~g_KeyPoolMap; while((i = fls(bits) - 1) >= 0) { bits &= ~(1 << i); g_KeyIrqHooks[i].hook(g_KeyIrqHooks[i].data); } } } clr_int_status_bit(FPGA_INT_REG_MASK); in_be32((const volatile unsigned int*)&g_pIrqRegBase[MPIC_IACK_OFFSET]); out_be32((volatile unsigned int*)&g_pIrqRegBase[MPIC_EOI_OFFSET], MPIC_EOI_VALUE); fpga_enable_irq(FPGA_GPIO_STOP_BIT); return IRQ_HANDLED; } static int mpic_irq_init(enum IRQ_TYPE_NAME irqType, irqreturn_t (*handler)(int irq, void* dev_id)) { int ret = 0; unsigned int count; unsigned int value; unsigned int vector; value = g_pIrqRegBase[MPIC_EIVPR_OFFSET(g_IrqInfo[irqType].irqMap)]; vector = value & MPIC_EIVPR_VECTOR_MASK; g_IrqInfo[irqType].irqId = irq_create_mapping(NULL, vector); //printk("irq %d irq no: %d\n", g_IrqInfo[irqType].irqMap, g_IrqInfo[irqType].irqId); value = (value & MPIC_EIVPR_VECTOR_MASK) | MPIC_EIVPR_MSK | MPIC_EIVPR_PRIORITY( vector) ; /*active high to low*/ g_pIrqRegBase[MPIC_EIVPR_OFFSET(g_IrqInfo[irqType].irqMap)] = value; g_pIrqRegBase[MPIC_EIDR_OFFSET(g_IrqInfo[irqType].irqMap)] = MPIC_EIDR_VALUE; g_pIrqRegBase[MPIC_CTPR_OFFSET] = MPIC_CTPR_VALUE; g_pIrqRegBase[MPIC_GCR_OFFSET] |= MPIC_GCR_M; /* start irq */ count = g_pIrqRegBase[MPIC_FRR_OFFSET]; count = (count & IRQ_NUM_MASK) >> 16 ; while(count--) { in_be32((const volatile unsigned int*)&g_pIrqRegBase[MPIC_IACK_OFFSET]); out_be32((volatile unsigned int*)&g_pIrqRegBase[MPIC_EOI_OFFSET], MPIC_EOI_VALUE); } ret = request_irq(g_IrqInfo[irqType].irqId, handler, 0, g_IrqInfo[irqType].irqName, 0); g_pIrqRegBase[MPIC_MER_OFFSET] = MPIC_MER_VALUE; g_pIrqRegBase[MPIC_CTPR_OFFSET] = MPIC_CTPR_VALUE; /* start irq */ g_pIrqRegBase[MPIC_EIVPR_OFFSET(g_IrqInfo[irqType].irqMap)] &= ~ MPIC_EIVPR_MSK; return ret; } static void mpic_irq_exit(enum IRQ_TYPE_NAME irqType) { mdelay(1); g_pIrqRegBase[MPIC_EIVPR_OFFSET(g_IrqInfo[irqType].irqMap)] |= MPIC_EIVPR_MSK; free_irq(g_IrqInfo[irqType].irqId, NULL); } static int fpga_irq_proc_show(struct seq_file* m, void* v) { seq_printf(m, "--------FPGA IRQ INFO--------\n"); seq_puts(m, "\n"); seq_puts(m, "+++++MRS_KEY_IRQ IRQ Info:+++++\n"); seq_printf(m, "IRQ ID: %u\n", g_IrqInfo[0].irqId); seq_printf(m, "IRQ MAP ID: %u\n", g_IrqInfo[0].irqMap); seq_printf(m, "IRQ TYPE: %u\n", g_IrqInfo[0].irqType); seq_printf(m, "IRQ Name: %s\n", g_IrqInfo[0].irqName); seq_printf(m, "IRQ HOOK MAP: 0x%08X\n", g_KeyPoolMap); seq_printf(m, "IRQ Key Count: 0x%08X\n", g_KeyCnt); if(g_KeyCnt > 0) { seq_printf(m, "At [%02d:%02d:%02d:%03d] Stop Key Pressed\n", g_LastKeyTime.tm_hour, g_LastKeyTime.tm_min, g_LastKeyTime.tm_sec, g_LastKeyTime.tm_yday); } seq_puts(m, "-----MRS_KEY_IRQ IRQ Info:-----\n"); seq_puts(m, "\n"); seq_puts(m, "+++++MRS_1MS_IRQ IRQ Info:+++++\n"); seq_printf(m, "IRQ ID: %u\n", g_IrqInfo[1].irqId); seq_printf(m, "IRQ MAP ID: %u\n", g_IrqInfo[1].irqMap); seq_printf(m, "IRQ TYPE: %u\n", g_IrqInfo[1].irqType); seq_printf(m, "IRQ Name: %s\n", g_IrqInfo[1].irqName); seq_printf(m, "IRQ HOOK MAP: 0x%08X\n", g_1MSPoolMap); seq_printf(m, "IRQ 1MS Count: 0x%08X(%u)\n", g_IrqCnt, g_IrqCnt); seq_puts(m, "-----MRS_1MS_IRQ IRQ Info:-----\n"); return 0; } static int fpga_irq_proc_open(struct inode* inode, struct file* file) { return single_open(file, fpga_irq_proc_show, NULL); } static ssize_t fpga_irq_write(struct file* file, const char __user* userbuf, size_t count, loff_t* data) { char buf[20]; if(count >= sizeof(buf)) { printk("Input Params Error:count = %d, max size = %d\n", count, sizeof(buf)); return -1; } if(copy_from_user(buf, userbuf, count)) { printk("Copy Data To Kernel Error\n"); return -2; } buf[count] = '\0'; if(strict_strtoul(buf, 0, (long unsigned int*)&g_FPGAINfoOption)) { return -3; } printk("Set Options To [%u]\n", g_FPGAINfoOption); return count; } static const struct file_operations fpga_irq_proc_fops = { .open = fpga_irq_proc_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, .write = fpga_irq_write, }; int mrs_irq_init(void) { int uRet = 0; #ifdef PLATFORM_P1010 printk("Init PLATFORM P1010 Build:%s(%s)\n", __DATE__, __TIME__); #else printk("Init PLATFORM MPC8309 Build:%s(%s)\n", __DATE__, __TIME__); #endif proc_create(PROC_NAME, 0, NULL, &fpga_irq_proc_fops); fpga_bus_init(); g_IrqInfo[0].irqId = -1; g_IrqInfo[0].irqMap = MAP_KEY_IRQ; g_IrqInfo[0].irqType = MRS_KEY_IRQ; strcpy(g_IrqInfo[0].irqName, "MRS_KEY_IRQ"); g_IrqInfo[1].irqId = -1; g_IrqInfo[1].irqMap = MAP_1MS_IRQ; g_IrqInfo[1].irqType = MRS_1MS_IRQ; strcpy(g_IrqInfo[1].irqName, "MRS_1MS_IRQ"); g_pIrqRegBase = (unsigned int*)ioremap(MPIC_REGS_BASE, MPIC_REG_MAP_SIZE); // printk("g_pRegBase = 0x%08X, g_pIrqRegBase = 0x%08X\n", g_pIrqRegBase, g_pIrqRegBase); /** disable all fpga interrupt **/ fpga_disable_irq(FPGA_INT_MASK); /** enable the switch key **/ fpga_enable_irq(FPGA_GPIO_STOP_BIT); /** enable board select interrupt **/ fpga_enable_irq(FPGA_GPIO_BD_SEL); fpga_irq_clr(); mpic_irq_init(MRS_KEY_IRQ, key_irq_handler); mpic_irq_init(MRS_1MS_IRQ, ext1ms_irq_handler); return uRet; } void mrs_irq_exit(void) { #ifdef PLATFORM_P1010 printk("Exit PLATFORM P1010 Build:%s(%s)\n", __DATE__, __TIME__); #else printk("Exit PLATFORM MPC8309 Build:%s(%s)\n", __DATE__, __TIME__); #endif mpic_irq_exit(MRS_KEY_IRQ); mpic_irq_exit(MRS_1MS_IRQ); if(g_pIrqRegBase != NULL) { iounmap(g_pIrqRegBase); g_pIrqRegBase = NULL; } fpga_bus_exit(); remove_proc_entry(PROC_NAME, NULL); }