Mercurial > ecos-v3_0-branch
diff packages/hal/powerpc/ppc40x/current/src/var_intr.c @ 136:a9ac27ec7abc ecos-sw-2000-11-17
Merge from eCos master repository on 2000-11-17-18:24:25-GMT
| author | jlarmour |
|---|---|
| date | Fri, 17 Nov 2000 23:16:43 +0000 |
| parents | d2f49caf9e38 |
| children | 52c99470ec11 |
line wrap: on
line diff
--- a/packages/hal/powerpc/ppc40x/current/src/var_intr.c +++ b/packages/hal/powerpc/ppc40x/current/src/var_intr.c @@ -43,12 +43,242 @@ //========================================================================== #include <pkgconf/hal.h> +#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS +#include <cyg/hal/ppc_regs.h> +#include <cyg/hal/hal_intr.h> #include <cyg/infra/cyg_type.h> +static cyg_uint32 exier_mask[] = { + 0x00000000, // Unused + 0x00000000, // Unused + 0x80000000, // CYGNUM_HAL_INTERRUPT_CRITICAL 2 + 0x08000000, // CYGNUM_HAL_INTERRUPT_SERIAL_RCV 3 + 0x04000000, // CYGNUM_HAL_INTERRUPT_SERIAL_XMT 4 + 0x02000000, // CYGNUM_HAL_INTERRUPT_JTAG_RCV 5 + 0x01000000, // CYGNUM_HAL_INTERRUPT_JTAG_XMT 6 + 0x00800000, // CYGNUM_HAL_INTERRUPT_DMA0 7 + 0x00400000, // CYGNUM_HAL_INTERRUPT_DMA1 8 + 0x00200000, // CYGNUM_HAL_INTERRUPT_DMA2 9 + 0x00100000, // CYGNUM_HAL_INTERRUPT_DMA3 10 + 0x00000010, // CYGNUM_HAL_INTERRUPT_EXT0 11 + 0x00000008, // CYGNUM_HAL_INTERRUPT_EXT1 12 + 0x00000004, // CYGNUM_HAL_INTERRUPT_EXT2 13 + 0x00000002, // CYGNUM_HAL_INTERRUPT_EXT3 14 + 0x00000001, // CYGNUM_HAL_INTERRUPT_EXT4 15 +}; + +// This table inverts bit number to signal number +cyg_uint32 EXISR_TAB[] = { + CYGNUM_HAL_INTERRUPT_CRITICAL, // 0x80000000 + 0x00000000, // 0x40000000 + 0x00000000, // 0x20000000 + 0x00000000, // 0x10000000 + CYGNUM_HAL_INTERRUPT_SERIAL_RCV, // 0x08000000 + CYGNUM_HAL_INTERRUPT_SERIAL_XMT, // 0x04000000 + CYGNUM_HAL_INTERRUPT_JTAG_RCV, // 0x02000000 + CYGNUM_HAL_INTERRUPT_JTAG_XMT, // 0x01000000 + CYGNUM_HAL_INTERRUPT_DMA0, // 0x00800000 + CYGNUM_HAL_INTERRUPT_DMA1, // 0x00400000 + CYGNUM_HAL_INTERRUPT_DMA2, // 0x00200000 + CYGNUM_HAL_INTERRUPT_DMA3, // 0x00100000 + 0x00000000, // 0x00080000 + 0x00000000, // 0x00040000 + 0x00000000, // 0x00020000 + 0x00000000, // 0x00010000 + 0x00000000, // 0x00008000 + 0x00000000, // 0x00004000 + 0x00000000, // 0x00002000 + 0x00000000, // 0x00001000 + 0x00000000, // 0x00000800 + 0x00000000, // 0x00000400 + 0x00000000, // 0x00000200 + 0x00000000, // 0x00000100 + 0x00000000, // 0x00000080 + 0x00000000, // 0x00000040 + 0x00000000, // 0x00000020 + CYGNUM_HAL_INTERRUPT_EXT0, // 0x00000010 + CYGNUM_HAL_INTERRUPT_EXT1, // 0x00000008 + CYGNUM_HAL_INTERRUPT_EXT2, // 0x00000004 + CYGNUM_HAL_INTERRUPT_EXT3, // 0x00000002 + CYGNUM_HAL_INTERRUPT_EXT4 // 0x00000001 +}; + +cyg_uint32 _hold_tcr = 0; // Shadow of hardware register + externC void hal_variant_IRQ_init(void) { - // No special init required for 40x series. + cyg_uint32 iocr; + + // Ensure all interrupts masked (disabled) & cleared + CYGARC_MTDCR(DCR_EXIER, 0); + CYGARC_MTDCR(DCR_EXISR, 0xFFFFFFFF); + + // Configure all external interrupts to be level/low + CYGARC_MFDCR(DCR_IOCR, iocr); + iocr &= ~0xFFC00000; + CYGARC_MTDCR(DCR_IOCR, iocr); + + // Disable timers + CYGARC_MTSPR(SPR_TCR, 0); +} + +externC void +hal_ppc40x_interrupt_mask(int vector) +{ + cyg_uint32 exier, tcr; + + switch (vector) { + case CYGNUM_HAL_INTERRUPT_CRITICAL: + case CYGNUM_HAL_INTERRUPT_SERIAL_RCV: + case CYGNUM_HAL_INTERRUPT_SERIAL_XMT: + case CYGNUM_HAL_INTERRUPT_JTAG_RCV: + case CYGNUM_HAL_INTERRUPT_JTAG_XMT: + case CYGNUM_HAL_INTERRUPT_DMA0: + case CYGNUM_HAL_INTERRUPT_DMA1: + case CYGNUM_HAL_INTERRUPT_DMA2: + case CYGNUM_HAL_INTERRUPT_DMA3: + case CYGNUM_HAL_INTERRUPT_EXT0: + case CYGNUM_HAL_INTERRUPT_EXT1: + case CYGNUM_HAL_INTERRUPT_EXT2: + case CYGNUM_HAL_INTERRUPT_EXT3: + case CYGNUM_HAL_INTERRUPT_EXT4: + CYGARC_MFDCR(DCR_EXIER, exier); + exier &= ~exier_mask[vector]; + CYGARC_MTDCR(DCR_EXIER, exier); + break; + case CYGNUM_HAL_INTERRUPT_VAR_TIMER: + CYGARC_MFSPR(SPR_TCR, tcr); + tcr = _hold_tcr; + tcr &= ~TCR_PIE; + CYGARC_MTSPR(SPR_TCR, tcr); + _hold_tcr = tcr; + break; + case CYGNUM_HAL_INTERRUPT_FIXED_TIMER: + CYGARC_MFSPR(SPR_TCR, tcr); + tcr = _hold_tcr; + tcr &= ~TCR_FIE; + CYGARC_MTSPR(SPR_TCR, tcr); + _hold_tcr = tcr; + break; + case CYGNUM_HAL_INTERRUPT_WATCHDOG_TIMER: + CYGARC_MFSPR(SPR_TCR, tcr); + tcr = _hold_tcr; + tcr &= ~TCR_WIE; + CYGARC_MTSPR(SPR_TCR, tcr); + _hold_tcr = tcr; + break; + default: + } +} + +externC void +hal_ppc40x_interrupt_unmask(int vector) +{ + cyg_uint32 exier, tcr; + + switch (vector) { + case CYGNUM_HAL_INTERRUPT_CRITICAL: + case CYGNUM_HAL_INTERRUPT_SERIAL_RCV: + case CYGNUM_HAL_INTERRUPT_SERIAL_XMT: + case CYGNUM_HAL_INTERRUPT_JTAG_RCV: + case CYGNUM_HAL_INTERRUPT_JTAG_XMT: + case CYGNUM_HAL_INTERRUPT_DMA0: + case CYGNUM_HAL_INTERRUPT_DMA1: + case CYGNUM_HAL_INTERRUPT_DMA2: + case CYGNUM_HAL_INTERRUPT_DMA3: + case CYGNUM_HAL_INTERRUPT_EXT0: + case CYGNUM_HAL_INTERRUPT_EXT1: + case CYGNUM_HAL_INTERRUPT_EXT2: + case CYGNUM_HAL_INTERRUPT_EXT3: + case CYGNUM_HAL_INTERRUPT_EXT4: + CYGARC_MFDCR(DCR_EXIER, exier); + exier |= exier_mask[vector]; + CYGARC_MTDCR(DCR_EXIER, exier); + break; + case CYGNUM_HAL_INTERRUPT_VAR_TIMER: + CYGARC_MFSPR(SPR_TCR, tcr); + tcr = _hold_tcr; + tcr |= TCR_PIE; + CYGARC_MTSPR(SPR_TCR, tcr); + _hold_tcr = tcr; + break; + case CYGNUM_HAL_INTERRUPT_FIXED_TIMER: + CYGARC_MFSPR(SPR_TCR, tcr); + tcr = _hold_tcr; + tcr |= TCR_FIE; + CYGARC_MTSPR(SPR_TCR, tcr); + _hold_tcr = tcr; + break; + case CYGNUM_HAL_INTERRUPT_WATCHDOG_TIMER: + CYGARC_MFSPR(SPR_TCR, tcr); + tcr = _hold_tcr; + tcr |= TCR_WIE; + CYGARC_MTSPR(SPR_TCR, tcr); + _hold_tcr = tcr; + break; + default: + } +} + +externC void +hal_ppc40x_interrupt_acknowledge(int vector) +{ + switch (vector) { + case CYGNUM_HAL_INTERRUPT_EXT0: + case CYGNUM_HAL_INTERRUPT_EXT1: + case CYGNUM_HAL_INTERRUPT_EXT2: + case CYGNUM_HAL_INTERRUPT_EXT3: + case CYGNUM_HAL_INTERRUPT_EXT4: + CYGARC_MTDCR(DCR_EXISR, exier_mask[vector]); + break; + case CYGNUM_HAL_INTERRUPT_VAR_TIMER: + CYGARC_MTSPR(SPR_TSR, TSR_PIS); // clear & acknowledge interrupt + break; + case CYGNUM_HAL_INTERRUPT_FIXED_TIMER: + CYGARC_MTSPR(SPR_TSR, TSR_FIS); // clear & acknowledge interrupt + break; + case CYGNUM_HAL_INTERRUPT_WATCHDOG_TIMER: + CYGARC_MTSPR(SPR_TSR, TSR_WIS); // clear & acknowledge interrupt + break; + case CYGNUM_HAL_INTERRUPT_CRITICAL: + case CYGNUM_HAL_INTERRUPT_SERIAL_RCV: + case CYGNUM_HAL_INTERRUPT_SERIAL_XMT: + case CYGNUM_HAL_INTERRUPT_JTAG_RCV: + case CYGNUM_HAL_INTERRUPT_JTAG_XMT: + case CYGNUM_HAL_INTERRUPT_DMA0: + case CYGNUM_HAL_INTERRUPT_DMA1: + case CYGNUM_HAL_INTERRUPT_DMA2: + case CYGNUM_HAL_INTERRUPT_DMA3: + default: + } +} + +// Note: These functions are only [well] defined for "external" interrupts +// which can be controlled via the EXIER register. +externC void +hal_ppc40x_interrupt_configure(int vector, int level, int dir) +{ + cyg_uint32 mask, new_state, iocr; + + if ((vector >= CYGNUM_HAL_INTERRUPT_EXT0) && + (vector <= CYGNUM_HAL_INTERRUPT_EXT4)) { + mask = 0x03 << (30 - ((vector - CYGNUM_HAL_INTERRUPT_EXT0)*2)); + new_state = 0x00; + if (level == 0) { + // Edge triggered + new_state = 0x02 | (dir & 0x01); // Up/Down + } + new_state <<= (30 - ((vector - CYGNUM_HAL_INTERRUPT_EXT0)*2)); + CYGARC_MFDCR(DCR_IOCR, iocr); + iocr = (iocr & ~mask) | new_state; + CYGARC_MTDCR(DCR_IOCR, iocr); + } +} + +externC void +hal_ppc40x_interrupt_set_level(int vector, int level) +{ } // -------------------------------------------------------------------------
