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 phy_interface_t (*interface)(struct udevice *dev); 2867a4c4eddSChristophe Roullier struct eqos_ops *ops; 2877a4c4eddSChristophe Roullier }; 2887a4c4eddSChristophe Roullier 2897a4c4eddSChristophe Roullier struct eqos_ops { 2907a4c4eddSChristophe Roullier void (*eqos_inval_desc)(void *desc); 2917a4c4eddSChristophe Roullier void (*eqos_flush_desc)(void *desc); 2927a4c4eddSChristophe Roullier void (*eqos_inval_buffer)(void *buf, size_t size); 2937a4c4eddSChristophe Roullier void (*eqos_flush_buffer)(void *buf, size_t size); 2947a4c4eddSChristophe Roullier int (*eqos_probe_resources)(struct udevice *dev); 2957a4c4eddSChristophe Roullier int (*eqos_remove_resources)(struct udevice *dev); 2967a4c4eddSChristophe Roullier int (*eqos_stop_resets)(struct udevice *dev); 2977a4c4eddSChristophe Roullier int (*eqos_start_resets)(struct udevice *dev); 2987a4c4eddSChristophe Roullier void (*eqos_stop_clks)(struct udevice *dev); 2997a4c4eddSChristophe Roullier int (*eqos_start_clks)(struct udevice *dev); 3007a4c4eddSChristophe Roullier int (*eqos_calibrate_pads)(struct udevice *dev); 3017a4c4eddSChristophe Roullier int (*eqos_disable_calibration)(struct udevice *dev); 3027a4c4eddSChristophe Roullier int (*eqos_set_tx_clk_speed)(struct udevice *dev); 3037a4c4eddSChristophe Roullier ulong (*eqos_get_tick_clk_rate)(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; 316ba4dfef1SStephen Warren struct clk clk_master_bus; 317ba4dfef1SStephen Warren struct clk clk_rx; 318ba4dfef1SStephen Warren struct clk clk_ptp_ref; 319ba4dfef1SStephen Warren struct clk clk_tx; 3207a4c4eddSChristophe Roullier struct clk clk_ck; 321ba4dfef1SStephen Warren struct clk clk_slave_bus; 322ba4dfef1SStephen Warren struct mii_dev *mii; 323ba4dfef1SStephen Warren struct phy_device *phy; 32483d31c08SPatrick Delaunay int phyaddr; 32583d31c08SPatrick Delaunay u32 max_speed; 326ba4dfef1SStephen Warren void *descs; 327ba4dfef1SStephen Warren struct eqos_desc *tx_descs; 328ba4dfef1SStephen Warren struct eqos_desc *rx_descs; 329ba4dfef1SStephen Warren int tx_desc_idx, rx_desc_idx; 330ba4dfef1SStephen Warren void *tx_dma_buf; 331ba4dfef1SStephen Warren void *rx_dma_buf; 332ba4dfef1SStephen Warren void *rx_pkt; 333ba4dfef1SStephen Warren bool started; 334ba4dfef1SStephen Warren bool reg_access_ok; 335ba4dfef1SStephen Warren }; 336ba4dfef1SStephen Warren 337ba4dfef1SStephen Warren /* 338ba4dfef1SStephen Warren * TX and RX descriptors are 16 bytes. This causes problems with the cache 339ba4dfef1SStephen Warren * maintenance on CPUs where the cache-line size exceeds the size of these 340ba4dfef1SStephen Warren * descriptors. What will happen is that when the driver receives a packet 341ba4dfef1SStephen Warren * it will be immediately requeued for the hardware to reuse. The CPU will 342ba4dfef1SStephen Warren * therefore need to flush the cache-line containing the descriptor, which 343ba4dfef1SStephen Warren * will cause all other descriptors in the same cache-line to be flushed 344ba4dfef1SStephen Warren * along with it. If one of those descriptors had been written to by the 345ba4dfef1SStephen Warren * device those changes (and the associated packet) will be lost. 346ba4dfef1SStephen Warren * 347ba4dfef1SStephen Warren * To work around this, we make use of non-cached memory if available. If 348ba4dfef1SStephen Warren * descriptors are mapped uncached there's no need to manually flush them 349ba4dfef1SStephen Warren * or invalidate them. 350ba4dfef1SStephen Warren * 351ba4dfef1SStephen Warren * Note that this only applies to descriptors. The packet data buffers do 352ba4dfef1SStephen Warren * not have the same constraints since they are 1536 bytes large, so they 353ba4dfef1SStephen Warren * are unlikely to share cache-lines. 354ba4dfef1SStephen Warren */ 355ba4dfef1SStephen Warren static void *eqos_alloc_descs(unsigned int num) 356ba4dfef1SStephen Warren { 357ba4dfef1SStephen Warren #ifdef CONFIG_SYS_NONCACHED_MEMORY 358ba4dfef1SStephen Warren return (void *)noncached_alloc(EQOS_DESCRIPTORS_SIZE, 359ba4dfef1SStephen Warren EQOS_DESCRIPTOR_ALIGN); 360ba4dfef1SStephen Warren #else 361ba4dfef1SStephen Warren return memalign(EQOS_DESCRIPTOR_ALIGN, EQOS_DESCRIPTORS_SIZE); 362ba4dfef1SStephen Warren #endif 363ba4dfef1SStephen Warren } 364ba4dfef1SStephen Warren 365ba4dfef1SStephen Warren static void eqos_free_descs(void *descs) 366ba4dfef1SStephen Warren { 367ba4dfef1SStephen Warren #ifdef CONFIG_SYS_NONCACHED_MEMORY 368ba4dfef1SStephen Warren /* FIXME: noncached_alloc() has no opposite */ 369ba4dfef1SStephen Warren #else 370ba4dfef1SStephen Warren free(descs); 371ba4dfef1SStephen Warren #endif 372ba4dfef1SStephen Warren } 373ba4dfef1SStephen Warren 3747a4c4eddSChristophe Roullier static void eqos_inval_desc_tegra186(void *desc) 375ba4dfef1SStephen Warren { 376ba4dfef1SStephen Warren #ifndef CONFIG_SYS_NONCACHED_MEMORY 377ba4dfef1SStephen Warren unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1); 378ba4dfef1SStephen Warren unsigned long end = ALIGN(start + EQOS_DESCRIPTOR_SIZE, 379ba4dfef1SStephen Warren ARCH_DMA_MINALIGN); 380ba4dfef1SStephen Warren 381ba4dfef1SStephen Warren invalidate_dcache_range(start, end); 382ba4dfef1SStephen Warren #endif 383ba4dfef1SStephen Warren } 384ba4dfef1SStephen Warren 385a7b3400fSFugang Duan static void eqos_inval_desc_generic(void *desc) 3867a4c4eddSChristophe Roullier { 3877a4c4eddSChristophe Roullier #ifndef CONFIG_SYS_NONCACHED_MEMORY 3887a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); 3897a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, 3907a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 3917a4c4eddSChristophe Roullier 3927a4c4eddSChristophe Roullier invalidate_dcache_range(start, end); 3937a4c4eddSChristophe Roullier #endif 3947a4c4eddSChristophe Roullier } 3957a4c4eddSChristophe Roullier 3967a4c4eddSChristophe Roullier static void eqos_flush_desc_tegra186(void *desc) 397ba4dfef1SStephen Warren { 398ba4dfef1SStephen Warren #ifndef CONFIG_SYS_NONCACHED_MEMORY 399ba4dfef1SStephen Warren flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE); 400ba4dfef1SStephen Warren #endif 401ba4dfef1SStephen Warren } 402ba4dfef1SStephen Warren 403a7b3400fSFugang Duan static void eqos_flush_desc_generic(void *desc) 4047a4c4eddSChristophe Roullier { 4057a4c4eddSChristophe Roullier #ifndef CONFIG_SYS_NONCACHED_MEMORY 4067a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); 4077a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, 4087a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 4097a4c4eddSChristophe Roullier 4107a4c4eddSChristophe Roullier flush_dcache_range(start, end); 4117a4c4eddSChristophe Roullier #endif 4127a4c4eddSChristophe Roullier } 4137a4c4eddSChristophe Roullier 4147a4c4eddSChristophe Roullier static void eqos_inval_buffer_tegra186(void *buf, size_t size) 415ba4dfef1SStephen Warren { 416ba4dfef1SStephen Warren unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1); 417ba4dfef1SStephen Warren unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN); 418ba4dfef1SStephen Warren 419ba4dfef1SStephen Warren invalidate_dcache_range(start, end); 420ba4dfef1SStephen Warren } 421ba4dfef1SStephen Warren 422a7b3400fSFugang Duan static void eqos_inval_buffer_generic(void *buf, size_t size) 4237a4c4eddSChristophe Roullier { 4247a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN); 4257a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)buf + size, 4267a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 4277a4c4eddSChristophe Roullier 4287a4c4eddSChristophe Roullier invalidate_dcache_range(start, end); 4297a4c4eddSChristophe Roullier } 4307a4c4eddSChristophe Roullier 4317a4c4eddSChristophe Roullier static void eqos_flush_buffer_tegra186(void *buf, size_t size) 432ba4dfef1SStephen Warren { 433ba4dfef1SStephen Warren flush_cache((unsigned long)buf, size); 434ba4dfef1SStephen Warren } 435ba4dfef1SStephen Warren 436a7b3400fSFugang Duan static void eqos_flush_buffer_generic(void *buf, size_t size) 4377a4c4eddSChristophe Roullier { 4387a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN); 4397a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)buf + size, 4407a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 4417a4c4eddSChristophe Roullier 4427a4c4eddSChristophe Roullier flush_dcache_range(start, end); 4437a4c4eddSChristophe Roullier } 4447a4c4eddSChristophe Roullier 445ba4dfef1SStephen Warren static int eqos_mdio_wait_idle(struct eqos_priv *eqos) 446ba4dfef1SStephen Warren { 447b491b498SJon Lin return wait_for_bit_le32(&eqos->mac_regs->mdio_address, 448b491b498SJon Lin EQOS_MAC_MDIO_ADDRESS_GB, false, 449b491b498SJon Lin 1000000, true); 450ba4dfef1SStephen Warren } 451ba4dfef1SStephen Warren 452ba4dfef1SStephen Warren static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad, 453ba4dfef1SStephen Warren int mdio_reg) 454ba4dfef1SStephen Warren { 455ba4dfef1SStephen Warren struct eqos_priv *eqos = bus->priv; 456ba4dfef1SStephen Warren u32 val; 457ba4dfef1SStephen Warren int ret; 458ba4dfef1SStephen Warren 459ba4dfef1SStephen Warren debug("%s(dev=%p, addr=%x, reg=%d):\n", __func__, eqos->dev, mdio_addr, 460ba4dfef1SStephen Warren mdio_reg); 461ba4dfef1SStephen Warren 462ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 463ba4dfef1SStephen Warren if (ret) { 46490aa625cSMasahiro Yamada pr_err("MDIO not idle at entry"); 465ba4dfef1SStephen Warren return ret; 466ba4dfef1SStephen Warren } 467ba4dfef1SStephen Warren 468ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->mdio_address); 469ba4dfef1SStephen Warren val &= EQOS_MAC_MDIO_ADDRESS_SKAP | 470ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_C45E; 471ba4dfef1SStephen Warren val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | 472ba4dfef1SStephen Warren (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) | 4737a4c4eddSChristophe Roullier (eqos->config->config_mac_mdio << 474ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | 475ba4dfef1SStephen Warren (EQOS_MAC_MDIO_ADDRESS_GOC_READ << 476ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | 477ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GB; 478ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->mdio_address); 479ba4dfef1SStephen Warren 4807a4c4eddSChristophe Roullier udelay(eqos->config->mdio_wait); 481ba4dfef1SStephen Warren 482ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 483ba4dfef1SStephen Warren if (ret) { 48490aa625cSMasahiro Yamada pr_err("MDIO read didn't complete"); 485ba4dfef1SStephen Warren return ret; 486ba4dfef1SStephen Warren } 487ba4dfef1SStephen Warren 488ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->mdio_data); 489ba4dfef1SStephen Warren val &= EQOS_MAC_MDIO_DATA_GD_MASK; 490ba4dfef1SStephen Warren 491ba4dfef1SStephen Warren debug("%s: val=%x\n", __func__, val); 492ba4dfef1SStephen Warren 493ba4dfef1SStephen Warren return val; 494ba4dfef1SStephen Warren } 495ba4dfef1SStephen Warren 496ba4dfef1SStephen Warren static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad, 497ba4dfef1SStephen Warren int mdio_reg, u16 mdio_val) 498ba4dfef1SStephen Warren { 499ba4dfef1SStephen Warren struct eqos_priv *eqos = bus->priv; 500ba4dfef1SStephen Warren u32 val; 501ba4dfef1SStephen Warren int ret; 502ba4dfef1SStephen Warren 503ba4dfef1SStephen Warren debug("%s(dev=%p, addr=%x, reg=%d, val=%x):\n", __func__, eqos->dev, 504ba4dfef1SStephen Warren mdio_addr, mdio_reg, mdio_val); 505ba4dfef1SStephen Warren 506ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 507ba4dfef1SStephen Warren if (ret) { 50890aa625cSMasahiro Yamada pr_err("MDIO not idle at entry"); 509ba4dfef1SStephen Warren return ret; 510ba4dfef1SStephen Warren } 511ba4dfef1SStephen Warren 512ba4dfef1SStephen Warren writel(mdio_val, &eqos->mac_regs->mdio_data); 513ba4dfef1SStephen Warren 514ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->mdio_address); 515ba4dfef1SStephen Warren val &= EQOS_MAC_MDIO_ADDRESS_SKAP | 516ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_C45E; 517ba4dfef1SStephen Warren val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | 518ba4dfef1SStephen Warren (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) | 5197a4c4eddSChristophe Roullier (eqos->config->config_mac_mdio << 520ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | 521ba4dfef1SStephen Warren (EQOS_MAC_MDIO_ADDRESS_GOC_WRITE << 522ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | 523ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GB; 524ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->mdio_address); 525ba4dfef1SStephen Warren 5267a4c4eddSChristophe Roullier udelay(eqos->config->mdio_wait); 527ba4dfef1SStephen Warren 528ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 529ba4dfef1SStephen Warren if (ret) { 53090aa625cSMasahiro Yamada pr_err("MDIO read didn't complete"); 531ba4dfef1SStephen Warren return ret; 532ba4dfef1SStephen Warren } 533ba4dfef1SStephen Warren 534ba4dfef1SStephen Warren return 0; 535ba4dfef1SStephen Warren } 536ba4dfef1SStephen Warren 537ba4dfef1SStephen Warren static int eqos_start_clks_tegra186(struct udevice *dev) 538ba4dfef1SStephen Warren { 539a7b3400fSFugang Duan #ifdef CONFIG_CLK 540ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 541ba4dfef1SStephen Warren int ret; 542ba4dfef1SStephen Warren 543ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 544ba4dfef1SStephen Warren 545ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_slave_bus); 546ba4dfef1SStephen Warren if (ret < 0) { 54790aa625cSMasahiro Yamada pr_err("clk_enable(clk_slave_bus) failed: %d", ret); 548ba4dfef1SStephen Warren goto err; 549ba4dfef1SStephen Warren } 550ba4dfef1SStephen Warren 551ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_master_bus); 552ba4dfef1SStephen Warren if (ret < 0) { 55390aa625cSMasahiro Yamada pr_err("clk_enable(clk_master_bus) failed: %d", ret); 554ba4dfef1SStephen Warren goto err_disable_clk_slave_bus; 555ba4dfef1SStephen Warren } 556ba4dfef1SStephen Warren 557ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_rx); 558ba4dfef1SStephen Warren if (ret < 0) { 55990aa625cSMasahiro Yamada pr_err("clk_enable(clk_rx) failed: %d", ret); 560ba4dfef1SStephen Warren goto err_disable_clk_master_bus; 561ba4dfef1SStephen Warren } 562ba4dfef1SStephen Warren 563ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_ptp_ref); 564ba4dfef1SStephen Warren if (ret < 0) { 56590aa625cSMasahiro Yamada pr_err("clk_enable(clk_ptp_ref) failed: %d", ret); 566ba4dfef1SStephen Warren goto err_disable_clk_rx; 567ba4dfef1SStephen Warren } 568ba4dfef1SStephen Warren 569ba4dfef1SStephen Warren ret = clk_set_rate(&eqos->clk_ptp_ref, 125 * 1000 * 1000); 570ba4dfef1SStephen Warren if (ret < 0) { 57190aa625cSMasahiro Yamada pr_err("clk_set_rate(clk_ptp_ref) failed: %d", ret); 572ba4dfef1SStephen Warren goto err_disable_clk_ptp_ref; 573ba4dfef1SStephen Warren } 574ba4dfef1SStephen Warren 575ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_tx); 576ba4dfef1SStephen Warren if (ret < 0) { 57790aa625cSMasahiro Yamada pr_err("clk_enable(clk_tx) failed: %d", ret); 578ba4dfef1SStephen Warren goto err_disable_clk_ptp_ref; 579ba4dfef1SStephen Warren } 580a7b3400fSFugang Duan #endif 581ba4dfef1SStephen Warren 582ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 583ba4dfef1SStephen Warren return 0; 584ba4dfef1SStephen Warren 585a7b3400fSFugang Duan #ifdef CONFIG_CLK 586ba4dfef1SStephen Warren err_disable_clk_ptp_ref: 587ba4dfef1SStephen Warren clk_disable(&eqos->clk_ptp_ref); 588ba4dfef1SStephen Warren err_disable_clk_rx: 589ba4dfef1SStephen Warren clk_disable(&eqos->clk_rx); 590ba4dfef1SStephen Warren err_disable_clk_master_bus: 591ba4dfef1SStephen Warren clk_disable(&eqos->clk_master_bus); 592ba4dfef1SStephen Warren err_disable_clk_slave_bus: 593ba4dfef1SStephen Warren clk_disable(&eqos->clk_slave_bus); 594ba4dfef1SStephen Warren err: 595ba4dfef1SStephen Warren debug("%s: FAILED: %d\n", __func__, ret); 596ba4dfef1SStephen Warren return ret; 597a7b3400fSFugang Duan #endif 598ba4dfef1SStephen Warren } 599ba4dfef1SStephen Warren 6007a4c4eddSChristophe Roullier static int eqos_start_clks_stm32(struct udevice *dev) 6017a4c4eddSChristophe Roullier { 602a7b3400fSFugang Duan #ifdef CONFIG_CLK 6037a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 6047a4c4eddSChristophe Roullier int ret; 6057a4c4eddSChristophe Roullier 6067a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 6077a4c4eddSChristophe Roullier 6087a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_master_bus); 6097a4c4eddSChristophe Roullier if (ret < 0) { 6107a4c4eddSChristophe Roullier pr_err("clk_enable(clk_master_bus) failed: %d", ret); 6117a4c4eddSChristophe Roullier goto err; 6127a4c4eddSChristophe Roullier } 6137a4c4eddSChristophe Roullier 6147a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_rx); 6157a4c4eddSChristophe Roullier if (ret < 0) { 6167a4c4eddSChristophe Roullier pr_err("clk_enable(clk_rx) failed: %d", ret); 6177a4c4eddSChristophe Roullier goto err_disable_clk_master_bus; 6187a4c4eddSChristophe Roullier } 6197a4c4eddSChristophe Roullier 6207a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_tx); 6217a4c4eddSChristophe Roullier if (ret < 0) { 6227a4c4eddSChristophe Roullier pr_err("clk_enable(clk_tx) failed: %d", ret); 6237a4c4eddSChristophe Roullier goto err_disable_clk_rx; 6247a4c4eddSChristophe Roullier } 6257a4c4eddSChristophe Roullier 6267a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) { 6277a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_ck); 6287a4c4eddSChristophe Roullier if (ret < 0) { 6297a4c4eddSChristophe Roullier pr_err("clk_enable(clk_ck) failed: %d", ret); 6307a4c4eddSChristophe Roullier goto err_disable_clk_tx; 6317a4c4eddSChristophe Roullier } 6327a4c4eddSChristophe Roullier } 633a7b3400fSFugang Duan #endif 6347a4c4eddSChristophe Roullier 6357a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 6367a4c4eddSChristophe Roullier return 0; 6377a4c4eddSChristophe Roullier 638a7b3400fSFugang Duan #ifdef CONFIG_CLK 6397a4c4eddSChristophe Roullier err_disable_clk_tx: 6407a4c4eddSChristophe Roullier clk_disable(&eqos->clk_tx); 6417a4c4eddSChristophe Roullier err_disable_clk_rx: 6427a4c4eddSChristophe Roullier clk_disable(&eqos->clk_rx); 6437a4c4eddSChristophe Roullier err_disable_clk_master_bus: 6447a4c4eddSChristophe Roullier clk_disable(&eqos->clk_master_bus); 6457a4c4eddSChristophe Roullier err: 6467a4c4eddSChristophe Roullier debug("%s: FAILED: %d\n", __func__, ret); 6477a4c4eddSChristophe Roullier return ret; 648a7b3400fSFugang Duan #endif 649a7b3400fSFugang Duan } 650a7b3400fSFugang Duan 651a7b3400fSFugang Duan static int eqos_start_clks_imx(struct udevice *dev) 652a7b3400fSFugang Duan { 653a7b3400fSFugang Duan return 0; 6547a4c4eddSChristophe Roullier } 6557a4c4eddSChristophe Roullier 6568aaada72SPatrick Delaunay static void eqos_stop_clks_tegra186(struct udevice *dev) 657ba4dfef1SStephen Warren { 658a7b3400fSFugang Duan #ifdef CONFIG_CLK 659ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 660ba4dfef1SStephen Warren 661ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 662ba4dfef1SStephen Warren 663ba4dfef1SStephen Warren clk_disable(&eqos->clk_tx); 664ba4dfef1SStephen Warren clk_disable(&eqos->clk_ptp_ref); 665ba4dfef1SStephen Warren clk_disable(&eqos->clk_rx); 666ba4dfef1SStephen Warren clk_disable(&eqos->clk_master_bus); 667ba4dfef1SStephen Warren clk_disable(&eqos->clk_slave_bus); 668a7b3400fSFugang Duan #endif 669ba4dfef1SStephen Warren 670ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 671ba4dfef1SStephen Warren } 672ba4dfef1SStephen Warren 6738aaada72SPatrick Delaunay static void eqos_stop_clks_stm32(struct udevice *dev) 6747a4c4eddSChristophe Roullier { 675a7b3400fSFugang Duan #ifdef CONFIG_CLK 6767a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 6777a4c4eddSChristophe Roullier 6787a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 6797a4c4eddSChristophe Roullier 6807a4c4eddSChristophe Roullier clk_disable(&eqos->clk_tx); 6817a4c4eddSChristophe Roullier clk_disable(&eqos->clk_rx); 6827a4c4eddSChristophe Roullier clk_disable(&eqos->clk_master_bus); 6837a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) 6847a4c4eddSChristophe Roullier clk_disable(&eqos->clk_ck); 685a7b3400fSFugang Duan #endif 6867a4c4eddSChristophe Roullier 6877a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 6887a4c4eddSChristophe Roullier } 6897a4c4eddSChristophe Roullier 690a7b3400fSFugang Duan static void eqos_stop_clks_imx(struct udevice *dev) 691a7b3400fSFugang Duan { 692a7b3400fSFugang Duan /* empty */ 693a7b3400fSFugang Duan } 694a7b3400fSFugang Duan 695ba4dfef1SStephen Warren static int eqos_start_resets_tegra186(struct udevice *dev) 696ba4dfef1SStephen Warren { 697ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 698ba4dfef1SStephen Warren int ret; 699ba4dfef1SStephen Warren 700ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 701ba4dfef1SStephen Warren 702ba4dfef1SStephen Warren ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 703ba4dfef1SStephen Warren if (ret < 0) { 70490aa625cSMasahiro Yamada pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", ret); 705ba4dfef1SStephen Warren return ret; 706ba4dfef1SStephen Warren } 707ba4dfef1SStephen Warren 708ba4dfef1SStephen Warren udelay(2); 709ba4dfef1SStephen Warren 710ba4dfef1SStephen Warren ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); 711ba4dfef1SStephen Warren if (ret < 0) { 71290aa625cSMasahiro Yamada pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret); 713ba4dfef1SStephen Warren return ret; 714ba4dfef1SStephen Warren } 715ba4dfef1SStephen Warren 716ba4dfef1SStephen Warren ret = reset_assert(&eqos->reset_ctl); 717ba4dfef1SStephen Warren if (ret < 0) { 71890aa625cSMasahiro Yamada pr_err("reset_assert() failed: %d", ret); 719ba4dfef1SStephen Warren return ret; 720ba4dfef1SStephen Warren } 721ba4dfef1SStephen Warren 722ba4dfef1SStephen Warren udelay(2); 723ba4dfef1SStephen Warren 724ba4dfef1SStephen Warren ret = reset_deassert(&eqos->reset_ctl); 725ba4dfef1SStephen Warren if (ret < 0) { 72690aa625cSMasahiro Yamada pr_err("reset_deassert() failed: %d", ret); 727ba4dfef1SStephen Warren return ret; 728ba4dfef1SStephen Warren } 729ba4dfef1SStephen Warren 730ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 731ba4dfef1SStephen Warren return 0; 732ba4dfef1SStephen Warren } 733ba4dfef1SStephen Warren 7347a4c4eddSChristophe Roullier static int eqos_start_resets_stm32(struct udevice *dev) 7357a4c4eddSChristophe Roullier { 7365bd3c538SChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 7375bd3c538SChristophe Roullier int ret; 7385bd3c538SChristophe Roullier 7395bd3c538SChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 7405bd3c538SChristophe Roullier if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) { 7415bd3c538SChristophe Roullier ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 7425bd3c538SChristophe Roullier if (ret < 0) { 7435bd3c538SChristophe Roullier pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", 7445bd3c538SChristophe Roullier ret); 7455bd3c538SChristophe Roullier return ret; 7465bd3c538SChristophe Roullier } 7475bd3c538SChristophe Roullier 7485bd3c538SChristophe Roullier udelay(2); 7495bd3c538SChristophe Roullier 7505bd3c538SChristophe Roullier ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); 7515bd3c538SChristophe Roullier if (ret < 0) { 7525bd3c538SChristophe Roullier pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", 7535bd3c538SChristophe Roullier ret); 7545bd3c538SChristophe Roullier return ret; 7555bd3c538SChristophe Roullier } 7565bd3c538SChristophe Roullier } 7575bd3c538SChristophe Roullier debug("%s: OK\n", __func__); 7585bd3c538SChristophe Roullier 7597a4c4eddSChristophe Roullier return 0; 7607a4c4eddSChristophe Roullier } 7617a4c4eddSChristophe Roullier 762a7b3400fSFugang Duan static int eqos_start_resets_imx(struct udevice *dev) 763a7b3400fSFugang Duan { 764a7b3400fSFugang Duan return 0; 765a7b3400fSFugang Duan } 766a7b3400fSFugang Duan 767ba4dfef1SStephen Warren static int eqos_stop_resets_tegra186(struct udevice *dev) 768ba4dfef1SStephen Warren { 769ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 770ba4dfef1SStephen Warren 771ba4dfef1SStephen Warren reset_assert(&eqos->reset_ctl); 772ba4dfef1SStephen Warren dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 773ba4dfef1SStephen Warren 774ba4dfef1SStephen Warren return 0; 775ba4dfef1SStephen Warren } 776ba4dfef1SStephen Warren 7777a4c4eddSChristophe Roullier static int eqos_stop_resets_stm32(struct udevice *dev) 7787a4c4eddSChristophe Roullier { 7795bd3c538SChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 7805bd3c538SChristophe Roullier int ret; 7815bd3c538SChristophe Roullier 7825bd3c538SChristophe Roullier if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) { 7835bd3c538SChristophe Roullier ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 7845bd3c538SChristophe Roullier if (ret < 0) { 7855bd3c538SChristophe Roullier pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", 7865bd3c538SChristophe Roullier ret); 7875bd3c538SChristophe Roullier return ret; 7885bd3c538SChristophe Roullier } 7895bd3c538SChristophe Roullier } 7905bd3c538SChristophe Roullier 7917a4c4eddSChristophe Roullier return 0; 7927a4c4eddSChristophe Roullier } 7937a4c4eddSChristophe Roullier 794a7b3400fSFugang Duan static int eqos_stop_resets_imx(struct udevice *dev) 795a7b3400fSFugang Duan { 796a7b3400fSFugang Duan return 0; 797a7b3400fSFugang Duan } 798a7b3400fSFugang Duan 799ba4dfef1SStephen Warren static int eqos_calibrate_pads_tegra186(struct udevice *dev) 800ba4dfef1SStephen Warren { 801ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 802ba4dfef1SStephen Warren int ret; 803ba4dfef1SStephen Warren 804ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 805ba4dfef1SStephen Warren 806ba4dfef1SStephen Warren setbits_le32(&eqos->tegra186_regs->sdmemcomppadctrl, 807ba4dfef1SStephen Warren EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD); 808ba4dfef1SStephen Warren 809ba4dfef1SStephen Warren udelay(1); 810ba4dfef1SStephen Warren 811ba4dfef1SStephen Warren setbits_le32(&eqos->tegra186_regs->auto_cal_config, 812ba4dfef1SStephen Warren EQOS_AUTO_CAL_CONFIG_START | EQOS_AUTO_CAL_CONFIG_ENABLE); 813ba4dfef1SStephen Warren 814b491b498SJon Lin ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, 815ba4dfef1SStephen Warren EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false); 816ba4dfef1SStephen Warren if (ret) { 81790aa625cSMasahiro Yamada pr_err("calibrate didn't start"); 818ba4dfef1SStephen Warren goto failed; 819ba4dfef1SStephen Warren } 820ba4dfef1SStephen Warren 821b491b498SJon Lin ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, 822ba4dfef1SStephen Warren EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false); 823ba4dfef1SStephen Warren if (ret) { 82490aa625cSMasahiro Yamada pr_err("calibrate didn't finish"); 825ba4dfef1SStephen Warren goto failed; 826ba4dfef1SStephen Warren } 827ba4dfef1SStephen Warren 828ba4dfef1SStephen Warren ret = 0; 829ba4dfef1SStephen Warren 830ba4dfef1SStephen Warren failed: 831ba4dfef1SStephen Warren clrbits_le32(&eqos->tegra186_regs->sdmemcomppadctrl, 832ba4dfef1SStephen Warren EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD); 833ba4dfef1SStephen Warren 834ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 835ba4dfef1SStephen Warren 836ba4dfef1SStephen Warren return ret; 837ba4dfef1SStephen Warren } 838ba4dfef1SStephen Warren 839ba4dfef1SStephen Warren static int eqos_disable_calibration_tegra186(struct udevice *dev) 840ba4dfef1SStephen Warren { 841ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 842ba4dfef1SStephen Warren 843ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 844ba4dfef1SStephen Warren 845ba4dfef1SStephen Warren clrbits_le32(&eqos->tegra186_regs->auto_cal_config, 846ba4dfef1SStephen Warren EQOS_AUTO_CAL_CONFIG_ENABLE); 847ba4dfef1SStephen Warren 848ba4dfef1SStephen Warren return 0; 849ba4dfef1SStephen Warren } 850ba4dfef1SStephen Warren 851ba4dfef1SStephen Warren static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev) 852ba4dfef1SStephen Warren { 853a7b3400fSFugang Duan #ifdef CONFIG_CLK 854ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 855ba4dfef1SStephen Warren 856ba4dfef1SStephen Warren return clk_get_rate(&eqos->clk_slave_bus); 857a7b3400fSFugang Duan #else 858a7b3400fSFugang Duan return 0; 859a7b3400fSFugang Duan #endif 860ba4dfef1SStephen Warren } 861ba4dfef1SStephen Warren 8627a4c4eddSChristophe Roullier static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) 8637a4c4eddSChristophe Roullier { 864a7b3400fSFugang Duan #ifdef CONFIG_CLK 8657a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 8667a4c4eddSChristophe Roullier 8677a4c4eddSChristophe Roullier return clk_get_rate(&eqos->clk_master_bus); 868a7b3400fSFugang Duan #else 869a7b3400fSFugang Duan return 0; 870a7b3400fSFugang Duan #endif 871a7b3400fSFugang Duan } 872a7b3400fSFugang Duan 873ad018a0cSFugang Duan __weak u32 imx_get_eqos_csr_clk(void) 874ad018a0cSFugang Duan { 875ad018a0cSFugang Duan return 100 * 1000000; 876ad018a0cSFugang Duan } 877ad018a0cSFugang Duan __weak int imx_eqos_txclk_set_rate(unsigned long rate) 878ad018a0cSFugang Duan { 879ad018a0cSFugang Duan return 0; 880ad018a0cSFugang Duan } 881ad018a0cSFugang Duan 882a7b3400fSFugang Duan static ulong eqos_get_tick_clk_rate_imx(struct udevice *dev) 883a7b3400fSFugang Duan { 884ad018a0cSFugang Duan return imx_get_eqos_csr_clk(); 8857a4c4eddSChristophe Roullier } 8867a4c4eddSChristophe Roullier 8877a4c4eddSChristophe Roullier static int eqos_calibrate_pads_stm32(struct udevice *dev) 8887a4c4eddSChristophe Roullier { 8897a4c4eddSChristophe Roullier return 0; 8907a4c4eddSChristophe Roullier } 8917a4c4eddSChristophe Roullier 892a7b3400fSFugang Duan static int eqos_calibrate_pads_imx(struct udevice *dev) 893a7b3400fSFugang Duan { 894a7b3400fSFugang Duan return 0; 895a7b3400fSFugang Duan } 896a7b3400fSFugang Duan 8977a4c4eddSChristophe Roullier static int eqos_disable_calibration_stm32(struct udevice *dev) 8987a4c4eddSChristophe Roullier { 8997a4c4eddSChristophe Roullier return 0; 9007a4c4eddSChristophe Roullier } 9017a4c4eddSChristophe Roullier 902a7b3400fSFugang Duan static int eqos_disable_calibration_imx(struct udevice *dev) 903a7b3400fSFugang Duan { 904a7b3400fSFugang Duan return 0; 905a7b3400fSFugang Duan } 906a7b3400fSFugang Duan 907ba4dfef1SStephen Warren static int eqos_set_full_duplex(struct udevice *dev) 908ba4dfef1SStephen Warren { 909ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 910ba4dfef1SStephen Warren 911ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 912ba4dfef1SStephen Warren 913ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->configuration, EQOS_MAC_CONFIGURATION_DM); 914ba4dfef1SStephen Warren 915ba4dfef1SStephen Warren return 0; 916ba4dfef1SStephen Warren } 917ba4dfef1SStephen Warren 918ba4dfef1SStephen Warren static int eqos_set_half_duplex(struct udevice *dev) 919ba4dfef1SStephen Warren { 920ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 921ba4dfef1SStephen Warren 922ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 923ba4dfef1SStephen Warren 924ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, EQOS_MAC_CONFIGURATION_DM); 925ba4dfef1SStephen Warren 926ba4dfef1SStephen Warren /* WAR: Flush TX queue when switching to half-duplex */ 927ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->txq0_operation_mode, 928ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_FTQ); 929ba4dfef1SStephen Warren 930ba4dfef1SStephen Warren return 0; 931ba4dfef1SStephen Warren } 932ba4dfef1SStephen Warren 933ba4dfef1SStephen Warren static int eqos_set_gmii_speed(struct udevice *dev) 934ba4dfef1SStephen Warren { 935ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 936ba4dfef1SStephen Warren 937ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 938ba4dfef1SStephen Warren 939ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, 940ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_PS | EQOS_MAC_CONFIGURATION_FES); 941ba4dfef1SStephen Warren 942ba4dfef1SStephen Warren return 0; 943ba4dfef1SStephen Warren } 944ba4dfef1SStephen Warren 945ba4dfef1SStephen Warren static int eqos_set_mii_speed_100(struct udevice *dev) 946ba4dfef1SStephen Warren { 947ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 948ba4dfef1SStephen Warren 949ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 950ba4dfef1SStephen Warren 951ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->configuration, 952ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_PS | EQOS_MAC_CONFIGURATION_FES); 953ba4dfef1SStephen Warren 954ba4dfef1SStephen Warren return 0; 955ba4dfef1SStephen Warren } 956ba4dfef1SStephen Warren 957ba4dfef1SStephen Warren static int eqos_set_mii_speed_10(struct udevice *dev) 958ba4dfef1SStephen Warren { 959ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 960ba4dfef1SStephen Warren 961ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 962ba4dfef1SStephen Warren 963ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->configuration, 964ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_FES, EQOS_MAC_CONFIGURATION_PS); 965ba4dfef1SStephen Warren 966ba4dfef1SStephen Warren return 0; 967ba4dfef1SStephen Warren } 968ba4dfef1SStephen Warren 969ba4dfef1SStephen Warren static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev) 970ba4dfef1SStephen Warren { 971a7b3400fSFugang Duan #ifdef CONFIG_CLK 972ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 973ba4dfef1SStephen Warren ulong rate; 974ba4dfef1SStephen Warren int ret; 975ba4dfef1SStephen Warren 976ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 977ba4dfef1SStephen Warren 978ba4dfef1SStephen Warren switch (eqos->phy->speed) { 979ba4dfef1SStephen Warren case SPEED_1000: 980ba4dfef1SStephen Warren rate = 125 * 1000 * 1000; 981ba4dfef1SStephen Warren break; 982ba4dfef1SStephen Warren case SPEED_100: 983ba4dfef1SStephen Warren rate = 25 * 1000 * 1000; 984ba4dfef1SStephen Warren break; 985ba4dfef1SStephen Warren case SPEED_10: 986ba4dfef1SStephen Warren rate = 2.5 * 1000 * 1000; 987ba4dfef1SStephen Warren break; 988ba4dfef1SStephen Warren default: 98990aa625cSMasahiro Yamada pr_err("invalid speed %d", eqos->phy->speed); 990ba4dfef1SStephen Warren return -EINVAL; 991ba4dfef1SStephen Warren } 992ba4dfef1SStephen Warren 993ba4dfef1SStephen Warren ret = clk_set_rate(&eqos->clk_tx, rate); 994ba4dfef1SStephen Warren if (ret < 0) { 99590aa625cSMasahiro Yamada pr_err("clk_set_rate(tx_clk, %lu) failed: %d", rate, ret); 996ba4dfef1SStephen Warren return ret; 997ba4dfef1SStephen Warren } 998a7b3400fSFugang Duan #endif 999ba4dfef1SStephen Warren 1000ba4dfef1SStephen Warren return 0; 1001ba4dfef1SStephen Warren } 1002ba4dfef1SStephen Warren 10037a4c4eddSChristophe Roullier static int eqos_set_tx_clk_speed_stm32(struct udevice *dev) 10047a4c4eddSChristophe Roullier { 10057a4c4eddSChristophe Roullier return 0; 10067a4c4eddSChristophe Roullier } 10077a4c4eddSChristophe Roullier 1008a7b3400fSFugang Duan static int eqos_set_tx_clk_speed_imx(struct udevice *dev) 1009a7b3400fSFugang Duan { 1010ad018a0cSFugang Duan struct eqos_priv *eqos = dev_get_priv(dev); 1011ad018a0cSFugang Duan ulong rate; 1012ad018a0cSFugang Duan int ret; 1013ad018a0cSFugang Duan 1014ad018a0cSFugang Duan debug("%s(dev=%p):\n", __func__, dev); 1015ad018a0cSFugang Duan 1016ad018a0cSFugang Duan switch (eqos->phy->speed) { 1017ad018a0cSFugang Duan case SPEED_1000: 1018ad018a0cSFugang Duan rate = 125 * 1000 * 1000; 1019ad018a0cSFugang Duan break; 1020ad018a0cSFugang Duan case SPEED_100: 1021ad018a0cSFugang Duan rate = 25 * 1000 * 1000; 1022ad018a0cSFugang Duan break; 1023ad018a0cSFugang Duan case SPEED_10: 1024ad018a0cSFugang Duan rate = 2.5 * 1000 * 1000; 1025ad018a0cSFugang Duan break; 1026ad018a0cSFugang Duan default: 1027ad018a0cSFugang Duan pr_err("invalid speed %d", eqos->phy->speed); 1028ad018a0cSFugang Duan return -EINVAL; 1029ad018a0cSFugang Duan } 1030ad018a0cSFugang Duan 1031ad018a0cSFugang Duan ret = imx_eqos_txclk_set_rate(rate); 1032ad018a0cSFugang Duan if (ret < 0) { 1033ad018a0cSFugang Duan pr_err("imx (tx_clk, %lu) failed: %d", rate, ret); 1034ad018a0cSFugang Duan return ret; 1035ad018a0cSFugang Duan } 1036ad018a0cSFugang Duan 1037a7b3400fSFugang Duan return 0; 1038a7b3400fSFugang Duan } 1039a7b3400fSFugang Duan 1040ba4dfef1SStephen Warren static int eqos_adjust_link(struct udevice *dev) 1041ba4dfef1SStephen Warren { 1042ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1043ba4dfef1SStephen Warren int ret; 1044ba4dfef1SStephen Warren bool en_calibration; 1045ba4dfef1SStephen Warren 1046ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1047ba4dfef1SStephen Warren 1048ba4dfef1SStephen Warren if (eqos->phy->duplex) 1049ba4dfef1SStephen Warren ret = eqos_set_full_duplex(dev); 1050ba4dfef1SStephen Warren else 1051ba4dfef1SStephen Warren ret = eqos_set_half_duplex(dev); 1052ba4dfef1SStephen Warren if (ret < 0) { 105390aa625cSMasahiro Yamada pr_err("eqos_set_*_duplex() failed: %d", ret); 1054ba4dfef1SStephen Warren return ret; 1055ba4dfef1SStephen Warren } 1056ba4dfef1SStephen Warren 1057ba4dfef1SStephen Warren switch (eqos->phy->speed) { 1058ba4dfef1SStephen Warren case SPEED_1000: 1059ba4dfef1SStephen Warren en_calibration = true; 1060ba4dfef1SStephen Warren ret = eqos_set_gmii_speed(dev); 1061ba4dfef1SStephen Warren break; 1062ba4dfef1SStephen Warren case SPEED_100: 1063ba4dfef1SStephen Warren en_calibration = true; 1064ba4dfef1SStephen Warren ret = eqos_set_mii_speed_100(dev); 1065ba4dfef1SStephen Warren break; 1066ba4dfef1SStephen Warren case SPEED_10: 1067ba4dfef1SStephen Warren en_calibration = false; 1068ba4dfef1SStephen Warren ret = eqos_set_mii_speed_10(dev); 1069ba4dfef1SStephen Warren break; 1070ba4dfef1SStephen Warren default: 107190aa625cSMasahiro Yamada pr_err("invalid speed %d", eqos->phy->speed); 1072ba4dfef1SStephen Warren return -EINVAL; 1073ba4dfef1SStephen Warren } 1074ba4dfef1SStephen Warren if (ret < 0) { 107590aa625cSMasahiro Yamada pr_err("eqos_set_*mii_speed*() failed: %d", ret); 1076ba4dfef1SStephen Warren return ret; 1077ba4dfef1SStephen Warren } 1078ba4dfef1SStephen Warren 1079ba4dfef1SStephen Warren if (en_calibration) { 10807a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_calibrate_pads(dev); 1081ba4dfef1SStephen Warren if (ret < 0) { 10827a4c4eddSChristophe Roullier pr_err("eqos_calibrate_pads() failed: %d", 10837a4c4eddSChristophe Roullier ret); 1084ba4dfef1SStephen Warren return ret; 1085ba4dfef1SStephen Warren } 1086ba4dfef1SStephen Warren } else { 10877a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_disable_calibration(dev); 1088ba4dfef1SStephen Warren if (ret < 0) { 10897a4c4eddSChristophe Roullier pr_err("eqos_disable_calibration() failed: %d", 1090ba4dfef1SStephen Warren ret); 1091ba4dfef1SStephen Warren return ret; 1092ba4dfef1SStephen Warren } 1093ba4dfef1SStephen Warren } 10947a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_set_tx_clk_speed(dev); 1095ba4dfef1SStephen Warren if (ret < 0) { 10967a4c4eddSChristophe Roullier pr_err("eqos_set_tx_clk_speed() failed: %d", ret); 1097ba4dfef1SStephen Warren return ret; 1098ba4dfef1SStephen Warren } 1099ba4dfef1SStephen Warren 1100ba4dfef1SStephen Warren return 0; 1101ba4dfef1SStephen Warren } 1102ba4dfef1SStephen Warren 1103ba4dfef1SStephen Warren static int eqos_write_hwaddr(struct udevice *dev) 1104ba4dfef1SStephen Warren { 1105ba4dfef1SStephen Warren struct eth_pdata *plat = dev_get_platdata(dev); 1106ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1107ba4dfef1SStephen Warren uint32_t val; 1108ba4dfef1SStephen Warren 1109ba4dfef1SStephen Warren /* 1110ba4dfef1SStephen Warren * This function may be called before start() or after stop(). At that 1111ba4dfef1SStephen Warren * time, on at least some configurations of the EQoS HW, all clocks to 1112ba4dfef1SStephen Warren * the EQoS HW block will be stopped, and a reset signal applied. If 1113ba4dfef1SStephen Warren * any register access is attempted in this state, bus timeouts or CPU 1114ba4dfef1SStephen Warren * hangs may occur. This check prevents that. 1115ba4dfef1SStephen Warren * 1116ba4dfef1SStephen Warren * A simple solution to this problem would be to not implement 1117ba4dfef1SStephen Warren * write_hwaddr(), since start() always writes the MAC address into HW 1118ba4dfef1SStephen Warren * anyway. However, it is desirable to implement write_hwaddr() to 1119ba4dfef1SStephen Warren * support the case of SW that runs subsequent to U-Boot which expects 1120ba4dfef1SStephen Warren * the MAC address to already be programmed into the EQoS registers, 1121ba4dfef1SStephen Warren * which must happen irrespective of whether the U-Boot user (or 1122ba4dfef1SStephen Warren * scripts) actually made use of the EQoS device, and hence 1123ba4dfef1SStephen Warren * irrespective of whether start() was ever called. 1124ba4dfef1SStephen Warren * 1125ba4dfef1SStephen Warren * Note that this requirement by subsequent SW is not valid for 1126ba4dfef1SStephen Warren * Tegra186, and is likely not valid for any non-PCI instantiation of 1127ba4dfef1SStephen Warren * the EQoS HW block. This function is implemented solely as 1128ba4dfef1SStephen Warren * future-proofing with the expectation the driver will eventually be 1129ba4dfef1SStephen Warren * ported to some system where the expectation above is true. 1130ba4dfef1SStephen Warren */ 1131ba4dfef1SStephen Warren if (!eqos->config->reg_access_always_ok && !eqos->reg_access_ok) 1132ba4dfef1SStephen Warren return 0; 1133ba4dfef1SStephen Warren 1134ba4dfef1SStephen Warren /* Update the MAC address */ 1135ba4dfef1SStephen Warren val = (plat->enetaddr[5] << 8) | 1136ba4dfef1SStephen Warren (plat->enetaddr[4]); 1137ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->address0_high); 1138ba4dfef1SStephen Warren val = (plat->enetaddr[3] << 24) | 1139ba4dfef1SStephen Warren (plat->enetaddr[2] << 16) | 1140ba4dfef1SStephen Warren (plat->enetaddr[1] << 8) | 1141ba4dfef1SStephen Warren (plat->enetaddr[0]); 1142ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->address0_low); 1143ba4dfef1SStephen Warren 1144ba4dfef1SStephen Warren return 0; 1145ba4dfef1SStephen Warren } 1146ba4dfef1SStephen Warren 11474d0fb6f0SYe Li static int eqos_read_rom_hwaddr(struct udevice *dev) 11484d0fb6f0SYe Li { 11494d0fb6f0SYe Li struct eth_pdata *pdata = dev_get_platdata(dev); 11504d0fb6f0SYe Li 11514d0fb6f0SYe Li #ifdef CONFIG_ARCH_IMX8M 11524d0fb6f0SYe Li imx_get_mac_from_fuse(dev->req_seq, pdata->enetaddr); 11534d0fb6f0SYe Li #endif 11544d0fb6f0SYe Li return !is_valid_ethaddr(pdata->enetaddr); 11554d0fb6f0SYe Li } 11564d0fb6f0SYe Li 1157ba4dfef1SStephen Warren static int eqos_start(struct udevice *dev) 1158ba4dfef1SStephen Warren { 1159ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1160ba4dfef1SStephen Warren int ret, i; 1161ba4dfef1SStephen Warren ulong rate; 1162ba4dfef1SStephen Warren u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl; 1163ba4dfef1SStephen Warren ulong last_rx_desc; 1164ba4dfef1SStephen Warren 1165ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1166ba4dfef1SStephen Warren 1167ba4dfef1SStephen Warren eqos->tx_desc_idx = 0; 1168ba4dfef1SStephen Warren eqos->rx_desc_idx = 0; 1169ba4dfef1SStephen Warren 11707a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_start_clks(dev); 1171ba4dfef1SStephen Warren if (ret < 0) { 11727a4c4eddSChristophe Roullier pr_err("eqos_start_clks() failed: %d", ret); 1173ba4dfef1SStephen Warren goto err; 1174ba4dfef1SStephen Warren } 1175ba4dfef1SStephen Warren 11767a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_start_resets(dev); 1177ba4dfef1SStephen Warren if (ret < 0) { 11787a4c4eddSChristophe Roullier pr_err("eqos_start_resets() failed: %d", ret); 1179ba4dfef1SStephen Warren goto err_stop_clks; 1180ba4dfef1SStephen Warren } 1181ba4dfef1SStephen Warren 1182ba4dfef1SStephen Warren udelay(10); 1183ba4dfef1SStephen Warren 1184ba4dfef1SStephen Warren eqos->reg_access_ok = true; 1185ba4dfef1SStephen Warren 1186b491b498SJon Lin ret = wait_for_bit_le32(&eqos->dma_regs->mode, 11877a4c4eddSChristophe Roullier EQOS_DMA_MODE_SWR, false, 11887a4c4eddSChristophe Roullier eqos->config->swr_wait, false); 1189ba4dfef1SStephen Warren if (ret) { 119090aa625cSMasahiro Yamada pr_err("EQOS_DMA_MODE_SWR stuck"); 1191ba4dfef1SStephen Warren goto err_stop_resets; 1192ba4dfef1SStephen Warren } 1193ba4dfef1SStephen Warren 11947a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_calibrate_pads(dev); 1195ba4dfef1SStephen Warren if (ret < 0) { 11967a4c4eddSChristophe Roullier pr_err("eqos_calibrate_pads() failed: %d", ret); 1197ba4dfef1SStephen Warren goto err_stop_resets; 1198ba4dfef1SStephen Warren } 11997a4c4eddSChristophe Roullier rate = eqos->config->ops->eqos_get_tick_clk_rate(dev); 1200ba4dfef1SStephen Warren 1201ba4dfef1SStephen Warren val = (rate / 1000000) - 1; 1202ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->us_tic_counter); 1203ba4dfef1SStephen Warren 12047a4c4eddSChristophe Roullier /* 12057a4c4eddSChristophe Roullier * if PHY was already connected and configured, 12067a4c4eddSChristophe Roullier * don't need to reconnect/reconfigure again 12077a4c4eddSChristophe Roullier */ 12087a4c4eddSChristophe Roullier if (!eqos->phy) { 12098e3eceb0SYe Li int addr = -1; 12108e3eceb0SYe Li #ifdef CONFIG_DM_ETH_PHY 12118e3eceb0SYe Li addr = eth_phy_get_addr(dev); 12128e3eceb0SYe Li #endif 12138e3eceb0SYe Li #ifdef DWC_NET_PHYADDR 12148e3eceb0SYe Li addr = DWC_NET_PHYADDR; 12158e3eceb0SYe Li #endif 12168e3eceb0SYe Li eqos->phy = phy_connect(eqos->mii, addr, dev, 12177a4c4eddSChristophe Roullier eqos->config->interface(dev)); 1218ba4dfef1SStephen Warren if (!eqos->phy) { 121990aa625cSMasahiro Yamada pr_err("phy_connect() failed"); 1220ba4dfef1SStephen Warren goto err_stop_resets; 1221ba4dfef1SStephen Warren } 122283d31c08SPatrick Delaunay 122383d31c08SPatrick Delaunay if (eqos->max_speed) { 122483d31c08SPatrick Delaunay ret = phy_set_supported(eqos->phy, eqos->max_speed); 122583d31c08SPatrick Delaunay if (ret) { 122683d31c08SPatrick Delaunay pr_err("phy_set_supported() failed: %d", ret); 122783d31c08SPatrick Delaunay goto err_shutdown_phy; 122883d31c08SPatrick Delaunay } 122983d31c08SPatrick Delaunay } 123083d31c08SPatrick Delaunay 1231ba4dfef1SStephen Warren ret = phy_config(eqos->phy); 1232ba4dfef1SStephen Warren if (ret < 0) { 123390aa625cSMasahiro Yamada pr_err("phy_config() failed: %d", ret); 1234ba4dfef1SStephen Warren goto err_shutdown_phy; 1235ba4dfef1SStephen Warren } 12367a4c4eddSChristophe Roullier } 12377a4c4eddSChristophe Roullier 1238ba4dfef1SStephen Warren ret = phy_startup(eqos->phy); 1239ba4dfef1SStephen Warren if (ret < 0) { 124090aa625cSMasahiro Yamada pr_err("phy_startup() failed: %d", ret); 1241ba4dfef1SStephen Warren goto err_shutdown_phy; 1242ba4dfef1SStephen Warren } 1243ba4dfef1SStephen Warren 1244ba4dfef1SStephen Warren if (!eqos->phy->link) { 124590aa625cSMasahiro Yamada pr_err("No link"); 1246ba4dfef1SStephen Warren goto err_shutdown_phy; 1247ba4dfef1SStephen Warren } 1248ba4dfef1SStephen Warren 1249ba4dfef1SStephen Warren ret = eqos_adjust_link(dev); 1250ba4dfef1SStephen Warren if (ret < 0) { 125190aa625cSMasahiro Yamada pr_err("eqos_adjust_link() failed: %d", ret); 1252ba4dfef1SStephen Warren goto err_shutdown_phy; 1253ba4dfef1SStephen Warren } 1254ba4dfef1SStephen Warren 1255ba4dfef1SStephen Warren /* Configure MTL */ 1256a7b3400fSFugang Duan writel(0x60, &eqos->mtl_regs->txq0_quantum_weight - 0x100); 1257ba4dfef1SStephen Warren 1258ba4dfef1SStephen Warren /* Enable Store and Forward mode for TX */ 1259ba4dfef1SStephen Warren /* Program Tx operating mode */ 1260ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->txq0_operation_mode, 1261ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TSF | 1262ba4dfef1SStephen Warren (EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_ENABLED << 1263ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_SHIFT)); 1264ba4dfef1SStephen Warren 1265ba4dfef1SStephen Warren /* Transmit Queue weight */ 1266ba4dfef1SStephen Warren writel(0x10, &eqos->mtl_regs->txq0_quantum_weight); 1267ba4dfef1SStephen Warren 1268ba4dfef1SStephen Warren /* Enable Store and Forward mode for RX, since no jumbo frame */ 1269ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1270a7b3400fSFugang Duan EQOS_MTL_RXQ0_OPERATION_MODE_RSF | 1271a7b3400fSFugang Duan EQOS_MTL_RXQ0_OPERATION_MODE_FEP | 1272a7b3400fSFugang Duan EQOS_MTL_RXQ0_OPERATION_MODE_FUP); 1273ba4dfef1SStephen Warren 1274ba4dfef1SStephen Warren /* Transmit/Receive queue fifo size; use all RAM for 1 queue */ 1275ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->hw_feature1); 1276ba4dfef1SStephen Warren tx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_SHIFT) & 1277ba4dfef1SStephen Warren EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_MASK; 1278ba4dfef1SStephen Warren rx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT) & 1279ba4dfef1SStephen Warren EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK; 1280ba4dfef1SStephen Warren 1281ba4dfef1SStephen Warren /* 1282ba4dfef1SStephen Warren * r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting. 1283ba4dfef1SStephen Warren * r/tqs is encoded as (n / 256) - 1. 1284ba4dfef1SStephen Warren */ 1285ba4dfef1SStephen Warren tqs = (128 << tx_fifo_sz) / 256 - 1; 1286ba4dfef1SStephen Warren rqs = (128 << rx_fifo_sz) / 256 - 1; 1287ba4dfef1SStephen Warren 1288ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->txq0_operation_mode, 1289ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK << 1290ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT, 1291ba4dfef1SStephen Warren tqs << EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT); 1292ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1293ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RQS_MASK << 1294ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT, 1295ba4dfef1SStephen Warren rqs << EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT); 1296ba4dfef1SStephen Warren 1297ba4dfef1SStephen Warren /* Flow control used only if each channel gets 4KB or more FIFO */ 1298ba4dfef1SStephen Warren if (rqs >= ((4096 / 256) - 1)) { 1299ba4dfef1SStephen Warren u32 rfd, rfa; 1300ba4dfef1SStephen Warren 1301ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1302ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_EHFC); 1303ba4dfef1SStephen Warren 1304ba4dfef1SStephen Warren /* 1305ba4dfef1SStephen Warren * Set Threshold for Activating Flow Contol space for min 2 1306ba4dfef1SStephen Warren * frames ie, (1500 * 1) = 1500 bytes. 1307ba4dfef1SStephen Warren * 1308ba4dfef1SStephen Warren * Set Threshold for Deactivating Flow Contol for space of 1309ba4dfef1SStephen Warren * min 1 frame (frame size 1500bytes) in receive fifo 1310ba4dfef1SStephen Warren */ 1311ba4dfef1SStephen Warren if (rqs == ((4096 / 256) - 1)) { 1312ba4dfef1SStephen Warren /* 1313ba4dfef1SStephen Warren * This violates the above formula because of FIFO size 1314ba4dfef1SStephen Warren * limit therefore overflow may occur inspite of this. 1315ba4dfef1SStephen Warren */ 1316ba4dfef1SStephen Warren rfd = 0x3; /* Full-3K */ 1317ba4dfef1SStephen Warren rfa = 0x1; /* Full-1.5K */ 1318ba4dfef1SStephen Warren } else if (rqs == ((8192 / 256) - 1)) { 1319ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1320ba4dfef1SStephen Warren rfa = 0xa; /* Full-6K */ 1321ba4dfef1SStephen Warren } else if (rqs == ((16384 / 256) - 1)) { 1322ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1323ba4dfef1SStephen Warren rfa = 0x12; /* Full-10K */ 1324ba4dfef1SStephen Warren } else { 1325ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1326ba4dfef1SStephen Warren rfa = 0x1E; /* Full-16K */ 1327ba4dfef1SStephen Warren } 1328ba4dfef1SStephen Warren 1329ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1330ba4dfef1SStephen Warren (EQOS_MTL_RXQ0_OPERATION_MODE_RFD_MASK << 1331ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT) | 1332ba4dfef1SStephen Warren (EQOS_MTL_RXQ0_OPERATION_MODE_RFA_MASK << 1333ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT), 1334ba4dfef1SStephen Warren (rfd << 1335ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT) | 1336ba4dfef1SStephen Warren (rfa << 1337ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT)); 1338ba4dfef1SStephen Warren } 1339ba4dfef1SStephen Warren 1340ba4dfef1SStephen Warren /* Configure MAC */ 1341ba4dfef1SStephen Warren 1342ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0, 1343ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK << 1344ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT, 13457a4c4eddSChristophe Roullier eqos->config->config_mac << 1346ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT); 1347ba4dfef1SStephen Warren 1348a7b3400fSFugang Duan clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0, 1349a7b3400fSFugang Duan EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK << 1350a7b3400fSFugang Duan EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT, 1351a7b3400fSFugang Duan 0x2 << 1352a7b3400fSFugang Duan EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT); 1353a7b3400fSFugang Duan 1354a7b3400fSFugang Duan /* Multicast and Broadcast Queue Enable */ 1355a7b3400fSFugang Duan setbits_le32(&eqos->mac_regs->unused_0a4, 1356a7b3400fSFugang Duan 0x00100000); 1357a7b3400fSFugang Duan /* enable promise mode */ 1358a7b3400fSFugang Duan setbits_le32(&eqos->mac_regs->unused_004[1], 1359a7b3400fSFugang Duan 0x1); 1360a7b3400fSFugang Duan 1361ba4dfef1SStephen Warren /* Set TX flow control parameters */ 1362ba4dfef1SStephen Warren /* Set Pause Time */ 1363ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->q0_tx_flow_ctrl, 1364ba4dfef1SStephen Warren 0xffff << EQOS_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT); 1365ba4dfef1SStephen Warren /* Assign priority for TX flow control */ 1366ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->txq_prty_map0, 1367ba4dfef1SStephen Warren EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_MASK << 1368ba4dfef1SStephen Warren EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_SHIFT); 1369ba4dfef1SStephen Warren /* Assign priority for RX flow control */ 1370ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->rxq_ctrl2, 1371ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK << 1372ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT); 1373ba4dfef1SStephen Warren /* Enable flow control */ 1374ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->q0_tx_flow_ctrl, 1375ba4dfef1SStephen Warren EQOS_MAC_Q0_TX_FLOW_CTRL_TFE); 1376ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->rx_flow_ctrl, 1377ba4dfef1SStephen Warren EQOS_MAC_RX_FLOW_CTRL_RFE); 1378ba4dfef1SStephen Warren 1379ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->configuration, 1380ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_GPSLCE | 1381ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_WD | 1382ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_JD | 1383ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_JE, 1384ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_CST | 1385ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_ACS); 1386ba4dfef1SStephen Warren 1387ba4dfef1SStephen Warren eqos_write_hwaddr(dev); 1388ba4dfef1SStephen Warren 1389ba4dfef1SStephen Warren /* Configure DMA */ 1390ba4dfef1SStephen Warren 1391ba4dfef1SStephen Warren /* Enable OSP mode */ 1392ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_tx_control, 1393ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_OSP); 1394ba4dfef1SStephen Warren 1395ba4dfef1SStephen Warren /* RX buffer size. Must be a multiple of bus width */ 1396ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_rx_control, 1397ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_MASK << 1398ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT, 1399ba4dfef1SStephen Warren EQOS_MAX_PACKET_SIZE << 1400ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT); 1401ba4dfef1SStephen Warren 1402ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_control, 1403ba4dfef1SStephen Warren EQOS_DMA_CH0_CONTROL_PBLX8); 1404ba4dfef1SStephen Warren 1405ba4dfef1SStephen Warren /* 1406ba4dfef1SStephen Warren * Burst length must be < 1/2 FIFO size. 1407ba4dfef1SStephen Warren * FIFO size in tqs is encoded as (n / 256) - 1. 1408ba4dfef1SStephen Warren * Each burst is n * 8 (PBLX8) * 16 (AXI width) == 128 bytes. 1409ba4dfef1SStephen Warren * Half of n * 256 is n * 128, so pbl == tqs, modulo the -1. 1410ba4dfef1SStephen Warren */ 1411ba4dfef1SStephen Warren pbl = tqs + 1; 1412ba4dfef1SStephen Warren if (pbl > 32) 1413ba4dfef1SStephen Warren pbl = 32; 1414ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_tx_control, 1415ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_TXPBL_MASK << 1416ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT, 1417ba4dfef1SStephen Warren pbl << EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT); 1418ba4dfef1SStephen Warren 1419ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_rx_control, 1420ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RXPBL_MASK << 1421ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT, 1422ba4dfef1SStephen Warren 8 << EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT); 1423ba4dfef1SStephen Warren 1424ba4dfef1SStephen Warren /* DMA performance configuration */ 1425ba4dfef1SStephen Warren val = (2 << EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_SHIFT) | 1426ba4dfef1SStephen Warren EQOS_DMA_SYSBUS_MODE_EAME | EQOS_DMA_SYSBUS_MODE_BLEN16 | 1427ba4dfef1SStephen Warren EQOS_DMA_SYSBUS_MODE_BLEN8 | EQOS_DMA_SYSBUS_MODE_BLEN4; 1428ba4dfef1SStephen Warren writel(val, &eqos->dma_regs->sysbus_mode); 1429ba4dfef1SStephen Warren 1430ba4dfef1SStephen Warren /* Set up descriptors */ 1431ba4dfef1SStephen Warren 1432ba4dfef1SStephen Warren memset(eqos->descs, 0, EQOS_DESCRIPTORS_SIZE); 1433ba4dfef1SStephen Warren for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) { 1434ba4dfef1SStephen Warren struct eqos_desc *rx_desc = &(eqos->rx_descs[i]); 1435ba4dfef1SStephen Warren rx_desc->des0 = (u32)(ulong)(eqos->rx_dma_buf + 1436ba4dfef1SStephen Warren (i * EQOS_MAX_PACKET_SIZE)); 14376143c348SMarek Vasut rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; 1438a7b3400fSFugang Duan mb(); 14396399c699SMarek Vasut eqos->config->ops->eqos_flush_desc(rx_desc); 1440a7b3400fSFugang Duan eqos->config->ops->eqos_inval_buffer(eqos->rx_dma_buf + 1441a7b3400fSFugang Duan (i * EQOS_MAX_PACKET_SIZE), 1442a7b3400fSFugang Duan EQOS_MAX_PACKET_SIZE); 1443ba4dfef1SStephen Warren } 1444ba4dfef1SStephen Warren 1445ba4dfef1SStephen Warren writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress); 1446ba4dfef1SStephen Warren writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address); 1447ba4dfef1SStephen Warren writel(EQOS_DESCRIPTORS_TX - 1, 1448ba4dfef1SStephen Warren &eqos->dma_regs->ch0_txdesc_ring_length); 1449ba4dfef1SStephen Warren 1450ba4dfef1SStephen Warren writel(0, &eqos->dma_regs->ch0_rxdesc_list_haddress); 1451ba4dfef1SStephen Warren writel((ulong)eqos->rx_descs, &eqos->dma_regs->ch0_rxdesc_list_address); 1452ba4dfef1SStephen Warren writel(EQOS_DESCRIPTORS_RX - 1, 1453ba4dfef1SStephen Warren &eqos->dma_regs->ch0_rxdesc_ring_length); 1454ba4dfef1SStephen Warren 1455ba4dfef1SStephen Warren /* Enable everything */ 1456ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_tx_control, 1457ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_ST); 1458ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_rx_control, 1459ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_SR); 1460a7b3400fSFugang Duan setbits_le32(&eqos->mac_regs->configuration, 1461a7b3400fSFugang Duan EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE); 1462ba4dfef1SStephen Warren 1463ba4dfef1SStephen Warren /* TX tail pointer not written until we need to TX a packet */ 1464ba4dfef1SStephen Warren /* 1465ba4dfef1SStephen Warren * Point RX tail pointer at last descriptor. Ideally, we'd point at the 1466ba4dfef1SStephen Warren * first descriptor, implying all descriptors were available. However, 1467ba4dfef1SStephen Warren * that's not distinguishable from none of the descriptors being 1468ba4dfef1SStephen Warren * available. 1469ba4dfef1SStephen Warren */ 1470ba4dfef1SStephen Warren last_rx_desc = (ulong)&(eqos->rx_descs[(EQOS_DESCRIPTORS_RX - 1)]); 1471ba4dfef1SStephen Warren writel(last_rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); 1472ba4dfef1SStephen Warren 1473ba4dfef1SStephen Warren eqos->started = true; 1474ba4dfef1SStephen Warren 1475ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1476ba4dfef1SStephen Warren return 0; 1477ba4dfef1SStephen Warren 1478ba4dfef1SStephen Warren err_shutdown_phy: 1479ba4dfef1SStephen Warren phy_shutdown(eqos->phy); 1480ba4dfef1SStephen Warren err_stop_resets: 14817a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_resets(dev); 1482ba4dfef1SStephen Warren err_stop_clks: 14837a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_clks(dev); 1484ba4dfef1SStephen Warren err: 148590aa625cSMasahiro Yamada pr_err("FAILED: %d", ret); 1486ba4dfef1SStephen Warren return ret; 1487ba4dfef1SStephen Warren } 1488ba4dfef1SStephen Warren 14898aaada72SPatrick Delaunay static void eqos_stop(struct udevice *dev) 1490ba4dfef1SStephen Warren { 1491ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1492ba4dfef1SStephen Warren int i; 1493ba4dfef1SStephen Warren 1494ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1495ba4dfef1SStephen Warren 1496ba4dfef1SStephen Warren if (!eqos->started) 1497ba4dfef1SStephen Warren return; 1498ba4dfef1SStephen Warren eqos->started = false; 1499ba4dfef1SStephen Warren eqos->reg_access_ok = false; 1500ba4dfef1SStephen Warren 1501ba4dfef1SStephen Warren /* Disable TX DMA */ 1502ba4dfef1SStephen Warren clrbits_le32(&eqos->dma_regs->ch0_tx_control, 1503ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_ST); 1504ba4dfef1SStephen Warren 1505ba4dfef1SStephen Warren /* Wait for TX all packets to drain out of MTL */ 1506ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 1507ba4dfef1SStephen Warren u32 val = readl(&eqos->mtl_regs->txq0_debug); 1508ba4dfef1SStephen Warren u32 trcsts = (val >> EQOS_MTL_TXQ0_DEBUG_TRCSTS_SHIFT) & 1509ba4dfef1SStephen Warren EQOS_MTL_TXQ0_DEBUG_TRCSTS_MASK; 1510ba4dfef1SStephen Warren u32 txqsts = val & EQOS_MTL_TXQ0_DEBUG_TXQSTS; 1511ba4dfef1SStephen Warren if ((trcsts != 1) && (!txqsts)) 1512ba4dfef1SStephen Warren break; 1513ba4dfef1SStephen Warren } 1514ba4dfef1SStephen Warren 1515ba4dfef1SStephen Warren /* Turn off MAC TX and RX */ 1516ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, 1517ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE); 1518ba4dfef1SStephen Warren 1519ba4dfef1SStephen Warren /* Wait for all RX packets to drain out of MTL */ 1520ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 1521ba4dfef1SStephen Warren u32 val = readl(&eqos->mtl_regs->rxq0_debug); 1522ba4dfef1SStephen Warren u32 prxq = (val >> EQOS_MTL_RXQ0_DEBUG_PRXQ_SHIFT) & 1523ba4dfef1SStephen Warren EQOS_MTL_RXQ0_DEBUG_PRXQ_MASK; 1524ba4dfef1SStephen Warren u32 rxqsts = (val >> EQOS_MTL_RXQ0_DEBUG_RXQSTS_SHIFT) & 1525ba4dfef1SStephen Warren EQOS_MTL_RXQ0_DEBUG_RXQSTS_MASK; 1526ba4dfef1SStephen Warren if ((!prxq) && (!rxqsts)) 1527ba4dfef1SStephen Warren break; 1528ba4dfef1SStephen Warren } 1529ba4dfef1SStephen Warren 1530ba4dfef1SStephen Warren /* Turn off RX DMA */ 1531ba4dfef1SStephen Warren clrbits_le32(&eqos->dma_regs->ch0_rx_control, 1532ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_SR); 1533ba4dfef1SStephen Warren 1534ba4dfef1SStephen Warren if (eqos->phy) { 1535ba4dfef1SStephen Warren phy_shutdown(eqos->phy); 1536ba4dfef1SStephen Warren } 15377a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_resets(dev); 15387a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_clks(dev); 1539ba4dfef1SStephen Warren 1540ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1541ba4dfef1SStephen Warren } 1542ba4dfef1SStephen Warren 15438aaada72SPatrick Delaunay static int eqos_send(struct udevice *dev, void *packet, int length) 1544ba4dfef1SStephen Warren { 1545ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1546ba4dfef1SStephen Warren struct eqos_desc *tx_desc; 1547ba4dfef1SStephen Warren int i; 1548ba4dfef1SStephen Warren 1549ba4dfef1SStephen Warren debug("%s(dev=%p, packet=%p, length=%d):\n", __func__, dev, packet, 1550ba4dfef1SStephen Warren length); 1551ba4dfef1SStephen Warren 1552ba4dfef1SStephen Warren memcpy(eqos->tx_dma_buf, packet, length); 15537a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length); 1554ba4dfef1SStephen Warren 1555ba4dfef1SStephen Warren tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]); 1556ba4dfef1SStephen Warren eqos->tx_desc_idx++; 1557ba4dfef1SStephen Warren eqos->tx_desc_idx %= EQOS_DESCRIPTORS_TX; 1558ba4dfef1SStephen Warren 1559ba4dfef1SStephen Warren tx_desc->des0 = (ulong)eqos->tx_dma_buf; 1560ba4dfef1SStephen Warren tx_desc->des1 = 0; 1561ba4dfef1SStephen Warren tx_desc->des2 = length; 1562ba4dfef1SStephen Warren /* 1563ba4dfef1SStephen Warren * Make sure that if HW sees the _OWN write below, it will see all the 1564ba4dfef1SStephen Warren * writes to the rest of the descriptor too. 1565ba4dfef1SStephen Warren */ 1566ba4dfef1SStephen Warren mb(); 1567ba4dfef1SStephen Warren tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length; 15687a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_desc(tx_desc); 1569ba4dfef1SStephen Warren 1570364f8fdcSMarek Vasut writel((ulong)(&(eqos->tx_descs[eqos->tx_desc_idx])), 1571364f8fdcSMarek Vasut &eqos->dma_regs->ch0_txdesc_tail_pointer); 1572ba4dfef1SStephen Warren 1573ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 15747a4c4eddSChristophe Roullier eqos->config->ops->eqos_inval_desc(tx_desc); 1575ba4dfef1SStephen Warren if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN)) 1576ba4dfef1SStephen Warren return 0; 1577ba4dfef1SStephen Warren udelay(1); 1578ba4dfef1SStephen Warren } 1579ba4dfef1SStephen Warren 1580ba4dfef1SStephen Warren debug("%s: TX timeout\n", __func__); 1581ba4dfef1SStephen Warren 1582ba4dfef1SStephen Warren return -ETIMEDOUT; 1583ba4dfef1SStephen Warren } 1584ba4dfef1SStephen Warren 15858aaada72SPatrick Delaunay static int eqos_recv(struct udevice *dev, int flags, uchar **packetp) 1586ba4dfef1SStephen Warren { 1587ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1588ba4dfef1SStephen Warren struct eqos_desc *rx_desc; 1589ba4dfef1SStephen Warren int length; 1590ba4dfef1SStephen Warren 1591ba4dfef1SStephen Warren debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags); 1592ba4dfef1SStephen Warren 1593ba4dfef1SStephen Warren rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); 1594865fce80SMarek Vasut eqos->config->ops->eqos_inval_desc(rx_desc); 1595ba4dfef1SStephen Warren if (rx_desc->des3 & EQOS_DESC3_OWN) { 1596ba4dfef1SStephen Warren debug("%s: RX packet not available\n", __func__); 1597ba4dfef1SStephen Warren return -EAGAIN; 1598ba4dfef1SStephen Warren } 1599ba4dfef1SStephen Warren 1600ba4dfef1SStephen Warren *packetp = eqos->rx_dma_buf + 1601ba4dfef1SStephen Warren (eqos->rx_desc_idx * EQOS_MAX_PACKET_SIZE); 1602ba4dfef1SStephen Warren length = rx_desc->des3 & 0x7fff; 1603ba4dfef1SStephen Warren debug("%s: *packetp=%p, length=%d\n", __func__, *packetp, length); 1604ba4dfef1SStephen Warren 16057a4c4eddSChristophe Roullier eqos->config->ops->eqos_inval_buffer(*packetp, length); 1606ba4dfef1SStephen Warren 1607ba4dfef1SStephen Warren return length; 1608ba4dfef1SStephen Warren } 1609ba4dfef1SStephen Warren 16108aaada72SPatrick Delaunay static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) 1611ba4dfef1SStephen Warren { 1612ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1613ba4dfef1SStephen Warren uchar *packet_expected; 1614ba4dfef1SStephen Warren struct eqos_desc *rx_desc; 1615ba4dfef1SStephen Warren 1616ba4dfef1SStephen Warren debug("%s(packet=%p, length=%d)\n", __func__, packet, length); 1617ba4dfef1SStephen Warren 1618ba4dfef1SStephen Warren packet_expected = eqos->rx_dma_buf + 1619ba4dfef1SStephen Warren (eqos->rx_desc_idx * EQOS_MAX_PACKET_SIZE); 1620ba4dfef1SStephen Warren if (packet != packet_expected) { 1621ba4dfef1SStephen Warren debug("%s: Unexpected packet (expected %p)\n", __func__, 1622ba4dfef1SStephen Warren packet_expected); 1623ba4dfef1SStephen Warren return -EINVAL; 1624ba4dfef1SStephen Warren } 1625ba4dfef1SStephen Warren 1626a7b3400fSFugang Duan eqos->config->ops->eqos_inval_buffer(packet, length); 1627a7b3400fSFugang Duan 1628ba4dfef1SStephen Warren rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); 1629076e66fbSMarek Vasut 163007314278SMarek Vasut rx_desc->des0 = 0; 163107314278SMarek Vasut mb(); 163207314278SMarek Vasut eqos->config->ops->eqos_flush_desc(rx_desc); 1633076e66fbSMarek Vasut eqos->config->ops->eqos_inval_buffer(packet, length); 1634ba4dfef1SStephen Warren rx_desc->des0 = (u32)(ulong)packet; 1635ba4dfef1SStephen Warren rx_desc->des1 = 0; 1636ba4dfef1SStephen Warren rx_desc->des2 = 0; 1637ba4dfef1SStephen Warren /* 1638ba4dfef1SStephen Warren * Make sure that if HW sees the _OWN write below, it will see all the 1639ba4dfef1SStephen Warren * writes to the rest of the descriptor too. 1640ba4dfef1SStephen Warren */ 1641ba4dfef1SStephen Warren mb(); 16426143c348SMarek Vasut rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; 16437a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_desc(rx_desc); 1644ba4dfef1SStephen Warren 1645ba4dfef1SStephen Warren writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); 1646ba4dfef1SStephen Warren 1647ba4dfef1SStephen Warren eqos->rx_desc_idx++; 1648ba4dfef1SStephen Warren eqos->rx_desc_idx %= EQOS_DESCRIPTORS_RX; 1649ba4dfef1SStephen Warren 1650ba4dfef1SStephen Warren return 0; 1651ba4dfef1SStephen Warren } 1652ba4dfef1SStephen Warren 1653ba4dfef1SStephen Warren static int eqos_probe_resources_core(struct udevice *dev) 1654ba4dfef1SStephen Warren { 1655ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1656ba4dfef1SStephen Warren int ret; 1657ba4dfef1SStephen Warren 1658ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1659ba4dfef1SStephen Warren 1660ba4dfef1SStephen Warren eqos->descs = eqos_alloc_descs(EQOS_DESCRIPTORS_TX + 1661ba4dfef1SStephen Warren EQOS_DESCRIPTORS_RX); 1662ba4dfef1SStephen Warren if (!eqos->descs) { 1663ba4dfef1SStephen Warren debug("%s: eqos_alloc_descs() failed\n", __func__); 1664ba4dfef1SStephen Warren ret = -ENOMEM; 1665ba4dfef1SStephen Warren goto err; 1666ba4dfef1SStephen Warren } 1667ba4dfef1SStephen Warren eqos->tx_descs = (struct eqos_desc *)eqos->descs; 1668ba4dfef1SStephen Warren eqos->rx_descs = (eqos->tx_descs + EQOS_DESCRIPTORS_TX); 1669ba4dfef1SStephen Warren debug("%s: tx_descs=%p, rx_descs=%p\n", __func__, eqos->tx_descs, 1670ba4dfef1SStephen Warren eqos->rx_descs); 1671ba4dfef1SStephen Warren 1672ba4dfef1SStephen Warren eqos->tx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_MAX_PACKET_SIZE); 1673ba4dfef1SStephen Warren if (!eqos->tx_dma_buf) { 1674ba4dfef1SStephen Warren debug("%s: memalign(tx_dma_buf) failed\n", __func__); 1675ba4dfef1SStephen Warren ret = -ENOMEM; 1676ba4dfef1SStephen Warren goto err_free_descs; 1677ba4dfef1SStephen Warren } 16787a4c4eddSChristophe Roullier debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf); 1679ba4dfef1SStephen Warren 1680ba4dfef1SStephen Warren eqos->rx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_RX_BUFFER_SIZE); 1681ba4dfef1SStephen Warren if (!eqos->rx_dma_buf) { 1682ba4dfef1SStephen Warren debug("%s: memalign(rx_dma_buf) failed\n", __func__); 1683ba4dfef1SStephen Warren ret = -ENOMEM; 1684ba4dfef1SStephen Warren goto err_free_tx_dma_buf; 1685ba4dfef1SStephen Warren } 16867a4c4eddSChristophe Roullier debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf); 1687ba4dfef1SStephen Warren 1688ba4dfef1SStephen Warren eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE); 1689ba4dfef1SStephen Warren if (!eqos->rx_pkt) { 1690ba4dfef1SStephen Warren debug("%s: malloc(rx_pkt) failed\n", __func__); 1691ba4dfef1SStephen Warren ret = -ENOMEM; 1692ba4dfef1SStephen Warren goto err_free_rx_dma_buf; 1693ba4dfef1SStephen Warren } 1694ba4dfef1SStephen Warren debug("%s: rx_pkt=%p\n", __func__, eqos->rx_pkt); 1695ba4dfef1SStephen Warren 1696076e66fbSMarek Vasut eqos->config->ops->eqos_inval_buffer(eqos->rx_dma_buf, 1697076e66fbSMarek Vasut EQOS_MAX_PACKET_SIZE * EQOS_DESCRIPTORS_RX); 1698076e66fbSMarek Vasut 1699ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1700ba4dfef1SStephen Warren return 0; 1701ba4dfef1SStephen Warren 1702ba4dfef1SStephen Warren err_free_rx_dma_buf: 1703ba4dfef1SStephen Warren free(eqos->rx_dma_buf); 1704ba4dfef1SStephen Warren err_free_tx_dma_buf: 1705ba4dfef1SStephen Warren free(eqos->tx_dma_buf); 1706ba4dfef1SStephen Warren err_free_descs: 1707ba4dfef1SStephen Warren eqos_free_descs(eqos->descs); 1708ba4dfef1SStephen Warren err: 1709ba4dfef1SStephen Warren 1710ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 1711ba4dfef1SStephen Warren return ret; 1712ba4dfef1SStephen Warren } 1713ba4dfef1SStephen Warren 1714ba4dfef1SStephen Warren static int eqos_remove_resources_core(struct udevice *dev) 1715ba4dfef1SStephen Warren { 1716ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1717ba4dfef1SStephen Warren 1718ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1719ba4dfef1SStephen Warren 1720ba4dfef1SStephen Warren free(eqos->rx_pkt); 1721ba4dfef1SStephen Warren free(eqos->rx_dma_buf); 1722ba4dfef1SStephen Warren free(eqos->tx_dma_buf); 1723ba4dfef1SStephen Warren eqos_free_descs(eqos->descs); 1724ba4dfef1SStephen Warren 1725ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1726ba4dfef1SStephen Warren return 0; 1727ba4dfef1SStephen Warren } 1728ba4dfef1SStephen Warren 1729ba4dfef1SStephen Warren static int eqos_probe_resources_tegra186(struct udevice *dev) 1730ba4dfef1SStephen Warren { 1731ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1732ba4dfef1SStephen Warren int ret; 1733ba4dfef1SStephen Warren 1734ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1735ba4dfef1SStephen Warren 1736ba4dfef1SStephen Warren ret = reset_get_by_name(dev, "eqos", &eqos->reset_ctl); 1737ba4dfef1SStephen Warren if (ret) { 173890aa625cSMasahiro Yamada pr_err("reset_get_by_name(rst) failed: %d", ret); 1739ba4dfef1SStephen Warren return ret; 1740ba4dfef1SStephen Warren } 1741ba4dfef1SStephen Warren 1742ba4dfef1SStephen Warren ret = gpio_request_by_name(dev, "phy-reset-gpios", 0, 1743ba4dfef1SStephen Warren &eqos->phy_reset_gpio, 1744ba4dfef1SStephen Warren GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); 1745ba4dfef1SStephen Warren if (ret) { 174690aa625cSMasahiro Yamada pr_err("gpio_request_by_name(phy reset) failed: %d", ret); 1747ba4dfef1SStephen Warren goto err_free_reset_eqos; 1748ba4dfef1SStephen Warren } 1749ba4dfef1SStephen Warren 1750ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "slave_bus", &eqos->clk_slave_bus); 1751ba4dfef1SStephen Warren if (ret) { 175290aa625cSMasahiro Yamada pr_err("clk_get_by_name(slave_bus) failed: %d", ret); 1753ba4dfef1SStephen Warren goto err_free_gpio_phy_reset; 1754ba4dfef1SStephen Warren } 1755ba4dfef1SStephen Warren 1756ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "master_bus", &eqos->clk_master_bus); 1757ba4dfef1SStephen Warren if (ret) { 175890aa625cSMasahiro Yamada pr_err("clk_get_by_name(master_bus) failed: %d", ret); 1759ba4dfef1SStephen Warren goto err_free_clk_slave_bus; 1760ba4dfef1SStephen Warren } 1761ba4dfef1SStephen Warren 1762ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "rx", &eqos->clk_rx); 1763ba4dfef1SStephen Warren if (ret) { 176490aa625cSMasahiro Yamada pr_err("clk_get_by_name(rx) failed: %d", ret); 1765ba4dfef1SStephen Warren goto err_free_clk_master_bus; 1766ba4dfef1SStephen Warren } 1767ba4dfef1SStephen Warren 1768ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "ptp_ref", &eqos->clk_ptp_ref); 1769ba4dfef1SStephen Warren if (ret) { 177090aa625cSMasahiro Yamada pr_err("clk_get_by_name(ptp_ref) failed: %d", ret); 1771ba4dfef1SStephen Warren goto err_free_clk_rx; 1772ba4dfef1SStephen Warren return ret; 1773ba4dfef1SStephen Warren } 1774ba4dfef1SStephen Warren 1775ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "tx", &eqos->clk_tx); 1776ba4dfef1SStephen Warren if (ret) { 177790aa625cSMasahiro Yamada pr_err("clk_get_by_name(tx) failed: %d", ret); 1778ba4dfef1SStephen Warren goto err_free_clk_ptp_ref; 1779ba4dfef1SStephen Warren } 1780ba4dfef1SStephen Warren 1781ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1782ba4dfef1SStephen Warren return 0; 1783ba4dfef1SStephen Warren 1784ba4dfef1SStephen Warren err_free_clk_ptp_ref: 1785ba4dfef1SStephen Warren clk_free(&eqos->clk_ptp_ref); 1786ba4dfef1SStephen Warren err_free_clk_rx: 1787ba4dfef1SStephen Warren clk_free(&eqos->clk_rx); 1788ba4dfef1SStephen Warren err_free_clk_master_bus: 1789ba4dfef1SStephen Warren clk_free(&eqos->clk_master_bus); 1790ba4dfef1SStephen Warren err_free_clk_slave_bus: 1791ba4dfef1SStephen Warren clk_free(&eqos->clk_slave_bus); 1792ba4dfef1SStephen Warren err_free_gpio_phy_reset: 1793ba4dfef1SStephen Warren dm_gpio_free(dev, &eqos->phy_reset_gpio); 1794ba4dfef1SStephen Warren err_free_reset_eqos: 1795ba4dfef1SStephen Warren reset_free(&eqos->reset_ctl); 1796ba4dfef1SStephen Warren 1797ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 1798ba4dfef1SStephen Warren return ret; 1799ba4dfef1SStephen Warren } 1800ba4dfef1SStephen Warren 18017a4c4eddSChristophe Roullier /* board-specific Ethernet Interface initializations. */ 18021e8d5d80SPatrick Delaunay __weak int board_interface_eth_init(struct udevice *dev, 18031e8d5d80SPatrick Delaunay phy_interface_t interface_type) 18047a4c4eddSChristophe Roullier { 18057a4c4eddSChristophe Roullier return 0; 18067a4c4eddSChristophe Roullier } 18077a4c4eddSChristophe Roullier 18087a4c4eddSChristophe Roullier static int eqos_probe_resources_stm32(struct udevice *dev) 18097a4c4eddSChristophe Roullier { 18107a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 18117a4c4eddSChristophe Roullier int ret; 18127a4c4eddSChristophe Roullier phy_interface_t interface; 18135bd3c538SChristophe Roullier struct ofnode_phandle_args phandle_args; 18147a4c4eddSChristophe Roullier 18157a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 18167a4c4eddSChristophe Roullier 18177a4c4eddSChristophe Roullier interface = eqos->config->interface(dev); 18187a4c4eddSChristophe Roullier 18197a4c4eddSChristophe Roullier if (interface == PHY_INTERFACE_MODE_NONE) { 18207a4c4eddSChristophe Roullier pr_err("Invalid PHY interface\n"); 18217a4c4eddSChristophe Roullier return -EINVAL; 18227a4c4eddSChristophe Roullier } 18237a4c4eddSChristophe Roullier 18241e8d5d80SPatrick Delaunay ret = board_interface_eth_init(dev, interface); 18257a4c4eddSChristophe Roullier if (ret) 18267a4c4eddSChristophe Roullier return -EINVAL; 18277a4c4eddSChristophe Roullier 182883d31c08SPatrick Delaunay eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0); 182983d31c08SPatrick Delaunay 18307a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); 18317a4c4eddSChristophe Roullier if (ret) { 18327a4c4eddSChristophe Roullier pr_err("clk_get_by_name(master_bus) failed: %d", ret); 18337a4c4eddSChristophe Roullier goto err_probe; 18347a4c4eddSChristophe Roullier } 18357a4c4eddSChristophe Roullier 18367a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); 18377a4c4eddSChristophe Roullier if (ret) { 18387a4c4eddSChristophe Roullier pr_err("clk_get_by_name(rx) failed: %d", ret); 18397a4c4eddSChristophe Roullier goto err_free_clk_master_bus; 18407a4c4eddSChristophe Roullier } 18417a4c4eddSChristophe Roullier 18427a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); 18437a4c4eddSChristophe Roullier if (ret) { 18447a4c4eddSChristophe Roullier pr_err("clk_get_by_name(tx) failed: %d", ret); 18457a4c4eddSChristophe Roullier goto err_free_clk_rx; 18467a4c4eddSChristophe Roullier } 18477a4c4eddSChristophe Roullier 18487a4c4eddSChristophe Roullier /* Get ETH_CLK clocks (optional) */ 18497a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck); 18507a4c4eddSChristophe Roullier if (ret) 18517a4c4eddSChristophe Roullier pr_warn("No phy clock provided %d", ret); 18527a4c4eddSChristophe Roullier 185383d31c08SPatrick Delaunay eqos->phyaddr = -1; 18545bd3c538SChristophe Roullier ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, 18555bd3c538SChristophe Roullier &phandle_args); 18565bd3c538SChristophe Roullier if (!ret) { 18575bd3c538SChristophe Roullier /* search "reset-gpios" in phy node */ 18585bd3c538SChristophe Roullier ret = gpio_request_by_name_nodev(phandle_args.node, 18595bd3c538SChristophe Roullier "reset-gpios", 0, 18605bd3c538SChristophe Roullier &eqos->phy_reset_gpio, 18615bd3c538SChristophe Roullier GPIOD_IS_OUT | 18625bd3c538SChristophe Roullier GPIOD_IS_OUT_ACTIVE); 18635bd3c538SChristophe Roullier if (ret) 18645bd3c538SChristophe Roullier pr_warn("gpio_request_by_name(phy reset) not provided %d", 18655bd3c538SChristophe Roullier ret); 186683d31c08SPatrick Delaunay 186783d31c08SPatrick Delaunay eqos->phyaddr = ofnode_read_u32_default(phandle_args.node, 186883d31c08SPatrick Delaunay "reg", -1); 18695bd3c538SChristophe Roullier } 18705bd3c538SChristophe Roullier 18717a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 18727a4c4eddSChristophe Roullier return 0; 18737a4c4eddSChristophe Roullier 18747a4c4eddSChristophe Roullier err_free_clk_rx: 18757a4c4eddSChristophe Roullier clk_free(&eqos->clk_rx); 18767a4c4eddSChristophe Roullier err_free_clk_master_bus: 18777a4c4eddSChristophe Roullier clk_free(&eqos->clk_master_bus); 18787a4c4eddSChristophe Roullier err_probe: 18797a4c4eddSChristophe Roullier 18807a4c4eddSChristophe Roullier debug("%s: returns %d\n", __func__, ret); 18817a4c4eddSChristophe Roullier return ret; 18827a4c4eddSChristophe Roullier } 18837a4c4eddSChristophe Roullier 18847a4c4eddSChristophe Roullier static phy_interface_t eqos_get_interface_stm32(struct udevice *dev) 18857a4c4eddSChristophe Roullier { 18867a4c4eddSChristophe Roullier const char *phy_mode; 18877a4c4eddSChristophe Roullier phy_interface_t interface = PHY_INTERFACE_MODE_NONE; 18887a4c4eddSChristophe Roullier 18897a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 18907a4c4eddSChristophe Roullier 1891*dcf8de12SDavid Wu phy_mode = dev_read_string(dev, "phy-mode"); 18927a4c4eddSChristophe Roullier if (phy_mode) 18937a4c4eddSChristophe Roullier interface = phy_get_interface_by_name(phy_mode); 18947a4c4eddSChristophe Roullier 18957a4c4eddSChristophe Roullier return interface; 18967a4c4eddSChristophe Roullier } 18977a4c4eddSChristophe Roullier 18987a4c4eddSChristophe Roullier static phy_interface_t eqos_get_interface_tegra186(struct udevice *dev) 18997a4c4eddSChristophe Roullier { 19007a4c4eddSChristophe Roullier return PHY_INTERFACE_MODE_MII; 19017a4c4eddSChristophe Roullier } 19027a4c4eddSChristophe Roullier 1903a7b3400fSFugang Duan static int eqos_probe_resources_imx(struct udevice *dev) 1904a7b3400fSFugang Duan { 1905a7b3400fSFugang Duan struct eqos_priv *eqos = dev_get_priv(dev); 1906a7b3400fSFugang Duan phy_interface_t interface; 1907a7b3400fSFugang Duan 1908a7b3400fSFugang Duan debug("%s(dev=%p):\n", __func__, dev); 1909a7b3400fSFugang Duan 1910a7b3400fSFugang Duan interface = eqos->config->interface(dev); 1911a7b3400fSFugang Duan 1912a7b3400fSFugang Duan if (interface == PHY_INTERFACE_MODE_NONE) { 1913a7b3400fSFugang Duan pr_err("Invalid PHY interface\n"); 1914a7b3400fSFugang Duan return -EINVAL; 1915a7b3400fSFugang Duan } 1916a7b3400fSFugang Duan 1917a7b3400fSFugang Duan debug("%s: OK\n", __func__); 1918a7b3400fSFugang Duan return 0; 1919a7b3400fSFugang Duan } 1920a7b3400fSFugang Duan 1921a7b3400fSFugang Duan static phy_interface_t eqos_get_interface_imx(struct udevice *dev) 1922a7b3400fSFugang Duan { 1923ad018a0cSFugang Duan const char *phy_mode; 1924ad018a0cSFugang Duan phy_interface_t interface = PHY_INTERFACE_MODE_NONE; 1925ad018a0cSFugang Duan 1926ad018a0cSFugang Duan debug("%s(dev=%p):\n", __func__, dev); 1927ad018a0cSFugang Duan 1928ad018a0cSFugang Duan phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", 1929ad018a0cSFugang Duan NULL); 1930ad018a0cSFugang Duan if (phy_mode) 1931ad018a0cSFugang Duan interface = phy_get_interface_by_name(phy_mode); 1932ad018a0cSFugang Duan 1933ad018a0cSFugang Duan return interface; 1934a7b3400fSFugang Duan } 1935a7b3400fSFugang Duan 1936ba4dfef1SStephen Warren static int eqos_remove_resources_tegra186(struct udevice *dev) 1937ba4dfef1SStephen Warren { 1938ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1939ba4dfef1SStephen Warren 1940ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1941ba4dfef1SStephen Warren 1942a7b3400fSFugang Duan #ifdef CONFIG_CLK 1943ba4dfef1SStephen Warren clk_free(&eqos->clk_tx); 1944ba4dfef1SStephen Warren clk_free(&eqos->clk_ptp_ref); 1945ba4dfef1SStephen Warren clk_free(&eqos->clk_rx); 1946ba4dfef1SStephen Warren clk_free(&eqos->clk_slave_bus); 1947ba4dfef1SStephen Warren clk_free(&eqos->clk_master_bus); 1948a7b3400fSFugang Duan #endif 1949ba4dfef1SStephen Warren dm_gpio_free(dev, &eqos->phy_reset_gpio); 1950ba4dfef1SStephen Warren reset_free(&eqos->reset_ctl); 1951ba4dfef1SStephen Warren 1952ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1953ba4dfef1SStephen Warren return 0; 1954ba4dfef1SStephen Warren } 1955ba4dfef1SStephen Warren 19567a4c4eddSChristophe Roullier static int eqos_remove_resources_stm32(struct udevice *dev) 19577a4c4eddSChristophe Roullier { 1958a7b3400fSFugang Duan #ifdef CONFIG_CLK 19597a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 19607a4c4eddSChristophe Roullier 19617a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 19627a4c4eddSChristophe Roullier 19637a4c4eddSChristophe Roullier clk_free(&eqos->clk_tx); 19647a4c4eddSChristophe Roullier clk_free(&eqos->clk_rx); 19657a4c4eddSChristophe Roullier clk_free(&eqos->clk_master_bus); 19667a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) 19677a4c4eddSChristophe Roullier clk_free(&eqos->clk_ck); 1968a7b3400fSFugang Duan #endif 19697a4c4eddSChristophe Roullier 19705bd3c538SChristophe Roullier if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) 19715bd3c538SChristophe Roullier dm_gpio_free(dev, &eqos->phy_reset_gpio); 19725bd3c538SChristophe Roullier 19737a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 19747a4c4eddSChristophe Roullier return 0; 19757a4c4eddSChristophe Roullier } 19767a4c4eddSChristophe Roullier 1977a7b3400fSFugang Duan static int eqos_remove_resources_imx(struct udevice *dev) 1978a7b3400fSFugang Duan { 1979a7b3400fSFugang Duan return 0; 1980a7b3400fSFugang Duan } 1981a7b3400fSFugang Duan 1982ba4dfef1SStephen Warren static int eqos_probe(struct udevice *dev) 1983ba4dfef1SStephen Warren { 1984ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1985ba4dfef1SStephen Warren int ret; 1986ba4dfef1SStephen Warren 1987ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1988ba4dfef1SStephen Warren 1989ba4dfef1SStephen Warren eqos->dev = dev; 1990ba4dfef1SStephen Warren eqos->config = (void *)dev_get_driver_data(dev); 1991ba4dfef1SStephen Warren 1992*dcf8de12SDavid Wu eqos->regs = dev_read_addr(dev); 1993ba4dfef1SStephen Warren if (eqos->regs == FDT_ADDR_T_NONE) { 1994*dcf8de12SDavid Wu pr_err("dev_read_addr() failed"); 1995ba4dfef1SStephen Warren return -ENODEV; 1996ba4dfef1SStephen Warren } 1997ba4dfef1SStephen Warren eqos->mac_regs = (void *)(eqos->regs + EQOS_MAC_REGS_BASE); 1998ba4dfef1SStephen Warren eqos->mtl_regs = (void *)(eqos->regs + EQOS_MTL_REGS_BASE); 1999ba4dfef1SStephen Warren eqos->dma_regs = (void *)(eqos->regs + EQOS_DMA_REGS_BASE); 2000ba4dfef1SStephen Warren eqos->tegra186_regs = (void *)(eqos->regs + EQOS_TEGRA186_REGS_BASE); 2001ba4dfef1SStephen Warren 2002ba4dfef1SStephen Warren ret = eqos_probe_resources_core(dev); 2003ba4dfef1SStephen Warren if (ret < 0) { 200490aa625cSMasahiro Yamada pr_err("eqos_probe_resources_core() failed: %d", ret); 2005ba4dfef1SStephen Warren return ret; 2006ba4dfef1SStephen Warren } 2007ba4dfef1SStephen Warren 20087a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_probe_resources(dev); 2009ba4dfef1SStephen Warren if (ret < 0) { 20107a4c4eddSChristophe Roullier pr_err("eqos_probe_resources() failed: %d", ret); 2011ba4dfef1SStephen Warren goto err_remove_resources_core; 2012ba4dfef1SStephen Warren } 2013ba4dfef1SStephen Warren 20148e3eceb0SYe Li #ifdef CONFIG_DM_ETH_PHY 20158e3eceb0SYe Li eqos->mii = eth_phy_get_mdio_bus(dev); 20168e3eceb0SYe Li #endif 20178e3eceb0SYe Li if (!eqos->mii) { 2018ba4dfef1SStephen Warren eqos->mii = mdio_alloc(); 2019ba4dfef1SStephen Warren if (!eqos->mii) { 202090aa625cSMasahiro Yamada pr_err("mdio_alloc() failed"); 20217a4c4eddSChristophe Roullier ret = -ENOMEM; 2022ba4dfef1SStephen Warren goto err_remove_resources_tegra; 2023ba4dfef1SStephen Warren } 2024ba4dfef1SStephen Warren eqos->mii->read = eqos_mdio_read; 2025ba4dfef1SStephen Warren eqos->mii->write = eqos_mdio_write; 2026ba4dfef1SStephen Warren eqos->mii->priv = eqos; 2027ba4dfef1SStephen Warren strcpy(eqos->mii->name, dev->name); 2028ba4dfef1SStephen Warren 2029ba4dfef1SStephen Warren ret = mdio_register(eqos->mii); 2030ba4dfef1SStephen Warren if (ret < 0) { 203190aa625cSMasahiro Yamada pr_err("mdio_register() failed: %d", ret); 2032ba4dfef1SStephen Warren goto err_free_mdio; 2033ba4dfef1SStephen Warren } 20348e3eceb0SYe Li } 20358e3eceb0SYe Li 20368e3eceb0SYe Li #ifdef CONFIG_DM_ETH_PHY 20378e3eceb0SYe Li eth_phy_set_mdio_bus(dev, eqos->mii); 20388e3eceb0SYe Li #endif 2039ba4dfef1SStephen Warren 2040ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 2041ba4dfef1SStephen Warren return 0; 2042ba4dfef1SStephen Warren 2043ba4dfef1SStephen Warren err_free_mdio: 2044ba4dfef1SStephen Warren mdio_free(eqos->mii); 2045ba4dfef1SStephen Warren err_remove_resources_tegra: 20467a4c4eddSChristophe Roullier eqos->config->ops->eqos_remove_resources(dev); 2047ba4dfef1SStephen Warren err_remove_resources_core: 2048ba4dfef1SStephen Warren eqos_remove_resources_core(dev); 2049ba4dfef1SStephen Warren 2050ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 2051ba4dfef1SStephen Warren return ret; 2052ba4dfef1SStephen Warren } 2053ba4dfef1SStephen Warren 2054ba4dfef1SStephen Warren static int eqos_remove(struct udevice *dev) 2055ba4dfef1SStephen Warren { 2056ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 2057ba4dfef1SStephen Warren 2058ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 2059ba4dfef1SStephen Warren 2060ba4dfef1SStephen Warren mdio_unregister(eqos->mii); 2061ba4dfef1SStephen Warren mdio_free(eqos->mii); 20627a4c4eddSChristophe Roullier eqos->config->ops->eqos_remove_resources(dev); 20637a4c4eddSChristophe Roullier 2064ba4dfef1SStephen Warren eqos_probe_resources_core(dev); 2065ba4dfef1SStephen Warren 2066ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 2067ba4dfef1SStephen Warren return 0; 2068ba4dfef1SStephen Warren } 2069ba4dfef1SStephen Warren 2070ba4dfef1SStephen Warren static const struct eth_ops eqos_ops = { 2071ba4dfef1SStephen Warren .start = eqos_start, 2072ba4dfef1SStephen Warren .stop = eqos_stop, 2073ba4dfef1SStephen Warren .send = eqos_send, 2074ba4dfef1SStephen Warren .recv = eqos_recv, 2075ba4dfef1SStephen Warren .free_pkt = eqos_free_pkt, 2076ba4dfef1SStephen Warren .write_hwaddr = eqos_write_hwaddr, 20774d0fb6f0SYe Li .read_rom_hwaddr = eqos_read_rom_hwaddr, 2078ba4dfef1SStephen Warren }; 2079ba4dfef1SStephen Warren 20807a4c4eddSChristophe Roullier static struct eqos_ops eqos_tegra186_ops = { 20817a4c4eddSChristophe Roullier .eqos_inval_desc = eqos_inval_desc_tegra186, 20827a4c4eddSChristophe Roullier .eqos_flush_desc = eqos_flush_desc_tegra186, 20837a4c4eddSChristophe Roullier .eqos_inval_buffer = eqos_inval_buffer_tegra186, 20847a4c4eddSChristophe Roullier .eqos_flush_buffer = eqos_flush_buffer_tegra186, 20857a4c4eddSChristophe Roullier .eqos_probe_resources = eqos_probe_resources_tegra186, 20867a4c4eddSChristophe Roullier .eqos_remove_resources = eqos_remove_resources_tegra186, 20877a4c4eddSChristophe Roullier .eqos_stop_resets = eqos_stop_resets_tegra186, 20887a4c4eddSChristophe Roullier .eqos_start_resets = eqos_start_resets_tegra186, 20897a4c4eddSChristophe Roullier .eqos_stop_clks = eqos_stop_clks_tegra186, 20907a4c4eddSChristophe Roullier .eqos_start_clks = eqos_start_clks_tegra186, 20917a4c4eddSChristophe Roullier .eqos_calibrate_pads = eqos_calibrate_pads_tegra186, 20927a4c4eddSChristophe Roullier .eqos_disable_calibration = eqos_disable_calibration_tegra186, 20937a4c4eddSChristophe Roullier .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186, 20947a4c4eddSChristophe Roullier .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186 20957a4c4eddSChristophe Roullier }; 20967a4c4eddSChristophe Roullier 2097ba4dfef1SStephen Warren static const struct eqos_config eqos_tegra186_config = { 2098ba4dfef1SStephen Warren .reg_access_always_ok = false, 20997a4c4eddSChristophe Roullier .mdio_wait = 10, 21007a4c4eddSChristophe Roullier .swr_wait = 10, 21017a4c4eddSChristophe Roullier .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, 21027a4c4eddSChristophe Roullier .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35, 21037a4c4eddSChristophe Roullier .interface = eqos_get_interface_tegra186, 21047a4c4eddSChristophe Roullier .ops = &eqos_tegra186_ops 21057a4c4eddSChristophe Roullier }; 21067a4c4eddSChristophe Roullier 21077a4c4eddSChristophe Roullier static struct eqos_ops eqos_stm32_ops = { 2108a7b3400fSFugang Duan .eqos_inval_desc = eqos_inval_desc_generic, 2109a7b3400fSFugang Duan .eqos_flush_desc = eqos_flush_desc_generic, 2110a7b3400fSFugang Duan .eqos_inval_buffer = eqos_inval_buffer_generic, 2111a7b3400fSFugang Duan .eqos_flush_buffer = eqos_flush_buffer_generic, 21127a4c4eddSChristophe Roullier .eqos_probe_resources = eqos_probe_resources_stm32, 21137a4c4eddSChristophe Roullier .eqos_remove_resources = eqos_remove_resources_stm32, 21147a4c4eddSChristophe Roullier .eqos_stop_resets = eqos_stop_resets_stm32, 21157a4c4eddSChristophe Roullier .eqos_start_resets = eqos_start_resets_stm32, 21167a4c4eddSChristophe Roullier .eqos_stop_clks = eqos_stop_clks_stm32, 21177a4c4eddSChristophe Roullier .eqos_start_clks = eqos_start_clks_stm32, 21187a4c4eddSChristophe Roullier .eqos_calibrate_pads = eqos_calibrate_pads_stm32, 21197a4c4eddSChristophe Roullier .eqos_disable_calibration = eqos_disable_calibration_stm32, 21207a4c4eddSChristophe Roullier .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_stm32, 21217a4c4eddSChristophe Roullier .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 21227a4c4eddSChristophe Roullier }; 21237a4c4eddSChristophe Roullier 21247a4c4eddSChristophe Roullier static const struct eqos_config eqos_stm32_config = { 21257a4c4eddSChristophe Roullier .reg_access_always_ok = false, 21267a4c4eddSChristophe Roullier .mdio_wait = 10000, 21277a4c4eddSChristophe Roullier .swr_wait = 50, 21287a4c4eddSChristophe Roullier .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, 21297a4c4eddSChristophe Roullier .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, 21307a4c4eddSChristophe Roullier .interface = eqos_get_interface_stm32, 21317a4c4eddSChristophe Roullier .ops = &eqos_stm32_ops 2132ba4dfef1SStephen Warren }; 2133ba4dfef1SStephen Warren 2134a7b3400fSFugang Duan static struct eqos_ops eqos_imx_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, 2139a7b3400fSFugang Duan .eqos_probe_resources = eqos_probe_resources_imx, 2140a7b3400fSFugang Duan .eqos_remove_resources = eqos_remove_resources_imx, 2141a7b3400fSFugang Duan .eqos_stop_resets = eqos_stop_resets_imx, 2142a7b3400fSFugang Duan .eqos_start_resets = eqos_start_resets_imx, 2143a7b3400fSFugang Duan .eqos_stop_clks = eqos_stop_clks_imx, 2144a7b3400fSFugang Duan .eqos_start_clks = eqos_start_clks_imx, 2145a7b3400fSFugang Duan .eqos_calibrate_pads = eqos_calibrate_pads_imx, 2146a7b3400fSFugang Duan .eqos_disable_calibration = eqos_disable_calibration_imx, 2147a7b3400fSFugang Duan .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_imx, 2148a7b3400fSFugang Duan .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_imx 2149a7b3400fSFugang Duan }; 2150a7b3400fSFugang Duan 2151a7b3400fSFugang Duan struct eqos_config eqos_imx_config = { 2152a7b3400fSFugang Duan .reg_access_always_ok = false, 2153a7b3400fSFugang Duan .mdio_wait = 10000, 2154a7b3400fSFugang Duan .swr_wait = 50, 2155a7b3400fSFugang Duan .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, 2156a7b3400fSFugang Duan .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, 2157a7b3400fSFugang Duan .interface = eqos_get_interface_imx, 2158a7b3400fSFugang Duan .ops = &eqos_imx_ops 2159a7b3400fSFugang Duan }; 2160a7b3400fSFugang Duan 2161ba4dfef1SStephen Warren static const struct udevice_id eqos_ids[] = { 2162ba4dfef1SStephen Warren { 2163ba4dfef1SStephen Warren .compatible = "nvidia,tegra186-eqos", 2164ba4dfef1SStephen Warren .data = (ulong)&eqos_tegra186_config 2165ba4dfef1SStephen Warren }, 21667a4c4eddSChristophe Roullier { 21677a4c4eddSChristophe Roullier .compatible = "snps,dwmac-4.20a", 21687a4c4eddSChristophe Roullier .data = (ulong)&eqos_stm32_config 21697a4c4eddSChristophe Roullier }, 2170a7b3400fSFugang Duan { 2171a7b3400fSFugang Duan .compatible = "fsl,imx-eqos", 2172a7b3400fSFugang Duan .data = (ulong)&eqos_imx_config 2173a7b3400fSFugang Duan }, 21747a4c4eddSChristophe Roullier 2175ba4dfef1SStephen Warren { } 2176ba4dfef1SStephen Warren }; 2177ba4dfef1SStephen Warren 2178ba4dfef1SStephen Warren U_BOOT_DRIVER(eth_eqos) = { 2179ba4dfef1SStephen Warren .name = "eth_eqos", 2180ba4dfef1SStephen Warren .id = UCLASS_ETH, 2181a7b3400fSFugang Duan .of_match = of_match_ptr(eqos_ids), 2182ba4dfef1SStephen Warren .probe = eqos_probe, 2183ba4dfef1SStephen Warren .remove = eqos_remove, 2184ba4dfef1SStephen Warren .ops = &eqos_ops, 2185ba4dfef1SStephen Warren .priv_auto_alloc_size = sizeof(struct eqos_priv), 2186ba4dfef1SStephen Warren .platdata_auto_alloc_size = sizeof(struct eth_pdata), 2187ba4dfef1SStephen Warren }; 2188