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> 43*8e3eceb0SYe Li #include <eth_phy.h> 44ba4dfef1SStephen Warren 45ba4dfef1SStephen Warren /* Core registers */ 46ba4dfef1SStephen Warren 47ba4dfef1SStephen Warren #define EQOS_MAC_REGS_BASE 0x000 48ba4dfef1SStephen Warren struct eqos_mac_regs { 49ba4dfef1SStephen Warren uint32_t configuration; /* 0x000 */ 50ba4dfef1SStephen Warren uint32_t unused_004[(0x070 - 0x004) / 4]; /* 0x004 */ 51ba4dfef1SStephen Warren uint32_t q0_tx_flow_ctrl; /* 0x070 */ 52ba4dfef1SStephen Warren uint32_t unused_070[(0x090 - 0x074) / 4]; /* 0x074 */ 53ba4dfef1SStephen Warren uint32_t rx_flow_ctrl; /* 0x090 */ 54ba4dfef1SStephen Warren uint32_t unused_094; /* 0x094 */ 55ba4dfef1SStephen Warren uint32_t txq_prty_map0; /* 0x098 */ 56ba4dfef1SStephen Warren uint32_t unused_09c; /* 0x09c */ 57ba4dfef1SStephen Warren uint32_t rxq_ctrl0; /* 0x0a0 */ 58ba4dfef1SStephen Warren uint32_t unused_0a4; /* 0x0a4 */ 59ba4dfef1SStephen Warren uint32_t rxq_ctrl2; /* 0x0a8 */ 60ba4dfef1SStephen Warren uint32_t unused_0ac[(0x0dc - 0x0ac) / 4]; /* 0x0ac */ 61ba4dfef1SStephen Warren uint32_t us_tic_counter; /* 0x0dc */ 62ba4dfef1SStephen Warren uint32_t unused_0e0[(0x11c - 0x0e0) / 4]; /* 0x0e0 */ 63ba4dfef1SStephen Warren uint32_t hw_feature0; /* 0x11c */ 64ba4dfef1SStephen Warren uint32_t hw_feature1; /* 0x120 */ 65ba4dfef1SStephen Warren uint32_t hw_feature2; /* 0x124 */ 66ba4dfef1SStephen Warren uint32_t unused_128[(0x200 - 0x128) / 4]; /* 0x128 */ 67ba4dfef1SStephen Warren uint32_t mdio_address; /* 0x200 */ 68ba4dfef1SStephen Warren uint32_t mdio_data; /* 0x204 */ 69ba4dfef1SStephen Warren uint32_t unused_208[(0x300 - 0x208) / 4]; /* 0x208 */ 70ba4dfef1SStephen Warren uint32_t address0_high; /* 0x300 */ 71ba4dfef1SStephen Warren uint32_t address0_low; /* 0x304 */ 72ba4dfef1SStephen Warren }; 73ba4dfef1SStephen Warren 74ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_GPSLCE BIT(23) 75ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_CST BIT(21) 76ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_ACS BIT(20) 77ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_WD BIT(19) 78ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_JD BIT(17) 79ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_JE BIT(16) 80ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_PS BIT(15) 81ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_FES BIT(14) 82ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_DM BIT(13) 83ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_TE BIT(1) 84ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_RE BIT(0) 85ba4dfef1SStephen Warren 86ba4dfef1SStephen Warren #define EQOS_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT 16 87ba4dfef1SStephen Warren #define EQOS_MAC_Q0_TX_FLOW_CTRL_PT_MASK 0xffff 88ba4dfef1SStephen Warren #define EQOS_MAC_Q0_TX_FLOW_CTRL_TFE BIT(1) 89ba4dfef1SStephen Warren 90ba4dfef1SStephen Warren #define EQOS_MAC_RX_FLOW_CTRL_RFE BIT(0) 91ba4dfef1SStephen Warren 92ba4dfef1SStephen Warren #define EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_SHIFT 0 93ba4dfef1SStephen Warren #define EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_MASK 0xff 94ba4dfef1SStephen Warren 95ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT 0 96ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK 3 97ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_NOT_ENABLED 0 98ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB 2 997a4c4eddSChristophe Roullier #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV 1 100ba4dfef1SStephen Warren 101ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT 0 102ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK 0xff 103ba4dfef1SStephen Warren 104ba4dfef1SStephen Warren #define EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_SHIFT 6 105ba4dfef1SStephen Warren #define EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_MASK 0x1f 106ba4dfef1SStephen Warren #define EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT 0 107ba4dfef1SStephen Warren #define EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK 0x1f 108ba4dfef1SStephen Warren 109ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_PA_SHIFT 21 110ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT 16 111ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT 8 112ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_CR_20_35 2 1137a4c4eddSChristophe Roullier #define EQOS_MAC_MDIO_ADDRESS_CR_250_300 5 114ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_SKAP BIT(4) 115ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT 2 116ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_GOC_READ 3 117ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_GOC_WRITE 1 118ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_C45E BIT(1) 119ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_GB BIT(0) 120ba4dfef1SStephen Warren 121ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_DATA_GD_MASK 0xffff 122ba4dfef1SStephen Warren 123ba4dfef1SStephen Warren #define EQOS_MTL_REGS_BASE 0xd00 124ba4dfef1SStephen Warren struct eqos_mtl_regs { 125ba4dfef1SStephen Warren uint32_t txq0_operation_mode; /* 0xd00 */ 126ba4dfef1SStephen Warren uint32_t unused_d04; /* 0xd04 */ 127ba4dfef1SStephen Warren uint32_t txq0_debug; /* 0xd08 */ 128ba4dfef1SStephen Warren uint32_t unused_d0c[(0xd18 - 0xd0c) / 4]; /* 0xd0c */ 129ba4dfef1SStephen Warren uint32_t txq0_quantum_weight; /* 0xd18 */ 130ba4dfef1SStephen Warren uint32_t unused_d1c[(0xd30 - 0xd1c) / 4]; /* 0xd1c */ 131ba4dfef1SStephen Warren uint32_t rxq0_operation_mode; /* 0xd30 */ 132ba4dfef1SStephen Warren uint32_t unused_d34; /* 0xd34 */ 133ba4dfef1SStephen Warren uint32_t rxq0_debug; /* 0xd38 */ 134ba4dfef1SStephen Warren }; 135ba4dfef1SStephen Warren 136ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT 16 137ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK 0x1ff 138ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_SHIFT 2 139ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_MASK 3 140ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_ENABLED 2 141ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TSF BIT(1) 142ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_FTQ BIT(0) 143ba4dfef1SStephen Warren 144ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_DEBUG_TXQSTS BIT(4) 145ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_DEBUG_TRCSTS_SHIFT 1 146ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_DEBUG_TRCSTS_MASK 3 147ba4dfef1SStephen Warren 148ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT 20 149ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RQS_MASK 0x3ff 150ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT 14 151ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RFD_MASK 0x3f 152ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT 8 153ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RFA_MASK 0x3f 154ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_EHFC BIT(7) 155ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RSF BIT(5) 156ba4dfef1SStephen Warren 157ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_DEBUG_PRXQ_SHIFT 16 158ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_DEBUG_PRXQ_MASK 0x7fff 159ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_DEBUG_RXQSTS_SHIFT 4 160ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_DEBUG_RXQSTS_MASK 3 161ba4dfef1SStephen Warren 162ba4dfef1SStephen Warren #define EQOS_DMA_REGS_BASE 0x1000 163ba4dfef1SStephen Warren struct eqos_dma_regs { 164ba4dfef1SStephen Warren uint32_t mode; /* 0x1000 */ 165ba4dfef1SStephen Warren uint32_t sysbus_mode; /* 0x1004 */ 166ba4dfef1SStephen Warren uint32_t unused_1008[(0x1100 - 0x1008) / 4]; /* 0x1008 */ 167ba4dfef1SStephen Warren uint32_t ch0_control; /* 0x1100 */ 168ba4dfef1SStephen Warren uint32_t ch0_tx_control; /* 0x1104 */ 169ba4dfef1SStephen Warren uint32_t ch0_rx_control; /* 0x1108 */ 170ba4dfef1SStephen Warren uint32_t unused_110c; /* 0x110c */ 171ba4dfef1SStephen Warren uint32_t ch0_txdesc_list_haddress; /* 0x1110 */ 172ba4dfef1SStephen Warren uint32_t ch0_txdesc_list_address; /* 0x1114 */ 173ba4dfef1SStephen Warren uint32_t ch0_rxdesc_list_haddress; /* 0x1118 */ 174ba4dfef1SStephen Warren uint32_t ch0_rxdesc_list_address; /* 0x111c */ 175ba4dfef1SStephen Warren uint32_t ch0_txdesc_tail_pointer; /* 0x1120 */ 176ba4dfef1SStephen Warren uint32_t unused_1124; /* 0x1124 */ 177ba4dfef1SStephen Warren uint32_t ch0_rxdesc_tail_pointer; /* 0x1128 */ 178ba4dfef1SStephen Warren uint32_t ch0_txdesc_ring_length; /* 0x112c */ 179ba4dfef1SStephen Warren uint32_t ch0_rxdesc_ring_length; /* 0x1130 */ 180ba4dfef1SStephen Warren }; 181ba4dfef1SStephen Warren 182ba4dfef1SStephen Warren #define EQOS_DMA_MODE_SWR BIT(0) 183ba4dfef1SStephen Warren 184ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_SHIFT 16 185ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_MASK 0xf 186ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_EAME BIT(11) 187ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_BLEN16 BIT(3) 188ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_BLEN8 BIT(2) 189ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_BLEN4 BIT(1) 190ba4dfef1SStephen Warren 191ba4dfef1SStephen Warren #define EQOS_DMA_CH0_CONTROL_PBLX8 BIT(16) 192ba4dfef1SStephen Warren 193ba4dfef1SStephen Warren #define EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT 16 194ba4dfef1SStephen Warren #define EQOS_DMA_CH0_TX_CONTROL_TXPBL_MASK 0x3f 195ba4dfef1SStephen Warren #define EQOS_DMA_CH0_TX_CONTROL_OSP BIT(4) 196ba4dfef1SStephen Warren #define EQOS_DMA_CH0_TX_CONTROL_ST BIT(0) 197ba4dfef1SStephen Warren 198ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT 16 199ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_RXPBL_MASK 0x3f 200ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT 1 201ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_RBSZ_MASK 0x3fff 202ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_SR BIT(0) 203ba4dfef1SStephen Warren 204ba4dfef1SStephen Warren /* These registers are Tegra186-specific */ 205ba4dfef1SStephen Warren #define EQOS_TEGRA186_REGS_BASE 0x8800 206ba4dfef1SStephen Warren struct eqos_tegra186_regs { 207ba4dfef1SStephen Warren uint32_t sdmemcomppadctrl; /* 0x8800 */ 208ba4dfef1SStephen Warren uint32_t auto_cal_config; /* 0x8804 */ 209ba4dfef1SStephen Warren uint32_t unused_8808; /* 0x8808 */ 210ba4dfef1SStephen Warren uint32_t auto_cal_status; /* 0x880c */ 211ba4dfef1SStephen Warren }; 212ba4dfef1SStephen Warren 213ba4dfef1SStephen Warren #define EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31) 214ba4dfef1SStephen Warren 215ba4dfef1SStephen Warren #define EQOS_AUTO_CAL_CONFIG_START BIT(31) 216ba4dfef1SStephen Warren #define EQOS_AUTO_CAL_CONFIG_ENABLE BIT(29) 217ba4dfef1SStephen Warren 218ba4dfef1SStephen Warren #define EQOS_AUTO_CAL_STATUS_ACTIVE BIT(31) 219ba4dfef1SStephen Warren 220ba4dfef1SStephen Warren /* Descriptors */ 221ba4dfef1SStephen Warren 222ba4dfef1SStephen Warren #define EQOS_DESCRIPTOR_WORDS 4 223ba4dfef1SStephen Warren #define EQOS_DESCRIPTOR_SIZE (EQOS_DESCRIPTOR_WORDS * 4) 224ba4dfef1SStephen Warren /* We assume ARCH_DMA_MINALIGN >= 16; 16 is the EQOS HW minimum */ 225ba4dfef1SStephen Warren #define EQOS_DESCRIPTOR_ALIGN ARCH_DMA_MINALIGN 226ba4dfef1SStephen Warren #define EQOS_DESCRIPTORS_TX 4 227ba4dfef1SStephen Warren #define EQOS_DESCRIPTORS_RX 4 228ba4dfef1SStephen Warren #define EQOS_DESCRIPTORS_NUM (EQOS_DESCRIPTORS_TX + EQOS_DESCRIPTORS_RX) 229ba4dfef1SStephen Warren #define EQOS_DESCRIPTORS_SIZE ALIGN(EQOS_DESCRIPTORS_NUM * \ 230ba4dfef1SStephen Warren EQOS_DESCRIPTOR_SIZE, ARCH_DMA_MINALIGN) 231ba4dfef1SStephen Warren #define EQOS_BUFFER_ALIGN ARCH_DMA_MINALIGN 232ba4dfef1SStephen Warren #define EQOS_MAX_PACKET_SIZE ALIGN(1568, ARCH_DMA_MINALIGN) 233ba4dfef1SStephen Warren #define EQOS_RX_BUFFER_SIZE (EQOS_DESCRIPTORS_RX * EQOS_MAX_PACKET_SIZE) 234ba4dfef1SStephen Warren 235ba4dfef1SStephen Warren /* 236ba4dfef1SStephen Warren * Warn if the cache-line size is larger than the descriptor size. In such 237ba4dfef1SStephen Warren * cases the driver will likely fail because the CPU needs to flush the cache 238ba4dfef1SStephen Warren * when requeuing RX buffers, therefore descriptors written by the hardware 239ba4dfef1SStephen Warren * may be discarded. Architectures with full IO coherence, such as x86, do not 240ba4dfef1SStephen Warren * experience this issue, and hence are excluded from this condition. 241ba4dfef1SStephen Warren * 242ba4dfef1SStephen Warren * This can be fixed by defining CONFIG_SYS_NONCACHED_MEMORY which will cause 243ba4dfef1SStephen Warren * the driver to allocate descriptors from a pool of non-cached memory. 244ba4dfef1SStephen Warren */ 245ba4dfef1SStephen Warren #if EQOS_DESCRIPTOR_SIZE < ARCH_DMA_MINALIGN 246ba4dfef1SStephen Warren #if !defined(CONFIG_SYS_NONCACHED_MEMORY) && \ 247ba4dfef1SStephen Warren !defined(CONFIG_SYS_DCACHE_OFF) && !defined(CONFIG_X86) 248ba4dfef1SStephen Warren #warning Cache line size is larger than descriptor size 249ba4dfef1SStephen Warren #endif 250ba4dfef1SStephen Warren #endif 251ba4dfef1SStephen Warren 252ba4dfef1SStephen Warren struct eqos_desc { 253ba4dfef1SStephen Warren u32 des0; 254ba4dfef1SStephen Warren u32 des1; 255ba4dfef1SStephen Warren u32 des2; 256ba4dfef1SStephen Warren u32 des3; 257ba4dfef1SStephen Warren }; 258ba4dfef1SStephen Warren 259ba4dfef1SStephen Warren #define EQOS_DESC3_OWN BIT(31) 260ba4dfef1SStephen Warren #define EQOS_DESC3_FD BIT(29) 261ba4dfef1SStephen Warren #define EQOS_DESC3_LD BIT(28) 262ba4dfef1SStephen Warren #define EQOS_DESC3_BUF1V BIT(24) 263ba4dfef1SStephen Warren 264ba4dfef1SStephen Warren struct eqos_config { 265ba4dfef1SStephen Warren bool reg_access_always_ok; 2667a4c4eddSChristophe Roullier int mdio_wait; 2677a4c4eddSChristophe Roullier int swr_wait; 2687a4c4eddSChristophe Roullier int config_mac; 2697a4c4eddSChristophe Roullier int config_mac_mdio; 2707a4c4eddSChristophe Roullier phy_interface_t (*interface)(struct udevice *dev); 2717a4c4eddSChristophe Roullier struct eqos_ops *ops; 2727a4c4eddSChristophe Roullier }; 2737a4c4eddSChristophe Roullier 2747a4c4eddSChristophe Roullier struct eqos_ops { 2757a4c4eddSChristophe Roullier void (*eqos_inval_desc)(void *desc); 2767a4c4eddSChristophe Roullier void (*eqos_flush_desc)(void *desc); 2777a4c4eddSChristophe Roullier void (*eqos_inval_buffer)(void *buf, size_t size); 2787a4c4eddSChristophe Roullier void (*eqos_flush_buffer)(void *buf, size_t size); 2797a4c4eddSChristophe Roullier int (*eqos_probe_resources)(struct udevice *dev); 2807a4c4eddSChristophe Roullier int (*eqos_remove_resources)(struct udevice *dev); 2817a4c4eddSChristophe Roullier int (*eqos_stop_resets)(struct udevice *dev); 2827a4c4eddSChristophe Roullier int (*eqos_start_resets)(struct udevice *dev); 2837a4c4eddSChristophe Roullier void (*eqos_stop_clks)(struct udevice *dev); 2847a4c4eddSChristophe Roullier int (*eqos_start_clks)(struct udevice *dev); 2857a4c4eddSChristophe Roullier int (*eqos_calibrate_pads)(struct udevice *dev); 2867a4c4eddSChristophe Roullier int (*eqos_disable_calibration)(struct udevice *dev); 2877a4c4eddSChristophe Roullier int (*eqos_set_tx_clk_speed)(struct udevice *dev); 2887a4c4eddSChristophe Roullier ulong (*eqos_get_tick_clk_rate)(struct udevice *dev); 289ba4dfef1SStephen Warren }; 290ba4dfef1SStephen Warren 291ba4dfef1SStephen Warren struct eqos_priv { 292ba4dfef1SStephen Warren struct udevice *dev; 293ba4dfef1SStephen Warren const struct eqos_config *config; 294ba4dfef1SStephen Warren fdt_addr_t regs; 295ba4dfef1SStephen Warren struct eqos_mac_regs *mac_regs; 296ba4dfef1SStephen Warren struct eqos_mtl_regs *mtl_regs; 297ba4dfef1SStephen Warren struct eqos_dma_regs *dma_regs; 298ba4dfef1SStephen Warren struct eqos_tegra186_regs *tegra186_regs; 299ba4dfef1SStephen Warren struct reset_ctl reset_ctl; 300ba4dfef1SStephen Warren struct gpio_desc phy_reset_gpio; 301ba4dfef1SStephen Warren struct clk clk_master_bus; 302ba4dfef1SStephen Warren struct clk clk_rx; 303ba4dfef1SStephen Warren struct clk clk_ptp_ref; 304ba4dfef1SStephen Warren struct clk clk_tx; 3057a4c4eddSChristophe Roullier struct clk clk_ck; 306ba4dfef1SStephen Warren struct clk clk_slave_bus; 307ba4dfef1SStephen Warren struct mii_dev *mii; 308ba4dfef1SStephen Warren struct phy_device *phy; 30983d31c08SPatrick Delaunay int phyaddr; 31083d31c08SPatrick Delaunay u32 max_speed; 311ba4dfef1SStephen Warren void *descs; 312ba4dfef1SStephen Warren struct eqos_desc *tx_descs; 313ba4dfef1SStephen Warren struct eqos_desc *rx_descs; 314ba4dfef1SStephen Warren int tx_desc_idx, rx_desc_idx; 315ba4dfef1SStephen Warren void *tx_dma_buf; 316ba4dfef1SStephen Warren void *rx_dma_buf; 317ba4dfef1SStephen Warren void *rx_pkt; 318ba4dfef1SStephen Warren bool started; 319ba4dfef1SStephen Warren bool reg_access_ok; 320ba4dfef1SStephen Warren }; 321ba4dfef1SStephen Warren 322ba4dfef1SStephen Warren /* 323ba4dfef1SStephen Warren * TX and RX descriptors are 16 bytes. This causes problems with the cache 324ba4dfef1SStephen Warren * maintenance on CPUs where the cache-line size exceeds the size of these 325ba4dfef1SStephen Warren * descriptors. What will happen is that when the driver receives a packet 326ba4dfef1SStephen Warren * it will be immediately requeued for the hardware to reuse. The CPU will 327ba4dfef1SStephen Warren * therefore need to flush the cache-line containing the descriptor, which 328ba4dfef1SStephen Warren * will cause all other descriptors in the same cache-line to be flushed 329ba4dfef1SStephen Warren * along with it. If one of those descriptors had been written to by the 330ba4dfef1SStephen Warren * device those changes (and the associated packet) will be lost. 331ba4dfef1SStephen Warren * 332ba4dfef1SStephen Warren * To work around this, we make use of non-cached memory if available. If 333ba4dfef1SStephen Warren * descriptors are mapped uncached there's no need to manually flush them 334ba4dfef1SStephen Warren * or invalidate them. 335ba4dfef1SStephen Warren * 336ba4dfef1SStephen Warren * Note that this only applies to descriptors. The packet data buffers do 337ba4dfef1SStephen Warren * not have the same constraints since they are 1536 bytes large, so they 338ba4dfef1SStephen Warren * are unlikely to share cache-lines. 339ba4dfef1SStephen Warren */ 340ba4dfef1SStephen Warren static void *eqos_alloc_descs(unsigned int num) 341ba4dfef1SStephen Warren { 342ba4dfef1SStephen Warren #ifdef CONFIG_SYS_NONCACHED_MEMORY 343ba4dfef1SStephen Warren return (void *)noncached_alloc(EQOS_DESCRIPTORS_SIZE, 344ba4dfef1SStephen Warren EQOS_DESCRIPTOR_ALIGN); 345ba4dfef1SStephen Warren #else 346ba4dfef1SStephen Warren return memalign(EQOS_DESCRIPTOR_ALIGN, EQOS_DESCRIPTORS_SIZE); 347ba4dfef1SStephen Warren #endif 348ba4dfef1SStephen Warren } 349ba4dfef1SStephen Warren 350ba4dfef1SStephen Warren static void eqos_free_descs(void *descs) 351ba4dfef1SStephen Warren { 352ba4dfef1SStephen Warren #ifdef CONFIG_SYS_NONCACHED_MEMORY 353ba4dfef1SStephen Warren /* FIXME: noncached_alloc() has no opposite */ 354ba4dfef1SStephen Warren #else 355ba4dfef1SStephen Warren free(descs); 356ba4dfef1SStephen Warren #endif 357ba4dfef1SStephen Warren } 358ba4dfef1SStephen Warren 3597a4c4eddSChristophe Roullier static void eqos_inval_desc_tegra186(void *desc) 360ba4dfef1SStephen Warren { 361ba4dfef1SStephen Warren #ifndef CONFIG_SYS_NONCACHED_MEMORY 362ba4dfef1SStephen Warren unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1); 363ba4dfef1SStephen Warren unsigned long end = ALIGN(start + EQOS_DESCRIPTOR_SIZE, 364ba4dfef1SStephen Warren ARCH_DMA_MINALIGN); 365ba4dfef1SStephen Warren 366ba4dfef1SStephen Warren invalidate_dcache_range(start, end); 367ba4dfef1SStephen Warren #endif 368ba4dfef1SStephen Warren } 369ba4dfef1SStephen Warren 3707a4c4eddSChristophe Roullier static void eqos_inval_desc_stm32(void *desc) 3717a4c4eddSChristophe Roullier { 3727a4c4eddSChristophe Roullier #ifndef CONFIG_SYS_NONCACHED_MEMORY 3737a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); 3747a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, 3757a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 3767a4c4eddSChristophe Roullier 3777a4c4eddSChristophe Roullier invalidate_dcache_range(start, end); 3787a4c4eddSChristophe Roullier #endif 3797a4c4eddSChristophe Roullier } 3807a4c4eddSChristophe Roullier 3817a4c4eddSChristophe Roullier static void eqos_flush_desc_tegra186(void *desc) 382ba4dfef1SStephen Warren { 383ba4dfef1SStephen Warren #ifndef CONFIG_SYS_NONCACHED_MEMORY 384ba4dfef1SStephen Warren flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE); 385ba4dfef1SStephen Warren #endif 386ba4dfef1SStephen Warren } 387ba4dfef1SStephen Warren 3887a4c4eddSChristophe Roullier static void eqos_flush_desc_stm32(void *desc) 3897a4c4eddSChristophe Roullier { 3907a4c4eddSChristophe Roullier #ifndef CONFIG_SYS_NONCACHED_MEMORY 3917a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); 3927a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, 3937a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 3947a4c4eddSChristophe Roullier 3957a4c4eddSChristophe Roullier flush_dcache_range(start, end); 3967a4c4eddSChristophe Roullier #endif 3977a4c4eddSChristophe Roullier } 3987a4c4eddSChristophe Roullier 3997a4c4eddSChristophe Roullier static void eqos_inval_buffer_tegra186(void *buf, size_t size) 400ba4dfef1SStephen Warren { 401ba4dfef1SStephen Warren unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1); 402ba4dfef1SStephen Warren unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN); 403ba4dfef1SStephen Warren 404ba4dfef1SStephen Warren invalidate_dcache_range(start, end); 405ba4dfef1SStephen Warren } 406ba4dfef1SStephen Warren 4077a4c4eddSChristophe Roullier static void eqos_inval_buffer_stm32(void *buf, size_t size) 4087a4c4eddSChristophe Roullier { 4097a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN); 4107a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)buf + size, 4117a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 4127a4c4eddSChristophe Roullier 4137a4c4eddSChristophe Roullier invalidate_dcache_range(start, end); 4147a4c4eddSChristophe Roullier } 4157a4c4eddSChristophe Roullier 4167a4c4eddSChristophe Roullier static void eqos_flush_buffer_tegra186(void *buf, size_t size) 417ba4dfef1SStephen Warren { 418ba4dfef1SStephen Warren flush_cache((unsigned long)buf, size); 419ba4dfef1SStephen Warren } 420ba4dfef1SStephen Warren 4217a4c4eddSChristophe Roullier static void eqos_flush_buffer_stm32(void *buf, size_t size) 4227a4c4eddSChristophe Roullier { 4237a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN); 4247a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)buf + size, 4257a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 4267a4c4eddSChristophe Roullier 4277a4c4eddSChristophe Roullier flush_dcache_range(start, end); 4287a4c4eddSChristophe Roullier } 4297a4c4eddSChristophe Roullier 430ba4dfef1SStephen Warren static int eqos_mdio_wait_idle(struct eqos_priv *eqos) 431ba4dfef1SStephen Warren { 432b491b498SJon Lin return wait_for_bit_le32(&eqos->mac_regs->mdio_address, 433b491b498SJon Lin EQOS_MAC_MDIO_ADDRESS_GB, false, 434b491b498SJon Lin 1000000, true); 435ba4dfef1SStephen Warren } 436ba4dfef1SStephen Warren 437ba4dfef1SStephen Warren static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad, 438ba4dfef1SStephen Warren int mdio_reg) 439ba4dfef1SStephen Warren { 440ba4dfef1SStephen Warren struct eqos_priv *eqos = bus->priv; 441ba4dfef1SStephen Warren u32 val; 442ba4dfef1SStephen Warren int ret; 443ba4dfef1SStephen Warren 444ba4dfef1SStephen Warren debug("%s(dev=%p, addr=%x, reg=%d):\n", __func__, eqos->dev, mdio_addr, 445ba4dfef1SStephen Warren mdio_reg); 446ba4dfef1SStephen Warren 447ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 448ba4dfef1SStephen Warren if (ret) { 44990aa625cSMasahiro Yamada pr_err("MDIO not idle at entry"); 450ba4dfef1SStephen Warren return ret; 451ba4dfef1SStephen Warren } 452ba4dfef1SStephen Warren 453ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->mdio_address); 454ba4dfef1SStephen Warren val &= EQOS_MAC_MDIO_ADDRESS_SKAP | 455ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_C45E; 456ba4dfef1SStephen Warren val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | 457ba4dfef1SStephen Warren (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) | 4587a4c4eddSChristophe Roullier (eqos->config->config_mac_mdio << 459ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | 460ba4dfef1SStephen Warren (EQOS_MAC_MDIO_ADDRESS_GOC_READ << 461ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | 462ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GB; 463ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->mdio_address); 464ba4dfef1SStephen Warren 4657a4c4eddSChristophe Roullier udelay(eqos->config->mdio_wait); 466ba4dfef1SStephen Warren 467ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 468ba4dfef1SStephen Warren if (ret) { 46990aa625cSMasahiro Yamada pr_err("MDIO read didn't complete"); 470ba4dfef1SStephen Warren return ret; 471ba4dfef1SStephen Warren } 472ba4dfef1SStephen Warren 473ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->mdio_data); 474ba4dfef1SStephen Warren val &= EQOS_MAC_MDIO_DATA_GD_MASK; 475ba4dfef1SStephen Warren 476ba4dfef1SStephen Warren debug("%s: val=%x\n", __func__, val); 477ba4dfef1SStephen Warren 478ba4dfef1SStephen Warren return val; 479ba4dfef1SStephen Warren } 480ba4dfef1SStephen Warren 481ba4dfef1SStephen Warren static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad, 482ba4dfef1SStephen Warren int mdio_reg, u16 mdio_val) 483ba4dfef1SStephen Warren { 484ba4dfef1SStephen Warren struct eqos_priv *eqos = bus->priv; 485ba4dfef1SStephen Warren u32 val; 486ba4dfef1SStephen Warren int ret; 487ba4dfef1SStephen Warren 488ba4dfef1SStephen Warren debug("%s(dev=%p, addr=%x, reg=%d, val=%x):\n", __func__, eqos->dev, 489ba4dfef1SStephen Warren mdio_addr, mdio_reg, mdio_val); 490ba4dfef1SStephen Warren 491ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 492ba4dfef1SStephen Warren if (ret) { 49390aa625cSMasahiro Yamada pr_err("MDIO not idle at entry"); 494ba4dfef1SStephen Warren return ret; 495ba4dfef1SStephen Warren } 496ba4dfef1SStephen Warren 497ba4dfef1SStephen Warren writel(mdio_val, &eqos->mac_regs->mdio_data); 498ba4dfef1SStephen Warren 499ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->mdio_address); 500ba4dfef1SStephen Warren val &= EQOS_MAC_MDIO_ADDRESS_SKAP | 501ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_C45E; 502ba4dfef1SStephen Warren val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | 503ba4dfef1SStephen Warren (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) | 5047a4c4eddSChristophe Roullier (eqos->config->config_mac_mdio << 505ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | 506ba4dfef1SStephen Warren (EQOS_MAC_MDIO_ADDRESS_GOC_WRITE << 507ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | 508ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GB; 509ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->mdio_address); 510ba4dfef1SStephen Warren 5117a4c4eddSChristophe Roullier udelay(eqos->config->mdio_wait); 512ba4dfef1SStephen Warren 513ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 514ba4dfef1SStephen Warren if (ret) { 51590aa625cSMasahiro Yamada pr_err("MDIO read didn't complete"); 516ba4dfef1SStephen Warren return ret; 517ba4dfef1SStephen Warren } 518ba4dfef1SStephen Warren 519ba4dfef1SStephen Warren return 0; 520ba4dfef1SStephen Warren } 521ba4dfef1SStephen Warren 522ba4dfef1SStephen Warren static int eqos_start_clks_tegra186(struct udevice *dev) 523ba4dfef1SStephen Warren { 524ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 525ba4dfef1SStephen Warren int ret; 526ba4dfef1SStephen Warren 527ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 528ba4dfef1SStephen Warren 529ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_slave_bus); 530ba4dfef1SStephen Warren if (ret < 0) { 53190aa625cSMasahiro Yamada pr_err("clk_enable(clk_slave_bus) failed: %d", ret); 532ba4dfef1SStephen Warren goto err; 533ba4dfef1SStephen Warren } 534ba4dfef1SStephen Warren 535ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_master_bus); 536ba4dfef1SStephen Warren if (ret < 0) { 53790aa625cSMasahiro Yamada pr_err("clk_enable(clk_master_bus) failed: %d", ret); 538ba4dfef1SStephen Warren goto err_disable_clk_slave_bus; 539ba4dfef1SStephen Warren } 540ba4dfef1SStephen Warren 541ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_rx); 542ba4dfef1SStephen Warren if (ret < 0) { 54390aa625cSMasahiro Yamada pr_err("clk_enable(clk_rx) failed: %d", ret); 544ba4dfef1SStephen Warren goto err_disable_clk_master_bus; 545ba4dfef1SStephen Warren } 546ba4dfef1SStephen Warren 547ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_ptp_ref); 548ba4dfef1SStephen Warren if (ret < 0) { 54990aa625cSMasahiro Yamada pr_err("clk_enable(clk_ptp_ref) failed: %d", ret); 550ba4dfef1SStephen Warren goto err_disable_clk_rx; 551ba4dfef1SStephen Warren } 552ba4dfef1SStephen Warren 553ba4dfef1SStephen Warren ret = clk_set_rate(&eqos->clk_ptp_ref, 125 * 1000 * 1000); 554ba4dfef1SStephen Warren if (ret < 0) { 55590aa625cSMasahiro Yamada pr_err("clk_set_rate(clk_ptp_ref) failed: %d", ret); 556ba4dfef1SStephen Warren goto err_disable_clk_ptp_ref; 557ba4dfef1SStephen Warren } 558ba4dfef1SStephen Warren 559ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_tx); 560ba4dfef1SStephen Warren if (ret < 0) { 56190aa625cSMasahiro Yamada pr_err("clk_enable(clk_tx) failed: %d", ret); 562ba4dfef1SStephen Warren goto err_disable_clk_ptp_ref; 563ba4dfef1SStephen Warren } 564ba4dfef1SStephen Warren 565ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 566ba4dfef1SStephen Warren return 0; 567ba4dfef1SStephen Warren 568ba4dfef1SStephen Warren err_disable_clk_ptp_ref: 569ba4dfef1SStephen Warren clk_disable(&eqos->clk_ptp_ref); 570ba4dfef1SStephen Warren err_disable_clk_rx: 571ba4dfef1SStephen Warren clk_disable(&eqos->clk_rx); 572ba4dfef1SStephen Warren err_disable_clk_master_bus: 573ba4dfef1SStephen Warren clk_disable(&eqos->clk_master_bus); 574ba4dfef1SStephen Warren err_disable_clk_slave_bus: 575ba4dfef1SStephen Warren clk_disable(&eqos->clk_slave_bus); 576ba4dfef1SStephen Warren err: 577ba4dfef1SStephen Warren debug("%s: FAILED: %d\n", __func__, ret); 578ba4dfef1SStephen Warren return ret; 579ba4dfef1SStephen Warren } 580ba4dfef1SStephen Warren 5817a4c4eddSChristophe Roullier static int eqos_start_clks_stm32(struct udevice *dev) 5827a4c4eddSChristophe Roullier { 5837a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 5847a4c4eddSChristophe Roullier int ret; 5857a4c4eddSChristophe Roullier 5867a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 5877a4c4eddSChristophe Roullier 5887a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_master_bus); 5897a4c4eddSChristophe Roullier if (ret < 0) { 5907a4c4eddSChristophe Roullier pr_err("clk_enable(clk_master_bus) failed: %d", ret); 5917a4c4eddSChristophe Roullier goto err; 5927a4c4eddSChristophe Roullier } 5937a4c4eddSChristophe Roullier 5947a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_rx); 5957a4c4eddSChristophe Roullier if (ret < 0) { 5967a4c4eddSChristophe Roullier pr_err("clk_enable(clk_rx) failed: %d", ret); 5977a4c4eddSChristophe Roullier goto err_disable_clk_master_bus; 5987a4c4eddSChristophe Roullier } 5997a4c4eddSChristophe Roullier 6007a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_tx); 6017a4c4eddSChristophe Roullier if (ret < 0) { 6027a4c4eddSChristophe Roullier pr_err("clk_enable(clk_tx) failed: %d", ret); 6037a4c4eddSChristophe Roullier goto err_disable_clk_rx; 6047a4c4eddSChristophe Roullier } 6057a4c4eddSChristophe Roullier 6067a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) { 6077a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_ck); 6087a4c4eddSChristophe Roullier if (ret < 0) { 6097a4c4eddSChristophe Roullier pr_err("clk_enable(clk_ck) failed: %d", ret); 6107a4c4eddSChristophe Roullier goto err_disable_clk_tx; 6117a4c4eddSChristophe Roullier } 6127a4c4eddSChristophe Roullier } 6137a4c4eddSChristophe Roullier 6147a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 6157a4c4eddSChristophe Roullier return 0; 6167a4c4eddSChristophe Roullier 6177a4c4eddSChristophe Roullier err_disable_clk_tx: 6187a4c4eddSChristophe Roullier clk_disable(&eqos->clk_tx); 6197a4c4eddSChristophe Roullier err_disable_clk_rx: 6207a4c4eddSChristophe Roullier clk_disable(&eqos->clk_rx); 6217a4c4eddSChristophe Roullier err_disable_clk_master_bus: 6227a4c4eddSChristophe Roullier clk_disable(&eqos->clk_master_bus); 6237a4c4eddSChristophe Roullier err: 6247a4c4eddSChristophe Roullier debug("%s: FAILED: %d\n", __func__, ret); 6257a4c4eddSChristophe Roullier return ret; 6267a4c4eddSChristophe Roullier } 6277a4c4eddSChristophe Roullier 6288aaada72SPatrick Delaunay static void eqos_stop_clks_tegra186(struct udevice *dev) 629ba4dfef1SStephen Warren { 630ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 631ba4dfef1SStephen Warren 632ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 633ba4dfef1SStephen Warren 634ba4dfef1SStephen Warren clk_disable(&eqos->clk_tx); 635ba4dfef1SStephen Warren clk_disable(&eqos->clk_ptp_ref); 636ba4dfef1SStephen Warren clk_disable(&eqos->clk_rx); 637ba4dfef1SStephen Warren clk_disable(&eqos->clk_master_bus); 638ba4dfef1SStephen Warren clk_disable(&eqos->clk_slave_bus); 639ba4dfef1SStephen Warren 640ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 641ba4dfef1SStephen Warren } 642ba4dfef1SStephen Warren 6438aaada72SPatrick Delaunay static void eqos_stop_clks_stm32(struct udevice *dev) 6447a4c4eddSChristophe Roullier { 6457a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 6467a4c4eddSChristophe Roullier 6477a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 6487a4c4eddSChristophe Roullier 6497a4c4eddSChristophe Roullier clk_disable(&eqos->clk_tx); 6507a4c4eddSChristophe Roullier clk_disable(&eqos->clk_rx); 6517a4c4eddSChristophe Roullier clk_disable(&eqos->clk_master_bus); 6527a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) 6537a4c4eddSChristophe Roullier clk_disable(&eqos->clk_ck); 6547a4c4eddSChristophe Roullier 6557a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 6567a4c4eddSChristophe Roullier } 6577a4c4eddSChristophe Roullier 658ba4dfef1SStephen Warren static int eqos_start_resets_tegra186(struct udevice *dev) 659ba4dfef1SStephen Warren { 660ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 661ba4dfef1SStephen Warren int ret; 662ba4dfef1SStephen Warren 663ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 664ba4dfef1SStephen Warren 665ba4dfef1SStephen Warren ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 666ba4dfef1SStephen Warren if (ret < 0) { 66790aa625cSMasahiro Yamada pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", ret); 668ba4dfef1SStephen Warren return ret; 669ba4dfef1SStephen Warren } 670ba4dfef1SStephen Warren 671ba4dfef1SStephen Warren udelay(2); 672ba4dfef1SStephen Warren 673ba4dfef1SStephen Warren ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); 674ba4dfef1SStephen Warren if (ret < 0) { 67590aa625cSMasahiro Yamada pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret); 676ba4dfef1SStephen Warren return ret; 677ba4dfef1SStephen Warren } 678ba4dfef1SStephen Warren 679ba4dfef1SStephen Warren ret = reset_assert(&eqos->reset_ctl); 680ba4dfef1SStephen Warren if (ret < 0) { 68190aa625cSMasahiro Yamada pr_err("reset_assert() failed: %d", ret); 682ba4dfef1SStephen Warren return ret; 683ba4dfef1SStephen Warren } 684ba4dfef1SStephen Warren 685ba4dfef1SStephen Warren udelay(2); 686ba4dfef1SStephen Warren 687ba4dfef1SStephen Warren ret = reset_deassert(&eqos->reset_ctl); 688ba4dfef1SStephen Warren if (ret < 0) { 68990aa625cSMasahiro Yamada pr_err("reset_deassert() failed: %d", ret); 690ba4dfef1SStephen Warren return ret; 691ba4dfef1SStephen Warren } 692ba4dfef1SStephen Warren 693ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 694ba4dfef1SStephen Warren return 0; 695ba4dfef1SStephen Warren } 696ba4dfef1SStephen Warren 6977a4c4eddSChristophe Roullier static int eqos_start_resets_stm32(struct udevice *dev) 6987a4c4eddSChristophe Roullier { 6995bd3c538SChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 7005bd3c538SChristophe Roullier int ret; 7015bd3c538SChristophe Roullier 7025bd3c538SChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 7035bd3c538SChristophe Roullier if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) { 7045bd3c538SChristophe Roullier ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 7055bd3c538SChristophe Roullier if (ret < 0) { 7065bd3c538SChristophe Roullier pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", 7075bd3c538SChristophe Roullier ret); 7085bd3c538SChristophe Roullier return ret; 7095bd3c538SChristophe Roullier } 7105bd3c538SChristophe Roullier 7115bd3c538SChristophe Roullier udelay(2); 7125bd3c538SChristophe Roullier 7135bd3c538SChristophe Roullier ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); 7145bd3c538SChristophe Roullier if (ret < 0) { 7155bd3c538SChristophe Roullier pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", 7165bd3c538SChristophe Roullier ret); 7175bd3c538SChristophe Roullier return ret; 7185bd3c538SChristophe Roullier } 7195bd3c538SChristophe Roullier } 7205bd3c538SChristophe Roullier debug("%s: OK\n", __func__); 7215bd3c538SChristophe Roullier 7227a4c4eddSChristophe Roullier return 0; 7237a4c4eddSChristophe Roullier } 7247a4c4eddSChristophe Roullier 725ba4dfef1SStephen Warren static int eqos_stop_resets_tegra186(struct udevice *dev) 726ba4dfef1SStephen Warren { 727ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 728ba4dfef1SStephen Warren 729ba4dfef1SStephen Warren reset_assert(&eqos->reset_ctl); 730ba4dfef1SStephen Warren dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 731ba4dfef1SStephen Warren 732ba4dfef1SStephen Warren return 0; 733ba4dfef1SStephen Warren } 734ba4dfef1SStephen Warren 7357a4c4eddSChristophe Roullier static int eqos_stop_resets_stm32(struct udevice *dev) 7367a4c4eddSChristophe Roullier { 7375bd3c538SChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 7385bd3c538SChristophe Roullier int ret; 7395bd3c538SChristophe Roullier 7405bd3c538SChristophe Roullier 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 7497a4c4eddSChristophe Roullier return 0; 7507a4c4eddSChristophe Roullier } 7517a4c4eddSChristophe Roullier 752ba4dfef1SStephen Warren static int eqos_calibrate_pads_tegra186(struct udevice *dev) 753ba4dfef1SStephen Warren { 754ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 755ba4dfef1SStephen Warren int ret; 756ba4dfef1SStephen Warren 757ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 758ba4dfef1SStephen Warren 759ba4dfef1SStephen Warren setbits_le32(&eqos->tegra186_regs->sdmemcomppadctrl, 760ba4dfef1SStephen Warren EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD); 761ba4dfef1SStephen Warren 762ba4dfef1SStephen Warren udelay(1); 763ba4dfef1SStephen Warren 764ba4dfef1SStephen Warren setbits_le32(&eqos->tegra186_regs->auto_cal_config, 765ba4dfef1SStephen Warren EQOS_AUTO_CAL_CONFIG_START | EQOS_AUTO_CAL_CONFIG_ENABLE); 766ba4dfef1SStephen Warren 767b491b498SJon Lin ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, 768ba4dfef1SStephen Warren EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false); 769ba4dfef1SStephen Warren if (ret) { 77090aa625cSMasahiro Yamada pr_err("calibrate didn't start"); 771ba4dfef1SStephen Warren goto failed; 772ba4dfef1SStephen Warren } 773ba4dfef1SStephen Warren 774b491b498SJon Lin ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, 775ba4dfef1SStephen Warren EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false); 776ba4dfef1SStephen Warren if (ret) { 77790aa625cSMasahiro Yamada pr_err("calibrate didn't finish"); 778ba4dfef1SStephen Warren goto failed; 779ba4dfef1SStephen Warren } 780ba4dfef1SStephen Warren 781ba4dfef1SStephen Warren ret = 0; 782ba4dfef1SStephen Warren 783ba4dfef1SStephen Warren failed: 784ba4dfef1SStephen Warren clrbits_le32(&eqos->tegra186_regs->sdmemcomppadctrl, 785ba4dfef1SStephen Warren EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD); 786ba4dfef1SStephen Warren 787ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 788ba4dfef1SStephen Warren 789ba4dfef1SStephen Warren return ret; 790ba4dfef1SStephen Warren } 791ba4dfef1SStephen Warren 792ba4dfef1SStephen Warren static int eqos_disable_calibration_tegra186(struct udevice *dev) 793ba4dfef1SStephen Warren { 794ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 795ba4dfef1SStephen Warren 796ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 797ba4dfef1SStephen Warren 798ba4dfef1SStephen Warren clrbits_le32(&eqos->tegra186_regs->auto_cal_config, 799ba4dfef1SStephen Warren EQOS_AUTO_CAL_CONFIG_ENABLE); 800ba4dfef1SStephen Warren 801ba4dfef1SStephen Warren return 0; 802ba4dfef1SStephen Warren } 803ba4dfef1SStephen Warren 804ba4dfef1SStephen Warren static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev) 805ba4dfef1SStephen Warren { 806ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 807ba4dfef1SStephen Warren 808ba4dfef1SStephen Warren return clk_get_rate(&eqos->clk_slave_bus); 809ba4dfef1SStephen Warren } 810ba4dfef1SStephen Warren 8117a4c4eddSChristophe Roullier static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) 8127a4c4eddSChristophe Roullier { 8137a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 8147a4c4eddSChristophe Roullier 8157a4c4eddSChristophe Roullier return clk_get_rate(&eqos->clk_master_bus); 8167a4c4eddSChristophe Roullier } 8177a4c4eddSChristophe Roullier 8187a4c4eddSChristophe Roullier static int eqos_calibrate_pads_stm32(struct udevice *dev) 8197a4c4eddSChristophe Roullier { 8207a4c4eddSChristophe Roullier return 0; 8217a4c4eddSChristophe Roullier } 8227a4c4eddSChristophe Roullier 8237a4c4eddSChristophe Roullier static int eqos_disable_calibration_stm32(struct udevice *dev) 8247a4c4eddSChristophe Roullier { 8257a4c4eddSChristophe Roullier return 0; 8267a4c4eddSChristophe Roullier } 8277a4c4eddSChristophe Roullier 828ba4dfef1SStephen Warren static int eqos_set_full_duplex(struct udevice *dev) 829ba4dfef1SStephen Warren { 830ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 831ba4dfef1SStephen Warren 832ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 833ba4dfef1SStephen Warren 834ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->configuration, EQOS_MAC_CONFIGURATION_DM); 835ba4dfef1SStephen Warren 836ba4dfef1SStephen Warren return 0; 837ba4dfef1SStephen Warren } 838ba4dfef1SStephen Warren 839ba4dfef1SStephen Warren static int eqos_set_half_duplex(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->mac_regs->configuration, EQOS_MAC_CONFIGURATION_DM); 846ba4dfef1SStephen Warren 847ba4dfef1SStephen Warren /* WAR: Flush TX queue when switching to half-duplex */ 848ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->txq0_operation_mode, 849ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_FTQ); 850ba4dfef1SStephen Warren 851ba4dfef1SStephen Warren return 0; 852ba4dfef1SStephen Warren } 853ba4dfef1SStephen Warren 854ba4dfef1SStephen Warren static int eqos_set_gmii_speed(struct udevice *dev) 855ba4dfef1SStephen Warren { 856ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 857ba4dfef1SStephen Warren 858ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 859ba4dfef1SStephen Warren 860ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, 861ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_PS | EQOS_MAC_CONFIGURATION_FES); 862ba4dfef1SStephen Warren 863ba4dfef1SStephen Warren return 0; 864ba4dfef1SStephen Warren } 865ba4dfef1SStephen Warren 866ba4dfef1SStephen Warren static int eqos_set_mii_speed_100(struct udevice *dev) 867ba4dfef1SStephen Warren { 868ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 869ba4dfef1SStephen Warren 870ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 871ba4dfef1SStephen Warren 872ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->configuration, 873ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_PS | EQOS_MAC_CONFIGURATION_FES); 874ba4dfef1SStephen Warren 875ba4dfef1SStephen Warren return 0; 876ba4dfef1SStephen Warren } 877ba4dfef1SStephen Warren 878ba4dfef1SStephen Warren static int eqos_set_mii_speed_10(struct udevice *dev) 879ba4dfef1SStephen Warren { 880ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 881ba4dfef1SStephen Warren 882ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 883ba4dfef1SStephen Warren 884ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->configuration, 885ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_FES, EQOS_MAC_CONFIGURATION_PS); 886ba4dfef1SStephen Warren 887ba4dfef1SStephen Warren return 0; 888ba4dfef1SStephen Warren } 889ba4dfef1SStephen Warren 890ba4dfef1SStephen Warren static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev) 891ba4dfef1SStephen Warren { 892ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 893ba4dfef1SStephen Warren ulong rate; 894ba4dfef1SStephen Warren int ret; 895ba4dfef1SStephen Warren 896ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 897ba4dfef1SStephen Warren 898ba4dfef1SStephen Warren switch (eqos->phy->speed) { 899ba4dfef1SStephen Warren case SPEED_1000: 900ba4dfef1SStephen Warren rate = 125 * 1000 * 1000; 901ba4dfef1SStephen Warren break; 902ba4dfef1SStephen Warren case SPEED_100: 903ba4dfef1SStephen Warren rate = 25 * 1000 * 1000; 904ba4dfef1SStephen Warren break; 905ba4dfef1SStephen Warren case SPEED_10: 906ba4dfef1SStephen Warren rate = 2.5 * 1000 * 1000; 907ba4dfef1SStephen Warren break; 908ba4dfef1SStephen Warren default: 90990aa625cSMasahiro Yamada pr_err("invalid speed %d", eqos->phy->speed); 910ba4dfef1SStephen Warren return -EINVAL; 911ba4dfef1SStephen Warren } 912ba4dfef1SStephen Warren 913ba4dfef1SStephen Warren ret = clk_set_rate(&eqos->clk_tx, rate); 914ba4dfef1SStephen Warren if (ret < 0) { 91590aa625cSMasahiro Yamada pr_err("clk_set_rate(tx_clk, %lu) failed: %d", rate, ret); 916ba4dfef1SStephen Warren return ret; 917ba4dfef1SStephen Warren } 918ba4dfef1SStephen Warren 919ba4dfef1SStephen Warren return 0; 920ba4dfef1SStephen Warren } 921ba4dfef1SStephen Warren 9227a4c4eddSChristophe Roullier static int eqos_set_tx_clk_speed_stm32(struct udevice *dev) 9237a4c4eddSChristophe Roullier { 9247a4c4eddSChristophe Roullier return 0; 9257a4c4eddSChristophe Roullier } 9267a4c4eddSChristophe Roullier 927ba4dfef1SStephen Warren static int eqos_adjust_link(struct udevice *dev) 928ba4dfef1SStephen Warren { 929ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 930ba4dfef1SStephen Warren int ret; 931ba4dfef1SStephen Warren bool en_calibration; 932ba4dfef1SStephen Warren 933ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 934ba4dfef1SStephen Warren 935ba4dfef1SStephen Warren if (eqos->phy->duplex) 936ba4dfef1SStephen Warren ret = eqos_set_full_duplex(dev); 937ba4dfef1SStephen Warren else 938ba4dfef1SStephen Warren ret = eqos_set_half_duplex(dev); 939ba4dfef1SStephen Warren if (ret < 0) { 94090aa625cSMasahiro Yamada pr_err("eqos_set_*_duplex() failed: %d", ret); 941ba4dfef1SStephen Warren return ret; 942ba4dfef1SStephen Warren } 943ba4dfef1SStephen Warren 944ba4dfef1SStephen Warren switch (eqos->phy->speed) { 945ba4dfef1SStephen Warren case SPEED_1000: 946ba4dfef1SStephen Warren en_calibration = true; 947ba4dfef1SStephen Warren ret = eqos_set_gmii_speed(dev); 948ba4dfef1SStephen Warren break; 949ba4dfef1SStephen Warren case SPEED_100: 950ba4dfef1SStephen Warren en_calibration = true; 951ba4dfef1SStephen Warren ret = eqos_set_mii_speed_100(dev); 952ba4dfef1SStephen Warren break; 953ba4dfef1SStephen Warren case SPEED_10: 954ba4dfef1SStephen Warren en_calibration = false; 955ba4dfef1SStephen Warren ret = eqos_set_mii_speed_10(dev); 956ba4dfef1SStephen Warren break; 957ba4dfef1SStephen Warren default: 95890aa625cSMasahiro Yamada pr_err("invalid speed %d", eqos->phy->speed); 959ba4dfef1SStephen Warren return -EINVAL; 960ba4dfef1SStephen Warren } 961ba4dfef1SStephen Warren if (ret < 0) { 96290aa625cSMasahiro Yamada pr_err("eqos_set_*mii_speed*() failed: %d", ret); 963ba4dfef1SStephen Warren return ret; 964ba4dfef1SStephen Warren } 965ba4dfef1SStephen Warren 966ba4dfef1SStephen Warren if (en_calibration) { 9677a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_calibrate_pads(dev); 968ba4dfef1SStephen Warren if (ret < 0) { 9697a4c4eddSChristophe Roullier pr_err("eqos_calibrate_pads() failed: %d", 9707a4c4eddSChristophe Roullier ret); 971ba4dfef1SStephen Warren return ret; 972ba4dfef1SStephen Warren } 973ba4dfef1SStephen Warren } else { 9747a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_disable_calibration(dev); 975ba4dfef1SStephen Warren if (ret < 0) { 9767a4c4eddSChristophe Roullier pr_err("eqos_disable_calibration() failed: %d", 977ba4dfef1SStephen Warren ret); 978ba4dfef1SStephen Warren return ret; 979ba4dfef1SStephen Warren } 980ba4dfef1SStephen Warren } 9817a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_set_tx_clk_speed(dev); 982ba4dfef1SStephen Warren if (ret < 0) { 9837a4c4eddSChristophe Roullier pr_err("eqos_set_tx_clk_speed() failed: %d", ret); 984ba4dfef1SStephen Warren return ret; 985ba4dfef1SStephen Warren } 986ba4dfef1SStephen Warren 987ba4dfef1SStephen Warren return 0; 988ba4dfef1SStephen Warren } 989ba4dfef1SStephen Warren 990ba4dfef1SStephen Warren static int eqos_write_hwaddr(struct udevice *dev) 991ba4dfef1SStephen Warren { 992ba4dfef1SStephen Warren struct eth_pdata *plat = dev_get_platdata(dev); 993ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 994ba4dfef1SStephen Warren uint32_t val; 995ba4dfef1SStephen Warren 996ba4dfef1SStephen Warren /* 997ba4dfef1SStephen Warren * This function may be called before start() or after stop(). At that 998ba4dfef1SStephen Warren * time, on at least some configurations of the EQoS HW, all clocks to 999ba4dfef1SStephen Warren * the EQoS HW block will be stopped, and a reset signal applied. If 1000ba4dfef1SStephen Warren * any register access is attempted in this state, bus timeouts or CPU 1001ba4dfef1SStephen Warren * hangs may occur. This check prevents that. 1002ba4dfef1SStephen Warren * 1003ba4dfef1SStephen Warren * A simple solution to this problem would be to not implement 1004ba4dfef1SStephen Warren * write_hwaddr(), since start() always writes the MAC address into HW 1005ba4dfef1SStephen Warren * anyway. However, it is desirable to implement write_hwaddr() to 1006ba4dfef1SStephen Warren * support the case of SW that runs subsequent to U-Boot which expects 1007ba4dfef1SStephen Warren * the MAC address to already be programmed into the EQoS registers, 1008ba4dfef1SStephen Warren * which must happen irrespective of whether the U-Boot user (or 1009ba4dfef1SStephen Warren * scripts) actually made use of the EQoS device, and hence 1010ba4dfef1SStephen Warren * irrespective of whether start() was ever called. 1011ba4dfef1SStephen Warren * 1012ba4dfef1SStephen Warren * Note that this requirement by subsequent SW is not valid for 1013ba4dfef1SStephen Warren * Tegra186, and is likely not valid for any non-PCI instantiation of 1014ba4dfef1SStephen Warren * the EQoS HW block. This function is implemented solely as 1015ba4dfef1SStephen Warren * future-proofing with the expectation the driver will eventually be 1016ba4dfef1SStephen Warren * ported to some system where the expectation above is true. 1017ba4dfef1SStephen Warren */ 1018ba4dfef1SStephen Warren if (!eqos->config->reg_access_always_ok && !eqos->reg_access_ok) 1019ba4dfef1SStephen Warren return 0; 1020ba4dfef1SStephen Warren 1021ba4dfef1SStephen Warren /* Update the MAC address */ 1022ba4dfef1SStephen Warren val = (plat->enetaddr[5] << 8) | 1023ba4dfef1SStephen Warren (plat->enetaddr[4]); 1024ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->address0_high); 1025ba4dfef1SStephen Warren val = (plat->enetaddr[3] << 24) | 1026ba4dfef1SStephen Warren (plat->enetaddr[2] << 16) | 1027ba4dfef1SStephen Warren (plat->enetaddr[1] << 8) | 1028ba4dfef1SStephen Warren (plat->enetaddr[0]); 1029ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->address0_low); 1030ba4dfef1SStephen Warren 1031ba4dfef1SStephen Warren return 0; 1032ba4dfef1SStephen Warren } 1033ba4dfef1SStephen Warren 1034ba4dfef1SStephen Warren static int eqos_start(struct udevice *dev) 1035ba4dfef1SStephen Warren { 1036ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1037ba4dfef1SStephen Warren int ret, i; 1038ba4dfef1SStephen Warren ulong rate; 1039ba4dfef1SStephen Warren u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl; 1040ba4dfef1SStephen Warren ulong last_rx_desc; 1041ba4dfef1SStephen Warren 1042ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1043ba4dfef1SStephen Warren 1044ba4dfef1SStephen Warren eqos->tx_desc_idx = 0; 1045ba4dfef1SStephen Warren eqos->rx_desc_idx = 0; 1046ba4dfef1SStephen Warren 10477a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_start_clks(dev); 1048ba4dfef1SStephen Warren if (ret < 0) { 10497a4c4eddSChristophe Roullier pr_err("eqos_start_clks() failed: %d", ret); 1050ba4dfef1SStephen Warren goto err; 1051ba4dfef1SStephen Warren } 1052ba4dfef1SStephen Warren 10537a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_start_resets(dev); 1054ba4dfef1SStephen Warren if (ret < 0) { 10557a4c4eddSChristophe Roullier pr_err("eqos_start_resets() failed: %d", ret); 1056ba4dfef1SStephen Warren goto err_stop_clks; 1057ba4dfef1SStephen Warren } 1058ba4dfef1SStephen Warren 1059ba4dfef1SStephen Warren udelay(10); 1060ba4dfef1SStephen Warren 1061ba4dfef1SStephen Warren eqos->reg_access_ok = true; 1062ba4dfef1SStephen Warren 1063b491b498SJon Lin ret = wait_for_bit_le32(&eqos->dma_regs->mode, 10647a4c4eddSChristophe Roullier EQOS_DMA_MODE_SWR, false, 10657a4c4eddSChristophe Roullier eqos->config->swr_wait, false); 1066ba4dfef1SStephen Warren if (ret) { 106790aa625cSMasahiro Yamada pr_err("EQOS_DMA_MODE_SWR stuck"); 1068ba4dfef1SStephen Warren goto err_stop_resets; 1069ba4dfef1SStephen Warren } 1070ba4dfef1SStephen Warren 10717a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_calibrate_pads(dev); 1072ba4dfef1SStephen Warren if (ret < 0) { 10737a4c4eddSChristophe Roullier pr_err("eqos_calibrate_pads() failed: %d", ret); 1074ba4dfef1SStephen Warren goto err_stop_resets; 1075ba4dfef1SStephen Warren } 10767a4c4eddSChristophe Roullier rate = eqos->config->ops->eqos_get_tick_clk_rate(dev); 1077ba4dfef1SStephen Warren 1078ba4dfef1SStephen Warren val = (rate / 1000000) - 1; 1079ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->us_tic_counter); 1080ba4dfef1SStephen Warren 10817a4c4eddSChristophe Roullier /* 10827a4c4eddSChristophe Roullier * if PHY was already connected and configured, 10837a4c4eddSChristophe Roullier * don't need to reconnect/reconfigure again 10847a4c4eddSChristophe Roullier */ 10857a4c4eddSChristophe Roullier if (!eqos->phy) { 1086*8e3eceb0SYe Li int addr = -1; 1087*8e3eceb0SYe Li #ifdef CONFIG_DM_ETH_PHY 1088*8e3eceb0SYe Li addr = eth_phy_get_addr(dev); 1089*8e3eceb0SYe Li #endif 1090*8e3eceb0SYe Li #ifdef DWC_NET_PHYADDR 1091*8e3eceb0SYe Li addr = DWC_NET_PHYADDR; 1092*8e3eceb0SYe Li #endif 1093*8e3eceb0SYe Li eqos->phy = phy_connect(eqos->mii, addr, dev, 10947a4c4eddSChristophe Roullier eqos->config->interface(dev)); 1095ba4dfef1SStephen Warren if (!eqos->phy) { 109690aa625cSMasahiro Yamada pr_err("phy_connect() failed"); 1097ba4dfef1SStephen Warren goto err_stop_resets; 1098ba4dfef1SStephen Warren } 109983d31c08SPatrick Delaunay 110083d31c08SPatrick Delaunay if (eqos->max_speed) { 110183d31c08SPatrick Delaunay ret = phy_set_supported(eqos->phy, eqos->max_speed); 110283d31c08SPatrick Delaunay if (ret) { 110383d31c08SPatrick Delaunay pr_err("phy_set_supported() failed: %d", ret); 110483d31c08SPatrick Delaunay goto err_shutdown_phy; 110583d31c08SPatrick Delaunay } 110683d31c08SPatrick Delaunay } 110783d31c08SPatrick Delaunay 1108ba4dfef1SStephen Warren ret = phy_config(eqos->phy); 1109ba4dfef1SStephen Warren if (ret < 0) { 111090aa625cSMasahiro Yamada pr_err("phy_config() failed: %d", ret); 1111ba4dfef1SStephen Warren goto err_shutdown_phy; 1112ba4dfef1SStephen Warren } 11137a4c4eddSChristophe Roullier } 11147a4c4eddSChristophe Roullier 1115ba4dfef1SStephen Warren ret = phy_startup(eqos->phy); 1116ba4dfef1SStephen Warren if (ret < 0) { 111790aa625cSMasahiro Yamada pr_err("phy_startup() failed: %d", ret); 1118ba4dfef1SStephen Warren goto err_shutdown_phy; 1119ba4dfef1SStephen Warren } 1120ba4dfef1SStephen Warren 1121ba4dfef1SStephen Warren if (!eqos->phy->link) { 112290aa625cSMasahiro Yamada pr_err("No link"); 1123ba4dfef1SStephen Warren goto err_shutdown_phy; 1124ba4dfef1SStephen Warren } 1125ba4dfef1SStephen Warren 1126ba4dfef1SStephen Warren ret = eqos_adjust_link(dev); 1127ba4dfef1SStephen Warren if (ret < 0) { 112890aa625cSMasahiro Yamada pr_err("eqos_adjust_link() failed: %d", ret); 1129ba4dfef1SStephen Warren goto err_shutdown_phy; 1130ba4dfef1SStephen Warren } 1131ba4dfef1SStephen Warren 1132ba4dfef1SStephen Warren /* Configure MTL */ 1133ba4dfef1SStephen Warren 1134ba4dfef1SStephen Warren /* Enable Store and Forward mode for TX */ 1135ba4dfef1SStephen Warren /* Program Tx operating mode */ 1136ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->txq0_operation_mode, 1137ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TSF | 1138ba4dfef1SStephen Warren (EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_ENABLED << 1139ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_SHIFT)); 1140ba4dfef1SStephen Warren 1141ba4dfef1SStephen Warren /* Transmit Queue weight */ 1142ba4dfef1SStephen Warren writel(0x10, &eqos->mtl_regs->txq0_quantum_weight); 1143ba4dfef1SStephen Warren 1144ba4dfef1SStephen Warren /* Enable Store and Forward mode for RX, since no jumbo frame */ 1145ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1146ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RSF); 1147ba4dfef1SStephen Warren 1148ba4dfef1SStephen Warren /* Transmit/Receive queue fifo size; use all RAM for 1 queue */ 1149ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->hw_feature1); 1150ba4dfef1SStephen Warren tx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_SHIFT) & 1151ba4dfef1SStephen Warren EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_MASK; 1152ba4dfef1SStephen Warren rx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT) & 1153ba4dfef1SStephen Warren EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK; 1154ba4dfef1SStephen Warren 1155ba4dfef1SStephen Warren /* 1156ba4dfef1SStephen Warren * r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting. 1157ba4dfef1SStephen Warren * r/tqs is encoded as (n / 256) - 1. 1158ba4dfef1SStephen Warren */ 1159ba4dfef1SStephen Warren tqs = (128 << tx_fifo_sz) / 256 - 1; 1160ba4dfef1SStephen Warren rqs = (128 << rx_fifo_sz) / 256 - 1; 1161ba4dfef1SStephen Warren 1162ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->txq0_operation_mode, 1163ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK << 1164ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT, 1165ba4dfef1SStephen Warren tqs << EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT); 1166ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1167ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RQS_MASK << 1168ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT, 1169ba4dfef1SStephen Warren rqs << EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT); 1170ba4dfef1SStephen Warren 1171ba4dfef1SStephen Warren /* Flow control used only if each channel gets 4KB or more FIFO */ 1172ba4dfef1SStephen Warren if (rqs >= ((4096 / 256) - 1)) { 1173ba4dfef1SStephen Warren u32 rfd, rfa; 1174ba4dfef1SStephen Warren 1175ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1176ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_EHFC); 1177ba4dfef1SStephen Warren 1178ba4dfef1SStephen Warren /* 1179ba4dfef1SStephen Warren * Set Threshold for Activating Flow Contol space for min 2 1180ba4dfef1SStephen Warren * frames ie, (1500 * 1) = 1500 bytes. 1181ba4dfef1SStephen Warren * 1182ba4dfef1SStephen Warren * Set Threshold for Deactivating Flow Contol for space of 1183ba4dfef1SStephen Warren * min 1 frame (frame size 1500bytes) in receive fifo 1184ba4dfef1SStephen Warren */ 1185ba4dfef1SStephen Warren if (rqs == ((4096 / 256) - 1)) { 1186ba4dfef1SStephen Warren /* 1187ba4dfef1SStephen Warren * This violates the above formula because of FIFO size 1188ba4dfef1SStephen Warren * limit therefore overflow may occur inspite of this. 1189ba4dfef1SStephen Warren */ 1190ba4dfef1SStephen Warren rfd = 0x3; /* Full-3K */ 1191ba4dfef1SStephen Warren rfa = 0x1; /* Full-1.5K */ 1192ba4dfef1SStephen Warren } else if (rqs == ((8192 / 256) - 1)) { 1193ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1194ba4dfef1SStephen Warren rfa = 0xa; /* Full-6K */ 1195ba4dfef1SStephen Warren } else if (rqs == ((16384 / 256) - 1)) { 1196ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1197ba4dfef1SStephen Warren rfa = 0x12; /* Full-10K */ 1198ba4dfef1SStephen Warren } else { 1199ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1200ba4dfef1SStephen Warren rfa = 0x1E; /* Full-16K */ 1201ba4dfef1SStephen Warren } 1202ba4dfef1SStephen Warren 1203ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1204ba4dfef1SStephen Warren (EQOS_MTL_RXQ0_OPERATION_MODE_RFD_MASK << 1205ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT) | 1206ba4dfef1SStephen Warren (EQOS_MTL_RXQ0_OPERATION_MODE_RFA_MASK << 1207ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT), 1208ba4dfef1SStephen Warren (rfd << 1209ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT) | 1210ba4dfef1SStephen Warren (rfa << 1211ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT)); 1212ba4dfef1SStephen Warren } 1213ba4dfef1SStephen Warren 1214ba4dfef1SStephen Warren /* Configure MAC */ 1215ba4dfef1SStephen Warren 1216ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0, 1217ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK << 1218ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT, 12197a4c4eddSChristophe Roullier eqos->config->config_mac << 1220ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT); 1221ba4dfef1SStephen Warren 1222ba4dfef1SStephen Warren /* Set TX flow control parameters */ 1223ba4dfef1SStephen Warren /* Set Pause Time */ 1224ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->q0_tx_flow_ctrl, 1225ba4dfef1SStephen Warren 0xffff << EQOS_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT); 1226ba4dfef1SStephen Warren /* Assign priority for TX flow control */ 1227ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->txq_prty_map0, 1228ba4dfef1SStephen Warren EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_MASK << 1229ba4dfef1SStephen Warren EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_SHIFT); 1230ba4dfef1SStephen Warren /* Assign priority for RX flow control */ 1231ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->rxq_ctrl2, 1232ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK << 1233ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT); 1234ba4dfef1SStephen Warren /* Enable flow control */ 1235ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->q0_tx_flow_ctrl, 1236ba4dfef1SStephen Warren EQOS_MAC_Q0_TX_FLOW_CTRL_TFE); 1237ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->rx_flow_ctrl, 1238ba4dfef1SStephen Warren EQOS_MAC_RX_FLOW_CTRL_RFE); 1239ba4dfef1SStephen Warren 1240ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->configuration, 1241ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_GPSLCE | 1242ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_WD | 1243ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_JD | 1244ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_JE, 1245ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_CST | 1246ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_ACS); 1247ba4dfef1SStephen Warren 1248ba4dfef1SStephen Warren eqos_write_hwaddr(dev); 1249ba4dfef1SStephen Warren 1250ba4dfef1SStephen Warren /* Configure DMA */ 1251ba4dfef1SStephen Warren 1252ba4dfef1SStephen Warren /* Enable OSP mode */ 1253ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_tx_control, 1254ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_OSP); 1255ba4dfef1SStephen Warren 1256ba4dfef1SStephen Warren /* RX buffer size. Must be a multiple of bus width */ 1257ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_rx_control, 1258ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_MASK << 1259ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT, 1260ba4dfef1SStephen Warren EQOS_MAX_PACKET_SIZE << 1261ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT); 1262ba4dfef1SStephen Warren 1263ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_control, 1264ba4dfef1SStephen Warren EQOS_DMA_CH0_CONTROL_PBLX8); 1265ba4dfef1SStephen Warren 1266ba4dfef1SStephen Warren /* 1267ba4dfef1SStephen Warren * Burst length must be < 1/2 FIFO size. 1268ba4dfef1SStephen Warren * FIFO size in tqs is encoded as (n / 256) - 1. 1269ba4dfef1SStephen Warren * Each burst is n * 8 (PBLX8) * 16 (AXI width) == 128 bytes. 1270ba4dfef1SStephen Warren * Half of n * 256 is n * 128, so pbl == tqs, modulo the -1. 1271ba4dfef1SStephen Warren */ 1272ba4dfef1SStephen Warren pbl = tqs + 1; 1273ba4dfef1SStephen Warren if (pbl > 32) 1274ba4dfef1SStephen Warren pbl = 32; 1275ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_tx_control, 1276ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_TXPBL_MASK << 1277ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT, 1278ba4dfef1SStephen Warren pbl << EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT); 1279ba4dfef1SStephen Warren 1280ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_rx_control, 1281ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RXPBL_MASK << 1282ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT, 1283ba4dfef1SStephen Warren 8 << EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT); 1284ba4dfef1SStephen Warren 1285ba4dfef1SStephen Warren /* DMA performance configuration */ 1286ba4dfef1SStephen Warren val = (2 << EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_SHIFT) | 1287ba4dfef1SStephen Warren EQOS_DMA_SYSBUS_MODE_EAME | EQOS_DMA_SYSBUS_MODE_BLEN16 | 1288ba4dfef1SStephen Warren EQOS_DMA_SYSBUS_MODE_BLEN8 | EQOS_DMA_SYSBUS_MODE_BLEN4; 1289ba4dfef1SStephen Warren writel(val, &eqos->dma_regs->sysbus_mode); 1290ba4dfef1SStephen Warren 1291ba4dfef1SStephen Warren /* Set up descriptors */ 1292ba4dfef1SStephen Warren 1293ba4dfef1SStephen Warren memset(eqos->descs, 0, EQOS_DESCRIPTORS_SIZE); 1294ba4dfef1SStephen Warren for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) { 1295ba4dfef1SStephen Warren struct eqos_desc *rx_desc = &(eqos->rx_descs[i]); 1296ba4dfef1SStephen Warren rx_desc->des0 = (u32)(ulong)(eqos->rx_dma_buf + 1297ba4dfef1SStephen Warren (i * EQOS_MAX_PACKET_SIZE)); 12986143c348SMarek Vasut rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; 12996399c699SMarek Vasut eqos->config->ops->eqos_flush_desc(rx_desc); 1300ba4dfef1SStephen Warren } 1301ba4dfef1SStephen Warren 1302ba4dfef1SStephen Warren writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress); 1303ba4dfef1SStephen Warren writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address); 1304ba4dfef1SStephen Warren writel(EQOS_DESCRIPTORS_TX - 1, 1305ba4dfef1SStephen Warren &eqos->dma_regs->ch0_txdesc_ring_length); 1306ba4dfef1SStephen Warren 1307ba4dfef1SStephen Warren writel(0, &eqos->dma_regs->ch0_rxdesc_list_haddress); 1308ba4dfef1SStephen Warren writel((ulong)eqos->rx_descs, &eqos->dma_regs->ch0_rxdesc_list_address); 1309ba4dfef1SStephen Warren writel(EQOS_DESCRIPTORS_RX - 1, 1310ba4dfef1SStephen Warren &eqos->dma_regs->ch0_rxdesc_ring_length); 1311ba4dfef1SStephen Warren 1312ba4dfef1SStephen Warren /* Enable everything */ 1313ba4dfef1SStephen Warren 1314ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->configuration, 1315ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE); 1316ba4dfef1SStephen Warren 1317ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_tx_control, 1318ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_ST); 1319ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_rx_control, 1320ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_SR); 1321ba4dfef1SStephen Warren 1322ba4dfef1SStephen Warren /* TX tail pointer not written until we need to TX a packet */ 1323ba4dfef1SStephen Warren /* 1324ba4dfef1SStephen Warren * Point RX tail pointer at last descriptor. Ideally, we'd point at the 1325ba4dfef1SStephen Warren * first descriptor, implying all descriptors were available. However, 1326ba4dfef1SStephen Warren * that's not distinguishable from none of the descriptors being 1327ba4dfef1SStephen Warren * available. 1328ba4dfef1SStephen Warren */ 1329ba4dfef1SStephen Warren last_rx_desc = (ulong)&(eqos->rx_descs[(EQOS_DESCRIPTORS_RX - 1)]); 1330ba4dfef1SStephen Warren writel(last_rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); 1331ba4dfef1SStephen Warren 1332ba4dfef1SStephen Warren eqos->started = true; 1333ba4dfef1SStephen Warren 1334ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1335ba4dfef1SStephen Warren return 0; 1336ba4dfef1SStephen Warren 1337ba4dfef1SStephen Warren err_shutdown_phy: 1338ba4dfef1SStephen Warren phy_shutdown(eqos->phy); 1339ba4dfef1SStephen Warren err_stop_resets: 13407a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_resets(dev); 1341ba4dfef1SStephen Warren err_stop_clks: 13427a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_clks(dev); 1343ba4dfef1SStephen Warren err: 134490aa625cSMasahiro Yamada pr_err("FAILED: %d", ret); 1345ba4dfef1SStephen Warren return ret; 1346ba4dfef1SStephen Warren } 1347ba4dfef1SStephen Warren 13488aaada72SPatrick Delaunay static void eqos_stop(struct udevice *dev) 1349ba4dfef1SStephen Warren { 1350ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1351ba4dfef1SStephen Warren int i; 1352ba4dfef1SStephen Warren 1353ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1354ba4dfef1SStephen Warren 1355ba4dfef1SStephen Warren if (!eqos->started) 1356ba4dfef1SStephen Warren return; 1357ba4dfef1SStephen Warren eqos->started = false; 1358ba4dfef1SStephen Warren eqos->reg_access_ok = false; 1359ba4dfef1SStephen Warren 1360ba4dfef1SStephen Warren /* Disable TX DMA */ 1361ba4dfef1SStephen Warren clrbits_le32(&eqos->dma_regs->ch0_tx_control, 1362ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_ST); 1363ba4dfef1SStephen Warren 1364ba4dfef1SStephen Warren /* Wait for TX all packets to drain out of MTL */ 1365ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 1366ba4dfef1SStephen Warren u32 val = readl(&eqos->mtl_regs->txq0_debug); 1367ba4dfef1SStephen Warren u32 trcsts = (val >> EQOS_MTL_TXQ0_DEBUG_TRCSTS_SHIFT) & 1368ba4dfef1SStephen Warren EQOS_MTL_TXQ0_DEBUG_TRCSTS_MASK; 1369ba4dfef1SStephen Warren u32 txqsts = val & EQOS_MTL_TXQ0_DEBUG_TXQSTS; 1370ba4dfef1SStephen Warren if ((trcsts != 1) && (!txqsts)) 1371ba4dfef1SStephen Warren break; 1372ba4dfef1SStephen Warren } 1373ba4dfef1SStephen Warren 1374ba4dfef1SStephen Warren /* Turn off MAC TX and RX */ 1375ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, 1376ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE); 1377ba4dfef1SStephen Warren 1378ba4dfef1SStephen Warren /* Wait for all RX packets to drain out of MTL */ 1379ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 1380ba4dfef1SStephen Warren u32 val = readl(&eqos->mtl_regs->rxq0_debug); 1381ba4dfef1SStephen Warren u32 prxq = (val >> EQOS_MTL_RXQ0_DEBUG_PRXQ_SHIFT) & 1382ba4dfef1SStephen Warren EQOS_MTL_RXQ0_DEBUG_PRXQ_MASK; 1383ba4dfef1SStephen Warren u32 rxqsts = (val >> EQOS_MTL_RXQ0_DEBUG_RXQSTS_SHIFT) & 1384ba4dfef1SStephen Warren EQOS_MTL_RXQ0_DEBUG_RXQSTS_MASK; 1385ba4dfef1SStephen Warren if ((!prxq) && (!rxqsts)) 1386ba4dfef1SStephen Warren break; 1387ba4dfef1SStephen Warren } 1388ba4dfef1SStephen Warren 1389ba4dfef1SStephen Warren /* Turn off RX DMA */ 1390ba4dfef1SStephen Warren clrbits_le32(&eqos->dma_regs->ch0_rx_control, 1391ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_SR); 1392ba4dfef1SStephen Warren 1393ba4dfef1SStephen Warren if (eqos->phy) { 1394ba4dfef1SStephen Warren phy_shutdown(eqos->phy); 1395ba4dfef1SStephen Warren } 13967a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_resets(dev); 13977a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_clks(dev); 1398ba4dfef1SStephen Warren 1399ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1400ba4dfef1SStephen Warren } 1401ba4dfef1SStephen Warren 14028aaada72SPatrick Delaunay static int eqos_send(struct udevice *dev, void *packet, int length) 1403ba4dfef1SStephen Warren { 1404ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1405ba4dfef1SStephen Warren struct eqos_desc *tx_desc; 1406ba4dfef1SStephen Warren int i; 1407ba4dfef1SStephen Warren 1408ba4dfef1SStephen Warren debug("%s(dev=%p, packet=%p, length=%d):\n", __func__, dev, packet, 1409ba4dfef1SStephen Warren length); 1410ba4dfef1SStephen Warren 1411ba4dfef1SStephen Warren memcpy(eqos->tx_dma_buf, packet, length); 14127a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length); 1413ba4dfef1SStephen Warren 1414ba4dfef1SStephen Warren tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]); 1415ba4dfef1SStephen Warren eqos->tx_desc_idx++; 1416ba4dfef1SStephen Warren eqos->tx_desc_idx %= EQOS_DESCRIPTORS_TX; 1417ba4dfef1SStephen Warren 1418ba4dfef1SStephen Warren tx_desc->des0 = (ulong)eqos->tx_dma_buf; 1419ba4dfef1SStephen Warren tx_desc->des1 = 0; 1420ba4dfef1SStephen Warren tx_desc->des2 = length; 1421ba4dfef1SStephen Warren /* 1422ba4dfef1SStephen Warren * Make sure that if HW sees the _OWN write below, it will see all the 1423ba4dfef1SStephen Warren * writes to the rest of the descriptor too. 1424ba4dfef1SStephen Warren */ 1425ba4dfef1SStephen Warren mb(); 1426ba4dfef1SStephen Warren tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length; 14277a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_desc(tx_desc); 1428ba4dfef1SStephen Warren 1429364f8fdcSMarek Vasut writel((ulong)(&(eqos->tx_descs[eqos->tx_desc_idx])), 1430364f8fdcSMarek Vasut &eqos->dma_regs->ch0_txdesc_tail_pointer); 1431ba4dfef1SStephen Warren 1432ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 14337a4c4eddSChristophe Roullier eqos->config->ops->eqos_inval_desc(tx_desc); 1434ba4dfef1SStephen Warren if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN)) 1435ba4dfef1SStephen Warren return 0; 1436ba4dfef1SStephen Warren udelay(1); 1437ba4dfef1SStephen Warren } 1438ba4dfef1SStephen Warren 1439ba4dfef1SStephen Warren debug("%s: TX timeout\n", __func__); 1440ba4dfef1SStephen Warren 1441ba4dfef1SStephen Warren return -ETIMEDOUT; 1442ba4dfef1SStephen Warren } 1443ba4dfef1SStephen Warren 14448aaada72SPatrick Delaunay static int eqos_recv(struct udevice *dev, int flags, uchar **packetp) 1445ba4dfef1SStephen Warren { 1446ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1447ba4dfef1SStephen Warren struct eqos_desc *rx_desc; 1448ba4dfef1SStephen Warren int length; 1449ba4dfef1SStephen Warren 1450ba4dfef1SStephen Warren debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags); 1451ba4dfef1SStephen Warren 1452ba4dfef1SStephen Warren rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); 1453865fce80SMarek Vasut eqos->config->ops->eqos_inval_desc(rx_desc); 1454ba4dfef1SStephen Warren if (rx_desc->des3 & EQOS_DESC3_OWN) { 1455ba4dfef1SStephen Warren debug("%s: RX packet not available\n", __func__); 1456ba4dfef1SStephen Warren return -EAGAIN; 1457ba4dfef1SStephen Warren } 1458ba4dfef1SStephen Warren 1459ba4dfef1SStephen Warren *packetp = eqos->rx_dma_buf + 1460ba4dfef1SStephen Warren (eqos->rx_desc_idx * EQOS_MAX_PACKET_SIZE); 1461ba4dfef1SStephen Warren length = rx_desc->des3 & 0x7fff; 1462ba4dfef1SStephen Warren debug("%s: *packetp=%p, length=%d\n", __func__, *packetp, length); 1463ba4dfef1SStephen Warren 14647a4c4eddSChristophe Roullier eqos->config->ops->eqos_inval_buffer(*packetp, length); 1465ba4dfef1SStephen Warren 1466ba4dfef1SStephen Warren return length; 1467ba4dfef1SStephen Warren } 1468ba4dfef1SStephen Warren 14698aaada72SPatrick Delaunay static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) 1470ba4dfef1SStephen Warren { 1471ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1472ba4dfef1SStephen Warren uchar *packet_expected; 1473ba4dfef1SStephen Warren struct eqos_desc *rx_desc; 1474ba4dfef1SStephen Warren 1475ba4dfef1SStephen Warren debug("%s(packet=%p, length=%d)\n", __func__, packet, length); 1476ba4dfef1SStephen Warren 1477ba4dfef1SStephen Warren packet_expected = eqos->rx_dma_buf + 1478ba4dfef1SStephen Warren (eqos->rx_desc_idx * EQOS_MAX_PACKET_SIZE); 1479ba4dfef1SStephen Warren if (packet != packet_expected) { 1480ba4dfef1SStephen Warren debug("%s: Unexpected packet (expected %p)\n", __func__, 1481ba4dfef1SStephen Warren packet_expected); 1482ba4dfef1SStephen Warren return -EINVAL; 1483ba4dfef1SStephen Warren } 1484ba4dfef1SStephen Warren 1485ba4dfef1SStephen Warren rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); 1486076e66fbSMarek Vasut 148707314278SMarek Vasut rx_desc->des0 = 0; 148807314278SMarek Vasut mb(); 148907314278SMarek Vasut eqos->config->ops->eqos_flush_desc(rx_desc); 1490076e66fbSMarek Vasut eqos->config->ops->eqos_inval_buffer(packet, length); 1491ba4dfef1SStephen Warren rx_desc->des0 = (u32)(ulong)packet; 1492ba4dfef1SStephen Warren rx_desc->des1 = 0; 1493ba4dfef1SStephen Warren rx_desc->des2 = 0; 1494ba4dfef1SStephen Warren /* 1495ba4dfef1SStephen Warren * Make sure that if HW sees the _OWN write below, it will see all the 1496ba4dfef1SStephen Warren * writes to the rest of the descriptor too. 1497ba4dfef1SStephen Warren */ 1498ba4dfef1SStephen Warren mb(); 14996143c348SMarek Vasut rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; 15007a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_desc(rx_desc); 1501ba4dfef1SStephen Warren 1502ba4dfef1SStephen Warren writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); 1503ba4dfef1SStephen Warren 1504ba4dfef1SStephen Warren eqos->rx_desc_idx++; 1505ba4dfef1SStephen Warren eqos->rx_desc_idx %= EQOS_DESCRIPTORS_RX; 1506ba4dfef1SStephen Warren 1507ba4dfef1SStephen Warren return 0; 1508ba4dfef1SStephen Warren } 1509ba4dfef1SStephen Warren 1510ba4dfef1SStephen Warren static int eqos_probe_resources_core(struct udevice *dev) 1511ba4dfef1SStephen Warren { 1512ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1513ba4dfef1SStephen Warren int ret; 1514ba4dfef1SStephen Warren 1515ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1516ba4dfef1SStephen Warren 1517ba4dfef1SStephen Warren eqos->descs = eqos_alloc_descs(EQOS_DESCRIPTORS_TX + 1518ba4dfef1SStephen Warren EQOS_DESCRIPTORS_RX); 1519ba4dfef1SStephen Warren if (!eqos->descs) { 1520ba4dfef1SStephen Warren debug("%s: eqos_alloc_descs() failed\n", __func__); 1521ba4dfef1SStephen Warren ret = -ENOMEM; 1522ba4dfef1SStephen Warren goto err; 1523ba4dfef1SStephen Warren } 1524ba4dfef1SStephen Warren eqos->tx_descs = (struct eqos_desc *)eqos->descs; 1525ba4dfef1SStephen Warren eqos->rx_descs = (eqos->tx_descs + EQOS_DESCRIPTORS_TX); 1526ba4dfef1SStephen Warren debug("%s: tx_descs=%p, rx_descs=%p\n", __func__, eqos->tx_descs, 1527ba4dfef1SStephen Warren eqos->rx_descs); 1528ba4dfef1SStephen Warren 1529ba4dfef1SStephen Warren eqos->tx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_MAX_PACKET_SIZE); 1530ba4dfef1SStephen Warren if (!eqos->tx_dma_buf) { 1531ba4dfef1SStephen Warren debug("%s: memalign(tx_dma_buf) failed\n", __func__); 1532ba4dfef1SStephen Warren ret = -ENOMEM; 1533ba4dfef1SStephen Warren goto err_free_descs; 1534ba4dfef1SStephen Warren } 15357a4c4eddSChristophe Roullier debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf); 1536ba4dfef1SStephen Warren 1537ba4dfef1SStephen Warren eqos->rx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_RX_BUFFER_SIZE); 1538ba4dfef1SStephen Warren if (!eqos->rx_dma_buf) { 1539ba4dfef1SStephen Warren debug("%s: memalign(rx_dma_buf) failed\n", __func__); 1540ba4dfef1SStephen Warren ret = -ENOMEM; 1541ba4dfef1SStephen Warren goto err_free_tx_dma_buf; 1542ba4dfef1SStephen Warren } 15437a4c4eddSChristophe Roullier debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf); 1544ba4dfef1SStephen Warren 1545ba4dfef1SStephen Warren eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE); 1546ba4dfef1SStephen Warren if (!eqos->rx_pkt) { 1547ba4dfef1SStephen Warren debug("%s: malloc(rx_pkt) failed\n", __func__); 1548ba4dfef1SStephen Warren ret = -ENOMEM; 1549ba4dfef1SStephen Warren goto err_free_rx_dma_buf; 1550ba4dfef1SStephen Warren } 1551ba4dfef1SStephen Warren debug("%s: rx_pkt=%p\n", __func__, eqos->rx_pkt); 1552ba4dfef1SStephen Warren 1553076e66fbSMarek Vasut eqos->config->ops->eqos_inval_buffer(eqos->rx_dma_buf, 1554076e66fbSMarek Vasut EQOS_MAX_PACKET_SIZE * EQOS_DESCRIPTORS_RX); 1555076e66fbSMarek Vasut 1556ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1557ba4dfef1SStephen Warren return 0; 1558ba4dfef1SStephen Warren 1559ba4dfef1SStephen Warren err_free_rx_dma_buf: 1560ba4dfef1SStephen Warren free(eqos->rx_dma_buf); 1561ba4dfef1SStephen Warren err_free_tx_dma_buf: 1562ba4dfef1SStephen Warren free(eqos->tx_dma_buf); 1563ba4dfef1SStephen Warren err_free_descs: 1564ba4dfef1SStephen Warren eqos_free_descs(eqos->descs); 1565ba4dfef1SStephen Warren err: 1566ba4dfef1SStephen Warren 1567ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 1568ba4dfef1SStephen Warren return ret; 1569ba4dfef1SStephen Warren } 1570ba4dfef1SStephen Warren 1571ba4dfef1SStephen Warren static int eqos_remove_resources_core(struct udevice *dev) 1572ba4dfef1SStephen Warren { 1573ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1574ba4dfef1SStephen Warren 1575ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1576ba4dfef1SStephen Warren 1577ba4dfef1SStephen Warren free(eqos->rx_pkt); 1578ba4dfef1SStephen Warren free(eqos->rx_dma_buf); 1579ba4dfef1SStephen Warren free(eqos->tx_dma_buf); 1580ba4dfef1SStephen Warren eqos_free_descs(eqos->descs); 1581ba4dfef1SStephen Warren 1582ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1583ba4dfef1SStephen Warren return 0; 1584ba4dfef1SStephen Warren } 1585ba4dfef1SStephen Warren 1586ba4dfef1SStephen Warren static int eqos_probe_resources_tegra186(struct udevice *dev) 1587ba4dfef1SStephen Warren { 1588ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1589ba4dfef1SStephen Warren int ret; 1590ba4dfef1SStephen Warren 1591ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1592ba4dfef1SStephen Warren 1593ba4dfef1SStephen Warren ret = reset_get_by_name(dev, "eqos", &eqos->reset_ctl); 1594ba4dfef1SStephen Warren if (ret) { 159590aa625cSMasahiro Yamada pr_err("reset_get_by_name(rst) failed: %d", ret); 1596ba4dfef1SStephen Warren return ret; 1597ba4dfef1SStephen Warren } 1598ba4dfef1SStephen Warren 1599ba4dfef1SStephen Warren ret = gpio_request_by_name(dev, "phy-reset-gpios", 0, 1600ba4dfef1SStephen Warren &eqos->phy_reset_gpio, 1601ba4dfef1SStephen Warren GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); 1602ba4dfef1SStephen Warren if (ret) { 160390aa625cSMasahiro Yamada pr_err("gpio_request_by_name(phy reset) failed: %d", ret); 1604ba4dfef1SStephen Warren goto err_free_reset_eqos; 1605ba4dfef1SStephen Warren } 1606ba4dfef1SStephen Warren 1607ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "slave_bus", &eqos->clk_slave_bus); 1608ba4dfef1SStephen Warren if (ret) { 160990aa625cSMasahiro Yamada pr_err("clk_get_by_name(slave_bus) failed: %d", ret); 1610ba4dfef1SStephen Warren goto err_free_gpio_phy_reset; 1611ba4dfef1SStephen Warren } 1612ba4dfef1SStephen Warren 1613ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "master_bus", &eqos->clk_master_bus); 1614ba4dfef1SStephen Warren if (ret) { 161590aa625cSMasahiro Yamada pr_err("clk_get_by_name(master_bus) failed: %d", ret); 1616ba4dfef1SStephen Warren goto err_free_clk_slave_bus; 1617ba4dfef1SStephen Warren } 1618ba4dfef1SStephen Warren 1619ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "rx", &eqos->clk_rx); 1620ba4dfef1SStephen Warren if (ret) { 162190aa625cSMasahiro Yamada pr_err("clk_get_by_name(rx) failed: %d", ret); 1622ba4dfef1SStephen Warren goto err_free_clk_master_bus; 1623ba4dfef1SStephen Warren } 1624ba4dfef1SStephen Warren 1625ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "ptp_ref", &eqos->clk_ptp_ref); 1626ba4dfef1SStephen Warren if (ret) { 162790aa625cSMasahiro Yamada pr_err("clk_get_by_name(ptp_ref) failed: %d", ret); 1628ba4dfef1SStephen Warren goto err_free_clk_rx; 1629ba4dfef1SStephen Warren return ret; 1630ba4dfef1SStephen Warren } 1631ba4dfef1SStephen Warren 1632ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "tx", &eqos->clk_tx); 1633ba4dfef1SStephen Warren if (ret) { 163490aa625cSMasahiro Yamada pr_err("clk_get_by_name(tx) failed: %d", ret); 1635ba4dfef1SStephen Warren goto err_free_clk_ptp_ref; 1636ba4dfef1SStephen Warren } 1637ba4dfef1SStephen Warren 1638ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1639ba4dfef1SStephen Warren return 0; 1640ba4dfef1SStephen Warren 1641ba4dfef1SStephen Warren err_free_clk_ptp_ref: 1642ba4dfef1SStephen Warren clk_free(&eqos->clk_ptp_ref); 1643ba4dfef1SStephen Warren err_free_clk_rx: 1644ba4dfef1SStephen Warren clk_free(&eqos->clk_rx); 1645ba4dfef1SStephen Warren err_free_clk_master_bus: 1646ba4dfef1SStephen Warren clk_free(&eqos->clk_master_bus); 1647ba4dfef1SStephen Warren err_free_clk_slave_bus: 1648ba4dfef1SStephen Warren clk_free(&eqos->clk_slave_bus); 1649ba4dfef1SStephen Warren err_free_gpio_phy_reset: 1650ba4dfef1SStephen Warren dm_gpio_free(dev, &eqos->phy_reset_gpio); 1651ba4dfef1SStephen Warren err_free_reset_eqos: 1652ba4dfef1SStephen Warren reset_free(&eqos->reset_ctl); 1653ba4dfef1SStephen Warren 1654ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 1655ba4dfef1SStephen Warren return ret; 1656ba4dfef1SStephen Warren } 1657ba4dfef1SStephen Warren 16587a4c4eddSChristophe Roullier /* board-specific Ethernet Interface initializations. */ 16591e8d5d80SPatrick Delaunay __weak int board_interface_eth_init(struct udevice *dev, 16601e8d5d80SPatrick Delaunay phy_interface_t interface_type) 16617a4c4eddSChristophe Roullier { 16627a4c4eddSChristophe Roullier return 0; 16637a4c4eddSChristophe Roullier } 16647a4c4eddSChristophe Roullier 16657a4c4eddSChristophe Roullier static int eqos_probe_resources_stm32(struct udevice *dev) 16667a4c4eddSChristophe Roullier { 16677a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 16687a4c4eddSChristophe Roullier int ret; 16697a4c4eddSChristophe Roullier phy_interface_t interface; 16705bd3c538SChristophe Roullier struct ofnode_phandle_args phandle_args; 16717a4c4eddSChristophe Roullier 16727a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 16737a4c4eddSChristophe Roullier 16747a4c4eddSChristophe Roullier interface = eqos->config->interface(dev); 16757a4c4eddSChristophe Roullier 16767a4c4eddSChristophe Roullier if (interface == PHY_INTERFACE_MODE_NONE) { 16777a4c4eddSChristophe Roullier pr_err("Invalid PHY interface\n"); 16787a4c4eddSChristophe Roullier return -EINVAL; 16797a4c4eddSChristophe Roullier } 16807a4c4eddSChristophe Roullier 16811e8d5d80SPatrick Delaunay ret = board_interface_eth_init(dev, interface); 16827a4c4eddSChristophe Roullier if (ret) 16837a4c4eddSChristophe Roullier return -EINVAL; 16847a4c4eddSChristophe Roullier 168583d31c08SPatrick Delaunay eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0); 168683d31c08SPatrick Delaunay 16877a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); 16887a4c4eddSChristophe Roullier if (ret) { 16897a4c4eddSChristophe Roullier pr_err("clk_get_by_name(master_bus) failed: %d", ret); 16907a4c4eddSChristophe Roullier goto err_probe; 16917a4c4eddSChristophe Roullier } 16927a4c4eddSChristophe Roullier 16937a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); 16947a4c4eddSChristophe Roullier if (ret) { 16957a4c4eddSChristophe Roullier pr_err("clk_get_by_name(rx) failed: %d", ret); 16967a4c4eddSChristophe Roullier goto err_free_clk_master_bus; 16977a4c4eddSChristophe Roullier } 16987a4c4eddSChristophe Roullier 16997a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); 17007a4c4eddSChristophe Roullier if (ret) { 17017a4c4eddSChristophe Roullier pr_err("clk_get_by_name(tx) failed: %d", ret); 17027a4c4eddSChristophe Roullier goto err_free_clk_rx; 17037a4c4eddSChristophe Roullier } 17047a4c4eddSChristophe Roullier 17057a4c4eddSChristophe Roullier /* Get ETH_CLK clocks (optional) */ 17067a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck); 17077a4c4eddSChristophe Roullier if (ret) 17087a4c4eddSChristophe Roullier pr_warn("No phy clock provided %d", ret); 17097a4c4eddSChristophe Roullier 171083d31c08SPatrick Delaunay eqos->phyaddr = -1; 17115bd3c538SChristophe Roullier ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, 17125bd3c538SChristophe Roullier &phandle_args); 17135bd3c538SChristophe Roullier if (!ret) { 17145bd3c538SChristophe Roullier /* search "reset-gpios" in phy node */ 17155bd3c538SChristophe Roullier ret = gpio_request_by_name_nodev(phandle_args.node, 17165bd3c538SChristophe Roullier "reset-gpios", 0, 17175bd3c538SChristophe Roullier &eqos->phy_reset_gpio, 17185bd3c538SChristophe Roullier GPIOD_IS_OUT | 17195bd3c538SChristophe Roullier GPIOD_IS_OUT_ACTIVE); 17205bd3c538SChristophe Roullier if (ret) 17215bd3c538SChristophe Roullier pr_warn("gpio_request_by_name(phy reset) not provided %d", 17225bd3c538SChristophe Roullier ret); 172383d31c08SPatrick Delaunay 172483d31c08SPatrick Delaunay eqos->phyaddr = ofnode_read_u32_default(phandle_args.node, 172583d31c08SPatrick Delaunay "reg", -1); 17265bd3c538SChristophe Roullier } 17275bd3c538SChristophe Roullier 17287a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 17297a4c4eddSChristophe Roullier return 0; 17307a4c4eddSChristophe Roullier 17317a4c4eddSChristophe Roullier err_free_clk_rx: 17327a4c4eddSChristophe Roullier clk_free(&eqos->clk_rx); 17337a4c4eddSChristophe Roullier err_free_clk_master_bus: 17347a4c4eddSChristophe Roullier clk_free(&eqos->clk_master_bus); 17357a4c4eddSChristophe Roullier err_probe: 17367a4c4eddSChristophe Roullier 17377a4c4eddSChristophe Roullier debug("%s: returns %d\n", __func__, ret); 17387a4c4eddSChristophe Roullier return ret; 17397a4c4eddSChristophe Roullier } 17407a4c4eddSChristophe Roullier 17417a4c4eddSChristophe Roullier static phy_interface_t eqos_get_interface_stm32(struct udevice *dev) 17427a4c4eddSChristophe Roullier { 17437a4c4eddSChristophe Roullier const char *phy_mode; 17447a4c4eddSChristophe Roullier phy_interface_t interface = PHY_INTERFACE_MODE_NONE; 17457a4c4eddSChristophe Roullier 17467a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 17477a4c4eddSChristophe Roullier 17487a4c4eddSChristophe Roullier phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", 17497a4c4eddSChristophe Roullier NULL); 17507a4c4eddSChristophe Roullier if (phy_mode) 17517a4c4eddSChristophe Roullier interface = phy_get_interface_by_name(phy_mode); 17527a4c4eddSChristophe Roullier 17537a4c4eddSChristophe Roullier return interface; 17547a4c4eddSChristophe Roullier } 17557a4c4eddSChristophe Roullier 17567a4c4eddSChristophe Roullier static phy_interface_t eqos_get_interface_tegra186(struct udevice *dev) 17577a4c4eddSChristophe Roullier { 17587a4c4eddSChristophe Roullier return PHY_INTERFACE_MODE_MII; 17597a4c4eddSChristophe Roullier } 17607a4c4eddSChristophe Roullier 1761ba4dfef1SStephen Warren static int eqos_remove_resources_tegra186(struct udevice *dev) 1762ba4dfef1SStephen Warren { 1763ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1764ba4dfef1SStephen Warren 1765ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1766ba4dfef1SStephen Warren 1767ba4dfef1SStephen Warren clk_free(&eqos->clk_tx); 1768ba4dfef1SStephen Warren clk_free(&eqos->clk_ptp_ref); 1769ba4dfef1SStephen Warren clk_free(&eqos->clk_rx); 1770ba4dfef1SStephen Warren clk_free(&eqos->clk_slave_bus); 1771ba4dfef1SStephen Warren clk_free(&eqos->clk_master_bus); 1772ba4dfef1SStephen Warren dm_gpio_free(dev, &eqos->phy_reset_gpio); 1773ba4dfef1SStephen Warren reset_free(&eqos->reset_ctl); 1774ba4dfef1SStephen Warren 1775ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1776ba4dfef1SStephen Warren return 0; 1777ba4dfef1SStephen Warren } 1778ba4dfef1SStephen Warren 17797a4c4eddSChristophe Roullier static int eqos_remove_resources_stm32(struct udevice *dev) 17807a4c4eddSChristophe Roullier { 17817a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 17827a4c4eddSChristophe Roullier 17837a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 17847a4c4eddSChristophe Roullier 17857a4c4eddSChristophe Roullier clk_free(&eqos->clk_tx); 17867a4c4eddSChristophe Roullier clk_free(&eqos->clk_rx); 17877a4c4eddSChristophe Roullier clk_free(&eqos->clk_master_bus); 17887a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) 17897a4c4eddSChristophe Roullier clk_free(&eqos->clk_ck); 17907a4c4eddSChristophe Roullier 17915bd3c538SChristophe Roullier if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) 17925bd3c538SChristophe Roullier dm_gpio_free(dev, &eqos->phy_reset_gpio); 17935bd3c538SChristophe Roullier 17947a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 17957a4c4eddSChristophe Roullier return 0; 17967a4c4eddSChristophe Roullier } 17977a4c4eddSChristophe Roullier 1798ba4dfef1SStephen Warren static int eqos_probe(struct udevice *dev) 1799ba4dfef1SStephen Warren { 1800ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1801ba4dfef1SStephen Warren int ret; 1802ba4dfef1SStephen Warren 1803ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1804ba4dfef1SStephen Warren 1805ba4dfef1SStephen Warren eqos->dev = dev; 1806ba4dfef1SStephen Warren eqos->config = (void *)dev_get_driver_data(dev); 1807ba4dfef1SStephen Warren 1808a821c4afSSimon Glass eqos->regs = devfdt_get_addr(dev); 1809ba4dfef1SStephen Warren if (eqos->regs == FDT_ADDR_T_NONE) { 181090aa625cSMasahiro Yamada pr_err("devfdt_get_addr() failed"); 1811ba4dfef1SStephen Warren return -ENODEV; 1812ba4dfef1SStephen Warren } 1813ba4dfef1SStephen Warren eqos->mac_regs = (void *)(eqos->regs + EQOS_MAC_REGS_BASE); 1814ba4dfef1SStephen Warren eqos->mtl_regs = (void *)(eqos->regs + EQOS_MTL_REGS_BASE); 1815ba4dfef1SStephen Warren eqos->dma_regs = (void *)(eqos->regs + EQOS_DMA_REGS_BASE); 1816ba4dfef1SStephen Warren eqos->tegra186_regs = (void *)(eqos->regs + EQOS_TEGRA186_REGS_BASE); 1817ba4dfef1SStephen Warren 1818ba4dfef1SStephen Warren ret = eqos_probe_resources_core(dev); 1819ba4dfef1SStephen Warren if (ret < 0) { 182090aa625cSMasahiro Yamada pr_err("eqos_probe_resources_core() failed: %d", ret); 1821ba4dfef1SStephen Warren return ret; 1822ba4dfef1SStephen Warren } 1823ba4dfef1SStephen Warren 18247a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_probe_resources(dev); 1825ba4dfef1SStephen Warren if (ret < 0) { 18267a4c4eddSChristophe Roullier pr_err("eqos_probe_resources() failed: %d", ret); 1827ba4dfef1SStephen Warren goto err_remove_resources_core; 1828ba4dfef1SStephen Warren } 1829ba4dfef1SStephen Warren 1830*8e3eceb0SYe Li #ifdef CONFIG_DM_ETH_PHY 1831*8e3eceb0SYe Li eqos->mii = eth_phy_get_mdio_bus(dev); 1832*8e3eceb0SYe Li #endif 1833*8e3eceb0SYe Li if (!eqos->mii) { 1834ba4dfef1SStephen Warren eqos->mii = mdio_alloc(); 1835ba4dfef1SStephen Warren if (!eqos->mii) { 183690aa625cSMasahiro Yamada pr_err("mdio_alloc() failed"); 18377a4c4eddSChristophe Roullier ret = -ENOMEM; 1838ba4dfef1SStephen Warren goto err_remove_resources_tegra; 1839ba4dfef1SStephen Warren } 1840ba4dfef1SStephen Warren eqos->mii->read = eqos_mdio_read; 1841ba4dfef1SStephen Warren eqos->mii->write = eqos_mdio_write; 1842ba4dfef1SStephen Warren eqos->mii->priv = eqos; 1843ba4dfef1SStephen Warren strcpy(eqos->mii->name, dev->name); 1844ba4dfef1SStephen Warren 1845ba4dfef1SStephen Warren ret = mdio_register(eqos->mii); 1846ba4dfef1SStephen Warren if (ret < 0) { 184790aa625cSMasahiro Yamada pr_err("mdio_register() failed: %d", ret); 1848ba4dfef1SStephen Warren goto err_free_mdio; 1849ba4dfef1SStephen Warren } 1850*8e3eceb0SYe Li } 1851*8e3eceb0SYe Li 1852*8e3eceb0SYe Li #ifdef CONFIG_DM_ETH_PHY 1853*8e3eceb0SYe Li eth_phy_set_mdio_bus(dev, eqos->mii); 1854*8e3eceb0SYe Li #endif 1855ba4dfef1SStephen Warren 1856ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1857ba4dfef1SStephen Warren return 0; 1858ba4dfef1SStephen Warren 1859ba4dfef1SStephen Warren err_free_mdio: 1860ba4dfef1SStephen Warren mdio_free(eqos->mii); 1861ba4dfef1SStephen Warren err_remove_resources_tegra: 18627a4c4eddSChristophe Roullier eqos->config->ops->eqos_remove_resources(dev); 1863ba4dfef1SStephen Warren err_remove_resources_core: 1864ba4dfef1SStephen Warren eqos_remove_resources_core(dev); 1865ba4dfef1SStephen Warren 1866ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 1867ba4dfef1SStephen Warren return ret; 1868ba4dfef1SStephen Warren } 1869ba4dfef1SStephen Warren 1870ba4dfef1SStephen Warren static int eqos_remove(struct udevice *dev) 1871ba4dfef1SStephen Warren { 1872ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1873ba4dfef1SStephen Warren 1874ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1875ba4dfef1SStephen Warren 1876ba4dfef1SStephen Warren mdio_unregister(eqos->mii); 1877ba4dfef1SStephen Warren mdio_free(eqos->mii); 18787a4c4eddSChristophe Roullier eqos->config->ops->eqos_remove_resources(dev); 18797a4c4eddSChristophe Roullier 1880ba4dfef1SStephen Warren eqos_probe_resources_core(dev); 1881ba4dfef1SStephen Warren 1882ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1883ba4dfef1SStephen Warren return 0; 1884ba4dfef1SStephen Warren } 1885ba4dfef1SStephen Warren 1886ba4dfef1SStephen Warren static const struct eth_ops eqos_ops = { 1887ba4dfef1SStephen Warren .start = eqos_start, 1888ba4dfef1SStephen Warren .stop = eqos_stop, 1889ba4dfef1SStephen Warren .send = eqos_send, 1890ba4dfef1SStephen Warren .recv = eqos_recv, 1891ba4dfef1SStephen Warren .free_pkt = eqos_free_pkt, 1892ba4dfef1SStephen Warren .write_hwaddr = eqos_write_hwaddr, 1893ba4dfef1SStephen Warren }; 1894ba4dfef1SStephen Warren 18957a4c4eddSChristophe Roullier static struct eqos_ops eqos_tegra186_ops = { 18967a4c4eddSChristophe Roullier .eqos_inval_desc = eqos_inval_desc_tegra186, 18977a4c4eddSChristophe Roullier .eqos_flush_desc = eqos_flush_desc_tegra186, 18987a4c4eddSChristophe Roullier .eqos_inval_buffer = eqos_inval_buffer_tegra186, 18997a4c4eddSChristophe Roullier .eqos_flush_buffer = eqos_flush_buffer_tegra186, 19007a4c4eddSChristophe Roullier .eqos_probe_resources = eqos_probe_resources_tegra186, 19017a4c4eddSChristophe Roullier .eqos_remove_resources = eqos_remove_resources_tegra186, 19027a4c4eddSChristophe Roullier .eqos_stop_resets = eqos_stop_resets_tegra186, 19037a4c4eddSChristophe Roullier .eqos_start_resets = eqos_start_resets_tegra186, 19047a4c4eddSChristophe Roullier .eqos_stop_clks = eqos_stop_clks_tegra186, 19057a4c4eddSChristophe Roullier .eqos_start_clks = eqos_start_clks_tegra186, 19067a4c4eddSChristophe Roullier .eqos_calibrate_pads = eqos_calibrate_pads_tegra186, 19077a4c4eddSChristophe Roullier .eqos_disable_calibration = eqos_disable_calibration_tegra186, 19087a4c4eddSChristophe Roullier .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186, 19097a4c4eddSChristophe Roullier .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186 19107a4c4eddSChristophe Roullier }; 19117a4c4eddSChristophe Roullier 1912ba4dfef1SStephen Warren static const struct eqos_config eqos_tegra186_config = { 1913ba4dfef1SStephen Warren .reg_access_always_ok = false, 19147a4c4eddSChristophe Roullier .mdio_wait = 10, 19157a4c4eddSChristophe Roullier .swr_wait = 10, 19167a4c4eddSChristophe Roullier .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, 19177a4c4eddSChristophe Roullier .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35, 19187a4c4eddSChristophe Roullier .interface = eqos_get_interface_tegra186, 19197a4c4eddSChristophe Roullier .ops = &eqos_tegra186_ops 19207a4c4eddSChristophe Roullier }; 19217a4c4eddSChristophe Roullier 19227a4c4eddSChristophe Roullier static struct eqos_ops eqos_stm32_ops = { 19237a4c4eddSChristophe Roullier .eqos_inval_desc = eqos_inval_desc_stm32, 19247a4c4eddSChristophe Roullier .eqos_flush_desc = eqos_flush_desc_stm32, 19257a4c4eddSChristophe Roullier .eqos_inval_buffer = eqos_inval_buffer_stm32, 19267a4c4eddSChristophe Roullier .eqos_flush_buffer = eqos_flush_buffer_stm32, 19277a4c4eddSChristophe Roullier .eqos_probe_resources = eqos_probe_resources_stm32, 19287a4c4eddSChristophe Roullier .eqos_remove_resources = eqos_remove_resources_stm32, 19297a4c4eddSChristophe Roullier .eqos_stop_resets = eqos_stop_resets_stm32, 19307a4c4eddSChristophe Roullier .eqos_start_resets = eqos_start_resets_stm32, 19317a4c4eddSChristophe Roullier .eqos_stop_clks = eqos_stop_clks_stm32, 19327a4c4eddSChristophe Roullier .eqos_start_clks = eqos_start_clks_stm32, 19337a4c4eddSChristophe Roullier .eqos_calibrate_pads = eqos_calibrate_pads_stm32, 19347a4c4eddSChristophe Roullier .eqos_disable_calibration = eqos_disable_calibration_stm32, 19357a4c4eddSChristophe Roullier .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_stm32, 19367a4c4eddSChristophe Roullier .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 19377a4c4eddSChristophe Roullier }; 19387a4c4eddSChristophe Roullier 19397a4c4eddSChristophe Roullier static const struct eqos_config eqos_stm32_config = { 19407a4c4eddSChristophe Roullier .reg_access_always_ok = false, 19417a4c4eddSChristophe Roullier .mdio_wait = 10000, 19427a4c4eddSChristophe Roullier .swr_wait = 50, 19437a4c4eddSChristophe Roullier .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, 19447a4c4eddSChristophe Roullier .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, 19457a4c4eddSChristophe Roullier .interface = eqos_get_interface_stm32, 19467a4c4eddSChristophe Roullier .ops = &eqos_stm32_ops 1947ba4dfef1SStephen Warren }; 1948ba4dfef1SStephen Warren 1949ba4dfef1SStephen Warren static const struct udevice_id eqos_ids[] = { 1950ba4dfef1SStephen Warren { 1951ba4dfef1SStephen Warren .compatible = "nvidia,tegra186-eqos", 1952ba4dfef1SStephen Warren .data = (ulong)&eqos_tegra186_config 1953ba4dfef1SStephen Warren }, 19547a4c4eddSChristophe Roullier { 19557a4c4eddSChristophe Roullier .compatible = "snps,dwmac-4.20a", 19567a4c4eddSChristophe Roullier .data = (ulong)&eqos_stm32_config 19577a4c4eddSChristophe Roullier }, 19587a4c4eddSChristophe Roullier 1959ba4dfef1SStephen Warren { } 1960ba4dfef1SStephen Warren }; 1961ba4dfef1SStephen Warren 1962ba4dfef1SStephen Warren U_BOOT_DRIVER(eth_eqos) = { 1963ba4dfef1SStephen Warren .name = "eth_eqos", 1964ba4dfef1SStephen Warren .id = UCLASS_ETH, 1965ba4dfef1SStephen Warren .of_match = eqos_ids, 1966ba4dfef1SStephen Warren .probe = eqos_probe, 1967ba4dfef1SStephen Warren .remove = eqos_remove, 1968ba4dfef1SStephen Warren .ops = &eqos_ops, 1969ba4dfef1SStephen Warren .priv_auto_alloc_size = sizeof(struct eqos_priv), 1970ba4dfef1SStephen Warren .platdata_auto_alloc_size = sizeof(struct eth_pdata), 1971ba4dfef1SStephen Warren }; 1972