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); 303bbbbc81cSDavid 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 615*b29cefabSDavid Wu if (clk_valid(&eqos->clk_rx)) { 6167a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_rx); 6177a4c4eddSChristophe Roullier if (ret < 0) { 6187a4c4eddSChristophe Roullier pr_err("clk_enable(clk_rx) failed: %d", ret); 6197a4c4eddSChristophe Roullier goto err_disable_clk_master_bus; 6207a4c4eddSChristophe Roullier } 621*b29cefabSDavid Wu } 6227a4c4eddSChristophe Roullier 623*b29cefabSDavid Wu if (clk_valid(&eqos->clk_tx)) { 6247a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_tx); 6257a4c4eddSChristophe Roullier if (ret < 0) { 6267a4c4eddSChristophe Roullier pr_err("clk_enable(clk_tx) failed: %d", ret); 6277a4c4eddSChristophe Roullier goto err_disable_clk_rx; 6287a4c4eddSChristophe Roullier } 629*b29cefabSDavid Wu } 6307a4c4eddSChristophe Roullier 6317a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) { 6327a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_ck); 6337a4c4eddSChristophe Roullier if (ret < 0) { 6347a4c4eddSChristophe Roullier pr_err("clk_enable(clk_ck) failed: %d", ret); 6357a4c4eddSChristophe Roullier goto err_disable_clk_tx; 6367a4c4eddSChristophe Roullier } 6377a4c4eddSChristophe Roullier } 638a7b3400fSFugang Duan #endif 6397a4c4eddSChristophe Roullier 6407a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 6417a4c4eddSChristophe Roullier return 0; 6427a4c4eddSChristophe Roullier 643a7b3400fSFugang Duan #ifdef CONFIG_CLK 6447a4c4eddSChristophe Roullier err_disable_clk_tx: 645*b29cefabSDavid Wu if (clk_valid(&eqos->clk_tx)) 6467a4c4eddSChristophe Roullier clk_disable(&eqos->clk_tx); 6477a4c4eddSChristophe Roullier err_disable_clk_rx: 648*b29cefabSDavid Wu if (clk_valid(&eqos->clk_rx)) 6497a4c4eddSChristophe Roullier clk_disable(&eqos->clk_rx); 6507a4c4eddSChristophe Roullier err_disable_clk_master_bus: 6517a4c4eddSChristophe Roullier clk_disable(&eqos->clk_master_bus); 6527a4c4eddSChristophe Roullier err: 6537a4c4eddSChristophe Roullier debug("%s: FAILED: %d\n", __func__, ret); 6547a4c4eddSChristophe Roullier return ret; 655a7b3400fSFugang Duan #endif 656a7b3400fSFugang Duan } 657a7b3400fSFugang Duan 658a7b3400fSFugang Duan static int eqos_start_clks_imx(struct udevice *dev) 659a7b3400fSFugang Duan { 660a7b3400fSFugang Duan return 0; 6617a4c4eddSChristophe Roullier } 6627a4c4eddSChristophe Roullier 6638aaada72SPatrick Delaunay static void eqos_stop_clks_tegra186(struct udevice *dev) 664ba4dfef1SStephen Warren { 665a7b3400fSFugang Duan #ifdef CONFIG_CLK 666ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 667ba4dfef1SStephen Warren 668ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 669ba4dfef1SStephen Warren 670ba4dfef1SStephen Warren clk_disable(&eqos->clk_tx); 671ba4dfef1SStephen Warren clk_disable(&eqos->clk_ptp_ref); 672ba4dfef1SStephen Warren clk_disable(&eqos->clk_rx); 673ba4dfef1SStephen Warren clk_disable(&eqos->clk_master_bus); 674ba4dfef1SStephen Warren clk_disable(&eqos->clk_slave_bus); 675a7b3400fSFugang Duan #endif 676ba4dfef1SStephen Warren 677ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 678ba4dfef1SStephen Warren } 679ba4dfef1SStephen Warren 6808aaada72SPatrick Delaunay static void eqos_stop_clks_stm32(struct udevice *dev) 6817a4c4eddSChristophe Roullier { 682a7b3400fSFugang Duan #ifdef CONFIG_CLK 6837a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 6847a4c4eddSChristophe Roullier 6857a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 6867a4c4eddSChristophe Roullier 687*b29cefabSDavid Wu if (clk_valid(&eqos->clk_tx)) 6887a4c4eddSChristophe Roullier clk_disable(&eqos->clk_tx); 689*b29cefabSDavid Wu if (clk_valid(&eqos->clk_rx)) 6907a4c4eddSChristophe Roullier clk_disable(&eqos->clk_rx); 6917a4c4eddSChristophe Roullier clk_disable(&eqos->clk_master_bus); 6927a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) 6937a4c4eddSChristophe Roullier clk_disable(&eqos->clk_ck); 694a7b3400fSFugang Duan #endif 6957a4c4eddSChristophe Roullier 6967a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 6977a4c4eddSChristophe Roullier } 6987a4c4eddSChristophe Roullier 699a7b3400fSFugang Duan static void eqos_stop_clks_imx(struct udevice *dev) 700a7b3400fSFugang Duan { 701a7b3400fSFugang Duan /* empty */ 702a7b3400fSFugang Duan } 703a7b3400fSFugang Duan 704ba4dfef1SStephen Warren static int eqos_start_resets_tegra186(struct udevice *dev) 705ba4dfef1SStephen Warren { 706ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 707ba4dfef1SStephen Warren int ret; 708ba4dfef1SStephen Warren 709ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 710ba4dfef1SStephen Warren 711ba4dfef1SStephen Warren ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 712ba4dfef1SStephen Warren if (ret < 0) { 71390aa625cSMasahiro Yamada pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", ret); 714ba4dfef1SStephen Warren return ret; 715ba4dfef1SStephen Warren } 716ba4dfef1SStephen Warren 717ba4dfef1SStephen Warren udelay(2); 718ba4dfef1SStephen Warren 719ba4dfef1SStephen Warren ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); 720ba4dfef1SStephen Warren if (ret < 0) { 72190aa625cSMasahiro Yamada pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret); 722ba4dfef1SStephen Warren return ret; 723ba4dfef1SStephen Warren } 724ba4dfef1SStephen Warren 725ba4dfef1SStephen Warren ret = reset_assert(&eqos->reset_ctl); 726ba4dfef1SStephen Warren if (ret < 0) { 72790aa625cSMasahiro Yamada pr_err("reset_assert() failed: %d", ret); 728ba4dfef1SStephen Warren return ret; 729ba4dfef1SStephen Warren } 730ba4dfef1SStephen Warren 731ba4dfef1SStephen Warren udelay(2); 732ba4dfef1SStephen Warren 733ba4dfef1SStephen Warren ret = reset_deassert(&eqos->reset_ctl); 734ba4dfef1SStephen Warren if (ret < 0) { 73590aa625cSMasahiro Yamada pr_err("reset_deassert() failed: %d", ret); 736ba4dfef1SStephen Warren return ret; 737ba4dfef1SStephen Warren } 738ba4dfef1SStephen Warren 739ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 740ba4dfef1SStephen Warren return 0; 741ba4dfef1SStephen Warren } 742ba4dfef1SStephen Warren 7437a4c4eddSChristophe Roullier static int eqos_start_resets_stm32(struct udevice *dev) 7447a4c4eddSChristophe Roullier { 7455bd3c538SChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 7465bd3c538SChristophe Roullier int ret; 7475bd3c538SChristophe Roullier 7485bd3c538SChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 7495bd3c538SChristophe Roullier if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) { 75013105a0bSDavid Wu ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); 75113105a0bSDavid Wu if (ret < 0) { 75213105a0bSDavid Wu pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", 75313105a0bSDavid Wu ret); 75413105a0bSDavid Wu return ret; 75513105a0bSDavid Wu } 75613105a0bSDavid Wu 75713105a0bSDavid Wu udelay(eqos->reset_delays[0]); 75813105a0bSDavid Wu 7595bd3c538SChristophe Roullier ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 7605bd3c538SChristophe Roullier if (ret < 0) { 7615bd3c538SChristophe Roullier pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", 7625bd3c538SChristophe Roullier ret); 7635bd3c538SChristophe Roullier return ret; 7645bd3c538SChristophe Roullier } 7655bd3c538SChristophe Roullier 76613105a0bSDavid Wu udelay(eqos->reset_delays[1]); 7675bd3c538SChristophe Roullier 7685bd3c538SChristophe Roullier ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); 7695bd3c538SChristophe Roullier if (ret < 0) { 7705bd3c538SChristophe Roullier pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", 7715bd3c538SChristophe Roullier ret); 7725bd3c538SChristophe Roullier return ret; 7735bd3c538SChristophe Roullier } 77413105a0bSDavid Wu 77513105a0bSDavid Wu udelay(eqos->reset_delays[2]); 7765bd3c538SChristophe Roullier } 7775bd3c538SChristophe Roullier debug("%s: OK\n", __func__); 7785bd3c538SChristophe Roullier 7797a4c4eddSChristophe Roullier return 0; 7807a4c4eddSChristophe Roullier } 7817a4c4eddSChristophe Roullier 782a7b3400fSFugang Duan static int eqos_start_resets_imx(struct udevice *dev) 783a7b3400fSFugang Duan { 784a7b3400fSFugang Duan return 0; 785a7b3400fSFugang Duan } 786a7b3400fSFugang Duan 787ba4dfef1SStephen Warren static int eqos_stop_resets_tegra186(struct udevice *dev) 788ba4dfef1SStephen Warren { 789ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 790ba4dfef1SStephen Warren 791ba4dfef1SStephen Warren reset_assert(&eqos->reset_ctl); 792ba4dfef1SStephen Warren dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 793ba4dfef1SStephen Warren 794ba4dfef1SStephen Warren return 0; 795ba4dfef1SStephen Warren } 796ba4dfef1SStephen Warren 7977a4c4eddSChristophe Roullier static int eqos_stop_resets_stm32(struct udevice *dev) 7987a4c4eddSChristophe Roullier { 7995bd3c538SChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 8005bd3c538SChristophe Roullier int ret; 8015bd3c538SChristophe Roullier 8025bd3c538SChristophe Roullier if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) { 8035bd3c538SChristophe Roullier ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 8045bd3c538SChristophe Roullier if (ret < 0) { 8055bd3c538SChristophe Roullier pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", 8065bd3c538SChristophe Roullier ret); 8075bd3c538SChristophe Roullier return ret; 8085bd3c538SChristophe Roullier } 8095bd3c538SChristophe Roullier } 8105bd3c538SChristophe Roullier 8117a4c4eddSChristophe Roullier return 0; 8127a4c4eddSChristophe Roullier } 8137a4c4eddSChristophe Roullier 814a7b3400fSFugang Duan static int eqos_stop_resets_imx(struct udevice *dev) 815a7b3400fSFugang Duan { 816a7b3400fSFugang Duan return 0; 817a7b3400fSFugang Duan } 818a7b3400fSFugang Duan 819ba4dfef1SStephen Warren static int eqos_calibrate_pads_tegra186(struct udevice *dev) 820ba4dfef1SStephen Warren { 821ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 822ba4dfef1SStephen Warren int ret; 823ba4dfef1SStephen Warren 824ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 825ba4dfef1SStephen Warren 826ba4dfef1SStephen Warren setbits_le32(&eqos->tegra186_regs->sdmemcomppadctrl, 827ba4dfef1SStephen Warren EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD); 828ba4dfef1SStephen Warren 829ba4dfef1SStephen Warren udelay(1); 830ba4dfef1SStephen Warren 831ba4dfef1SStephen Warren setbits_le32(&eqos->tegra186_regs->auto_cal_config, 832ba4dfef1SStephen Warren EQOS_AUTO_CAL_CONFIG_START | EQOS_AUTO_CAL_CONFIG_ENABLE); 833ba4dfef1SStephen Warren 834b491b498SJon Lin ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, 835ba4dfef1SStephen Warren EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false); 836ba4dfef1SStephen Warren if (ret) { 83790aa625cSMasahiro Yamada pr_err("calibrate didn't start"); 838ba4dfef1SStephen Warren goto failed; 839ba4dfef1SStephen Warren } 840ba4dfef1SStephen Warren 841b491b498SJon Lin ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, 842ba4dfef1SStephen Warren EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false); 843ba4dfef1SStephen Warren if (ret) { 84490aa625cSMasahiro Yamada pr_err("calibrate didn't finish"); 845ba4dfef1SStephen Warren goto failed; 846ba4dfef1SStephen Warren } 847ba4dfef1SStephen Warren 848ba4dfef1SStephen Warren ret = 0; 849ba4dfef1SStephen Warren 850ba4dfef1SStephen Warren failed: 851ba4dfef1SStephen Warren clrbits_le32(&eqos->tegra186_regs->sdmemcomppadctrl, 852ba4dfef1SStephen Warren EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD); 853ba4dfef1SStephen Warren 854ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 855ba4dfef1SStephen Warren 856ba4dfef1SStephen Warren return ret; 857ba4dfef1SStephen Warren } 858ba4dfef1SStephen Warren 859ba4dfef1SStephen Warren static int eqos_disable_calibration_tegra186(struct udevice *dev) 860ba4dfef1SStephen Warren { 861ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 862ba4dfef1SStephen Warren 863ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 864ba4dfef1SStephen Warren 865ba4dfef1SStephen Warren clrbits_le32(&eqos->tegra186_regs->auto_cal_config, 866ba4dfef1SStephen Warren EQOS_AUTO_CAL_CONFIG_ENABLE); 867ba4dfef1SStephen Warren 868ba4dfef1SStephen Warren return 0; 869ba4dfef1SStephen Warren } 870ba4dfef1SStephen Warren 871ba4dfef1SStephen Warren static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev) 872ba4dfef1SStephen Warren { 873a7b3400fSFugang Duan #ifdef CONFIG_CLK 874ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 875ba4dfef1SStephen Warren 876ba4dfef1SStephen Warren return clk_get_rate(&eqos->clk_slave_bus); 877a7b3400fSFugang Duan #else 878a7b3400fSFugang Duan return 0; 879a7b3400fSFugang Duan #endif 880ba4dfef1SStephen Warren } 881ba4dfef1SStephen Warren 8827a4c4eddSChristophe Roullier static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) 8837a4c4eddSChristophe Roullier { 884a7b3400fSFugang Duan #ifdef CONFIG_CLK 8857a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 8867a4c4eddSChristophe Roullier 8877a4c4eddSChristophe Roullier return clk_get_rate(&eqos->clk_master_bus); 888a7b3400fSFugang Duan #else 889a7b3400fSFugang Duan return 0; 890a7b3400fSFugang Duan #endif 891a7b3400fSFugang Duan } 892a7b3400fSFugang Duan 893ad018a0cSFugang Duan __weak u32 imx_get_eqos_csr_clk(void) 894ad018a0cSFugang Duan { 895ad018a0cSFugang Duan return 100 * 1000000; 896ad018a0cSFugang Duan } 897ad018a0cSFugang Duan __weak int imx_eqos_txclk_set_rate(unsigned long rate) 898ad018a0cSFugang Duan { 899ad018a0cSFugang Duan return 0; 900ad018a0cSFugang Duan } 901ad018a0cSFugang Duan 902a7b3400fSFugang Duan static ulong eqos_get_tick_clk_rate_imx(struct udevice *dev) 903a7b3400fSFugang Duan { 904ad018a0cSFugang Duan return imx_get_eqos_csr_clk(); 9057a4c4eddSChristophe Roullier } 9067a4c4eddSChristophe Roullier 9077a4c4eddSChristophe Roullier static int eqos_calibrate_pads_stm32(struct udevice *dev) 9087a4c4eddSChristophe Roullier { 9097a4c4eddSChristophe Roullier return 0; 9107a4c4eddSChristophe Roullier } 9117a4c4eddSChristophe Roullier 912a7b3400fSFugang Duan static int eqos_calibrate_pads_imx(struct udevice *dev) 913a7b3400fSFugang Duan { 914a7b3400fSFugang Duan return 0; 915a7b3400fSFugang Duan } 916a7b3400fSFugang Duan 9177a4c4eddSChristophe Roullier static int eqos_disable_calibration_stm32(struct udevice *dev) 9187a4c4eddSChristophe Roullier { 9197a4c4eddSChristophe Roullier return 0; 9207a4c4eddSChristophe Roullier } 9217a4c4eddSChristophe Roullier 922a7b3400fSFugang Duan static int eqos_disable_calibration_imx(struct udevice *dev) 923a7b3400fSFugang Duan { 924a7b3400fSFugang Duan return 0; 925a7b3400fSFugang Duan } 926a7b3400fSFugang Duan 927ba4dfef1SStephen Warren static int eqos_set_full_duplex(struct udevice *dev) 928ba4dfef1SStephen Warren { 929ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 930ba4dfef1SStephen Warren 931ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 932ba4dfef1SStephen Warren 933ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->configuration, EQOS_MAC_CONFIGURATION_DM); 934ba4dfef1SStephen Warren 935ba4dfef1SStephen Warren return 0; 936ba4dfef1SStephen Warren } 937ba4dfef1SStephen Warren 938ba4dfef1SStephen Warren static int eqos_set_half_duplex(struct udevice *dev) 939ba4dfef1SStephen Warren { 940ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 941ba4dfef1SStephen Warren 942ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 943ba4dfef1SStephen Warren 944ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, EQOS_MAC_CONFIGURATION_DM); 945ba4dfef1SStephen Warren 946ba4dfef1SStephen Warren /* WAR: Flush TX queue when switching to half-duplex */ 947ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->txq0_operation_mode, 948ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_FTQ); 949ba4dfef1SStephen Warren 950ba4dfef1SStephen Warren return 0; 951ba4dfef1SStephen Warren } 952ba4dfef1SStephen Warren 953ba4dfef1SStephen Warren static int eqos_set_gmii_speed(struct udevice *dev) 954ba4dfef1SStephen Warren { 955ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 956ba4dfef1SStephen Warren 957ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 958ba4dfef1SStephen Warren 959ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, 960ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_PS | EQOS_MAC_CONFIGURATION_FES); 961ba4dfef1SStephen Warren 962ba4dfef1SStephen Warren return 0; 963ba4dfef1SStephen Warren } 964ba4dfef1SStephen Warren 965ba4dfef1SStephen Warren static int eqos_set_mii_speed_100(struct udevice *dev) 966ba4dfef1SStephen Warren { 967ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 968ba4dfef1SStephen Warren 969ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 970ba4dfef1SStephen Warren 971ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->configuration, 972ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_PS | EQOS_MAC_CONFIGURATION_FES); 973ba4dfef1SStephen Warren 974ba4dfef1SStephen Warren return 0; 975ba4dfef1SStephen Warren } 976ba4dfef1SStephen Warren 977ba4dfef1SStephen Warren static int eqos_set_mii_speed_10(struct udevice *dev) 978ba4dfef1SStephen Warren { 979ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 980ba4dfef1SStephen Warren 981ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 982ba4dfef1SStephen Warren 983ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->configuration, 984ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_FES, EQOS_MAC_CONFIGURATION_PS); 985ba4dfef1SStephen Warren 986ba4dfef1SStephen Warren return 0; 987ba4dfef1SStephen Warren } 988ba4dfef1SStephen Warren 989ba4dfef1SStephen Warren static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev) 990ba4dfef1SStephen Warren { 991a7b3400fSFugang Duan #ifdef CONFIG_CLK 992ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 993ba4dfef1SStephen Warren ulong rate; 994ba4dfef1SStephen Warren int ret; 995ba4dfef1SStephen Warren 996ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 997ba4dfef1SStephen Warren 998ba4dfef1SStephen Warren switch (eqos->phy->speed) { 999ba4dfef1SStephen Warren case SPEED_1000: 1000ba4dfef1SStephen Warren rate = 125 * 1000 * 1000; 1001ba4dfef1SStephen Warren break; 1002ba4dfef1SStephen Warren case SPEED_100: 1003ba4dfef1SStephen Warren rate = 25 * 1000 * 1000; 1004ba4dfef1SStephen Warren break; 1005ba4dfef1SStephen Warren case SPEED_10: 1006ba4dfef1SStephen Warren rate = 2.5 * 1000 * 1000; 1007ba4dfef1SStephen Warren break; 1008ba4dfef1SStephen Warren default: 100990aa625cSMasahiro Yamada pr_err("invalid speed %d", eqos->phy->speed); 1010ba4dfef1SStephen Warren return -EINVAL; 1011ba4dfef1SStephen Warren } 1012ba4dfef1SStephen Warren 1013ba4dfef1SStephen Warren ret = clk_set_rate(&eqos->clk_tx, rate); 1014ba4dfef1SStephen Warren if (ret < 0) { 101590aa625cSMasahiro Yamada pr_err("clk_set_rate(tx_clk, %lu) failed: %d", rate, ret); 1016ba4dfef1SStephen Warren return ret; 1017ba4dfef1SStephen Warren } 1018a7b3400fSFugang Duan #endif 1019ba4dfef1SStephen Warren 1020ba4dfef1SStephen Warren return 0; 1021ba4dfef1SStephen Warren } 1022ba4dfef1SStephen Warren 10237a4c4eddSChristophe Roullier static int eqos_set_tx_clk_speed_stm32(struct udevice *dev) 10247a4c4eddSChristophe Roullier { 10257a4c4eddSChristophe Roullier return 0; 10267a4c4eddSChristophe Roullier } 10277a4c4eddSChristophe Roullier 1028a7b3400fSFugang Duan static int eqos_set_tx_clk_speed_imx(struct udevice *dev) 1029a7b3400fSFugang Duan { 1030ad018a0cSFugang Duan struct eqos_priv *eqos = dev_get_priv(dev); 1031ad018a0cSFugang Duan ulong rate; 1032ad018a0cSFugang Duan int ret; 1033ad018a0cSFugang Duan 1034ad018a0cSFugang Duan debug("%s(dev=%p):\n", __func__, dev); 1035ad018a0cSFugang Duan 1036ad018a0cSFugang Duan switch (eqos->phy->speed) { 1037ad018a0cSFugang Duan case SPEED_1000: 1038ad018a0cSFugang Duan rate = 125 * 1000 * 1000; 1039ad018a0cSFugang Duan break; 1040ad018a0cSFugang Duan case SPEED_100: 1041ad018a0cSFugang Duan rate = 25 * 1000 * 1000; 1042ad018a0cSFugang Duan break; 1043ad018a0cSFugang Duan case SPEED_10: 1044ad018a0cSFugang Duan rate = 2.5 * 1000 * 1000; 1045ad018a0cSFugang Duan break; 1046ad018a0cSFugang Duan default: 1047ad018a0cSFugang Duan pr_err("invalid speed %d", eqos->phy->speed); 1048ad018a0cSFugang Duan return -EINVAL; 1049ad018a0cSFugang Duan } 1050ad018a0cSFugang Duan 1051ad018a0cSFugang Duan ret = imx_eqos_txclk_set_rate(rate); 1052ad018a0cSFugang Duan if (ret < 0) { 1053ad018a0cSFugang Duan pr_err("imx (tx_clk, %lu) failed: %d", rate, ret); 1054ad018a0cSFugang Duan return ret; 1055ad018a0cSFugang Duan } 1056ad018a0cSFugang Duan 1057a7b3400fSFugang Duan return 0; 1058a7b3400fSFugang Duan } 1059a7b3400fSFugang Duan 1060ba4dfef1SStephen Warren static int eqos_adjust_link(struct udevice *dev) 1061ba4dfef1SStephen Warren { 1062ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1063ba4dfef1SStephen Warren int ret; 1064ba4dfef1SStephen Warren bool en_calibration; 1065ba4dfef1SStephen Warren 1066ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1067ba4dfef1SStephen Warren 1068ba4dfef1SStephen Warren if (eqos->phy->duplex) 1069ba4dfef1SStephen Warren ret = eqos_set_full_duplex(dev); 1070ba4dfef1SStephen Warren else 1071ba4dfef1SStephen Warren ret = eqos_set_half_duplex(dev); 1072ba4dfef1SStephen Warren if (ret < 0) { 107390aa625cSMasahiro Yamada pr_err("eqos_set_*_duplex() failed: %d", ret); 1074ba4dfef1SStephen Warren return ret; 1075ba4dfef1SStephen Warren } 1076ba4dfef1SStephen Warren 1077ba4dfef1SStephen Warren switch (eqos->phy->speed) { 1078ba4dfef1SStephen Warren case SPEED_1000: 1079ba4dfef1SStephen Warren en_calibration = true; 1080ba4dfef1SStephen Warren ret = eqos_set_gmii_speed(dev); 1081ba4dfef1SStephen Warren break; 1082ba4dfef1SStephen Warren case SPEED_100: 1083ba4dfef1SStephen Warren en_calibration = true; 1084ba4dfef1SStephen Warren ret = eqos_set_mii_speed_100(dev); 1085ba4dfef1SStephen Warren break; 1086ba4dfef1SStephen Warren case SPEED_10: 1087ba4dfef1SStephen Warren en_calibration = false; 1088ba4dfef1SStephen Warren ret = eqos_set_mii_speed_10(dev); 1089ba4dfef1SStephen Warren break; 1090ba4dfef1SStephen Warren default: 109190aa625cSMasahiro Yamada pr_err("invalid speed %d", eqos->phy->speed); 1092ba4dfef1SStephen Warren return -EINVAL; 1093ba4dfef1SStephen Warren } 1094ba4dfef1SStephen Warren if (ret < 0) { 109590aa625cSMasahiro Yamada pr_err("eqos_set_*mii_speed*() failed: %d", ret); 1096ba4dfef1SStephen Warren return ret; 1097ba4dfef1SStephen Warren } 1098ba4dfef1SStephen Warren 1099ba4dfef1SStephen Warren if (en_calibration) { 11007a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_calibrate_pads(dev); 1101ba4dfef1SStephen Warren if (ret < 0) { 11027a4c4eddSChristophe Roullier pr_err("eqos_calibrate_pads() failed: %d", 11037a4c4eddSChristophe Roullier ret); 1104ba4dfef1SStephen Warren return ret; 1105ba4dfef1SStephen Warren } 1106ba4dfef1SStephen Warren } else { 11077a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_disable_calibration(dev); 1108ba4dfef1SStephen Warren if (ret < 0) { 11097a4c4eddSChristophe Roullier pr_err("eqos_disable_calibration() failed: %d", 1110ba4dfef1SStephen Warren ret); 1111ba4dfef1SStephen Warren return ret; 1112ba4dfef1SStephen Warren } 1113ba4dfef1SStephen Warren } 11147a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_set_tx_clk_speed(dev); 1115ba4dfef1SStephen Warren if (ret < 0) { 11167a4c4eddSChristophe Roullier pr_err("eqos_set_tx_clk_speed() failed: %d", ret); 1117ba4dfef1SStephen Warren return ret; 1118ba4dfef1SStephen Warren } 1119ba4dfef1SStephen Warren 1120ba4dfef1SStephen Warren return 0; 1121ba4dfef1SStephen Warren } 1122ba4dfef1SStephen Warren 1123ba4dfef1SStephen Warren static int eqos_write_hwaddr(struct udevice *dev) 1124ba4dfef1SStephen Warren { 1125ba4dfef1SStephen Warren struct eth_pdata *plat = dev_get_platdata(dev); 1126ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1127ba4dfef1SStephen Warren uint32_t val; 1128ba4dfef1SStephen Warren 1129ba4dfef1SStephen Warren /* 1130ba4dfef1SStephen Warren * This function may be called before start() or after stop(). At that 1131ba4dfef1SStephen Warren * time, on at least some configurations of the EQoS HW, all clocks to 1132ba4dfef1SStephen Warren * the EQoS HW block will be stopped, and a reset signal applied. If 1133ba4dfef1SStephen Warren * any register access is attempted in this state, bus timeouts or CPU 1134ba4dfef1SStephen Warren * hangs may occur. This check prevents that. 1135ba4dfef1SStephen Warren * 1136ba4dfef1SStephen Warren * A simple solution to this problem would be to not implement 1137ba4dfef1SStephen Warren * write_hwaddr(), since start() always writes the MAC address into HW 1138ba4dfef1SStephen Warren * anyway. However, it is desirable to implement write_hwaddr() to 1139ba4dfef1SStephen Warren * support the case of SW that runs subsequent to U-Boot which expects 1140ba4dfef1SStephen Warren * the MAC address to already be programmed into the EQoS registers, 1141ba4dfef1SStephen Warren * which must happen irrespective of whether the U-Boot user (or 1142ba4dfef1SStephen Warren * scripts) actually made use of the EQoS device, and hence 1143ba4dfef1SStephen Warren * irrespective of whether start() was ever called. 1144ba4dfef1SStephen Warren * 1145ba4dfef1SStephen Warren * Note that this requirement by subsequent SW is not valid for 1146ba4dfef1SStephen Warren * Tegra186, and is likely not valid for any non-PCI instantiation of 1147ba4dfef1SStephen Warren * the EQoS HW block. This function is implemented solely as 1148ba4dfef1SStephen Warren * future-proofing with the expectation the driver will eventually be 1149ba4dfef1SStephen Warren * ported to some system where the expectation above is true. 1150ba4dfef1SStephen Warren */ 1151ba4dfef1SStephen Warren if (!eqos->config->reg_access_always_ok && !eqos->reg_access_ok) 1152ba4dfef1SStephen Warren return 0; 1153ba4dfef1SStephen Warren 1154ba4dfef1SStephen Warren /* Update the MAC address */ 1155ba4dfef1SStephen Warren val = (plat->enetaddr[5] << 8) | 1156ba4dfef1SStephen Warren (plat->enetaddr[4]); 1157ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->address0_high); 1158ba4dfef1SStephen Warren val = (plat->enetaddr[3] << 24) | 1159ba4dfef1SStephen Warren (plat->enetaddr[2] << 16) | 1160ba4dfef1SStephen Warren (plat->enetaddr[1] << 8) | 1161ba4dfef1SStephen Warren (plat->enetaddr[0]); 1162ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->address0_low); 1163ba4dfef1SStephen Warren 1164ba4dfef1SStephen Warren return 0; 1165ba4dfef1SStephen Warren } 1166ba4dfef1SStephen Warren 11674d0fb6f0SYe Li static int eqos_read_rom_hwaddr(struct udevice *dev) 11684d0fb6f0SYe Li { 11694d0fb6f0SYe Li struct eth_pdata *pdata = dev_get_platdata(dev); 11704d0fb6f0SYe Li 11714d0fb6f0SYe Li #ifdef CONFIG_ARCH_IMX8M 11724d0fb6f0SYe Li imx_get_mac_from_fuse(dev->req_seq, pdata->enetaddr); 11734d0fb6f0SYe Li #endif 11744d0fb6f0SYe Li return !is_valid_ethaddr(pdata->enetaddr); 11754d0fb6f0SYe Li } 11764d0fb6f0SYe Li 1177ba4dfef1SStephen Warren static int eqos_start(struct udevice *dev) 1178ba4dfef1SStephen Warren { 1179ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1180ba4dfef1SStephen Warren int ret, i; 1181ba4dfef1SStephen Warren ulong rate; 1182ba4dfef1SStephen Warren u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl; 1183ba4dfef1SStephen Warren ulong last_rx_desc; 1184ba4dfef1SStephen Warren 1185ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1186ba4dfef1SStephen Warren 1187ba4dfef1SStephen Warren eqos->tx_desc_idx = 0; 1188ba4dfef1SStephen Warren eqos->rx_desc_idx = 0; 1189ba4dfef1SStephen Warren 11907a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_start_clks(dev); 1191ba4dfef1SStephen Warren if (ret < 0) { 11927a4c4eddSChristophe Roullier pr_err("eqos_start_clks() failed: %d", ret); 1193ba4dfef1SStephen Warren goto err; 1194ba4dfef1SStephen Warren } 1195ba4dfef1SStephen Warren 11967a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_start_resets(dev); 1197ba4dfef1SStephen Warren if (ret < 0) { 11987a4c4eddSChristophe Roullier pr_err("eqos_start_resets() failed: %d", ret); 1199ba4dfef1SStephen Warren goto err_stop_clks; 1200ba4dfef1SStephen Warren } 1201ba4dfef1SStephen Warren 1202ba4dfef1SStephen Warren udelay(10); 1203ba4dfef1SStephen Warren 1204ba4dfef1SStephen Warren eqos->reg_access_ok = true; 1205ba4dfef1SStephen Warren 1206b491b498SJon Lin ret = wait_for_bit_le32(&eqos->dma_regs->mode, 12077a4c4eddSChristophe Roullier EQOS_DMA_MODE_SWR, false, 12087a4c4eddSChristophe Roullier eqos->config->swr_wait, false); 1209ba4dfef1SStephen Warren if (ret) { 121090aa625cSMasahiro Yamada pr_err("EQOS_DMA_MODE_SWR stuck"); 1211ba4dfef1SStephen Warren goto err_stop_resets; 1212ba4dfef1SStephen Warren } 1213ba4dfef1SStephen Warren 12147a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_calibrate_pads(dev); 1215ba4dfef1SStephen Warren if (ret < 0) { 12167a4c4eddSChristophe Roullier pr_err("eqos_calibrate_pads() failed: %d", ret); 1217ba4dfef1SStephen Warren goto err_stop_resets; 1218ba4dfef1SStephen Warren } 12197a4c4eddSChristophe Roullier rate = eqos->config->ops->eqos_get_tick_clk_rate(dev); 1220ba4dfef1SStephen Warren 1221ba4dfef1SStephen Warren val = (rate / 1000000) - 1; 1222ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->us_tic_counter); 1223ba4dfef1SStephen Warren 12247a4c4eddSChristophe Roullier /* 12257a4c4eddSChristophe Roullier * if PHY was already connected and configured, 12267a4c4eddSChristophe Roullier * don't need to reconnect/reconfigure again 12277a4c4eddSChristophe Roullier */ 12287a4c4eddSChristophe Roullier if (!eqos->phy) { 12298e3eceb0SYe Li int addr = -1; 12308e3eceb0SYe Li #ifdef CONFIG_DM_ETH_PHY 12318e3eceb0SYe Li addr = eth_phy_get_addr(dev); 12328e3eceb0SYe Li #endif 12338e3eceb0SYe Li #ifdef DWC_NET_PHYADDR 12348e3eceb0SYe Li addr = DWC_NET_PHYADDR; 12358e3eceb0SYe Li #endif 12368e3eceb0SYe Li eqos->phy = phy_connect(eqos->mii, addr, dev, 1237bbbbc81cSDavid Wu eqos->config->ops->eqos_get_interface(dev)); 1238ba4dfef1SStephen Warren if (!eqos->phy) { 123990aa625cSMasahiro Yamada pr_err("phy_connect() failed"); 1240ba4dfef1SStephen Warren goto err_stop_resets; 1241ba4dfef1SStephen Warren } 124283d31c08SPatrick Delaunay 124383d31c08SPatrick Delaunay if (eqos->max_speed) { 124483d31c08SPatrick Delaunay ret = phy_set_supported(eqos->phy, eqos->max_speed); 124583d31c08SPatrick Delaunay if (ret) { 124683d31c08SPatrick Delaunay pr_err("phy_set_supported() failed: %d", ret); 124783d31c08SPatrick Delaunay goto err_shutdown_phy; 124883d31c08SPatrick Delaunay } 124983d31c08SPatrick Delaunay } 125083d31c08SPatrick Delaunay 1251ba4dfef1SStephen Warren ret = phy_config(eqos->phy); 1252ba4dfef1SStephen Warren if (ret < 0) { 125390aa625cSMasahiro Yamada pr_err("phy_config() failed: %d", ret); 1254ba4dfef1SStephen Warren goto err_shutdown_phy; 1255ba4dfef1SStephen Warren } 12567a4c4eddSChristophe Roullier } 12577a4c4eddSChristophe Roullier 1258ba4dfef1SStephen Warren ret = phy_startup(eqos->phy); 1259ba4dfef1SStephen Warren if (ret < 0) { 126090aa625cSMasahiro Yamada pr_err("phy_startup() failed: %d", ret); 1261ba4dfef1SStephen Warren goto err_shutdown_phy; 1262ba4dfef1SStephen Warren } 1263ba4dfef1SStephen Warren 1264ba4dfef1SStephen Warren if (!eqos->phy->link) { 126590aa625cSMasahiro Yamada pr_err("No link"); 1266ba4dfef1SStephen Warren goto err_shutdown_phy; 1267ba4dfef1SStephen Warren } 1268ba4dfef1SStephen Warren 1269ba4dfef1SStephen Warren ret = eqos_adjust_link(dev); 1270ba4dfef1SStephen Warren if (ret < 0) { 127190aa625cSMasahiro Yamada pr_err("eqos_adjust_link() failed: %d", ret); 1272ba4dfef1SStephen Warren goto err_shutdown_phy; 1273ba4dfef1SStephen Warren } 1274ba4dfef1SStephen Warren 1275ba4dfef1SStephen Warren /* Configure MTL */ 1276a7b3400fSFugang Duan writel(0x60, &eqos->mtl_regs->txq0_quantum_weight - 0x100); 1277ba4dfef1SStephen Warren 1278ba4dfef1SStephen Warren /* Enable Store and Forward mode for TX */ 1279ba4dfef1SStephen Warren /* Program Tx operating mode */ 1280ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->txq0_operation_mode, 1281ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TSF | 1282ba4dfef1SStephen Warren (EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_ENABLED << 1283ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_SHIFT)); 1284ba4dfef1SStephen Warren 1285ba4dfef1SStephen Warren /* Transmit Queue weight */ 1286ba4dfef1SStephen Warren writel(0x10, &eqos->mtl_regs->txq0_quantum_weight); 1287ba4dfef1SStephen Warren 1288ba4dfef1SStephen Warren /* Enable Store and Forward mode for RX, since no jumbo frame */ 1289ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1290a7b3400fSFugang Duan EQOS_MTL_RXQ0_OPERATION_MODE_RSF | 1291a7b3400fSFugang Duan EQOS_MTL_RXQ0_OPERATION_MODE_FEP | 1292a7b3400fSFugang Duan EQOS_MTL_RXQ0_OPERATION_MODE_FUP); 1293ba4dfef1SStephen Warren 1294ba4dfef1SStephen Warren /* Transmit/Receive queue fifo size; use all RAM for 1 queue */ 1295ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->hw_feature1); 1296ba4dfef1SStephen Warren tx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_SHIFT) & 1297ba4dfef1SStephen Warren EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_MASK; 1298ba4dfef1SStephen Warren rx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT) & 1299ba4dfef1SStephen Warren EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK; 1300ba4dfef1SStephen Warren 1301ba4dfef1SStephen Warren /* 1302ba4dfef1SStephen Warren * r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting. 1303ba4dfef1SStephen Warren * r/tqs is encoded as (n / 256) - 1. 1304ba4dfef1SStephen Warren */ 1305ba4dfef1SStephen Warren tqs = (128 << tx_fifo_sz) / 256 - 1; 1306ba4dfef1SStephen Warren rqs = (128 << rx_fifo_sz) / 256 - 1; 1307ba4dfef1SStephen Warren 1308ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->txq0_operation_mode, 1309ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK << 1310ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT, 1311ba4dfef1SStephen Warren tqs << EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT); 1312ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1313ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RQS_MASK << 1314ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT, 1315ba4dfef1SStephen Warren rqs << EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT); 1316ba4dfef1SStephen Warren 1317ba4dfef1SStephen Warren /* Flow control used only if each channel gets 4KB or more FIFO */ 1318ba4dfef1SStephen Warren if (rqs >= ((4096 / 256) - 1)) { 1319ba4dfef1SStephen Warren u32 rfd, rfa; 1320ba4dfef1SStephen Warren 1321ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1322ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_EHFC); 1323ba4dfef1SStephen Warren 1324ba4dfef1SStephen Warren /* 1325ba4dfef1SStephen Warren * Set Threshold for Activating Flow Contol space for min 2 1326ba4dfef1SStephen Warren * frames ie, (1500 * 1) = 1500 bytes. 1327ba4dfef1SStephen Warren * 1328ba4dfef1SStephen Warren * Set Threshold for Deactivating Flow Contol for space of 1329ba4dfef1SStephen Warren * min 1 frame (frame size 1500bytes) in receive fifo 1330ba4dfef1SStephen Warren */ 1331ba4dfef1SStephen Warren if (rqs == ((4096 / 256) - 1)) { 1332ba4dfef1SStephen Warren /* 1333ba4dfef1SStephen Warren * This violates the above formula because of FIFO size 1334ba4dfef1SStephen Warren * limit therefore overflow may occur inspite of this. 1335ba4dfef1SStephen Warren */ 1336ba4dfef1SStephen Warren rfd = 0x3; /* Full-3K */ 1337ba4dfef1SStephen Warren rfa = 0x1; /* Full-1.5K */ 1338ba4dfef1SStephen Warren } else if (rqs == ((8192 / 256) - 1)) { 1339ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1340ba4dfef1SStephen Warren rfa = 0xa; /* Full-6K */ 1341ba4dfef1SStephen Warren } else if (rqs == ((16384 / 256) - 1)) { 1342ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1343ba4dfef1SStephen Warren rfa = 0x12; /* Full-10K */ 1344ba4dfef1SStephen Warren } else { 1345ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1346ba4dfef1SStephen Warren rfa = 0x1E; /* Full-16K */ 1347ba4dfef1SStephen Warren } 1348ba4dfef1SStephen Warren 1349ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1350ba4dfef1SStephen Warren (EQOS_MTL_RXQ0_OPERATION_MODE_RFD_MASK << 1351ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT) | 1352ba4dfef1SStephen Warren (EQOS_MTL_RXQ0_OPERATION_MODE_RFA_MASK << 1353ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT), 1354ba4dfef1SStephen Warren (rfd << 1355ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT) | 1356ba4dfef1SStephen Warren (rfa << 1357ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT)); 1358ba4dfef1SStephen Warren } 1359ba4dfef1SStephen Warren 1360ba4dfef1SStephen Warren /* Configure MAC */ 1361ba4dfef1SStephen Warren 1362ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0, 1363ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK << 1364ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT, 13657a4c4eddSChristophe Roullier eqos->config->config_mac << 1366ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT); 1367ba4dfef1SStephen Warren 1368a7b3400fSFugang Duan clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0, 1369a7b3400fSFugang Duan EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK << 1370a7b3400fSFugang Duan EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT, 1371a7b3400fSFugang Duan 0x2 << 1372a7b3400fSFugang Duan EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT); 1373a7b3400fSFugang Duan 1374a7b3400fSFugang Duan /* Multicast and Broadcast Queue Enable */ 1375a7b3400fSFugang Duan setbits_le32(&eqos->mac_regs->unused_0a4, 1376a7b3400fSFugang Duan 0x00100000); 1377a7b3400fSFugang Duan /* enable promise mode */ 1378a7b3400fSFugang Duan setbits_le32(&eqos->mac_regs->unused_004[1], 1379a7b3400fSFugang Duan 0x1); 1380a7b3400fSFugang Duan 1381ba4dfef1SStephen Warren /* Set TX flow control parameters */ 1382ba4dfef1SStephen Warren /* Set Pause Time */ 1383ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->q0_tx_flow_ctrl, 1384ba4dfef1SStephen Warren 0xffff << EQOS_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT); 1385ba4dfef1SStephen Warren /* Assign priority for TX flow control */ 1386ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->txq_prty_map0, 1387ba4dfef1SStephen Warren EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_MASK << 1388ba4dfef1SStephen Warren EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_SHIFT); 1389ba4dfef1SStephen Warren /* Assign priority for RX flow control */ 1390ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->rxq_ctrl2, 1391ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK << 1392ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT); 1393ba4dfef1SStephen Warren /* Enable flow control */ 1394ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->q0_tx_flow_ctrl, 1395ba4dfef1SStephen Warren EQOS_MAC_Q0_TX_FLOW_CTRL_TFE); 1396ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->rx_flow_ctrl, 1397ba4dfef1SStephen Warren EQOS_MAC_RX_FLOW_CTRL_RFE); 1398ba4dfef1SStephen Warren 1399ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->configuration, 1400ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_GPSLCE | 1401ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_WD | 1402ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_JD | 1403ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_JE, 1404ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_CST | 1405ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_ACS); 1406ba4dfef1SStephen Warren 1407ba4dfef1SStephen Warren eqos_write_hwaddr(dev); 1408ba4dfef1SStephen Warren 1409ba4dfef1SStephen Warren /* Configure DMA */ 1410ba4dfef1SStephen Warren 1411ba4dfef1SStephen Warren /* Enable OSP mode */ 1412ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_tx_control, 1413ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_OSP); 1414ba4dfef1SStephen Warren 1415ba4dfef1SStephen Warren /* RX buffer size. Must be a multiple of bus width */ 1416ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_rx_control, 1417ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_MASK << 1418ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT, 1419ba4dfef1SStephen Warren EQOS_MAX_PACKET_SIZE << 1420ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT); 1421ba4dfef1SStephen Warren 1422ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_control, 1423ba4dfef1SStephen Warren EQOS_DMA_CH0_CONTROL_PBLX8); 1424ba4dfef1SStephen Warren 1425ba4dfef1SStephen Warren /* 1426ba4dfef1SStephen Warren * Burst length must be < 1/2 FIFO size. 1427ba4dfef1SStephen Warren * FIFO size in tqs is encoded as (n / 256) - 1. 1428ba4dfef1SStephen Warren * Each burst is n * 8 (PBLX8) * 16 (AXI width) == 128 bytes. 1429ba4dfef1SStephen Warren * Half of n * 256 is n * 128, so pbl == tqs, modulo the -1. 1430ba4dfef1SStephen Warren */ 1431ba4dfef1SStephen Warren pbl = tqs + 1; 1432ba4dfef1SStephen Warren if (pbl > 32) 1433ba4dfef1SStephen Warren pbl = 32; 1434ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_tx_control, 1435ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_TXPBL_MASK << 1436ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT, 1437ba4dfef1SStephen Warren pbl << EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT); 1438ba4dfef1SStephen Warren 1439ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_rx_control, 1440ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RXPBL_MASK << 1441ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT, 1442ba4dfef1SStephen Warren 8 << EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT); 1443ba4dfef1SStephen Warren 1444ba4dfef1SStephen Warren /* DMA performance configuration */ 1445ba4dfef1SStephen Warren val = (2 << EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_SHIFT) | 1446ba4dfef1SStephen Warren EQOS_DMA_SYSBUS_MODE_EAME | EQOS_DMA_SYSBUS_MODE_BLEN16 | 1447ba4dfef1SStephen Warren EQOS_DMA_SYSBUS_MODE_BLEN8 | EQOS_DMA_SYSBUS_MODE_BLEN4; 1448ba4dfef1SStephen Warren writel(val, &eqos->dma_regs->sysbus_mode); 1449ba4dfef1SStephen Warren 1450ba4dfef1SStephen Warren /* Set up descriptors */ 1451ba4dfef1SStephen Warren 1452ba4dfef1SStephen Warren memset(eqos->descs, 0, EQOS_DESCRIPTORS_SIZE); 1453ba4dfef1SStephen Warren for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) { 1454ba4dfef1SStephen Warren struct eqos_desc *rx_desc = &(eqos->rx_descs[i]); 1455ba4dfef1SStephen Warren rx_desc->des0 = (u32)(ulong)(eqos->rx_dma_buf + 1456ba4dfef1SStephen Warren (i * EQOS_MAX_PACKET_SIZE)); 14576143c348SMarek Vasut rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; 1458a7b3400fSFugang Duan mb(); 14596399c699SMarek Vasut eqos->config->ops->eqos_flush_desc(rx_desc); 1460a7b3400fSFugang Duan eqos->config->ops->eqos_inval_buffer(eqos->rx_dma_buf + 1461a7b3400fSFugang Duan (i * EQOS_MAX_PACKET_SIZE), 1462a7b3400fSFugang Duan EQOS_MAX_PACKET_SIZE); 1463ba4dfef1SStephen Warren } 1464ba4dfef1SStephen Warren 1465ba4dfef1SStephen Warren writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress); 1466ba4dfef1SStephen Warren writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address); 1467ba4dfef1SStephen Warren writel(EQOS_DESCRIPTORS_TX - 1, 1468ba4dfef1SStephen Warren &eqos->dma_regs->ch0_txdesc_ring_length); 1469ba4dfef1SStephen Warren 1470ba4dfef1SStephen Warren writel(0, &eqos->dma_regs->ch0_rxdesc_list_haddress); 1471ba4dfef1SStephen Warren writel((ulong)eqos->rx_descs, &eqos->dma_regs->ch0_rxdesc_list_address); 1472ba4dfef1SStephen Warren writel(EQOS_DESCRIPTORS_RX - 1, 1473ba4dfef1SStephen Warren &eqos->dma_regs->ch0_rxdesc_ring_length); 1474ba4dfef1SStephen Warren 1475ba4dfef1SStephen Warren /* Enable everything */ 1476ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_tx_control, 1477ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_ST); 1478ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_rx_control, 1479ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_SR); 1480a7b3400fSFugang Duan setbits_le32(&eqos->mac_regs->configuration, 1481a7b3400fSFugang Duan EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE); 1482ba4dfef1SStephen Warren 1483ba4dfef1SStephen Warren /* TX tail pointer not written until we need to TX a packet */ 1484ba4dfef1SStephen Warren /* 1485ba4dfef1SStephen Warren * Point RX tail pointer at last descriptor. Ideally, we'd point at the 1486ba4dfef1SStephen Warren * first descriptor, implying all descriptors were available. However, 1487ba4dfef1SStephen Warren * that's not distinguishable from none of the descriptors being 1488ba4dfef1SStephen Warren * available. 1489ba4dfef1SStephen Warren */ 1490ba4dfef1SStephen Warren last_rx_desc = (ulong)&(eqos->rx_descs[(EQOS_DESCRIPTORS_RX - 1)]); 1491ba4dfef1SStephen Warren writel(last_rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); 1492ba4dfef1SStephen Warren 1493ba4dfef1SStephen Warren eqos->started = true; 1494ba4dfef1SStephen Warren 1495ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1496ba4dfef1SStephen Warren return 0; 1497ba4dfef1SStephen Warren 1498ba4dfef1SStephen Warren err_shutdown_phy: 1499ba4dfef1SStephen Warren phy_shutdown(eqos->phy); 1500ba4dfef1SStephen Warren err_stop_resets: 15017a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_resets(dev); 1502ba4dfef1SStephen Warren err_stop_clks: 15037a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_clks(dev); 1504ba4dfef1SStephen Warren err: 150590aa625cSMasahiro Yamada pr_err("FAILED: %d", ret); 1506ba4dfef1SStephen Warren return ret; 1507ba4dfef1SStephen Warren } 1508ba4dfef1SStephen Warren 15098aaada72SPatrick Delaunay static void eqos_stop(struct udevice *dev) 1510ba4dfef1SStephen Warren { 1511ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1512ba4dfef1SStephen Warren int i; 1513ba4dfef1SStephen Warren 1514ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1515ba4dfef1SStephen Warren 1516ba4dfef1SStephen Warren if (!eqos->started) 1517ba4dfef1SStephen Warren return; 1518ba4dfef1SStephen Warren eqos->started = false; 1519ba4dfef1SStephen Warren eqos->reg_access_ok = false; 1520ba4dfef1SStephen Warren 1521ba4dfef1SStephen Warren /* Disable TX DMA */ 1522ba4dfef1SStephen Warren clrbits_le32(&eqos->dma_regs->ch0_tx_control, 1523ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_ST); 1524ba4dfef1SStephen Warren 1525ba4dfef1SStephen Warren /* Wait for TX all packets to drain out of MTL */ 1526ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 1527ba4dfef1SStephen Warren u32 val = readl(&eqos->mtl_regs->txq0_debug); 1528ba4dfef1SStephen Warren u32 trcsts = (val >> EQOS_MTL_TXQ0_DEBUG_TRCSTS_SHIFT) & 1529ba4dfef1SStephen Warren EQOS_MTL_TXQ0_DEBUG_TRCSTS_MASK; 1530ba4dfef1SStephen Warren u32 txqsts = val & EQOS_MTL_TXQ0_DEBUG_TXQSTS; 1531ba4dfef1SStephen Warren if ((trcsts != 1) && (!txqsts)) 1532ba4dfef1SStephen Warren break; 1533ba4dfef1SStephen Warren } 1534ba4dfef1SStephen Warren 1535ba4dfef1SStephen Warren /* Turn off MAC TX and RX */ 1536ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, 1537ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE); 1538ba4dfef1SStephen Warren 1539ba4dfef1SStephen Warren /* Wait for all RX packets to drain out of MTL */ 1540ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 1541ba4dfef1SStephen Warren u32 val = readl(&eqos->mtl_regs->rxq0_debug); 1542ba4dfef1SStephen Warren u32 prxq = (val >> EQOS_MTL_RXQ0_DEBUG_PRXQ_SHIFT) & 1543ba4dfef1SStephen Warren EQOS_MTL_RXQ0_DEBUG_PRXQ_MASK; 1544ba4dfef1SStephen Warren u32 rxqsts = (val >> EQOS_MTL_RXQ0_DEBUG_RXQSTS_SHIFT) & 1545ba4dfef1SStephen Warren EQOS_MTL_RXQ0_DEBUG_RXQSTS_MASK; 1546ba4dfef1SStephen Warren if ((!prxq) && (!rxqsts)) 1547ba4dfef1SStephen Warren break; 1548ba4dfef1SStephen Warren } 1549ba4dfef1SStephen Warren 1550ba4dfef1SStephen Warren /* Turn off RX DMA */ 1551ba4dfef1SStephen Warren clrbits_le32(&eqos->dma_regs->ch0_rx_control, 1552ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_SR); 1553ba4dfef1SStephen Warren 1554ba4dfef1SStephen Warren if (eqos->phy) { 1555ba4dfef1SStephen Warren phy_shutdown(eqos->phy); 1556ba4dfef1SStephen Warren } 15577a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_resets(dev); 15587a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_clks(dev); 1559ba4dfef1SStephen Warren 1560ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1561ba4dfef1SStephen Warren } 1562ba4dfef1SStephen Warren 15638aaada72SPatrick Delaunay static int eqos_send(struct udevice *dev, void *packet, int length) 1564ba4dfef1SStephen Warren { 1565ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1566ba4dfef1SStephen Warren struct eqos_desc *tx_desc; 1567ba4dfef1SStephen Warren int i; 1568ba4dfef1SStephen Warren 1569ba4dfef1SStephen Warren debug("%s(dev=%p, packet=%p, length=%d):\n", __func__, dev, packet, 1570ba4dfef1SStephen Warren length); 1571ba4dfef1SStephen Warren 1572ba4dfef1SStephen Warren memcpy(eqos->tx_dma_buf, packet, length); 15737a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length); 1574ba4dfef1SStephen Warren 1575ba4dfef1SStephen Warren tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]); 1576ba4dfef1SStephen Warren eqos->tx_desc_idx++; 1577ba4dfef1SStephen Warren eqos->tx_desc_idx %= EQOS_DESCRIPTORS_TX; 1578ba4dfef1SStephen Warren 1579ba4dfef1SStephen Warren tx_desc->des0 = (ulong)eqos->tx_dma_buf; 1580ba4dfef1SStephen Warren tx_desc->des1 = 0; 1581ba4dfef1SStephen Warren tx_desc->des2 = length; 1582ba4dfef1SStephen Warren /* 1583ba4dfef1SStephen Warren * Make sure that if HW sees the _OWN write below, it will see all the 1584ba4dfef1SStephen Warren * writes to the rest of the descriptor too. 1585ba4dfef1SStephen Warren */ 1586ba4dfef1SStephen Warren mb(); 1587ba4dfef1SStephen Warren tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length; 15887a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_desc(tx_desc); 1589ba4dfef1SStephen Warren 1590364f8fdcSMarek Vasut writel((ulong)(&(eqos->tx_descs[eqos->tx_desc_idx])), 1591364f8fdcSMarek Vasut &eqos->dma_regs->ch0_txdesc_tail_pointer); 1592ba4dfef1SStephen Warren 1593ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 15947a4c4eddSChristophe Roullier eqos->config->ops->eqos_inval_desc(tx_desc); 1595ba4dfef1SStephen Warren if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN)) 1596ba4dfef1SStephen Warren return 0; 1597ba4dfef1SStephen Warren udelay(1); 1598ba4dfef1SStephen Warren } 1599ba4dfef1SStephen Warren 1600ba4dfef1SStephen Warren debug("%s: TX timeout\n", __func__); 1601ba4dfef1SStephen Warren 1602ba4dfef1SStephen Warren return -ETIMEDOUT; 1603ba4dfef1SStephen Warren } 1604ba4dfef1SStephen Warren 16058aaada72SPatrick Delaunay static int eqos_recv(struct udevice *dev, int flags, uchar **packetp) 1606ba4dfef1SStephen Warren { 1607ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1608ba4dfef1SStephen Warren struct eqos_desc *rx_desc; 1609ba4dfef1SStephen Warren int length; 1610ba4dfef1SStephen Warren 1611ba4dfef1SStephen Warren debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags); 1612ba4dfef1SStephen Warren 1613ba4dfef1SStephen Warren rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); 1614865fce80SMarek Vasut eqos->config->ops->eqos_inval_desc(rx_desc); 1615ba4dfef1SStephen Warren if (rx_desc->des3 & EQOS_DESC3_OWN) { 1616ba4dfef1SStephen Warren debug("%s: RX packet not available\n", __func__); 1617ba4dfef1SStephen Warren return -EAGAIN; 1618ba4dfef1SStephen Warren } 1619ba4dfef1SStephen Warren 1620ba4dfef1SStephen Warren *packetp = eqos->rx_dma_buf + 1621ba4dfef1SStephen Warren (eqos->rx_desc_idx * EQOS_MAX_PACKET_SIZE); 1622ba4dfef1SStephen Warren length = rx_desc->des3 & 0x7fff; 1623ba4dfef1SStephen Warren debug("%s: *packetp=%p, length=%d\n", __func__, *packetp, length); 1624ba4dfef1SStephen Warren 16257a4c4eddSChristophe Roullier eqos->config->ops->eqos_inval_buffer(*packetp, length); 1626ba4dfef1SStephen Warren 1627ba4dfef1SStephen Warren return length; 1628ba4dfef1SStephen Warren } 1629ba4dfef1SStephen Warren 16308aaada72SPatrick Delaunay static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) 1631ba4dfef1SStephen Warren { 1632ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1633ba4dfef1SStephen Warren uchar *packet_expected; 1634ba4dfef1SStephen Warren struct eqos_desc *rx_desc; 1635ba4dfef1SStephen Warren 1636ba4dfef1SStephen Warren debug("%s(packet=%p, length=%d)\n", __func__, packet, length); 1637ba4dfef1SStephen Warren 1638ba4dfef1SStephen Warren packet_expected = eqos->rx_dma_buf + 1639ba4dfef1SStephen Warren (eqos->rx_desc_idx * EQOS_MAX_PACKET_SIZE); 1640ba4dfef1SStephen Warren if (packet != packet_expected) { 1641ba4dfef1SStephen Warren debug("%s: Unexpected packet (expected %p)\n", __func__, 1642ba4dfef1SStephen Warren packet_expected); 1643ba4dfef1SStephen Warren return -EINVAL; 1644ba4dfef1SStephen Warren } 1645ba4dfef1SStephen Warren 1646a7b3400fSFugang Duan eqos->config->ops->eqos_inval_buffer(packet, length); 1647a7b3400fSFugang Duan 1648ba4dfef1SStephen Warren rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); 1649076e66fbSMarek Vasut 165007314278SMarek Vasut rx_desc->des0 = 0; 165107314278SMarek Vasut mb(); 165207314278SMarek Vasut eqos->config->ops->eqos_flush_desc(rx_desc); 1653076e66fbSMarek Vasut eqos->config->ops->eqos_inval_buffer(packet, length); 1654ba4dfef1SStephen Warren rx_desc->des0 = (u32)(ulong)packet; 1655ba4dfef1SStephen Warren rx_desc->des1 = 0; 1656ba4dfef1SStephen Warren rx_desc->des2 = 0; 1657ba4dfef1SStephen Warren /* 1658ba4dfef1SStephen Warren * Make sure that if HW sees the _OWN write below, it will see all the 1659ba4dfef1SStephen Warren * writes to the rest of the descriptor too. 1660ba4dfef1SStephen Warren */ 1661ba4dfef1SStephen Warren mb(); 16626143c348SMarek Vasut rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; 16637a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_desc(rx_desc); 1664ba4dfef1SStephen Warren 1665ba4dfef1SStephen Warren writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); 1666ba4dfef1SStephen Warren 1667ba4dfef1SStephen Warren eqos->rx_desc_idx++; 1668ba4dfef1SStephen Warren eqos->rx_desc_idx %= EQOS_DESCRIPTORS_RX; 1669ba4dfef1SStephen Warren 1670ba4dfef1SStephen Warren return 0; 1671ba4dfef1SStephen Warren } 1672ba4dfef1SStephen Warren 1673ba4dfef1SStephen Warren static int eqos_probe_resources_core(struct udevice *dev) 1674ba4dfef1SStephen Warren { 1675ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1676ba4dfef1SStephen Warren int ret; 1677ba4dfef1SStephen Warren 1678ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1679ba4dfef1SStephen Warren 1680ba4dfef1SStephen Warren eqos->descs = eqos_alloc_descs(EQOS_DESCRIPTORS_TX + 1681ba4dfef1SStephen Warren EQOS_DESCRIPTORS_RX); 1682ba4dfef1SStephen Warren if (!eqos->descs) { 1683ba4dfef1SStephen Warren debug("%s: eqos_alloc_descs() failed\n", __func__); 1684ba4dfef1SStephen Warren ret = -ENOMEM; 1685ba4dfef1SStephen Warren goto err; 1686ba4dfef1SStephen Warren } 1687ba4dfef1SStephen Warren eqos->tx_descs = (struct eqos_desc *)eqos->descs; 1688ba4dfef1SStephen Warren eqos->rx_descs = (eqos->tx_descs + EQOS_DESCRIPTORS_TX); 1689ba4dfef1SStephen Warren debug("%s: tx_descs=%p, rx_descs=%p\n", __func__, eqos->tx_descs, 1690ba4dfef1SStephen Warren eqos->rx_descs); 1691ba4dfef1SStephen Warren 1692ba4dfef1SStephen Warren eqos->tx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_MAX_PACKET_SIZE); 1693ba4dfef1SStephen Warren if (!eqos->tx_dma_buf) { 1694ba4dfef1SStephen Warren debug("%s: memalign(tx_dma_buf) failed\n", __func__); 1695ba4dfef1SStephen Warren ret = -ENOMEM; 1696ba4dfef1SStephen Warren goto err_free_descs; 1697ba4dfef1SStephen Warren } 16987a4c4eddSChristophe Roullier debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf); 1699ba4dfef1SStephen Warren 1700ba4dfef1SStephen Warren eqos->rx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_RX_BUFFER_SIZE); 1701ba4dfef1SStephen Warren if (!eqos->rx_dma_buf) { 1702ba4dfef1SStephen Warren debug("%s: memalign(rx_dma_buf) failed\n", __func__); 1703ba4dfef1SStephen Warren ret = -ENOMEM; 1704ba4dfef1SStephen Warren goto err_free_tx_dma_buf; 1705ba4dfef1SStephen Warren } 17067a4c4eddSChristophe Roullier debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf); 1707ba4dfef1SStephen Warren 1708ba4dfef1SStephen Warren eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE); 1709ba4dfef1SStephen Warren if (!eqos->rx_pkt) { 1710ba4dfef1SStephen Warren debug("%s: malloc(rx_pkt) failed\n", __func__); 1711ba4dfef1SStephen Warren ret = -ENOMEM; 1712ba4dfef1SStephen Warren goto err_free_rx_dma_buf; 1713ba4dfef1SStephen Warren } 1714ba4dfef1SStephen Warren debug("%s: rx_pkt=%p\n", __func__, eqos->rx_pkt); 1715ba4dfef1SStephen Warren 1716076e66fbSMarek Vasut eqos->config->ops->eqos_inval_buffer(eqos->rx_dma_buf, 1717076e66fbSMarek Vasut EQOS_MAX_PACKET_SIZE * EQOS_DESCRIPTORS_RX); 1718076e66fbSMarek Vasut 1719ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1720ba4dfef1SStephen Warren return 0; 1721ba4dfef1SStephen Warren 1722ba4dfef1SStephen Warren err_free_rx_dma_buf: 1723ba4dfef1SStephen Warren free(eqos->rx_dma_buf); 1724ba4dfef1SStephen Warren err_free_tx_dma_buf: 1725ba4dfef1SStephen Warren free(eqos->tx_dma_buf); 1726ba4dfef1SStephen Warren err_free_descs: 1727ba4dfef1SStephen Warren eqos_free_descs(eqos->descs); 1728ba4dfef1SStephen Warren err: 1729ba4dfef1SStephen Warren 1730ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 1731ba4dfef1SStephen Warren return ret; 1732ba4dfef1SStephen Warren } 1733ba4dfef1SStephen Warren 1734ba4dfef1SStephen Warren static int eqos_remove_resources_core(struct udevice *dev) 1735ba4dfef1SStephen Warren { 1736ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1737ba4dfef1SStephen Warren 1738ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1739ba4dfef1SStephen Warren 1740ba4dfef1SStephen Warren free(eqos->rx_pkt); 1741ba4dfef1SStephen Warren free(eqos->rx_dma_buf); 1742ba4dfef1SStephen Warren free(eqos->tx_dma_buf); 1743ba4dfef1SStephen Warren eqos_free_descs(eqos->descs); 1744ba4dfef1SStephen Warren 1745ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1746ba4dfef1SStephen Warren return 0; 1747ba4dfef1SStephen Warren } 1748ba4dfef1SStephen Warren 1749ba4dfef1SStephen Warren static int eqos_probe_resources_tegra186(struct udevice *dev) 1750ba4dfef1SStephen Warren { 1751ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1752ba4dfef1SStephen Warren int ret; 1753ba4dfef1SStephen Warren 1754ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1755ba4dfef1SStephen Warren 1756ba4dfef1SStephen Warren ret = reset_get_by_name(dev, "eqos", &eqos->reset_ctl); 1757ba4dfef1SStephen Warren if (ret) { 175890aa625cSMasahiro Yamada pr_err("reset_get_by_name(rst) failed: %d", ret); 1759ba4dfef1SStephen Warren return ret; 1760ba4dfef1SStephen Warren } 1761ba4dfef1SStephen Warren 1762ba4dfef1SStephen Warren ret = gpio_request_by_name(dev, "phy-reset-gpios", 0, 1763ba4dfef1SStephen Warren &eqos->phy_reset_gpio, 1764ba4dfef1SStephen Warren GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); 1765ba4dfef1SStephen Warren if (ret) { 176690aa625cSMasahiro Yamada pr_err("gpio_request_by_name(phy reset) failed: %d", ret); 1767ba4dfef1SStephen Warren goto err_free_reset_eqos; 1768ba4dfef1SStephen Warren } 1769ba4dfef1SStephen Warren 1770ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "slave_bus", &eqos->clk_slave_bus); 1771ba4dfef1SStephen Warren if (ret) { 177290aa625cSMasahiro Yamada pr_err("clk_get_by_name(slave_bus) failed: %d", ret); 1773ba4dfef1SStephen Warren goto err_free_gpio_phy_reset; 1774ba4dfef1SStephen Warren } 1775ba4dfef1SStephen Warren 1776ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "master_bus", &eqos->clk_master_bus); 1777ba4dfef1SStephen Warren if (ret) { 177890aa625cSMasahiro Yamada pr_err("clk_get_by_name(master_bus) failed: %d", ret); 1779ba4dfef1SStephen Warren goto err_free_clk_slave_bus; 1780ba4dfef1SStephen Warren } 1781ba4dfef1SStephen Warren 1782ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "rx", &eqos->clk_rx); 1783ba4dfef1SStephen Warren if (ret) { 178490aa625cSMasahiro Yamada pr_err("clk_get_by_name(rx) failed: %d", ret); 1785ba4dfef1SStephen Warren goto err_free_clk_master_bus; 1786ba4dfef1SStephen Warren } 1787ba4dfef1SStephen Warren 1788ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "ptp_ref", &eqos->clk_ptp_ref); 1789ba4dfef1SStephen Warren if (ret) { 179090aa625cSMasahiro Yamada pr_err("clk_get_by_name(ptp_ref) failed: %d", ret); 1791ba4dfef1SStephen Warren goto err_free_clk_rx; 1792ba4dfef1SStephen Warren return ret; 1793ba4dfef1SStephen Warren } 1794ba4dfef1SStephen Warren 1795ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "tx", &eqos->clk_tx); 1796ba4dfef1SStephen Warren if (ret) { 179790aa625cSMasahiro Yamada pr_err("clk_get_by_name(tx) failed: %d", ret); 1798ba4dfef1SStephen Warren goto err_free_clk_ptp_ref; 1799ba4dfef1SStephen Warren } 1800ba4dfef1SStephen Warren 1801ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1802ba4dfef1SStephen Warren return 0; 1803ba4dfef1SStephen Warren 1804ba4dfef1SStephen Warren err_free_clk_ptp_ref: 1805ba4dfef1SStephen Warren clk_free(&eqos->clk_ptp_ref); 1806ba4dfef1SStephen Warren err_free_clk_rx: 1807ba4dfef1SStephen Warren clk_free(&eqos->clk_rx); 1808ba4dfef1SStephen Warren err_free_clk_master_bus: 1809ba4dfef1SStephen Warren clk_free(&eqos->clk_master_bus); 1810ba4dfef1SStephen Warren err_free_clk_slave_bus: 1811ba4dfef1SStephen Warren clk_free(&eqos->clk_slave_bus); 1812ba4dfef1SStephen Warren err_free_gpio_phy_reset: 1813ba4dfef1SStephen Warren dm_gpio_free(dev, &eqos->phy_reset_gpio); 1814ba4dfef1SStephen Warren err_free_reset_eqos: 1815ba4dfef1SStephen Warren reset_free(&eqos->reset_ctl); 1816ba4dfef1SStephen Warren 1817ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 1818ba4dfef1SStephen Warren return ret; 1819ba4dfef1SStephen Warren } 1820ba4dfef1SStephen Warren 18217a4c4eddSChristophe Roullier /* board-specific Ethernet Interface initializations. */ 18221e8d5d80SPatrick Delaunay __weak int board_interface_eth_init(struct udevice *dev, 18231e8d5d80SPatrick Delaunay phy_interface_t interface_type) 18247a4c4eddSChristophe Roullier { 18257a4c4eddSChristophe Roullier return 0; 18267a4c4eddSChristophe Roullier } 18277a4c4eddSChristophe Roullier 18287a4c4eddSChristophe Roullier static int eqos_probe_resources_stm32(struct udevice *dev) 18297a4c4eddSChristophe Roullier { 18307a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 18317a4c4eddSChristophe Roullier int ret; 18327a4c4eddSChristophe Roullier phy_interface_t interface; 18335bd3c538SChristophe Roullier struct ofnode_phandle_args phandle_args; 18347a4c4eddSChristophe Roullier 18357a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 18367a4c4eddSChristophe Roullier 1837bbbbc81cSDavid Wu interface = eqos->config->ops->eqos_get_interface(dev); 18387a4c4eddSChristophe Roullier 18397a4c4eddSChristophe Roullier if (interface == PHY_INTERFACE_MODE_NONE) { 18407a4c4eddSChristophe Roullier pr_err("Invalid PHY interface\n"); 18417a4c4eddSChristophe Roullier return -EINVAL; 18427a4c4eddSChristophe Roullier } 18437a4c4eddSChristophe Roullier 18441e8d5d80SPatrick Delaunay ret = board_interface_eth_init(dev, interface); 18457a4c4eddSChristophe Roullier if (ret) 18467a4c4eddSChristophe Roullier return -EINVAL; 18477a4c4eddSChristophe Roullier 184883d31c08SPatrick Delaunay eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0); 184983d31c08SPatrick Delaunay 18507a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); 18517a4c4eddSChristophe Roullier if (ret) { 18527a4c4eddSChristophe Roullier pr_err("clk_get_by_name(master_bus) failed: %d", ret); 1853*b29cefabSDavid Wu return ret; 18547a4c4eddSChristophe Roullier } 18557a4c4eddSChristophe Roullier 18567a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); 1857*b29cefabSDavid Wu if (ret) 1858*b29cefabSDavid Wu pr_warn("clk_get_by_name(rx) failed: %d", ret); 18597a4c4eddSChristophe Roullier 18607a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); 1861*b29cefabSDavid Wu if (ret) 1862*b29cefabSDavid Wu pr_warn("clk_get_by_name(tx) failed: %d", ret); 18637a4c4eddSChristophe Roullier 18647a4c4eddSChristophe Roullier /* Get ETH_CLK clocks (optional) */ 18657a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck); 18667a4c4eddSChristophe Roullier if (ret) 18677a4c4eddSChristophe Roullier pr_warn("No phy clock provided %d", ret); 18687a4c4eddSChristophe Roullier 186983d31c08SPatrick Delaunay eqos->phyaddr = -1; 18705bd3c538SChristophe Roullier ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, 18715bd3c538SChristophe Roullier &phandle_args); 18725bd3c538SChristophe Roullier if (!ret) { 18735bd3c538SChristophe Roullier /* search "reset-gpios" in phy node */ 18745bd3c538SChristophe Roullier ret = gpio_request_by_name_nodev(phandle_args.node, 18755bd3c538SChristophe Roullier "reset-gpios", 0, 18765bd3c538SChristophe Roullier &eqos->phy_reset_gpio, 18775bd3c538SChristophe Roullier GPIOD_IS_OUT | 18785bd3c538SChristophe Roullier GPIOD_IS_OUT_ACTIVE); 18795bd3c538SChristophe Roullier if (ret) 18805bd3c538SChristophe Roullier pr_warn("gpio_request_by_name(phy reset) not provided %d", 18815bd3c538SChristophe Roullier ret); 188213105a0bSDavid Wu else 188313105a0bSDavid Wu eqos->reset_delays[1] = 2; 188483d31c08SPatrick Delaunay 188583d31c08SPatrick Delaunay eqos->phyaddr = ofnode_read_u32_default(phandle_args.node, 188683d31c08SPatrick Delaunay "reg", -1); 18875bd3c538SChristophe Roullier } 18885bd3c538SChristophe Roullier 188913105a0bSDavid Wu if (!dm_gpio_is_valid(&eqos->phy_reset_gpio)) { 189013105a0bSDavid Wu int reset_flags = GPIOD_IS_OUT; 189113105a0bSDavid Wu 189213105a0bSDavid Wu if (dev_read_bool(dev, "snps,reset-active-low")) 189313105a0bSDavid Wu reset_flags |= GPIOD_ACTIVE_LOW; 189413105a0bSDavid Wu 189513105a0bSDavid Wu ret = gpio_request_by_name(dev, "snps,reset-gpio", 0, 189613105a0bSDavid Wu &eqos->phy_reset_gpio, reset_flags); 189713105a0bSDavid Wu if (ret == 0) 189813105a0bSDavid Wu ret = dev_read_u32_array(dev, "snps,reset-delays-us", 189913105a0bSDavid Wu eqos->reset_delays, 3); 190013105a0bSDavid Wu else 190113105a0bSDavid Wu pr_warn("gpio_request_by_name(snps,reset-gpio) failed: %d", 190213105a0bSDavid Wu ret); 190313105a0bSDavid Wu } 190413105a0bSDavid Wu 19057a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 19067a4c4eddSChristophe Roullier return 0; 19077a4c4eddSChristophe Roullier } 19087a4c4eddSChristophe Roullier 19097a4c4eddSChristophe Roullier static phy_interface_t eqos_get_interface_stm32(struct udevice *dev) 19107a4c4eddSChristophe Roullier { 19117a4c4eddSChristophe Roullier const char *phy_mode; 19127a4c4eddSChristophe Roullier phy_interface_t interface = PHY_INTERFACE_MODE_NONE; 19137a4c4eddSChristophe Roullier 19147a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 19157a4c4eddSChristophe Roullier 1916dcf8de12SDavid Wu phy_mode = dev_read_string(dev, "phy-mode"); 19177a4c4eddSChristophe Roullier if (phy_mode) 19187a4c4eddSChristophe Roullier interface = phy_get_interface_by_name(phy_mode); 19197a4c4eddSChristophe Roullier 19207a4c4eddSChristophe Roullier return interface; 19217a4c4eddSChristophe Roullier } 19227a4c4eddSChristophe Roullier 19237a4c4eddSChristophe Roullier static phy_interface_t eqos_get_interface_tegra186(struct udevice *dev) 19247a4c4eddSChristophe Roullier { 19257a4c4eddSChristophe Roullier return PHY_INTERFACE_MODE_MII; 19267a4c4eddSChristophe Roullier } 19277a4c4eddSChristophe Roullier 1928a7b3400fSFugang Duan static int eqos_probe_resources_imx(struct udevice *dev) 1929a7b3400fSFugang Duan { 1930a7b3400fSFugang Duan struct eqos_priv *eqos = dev_get_priv(dev); 1931a7b3400fSFugang Duan phy_interface_t interface; 1932a7b3400fSFugang Duan 1933a7b3400fSFugang Duan debug("%s(dev=%p):\n", __func__, dev); 1934a7b3400fSFugang Duan 1935bbbbc81cSDavid Wu interface = eqos->config->ops->eqos_get_interface(dev); 1936a7b3400fSFugang Duan 1937a7b3400fSFugang Duan if (interface == PHY_INTERFACE_MODE_NONE) { 1938a7b3400fSFugang Duan pr_err("Invalid PHY interface\n"); 1939a7b3400fSFugang Duan return -EINVAL; 1940a7b3400fSFugang Duan } 1941a7b3400fSFugang Duan 1942a7b3400fSFugang Duan debug("%s: OK\n", __func__); 1943a7b3400fSFugang Duan return 0; 1944a7b3400fSFugang Duan } 1945a7b3400fSFugang Duan 1946a7b3400fSFugang Duan static phy_interface_t eqos_get_interface_imx(struct udevice *dev) 1947a7b3400fSFugang Duan { 1948ad018a0cSFugang Duan const char *phy_mode; 1949ad018a0cSFugang Duan phy_interface_t interface = PHY_INTERFACE_MODE_NONE; 1950ad018a0cSFugang Duan 1951ad018a0cSFugang Duan debug("%s(dev=%p):\n", __func__, dev); 1952ad018a0cSFugang Duan 1953ad018a0cSFugang Duan phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", 1954ad018a0cSFugang Duan NULL); 1955ad018a0cSFugang Duan if (phy_mode) 1956ad018a0cSFugang Duan interface = phy_get_interface_by_name(phy_mode); 1957ad018a0cSFugang Duan 1958ad018a0cSFugang Duan return interface; 1959a7b3400fSFugang Duan } 1960a7b3400fSFugang Duan 1961ba4dfef1SStephen Warren static int eqos_remove_resources_tegra186(struct udevice *dev) 1962ba4dfef1SStephen Warren { 1963ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1964ba4dfef1SStephen Warren 1965ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1966ba4dfef1SStephen Warren 1967a7b3400fSFugang Duan #ifdef CONFIG_CLK 1968ba4dfef1SStephen Warren clk_free(&eqos->clk_tx); 1969ba4dfef1SStephen Warren clk_free(&eqos->clk_ptp_ref); 1970ba4dfef1SStephen Warren clk_free(&eqos->clk_rx); 1971ba4dfef1SStephen Warren clk_free(&eqos->clk_slave_bus); 1972ba4dfef1SStephen Warren clk_free(&eqos->clk_master_bus); 1973a7b3400fSFugang Duan #endif 1974ba4dfef1SStephen Warren dm_gpio_free(dev, &eqos->phy_reset_gpio); 1975ba4dfef1SStephen Warren reset_free(&eqos->reset_ctl); 1976ba4dfef1SStephen Warren 1977ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1978ba4dfef1SStephen Warren return 0; 1979ba4dfef1SStephen Warren } 1980ba4dfef1SStephen Warren 19817a4c4eddSChristophe Roullier static int eqos_remove_resources_stm32(struct udevice *dev) 19827a4c4eddSChristophe Roullier { 1983a7b3400fSFugang Duan #ifdef CONFIG_CLK 19847a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 19857a4c4eddSChristophe Roullier 19867a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 19877a4c4eddSChristophe Roullier 1988*b29cefabSDavid Wu if (clk_valid(&eqos->clk_tx)) 19897a4c4eddSChristophe Roullier clk_free(&eqos->clk_tx); 1990*b29cefabSDavid Wu if (clk_valid(&eqos->clk_rx)) 19917a4c4eddSChristophe Roullier clk_free(&eqos->clk_rx); 19927a4c4eddSChristophe Roullier clk_free(&eqos->clk_master_bus); 19937a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) 19947a4c4eddSChristophe Roullier clk_free(&eqos->clk_ck); 1995a7b3400fSFugang Duan #endif 19967a4c4eddSChristophe Roullier 19975bd3c538SChristophe Roullier if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) 19985bd3c538SChristophe Roullier dm_gpio_free(dev, &eqos->phy_reset_gpio); 19995bd3c538SChristophe Roullier 20007a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 20017a4c4eddSChristophe Roullier return 0; 20027a4c4eddSChristophe Roullier } 20037a4c4eddSChristophe Roullier 2004a7b3400fSFugang Duan static int eqos_remove_resources_imx(struct udevice *dev) 2005a7b3400fSFugang Duan { 2006a7b3400fSFugang Duan return 0; 2007a7b3400fSFugang Duan } 2008a7b3400fSFugang Duan 2009ba4dfef1SStephen Warren static int eqos_probe(struct udevice *dev) 2010ba4dfef1SStephen Warren { 2011ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 2012ba4dfef1SStephen Warren int ret; 2013ba4dfef1SStephen Warren 2014ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 2015ba4dfef1SStephen Warren 2016ba4dfef1SStephen Warren eqos->dev = dev; 2017ba4dfef1SStephen Warren eqos->config = (void *)dev_get_driver_data(dev); 2018ba4dfef1SStephen Warren 2019dcf8de12SDavid Wu eqos->regs = dev_read_addr(dev); 2020ba4dfef1SStephen Warren if (eqos->regs == FDT_ADDR_T_NONE) { 2021dcf8de12SDavid Wu pr_err("dev_read_addr() failed"); 2022ba4dfef1SStephen Warren return -ENODEV; 2023ba4dfef1SStephen Warren } 2024ba4dfef1SStephen Warren eqos->mac_regs = (void *)(eqos->regs + EQOS_MAC_REGS_BASE); 2025ba4dfef1SStephen Warren eqos->mtl_regs = (void *)(eqos->regs + EQOS_MTL_REGS_BASE); 2026ba4dfef1SStephen Warren eqos->dma_regs = (void *)(eqos->regs + EQOS_DMA_REGS_BASE); 2027ba4dfef1SStephen Warren eqos->tegra186_regs = (void *)(eqos->regs + EQOS_TEGRA186_REGS_BASE); 2028ba4dfef1SStephen Warren 2029ba4dfef1SStephen Warren ret = eqos_probe_resources_core(dev); 2030ba4dfef1SStephen Warren if (ret < 0) { 203190aa625cSMasahiro Yamada pr_err("eqos_probe_resources_core() failed: %d", ret); 2032ba4dfef1SStephen Warren return ret; 2033ba4dfef1SStephen Warren } 2034ba4dfef1SStephen Warren 20357a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_probe_resources(dev); 2036ba4dfef1SStephen Warren if (ret < 0) { 20377a4c4eddSChristophe Roullier pr_err("eqos_probe_resources() failed: %d", ret); 2038ba4dfef1SStephen Warren goto err_remove_resources_core; 2039ba4dfef1SStephen Warren } 2040ba4dfef1SStephen Warren 20418e3eceb0SYe Li #ifdef CONFIG_DM_ETH_PHY 20428e3eceb0SYe Li eqos->mii = eth_phy_get_mdio_bus(dev); 20438e3eceb0SYe Li #endif 20448e3eceb0SYe Li if (!eqos->mii) { 2045ba4dfef1SStephen Warren eqos->mii = mdio_alloc(); 2046ba4dfef1SStephen Warren if (!eqos->mii) { 204790aa625cSMasahiro Yamada pr_err("mdio_alloc() failed"); 20487a4c4eddSChristophe Roullier ret = -ENOMEM; 2049ba4dfef1SStephen Warren goto err_remove_resources_tegra; 2050ba4dfef1SStephen Warren } 2051ba4dfef1SStephen Warren eqos->mii->read = eqos_mdio_read; 2052ba4dfef1SStephen Warren eqos->mii->write = eqos_mdio_write; 2053ba4dfef1SStephen Warren eqos->mii->priv = eqos; 2054ba4dfef1SStephen Warren strcpy(eqos->mii->name, dev->name); 2055ba4dfef1SStephen Warren 2056ba4dfef1SStephen Warren ret = mdio_register(eqos->mii); 2057ba4dfef1SStephen Warren if (ret < 0) { 205890aa625cSMasahiro Yamada pr_err("mdio_register() failed: %d", ret); 2059ba4dfef1SStephen Warren goto err_free_mdio; 2060ba4dfef1SStephen Warren } 20618e3eceb0SYe Li } 20628e3eceb0SYe Li 20638e3eceb0SYe Li #ifdef CONFIG_DM_ETH_PHY 20648e3eceb0SYe Li eth_phy_set_mdio_bus(dev, eqos->mii); 20658e3eceb0SYe Li #endif 2066ba4dfef1SStephen Warren 2067ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 2068ba4dfef1SStephen Warren return 0; 2069ba4dfef1SStephen Warren 2070ba4dfef1SStephen Warren err_free_mdio: 2071ba4dfef1SStephen Warren mdio_free(eqos->mii); 2072ba4dfef1SStephen Warren err_remove_resources_tegra: 20737a4c4eddSChristophe Roullier eqos->config->ops->eqos_remove_resources(dev); 2074ba4dfef1SStephen Warren err_remove_resources_core: 2075ba4dfef1SStephen Warren eqos_remove_resources_core(dev); 2076ba4dfef1SStephen Warren 2077ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 2078ba4dfef1SStephen Warren return ret; 2079ba4dfef1SStephen Warren } 2080ba4dfef1SStephen Warren 2081ba4dfef1SStephen Warren static int eqos_remove(struct udevice *dev) 2082ba4dfef1SStephen Warren { 2083ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 2084ba4dfef1SStephen Warren 2085ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 2086ba4dfef1SStephen Warren 2087ba4dfef1SStephen Warren mdio_unregister(eqos->mii); 2088ba4dfef1SStephen Warren mdio_free(eqos->mii); 20897a4c4eddSChristophe Roullier eqos->config->ops->eqos_remove_resources(dev); 20907a4c4eddSChristophe Roullier 2091ba4dfef1SStephen Warren eqos_probe_resources_core(dev); 2092ba4dfef1SStephen Warren 2093ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 2094ba4dfef1SStephen Warren return 0; 2095ba4dfef1SStephen Warren } 2096ba4dfef1SStephen Warren 2097ba4dfef1SStephen Warren static const struct eth_ops eqos_ops = { 2098ba4dfef1SStephen Warren .start = eqos_start, 2099ba4dfef1SStephen Warren .stop = eqos_stop, 2100ba4dfef1SStephen Warren .send = eqos_send, 2101ba4dfef1SStephen Warren .recv = eqos_recv, 2102ba4dfef1SStephen Warren .free_pkt = eqos_free_pkt, 2103ba4dfef1SStephen Warren .write_hwaddr = eqos_write_hwaddr, 21044d0fb6f0SYe Li .read_rom_hwaddr = eqos_read_rom_hwaddr, 2105ba4dfef1SStephen Warren }; 2106ba4dfef1SStephen Warren 21077a4c4eddSChristophe Roullier static struct eqos_ops eqos_tegra186_ops = { 21087a4c4eddSChristophe Roullier .eqos_inval_desc = eqos_inval_desc_tegra186, 21097a4c4eddSChristophe Roullier .eqos_flush_desc = eqos_flush_desc_tegra186, 21107a4c4eddSChristophe Roullier .eqos_inval_buffer = eqos_inval_buffer_tegra186, 21117a4c4eddSChristophe Roullier .eqos_flush_buffer = eqos_flush_buffer_tegra186, 21127a4c4eddSChristophe Roullier .eqos_probe_resources = eqos_probe_resources_tegra186, 21137a4c4eddSChristophe Roullier .eqos_remove_resources = eqos_remove_resources_tegra186, 21147a4c4eddSChristophe Roullier .eqos_stop_resets = eqos_stop_resets_tegra186, 21157a4c4eddSChristophe Roullier .eqos_start_resets = eqos_start_resets_tegra186, 21167a4c4eddSChristophe Roullier .eqos_stop_clks = eqos_stop_clks_tegra186, 21177a4c4eddSChristophe Roullier .eqos_start_clks = eqos_start_clks_tegra186, 21187a4c4eddSChristophe Roullier .eqos_calibrate_pads = eqos_calibrate_pads_tegra186, 21197a4c4eddSChristophe Roullier .eqos_disable_calibration = eqos_disable_calibration_tegra186, 21207a4c4eddSChristophe Roullier .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186, 2121bbbbc81cSDavid Wu .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186, 2122bbbbc81cSDavid Wu .eqos_get_interface = eqos_get_interface_tegra186 21237a4c4eddSChristophe Roullier }; 21247a4c4eddSChristophe Roullier 2125ba4dfef1SStephen Warren static const struct eqos_config eqos_tegra186_config = { 2126ba4dfef1SStephen Warren .reg_access_always_ok = false, 21277a4c4eddSChristophe Roullier .mdio_wait = 10, 21287a4c4eddSChristophe Roullier .swr_wait = 10, 21297a4c4eddSChristophe Roullier .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, 21307a4c4eddSChristophe Roullier .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35, 21317a4c4eddSChristophe Roullier .ops = &eqos_tegra186_ops 21327a4c4eddSChristophe Roullier }; 21337a4c4eddSChristophe Roullier 21347a4c4eddSChristophe Roullier static struct eqos_ops eqos_stm32_ops = { 2135a7b3400fSFugang Duan .eqos_inval_desc = eqos_inval_desc_generic, 2136a7b3400fSFugang Duan .eqos_flush_desc = eqos_flush_desc_generic, 2137a7b3400fSFugang Duan .eqos_inval_buffer = eqos_inval_buffer_generic, 2138a7b3400fSFugang Duan .eqos_flush_buffer = eqos_flush_buffer_generic, 21397a4c4eddSChristophe Roullier .eqos_probe_resources = eqos_probe_resources_stm32, 21407a4c4eddSChristophe Roullier .eqos_remove_resources = eqos_remove_resources_stm32, 21417a4c4eddSChristophe Roullier .eqos_stop_resets = eqos_stop_resets_stm32, 21427a4c4eddSChristophe Roullier .eqos_start_resets = eqos_start_resets_stm32, 21437a4c4eddSChristophe Roullier .eqos_stop_clks = eqos_stop_clks_stm32, 21447a4c4eddSChristophe Roullier .eqos_start_clks = eqos_start_clks_stm32, 21457a4c4eddSChristophe Roullier .eqos_calibrate_pads = eqos_calibrate_pads_stm32, 21467a4c4eddSChristophe Roullier .eqos_disable_calibration = eqos_disable_calibration_stm32, 21477a4c4eddSChristophe Roullier .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_stm32, 2148bbbbc81cSDavid Wu .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32, 2149bbbbc81cSDavid Wu .eqos_get_interface = eqos_get_interface_stm32 21507a4c4eddSChristophe Roullier }; 21517a4c4eddSChristophe Roullier 21527a4c4eddSChristophe Roullier static const struct eqos_config eqos_stm32_config = { 21537a4c4eddSChristophe Roullier .reg_access_always_ok = false, 21547a4c4eddSChristophe Roullier .mdio_wait = 10000, 21557a4c4eddSChristophe Roullier .swr_wait = 50, 21567a4c4eddSChristophe Roullier .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, 21577a4c4eddSChristophe Roullier .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, 21587a4c4eddSChristophe Roullier .ops = &eqos_stm32_ops 2159ba4dfef1SStephen Warren }; 2160ba4dfef1SStephen Warren 2161a7b3400fSFugang Duan static struct eqos_ops eqos_imx_ops = { 2162a7b3400fSFugang Duan .eqos_inval_desc = eqos_inval_desc_generic, 2163a7b3400fSFugang Duan .eqos_flush_desc = eqos_flush_desc_generic, 2164a7b3400fSFugang Duan .eqos_inval_buffer = eqos_inval_buffer_generic, 2165a7b3400fSFugang Duan .eqos_flush_buffer = eqos_flush_buffer_generic, 2166a7b3400fSFugang Duan .eqos_probe_resources = eqos_probe_resources_imx, 2167a7b3400fSFugang Duan .eqos_remove_resources = eqos_remove_resources_imx, 2168a7b3400fSFugang Duan .eqos_stop_resets = eqos_stop_resets_imx, 2169a7b3400fSFugang Duan .eqos_start_resets = eqos_start_resets_imx, 2170a7b3400fSFugang Duan .eqos_stop_clks = eqos_stop_clks_imx, 2171a7b3400fSFugang Duan .eqos_start_clks = eqos_start_clks_imx, 2172a7b3400fSFugang Duan .eqos_calibrate_pads = eqos_calibrate_pads_imx, 2173a7b3400fSFugang Duan .eqos_disable_calibration = eqos_disable_calibration_imx, 2174a7b3400fSFugang Duan .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_imx, 2175bbbbc81cSDavid Wu .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_imx, 2176bbbbc81cSDavid Wu .eqos_get_interface = eqos_get_interface_imx 2177a7b3400fSFugang Duan }; 2178a7b3400fSFugang Duan 2179a7b3400fSFugang Duan struct eqos_config eqos_imx_config = { 2180a7b3400fSFugang Duan .reg_access_always_ok = false, 2181a7b3400fSFugang Duan .mdio_wait = 10000, 2182a7b3400fSFugang Duan .swr_wait = 50, 2183a7b3400fSFugang Duan .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, 2184a7b3400fSFugang Duan .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, 2185a7b3400fSFugang Duan .ops = &eqos_imx_ops 2186a7b3400fSFugang Duan }; 2187a7b3400fSFugang Duan 2188ba4dfef1SStephen Warren static const struct udevice_id eqos_ids[] = { 2189ba4dfef1SStephen Warren { 2190ba4dfef1SStephen Warren .compatible = "nvidia,tegra186-eqos", 2191ba4dfef1SStephen Warren .data = (ulong)&eqos_tegra186_config 2192ba4dfef1SStephen Warren }, 21937a4c4eddSChristophe Roullier { 21947a4c4eddSChristophe Roullier .compatible = "snps,dwmac-4.20a", 21957a4c4eddSChristophe Roullier .data = (ulong)&eqos_stm32_config 21967a4c4eddSChristophe Roullier }, 2197a7b3400fSFugang Duan { 2198a7b3400fSFugang Duan .compatible = "fsl,imx-eqos", 2199a7b3400fSFugang Duan .data = (ulong)&eqos_imx_config 2200a7b3400fSFugang Duan }, 22017a4c4eddSChristophe Roullier 2202ba4dfef1SStephen Warren { } 2203ba4dfef1SStephen Warren }; 2204ba4dfef1SStephen Warren 2205ba4dfef1SStephen Warren U_BOOT_DRIVER(eth_eqos) = { 2206ba4dfef1SStephen Warren .name = "eth_eqos", 2207ba4dfef1SStephen Warren .id = UCLASS_ETH, 2208a7b3400fSFugang Duan .of_match = of_match_ptr(eqos_ids), 2209ba4dfef1SStephen Warren .probe = eqos_probe, 2210ba4dfef1SStephen Warren .remove = eqos_remove, 2211ba4dfef1SStephen Warren .ops = &eqos_ops, 2212ba4dfef1SStephen Warren .priv_auto_alloc_size = sizeof(struct eqos_priv), 2213ba4dfef1SStephen Warren .platdata_auto_alloc_size = sizeof(struct eth_pdata), 2214ba4dfef1SStephen Warren }; 2215