adam's home
1. Grab interrups: interrpt.S
In __common_int_entry:
#ifdef CONFIG_IPIPE
call ___ipipe_grab_irq
SP += 12;
cc = r0 == 0;
if cc jump common_restore_context;
#else /* CONFIG_IPIPE */
call _do_irq;
SP += 12;
#endif /* CONFIG_IPIPE */
call return_from_int;
common_restore_context:
RESTORE_CONTEXT
rti;
/--------------------------------
Note: if returns (r0 == 1), should not call return_from_int.
---------------------------------/
2. asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
{
struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop;
struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst;
unsigned long sic_status;
ipipe_declare_cpuid;
int irq;
/--------------------------------------------------------
"struct ivgx {
/* irq number for request_irq, available in mach-bf533/irq.h */
int irqno;
/* corresponding bit in the SIC_ISR register */
int isrflag;
} ivg_table[NR_PERI_INTS];
struct ivg_slice {
/* position of first irq in ivg_table for given ivg */
struct ivgx *ifirst;
struct ivgx *istop;
} ivg7_13[IVG13 - IVG7 + 1];"
ivg7_13 is a table stores the mapping of peripheral interrupt to Core
interrupt IVG7-13.
ivg_table contains "IRQ NUM" and "Position in SIC_ISR" of peripheral
interrupts.
------------------------------------/
if (likely(vec == EVT_IVTMR_P)) {
irq = IRQ_CORETMR;
goto handle_irq;
}
/-----------------------------------------
CORETMR interrupt is likely to happen
-----------------------------------------/
__builtin_bfin_ssync();
sic_status = *pSIC_IMASK & *pSIC_ISR;
/----------------------------------------
sic_status: system interrupt happened and not masked.
------------------------------------------/
for(;; ivg++) {
if (ivg >= ivg_stop) {
num_spurious++;
return 0;
}
else if (sic_status & ivg->isrflag)
break;
/---------------------------------------
Find the system interrupt who triggers "vec"
----------------------------------------/
}
irq = ivg->irqno;
/---------------
irq defined:
See irq.h - peripheral interrupts IRQ NUM starts from 7 - sames order as
SIC_ISR
----------------/
ipipe_load_cpuid();
if (irq == IRQ_SYSTMR) {
*pTIMER_STATUS = 1; /* Latch TIMIL0 */
/* for update_process_times() */
__ipipe_tick_regs[cpuid].ipend = regs->ipend;
}
/--------------
IRQ_SYSTMR is peripheral, while CORE TIMER is CORE interrupt.
Why it need regs->ipend here?
-----------------/
handle_irq:
__ipipe_handle_irq(irq, regs);
return (ipipe_percpu_domain[cpuid] == ipipe_root_domain &&
!test_bit(IPIPE_STALL_FLAG,
&ipipe_root_domain->cpudata[cpuid].status));
/--------------
If this is Linux domain and Linux want to handle interrupt - return 1.
That means, this interrupt is handled the same way as Linux
---------------/
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment