?? irq.c
字號:
/* * Copyright (C) 2002 MIZI Research, Inc. * * machine dependent irq handling routine * * Author: Nandy Lyu <nandy@mizi.com> * Date : $Date: 2002/05/14 02:19:42 $ * * $Revision: 1.1.2.4 $ Tue May 21 2002 Nandy Lyu <nandy@mizi.com> - initial - BUG: 1) set_EINT_IRQ_edge 頰毫具 凳 2) INTSUBMSK綽 阿 device driver俊輯 力絹竅檔廢 秦具 竊. Wed Aug 14 2002 Yong-iL Joh <tolkien@mizi.com> - new irq scheme闌 利儈, 困俊 攫鞭等 bug 絆魔 * * 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. */#include "./hardware.h"#include "./irqs.h"#include "errno.h"#include "2410addr.h"#include "S3C2410.h"#define EINT_OFFSET(x) ((x) - NORMAL_IRQ_OFFSET + 4)#define SUBIRQ_OFFSET(x) ((x) - EXT_IRQ_OFFSET)#define EXTINT_MASK 0x7#if 1/* * set_GPIO_IRQ_edge - set interrupt signal for External Interrupts * * parameters: * irq number of external interrupt (IRQ_EINT0 ~ IRQ_EINT23) * edge signal method */#define EXTINT_OFFSET 0x4#define EXTINT_MASK 0x7int set_EXT_IRQ_mode(int irq, int edge) { unsigned long flags; int shift_value; if (!(((IRQ_EINT4 <= irq) && (irq <= IRQ_EINT23)) || ((IRQ_EINT0 <= irq) && (irq <= IRQ_EINT3)))) return -EINVAL; if (irq < IRQ_EINT4) { /* IRQ_EINT0 ~ IRQ_EINT3 */ shift_value = (irq % 8) * EXTINT_OFFSET; rEXTINT0 &= ~(EXTINT_MASK << shift_value); rEXTINT0 |= (edge << shift_value); ClearPending(0x1<<irq); } else { shift_value = ((irq + 4) % 8) * EXTINT_OFFSET; if (irq < IRQ_EINT8) { /* IRQ_EINT4 ~ IRQ_EINT7 */ rEXTINT0 &= ~(EXTINT_MASK << shift_value); rEXTINT0 |= (edge << shift_value); rEINTPEND = (1 << shift_value); ClearPending(0x1<<IRQ_EINT4_7); } else if (irq < IRQ_EINT16) { /* IRQ_EINT8 ~ IRQ_EINT15 */ rEXTINT1 &= ~(EXTINT_MASK << shift_value); rEXTINT1 |= (edge << shift_value); rEINTPEND = (1 << shift_value); ClearPending(0x1<<IRQ_EINT8_23); } else { /* IRQ_EINT16 ~ IRQ_EINT23 */ rEXTINT2 &= ~(EXTINT_MASK << shift_value); rEXTINT2 |= (edge << shift_value); rEINTPEND = (1 << shift_value); ClearPending(0x1<<IRQ_EINT8_23); } } return 0;}#endif/* * External IRQ甫 力寇茄 IRQ甸闌 request_irq()肺 殿廢竅扁 傈俊 * 購啊 秦林絹具 瞪 老甸撈 樂闌鱉夸? 力 積阿俊綽 絕促絆 壕聰促. * IRQ甸 吝俊輯 External IRQ(伙己俊輯 林厘竅綽 儈絹)父撈 GPIO甫 * 固府 汲瀝竅絆 甸絹啊具 鄧聰促. 弊貳輯 竅唱狼 竊薦俊輯 * 葛電 巴闌 秦搬秦 滾府綽 巴籃 絹凍鱉 酵焙夸. * * 2002.09.03 厘繞. */static int fixup_irq_num(int irq){ if (irq < IRQ_EINT4) return irq; else return ((irq + 4) - NORMAL_IRQ_OFFSET);}static voidset_gpios(int irq, int pullup){ int shift; if (irq < 8) { shift = 2*irq; rGPFCON &= ~(0x3 << shift); rGPFCON |= (0x2 << shift); rGPFUP &= ~(GRAB_PULLUP(pullup) << irq); rGPFUP |= (GRAB_PULLUP(pullup) << irq); } else { shift = 2*(irq - 8); rGPGCON &= ~(0x3 << shift); rGPGCON |= (0x2 << shift); rGPGUP &= ~(GRAB_PULLUP(pullup) << (irq - 8)); rGPGUP |= (GRAB_PULLUP(pullup) << (irq - 8)); } }int set_external_irq(int irq, int edge, int pullup){ unsigned long flags; int real_irq, reg_ofs, shift; volatile unsigned *extint = (volatile unsigned *)(0x56000088); //printk(__FUNCTION__" called\n"); if (((irq < IRQ_EINT0) && (irq > IRQ_EINT23)) || ((irq > IRQ_EINT3) && (irq < IRQ_EINT4))) return -EINVAL; real_irq = fixup_irq_num(irq); //printk(__FUNCTION__"(): real_irq = %d\n", real_irq); set_gpios(real_irq, pullup); reg_ofs = (real_irq / 8); //printk(__FUNCTION__"(): regs_ofs = %d\n", reg_ofs); shift = 4 * (real_irq - 8 * reg_ofs); extint += reg_ofs; *extint &= ~(EXTINT_MASK << shift); *extint |= (edge << shift); if (irq < 4) { rSRCPND |= (1 << real_irq); rINTPND |= (1 << real_irq); } else { rEINTPEND |= (1 << real_irq); } return 0;}/* * Defined irq handlers */static void s3c2410_mask_ack_irq(unsigned int irq){ rINTMSK |= (1 << irq); rSRCPND = (1 << irq); rINTPND = (1 << irq);}static void s3c2410_mask_irq(unsigned int irq){ rINTMSK |= (1 << irq);}static void s3c2410_unmask_irq(unsigned int irq){ rINTMSK &= ~(1 << irq);}/* for EINT? */static void EINT4_23mask_ack_irq(unsigned int irq){ irq = EINT_OFFSET(irq); rEINTMASK |= (1 << irq); rEINTPEND = (1 << irq); if (irq < EINT_OFFSET(IRQ_EINT8)) {// INTMSK |= (1 << SHIFT_EINT4_7); ClearPending(0x1<<SHIFT_EINT4_7); } else {// INTMSK |= (1 << SHIFT_EINT8_23); ClearPending(0x1<<SHIFT_EINT8_23); }}static void EINT4_23mask_irq(unsigned int irq){#if 0 if (irq < IRQ_EINT8) { INTMSK |= (1 << SHIFT_EINT4_7); } else { INTMSK |= (1 << SHIFT_EINT8_23); }#endif irq = EINT_OFFSET(irq); rEINTMASK |= (1 << irq);}static void EINT4_23unmask_irq(unsigned int irq){ rEINTMASK &= ~(1 << EINT_OFFSET(irq)); if (irq < IRQ_EINT8) { rINTMSK &= ~(1 << SHIFT_EINT4_7); } else { rINTMSK &= ~(1 << SHIFT_EINT8_23); }}/* for sub_IRQ */static void SUB_mask_ack_irq(unsigned int irq){ rINTSUBMSK |= (1 << SUBIRQ_OFFSET(irq)); rSUBSRCPND = (1 << SUBIRQ_OFFSET(irq)); if (irq <= IRQ_ERR0) { ClearPending(0x1<<SHIFT_UART0); } else if (irq <= IRQ_ERR1) { ClearPending(0x1<<SHIFT_UART1); } else if (irq <= IRQ_ERR2){ ClearPending(0x1<<SHIFT_UART2); } else { /* if ( irq <= IRQ_ADC_DONE ) { */ ClearPending(0x1<<SHIFT_ADCTC); }}static void SUB_mask_irq(unsigned int irq){ rINTSUBMSK |= (1 << SUBIRQ_OFFSET(irq));}static void SUB_unmask_irq(unsigned int irq){ rINTSUBMSK &= ~(1 << SUBIRQ_OFFSET(irq)); if (irq <= IRQ_ERR0) { rINTMSK &= ~(1 << SHIFT_UART0); } else if (irq <= IRQ_ERR1) { rINTMSK &= ~(1 << SHIFT_UART1); } else if (irq <= IRQ_ERR2){ rINTMSK &= ~(1 << SHIFT_UART2); } else { /* if ( irq <= IRQ_ADC_DONE ) { */ rINTMSK &= ~(1 << SHIFT_ADCTC); }}/* * fixup_irq() for do_IRQ() in kernel/irq.c */ unsigned int get_subIRQ(int irq, int begin, int end, int fail_irq) { int i; for(i=begin; i <= end; i++) { if (irq & (1 << i)) return (EXT_IRQ_OFFSET + i); } return fail_irq;} unsigned int get_extIRQ(int irq, int begin, int end, int fail_irq) { int i; for(i=begin; i <= end; i++) { if (irq & (1 << i)) return (NORMAL_IRQ_OFFSET - 4 + i); } return fail_irq;}unsigned int fixup_irq(int irq) { unsigned int ret; unsigned long sub_mask, ext_mask; if (irq == OS_TIMER) return irq; switch (irq) { case IRQ_UART0: sub_mask = rSUBSRCPND & ~rINTSUBMSK; ret = get_subIRQ(sub_mask, 0, 2, irq); break; case IRQ_UART1: sub_mask = rSUBSRCPND & ~rINTSUBMSK; ret = get_subIRQ(sub_mask, 3, 5, irq); break; case IRQ_UART2: sub_mask = rSUBSRCPND & ~rINTSUBMSK; ret = get_subIRQ(sub_mask, 6, 8, irq); break; case IRQ_ADCTC: sub_mask = rSUBSRCPND & ~rINTSUBMSK; ret = get_subIRQ(sub_mask, 9, 10, irq); break; case IRQ_EINT4_7: ext_mask = rEINTPEND & ~rEINTMASK; ret = get_extIRQ(ext_mask, 4, 7, irq); break; case IRQ_EINT8_23: ext_mask = rEINTPEND & ~rEINTMASK; ret = get_extIRQ(ext_mask, 8, 23, irq); break; default: ret = irq; } return ret;}void s3c2410_init_irq(void) { int irq; /* disable all IRQs */ rINTMSK = 0xffffffff; rINTSUBMSK = 0x7ff; rEINTMASK = 0x00fffff0; /* all IRQs are IRQ, not FIQ 0 : IRQ mode 1 : FIQ mode */ rINTMOD = 0x00000000; /* clear Source/Interrupt Pending Register */ rSRCPND = 0xffffffff; rINTPND = 0xffffffff; rSUBSRCPND = 0x7ff; rEINTPEND = 0x00fffff0; }/* | $Id: event.c,v 1.1.2.4 2002/05/14 02:19:42 tolkien Exp $ | | Local Variables: | mode: c | mode: font-lock | version-control: t | delete-old-versions: t | End: | | -*- End-Of-File -*- */
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -