externC void hal_ppc40x_delay_us(int us) { cyg_uint32 delay_period, delay, diff; cyg_uint32 pit_val1, pit_val2; delay_period = (_period * us) / 10000; delay_period = ((_period / 10000) * us); delay = 0; CYGARC_MFSPR(SPR_PIT, pit_val1); while (delay < delay_period) { // Wait for clock to "tick" while (true) { CYGARC_MFSPR(SPR_PIT, pit_val2); if (pit_val1 != pit_val2) break; } // The counter ticks down if (pit_val2 < pit_val1) { diff = pit_val1 - pit_val2; } else { diff = (_period - pit_val2) + pit_val1; } delay += diff; pit_val1 = pit_val2; } }
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; } }
// Returns the number of clocks since the last interrupt externC void hal_ppc40x_clock_read(cyg_uint32 *val) { cyg_uint32 cur_val; CYGARC_MFSPR(SPR_PIT, cur_val); *val = _period - cur_val; }
//-------------------------------------------------------------------------- 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; } }
//-------------------------------------------------------------------------- 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 }
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); }
// // Initialize the interface - performed at system startup // This function must set up the interface, including arranging to // handle interrupts, etc, so that it may be "started" cheaply later. // static bool fec_eth_init(struct cyg_netdevtab_entry *tab) { struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance; struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private; volatile EPPC *eppc = (volatile EPPC *)eppc_base(); volatile struct fec *fec = (volatile struct fec *)((unsigned char *)eppc + FEC_OFFSET); unsigned short phy_state = 0; int cache_state; int i; unsigned long proc_rev; bool esa_ok, phy_ok; int phy_timeout = 5*1000; // Wait 5 seconds max for link to clear // Ensure consistent state between cache and what the FEC sees HAL_DCACHE_IS_ENABLED(cache_state); HAL_DCACHE_SYNC(); HAL_DCACHE_DISABLE(); qi->fec = fec; fec_eth_stop(sc); // Make sure it's not running yet #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED #ifdef _FEC_USE_INTS // Set up to handle interrupts cyg_drv_interrupt_create(FEC_ETH_INT, CYGARC_SIU_PRIORITY_HIGH, (cyg_addrword_t)sc, // Data item passed to interrupt handler (cyg_ISR_t *)fec_eth_isr, (cyg_DSR_t *)eth_drv_dsr, &fec_eth_interrupt_handle, &fec_eth_interrupt); cyg_drv_interrupt_attach(fec_eth_interrupt_handle); cyg_drv_interrupt_acknowledge(FEC_ETH_INT); cyg_drv_interrupt_unmask(FEC_ETH_INT); #else // _FEC_USE_INTS // Hack - use a thread to simulate interrupts cyg_thread_create(1, // Priority fec_fake_int, // entry (cyg_addrword_t)sc, // entry parameter "CS8900 int", // Name &fec_fake_int_stack[0], // Stack STACK_SIZE, // Size &fec_fake_int_thread_handle, // Handle &fec_fake_int_thread_data // Thread data structure ); cyg_thread_resume(fec_fake_int_thread_handle); // Start it #endif #endif // Set up parallel port for connection to ethernet tranceiver eppc->pio_pdpar = 0x1FFF; CYGARC_MFSPR( CYGARC_REG_PVR, proc_rev ); #define PROC_REVB 0x0020 if ((proc_rev & 0x0000FFFF) == PROC_REVB) { eppc->pio_pddir = 0x1C58; } else { eppc->pio_pddir = 0x1FFF; } // Get physical device address #ifdef CYGPKG_REDBOOT esa_ok = flash_get_config("fec_esa", enaddr, CONFIG_ESA); #else esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET, "fec_esa", enaddr, CONFIG_ESA); #endif if (!esa_ok) { // Can't figure out ESA os_printf("FEC_ETH - Warning! ESA unknown\n"); memcpy(&enaddr, &_default_enaddr, sizeof(enaddr)); } // Configure the device if (!fec_eth_reset(sc, enaddr, 0)) { return false; } // Reset PHY (transceiver) eppc->pip_pbdat &= ~0x00004000; // Reset PHY chip CYGACC_CALL_IF_DELAY_US(10000); // 10ms eppc->pip_pbdat |= 0x00004000; // Enable PHY chip // Enable transceiver (PHY) phy_ok = 0; phy_write(PHY_BMCR, 0, PHY_BMCR_RESET); for (i = 0; i < 10; i++) { phy_ok = phy_read(PHY_BMCR, 0, &phy_state); if (!phy_ok) break; if (!(phy_state & PHY_BMCR_RESET)) break; } if (!phy_ok || (phy_state & PHY_BMCR_RESET)) { os_printf("FEC: Can't get PHY unit to reset: %x\n", phy_state); return false; } fec->iEvent = 0xFFFFFFFF; // Clear all interrupts phy_write(PHY_BMCR, 0, PHY_BMCR_AUTO_NEG|PHY_BMCR_RESTART); while (phy_timeout-- >= 0) { int ev = fec->iEvent; unsigned short state; fec->iEvent = ev; if (ev & iEvent_MII) { phy_ok = phy_read(PHY_BMSR, 0, &state); if (phy_ok && (state & PHY_BMSR_AUTO_NEG)) { // os_printf("State: %x\n", state); break; } else { CYGACC_CALL_IF_DELAY_US(1000); // 1ms } } } if (phy_timeout <= 0) { os_printf("** FEC Warning: PHY auto-negotiation failed\n"); } // Initialize upper level driver (sc->funs->eth_drv->init)(sc, (unsigned char *)&enaddr); return true; }