📄 ints.c
字号:
/* * linux/arch/h8300/platform/h8s/ints.c * * Yoshinori Sato <ysato@users.sourceforge.jp> * * Based on linux/arch/$(ARCH)/platform/$(PLATFORM)/ints.c * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details. * * Copyright 1996 Roman Zippel * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com> */#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/kernel_stat.h>#include <linux/seq_file.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/bootmem.h>#include <linux/random.h>#include <linux/hardirq.h>#include <asm/system.h>#include <asm/irq.h>#include <asm/traps.h>#include <asm/io.h>#include <asm/setup.h>#include <asm/gpio.h>#include <asm/regs267x.h>#include <asm/errno.h>/* * This structure has only 4 elements for speed reasons */typedef struct irq_handler { irqreturn_t (*handler)(int, void *, struct pt_regs *); int flags; int count; void *dev_id; const char *devname;} irq_handler_t;static irq_handler_t *irq_list[NR_IRQS];/* IRQ pin assignment */struct irq_pins { unsigned char port_no; unsigned char bit_no;};/* ISTR = 0 */static const struct irq_pins irq_assign_table0[16]={ {H8300_GPIO_P5,H8300_GPIO_B0},{H8300_GPIO_P5,H8300_GPIO_B1}, {H8300_GPIO_P5,H8300_GPIO_B2},{H8300_GPIO_P5,H8300_GPIO_B3}, {H8300_GPIO_P5,H8300_GPIO_B4},{H8300_GPIO_P5,H8300_GPIO_B5}, {H8300_GPIO_P5,H8300_GPIO_B6},{H8300_GPIO_P5,H8300_GPIO_B7}, {H8300_GPIO_P6,H8300_GPIO_B0},{H8300_GPIO_P6,H8300_GPIO_B1}, {H8300_GPIO_P6,H8300_GPIO_B2},{H8300_GPIO_P6,H8300_GPIO_B3}, {H8300_GPIO_P6,H8300_GPIO_B4},{H8300_GPIO_P6,H8300_GPIO_B5}, {H8300_GPIO_PF,H8300_GPIO_B1},{H8300_GPIO_PF,H8300_GPIO_B2},};/* ISTR = 1 */static const struct irq_pins irq_assign_table1[16]={ {H8300_GPIO_P8,H8300_GPIO_B0},{H8300_GPIO_P8,H8300_GPIO_B1}, {H8300_GPIO_P8,H8300_GPIO_B2},{H8300_GPIO_P8,H8300_GPIO_B3}, {H8300_GPIO_P8,H8300_GPIO_B4},{H8300_GPIO_P8,H8300_GPIO_B5}, {H8300_GPIO_PH,H8300_GPIO_B2},{H8300_GPIO_PH,H8300_GPIO_B3}, {H8300_GPIO_P2,H8300_GPIO_B0},{H8300_GPIO_P2,H8300_GPIO_B1}, {H8300_GPIO_P2,H8300_GPIO_B2},{H8300_GPIO_P2,H8300_GPIO_B3}, {H8300_GPIO_P2,H8300_GPIO_B4},{H8300_GPIO_P2,H8300_GPIO_B5}, {H8300_GPIO_P2,H8300_GPIO_B6},{H8300_GPIO_P2,H8300_GPIO_B7},};static short use_kmalloc = 0;extern unsigned long *interrupt_redirect_table;#define CPU_VECTOR ((unsigned long *)0x000000)#define ADDR_MASK (0xffffff)static inline unsigned long *get_vector_address(void){ volatile unsigned long *rom_vector = CPU_VECTOR; unsigned long base,tmp; int vec_no; base = rom_vector[EXT_IRQ0] & ADDR_MASK; /* check romvector format */ for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ15; vec_no++) { if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK)) return NULL; } /* ramvector base address */ base -= EXT_IRQ0*4; /* writerble check */ tmp = ~(*(unsigned long *)base); (*(unsigned long *)base) = tmp; if ((*(unsigned long *)base) != tmp) return NULL; return (unsigned long *)base;}void __init init_IRQ(void){#if defined(CONFIG_RAMKERNEL) int i; unsigned long *ramvec,*ramvec_p; unsigned long break_vec; ramvec = get_vector_address(); if (ramvec == NULL) panic("interrupt vector serup failed."); else printk("virtual vector at 0x%08lx\n",(unsigned long)ramvec);#if defined(CONFIG_GDB_DEBUG) /* save orignal break vector */ break_vec = ramvec[TRAP3_VEC];#else break_vec = VECTOR(trace_break);#endif /* create redirect table */ for (ramvec_p = ramvec, i = 0; i < NR_IRQS; i++) *ramvec_p++ = REDIRECT(interrupt_entry); /* set special vector */ ramvec[TRAP0_VEC] = VECTOR(system_call); ramvec[TRAP3_VEC] = break_vec; interrupt_redirect_table = ramvec;#ifdef DUMP_VECTOR ramvec_p = ramvec; for (i = 0; i < NR_IRQS; i++) { if ((i % 8) == 0) printk("\n%p: ",ramvec_p); printk("%p ",*ramvec_p); ramvec_p++; } printk("\n");#endif#endif}int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id){ unsigned short ptn = 1 << (irq - EXT_IRQ0); irq_handler_t *irq_handle; if (irq < 0 || irq >= NR_IRQS) { printk("Incorrect IRQ %d from %s\n", irq, devname); return -EINVAL; } if (irq_list[irq]) return -EBUSY; /* already used */ if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) { /* initialize IRQ pin */ unsigned int port_no,bit_no; if (*(volatile unsigned short *)ITSR & ptn) { port_no = irq_assign_table1[irq - EXT_IRQ0].port_no; bit_no = irq_assign_table1[irq - EXT_IRQ0].bit_no; } else { port_no = irq_assign_table0[irq - EXT_IRQ0].port_no; bit_no = irq_assign_table0[irq - EXT_IRQ0].bit_no; } if (H8300_GPIO_RESERVE(port_no, bit_no) == 0) return -EBUSY; /* pin already use */ H8300_GPIO_DDR(port_no, bit_no, H8300_GPIO_INPUT); *(volatile unsigned short *)ISR &= ~ptn; /* ISR clear */ } if (use_kmalloc) irq_handle = kmalloc(sizeof(irq_handler_t), GFP_ATOMIC); else { /* use bootmem allocator */ irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t)); irq_handle = (irq_handler_t *)((unsigned long)irq_handle | 0x80000000); } if (irq_handle == NULL) return -ENOMEM; irq_handle->handler = handler; irq_handle->flags = flags; irq_handle->count = 0; irq_handle->dev_id = dev_id; irq_handle->devname = devname; irq_list[irq] = irq_handle; if (irq_handle->flags & IRQF_SAMPLE_RANDOM) rand_initialize_irq(irq); /* enable interrupt */ /* compatible i386 */ if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) *(volatile unsigned short *)IER |= ptn; return 0;}EXPORT_SYMBOL(request_irq);void free_irq(unsigned int irq, void *dev_id){ if (irq >= NR_IRQS) return; if (irq_list[irq]->dev_id != dev_id) printk("%s: Removing probably wrong IRQ %d from %s\n", __FUNCTION__, irq, irq_list[irq]->devname); if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) { /* disable interrupt & release IRQ pin */ unsigned short port_no,bit_no; *(volatile unsigned short *)ISR &= ~(1 << (irq - EXT_IRQ0)); *(volatile unsigned short *)IER |= 1 << (irq - EXT_IRQ0); if (*(volatile unsigned short *)ITSR & (1 << (irq - EXT_IRQ0))) { port_no = irq_assign_table1[irq - EXT_IRQ0].port_no; bit_no = irq_assign_table1[irq - EXT_IRQ0].bit_no; } else { port_no = irq_assign_table0[irq - EXT_IRQ0].port_no; bit_no = irq_assign_table0[irq - EXT_IRQ0].bit_no; } H8300_GPIO_FREE(port_no, bit_no); } if (((unsigned long)irq_list[irq] & 0x80000000) == 0) { kfree(irq_list[irq]); irq_list[irq] = NULL; }}EXPORT_SYMBOL(free_irq);unsigned long probe_irq_on (void){ return 0;}EXPORT_SYMBOL(probe_irq_on);int probe_irq_off (unsigned long irqs){ return 0;}EXPORT_SYMBOL(probe_irq_off);void enable_irq(unsigned int irq){ if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) *(volatile unsigned short *)IER |= 1 << (irq - EXT_IRQ0);}void disable_irq(unsigned int irq){ if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) *(volatile unsigned short *)IER &= ~(1 << (irq - EXT_IRQ0));}asmlinkage void process_int(unsigned long vec, struct pt_regs *fp){ irq_enter(); /* ISR clear */ /* compatible i386 */ if (vec >= EXT_IRQ0 && vec <= EXT_IRQ15) *(volatile unsigned short *)ISR &= ~(1 << (vec - EXT_IRQ0)); if (vec < NR_IRQS) { if (irq_list[vec]) { irq_list[vec]->handler(vec, irq_list[vec]->dev_id, fp); irq_list[vec]->count++; if (irq_list[vec]->flags & IRQF_SAMPLE_RANDOM) add_interrupt_randomness(vec); } } else { BUG(); } irq_exit();}int show_interrupts(struct seq_file *p, void *v){ int i = *(loff_t *) v; if ((i < NR_IRQS) && (irq_list[i] !=NULL)) { seq_printf(p, "%3d: %10u ",i,irq_list[i]->count); seq_printf(p, "%s\n", irq_list[i]->devname); } return 0;}void init_irq_proc(void){}static int __init enable_kmalloc(void){ use_kmalloc = 1; return 0;}core_initcall(enable_kmalloc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -