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