#include #include #include #include #include #include #include #include #include #include #include #define ETH_MAC_LOCAL_CONFIG 0x1560 #define ETH_MAC_4321 0x1564 #define ETH_MAC_65 0x1568 #define MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT 16 #define MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK (0xf<priv; int xcno = priv->xcno; unsigned int val; int timeout = 500; unsigned char *dst = (unsigned char *)(SRAM_BASE(xcno) + 1560); memcpy(dst, (void *)packet, length); if( length < 60 ) { memset(dst + length, 0, 60 - length); length = 60; } PFIFO_REG(PFIFO_BASE(REQ_FIFO_PORT_LO(xcno))) = FIFO_PTR_SEGMENT(xcno) | FIFO_PTR_FRAMENO(1) | FIFO_PTR_FRAMELEN(length); while (!PFIFO_REG( PFIFO_FILL_LEVEL(CON_FIFO_PORT_LO(xcno))) && timeout) { timeout--; udelay(100); } #if 0 if (!timeout) { loadxc(0); loadxc(1); eth_init(gd->bd); return -1; } #endif val = PFIFO_REG( PFIFO_BASE(CON_FIFO_PORT_LO(xcno)) ); if((val & FIFO_PTR_ERROR_MASK) & 0x8) printf("error sending frame: %u\n", val); return 0; } static int netx_eth_rx (struct eth_device *edev) { struct netx_eth_priv *priv = (struct netx_eth_priv *)edev->priv; int xcno = priv->xcno; unsigned int val, frameno, seg, len; if(!PFIFO_REG( PFIFO_FILL_LEVEL(IND_FIFO_PORT_LO(xcno)))) { return 0; } val = PFIFO_REG( PFIFO_BASE(IND_FIFO_PORT_LO(xcno)) ); frameno = (val & FIFO_PTR_FRAMENO_MASK) >> FIFO_PTR_FRAMENO_SHIFT; seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT; len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT; /* get data */ memcpy((void*)NetRxPackets[0], (void *)(SRAM_BASE(seg) + frameno * 1560), len); /* pass to barebox */ net_receive(edev, NetRxPackets[0], len); PFIFO_REG(PFIFO_BASE(EMPTY_PTR_FIFO(xcno))) = FIFO_PTR_SEGMENT(seg) | FIFO_PTR_FRAMENO(frameno); return 0; } static int netx_miibus_read(struct mii_bus *bus, int phy_addr, int reg) { int value; MIIMU_REG = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_addr) | MIIMU_REGADDR(reg) | MIIMU_PHY_NRES; while(MIIMU_REG & MIIMU_SNRDY); value = MIIMU_REG >> 16; debug("%s: addr: 0x%02x reg: 0x%02x val: 0x%04x\n", __func__, phy_addr, reg, value); return value; } static int netx_miibus_write(struct mii_bus *bus, int phy_addr, int reg, u16 val) { debug("%s: addr: 0x%02x reg: 0x%02x val: 0x%04x\n",__func__, phy_addr, reg, val); MIIMU_REG = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_addr) | MIIMU_REGADDR(reg) | MIIMU_PHY_NRES | MIIMU_OPMODE_WRITE | MIIMU_DATA(val); while(MIIMU_REG & MIIMU_SNRDY); return 0; } static int netx_eth_init_phy(void) { unsigned int phy_control; phy_control = PHY_CONTROL_PHY_ADDRESS(0xe) | PHY_CONTROL_PHY1_MODE(PHY_MODE_ALL) | PHY_CONTROL_PHY1_AUTOMDIX | PHY_CONTROL_PHY1_EN | PHY_CONTROL_PHY0_MODE(PHY_MODE_ALL) | PHY_CONTROL_PHY0_AUTOMDIX | PHY_CONTROL_PHY0_EN | PHY_CONTROL_CLK_XLATIN; /* enable asic control */ SYSTEM_REG(SYSTEM_IOC_ACCESS_KEY) = SYSTEM_REG(SYSTEM_IOC_ACCESS_KEY); SYSTEM_REG(SYSTEM_PHY_CONTROL) = phy_control | PHY_CONTROL_RESET; udelay(100); /* enable asic control */ SYSTEM_REG(SYSTEM_IOC_ACCESS_KEY) = SYSTEM_REG(SYSTEM_IOC_ACCESS_KEY); SYSTEM_REG(SYSTEM_PHY_CONTROL) = phy_control; return 0; } static int netx_eth_init_dev(struct eth_device *edev) { struct netx_eth_priv *priv = (struct netx_eth_priv *)edev->priv; int xcno = priv->xcno; int i; loadxc(xcno); /* Fill empty pointer fifo */ for (i = 2; i <= 18; i++) PFIFO_REG( PFIFO_BASE(EMPTY_PTR_FIFO(xcno)) ) = FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(xcno); return 0; } static int netx_eth_open(struct eth_device *edev) { struct netx_eth_priv *priv = (struct netx_eth_priv *)edev->priv; return phy_device_connect(edev, &priv->miibus, 0, NULL, 0, PHY_INTERFACE_MODE_NA); } static void netx_eth_halt (struct eth_device *edev) { } static int netx_eth_get_ethaddr(struct eth_device *edev, unsigned char *adr) { /* FIXME: get from crypto flash */ return -1; } static int netx_eth_set_ethaddr(struct eth_device *edev, const unsigned char *adr) { struct netx_eth_priv *priv = (struct netx_eth_priv *)edev->priv; int xcno = priv->xcno; debug("%s\n", __func__); /* set MAC address */ XMAC_REG(xcno, XMAC_RPU_HOLD_PC) = RPU_HOLD_PC; XMAC_REG(xcno, XMAC_TPU_HOLD_PC) = TPU_HOLD_PC; XPEC_REG(xcno, XPEC_XPU_HOLD_PC) = XPU_HOLD_PC; XPEC_REG(xcno, XPEC_RAM_START + ETH_MAC_4321) = adr[0] | adr[1]<<8 | adr[2]<<16 | adr[3]<<24; XPEC_REG(xcno, XPEC_RAM_START + ETH_MAC_65) = adr[4] | adr[5]<<8; XPEC_REG(xcno, XPEC_RAM_START + ETH_MAC_LOCAL_CONFIG) = MAC_TRAFFIC_CLASS_ARRANGEMENT(8); XMAC_REG(xcno, XMAC_RPU_HOLD_PC) = 0; XMAC_REG(xcno, XMAC_TPU_HOLD_PC) = 0; XPEC_REG(xcno, XPEC_XPU_HOLD_PC) = 0; #if 0 for (i = 0; i < 5; i++) printf ("%02x:", adr[i]); printf ("%02x\n", adr[5]); #endif return -0; } static int netx_eth_probe(struct device_d *dev) { struct eth_device *edev; struct netx_eth_priv *priv; struct netx_eth_platform_data *pdata; debug("netx_eth_probe()\n"); pdata = dev->platform_data; edev = xzalloc(sizeof(struct eth_device) + sizeof(struct netx_eth_priv)); edev->priv = (struct netx_priv *)(edev + 1); priv = edev->priv; priv->xcno = pdata->xcno; edev->init = netx_eth_init_dev; edev->open = netx_eth_open; edev->send = netx_eth_send; edev->recv = netx_eth_rx; edev->halt = netx_eth_halt; edev->get_ethaddr = netx_eth_get_ethaddr; edev->set_ethaddr = netx_eth_set_ethaddr; edev->parent = dev; priv->miibus.read = netx_miibus_read; priv->miibus.write = netx_miibus_write; priv->miibus.parent = dev; netx_eth_init_phy(); mdiobus_register(&priv->miibus); eth_register(edev); return 0; } static struct driver_d netx_eth_driver = { .name = "netx-eth", .probe = netx_eth_probe, }; device_platform_driver(netx_eth_driver);