int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value) { unsigned long netctl; unsigned long netstat; unsigned long frame; int iflag; iflag = disable_interrupts(); netctl = macb_readl(&macb, EMACB_NCR); netctl |= MACB_BIT(MPE); macb_writel(&macb, EMACB_NCR, netctl); if (iflag) enable_interrupts(); frame = (MACB_BF(SOF, 1) | MACB_BF(RW, 1) | MACB_BF(PHYA, addr) | MACB_BF(REGA, reg) | MACB_BF(CODE, 2) | MACB_BF(DATA, value)); macb_writel(&macb, EMACB_MAN, frame); do { netstat = macb_readl(&macb, EMACB_NSR); } while (!(netstat & MACB_BIT(IDLE))); iflag = disable_interrupts(); netctl = macb_readl(&macb, EMACB_NCR); netctl &= ~MACB_BIT(MPE); macb_writel(&macb, EMACB_NCR, netctl); if (iflag) enable_interrupts(); return 0; }
static u16 macb_mdio_read(struct macb_device *macb, u8 reg) { unsigned long netctl; unsigned long netstat; unsigned long frame; netctl = macb_readl(macb, NCR); netctl |= MACB_BIT(MPE); macb_writel(macb, NCR, netctl); frame = (MACB_BF(SOF, 1) | MACB_BF(RW, 2) | MACB_BF(PHYA, macb->phy_addr) | MACB_BF(REGA, reg) | MACB_BF(CODE, 2)); macb_writel(macb, MAN, frame); do { netstat = macb_readl(macb, NSR); } while (!(netstat & MACB_BIT(IDLE))); frame = macb_readl(macb, MAN); netctl = macb_readl(macb, NCR); netctl &= ~MACB_BIT(MPE); macb_writel(macb, NCR, netctl); return MACB_BFEXT(DATA, frame); }
static int macb_phy_write(struct mii_device *mdev, int addr, int reg, int value) { struct eth_device *edev = mdev->edev; struct macb_device *macb = edev->priv; unsigned long netctl; unsigned long netstat; unsigned long frame; debug("%s\n", __func__); netctl = readl(macb->regs + MACB_NCR); netctl |= MACB_BIT(MPE); writel(netctl, macb->regs + MACB_NCR); frame = (MACB_BF(SOF, 1) | MACB_BF(RW, 1) | MACB_BF(PHYA, addr) | MACB_BF(REGA, reg) | MACB_BF(CODE, 2) | MACB_BF(DATA, value)); writel(frame, macb->regs + MACB_MAN); do { netstat = readl(macb->regs + MACB_NSR); } while (!(netstat & MACB_BIT(IDLE))); netctl = readl(macb->regs + MACB_NCR); netctl &= ~MACB_BIT(MPE); writel(netctl, macb->regs + MACB_NCR); return 0; }
static void macb_smi_write(struct macb_device *macb, u16 phy, u8 reg, u16 value) { unsigned long netctl; unsigned long netstat; unsigned long frame; netctl = macb_readl(macb, NCR); netctl |= MACB_BIT(MPE); macb_writel(macb, NCR, netctl); frame = (MACB_BF(SOF, 1) | MACB_BF(RW, 1) | MACB_BF(PHYA, phy) | MACB_BF(REGA, reg) | MACB_BF(CODE, 2) | MACB_BF(DATA, value)); macb_writel(macb, MAN, frame); do { netstat = macb_readl(macb, NSR); } while (!(netstat & MACB_BIT(IDLE))); netctl = macb_readl(macb, NCR); netctl &= ~MACB_BIT(MPE); macb_writel(macb, NCR, netctl); }
/* Close the interface */ static int at91ether_close(struct net_device *dev) { struct macb *lp = netdev_priv(dev); u32 ctl; /* Disable Receiver and Transmitter */ ctl = macb_readl(lp, NCR); macb_writel(lp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE))); /* Disable MAC interrupts */ macb_writel(lp, IDR, MACB_BIT(RCOMP) | MACB_BIT(RXUBR) | MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE) | MACB_BIT(TCOMP) | MACB_BIT(ISR_ROVR) | MACB_BIT(HRESP)); netif_stop_queue(dev); dma_free_coherent(&lp->pdev->dev, MAX_RX_DESCR * sizeof(struct macb_dma_desc), lp->rx_ring, lp->rx_ring_dma); lp->rx_ring = NULL; dma_free_coherent(&lp->pdev->dev, MAX_RX_DESCR * MAX_RBUFF_SZ, lp->rx_buffers, lp->rx_buffers_dma); lp->rx_buffers = NULL; return 0; }
static int macb_phy_init(struct macb_device *macb) { struct eth_device *netdev = &macb->netdev; u32 ncfgr; u16 phy_id, status, adv, lpa; int media, speed, duplex; int i; /* Check if the PHY is up to snuff... */ phy_id = macb_mdio_read(macb, MII_PHYSID1); if (phy_id == 0xffff) { printf("%s: No PHY present\n", netdev->name); return 0; } status = macb_mdio_read(macb, MII_BMSR); if (!(status & BMSR_LSTATUS)) { /* Try to re-negotiate if we don't have link already. */ macb_phy_reset(macb); for (i = 0; i < CONFIG_SYS_MACB_AUTONEG_TIMEOUT / 100; i++) { status = macb_mdio_read(macb, MII_BMSR); if (status & BMSR_LSTATUS) break; udelay(100); } } if (!(status & BMSR_LSTATUS)) { printf("%s: link down (status: 0x%04x)\n", netdev->name, status); return 0; } else { adv = macb_mdio_read(macb, MII_ADVERTISE); lpa = macb_mdio_read(macb, MII_LPA); media = mii_nway_result(lpa & adv); speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? 1 : 0); duplex = (media & ADVERTISE_FULL) ? 1 : 0; printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", netdev->name, speed ? "100" : "10", duplex ? "full" : "half", lpa); ncfgr = macb_readl(macb, NCFGR); ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); if (speed) ncfgr |= MACB_BIT(SPD); if (duplex) ncfgr |= MACB_BIT(FD); macb_writel(macb, NCFGR, ncfgr); return 1; } }
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; }
/* Open the ethernet interface */ static int at91ether_open(struct net_device *dev) { struct macb *lp = netdev_priv(dev); u32 ctl; int ret; /* Clear internal statistics */ ctl = macb_readl(lp, NCR); macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT)); macb_set_hwaddr(lp); ret = at91ether_start(dev); if (ret) return ret; /* Enable MAC interrupts */ macb_writel(lp, IER, MACB_BIT(RCOMP) | MACB_BIT(RXUBR) | MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE) | MACB_BIT(TCOMP) | MACB_BIT(ISR_ROVR) | MACB_BIT(HRESP)); /* schedule a link state check */ phy_start(lp->phy_dev); netif_start_queue(dev); return 0; }
/* Initialize and start the Receiver and Transmit subsystems */ static int at91ether_start(struct net_device *dev) { struct macb *lp = netdev_priv(dev); dma_addr_t addr; u32 ctl; int i; lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev, MAX_RX_DESCR * sizeof(struct macb_dma_desc), &lp->rx_ring_dma, GFP_KERNEL); if (!lp->rx_ring) { netdev_err(dev, "unable to alloc rx ring DMA buffer\n"); return -ENOMEM; } lp->rx_buffers = dma_alloc_coherent(&lp->pdev->dev, MAX_RX_DESCR * MAX_RBUFF_SZ, &lp->rx_buffers_dma, GFP_KERNEL); if (!lp->rx_buffers) { netdev_err(dev, "unable to alloc rx data DMA buffer\n"); dma_free_coherent(&lp->pdev->dev, MAX_RX_DESCR * sizeof(struct macb_dma_desc), lp->rx_ring, lp->rx_ring_dma); lp->rx_ring = NULL; return -ENOMEM; } addr = lp->rx_buffers_dma; for (i = 0; i < MAX_RX_DESCR; i++) { lp->rx_ring[i].addr = addr; lp->rx_ring[i].ctrl = 0; addr += MAX_RBUFF_SZ; } /* Set the Wrap bit on the last descriptor */ lp->rx_ring[MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP); /* Reset buffer index */ lp->rx_tail = 0; /* Program address of descriptor list in Rx Buffer Queue register */ macb_writel(lp, RBQP, lp->rx_ring_dma); /* Enable Receive and Transmit */ ctl = macb_readl(lp, NCR); macb_writel(lp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE)); return 0; }
static int macb_phy_read(struct mii_device *mdev, int addr, int reg) { struct eth_device *edev = mdev->edev; struct macb_device *macb = edev->priv; unsigned long netctl; unsigned long netstat; unsigned long frame; int iflag; int value; uint64_t start; debug("%s\n", __func__); iflag = disable_interrupts(); netctl = readl(macb->regs + MACB_NCR); netctl |= MACB_BIT(MPE); writel(netctl, macb->regs + MACB_NCR); if (iflag) enable_interrupts(); frame = (MACB_BF(SOF, 1) | MACB_BF(RW, 2) | MACB_BF(PHYA, addr) | MACB_BF(REGA, reg) | MACB_BF(CODE, 2)); writel(frame, macb->regs + MACB_MAN); start = get_time_ns(); do { netstat = readl(macb->regs + MACB_NSR); if (is_timeout(start, SECOND)) { printf("phy read timed out\n"); return -1; } } while (!(netstat & MACB_BIT(IDLE))); frame = readl(macb->regs + MACB_MAN); value = MACB_BFEXT(DATA, frame); iflag = disable_interrupts(); netctl = readl(macb->regs + MACB_NCR); netctl &= ~MACB_BIT(MPE); writel(netctl, macb->regs + MACB_NCR); if (iflag) enable_interrupts(); return value; }
/* Transmit packet */ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct macb *lp = netdev_priv(dev); if (macb_readl(lp, TSR) & MACB_BIT(RM9200_BNQ)) { netif_stop_queue(dev); /* Store packet information (to free when Tx completed) */ lp->skb = skb; lp->skb_length = skb->len; lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE); /* Set address of the data in the Transmit Address register */ macb_writel(lp, TAR, lp->skb_physaddr); /* Set length of the packet in the Transmit Control register */ macb_writel(lp, TCR, skb->len); } else { netdev_err(dev, "%s called, but device is busy!\n", __func__); return NETDEV_TX_BUSY; } return NETDEV_TX_OK; }
static void _macb_halt(struct macb_device *macb) { 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_init(struct eth_device *edev) { struct macb_device *macb = edev->priv; unsigned long paddr, val = 0; int i; debug("%s\n", __func__); /* * macb_halt should have been called at some point before now, * so we'll assume the controller is idle. */ /* initialize DMA descriptors */ paddr = (ulong)macb->rx_buffer; for (i = 0; i < CFG_MACB_RX_RING_SIZE; i++) { if (i == (CFG_MACB_RX_RING_SIZE - 1)) paddr |= RXADDR_WRAP; macb->rx_ring[i].addr = paddr; macb->rx_ring[i].ctrl = 0; paddr += 128; } macb->tx_ring[0].addr = 0; macb->tx_ring[0].ctrl = TXBUF_USED | TXBUF_WRAP; macb->rx_tail = macb->tx_tail = 0; writel((ulong)macb->rx_ring, macb->regs + MACB_RBQP); writel((ulong)macb->tx_ring, macb->regs + MACB_TBQP); if (macb->flags & AT91SAM_ETHER_RMII) val |= MACB_BIT(RMII); else val &= ~MACB_BIT(RMII); #if defined(CONFIG_ARCH_AT91) val |= MACB_BIT(CLKEN); #endif writel(val, macb->regs + MACB_USRIO); /* Enable TX and RX */ writel(MACB_BIT(TE) | MACB_BIT(RE), macb->regs + MACB_NCR); return 0; }
static void macb_halt(struct eth_device *edev) { struct macb_device *macb = edev->priv; u32 ncr, tsr; /* Halt the controller and wait for any ongoing transmission to end. */ ncr = readl(macb->regs + MACB_NCR); ncr |= MACB_BIT(THALT); writel(ncr, macb->regs + MACB_NCR); do { tsr = readl(macb->regs + MACB_TSR); } while (tsr & MACB_BIT(TGO)); /* Disable TX and RX, and clear statistics */ writel(MACB_BIT(CLRSTAT), macb->regs + MACB_NCR); }
static int macb_open(struct eth_device *edev) { struct macb_device *macb = edev->priv; int duplex = 1, speed = 1; u32 ncfgr; debug("%s\n", __func__); miidev_wait_aneg(&macb->miidev); miidev_print_status(&macb->miidev); ncfgr = readl(macb->regs + MACB_NCFGR); ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); if (speed) ncfgr |= MACB_BIT(SPD); if (duplex) ncfgr |= MACB_BIT(FD); writel(ncfgr, macb->regs + MACB_NCFGR); return 0; }
/* Extract received frame from buffer descriptors and sent to upper layers. * (Called from interrupt context) */ static void at91ether_rx(struct net_device *dev) { struct macb *lp = netdev_priv(dev); unsigned char *p_recv; struct sk_buff *skb; unsigned int pktlen; while (lp->rx_ring[lp->rx_tail].addr & MACB_BIT(RX_USED)) { p_recv = lp->rx_buffers + lp->rx_tail * MAX_RBUFF_SZ; pktlen = MACB_BF(RX_FRMLEN, lp->rx_ring[lp->rx_tail].ctrl); skb = netdev_alloc_skb(dev, pktlen + 2); if (skb) { skb_reserve(skb, 2); memcpy(skb_put(skb, pktlen), p_recv, pktlen); skb->protocol = eth_type_trans(skb, dev); lp->stats.rx_packets++; lp->stats.rx_bytes += pktlen; netif_rx(skb); } else { lp->stats.rx_dropped++; netdev_notice(dev, "Memory squeeze, dropping packet.\n"); } if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH)) lp->stats.multicast++; /* reset ownership bit */ lp->rx_ring[lp->rx_tail].addr &= ~MACB_BIT(RX_USED); /* wrap after last buffer */ if (lp->rx_tail == MAX_RX_DESCR - 1) lp->rx_tail = 0; else lp->rx_tail++; } }
static int macb_send(struct eth_device *edev, void *packet, int length) { struct macb_device *macb = edev->priv; unsigned long ctrl; debug("%s\n", __func__); ctrl = length & TXBUF_FRMLEN_MASK; ctrl |= TXBUF_FRAME_END | TXBUF_WRAP; macb->tx_ring[0].ctrl = ctrl; macb->tx_ring[0].addr = (ulong)packet; barrier(); writel(MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART), macb->regs + MACB_NCR); if (ctrl & TXBUF_UNDERRUN) printf("TX underrun\n"); if (ctrl & TXBUF_EXHAUSTED) printf("TX buffers exhausted in mid frame\n"); /* No one cares anyway */ return 0; }
/* MAC interrupt handler */ static irqreturn_t at91ether_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct macb *lp = netdev_priv(dev); u32 intstatus, ctl; /* MAC Interrupt Status register indicates what interrupts are pending. * It is automatically cleared once read. */ intstatus = macb_readl(lp, ISR); /* Receive complete */ if (intstatus & MACB_BIT(RCOMP)) at91ether_rx(dev); /* Transmit complete */ if (intstatus & MACB_BIT(TCOMP)) { /* The TCOM bit is set even if the transmission failed */ if (intstatus & (MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE))) lp->stats.tx_errors++; if (lp->skb) { dev_kfree_skb_irq(lp->skb); lp->skb = NULL; dma_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE); lp->stats.tx_packets++; lp->stats.tx_bytes += lp->skb_length; } netif_wake_queue(dev); } /* Work-around for EMAC Errata section 41.3.1 */ if (intstatus & MACB_BIT(RXUBR)) { ctl = macb_readl(lp, NCR); macb_writel(lp, NCR, ctl & ~MACB_BIT(RE)); macb_writel(lp, NCR, ctl | MACB_BIT(RE)); } if (intstatus & MACB_BIT(ISR_ROVR)) netdev_err(dev, "ROVR error\n"); return IRQ_HANDLED; }
/* Detect MAC & PHY and perform ethernet interface initialization */ static int __init at91ether_probe(struct platform_device *pdev) { struct macb_platform_data *board_data = dev_get_platdata(&pdev->dev); struct resource *regs; struct net_device *dev; struct phy_device *phydev; struct macb *lp; int res; u32 reg; const char *mac; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) return -ENOENT; dev = alloc_etherdev(sizeof(struct macb)); if (!dev) return -ENOMEM; lp = netdev_priv(dev); lp->pdev = pdev; lp->dev = dev; spin_lock_init(&lp->lock); /* physical base address */ dev->base_addr = regs->start; lp->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); if (!lp->regs) { res = -ENOMEM; goto err_free_dev; } /* Clock */ lp->pclk = devm_clk_get(&pdev->dev, "ether_clk"); if (IS_ERR(lp->pclk)) { res = PTR_ERR(lp->pclk); goto err_free_dev; } clk_enable(lp->pclk); lp->hclk = ERR_PTR(-ENOENT); lp->tx_clk = ERR_PTR(-ENOENT); /* Install the interrupt handler */ dev->irq = platform_get_irq(pdev, 0); res = devm_request_irq(&pdev->dev, dev->irq, at91ether_interrupt, 0, dev->name, dev); if (res) goto err_disable_clock; ether_setup(dev); dev->netdev_ops = &at91ether_netdev_ops; dev->ethtool_ops = &macb_ethtool_ops; platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); mac = of_get_mac_address(pdev->dev.of_node); if (mac) memcpy(lp->dev->dev_addr, mac, ETH_ALEN); else macb_get_hwaddr(lp); res = of_get_phy_mode(pdev->dev.of_node); if (res < 0) { if (board_data && board_data->is_rmii) lp->phy_interface = PHY_INTERFACE_MODE_RMII; else lp->phy_interface = PHY_INTERFACE_MODE_MII; } else { lp->phy_interface = res; } macb_writel(lp, NCR, 0); reg = MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG); if (lp->phy_interface == PHY_INTERFACE_MODE_RMII) reg |= MACB_BIT(RM9200_RMII); macb_writel(lp, NCFGR, reg); /* Register the network interface */ res = register_netdev(dev); if (res) goto err_disable_clock; res = macb_mii_init(lp); if (res) goto err_out_unregister_netdev; /* will be enabled in open() */ netif_carrier_off(dev); phydev = lp->phy_dev; netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", phydev->drv->name, dev_name(&phydev->dev), phydev->irq); /* Display ethernet banner */ netdev_info(dev, "AT91 ethernet at 0x%08lx int=%d (%pM)\n", dev->base_addr, dev->irq, dev->dev_addr); return 0; err_out_unregister_netdev: unregister_netdev(dev); err_disable_clock: clk_disable(lp->pclk); err_free_dev: free_netdev(dev); return res; }
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; }
static int _macb_init(struct macb_device *macb, const char *name) #endif { #ifdef CONFIG_DM_ETH struct macb_device *macb = dev_get_priv(dev); #endif 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 < MACB_RX_RING_SIZE; i++) { if (i == (MACB_RX_RING_SIZE - 1)) paddr |= RXADDR_WRAP; macb->rx_ring[i].addr = paddr; macb->rx_ring[i].ctrl = 0; paddr += 128; } macb_flush_ring_desc(macb, RX); macb_flush_rx_buffer(macb); for (i = 0; i < MACB_TX_RING_SIZE; i++) { macb->tx_ring[i].addr = 0; if (i == (MACB_TX_RING_SIZE - 1)) macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP; else macb->tx_ring[i].ctrl = TXBUF_USED; } macb_flush_ring_desc(macb, TX); macb->rx_tail = 0; macb->tx_head = 0; macb->tx_tail = 0; macb->next_rx_tail = 0; macb_writel(macb, RBQP, macb->rx_ring_dma); macb_writel(macb, TBQP, macb->tx_ring_dma); if (macb_is_gem(macb)) { /* Check the multi queue and initialize the queue for tx */ gmac_init_multi_queues(macb); /* * When the GMAC IP with GE feature, this bit is used to * select interface between RGMII and GMII. * When the GMAC IP without GE feature, this bit is used * to select interface between RMII and MII. */ #ifdef CONFIG_DM_ETH if ((macb->phy_interface == PHY_INTERFACE_MODE_RMII) || (macb->phy_interface == PHY_INTERFACE_MODE_RGMII)) gem_writel(macb, UR, GEM_BIT(RGMII)); else gem_writel(macb, UR, 0); #else #if defined(CONFIG_RGMII) || defined(CONFIG_RMII) gem_writel(macb, UR, GEM_BIT(RGMII)); #else gem_writel(macb, UR, 0); #endif #endif } else { /* choose RMII or MII mode. This depends on the board */ #ifdef CONFIG_DM_ETH #ifdef CONFIG_AT91FAMILY if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) { macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN)); } else { macb_writel(macb, USRIO, MACB_BIT(CLKEN)); } #else if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) macb_writel(macb, USRIO, 0); else macb_writel(macb, USRIO, MACB_BIT(MII)); #endif #else #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 */ #endif } #ifdef CONFIG_DM_ETH if (!macb_phy_init(dev, name)) #else if (!macb_phy_init(macb, name)) #endif return -1; /* Enable TX and RX */ macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE)); return 0; }
static int macb_phy_init(struct macb_device *macb, const char *name) #endif { #ifdef CONFIG_DM_ETH struct macb_device *macb = dev_get_priv(dev); #endif u32 ncfgr; u16 phy_id, status, adv, lpa; int media, speed, duplex; int i; arch_get_mdio_control(name); /* Auto-detect phy_addr */ if (!macb_phy_find(macb, name)) return 0; /* Check if the PHY is up to snuff... */ phy_id = macb_mdio_read(macb, MII_PHYSID1); if (phy_id == 0xffff) { printf("%s: No PHY present\n", name); return 0; } #ifdef CONFIG_PHYLIB #ifdef CONFIG_DM_ETH macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev, macb->phy_interface); #else /* need to consider other phy interface mode */ macb->phydev = phy_connect(macb->bus, macb->phy_addr, &macb->netdev, PHY_INTERFACE_MODE_RGMII); #endif if (!macb->phydev) { printf("phy_connect failed\n"); return -ENODEV; } phy_config(macb->phydev); #endif status = macb_mdio_read(macb, MII_BMSR); if (!(status & BMSR_LSTATUS)) { /* Try to re-negotiate if we don't have link already. */ macb_phy_reset(macb, name); for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) { status = macb_mdio_read(macb, MII_BMSR); if (status & BMSR_LSTATUS) break; udelay(100); } } if (!(status & BMSR_LSTATUS)) { printf("%s: link down (status: 0x%04x)\n", name, status); return 0; } /* First check for GMAC and that it is GiB capable */ if (gem_is_gigabit_capable(macb)) { lpa = macb_mdio_read(macb, MII_STAT1000); if (lpa & (LPA_1000FULL | LPA_1000HALF)) { duplex = ((lpa & LPA_1000FULL) ? 1 : 0); printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n", name, duplex ? "full" : "half", lpa); ncfgr = macb_readl(macb, NCFGR); ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); ncfgr |= GEM_BIT(GBE); if (duplex) ncfgr |= MACB_BIT(FD); macb_writel(macb, NCFGR, ncfgr); return 1; } } /* fall back for EMAC checking */ adv = macb_mdio_read(macb, MII_ADVERTISE); lpa = macb_mdio_read(macb, MII_LPA); media = mii_nway_result(lpa & adv); speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? 1 : 0); duplex = (media & ADVERTISE_FULL) ? 1 : 0; printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", name, speed ? "100" : "10", duplex ? "full" : "half", lpa); ncfgr = macb_readl(macb, NCFGR); ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE)); if (speed) ncfgr |= MACB_BIT(SPD); if (duplex) ncfgr |= MACB_BIT(FD); macb_writel(macb, NCFGR, ncfgr); return 1; }
static int macb_phy_init(struct macb_device *macb) { struct eth_device *netdev = &macb->netdev; #ifdef CONFIG_PHYLIB struct phy_device *phydev; #endif u32 ncfgr; u16 phy_id, status, adv, lpa; int media, speed, duplex; int i; arch_get_mdio_control(netdev->name); #ifdef CONFIG_MACB_SEARCH_PHY /* Auto-detect phy_addr */ if (!macb_phy_find(macb)) { return 0; } #endif /* CONFIG_MACB_SEARCH_PHY */ /* Check if the PHY is up to snuff... */ phy_id = macb_mdio_read(macb, MII_PHYSID1); if (phy_id == 0xffff) { printf("%s: No PHY present\n", netdev->name); return 0; } #ifdef CONFIG_PHYLIB phydev->bus = macb->bus; phydev->dev = netdev; phydev->addr = macb->phy_addr; phy_config(phydev); #endif status = macb_mdio_read(macb, MII_BMSR); if (!(status & BMSR_LSTATUS)) { /* Try to re-negotiate if we don't have link already. */ macb_phy_reset(macb); for (i = 0; i < CONFIG_SYS_MACB_AUTONEG_TIMEOUT / 100; i++) { status = macb_mdio_read(macb, MII_BMSR); if (status & BMSR_LSTATUS) break; udelay(100); } } if (!(status & BMSR_LSTATUS)) { printf("%s: link down (status: 0x%04x)\n", netdev->name, status); return 0; } /* First check for GMAC */ if (macb_is_gem(macb)) { lpa = macb_mdio_read(macb, MII_STAT1000); if (lpa & (1 << 11)) { speed = 1000; duplex = 1; } else { if (lpa & (1 << 10)) { speed = 1000; duplex = 1; } else { speed = 0; } } if (speed == 1000) { printf("%s: link up, %dMbps %s-duplex (lpa: 0x%04x)\n", netdev->name, speed, duplex ? "full" : "half", lpa); ncfgr = macb_readl(macb, NCFGR); ncfgr &= ~(GEM_BIT(GBE) | MACB_BIT(SPD) | MACB_BIT(FD)); if (speed) ncfgr |= GEM_BIT(GBE); if (duplex) ncfgr |= MACB_BIT(FD); macb_writel(macb, NCFGR, ncfgr); return 1; } } /* fall back for EMAC checking */ adv = macb_mdio_read(macb, MII_ADVERTISE); lpa = macb_mdio_read(macb, MII_LPA); media = mii_nway_result(lpa & adv); speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? 1 : 0); duplex = (media & ADVERTISE_FULL) ? 1 : 0; printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", netdev->name, speed ? "100" : "10", duplex ? "full" : "half", lpa); ncfgr = macb_readl(macb, NCFGR); ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); if (speed) ncfgr |= MACB_BIT(SPD); if (duplex) ncfgr |= MACB_BIT(FD); macb_writel(macb, NCFGR, ncfgr); return 1; }
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; }