/*============================================================================*
 *				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;
}
Пример #2
0
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;
}