12439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 22439e4bfSJean-Christophe PLAGNIOL-VILLARD * Copyright (C) 2005-2006 Atmel Corporation 32439e4bfSJean-Christophe PLAGNIOL-VILLARD * 41a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 52439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 62439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 7*f1dcc19bSSimon Glass #include <dm.h> 82439e4bfSJean-Christophe PLAGNIOL-VILLARD 92439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 102439e4bfSJean-Christophe PLAGNIOL-VILLARD * The u-boot networking stack is a little weird. It seems like the 112439e4bfSJean-Christophe PLAGNIOL-VILLARD * networking core allocates receive buffers up front without any 122439e4bfSJean-Christophe PLAGNIOL-VILLARD * regard to the hardware that's supposed to actually receive those 132439e4bfSJean-Christophe PLAGNIOL-VILLARD * packets. 142439e4bfSJean-Christophe PLAGNIOL-VILLARD * 152439e4bfSJean-Christophe PLAGNIOL-VILLARD * The MACB receives packets into 128-byte receive buffers, so the 162439e4bfSJean-Christophe PLAGNIOL-VILLARD * buffers allocated by the core isn't very practical to use. We'll 172439e4bfSJean-Christophe PLAGNIOL-VILLARD * allocate our own, but we need one such buffer in case a packet 182439e4bfSJean-Christophe PLAGNIOL-VILLARD * wraps around the DMA ring so that we have to copy it. 192439e4bfSJean-Christophe PLAGNIOL-VILLARD * 206d0f6bcfSJean-Christophe PLAGNIOL-VILLARD * Therefore, define CONFIG_SYS_RX_ETH_BUFFER to 1 in the board-specific 212439e4bfSJean-Christophe PLAGNIOL-VILLARD * configuration header. This way, the core allocates one RX buffer 222439e4bfSJean-Christophe PLAGNIOL-VILLARD * and one TX buffer, each of which can hold a ethernet packet of 232439e4bfSJean-Christophe PLAGNIOL-VILLARD * maximum size. 242439e4bfSJean-Christophe PLAGNIOL-VILLARD * 252439e4bfSJean-Christophe PLAGNIOL-VILLARD * For some reason, the networking core unconditionally specifies a 262439e4bfSJean-Christophe PLAGNIOL-VILLARD * 32-byte packet "alignment" (which really should be called 272439e4bfSJean-Christophe PLAGNIOL-VILLARD * "padding"). MACB shouldn't need that, but we'll refrain from any 282439e4bfSJean-Christophe PLAGNIOL-VILLARD * core modifications here... 292439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 302439e4bfSJean-Christophe PLAGNIOL-VILLARD 312439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h> 32*f1dcc19bSSimon Glass #ifndef CONFIG_DM_ETH 3389973f8aSBen Warren #include <netdev.h> 34*f1dcc19bSSimon Glass #endif 352439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <malloc.h> 360f751d6eSSemih Hazar #include <miiphy.h> 372439e4bfSJean-Christophe PLAGNIOL-VILLARD 382439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <linux/mii.h> 392439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h> 402439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <asm/dma-mapping.h> 412439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/clk.h> 428314ccd8SBo Shen #include <asm-generic/errno.h> 432439e4bfSJean-Christophe PLAGNIOL-VILLARD 442439e4bfSJean-Christophe PLAGNIOL-VILLARD #include "macb.h" 452439e4bfSJean-Christophe PLAGNIOL-VILLARD 46ceef983bSAndreas Bießmann #define MACB_RX_BUFFER_SIZE 4096 47ceef983bSAndreas Bießmann #define MACB_RX_RING_SIZE (MACB_RX_BUFFER_SIZE / 128) 48ceef983bSAndreas Bießmann #define MACB_TX_RING_SIZE 16 49ceef983bSAndreas Bießmann #define MACB_TX_TIMEOUT 1000 50ceef983bSAndreas Bießmann #define MACB_AUTONEG_TIMEOUT 5000000 512439e4bfSJean-Christophe PLAGNIOL-VILLARD 522439e4bfSJean-Christophe PLAGNIOL-VILLARD struct macb_dma_desc { 532439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 addr; 542439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 ctrl; 552439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 562439e4bfSJean-Christophe PLAGNIOL-VILLARD 575ae0e382SWu, Josh #define DMA_DESC_BYTES(n) (n * sizeof(struct macb_dma_desc)) 585ae0e382SWu, Josh #define MACB_TX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_TX_RING_SIZE)) 595ae0e382SWu, Josh #define MACB_RX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_RX_RING_SIZE)) 60ade4ea4dSWu, Josh #define MACB_TX_DUMMY_DMA_DESC_SIZE (DMA_DESC_BYTES(1)) 615ae0e382SWu, Josh 622439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RXADDR_USED 0x00000001 632439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RXADDR_WRAP 0x00000002 642439e4bfSJean-Christophe PLAGNIOL-VILLARD 652439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RXBUF_FRMLEN_MASK 0x00000fff 662439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RXBUF_FRAME_START 0x00004000 672439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RXBUF_FRAME_END 0x00008000 682439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RXBUF_TYPEID_MATCH 0x00400000 692439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RXBUF_ADDR4_MATCH 0x00800000 702439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RXBUF_ADDR3_MATCH 0x01000000 712439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RXBUF_ADDR2_MATCH 0x02000000 722439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RXBUF_ADDR1_MATCH 0x04000000 732439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RXBUF_BROADCAST 0x80000000 742439e4bfSJean-Christophe PLAGNIOL-VILLARD 752439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TXBUF_FRMLEN_MASK 0x000007ff 762439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TXBUF_FRAME_END 0x00008000 772439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TXBUF_NOCRC 0x00010000 782439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TXBUF_EXHAUSTED 0x08000000 792439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TXBUF_UNDERRUN 0x10000000 802439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TXBUF_MAXRETRY 0x20000000 812439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TXBUF_WRAP 0x40000000 822439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TXBUF_USED 0x80000000 832439e4bfSJean-Christophe PLAGNIOL-VILLARD 842439e4bfSJean-Christophe PLAGNIOL-VILLARD struct macb_device { 852439e4bfSJean-Christophe PLAGNIOL-VILLARD void *regs; 862439e4bfSJean-Christophe PLAGNIOL-VILLARD 872439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int rx_tail; 882439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int tx_head; 892439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int tx_tail; 90d5555b70SSimon Glass unsigned int next_rx_tail; 91d5555b70SSimon Glass bool wrapped; 922439e4bfSJean-Christophe PLAGNIOL-VILLARD 932439e4bfSJean-Christophe PLAGNIOL-VILLARD void *rx_buffer; 942439e4bfSJean-Christophe PLAGNIOL-VILLARD void *tx_buffer; 952439e4bfSJean-Christophe PLAGNIOL-VILLARD struct macb_dma_desc *rx_ring; 962439e4bfSJean-Christophe PLAGNIOL-VILLARD struct macb_dma_desc *tx_ring; 972439e4bfSJean-Christophe PLAGNIOL-VILLARD 982439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long rx_buffer_dma; 992439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long rx_ring_dma; 1002439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long tx_ring_dma; 1012439e4bfSJean-Christophe PLAGNIOL-VILLARD 102ade4ea4dSWu, Josh struct macb_dma_desc *dummy_desc; 103ade4ea4dSWu, Josh unsigned long dummy_desc_dma; 104ade4ea4dSWu, Josh 1052439e4bfSJean-Christophe PLAGNIOL-VILLARD const struct device *dev; 106*f1dcc19bSSimon Glass #ifndef CONFIG_DM_ETH 1072439e4bfSJean-Christophe PLAGNIOL-VILLARD struct eth_device netdev; 108*f1dcc19bSSimon Glass #endif 1092439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned short phy_addr; 110b1a0006eSBo Shen struct mii_dev *bus; 1112439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 112*f1dcc19bSSimon Glass #ifndef CONFIG_DM_ETH 1132439e4bfSJean-Christophe PLAGNIOL-VILLARD #define to_macb(_nd) container_of(_nd, struct macb_device, netdev) 114*f1dcc19bSSimon Glass #endif 1152439e4bfSJean-Christophe PLAGNIOL-VILLARD 116d256be29SBo Shen static int macb_is_gem(struct macb_device *macb) 117d256be29SBo Shen { 118d256be29SBo Shen return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) == 0x2; 119d256be29SBo Shen } 120d256be29SBo Shen 12175b03cf1SGregory CLEMENT #ifndef cpu_is_sama5d2 12275b03cf1SGregory CLEMENT #define cpu_is_sama5d2() 0 12375b03cf1SGregory CLEMENT #endif 12475b03cf1SGregory CLEMENT 12575b03cf1SGregory CLEMENT #ifndef cpu_is_sama5d4 12675b03cf1SGregory CLEMENT #define cpu_is_sama5d4() 0 12775b03cf1SGregory CLEMENT #endif 12875b03cf1SGregory CLEMENT 12975b03cf1SGregory CLEMENT static int gem_is_gigabit_capable(struct macb_device *macb) 13075b03cf1SGregory CLEMENT { 13175b03cf1SGregory CLEMENT /* 1321cc0a9f4SRobert P. J. Day * The GEM controllers embedded in SAMA5D2 and SAMA5D4 are 13375b03cf1SGregory CLEMENT * configured to support only 10/100. 13475b03cf1SGregory CLEMENT */ 13575b03cf1SGregory CLEMENT return macb_is_gem(macb) && !cpu_is_sama5d2() && !cpu_is_sama5d4(); 13675b03cf1SGregory CLEMENT } 13775b03cf1SGregory CLEMENT 1382439e4bfSJean-Christophe PLAGNIOL-VILLARD static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value) 1392439e4bfSJean-Christophe PLAGNIOL-VILLARD { 1402439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long netctl; 1412439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long netstat; 1422439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long frame; 1432439e4bfSJean-Christophe PLAGNIOL-VILLARD 1442439e4bfSJean-Christophe PLAGNIOL-VILLARD netctl = macb_readl(macb, NCR); 1452439e4bfSJean-Christophe PLAGNIOL-VILLARD netctl |= MACB_BIT(MPE); 1462439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, NCR, netctl); 1472439e4bfSJean-Christophe PLAGNIOL-VILLARD 1482439e4bfSJean-Christophe PLAGNIOL-VILLARD frame = (MACB_BF(SOF, 1) 1492439e4bfSJean-Christophe PLAGNIOL-VILLARD | MACB_BF(RW, 1) 1502439e4bfSJean-Christophe PLAGNIOL-VILLARD | MACB_BF(PHYA, macb->phy_addr) 1512439e4bfSJean-Christophe PLAGNIOL-VILLARD | MACB_BF(REGA, reg) 1522439e4bfSJean-Christophe PLAGNIOL-VILLARD | MACB_BF(CODE, 2) 1532439e4bfSJean-Christophe PLAGNIOL-VILLARD | MACB_BF(DATA, value)); 1542439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, MAN, frame); 1552439e4bfSJean-Christophe PLAGNIOL-VILLARD 1562439e4bfSJean-Christophe PLAGNIOL-VILLARD do { 1572439e4bfSJean-Christophe PLAGNIOL-VILLARD netstat = macb_readl(macb, NSR); 1582439e4bfSJean-Christophe PLAGNIOL-VILLARD } while (!(netstat & MACB_BIT(IDLE))); 1592439e4bfSJean-Christophe PLAGNIOL-VILLARD 1602439e4bfSJean-Christophe PLAGNIOL-VILLARD netctl = macb_readl(macb, NCR); 1612439e4bfSJean-Christophe PLAGNIOL-VILLARD netctl &= ~MACB_BIT(MPE); 1622439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, NCR, netctl); 1632439e4bfSJean-Christophe PLAGNIOL-VILLARD } 1642439e4bfSJean-Christophe PLAGNIOL-VILLARD 1652439e4bfSJean-Christophe PLAGNIOL-VILLARD static u16 macb_mdio_read(struct macb_device *macb, u8 reg) 1662439e4bfSJean-Christophe PLAGNIOL-VILLARD { 1672439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long netctl; 1682439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long netstat; 1692439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long frame; 1702439e4bfSJean-Christophe PLAGNIOL-VILLARD 1712439e4bfSJean-Christophe PLAGNIOL-VILLARD netctl = macb_readl(macb, NCR); 1722439e4bfSJean-Christophe PLAGNIOL-VILLARD netctl |= MACB_BIT(MPE); 1732439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, NCR, netctl); 1742439e4bfSJean-Christophe PLAGNIOL-VILLARD 1752439e4bfSJean-Christophe PLAGNIOL-VILLARD frame = (MACB_BF(SOF, 1) 1762439e4bfSJean-Christophe PLAGNIOL-VILLARD | MACB_BF(RW, 2) 1772439e4bfSJean-Christophe PLAGNIOL-VILLARD | MACB_BF(PHYA, macb->phy_addr) 1782439e4bfSJean-Christophe PLAGNIOL-VILLARD | MACB_BF(REGA, reg) 1792439e4bfSJean-Christophe PLAGNIOL-VILLARD | MACB_BF(CODE, 2)); 1802439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, MAN, frame); 1812439e4bfSJean-Christophe PLAGNIOL-VILLARD 1822439e4bfSJean-Christophe PLAGNIOL-VILLARD do { 1832439e4bfSJean-Christophe PLAGNIOL-VILLARD netstat = macb_readl(macb, NSR); 1842439e4bfSJean-Christophe PLAGNIOL-VILLARD } while (!(netstat & MACB_BIT(IDLE))); 1852439e4bfSJean-Christophe PLAGNIOL-VILLARD 1862439e4bfSJean-Christophe PLAGNIOL-VILLARD frame = macb_readl(macb, MAN); 1872439e4bfSJean-Christophe PLAGNIOL-VILLARD 1882439e4bfSJean-Christophe PLAGNIOL-VILLARD netctl = macb_readl(macb, NCR); 1892439e4bfSJean-Christophe PLAGNIOL-VILLARD netctl &= ~MACB_BIT(MPE); 1902439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, NCR, netctl); 1912439e4bfSJean-Christophe PLAGNIOL-VILLARD 1922439e4bfSJean-Christophe PLAGNIOL-VILLARD return MACB_BFEXT(DATA, frame); 1932439e4bfSJean-Christophe PLAGNIOL-VILLARD } 1942439e4bfSJean-Christophe PLAGNIOL-VILLARD 1951b8c18b9SJoe Hershberger void __weak arch_get_mdio_control(const char *name) 196416ce623SShiraz Hashim { 197416ce623SShiraz Hashim return; 198416ce623SShiraz Hashim } 199416ce623SShiraz Hashim 200b1a0006eSBo Shen #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) 2010f751d6eSSemih Hazar 2025700bb63SMike Frysinger int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value) 2030f751d6eSSemih Hazar { 204*f1dcc19bSSimon Glass #ifdef CONFIG_DM_ETH 205*f1dcc19bSSimon Glass struct udevice *dev = eth_get_dev_by_name(devname); 206*f1dcc19bSSimon Glass struct macb_device *macb = dev_get_priv(dev); 207*f1dcc19bSSimon Glass #else 2080f751d6eSSemih Hazar struct eth_device *dev = eth_get_dev_by_name(devname); 2090f751d6eSSemih Hazar struct macb_device *macb = to_macb(dev); 210*f1dcc19bSSimon Glass #endif 2110f751d6eSSemih Hazar 2120f751d6eSSemih Hazar if (macb->phy_addr != phy_adr) 2130f751d6eSSemih Hazar return -1; 2140f751d6eSSemih Hazar 215416ce623SShiraz Hashim arch_get_mdio_control(devname); 2160f751d6eSSemih Hazar *value = macb_mdio_read(macb, reg); 2170f751d6eSSemih Hazar 2180f751d6eSSemih Hazar return 0; 2190f751d6eSSemih Hazar } 2200f751d6eSSemih Hazar 2215700bb63SMike Frysinger int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value) 2220f751d6eSSemih Hazar { 223*f1dcc19bSSimon Glass #ifdef CONFIG_DM_ETH 224*f1dcc19bSSimon Glass struct udevice *dev = eth_get_dev_by_name(devname); 225*f1dcc19bSSimon Glass struct macb_device *macb = dev_get_priv(dev); 226*f1dcc19bSSimon Glass #else 2270f751d6eSSemih Hazar struct eth_device *dev = eth_get_dev_by_name(devname); 2280f751d6eSSemih Hazar struct macb_device *macb = to_macb(dev); 229*f1dcc19bSSimon Glass #endif 2300f751d6eSSemih Hazar 2310f751d6eSSemih Hazar if (macb->phy_addr != phy_adr) 2320f751d6eSSemih Hazar return -1; 2330f751d6eSSemih Hazar 234416ce623SShiraz Hashim arch_get_mdio_control(devname); 2350f751d6eSSemih Hazar macb_mdio_write(macb, reg, value); 2360f751d6eSSemih Hazar 2370f751d6eSSemih Hazar return 0; 2380f751d6eSSemih Hazar } 2390f751d6eSSemih Hazar #endif 2400f751d6eSSemih Hazar 2415ae0e382SWu, Josh #define RX 1 2425ae0e382SWu, Josh #define TX 0 2435ae0e382SWu, Josh static inline void macb_invalidate_ring_desc(struct macb_device *macb, bool rx) 2445ae0e382SWu, Josh { 2455ae0e382SWu, Josh if (rx) 2465ae0e382SWu, Josh invalidate_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma + 2475ae0e382SWu, Josh MACB_RX_DMA_DESC_SIZE); 2485ae0e382SWu, Josh else 2495ae0e382SWu, Josh invalidate_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma + 2505ae0e382SWu, Josh MACB_TX_DMA_DESC_SIZE); 2515ae0e382SWu, Josh } 2525ae0e382SWu, Josh 2535ae0e382SWu, Josh static inline void macb_flush_ring_desc(struct macb_device *macb, bool rx) 2545ae0e382SWu, Josh { 2555ae0e382SWu, Josh if (rx) 2565ae0e382SWu, Josh flush_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma + 2575ae0e382SWu, Josh MACB_RX_DMA_DESC_SIZE); 2585ae0e382SWu, Josh else 2595ae0e382SWu, Josh flush_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma + 2605ae0e382SWu, Josh MACB_TX_DMA_DESC_SIZE); 2615ae0e382SWu, Josh } 2625ae0e382SWu, Josh 2635ae0e382SWu, Josh static inline void macb_flush_rx_buffer(struct macb_device *macb) 2645ae0e382SWu, Josh { 2655ae0e382SWu, Josh flush_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + 2665ae0e382SWu, Josh MACB_RX_BUFFER_SIZE); 2675ae0e382SWu, Josh } 2685ae0e382SWu, Josh 2695ae0e382SWu, Josh static inline void macb_invalidate_rx_buffer(struct macb_device *macb) 2705ae0e382SWu, Josh { 2715ae0e382SWu, Josh invalidate_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + 2725ae0e382SWu, Josh MACB_RX_BUFFER_SIZE); 2735ae0e382SWu, Josh } 2740f751d6eSSemih Hazar 2752439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_CMD_NET) 2762439e4bfSJean-Christophe PLAGNIOL-VILLARD 277d5555b70SSimon Glass static int _macb_send(struct macb_device *macb, const char *name, void *packet, 278d5555b70SSimon Glass int length) 2792439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2802439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long paddr, ctrl; 2812439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int tx_head = macb->tx_head; 2822439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 2832439e4bfSJean-Christophe PLAGNIOL-VILLARD 2842439e4bfSJean-Christophe PLAGNIOL-VILLARD paddr = dma_map_single(packet, length, DMA_TO_DEVICE); 2852439e4bfSJean-Christophe PLAGNIOL-VILLARD 2862439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = length & TXBUF_FRMLEN_MASK; 2872439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= TXBUF_FRAME_END; 288ceef983bSAndreas Bießmann if (tx_head == (MACB_TX_RING_SIZE - 1)) { 2892439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= TXBUF_WRAP; 2902439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->tx_head = 0; 291ceef983bSAndreas Bießmann } else { 2922439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->tx_head++; 293ceef983bSAndreas Bießmann } 2942439e4bfSJean-Christophe PLAGNIOL-VILLARD 2952439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->tx_ring[tx_head].ctrl = ctrl; 2962439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->tx_ring[tx_head].addr = paddr; 2972439e4bfSJean-Christophe PLAGNIOL-VILLARD barrier(); 2985ae0e382SWu, Josh macb_flush_ring_desc(macb, TX); 2995ae0e382SWu, Josh /* Do we need check paddr and length is dcache line aligned? */ 300f589f8ccSSimon Glass flush_dcache_range(paddr, paddr + ALIGN(length, ARCH_DMA_MINALIGN)); 3012439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART)); 3022439e4bfSJean-Christophe PLAGNIOL-VILLARD 3032439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 3042439e4bfSJean-Christophe PLAGNIOL-VILLARD * I guess this is necessary because the networking core may 3052439e4bfSJean-Christophe PLAGNIOL-VILLARD * re-use the transmit buffer as soon as we return... 3062439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 307ceef983bSAndreas Bießmann for (i = 0; i <= MACB_TX_TIMEOUT; i++) { 3082439e4bfSJean-Christophe PLAGNIOL-VILLARD barrier(); 3095ae0e382SWu, Josh macb_invalidate_ring_desc(macb, TX); 3102439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = macb->tx_ring[tx_head].ctrl; 3112439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ctrl & TXBUF_USED) 3122439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 3132439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 3142439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3152439e4bfSJean-Christophe PLAGNIOL-VILLARD 3162439e4bfSJean-Christophe PLAGNIOL-VILLARD dma_unmap_single(packet, length, paddr); 3172439e4bfSJean-Christophe PLAGNIOL-VILLARD 318ceef983bSAndreas Bießmann if (i <= MACB_TX_TIMEOUT) { 3192439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ctrl & TXBUF_UNDERRUN) 320d5555b70SSimon Glass printf("%s: TX underrun\n", name); 3212439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ctrl & TXBUF_EXHAUSTED) 322d5555b70SSimon Glass printf("%s: TX buffers exhausted in mid frame\n", name); 3232439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 324d5555b70SSimon Glass printf("%s: TX timeout\n", name); 3252439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3262439e4bfSJean-Christophe PLAGNIOL-VILLARD 3272439e4bfSJean-Christophe PLAGNIOL-VILLARD /* No one cares anyway */ 3282439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 3292439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3302439e4bfSJean-Christophe PLAGNIOL-VILLARD 3312439e4bfSJean-Christophe PLAGNIOL-VILLARD static void reclaim_rx_buffers(struct macb_device *macb, 3322439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int new_tail) 3332439e4bfSJean-Christophe PLAGNIOL-VILLARD { 3342439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int i; 3352439e4bfSJean-Christophe PLAGNIOL-VILLARD 3362439e4bfSJean-Christophe PLAGNIOL-VILLARD i = macb->rx_tail; 3375ae0e382SWu, Josh 3385ae0e382SWu, Josh macb_invalidate_ring_desc(macb, RX); 3392439e4bfSJean-Christophe PLAGNIOL-VILLARD while (i > new_tail) { 3402439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->rx_ring[i].addr &= ~RXADDR_USED; 3412439e4bfSJean-Christophe PLAGNIOL-VILLARD i++; 342ceef983bSAndreas Bießmann if (i > MACB_RX_RING_SIZE) 3432439e4bfSJean-Christophe PLAGNIOL-VILLARD i = 0; 3442439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3452439e4bfSJean-Christophe PLAGNIOL-VILLARD 3462439e4bfSJean-Christophe PLAGNIOL-VILLARD while (i < new_tail) { 3472439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->rx_ring[i].addr &= ~RXADDR_USED; 3482439e4bfSJean-Christophe PLAGNIOL-VILLARD i++; 3492439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3502439e4bfSJean-Christophe PLAGNIOL-VILLARD 3512439e4bfSJean-Christophe PLAGNIOL-VILLARD barrier(); 3525ae0e382SWu, Josh macb_flush_ring_desc(macb, RX); 3532439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->rx_tail = new_tail; 3542439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3552439e4bfSJean-Christophe PLAGNIOL-VILLARD 356d5555b70SSimon Glass static int _macb_recv(struct macb_device *macb, uchar **packetp) 3572439e4bfSJean-Christophe PLAGNIOL-VILLARD { 358d5555b70SSimon Glass unsigned int next_rx_tail = macb->next_rx_tail; 3592439e4bfSJean-Christophe PLAGNIOL-VILLARD void *buffer; 3602439e4bfSJean-Christophe PLAGNIOL-VILLARD int length; 3612439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 status; 3622439e4bfSJean-Christophe PLAGNIOL-VILLARD 363d5555b70SSimon Glass macb->wrapped = false; 3642439e4bfSJean-Christophe PLAGNIOL-VILLARD for (;;) { 3655ae0e382SWu, Josh macb_invalidate_ring_desc(macb, RX); 3665ae0e382SWu, Josh 367d5555b70SSimon Glass if (!(macb->rx_ring[next_rx_tail].addr & RXADDR_USED)) 368d5555b70SSimon Glass return -EAGAIN; 3692439e4bfSJean-Christophe PLAGNIOL-VILLARD 370d5555b70SSimon Glass status = macb->rx_ring[next_rx_tail].ctrl; 3712439e4bfSJean-Christophe PLAGNIOL-VILLARD if (status & RXBUF_FRAME_START) { 372d5555b70SSimon Glass if (next_rx_tail != macb->rx_tail) 373d5555b70SSimon Glass reclaim_rx_buffers(macb, next_rx_tail); 374d5555b70SSimon Glass macb->wrapped = false; 3752439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3762439e4bfSJean-Christophe PLAGNIOL-VILLARD 3772439e4bfSJean-Christophe PLAGNIOL-VILLARD if (status & RXBUF_FRAME_END) { 3782439e4bfSJean-Christophe PLAGNIOL-VILLARD buffer = macb->rx_buffer + 128 * macb->rx_tail; 3792439e4bfSJean-Christophe PLAGNIOL-VILLARD length = status & RXBUF_FRMLEN_MASK; 3805ae0e382SWu, Josh 3815ae0e382SWu, Josh macb_invalidate_rx_buffer(macb); 382d5555b70SSimon Glass if (macb->wrapped) { 3832439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int headlen, taillen; 3842439e4bfSJean-Christophe PLAGNIOL-VILLARD 385ceef983bSAndreas Bießmann headlen = 128 * (MACB_RX_RING_SIZE 3862439e4bfSJean-Christophe PLAGNIOL-VILLARD - macb->rx_tail); 3872439e4bfSJean-Christophe PLAGNIOL-VILLARD taillen = length - headlen; 3881fd92db8SJoe Hershberger memcpy((void *)net_rx_packets[0], 3892439e4bfSJean-Christophe PLAGNIOL-VILLARD buffer, headlen); 3901fd92db8SJoe Hershberger memcpy((void *)net_rx_packets[0] + headlen, 3912439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->rx_buffer, taillen); 392d5555b70SSimon Glass *packetp = (void *)net_rx_packets[0]; 393d5555b70SSimon Glass } else { 394d5555b70SSimon Glass *packetp = buffer; 3952439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3962439e4bfSJean-Christophe PLAGNIOL-VILLARD 397d5555b70SSimon Glass if (++next_rx_tail >= MACB_RX_RING_SIZE) 398d5555b70SSimon Glass next_rx_tail = 0; 399d5555b70SSimon Glass macb->next_rx_tail = next_rx_tail; 400d5555b70SSimon Glass return length; 4012439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 402d5555b70SSimon Glass if (++next_rx_tail >= MACB_RX_RING_SIZE) { 403d5555b70SSimon Glass macb->wrapped = true; 404d5555b70SSimon Glass next_rx_tail = 0; 4052439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4062439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4072439e4bfSJean-Christophe PLAGNIOL-VILLARD barrier(); 4082439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4092439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4102439e4bfSJean-Christophe PLAGNIOL-VILLARD 411d5555b70SSimon Glass static void macb_phy_reset(struct macb_device *macb, const char *name) 4122439e4bfSJean-Christophe PLAGNIOL-VILLARD { 4132439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 4142439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 status, adv; 4152439e4bfSJean-Christophe PLAGNIOL-VILLARD 4162439e4bfSJean-Christophe PLAGNIOL-VILLARD adv = ADVERTISE_CSMA | ADVERTISE_ALL; 4172439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_mdio_write(macb, MII_ADVERTISE, adv); 418d5555b70SSimon Glass printf("%s: Starting autonegotiation...\n", name); 4192439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE 4202439e4bfSJean-Christophe PLAGNIOL-VILLARD | BMCR_ANRESTART)); 4212439e4bfSJean-Christophe PLAGNIOL-VILLARD 422ceef983bSAndreas Bießmann for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) { 4232439e4bfSJean-Christophe PLAGNIOL-VILLARD status = macb_mdio_read(macb, MII_BMSR); 4242439e4bfSJean-Christophe PLAGNIOL-VILLARD if (status & BMSR_ANEGCOMPLETE) 4252439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 4262439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(100); 4272439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4282439e4bfSJean-Christophe PLAGNIOL-VILLARD 4292439e4bfSJean-Christophe PLAGNIOL-VILLARD if (status & BMSR_ANEGCOMPLETE) 430d5555b70SSimon Glass printf("%s: Autonegotiation complete\n", name); 4312439e4bfSJean-Christophe PLAGNIOL-VILLARD else 4322439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: Autonegotiation timed out (status=0x%04x)\n", 433d5555b70SSimon Glass name, status); 4342439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4352439e4bfSJean-Christophe PLAGNIOL-VILLARD 436fc01ea1eSGunnar Rangoy #ifdef CONFIG_MACB_SEARCH_PHY 437fc01ea1eSGunnar Rangoy static int macb_phy_find(struct macb_device *macb) 438fc01ea1eSGunnar Rangoy { 439fc01ea1eSGunnar Rangoy int i; 440fc01ea1eSGunnar Rangoy u16 phy_id; 441fc01ea1eSGunnar Rangoy 442fc01ea1eSGunnar Rangoy /* Search for PHY... */ 443fc01ea1eSGunnar Rangoy for (i = 0; i < 32; i++) { 444fc01ea1eSGunnar Rangoy macb->phy_addr = i; 445fc01ea1eSGunnar Rangoy phy_id = macb_mdio_read(macb, MII_PHYSID1); 446fc01ea1eSGunnar Rangoy if (phy_id != 0xffff) { 447fc01ea1eSGunnar Rangoy printf("%s: PHY present at %d\n", macb->netdev.name, i); 448fc01ea1eSGunnar Rangoy return 1; 449fc01ea1eSGunnar Rangoy } 450fc01ea1eSGunnar Rangoy } 451fc01ea1eSGunnar Rangoy 452fc01ea1eSGunnar Rangoy /* PHY isn't up to snuff */ 4536ed0e940SAndreas Bießmann printf("%s: PHY not found\n", macb->netdev.name); 454fc01ea1eSGunnar Rangoy 455fc01ea1eSGunnar Rangoy return 0; 456fc01ea1eSGunnar Rangoy } 457fc01ea1eSGunnar Rangoy #endif /* CONFIG_MACB_SEARCH_PHY */ 458fc01ea1eSGunnar Rangoy 459fc01ea1eSGunnar Rangoy 460d5555b70SSimon Glass static int macb_phy_init(struct macb_device *macb, const char *name) 4612439e4bfSJean-Christophe PLAGNIOL-VILLARD { 462b1a0006eSBo Shen #ifdef CONFIG_PHYLIB 463b1a0006eSBo Shen struct phy_device *phydev; 464b1a0006eSBo Shen #endif 4652439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 ncfgr; 4662439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 phy_id, status, adv, lpa; 4672439e4bfSJean-Christophe PLAGNIOL-VILLARD int media, speed, duplex; 4682439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 4692439e4bfSJean-Christophe PLAGNIOL-VILLARD 470d5555b70SSimon Glass arch_get_mdio_control(name); 471fc01ea1eSGunnar Rangoy #ifdef CONFIG_MACB_SEARCH_PHY 472fc01ea1eSGunnar Rangoy /* Auto-detect phy_addr */ 473ceef983bSAndreas Bießmann if (!macb_phy_find(macb)) 474fc01ea1eSGunnar Rangoy return 0; 475fc01ea1eSGunnar Rangoy #endif /* CONFIG_MACB_SEARCH_PHY */ 476fc01ea1eSGunnar Rangoy 4772439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check if the PHY is up to snuff... */ 4782439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_id = macb_mdio_read(macb, MII_PHYSID1); 4792439e4bfSJean-Christophe PLAGNIOL-VILLARD if (phy_id == 0xffff) { 480d5555b70SSimon Glass printf("%s: No PHY present\n", name); 4812439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 4822439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4832439e4bfSJean-Christophe PLAGNIOL-VILLARD 484b1a0006eSBo Shen #ifdef CONFIG_PHYLIB 4858314ccd8SBo Shen /* need to consider other phy interface mode */ 486d5555b70SSimon Glass phydev = phy_connect(macb->bus, macb->phy_addr, &macb->netdev, 4878314ccd8SBo Shen PHY_INTERFACE_MODE_RGMII); 4888314ccd8SBo Shen if (!phydev) { 4898314ccd8SBo Shen printf("phy_connect failed\n"); 4908314ccd8SBo Shen return -ENODEV; 4918314ccd8SBo Shen } 4928314ccd8SBo Shen 493b1a0006eSBo Shen phy_config(phydev); 494b1a0006eSBo Shen #endif 495b1a0006eSBo Shen 4962439e4bfSJean-Christophe PLAGNIOL-VILLARD status = macb_mdio_read(macb, MII_BMSR); 4972439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(status & BMSR_LSTATUS)) { 4982439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Try to re-negotiate if we don't have link already. */ 499d5555b70SSimon Glass macb_phy_reset(macb, name); 5002439e4bfSJean-Christophe PLAGNIOL-VILLARD 501ceef983bSAndreas Bießmann for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) { 5022439e4bfSJean-Christophe PLAGNIOL-VILLARD status = macb_mdio_read(macb, MII_BMSR); 5032439e4bfSJean-Christophe PLAGNIOL-VILLARD if (status & BMSR_LSTATUS) 5042439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 5052439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(100); 5062439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5072439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5082439e4bfSJean-Christophe PLAGNIOL-VILLARD 5092439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(status & BMSR_LSTATUS)) { 5102439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: link down (status: 0x%04x)\n", 511d5555b70SSimon Glass name, status); 5122439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 513d256be29SBo Shen } 514d256be29SBo Shen 51575b03cf1SGregory CLEMENT /* First check for GMAC and that it is GiB capable */ 51675b03cf1SGregory CLEMENT if (gem_is_gigabit_capable(macb)) { 517d256be29SBo Shen lpa = macb_mdio_read(macb, MII_STAT1000); 518d256be29SBo Shen 51947609577SAndreas Bießmann if (lpa & (LPA_1000FULL | LPA_1000HALF)) { 52047609577SAndreas Bießmann duplex = ((lpa & LPA_1000FULL) ? 1 : 0); 52147609577SAndreas Bießmann 52247609577SAndreas Bießmann printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n", 523d5555b70SSimon Glass name, 524d256be29SBo Shen duplex ? "full" : "half", 525d256be29SBo Shen lpa); 526d256be29SBo Shen 527d256be29SBo Shen ncfgr = macb_readl(macb, NCFGR); 52847609577SAndreas Bießmann ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); 529d256be29SBo Shen ncfgr |= GEM_BIT(GBE); 53047609577SAndreas Bießmann 531d256be29SBo Shen if (duplex) 532d256be29SBo Shen ncfgr |= MACB_BIT(FD); 53347609577SAndreas Bießmann 534d256be29SBo Shen macb_writel(macb, NCFGR, ncfgr); 535d256be29SBo Shen 536d256be29SBo Shen return 1; 537d256be29SBo Shen } 538d256be29SBo Shen } 539d256be29SBo Shen 540d256be29SBo Shen /* fall back for EMAC checking */ 5412439e4bfSJean-Christophe PLAGNIOL-VILLARD adv = macb_mdio_read(macb, MII_ADVERTISE); 5422439e4bfSJean-Christophe PLAGNIOL-VILLARD lpa = macb_mdio_read(macb, MII_LPA); 5432439e4bfSJean-Christophe PLAGNIOL-VILLARD media = mii_nway_result(lpa & adv); 5442439e4bfSJean-Christophe PLAGNIOL-VILLARD speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) 5452439e4bfSJean-Christophe PLAGNIOL-VILLARD ? 1 : 0); 5462439e4bfSJean-Christophe PLAGNIOL-VILLARD duplex = (media & ADVERTISE_FULL) ? 1 : 0; 5472439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", 548d5555b70SSimon Glass name, 5492439e4bfSJean-Christophe PLAGNIOL-VILLARD speed ? "100" : "10", 5502439e4bfSJean-Christophe PLAGNIOL-VILLARD duplex ? "full" : "half", 5512439e4bfSJean-Christophe PLAGNIOL-VILLARD lpa); 5522439e4bfSJean-Christophe PLAGNIOL-VILLARD 5532439e4bfSJean-Christophe PLAGNIOL-VILLARD ncfgr = macb_readl(macb, NCFGR); 554c83cb5f6SBo Shen ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE)); 5552439e4bfSJean-Christophe PLAGNIOL-VILLARD if (speed) 5562439e4bfSJean-Christophe PLAGNIOL-VILLARD ncfgr |= MACB_BIT(SPD); 5572439e4bfSJean-Christophe PLAGNIOL-VILLARD if (duplex) 5582439e4bfSJean-Christophe PLAGNIOL-VILLARD ncfgr |= MACB_BIT(FD); 5592439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, NCFGR, ncfgr); 560d256be29SBo Shen 5612439e4bfSJean-Christophe PLAGNIOL-VILLARD return 1; 5622439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5632439e4bfSJean-Christophe PLAGNIOL-VILLARD 564ade4ea4dSWu, Josh static int gmac_init_multi_queues(struct macb_device *macb) 565ade4ea4dSWu, Josh { 566ade4ea4dSWu, Josh int i, num_queues = 1; 567ade4ea4dSWu, Josh u32 queue_mask; 568ade4ea4dSWu, Josh 569ade4ea4dSWu, Josh /* bit 0 is never set but queue 0 always exists */ 570ade4ea4dSWu, Josh queue_mask = gem_readl(macb, DCFG6) & 0xff; 571ade4ea4dSWu, Josh queue_mask |= 0x1; 572ade4ea4dSWu, Josh 573ade4ea4dSWu, Josh for (i = 1; i < MACB_MAX_QUEUES; i++) 574ade4ea4dSWu, Josh if (queue_mask & (1 << i)) 575ade4ea4dSWu, Josh num_queues++; 576ade4ea4dSWu, Josh 577ade4ea4dSWu, Josh macb->dummy_desc->ctrl = TXBUF_USED; 578ade4ea4dSWu, Josh macb->dummy_desc->addr = 0; 579ade4ea4dSWu, Josh flush_dcache_range(macb->dummy_desc_dma, macb->dummy_desc_dma + 580ade4ea4dSWu, Josh MACB_TX_DUMMY_DMA_DESC_SIZE); 581ade4ea4dSWu, Josh 582ade4ea4dSWu, Josh for (i = 1; i < num_queues; i++) 583ade4ea4dSWu, Josh gem_writel_queue_TBQP(macb, macb->dummy_desc_dma, i - 1); 584ade4ea4dSWu, Josh 585ade4ea4dSWu, Josh return 0; 586ade4ea4dSWu, Josh } 587ade4ea4dSWu, Josh 588d5555b70SSimon Glass static int _macb_init(struct macb_device *macb, const char *name) 5892439e4bfSJean-Christophe PLAGNIOL-VILLARD { 5902439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long paddr; 5912439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 5922439e4bfSJean-Christophe PLAGNIOL-VILLARD 5932439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 5942439e4bfSJean-Christophe PLAGNIOL-VILLARD * macb_halt should have been called at some point before now, 5952439e4bfSJean-Christophe PLAGNIOL-VILLARD * so we'll assume the controller is idle. 5962439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 5972439e4bfSJean-Christophe PLAGNIOL-VILLARD 5982439e4bfSJean-Christophe PLAGNIOL-VILLARD /* initialize DMA descriptors */ 5992439e4bfSJean-Christophe PLAGNIOL-VILLARD paddr = macb->rx_buffer_dma; 600ceef983bSAndreas Bießmann for (i = 0; i < MACB_RX_RING_SIZE; i++) { 601ceef983bSAndreas Bießmann if (i == (MACB_RX_RING_SIZE - 1)) 6022439e4bfSJean-Christophe PLAGNIOL-VILLARD paddr |= RXADDR_WRAP; 6032439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->rx_ring[i].addr = paddr; 6042439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->rx_ring[i].ctrl = 0; 6052439e4bfSJean-Christophe PLAGNIOL-VILLARD paddr += 128; 6062439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6075ae0e382SWu, Josh macb_flush_ring_desc(macb, RX); 6085ae0e382SWu, Josh macb_flush_rx_buffer(macb); 6095ae0e382SWu, Josh 610ceef983bSAndreas Bießmann for (i = 0; i < MACB_TX_RING_SIZE; i++) { 6112439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->tx_ring[i].addr = 0; 612ceef983bSAndreas Bießmann if (i == (MACB_TX_RING_SIZE - 1)) 6132439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP; 6142439e4bfSJean-Christophe PLAGNIOL-VILLARD else 6152439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->tx_ring[i].ctrl = TXBUF_USED; 6162439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6175ae0e382SWu, Josh macb_flush_ring_desc(macb, TX); 6185ae0e382SWu, Josh 619ceef983bSAndreas Bießmann macb->rx_tail = 0; 620ceef983bSAndreas Bießmann macb->tx_head = 0; 621ceef983bSAndreas Bießmann macb->tx_tail = 0; 622d5555b70SSimon Glass macb->next_rx_tail = 0; 6232439e4bfSJean-Christophe PLAGNIOL-VILLARD 6242439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, RBQP, macb->rx_ring_dma); 6252439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, TBQP, macb->tx_ring_dma); 6262439e4bfSJean-Christophe PLAGNIOL-VILLARD 627d256be29SBo Shen if (macb_is_gem(macb)) { 628ade4ea4dSWu, Josh /* Check the multi queue and initialize the queue for tx */ 629ade4ea4dSWu, Josh gmac_init_multi_queues(macb); 630ade4ea4dSWu, Josh 631cabf61ceSBo Shen /* 632cabf61ceSBo Shen * When the GMAC IP with GE feature, this bit is used to 633cabf61ceSBo Shen * select interface between RGMII and GMII. 634cabf61ceSBo Shen * When the GMAC IP without GE feature, this bit is used 635cabf61ceSBo Shen * to select interface between RMII and MII. 636cabf61ceSBo Shen */ 637cabf61ceSBo Shen #if defined(CONFIG_RGMII) || defined(CONFIG_RMII) 638d256be29SBo Shen gem_writel(macb, UR, GEM_BIT(RGMII)); 639d256be29SBo Shen #else 640d256be29SBo Shen gem_writel(macb, UR, 0); 641d256be29SBo Shen #endif 642d256be29SBo Shen } else { 6432439e4bfSJean-Christophe PLAGNIOL-VILLARD /* choose RMII or MII mode. This depends on the board */ 6442439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_RMII 645d8f64b44SBo Shen #ifdef CONFIG_AT91FAMILY 6467263ef19SStelian Pop macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN)); 6477263ef19SStelian Pop #else 6482439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, USRIO, 0); 6497263ef19SStelian Pop #endif 6507263ef19SStelian Pop #else 651d8f64b44SBo Shen #ifdef CONFIG_AT91FAMILY 6527263ef19SStelian Pop macb_writel(macb, USRIO, MACB_BIT(CLKEN)); 6532439e4bfSJean-Christophe PLAGNIOL-VILLARD #else 6542439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, USRIO, MACB_BIT(MII)); 6552439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 6567263ef19SStelian Pop #endif /* CONFIG_RMII */ 657d256be29SBo Shen } 6582439e4bfSJean-Christophe PLAGNIOL-VILLARD 659d5555b70SSimon Glass if (!macb_phy_init(macb, name)) 660422b1a01SBen Warren return -1; 6612439e4bfSJean-Christophe PLAGNIOL-VILLARD 6622439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Enable TX and RX */ 6632439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE)); 6642439e4bfSJean-Christophe PLAGNIOL-VILLARD 665422b1a01SBen Warren return 0; 6662439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6672439e4bfSJean-Christophe PLAGNIOL-VILLARD 668d5555b70SSimon Glass static void _macb_halt(struct macb_device *macb) 6692439e4bfSJean-Christophe PLAGNIOL-VILLARD { 6702439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 ncr, tsr; 6712439e4bfSJean-Christophe PLAGNIOL-VILLARD 6722439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Halt the controller and wait for any ongoing transmission to end. */ 6732439e4bfSJean-Christophe PLAGNIOL-VILLARD ncr = macb_readl(macb, NCR); 6742439e4bfSJean-Christophe PLAGNIOL-VILLARD ncr |= MACB_BIT(THALT); 6752439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, NCR, ncr); 6762439e4bfSJean-Christophe PLAGNIOL-VILLARD 6772439e4bfSJean-Christophe PLAGNIOL-VILLARD do { 6782439e4bfSJean-Christophe PLAGNIOL-VILLARD tsr = macb_readl(macb, TSR); 6792439e4bfSJean-Christophe PLAGNIOL-VILLARD } while (tsr & MACB_BIT(TGO)); 6802439e4bfSJean-Christophe PLAGNIOL-VILLARD 6812439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Disable TX and RX, and clear statistics */ 6822439e4bfSJean-Christophe PLAGNIOL-VILLARD macb_writel(macb, NCR, MACB_BIT(CLRSTAT)); 6832439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6842439e4bfSJean-Christophe PLAGNIOL-VILLARD 685d5555b70SSimon Glass static int _macb_write_hwaddr(struct macb_device *macb, unsigned char *enetaddr) 6866bb46790SBen Warren { 6876bb46790SBen Warren u32 hwaddr_bottom; 6886bb46790SBen Warren u16 hwaddr_top; 6896bb46790SBen Warren 6906bb46790SBen Warren /* set hardware address */ 691d5555b70SSimon Glass hwaddr_bottom = enetaddr[0] | enetaddr[1] << 8 | 692d5555b70SSimon Glass enetaddr[2] << 16 | enetaddr[3] << 24; 6936bb46790SBen Warren macb_writel(macb, SA1B, hwaddr_bottom); 694d5555b70SSimon Glass hwaddr_top = enetaddr[4] | enetaddr[5] << 8; 6956bb46790SBen Warren macb_writel(macb, SA1T, hwaddr_top); 6966bb46790SBen Warren return 0; 6976bb46790SBen Warren } 6986bb46790SBen Warren 699d256be29SBo Shen static u32 macb_mdc_clk_div(int id, struct macb_device *macb) 700d256be29SBo Shen { 701d256be29SBo Shen u32 config; 702d256be29SBo Shen unsigned long macb_hz = get_macb_pclk_rate(id); 703d256be29SBo Shen 704d256be29SBo Shen if (macb_hz < 20000000) 705d256be29SBo Shen config = MACB_BF(CLK, MACB_CLK_DIV8); 706d256be29SBo Shen else if (macb_hz < 40000000) 707d256be29SBo Shen config = MACB_BF(CLK, MACB_CLK_DIV16); 708d256be29SBo Shen else if (macb_hz < 80000000) 709d256be29SBo Shen config = MACB_BF(CLK, MACB_CLK_DIV32); 710d256be29SBo Shen else 711d256be29SBo Shen config = MACB_BF(CLK, MACB_CLK_DIV64); 712d256be29SBo Shen 713d256be29SBo Shen return config; 714d256be29SBo Shen } 715d256be29SBo Shen 716d256be29SBo Shen static u32 gem_mdc_clk_div(int id, struct macb_device *macb) 717d256be29SBo Shen { 718d256be29SBo Shen u32 config; 719d256be29SBo Shen unsigned long macb_hz = get_macb_pclk_rate(id); 720d256be29SBo Shen 721d256be29SBo Shen if (macb_hz < 20000000) 722d256be29SBo Shen config = GEM_BF(CLK, GEM_CLK_DIV8); 723d256be29SBo Shen else if (macb_hz < 40000000) 724d256be29SBo Shen config = GEM_BF(CLK, GEM_CLK_DIV16); 725d256be29SBo Shen else if (macb_hz < 80000000) 726d256be29SBo Shen config = GEM_BF(CLK, GEM_CLK_DIV32); 727d256be29SBo Shen else if (macb_hz < 120000000) 728d256be29SBo Shen config = GEM_BF(CLK, GEM_CLK_DIV48); 729d256be29SBo Shen else if (macb_hz < 160000000) 730d256be29SBo Shen config = GEM_BF(CLK, GEM_CLK_DIV64); 731d256be29SBo Shen else 732d256be29SBo Shen config = GEM_BF(CLK, GEM_CLK_DIV96); 733d256be29SBo Shen 734d256be29SBo Shen return config; 735d256be29SBo Shen } 736d256be29SBo Shen 73732e4f6bfSBo Shen /* 73832e4f6bfSBo Shen * Get the DMA bus width field of the network configuration register that we 73932e4f6bfSBo Shen * should program. We find the width from decoding the design configuration 74032e4f6bfSBo Shen * register to find the maximum supported data bus width. 74132e4f6bfSBo Shen */ 74232e4f6bfSBo Shen static u32 macb_dbw(struct macb_device *macb) 74332e4f6bfSBo Shen { 74432e4f6bfSBo Shen switch (GEM_BFEXT(DBWDEF, gem_readl(macb, DCFG1))) { 74532e4f6bfSBo Shen case 4: 74632e4f6bfSBo Shen return GEM_BF(DBW, GEM_DBW128); 74732e4f6bfSBo Shen case 2: 74832e4f6bfSBo Shen return GEM_BF(DBW, GEM_DBW64); 74932e4f6bfSBo Shen case 1: 75032e4f6bfSBo Shen default: 75132e4f6bfSBo Shen return GEM_BF(DBW, GEM_DBW32); 75232e4f6bfSBo Shen } 75332e4f6bfSBo Shen } 75432e4f6bfSBo Shen 755d5555b70SSimon Glass static void _macb_eth_initialize(struct macb_device *macb) 7562439e4bfSJean-Christophe PLAGNIOL-VILLARD { 757d5555b70SSimon Glass int id = 0; /* This is not used by functions we call */ 7582439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 ncfgr; 7592439e4bfSJean-Christophe PLAGNIOL-VILLARD 760d5555b70SSimon Glass /* TODO: we need check the rx/tx_ring_dma is dcache line aligned */ 761ceef983bSAndreas Bießmann macb->rx_buffer = dma_alloc_coherent(MACB_RX_BUFFER_SIZE, 7622439e4bfSJean-Christophe PLAGNIOL-VILLARD &macb->rx_buffer_dma); 7635ae0e382SWu, Josh macb->rx_ring = dma_alloc_coherent(MACB_RX_DMA_DESC_SIZE, 7642439e4bfSJean-Christophe PLAGNIOL-VILLARD &macb->rx_ring_dma); 7655ae0e382SWu, Josh macb->tx_ring = dma_alloc_coherent(MACB_TX_DMA_DESC_SIZE, 7662439e4bfSJean-Christophe PLAGNIOL-VILLARD &macb->tx_ring_dma); 767ade4ea4dSWu, Josh macb->dummy_desc = dma_alloc_coherent(MACB_TX_DUMMY_DMA_DESC_SIZE, 768ade4ea4dSWu, Josh &macb->dummy_desc_dma); 7692439e4bfSJean-Christophe PLAGNIOL-VILLARD 770d5555b70SSimon Glass /* 771d5555b70SSimon Glass * Do some basic initialization so that we at least can talk 772d5555b70SSimon Glass * to the PHY 773d5555b70SSimon Glass */ 774d5555b70SSimon Glass if (macb_is_gem(macb)) { 775d5555b70SSimon Glass ncfgr = gem_mdc_clk_div(id, macb); 776d5555b70SSimon Glass ncfgr |= macb_dbw(macb); 777d5555b70SSimon Glass } else { 778d5555b70SSimon Glass ncfgr = macb_mdc_clk_div(id, macb); 779d5555b70SSimon Glass } 780d5555b70SSimon Glass 781d5555b70SSimon Glass macb_writel(macb, NCFGR, ncfgr); 782d5555b70SSimon Glass } 783d5555b70SSimon Glass 784*f1dcc19bSSimon Glass #ifndef CONFIG_DM_ETH 785d5555b70SSimon Glass static int macb_send(struct eth_device *netdev, void *packet, int length) 786d5555b70SSimon Glass { 787d5555b70SSimon Glass struct macb_device *macb = to_macb(netdev); 788d5555b70SSimon Glass 789d5555b70SSimon Glass return _macb_send(macb, netdev->name, packet, length); 790d5555b70SSimon Glass } 791d5555b70SSimon Glass 792d5555b70SSimon Glass static int macb_recv(struct eth_device *netdev) 793d5555b70SSimon Glass { 794d5555b70SSimon Glass struct macb_device *macb = to_macb(netdev); 795d5555b70SSimon Glass uchar *packet; 796d5555b70SSimon Glass int length; 797d5555b70SSimon Glass 798d5555b70SSimon Glass macb->wrapped = false; 799d5555b70SSimon Glass for (;;) { 800d5555b70SSimon Glass macb->next_rx_tail = macb->rx_tail; 801d5555b70SSimon Glass length = _macb_recv(macb, &packet); 802d5555b70SSimon Glass if (length >= 0) { 803d5555b70SSimon Glass net_process_received_packet(packet, length); 804d5555b70SSimon Glass reclaim_rx_buffers(macb, macb->next_rx_tail); 805d5555b70SSimon Glass } else if (length < 0) { 806d5555b70SSimon Glass return length; 807d5555b70SSimon Glass } 808d5555b70SSimon Glass } 809d5555b70SSimon Glass } 810d5555b70SSimon Glass 811d5555b70SSimon Glass static int macb_init(struct eth_device *netdev, bd_t *bd) 812d5555b70SSimon Glass { 813d5555b70SSimon Glass struct macb_device *macb = to_macb(netdev); 814d5555b70SSimon Glass 815d5555b70SSimon Glass return _macb_init(macb, netdev->name); 816d5555b70SSimon Glass } 817d5555b70SSimon Glass 818d5555b70SSimon Glass static void macb_halt(struct eth_device *netdev) 819d5555b70SSimon Glass { 820d5555b70SSimon Glass struct macb_device *macb = to_macb(netdev); 821d5555b70SSimon Glass 822d5555b70SSimon Glass return _macb_halt(macb); 823d5555b70SSimon Glass } 824d5555b70SSimon Glass 825d5555b70SSimon Glass static int macb_write_hwaddr(struct eth_device *netdev) 826d5555b70SSimon Glass { 827d5555b70SSimon Glass struct macb_device *macb = to_macb(netdev); 828d5555b70SSimon Glass 829d5555b70SSimon Glass return _macb_write_hwaddr(macb, netdev->enetaddr); 830d5555b70SSimon Glass } 831d5555b70SSimon Glass 832d5555b70SSimon Glass int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) 833d5555b70SSimon Glass { 834d5555b70SSimon Glass struct macb_device *macb; 835d5555b70SSimon Glass struct eth_device *netdev; 836d5555b70SSimon Glass 837d5555b70SSimon Glass macb = malloc(sizeof(struct macb_device)); 838d5555b70SSimon Glass if (!macb) { 839d5555b70SSimon Glass printf("Error: Failed to allocate memory for MACB%d\n", id); 840d5555b70SSimon Glass return -1; 841d5555b70SSimon Glass } 842d5555b70SSimon Glass memset(macb, 0, sizeof(struct macb_device)); 843d5555b70SSimon Glass 844d5555b70SSimon Glass netdev = &macb->netdev; 8455ae0e382SWu, Josh 8462439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->regs = regs; 8472439e4bfSJean-Christophe PLAGNIOL-VILLARD macb->phy_addr = phy_addr; 8482439e4bfSJean-Christophe PLAGNIOL-VILLARD 849d256be29SBo Shen if (macb_is_gem(macb)) 850d256be29SBo Shen sprintf(netdev->name, "gmac%d", id); 851d256be29SBo Shen else 8522439e4bfSJean-Christophe PLAGNIOL-VILLARD sprintf(netdev->name, "macb%d", id); 853d256be29SBo Shen 8542439e4bfSJean-Christophe PLAGNIOL-VILLARD netdev->init = macb_init; 8552439e4bfSJean-Christophe PLAGNIOL-VILLARD netdev->halt = macb_halt; 8562439e4bfSJean-Christophe PLAGNIOL-VILLARD netdev->send = macb_send; 8572439e4bfSJean-Christophe PLAGNIOL-VILLARD netdev->recv = macb_recv; 8586bb46790SBen Warren netdev->write_hwaddr = macb_write_hwaddr; 8592439e4bfSJean-Christophe PLAGNIOL-VILLARD 860d5555b70SSimon Glass _macb_eth_initialize(macb); 8612439e4bfSJean-Christophe PLAGNIOL-VILLARD 8622439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_register(netdev); 8632439e4bfSJean-Christophe PLAGNIOL-VILLARD 864b1a0006eSBo Shen #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) 8650f751d6eSSemih Hazar miiphy_register(netdev->name, macb_miiphy_read, macb_miiphy_write); 866b1a0006eSBo Shen macb->bus = miiphy_get_dev_by_name(netdev->name); 8670f751d6eSSemih Hazar #endif 8682439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 8692439e4bfSJean-Christophe PLAGNIOL-VILLARD } 870*f1dcc19bSSimon Glass #endif /* !CONFIG_DM_ETH */ 871*f1dcc19bSSimon Glass 872*f1dcc19bSSimon Glass #ifdef CONFIG_DM_ETH 873*f1dcc19bSSimon Glass 874*f1dcc19bSSimon Glass static int macb_start(struct udevice *dev) 875*f1dcc19bSSimon Glass { 876*f1dcc19bSSimon Glass struct macb_device *macb = dev_get_priv(dev); 877*f1dcc19bSSimon Glass 878*f1dcc19bSSimon Glass return _macb_init(macb, dev->name); 879*f1dcc19bSSimon Glass } 880*f1dcc19bSSimon Glass 881*f1dcc19bSSimon Glass static int macb_send(struct udevice *dev, void *packet, int length) 882*f1dcc19bSSimon Glass { 883*f1dcc19bSSimon Glass struct macb_device *macb = dev_get_priv(dev); 884*f1dcc19bSSimon Glass 885*f1dcc19bSSimon Glass return _macb_send(macb, dev->name, packet, length); 886*f1dcc19bSSimon Glass } 887*f1dcc19bSSimon Glass 888*f1dcc19bSSimon Glass static int macb_recv(struct udevice *dev, int flags, uchar **packetp) 889*f1dcc19bSSimon Glass { 890*f1dcc19bSSimon Glass struct macb_device *macb = dev_get_priv(dev); 891*f1dcc19bSSimon Glass 892*f1dcc19bSSimon Glass macb->next_rx_tail = macb->rx_tail; 893*f1dcc19bSSimon Glass macb->wrapped = false; 894*f1dcc19bSSimon Glass 895*f1dcc19bSSimon Glass return _macb_recv(macb, packetp); 896*f1dcc19bSSimon Glass } 897*f1dcc19bSSimon Glass 898*f1dcc19bSSimon Glass static int macb_free_pkt(struct udevice *dev, uchar *packet, int length) 899*f1dcc19bSSimon Glass { 900*f1dcc19bSSimon Glass struct macb_device *macb = dev_get_priv(dev); 901*f1dcc19bSSimon Glass 902*f1dcc19bSSimon Glass reclaim_rx_buffers(macb, macb->next_rx_tail); 903*f1dcc19bSSimon Glass 904*f1dcc19bSSimon Glass return 0; 905*f1dcc19bSSimon Glass } 906*f1dcc19bSSimon Glass 907*f1dcc19bSSimon Glass static void macb_stop(struct udevice *dev) 908*f1dcc19bSSimon Glass { 909*f1dcc19bSSimon Glass struct macb_device *macb = dev_get_priv(dev); 910*f1dcc19bSSimon Glass 911*f1dcc19bSSimon Glass _macb_halt(macb); 912*f1dcc19bSSimon Glass } 913*f1dcc19bSSimon Glass 914*f1dcc19bSSimon Glass static int macb_write_hwaddr(struct udevice *dev) 915*f1dcc19bSSimon Glass { 916*f1dcc19bSSimon Glass struct eth_pdata *plat = dev_get_platdata(dev); 917*f1dcc19bSSimon Glass struct macb_device *macb = dev_get_priv(dev); 918*f1dcc19bSSimon Glass 919*f1dcc19bSSimon Glass return _macb_write_hwaddr(macb, plat->enetaddr); 920*f1dcc19bSSimon Glass } 921*f1dcc19bSSimon Glass 922*f1dcc19bSSimon Glass static const struct eth_ops macb_eth_ops = { 923*f1dcc19bSSimon Glass .start = macb_start, 924*f1dcc19bSSimon Glass .send = macb_send, 925*f1dcc19bSSimon Glass .recv = macb_recv, 926*f1dcc19bSSimon Glass .stop = macb_stop, 927*f1dcc19bSSimon Glass .free_pkt = macb_free_pkt, 928*f1dcc19bSSimon Glass .write_hwaddr = macb_write_hwaddr, 929*f1dcc19bSSimon Glass }; 930*f1dcc19bSSimon Glass 931*f1dcc19bSSimon Glass static int macb_eth_probe(struct udevice *dev) 932*f1dcc19bSSimon Glass { 933*f1dcc19bSSimon Glass struct eth_pdata *pdata = dev_get_platdata(dev); 934*f1dcc19bSSimon Glass struct macb_device *macb = dev_get_priv(dev); 935*f1dcc19bSSimon Glass 936*f1dcc19bSSimon Glass macb->regs = (void *)pdata->iobase; 937*f1dcc19bSSimon Glass 938*f1dcc19bSSimon Glass _macb_eth_initialize(macb); 939*f1dcc19bSSimon Glass #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) 940*f1dcc19bSSimon Glass miiphy_register(dev->name, macb_miiphy_read, macb_miiphy_write); 941*f1dcc19bSSimon Glass macb->bus = miiphy_get_dev_by_name(dev->name); 942*f1dcc19bSSimon Glass #endif 943*f1dcc19bSSimon Glass 944*f1dcc19bSSimon Glass return 0; 945*f1dcc19bSSimon Glass } 946*f1dcc19bSSimon Glass 947*f1dcc19bSSimon Glass static int macb_eth_ofdata_to_platdata(struct udevice *dev) 948*f1dcc19bSSimon Glass { 949*f1dcc19bSSimon Glass struct eth_pdata *pdata = dev_get_platdata(dev); 950*f1dcc19bSSimon Glass 951*f1dcc19bSSimon Glass pdata->iobase = dev_get_addr(dev); 952*f1dcc19bSSimon Glass return 0; 953*f1dcc19bSSimon Glass } 954*f1dcc19bSSimon Glass 955*f1dcc19bSSimon Glass static const struct udevice_id macb_eth_ids[] = { 956*f1dcc19bSSimon Glass { .compatible = "cdns,macb" }, 957*f1dcc19bSSimon Glass { } 958*f1dcc19bSSimon Glass }; 959*f1dcc19bSSimon Glass 960*f1dcc19bSSimon Glass U_BOOT_DRIVER(eth_macb) = { 961*f1dcc19bSSimon Glass .name = "eth_macb", 962*f1dcc19bSSimon Glass .id = UCLASS_ETH, 963*f1dcc19bSSimon Glass .of_match = macb_eth_ids, 964*f1dcc19bSSimon Glass .ofdata_to_platdata = macb_eth_ofdata_to_platdata, 965*f1dcc19bSSimon Glass .probe = macb_eth_probe, 966*f1dcc19bSSimon Glass .ops = &macb_eth_ops, 967*f1dcc19bSSimon Glass .priv_auto_alloc_size = sizeof(struct macb_device), 968*f1dcc19bSSimon Glass .platdata_auto_alloc_size = sizeof(struct eth_pdata), 969*f1dcc19bSSimon Glass }; 970*f1dcc19bSSimon Glass #endif 9712439e4bfSJean-Christophe PLAGNIOL-VILLARD 9722439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 973