18ae51b6fSMarek Vasut /* 28ae51b6fSMarek Vasut * drivers/net/ravb.c 38ae51b6fSMarek Vasut * This file is driver for Renesas Ethernet AVB. 48ae51b6fSMarek Vasut * 58ae51b6fSMarek Vasut * Copyright (C) 2015-2017 Renesas Electronics Corporation 68ae51b6fSMarek Vasut * 78ae51b6fSMarek Vasut * Based on the SuperH Ethernet driver. 88ae51b6fSMarek Vasut * 98ae51b6fSMarek Vasut * SPDX-License-Identifier: GPL-2.0+ 108ae51b6fSMarek Vasut */ 118ae51b6fSMarek Vasut 128ae51b6fSMarek Vasut #include <common.h> 138ae51b6fSMarek Vasut #include <dm.h> 148ae51b6fSMarek Vasut #include <errno.h> 158ae51b6fSMarek Vasut #include <miiphy.h> 168ae51b6fSMarek Vasut #include <malloc.h> 178ae51b6fSMarek Vasut #include <linux/mii.h> 188ae51b6fSMarek Vasut #include <wait_bit.h> 198ae51b6fSMarek Vasut #include <asm/io.h> 208ae51b6fSMarek Vasut 218ae51b6fSMarek Vasut /* Registers */ 228ae51b6fSMarek Vasut #define RAVB_REG_CCC 0x000 238ae51b6fSMarek Vasut #define RAVB_REG_DBAT 0x004 248ae51b6fSMarek Vasut #define RAVB_REG_CSR 0x00C 258ae51b6fSMarek Vasut #define RAVB_REG_APSR 0x08C 268ae51b6fSMarek Vasut #define RAVB_REG_RCR 0x090 278ae51b6fSMarek Vasut #define RAVB_REG_TGC 0x300 288ae51b6fSMarek Vasut #define RAVB_REG_TCCR 0x304 298ae51b6fSMarek Vasut #define RAVB_REG_RIC0 0x360 308ae51b6fSMarek Vasut #define RAVB_REG_RIC1 0x368 318ae51b6fSMarek Vasut #define RAVB_REG_RIC2 0x370 328ae51b6fSMarek Vasut #define RAVB_REG_TIC 0x378 338ae51b6fSMarek Vasut #define RAVB_REG_ECMR 0x500 348ae51b6fSMarek Vasut #define RAVB_REG_RFLR 0x508 358ae51b6fSMarek Vasut #define RAVB_REG_ECSIPR 0x518 368ae51b6fSMarek Vasut #define RAVB_REG_PIR 0x520 378ae51b6fSMarek Vasut #define RAVB_REG_GECMR 0x5b0 388ae51b6fSMarek Vasut #define RAVB_REG_MAHR 0x5c0 398ae51b6fSMarek Vasut #define RAVB_REG_MALR 0x5c8 408ae51b6fSMarek Vasut 418ae51b6fSMarek Vasut #define CCC_OPC_CONFIG BIT(0) 428ae51b6fSMarek Vasut #define CCC_OPC_OPERATION BIT(1) 438ae51b6fSMarek Vasut #define CCC_BOC BIT(20) 448ae51b6fSMarek Vasut 458ae51b6fSMarek Vasut #define CSR_OPS 0x0000000F 468ae51b6fSMarek Vasut #define CSR_OPS_CONFIG BIT(1) 478ae51b6fSMarek Vasut 488ae51b6fSMarek Vasut #define TCCR_TSRQ0 BIT(0) 498ae51b6fSMarek Vasut 508ae51b6fSMarek Vasut #define RFLR_RFL_MIN 0x05EE 518ae51b6fSMarek Vasut 528ae51b6fSMarek Vasut #define PIR_MDI BIT(3) 538ae51b6fSMarek Vasut #define PIR_MDO BIT(2) 548ae51b6fSMarek Vasut #define PIR_MMD BIT(1) 558ae51b6fSMarek Vasut #define PIR_MDC BIT(0) 568ae51b6fSMarek Vasut 578ae51b6fSMarek Vasut #define ECMR_TRCCM BIT(26) 588ae51b6fSMarek Vasut #define ECMR_RZPF BIT(20) 598ae51b6fSMarek Vasut #define ECMR_PFR BIT(18) 608ae51b6fSMarek Vasut #define ECMR_RXF BIT(17) 618ae51b6fSMarek Vasut #define ECMR_RE BIT(6) 628ae51b6fSMarek Vasut #define ECMR_TE BIT(5) 638ae51b6fSMarek Vasut #define ECMR_DM BIT(1) 648ae51b6fSMarek Vasut #define ECMR_CHG_DM (ECMR_TRCCM | ECMR_RZPF | ECMR_PFR | ECMR_RXF) 658ae51b6fSMarek Vasut 668ae51b6fSMarek Vasut /* DMA Descriptors */ 678ae51b6fSMarek Vasut #define RAVB_NUM_BASE_DESC 16 688ae51b6fSMarek Vasut #define RAVB_NUM_TX_DESC 8 698ae51b6fSMarek Vasut #define RAVB_NUM_RX_DESC 8 708ae51b6fSMarek Vasut 718ae51b6fSMarek Vasut #define RAVB_TX_QUEUE_OFFSET 0 728ae51b6fSMarek Vasut #define RAVB_RX_QUEUE_OFFSET 4 738ae51b6fSMarek Vasut 748ae51b6fSMarek Vasut #define RAVB_DESC_DT(n) ((n) << 28) 758ae51b6fSMarek Vasut #define RAVB_DESC_DT_FSINGLE RAVB_DESC_DT(0x7) 768ae51b6fSMarek Vasut #define RAVB_DESC_DT_LINKFIX RAVB_DESC_DT(0x9) 778ae51b6fSMarek Vasut #define RAVB_DESC_DT_EOS RAVB_DESC_DT(0xa) 788ae51b6fSMarek Vasut #define RAVB_DESC_DT_FEMPTY RAVB_DESC_DT(0xc) 798ae51b6fSMarek Vasut #define RAVB_DESC_DT_EEMPTY RAVB_DESC_DT(0x3) 808ae51b6fSMarek Vasut #define RAVB_DESC_DT_MASK RAVB_DESC_DT(0xf) 818ae51b6fSMarek Vasut 828ae51b6fSMarek Vasut #define RAVB_DESC_DS(n) (((n) & 0xfff) << 0) 838ae51b6fSMarek Vasut #define RAVB_DESC_DS_MASK 0xfff 848ae51b6fSMarek Vasut 858ae51b6fSMarek Vasut #define RAVB_RX_DESC_MSC_MC BIT(23) 868ae51b6fSMarek Vasut #define RAVB_RX_DESC_MSC_CEEF BIT(22) 878ae51b6fSMarek Vasut #define RAVB_RX_DESC_MSC_CRL BIT(21) 888ae51b6fSMarek Vasut #define RAVB_RX_DESC_MSC_FRE BIT(20) 898ae51b6fSMarek Vasut #define RAVB_RX_DESC_MSC_RTLF BIT(19) 908ae51b6fSMarek Vasut #define RAVB_RX_DESC_MSC_RTSF BIT(18) 918ae51b6fSMarek Vasut #define RAVB_RX_DESC_MSC_RFE BIT(17) 928ae51b6fSMarek Vasut #define RAVB_RX_DESC_MSC_CRC BIT(16) 938ae51b6fSMarek Vasut #define RAVB_RX_DESC_MSC_MASK (0xff << 16) 948ae51b6fSMarek Vasut 958ae51b6fSMarek Vasut #define RAVB_RX_DESC_MSC_RX_ERR_MASK \ 968ae51b6fSMarek Vasut (RAVB_RX_DESC_MSC_CRC | RAVB_RX_DESC_MSC_RFE | RAVB_RX_DESC_MSC_RTLF | \ 978ae51b6fSMarek Vasut RAVB_RX_DESC_MSC_RTSF | RAVB_RX_DESC_MSC_CEEF) 988ae51b6fSMarek Vasut 998ae51b6fSMarek Vasut #define RAVB_TX_TIMEOUT_MS 1000 1008ae51b6fSMarek Vasut 1018ae51b6fSMarek Vasut struct ravb_desc { 1028ae51b6fSMarek Vasut u32 ctrl; 1038ae51b6fSMarek Vasut u32 dptr; 1048ae51b6fSMarek Vasut }; 1058ae51b6fSMarek Vasut 1068ae51b6fSMarek Vasut struct ravb_rxdesc { 1078ae51b6fSMarek Vasut struct ravb_desc data; 1088ae51b6fSMarek Vasut struct ravb_desc link; 1098ae51b6fSMarek Vasut u8 __pad[48]; 1108ae51b6fSMarek Vasut u8 packet[PKTSIZE_ALIGN]; 1118ae51b6fSMarek Vasut }; 1128ae51b6fSMarek Vasut 1138ae51b6fSMarek Vasut struct ravb_priv { 1148ae51b6fSMarek Vasut struct ravb_desc base_desc[RAVB_NUM_BASE_DESC]; 1158ae51b6fSMarek Vasut struct ravb_desc tx_desc[RAVB_NUM_TX_DESC]; 1168ae51b6fSMarek Vasut struct ravb_rxdesc rx_desc[RAVB_NUM_RX_DESC]; 1178ae51b6fSMarek Vasut u32 rx_desc_idx; 1188ae51b6fSMarek Vasut u32 tx_desc_idx; 1198ae51b6fSMarek Vasut 1208ae51b6fSMarek Vasut struct phy_device *phydev; 1218ae51b6fSMarek Vasut struct mii_dev *bus; 1228ae51b6fSMarek Vasut void __iomem *iobase; 1238ae51b6fSMarek Vasut }; 1248ae51b6fSMarek Vasut 1258ae51b6fSMarek Vasut static inline void ravb_flush_dcache(u32 addr, u32 len) 1268ae51b6fSMarek Vasut { 1278ae51b6fSMarek Vasut flush_dcache_range(addr, addr + len); 1288ae51b6fSMarek Vasut } 1298ae51b6fSMarek Vasut 1308ae51b6fSMarek Vasut static inline void ravb_invalidate_dcache(u32 addr, u32 len) 1318ae51b6fSMarek Vasut { 1328ae51b6fSMarek Vasut u32 start = addr & ~((uintptr_t)ARCH_DMA_MINALIGN - 1); 1338ae51b6fSMarek Vasut u32 end = roundup(addr + len, ARCH_DMA_MINALIGN); 1348ae51b6fSMarek Vasut invalidate_dcache_range(start, end); 1358ae51b6fSMarek Vasut } 1368ae51b6fSMarek Vasut 1378ae51b6fSMarek Vasut static int ravb_send(struct udevice *dev, void *packet, int len) 1388ae51b6fSMarek Vasut { 1398ae51b6fSMarek Vasut struct ravb_priv *eth = dev_get_priv(dev); 1408ae51b6fSMarek Vasut struct ravb_desc *desc = ð->tx_desc[eth->tx_desc_idx]; 1418ae51b6fSMarek Vasut unsigned int start; 1428ae51b6fSMarek Vasut 1438ae51b6fSMarek Vasut /* Update TX descriptor */ 1448ae51b6fSMarek Vasut ravb_flush_dcache((uintptr_t)packet, len); 1458ae51b6fSMarek Vasut memset(desc, 0x0, sizeof(*desc)); 1468ae51b6fSMarek Vasut desc->ctrl = RAVB_DESC_DT_FSINGLE | RAVB_DESC_DS(len); 1478ae51b6fSMarek Vasut desc->dptr = (uintptr_t)packet; 1488ae51b6fSMarek Vasut ravb_flush_dcache((uintptr_t)desc, sizeof(*desc)); 1498ae51b6fSMarek Vasut 1508ae51b6fSMarek Vasut /* Restart the transmitter if disabled */ 1518ae51b6fSMarek Vasut if (!(readl(eth->iobase + RAVB_REG_TCCR) & TCCR_TSRQ0)) 1528ae51b6fSMarek Vasut setbits_le32(eth->iobase + RAVB_REG_TCCR, TCCR_TSRQ0); 1538ae51b6fSMarek Vasut 1548ae51b6fSMarek Vasut /* Wait until packet is transmitted */ 1558ae51b6fSMarek Vasut start = get_timer(0); 1568ae51b6fSMarek Vasut while (get_timer(start) < RAVB_TX_TIMEOUT_MS) { 1578ae51b6fSMarek Vasut ravb_invalidate_dcache((uintptr_t)desc, sizeof(*desc)); 1588ae51b6fSMarek Vasut if ((desc->ctrl & RAVB_DESC_DT_MASK) != RAVB_DESC_DT_FSINGLE) 1598ae51b6fSMarek Vasut break; 1608ae51b6fSMarek Vasut udelay(10); 1618ae51b6fSMarek Vasut }; 1628ae51b6fSMarek Vasut 1638ae51b6fSMarek Vasut if (get_timer(start) >= RAVB_TX_TIMEOUT_MS) 1648ae51b6fSMarek Vasut return -ETIMEDOUT; 1658ae51b6fSMarek Vasut 1668ae51b6fSMarek Vasut eth->tx_desc_idx = (eth->tx_desc_idx + 1) % (RAVB_NUM_TX_DESC - 1); 1678ae51b6fSMarek Vasut return 0; 1688ae51b6fSMarek Vasut } 1698ae51b6fSMarek Vasut 1708ae51b6fSMarek Vasut static int ravb_recv(struct udevice *dev, int flags, uchar **packetp) 1718ae51b6fSMarek Vasut { 1728ae51b6fSMarek Vasut struct ravb_priv *eth = dev_get_priv(dev); 1738ae51b6fSMarek Vasut struct ravb_rxdesc *desc = ð->rx_desc[eth->rx_desc_idx]; 1748ae51b6fSMarek Vasut int len; 1758ae51b6fSMarek Vasut u8 *packet; 1768ae51b6fSMarek Vasut 1778ae51b6fSMarek Vasut /* Check if the rx descriptor is ready */ 1788ae51b6fSMarek Vasut ravb_invalidate_dcache((uintptr_t)desc, sizeof(*desc)); 1798ae51b6fSMarek Vasut if ((desc->data.ctrl & RAVB_DESC_DT_MASK) == RAVB_DESC_DT_FEMPTY) 1808ae51b6fSMarek Vasut return -EAGAIN; 1818ae51b6fSMarek Vasut 1828ae51b6fSMarek Vasut /* Check for errors */ 1838ae51b6fSMarek Vasut if (desc->data.ctrl & RAVB_RX_DESC_MSC_RX_ERR_MASK) { 1848ae51b6fSMarek Vasut desc->data.ctrl &= ~RAVB_RX_DESC_MSC_MASK; 1858ae51b6fSMarek Vasut return -EAGAIN; 1868ae51b6fSMarek Vasut } 1878ae51b6fSMarek Vasut 1888ae51b6fSMarek Vasut len = desc->data.ctrl & RAVB_DESC_DS_MASK; 1898ae51b6fSMarek Vasut packet = (u8 *)(uintptr_t)desc->data.dptr; 1908ae51b6fSMarek Vasut ravb_invalidate_dcache((uintptr_t)packet, len); 1918ae51b6fSMarek Vasut 1928ae51b6fSMarek Vasut *packetp = packet; 1938ae51b6fSMarek Vasut return len; 1948ae51b6fSMarek Vasut } 1958ae51b6fSMarek Vasut 1968ae51b6fSMarek Vasut static int ravb_free_pkt(struct udevice *dev, uchar *packet, int length) 1978ae51b6fSMarek Vasut { 1988ae51b6fSMarek Vasut struct ravb_priv *eth = dev_get_priv(dev); 1998ae51b6fSMarek Vasut struct ravb_rxdesc *desc = ð->rx_desc[eth->rx_desc_idx]; 2008ae51b6fSMarek Vasut 2018ae51b6fSMarek Vasut /* Make current descriptor available again */ 2028ae51b6fSMarek Vasut desc->data.ctrl = RAVB_DESC_DT_FEMPTY | RAVB_DESC_DS(PKTSIZE_ALIGN); 2038ae51b6fSMarek Vasut ravb_flush_dcache((uintptr_t)desc, sizeof(*desc)); 2048ae51b6fSMarek Vasut 2058ae51b6fSMarek Vasut /* Point to the next descriptor */ 2068ae51b6fSMarek Vasut eth->rx_desc_idx = (eth->rx_desc_idx + 1) % RAVB_NUM_RX_DESC; 2078ae51b6fSMarek Vasut desc = ð->rx_desc[eth->rx_desc_idx]; 2088ae51b6fSMarek Vasut ravb_invalidate_dcache((uintptr_t)desc, sizeof(*desc)); 2098ae51b6fSMarek Vasut 2108ae51b6fSMarek Vasut return 0; 2118ae51b6fSMarek Vasut } 2128ae51b6fSMarek Vasut 2138ae51b6fSMarek Vasut static int ravb_reset(struct udevice *dev) 2148ae51b6fSMarek Vasut { 2158ae51b6fSMarek Vasut struct ravb_priv *eth = dev_get_priv(dev); 2168ae51b6fSMarek Vasut 2178ae51b6fSMarek Vasut /* Set config mode */ 2188ae51b6fSMarek Vasut writel(CCC_OPC_CONFIG, eth->iobase + RAVB_REG_CCC); 2198ae51b6fSMarek Vasut 2208ae51b6fSMarek Vasut /* Check the operating mode is changed to the config mode. */ 2218ae51b6fSMarek Vasut return wait_for_bit(dev->name, (void *)eth->iobase + RAVB_REG_CSR, 2228ae51b6fSMarek Vasut CSR_OPS_CONFIG, true, 100, true); 2238ae51b6fSMarek Vasut } 2248ae51b6fSMarek Vasut 2258ae51b6fSMarek Vasut static void ravb_base_desc_init(struct ravb_priv *eth) 2268ae51b6fSMarek Vasut { 2278ae51b6fSMarek Vasut const u32 desc_size = RAVB_NUM_BASE_DESC * sizeof(struct ravb_desc); 2288ae51b6fSMarek Vasut int i; 2298ae51b6fSMarek Vasut 2308ae51b6fSMarek Vasut /* Initialize all descriptors */ 2318ae51b6fSMarek Vasut memset(eth->base_desc, 0x0, desc_size); 2328ae51b6fSMarek Vasut 2338ae51b6fSMarek Vasut for (i = 0; i < RAVB_NUM_BASE_DESC; i++) 2348ae51b6fSMarek Vasut eth->base_desc[i].ctrl = RAVB_DESC_DT_EOS; 2358ae51b6fSMarek Vasut 2368ae51b6fSMarek Vasut ravb_flush_dcache((uintptr_t)eth->base_desc, desc_size); 2378ae51b6fSMarek Vasut 2388ae51b6fSMarek Vasut /* Register the descriptor base address table */ 2398ae51b6fSMarek Vasut writel((uintptr_t)eth->base_desc, eth->iobase + RAVB_REG_DBAT); 2408ae51b6fSMarek Vasut } 2418ae51b6fSMarek Vasut 2428ae51b6fSMarek Vasut static void ravb_tx_desc_init(struct ravb_priv *eth) 2438ae51b6fSMarek Vasut { 2448ae51b6fSMarek Vasut const u32 desc_size = RAVB_NUM_TX_DESC * sizeof(struct ravb_desc); 2458ae51b6fSMarek Vasut int i; 2468ae51b6fSMarek Vasut 2478ae51b6fSMarek Vasut /* Initialize all descriptors */ 2488ae51b6fSMarek Vasut memset(eth->tx_desc, 0x0, desc_size); 2498ae51b6fSMarek Vasut eth->tx_desc_idx = 0; 2508ae51b6fSMarek Vasut 2518ae51b6fSMarek Vasut for (i = 0; i < RAVB_NUM_TX_DESC; i++) 2528ae51b6fSMarek Vasut eth->tx_desc[i].ctrl = RAVB_DESC_DT_EEMPTY; 2538ae51b6fSMarek Vasut 2548ae51b6fSMarek Vasut /* Mark the end of the descriptors */ 2558ae51b6fSMarek Vasut eth->tx_desc[RAVB_NUM_TX_DESC - 1].ctrl = RAVB_DESC_DT_LINKFIX; 2568ae51b6fSMarek Vasut eth->tx_desc[RAVB_NUM_TX_DESC - 1].dptr = (uintptr_t)eth->tx_desc; 2578ae51b6fSMarek Vasut ravb_flush_dcache((uintptr_t)eth->tx_desc, desc_size); 2588ae51b6fSMarek Vasut 2598ae51b6fSMarek Vasut /* Point the controller to the TX descriptor list. */ 2608ae51b6fSMarek Vasut eth->base_desc[RAVB_TX_QUEUE_OFFSET].ctrl = RAVB_DESC_DT_LINKFIX; 2618ae51b6fSMarek Vasut eth->base_desc[RAVB_TX_QUEUE_OFFSET].dptr = (uintptr_t)eth->tx_desc; 2628ae51b6fSMarek Vasut ravb_flush_dcache((uintptr_t)ð->base_desc[RAVB_TX_QUEUE_OFFSET], 2638ae51b6fSMarek Vasut sizeof(struct ravb_desc)); 2648ae51b6fSMarek Vasut } 2658ae51b6fSMarek Vasut 2668ae51b6fSMarek Vasut static void ravb_rx_desc_init(struct ravb_priv *eth) 2678ae51b6fSMarek Vasut { 2688ae51b6fSMarek Vasut const u32 desc_size = RAVB_NUM_RX_DESC * sizeof(struct ravb_rxdesc); 2698ae51b6fSMarek Vasut int i; 2708ae51b6fSMarek Vasut 2718ae51b6fSMarek Vasut /* Initialize all descriptors */ 2728ae51b6fSMarek Vasut memset(eth->rx_desc, 0x0, desc_size); 2738ae51b6fSMarek Vasut eth->rx_desc_idx = 0; 2748ae51b6fSMarek Vasut 2758ae51b6fSMarek Vasut for (i = 0; i < RAVB_NUM_RX_DESC; i++) { 2768ae51b6fSMarek Vasut eth->rx_desc[i].data.ctrl = RAVB_DESC_DT_EEMPTY | 2778ae51b6fSMarek Vasut RAVB_DESC_DS(PKTSIZE_ALIGN); 2788ae51b6fSMarek Vasut eth->rx_desc[i].data.dptr = (uintptr_t)eth->rx_desc[i].packet; 2798ae51b6fSMarek Vasut 2808ae51b6fSMarek Vasut eth->rx_desc[i].link.ctrl = RAVB_DESC_DT_LINKFIX; 2818ae51b6fSMarek Vasut eth->rx_desc[i].link.dptr = (uintptr_t)ð->rx_desc[i + 1]; 2828ae51b6fSMarek Vasut } 2838ae51b6fSMarek Vasut 2848ae51b6fSMarek Vasut /* Mark the end of the descriptors */ 2858ae51b6fSMarek Vasut eth->rx_desc[RAVB_NUM_RX_DESC - 1].link.ctrl = RAVB_DESC_DT_LINKFIX; 2868ae51b6fSMarek Vasut eth->rx_desc[RAVB_NUM_RX_DESC - 1].link.dptr = (uintptr_t)eth->rx_desc; 2878ae51b6fSMarek Vasut ravb_flush_dcache((uintptr_t)eth->rx_desc, desc_size); 2888ae51b6fSMarek Vasut 2898ae51b6fSMarek Vasut /* Point the controller to the rx descriptor list */ 2908ae51b6fSMarek Vasut eth->base_desc[RAVB_RX_QUEUE_OFFSET].ctrl = RAVB_DESC_DT_LINKFIX; 2918ae51b6fSMarek Vasut eth->base_desc[RAVB_RX_QUEUE_OFFSET].dptr = (uintptr_t)eth->rx_desc; 2928ae51b6fSMarek Vasut ravb_flush_dcache((uintptr_t)ð->base_desc[RAVB_RX_QUEUE_OFFSET], 2938ae51b6fSMarek Vasut sizeof(struct ravb_desc)); 2948ae51b6fSMarek Vasut } 2958ae51b6fSMarek Vasut 2968ae51b6fSMarek Vasut static int ravb_phy_config(struct udevice *dev) 2978ae51b6fSMarek Vasut { 2988ae51b6fSMarek Vasut struct ravb_priv *eth = dev_get_priv(dev); 2998ae51b6fSMarek Vasut struct eth_pdata *pdata = dev_get_platdata(dev); 3008ae51b6fSMarek Vasut struct phy_device *phydev; 301*e821a7bdSMarek Vasut int mask = 0xffffffff, reg; 3028ae51b6fSMarek Vasut 303*e821a7bdSMarek Vasut phydev = phy_find_by_mask(eth->bus, mask, pdata->phy_interface); 3048ae51b6fSMarek Vasut if (!phydev) 3058ae51b6fSMarek Vasut return -ENODEV; 3068ae51b6fSMarek Vasut 307*e821a7bdSMarek Vasut phy_connect_dev(phydev, dev); 308*e821a7bdSMarek Vasut 3098ae51b6fSMarek Vasut eth->phydev = phydev; 3108ae51b6fSMarek Vasut 3118ae51b6fSMarek Vasut /* 10BASE is not supported for Ethernet AVB MAC */ 3128ae51b6fSMarek Vasut phydev->supported &= ~(SUPPORTED_10baseT_Full 3138ae51b6fSMarek Vasut | SUPPORTED_10baseT_Half); 3148ae51b6fSMarek Vasut if (pdata->max_speed != 1000) { 3158ae51b6fSMarek Vasut phydev->supported &= ~(SUPPORTED_1000baseT_Half 3168ae51b6fSMarek Vasut | SUPPORTED_1000baseT_Full); 3178ae51b6fSMarek Vasut reg = phy_read(phydev, -1, MII_CTRL1000); 3188ae51b6fSMarek Vasut reg &= ~(BIT(9) | BIT(8)); 3198ae51b6fSMarek Vasut phy_write(phydev, -1, MII_CTRL1000, reg); 3208ae51b6fSMarek Vasut } 3218ae51b6fSMarek Vasut 3228ae51b6fSMarek Vasut phy_config(phydev); 3238ae51b6fSMarek Vasut 3248ae51b6fSMarek Vasut return 0; 3258ae51b6fSMarek Vasut } 3268ae51b6fSMarek Vasut 3278ae51b6fSMarek Vasut /* Set Mac address */ 3288ae51b6fSMarek Vasut static int ravb_write_hwaddr(struct udevice *dev) 3298ae51b6fSMarek Vasut { 3308ae51b6fSMarek Vasut struct ravb_priv *eth = dev_get_priv(dev); 3318ae51b6fSMarek Vasut struct eth_pdata *pdata = dev_get_platdata(dev); 3328ae51b6fSMarek Vasut unsigned char *mac = pdata->enetaddr; 3338ae51b6fSMarek Vasut 3348ae51b6fSMarek Vasut writel((mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3], 3358ae51b6fSMarek Vasut eth->iobase + RAVB_REG_MAHR); 3368ae51b6fSMarek Vasut 3378ae51b6fSMarek Vasut writel((mac[4] << 8) | mac[5], eth->iobase + RAVB_REG_MALR); 3388ae51b6fSMarek Vasut 3398ae51b6fSMarek Vasut return 0; 3408ae51b6fSMarek Vasut } 3418ae51b6fSMarek Vasut 3428ae51b6fSMarek Vasut /* E-MAC init function */ 3438ae51b6fSMarek Vasut static int ravb_mac_init(struct ravb_priv *eth) 3448ae51b6fSMarek Vasut { 3458ae51b6fSMarek Vasut /* Disable MAC Interrupt */ 3468ae51b6fSMarek Vasut writel(0, eth->iobase + RAVB_REG_ECSIPR); 3478ae51b6fSMarek Vasut 3488ae51b6fSMarek Vasut /* Recv frame limit set register */ 3498ae51b6fSMarek Vasut writel(RFLR_RFL_MIN, eth->iobase + RAVB_REG_RFLR); 3508ae51b6fSMarek Vasut 3518ae51b6fSMarek Vasut return 0; 3528ae51b6fSMarek Vasut } 3538ae51b6fSMarek Vasut 3548ae51b6fSMarek Vasut /* AVB-DMAC init function */ 3558ae51b6fSMarek Vasut static int ravb_dmac_init(struct udevice *dev) 3568ae51b6fSMarek Vasut { 3578ae51b6fSMarek Vasut struct ravb_priv *eth = dev_get_priv(dev); 3588ae51b6fSMarek Vasut struct eth_pdata *pdata = dev_get_platdata(dev); 3598ae51b6fSMarek Vasut int ret = 0; 3608ae51b6fSMarek Vasut 3618ae51b6fSMarek Vasut /* Set CONFIG mode */ 3628ae51b6fSMarek Vasut ret = ravb_reset(dev); 3638ae51b6fSMarek Vasut if (ret) 3648ae51b6fSMarek Vasut return ret; 3658ae51b6fSMarek Vasut 3668ae51b6fSMarek Vasut /* Disable all interrupts */ 3678ae51b6fSMarek Vasut writel(0, eth->iobase + RAVB_REG_RIC0); 3688ae51b6fSMarek Vasut writel(0, eth->iobase + RAVB_REG_RIC1); 3698ae51b6fSMarek Vasut writel(0, eth->iobase + RAVB_REG_RIC2); 3708ae51b6fSMarek Vasut writel(0, eth->iobase + RAVB_REG_TIC); 3718ae51b6fSMarek Vasut 3728ae51b6fSMarek Vasut /* Set little endian */ 3738ae51b6fSMarek Vasut clrbits_le32(eth->iobase + RAVB_REG_CCC, CCC_BOC); 3748ae51b6fSMarek Vasut 3758ae51b6fSMarek Vasut /* AVB rx set */ 3768ae51b6fSMarek Vasut writel(0x18000001, eth->iobase + RAVB_REG_RCR); 3778ae51b6fSMarek Vasut 3788ae51b6fSMarek Vasut /* FIFO size set */ 3798ae51b6fSMarek Vasut writel(0x00222210, eth->iobase + RAVB_REG_TGC); 3808ae51b6fSMarek Vasut 3818ae51b6fSMarek Vasut /* Delay CLK: 2ns */ 3828ae51b6fSMarek Vasut if (pdata->max_speed == 1000) 3838ae51b6fSMarek Vasut writel(BIT(14), eth->iobase + RAVB_REG_APSR); 3848ae51b6fSMarek Vasut 3858ae51b6fSMarek Vasut return 0; 3868ae51b6fSMarek Vasut } 3878ae51b6fSMarek Vasut 3888ae51b6fSMarek Vasut static int ravb_config(struct udevice *dev) 3898ae51b6fSMarek Vasut { 3908ae51b6fSMarek Vasut struct ravb_priv *eth = dev_get_priv(dev); 3918ae51b6fSMarek Vasut struct phy_device *phy; 3928ae51b6fSMarek Vasut u32 mask = ECMR_CHG_DM | ECMR_RE | ECMR_TE; 3938ae51b6fSMarek Vasut int ret; 3948ae51b6fSMarek Vasut 3958ae51b6fSMarek Vasut /* Configure AVB-DMAC register */ 3968ae51b6fSMarek Vasut ravb_dmac_init(dev); 3978ae51b6fSMarek Vasut 3988ae51b6fSMarek Vasut /* Configure E-MAC registers */ 3998ae51b6fSMarek Vasut ravb_mac_init(eth); 4008ae51b6fSMarek Vasut ravb_write_hwaddr(dev); 4018ae51b6fSMarek Vasut 4028ae51b6fSMarek Vasut /* Configure phy */ 4038ae51b6fSMarek Vasut ret = ravb_phy_config(dev); 4048ae51b6fSMarek Vasut if (ret) 4058ae51b6fSMarek Vasut return ret; 4068ae51b6fSMarek Vasut 4078ae51b6fSMarek Vasut phy = eth->phydev; 4088ae51b6fSMarek Vasut 4098ae51b6fSMarek Vasut ret = phy_startup(phy); 4108ae51b6fSMarek Vasut if (ret) 4118ae51b6fSMarek Vasut return ret; 4128ae51b6fSMarek Vasut 4138ae51b6fSMarek Vasut /* Set the transfer speed */ 4148ae51b6fSMarek Vasut if (phy->speed == 100) 4158ae51b6fSMarek Vasut writel(0, eth->iobase + RAVB_REG_GECMR); 4168ae51b6fSMarek Vasut else if (phy->speed == 1000) 4178ae51b6fSMarek Vasut writel(1, eth->iobase + RAVB_REG_GECMR); 4188ae51b6fSMarek Vasut 4198ae51b6fSMarek Vasut /* Check if full duplex mode is supported by the phy */ 4208ae51b6fSMarek Vasut if (phy->duplex) 4218ae51b6fSMarek Vasut mask |= ECMR_DM; 4228ae51b6fSMarek Vasut 4238ae51b6fSMarek Vasut writel(mask, eth->iobase + RAVB_REG_ECMR); 4248ae51b6fSMarek Vasut 4258ae51b6fSMarek Vasut phy->drv->writeext(phy, -1, 0x02, 0x08, (0x0f << 5) | 0x19); 4268ae51b6fSMarek Vasut 4278ae51b6fSMarek Vasut return 0; 4288ae51b6fSMarek Vasut } 4298ae51b6fSMarek Vasut 4308ae51b6fSMarek Vasut int ravb_start(struct udevice *dev) 4318ae51b6fSMarek Vasut { 4328ae51b6fSMarek Vasut struct ravb_priv *eth = dev_get_priv(dev); 4338ae51b6fSMarek Vasut int ret; 4348ae51b6fSMarek Vasut 4358ae51b6fSMarek Vasut ret = ravb_reset(dev); 4368ae51b6fSMarek Vasut if (ret) 4378ae51b6fSMarek Vasut return ret; 4388ae51b6fSMarek Vasut 4398ae51b6fSMarek Vasut ravb_base_desc_init(eth); 4408ae51b6fSMarek Vasut ravb_tx_desc_init(eth); 4418ae51b6fSMarek Vasut ravb_rx_desc_init(eth); 4428ae51b6fSMarek Vasut 4438ae51b6fSMarek Vasut ret = ravb_config(dev); 4448ae51b6fSMarek Vasut if (ret) 4458ae51b6fSMarek Vasut return ret; 4468ae51b6fSMarek Vasut 4478ae51b6fSMarek Vasut /* Setting the control will start the AVB-DMAC process. */ 4488ae51b6fSMarek Vasut writel(CCC_OPC_OPERATION, eth->iobase + RAVB_REG_CCC); 4498ae51b6fSMarek Vasut 4508ae51b6fSMarek Vasut return 0; 4518ae51b6fSMarek Vasut } 4528ae51b6fSMarek Vasut 4538ae51b6fSMarek Vasut static void ravb_stop(struct udevice *dev) 4548ae51b6fSMarek Vasut { 4558ae51b6fSMarek Vasut ravb_reset(dev); 4568ae51b6fSMarek Vasut } 4578ae51b6fSMarek Vasut 4588ae51b6fSMarek Vasut static int ravb_probe(struct udevice *dev) 4598ae51b6fSMarek Vasut { 4608ae51b6fSMarek Vasut struct eth_pdata *pdata = dev_get_platdata(dev); 4618ae51b6fSMarek Vasut struct ravb_priv *eth = dev_get_priv(dev); 4628ae51b6fSMarek Vasut struct mii_dev *mdiodev; 4638ae51b6fSMarek Vasut void __iomem *iobase; 4648ae51b6fSMarek Vasut int ret; 4658ae51b6fSMarek Vasut 4668ae51b6fSMarek Vasut iobase = map_physmem(pdata->iobase, 0x1000, MAP_NOCACHE); 4678ae51b6fSMarek Vasut eth->iobase = iobase; 4688ae51b6fSMarek Vasut 4698ae51b6fSMarek Vasut mdiodev = mdio_alloc(); 4708ae51b6fSMarek Vasut if (!mdiodev) { 4718ae51b6fSMarek Vasut ret = -ENOMEM; 4728ae51b6fSMarek Vasut goto err_mdio_alloc; 4738ae51b6fSMarek Vasut } 4748ae51b6fSMarek Vasut 4758ae51b6fSMarek Vasut mdiodev->read = bb_miiphy_read; 4768ae51b6fSMarek Vasut mdiodev->write = bb_miiphy_write; 4778ae51b6fSMarek Vasut bb_miiphy_buses[0].priv = eth; 4788ae51b6fSMarek Vasut snprintf(mdiodev->name, sizeof(mdiodev->name), dev->name); 4798ae51b6fSMarek Vasut 4808ae51b6fSMarek Vasut ret = mdio_register(mdiodev); 4818ae51b6fSMarek Vasut if (ret < 0) 4828ae51b6fSMarek Vasut goto err_mdio_register; 4838ae51b6fSMarek Vasut 4848ae51b6fSMarek Vasut eth->bus = miiphy_get_dev_by_name(dev->name); 4858ae51b6fSMarek Vasut 4868ae51b6fSMarek Vasut return 0; 4878ae51b6fSMarek Vasut 4888ae51b6fSMarek Vasut err_mdio_register: 4898ae51b6fSMarek Vasut mdio_free(mdiodev); 4908ae51b6fSMarek Vasut err_mdio_alloc: 4918ae51b6fSMarek Vasut unmap_physmem(eth->iobase, MAP_NOCACHE); 4928ae51b6fSMarek Vasut return ret; 4938ae51b6fSMarek Vasut } 4948ae51b6fSMarek Vasut 4958ae51b6fSMarek Vasut static int ravb_remove(struct udevice *dev) 4968ae51b6fSMarek Vasut { 4978ae51b6fSMarek Vasut struct ravb_priv *eth = dev_get_priv(dev); 4988ae51b6fSMarek Vasut 4998ae51b6fSMarek Vasut free(eth->phydev); 5008ae51b6fSMarek Vasut mdio_unregister(eth->bus); 5018ae51b6fSMarek Vasut mdio_free(eth->bus); 5028ae51b6fSMarek Vasut unmap_physmem(eth->iobase, MAP_NOCACHE); 5038ae51b6fSMarek Vasut 5048ae51b6fSMarek Vasut return 0; 5058ae51b6fSMarek Vasut } 5068ae51b6fSMarek Vasut 5078ae51b6fSMarek Vasut int ravb_bb_init(struct bb_miiphy_bus *bus) 5088ae51b6fSMarek Vasut { 5098ae51b6fSMarek Vasut return 0; 5108ae51b6fSMarek Vasut } 5118ae51b6fSMarek Vasut 5128ae51b6fSMarek Vasut int ravb_bb_mdio_active(struct bb_miiphy_bus *bus) 5138ae51b6fSMarek Vasut { 5148ae51b6fSMarek Vasut struct ravb_priv *eth = bus->priv; 5158ae51b6fSMarek Vasut 5168ae51b6fSMarek Vasut setbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MMD); 5178ae51b6fSMarek Vasut 5188ae51b6fSMarek Vasut return 0; 5198ae51b6fSMarek Vasut } 5208ae51b6fSMarek Vasut 5218ae51b6fSMarek Vasut int ravb_bb_mdio_tristate(struct bb_miiphy_bus *bus) 5228ae51b6fSMarek Vasut { 5238ae51b6fSMarek Vasut struct ravb_priv *eth = bus->priv; 5248ae51b6fSMarek Vasut 5258ae51b6fSMarek Vasut clrbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MMD); 5268ae51b6fSMarek Vasut 5278ae51b6fSMarek Vasut return 0; 5288ae51b6fSMarek Vasut } 5298ae51b6fSMarek Vasut 5308ae51b6fSMarek Vasut int ravb_bb_set_mdio(struct bb_miiphy_bus *bus, int v) 5318ae51b6fSMarek Vasut { 5328ae51b6fSMarek Vasut struct ravb_priv *eth = bus->priv; 5338ae51b6fSMarek Vasut 5348ae51b6fSMarek Vasut if (v) 5358ae51b6fSMarek Vasut setbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MDO); 5368ae51b6fSMarek Vasut else 5378ae51b6fSMarek Vasut clrbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MDO); 5388ae51b6fSMarek Vasut 5398ae51b6fSMarek Vasut return 0; 5408ae51b6fSMarek Vasut } 5418ae51b6fSMarek Vasut 5428ae51b6fSMarek Vasut int ravb_bb_get_mdio(struct bb_miiphy_bus *bus, int *v) 5438ae51b6fSMarek Vasut { 5448ae51b6fSMarek Vasut struct ravb_priv *eth = bus->priv; 5458ae51b6fSMarek Vasut 5468ae51b6fSMarek Vasut *v = (readl(eth->iobase + RAVB_REG_PIR) & PIR_MDI) >> 3; 5478ae51b6fSMarek Vasut 5488ae51b6fSMarek Vasut return 0; 5498ae51b6fSMarek Vasut } 5508ae51b6fSMarek Vasut 5518ae51b6fSMarek Vasut int ravb_bb_set_mdc(struct bb_miiphy_bus *bus, int v) 5528ae51b6fSMarek Vasut { 5538ae51b6fSMarek Vasut struct ravb_priv *eth = bus->priv; 5548ae51b6fSMarek Vasut 5558ae51b6fSMarek Vasut if (v) 5568ae51b6fSMarek Vasut setbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MDC); 5578ae51b6fSMarek Vasut else 5588ae51b6fSMarek Vasut clrbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MDC); 5598ae51b6fSMarek Vasut 5608ae51b6fSMarek Vasut return 0; 5618ae51b6fSMarek Vasut } 5628ae51b6fSMarek Vasut 5638ae51b6fSMarek Vasut int ravb_bb_delay(struct bb_miiphy_bus *bus) 5648ae51b6fSMarek Vasut { 5658ae51b6fSMarek Vasut udelay(10); 5668ae51b6fSMarek Vasut 5678ae51b6fSMarek Vasut return 0; 5688ae51b6fSMarek Vasut } 5698ae51b6fSMarek Vasut 5708ae51b6fSMarek Vasut struct bb_miiphy_bus bb_miiphy_buses[] = { 5718ae51b6fSMarek Vasut { 5728ae51b6fSMarek Vasut .name = "ravb", 5738ae51b6fSMarek Vasut .init = ravb_bb_init, 5748ae51b6fSMarek Vasut .mdio_active = ravb_bb_mdio_active, 5758ae51b6fSMarek Vasut .mdio_tristate = ravb_bb_mdio_tristate, 5768ae51b6fSMarek Vasut .set_mdio = ravb_bb_set_mdio, 5778ae51b6fSMarek Vasut .get_mdio = ravb_bb_get_mdio, 5788ae51b6fSMarek Vasut .set_mdc = ravb_bb_set_mdc, 5798ae51b6fSMarek Vasut .delay = ravb_bb_delay, 5808ae51b6fSMarek Vasut }, 5818ae51b6fSMarek Vasut }; 5828ae51b6fSMarek Vasut int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses); 5838ae51b6fSMarek Vasut 5848ae51b6fSMarek Vasut static const struct eth_ops ravb_ops = { 5858ae51b6fSMarek Vasut .start = ravb_start, 5868ae51b6fSMarek Vasut .send = ravb_send, 5878ae51b6fSMarek Vasut .recv = ravb_recv, 5888ae51b6fSMarek Vasut .free_pkt = ravb_free_pkt, 5898ae51b6fSMarek Vasut .stop = ravb_stop, 5908ae51b6fSMarek Vasut .write_hwaddr = ravb_write_hwaddr, 5918ae51b6fSMarek Vasut }; 5928ae51b6fSMarek Vasut 5935ee8b4d7SMarek Vasut int ravb_ofdata_to_platdata(struct udevice *dev) 5945ee8b4d7SMarek Vasut { 5955ee8b4d7SMarek Vasut struct eth_pdata *pdata = dev_get_platdata(dev); 5965ee8b4d7SMarek Vasut const char *phy_mode; 5975ee8b4d7SMarek Vasut const fdt32_t *cell; 5985ee8b4d7SMarek Vasut int ret = 0; 5995ee8b4d7SMarek Vasut 6005ee8b4d7SMarek Vasut pdata->iobase = devfdt_get_addr(dev); 6015ee8b4d7SMarek Vasut pdata->phy_interface = -1; 6025ee8b4d7SMarek Vasut phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", 6035ee8b4d7SMarek Vasut NULL); 6045ee8b4d7SMarek Vasut if (phy_mode) 6055ee8b4d7SMarek Vasut pdata->phy_interface = phy_get_interface_by_name(phy_mode); 6065ee8b4d7SMarek Vasut if (pdata->phy_interface == -1) { 6075ee8b4d7SMarek Vasut debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); 6085ee8b4d7SMarek Vasut return -EINVAL; 6095ee8b4d7SMarek Vasut } 6105ee8b4d7SMarek Vasut 6115ee8b4d7SMarek Vasut pdata->max_speed = 1000; 6125ee8b4d7SMarek Vasut cell = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "max-speed", NULL); 6135ee8b4d7SMarek Vasut if (cell) 6145ee8b4d7SMarek Vasut pdata->max_speed = fdt32_to_cpu(*cell); 6155ee8b4d7SMarek Vasut 6165ee8b4d7SMarek Vasut sprintf(bb_miiphy_buses[0].name, dev->name); 6175ee8b4d7SMarek Vasut 6185ee8b4d7SMarek Vasut return ret; 6195ee8b4d7SMarek Vasut } 6205ee8b4d7SMarek Vasut 6215ee8b4d7SMarek Vasut static const struct udevice_id ravb_ids[] = { 6225ee8b4d7SMarek Vasut { .compatible = "renesas,etheravb-r8a7795" }, 6235ee8b4d7SMarek Vasut { .compatible = "renesas,etheravb-r8a7796" }, 6245ee8b4d7SMarek Vasut { .compatible = "renesas,etheravb-rcar-gen3" }, 6255ee8b4d7SMarek Vasut { } 6265ee8b4d7SMarek Vasut }; 6275ee8b4d7SMarek Vasut 6288ae51b6fSMarek Vasut U_BOOT_DRIVER(eth_ravb) = { 6298ae51b6fSMarek Vasut .name = "ravb", 6308ae51b6fSMarek Vasut .id = UCLASS_ETH, 6315ee8b4d7SMarek Vasut .of_match = ravb_ids, 6325ee8b4d7SMarek Vasut .ofdata_to_platdata = ravb_ofdata_to_platdata, 6338ae51b6fSMarek Vasut .probe = ravb_probe, 6348ae51b6fSMarek Vasut .remove = ravb_remove, 6358ae51b6fSMarek Vasut .ops = &ravb_ops, 6368ae51b6fSMarek Vasut .priv_auto_alloc_size = sizeof(struct ravb_priv), 6378ae51b6fSMarek Vasut .platdata_auto_alloc_size = sizeof(struct eth_pdata), 6388ae51b6fSMarek Vasut .flags = DM_FLAG_ALLOC_PRIV_DMA, 6398ae51b6fSMarek Vasut }; 640