/*============================================================================* * lan8710a_init_hw * *============================================================================*/ static int lan8710a_init_hw(netdriver_addr_t * addr, unsigned int instance) { int r, i; /* * Set the interrupt handler and policy. Do not automatically * re-enable interrupts. Return the IRQ line number on interrupts. */ lan8710a_state.irq_rx_hook = RX_INT; if ((r = sys_irqsetpolicy(LAN8710A_RX_INTR, 0, &lan8710a_state.irq_rx_hook)) != OK) { panic("sys_irqsetpolicy failed: %d", r); } lan8710a_state.irq_tx_hook = TX_INT; if ((r = sys_irqsetpolicy(LAN8710A_TX_INTR, 0, &lan8710a_state.irq_tx_hook)) != OK) { panic("sys_irqsetpolicy failed: %d", r); } /* Reset hardware. */ lan8710a_reset_hw(); /* * Select the Interface (GMII/RGMII/MII) Mode in the Control Module. * Port1 GMII/MII Mode, Port2 not used. */ lan8710a_reg_write(GMII_SEL, (GMII2_SEL_BIT1 | GMII2_SEL_BIT0)); /* * Configure pads (PIN muxing) as per the Interface Selected using the * appropriate pin muxing conf_xxx registers in the Control Module. * * CONF_MOD_SLEW_CTRL when 0 - Fast Mode, when 1 - Slow Mode * CONF_MOD_RX_ACTIVE when 0 - Only output, when 1 - Also input * CONF_MOD_PU_TYPESEL when 0 - Pull-down, when 1 - Pull-up * CONF_MOD_PUDEN when 0 Pull* enabled, when 1 Pull* disabled * CONF_MOD_MMODE_MII selects pin to work for MII interface */ lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_SLEW_CTRL); lan8710a_reg_set(CONF_MII1_COL, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_COL, CONF_MOD_PU_TYPESEL); lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_SLEW_CTRL); lan8710a_reg_set(CONF_MII1_CRS, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_CRS, CONF_MOD_PU_TYPESEL); lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_SLEW_CTRL); lan8710a_reg_set(CONF_MII1_RX_ER, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_RX_ER, CONF_MOD_PU_TYPESEL); lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_SLEW_CTRL); lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_TX_EN, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_SLEW_CTRL); lan8710a_reg_set(CONF_MII1_RX_DV, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_RX_DV, CONF_MOD_PU_TYPESEL); lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_SLEW_CTRL); lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_TXD3, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_SLEW_CTRL); lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_TXD2, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_SLEW_CTRL); lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_TXD1, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_SLEW_CTRL); lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_TXD0, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_TX_CLK, CONF_MOD_SLEW_CTRL); lan8710a_reg_set(CONF_MII1_TX_CLK, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_TX_CLK, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_TX_CLK, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_RX_CLK, CONF_MOD_SLEW_CTRL); lan8710a_reg_set(CONF_MII1_RX_CLK, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_RX_CLK, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_RX_CLK, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_SLEW_CTRL); lan8710a_reg_set(CONF_MII1_RXD3, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_RXD3, CONF_MOD_PU_TYPESEL); lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_SLEW_CTRL); lan8710a_reg_set(CONF_MII1_RXD2, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_RXD2, CONF_MOD_PU_TYPESEL); lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_SLEW_CTRL); lan8710a_reg_set(CONF_MII1_RXD1, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_RXD1, CONF_MOD_PU_TYPESEL); lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_SLEW_CTRL); lan8710a_reg_set(CONF_MII1_RXD0, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MII1_RXD0, CONF_MOD_PU_TYPESEL); lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MDIO, CONF_MOD_SLEW_CTRL); lan8710a_reg_set(CONF_MDIO, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MDIO, CONF_MOD_PU_TYPESEL); lan8710a_reg_unset(CONF_MDIO, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MDIO, CONF_MOD_MMODE_MII); lan8710a_reg_unset(CONF_MDC, CONF_MOD_SLEW_CTRL); lan8710a_reg_unset(CONF_MDC, CONF_MOD_RX_ACTIVE); lan8710a_reg_set(CONF_MDC, CONF_MOD_PUDEN); lan8710a_reg_unset(CONF_MDC, CONF_MOD_MMODE_MII); /* Apply soft reset to 3PSW Subsytem, CPSW_3G, CPGMAC_SL, and CPDMA. */ lan8710a_reg_write(CPSW_SS_SOFT_RESET, SOFT_RESET); lan8710a_reg_write(CPSW_SL_SOFT_RESET(1), SOFT_RESET); lan8710a_reg_write(CPSW_SL_SOFT_RESET(2), SOFT_RESET); /* Wait for software resets completion */ while ((lan8710a_reg_read(CPSW_SS_SOFT_RESET) & SOFT_RESET) || (lan8710a_reg_read(CPSW_SL_SOFT_RESET(1)) & SOFT_RESET) || (lan8710a_reg_read(CPSW_SL_SOFT_RESET(2)) & SOFT_RESET)); /* Configure the Statistics Port Enable register. */ /* Enable port 0 and 1 statistics. */ lan8710a_reg_write(CPSW_SS_STAT_PORT_EN, (CPSW_P1_STAT_EN | CPSW_P0_STAT_EN)); /* * Configure the ALE. * Enabling Ale. * All packets received on ports 1 are * sent to the host (only to the host). */ lan8710a_reg_write(CPSW_ALE_CONTROL, (CPSW_ALE_ENABLE | CPSW_ALE_BYPASS)); /* Port 0 (host) in forwarding mode. */ lan8710a_reg_write(CPSW_ALE_PORTCTL0, CPSW_ALE_PORT_FWD); /* Port 1 in forwarding mode. */ lan8710a_reg_write(CPSW_ALE_PORTCTL1, CPSW_ALE_PORT_FWD); /* * Configure CPSW_SL Register * Full duplex mode. */ lan8710a_reg_write(CPSW_SL_MACCONTROL(1), CPSW_SL_FULLDUPLEX); /* Initialize MDIO Protocol */ lan8710a_init_mdio(); /* Getting MAC Address */ lan8710a_init_addr(addr, instance); /* Initialize descriptors */ lan8710a_init_desc(); /* Reset and initialize CPDMA */ lan8710a_dma_reset_init(); /* * Configure the Interrupts. * Routing all channel Rx int to RX_PULSE signal. */ lan8710a_reg_set(CPSW_WR_C0_RX_EN, CPSW_FIRST_CHAN_INT); /* * Enabling LAN8710A Auto-negotiation */ lan8710a_phy_write(LAN8710A_CTRL_REG, LAN8710A_AUTO_NEG); /* Waiting for auto-negotiaion completion. */ for (i = 0; !(lan8710a_phy_read(LAN8710A_STATUS_REG) & LAN8710A_AUTO_NEG_COMPL); ++i) { if (i == 100) { LAN8710A_DEBUG_PRINT(("Autonegotiation failed")); break; } micro_delay(1666666); } /* GMII RX and TX release from reset. */ lan8710a_reg_set(CPSW_SL_MACCONTROL(1), CPSW_SL_GMII_EN); /* Enable interrupts. */ lan8710a_enable_interrupt(RX_INT | TX_INT); return TRUE; }
int cpsw_init(struct ifnet *ifp) { struct cpsw_softc * const sc = ifp->if_softc; struct arpcom *ac = &sc->sc_ac; struct mii_data * const mii = &sc->sc_mii; int i; cpsw_stop(ifp); sc->sc_txnext = 0; sc->sc_txhead = 0; /* Reset wrapper */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_SOFT_RESET, 1); while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_SOFT_RESET) & 1); /* Reset SS */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_SOFT_RESET, 1); while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_SOFT_RESET) & 1); /* Clear table (30) and enable ALE(31) and set passthrough (4) */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_ALE_CONTROL, (3 << 30) | 0x10); /* Reset and init Sliver port 1 and 2 */ for (i = 0; i < 2; i++) { /* Reset */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_SOFT_RESET(i), 1); while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_SOFT_RESET(i)) & 1); /* Set Slave Mapping */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_RX_PRI_MAP(i), 0x76543210); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P_TX_PRI_MAP(i+1), 0x33221100); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_RX_MAXLEN(i), 0x5f2); /* Set MAC Address */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P_SA_HI(i+1), ac->ac_enaddr[0] | (ac->ac_enaddr[1] << 8) | (ac->ac_enaddr[2] << 16) | (ac->ac_enaddr[3] << 24)); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P_SA_LO(i+1), ac->ac_enaddr[4] | (ac->ac_enaddr[5] << 8)); /* Set MACCONTROL for ports 0,1: FULLDUPLEX(1), GMII_EN(5), IFCTL_A(15), IFCTL_B(16) FIXME */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_MACCONTROL(i), 1 | (1<<5) | (1<<15) | (1<<16)); /* Set ALE port to forwarding(3) */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_ALE_PORTCTL(i+1), 3); } /* Set Host Port Mapping */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P0_CPDMA_TX_PRI_MAP, 0x76543210); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P0_CPDMA_RX_CH_MAP, 0); /* Set ALE port to forwarding(3) */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_ALE_PORTCTL(0), 3); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_PTYPE, 0); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_STAT_PORT_EN, 7); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_SOFT_RESET, 1); while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_SOFT_RESET) & 1); for (i = 0; i < 8; i++) { bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_HDP(i), 0); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_HDP(i), 0); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CP(i), 0); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_CP(i), 0); } bus_space_set_region_4(sc->sc_bst, sc->sc_bsh_txdescs, 0, 0, CPSW_CPPI_RAM_TXDESCS_SIZE/4); sc->sc_txhead = 0; sc->sc_txnext = 0; bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_FREEBUFFER(0), 0); bus_space_set_region_4(sc->sc_bst, sc->sc_bsh_rxdescs, 0, 0, CPSW_CPPI_RAM_RXDESCS_SIZE/4); /* Initialize RX Buffer Descriptors */ cpsw_set_rxdesc_next(sc, RXDESC_PREV(0), 0); for (i = 0; i < CPSW_NRXDESCS; i++) { cpsw_new_rxbuf(sc, i); } sc->sc_rxhead = 0; /* align layer 3 header to 32-bit */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_BUFFER_OFFSET, ETHER_ALIGN); /* Clear all interrupt Masks */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF); /* Enable TX & RX DMA */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CONTROL, 1); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_CONTROL, 1); /* Enable TX and RX interrupt receive for core 0 */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_TX_EN(0), 1); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_RX_EN(0), 1); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_MISC_EN(0), 0x1F); /* Enable host Error Interrupt */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_DMA_INTMASK_SET, 2); /* Enable interrupts for TX and RX Channel 0 */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_INTMASK_SET, 1); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_INTMASK_SET, 1); /* Ack stalled irqs */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_RXTH); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_RX); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_TX); bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_MISC); /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */ /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, MDIOCONTROL, (1<<30) | (1<<18) | 0xFF); mii_mediachg(mii); /* Write channel 0 RX HDP */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_HDP(0), cpsw_rxdesc_paddr(sc, 0)); sc->sc_rxrun = true; sc->sc_rxeoq = false; sc->sc_txrun = true; sc->sc_txeoq = true; ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; timeout_add_sec(&sc->sc_tick, 1); return 0; }