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: break; } }
int cyg_hal_map_memory (int id,CYG_ADDRESS virt, CYG_ADDRESS phys, cyg_int32 size, cyg_uint8 flags) { cyg_uint32 epn, rpn, twc, ctr = 0; epn = (virt & MI_EPN_EPNMASK) | MI_EPN_EV; rpn = ((phys & MI_RPN_RPNMASK) | MI_RPN_PPRWRW | MI_RPN_LPS | MI_RPN_SH | MI_RPN_V); if (flags & CYGARC_MEMDESC_CI) rpn |= MI_RPN_CI; twc = MI_TWC_PS8MB | MI_TWC_V; if (flags & CYGARC_MEMDESC_GUARDED) twc |= MI_TWC_G; // Ignore attempts to use more than max_tlbs. while (id < NUM_TLBS && size > 0) { ctr = id << MI_CTR_INDX_SHIFT; // Instruction TLB. CYGARC_MTSPR (MI_TWC, twc); CYGARC_MTSPR (MI_CTR, ctr); CYGARC_MTSPR (MI_EPN, epn); CYGARC_MTSPR (MI_RPN, rpn); // Data TLB. { cyg_uint32 drpn; // Need to mark data page as changed or an exception // will be generated on first write to the page. drpn = rpn | MD_RPN_CHANGED; CYGARC_MTSPR (MD_TWC, twc); CYGARC_MTSPR (MD_CTR, ctr); CYGARC_MTSPR (MD_EPN, epn); CYGARC_MTSPR (MD_RPN, drpn); } // Move to next 8MB block. size -= 8*1024*1024; epn += 8*1024*1024; rpn += 8*1024*1024; id++; } // Make caches default disabled when MMU is disabled. CYGARC_MTSPR (MI_CTR, ctr | CYGARC_REG_MI_CTR_CIDEF); CYGARC_MTSPR (MD_CTR, ctr | CYGARC_REG_MD_CTR_CIDEF); return id; }
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: break; } }
void hal_ppc40x_clock_initialize(cyg_uint32 period) { cyg_uint32 tcr; // Enable auto-reload CYGARC_MFSPR(SPR_TCR, tcr); tcr = _hold_tcr; tcr |= TCR_ARE; CYGARC_MTSPR(SPR_TCR, tcr); _hold_tcr = tcr; // Set up the counter register _period = period; CYGARC_MTSPR(SPR_PIT, period); }
//-------------------------------------------------------------------------- void hal_variant_init(void) { // Disable serialization { cyg_uint32 ictrl; CYGARC_MFSPR (ICTRL, ictrl); ictrl |= ICTRL_NOSERSHOW; CYGARC_MTSPR (ICTRL, ictrl); } }
externC void hal_ppc40x_interrupt_unmask(int vector) { cyg_uint32 exier, tcr; switch (vector) { case CYGNUM_HAL_INTERRUPT_first...CYGNUM_HAL_INTERRUPT_last: #ifndef HAL_PLF_INTERRUPT_UNMASK CYGARC_MFDCR(DCR_UIC0_ER, exier); exier |= (1<<(31-(vector-CYGNUM_HAL_INTERRUPT_405_BASE))); CYGARC_MTDCR(DCR_UIC0_ER, exier); #else HAL_PLF_INTERRUPT_UNMASK(vector); #endif 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: break; } }
externC void hal_ppc40x_interrupt_acknowledge(int vector) { switch (vector) { case CYGNUM_HAL_INTERRUPT_first...CYGNUM_HAL_INTERRUPT_last: #ifndef HAL_PLF_INTERRUPT_ACKNOWLEDGE CYGARC_MTDCR(DCR_UIC0_SR, (1<<(31-(vector-CYGNUM_HAL_INTERRUPT_405_BASE)))); #else HAL_PLF_INTERRUPT_ACKNOWLEDGE(vector); #endif 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; default: break; } }
//-------------------------------------------------------------------------- void hal_variant_init(void) { // Disable serialization { cyg_uint32 ictrl; CYGARC_MFSPR (ICTRL, ictrl); ictrl |= ICTRL_NOSERSHOW; CYGARC_MTSPR (ICTRL, ictrl); } #ifndef CYGSEM_HAL_USE_ROM_MONITOR // Reset CPM _mpc8xx_reset_cpm(); #endif }
// Initialize MMU to a sane (NOP) state. // // Initialize TLBs with 0, Valid bits unset. void cyg_hal_clear_MMU (void) { cyg_uint32 tlbhi = 0; cyg_uint32 tlblo = 0; int id, max_tlbs; // There are 64 TLBs. max_tlbs = 64; CYGARC_MTSPR (SPR_PID, 0); for (id = 0; id < max_tlbs; id++) { CYGARC_TLBWE(id, tlbhi, tlblo); } }
externC void hal_variant_IRQ_init(void) { 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); // Let the platform do any overrides hal_platform_IRQ_init(); }
externC void hal_variant_IRQ_init(void) { #ifndef HAL_PLF_INTERRUPT_INIT // Ensure all interrupts masked (disabled) & cleared CYGARC_MTDCR(DCR_UIC0_ER, 0); CYGARC_MTDCR(DCR_UIC0_CR, 0); CYGARC_MTDCR(DCR_UIC0_PR, 0xFFFFE000); CYGARC_MTDCR(DCR_UIC0_TR, 0); CYGARC_MTDCR(DCR_UIC0_VCR, 0); // Makes vector identification easy CYGARC_MTDCR(DCR_UIC0_SR, 0xFFFFFFFF); #else HAL_PLF_INTERRUPT_INIT(); #endif // Disable timers CYGARC_MTSPR(SPR_TCR, 0); // Let the platform do any overrides hal_platform_IRQ_init(); }
// Initialize MMU to a sane (NOP) state. // // Initialize TLBs with 0, Valid bits unset. void cyg_hal_clear_MMU (void) { cyg_uint32 ctr = 0; int id; CYGARC_MTSPR (M_CASID, 0); for (id = 0; id < NUM_TLBS; id++) { ctr = id << MI_CTR_INDX_SHIFT; // Instruction TLBs. CYGARC_MTSPR (MI_TWC, 0); CYGARC_MTSPR (MI_CTR, ctr); CYGARC_MTSPR (MI_EPN, 0); CYGARC_MTSPR (MI_RPN, 0); // Data TLBs. CYGARC_MTSPR (MD_TWC, 0); CYGARC_MTSPR (MD_CTR, ctr); CYGARC_MTSPR (MD_EPN, 0); CYGARC_MTSPR (MD_RPN, 0); } // Make caches default disabled when MMU is disabled. CYGARC_MTSPR (MI_CTR, ctr | CYGARC_REG_MI_CTR_CIDEF); CYGARC_MTSPR (MD_CTR, ctr | CYGARC_REG_MD_CTR_CIDEF); }
// Initialize MMU to a sane (NOP) state. // // Initialize TLBs with 0, Valid bits unset. void cyg_hal_clear_MMU (void) { cyg_uint32 ctr = 0; int id; int max_tlbs; #if defined(CYGPKG_HAL_POWERPC_MPC860) // There are 32 TLBs. max_tlbs = 32; #elif defined(CYGPKG_HAL_POWERPC_MPC823) || defined(CYGPKG_HAL_POWERPC_MPC850) // There are 8 TLBs. max_tlbs = 8; #endif CYGARC_MTSPR (M_CASID, 0); for (id = 0; id < max_tlbs; id++) { ctr = id << MI_CTR_INDX_SHIFT; // Instruction TLBs. CYGARC_MTSPR (MI_TWC, 0); CYGARC_MTSPR (MI_CTR, ctr); CYGARC_MTSPR (MI_EPN, 0); CYGARC_MTSPR (MI_RPN, 0); // Data TLBs. CYGARC_MTSPR (MD_TWC, 0); CYGARC_MTSPR (MD_CTR, ctr); CYGARC_MTSPR (MD_EPN, 0); CYGARC_MTSPR (MD_RPN, 0); } // Make caches default disabled when MMU is disabled. CYGARC_MTSPR (MI_CTR, ctr | CYGARC_REG_MI_CTR_CIDEF); CYGARC_MTSPR (MD_CTR, ctr | CYGARC_REG_MD_CTR_CIDEF); }
//---------------------------------------------------------------------------- // Reset. void _virtex4_reset(void) { CYGARC_MTSPR(SPR_DBCR0, 0x30000000); // Asserts system reset while (1) ; }
//--------------------------------------------------------------------------- // Use MMU resources to map memory regions. // Takes and returns an int used to ID the MMU resource to use. This ID // is increased as resources are used and should be used for subsequent // invocations. int cyg_hal_map_memory (int id,CYG_ADDRESS virt, CYG_ADDRESS phys, cyg_int32 size, cyg_uint8 flags) { // Use BATs to map the memory. cyg_uint32 ubat, lbat; ubat = (virt & UBAT_BEPIMASK) | UBAT_VS | UBAT_VP; lbat = (phys & LBAT_BRPNMASK); if (flags & CYGARC_MEMDESC_CI) lbat |= LBAT_I; if (flags & CYGARC_MEMDESC_GUARDED) lbat |= LBAT_G; #define IWASPATRICK #ifdef IWASPATRICK lbat |= LBAT_PP_RW; // Always enable for Read-Write #else if (flags & CYGARC_MEMDESC_RO) // Memory is Read Only lbat |= LBAT_PP_RO; if (flags & CYGARC_MEMDESC_RW) // Memory is RW lbat |= LBAT_PP_RW; #endif // There are 4 BATs, size is programmable. while (id < 4 && size > 0) { cyg_uint32 blk_size = 128*1024; cyg_uint32 bl = 0; while (blk_size < 256*1024*1024 && blk_size < size) { blk_size *= 2; bl = (bl << 1) | 1; } ubat = (ubat & ~UBAT_BLMASK) | (bl << 2); switch (id) { case 0: CYGARC_MTSPR (IBAT0U, ubat); CYGARC_MTSPR (IBAT0L, lbat); CYGARC_MTSPR (DBAT0U, ubat); CYGARC_MTSPR (DBAT0L, lbat); break; case 1: CYGARC_MTSPR (IBAT1U, ubat); CYGARC_MTSPR (IBAT1L, lbat); CYGARC_MTSPR (DBAT1U, ubat); CYGARC_MTSPR (DBAT1L, lbat); break; case 2: CYGARC_MTSPR (IBAT2U, ubat); CYGARC_MTSPR (IBAT2L, lbat); CYGARC_MTSPR (DBAT2U, ubat); CYGARC_MTSPR (DBAT2L, lbat); break; case 3: CYGARC_MTSPR (IBAT3U, ubat); CYGARC_MTSPR (IBAT3L, lbat); CYGARC_MTSPR (DBAT3U, ubat); CYGARC_MTSPR (DBAT3L, lbat); break; } size -= blk_size; id++; } return id; }
// Initialize MMU to a sane (NOP) state. void cyg_hal_clear_MMU (void) { cyg_uint32 ubat, lbat; // Initialize BATs with 0 -- VS&VP are unset, making all matches fail ubat = 0; lbat = 0; CYGARC_MTSPR (IBAT0U, ubat); CYGARC_MTSPR (IBAT0L, lbat); CYGARC_MTSPR (DBAT0U, ubat); CYGARC_MTSPR (DBAT0L, lbat); CYGARC_MTSPR (IBAT1U, ubat); CYGARC_MTSPR (IBAT1L, lbat); CYGARC_MTSPR (DBAT1U, ubat); CYGARC_MTSPR (DBAT1L, lbat); CYGARC_MTSPR (IBAT2U, ubat); CYGARC_MTSPR (IBAT2L, lbat); CYGARC_MTSPR (DBAT2U, ubat); CYGARC_MTSPR (DBAT2L, lbat); CYGARC_MTSPR (IBAT3U, ubat); CYGARC_MTSPR (IBAT3L, lbat); CYGARC_MTSPR (DBAT3U, ubat); CYGARC_MTSPR (DBAT3L, lbat); }