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> 43ba4dfef1SStephen Warren 44ba4dfef1SStephen Warren /* Core registers */ 45ba4dfef1SStephen Warren 46ba4dfef1SStephen Warren #define EQOS_MAC_REGS_BASE 0x000 47ba4dfef1SStephen Warren struct eqos_mac_regs { 48ba4dfef1SStephen Warren uint32_t configuration; /* 0x000 */ 49ba4dfef1SStephen Warren uint32_t unused_004[(0x070 - 0x004) / 4]; /* 0x004 */ 50ba4dfef1SStephen Warren uint32_t q0_tx_flow_ctrl; /* 0x070 */ 51ba4dfef1SStephen Warren uint32_t unused_070[(0x090 - 0x074) / 4]; /* 0x074 */ 52ba4dfef1SStephen Warren uint32_t rx_flow_ctrl; /* 0x090 */ 53ba4dfef1SStephen Warren uint32_t unused_094; /* 0x094 */ 54ba4dfef1SStephen Warren uint32_t txq_prty_map0; /* 0x098 */ 55ba4dfef1SStephen Warren uint32_t unused_09c; /* 0x09c */ 56ba4dfef1SStephen Warren uint32_t rxq_ctrl0; /* 0x0a0 */ 57ba4dfef1SStephen Warren uint32_t unused_0a4; /* 0x0a4 */ 58ba4dfef1SStephen Warren uint32_t rxq_ctrl2; /* 0x0a8 */ 59ba4dfef1SStephen Warren uint32_t unused_0ac[(0x0dc - 0x0ac) / 4]; /* 0x0ac */ 60ba4dfef1SStephen Warren uint32_t us_tic_counter; /* 0x0dc */ 61ba4dfef1SStephen Warren uint32_t unused_0e0[(0x11c - 0x0e0) / 4]; /* 0x0e0 */ 62ba4dfef1SStephen Warren uint32_t hw_feature0; /* 0x11c */ 63ba4dfef1SStephen Warren uint32_t hw_feature1; /* 0x120 */ 64ba4dfef1SStephen Warren uint32_t hw_feature2; /* 0x124 */ 65ba4dfef1SStephen Warren uint32_t unused_128[(0x200 - 0x128) / 4]; /* 0x128 */ 66ba4dfef1SStephen Warren uint32_t mdio_address; /* 0x200 */ 67ba4dfef1SStephen Warren uint32_t mdio_data; /* 0x204 */ 68ba4dfef1SStephen Warren uint32_t unused_208[(0x300 - 0x208) / 4]; /* 0x208 */ 69ba4dfef1SStephen Warren uint32_t address0_high; /* 0x300 */ 70ba4dfef1SStephen Warren uint32_t address0_low; /* 0x304 */ 71ba4dfef1SStephen Warren }; 72ba4dfef1SStephen Warren 73ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_GPSLCE BIT(23) 74ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_CST BIT(21) 75ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_ACS BIT(20) 76ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_WD BIT(19) 77ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_JD BIT(17) 78ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_JE BIT(16) 79ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_PS BIT(15) 80ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_FES BIT(14) 81ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_DM BIT(13) 82ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_TE BIT(1) 83ba4dfef1SStephen Warren #define EQOS_MAC_CONFIGURATION_RE BIT(0) 84ba4dfef1SStephen Warren 85ba4dfef1SStephen Warren #define EQOS_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT 16 86ba4dfef1SStephen Warren #define EQOS_MAC_Q0_TX_FLOW_CTRL_PT_MASK 0xffff 87ba4dfef1SStephen Warren #define EQOS_MAC_Q0_TX_FLOW_CTRL_TFE BIT(1) 88ba4dfef1SStephen Warren 89ba4dfef1SStephen Warren #define EQOS_MAC_RX_FLOW_CTRL_RFE BIT(0) 90ba4dfef1SStephen Warren 91ba4dfef1SStephen Warren #define EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_SHIFT 0 92ba4dfef1SStephen Warren #define EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_MASK 0xff 93ba4dfef1SStephen Warren 94ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT 0 95ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK 3 96ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_NOT_ENABLED 0 97ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB 2 98*7a4c4eddSChristophe Roullier #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV 1 99ba4dfef1SStephen Warren 100ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT 0 101ba4dfef1SStephen Warren #define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK 0xff 102ba4dfef1SStephen Warren 103ba4dfef1SStephen Warren #define EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_SHIFT 6 104ba4dfef1SStephen Warren #define EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_MASK 0x1f 105ba4dfef1SStephen Warren #define EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT 0 106ba4dfef1SStephen Warren #define EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK 0x1f 107ba4dfef1SStephen Warren 108ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_PA_SHIFT 21 109ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT 16 110ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT 8 111ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_CR_20_35 2 112*7a4c4eddSChristophe Roullier #define EQOS_MAC_MDIO_ADDRESS_CR_250_300 5 113ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_SKAP BIT(4) 114ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT 2 115ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_GOC_READ 3 116ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_GOC_WRITE 1 117ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_C45E BIT(1) 118ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_ADDRESS_GB BIT(0) 119ba4dfef1SStephen Warren 120ba4dfef1SStephen Warren #define EQOS_MAC_MDIO_DATA_GD_MASK 0xffff 121ba4dfef1SStephen Warren 122ba4dfef1SStephen Warren #define EQOS_MTL_REGS_BASE 0xd00 123ba4dfef1SStephen Warren struct eqos_mtl_regs { 124ba4dfef1SStephen Warren uint32_t txq0_operation_mode; /* 0xd00 */ 125ba4dfef1SStephen Warren uint32_t unused_d04; /* 0xd04 */ 126ba4dfef1SStephen Warren uint32_t txq0_debug; /* 0xd08 */ 127ba4dfef1SStephen Warren uint32_t unused_d0c[(0xd18 - 0xd0c) / 4]; /* 0xd0c */ 128ba4dfef1SStephen Warren uint32_t txq0_quantum_weight; /* 0xd18 */ 129ba4dfef1SStephen Warren uint32_t unused_d1c[(0xd30 - 0xd1c) / 4]; /* 0xd1c */ 130ba4dfef1SStephen Warren uint32_t rxq0_operation_mode; /* 0xd30 */ 131ba4dfef1SStephen Warren uint32_t unused_d34; /* 0xd34 */ 132ba4dfef1SStephen Warren uint32_t rxq0_debug; /* 0xd38 */ 133ba4dfef1SStephen Warren }; 134ba4dfef1SStephen Warren 135ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT 16 136ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK 0x1ff 137ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_SHIFT 2 138ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_MASK 3 139ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_ENABLED 2 140ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_TSF BIT(1) 141ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_OPERATION_MODE_FTQ BIT(0) 142ba4dfef1SStephen Warren 143ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_DEBUG_TXQSTS BIT(4) 144ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_DEBUG_TRCSTS_SHIFT 1 145ba4dfef1SStephen Warren #define EQOS_MTL_TXQ0_DEBUG_TRCSTS_MASK 3 146ba4dfef1SStephen Warren 147ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT 20 148ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RQS_MASK 0x3ff 149ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT 14 150ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RFD_MASK 0x3f 151ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT 8 152ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RFA_MASK 0x3f 153ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_EHFC BIT(7) 154ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_OPERATION_MODE_RSF BIT(5) 155ba4dfef1SStephen Warren 156ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_DEBUG_PRXQ_SHIFT 16 157ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_DEBUG_PRXQ_MASK 0x7fff 158ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_DEBUG_RXQSTS_SHIFT 4 159ba4dfef1SStephen Warren #define EQOS_MTL_RXQ0_DEBUG_RXQSTS_MASK 3 160ba4dfef1SStephen Warren 161ba4dfef1SStephen Warren #define EQOS_DMA_REGS_BASE 0x1000 162ba4dfef1SStephen Warren struct eqos_dma_regs { 163ba4dfef1SStephen Warren uint32_t mode; /* 0x1000 */ 164ba4dfef1SStephen Warren uint32_t sysbus_mode; /* 0x1004 */ 165ba4dfef1SStephen Warren uint32_t unused_1008[(0x1100 - 0x1008) / 4]; /* 0x1008 */ 166ba4dfef1SStephen Warren uint32_t ch0_control; /* 0x1100 */ 167ba4dfef1SStephen Warren uint32_t ch0_tx_control; /* 0x1104 */ 168ba4dfef1SStephen Warren uint32_t ch0_rx_control; /* 0x1108 */ 169ba4dfef1SStephen Warren uint32_t unused_110c; /* 0x110c */ 170ba4dfef1SStephen Warren uint32_t ch0_txdesc_list_haddress; /* 0x1110 */ 171ba4dfef1SStephen Warren uint32_t ch0_txdesc_list_address; /* 0x1114 */ 172ba4dfef1SStephen Warren uint32_t ch0_rxdesc_list_haddress; /* 0x1118 */ 173ba4dfef1SStephen Warren uint32_t ch0_rxdesc_list_address; /* 0x111c */ 174ba4dfef1SStephen Warren uint32_t ch0_txdesc_tail_pointer; /* 0x1120 */ 175ba4dfef1SStephen Warren uint32_t unused_1124; /* 0x1124 */ 176ba4dfef1SStephen Warren uint32_t ch0_rxdesc_tail_pointer; /* 0x1128 */ 177ba4dfef1SStephen Warren uint32_t ch0_txdesc_ring_length; /* 0x112c */ 178ba4dfef1SStephen Warren uint32_t ch0_rxdesc_ring_length; /* 0x1130 */ 179ba4dfef1SStephen Warren }; 180ba4dfef1SStephen Warren 181ba4dfef1SStephen Warren #define EQOS_DMA_MODE_SWR BIT(0) 182ba4dfef1SStephen Warren 183ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_SHIFT 16 184ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_MASK 0xf 185ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_EAME BIT(11) 186ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_BLEN16 BIT(3) 187ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_BLEN8 BIT(2) 188ba4dfef1SStephen Warren #define EQOS_DMA_SYSBUS_MODE_BLEN4 BIT(1) 189ba4dfef1SStephen Warren 190ba4dfef1SStephen Warren #define EQOS_DMA_CH0_CONTROL_PBLX8 BIT(16) 191ba4dfef1SStephen Warren 192ba4dfef1SStephen Warren #define EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT 16 193ba4dfef1SStephen Warren #define EQOS_DMA_CH0_TX_CONTROL_TXPBL_MASK 0x3f 194ba4dfef1SStephen Warren #define EQOS_DMA_CH0_TX_CONTROL_OSP BIT(4) 195ba4dfef1SStephen Warren #define EQOS_DMA_CH0_TX_CONTROL_ST BIT(0) 196ba4dfef1SStephen Warren 197ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT 16 198ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_RXPBL_MASK 0x3f 199ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT 1 200ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_RBSZ_MASK 0x3fff 201ba4dfef1SStephen Warren #define EQOS_DMA_CH0_RX_CONTROL_SR BIT(0) 202ba4dfef1SStephen Warren 203ba4dfef1SStephen Warren /* These registers are Tegra186-specific */ 204ba4dfef1SStephen Warren #define EQOS_TEGRA186_REGS_BASE 0x8800 205ba4dfef1SStephen Warren struct eqos_tegra186_regs { 206ba4dfef1SStephen Warren uint32_t sdmemcomppadctrl; /* 0x8800 */ 207ba4dfef1SStephen Warren uint32_t auto_cal_config; /* 0x8804 */ 208ba4dfef1SStephen Warren uint32_t unused_8808; /* 0x8808 */ 209ba4dfef1SStephen Warren uint32_t auto_cal_status; /* 0x880c */ 210ba4dfef1SStephen Warren }; 211ba4dfef1SStephen Warren 212ba4dfef1SStephen Warren #define EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31) 213ba4dfef1SStephen Warren 214ba4dfef1SStephen Warren #define EQOS_AUTO_CAL_CONFIG_START BIT(31) 215ba4dfef1SStephen Warren #define EQOS_AUTO_CAL_CONFIG_ENABLE BIT(29) 216ba4dfef1SStephen Warren 217ba4dfef1SStephen Warren #define EQOS_AUTO_CAL_STATUS_ACTIVE BIT(31) 218ba4dfef1SStephen Warren 219ba4dfef1SStephen Warren /* Descriptors */ 220ba4dfef1SStephen Warren 221ba4dfef1SStephen Warren #define EQOS_DESCRIPTOR_WORDS 4 222ba4dfef1SStephen Warren #define EQOS_DESCRIPTOR_SIZE (EQOS_DESCRIPTOR_WORDS * 4) 223ba4dfef1SStephen Warren /* We assume ARCH_DMA_MINALIGN >= 16; 16 is the EQOS HW minimum */ 224ba4dfef1SStephen Warren #define EQOS_DESCRIPTOR_ALIGN ARCH_DMA_MINALIGN 225ba4dfef1SStephen Warren #define EQOS_DESCRIPTORS_TX 4 226ba4dfef1SStephen Warren #define EQOS_DESCRIPTORS_RX 4 227ba4dfef1SStephen Warren #define EQOS_DESCRIPTORS_NUM (EQOS_DESCRIPTORS_TX + EQOS_DESCRIPTORS_RX) 228ba4dfef1SStephen Warren #define EQOS_DESCRIPTORS_SIZE ALIGN(EQOS_DESCRIPTORS_NUM * \ 229ba4dfef1SStephen Warren EQOS_DESCRIPTOR_SIZE, ARCH_DMA_MINALIGN) 230ba4dfef1SStephen Warren #define EQOS_BUFFER_ALIGN ARCH_DMA_MINALIGN 231ba4dfef1SStephen Warren #define EQOS_MAX_PACKET_SIZE ALIGN(1568, ARCH_DMA_MINALIGN) 232ba4dfef1SStephen Warren #define EQOS_RX_BUFFER_SIZE (EQOS_DESCRIPTORS_RX * EQOS_MAX_PACKET_SIZE) 233ba4dfef1SStephen Warren 234ba4dfef1SStephen Warren /* 235ba4dfef1SStephen Warren * Warn if the cache-line size is larger than the descriptor size. In such 236ba4dfef1SStephen Warren * cases the driver will likely fail because the CPU needs to flush the cache 237ba4dfef1SStephen Warren * when requeuing RX buffers, therefore descriptors written by the hardware 238ba4dfef1SStephen Warren * may be discarded. Architectures with full IO coherence, such as x86, do not 239ba4dfef1SStephen Warren * experience this issue, and hence are excluded from this condition. 240ba4dfef1SStephen Warren * 241ba4dfef1SStephen Warren * This can be fixed by defining CONFIG_SYS_NONCACHED_MEMORY which will cause 242ba4dfef1SStephen Warren * the driver to allocate descriptors from a pool of non-cached memory. 243ba4dfef1SStephen Warren */ 244ba4dfef1SStephen Warren #if EQOS_DESCRIPTOR_SIZE < ARCH_DMA_MINALIGN 245ba4dfef1SStephen Warren #if !defined(CONFIG_SYS_NONCACHED_MEMORY) && \ 246ba4dfef1SStephen Warren !defined(CONFIG_SYS_DCACHE_OFF) && !defined(CONFIG_X86) 247ba4dfef1SStephen Warren #warning Cache line size is larger than descriptor size 248ba4dfef1SStephen Warren #endif 249ba4dfef1SStephen Warren #endif 250ba4dfef1SStephen Warren 251ba4dfef1SStephen Warren struct eqos_desc { 252ba4dfef1SStephen Warren u32 des0; 253ba4dfef1SStephen Warren u32 des1; 254ba4dfef1SStephen Warren u32 des2; 255ba4dfef1SStephen Warren u32 des3; 256ba4dfef1SStephen Warren }; 257ba4dfef1SStephen Warren 258ba4dfef1SStephen Warren #define EQOS_DESC3_OWN BIT(31) 259ba4dfef1SStephen Warren #define EQOS_DESC3_FD BIT(29) 260ba4dfef1SStephen Warren #define EQOS_DESC3_LD BIT(28) 261ba4dfef1SStephen Warren #define EQOS_DESC3_BUF1V BIT(24) 262ba4dfef1SStephen Warren 263ba4dfef1SStephen Warren struct eqos_config { 264ba4dfef1SStephen Warren bool reg_access_always_ok; 265*7a4c4eddSChristophe Roullier int mdio_wait; 266*7a4c4eddSChristophe Roullier int swr_wait; 267*7a4c4eddSChristophe Roullier int config_mac; 268*7a4c4eddSChristophe Roullier int config_mac_mdio; 269*7a4c4eddSChristophe Roullier phy_interface_t (*interface)(struct udevice *dev); 270*7a4c4eddSChristophe Roullier struct eqos_ops *ops; 271*7a4c4eddSChristophe Roullier }; 272*7a4c4eddSChristophe Roullier 273*7a4c4eddSChristophe Roullier struct eqos_ops { 274*7a4c4eddSChristophe Roullier void (*eqos_inval_desc)(void *desc); 275*7a4c4eddSChristophe Roullier void (*eqos_flush_desc)(void *desc); 276*7a4c4eddSChristophe Roullier void (*eqos_inval_buffer)(void *buf, size_t size); 277*7a4c4eddSChristophe Roullier void (*eqos_flush_buffer)(void *buf, size_t size); 278*7a4c4eddSChristophe Roullier int (*eqos_probe_resources)(struct udevice *dev); 279*7a4c4eddSChristophe Roullier int (*eqos_remove_resources)(struct udevice *dev); 280*7a4c4eddSChristophe Roullier int (*eqos_stop_resets)(struct udevice *dev); 281*7a4c4eddSChristophe Roullier int (*eqos_start_resets)(struct udevice *dev); 282*7a4c4eddSChristophe Roullier void (*eqos_stop_clks)(struct udevice *dev); 283*7a4c4eddSChristophe Roullier int (*eqos_start_clks)(struct udevice *dev); 284*7a4c4eddSChristophe Roullier int (*eqos_calibrate_pads)(struct udevice *dev); 285*7a4c4eddSChristophe Roullier int (*eqos_disable_calibration)(struct udevice *dev); 286*7a4c4eddSChristophe Roullier int (*eqos_set_tx_clk_speed)(struct udevice *dev); 287*7a4c4eddSChristophe Roullier ulong (*eqos_get_tick_clk_rate)(struct udevice *dev); 288ba4dfef1SStephen Warren }; 289ba4dfef1SStephen Warren 290ba4dfef1SStephen Warren struct eqos_priv { 291ba4dfef1SStephen Warren struct udevice *dev; 292ba4dfef1SStephen Warren const struct eqos_config *config; 293ba4dfef1SStephen Warren fdt_addr_t regs; 294ba4dfef1SStephen Warren struct eqos_mac_regs *mac_regs; 295ba4dfef1SStephen Warren struct eqos_mtl_regs *mtl_regs; 296ba4dfef1SStephen Warren struct eqos_dma_regs *dma_regs; 297ba4dfef1SStephen Warren struct eqos_tegra186_regs *tegra186_regs; 298ba4dfef1SStephen Warren struct reset_ctl reset_ctl; 299ba4dfef1SStephen Warren struct gpio_desc phy_reset_gpio; 300ba4dfef1SStephen Warren struct clk clk_master_bus; 301ba4dfef1SStephen Warren struct clk clk_rx; 302ba4dfef1SStephen Warren struct clk clk_ptp_ref; 303ba4dfef1SStephen Warren struct clk clk_tx; 304*7a4c4eddSChristophe Roullier struct clk clk_ck; 305ba4dfef1SStephen Warren struct clk clk_slave_bus; 306ba4dfef1SStephen Warren struct mii_dev *mii; 307ba4dfef1SStephen Warren struct phy_device *phy; 308ba4dfef1SStephen Warren void *descs; 309ba4dfef1SStephen Warren struct eqos_desc *tx_descs; 310ba4dfef1SStephen Warren struct eqos_desc *rx_descs; 311ba4dfef1SStephen Warren int tx_desc_idx, rx_desc_idx; 312ba4dfef1SStephen Warren void *tx_dma_buf; 313ba4dfef1SStephen Warren void *rx_dma_buf; 314ba4dfef1SStephen Warren void *rx_pkt; 315ba4dfef1SStephen Warren bool started; 316ba4dfef1SStephen Warren bool reg_access_ok; 317ba4dfef1SStephen Warren }; 318ba4dfef1SStephen Warren 319ba4dfef1SStephen Warren /* 320ba4dfef1SStephen Warren * TX and RX descriptors are 16 bytes. This causes problems with the cache 321ba4dfef1SStephen Warren * maintenance on CPUs where the cache-line size exceeds the size of these 322ba4dfef1SStephen Warren * descriptors. What will happen is that when the driver receives a packet 323ba4dfef1SStephen Warren * it will be immediately requeued for the hardware to reuse. The CPU will 324ba4dfef1SStephen Warren * therefore need to flush the cache-line containing the descriptor, which 325ba4dfef1SStephen Warren * will cause all other descriptors in the same cache-line to be flushed 326ba4dfef1SStephen Warren * along with it. If one of those descriptors had been written to by the 327ba4dfef1SStephen Warren * device those changes (and the associated packet) will be lost. 328ba4dfef1SStephen Warren * 329ba4dfef1SStephen Warren * To work around this, we make use of non-cached memory if available. If 330ba4dfef1SStephen Warren * descriptors are mapped uncached there's no need to manually flush them 331ba4dfef1SStephen Warren * or invalidate them. 332ba4dfef1SStephen Warren * 333ba4dfef1SStephen Warren * Note that this only applies to descriptors. The packet data buffers do 334ba4dfef1SStephen Warren * not have the same constraints since they are 1536 bytes large, so they 335ba4dfef1SStephen Warren * are unlikely to share cache-lines. 336ba4dfef1SStephen Warren */ 337ba4dfef1SStephen Warren static void *eqos_alloc_descs(unsigned int num) 338ba4dfef1SStephen Warren { 339ba4dfef1SStephen Warren #ifdef CONFIG_SYS_NONCACHED_MEMORY 340ba4dfef1SStephen Warren return (void *)noncached_alloc(EQOS_DESCRIPTORS_SIZE, 341ba4dfef1SStephen Warren EQOS_DESCRIPTOR_ALIGN); 342ba4dfef1SStephen Warren #else 343ba4dfef1SStephen Warren return memalign(EQOS_DESCRIPTOR_ALIGN, EQOS_DESCRIPTORS_SIZE); 344ba4dfef1SStephen Warren #endif 345ba4dfef1SStephen Warren } 346ba4dfef1SStephen Warren 347ba4dfef1SStephen Warren static void eqos_free_descs(void *descs) 348ba4dfef1SStephen Warren { 349ba4dfef1SStephen Warren #ifdef CONFIG_SYS_NONCACHED_MEMORY 350ba4dfef1SStephen Warren /* FIXME: noncached_alloc() has no opposite */ 351ba4dfef1SStephen Warren #else 352ba4dfef1SStephen Warren free(descs); 353ba4dfef1SStephen Warren #endif 354ba4dfef1SStephen Warren } 355ba4dfef1SStephen Warren 356*7a4c4eddSChristophe Roullier static void eqos_inval_desc_tegra186(void *desc) 357ba4dfef1SStephen Warren { 358ba4dfef1SStephen Warren #ifndef CONFIG_SYS_NONCACHED_MEMORY 359ba4dfef1SStephen Warren unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1); 360ba4dfef1SStephen Warren unsigned long end = ALIGN(start + EQOS_DESCRIPTOR_SIZE, 361ba4dfef1SStephen Warren ARCH_DMA_MINALIGN); 362ba4dfef1SStephen Warren 363ba4dfef1SStephen Warren invalidate_dcache_range(start, end); 364ba4dfef1SStephen Warren #endif 365ba4dfef1SStephen Warren } 366ba4dfef1SStephen Warren 367*7a4c4eddSChristophe Roullier static void eqos_inval_desc_stm32(void *desc) 368*7a4c4eddSChristophe Roullier { 369*7a4c4eddSChristophe Roullier #ifndef CONFIG_SYS_NONCACHED_MEMORY 370*7a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); 371*7a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, 372*7a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 373*7a4c4eddSChristophe Roullier 374*7a4c4eddSChristophe Roullier invalidate_dcache_range(start, end); 375*7a4c4eddSChristophe Roullier #endif 376*7a4c4eddSChristophe Roullier } 377*7a4c4eddSChristophe Roullier 378*7a4c4eddSChristophe Roullier static void eqos_flush_desc_tegra186(void *desc) 379ba4dfef1SStephen Warren { 380ba4dfef1SStephen Warren #ifndef CONFIG_SYS_NONCACHED_MEMORY 381ba4dfef1SStephen Warren flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE); 382ba4dfef1SStephen Warren #endif 383ba4dfef1SStephen Warren } 384ba4dfef1SStephen Warren 385*7a4c4eddSChristophe Roullier static void eqos_flush_desc_stm32(void *desc) 386*7a4c4eddSChristophe Roullier { 387*7a4c4eddSChristophe Roullier #ifndef CONFIG_SYS_NONCACHED_MEMORY 388*7a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); 389*7a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, 390*7a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 391*7a4c4eddSChristophe Roullier 392*7a4c4eddSChristophe Roullier flush_dcache_range(start, end); 393*7a4c4eddSChristophe Roullier #endif 394*7a4c4eddSChristophe Roullier } 395*7a4c4eddSChristophe Roullier 396*7a4c4eddSChristophe Roullier static void eqos_inval_buffer_tegra186(void *buf, size_t size) 397ba4dfef1SStephen Warren { 398ba4dfef1SStephen Warren unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1); 399ba4dfef1SStephen Warren unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN); 400ba4dfef1SStephen Warren 401ba4dfef1SStephen Warren invalidate_dcache_range(start, end); 402ba4dfef1SStephen Warren } 403ba4dfef1SStephen Warren 404*7a4c4eddSChristophe Roullier static void eqos_inval_buffer_stm32(void *buf, size_t size) 405*7a4c4eddSChristophe Roullier { 406*7a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN); 407*7a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)buf + size, 408*7a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 409*7a4c4eddSChristophe Roullier 410*7a4c4eddSChristophe Roullier invalidate_dcache_range(start, end); 411*7a4c4eddSChristophe Roullier } 412*7a4c4eddSChristophe Roullier 413*7a4c4eddSChristophe Roullier static void eqos_flush_buffer_tegra186(void *buf, size_t size) 414ba4dfef1SStephen Warren { 415ba4dfef1SStephen Warren flush_cache((unsigned long)buf, size); 416ba4dfef1SStephen Warren } 417ba4dfef1SStephen Warren 418*7a4c4eddSChristophe Roullier static void eqos_flush_buffer_stm32(void *buf, size_t size) 419*7a4c4eddSChristophe Roullier { 420*7a4c4eddSChristophe Roullier unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN); 421*7a4c4eddSChristophe Roullier unsigned long end = roundup((unsigned long)buf + size, 422*7a4c4eddSChristophe Roullier ARCH_DMA_MINALIGN); 423*7a4c4eddSChristophe Roullier 424*7a4c4eddSChristophe Roullier flush_dcache_range(start, end); 425*7a4c4eddSChristophe Roullier } 426*7a4c4eddSChristophe Roullier 427ba4dfef1SStephen Warren static int eqos_mdio_wait_idle(struct eqos_priv *eqos) 428ba4dfef1SStephen Warren { 429b491b498SJon Lin return wait_for_bit_le32(&eqos->mac_regs->mdio_address, 430b491b498SJon Lin EQOS_MAC_MDIO_ADDRESS_GB, false, 431b491b498SJon Lin 1000000, true); 432ba4dfef1SStephen Warren } 433ba4dfef1SStephen Warren 434ba4dfef1SStephen Warren static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad, 435ba4dfef1SStephen Warren int mdio_reg) 436ba4dfef1SStephen Warren { 437ba4dfef1SStephen Warren struct eqos_priv *eqos = bus->priv; 438ba4dfef1SStephen Warren u32 val; 439ba4dfef1SStephen Warren int ret; 440ba4dfef1SStephen Warren 441ba4dfef1SStephen Warren debug("%s(dev=%p, addr=%x, reg=%d):\n", __func__, eqos->dev, mdio_addr, 442ba4dfef1SStephen Warren mdio_reg); 443ba4dfef1SStephen Warren 444ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 445ba4dfef1SStephen Warren if (ret) { 44690aa625cSMasahiro Yamada pr_err("MDIO not idle at entry"); 447ba4dfef1SStephen Warren return ret; 448ba4dfef1SStephen Warren } 449ba4dfef1SStephen Warren 450ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->mdio_address); 451ba4dfef1SStephen Warren val &= EQOS_MAC_MDIO_ADDRESS_SKAP | 452ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_C45E; 453ba4dfef1SStephen Warren val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | 454ba4dfef1SStephen Warren (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) | 455*7a4c4eddSChristophe Roullier (eqos->config->config_mac_mdio << 456ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | 457ba4dfef1SStephen Warren (EQOS_MAC_MDIO_ADDRESS_GOC_READ << 458ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | 459ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GB; 460ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->mdio_address); 461ba4dfef1SStephen Warren 462*7a4c4eddSChristophe Roullier udelay(eqos->config->mdio_wait); 463ba4dfef1SStephen Warren 464ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 465ba4dfef1SStephen Warren if (ret) { 46690aa625cSMasahiro Yamada pr_err("MDIO read didn't complete"); 467ba4dfef1SStephen Warren return ret; 468ba4dfef1SStephen Warren } 469ba4dfef1SStephen Warren 470ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->mdio_data); 471ba4dfef1SStephen Warren val &= EQOS_MAC_MDIO_DATA_GD_MASK; 472ba4dfef1SStephen Warren 473ba4dfef1SStephen Warren debug("%s: val=%x\n", __func__, val); 474ba4dfef1SStephen Warren 475ba4dfef1SStephen Warren return val; 476ba4dfef1SStephen Warren } 477ba4dfef1SStephen Warren 478ba4dfef1SStephen Warren static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad, 479ba4dfef1SStephen Warren int mdio_reg, u16 mdio_val) 480ba4dfef1SStephen Warren { 481ba4dfef1SStephen Warren struct eqos_priv *eqos = bus->priv; 482ba4dfef1SStephen Warren u32 val; 483ba4dfef1SStephen Warren int ret; 484ba4dfef1SStephen Warren 485ba4dfef1SStephen Warren debug("%s(dev=%p, addr=%x, reg=%d, val=%x):\n", __func__, eqos->dev, 486ba4dfef1SStephen Warren mdio_addr, mdio_reg, mdio_val); 487ba4dfef1SStephen Warren 488ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 489ba4dfef1SStephen Warren if (ret) { 49090aa625cSMasahiro Yamada pr_err("MDIO not idle at entry"); 491ba4dfef1SStephen Warren return ret; 492ba4dfef1SStephen Warren } 493ba4dfef1SStephen Warren 494ba4dfef1SStephen Warren writel(mdio_val, &eqos->mac_regs->mdio_data); 495ba4dfef1SStephen Warren 496ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->mdio_address); 497ba4dfef1SStephen Warren val &= EQOS_MAC_MDIO_ADDRESS_SKAP | 498ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_C45E; 499ba4dfef1SStephen Warren val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | 500ba4dfef1SStephen Warren (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) | 501*7a4c4eddSChristophe Roullier (eqos->config->config_mac_mdio << 502ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | 503ba4dfef1SStephen Warren (EQOS_MAC_MDIO_ADDRESS_GOC_WRITE << 504ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | 505ba4dfef1SStephen Warren EQOS_MAC_MDIO_ADDRESS_GB; 506ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->mdio_address); 507ba4dfef1SStephen Warren 508*7a4c4eddSChristophe Roullier udelay(eqos->config->mdio_wait); 509ba4dfef1SStephen Warren 510ba4dfef1SStephen Warren ret = eqos_mdio_wait_idle(eqos); 511ba4dfef1SStephen Warren if (ret) { 51290aa625cSMasahiro Yamada pr_err("MDIO read didn't complete"); 513ba4dfef1SStephen Warren return ret; 514ba4dfef1SStephen Warren } 515ba4dfef1SStephen Warren 516ba4dfef1SStephen Warren return 0; 517ba4dfef1SStephen Warren } 518ba4dfef1SStephen Warren 519ba4dfef1SStephen Warren static int eqos_start_clks_tegra186(struct udevice *dev) 520ba4dfef1SStephen Warren { 521ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 522ba4dfef1SStephen Warren int ret; 523ba4dfef1SStephen Warren 524ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 525ba4dfef1SStephen Warren 526ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_slave_bus); 527ba4dfef1SStephen Warren if (ret < 0) { 52890aa625cSMasahiro Yamada pr_err("clk_enable(clk_slave_bus) failed: %d", ret); 529ba4dfef1SStephen Warren goto err; 530ba4dfef1SStephen Warren } 531ba4dfef1SStephen Warren 532ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_master_bus); 533ba4dfef1SStephen Warren if (ret < 0) { 53490aa625cSMasahiro Yamada pr_err("clk_enable(clk_master_bus) failed: %d", ret); 535ba4dfef1SStephen Warren goto err_disable_clk_slave_bus; 536ba4dfef1SStephen Warren } 537ba4dfef1SStephen Warren 538ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_rx); 539ba4dfef1SStephen Warren if (ret < 0) { 54090aa625cSMasahiro Yamada pr_err("clk_enable(clk_rx) failed: %d", ret); 541ba4dfef1SStephen Warren goto err_disable_clk_master_bus; 542ba4dfef1SStephen Warren } 543ba4dfef1SStephen Warren 544ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_ptp_ref); 545ba4dfef1SStephen Warren if (ret < 0) { 54690aa625cSMasahiro Yamada pr_err("clk_enable(clk_ptp_ref) failed: %d", ret); 547ba4dfef1SStephen Warren goto err_disable_clk_rx; 548ba4dfef1SStephen Warren } 549ba4dfef1SStephen Warren 550ba4dfef1SStephen Warren ret = clk_set_rate(&eqos->clk_ptp_ref, 125 * 1000 * 1000); 551ba4dfef1SStephen Warren if (ret < 0) { 55290aa625cSMasahiro Yamada pr_err("clk_set_rate(clk_ptp_ref) failed: %d", ret); 553ba4dfef1SStephen Warren goto err_disable_clk_ptp_ref; 554ba4dfef1SStephen Warren } 555ba4dfef1SStephen Warren 556ba4dfef1SStephen Warren ret = clk_enable(&eqos->clk_tx); 557ba4dfef1SStephen Warren if (ret < 0) { 55890aa625cSMasahiro Yamada pr_err("clk_enable(clk_tx) failed: %d", ret); 559ba4dfef1SStephen Warren goto err_disable_clk_ptp_ref; 560ba4dfef1SStephen Warren } 561ba4dfef1SStephen Warren 562ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 563ba4dfef1SStephen Warren return 0; 564ba4dfef1SStephen Warren 565ba4dfef1SStephen Warren err_disable_clk_ptp_ref: 566ba4dfef1SStephen Warren clk_disable(&eqos->clk_ptp_ref); 567ba4dfef1SStephen Warren err_disable_clk_rx: 568ba4dfef1SStephen Warren clk_disable(&eqos->clk_rx); 569ba4dfef1SStephen Warren err_disable_clk_master_bus: 570ba4dfef1SStephen Warren clk_disable(&eqos->clk_master_bus); 571ba4dfef1SStephen Warren err_disable_clk_slave_bus: 572ba4dfef1SStephen Warren clk_disable(&eqos->clk_slave_bus); 573ba4dfef1SStephen Warren err: 574ba4dfef1SStephen Warren debug("%s: FAILED: %d\n", __func__, ret); 575ba4dfef1SStephen Warren return ret; 576ba4dfef1SStephen Warren } 577ba4dfef1SStephen Warren 578*7a4c4eddSChristophe Roullier static int eqos_start_clks_stm32(struct udevice *dev) 579*7a4c4eddSChristophe Roullier { 580*7a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 581*7a4c4eddSChristophe Roullier int ret; 582*7a4c4eddSChristophe Roullier 583*7a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 584*7a4c4eddSChristophe Roullier 585*7a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_master_bus); 586*7a4c4eddSChristophe Roullier if (ret < 0) { 587*7a4c4eddSChristophe Roullier pr_err("clk_enable(clk_master_bus) failed: %d", ret); 588*7a4c4eddSChristophe Roullier goto err; 589*7a4c4eddSChristophe Roullier } 590*7a4c4eddSChristophe Roullier 591*7a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_rx); 592*7a4c4eddSChristophe Roullier if (ret < 0) { 593*7a4c4eddSChristophe Roullier pr_err("clk_enable(clk_rx) failed: %d", ret); 594*7a4c4eddSChristophe Roullier goto err_disable_clk_master_bus; 595*7a4c4eddSChristophe Roullier } 596*7a4c4eddSChristophe Roullier 597*7a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_tx); 598*7a4c4eddSChristophe Roullier if (ret < 0) { 599*7a4c4eddSChristophe Roullier pr_err("clk_enable(clk_tx) failed: %d", ret); 600*7a4c4eddSChristophe Roullier goto err_disable_clk_rx; 601*7a4c4eddSChristophe Roullier } 602*7a4c4eddSChristophe Roullier 603*7a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) { 604*7a4c4eddSChristophe Roullier ret = clk_enable(&eqos->clk_ck); 605*7a4c4eddSChristophe Roullier if (ret < 0) { 606*7a4c4eddSChristophe Roullier pr_err("clk_enable(clk_ck) failed: %d", ret); 607*7a4c4eddSChristophe Roullier goto err_disable_clk_tx; 608*7a4c4eddSChristophe Roullier } 609*7a4c4eddSChristophe Roullier } 610*7a4c4eddSChristophe Roullier 611*7a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 612*7a4c4eddSChristophe Roullier return 0; 613*7a4c4eddSChristophe Roullier 614*7a4c4eddSChristophe Roullier err_disable_clk_tx: 615*7a4c4eddSChristophe Roullier clk_disable(&eqos->clk_tx); 616*7a4c4eddSChristophe Roullier err_disable_clk_rx: 617*7a4c4eddSChristophe Roullier clk_disable(&eqos->clk_rx); 618*7a4c4eddSChristophe Roullier err_disable_clk_master_bus: 619*7a4c4eddSChristophe Roullier clk_disable(&eqos->clk_master_bus); 620*7a4c4eddSChristophe Roullier err: 621*7a4c4eddSChristophe Roullier debug("%s: FAILED: %d\n", __func__, ret); 622*7a4c4eddSChristophe Roullier return ret; 623*7a4c4eddSChristophe Roullier } 624*7a4c4eddSChristophe Roullier 625ba4dfef1SStephen Warren void eqos_stop_clks_tegra186(struct udevice *dev) 626ba4dfef1SStephen Warren { 627ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 628ba4dfef1SStephen Warren 629ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 630ba4dfef1SStephen Warren 631ba4dfef1SStephen Warren clk_disable(&eqos->clk_tx); 632ba4dfef1SStephen Warren clk_disable(&eqos->clk_ptp_ref); 633ba4dfef1SStephen Warren clk_disable(&eqos->clk_rx); 634ba4dfef1SStephen Warren clk_disable(&eqos->clk_master_bus); 635ba4dfef1SStephen Warren clk_disable(&eqos->clk_slave_bus); 636ba4dfef1SStephen Warren 637ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 638ba4dfef1SStephen Warren } 639ba4dfef1SStephen Warren 640*7a4c4eddSChristophe Roullier void eqos_stop_clks_stm32(struct udevice *dev) 641*7a4c4eddSChristophe Roullier { 642*7a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 643*7a4c4eddSChristophe Roullier 644*7a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 645*7a4c4eddSChristophe Roullier 646*7a4c4eddSChristophe Roullier clk_disable(&eqos->clk_tx); 647*7a4c4eddSChristophe Roullier clk_disable(&eqos->clk_rx); 648*7a4c4eddSChristophe Roullier clk_disable(&eqos->clk_master_bus); 649*7a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) 650*7a4c4eddSChristophe Roullier clk_disable(&eqos->clk_ck); 651*7a4c4eddSChristophe Roullier 652*7a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 653*7a4c4eddSChristophe Roullier } 654*7a4c4eddSChristophe Roullier 655ba4dfef1SStephen Warren static int eqos_start_resets_tegra186(struct udevice *dev) 656ba4dfef1SStephen Warren { 657ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 658ba4dfef1SStephen Warren int ret; 659ba4dfef1SStephen Warren 660ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 661ba4dfef1SStephen Warren 662ba4dfef1SStephen Warren ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 663ba4dfef1SStephen Warren if (ret < 0) { 66490aa625cSMasahiro Yamada pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", ret); 665ba4dfef1SStephen Warren return ret; 666ba4dfef1SStephen Warren } 667ba4dfef1SStephen Warren 668ba4dfef1SStephen Warren udelay(2); 669ba4dfef1SStephen Warren 670ba4dfef1SStephen Warren ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); 671ba4dfef1SStephen Warren if (ret < 0) { 67290aa625cSMasahiro Yamada pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret); 673ba4dfef1SStephen Warren return ret; 674ba4dfef1SStephen Warren } 675ba4dfef1SStephen Warren 676ba4dfef1SStephen Warren ret = reset_assert(&eqos->reset_ctl); 677ba4dfef1SStephen Warren if (ret < 0) { 67890aa625cSMasahiro Yamada pr_err("reset_assert() failed: %d", ret); 679ba4dfef1SStephen Warren return ret; 680ba4dfef1SStephen Warren } 681ba4dfef1SStephen Warren 682ba4dfef1SStephen Warren udelay(2); 683ba4dfef1SStephen Warren 684ba4dfef1SStephen Warren ret = reset_deassert(&eqos->reset_ctl); 685ba4dfef1SStephen Warren if (ret < 0) { 68690aa625cSMasahiro Yamada pr_err("reset_deassert() failed: %d", ret); 687ba4dfef1SStephen Warren return ret; 688ba4dfef1SStephen Warren } 689ba4dfef1SStephen Warren 690ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 691ba4dfef1SStephen Warren return 0; 692ba4dfef1SStephen Warren } 693ba4dfef1SStephen Warren 694*7a4c4eddSChristophe Roullier static int eqos_start_resets_stm32(struct udevice *dev) 695*7a4c4eddSChristophe Roullier { 696*7a4c4eddSChristophe Roullier return 0; 697*7a4c4eddSChristophe Roullier } 698*7a4c4eddSChristophe Roullier 699ba4dfef1SStephen Warren static int eqos_stop_resets_tegra186(struct udevice *dev) 700ba4dfef1SStephen Warren { 701ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 702ba4dfef1SStephen Warren 703ba4dfef1SStephen Warren reset_assert(&eqos->reset_ctl); 704ba4dfef1SStephen Warren dm_gpio_set_value(&eqos->phy_reset_gpio, 1); 705ba4dfef1SStephen Warren 706ba4dfef1SStephen Warren return 0; 707ba4dfef1SStephen Warren } 708ba4dfef1SStephen Warren 709*7a4c4eddSChristophe Roullier static int eqos_stop_resets_stm32(struct udevice *dev) 710*7a4c4eddSChristophe Roullier { 711*7a4c4eddSChristophe Roullier return 0; 712*7a4c4eddSChristophe Roullier } 713*7a4c4eddSChristophe Roullier 714ba4dfef1SStephen Warren static int eqos_calibrate_pads_tegra186(struct udevice *dev) 715ba4dfef1SStephen Warren { 716ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 717ba4dfef1SStephen Warren int ret; 718ba4dfef1SStephen Warren 719ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 720ba4dfef1SStephen Warren 721ba4dfef1SStephen Warren setbits_le32(&eqos->tegra186_regs->sdmemcomppadctrl, 722ba4dfef1SStephen Warren EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD); 723ba4dfef1SStephen Warren 724ba4dfef1SStephen Warren udelay(1); 725ba4dfef1SStephen Warren 726ba4dfef1SStephen Warren setbits_le32(&eqos->tegra186_regs->auto_cal_config, 727ba4dfef1SStephen Warren EQOS_AUTO_CAL_CONFIG_START | EQOS_AUTO_CAL_CONFIG_ENABLE); 728ba4dfef1SStephen Warren 729b491b498SJon Lin ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, 730ba4dfef1SStephen Warren EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false); 731ba4dfef1SStephen Warren if (ret) { 73290aa625cSMasahiro Yamada pr_err("calibrate didn't start"); 733ba4dfef1SStephen Warren goto failed; 734ba4dfef1SStephen Warren } 735ba4dfef1SStephen Warren 736b491b498SJon Lin ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, 737ba4dfef1SStephen Warren EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false); 738ba4dfef1SStephen Warren if (ret) { 73990aa625cSMasahiro Yamada pr_err("calibrate didn't finish"); 740ba4dfef1SStephen Warren goto failed; 741ba4dfef1SStephen Warren } 742ba4dfef1SStephen Warren 743ba4dfef1SStephen Warren ret = 0; 744ba4dfef1SStephen Warren 745ba4dfef1SStephen Warren failed: 746ba4dfef1SStephen Warren clrbits_le32(&eqos->tegra186_regs->sdmemcomppadctrl, 747ba4dfef1SStephen Warren EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD); 748ba4dfef1SStephen Warren 749ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 750ba4dfef1SStephen Warren 751ba4dfef1SStephen Warren return ret; 752ba4dfef1SStephen Warren } 753ba4dfef1SStephen Warren 754ba4dfef1SStephen Warren static int eqos_disable_calibration_tegra186(struct udevice *dev) 755ba4dfef1SStephen Warren { 756ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 757ba4dfef1SStephen Warren 758ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 759ba4dfef1SStephen Warren 760ba4dfef1SStephen Warren clrbits_le32(&eqos->tegra186_regs->auto_cal_config, 761ba4dfef1SStephen Warren EQOS_AUTO_CAL_CONFIG_ENABLE); 762ba4dfef1SStephen Warren 763ba4dfef1SStephen Warren return 0; 764ba4dfef1SStephen Warren } 765ba4dfef1SStephen Warren 766ba4dfef1SStephen Warren static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev) 767ba4dfef1SStephen Warren { 768ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 769ba4dfef1SStephen Warren 770ba4dfef1SStephen Warren return clk_get_rate(&eqos->clk_slave_bus); 771ba4dfef1SStephen Warren } 772ba4dfef1SStephen Warren 773*7a4c4eddSChristophe Roullier static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) 774*7a4c4eddSChristophe Roullier { 775*7a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 776*7a4c4eddSChristophe Roullier 777*7a4c4eddSChristophe Roullier return clk_get_rate(&eqos->clk_master_bus); 778*7a4c4eddSChristophe Roullier } 779*7a4c4eddSChristophe Roullier 780*7a4c4eddSChristophe Roullier static int eqos_calibrate_pads_stm32(struct udevice *dev) 781*7a4c4eddSChristophe Roullier { 782*7a4c4eddSChristophe Roullier return 0; 783*7a4c4eddSChristophe Roullier } 784*7a4c4eddSChristophe Roullier 785*7a4c4eddSChristophe Roullier static int eqos_disable_calibration_stm32(struct udevice *dev) 786*7a4c4eddSChristophe Roullier { 787*7a4c4eddSChristophe Roullier return 0; 788*7a4c4eddSChristophe Roullier } 789*7a4c4eddSChristophe Roullier 790ba4dfef1SStephen Warren static int eqos_set_full_duplex(struct udevice *dev) 791ba4dfef1SStephen Warren { 792ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 793ba4dfef1SStephen Warren 794ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 795ba4dfef1SStephen Warren 796ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->configuration, EQOS_MAC_CONFIGURATION_DM); 797ba4dfef1SStephen Warren 798ba4dfef1SStephen Warren return 0; 799ba4dfef1SStephen Warren } 800ba4dfef1SStephen Warren 801ba4dfef1SStephen Warren static int eqos_set_half_duplex(struct udevice *dev) 802ba4dfef1SStephen Warren { 803ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 804ba4dfef1SStephen Warren 805ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 806ba4dfef1SStephen Warren 807ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, EQOS_MAC_CONFIGURATION_DM); 808ba4dfef1SStephen Warren 809ba4dfef1SStephen Warren /* WAR: Flush TX queue when switching to half-duplex */ 810ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->txq0_operation_mode, 811ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_FTQ); 812ba4dfef1SStephen Warren 813ba4dfef1SStephen Warren return 0; 814ba4dfef1SStephen Warren } 815ba4dfef1SStephen Warren 816ba4dfef1SStephen Warren static int eqos_set_gmii_speed(struct udevice *dev) 817ba4dfef1SStephen Warren { 818ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 819ba4dfef1SStephen Warren 820ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 821ba4dfef1SStephen Warren 822ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, 823ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_PS | EQOS_MAC_CONFIGURATION_FES); 824ba4dfef1SStephen Warren 825ba4dfef1SStephen Warren return 0; 826ba4dfef1SStephen Warren } 827ba4dfef1SStephen Warren 828ba4dfef1SStephen Warren static int eqos_set_mii_speed_100(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, 835ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_PS | EQOS_MAC_CONFIGURATION_FES); 836ba4dfef1SStephen Warren 837ba4dfef1SStephen Warren return 0; 838ba4dfef1SStephen Warren } 839ba4dfef1SStephen Warren 840ba4dfef1SStephen Warren static int eqos_set_mii_speed_10(struct udevice *dev) 841ba4dfef1SStephen Warren { 842ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 843ba4dfef1SStephen Warren 844ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 845ba4dfef1SStephen Warren 846ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->configuration, 847ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_FES, EQOS_MAC_CONFIGURATION_PS); 848ba4dfef1SStephen Warren 849ba4dfef1SStephen Warren return 0; 850ba4dfef1SStephen Warren } 851ba4dfef1SStephen Warren 852ba4dfef1SStephen Warren static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev) 853ba4dfef1SStephen Warren { 854ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 855ba4dfef1SStephen Warren ulong rate; 856ba4dfef1SStephen Warren int ret; 857ba4dfef1SStephen Warren 858ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 859ba4dfef1SStephen Warren 860ba4dfef1SStephen Warren switch (eqos->phy->speed) { 861ba4dfef1SStephen Warren case SPEED_1000: 862ba4dfef1SStephen Warren rate = 125 * 1000 * 1000; 863ba4dfef1SStephen Warren break; 864ba4dfef1SStephen Warren case SPEED_100: 865ba4dfef1SStephen Warren rate = 25 * 1000 * 1000; 866ba4dfef1SStephen Warren break; 867ba4dfef1SStephen Warren case SPEED_10: 868ba4dfef1SStephen Warren rate = 2.5 * 1000 * 1000; 869ba4dfef1SStephen Warren break; 870ba4dfef1SStephen Warren default: 87190aa625cSMasahiro Yamada pr_err("invalid speed %d", eqos->phy->speed); 872ba4dfef1SStephen Warren return -EINVAL; 873ba4dfef1SStephen Warren } 874ba4dfef1SStephen Warren 875ba4dfef1SStephen Warren ret = clk_set_rate(&eqos->clk_tx, rate); 876ba4dfef1SStephen Warren if (ret < 0) { 87790aa625cSMasahiro Yamada pr_err("clk_set_rate(tx_clk, %lu) failed: %d", rate, ret); 878ba4dfef1SStephen Warren return ret; 879ba4dfef1SStephen Warren } 880ba4dfef1SStephen Warren 881ba4dfef1SStephen Warren return 0; 882ba4dfef1SStephen Warren } 883ba4dfef1SStephen Warren 884*7a4c4eddSChristophe Roullier static int eqos_set_tx_clk_speed_stm32(struct udevice *dev) 885*7a4c4eddSChristophe Roullier { 886*7a4c4eddSChristophe Roullier return 0; 887*7a4c4eddSChristophe Roullier } 888*7a4c4eddSChristophe Roullier 889ba4dfef1SStephen Warren static int eqos_adjust_link(struct udevice *dev) 890ba4dfef1SStephen Warren { 891ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 892ba4dfef1SStephen Warren int ret; 893ba4dfef1SStephen Warren bool en_calibration; 894ba4dfef1SStephen Warren 895ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 896ba4dfef1SStephen Warren 897ba4dfef1SStephen Warren if (eqos->phy->duplex) 898ba4dfef1SStephen Warren ret = eqos_set_full_duplex(dev); 899ba4dfef1SStephen Warren else 900ba4dfef1SStephen Warren ret = eqos_set_half_duplex(dev); 901ba4dfef1SStephen Warren if (ret < 0) { 90290aa625cSMasahiro Yamada pr_err("eqos_set_*_duplex() failed: %d", ret); 903ba4dfef1SStephen Warren return ret; 904ba4dfef1SStephen Warren } 905ba4dfef1SStephen Warren 906ba4dfef1SStephen Warren switch (eqos->phy->speed) { 907ba4dfef1SStephen Warren case SPEED_1000: 908ba4dfef1SStephen Warren en_calibration = true; 909ba4dfef1SStephen Warren ret = eqos_set_gmii_speed(dev); 910ba4dfef1SStephen Warren break; 911ba4dfef1SStephen Warren case SPEED_100: 912ba4dfef1SStephen Warren en_calibration = true; 913ba4dfef1SStephen Warren ret = eqos_set_mii_speed_100(dev); 914ba4dfef1SStephen Warren break; 915ba4dfef1SStephen Warren case SPEED_10: 916ba4dfef1SStephen Warren en_calibration = false; 917ba4dfef1SStephen Warren ret = eqos_set_mii_speed_10(dev); 918ba4dfef1SStephen Warren break; 919ba4dfef1SStephen Warren default: 92090aa625cSMasahiro Yamada pr_err("invalid speed %d", eqos->phy->speed); 921ba4dfef1SStephen Warren return -EINVAL; 922ba4dfef1SStephen Warren } 923ba4dfef1SStephen Warren if (ret < 0) { 92490aa625cSMasahiro Yamada pr_err("eqos_set_*mii_speed*() failed: %d", ret); 925ba4dfef1SStephen Warren return ret; 926ba4dfef1SStephen Warren } 927ba4dfef1SStephen Warren 928ba4dfef1SStephen Warren if (en_calibration) { 929*7a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_calibrate_pads(dev); 930ba4dfef1SStephen Warren if (ret < 0) { 931*7a4c4eddSChristophe Roullier pr_err("eqos_calibrate_pads() failed: %d", 932*7a4c4eddSChristophe Roullier ret); 933ba4dfef1SStephen Warren return ret; 934ba4dfef1SStephen Warren } 935ba4dfef1SStephen Warren } else { 936*7a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_disable_calibration(dev); 937ba4dfef1SStephen Warren if (ret < 0) { 938*7a4c4eddSChristophe Roullier pr_err("eqos_disable_calibration() failed: %d", 939ba4dfef1SStephen Warren ret); 940ba4dfef1SStephen Warren return ret; 941ba4dfef1SStephen Warren } 942ba4dfef1SStephen Warren } 943*7a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_set_tx_clk_speed(dev); 944ba4dfef1SStephen Warren if (ret < 0) { 945*7a4c4eddSChristophe Roullier pr_err("eqos_set_tx_clk_speed() failed: %d", ret); 946ba4dfef1SStephen Warren return ret; 947ba4dfef1SStephen Warren } 948ba4dfef1SStephen Warren 949ba4dfef1SStephen Warren return 0; 950ba4dfef1SStephen Warren } 951ba4dfef1SStephen Warren 952ba4dfef1SStephen Warren static int eqos_write_hwaddr(struct udevice *dev) 953ba4dfef1SStephen Warren { 954ba4dfef1SStephen Warren struct eth_pdata *plat = dev_get_platdata(dev); 955ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 956ba4dfef1SStephen Warren uint32_t val; 957ba4dfef1SStephen Warren 958ba4dfef1SStephen Warren /* 959ba4dfef1SStephen Warren * This function may be called before start() or after stop(). At that 960ba4dfef1SStephen Warren * time, on at least some configurations of the EQoS HW, all clocks to 961ba4dfef1SStephen Warren * the EQoS HW block will be stopped, and a reset signal applied. If 962ba4dfef1SStephen Warren * any register access is attempted in this state, bus timeouts or CPU 963ba4dfef1SStephen Warren * hangs may occur. This check prevents that. 964ba4dfef1SStephen Warren * 965ba4dfef1SStephen Warren * A simple solution to this problem would be to not implement 966ba4dfef1SStephen Warren * write_hwaddr(), since start() always writes the MAC address into HW 967ba4dfef1SStephen Warren * anyway. However, it is desirable to implement write_hwaddr() to 968ba4dfef1SStephen Warren * support the case of SW that runs subsequent to U-Boot which expects 969ba4dfef1SStephen Warren * the MAC address to already be programmed into the EQoS registers, 970ba4dfef1SStephen Warren * which must happen irrespective of whether the U-Boot user (or 971ba4dfef1SStephen Warren * scripts) actually made use of the EQoS device, and hence 972ba4dfef1SStephen Warren * irrespective of whether start() was ever called. 973ba4dfef1SStephen Warren * 974ba4dfef1SStephen Warren * Note that this requirement by subsequent SW is not valid for 975ba4dfef1SStephen Warren * Tegra186, and is likely not valid for any non-PCI instantiation of 976ba4dfef1SStephen Warren * the EQoS HW block. This function is implemented solely as 977ba4dfef1SStephen Warren * future-proofing with the expectation the driver will eventually be 978ba4dfef1SStephen Warren * ported to some system where the expectation above is true. 979ba4dfef1SStephen Warren */ 980ba4dfef1SStephen Warren if (!eqos->config->reg_access_always_ok && !eqos->reg_access_ok) 981ba4dfef1SStephen Warren return 0; 982ba4dfef1SStephen Warren 983ba4dfef1SStephen Warren /* Update the MAC address */ 984ba4dfef1SStephen Warren val = (plat->enetaddr[5] << 8) | 985ba4dfef1SStephen Warren (plat->enetaddr[4]); 986ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->address0_high); 987ba4dfef1SStephen Warren val = (plat->enetaddr[3] << 24) | 988ba4dfef1SStephen Warren (plat->enetaddr[2] << 16) | 989ba4dfef1SStephen Warren (plat->enetaddr[1] << 8) | 990ba4dfef1SStephen Warren (plat->enetaddr[0]); 991ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->address0_low); 992ba4dfef1SStephen Warren 993ba4dfef1SStephen Warren return 0; 994ba4dfef1SStephen Warren } 995ba4dfef1SStephen Warren 996ba4dfef1SStephen Warren static int eqos_start(struct udevice *dev) 997ba4dfef1SStephen Warren { 998ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 999ba4dfef1SStephen Warren int ret, i; 1000ba4dfef1SStephen Warren ulong rate; 1001ba4dfef1SStephen Warren u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl; 1002ba4dfef1SStephen Warren ulong last_rx_desc; 1003ba4dfef1SStephen Warren 1004ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1005ba4dfef1SStephen Warren 1006ba4dfef1SStephen Warren eqos->tx_desc_idx = 0; 1007ba4dfef1SStephen Warren eqos->rx_desc_idx = 0; 1008ba4dfef1SStephen Warren 1009*7a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_start_clks(dev); 1010ba4dfef1SStephen Warren if (ret < 0) { 1011*7a4c4eddSChristophe Roullier pr_err("eqos_start_clks() failed: %d", ret); 1012ba4dfef1SStephen Warren goto err; 1013ba4dfef1SStephen Warren } 1014ba4dfef1SStephen Warren 1015*7a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_start_resets(dev); 1016ba4dfef1SStephen Warren if (ret < 0) { 1017*7a4c4eddSChristophe Roullier pr_err("eqos_start_resets() failed: %d", ret); 1018ba4dfef1SStephen Warren goto err_stop_clks; 1019ba4dfef1SStephen Warren } 1020ba4dfef1SStephen Warren 1021ba4dfef1SStephen Warren udelay(10); 1022ba4dfef1SStephen Warren 1023ba4dfef1SStephen Warren eqos->reg_access_ok = true; 1024ba4dfef1SStephen Warren 1025b491b498SJon Lin ret = wait_for_bit_le32(&eqos->dma_regs->mode, 1026*7a4c4eddSChristophe Roullier EQOS_DMA_MODE_SWR, false, 1027*7a4c4eddSChristophe Roullier eqos->config->swr_wait, false); 1028ba4dfef1SStephen Warren if (ret) { 102990aa625cSMasahiro Yamada pr_err("EQOS_DMA_MODE_SWR stuck"); 1030ba4dfef1SStephen Warren goto err_stop_resets; 1031ba4dfef1SStephen Warren } 1032ba4dfef1SStephen Warren 1033*7a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_calibrate_pads(dev); 1034ba4dfef1SStephen Warren if (ret < 0) { 1035*7a4c4eddSChristophe Roullier pr_err("eqos_calibrate_pads() failed: %d", ret); 1036ba4dfef1SStephen Warren goto err_stop_resets; 1037ba4dfef1SStephen Warren } 1038*7a4c4eddSChristophe Roullier rate = eqos->config->ops->eqos_get_tick_clk_rate(dev); 1039ba4dfef1SStephen Warren 1040ba4dfef1SStephen Warren val = (rate / 1000000) - 1; 1041ba4dfef1SStephen Warren writel(val, &eqos->mac_regs->us_tic_counter); 1042ba4dfef1SStephen Warren 1043*7a4c4eddSChristophe Roullier /* 1044*7a4c4eddSChristophe Roullier * if PHY was already connected and configured, 1045*7a4c4eddSChristophe Roullier * don't need to reconnect/reconfigure again 1046*7a4c4eddSChristophe Roullier */ 1047*7a4c4eddSChristophe Roullier if (!eqos->phy) { 1048*7a4c4eddSChristophe Roullier eqos->phy = phy_connect(eqos->mii, 0, dev, 1049*7a4c4eddSChristophe Roullier eqos->config->interface(dev)); 1050ba4dfef1SStephen Warren if (!eqos->phy) { 105190aa625cSMasahiro Yamada pr_err("phy_connect() failed"); 1052ba4dfef1SStephen Warren goto err_stop_resets; 1053ba4dfef1SStephen Warren } 1054ba4dfef1SStephen Warren ret = phy_config(eqos->phy); 1055ba4dfef1SStephen Warren if (ret < 0) { 105690aa625cSMasahiro Yamada pr_err("phy_config() failed: %d", ret); 1057ba4dfef1SStephen Warren goto err_shutdown_phy; 1058ba4dfef1SStephen Warren } 1059*7a4c4eddSChristophe Roullier } 1060*7a4c4eddSChristophe Roullier 1061ba4dfef1SStephen Warren ret = phy_startup(eqos->phy); 1062ba4dfef1SStephen Warren if (ret < 0) { 106390aa625cSMasahiro Yamada pr_err("phy_startup() failed: %d", ret); 1064ba4dfef1SStephen Warren goto err_shutdown_phy; 1065ba4dfef1SStephen Warren } 1066ba4dfef1SStephen Warren 1067ba4dfef1SStephen Warren if (!eqos->phy->link) { 106890aa625cSMasahiro Yamada pr_err("No link"); 1069ba4dfef1SStephen Warren goto err_shutdown_phy; 1070ba4dfef1SStephen Warren } 1071ba4dfef1SStephen Warren 1072ba4dfef1SStephen Warren ret = eqos_adjust_link(dev); 1073ba4dfef1SStephen Warren if (ret < 0) { 107490aa625cSMasahiro Yamada pr_err("eqos_adjust_link() failed: %d", ret); 1075ba4dfef1SStephen Warren goto err_shutdown_phy; 1076ba4dfef1SStephen Warren } 1077ba4dfef1SStephen Warren 1078ba4dfef1SStephen Warren /* Configure MTL */ 1079ba4dfef1SStephen Warren 1080ba4dfef1SStephen Warren /* Enable Store and Forward mode for TX */ 1081ba4dfef1SStephen Warren /* Program Tx operating mode */ 1082ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->txq0_operation_mode, 1083ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TSF | 1084ba4dfef1SStephen Warren (EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_ENABLED << 1085ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_SHIFT)); 1086ba4dfef1SStephen Warren 1087ba4dfef1SStephen Warren /* Transmit Queue weight */ 1088ba4dfef1SStephen Warren writel(0x10, &eqos->mtl_regs->txq0_quantum_weight); 1089ba4dfef1SStephen Warren 1090ba4dfef1SStephen Warren /* Enable Store and Forward mode for RX, since no jumbo frame */ 1091ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1092ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RSF); 1093ba4dfef1SStephen Warren 1094ba4dfef1SStephen Warren /* Transmit/Receive queue fifo size; use all RAM for 1 queue */ 1095ba4dfef1SStephen Warren val = readl(&eqos->mac_regs->hw_feature1); 1096ba4dfef1SStephen Warren tx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_SHIFT) & 1097ba4dfef1SStephen Warren EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_MASK; 1098ba4dfef1SStephen Warren rx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT) & 1099ba4dfef1SStephen Warren EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK; 1100ba4dfef1SStephen Warren 1101ba4dfef1SStephen Warren /* 1102ba4dfef1SStephen Warren * r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting. 1103ba4dfef1SStephen Warren * r/tqs is encoded as (n / 256) - 1. 1104ba4dfef1SStephen Warren */ 1105ba4dfef1SStephen Warren tqs = (128 << tx_fifo_sz) / 256 - 1; 1106ba4dfef1SStephen Warren rqs = (128 << rx_fifo_sz) / 256 - 1; 1107ba4dfef1SStephen Warren 1108ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->txq0_operation_mode, 1109ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK << 1110ba4dfef1SStephen Warren EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT, 1111ba4dfef1SStephen Warren tqs << EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT); 1112ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1113ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RQS_MASK << 1114ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT, 1115ba4dfef1SStephen Warren rqs << EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT); 1116ba4dfef1SStephen Warren 1117ba4dfef1SStephen Warren /* Flow control used only if each channel gets 4KB or more FIFO */ 1118ba4dfef1SStephen Warren if (rqs >= ((4096 / 256) - 1)) { 1119ba4dfef1SStephen Warren u32 rfd, rfa; 1120ba4dfef1SStephen Warren 1121ba4dfef1SStephen Warren setbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1122ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_EHFC); 1123ba4dfef1SStephen Warren 1124ba4dfef1SStephen Warren /* 1125ba4dfef1SStephen Warren * Set Threshold for Activating Flow Contol space for min 2 1126ba4dfef1SStephen Warren * frames ie, (1500 * 1) = 1500 bytes. 1127ba4dfef1SStephen Warren * 1128ba4dfef1SStephen Warren * Set Threshold for Deactivating Flow Contol for space of 1129ba4dfef1SStephen Warren * min 1 frame (frame size 1500bytes) in receive fifo 1130ba4dfef1SStephen Warren */ 1131ba4dfef1SStephen Warren if (rqs == ((4096 / 256) - 1)) { 1132ba4dfef1SStephen Warren /* 1133ba4dfef1SStephen Warren * This violates the above formula because of FIFO size 1134ba4dfef1SStephen Warren * limit therefore overflow may occur inspite of this. 1135ba4dfef1SStephen Warren */ 1136ba4dfef1SStephen Warren rfd = 0x3; /* Full-3K */ 1137ba4dfef1SStephen Warren rfa = 0x1; /* Full-1.5K */ 1138ba4dfef1SStephen Warren } else if (rqs == ((8192 / 256) - 1)) { 1139ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1140ba4dfef1SStephen Warren rfa = 0xa; /* Full-6K */ 1141ba4dfef1SStephen Warren } else if (rqs == ((16384 / 256) - 1)) { 1142ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1143ba4dfef1SStephen Warren rfa = 0x12; /* Full-10K */ 1144ba4dfef1SStephen Warren } else { 1145ba4dfef1SStephen Warren rfd = 0x6; /* Full-4K */ 1146ba4dfef1SStephen Warren rfa = 0x1E; /* Full-16K */ 1147ba4dfef1SStephen Warren } 1148ba4dfef1SStephen Warren 1149ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mtl_regs->rxq0_operation_mode, 1150ba4dfef1SStephen Warren (EQOS_MTL_RXQ0_OPERATION_MODE_RFD_MASK << 1151ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT) | 1152ba4dfef1SStephen Warren (EQOS_MTL_RXQ0_OPERATION_MODE_RFA_MASK << 1153ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT), 1154ba4dfef1SStephen Warren (rfd << 1155ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT) | 1156ba4dfef1SStephen Warren (rfa << 1157ba4dfef1SStephen Warren EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT)); 1158ba4dfef1SStephen Warren } 1159ba4dfef1SStephen Warren 1160ba4dfef1SStephen Warren /* Configure MAC */ 1161ba4dfef1SStephen Warren 1162ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0, 1163ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK << 1164ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT, 1165*7a4c4eddSChristophe Roullier eqos->config->config_mac << 1166ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT); 1167ba4dfef1SStephen Warren 1168ba4dfef1SStephen Warren /* Set TX flow control parameters */ 1169ba4dfef1SStephen Warren /* Set Pause Time */ 1170ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->q0_tx_flow_ctrl, 1171ba4dfef1SStephen Warren 0xffff << EQOS_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT); 1172ba4dfef1SStephen Warren /* Assign priority for TX flow control */ 1173ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->txq_prty_map0, 1174ba4dfef1SStephen Warren EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_MASK << 1175ba4dfef1SStephen Warren EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_SHIFT); 1176ba4dfef1SStephen Warren /* Assign priority for RX flow control */ 1177ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->rxq_ctrl2, 1178ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK << 1179ba4dfef1SStephen Warren EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT); 1180ba4dfef1SStephen Warren /* Enable flow control */ 1181ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->q0_tx_flow_ctrl, 1182ba4dfef1SStephen Warren EQOS_MAC_Q0_TX_FLOW_CTRL_TFE); 1183ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->rx_flow_ctrl, 1184ba4dfef1SStephen Warren EQOS_MAC_RX_FLOW_CTRL_RFE); 1185ba4dfef1SStephen Warren 1186ba4dfef1SStephen Warren clrsetbits_le32(&eqos->mac_regs->configuration, 1187ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_GPSLCE | 1188ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_WD | 1189ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_JD | 1190ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_JE, 1191ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_CST | 1192ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_ACS); 1193ba4dfef1SStephen Warren 1194ba4dfef1SStephen Warren eqos_write_hwaddr(dev); 1195ba4dfef1SStephen Warren 1196ba4dfef1SStephen Warren /* Configure DMA */ 1197ba4dfef1SStephen Warren 1198ba4dfef1SStephen Warren /* Enable OSP mode */ 1199ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_tx_control, 1200ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_OSP); 1201ba4dfef1SStephen Warren 1202ba4dfef1SStephen Warren /* RX buffer size. Must be a multiple of bus width */ 1203ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_rx_control, 1204ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_MASK << 1205ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT, 1206ba4dfef1SStephen Warren EQOS_MAX_PACKET_SIZE << 1207ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT); 1208ba4dfef1SStephen Warren 1209ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_control, 1210ba4dfef1SStephen Warren EQOS_DMA_CH0_CONTROL_PBLX8); 1211ba4dfef1SStephen Warren 1212ba4dfef1SStephen Warren /* 1213ba4dfef1SStephen Warren * Burst length must be < 1/2 FIFO size. 1214ba4dfef1SStephen Warren * FIFO size in tqs is encoded as (n / 256) - 1. 1215ba4dfef1SStephen Warren * Each burst is n * 8 (PBLX8) * 16 (AXI width) == 128 bytes. 1216ba4dfef1SStephen Warren * Half of n * 256 is n * 128, so pbl == tqs, modulo the -1. 1217ba4dfef1SStephen Warren */ 1218ba4dfef1SStephen Warren pbl = tqs + 1; 1219ba4dfef1SStephen Warren if (pbl > 32) 1220ba4dfef1SStephen Warren pbl = 32; 1221ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_tx_control, 1222ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_TXPBL_MASK << 1223ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT, 1224ba4dfef1SStephen Warren pbl << EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT); 1225ba4dfef1SStephen Warren 1226ba4dfef1SStephen Warren clrsetbits_le32(&eqos->dma_regs->ch0_rx_control, 1227ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RXPBL_MASK << 1228ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT, 1229ba4dfef1SStephen Warren 8 << EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT); 1230ba4dfef1SStephen Warren 1231ba4dfef1SStephen Warren /* DMA performance configuration */ 1232ba4dfef1SStephen Warren val = (2 << EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_SHIFT) | 1233ba4dfef1SStephen Warren EQOS_DMA_SYSBUS_MODE_EAME | EQOS_DMA_SYSBUS_MODE_BLEN16 | 1234ba4dfef1SStephen Warren EQOS_DMA_SYSBUS_MODE_BLEN8 | EQOS_DMA_SYSBUS_MODE_BLEN4; 1235ba4dfef1SStephen Warren writel(val, &eqos->dma_regs->sysbus_mode); 1236ba4dfef1SStephen Warren 1237ba4dfef1SStephen Warren /* Set up descriptors */ 1238ba4dfef1SStephen Warren 1239ba4dfef1SStephen Warren memset(eqos->descs, 0, EQOS_DESCRIPTORS_SIZE); 1240ba4dfef1SStephen Warren for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) { 1241ba4dfef1SStephen Warren struct eqos_desc *rx_desc = &(eqos->rx_descs[i]); 1242ba4dfef1SStephen Warren rx_desc->des0 = (u32)(ulong)(eqos->rx_dma_buf + 1243ba4dfef1SStephen Warren (i * EQOS_MAX_PACKET_SIZE)); 1244ba4dfef1SStephen Warren rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; 1245ba4dfef1SStephen Warren } 1246*7a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_desc(eqos->descs); 1247ba4dfef1SStephen Warren 1248ba4dfef1SStephen Warren writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress); 1249ba4dfef1SStephen Warren writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address); 1250ba4dfef1SStephen Warren writel(EQOS_DESCRIPTORS_TX - 1, 1251ba4dfef1SStephen Warren &eqos->dma_regs->ch0_txdesc_ring_length); 1252ba4dfef1SStephen Warren 1253ba4dfef1SStephen Warren writel(0, &eqos->dma_regs->ch0_rxdesc_list_haddress); 1254ba4dfef1SStephen Warren writel((ulong)eqos->rx_descs, &eqos->dma_regs->ch0_rxdesc_list_address); 1255ba4dfef1SStephen Warren writel(EQOS_DESCRIPTORS_RX - 1, 1256ba4dfef1SStephen Warren &eqos->dma_regs->ch0_rxdesc_ring_length); 1257ba4dfef1SStephen Warren 1258ba4dfef1SStephen Warren /* Enable everything */ 1259ba4dfef1SStephen Warren 1260ba4dfef1SStephen Warren setbits_le32(&eqos->mac_regs->configuration, 1261ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE); 1262ba4dfef1SStephen Warren 1263ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_tx_control, 1264ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_ST); 1265ba4dfef1SStephen Warren setbits_le32(&eqos->dma_regs->ch0_rx_control, 1266ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_SR); 1267ba4dfef1SStephen Warren 1268ba4dfef1SStephen Warren /* TX tail pointer not written until we need to TX a packet */ 1269ba4dfef1SStephen Warren /* 1270ba4dfef1SStephen Warren * Point RX tail pointer at last descriptor. Ideally, we'd point at the 1271ba4dfef1SStephen Warren * first descriptor, implying all descriptors were available. However, 1272ba4dfef1SStephen Warren * that's not distinguishable from none of the descriptors being 1273ba4dfef1SStephen Warren * available. 1274ba4dfef1SStephen Warren */ 1275ba4dfef1SStephen Warren last_rx_desc = (ulong)&(eqos->rx_descs[(EQOS_DESCRIPTORS_RX - 1)]); 1276ba4dfef1SStephen Warren writel(last_rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); 1277ba4dfef1SStephen Warren 1278ba4dfef1SStephen Warren eqos->started = true; 1279ba4dfef1SStephen Warren 1280ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1281ba4dfef1SStephen Warren return 0; 1282ba4dfef1SStephen Warren 1283ba4dfef1SStephen Warren err_shutdown_phy: 1284ba4dfef1SStephen Warren phy_shutdown(eqos->phy); 1285ba4dfef1SStephen Warren err_stop_resets: 1286*7a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_resets(dev); 1287ba4dfef1SStephen Warren err_stop_clks: 1288*7a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_clks(dev); 1289ba4dfef1SStephen Warren err: 129090aa625cSMasahiro Yamada pr_err("FAILED: %d", ret); 1291ba4dfef1SStephen Warren return ret; 1292ba4dfef1SStephen Warren } 1293ba4dfef1SStephen Warren 1294ba4dfef1SStephen Warren void eqos_stop(struct udevice *dev) 1295ba4dfef1SStephen Warren { 1296ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1297ba4dfef1SStephen Warren int i; 1298ba4dfef1SStephen Warren 1299ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1300ba4dfef1SStephen Warren 1301ba4dfef1SStephen Warren if (!eqos->started) 1302ba4dfef1SStephen Warren return; 1303ba4dfef1SStephen Warren eqos->started = false; 1304ba4dfef1SStephen Warren eqos->reg_access_ok = false; 1305ba4dfef1SStephen Warren 1306ba4dfef1SStephen Warren /* Disable TX DMA */ 1307ba4dfef1SStephen Warren clrbits_le32(&eqos->dma_regs->ch0_tx_control, 1308ba4dfef1SStephen Warren EQOS_DMA_CH0_TX_CONTROL_ST); 1309ba4dfef1SStephen Warren 1310ba4dfef1SStephen Warren /* Wait for TX all packets to drain out of MTL */ 1311ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 1312ba4dfef1SStephen Warren u32 val = readl(&eqos->mtl_regs->txq0_debug); 1313ba4dfef1SStephen Warren u32 trcsts = (val >> EQOS_MTL_TXQ0_DEBUG_TRCSTS_SHIFT) & 1314ba4dfef1SStephen Warren EQOS_MTL_TXQ0_DEBUG_TRCSTS_MASK; 1315ba4dfef1SStephen Warren u32 txqsts = val & EQOS_MTL_TXQ0_DEBUG_TXQSTS; 1316ba4dfef1SStephen Warren if ((trcsts != 1) && (!txqsts)) 1317ba4dfef1SStephen Warren break; 1318ba4dfef1SStephen Warren } 1319ba4dfef1SStephen Warren 1320ba4dfef1SStephen Warren /* Turn off MAC TX and RX */ 1321ba4dfef1SStephen Warren clrbits_le32(&eqos->mac_regs->configuration, 1322ba4dfef1SStephen Warren EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE); 1323ba4dfef1SStephen Warren 1324ba4dfef1SStephen Warren /* Wait for all RX packets to drain out of MTL */ 1325ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 1326ba4dfef1SStephen Warren u32 val = readl(&eqos->mtl_regs->rxq0_debug); 1327ba4dfef1SStephen Warren u32 prxq = (val >> EQOS_MTL_RXQ0_DEBUG_PRXQ_SHIFT) & 1328ba4dfef1SStephen Warren EQOS_MTL_RXQ0_DEBUG_PRXQ_MASK; 1329ba4dfef1SStephen Warren u32 rxqsts = (val >> EQOS_MTL_RXQ0_DEBUG_RXQSTS_SHIFT) & 1330ba4dfef1SStephen Warren EQOS_MTL_RXQ0_DEBUG_RXQSTS_MASK; 1331ba4dfef1SStephen Warren if ((!prxq) && (!rxqsts)) 1332ba4dfef1SStephen Warren break; 1333ba4dfef1SStephen Warren } 1334ba4dfef1SStephen Warren 1335ba4dfef1SStephen Warren /* Turn off RX DMA */ 1336ba4dfef1SStephen Warren clrbits_le32(&eqos->dma_regs->ch0_rx_control, 1337ba4dfef1SStephen Warren EQOS_DMA_CH0_RX_CONTROL_SR); 1338ba4dfef1SStephen Warren 1339ba4dfef1SStephen Warren if (eqos->phy) { 1340ba4dfef1SStephen Warren phy_shutdown(eqos->phy); 1341ba4dfef1SStephen Warren } 1342*7a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_resets(dev); 1343*7a4c4eddSChristophe Roullier eqos->config->ops->eqos_stop_clks(dev); 1344ba4dfef1SStephen Warren 1345ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1346ba4dfef1SStephen Warren } 1347ba4dfef1SStephen Warren 1348ba4dfef1SStephen Warren int eqos_send(struct udevice *dev, void *packet, int length) 1349ba4dfef1SStephen Warren { 1350ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1351ba4dfef1SStephen Warren struct eqos_desc *tx_desc; 1352ba4dfef1SStephen Warren int i; 1353ba4dfef1SStephen Warren 1354ba4dfef1SStephen Warren debug("%s(dev=%p, packet=%p, length=%d):\n", __func__, dev, packet, 1355ba4dfef1SStephen Warren length); 1356ba4dfef1SStephen Warren 1357ba4dfef1SStephen Warren memcpy(eqos->tx_dma_buf, packet, length); 1358*7a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length); 1359ba4dfef1SStephen Warren 1360ba4dfef1SStephen Warren tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]); 1361ba4dfef1SStephen Warren eqos->tx_desc_idx++; 1362ba4dfef1SStephen Warren eqos->tx_desc_idx %= EQOS_DESCRIPTORS_TX; 1363ba4dfef1SStephen Warren 1364ba4dfef1SStephen Warren tx_desc->des0 = (ulong)eqos->tx_dma_buf; 1365ba4dfef1SStephen Warren tx_desc->des1 = 0; 1366ba4dfef1SStephen Warren tx_desc->des2 = length; 1367ba4dfef1SStephen Warren /* 1368ba4dfef1SStephen Warren * Make sure that if HW sees the _OWN write below, it will see all the 1369ba4dfef1SStephen Warren * writes to the rest of the descriptor too. 1370ba4dfef1SStephen Warren */ 1371ba4dfef1SStephen Warren mb(); 1372ba4dfef1SStephen Warren tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length; 1373*7a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_desc(tx_desc); 1374ba4dfef1SStephen Warren 1375ba4dfef1SStephen Warren writel((ulong)(tx_desc + 1), &eqos->dma_regs->ch0_txdesc_tail_pointer); 1376ba4dfef1SStephen Warren 1377ba4dfef1SStephen Warren for (i = 0; i < 1000000; i++) { 1378*7a4c4eddSChristophe Roullier eqos->config->ops->eqos_inval_desc(tx_desc); 1379ba4dfef1SStephen Warren if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN)) 1380ba4dfef1SStephen Warren return 0; 1381ba4dfef1SStephen Warren udelay(1); 1382ba4dfef1SStephen Warren } 1383ba4dfef1SStephen Warren 1384ba4dfef1SStephen Warren debug("%s: TX timeout\n", __func__); 1385ba4dfef1SStephen Warren 1386ba4dfef1SStephen Warren return -ETIMEDOUT; 1387ba4dfef1SStephen Warren } 1388ba4dfef1SStephen Warren 1389ba4dfef1SStephen Warren int eqos_recv(struct udevice *dev, int flags, uchar **packetp) 1390ba4dfef1SStephen Warren { 1391ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1392ba4dfef1SStephen Warren struct eqos_desc *rx_desc; 1393ba4dfef1SStephen Warren int length; 1394ba4dfef1SStephen Warren 1395ba4dfef1SStephen Warren debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags); 1396ba4dfef1SStephen Warren 1397ba4dfef1SStephen Warren rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); 1398ba4dfef1SStephen Warren if (rx_desc->des3 & EQOS_DESC3_OWN) { 1399ba4dfef1SStephen Warren debug("%s: RX packet not available\n", __func__); 1400ba4dfef1SStephen Warren return -EAGAIN; 1401ba4dfef1SStephen Warren } 1402ba4dfef1SStephen Warren 1403ba4dfef1SStephen Warren *packetp = eqos->rx_dma_buf + 1404ba4dfef1SStephen Warren (eqos->rx_desc_idx * EQOS_MAX_PACKET_SIZE); 1405ba4dfef1SStephen Warren length = rx_desc->des3 & 0x7fff; 1406ba4dfef1SStephen Warren debug("%s: *packetp=%p, length=%d\n", __func__, *packetp, length); 1407ba4dfef1SStephen Warren 1408*7a4c4eddSChristophe Roullier eqos->config->ops->eqos_inval_buffer(*packetp, length); 1409ba4dfef1SStephen Warren 1410ba4dfef1SStephen Warren return length; 1411ba4dfef1SStephen Warren } 1412ba4dfef1SStephen Warren 1413ba4dfef1SStephen Warren int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) 1414ba4dfef1SStephen Warren { 1415ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1416ba4dfef1SStephen Warren uchar *packet_expected; 1417ba4dfef1SStephen Warren struct eqos_desc *rx_desc; 1418ba4dfef1SStephen Warren 1419ba4dfef1SStephen Warren debug("%s(packet=%p, length=%d)\n", __func__, packet, length); 1420ba4dfef1SStephen Warren 1421ba4dfef1SStephen Warren packet_expected = eqos->rx_dma_buf + 1422ba4dfef1SStephen Warren (eqos->rx_desc_idx * EQOS_MAX_PACKET_SIZE); 1423ba4dfef1SStephen Warren if (packet != packet_expected) { 1424ba4dfef1SStephen Warren debug("%s: Unexpected packet (expected %p)\n", __func__, 1425ba4dfef1SStephen Warren packet_expected); 1426ba4dfef1SStephen Warren return -EINVAL; 1427ba4dfef1SStephen Warren } 1428ba4dfef1SStephen Warren 1429ba4dfef1SStephen Warren rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); 1430ba4dfef1SStephen Warren rx_desc->des0 = (u32)(ulong)packet; 1431ba4dfef1SStephen Warren rx_desc->des1 = 0; 1432ba4dfef1SStephen Warren rx_desc->des2 = 0; 1433ba4dfef1SStephen Warren /* 1434ba4dfef1SStephen Warren * Make sure that if HW sees the _OWN write below, it will see all the 1435ba4dfef1SStephen Warren * writes to the rest of the descriptor too. 1436ba4dfef1SStephen Warren */ 1437ba4dfef1SStephen Warren mb(); 1438ba4dfef1SStephen Warren rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; 1439*7a4c4eddSChristophe Roullier eqos->config->ops->eqos_flush_desc(rx_desc); 1440ba4dfef1SStephen Warren 1441ba4dfef1SStephen Warren writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); 1442ba4dfef1SStephen Warren 1443ba4dfef1SStephen Warren eqos->rx_desc_idx++; 1444ba4dfef1SStephen Warren eqos->rx_desc_idx %= EQOS_DESCRIPTORS_RX; 1445ba4dfef1SStephen Warren 1446ba4dfef1SStephen Warren return 0; 1447ba4dfef1SStephen Warren } 1448ba4dfef1SStephen Warren 1449ba4dfef1SStephen Warren static int eqos_probe_resources_core(struct udevice *dev) 1450ba4dfef1SStephen Warren { 1451ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1452ba4dfef1SStephen Warren int ret; 1453ba4dfef1SStephen Warren 1454ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1455ba4dfef1SStephen Warren 1456ba4dfef1SStephen Warren eqos->descs = eqos_alloc_descs(EQOS_DESCRIPTORS_TX + 1457ba4dfef1SStephen Warren EQOS_DESCRIPTORS_RX); 1458ba4dfef1SStephen Warren if (!eqos->descs) { 1459ba4dfef1SStephen Warren debug("%s: eqos_alloc_descs() failed\n", __func__); 1460ba4dfef1SStephen Warren ret = -ENOMEM; 1461ba4dfef1SStephen Warren goto err; 1462ba4dfef1SStephen Warren } 1463ba4dfef1SStephen Warren eqos->tx_descs = (struct eqos_desc *)eqos->descs; 1464ba4dfef1SStephen Warren eqos->rx_descs = (eqos->tx_descs + EQOS_DESCRIPTORS_TX); 1465ba4dfef1SStephen Warren debug("%s: tx_descs=%p, rx_descs=%p\n", __func__, eqos->tx_descs, 1466ba4dfef1SStephen Warren eqos->rx_descs); 1467ba4dfef1SStephen Warren 1468ba4dfef1SStephen Warren eqos->tx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_MAX_PACKET_SIZE); 1469ba4dfef1SStephen Warren if (!eqos->tx_dma_buf) { 1470ba4dfef1SStephen Warren debug("%s: memalign(tx_dma_buf) failed\n", __func__); 1471ba4dfef1SStephen Warren ret = -ENOMEM; 1472ba4dfef1SStephen Warren goto err_free_descs; 1473ba4dfef1SStephen Warren } 1474*7a4c4eddSChristophe Roullier debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf); 1475ba4dfef1SStephen Warren 1476ba4dfef1SStephen Warren eqos->rx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_RX_BUFFER_SIZE); 1477ba4dfef1SStephen Warren if (!eqos->rx_dma_buf) { 1478ba4dfef1SStephen Warren debug("%s: memalign(rx_dma_buf) failed\n", __func__); 1479ba4dfef1SStephen Warren ret = -ENOMEM; 1480ba4dfef1SStephen Warren goto err_free_tx_dma_buf; 1481ba4dfef1SStephen Warren } 1482*7a4c4eddSChristophe Roullier debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf); 1483ba4dfef1SStephen Warren 1484ba4dfef1SStephen Warren eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE); 1485ba4dfef1SStephen Warren if (!eqos->rx_pkt) { 1486ba4dfef1SStephen Warren debug("%s: malloc(rx_pkt) failed\n", __func__); 1487ba4dfef1SStephen Warren ret = -ENOMEM; 1488ba4dfef1SStephen Warren goto err_free_rx_dma_buf; 1489ba4dfef1SStephen Warren } 1490ba4dfef1SStephen Warren debug("%s: rx_pkt=%p\n", __func__, eqos->rx_pkt); 1491ba4dfef1SStephen Warren 1492ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1493ba4dfef1SStephen Warren return 0; 1494ba4dfef1SStephen Warren 1495ba4dfef1SStephen Warren err_free_rx_dma_buf: 1496ba4dfef1SStephen Warren free(eqos->rx_dma_buf); 1497ba4dfef1SStephen Warren err_free_tx_dma_buf: 1498ba4dfef1SStephen Warren free(eqos->tx_dma_buf); 1499ba4dfef1SStephen Warren err_free_descs: 1500ba4dfef1SStephen Warren eqos_free_descs(eqos->descs); 1501ba4dfef1SStephen Warren err: 1502ba4dfef1SStephen Warren 1503ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 1504ba4dfef1SStephen Warren return ret; 1505ba4dfef1SStephen Warren } 1506ba4dfef1SStephen Warren 1507ba4dfef1SStephen Warren static int eqos_remove_resources_core(struct udevice *dev) 1508ba4dfef1SStephen Warren { 1509ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1510ba4dfef1SStephen Warren 1511ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1512ba4dfef1SStephen Warren 1513ba4dfef1SStephen Warren free(eqos->rx_pkt); 1514ba4dfef1SStephen Warren free(eqos->rx_dma_buf); 1515ba4dfef1SStephen Warren free(eqos->tx_dma_buf); 1516ba4dfef1SStephen Warren eqos_free_descs(eqos->descs); 1517ba4dfef1SStephen Warren 1518ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1519ba4dfef1SStephen Warren return 0; 1520ba4dfef1SStephen Warren } 1521ba4dfef1SStephen Warren 1522ba4dfef1SStephen Warren static int eqos_probe_resources_tegra186(struct udevice *dev) 1523ba4dfef1SStephen Warren { 1524ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1525ba4dfef1SStephen Warren int ret; 1526ba4dfef1SStephen Warren 1527ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1528ba4dfef1SStephen Warren 1529ba4dfef1SStephen Warren ret = reset_get_by_name(dev, "eqos", &eqos->reset_ctl); 1530ba4dfef1SStephen Warren if (ret) { 153190aa625cSMasahiro Yamada pr_err("reset_get_by_name(rst) failed: %d", ret); 1532ba4dfef1SStephen Warren return ret; 1533ba4dfef1SStephen Warren } 1534ba4dfef1SStephen Warren 1535ba4dfef1SStephen Warren ret = gpio_request_by_name(dev, "phy-reset-gpios", 0, 1536ba4dfef1SStephen Warren &eqos->phy_reset_gpio, 1537ba4dfef1SStephen Warren GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); 1538ba4dfef1SStephen Warren if (ret) { 153990aa625cSMasahiro Yamada pr_err("gpio_request_by_name(phy reset) failed: %d", ret); 1540ba4dfef1SStephen Warren goto err_free_reset_eqos; 1541ba4dfef1SStephen Warren } 1542ba4dfef1SStephen Warren 1543ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "slave_bus", &eqos->clk_slave_bus); 1544ba4dfef1SStephen Warren if (ret) { 154590aa625cSMasahiro Yamada pr_err("clk_get_by_name(slave_bus) failed: %d", ret); 1546ba4dfef1SStephen Warren goto err_free_gpio_phy_reset; 1547ba4dfef1SStephen Warren } 1548ba4dfef1SStephen Warren 1549ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "master_bus", &eqos->clk_master_bus); 1550ba4dfef1SStephen Warren if (ret) { 155190aa625cSMasahiro Yamada pr_err("clk_get_by_name(master_bus) failed: %d", ret); 1552ba4dfef1SStephen Warren goto err_free_clk_slave_bus; 1553ba4dfef1SStephen Warren } 1554ba4dfef1SStephen Warren 1555ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "rx", &eqos->clk_rx); 1556ba4dfef1SStephen Warren if (ret) { 155790aa625cSMasahiro Yamada pr_err("clk_get_by_name(rx) failed: %d", ret); 1558ba4dfef1SStephen Warren goto err_free_clk_master_bus; 1559ba4dfef1SStephen Warren } 1560ba4dfef1SStephen Warren 1561ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "ptp_ref", &eqos->clk_ptp_ref); 1562ba4dfef1SStephen Warren if (ret) { 156390aa625cSMasahiro Yamada pr_err("clk_get_by_name(ptp_ref) failed: %d", ret); 1564ba4dfef1SStephen Warren goto err_free_clk_rx; 1565ba4dfef1SStephen Warren return ret; 1566ba4dfef1SStephen Warren } 1567ba4dfef1SStephen Warren 1568ba4dfef1SStephen Warren ret = clk_get_by_name(dev, "tx", &eqos->clk_tx); 1569ba4dfef1SStephen Warren if (ret) { 157090aa625cSMasahiro Yamada pr_err("clk_get_by_name(tx) failed: %d", ret); 1571ba4dfef1SStephen Warren goto err_free_clk_ptp_ref; 1572ba4dfef1SStephen Warren } 1573ba4dfef1SStephen Warren 1574ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1575ba4dfef1SStephen Warren return 0; 1576ba4dfef1SStephen Warren 1577ba4dfef1SStephen Warren err_free_clk_ptp_ref: 1578ba4dfef1SStephen Warren clk_free(&eqos->clk_ptp_ref); 1579ba4dfef1SStephen Warren err_free_clk_rx: 1580ba4dfef1SStephen Warren clk_free(&eqos->clk_rx); 1581ba4dfef1SStephen Warren err_free_clk_master_bus: 1582ba4dfef1SStephen Warren clk_free(&eqos->clk_master_bus); 1583ba4dfef1SStephen Warren err_free_clk_slave_bus: 1584ba4dfef1SStephen Warren clk_free(&eqos->clk_slave_bus); 1585ba4dfef1SStephen Warren err_free_gpio_phy_reset: 1586ba4dfef1SStephen Warren dm_gpio_free(dev, &eqos->phy_reset_gpio); 1587ba4dfef1SStephen Warren err_free_reset_eqos: 1588ba4dfef1SStephen Warren reset_free(&eqos->reset_ctl); 1589ba4dfef1SStephen Warren 1590ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 1591ba4dfef1SStephen Warren return ret; 1592ba4dfef1SStephen Warren } 1593ba4dfef1SStephen Warren 1594*7a4c4eddSChristophe Roullier /* board-specific Ethernet Interface initializations. */ 1595*7a4c4eddSChristophe Roullier __weak int board_interface_eth_init(int interface_type, bool eth_clk_sel_reg, 1596*7a4c4eddSChristophe Roullier bool eth_ref_clk_sel_reg) 1597*7a4c4eddSChristophe Roullier { 1598*7a4c4eddSChristophe Roullier return 0; 1599*7a4c4eddSChristophe Roullier } 1600*7a4c4eddSChristophe Roullier 1601*7a4c4eddSChristophe Roullier static int eqos_probe_resources_stm32(struct udevice *dev) 1602*7a4c4eddSChristophe Roullier { 1603*7a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 1604*7a4c4eddSChristophe Roullier int ret; 1605*7a4c4eddSChristophe Roullier phy_interface_t interface; 1606*7a4c4eddSChristophe Roullier bool eth_clk_sel_reg = false; 1607*7a4c4eddSChristophe Roullier bool eth_ref_clk_sel_reg = false; 1608*7a4c4eddSChristophe Roullier 1609*7a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 1610*7a4c4eddSChristophe Roullier 1611*7a4c4eddSChristophe Roullier interface = eqos->config->interface(dev); 1612*7a4c4eddSChristophe Roullier 1613*7a4c4eddSChristophe Roullier if (interface == PHY_INTERFACE_MODE_NONE) { 1614*7a4c4eddSChristophe Roullier pr_err("Invalid PHY interface\n"); 1615*7a4c4eddSChristophe Roullier return -EINVAL; 1616*7a4c4eddSChristophe Roullier } 1617*7a4c4eddSChristophe Roullier 1618*7a4c4eddSChristophe Roullier /* Gigabit Ethernet 125MHz clock selection. */ 1619*7a4c4eddSChristophe Roullier eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel"); 1620*7a4c4eddSChristophe Roullier 1621*7a4c4eddSChristophe Roullier /* Ethernet 50Mhz RMII clock selection */ 1622*7a4c4eddSChristophe Roullier eth_ref_clk_sel_reg = 1623*7a4c4eddSChristophe Roullier dev_read_bool(dev, "st,eth_ref_clk_sel"); 1624*7a4c4eddSChristophe Roullier 1625*7a4c4eddSChristophe Roullier ret = board_interface_eth_init(interface, eth_clk_sel_reg, 1626*7a4c4eddSChristophe Roullier eth_ref_clk_sel_reg); 1627*7a4c4eddSChristophe Roullier if (ret) 1628*7a4c4eddSChristophe Roullier return -EINVAL; 1629*7a4c4eddSChristophe Roullier 1630*7a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); 1631*7a4c4eddSChristophe Roullier if (ret) { 1632*7a4c4eddSChristophe Roullier pr_err("clk_get_by_name(master_bus) failed: %d", ret); 1633*7a4c4eddSChristophe Roullier goto err_probe; 1634*7a4c4eddSChristophe Roullier } 1635*7a4c4eddSChristophe Roullier 1636*7a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); 1637*7a4c4eddSChristophe Roullier if (ret) { 1638*7a4c4eddSChristophe Roullier pr_err("clk_get_by_name(rx) failed: %d", ret); 1639*7a4c4eddSChristophe Roullier goto err_free_clk_master_bus; 1640*7a4c4eddSChristophe Roullier } 1641*7a4c4eddSChristophe Roullier 1642*7a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); 1643*7a4c4eddSChristophe Roullier if (ret) { 1644*7a4c4eddSChristophe Roullier pr_err("clk_get_by_name(tx) failed: %d", ret); 1645*7a4c4eddSChristophe Roullier goto err_free_clk_rx; 1646*7a4c4eddSChristophe Roullier } 1647*7a4c4eddSChristophe Roullier 1648*7a4c4eddSChristophe Roullier /* Get ETH_CLK clocks (optional) */ 1649*7a4c4eddSChristophe Roullier ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck); 1650*7a4c4eddSChristophe Roullier if (ret) 1651*7a4c4eddSChristophe Roullier pr_warn("No phy clock provided %d", ret); 1652*7a4c4eddSChristophe Roullier 1653*7a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 1654*7a4c4eddSChristophe Roullier return 0; 1655*7a4c4eddSChristophe Roullier 1656*7a4c4eddSChristophe Roullier err_free_clk_rx: 1657*7a4c4eddSChristophe Roullier clk_free(&eqos->clk_rx); 1658*7a4c4eddSChristophe Roullier err_free_clk_master_bus: 1659*7a4c4eddSChristophe Roullier clk_free(&eqos->clk_master_bus); 1660*7a4c4eddSChristophe Roullier err_probe: 1661*7a4c4eddSChristophe Roullier 1662*7a4c4eddSChristophe Roullier debug("%s: returns %d\n", __func__, ret); 1663*7a4c4eddSChristophe Roullier return ret; 1664*7a4c4eddSChristophe Roullier } 1665*7a4c4eddSChristophe Roullier 1666*7a4c4eddSChristophe Roullier static phy_interface_t eqos_get_interface_stm32(struct udevice *dev) 1667*7a4c4eddSChristophe Roullier { 1668*7a4c4eddSChristophe Roullier const char *phy_mode; 1669*7a4c4eddSChristophe Roullier phy_interface_t interface = PHY_INTERFACE_MODE_NONE; 1670*7a4c4eddSChristophe Roullier 1671*7a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 1672*7a4c4eddSChristophe Roullier 1673*7a4c4eddSChristophe Roullier phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", 1674*7a4c4eddSChristophe Roullier NULL); 1675*7a4c4eddSChristophe Roullier if (phy_mode) 1676*7a4c4eddSChristophe Roullier interface = phy_get_interface_by_name(phy_mode); 1677*7a4c4eddSChristophe Roullier 1678*7a4c4eddSChristophe Roullier return interface; 1679*7a4c4eddSChristophe Roullier } 1680*7a4c4eddSChristophe Roullier 1681*7a4c4eddSChristophe Roullier static phy_interface_t eqos_get_interface_tegra186(struct udevice *dev) 1682*7a4c4eddSChristophe Roullier { 1683*7a4c4eddSChristophe Roullier return PHY_INTERFACE_MODE_MII; 1684*7a4c4eddSChristophe Roullier } 1685*7a4c4eddSChristophe Roullier 1686ba4dfef1SStephen Warren static int eqos_remove_resources_tegra186(struct udevice *dev) 1687ba4dfef1SStephen Warren { 1688ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1689ba4dfef1SStephen Warren 1690ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1691ba4dfef1SStephen Warren 1692ba4dfef1SStephen Warren clk_free(&eqos->clk_tx); 1693ba4dfef1SStephen Warren clk_free(&eqos->clk_ptp_ref); 1694ba4dfef1SStephen Warren clk_free(&eqos->clk_rx); 1695ba4dfef1SStephen Warren clk_free(&eqos->clk_slave_bus); 1696ba4dfef1SStephen Warren clk_free(&eqos->clk_master_bus); 1697ba4dfef1SStephen Warren dm_gpio_free(dev, &eqos->phy_reset_gpio); 1698ba4dfef1SStephen Warren reset_free(&eqos->reset_ctl); 1699ba4dfef1SStephen Warren 1700ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1701ba4dfef1SStephen Warren return 0; 1702ba4dfef1SStephen Warren } 1703ba4dfef1SStephen Warren 1704*7a4c4eddSChristophe Roullier static int eqos_remove_resources_stm32(struct udevice *dev) 1705*7a4c4eddSChristophe Roullier { 1706*7a4c4eddSChristophe Roullier struct eqos_priv *eqos = dev_get_priv(dev); 1707*7a4c4eddSChristophe Roullier 1708*7a4c4eddSChristophe Roullier debug("%s(dev=%p):\n", __func__, dev); 1709*7a4c4eddSChristophe Roullier 1710*7a4c4eddSChristophe Roullier clk_free(&eqos->clk_tx); 1711*7a4c4eddSChristophe Roullier clk_free(&eqos->clk_rx); 1712*7a4c4eddSChristophe Roullier clk_free(&eqos->clk_master_bus); 1713*7a4c4eddSChristophe Roullier if (clk_valid(&eqos->clk_ck)) 1714*7a4c4eddSChristophe Roullier clk_free(&eqos->clk_ck); 1715*7a4c4eddSChristophe Roullier 1716*7a4c4eddSChristophe Roullier debug("%s: OK\n", __func__); 1717*7a4c4eddSChristophe Roullier return 0; 1718*7a4c4eddSChristophe Roullier } 1719*7a4c4eddSChristophe Roullier 1720ba4dfef1SStephen Warren static int eqos_probe(struct udevice *dev) 1721ba4dfef1SStephen Warren { 1722ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1723ba4dfef1SStephen Warren int ret; 1724ba4dfef1SStephen Warren 1725ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1726ba4dfef1SStephen Warren 1727ba4dfef1SStephen Warren eqos->dev = dev; 1728ba4dfef1SStephen Warren eqos->config = (void *)dev_get_driver_data(dev); 1729ba4dfef1SStephen Warren 1730a821c4afSSimon Glass eqos->regs = devfdt_get_addr(dev); 1731ba4dfef1SStephen Warren if (eqos->regs == FDT_ADDR_T_NONE) { 173290aa625cSMasahiro Yamada pr_err("devfdt_get_addr() failed"); 1733ba4dfef1SStephen Warren return -ENODEV; 1734ba4dfef1SStephen Warren } 1735ba4dfef1SStephen Warren eqos->mac_regs = (void *)(eqos->regs + EQOS_MAC_REGS_BASE); 1736ba4dfef1SStephen Warren eqos->mtl_regs = (void *)(eqos->regs + EQOS_MTL_REGS_BASE); 1737ba4dfef1SStephen Warren eqos->dma_regs = (void *)(eqos->regs + EQOS_DMA_REGS_BASE); 1738ba4dfef1SStephen Warren eqos->tegra186_regs = (void *)(eqos->regs + EQOS_TEGRA186_REGS_BASE); 1739ba4dfef1SStephen Warren 1740ba4dfef1SStephen Warren ret = eqos_probe_resources_core(dev); 1741ba4dfef1SStephen Warren if (ret < 0) { 174290aa625cSMasahiro Yamada pr_err("eqos_probe_resources_core() failed: %d", ret); 1743ba4dfef1SStephen Warren return ret; 1744ba4dfef1SStephen Warren } 1745ba4dfef1SStephen Warren 1746*7a4c4eddSChristophe Roullier ret = eqos->config->ops->eqos_probe_resources(dev); 1747ba4dfef1SStephen Warren if (ret < 0) { 1748*7a4c4eddSChristophe Roullier pr_err("eqos_probe_resources() failed: %d", ret); 1749ba4dfef1SStephen Warren goto err_remove_resources_core; 1750ba4dfef1SStephen Warren } 1751ba4dfef1SStephen Warren 1752ba4dfef1SStephen Warren eqos->mii = mdio_alloc(); 1753ba4dfef1SStephen Warren if (!eqos->mii) { 175490aa625cSMasahiro Yamada pr_err("mdio_alloc() failed"); 1755*7a4c4eddSChristophe Roullier ret = -ENOMEM; 1756ba4dfef1SStephen Warren goto err_remove_resources_tegra; 1757ba4dfef1SStephen Warren } 1758ba4dfef1SStephen Warren eqos->mii->read = eqos_mdio_read; 1759ba4dfef1SStephen Warren eqos->mii->write = eqos_mdio_write; 1760ba4dfef1SStephen Warren eqos->mii->priv = eqos; 1761ba4dfef1SStephen Warren strcpy(eqos->mii->name, dev->name); 1762ba4dfef1SStephen Warren 1763ba4dfef1SStephen Warren ret = mdio_register(eqos->mii); 1764ba4dfef1SStephen Warren if (ret < 0) { 176590aa625cSMasahiro Yamada pr_err("mdio_register() failed: %d", ret); 1766ba4dfef1SStephen Warren goto err_free_mdio; 1767ba4dfef1SStephen Warren } 1768ba4dfef1SStephen Warren 1769ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1770ba4dfef1SStephen Warren return 0; 1771ba4dfef1SStephen Warren 1772ba4dfef1SStephen Warren err_free_mdio: 1773ba4dfef1SStephen Warren mdio_free(eqos->mii); 1774ba4dfef1SStephen Warren err_remove_resources_tegra: 1775*7a4c4eddSChristophe Roullier eqos->config->ops->eqos_remove_resources(dev); 1776ba4dfef1SStephen Warren err_remove_resources_core: 1777ba4dfef1SStephen Warren eqos_remove_resources_core(dev); 1778ba4dfef1SStephen Warren 1779ba4dfef1SStephen Warren debug("%s: returns %d\n", __func__, ret); 1780ba4dfef1SStephen Warren return ret; 1781ba4dfef1SStephen Warren } 1782ba4dfef1SStephen Warren 1783ba4dfef1SStephen Warren static int eqos_remove(struct udevice *dev) 1784ba4dfef1SStephen Warren { 1785ba4dfef1SStephen Warren struct eqos_priv *eqos = dev_get_priv(dev); 1786ba4dfef1SStephen Warren 1787ba4dfef1SStephen Warren debug("%s(dev=%p):\n", __func__, dev); 1788ba4dfef1SStephen Warren 1789ba4dfef1SStephen Warren mdio_unregister(eqos->mii); 1790ba4dfef1SStephen Warren mdio_free(eqos->mii); 1791*7a4c4eddSChristophe Roullier eqos->config->ops->eqos_remove_resources(dev); 1792*7a4c4eddSChristophe Roullier 1793ba4dfef1SStephen Warren eqos_probe_resources_core(dev); 1794ba4dfef1SStephen Warren 1795ba4dfef1SStephen Warren debug("%s: OK\n", __func__); 1796ba4dfef1SStephen Warren return 0; 1797ba4dfef1SStephen Warren } 1798ba4dfef1SStephen Warren 1799ba4dfef1SStephen Warren static const struct eth_ops eqos_ops = { 1800ba4dfef1SStephen Warren .start = eqos_start, 1801ba4dfef1SStephen Warren .stop = eqos_stop, 1802ba4dfef1SStephen Warren .send = eqos_send, 1803ba4dfef1SStephen Warren .recv = eqos_recv, 1804ba4dfef1SStephen Warren .free_pkt = eqos_free_pkt, 1805ba4dfef1SStephen Warren .write_hwaddr = eqos_write_hwaddr, 1806ba4dfef1SStephen Warren }; 1807ba4dfef1SStephen Warren 1808*7a4c4eddSChristophe Roullier static struct eqos_ops eqos_tegra186_ops = { 1809*7a4c4eddSChristophe Roullier .eqos_inval_desc = eqos_inval_desc_tegra186, 1810*7a4c4eddSChristophe Roullier .eqos_flush_desc = eqos_flush_desc_tegra186, 1811*7a4c4eddSChristophe Roullier .eqos_inval_buffer = eqos_inval_buffer_tegra186, 1812*7a4c4eddSChristophe Roullier .eqos_flush_buffer = eqos_flush_buffer_tegra186, 1813*7a4c4eddSChristophe Roullier .eqos_probe_resources = eqos_probe_resources_tegra186, 1814*7a4c4eddSChristophe Roullier .eqos_remove_resources = eqos_remove_resources_tegra186, 1815*7a4c4eddSChristophe Roullier .eqos_stop_resets = eqos_stop_resets_tegra186, 1816*7a4c4eddSChristophe Roullier .eqos_start_resets = eqos_start_resets_tegra186, 1817*7a4c4eddSChristophe Roullier .eqos_stop_clks = eqos_stop_clks_tegra186, 1818*7a4c4eddSChristophe Roullier .eqos_start_clks = eqos_start_clks_tegra186, 1819*7a4c4eddSChristophe Roullier .eqos_calibrate_pads = eqos_calibrate_pads_tegra186, 1820*7a4c4eddSChristophe Roullier .eqos_disable_calibration = eqos_disable_calibration_tegra186, 1821*7a4c4eddSChristophe Roullier .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186, 1822*7a4c4eddSChristophe Roullier .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186 1823*7a4c4eddSChristophe Roullier }; 1824*7a4c4eddSChristophe Roullier 1825ba4dfef1SStephen Warren static const struct eqos_config eqos_tegra186_config = { 1826ba4dfef1SStephen Warren .reg_access_always_ok = false, 1827*7a4c4eddSChristophe Roullier .mdio_wait = 10, 1828*7a4c4eddSChristophe Roullier .swr_wait = 10, 1829*7a4c4eddSChristophe Roullier .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, 1830*7a4c4eddSChristophe Roullier .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35, 1831*7a4c4eddSChristophe Roullier .interface = eqos_get_interface_tegra186, 1832*7a4c4eddSChristophe Roullier .ops = &eqos_tegra186_ops 1833*7a4c4eddSChristophe Roullier }; 1834*7a4c4eddSChristophe Roullier 1835*7a4c4eddSChristophe Roullier static struct eqos_ops eqos_stm32_ops = { 1836*7a4c4eddSChristophe Roullier .eqos_inval_desc = eqos_inval_desc_stm32, 1837*7a4c4eddSChristophe Roullier .eqos_flush_desc = eqos_flush_desc_stm32, 1838*7a4c4eddSChristophe Roullier .eqos_inval_buffer = eqos_inval_buffer_stm32, 1839*7a4c4eddSChristophe Roullier .eqos_flush_buffer = eqos_flush_buffer_stm32, 1840*7a4c4eddSChristophe Roullier .eqos_probe_resources = eqos_probe_resources_stm32, 1841*7a4c4eddSChristophe Roullier .eqos_remove_resources = eqos_remove_resources_stm32, 1842*7a4c4eddSChristophe Roullier .eqos_stop_resets = eqos_stop_resets_stm32, 1843*7a4c4eddSChristophe Roullier .eqos_start_resets = eqos_start_resets_stm32, 1844*7a4c4eddSChristophe Roullier .eqos_stop_clks = eqos_stop_clks_stm32, 1845*7a4c4eddSChristophe Roullier .eqos_start_clks = eqos_start_clks_stm32, 1846*7a4c4eddSChristophe Roullier .eqos_calibrate_pads = eqos_calibrate_pads_stm32, 1847*7a4c4eddSChristophe Roullier .eqos_disable_calibration = eqos_disable_calibration_stm32, 1848*7a4c4eddSChristophe Roullier .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_stm32, 1849*7a4c4eddSChristophe Roullier .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 1850*7a4c4eddSChristophe Roullier }; 1851*7a4c4eddSChristophe Roullier 1852*7a4c4eddSChristophe Roullier static const struct eqos_config eqos_stm32_config = { 1853*7a4c4eddSChristophe Roullier .reg_access_always_ok = false, 1854*7a4c4eddSChristophe Roullier .mdio_wait = 10000, 1855*7a4c4eddSChristophe Roullier .swr_wait = 50, 1856*7a4c4eddSChristophe Roullier .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, 1857*7a4c4eddSChristophe Roullier .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, 1858*7a4c4eddSChristophe Roullier .interface = eqos_get_interface_stm32, 1859*7a4c4eddSChristophe Roullier .ops = &eqos_stm32_ops 1860ba4dfef1SStephen Warren }; 1861ba4dfef1SStephen Warren 1862ba4dfef1SStephen Warren static const struct udevice_id eqos_ids[] = { 1863ba4dfef1SStephen Warren { 1864ba4dfef1SStephen Warren .compatible = "nvidia,tegra186-eqos", 1865ba4dfef1SStephen Warren .data = (ulong)&eqos_tegra186_config 1866ba4dfef1SStephen Warren }, 1867*7a4c4eddSChristophe Roullier { 1868*7a4c4eddSChristophe Roullier .compatible = "snps,dwmac-4.20a", 1869*7a4c4eddSChristophe Roullier .data = (ulong)&eqos_stm32_config 1870*7a4c4eddSChristophe Roullier }, 1871*7a4c4eddSChristophe Roullier 1872ba4dfef1SStephen Warren { } 1873ba4dfef1SStephen Warren }; 1874ba4dfef1SStephen Warren 1875ba4dfef1SStephen Warren U_BOOT_DRIVER(eth_eqos) = { 1876ba4dfef1SStephen Warren .name = "eth_eqos", 1877ba4dfef1SStephen Warren .id = UCLASS_ETH, 1878ba4dfef1SStephen Warren .of_match = eqos_ids, 1879ba4dfef1SStephen Warren .probe = eqos_probe, 1880ba4dfef1SStephen Warren .remove = eqos_remove, 1881ba4dfef1SStephen Warren .ops = &eqos_ops, 1882ba4dfef1SStephen Warren .priv_auto_alloc_size = sizeof(struct eqos_priv), 1883ba4dfef1SStephen Warren .platdata_auto_alloc_size = sizeof(struct eth_pdata), 1884ba4dfef1SStephen Warren }; 1885