static int macb_recv(struct eth_device *netdev) { struct macb_device *macb = to_macb(netdev); unsigned int rx_tail = macb->rx_tail; void *buffer; int length; int wrapped = 0; u32 status; for (;;) { macb_invalidate_ring_desc(macb, RX); if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED)) return -1; status = macb->rx_ring[rx_tail].ctrl; if (status & RXBUF_FRAME_START) { if (rx_tail != macb->rx_tail) reclaim_rx_buffers(macb, rx_tail); wrapped = 0; } if (status & RXBUF_FRAME_END) { buffer = macb->rx_buffer + 128 * macb->rx_tail; length = status & RXBUF_FRMLEN_MASK; macb_invalidate_rx_buffer(macb); if (wrapped) { unsigned int headlen, taillen; headlen = 128 * (MACB_RX_RING_SIZE - macb->rx_tail); taillen = length - headlen; memcpy((void *)NetRxPackets[0], buffer, headlen); memcpy((void *)NetRxPackets[0] + headlen, macb->rx_buffer, taillen); buffer = (void *)NetRxPackets[0]; } NetReceive(buffer, length); if (++rx_tail >= MACB_RX_RING_SIZE) rx_tail = 0; reclaim_rx_buffers(macb, rx_tail); } else { if (++rx_tail >= MACB_RX_RING_SIZE) { wrapped = 1; rx_tail = 0; } } barrier(); } return 0; }
static int macb_send(struct eth_device *netdev, void *packet, int length) { struct macb_device *macb = to_macb(netdev); unsigned long paddr, ctrl; unsigned int tx_head = macb->tx_head; int i; paddr = dma_map_single(packet, length, DMA_TO_DEVICE); ctrl = length & TXBUF_FRMLEN_MASK; ctrl |= TXBUF_FRAME_END; if (tx_head == (MACB_TX_RING_SIZE - 1)) { ctrl |= TXBUF_WRAP; macb->tx_head = 0; } else { macb->tx_head++; } macb->tx_ring[tx_head].ctrl = ctrl; macb->tx_ring[tx_head].addr = paddr; barrier(); macb_flush_ring_desc(macb, TX); /* Do we need check paddr and length is dcache line aligned? */ flush_dcache_range(paddr, paddr + length); macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART)); /* * I guess this is necessary because the networking core may * re-use the transmit buffer as soon as we return... */ for (i = 0; i <= MACB_TX_TIMEOUT; i++) { barrier(); macb_invalidate_ring_desc(macb, TX); ctrl = macb->tx_ring[tx_head].ctrl; if (ctrl & TXBUF_USED) break; udelay(1); } dma_unmap_single(packet, length, paddr); if (i <= MACB_TX_TIMEOUT) { if (ctrl & TXBUF_UNDERRUN) printf("%s: TX underrun\n", netdev->name); if (ctrl & TXBUF_EXHAUSTED) printf("%s: TX buffers exhausted in mid frame\n", netdev->name); } else { printf("%s: TX timeout\n", netdev->name); } /* No one cares anyway */ return 0; }
int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value) { struct eth_device *dev = eth_get_dev_by_name(devname); struct macb_device *macb = to_macb(dev); if ( macb->phy_addr != phy_adr ) return -1; macb_mdio_write(macb, reg, value); return 0; }
int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value) { struct eth_device *dev = eth_get_dev_by_name(devname); struct macb_device *macb = to_macb(dev); if ( macb->phy_addr != phy_adr ) return -1; arch_get_mdio_control(devname); *value = macb_mdio_read(macb, reg); return 0; }
static int macb_write_hwaddr(struct eth_device *dev) { struct macb_device *macb = to_macb(dev); u32 hwaddr_bottom; u16 hwaddr_top; /* set hardware address */ hwaddr_bottom = dev->enetaddr[0] | dev->enetaddr[1] << 8 | dev->enetaddr[2] << 16 | dev->enetaddr[3] << 24; macb_writel(macb, SA1B, hwaddr_bottom); hwaddr_top = dev->enetaddr[4] | dev->enetaddr[5] << 8; macb_writel(macb, SA1T, hwaddr_top); return 0; }
static void macb_halt(struct eth_device *netdev) { struct macb_device *macb = to_macb(netdev); u32 ncr, tsr; /* Halt the controller and wait for any ongoing transmission to end. */ ncr = macb_readl(macb, NCR); ncr |= MACB_BIT(THALT); macb_writel(macb, NCR, ncr); do { tsr = macb_readl(macb, TSR); } while (tsr & MACB_BIT(TGO)); /* Disable TX and RX, and clear statistics */ macb_writel(macb, NCR, MACB_BIT(CLRSTAT)); }
static int macb_recv(struct eth_device *netdev) { struct macb_device *macb = to_macb(netdev); uchar *packet; int length; macb->wrapped = false; for (;;) { macb->next_rx_tail = macb->rx_tail; length = _macb_recv(macb, &packet); if (length >= 0) { net_process_received_packet(packet, length); reclaim_rx_buffers(macb, macb->next_rx_tail); } else if (length < 0) { return length; } } }
int macb_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg, u16 value) { #ifdef CONFIG_DM_ETH struct udevice *dev = eth_get_dev_by_name(bus->name); struct macb_device *macb = dev_get_priv(dev); #else struct eth_device *dev = eth_get_dev_by_name(bus->name); struct macb_device *macb = to_macb(dev); #endif if (macb->phy_addr != phy_adr) return -1; arch_get_mdio_control(bus->name); macb_mdio_write(macb, reg, value); return 0; }
int macb_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg) { u16 value = 0; #ifdef CONFIG_DM_ETH struct udevice *dev = eth_get_dev_by_name(bus->name); struct macb_device *macb = dev_get_priv(dev); #else struct eth_device *dev = eth_get_dev_by_name(bus->name); struct macb_device *macb = to_macb(dev); #endif if (macb->phy_addr != phy_adr) return -1; arch_get_mdio_control(bus->name); value = macb_mdio_read(macb, reg); return value; }
static int macb_write_hwaddr(struct eth_device *netdev) { struct macb_device *macb = to_macb(netdev); return _macb_write_hwaddr(macb, netdev->enetaddr); }
static void macb_halt(struct eth_device *netdev) { struct macb_device *macb = to_macb(netdev); return _macb_halt(macb); }
static int macb_init(struct eth_device *netdev, bd_t *bd) { struct macb_device *macb = to_macb(netdev); return _macb_init(macb, netdev->name); }
static int macb_send(struct eth_device *netdev, void *packet, int length) { struct macb_device *macb = to_macb(netdev); return _macb_send(macb, netdev->name, packet, length); }
static int macb_init(struct eth_device *netdev, bd_t *bd) { struct macb_device *macb = to_macb(netdev); unsigned long paddr; int i; /* * macb_halt should have been called at some point before now, * so we'll assume the controller is idle. */ /* initialize DMA descriptors */ paddr = macb->rx_buffer_dma; for (i = 0; i < CONFIG_SYS_MACB_RX_RING_SIZE; i++) { if (i == (CONFIG_SYS_MACB_RX_RING_SIZE - 1)) paddr |= RXADDR_WRAP; macb->rx_ring[i].addr = paddr; macb->rx_ring[i].ctrl = 0; paddr += 128; } for (i = 0; i < CONFIG_SYS_MACB_TX_RING_SIZE; i++) { macb->tx_ring[i].addr = 0; if (i == (CONFIG_SYS_MACB_TX_RING_SIZE - 1)) macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP; else macb->tx_ring[i].ctrl = TXBUF_USED; } macb->rx_tail = macb->tx_head = macb->tx_tail = 0; macb_writel(macb, RBQP, macb->rx_ring_dma); macb_writel(macb, TBQP, macb->tx_ring_dma); if (macb_is_gem(macb)) { #ifdef CONFIG_RGMII gem_writel(macb, UR, GEM_BIT(RGMII)); #else gem_writel(macb, UR, 0); #endif } else { /* choose RMII or MII mode. This depends on the board */ #ifdef CONFIG_RMII #ifdef CONFIG_AT91FAMILY macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN)); #else macb_writel(macb, USRIO, 0); #endif #else #ifdef CONFIG_AT91FAMILY macb_writel(macb, USRIO, MACB_BIT(CLKEN)); #else macb_writel(macb, USRIO, MACB_BIT(MII)); #endif #endif /* CONFIG_RMII */ } if (!macb_phy_init(macb)) return -1; /* Enable TX and RX */ macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE)); return 0; }
static int macb_init(struct eth_device *netdev, bd_t *bd) { struct macb_device *macb = to_macb(netdev); unsigned long paddr; u32 hwaddr_bottom; u16 hwaddr_top; int i; /* * macb_halt should have been called at some point before now, * so we'll assume the controller is idle. */ /* initialize DMA descriptors */ paddr = macb->rx_buffer_dma; for (i = 0; i < CONFIG_SYS_MACB_RX_RING_SIZE; i++) { if (i == (CONFIG_SYS_MACB_RX_RING_SIZE - 1)) paddr |= RXADDR_WRAP; macb->rx_ring[i].addr = paddr; macb->rx_ring[i].ctrl = 0; paddr += 128; } for (i = 0; i < CONFIG_SYS_MACB_TX_RING_SIZE; i++) { macb->tx_ring[i].addr = 0; if (i == (CONFIG_SYS_MACB_TX_RING_SIZE - 1)) macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP; else macb->tx_ring[i].ctrl = TXBUF_USED; } macb->rx_tail = macb->tx_head = macb->tx_tail = 0; macb_writel(macb, RBQP, macb->rx_ring_dma); macb_writel(macb, TBQP, macb->tx_ring_dma); /* set hardware address */ hwaddr_bottom = cpu_to_le32(*((u32 *)netdev->enetaddr)); macb_writel(macb, SA1B, hwaddr_bottom); hwaddr_top = cpu_to_le16(*((u16 *)(netdev->enetaddr + 4))); macb_writel(macb, SA1T, hwaddr_top); /* choose RMII or MII mode. This depends on the board */ #ifdef CONFIG_RMII #if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \ defined(CONFIG_AT91SAM9263) macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN)); #else macb_writel(macb, USRIO, 0); #endif #else #if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \ defined(CONFIG_AT91SAM9263) macb_writel(macb, USRIO, MACB_BIT(CLKEN)); #else macb_writel(macb, USRIO, MACB_BIT(MII)); #endif #endif /* CONFIG_RMII */ if (!macb_phy_init(macb)) return -1; /* Enable TX and RX */ macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE)); return 0; }