1ba4dfef1SStephen Warren /* 2ba4dfef1SStephen Warren * Copyright (c) 2016, NVIDIA CORPORATION. 3ba4dfef1SStephen Warren * 4ba4dfef1SStephen Warren * SPDX-License-Identifier: GPL-2.0 5ba4dfef1SStephen Warren * 6ba4dfef1SStephen Warren * Portions based on U-Boot's rtl8169.c. 7ba4dfef1SStephen Warren */ 8ba4dfef1SStephen Warren 9ba4dfef1SStephen Warren /* 10ba4dfef1SStephen Warren * This driver supports the Synopsys Designware Ethernet QOS (Quality Of 11ba4dfef1SStephen Warren * Service) IP block. The IP supports multiple options for bus type, clocking/ 12ba4dfef1SStephen Warren * reset structure, and feature list. 13ba4dfef1SStephen Warren * 14ba4dfef1SStephen Warren * The driver is written such that generic core logic is kept separate from 15ba4dfef1SStephen Warren * configuration-specific logic. Code that interacts with configuration- 16ba4dfef1SStephen Warren * specific resources is split out into separate functions to avoid polluting 17ba4dfef1SStephen Warren * common code. If/when this driver is enhanced to support multiple 18ba4dfef1SStephen Warren * configurations, the core code should be adapted to call all configuration- 19ba4dfef1SStephen Warren * specific functions through function pointers, with the definition of those 20ba4dfef1SStephen Warren * function pointers being supplied by struct udevice_id eqos_ids[]'s .data 21ba4dfef1SStephen Warren * field. 22ba4dfef1SStephen Warren * 23ba4dfef1SStephen Warren * The following configurations are currently supported: 24ba4dfef1SStephen Warren * tegra186: 25ba4dfef1SStephen Warren * NVIDIA's Tegra186 chip. This configuration uses an AXI master/DMA bus, an 26ba4dfef1SStephen Warren * AHB slave/register bus, contains the DMA, MTL, and MAC sub-blocks, and 27ba4dfef1SStephen Warren * supports a single RGMII PHY. This configuration also has SW control over 28ba4dfef1SStephen Warren * all clock and reset signals to the HW block. 29ba4dfef1SStephen Warren */ 30ba4dfef1SStephen Warren #include <common.h> 31ba4dfef1SStephen Warren #include <clk.h> 32ba4dfef1SStephen Warren #include <dm.h> 33ba4dfef1SStephen Warren #include <errno.h> 34ba4dfef1SStephen Warren #include <memalign.h> 35ba4dfef1SStephen Warren #include <miiphy.h> 36ba4dfef1SStephen Warren #include <net.h> 37ba4dfef1SStephen Warren #include <netdev.h> 38ba4dfef1SStephen Warren #include <phy.h> 39ba4dfef1SStephen Warren #include <reset.h> 40ba4dfef1SStephen Warren #include <wait_bit.h> 41ba4dfef1SStephen Warren #include <asm/gpio.h> 42ba4dfef1SStephen Warren #include <asm/io.h> 438e3eceb0SYe Li #include <eth_phy.h> 44ad018a0cSFugang Duan #ifdef CONFIG_ARCH_IMX8M 45ad018a0cSFugang Duan #include <asm/arch/clock.h> 46ad018a0cSFugang Duan #include <asm/mach-imx/sys_proto.h> 47ad018a0cSFugang Duan #endif 48ba4dfef1SStephen Warren 49ba4dfef1SStephen Warren /* Core registers */ 50ba4dfef1SStephen Warren 51ba4dfef1SStephen Warren #define EQOS_MAC_REGS_BASE 0x000 52ba4dfef1SStephen Warren struct eqos_mac_regs { 53ba4dfef1SStephen Warren uint32_t configuration; /* 0x000 */ 54ba4dfef1SStephen Warren uint32_t unused_004[(0x070 - 0x004) / 4]; /* 0x004 */ 55ba4dfef1SStephen Warren uint32_t q0_tx_flow_ctrl; /* 0x070 */ 56ba4dfef1SStephen Warren uint32_t unused_070[(0x090 - 0x074) / 4]; /* 0x074 */ 57ba4dfef1SStephen Warren uint32_t rx_flow_ctrl; /* 0x090 */ 58ba4dfef1SStephen Warren uint32_t unused_094; /* 0x094 */ 59ba4dfef1SStephen Warren uint32_t txq_prty_map0; /* 0x098 */ 60ba4dfef1SStephen Warren uint32_t unused_09c; /* 0x09c */ 61ba4dfef1SStephen Warren uint32_t rxq_ctrl0; /* 0x0a0 */ 62ba4dfef1SStephen Warren uint32_t unused_0a4; /* 0x0a4 */ 63ba4dfef1SStephen Warren uint32_t rxq_ctrl2; /* 0x0a8 */ 64ba4dfef1SStephen Warren uint32_t unused_0ac[(0x0dc - 0x0ac) / 4]; /* 0x0ac */ 65ba4dfef1SStephen Warren uint32_t us_tic_counter; /* 0x0dc */ 66ba4dfef1SStephen Warren uint32_t unused_0e0[(0x11c - 0x0e0) / 4]; /* 0x0e0 */ 67ba4dfef1SStephen Warren uint32_t hw_feature0; /* 0x11c */ 68ba4dfef1SStephen Warren uint32_t hw_feature1; /* 0x120 */ 69ba4dfef1SStephen Warren uint32_t hw_feature2; /* 0x124 */ 70ba4dfef1SStephen Warren uint32_t unused_128[(0x200 - 0x128) / 4]; /* 0x128 */ 71ba4dfef1SStephen Warren uint32_t mdio_address; /* 0x200 */ 72ba4dfef1SStephen Warren uint32_t mdio_data; /* 0x204 */ 73ba4dfef1SStephen Warren uint32_t unused_208[(0x300 - 0x208) / 4]; /* 0x208 */ 74ba4dfef1SStephen Warren uint32_t address0_high; /* 0x300 */ 75ba4dfef1SStephen Warren uint32_t address0_low; /* 0x304 */ 76ba4dfef1SStephen Warren }; 77ba4dfef1SStephen Warren 78ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_GPSLCE BIT(23) 79ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_CST BIT(21) 80ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_ACS BIT(20) 81ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_WD BIT(19) 82ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_JD BIT(17) 83ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_JE BIT(16) 84ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_PS BIT(15) 85ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_FES BIT(14) 86ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_DM BIT(13) 87a7b3400fSFugang Duan #define EQOS_MAC_CONFIGURATION_LM BIT(12) 88ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_TE BIT(1) 89ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_RE BIT(0) 90ba4dfef1SStephen Warren 91ba4dfef1SStephen Warren #define EQOS_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT 16 92ba4dfef1SStephen Warren #define EQOS_MAC_Q0_TX_FLOW_CTRL_PT_MASK 0xffff 93ba4dfef1SStephen Warren #define EQOS_MAC_Q0_TX_FLOW_CTRL_TFE BIT(1) 94ba4dfef1SStephen Warren 95ba4dfef1SStephen Warren #define EQOS_MAC_RX_FLOW_CTRL_RFE BIT(0) 96ba4dfef1SStephen Warren 97ba4dfef1SStephen Warren #define EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_SHIFT 0 98ba4dfef1SStephen Warren #define EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_MASK 0xff 99ba4dfef1SStephen Warren 100ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT 0 101ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK 3 102ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_NOT_ENABLED 0 103ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB 2 1047a4c4eddSChristophe Roullier #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV 1 105ba4dfef1SStephen Warren 106ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT 0 107ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK 0xff 108ba4dfef1SStephen Warren 109a7b3400fSFugang Duan #define EQOS_MAC_HW_FEATURE0_MMCSEL_SHIFT 8 110a7b3400fSFugang Duan #define EQOS_MAC_HW_FEATURE0_HDSEL_SHIFT 2 111a7b3400fSFugang Duan #define EQOS_MAC_HW_FEATURE0_GMIISEL_SHIFT 1 112a7b3400fSFugang Duan #define EQOS_MAC_HW_FEATURE0_MIISEL_SHIFT 0 113a7b3400fSFugang Duan 114ba4dfef1SStephen Warren #define EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_SHIFT 6 115ba4dfef1SStephen Warren #define EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_MASK 0x1f 116ba4dfef1SStephen Warren #define EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT 0 117ba4dfef1SStephen Warren #define EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK 0x1f 118ba4dfef1SStephen Warren 119a7b3400fSFugang Duan #define EQOS_MAC_HW_FEATURE3_ASP_SHIFT 28 120a7b3400fSFugang Duan #define EQOS_MAC_HW_FEATURE3_ASP_MASK 0x3 121a7b3400fSFugang Duan 122ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_PA_SHIFT 21 123ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT 16 124ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT 8 125ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_CR_20_35 2 1267a4c4eddSChristophe Roullier #define EQOS_MAC_MDIO_ADDRESS_CR_250_300 5 127ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_SKAP BIT(4) 128ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT 2 129ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_GOC_READ 3 130ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_GOC_WRITE 1 131ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_C45E BIT(1) 132ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_GB BIT(0) 133ba4dfef1SStephen Warren 134ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_DATA_GD_MASK 0xffff 135ba4dfef1SStephen Warren 136ba4dfef1SStephen Warren #define EQOS_MTL_REGS_BASE 0xd00 137ba4dfef1SStephen Warren struct eqos_mtl_regs { 138ba4dfef1SStephen Warren uint32_t txq0_operation_mode; /* 0xd00 */ 139ba4dfef1SStephen Warren uint32_t unused_d04; /* 0xd04 */ 140ba4dfef1SStephen Warren uint32_t txq0_debug; /* 0xd08 */ 141ba4dfef1SStephen Warren uint32_t unused_d0c[(0xd18 - 0xd0c) / 4]; /* 0xd0c */ 142ba4dfef1SStephen Warren uint32_t txq0_quantum_weight; /* 0xd18 */ 143ba4dfef1SStephen Warren uint32_t unused_d1c[(0xd30 - 0xd1c) / 4]; /* 0xd1c */ 144ba4dfef1SStephen Warren uint32_t rxq0_operation_mode; /* 0xd30 */ 145ba4dfef1SStephen Warren uint32_t unused_d34; /* 0xd34 */ 146ba4dfef1SStephen Warren uint32_t rxq0_debug; /* 0xd38 */ 147ba4dfef1SStephen Warren }; 148ba4dfef1SStephen Warren 149ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT 16 150ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK 0x1ff 151ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_SHIFT 2 152ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_MASK 3 153ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_ENABLED 2 154ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TSF BIT(1) 155ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_FTQ BIT(0) 156ba4dfef1SStephen Warren 157ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_DEBUG_TXQSTS BIT(4) 158ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_DEBUG_TRCSTS_SHIFT 1 159ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_DEBUG_TRCSTS_MASK 3 160ba4dfef1SStephen Warren 161ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT 20 162ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RQS_MASK 0x3ff 163ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT 14 164ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RFD_MASK 0x3f 165ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT 8 166ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RFA_MASK 0x3f 167ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_EHFC BIT(7) 168ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RSF BIT(5) 169a7b3400fSFugang Duan #define EQOS_MTL_RXQ0_OPERATION_MODE_FEP BIT(4) 170a7b3400fSFugang Duan #define EQOS_MTL_RXQ0_OPERATION_MODE_FUP BIT(3) 171ba4dfef1SStephen Warren 172ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_DEBUG_PRXQ_SHIFT 16 173ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_DEBUG_PRXQ_MASK 0x7fff 174ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_DEBUG_RXQSTS_SHIFT 4 175ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_DEBUG_RXQSTS_MASK 3 176ba4dfef1SStephen Warren 177ba4dfef1SStephen Warren #define EQOS_DMA_REGS_BASE 0x1000 178ba4dfef1SStephen Warren struct eqos_dma_regs { 179ba4dfef1SStephen Warren uint32_t mode; /* 0x1000 */ 180ba4dfef1SStephen Warren uint32_t sysbus_mode; /* 0x1004 */ 181ba4dfef1SStephen Warren uint32_t unused_1008[(0x1100 - 0x1008) / 4]; /* 0x1008 */ 182ba4dfef1SStephen Warren uint32_t ch0_control; /* 0x1100 */ 183ba4dfef1SStephen Warren uint32_t ch0_tx_control; /* 0x1104 */ 184ba4dfef1SStephen Warren uint32_t ch0_rx_control; /* 0x1108 */ 185ba4dfef1SStephen Warren uint32_t unused_110c; /* 0x110c */ 186ba4dfef1SStephen Warren uint32_t ch0_txdesc_list_haddress; /* 0x1110 */ 187ba4dfef1SStephen Warren uint32_t ch0_txdesc_list_address; /* 0x1114 */ 188ba4dfef1SStephen Warren uint32_t ch0_rxdesc_list_haddress; /* 0x1118 */ 189ba4dfef1SStephen Warren uint32_t ch0_rxdesc_list_address; /* 0x111c */ 190ba4dfef1SStephen Warren uint32_t ch0_txdesc_tail_pointer; /* 0x1120 */ 191ba4dfef1SStephen Warren uint32_t unused_1124; /* 0x1124 */ 192ba4dfef1SStephen Warren uint32_t ch0_rxdesc_tail_pointer; /* 0x1128 */ 193ba4dfef1SStephen Warren uint32_t ch0_txdesc_ring_length; /* 0x112c */ 194ba4dfef1SStephen Warren uint32_t ch0_rxdesc_ring_length; /* 0x1130 */ 195ba4dfef1SStephen Warren }; 196ba4dfef1SStephen Warren 197ba4dfef1SStephen Warren #define EQOS_DMA_MODE_SWR BIT(0) 198ba4dfef1SStephen Warren 199ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_SHIFT 16 200ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_MASK 0xf 201ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_EAME BIT(11) 202ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_BLEN16 BIT(3) 203ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_BLEN8 BIT(2) 204ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_BLEN4 BIT(1) 205ba4dfef1SStephen Warren 206ba4dfef1SStephen Warren #define EQOS_DMA_CH0_CONTROL_PBLX8 BIT(16) 207ba4dfef1SStephen Warren 208ba4dfef1SStephen Warren #define EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT 16 209ba4dfef1SStephen Warren #define EQOS_DMA_CH0_TX_CONTROL_TXPBL_MASK 0x3f 210ba4dfef1SStephen Warren #define EQOS_DMA_CH0_TX_CONTROL_OSP BIT(4) 211ba4dfef1SStephen Warren #define EQOS_DMA_CH0_TX_CONTROL_ST BIT(0) 212ba4dfef1SStephen Warren 213ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT 16 214ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_RXPBL_MASK 0x3f 215ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT 1 216ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_RBSZ_MASK 0x3fff 217ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_SR BIT(0) 218ba4dfef1SStephen Warren 219ba4dfef1SStephen Warren /* These registers are Tegra186-specific */ 220ba4dfef1SStephen Warren #define EQOS_TEGRA186_REGS_BASE 0x8800 221ba4dfef1SStephen Warren struct eqos_tegra186_regs { 222ba4dfef1SStephen Warren uint32_t sdmemcomppadctrl; /* 0x8800 */ 223ba4dfef1SStephen Warren uint32_t auto_cal_config; /* 0x8804 */ 224ba4dfef1SStephen Warren uint32_t unused_8808; /* 0x8808 */ 225ba4dfef1SStephen Warren uint32_t auto_cal_status; /* 0x880c */ 226ba4dfef1SStephen Warren }; 227ba4dfef1SStephen Warren 228ba4dfef1SStephen Warren #define EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31) 229ba4dfef1SStephen Warren 230ba4dfef1SStephen Warren #define EQOS_AUTO_CAL_CONFIG_START BIT(31) 231ba4dfef1SStephen Warren #define EQOS_AUTO_CAL_CONFIG_ENABLE BIT(29) 232ba4dfef1SStephen Warren 233ba4dfef1SStephen Warren #define EQOS_AUTO_CAL_STATUS_ACTIVE BIT(31) 234ba4dfef1SStephen Warren 235ba4dfef1SStephen Warren /* Descriptors */ 236ba4dfef1SStephen Warren 237ba4dfef1SStephen Warren #define EQOS_DESCRIPTOR_WORDS 4 238ba4dfef1SStephen Warren #define EQOS_DESCRIPTOR_SIZE (EQOS_DESCRIPTOR_WORDS * 4) 239ba4dfef1SStephen Warren /* We assume ARCH_DMA_MINALIGN >= 16; 16 is the EQOS HW minimum */ 240ba4dfef1SStephen Warren #define EQOS_DESCRIPTOR_ALIGN ARCH_DMA_MINALIGN 241ba4dfef1SStephen Warren #define EQOS_DESCRIPTORS_TX 4 242ba4dfef1SStephen Warren #define EQOS_DESCRIPTORS_RX 4 243ba4dfef1SStephen Warren #define EQOS_DESCRIPTORS_NUM (EQOS_DESCRIPTORS_TX + EQOS_DESCRIPTORS_RX) 244ba4dfef1SStephen Warren #define EQOS_DESCRIPTORS_SIZE ALIGN(EQOS_DESCRIPTORS_NUM * \ 245ba4dfef1SStephen Warren EQOS_DESCRIPTOR_SIZE, ARCH_DMA_MINALIGN) 246ba4dfef1SStephen Warren #define EQOS_BUFFER_ALIGN ARCH_DMA_MINALIGN 247ba4dfef1SStephen Warren #define EQOS_MAX_PACKET_SIZE ALIGN(1568, ARCH_DMA_MINALIGN) 248ba4dfef1SStephen Warren #define EQOS_RX_BUFFER_SIZE (EQOS_DESCRIPTORS_RX * EQOS_MAX_PACKET_SIZE) 249ba4dfef1SStephen Warren 250ba4dfef1SStephen Warren /* 251ba4dfef1SStephen Warren * Warn if the cache-line size is larger than the descriptor size. In such 252ba4dfef1SStephen Warren * cases the driver will likely fail because the CPU needs to flush the cache 253ba4dfef1SStephen Warren * when requeuing RX buffers, therefore descriptors written by the hardware 254ba4dfef1SStephen Warren * may be discarded. Architectures with full IO coherence, such as x86, do not 255ba4dfef1SStephen Warren * experience this issue, and hence are excluded from this condition. 256ba4dfef1SStephen Warren * 257ba4dfef1SStephen Warren * This can be fixed by defining CONFIG_SYS_NONCACHED_MEMORY which will cause 258ba4dfef1SStephen Warren * the driver to allocate descriptors from a pool of non-cached memory. 259ba4dfef1SStephen Warren */ 260ba4dfef1SStephen Warren #if EQOS_DESCRIPTOR_SIZE < ARCH_DMA_MINALIGN 261ba4dfef1SStephen Warren #if !defined(CONFIG_SYS_NONCACHED_MEMORY) && \ 262ba4dfef1SStephen Warren !defined(CONFIG_SYS_DCACHE_OFF) && !defined(CONFIG_X86) 263ba4dfef1SStephen Warren #warning Cache line size is larger than descriptor size 264ba4dfef1SStephen Warren #endif 265ba4dfef1SStephen Warren #endif 266ba4dfef1SStephen Warren 267ba4dfef1SStephen Warren struct eqos_desc { 268ba4dfef1SStephen Warren u32 des0; 269ba4dfef1SStephen Warren u32 des1; 270ba4dfef1SStephen Warren u32 des2; 271ba4dfef1SStephen Warren u32 des3; 272ba4dfef1SStephen Warren }; 273ba4dfef1SStephen Warren 274ba4dfef1SStephen Warren #define EQOS_DESC3_OWN BIT(31) 275ba4dfef1SStephen Warren #define EQOS_DESC3_FD BIT(29) 276ba4dfef1SStephen Warren #define EQOS_DESC3_LD BIT(28) 277ba4dfef1SStephen Warren #define EQOS_DESC3_BUF1V BIT(24) 278ba4dfef1SStephen Warren 279ba4dfef1SStephen Warren struct eqos_config { 280ba4dfef1SStephen Warren bool reg_access_always_ok; 2817a4c4eddSChristophe Roullier int mdio_wait; 2827a4c4eddSChristophe Roullier int swr_wait; 2837a4c4eddSChristophe Roullier int config_mac; 2847a4c4eddSChristophe Roullier int config_mac_mdio; 2857a4c4eddSChristophe Roullier struct eqos_ops *ops; 2867a4c4eddSChristophe Roullier }; 2877a4c4eddSChristophe Roullier 2887a4c4eddSChristophe Roullier struct eqos_ops { 2897a4c4eddSChristophe Roullier void (*eqos_inval_desc)(void *desc); 2907a4c4eddSChristophe Roullier void (*eqos_flush_desc)(void *desc); 2917a4c4eddSChristophe Roullier void (*eqos_inval_buffer)(void *buf, size_t size); 2927a4c4eddSChristophe Roullier void (*eqos_flush_buffer)(void *buf, size_t size); 2937a4c4eddSChristophe Roullier int (*eqos_probe_resources)(struct udevice *dev); 2947a4c4eddSChristophe Roullier int (*eqos_remove_resources)(struct udevice *dev); 2957a4c4eddSChristophe Roullier int (*eqos_stop_resets)(struct udevice *dev); 2967a4c4eddSChristophe Roullier int (*eqos_start_resets)(struct udevice *dev); 2977a4c4eddSChristophe Roullier void (*eqos_stop_clks)(struct udevice *dev); 2987a4c4eddSChristophe Roullier int (*eqos_start_clks)(struct udevice *dev); 2997a4c4eddSChristophe Roullier int (*eqos_calibrate_pads)(struct udevice *dev); 3007a4c4eddSChristophe Roullier int (*eqos_disable_calibration)(struct udevice *dev); 3017a4c4eddSChristophe Roullier int (*eqos_set_tx_clk_speed)(struct udevice *dev); 3027a4c4eddSChristophe Roullier ulong (*eqos_get_tick_clk_rate)(struct udevice *dev); 303*bbbbc81cSDavid Wu phy_interface_t (*eqos_get_interface)(struct udevice *dev); 304ba4dfef1SStephen Warren }; 305ba4dfef1SStephen Warren 306ba4dfef1SStephen Warren struct eqos_priv { 307ba4dfef1SStephen Warren struct udevice *dev; 308ba4dfef1SStephen Warren const struct eqos_config *config; 309ba4dfef1SStephen Warren fdt_addr_t regs; 310ba4dfef1SStephen Warren struct eqos_mac_regs *mac_regs; 311ba4dfef1SStephen Warren struct eqos_mtl_regs *mtl_regs; 312ba4dfef1SStephen Warren struct eqos_dma_regs *dma_regs; 313ba4dfef1SStephen Warren struct eqos_tegra186_regs *tegra186_regs; 314ba4dfef1SStephen Warren struct reset_ctl reset_ctl; 315ba4dfef1SStephen Warren struct gpio_desc phy_reset_gpio; 31613105a0bSDavid Wu u32 reset_delays[3]; 317ba4dfef1SStephen Warren struct clk clk_master_bus; 318ba4dfef1SStephen Warren struct clk clk_rx; 319ba4dfef1SStephen Warren struct clk clk_ptp_ref; 320ba4dfef1SStephen Warren struct clk clk_tx; 3217a4c4eddSChristophe Roullier struct clk clk_ck; 322ba4dfef1SStephen Warren struct clk clk_slave_bus; 323ba4dfef1SStephen Warren struct mii_dev *mii; 324ba4dfef1SStephen Warren struct phy_device *phy; 32583d31c08SPatrick Delaunay int phyaddr; 32683d31c08SPatrick Delaunay u32 max_speed; 327ba4dfef1SStephen Warren void *descs; 328ba4dfef1SStephen Warren struct eqos_desc *tx_descs; 329ba4dfef1SStephen Warren struct eqos_desc *rx_descs; 330ba4dfef1SStephen Warren int tx_desc_idx, rx_desc_idx; 331ba4dfef1SStephen Warren void *tx_dma_buf; 332ba4dfef1SStephen Warren void *rx_dma_buf; 333ba4dfef1SStephen Warren void *rx_pkt; 334ba4dfef1SStephen Warren bool started; 335ba4dfef1SStephen Warren bool reg_access_ok; 336ba4dfef1SStephen Warren }; 337ba4dfef1SStephen Warren 338ba4dfef1SStephen Warren /* 339ba4dfef1SStephen Warren * TX and RX descriptors are 16 bytes. This causes problems with the cache 340ba4dfef1SStephen Warren * maintenance on CPUs where the cache-line size exceeds the size of these 341ba4dfef1SStephen Warren * descriptors. What will happen is that when the driver receives a packet 342ba4dfef1SStephen Warren * it will be immediately requeued for the hardware to reuse. The CPU will 343ba4dfef1SStephen Warren * therefore need to flush the cache-line containing the descriptor, which 344ba4dfef1SStephen Warren * will cause all other descriptors in the same cache-line to be flushed 345ba4dfef1SStephen Warren * along with it. If one of those descriptors had been written to by the 346ba4dfef1SStephen Warren * device those changes (and the associated packet) will be lost. 347ba4dfef1SStephen Warren * 348ba4dfef1SStephen Warren * To work around this, we make use of non-cached memory if available. If 349ba4dfef1SStephen Warren * descriptors are mapped uncached there's no need to manually flush them 350ba4dfef1SStephen Warren * or invalidate them. 351ba4dfef1SStephen Warren * 352ba4dfef1SStephen Warren * Note that this only applies to descriptors. The packet data buffers do 353ba4dfef1SStephen Warren * not have the same constraints since they are 1536 bytes large, so they 354ba4dfef1SStephen Warren * are unlikely to share cache-lines. 355ba4dfef1SStephen Warren */ 356ba4dfef1SStephen Warren static void *eqos_alloc_descs(unsigned int num) 357ba4dfef1SStephen Warren { 358ba4dfef1SStephen Warren #ifdef CONFIG_SYS_NONCACHED_MEMORY 359ba4dfef1SStephen Warren return (void *)noncached_alloc(EQOS_DESCRIPTORS_SIZE, 360ba4dfef1SStephen Warren EQOS_DESCRIPTOR_ALIGN); 361ba4dfef1SStephen Warren #else 362ba4dfef1SStephen Warren return memalign(EQOS_DESCRIPTOR_ALIGN, EQOS_DESCRIPTORS_SIZE); 363ba4dfef1SStephen Warren #endif 364ba4dfef1SStephen Warren } 365ba4dfef1SStephen Warren 366ba4dfef1SStephen Warren static void eqos_free_descs(void *descs) 367ba4dfef1SStephen Warren { 368ba4dfef1SStephen Warren #ifdef CONFIG_SYS_NONCACHED_MEMORY 369ba4dfef1SStephen Warren /* FIXME: noncached_alloc() has no opposite */ 370ba4dfef1SStephen Warren #else 371ba4dfef1SStephen Warren free(descs); 372ba4dfef1SStephen Warren #endif 373ba4dfef1SStephen Warren } 374ba4dfef1SStephen Warren 3757a4c4eddSChristophe Roullier static void eqos_inval_desc_tegra186(void *desc) 376ba4dfef1SStephen Warren { 377ba4dfef1SStephen Warren #ifndef CONFIG_SYS_NONCACHED_MEMORY 378ba4dfef1SStephen Warren unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1); 379ba4dfef1SStephen Warren unsigned long end = ALIGN(start + EQOS_DESCRIPTOR_SIZE, 380ba4dfef1SStephen Warren ARCH_DMA_MINALIGN); 381ba4dfef1SStephen Warren 382ba4dfef1SStephen Warren invalidate_dcache_range(start, end); 383ba4dfef1SStephen Warren #endif 384ba4dfef1SStephen Warren } 385ba4dfef1SStephen Warren 386a7b3400fSFugang Duan static void eqos_inval_desc_generic(void *desc) 3877a4c4eddSChristophe Roullier { 3887a4c4eddSChristophe Roullier #ifndef CONFIG_SYS_NONCACHED_MEMORY 3897a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); 3907a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, 3917a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 3927a4c4eddSChristophe Roullier 3937a4c4eddSChristophe Roullier invalidate_dcache_range(start, end); 3947a4c4eddSChristophe Roullier #endif 3957a4c4eddSChristophe Roullier } 3967a4c4eddSChristophe Roullier 3977a4c4eddSChristophe Roullier static void eqos_flush_desc_tegra186(void *desc) 398ba4dfef1SStephen Warren { 399ba4dfef1SStephen Warren #ifndef CONFIG_SYS_NONCACHED_MEMORY 400ba4dfef1SStephen Warren flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE); 401ba4dfef1SStephen Warren #endif 402ba4dfef1SStephen Warren } 403ba4dfef1SStephen Warren 404a7b3400fSFugang Duan static void eqos_flush_desc_generic(void *desc) 4057a4c4eddSChristophe Roullier { 4067a4c4eddSChristophe Roullier #ifndef CONFIG_SYS_NONCACHED_MEMORY 4077a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); 4087a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, 4097a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 4107a4c4eddSChristophe Roullier 4117a4c4eddSChristophe Roullier flush_dcache_range(start, end); 4127a4c4eddSChristophe Roullier #endif 4137a4c4eddSChristophe Roullier } 4147a4c4eddSChristophe Roullier 4157a4c4eddSChristophe Roullier static void eqos_inval_buffer_tegra186(void *buf, size_t size) 416ba4dfef1SStephen Warren { 417ba4dfef1SStephen Warren unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1); 418ba4dfef1SStephen Warren unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN); 419ba4dfef1SStephen Warren 420ba4dfef1SStephen Warren invalidate_dcache_range(start, end); 421ba4dfef1SStephen Warren } 422ba4dfef1SStephen Warren 423a7b3400fSFugang Duan static void eqos_inval_buffer_generic(void *buf, size_t size) 4247a4c4eddSChristophe Roullier { 4257a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN); 4267a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)buf + size, 4277a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 4287a4c4eddSChristophe Roullier 4297a4c4eddSChristophe Roullier invalidate_dcache_range(start, end); 4307a4c4eddSChristophe Roullier } 4317a4c4eddSChristophe Roullier 4327a4c4eddSChristophe Roullier static void eqos_flush_buffer_tegra186(void *buf, size_t size) 433ba4dfef1SStephen Warren { 434ba4dfef1SStephen Warren flush_cache((unsigned long)buf, size); 435ba4dfef1SStephen Warren } 436ba4dfef1SStephen Warren 437a7b3400fSFugang Duan static void eqos_flush_buffer_generic(void *buf, size_t size) 4387a4c4eddSChristophe Roullier { 4397a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN); 4407a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)buf + size, 4417a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 4427a4c4eddSChristophe Roullier 4437a4c4eddSChristophe Roullier flush_dcache_range(start, end); 4447a4c4eddSChristophe Roullier } 4457a4c4eddSChristophe Roullier 446ba4dfef1SStephen Warren static int eqos_mdio_wait_idle(struct eqos_priv *eqos) 447ba4dfef1SStephen Warren { 448b491b498SJon Lin return wait_for_bit_le32(&eqos->mac_regs->mdio_address, 449b491b498SJon Lin EQOS_MAC_MDIO_ADDRESS_GB, false, 450b491b498SJon Lin 1000000, true); 451ba4dfef1SStephen Warren } 452ba4dfef1SStephen Warren 453ba4dfef1SStephen Warren static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad, 454ba4dfef1SStephen Warren int mdio_reg) 455ba4dfef1SStephen Warren { 456ba4dfef1SStephen Warren struct eqos_priv *eqos = bus->priv; 457ba4dfef1SStephen Warren u32 val; 458ba4dfef1SStephen Warren int ret; 459ba4dfef1SStephen Warren 460ba4dfef1SStephen Warren debug("%s(dev=%p, addr=%x, reg=%d):\n", __func__, eqos->dev, mdio_addr, 461ba4dfef1SStephen Warren mdio_reg); 462ba4dfef1SStephen Warren 463ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 464ba4dfef1SStephen Warren if (ret) { 46590aa625cSMasahiro Yamada pr_err("MDIO not idle at entry"); 466ba4dfef1SStephen Warren return ret; 467ba4dfef1SStephen Warren } 468ba4dfef1SStephen Warren 469ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->mdio_address); 470ba4dfef1SStephen Warren val &= EQOS_MAC_MDIO_ADDRESS_SKAP | 471ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_C45E; 472ba4dfef1SStephen Warren val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | 473ba4dfef1SStephen Warren (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) | 4747a4c4eddSChristophe Roullier (eqos->config->config_mac_mdio << 475ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | 476ba4dfef1SStephen Warren (EQOS_MAC_MDIO_ADDRESS_GOC_READ << 477ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | 478ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GB; 479ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->mdio_address); 480ba4dfef1SStephen Warren 4817a4c4eddSChristophe Roullier udelay(eqos->config->mdio_wait); 482ba4dfef1SStephen Warren 483ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 484ba4dfef1SStephen Warren if (ret) { 48590aa625cSMasahiro Yamada pr_err("MDIO read didn't complete"); 486ba4dfef1SStephen Warren return ret; 487ba4dfef1SStephen Warren } 488ba4dfef1SStephen Warren 489ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->mdio_data); 490ba4dfef1SStephen Warren val &= EQOS_MAC_MDIO_DATA_GD_MASK; 491ba4dfef1SStephen Warren 492ba4dfef1SStephen Warren debug("%s: val=%x\n", __func__, val); 493ba4dfef1SStephen Warren 494ba4dfef1SStephen Warren return val; 495ba4dfef1SStephen Warren } 496ba4dfef1SStephen Warren 497ba4dfef1SStephen Warren static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad, 498ba4dfef1SStephen Warren int mdio_reg, u16 mdio_val) 499ba4dfef1SStephen Warren { 500ba4dfef1SStephen Warren struct eqos_priv *eqos = bus->priv; 501ba4dfef1SStephen Warren u32 val; 502ba4dfef1SStephen Warren int ret; 503ba4dfef1SStephen Warren 504ba4dfef1SStephen Warren debug("%s(dev=%p, addr=%x, reg=%d, val=%x):\n", __func__, eqos->dev, 505ba4dfef1SStephen Warren mdio_addr, mdio_reg, mdio_val); 506ba4dfef1SStephen Warren 507ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 508ba4dfef1SStephen Warren if (ret) { 50990aa625cSMasahiro Yamada pr_err("MDIO not idle at entry"); 510ba4dfef1SStephen Warren return ret; 511ba4dfef1SStephen Warren } 512ba4dfef1SStephen Warren 513ba4dfef1SStephen Warren writel(mdio_val, &eqos->mac_regs->mdio_data); 514ba4dfef1SStephen Warren 515ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->mdio_address); 516ba4dfef1SStephen Warren val &= EQOS_MAC_MDIO_ADDRESS_SKAP | 517ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_C45E; 518ba4dfef1SStephen Warren val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | 519ba4dfef1SStephen Warren (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) | 5207a4c4eddSChristophe Roullier (eqos->config->config_mac_mdio << 521ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | 522ba4dfef1SStephen Warren (EQOS_MAC_MDIO_ADDRESS_GOC_WRITE << 523ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | 524ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GB; 525ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->mdio_address); 526ba4dfef1SStephen Warren 5277a4c4eddSChristophe Roullier udelay(eqos->config->mdio_wait); 528ba4dfef1SStephen Warren 529ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 530ba4dfef1SStephen Warren if (ret) { 53190aa625cSMasahiro Yamada pr_err("MDIO read didn't complete"); 532ba4dfef1SStephen Warren return ret; 533ba4dfef1SStephen Warren } 534ba4dfef1SStephen Warren 535ba4dfef1SStephen Warren return 0; 536ba4dfef1SStephen Warren } 537ba4dfef1SStephen Warren 538ba4dfef1SStephen Warren static int eqos_start_clks_tegra186(struct udevice *dev) 539ba4dfef1SStephen Warren { 540a7b3400fSFugang Duan #ifdef CONFIG_CLK 541ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 542ba4dfef1SStephen Warren int ret; 543ba4dfef1SStephen Warren 544ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 545ba4dfef1SStephen Warren 546ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_slave_bus); 547ba4dfef1SStephen Warren if (ret < 0) { 54890aa625cSMasahiro Yamada pr_err("clk_enable(clk_slave_bus) failed: %d", ret); 549ba4dfef1SStephen Warren goto err; 550ba4dfef1SStephen Warren } 551ba4dfef1SStephen Warren 552ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_master_bus); 553ba4dfef1SStephen Warren if (ret < 0) { 55490aa625cSMasahiro Yamada pr_err("clk_enable(clk_master_bus) failed: %d", ret); 555ba4dfef1SStephen Warren goto err_disable_clk_slave_bus; 556ba4dfef1SStephen Warren } 557ba4dfef1SStephen Warren 558ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_rx); 559ba4dfef1SStephen Warren if (ret < 0) { 56090aa625cSMasahiro Yamada pr_err("clk_enable(clk_rx) failed: %d", ret); 561ba4dfef1SStephen Warren goto err_disable_clk_master_bus; 562ba4dfef1SStephen Warren } 563ba4dfef1SStephen Warren 564ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_ptp_ref); 565ba4dfef1SStephen Warren if (ret < 0) { 56690aa625cSMasahiro Yamada pr_err("clk_enable(clk_ptp_ref) failed: %d", ret); 567ba4dfef1SStephen Warren goto err_disable_clk_rx; 568ba4dfef1SStephen Warren } 569ba4dfef1SStephen Warren 570ba4dfef1SStephen Warren ret = clk_set_rate(&eqos->clk_ptp_ref, 125 * 1000 * 1000); 571ba4dfef1SStephen Warren if (ret < 0) { 57290aa625cSMasahiro Yamada pr_err("clk_set_rate(clk_ptp_ref) failed: %d", ret); 573ba4dfef1SStephen Warren goto err_disable_clk_ptp_ref; 574ba4dfef1SStephen Warren } 575ba4dfef1SStephen Warren 576ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_tx); 577ba4dfef1SStephen Warren if (ret < 0) { 57890aa625cSMasahiro Yamada pr_err("clk_enable(clk_tx) failed: %d", ret); 579ba4dfef1SStephen Warren goto err_disable_clk_ptp_ref; 580ba4dfef1SStephen Warren } 581a7b3400fSFugang Duan #endif 582ba4dfef1SStephen Warren 583ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 584ba4dfef1SStephen Warren return 0; 585ba4dfef1SStephen Warren 586a7b3400fSFugang Duan #ifdef CONFIG_CLK 587ba4dfef1SStephen Warren err_disable_clk_ptp_ref: 588ba4dfef1SStephen Warren clk_disable(&eqos->clk_ptp_ref); 589ba4dfef1SStephen Warren err_disable_clk_rx: 590ba4dfef1SStephen Warren clk_disable(&eqos->clk_rx); 591ba4dfef1SStephen Warren err_disable_clk_master_bus: 592ba4dfef1SStephen Warren clk_disable(&eqos->clk_master_bus); 593ba4dfef1SStephen Warren err_disable_clk_slave_bus: 594ba4dfef1SStephen Warren clk_disable(&eqos->clk_slave_bus); 595ba4dfef1SStephen Warren err: 596ba4dfef1SStephen Warren debug("%s: FAILED: %d\n", __func__, ret); 597ba4dfef1SStephen Warren return ret; 598a7b3400fSFugang Duan #endif 599ba4dfef1SStephen Warren } 600ba4dfef1SStephen Warren 6017a4c4eddSChristophe Roullier static int eqos_start_clks_stm32(struct udevice *dev) 6027a4c4eddSChristophe Roullier { 603a7b3400fSFugang Duan #ifdef CONFIG_CLK 6047a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 6057a4c4eddSChristophe Roullier int ret; 6067a4c4eddSChristophe Roullier 6077a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 6087a4c4eddSChristophe Roullier 6097a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_master_bus); 6107a4c4eddSChristophe Roullier if (ret < 0) { 6117a4c4eddSChristophe Roullier pr_err("clk_enable(clk_master_bus) failed: %d", ret); 6127a4c4eddSChristophe Roullier goto err; 6137a4c4eddSChristophe Roullier } 6147a4c4eddSChristophe Roullier 6157a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_rx); 6167a4c4eddSChristophe Roullier if (ret < 0) { 6177a4c4eddSChristophe Roullier pr_err("clk_enable(clk_rx) failed: %d", ret); 6187a4c4eddSChristophe Roullier goto err_disable_clk_master_bus; 6197a4c4eddSChristophe Roullier } 6207a4c4eddSChristophe Roullier 6217a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_tx); 6227a4c4eddSChristophe Roullier if (ret < 0) { 6237a4c4eddSChristophe Roullier pr_err("clk_enable(clk_tx) failed: %d", ret); 6247a4c4eddSChristophe Roullier goto err_disable_clk_rx; 6257a4c4eddSChristophe Roullier } 6267a4c4eddSChristophe Roullier 6277a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) { 6287a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_ck); 6297a4c4eddSChristophe Roullier if (ret < 0) { 6307a4c4eddSChristophe Roullier pr_err("clk_enable(clk_ck) failed: %d", ret); 6317a4c4eddSChristophe Roullier goto err_disable_clk_tx; 6327a4c4eddSChristophe Roullier } 6337a4c4eddSChristophe Roullier } 634a7b3400fSFugang Duan #endif 6357a4c4eddSChristophe Roullier 6367a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 6377a4c4eddSChristophe Roullier return 0; 6387a4c4eddSChristophe Roullier 639a7b3400fSFugang Duan #ifdef CONFIG_CLK 6407a4c4eddSChristophe Roullier err_disable_clk_tx: 6417a4c4eddSChristophe Roullier clk_disable(&eqos->clk_tx); 6427a4c4eddSChristophe Roullier err_disable_clk_rx: 6437a4c4eddSChristophe Roullier clk_disable(&eqos->clk_rx); 6447a4c4eddSChristophe Roullier err_disable_clk_master_bus: 6457a4c4eddSChristophe Roullier clk_disable(&eqos->clk_master_bus); 6467a4c4eddSChristophe Roullier err: 6477a4c4eddSChristophe Roullier debug("%s: FAILED: %d\n", __func__, ret); 6487a4c4eddSChristophe Roullier return ret; 649a7b3400fSFugang Duan #endif 650a7b3400fSFugang Duan } 651a7b3400fSFugang Duan 652a7b3400fSFugang Duan static int eqos_start_clks_imx(struct udevice *dev) 653a7b3400fSFugang Duan { 654a7b3400fSFugang Duan return 0; 6557a4c4eddSChristophe Roullier } 6567a4c4eddSChristophe Roullier 6578aaada72SPatrick Delaunay static void eqos_stop_clks_tegra186(struct udevice *dev) 658ba4dfef1SStephen Warren { 659a7b3400fSFugang Duan #ifdef CONFIG_CLK 660ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 661ba4dfef1SStephen Warren 662ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 663ba4dfef1SStephen Warren 664ba4dfef1SStephen Warren clk_disable(&eqos->clk_tx); 665ba4dfef1SStephen Warren clk_disable(&eqos->clk_ptp_ref); 666ba4dfef1SStephen Warren clk_disable(&eqos->clk_rx); 667ba4dfef1SStephen Warren clk_disable(&eqos->clk_master_bus); 668ba4dfef1SStephen Warren clk_disable(&eqos->clk_slave_bus); 669a7b3400fSFugang Duan #endif 670ba4dfef1SStephen Warren 671ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 672ba4dfef1SStephen Warren } 673ba4dfef1SStephen Warren 6748aaada72SPatrick Delaunay static void eqos_stop_clks_stm32(struct udevice *dev) 6757a4c4eddSChristophe Roullier { 676a7b3400fSFugang Duan #ifdef CONFIG_CLK 6777a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 6787a4c4eddSChristophe Roullier 6797a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 6807a4c4eddSChristophe Roullier 6817a4c4eddSChristophe Roullier clk_disable(&eqos->clk_tx); 6827a4c4eddSChristophe Roullier clk_disable(&eqos->clk_rx); 6837a4c4eddSChristophe Roullier clk_disable(&eqos->clk_master_bus); 6847a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) 6857a4c4eddSChristophe Roullier clk_disable(&eqos->clk_ck); 686a7b3400fSFugang Duan #endif 6877a4c4eddSChristophe Roullier 6887a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 6897a4c4eddSChristophe Roullier } 6907a4c4eddSChristophe Roullier 691a7b3400fSFugang Duan static void eqos_stop_clks_imx(struct udevice *dev) 692a7b3400fSFugang Duan { 693a7b3400fSFugang Duan /* empty */ 694a7b3400fSFugang Duan } 695a7b3400fSFugang Duan 696ba4dfef1SStephen Warren static int eqos_start_resets_tegra186(struct udevice *dev) 697ba4dfef1SStephen Warren { 698ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 699ba4dfef1SStephen Warren int ret; 700ba4dfef1SStephen Warren 701ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 702ba4dfef1SStephen Warren 703ba4dfef1SStephen Warren ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 704ba4dfef1SStephen Warren if (ret < 0) { 70590aa625cSMasahiro Yamada pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", ret); 706ba4dfef1SStephen Warren return ret; 707ba4dfef1SStephen Warren } 708ba4dfef1SStephen Warren 709ba4dfef1SStephen Warren udelay(2); 710ba4dfef1SStephen Warren 711ba4dfef1SStephen Warren ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); 712ba4dfef1SStephen Warren if (ret < 0) { 71390aa625cSMasahiro Yamada pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret); 714ba4dfef1SStephen Warren return ret; 715ba4dfef1SStephen Warren } 716ba4dfef1SStephen Warren 717ba4dfef1SStephen Warren ret = reset_assert(&eqos->reset_ctl); 718ba4dfef1SStephen Warren if (ret < 0) { 71990aa625cSMasahiro Yamada pr_err("reset_assert() failed: %d", ret); 720ba4dfef1SStephen Warren return ret; 721ba4dfef1SStephen Warren } 722ba4dfef1SStephen Warren 723ba4dfef1SStephen Warren udelay(2); 724ba4dfef1SStephen Warren 725ba4dfef1SStephen Warren ret = reset_deassert(&eqos->reset_ctl); 726ba4dfef1SStephen Warren if (ret < 0) { 72790aa625cSMasahiro Yamada pr_err("reset_deassert() failed: %d", ret); 728ba4dfef1SStephen Warren return ret; 729ba4dfef1SStephen Warren } 730ba4dfef1SStephen Warren 731ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 732ba4dfef1SStephen Warren return 0; 733ba4dfef1SStephen Warren } 734ba4dfef1SStephen Warren 7357a4c4eddSChristophe Roullier static int eqos_start_resets_stm32(struct udevice *dev) 7367a4c4eddSChristophe Roullier { 7375bd3c538SChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 7385bd3c538SChristophe Roullier int ret; 7395bd3c538SChristophe Roullier 7405bd3c538SChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 7415bd3c538SChristophe Roullier if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) { 74213105a0bSDavid Wu ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); 74313105a0bSDavid Wu if (ret < 0) { 74413105a0bSDavid Wu pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", 74513105a0bSDavid Wu ret); 74613105a0bSDavid Wu return ret; 74713105a0bSDavid Wu } 74813105a0bSDavid Wu 74913105a0bSDavid Wu udelay(eqos->reset_delays[0]); 75013105a0bSDavid Wu 7515bd3c538SChristophe Roullier ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 7525bd3c538SChristophe Roullier if (ret < 0) { 7535bd3c538SChristophe Roullier pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", 7545bd3c538SChristophe Roullier ret); 7555bd3c538SChristophe Roullier return ret; 7565bd3c538SChristophe Roullier } 7575bd3c538SChristophe Roullier 75813105a0bSDavid Wu udelay(eqos->reset_delays[1]); 7595bd3c538SChristophe Roullier 7605bd3c538SChristophe Roullier ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); 7615bd3c538SChristophe Roullier if (ret < 0) { 7625bd3c538SChristophe Roullier pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", 7635bd3c538SChristophe Roullier ret); 7645bd3c538SChristophe Roullier return ret; 7655bd3c538SChristophe Roullier } 76613105a0bSDavid Wu 76713105a0bSDavid Wu udelay(eqos->reset_delays[2]); 7685bd3c538SChristophe Roullier } 7695bd3c538SChristophe Roullier debug("%s: OK\n", __func__); 7705bd3c538SChristophe Roullier 7717a4c4eddSChristophe Roullier return 0; 7727a4c4eddSChristophe Roullier } 7737a4c4eddSChristophe Roullier 774a7b3400fSFugang Duan static int eqos_start_resets_imx(struct udevice *dev) 775a7b3400fSFugang Duan { 776a7b3400fSFugang Duan return 0; 777a7b3400fSFugang Duan } 778a7b3400fSFugang Duan 779ba4dfef1SStephen Warren static int eqos_stop_resets_tegra186(struct udevice *dev) 780ba4dfef1SStephen Warren { 781ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 782ba4dfef1SStephen Warren 783ba4dfef1SStephen Warren reset_assert(&eqos->reset_ctl); 784ba4dfef1SStephen Warren dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 785ba4dfef1SStephen Warren 786ba4dfef1SStephen Warren return 0; 787ba4dfef1SStephen Warren } 788ba4dfef1SStephen Warren 7897a4c4eddSChristophe Roullier static int eqos_stop_resets_stm32(struct udevice *dev) 7907a4c4eddSChristophe Roullier { 7915bd3c538SChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 7925bd3c538SChristophe Roullier int ret; 7935bd3c538SChristophe Roullier 7945bd3c538SChristophe Roullier if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) { 7955bd3c538SChristophe Roullier ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 7965bd3c538SChristophe Roullier if (ret < 0) { 7975bd3c538SChristophe Roullier pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", 7985bd3c538SChristophe Roullier ret); 7995bd3c538SChristophe Roullier return ret; 8005bd3c538SChristophe Roullier } 8015bd3c538SChristophe Roullier } 8025bd3c538SChristophe Roullier 8037a4c4eddSChristophe Roullier return 0; 8047a4c4eddSChristophe Roullier } 8057a4c4eddSChristophe Roullier 806a7b3400fSFugang Duan static int eqos_stop_resets_imx(struct udevice *dev) 807a7b3400fSFugang Duan { 808a7b3400fSFugang Duan return 0; 809a7b3400fSFugang Duan } 810a7b3400fSFugang Duan 811ba4dfef1SStephen Warren static int eqos_calibrate_pads_tegra186(struct udevice *dev) 812ba4dfef1SStephen Warren { 813ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 814ba4dfef1SStephen Warren int ret; 815ba4dfef1SStephen Warren 816ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 817ba4dfef1SStephen Warren 818ba4dfef1SStephen Warren setbits_le32(&eqos->tegra186_regs->sdmemcomppadctrl, 819ba4dfef1SStephen Warren EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD); 820ba4dfef1SStephen Warren 821ba4dfef1SStephen Warren udelay(1); 822ba4dfef1SStephen Warren 823ba4dfef1SStephen Warren setbits_le32(&eqos->tegra186_regs->auto_cal_config, 824ba4dfef1SStephen Warren EQOS_AUTO_CAL_CONFIG_START | EQOS_AUTO_CAL_CONFIG_ENABLE); 825ba4dfef1SStephen Warren 826b491b498SJon Lin ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, 827ba4dfef1SStephen Warren EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false); 828ba4dfef1SStephen Warren if (ret) { 82990aa625cSMasahiro Yamada pr_err("calibrate didn't start"); 830ba4dfef1SStephen Warren goto failed; 831ba4dfef1SStephen Warren } 832ba4dfef1SStephen Warren 833b491b498SJon Lin ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, 834ba4dfef1SStephen Warren EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false); 835ba4dfef1SStephen Warren if (ret) { 83690aa625cSMasahiro Yamada pr_err("calibrate didn't finish"); 837ba4dfef1SStephen Warren goto failed; 838ba4dfef1SStephen Warren } 839ba4dfef1SStephen Warren 840ba4dfef1SStephen Warren ret = 0; 841ba4dfef1SStephen Warren 842ba4dfef1SStephen Warren failed: 843ba4dfef1SStephen Warren clrbits_le32(&eqos->tegra186_regs->sdmemcomppadctrl, 844ba4dfef1SStephen Warren EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD); 845ba4dfef1SStephen Warren 846ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 847ba4dfef1SStephen Warren 848ba4dfef1SStephen Warren return ret; 849ba4dfef1SStephen Warren } 850ba4dfef1SStephen Warren 851ba4dfef1SStephen Warren static int eqos_disable_calibration_tegra186(struct udevice *dev) 852ba4dfef1SStephen Warren { 853ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 854ba4dfef1SStephen Warren 855ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 856ba4dfef1SStephen Warren 857ba4dfef1SStephen Warren clrbits_le32(&eqos->tegra186_regs->auto_cal_config, 858ba4dfef1SStephen Warren EQOS_AUTO_CAL_CONFIG_ENABLE); 859ba4dfef1SStephen Warren 860ba4dfef1SStephen Warren return 0; 861ba4dfef1SStephen Warren } 862ba4dfef1SStephen Warren 863ba4dfef1SStephen Warren static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev) 864ba4dfef1SStephen Warren { 865a7b3400fSFugang Duan #ifdef CONFIG_CLK 866ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 867ba4dfef1SStephen Warren 868ba4dfef1SStephen Warren return clk_get_rate(&eqos->clk_slave_bus); 869a7b3400fSFugang Duan #else 870a7b3400fSFugang Duan return 0; 871a7b3400fSFugang Duan #endif 872ba4dfef1SStephen Warren } 873ba4dfef1SStephen Warren 8747a4c4eddSChristophe Roullier static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) 8757a4c4eddSChristophe Roullier { 876a7b3400fSFugang Duan #ifdef CONFIG_CLK 8777a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 8787a4c4eddSChristophe Roullier 8797a4c4eddSChristophe Roullier return clk_get_rate(&eqos->clk_master_bus); 880a7b3400fSFugang Duan #else 881a7b3400fSFugang Duan return 0; 882a7b3400fSFugang Duan #endif 883a7b3400fSFugang Duan } 884a7b3400fSFugang Duan 885ad018a0cSFugang Duan __weak u32 imx_get_eqos_csr_clk(void) 886ad018a0cSFugang Duan { 887ad018a0cSFugang Duan return 100 * 1000000; 888ad018a0cSFugang Duan } 889ad018a0cSFugang Duan __weak int imx_eqos_txclk_set_rate(unsigned long rate) 890ad018a0cSFugang Duan { 891ad018a0cSFugang Duan return 0; 892ad018a0cSFugang Duan } 893ad018a0cSFugang Duan 894a7b3400fSFugang Duan static ulong eqos_get_tick_clk_rate_imx(struct udevice *dev) 895a7b3400fSFugang Duan { 896ad018a0cSFugang Duan return imx_get_eqos_csr_clk(); 8977a4c4eddSChristophe Roullier } 8987a4c4eddSChristophe Roullier 8997a4c4eddSChristophe Roullier static int eqos_calibrate_pads_stm32(struct udevice *dev) 9007a4c4eddSChristophe Roullier { 9017a4c4eddSChristophe Roullier return 0; 9027a4c4eddSChristophe Roullier } 9037a4c4eddSChristophe Roullier 904a7b3400fSFugang Duan static int eqos_calibrate_pads_imx(struct udevice *dev) 905a7b3400fSFugang Duan { 906a7b3400fSFugang Duan return 0; 907a7b3400fSFugang Duan } 908a7b3400fSFugang Duan 9097a4c4eddSChristophe Roullier static int eqos_disable_calibration_stm32(struct udevice *dev) 9107a4c4eddSChristophe Roullier { 9117a4c4eddSChristophe Roullier return 0; 9127a4c4eddSChristophe Roullier } 9137a4c4eddSChristophe Roullier 914a7b3400fSFugang Duan static int eqos_disable_calibration_imx(struct udevice *dev) 915a7b3400fSFugang Duan { 916a7b3400fSFugang Duan return 0; 917a7b3400fSFugang Duan } 918a7b3400fSFugang Duan 919ba4dfef1SStephen Warren static int eqos_set_full_duplex(struct udevice *dev) 920ba4dfef1SStephen Warren { 921ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 922ba4dfef1SStephen Warren 923ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 924ba4dfef1SStephen Warren 925ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->configuration, EQOS_MAC_CONFIGURATION_DM); 926ba4dfef1SStephen Warren 927ba4dfef1SStephen Warren return 0; 928ba4dfef1SStephen Warren } 929ba4dfef1SStephen Warren 930ba4dfef1SStephen Warren static int eqos_set_half_duplex(struct udevice *dev) 931ba4dfef1SStephen Warren { 932ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 933ba4dfef1SStephen Warren 934ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 935ba4dfef1SStephen Warren 936ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, EQOS_MAC_CONFIGURATION_DM); 937ba4dfef1SStephen Warren 938ba4dfef1SStephen Warren /* WAR: Flush TX queue when switching to half-duplex */ 939ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->txq0_operation_mode, 940ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_FTQ); 941ba4dfef1SStephen Warren 942ba4dfef1SStephen Warren return 0; 943ba4dfef1SStephen Warren } 944ba4dfef1SStephen Warren 945ba4dfef1SStephen Warren static int eqos_set_gmii_speed(struct udevice *dev) 946ba4dfef1SStephen Warren { 947ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 948ba4dfef1SStephen Warren 949ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 950ba4dfef1SStephen Warren 951ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, 952ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_PS | EQOS_MAC_CONFIGURATION_FES); 953ba4dfef1SStephen Warren 954ba4dfef1SStephen Warren return 0; 955ba4dfef1SStephen Warren } 956ba4dfef1SStephen Warren 957ba4dfef1SStephen Warren static int eqos_set_mii_speed_100(struct udevice *dev) 958ba4dfef1SStephen Warren { 959ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 960ba4dfef1SStephen Warren 961ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 962ba4dfef1SStephen Warren 963ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->configuration, 964ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_PS | EQOS_MAC_CONFIGURATION_FES); 965ba4dfef1SStephen Warren 966ba4dfef1SStephen Warren return 0; 967ba4dfef1SStephen Warren } 968ba4dfef1SStephen Warren 969ba4dfef1SStephen Warren static int eqos_set_mii_speed_10(struct udevice *dev) 970ba4dfef1SStephen Warren { 971ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 972ba4dfef1SStephen Warren 973ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 974ba4dfef1SStephen Warren 975ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->configuration, 976ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_FES, EQOS_MAC_CONFIGURATION_PS); 977ba4dfef1SStephen Warren 978ba4dfef1SStephen Warren return 0; 979ba4dfef1SStephen Warren } 980ba4dfef1SStephen Warren 981ba4dfef1SStephen Warren static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev) 982ba4dfef1SStephen Warren { 983a7b3400fSFugang Duan #ifdef CONFIG_CLK 984ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 985ba4dfef1SStephen Warren ulong rate; 986ba4dfef1SStephen Warren int ret; 987ba4dfef1SStephen Warren 988ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 989ba4dfef1SStephen Warren 990ba4dfef1SStephen Warren switch (eqos->phy->speed) { 991ba4dfef1SStephen Warren case SPEED_1000: 992ba4dfef1SStephen Warren rate = 125 * 1000 * 1000; 993ba4dfef1SStephen Warren break; 994ba4dfef1SStephen Warren case SPEED_100: 995ba4dfef1SStephen Warren rate = 25 * 1000 * 1000; 996ba4dfef1SStephen Warren break; 997ba4dfef1SStephen Warren case SPEED_10: 998ba4dfef1SStephen Warren rate = 2.5 * 1000 * 1000; 999ba4dfef1SStephen Warren break; 1000ba4dfef1SStephen Warren default: 100190aa625cSMasahiro Yamada pr_err("invalid speed %d", eqos->phy->speed); 1002ba4dfef1SStephen Warren return -EINVAL; 1003ba4dfef1SStephen Warren } 1004ba4dfef1SStephen Warren 1005ba4dfef1SStephen Warren ret = clk_set_rate(&eqos->clk_tx, rate); 1006ba4dfef1SStephen Warren if (ret < 0) { 100790aa625cSMasahiro Yamada pr_err("clk_set_rate(tx_clk, %lu) failed: %d", rate, ret); 1008ba4dfef1SStephen Warren return ret; 1009ba4dfef1SStephen Warren } 1010a7b3400fSFugang Duan #endif 1011ba4dfef1SStephen Warren 1012ba4dfef1SStephen Warren return 0; 1013ba4dfef1SStephen Warren } 1014ba4dfef1SStephen Warren 10157a4c4eddSChristophe Roullier static int eqos_set_tx_clk_speed_stm32(struct udevice *dev) 10167a4c4eddSChristophe Roullier { 10177a4c4eddSChristophe Roullier return 0; 10187a4c4eddSChristophe Roullier } 10197a4c4eddSChristophe Roullier 1020a7b3400fSFugang Duan static int eqos_set_tx_clk_speed_imx(struct udevice *dev) 1021a7b3400fSFugang Duan { 1022ad018a0cSFugang Duan struct eqos_priv *eqos = dev_get_priv(dev); 1023ad018a0cSFugang Duan ulong rate; 1024ad018a0cSFugang Duan int ret; 1025ad018a0cSFugang Duan 1026ad018a0cSFugang Duan debug("%s(dev=%p):\n", __func__, dev); 1027ad018a0cSFugang Duan 1028ad018a0cSFugang Duan switch (eqos->phy->speed) { 1029ad018a0cSFugang Duan case SPEED_1000: 1030ad018a0cSFugang Duan rate = 125 * 1000 * 1000; 1031ad018a0cSFugang Duan break; 1032ad018a0cSFugang Duan case SPEED_100: 1033ad018a0cSFugang Duan rate = 25 * 1000 * 1000; 1034ad018a0cSFugang Duan break; 1035ad018a0cSFugang Duan case SPEED_10: 1036ad018a0cSFugang Duan rate = 2.5 * 1000 * 1000; 1037ad018a0cSFugang Duan break; 1038ad018a0cSFugang Duan default: 1039ad018a0cSFugang Duan pr_err("invalid speed %d", eqos->phy->speed); 1040ad018a0cSFugang Duan return -EINVAL; 1041ad018a0cSFugang Duan } 1042ad018a0cSFugang Duan 1043ad018a0cSFugang Duan ret = imx_eqos_txclk_set_rate(rate); 1044ad018a0cSFugang Duan if (ret < 0) { 1045ad018a0cSFugang Duan pr_err("imx (tx_clk, %lu) failed: %d", rate, ret); 1046ad018a0cSFugang Duan return ret; 1047ad018a0cSFugang Duan } 1048ad018a0cSFugang Duan 1049a7b3400fSFugang Duan return 0; 1050a7b3400fSFugang Duan } 1051a7b3400fSFugang Duan 1052ba4dfef1SStephen Warren static int eqos_adjust_link(struct udevice *dev) 1053ba4dfef1SStephen Warren { 1054ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1055ba4dfef1SStephen Warren int ret; 1056ba4dfef1SStephen Warren bool en_calibration; 1057ba4dfef1SStephen Warren 1058ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1059ba4dfef1SStephen Warren 1060ba4dfef1SStephen Warren if (eqos->phy->duplex) 1061ba4dfef1SStephen Warren ret = eqos_set_full_duplex(dev); 1062ba4dfef1SStephen Warren else 1063ba4dfef1SStephen Warren ret = eqos_set_half_duplex(dev); 1064ba4dfef1SStephen Warren if (ret < 0) { 106590aa625cSMasahiro Yamada pr_err("eqos_set_*_duplex() failed: %d", ret); 1066ba4dfef1SStephen Warren return ret; 1067ba4dfef1SStephen Warren } 1068ba4dfef1SStephen Warren 1069ba4dfef1SStephen Warren switch (eqos->phy->speed) { 1070ba4dfef1SStephen Warren case SPEED_1000: 1071ba4dfef1SStephen Warren en_calibration = true; 1072ba4dfef1SStephen Warren ret = eqos_set_gmii_speed(dev); 1073ba4dfef1SStephen Warren break; 1074ba4dfef1SStephen Warren case SPEED_100: 1075ba4dfef1SStephen Warren en_calibration = true; 1076ba4dfef1SStephen Warren ret = eqos_set_mii_speed_100(dev); 1077ba4dfef1SStephen Warren break; 1078ba4dfef1SStephen Warren case SPEED_10: 1079ba4dfef1SStephen Warren en_calibration = false; 1080ba4dfef1SStephen Warren ret = eqos_set_mii_speed_10(dev); 1081ba4dfef1SStephen Warren break; 1082ba4dfef1SStephen Warren default: 108390aa625cSMasahiro Yamada pr_err("invalid speed %d", eqos->phy->speed); 1084ba4dfef1SStephen Warren return -EINVAL; 1085ba4dfef1SStephen Warren } 1086ba4dfef1SStephen Warren if (ret < 0) { 108790aa625cSMasahiro Yamada pr_err("eqos_set_*mii_speed*() failed: %d", ret); 1088ba4dfef1SStephen Warren return ret; 1089ba4dfef1SStephen Warren } 1090ba4dfef1SStephen Warren 1091ba4dfef1SStephen Warren if (en_calibration) { 10927a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_calibrate_pads(dev); 1093ba4dfef1SStephen Warren if (ret < 0) { 10947a4c4eddSChristophe Roullier pr_err("eqos_calibrate_pads() failed: %d", 10957a4c4eddSChristophe Roullier ret); 1096ba4dfef1SStephen Warren return ret; 1097ba4dfef1SStephen Warren } 1098ba4dfef1SStephen Warren } else { 10997a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_disable_calibration(dev); 1100ba4dfef1SStephen Warren if (ret < 0) { 11017a4c4eddSChristophe Roullier pr_err("eqos_disable_calibration() failed: %d", 1102ba4dfef1SStephen Warren ret); 1103ba4dfef1SStephen Warren return ret; 1104ba4dfef1SStephen Warren } 1105ba4dfef1SStephen Warren } 11067a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_set_tx_clk_speed(dev); 1107ba4dfef1SStephen Warren if (ret < 0) { 11087a4c4eddSChristophe Roullier pr_err("eqos_set_tx_clk_speed() failed: %d", ret); 1109ba4dfef1SStephen Warren return ret; 1110ba4dfef1SStephen Warren } 1111ba4dfef1SStephen Warren 1112ba4dfef1SStephen Warren return 0; 1113ba4dfef1SStephen Warren } 1114ba4dfef1SStephen Warren 1115ba4dfef1SStephen Warren static int eqos_write_hwaddr(struct udevice *dev) 1116ba4dfef1SStephen Warren { 1117ba4dfef1SStephen Warren struct eth_pdata *plat = dev_get_platdata(dev); 1118ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1119ba4dfef1SStephen Warren uint32_t val; 1120ba4dfef1SStephen Warren 1121ba4dfef1SStephen Warren /* 1122ba4dfef1SStephen Warren * This function may be called before start() or after stop(). At that 1123ba4dfef1SStephen Warren * time, on at least some configurations of the EQoS HW, all clocks to 1124ba4dfef1SStephen Warren * the EQoS HW block will be stopped, and a reset signal applied. If 1125ba4dfef1SStephen Warren * any register access is attempted in this state, bus timeouts or CPU 1126ba4dfef1SStephen Warren * hangs may occur. This check prevents that. 1127ba4dfef1SStephen Warren * 1128ba4dfef1SStephen Warren * A simple solution to this problem would be to not implement 1129ba4dfef1SStephen Warren * write_hwaddr(), since start() always writes the MAC address into HW 1130ba4dfef1SStephen Warren * anyway. However, it is desirable to implement write_hwaddr() to 1131ba4dfef1SStephen Warren * support the case of SW that runs subsequent to U-Boot which expects 1132ba4dfef1SStephen Warren * the MAC address to already be programmed into the EQoS registers, 1133ba4dfef1SStephen Warren * which must happen irrespective of whether the U-Boot user (or 1134ba4dfef1SStephen Warren * scripts) actually made use of the EQoS device, and hence 1135ba4dfef1SStephen Warren * irrespective of whether start() was ever called. 1136ba4dfef1SStephen Warren * 1137ba4dfef1SStephen Warren * Note that this requirement by subsequent SW is not valid for 1138ba4dfef1SStephen Warren * Tegra186, and is likely not valid for any non-PCI instantiation of 1139ba4dfef1SStephen Warren * the EQoS HW block. This function is implemented solely as 1140ba4dfef1SStephen Warren * future-proofing with the expectation the driver will eventually be 1141ba4dfef1SStephen Warren * ported to some system where the expectation above is true. 1142ba4dfef1SStephen Warren */ 1143ba4dfef1SStephen Warren if (!eqos->config->reg_access_always_ok && !eqos->reg_access_ok) 1144ba4dfef1SStephen Warren return 0; 1145ba4dfef1SStephen Warren 1146ba4dfef1SStephen Warren /* Update the MAC address */ 1147ba4dfef1SStephen Warren val = (plat->enetaddr[5] << 8) | 1148ba4dfef1SStephen Warren (plat->enetaddr[4]); 1149ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->address0_high); 1150ba4dfef1SStephen Warren val = (plat->enetaddr[3] << 24) | 1151ba4dfef1SStephen Warren (plat->enetaddr[2] << 16) | 1152ba4dfef1SStephen Warren (plat->enetaddr[1] << 8) | 1153ba4dfef1SStephen Warren (plat->enetaddr[0]); 1154ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->address0_low); 1155ba4dfef1SStephen Warren 1156ba4dfef1SStephen Warren return 0; 1157ba4dfef1SStephen Warren } 1158ba4dfef1SStephen Warren 11594d0fb6f0SYe Li static int eqos_read_rom_hwaddr(struct udevice *dev) 11604d0fb6f0SYe Li { 11614d0fb6f0SYe Li struct eth_pdata *pdata = dev_get_platdata(dev); 11624d0fb6f0SYe Li 11634d0fb6f0SYe Li #ifdef CONFIG_ARCH_IMX8M 11644d0fb6f0SYe Li imx_get_mac_from_fuse(dev->req_seq, pdata->enetaddr); 11654d0fb6f0SYe Li #endif 11664d0fb6f0SYe Li return !is_valid_ethaddr(pdata->enetaddr); 11674d0fb6f0SYe Li } 11684d0fb6f0SYe Li 1169ba4dfef1SStephen Warren static int eqos_start(struct udevice *dev) 1170ba4dfef1SStephen Warren { 1171ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1172ba4dfef1SStephen Warren int ret, i; 1173ba4dfef1SStephen Warren ulong rate; 1174ba4dfef1SStephen Warren u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl; 1175ba4dfef1SStephen Warren ulong last_rx_desc; 1176ba4dfef1SStephen Warren 1177ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1178ba4dfef1SStephen Warren 1179ba4dfef1SStephen Warren eqos->tx_desc_idx = 0; 1180ba4dfef1SStephen Warren eqos->rx_desc_idx = 0; 1181ba4dfef1SStephen Warren 11827a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_start_clks(dev); 1183ba4dfef1SStephen Warren if (ret < 0) { 11847a4c4eddSChristophe Roullier pr_err("eqos_start_clks() failed: %d", ret); 1185ba4dfef1SStephen Warren goto err; 1186ba4dfef1SStephen Warren } 1187ba4dfef1SStephen Warren 11887a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_start_resets(dev); 1189ba4dfef1SStephen Warren if (ret < 0) { 11907a4c4eddSChristophe Roullier pr_err("eqos_start_resets() failed: %d", ret); 1191ba4dfef1SStephen Warren goto err_stop_clks; 1192ba4dfef1SStephen Warren } 1193ba4dfef1SStephen Warren 1194ba4dfef1SStephen Warren udelay(10); 1195ba4dfef1SStephen Warren 1196ba4dfef1SStephen Warren eqos->reg_access_ok = true; 1197ba4dfef1SStephen Warren 1198b491b498SJon Lin ret = wait_for_bit_le32(&eqos->dma_regs->mode, 11997a4c4eddSChristophe Roullier EQOS_DMA_MODE_SWR, false, 12007a4c4eddSChristophe Roullier eqos->config->swr_wait, false); 1201ba4dfef1SStephen Warren if (ret) { 120290aa625cSMasahiro Yamada pr_err("EQOS_DMA_MODE_SWR stuck"); 1203ba4dfef1SStephen Warren goto err_stop_resets; 1204ba4dfef1SStephen Warren } 1205ba4dfef1SStephen Warren 12067a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_calibrate_pads(dev); 1207ba4dfef1SStephen Warren if (ret < 0) { 12087a4c4eddSChristophe Roullier pr_err("eqos_calibrate_pads() failed: %d", ret); 1209ba4dfef1SStephen Warren goto err_stop_resets; 1210ba4dfef1SStephen Warren } 12117a4c4eddSChristophe Roullier rate = eqos->config->ops->eqos_get_tick_clk_rate(dev); 1212ba4dfef1SStephen Warren 1213ba4dfef1SStephen Warren val = (rate / 1000000) - 1; 1214ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->us_tic_counter); 1215ba4dfef1SStephen Warren 12167a4c4eddSChristophe Roullier /* 12177a4c4eddSChristophe Roullier * if PHY was already connected and configured, 12187a4c4eddSChristophe Roullier * don't need to reconnect/reconfigure again 12197a4c4eddSChristophe Roullier */ 12207a4c4eddSChristophe Roullier if (!eqos->phy) { 12218e3eceb0SYe Li int addr = -1; 12228e3eceb0SYe Li #ifdef CONFIG_DM_ETH_PHY 12238e3eceb0SYe Li addr = eth_phy_get_addr(dev); 12248e3eceb0SYe Li #endif 12258e3eceb0SYe Li #ifdef DWC_NET_PHYADDR 12268e3eceb0SYe Li addr = DWC_NET_PHYADDR; 12278e3eceb0SYe Li #endif 12288e3eceb0SYe Li eqos->phy = phy_connect(eqos->mii, addr, dev, 1229*bbbbc81cSDavid Wu eqos->config->ops->eqos_get_interface(dev)); 1230ba4dfef1SStephen Warren if (!eqos->phy) { 123190aa625cSMasahiro Yamada pr_err("phy_connect() failed"); 1232ba4dfef1SStephen Warren goto err_stop_resets; 1233ba4dfef1SStephen Warren } 123483d31c08SPatrick Delaunay 123583d31c08SPatrick Delaunay if (eqos->max_speed) { 123683d31c08SPatrick Delaunay ret = phy_set_supported(eqos->phy, eqos->max_speed); 123783d31c08SPatrick Delaunay if (ret) { 123883d31c08SPatrick Delaunay pr_err("phy_set_supported() failed: %d", ret); 123983d31c08SPatrick Delaunay goto err_shutdown_phy; 124083d31c08SPatrick Delaunay } 124183d31c08SPatrick Delaunay } 124283d31c08SPatrick Delaunay 1243ba4dfef1SStephen Warren ret = phy_config(eqos->phy); 1244ba4dfef1SStephen Warren if (ret < 0) { 124590aa625cSMasahiro Yamada pr_err("phy_config() failed: %d", ret); 1246ba4dfef1SStephen Warren goto err_shutdown_phy; 1247ba4dfef1SStephen Warren } 12487a4c4eddSChristophe Roullier } 12497a4c4eddSChristophe Roullier 1250ba4dfef1SStephen Warren ret = phy_startup(eqos->phy); 1251ba4dfef1SStephen Warren if (ret < 0) { 125290aa625cSMasahiro Yamada pr_err("phy_startup() failed: %d", ret); 1253ba4dfef1SStephen Warren goto err_shutdown_phy; 1254ba4dfef1SStephen Warren } 1255ba4dfef1SStephen Warren 1256ba4dfef1SStephen Warren if (!eqos->phy->link) { 125790aa625cSMasahiro Yamada pr_err("No link"); 1258ba4dfef1SStephen Warren goto err_shutdown_phy; 1259ba4dfef1SStephen Warren } 1260ba4dfef1SStephen Warren 1261ba4dfef1SStephen Warren ret = eqos_adjust_link(dev); 1262ba4dfef1SStephen Warren if (ret < 0) { 126390aa625cSMasahiro Yamada pr_err("eqos_adjust_link() failed: %d", ret); 1264ba4dfef1SStephen Warren goto err_shutdown_phy; 1265ba4dfef1SStephen Warren } 1266ba4dfef1SStephen Warren 1267ba4dfef1SStephen Warren /* Configure MTL */ 1268a7b3400fSFugang Duan writel(0x60, &eqos->mtl_regs->txq0_quantum_weight - 0x100); 1269ba4dfef1SStephen Warren 1270ba4dfef1SStephen Warren /* Enable Store and Forward mode for TX */ 1271ba4dfef1SStephen Warren /* Program Tx operating mode */ 1272ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->txq0_operation_mode, 1273ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TSF | 1274ba4dfef1SStephen Warren (EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_ENABLED << 1275ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_SHIFT)); 1276ba4dfef1SStephen Warren 1277ba4dfef1SStephen Warren /* Transmit Queue weight */ 1278ba4dfef1SStephen Warren writel(0x10, &eqos->mtl_regs->txq0_quantum_weight); 1279ba4dfef1SStephen Warren 1280ba4dfef1SStephen Warren /* Enable Store and Forward mode for RX, since no jumbo frame */ 1281ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1282a7b3400fSFugang Duan EQOS_MTL_RXQ0_OPERATION_MODE_RSF | 1283a7b3400fSFugang Duan EQOS_MTL_RXQ0_OPERATION_MODE_FEP | 1284a7b3400fSFugang Duan EQOS_MTL_RXQ0_OPERATION_MODE_FUP); 1285ba4dfef1SStephen Warren 1286ba4dfef1SStephen Warren /* Transmit/Receive queue fifo size; use all RAM for 1 queue */ 1287ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->hw_feature1); 1288ba4dfef1SStephen Warren tx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_SHIFT) & 1289ba4dfef1SStephen Warren EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_MASK; 1290ba4dfef1SStephen Warren rx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT) & 1291ba4dfef1SStephen Warren EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK; 1292ba4dfef1SStephen Warren 1293ba4dfef1SStephen Warren /* 1294ba4dfef1SStephen Warren * r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting. 1295ba4dfef1SStephen Warren * r/tqs is encoded as (n / 256) - 1. 1296ba4dfef1SStephen Warren */ 1297ba4dfef1SStephen Warren tqs = (128 << tx_fifo_sz) / 256 - 1; 1298ba4dfef1SStephen Warren rqs = (128 << rx_fifo_sz) / 256 - 1; 1299ba4dfef1SStephen Warren 1300ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->txq0_operation_mode, 1301ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK << 1302ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT, 1303ba4dfef1SStephen Warren tqs << EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT); 1304ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1305ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RQS_MASK << 1306ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT, 1307ba4dfef1SStephen Warren rqs << EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT); 1308ba4dfef1SStephen Warren 1309ba4dfef1SStephen Warren /* Flow control used only if each channel gets 4KB or more FIFO */ 1310ba4dfef1SStephen Warren if (rqs >= ((4096 / 256) - 1)) { 1311ba4dfef1SStephen Warren u32 rfd, rfa; 1312ba4dfef1SStephen Warren 1313ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1314ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_EHFC); 1315ba4dfef1SStephen Warren 1316ba4dfef1SStephen Warren /* 1317ba4dfef1SStephen Warren * Set Threshold for Activating Flow Contol space for min 2 1318ba4dfef1SStephen Warren * frames ie, (1500 * 1) = 1500 bytes. 1319ba4dfef1SStephen Warren * 1320ba4dfef1SStephen Warren * Set Threshold for Deactivating Flow Contol for space of 1321ba4dfef1SStephen Warren * min 1 frame (frame size 1500bytes) in receive fifo 1322ba4dfef1SStephen Warren */ 1323ba4dfef1SStephen Warren if (rqs == ((4096 / 256) - 1)) { 1324ba4dfef1SStephen Warren /* 1325ba4dfef1SStephen Warren * This violates the above formula because of FIFO size 1326ba4dfef1SStephen Warren * limit therefore overflow may occur inspite of this. 1327ba4dfef1SStephen Warren */ 1328ba4dfef1SStephen Warren rfd = 0x3; /* Full-3K */ 1329ba4dfef1SStephen Warren rfa = 0x1; /* Full-1.5K */ 1330ba4dfef1SStephen Warren } else if (rqs == ((8192 / 256) - 1)) { 1331ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1332ba4dfef1SStephen Warren rfa = 0xa; /* Full-6K */ 1333ba4dfef1SStephen Warren } else if (rqs == ((16384 / 256) - 1)) { 1334ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1335ba4dfef1SStephen Warren rfa = 0x12; /* Full-10K */ 1336ba4dfef1SStephen Warren } else { 1337ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1338ba4dfef1SStephen Warren rfa = 0x1E; /* Full-16K */ 1339ba4dfef1SStephen Warren } 1340ba4dfef1SStephen Warren 1341ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1342ba4dfef1SStephen Warren (EQOS_MTL_RXQ0_OPERATION_MODE_RFD_MASK << 1343ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT) | 1344ba4dfef1SStephen Warren (EQOS_MTL_RXQ0_OPERATION_MODE_RFA_MASK << 1345ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT), 1346ba4dfef1SStephen Warren (rfd << 1347ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT) | 1348ba4dfef1SStephen Warren (rfa << 1349ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT)); 1350ba4dfef1SStephen Warren } 1351ba4dfef1SStephen Warren 1352ba4dfef1SStephen Warren /* Configure MAC */ 1353ba4dfef1SStephen Warren 1354ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0, 1355ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK << 1356ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT, 13577a4c4eddSChristophe Roullier eqos->config->config_mac << 1358ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT); 1359ba4dfef1SStephen Warren 1360a7b3400fSFugang Duan clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0, 1361a7b3400fSFugang Duan EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK << 1362a7b3400fSFugang Duan EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT, 1363a7b3400fSFugang Duan 0x2 << 1364a7b3400fSFugang Duan EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT); 1365a7b3400fSFugang Duan 1366a7b3400fSFugang Duan /* Multicast and Broadcast Queue Enable */ 1367a7b3400fSFugang Duan setbits_le32(&eqos->mac_regs->unused_0a4, 1368a7b3400fSFugang Duan 0x00100000); 1369a7b3400fSFugang Duan /* enable promise mode */ 1370a7b3400fSFugang Duan setbits_le32(&eqos->mac_regs->unused_004[1], 1371a7b3400fSFugang Duan 0x1); 1372a7b3400fSFugang Duan 1373ba4dfef1SStephen Warren /* Set TX flow control parameters */ 1374ba4dfef1SStephen Warren /* Set Pause Time */ 1375ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->q0_tx_flow_ctrl, 1376ba4dfef1SStephen Warren 0xffff << EQOS_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT); 1377ba4dfef1SStephen Warren /* Assign priority for TX flow control */ 1378ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->txq_prty_map0, 1379ba4dfef1SStephen Warren EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_MASK << 1380ba4dfef1SStephen Warren EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_SHIFT); 1381ba4dfef1SStephen Warren /* Assign priority for RX flow control */ 1382ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->rxq_ctrl2, 1383ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK << 1384ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT); 1385ba4dfef1SStephen Warren /* Enable flow control */ 1386ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->q0_tx_flow_ctrl, 1387ba4dfef1SStephen Warren EQOS_MAC_Q0_TX_FLOW_CTRL_TFE); 1388ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->rx_flow_ctrl, 1389ba4dfef1SStephen Warren EQOS_MAC_RX_FLOW_CTRL_RFE); 1390ba4dfef1SStephen Warren 1391ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->configuration, 1392ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_GPSLCE | 1393ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_WD | 1394ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_JD | 1395ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_JE, 1396ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_CST | 1397ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_ACS); 1398ba4dfef1SStephen Warren 1399ba4dfef1SStephen Warren eqos_write_hwaddr(dev); 1400ba4dfef1SStephen Warren 1401ba4dfef1SStephen Warren /* Configure DMA */ 1402ba4dfef1SStephen Warren 1403ba4dfef1SStephen Warren /* Enable OSP mode */ 1404ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_tx_control, 1405ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_OSP); 1406ba4dfef1SStephen Warren 1407ba4dfef1SStephen Warren /* RX buffer size. Must be a multiple of bus width */ 1408ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_rx_control, 1409ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_MASK << 1410ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT, 1411ba4dfef1SStephen Warren EQOS_MAX_PACKET_SIZE << 1412ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT); 1413ba4dfef1SStephen Warren 1414ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_control, 1415ba4dfef1SStephen Warren EQOS_DMA_CH0_CONTROL_PBLX8); 1416ba4dfef1SStephen Warren 1417ba4dfef1SStephen Warren /* 1418ba4dfef1SStephen Warren * Burst length must be < 1/2 FIFO size. 1419ba4dfef1SStephen Warren * FIFO size in tqs is encoded as (n / 256) - 1. 1420ba4dfef1SStephen Warren * Each burst is n * 8 (PBLX8) * 16 (AXI width) == 128 bytes. 1421ba4dfef1SStephen Warren * Half of n * 256 is n * 128, so pbl == tqs, modulo the -1. 1422ba4dfef1SStephen Warren */ 1423ba4dfef1SStephen Warren pbl = tqs + 1; 1424ba4dfef1SStephen Warren if (pbl > 32) 1425ba4dfef1SStephen Warren pbl = 32; 1426ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_tx_control, 1427ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_TXPBL_MASK << 1428ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT, 1429ba4dfef1SStephen Warren pbl << EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT); 1430ba4dfef1SStephen Warren 1431ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_rx_control, 1432ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RXPBL_MASK << 1433ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT, 1434ba4dfef1SStephen Warren 8 << EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT); 1435ba4dfef1SStephen Warren 1436ba4dfef1SStephen Warren /* DMA performance configuration */ 1437ba4dfef1SStephen Warren val = (2 << EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_SHIFT) | 1438ba4dfef1SStephen Warren EQOS_DMA_SYSBUS_MODE_EAME | EQOS_DMA_SYSBUS_MODE_BLEN16 | 1439ba4dfef1SStephen Warren EQOS_DMA_SYSBUS_MODE_BLEN8 | EQOS_DMA_SYSBUS_MODE_BLEN4; 1440ba4dfef1SStephen Warren writel(val, &eqos->dma_regs->sysbus_mode); 1441ba4dfef1SStephen Warren 1442ba4dfef1SStephen Warren /* Set up descriptors */ 1443ba4dfef1SStephen Warren 1444ba4dfef1SStephen Warren memset(eqos->descs, 0, EQOS_DESCRIPTORS_SIZE); 1445ba4dfef1SStephen Warren for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) { 1446ba4dfef1SStephen Warren struct eqos_desc *rx_desc = &(eqos->rx_descs[i]); 1447ba4dfef1SStephen Warren rx_desc->des0 = (u32)(ulong)(eqos->rx_dma_buf + 1448ba4dfef1SStephen Warren (i * EQOS_MAX_PACKET_SIZE)); 14496143c348SMarek Vasut rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; 1450a7b3400fSFugang Duan mb(); 14516399c699SMarek Vasut eqos->config->ops->eqos_flush_desc(rx_desc); 1452a7b3400fSFugang Duan eqos->config->ops->eqos_inval_buffer(eqos->rx_dma_buf + 1453a7b3400fSFugang Duan (i * EQOS_MAX_PACKET_SIZE), 1454a7b3400fSFugang Duan EQOS_MAX_PACKET_SIZE); 1455ba4dfef1SStephen Warren } 1456ba4dfef1SStephen Warren 1457ba4dfef1SStephen Warren writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress); 1458ba4dfef1SStephen Warren writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address); 1459ba4dfef1SStephen Warren writel(EQOS_DESCRIPTORS_TX - 1, 1460ba4dfef1SStephen Warren &eqos->dma_regs->ch0_txdesc_ring_length); 1461ba4dfef1SStephen Warren 1462ba4dfef1SStephen Warren writel(0, &eqos->dma_regs->ch0_rxdesc_list_haddress); 1463ba4dfef1SStephen Warren writel((ulong)eqos->rx_descs, &eqos->dma_regs->ch0_rxdesc_list_address); 1464ba4dfef1SStephen Warren writel(EQOS_DESCRIPTORS_RX - 1, 1465ba4dfef1SStephen Warren &eqos->dma_regs->ch0_rxdesc_ring_length); 1466ba4dfef1SStephen Warren 1467ba4dfef1SStephen Warren /* Enable everything */ 1468ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_tx_control, 1469ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_ST); 1470ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_rx_control, 1471ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_SR); 1472a7b3400fSFugang Duan setbits_le32(&eqos->mac_regs->configuration, 1473a7b3400fSFugang Duan EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE); 1474ba4dfef1SStephen Warren 1475ba4dfef1SStephen Warren /* TX tail pointer not written until we need to TX a packet */ 1476ba4dfef1SStephen Warren /* 1477ba4dfef1SStephen Warren * Point RX tail pointer at last descriptor. Ideally, we'd point at the 1478ba4dfef1SStephen Warren * first descriptor, implying all descriptors were available. However, 1479ba4dfef1SStephen Warren * that's not distinguishable from none of the descriptors being 1480ba4dfef1SStephen Warren * available. 1481ba4dfef1SStephen Warren */ 1482ba4dfef1SStephen Warren last_rx_desc = (ulong)&(eqos->rx_descs[(EQOS_DESCRIPTORS_RX - 1)]); 1483ba4dfef1SStephen Warren writel(last_rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); 1484ba4dfef1SStephen Warren 1485ba4dfef1SStephen Warren eqos->started = true; 1486ba4dfef1SStephen Warren 1487ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1488ba4dfef1SStephen Warren return 0; 1489ba4dfef1SStephen Warren 1490ba4dfef1SStephen Warren err_shutdown_phy: 1491ba4dfef1SStephen Warren phy_shutdown(eqos->phy); 1492ba4dfef1SStephen Warren err_stop_resets: 14937a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_resets(dev); 1494ba4dfef1SStephen Warren err_stop_clks: 14957a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_clks(dev); 1496ba4dfef1SStephen Warren err: 149790aa625cSMasahiro Yamada pr_err("FAILED: %d", ret); 1498ba4dfef1SStephen Warren return ret; 1499ba4dfef1SStephen Warren } 1500ba4dfef1SStephen Warren 15018aaada72SPatrick Delaunay static void eqos_stop(struct udevice *dev) 1502ba4dfef1SStephen Warren { 1503ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1504ba4dfef1SStephen Warren int i; 1505ba4dfef1SStephen Warren 1506ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1507ba4dfef1SStephen Warren 1508ba4dfef1SStephen Warren if (!eqos->started) 1509ba4dfef1SStephen Warren return; 1510ba4dfef1SStephen Warren eqos->started = false; 1511ba4dfef1SStephen Warren eqos->reg_access_ok = false; 1512ba4dfef1SStephen Warren 1513ba4dfef1SStephen Warren /* Disable TX DMA */ 1514ba4dfef1SStephen Warren clrbits_le32(&eqos->dma_regs->ch0_tx_control, 1515ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_ST); 1516ba4dfef1SStephen Warren 1517ba4dfef1SStephen Warren /* Wait for TX all packets to drain out of MTL */ 1518ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 1519ba4dfef1SStephen Warren u32 val = readl(&eqos->mtl_regs->txq0_debug); 1520ba4dfef1SStephen Warren u32 trcsts = (val >> EQOS_MTL_TXQ0_DEBUG_TRCSTS_SHIFT) & 1521ba4dfef1SStephen Warren EQOS_MTL_TXQ0_DEBUG_TRCSTS_MASK; 1522ba4dfef1SStephen Warren u32 txqsts = val & EQOS_MTL_TXQ0_DEBUG_TXQSTS; 1523ba4dfef1SStephen Warren if ((trcsts != 1) && (!txqsts)) 1524ba4dfef1SStephen Warren break; 1525ba4dfef1SStephen Warren } 1526ba4dfef1SStephen Warren 1527ba4dfef1SStephen Warren /* Turn off MAC TX and RX */ 1528ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, 1529ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE); 1530ba4dfef1SStephen Warren 1531ba4dfef1SStephen Warren /* Wait for all RX packets to drain out of MTL */ 1532ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 1533ba4dfef1SStephen Warren u32 val = readl(&eqos->mtl_regs->rxq0_debug); 1534ba4dfef1SStephen Warren u32 prxq = (val >> EQOS_MTL_RXQ0_DEBUG_PRXQ_SHIFT) & 1535ba4dfef1SStephen Warren EQOS_MTL_RXQ0_DEBUG_PRXQ_MASK; 1536ba4dfef1SStephen Warren u32 rxqsts = (val >> EQOS_MTL_RXQ0_DEBUG_RXQSTS_SHIFT) & 1537ba4dfef1SStephen Warren EQOS_MTL_RXQ0_DEBUG_RXQSTS_MASK; 1538ba4dfef1SStephen Warren if ((!prxq) && (!rxqsts)) 1539ba4dfef1SStephen Warren break; 1540ba4dfef1SStephen Warren } 1541ba4dfef1SStephen Warren 1542ba4dfef1SStephen Warren /* Turn off RX DMA */ 1543ba4dfef1SStephen Warren clrbits_le32(&eqos->dma_regs->ch0_rx_control, 1544ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_SR); 1545ba4dfef1SStephen Warren 1546ba4dfef1SStephen Warren if (eqos->phy) { 1547ba4dfef1SStephen Warren phy_shutdown(eqos->phy); 1548ba4dfef1SStephen Warren } 15497a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_resets(dev); 15507a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_clks(dev); 1551ba4dfef1SStephen Warren 1552ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1553ba4dfef1SStephen Warren } 1554ba4dfef1SStephen Warren 15558aaada72SPatrick Delaunay static int eqos_send(struct udevice *dev, void *packet, int length) 1556ba4dfef1SStephen Warren { 1557ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1558ba4dfef1SStephen Warren struct eqos_desc *tx_desc; 1559ba4dfef1SStephen Warren int i; 1560ba4dfef1SStephen Warren 1561ba4dfef1SStephen Warren debug("%s(dev=%p, packet=%p, length=%d):\n", __func__, dev, packet, 1562ba4dfef1SStephen Warren length); 1563ba4dfef1SStephen Warren 1564ba4dfef1SStephen Warren memcpy(eqos->tx_dma_buf, packet, length); 15657a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length); 1566ba4dfef1SStephen Warren 1567ba4dfef1SStephen Warren tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]); 1568ba4dfef1SStephen Warren eqos->tx_desc_idx++; 1569ba4dfef1SStephen Warren eqos->tx_desc_idx %= EQOS_DESCRIPTORS_TX; 1570ba4dfef1SStephen Warren 1571ba4dfef1SStephen Warren tx_desc->des0 = (ulong)eqos->tx_dma_buf; 1572ba4dfef1SStephen Warren tx_desc->des1 = 0; 1573ba4dfef1SStephen Warren tx_desc->des2 = length; 1574ba4dfef1SStephen Warren /* 1575ba4dfef1SStephen Warren * Make sure that if HW sees the _OWN write below, it will see all the 1576ba4dfef1SStephen Warren * writes to the rest of the descriptor too. 1577ba4dfef1SStephen Warren */ 1578ba4dfef1SStephen Warren mb(); 1579ba4dfef1SStephen Warren tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length; 15807a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_desc(tx_desc); 1581ba4dfef1SStephen Warren 1582364f8fdcSMarek Vasut writel((ulong)(&(eqos->tx_descs[eqos->tx_desc_idx])), 1583364f8fdcSMarek Vasut &eqos->dma_regs->ch0_txdesc_tail_pointer); 1584ba4dfef1SStephen Warren 1585ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 15867a4c4eddSChristophe Roullier eqos->config->ops->eqos_inval_desc(tx_desc); 1587ba4dfef1SStephen Warren if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN)) 1588ba4dfef1SStephen Warren return 0; 1589ba4dfef1SStephen Warren udelay(1); 1590ba4dfef1SStephen Warren } 1591ba4dfef1SStephen Warren 1592ba4dfef1SStephen Warren debug("%s: TX timeout\n", __func__); 1593ba4dfef1SStephen Warren 1594ba4dfef1SStephen Warren return -ETIMEDOUT; 1595ba4dfef1SStephen Warren } 1596ba4dfef1SStephen Warren 15978aaada72SPatrick Delaunay static int eqos_recv(struct udevice *dev, int flags, uchar **packetp) 1598ba4dfef1SStephen Warren { 1599ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1600ba4dfef1SStephen Warren struct eqos_desc *rx_desc; 1601ba4dfef1SStephen Warren int length; 1602ba4dfef1SStephen Warren 1603ba4dfef1SStephen Warren debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags); 1604ba4dfef1SStephen Warren 1605ba4dfef1SStephen Warren rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); 1606865fce80SMarek Vasut eqos->config->ops->eqos_inval_desc(rx_desc); 1607ba4dfef1SStephen Warren if (rx_desc->des3 & EQOS_DESC3_OWN) { 1608ba4dfef1SStephen Warren debug("%s: RX packet not available\n", __func__); 1609ba4dfef1SStephen Warren return -EAGAIN; 1610ba4dfef1SStephen Warren } 1611ba4dfef1SStephen Warren 1612ba4dfef1SStephen Warren *packetp = eqos->rx_dma_buf + 1613ba4dfef1SStephen Warren (eqos->rx_desc_idx * EQOS_MAX_PACKET_SIZE); 1614ba4dfef1SStephen Warren length = rx_desc->des3 & 0x7fff; 1615ba4dfef1SStephen Warren debug("%s: *packetp=%p, length=%d\n", __func__, *packetp, length); 1616ba4dfef1SStephen Warren 16177a4c4eddSChristophe Roullier eqos->config->ops->eqos_inval_buffer(*packetp, length); 1618ba4dfef1SStephen Warren 1619ba4dfef1SStephen Warren return length; 1620ba4dfef1SStephen Warren } 1621ba4dfef1SStephen Warren 16228aaada72SPatrick Delaunay static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) 1623ba4dfef1SStephen Warren { 1624ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1625ba4dfef1SStephen Warren uchar *packet_expected; 1626ba4dfef1SStephen Warren struct eqos_desc *rx_desc; 1627ba4dfef1SStephen Warren 1628ba4dfef1SStephen Warren debug("%s(packet=%p, length=%d)\n", __func__, packet, length); 1629ba4dfef1SStephen Warren 1630ba4dfef1SStephen Warren packet_expected = eqos->rx_dma_buf + 1631ba4dfef1SStephen Warren (eqos->rx_desc_idx * EQOS_MAX_PACKET_SIZE); 1632ba4dfef1SStephen Warren if (packet != packet_expected) { 1633ba4dfef1SStephen Warren debug("%s: Unexpected packet (expected %p)\n", __func__, 1634ba4dfef1SStephen Warren packet_expected); 1635ba4dfef1SStephen Warren return -EINVAL; 1636ba4dfef1SStephen Warren } 1637ba4dfef1SStephen Warren 1638a7b3400fSFugang Duan eqos->config->ops->eqos_inval_buffer(packet, length); 1639a7b3400fSFugang Duan 1640ba4dfef1SStephen Warren rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); 1641076e66fbSMarek Vasut 164207314278SMarek Vasut rx_desc->des0 = 0; 164307314278SMarek Vasut mb(); 164407314278SMarek Vasut eqos->config->ops->eqos_flush_desc(rx_desc); 1645076e66fbSMarek Vasut eqos->config->ops->eqos_inval_buffer(packet, length); 1646ba4dfef1SStephen Warren rx_desc->des0 = (u32)(ulong)packet; 1647ba4dfef1SStephen Warren rx_desc->des1 = 0; 1648ba4dfef1SStephen Warren rx_desc->des2 = 0; 1649ba4dfef1SStephen Warren /* 1650ba4dfef1SStephen Warren * Make sure that if HW sees the _OWN write below, it will see all the 1651ba4dfef1SStephen Warren * writes to the rest of the descriptor too. 1652ba4dfef1SStephen Warren */ 1653ba4dfef1SStephen Warren mb(); 16546143c348SMarek Vasut rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; 16557a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_desc(rx_desc); 1656ba4dfef1SStephen Warren 1657ba4dfef1SStephen Warren writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); 1658ba4dfef1SStephen Warren 1659ba4dfef1SStephen Warren eqos->rx_desc_idx++; 1660ba4dfef1SStephen Warren eqos->rx_desc_idx %= EQOS_DESCRIPTORS_RX; 1661ba4dfef1SStephen Warren 1662ba4dfef1SStephen Warren return 0; 1663ba4dfef1SStephen Warren } 1664ba4dfef1SStephen Warren 1665ba4dfef1SStephen Warren static int eqos_probe_resources_core(struct udevice *dev) 1666ba4dfef1SStephen Warren { 1667ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1668ba4dfef1SStephen Warren int ret; 1669ba4dfef1SStephen Warren 1670ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1671ba4dfef1SStephen Warren 1672ba4dfef1SStephen Warren eqos->descs = eqos_alloc_descs(EQOS_DESCRIPTORS_TX + 1673ba4dfef1SStephen Warren EQOS_DESCRIPTORS_RX); 1674ba4dfef1SStephen Warren if (!eqos->descs) { 1675ba4dfef1SStephen Warren debug("%s: eqos_alloc_descs() failed\n", __func__); 1676ba4dfef1SStephen Warren ret = -ENOMEM; 1677ba4dfef1SStephen Warren goto err; 1678ba4dfef1SStephen Warren } 1679ba4dfef1SStephen Warren eqos->tx_descs = (struct eqos_desc *)eqos->descs; 1680ba4dfef1SStephen Warren eqos->rx_descs = (eqos->tx_descs + EQOS_DESCRIPTORS_TX); 1681ba4dfef1SStephen Warren debug("%s: tx_descs=%p, rx_descs=%p\n", __func__, eqos->tx_descs, 1682ba4dfef1SStephen Warren eqos->rx_descs); 1683ba4dfef1SStephen Warren 1684ba4dfef1SStephen Warren eqos->tx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_MAX_PACKET_SIZE); 1685ba4dfef1SStephen Warren if (!eqos->tx_dma_buf) { 1686ba4dfef1SStephen Warren debug("%s: memalign(tx_dma_buf) failed\n", __func__); 1687ba4dfef1SStephen Warren ret = -ENOMEM; 1688ba4dfef1SStephen Warren goto err_free_descs; 1689ba4dfef1SStephen Warren } 16907a4c4eddSChristophe Roullier debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf); 1691ba4dfef1SStephen Warren 1692ba4dfef1SStephen Warren eqos->rx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_RX_BUFFER_SIZE); 1693ba4dfef1SStephen Warren if (!eqos->rx_dma_buf) { 1694ba4dfef1SStephen Warren debug("%s: memalign(rx_dma_buf) failed\n", __func__); 1695ba4dfef1SStephen Warren ret = -ENOMEM; 1696ba4dfef1SStephen Warren goto err_free_tx_dma_buf; 1697ba4dfef1SStephen Warren } 16987a4c4eddSChristophe Roullier debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf); 1699ba4dfef1SStephen Warren 1700ba4dfef1SStephen Warren eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE); 1701ba4dfef1SStephen Warren if (!eqos->rx_pkt) { 1702ba4dfef1SStephen Warren debug("%s: malloc(rx_pkt) failed\n", __func__); 1703ba4dfef1SStephen Warren ret = -ENOMEM; 1704ba4dfef1SStephen Warren goto err_free_rx_dma_buf; 1705ba4dfef1SStephen Warren } 1706ba4dfef1SStephen Warren debug("%s: rx_pkt=%p\n", __func__, eqos->rx_pkt); 1707ba4dfef1SStephen Warren 1708076e66fbSMarek Vasut eqos->config->ops->eqos_inval_buffer(eqos->rx_dma_buf, 1709076e66fbSMarek Vasut EQOS_MAX_PACKET_SIZE * EQOS_DESCRIPTORS_RX); 1710076e66fbSMarek Vasut 1711ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1712ba4dfef1SStephen Warren return 0; 1713ba4dfef1SStephen Warren 1714ba4dfef1SStephen Warren err_free_rx_dma_buf: 1715ba4dfef1SStephen Warren free(eqos->rx_dma_buf); 1716ba4dfef1SStephen Warren err_free_tx_dma_buf: 1717ba4dfef1SStephen Warren free(eqos->tx_dma_buf); 1718ba4dfef1SStephen Warren err_free_descs: 1719ba4dfef1SStephen Warren eqos_free_descs(eqos->descs); 1720ba4dfef1SStephen Warren err: 1721ba4dfef1SStephen Warren 1722ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 1723ba4dfef1SStephen Warren return ret; 1724ba4dfef1SStephen Warren } 1725ba4dfef1SStephen Warren 1726ba4dfef1SStephen Warren static int eqos_remove_resources_core(struct udevice *dev) 1727ba4dfef1SStephen Warren { 1728ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1729ba4dfef1SStephen Warren 1730ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1731ba4dfef1SStephen Warren 1732ba4dfef1SStephen Warren free(eqos->rx_pkt); 1733ba4dfef1SStephen Warren free(eqos->rx_dma_buf); 1734ba4dfef1SStephen Warren free(eqos->tx_dma_buf); 1735ba4dfef1SStephen Warren eqos_free_descs(eqos->descs); 1736ba4dfef1SStephen Warren 1737ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1738ba4dfef1SStephen Warren return 0; 1739ba4dfef1SStephen Warren } 1740ba4dfef1SStephen Warren 1741ba4dfef1SStephen Warren static int eqos_probe_resources_tegra186(struct udevice *dev) 1742ba4dfef1SStephen Warren { 1743ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1744ba4dfef1SStephen Warren int ret; 1745ba4dfef1SStephen Warren 1746ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1747ba4dfef1SStephen Warren 1748ba4dfef1SStephen Warren ret = reset_get_by_name(dev, "eqos", &eqos->reset_ctl); 1749ba4dfef1SStephen Warren if (ret) { 175090aa625cSMasahiro Yamada pr_err("reset_get_by_name(rst) failed: %d", ret); 1751ba4dfef1SStephen Warren return ret; 1752ba4dfef1SStephen Warren } 1753ba4dfef1SStephen Warren 1754ba4dfef1SStephen Warren ret = gpio_request_by_name(dev, "phy-reset-gpios", 0, 1755ba4dfef1SStephen Warren &eqos->phy_reset_gpio, 1756ba4dfef1SStephen Warren GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); 1757ba4dfef1SStephen Warren if (ret) { 175890aa625cSMasahiro Yamada pr_err("gpio_request_by_name(phy reset) failed: %d", ret); 1759ba4dfef1SStephen Warren goto err_free_reset_eqos; 1760ba4dfef1SStephen Warren } 1761ba4dfef1SStephen Warren 1762ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "slave_bus", &eqos->clk_slave_bus); 1763ba4dfef1SStephen Warren if (ret) { 176490aa625cSMasahiro Yamada pr_err("clk_get_by_name(slave_bus) failed: %d", ret); 1765ba4dfef1SStephen Warren goto err_free_gpio_phy_reset; 1766ba4dfef1SStephen Warren } 1767ba4dfef1SStephen Warren 1768ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "master_bus", &eqos->clk_master_bus); 1769ba4dfef1SStephen Warren if (ret) { 177090aa625cSMasahiro Yamada pr_err("clk_get_by_name(master_bus) failed: %d", ret); 1771ba4dfef1SStephen Warren goto err_free_clk_slave_bus; 1772ba4dfef1SStephen Warren } 1773ba4dfef1SStephen Warren 1774ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "rx", &eqos->clk_rx); 1775ba4dfef1SStephen Warren if (ret) { 177690aa625cSMasahiro Yamada pr_err("clk_get_by_name(rx) failed: %d", ret); 1777ba4dfef1SStephen Warren goto err_free_clk_master_bus; 1778ba4dfef1SStephen Warren } 1779ba4dfef1SStephen Warren 1780ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "ptp_ref", &eqos->clk_ptp_ref); 1781ba4dfef1SStephen Warren if (ret) { 178290aa625cSMasahiro Yamada pr_err("clk_get_by_name(ptp_ref) failed: %d", ret); 1783ba4dfef1SStephen Warren goto err_free_clk_rx; 1784ba4dfef1SStephen Warren return ret; 1785ba4dfef1SStephen Warren } 1786ba4dfef1SStephen Warren 1787ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "tx", &eqos->clk_tx); 1788ba4dfef1SStephen Warren if (ret) { 178990aa625cSMasahiro Yamada pr_err("clk_get_by_name(tx) failed: %d", ret); 1790ba4dfef1SStephen Warren goto err_free_clk_ptp_ref; 1791ba4dfef1SStephen Warren } 1792ba4dfef1SStephen Warren 1793ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1794ba4dfef1SStephen Warren return 0; 1795ba4dfef1SStephen Warren 1796ba4dfef1SStephen Warren err_free_clk_ptp_ref: 1797ba4dfef1SStephen Warren clk_free(&eqos->clk_ptp_ref); 1798ba4dfef1SStephen Warren err_free_clk_rx: 1799ba4dfef1SStephen Warren clk_free(&eqos->clk_rx); 1800ba4dfef1SStephen Warren err_free_clk_master_bus: 1801ba4dfef1SStephen Warren clk_free(&eqos->clk_master_bus); 1802ba4dfef1SStephen Warren err_free_clk_slave_bus: 1803ba4dfef1SStephen Warren clk_free(&eqos->clk_slave_bus); 1804ba4dfef1SStephen Warren err_free_gpio_phy_reset: 1805ba4dfef1SStephen Warren dm_gpio_free(dev, &eqos->phy_reset_gpio); 1806ba4dfef1SStephen Warren err_free_reset_eqos: 1807ba4dfef1SStephen Warren reset_free(&eqos->reset_ctl); 1808ba4dfef1SStephen Warren 1809ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 1810ba4dfef1SStephen Warren return ret; 1811ba4dfef1SStephen Warren } 1812ba4dfef1SStephen Warren 18137a4c4eddSChristophe Roullier /* board-specific Ethernet Interface initializations. */ 18141e8d5d80SPatrick Delaunay __weak int board_interface_eth_init(struct udevice *dev, 18151e8d5d80SPatrick Delaunay phy_interface_t interface_type) 18167a4c4eddSChristophe Roullier { 18177a4c4eddSChristophe Roullier return 0; 18187a4c4eddSChristophe Roullier } 18197a4c4eddSChristophe Roullier 18207a4c4eddSChristophe Roullier static int eqos_probe_resources_stm32(struct udevice *dev) 18217a4c4eddSChristophe Roullier { 18227a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 18237a4c4eddSChristophe Roullier int ret; 18247a4c4eddSChristophe Roullier phy_interface_t interface; 18255bd3c538SChristophe Roullier struct ofnode_phandle_args phandle_args; 18267a4c4eddSChristophe Roullier 18277a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 18287a4c4eddSChristophe Roullier 1829*bbbbc81cSDavid Wu interface = eqos->config->ops->eqos_get_interface(dev); 18307a4c4eddSChristophe Roullier 18317a4c4eddSChristophe Roullier if (interface == PHY_INTERFACE_MODE_NONE) { 18327a4c4eddSChristophe Roullier pr_err("Invalid PHY interface\n"); 18337a4c4eddSChristophe Roullier return -EINVAL; 18347a4c4eddSChristophe Roullier } 18357a4c4eddSChristophe Roullier 18361e8d5d80SPatrick Delaunay ret = board_interface_eth_init(dev, interface); 18377a4c4eddSChristophe Roullier if (ret) 18387a4c4eddSChristophe Roullier return -EINVAL; 18397a4c4eddSChristophe Roullier 184083d31c08SPatrick Delaunay eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0); 184183d31c08SPatrick Delaunay 18427a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); 18437a4c4eddSChristophe Roullier if (ret) { 18447a4c4eddSChristophe Roullier pr_err("clk_get_by_name(master_bus) failed: %d", ret); 18457a4c4eddSChristophe Roullier goto err_probe; 18467a4c4eddSChristophe Roullier } 18477a4c4eddSChristophe Roullier 18487a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); 18497a4c4eddSChristophe Roullier if (ret) { 18507a4c4eddSChristophe Roullier pr_err("clk_get_by_name(rx) failed: %d", ret); 18517a4c4eddSChristophe Roullier goto err_free_clk_master_bus; 18527a4c4eddSChristophe Roullier } 18537a4c4eddSChristophe Roullier 18547a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); 18557a4c4eddSChristophe Roullier if (ret) { 18567a4c4eddSChristophe Roullier pr_err("clk_get_by_name(tx) failed: %d", ret); 18577a4c4eddSChristophe Roullier goto err_free_clk_rx; 18587a4c4eddSChristophe Roullier } 18597a4c4eddSChristophe Roullier 18607a4c4eddSChristophe Roullier /* Get ETH_CLK clocks (optional) */ 18617a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck); 18627a4c4eddSChristophe Roullier if (ret) 18637a4c4eddSChristophe Roullier pr_warn("No phy clock provided %d", ret); 18647a4c4eddSChristophe Roullier 186583d31c08SPatrick Delaunay eqos->phyaddr = -1; 18665bd3c538SChristophe Roullier ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, 18675bd3c538SChristophe Roullier &phandle_args); 18685bd3c538SChristophe Roullier if (!ret) { 18695bd3c538SChristophe Roullier /* search "reset-gpios" in phy node */ 18705bd3c538SChristophe Roullier ret = gpio_request_by_name_nodev(phandle_args.node, 18715bd3c538SChristophe Roullier "reset-gpios", 0, 18725bd3c538SChristophe Roullier &eqos->phy_reset_gpio, 18735bd3c538SChristophe Roullier GPIOD_IS_OUT | 18745bd3c538SChristophe Roullier GPIOD_IS_OUT_ACTIVE); 18755bd3c538SChristophe Roullier if (ret) 18765bd3c538SChristophe Roullier pr_warn("gpio_request_by_name(phy reset) not provided %d", 18775bd3c538SChristophe Roullier ret); 187813105a0bSDavid Wu else 187913105a0bSDavid Wu eqos->reset_delays[1] = 2; 188083d31c08SPatrick Delaunay 188183d31c08SPatrick Delaunay eqos->phyaddr = ofnode_read_u32_default(phandle_args.node, 188283d31c08SPatrick Delaunay "reg", -1); 18835bd3c538SChristophe Roullier } 18845bd3c538SChristophe Roullier 188513105a0bSDavid Wu if (!dm_gpio_is_valid(&eqos->phy_reset_gpio)) { 188613105a0bSDavid Wu int reset_flags = GPIOD_IS_OUT; 188713105a0bSDavid Wu 188813105a0bSDavid Wu if (dev_read_bool(dev, "snps,reset-active-low")) 188913105a0bSDavid Wu reset_flags |= GPIOD_ACTIVE_LOW; 189013105a0bSDavid Wu 189113105a0bSDavid Wu ret = gpio_request_by_name(dev, "snps,reset-gpio", 0, 189213105a0bSDavid Wu &eqos->phy_reset_gpio, reset_flags); 189313105a0bSDavid Wu if (ret == 0) 189413105a0bSDavid Wu ret = dev_read_u32_array(dev, "snps,reset-delays-us", 189513105a0bSDavid Wu eqos->reset_delays, 3); 189613105a0bSDavid Wu else 189713105a0bSDavid Wu pr_warn("gpio_request_by_name(snps,reset-gpio) failed: %d", 189813105a0bSDavid Wu ret); 189913105a0bSDavid Wu } 190013105a0bSDavid Wu 19017a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 19027a4c4eddSChristophe Roullier return 0; 19037a4c4eddSChristophe Roullier 19047a4c4eddSChristophe Roullier err_free_clk_rx: 19057a4c4eddSChristophe Roullier clk_free(&eqos->clk_rx); 19067a4c4eddSChristophe Roullier err_free_clk_master_bus: 19077a4c4eddSChristophe Roullier clk_free(&eqos->clk_master_bus); 19087a4c4eddSChristophe Roullier err_probe: 19097a4c4eddSChristophe Roullier 19107a4c4eddSChristophe Roullier debug("%s: returns %d\n", __func__, ret); 19117a4c4eddSChristophe Roullier return ret; 19127a4c4eddSChristophe Roullier } 19137a4c4eddSChristophe Roullier 19147a4c4eddSChristophe Roullier static phy_interface_t eqos_get_interface_stm32(struct udevice *dev) 19157a4c4eddSChristophe Roullier { 19167a4c4eddSChristophe Roullier const char *phy_mode; 19177a4c4eddSChristophe Roullier phy_interface_t interface = PHY_INTERFACE_MODE_NONE; 19187a4c4eddSChristophe Roullier 19197a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 19207a4c4eddSChristophe Roullier 1921dcf8de12SDavid Wu phy_mode = dev_read_string(dev, "phy-mode"); 19227a4c4eddSChristophe Roullier if (phy_mode) 19237a4c4eddSChristophe Roullier interface = phy_get_interface_by_name(phy_mode); 19247a4c4eddSChristophe Roullier 19257a4c4eddSChristophe Roullier return interface; 19267a4c4eddSChristophe Roullier } 19277a4c4eddSChristophe Roullier 19287a4c4eddSChristophe Roullier static phy_interface_t eqos_get_interface_tegra186(struct udevice *dev) 19297a4c4eddSChristophe Roullier { 19307a4c4eddSChristophe Roullier return PHY_INTERFACE_MODE_MII; 19317a4c4eddSChristophe Roullier } 19327a4c4eddSChristophe Roullier 1933a7b3400fSFugang Duan static int eqos_probe_resources_imx(struct udevice *dev) 1934a7b3400fSFugang Duan { 1935a7b3400fSFugang Duan struct eqos_priv *eqos = dev_get_priv(dev); 1936a7b3400fSFugang Duan phy_interface_t interface; 1937a7b3400fSFugang Duan 1938a7b3400fSFugang Duan debug("%s(dev=%p):\n", __func__, dev); 1939a7b3400fSFugang Duan 1940*bbbbc81cSDavid Wu interface = eqos->config->ops->eqos_get_interface(dev); 1941a7b3400fSFugang Duan 1942a7b3400fSFugang Duan if (interface == PHY_INTERFACE_MODE_NONE) { 1943a7b3400fSFugang Duan pr_err("Invalid PHY interface\n"); 1944a7b3400fSFugang Duan return -EINVAL; 1945a7b3400fSFugang Duan } 1946a7b3400fSFugang Duan 1947a7b3400fSFugang Duan debug("%s: OK\n", __func__); 1948a7b3400fSFugang Duan return 0; 1949a7b3400fSFugang Duan } 1950a7b3400fSFugang Duan 1951a7b3400fSFugang Duan static phy_interface_t eqos_get_interface_imx(struct udevice *dev) 1952a7b3400fSFugang Duan { 1953ad018a0cSFugang Duan const char *phy_mode; 1954ad018a0cSFugang Duan phy_interface_t interface = PHY_INTERFACE_MODE_NONE; 1955ad018a0cSFugang Duan 1956ad018a0cSFugang Duan debug("%s(dev=%p):\n", __func__, dev); 1957ad018a0cSFugang Duan 1958ad018a0cSFugang Duan phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", 1959ad018a0cSFugang Duan NULL); 1960ad018a0cSFugang Duan if (phy_mode) 1961ad018a0cSFugang Duan interface = phy_get_interface_by_name(phy_mode); 1962ad018a0cSFugang Duan 1963ad018a0cSFugang Duan return interface; 1964a7b3400fSFugang Duan } 1965a7b3400fSFugang Duan 1966ba4dfef1SStephen Warren static int eqos_remove_resources_tegra186(struct udevice *dev) 1967ba4dfef1SStephen Warren { 1968ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1969ba4dfef1SStephen Warren 1970ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1971ba4dfef1SStephen Warren 1972a7b3400fSFugang Duan #ifdef CONFIG_CLK 1973ba4dfef1SStephen Warren clk_free(&eqos->clk_tx); 1974ba4dfef1SStephen Warren clk_free(&eqos->clk_ptp_ref); 1975ba4dfef1SStephen Warren clk_free(&eqos->clk_rx); 1976ba4dfef1SStephen Warren clk_free(&eqos->clk_slave_bus); 1977ba4dfef1SStephen Warren clk_free(&eqos->clk_master_bus); 1978a7b3400fSFugang Duan #endif 1979ba4dfef1SStephen Warren dm_gpio_free(dev, &eqos->phy_reset_gpio); 1980ba4dfef1SStephen Warren reset_free(&eqos->reset_ctl); 1981ba4dfef1SStephen Warren 1982ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1983ba4dfef1SStephen Warren return 0; 1984ba4dfef1SStephen Warren } 1985ba4dfef1SStephen Warren 19867a4c4eddSChristophe Roullier static int eqos_remove_resources_stm32(struct udevice *dev) 19877a4c4eddSChristophe Roullier { 1988a7b3400fSFugang Duan #ifdef CONFIG_CLK 19897a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 19907a4c4eddSChristophe Roullier 19917a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 19927a4c4eddSChristophe Roullier 19937a4c4eddSChristophe Roullier clk_free(&eqos->clk_tx); 19947a4c4eddSChristophe Roullier clk_free(&eqos->clk_rx); 19957a4c4eddSChristophe Roullier clk_free(&eqos->clk_master_bus); 19967a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) 19977a4c4eddSChristophe Roullier clk_free(&eqos->clk_ck); 1998a7b3400fSFugang Duan #endif 19997a4c4eddSChristophe Roullier 20005bd3c538SChristophe Roullier if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) 20015bd3c538SChristophe Roullier dm_gpio_free(dev, &eqos->phy_reset_gpio); 20025bd3c538SChristophe Roullier 20037a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 20047a4c4eddSChristophe Roullier return 0; 20057a4c4eddSChristophe Roullier } 20067a4c4eddSChristophe Roullier 2007a7b3400fSFugang Duan static int eqos_remove_resources_imx(struct udevice *dev) 2008a7b3400fSFugang Duan { 2009a7b3400fSFugang Duan return 0; 2010a7b3400fSFugang Duan } 2011a7b3400fSFugang Duan 2012ba4dfef1SStephen Warren static int eqos_probe(struct udevice *dev) 2013ba4dfef1SStephen Warren { 2014ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 2015ba4dfef1SStephen Warren int ret; 2016ba4dfef1SStephen Warren 2017ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 2018ba4dfef1SStephen Warren 2019ba4dfef1SStephen Warren eqos->dev = dev; 2020ba4dfef1SStephen Warren eqos->config = (void *)dev_get_driver_data(dev); 2021ba4dfef1SStephen Warren 2022dcf8de12SDavid Wu eqos->regs = dev_read_addr(dev); 2023ba4dfef1SStephen Warren if (eqos->regs == FDT_ADDR_T_NONE) { 2024dcf8de12SDavid Wu pr_err("dev_read_addr() failed"); 2025ba4dfef1SStephen Warren return -ENODEV; 2026ba4dfef1SStephen Warren } 2027ba4dfef1SStephen Warren eqos->mac_regs = (void *)(eqos->regs + EQOS_MAC_REGS_BASE); 2028ba4dfef1SStephen Warren eqos->mtl_regs = (void *)(eqos->regs + EQOS_MTL_REGS_BASE); 2029ba4dfef1SStephen Warren eqos->dma_regs = (void *)(eqos->regs + EQOS_DMA_REGS_BASE); 2030ba4dfef1SStephen Warren eqos->tegra186_regs = (void *)(eqos->regs + EQOS_TEGRA186_REGS_BASE); 2031ba4dfef1SStephen Warren 2032ba4dfef1SStephen Warren ret = eqos_probe_resources_core(dev); 2033ba4dfef1SStephen Warren if (ret < 0) { 203490aa625cSMasahiro Yamada pr_err("eqos_probe_resources_core() failed: %d", ret); 2035ba4dfef1SStephen Warren return ret; 2036ba4dfef1SStephen Warren } 2037ba4dfef1SStephen Warren 20387a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_probe_resources(dev); 2039ba4dfef1SStephen Warren if (ret < 0) { 20407a4c4eddSChristophe Roullier pr_err("eqos_probe_resources() failed: %d", ret); 2041ba4dfef1SStephen Warren goto err_remove_resources_core; 2042ba4dfef1SStephen Warren } 2043ba4dfef1SStephen Warren 20448e3eceb0SYe Li #ifdef CONFIG_DM_ETH_PHY 20458e3eceb0SYe Li eqos->mii = eth_phy_get_mdio_bus(dev); 20468e3eceb0SYe Li #endif 20478e3eceb0SYe Li if (!eqos->mii) { 2048ba4dfef1SStephen Warren eqos->mii = mdio_alloc(); 2049ba4dfef1SStephen Warren if (!eqos->mii) { 205090aa625cSMasahiro Yamada pr_err("mdio_alloc() failed"); 20517a4c4eddSChristophe Roullier ret = -ENOMEM; 2052ba4dfef1SStephen Warren goto err_remove_resources_tegra; 2053ba4dfef1SStephen Warren } 2054ba4dfef1SStephen Warren eqos->mii->read = eqos_mdio_read; 2055ba4dfef1SStephen Warren eqos->mii->write = eqos_mdio_write; 2056ba4dfef1SStephen Warren eqos->mii->priv = eqos; 2057ba4dfef1SStephen Warren strcpy(eqos->mii->name, dev->name); 2058ba4dfef1SStephen Warren 2059ba4dfef1SStephen Warren ret = mdio_register(eqos->mii); 2060ba4dfef1SStephen Warren if (ret < 0) { 206190aa625cSMasahiro Yamada pr_err("mdio_register() failed: %d", ret); 2062ba4dfef1SStephen Warren goto err_free_mdio; 2063ba4dfef1SStephen Warren } 20648e3eceb0SYe Li } 20658e3eceb0SYe Li 20668e3eceb0SYe Li #ifdef CONFIG_DM_ETH_PHY 20678e3eceb0SYe Li eth_phy_set_mdio_bus(dev, eqos->mii); 20688e3eceb0SYe Li #endif 2069ba4dfef1SStephen Warren 2070ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 2071ba4dfef1SStephen Warren return 0; 2072ba4dfef1SStephen Warren 2073ba4dfef1SStephen Warren err_free_mdio: 2074ba4dfef1SStephen Warren mdio_free(eqos->mii); 2075ba4dfef1SStephen Warren err_remove_resources_tegra: 20767a4c4eddSChristophe Roullier eqos->config->ops->eqos_remove_resources(dev); 2077ba4dfef1SStephen Warren err_remove_resources_core: 2078ba4dfef1SStephen Warren eqos_remove_resources_core(dev); 2079ba4dfef1SStephen Warren 2080ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 2081ba4dfef1SStephen Warren return ret; 2082ba4dfef1SStephen Warren } 2083ba4dfef1SStephen Warren 2084ba4dfef1SStephen Warren static int eqos_remove(struct udevice *dev) 2085ba4dfef1SStephen Warren { 2086ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 2087ba4dfef1SStephen Warren 2088ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 2089ba4dfef1SStephen Warren 2090ba4dfef1SStephen Warren mdio_unregister(eqos->mii); 2091ba4dfef1SStephen Warren mdio_free(eqos->mii); 20927a4c4eddSChristophe Roullier eqos->config->ops->eqos_remove_resources(dev); 20937a4c4eddSChristophe Roullier 2094ba4dfef1SStephen Warren eqos_probe_resources_core(dev); 2095ba4dfef1SStephen Warren 2096ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 2097ba4dfef1SStephen Warren return 0; 2098ba4dfef1SStephen Warren } 2099ba4dfef1SStephen Warren 2100ba4dfef1SStephen Warren static const struct eth_ops eqos_ops = { 2101ba4dfef1SStephen Warren .start = eqos_start, 2102ba4dfef1SStephen Warren .stop = eqos_stop, 2103ba4dfef1SStephen Warren .send = eqos_send, 2104ba4dfef1SStephen Warren .recv = eqos_recv, 2105ba4dfef1SStephen Warren .free_pkt = eqos_free_pkt, 2106ba4dfef1SStephen Warren .write_hwaddr = eqos_write_hwaddr, 21074d0fb6f0SYe Li .read_rom_hwaddr = eqos_read_rom_hwaddr, 2108ba4dfef1SStephen Warren }; 2109ba4dfef1SStephen Warren 21107a4c4eddSChristophe Roullier static struct eqos_ops eqos_tegra186_ops = { 21117a4c4eddSChristophe Roullier .eqos_inval_desc = eqos_inval_desc_tegra186, 21127a4c4eddSChristophe Roullier .eqos_flush_desc = eqos_flush_desc_tegra186, 21137a4c4eddSChristophe Roullier .eqos_inval_buffer = eqos_inval_buffer_tegra186, 21147a4c4eddSChristophe Roullier .eqos_flush_buffer = eqos_flush_buffer_tegra186, 21157a4c4eddSChristophe Roullier .eqos_probe_resources = eqos_probe_resources_tegra186, 21167a4c4eddSChristophe Roullier .eqos_remove_resources = eqos_remove_resources_tegra186, 21177a4c4eddSChristophe Roullier .eqos_stop_resets = eqos_stop_resets_tegra186, 21187a4c4eddSChristophe Roullier .eqos_start_resets = eqos_start_resets_tegra186, 21197a4c4eddSChristophe Roullier .eqos_stop_clks = eqos_stop_clks_tegra186, 21207a4c4eddSChristophe Roullier .eqos_start_clks = eqos_start_clks_tegra186, 21217a4c4eddSChristophe Roullier .eqos_calibrate_pads = eqos_calibrate_pads_tegra186, 21227a4c4eddSChristophe Roullier .eqos_disable_calibration = eqos_disable_calibration_tegra186, 21237a4c4eddSChristophe Roullier .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186, 2124*bbbbc81cSDavid Wu .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186, 2125*bbbbc81cSDavid Wu .eqos_get_interface = eqos_get_interface_tegra186 21267a4c4eddSChristophe Roullier }; 21277a4c4eddSChristophe Roullier 2128ba4dfef1SStephen Warren static const struct eqos_config eqos_tegra186_config = { 2129ba4dfef1SStephen Warren .reg_access_always_ok = false, 21307a4c4eddSChristophe Roullier .mdio_wait = 10, 21317a4c4eddSChristophe Roullier .swr_wait = 10, 21327a4c4eddSChristophe Roullier .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, 21337a4c4eddSChristophe Roullier .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35, 21347a4c4eddSChristophe Roullier .ops = &eqos_tegra186_ops 21357a4c4eddSChristophe Roullier }; 21367a4c4eddSChristophe Roullier 21377a4c4eddSChristophe Roullier static struct eqos_ops eqos_stm32_ops = { 2138a7b3400fSFugang Duan .eqos_inval_desc = eqos_inval_desc_generic, 2139a7b3400fSFugang Duan .eqos_flush_desc = eqos_flush_desc_generic, 2140a7b3400fSFugang Duan .eqos_inval_buffer = eqos_inval_buffer_generic, 2141a7b3400fSFugang Duan .eqos_flush_buffer = eqos_flush_buffer_generic, 21427a4c4eddSChristophe Roullier .eqos_probe_resources = eqos_probe_resources_stm32, 21437a4c4eddSChristophe Roullier .eqos_remove_resources = eqos_remove_resources_stm32, 21447a4c4eddSChristophe Roullier .eqos_stop_resets = eqos_stop_resets_stm32, 21457a4c4eddSChristophe Roullier .eqos_start_resets = eqos_start_resets_stm32, 21467a4c4eddSChristophe Roullier .eqos_stop_clks = eqos_stop_clks_stm32, 21477a4c4eddSChristophe Roullier .eqos_start_clks = eqos_start_clks_stm32, 21487a4c4eddSChristophe Roullier .eqos_calibrate_pads = eqos_calibrate_pads_stm32, 21497a4c4eddSChristophe Roullier .eqos_disable_calibration = eqos_disable_calibration_stm32, 21507a4c4eddSChristophe Roullier .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_stm32, 2151*bbbbc81cSDavid Wu .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32, 2152*bbbbc81cSDavid Wu .eqos_get_interface = eqos_get_interface_stm32 21537a4c4eddSChristophe Roullier }; 21547a4c4eddSChristophe Roullier 21557a4c4eddSChristophe Roullier static const struct eqos_config eqos_stm32_config = { 21567a4c4eddSChristophe Roullier .reg_access_always_ok = false, 21577a4c4eddSChristophe Roullier .mdio_wait = 10000, 21587a4c4eddSChristophe Roullier .swr_wait = 50, 21597a4c4eddSChristophe Roullier .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, 21607a4c4eddSChristophe Roullier .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, 21617a4c4eddSChristophe Roullier .ops = &eqos_stm32_ops 2162ba4dfef1SStephen Warren }; 2163ba4dfef1SStephen Warren 2164a7b3400fSFugang Duan static struct eqos_ops eqos_imx_ops = { 2165a7b3400fSFugang Duan .eqos_inval_desc = eqos_inval_desc_generic, 2166a7b3400fSFugang Duan .eqos_flush_desc = eqos_flush_desc_generic, 2167a7b3400fSFugang Duan .eqos_inval_buffer = eqos_inval_buffer_generic, 2168a7b3400fSFugang Duan .eqos_flush_buffer = eqos_flush_buffer_generic, 2169a7b3400fSFugang Duan .eqos_probe_resources = eqos_probe_resources_imx, 2170a7b3400fSFugang Duan .eqos_remove_resources = eqos_remove_resources_imx, 2171a7b3400fSFugang Duan .eqos_stop_resets = eqos_stop_resets_imx, 2172a7b3400fSFugang Duan .eqos_start_resets = eqos_start_resets_imx, 2173a7b3400fSFugang Duan .eqos_stop_clks = eqos_stop_clks_imx, 2174a7b3400fSFugang Duan .eqos_start_clks = eqos_start_clks_imx, 2175a7b3400fSFugang Duan .eqos_calibrate_pads = eqos_calibrate_pads_imx, 2176a7b3400fSFugang Duan .eqos_disable_calibration = eqos_disable_calibration_imx, 2177a7b3400fSFugang Duan .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_imx, 2178*bbbbc81cSDavid Wu .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_imx, 2179*bbbbc81cSDavid Wu .eqos_get_interface = eqos_get_interface_imx 2180a7b3400fSFugang Duan }; 2181a7b3400fSFugang Duan 2182a7b3400fSFugang Duan struct eqos_config eqos_imx_config = { 2183a7b3400fSFugang Duan .reg_access_always_ok = false, 2184a7b3400fSFugang Duan .mdio_wait = 10000, 2185a7b3400fSFugang Duan .swr_wait = 50, 2186a7b3400fSFugang Duan .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, 2187a7b3400fSFugang Duan .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, 2188a7b3400fSFugang Duan .ops = &eqos_imx_ops 2189a7b3400fSFugang Duan }; 2190a7b3400fSFugang Duan 2191ba4dfef1SStephen Warren static const struct udevice_id eqos_ids[] = { 2192ba4dfef1SStephen Warren { 2193ba4dfef1SStephen Warren .compatible = "nvidia,tegra186-eqos", 2194ba4dfef1SStephen Warren .data = (ulong)&eqos_tegra186_config 2195ba4dfef1SStephen Warren }, 21967a4c4eddSChristophe Roullier { 21977a4c4eddSChristophe Roullier .compatible = "snps,dwmac-4.20a", 21987a4c4eddSChristophe Roullier .data = (ulong)&eqos_stm32_config 21997a4c4eddSChristophe Roullier }, 2200a7b3400fSFugang Duan { 2201a7b3400fSFugang Duan .compatible = "fsl,imx-eqos", 2202a7b3400fSFugang Duan .data = (ulong)&eqos_imx_config 2203a7b3400fSFugang Duan }, 22047a4c4eddSChristophe Roullier 2205ba4dfef1SStephen Warren { } 2206ba4dfef1SStephen Warren }; 2207ba4dfef1SStephen Warren 2208ba4dfef1SStephen Warren U_BOOT_DRIVER(eth_eqos) = { 2209ba4dfef1SStephen Warren .name = "eth_eqos", 2210ba4dfef1SStephen Warren .id = UCLASS_ETH, 2211a7b3400fSFugang Duan .of_match = of_match_ptr(eqos_ids), 2212ba4dfef1SStephen Warren .probe = eqos_probe, 2213ba4dfef1SStephen Warren .remove = eqos_remove, 2214ba4dfef1SStephen Warren .ops = &eqos_ops, 2215ba4dfef1SStephen Warren .priv_auto_alloc_size = sizeof(struct eqos_priv), 2216ba4dfef1SStephen Warren .platdata_auto_alloc_size = sizeof(struct eth_pdata), 2217ba4dfef1SStephen Warren }; 2218