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); }
/* 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; }
/* 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; }
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; }
/* 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_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); }
static int _macb_write_hwaddr(struct macb_device *macb, unsigned char *enetaddr) { u32 hwaddr_bottom; u16 hwaddr_top; /* set hardware address */ hwaddr_bottom = enetaddr[0] | enetaddr[1] << 8 | enetaddr[2] << 16 | enetaddr[3] << 24; macb_writel(macb, SA1B, hwaddr_bottom); hwaddr_top = enetaddr[4] | enetaddr[5] << 8; macb_writel(macb, SA1T, hwaddr_top); 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_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_eth_initialize(struct macb_device *macb) { int id = 0; /* This is not used by functions we call */ u32 ncfgr; /* TODO: we need check the rx/tx_ring_dma is dcache line aligned */ macb->rx_buffer = dma_alloc_coherent(MACB_RX_BUFFER_SIZE, &macb->rx_buffer_dma); macb->rx_ring = dma_alloc_coherent(MACB_RX_DMA_DESC_SIZE, &macb->rx_ring_dma); macb->tx_ring = dma_alloc_coherent(MACB_TX_DMA_DESC_SIZE, &macb->tx_ring_dma); macb->dummy_desc = dma_alloc_coherent(MACB_TX_DUMMY_DMA_DESC_SIZE, &macb->dummy_desc_dma); /* * Do some basic initialization so that we at least can talk * to the PHY */ if (macb_is_gem(macb)) { ncfgr = gem_mdc_clk_div(id, macb); ncfgr |= macb_dbw(macb); } else { ncfgr = macb_mdc_clk_div(id, macb); } macb_writel(macb, NCFGR, ncfgr); }
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)); }
int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) { struct macb_device *macb; struct eth_device *netdev; u32 ncfgr; macb = malloc(sizeof(struct macb_device)); if (!macb) { printf("Error: Failed to allocate memory for MACB%d\n", id); return -1; } memset(macb, 0, sizeof(struct macb_device)); netdev = &macb->netdev; macb->rx_buffer = dma_alloc_coherent(CONFIG_SYS_MACB_RX_BUFFER_SIZE, &macb->rx_buffer_dma); macb->rx_ring = dma_alloc_coherent(CONFIG_SYS_MACB_RX_RING_SIZE * sizeof(struct macb_dma_desc), &macb->rx_ring_dma); macb->tx_ring = dma_alloc_coherent(CONFIG_SYS_MACB_TX_RING_SIZE * sizeof(struct macb_dma_desc), &macb->tx_ring_dma); macb->regs = regs; macb->phy_addr = phy_addr; if (macb_is_gem(macb)) sprintf(netdev->name, "gmac%d", id); else sprintf(netdev->name, "macb%d", id); netdev->init = macb_init; netdev->halt = macb_halt; netdev->send = macb_send; netdev->recv = macb_recv; netdev->write_hwaddr = macb_write_hwaddr; /* * Do some basic initialization so that we at least can talk * to the PHY */ if (macb_is_gem(macb)) { ncfgr = gem_mdc_clk_div(id, macb); ncfgr |= GEM_BF(DBW, 1); } else { ncfgr = macb_mdc_clk_div(id, macb); } macb_writel(macb, NCFGR, ncfgr); eth_register(netdev); #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) miiphy_register(netdev->name, macb_miiphy_read, macb_miiphy_write); macb->bus = miiphy_get_dev_by_name(netdev->name); #endif return 0; }
int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) { struct macb_device *macb; struct eth_device *netdev; unsigned long macb_hz; u32 ncfgr; macb = malloc(sizeof(struct macb_device)); if (!macb) { printf("Error: Failed to allocate memory for MACB%d\n", id); return -1; } memset(macb, 0, sizeof(struct macb_device)); netdev = &macb->netdev; macb->rx_buffer = dma_alloc_coherent(CONFIG_SYS_MACB_RX_BUFFER_SIZE, &macb->rx_buffer_dma); macb->rx_ring = dma_alloc_coherent(CONFIG_SYS_MACB_RX_RING_SIZE * sizeof(struct macb_dma_desc), &macb->rx_ring_dma); macb->tx_ring = dma_alloc_coherent(CONFIG_SYS_MACB_TX_RING_SIZE * sizeof(struct macb_dma_desc), &macb->tx_ring_dma); macb->regs = regs; macb->phy_addr = phy_addr; sprintf(netdev->name, "macb%d", id); netdev->init = macb_init; netdev->halt = macb_halt; netdev->send = macb_send; netdev->recv = macb_recv; netdev->write_hwaddr = macb_write_hwaddr; /* * Do some basic initialization so that we at least can talk * to the PHY */ macb_hz = get_macb_pclk_rate(id); if (macb_hz < 20000000) ncfgr = MACB_BF(CLK, MACB_CLK_DIV8); else if (macb_hz < 40000000) ncfgr = MACB_BF(CLK, MACB_CLK_DIV16); else if (macb_hz < 80000000) ncfgr = MACB_BF(CLK, MACB_CLK_DIV32); else ncfgr = MACB_BF(CLK, MACB_CLK_DIV64); macb_writel(macb, NCFGR, ncfgr); eth_register(netdev); #if defined(CONFIG_CMD_MII) miiphy_register(netdev->name, macb_miiphy_read, macb_miiphy_write); #endif 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; }
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; }
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; }
/* 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_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; }
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; }