📄 bcm1480_ircpoll.s
字号:
/* ********************************************************************* * BCM1280/BCM1480 Board Support Package * * IRQ polling File: bcm1480_ircpoll.S * * This module contains code to poll the interrupt controller * and invoke the servicing of pending, unmasked interrupts. * ********************************************************************* * * Copyright 2000,2001,2002,2003 * Broadcom Corporation. All rights reserved. * * This software is furnished under license and may be used and * copied only in accordance with the following terms and * conditions. Subject to these conditions, you may download, * copy, install, use, modify and distribute modified or unmodified * copies of this software in source and/or binary form. No title * or ownership is transferred hereby. * * 1) Any source code used, modified or distributed must reproduce * and retain this copyright notice and list of conditions * as they appear in the source file. * * 2) No right is granted to use any trade name, trademark, or * logo of Broadcom Corporation. The "Broadcom Corporation" * name may not be used to endorse or promote products derived * from this software without the prior written permission of * Broadcom Corporation. * * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************* */#include "sbmips.h" /* XXX updated IP and IM definitions needed */#include "mipsmacros.h"#include "cpu_config.h" /* for definition of HAZARD */#include "bcm1480_regs.h"#include "bcm1480_int.h" .set mips64/* * External interrupt conventions: * i0 (IP2) is used for for registered interrupts: * CFG_INTERRUPTS=1: unmasked, asynchronous hardware interrupts * CFG_INTERRUPTS=0: masked, synchronous software polling * i1-i4 are available for specific devices. * i5 (IP7) is reserved for sources within the CPU */ /* EOIs are issued when HT interrupts are programmed as levels. */ #define A_HT_EOI 0x90000000D8000000#define D_EOI_MDT (0x7 << 2) /* * Dispatch function address. Access to this function pointer assumes * that gp has been initialized and any relocation has been done. */ .sdata .globl irq_dispatchirq_dispatch: _LONG_ 0 .text /* ********************************************************************* * bcm1480_irq_install() * * Initialize dispatch pointer. See CALLINIT_RELOC in mipsmacros.h * for the logic used here. This function should be called after * any relocation is done and gp is initialized. * * This function should be called with interrupts disabled. * * Input parameters: * nothing * * Return value: * nothing ********************************************************************* */ .set push .set noreorder .extern bcm1480_dispatch_irqdispatch_func: _LONG_ bcm1480_dispatch_irq LEAF(bcm1480_irq_install) la v0,dispatch_func LR v0, 0(v0)1: SR v0, irq_dispatch jr ra nop END(bcm1480_irq_install) .set pop /* ********************************************************************* * CFE_IRQ_POLL * * Scan the interrupt_source_status and interrupt_ldt registers. * For those not masked by the interrupt_mask register, invoke * cfe_dispatch_irq with the interrupt number as argument. * * For HT-signaled interrupts, also clear the pending vector. * * For asynchronous dispatch, called with interrupts disabled. * * Input parameters: * nothing * * Return value: * nothing ********************************************************************* */ .set push .set noreorder .set noat .set mips64 /* This version accomodates level-triggered HT interrupts by issuing EOI's on return from each handler. This code depends on the fact that an EOI will cause a level-sensitive interrupt to resend the interrupt message if that interrupt is still pending. It is not safe for edge-triggered interrupts. */ /* Note that we rely on interrupt mapping hardware to do merging and masking by reading interrupt status[n], with n=0 (IP2) currently. We still need to determine which bits are sourced by HT and potentially require EOIs. We thus must read and save the HT interrupt vector before calling the handler(s). */LEAF(cfe_irq_poll) daddiu sp, -72 /* saved register space */ sd s0, 32(sp) /* start the load early */ la v0, K1BASE + A_IMR_CPU0_BASE ld s0, R_IMR_INTERRUPT_STATUS_BASE_H+0(v0) sd s1, 40(sp) sd s2, 48(sp) sd s3, 56(sp) sd ra, 64(sp) mfc0 a0, C0_CAUSE andi a0, a0, M_CAUSE_IP2 beqz a0, 5f /* Do the high vector first */high: ld s2, R_IMR_LDT_INTERRUPT_H(v0) beqz s0, low /* No interrupts. Return if no cascade? */ /* The bit scan loop */ dclz s1, s0 /* Find index of the next interrupt */3: li s3, 1 dsubu s1, zero, s1 daddiu s1, s1, 63 beqz s1, low /* this is the cascade bit */ dsllv s3, s3, s1 xor s0, s0, s3 /* clear current bit */ LR v0, irq_dispatch jalr ra, v0 move a0, s1 /* a0 is interrupt number */ and a0, s2, s3 beqz a0, 4f /* not HT */ dsll s1, s1, 16 /* Clear the latched bit and send EOI if a pending HT interrupt */ la v0, K1BASE + A_IMR_CPU0_BASE sd s3, R_IMR_LDT_INTERRUPT_CLR_H(v0) dla v0, A_HT_EOI + (V_HTVECT_RAISE_INTLDT_HIGH << 16) or v0, v0, s1 sync#ifndef __long64 mfc0 s3, C0_SR ori AT, s3, M_SR_KX mtc0 AT, C0_SR HAZARD#endif sw zero, D_EOI_MDT(v0)#ifndef __long64 mtc0 s3, C0_SR HAZARD#endif4: bnez s0, 3b /* More interrupts to service? */ dclz s1, s0 /* unroll for branch delay slot */ b 5f /* No cascade, so skip low. */ nop /* Then the low. */low: la v0, K1BASE + A_IMR_CPU0_BASE ld s0, R_IMR_INTERRUPT_STATUS_BASE_L+0(v0) ld s2, R_IMR_LDT_INTERRUPT_L(v0) beqz s0, 5f /* No more interrupts. Return */ /* The bit scan loop */ dclz s1, s0 /* Find index of the next interrupt */3: li s3, 1 dsubu s1, zero, s1 daddiu s1, s1, 63 dsllv s3, s3, s1 xor s0, s0, s3 /* clear current bit */ LR v0, irq_dispatch jalr ra, v0 daddiu a0, s1, 64 /* a0 is interrupt number */ and a0, s2, s3 beqz a0, 4f /* not HT */ dsll s1, s1, 16 /* Clear the latched bit and send EOI if a pending HT interrupt */ la v0, K1BASE + A_IMR_CPU0_BASE sd s3, R_IMR_LDT_INTERRUPT_CLR_L(v0) dla v0, A_HT_EOI + (V_HTVECT_RAISE_INTLDT_LOW << 16) or v0, v0, s1 sync#ifndef __long64 mfc0 s3, C0_SR ori AT, s3, M_SR_KX mtc0 AT, C0_SR HAZARD#endif sw zero, D_EOI_MDT(v0)#ifndef __long64 mtc0 s3, C0_SR HAZARD#endif4: bnez s0, 3b /* More interrupts to service? */ dclz s1, s0 /* unroll for branch delay slot */5: ld ra, 64(sp) /* restore registers */ ld s3, 56(sp) ld s2, 48(sp) ld s1, 40(sp) ld s0, 32(sp) jr ra daddiu sp, 72 /* saved register space */ END(cfe_irq_poll) .set pop/* ********************************************************************* * bcm1480_irq_arm() * * Set up CP0 Status and Cause per conventions above (not really -- yet) * * This function should be called with interrupts disabled. * * Input parameters: * nothing * * Return value: * nothing ********************************************************************* */ .set push .set noreorder .set mips64LEAF(bcm1480_irq_arm) mfc0 t0,C0_CAUSE or t0,t0,M_CAUSE_IV mtc0 t0,C0_CAUSE mfc0 t0,C0_SR li t1,M_SR_IMMASK /* Mask all interrupt levels */ nor t1,t1,zero and t0,t0,t1 or t0,t0,M_SR_IE /* but set IE */ mtc0 t0,C0_SR HAZARD jr ra nop END(bcm1480_irq_arm) .set pop/* ********************************************************************* * cfe_irq_disable() * * Disable interrupts * XXX: This is not really atomic. * * Input parameters: * none * * Return value: * current SR interrupt mask ********************************************************************* */ .set push .set noreorder .set mips64LEAF(cfe_irq_disable) mfc0 t0,C0_SR li t1,M_SR_IMMASK|M_SR_IE li t2,~(M_SR_IMMASK|M_SR_IE) and v0,t0,t1 /* current mask bits */ and t0,t0,t2 mtc0 t0,C0_SR /* all enables cleared */ HAZARD jr ra nop END(cfe_irq_disable) .set pop /* ********************************************************************* * cfe_irq_enable(mask) * * Restore enabled interrupts * XXX: This is not really atomic. * * Input parameters: * interrupt mask (from irq_disable) * * Return value: * nothing ********************************************************************* */ .set push .set noreorder .set mips64LEAF(cfe_irq_enable) mfc0 t0,C0_SR li t1,M_SR_IMMASK|M_SR_IE li t2,~(M_SR_IMMASK|M_SR_IE) and a0,a0,t1 and t0,t0,t2 or t0,t0,a0 mtc0 t0,C0_SR HAZARD jr ra nop END(cfe_irq_enable) .set pop/* ********************************************************************* * bcm1480_update_sr(clear,set) * * Upate Status.IM according to masks * * Caller should disable interrupts if the effect is to be atomic. * * Input parameters: * a0 SR bits to be cleared * a1 SR bits to be set * * Return value: * none ********************************************************************* */ .set push .set noreorder .set mips64LEAF(bcm1480_update_sr) nor a0,a0,zero mfc0 t0,C0_SR and t0,t0,a0 /* current mask bits */ or t0,t0,a1 mtc0 t0,C0_SR /* all enables cleared */ HAZARD jr ra nop END(bcm1480_update_sr) .set pop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -