X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=EmbeddedPkg%2FDrivers%2FLan9118Dxe%2FLan9118DxeUtil.c;h=ea308afe6b2086e530c235ea39c6f45de1155188;hb=4f0624e87a89afce8408a87997482b383e7ba131;hp=2ef1ecbb2887e0a1cec3b472b9b334ba60721ac7;hpb=a4626006bbf86113453aeb7920895e66cdd04737;p=mirror_edk2.git diff --git a/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.c b/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.c index 2ef1ecbb28..ea308afe6b 100644 --- a/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.c +++ b/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.c @@ -98,7 +98,7 @@ IndirectMACRead32 ( ASSERT(Index <= 12); // Wait until CSR busy bit is cleared - while ((MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); + while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); // Set CSR busy bit to ensure read will occur // Set the R/W bit to indicate we are reading @@ -106,13 +106,61 @@ IndirectMACRead32 ( MacCSR = MAC_CSR_BUSY | MAC_CSR_READ | MAC_CSR_ADDR(Index); // Write to the register - MmioWrite32 (LAN9118_MAC_CSR_CMD, MacCSR); + Lan9118MmioWrite32 (LAN9118_MAC_CSR_CMD, MacCSR); // Wait until CSR busy bit is cleared - while ((MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); + while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); // Now read from data register to get read value - return MmioRead32 (LAN9118_MAC_CSR_DATA); + return Lan9118MmioRead32 (LAN9118_MAC_CSR_DATA); +} + +/* + * LAN9118 chips have special restrictions on some back-to-back Write/Read or + * Read/Read pairs of accesses. After a read or write that changes the state of + * the device, there is a period in which stale values may be returned in + * response to a read. This period is dependent on the registers accessed. + * + * We must delay prior reads by this period. This can either be achieved by + * timer-based delays, or by performing dummy reads of the BYTE_TEST register, + * for which the recommended number of reads is described in the LAN9118 data + * sheet. This is required in addition to any memory barriers. + * + * This function performs a number of dummy reads of the BYTE_TEST register, as + * a building block for the above. + */ +VOID +WaitDummyReads ( + UINTN Count + ) +{ + while (Count--) + MmioRead32(LAN9118_BYTE_TEST); +} + +UINT32 +Lan9118RawMmioRead32( + UINTN Address, + UINTN Delay + ) +{ + UINT32 Value; + + Value = MmioRead32(Address); + WaitDummyReads(Delay); + return Value; +} + +UINT32 +Lan9118RawMmioWrite32( + UINTN Address, + UINT32 Value, + UINTN Delay + ) +{ + MmioWrite32(Address, Value); + WaitDummyReads(Delay); + return Value; } // Function to write to MAC indirect registers @@ -129,7 +177,7 @@ IndirectMACWrite32 ( ASSERT(Index <= 12); // Wait until CSR busy bit is cleared - while ((MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); + while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); // Set CSR busy bit to ensure read will occur // Set the R/W bit to indicate we are writing @@ -137,13 +185,13 @@ IndirectMACWrite32 ( MacCSR = MAC_CSR_BUSY | MAC_CSR_WRITE | MAC_CSR_ADDR(Index); // Now write the value to the register before issuing the write command - ValueWritten = MmioWrite32 (LAN9118_MAC_CSR_DATA, Value); + ValueWritten = Lan9118MmioWrite32 (LAN9118_MAC_CSR_DATA, Value); // Write the config to the register - MmioWrite32 (LAN9118_MAC_CSR_CMD, MacCSR); + Lan9118MmioWrite32 (LAN9118_MAC_CSR_CMD, MacCSR); // Wait until CSR busy bit is cleared - while ((MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); + while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); return ValueWritten; } @@ -235,23 +283,22 @@ IndirectEEPROMRead32 ( EepromCmd |= E2P_EPC_ADDRESS(Index); // Write to Eeprom command register - MmioWrite32 (LAN9118_E2P_CMD, EepromCmd); - MemoryFence(); + Lan9118MmioWrite32 (LAN9118_E2P_CMD, EepromCmd); // Wait until operation has completed - while (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); + while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); // Check that operation didn't time out - if (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_TIMEOUT) { + if (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_TIMEOUT) { DEBUG ((EFI_D_ERROR, "EEPROM Operation Timed out: Read command on index %x\n",Index)); return 0; } // Wait until operation has completed - while (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); + while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); // Finally read the value - return MmioRead32 (LAN9118_E2P_DATA); + return Lan9118MmioRead32 (LAN9118_E2P_DATA); } // Function to write to EEPROM memory @@ -267,7 +314,7 @@ IndirectEEPROMWrite32 ( ValueWritten = 0; // Read the EEPROM Command register - EepromCmd = MmioRead32 (LAN9118_E2P_CMD); + EepromCmd = Lan9118MmioRead32 (LAN9118_E2P_CMD); // Set the busy bit to ensure read will occur EepromCmd |= ((UINT32)1 << 31); @@ -280,23 +327,22 @@ IndirectEEPROMWrite32 ( EepromCmd |= (Index & 0xF); // Write the value to the data register first - ValueWritten = MmioWrite32 (LAN9118_E2P_DATA, Value); + ValueWritten = Lan9118MmioWrite32 (LAN9118_E2P_DATA, Value); // Write to Eeprom command register - MmioWrite32 (LAN9118_E2P_CMD, EepromCmd); - MemoryFence(); + Lan9118MmioWrite32 (LAN9118_E2P_CMD, EepromCmd); // Wait until operation has completed - while (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); + while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); // Check that operation didn't time out - if (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_TIMEOUT) { + if (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_TIMEOUT) { DEBUG ((EFI_D_ERROR, "EEPROM Operation Timed out: Write command at memloc 0x%x, with value 0x%x\n",Index, Value)); return 0; } // Wait until operation has completed - while (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); + while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); return ValueWritten; } @@ -355,39 +401,36 @@ Lan9118Initialize ( IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp ) { - UINTN Timeout; + UINTN Retries; UINT64 DefaultMacAddress; // Attempt to wake-up the device if it is in a lower power state - if (((MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_PM_MODE_MASK) >> 12) != 0) { + if (((Lan9118MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_PM_MODE_MASK) >> 12) != 0) { DEBUG ((DEBUG_NET, "Waking from reduced power state.\n")); - MmioWrite32 (LAN9118_BYTE_TEST, 0xFFFFFFFF); - MemoryFence(); + Lan9118MmioWrite32 (LAN9118_BYTE_TEST, 0xFFFFFFFF); } // Check that device is active - Timeout = 20; - while ((MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_READY) == 0 && --Timeout) { + Retries = 20; + while ((Lan9118MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_READY) == 0 && --Retries) { gBS->Stall (LAN9118_STALL); - MemoryFence(); } - if (!Timeout) { + if (!Retries) { return EFI_TIMEOUT; } // Check that EEPROM isn't active - Timeout = 20; - while ((MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY) && --Timeout){ + Retries = 20; + while ((Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY) && --Retries){ gBS->Stall (LAN9118_STALL); - MemoryFence(); } - if (!Timeout) { + if (!Retries) { return EFI_TIMEOUT; } // Check if a MAC address was loaded from EEPROM, and if it was, set it as the // current address. - if ((MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_MAC_ADDRESS_LOADED) == 0) { + if ((Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_MAC_ADDRESS_LOADED) == 0) { DEBUG ((EFI_D_ERROR, "Warning: There was an error detecting EEPROM or loading the MAC Address.\n")); // If we had an address before (set by StationAddess), continue to use it @@ -407,9 +450,9 @@ Lan9118Initialize ( } // Clear and acknowledge interrupts - MmioWrite32 (LAN9118_INT_EN, 0); - MmioWrite32 (LAN9118_IRQ_CFG, 0); - MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF); + Lan9118MmioWrite32 (LAN9118_INT_EN, 0); + Lan9118MmioWrite32 (LAN9118_IRQ_CFG, 0); + Lan9118MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF); // Do self tests here? @@ -436,7 +479,7 @@ SoftReset ( StopRx (STOP_RX_CLEAR, Snp); // Clear receiver FIFO // Issue the reset - HwConf = MmioRead32 (LAN9118_HW_CFG); + HwConf = Lan9118MmioRead32 (LAN9118_HW_CFG); HwConf |= 1; // Set the Must Be One (MBO) bit @@ -445,16 +488,14 @@ SoftReset ( } // Check that EEPROM isn't active - while (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); + while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); // Write the configuration - MmioWrite32 (LAN9118_HW_CFG, HwConf); - MemoryFence(); + Lan9118MmioWrite32 (LAN9118_HW_CFG, HwConf); // Wait for reset to complete - while (MmioRead32 (LAN9118_HW_CFG) & HWCFG_SRST) { + while (Lan9118MmioRead32 (LAN9118_HW_CFG) & HWCFG_SRST) { - MemoryFence(); gBS->Stall (LAN9118_STALL); ResetTime += 1; @@ -466,15 +507,15 @@ SoftReset ( } // Check that EEPROM isn't active - while (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); + while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); // TODO we probably need to re-set the mac address here. // Clear and acknowledge all interrupts if (Flags & SOFT_RESET_CLEAR_INT) { - MmioWrite32 (LAN9118_INT_EN, 0); - MmioWrite32 (LAN9118_IRQ_CFG, 0); - MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF); + Lan9118MmioWrite32 (LAN9118_INT_EN, 0); + Lan9118MmioWrite32 (LAN9118_IRQ_CFG, 0); + Lan9118MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF); } // Do self tests here? @@ -497,13 +538,13 @@ PhySoftReset ( // PMT PHY reset takes precedence over BCR if (Flags & PHY_RESET_PMT) { - PmtCtrl = MmioRead32 (LAN9118_PMT_CTRL); + PmtCtrl = Lan9118MmioRead32 (LAN9118_PMT_CTRL); PmtCtrl |= MPTCTRL_PHY_RST; - MmioWrite32 (LAN9118_PMT_CTRL,PmtCtrl); + Lan9118MmioWrite32 (LAN9118_PMT_CTRL,PmtCtrl); // Wait for completion - while (MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_PHY_RST) { - MemoryFence(); + while (Lan9118MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_PHY_RST) { + gBS->Stall (LAN9118_STALL); } // PHY Basic Control Register reset } else if (Flags & PHY_RESET_BCR) { @@ -511,15 +552,15 @@ PhySoftReset ( // Wait for completion while (IndirectPHYRead32 (PHY_INDEX_BASIC_CTRL) & PHYCR_RESET) { - MemoryFence(); + gBS->Stall (LAN9118_STALL); } } // Clear and acknowledge all interrupts if (Flags & PHY_SOFT_RESET_CLEAR_INT) { - MmioWrite32 (LAN9118_INT_EN, 0); - MmioWrite32 (LAN9118_IRQ_CFG, 0); - MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF); + Lan9118MmioWrite32 (LAN9118_INT_EN, 0); + Lan9118MmioWrite32 (LAN9118_IRQ_CFG, 0); + Lan9118MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF); } return EFI_SUCCESS; @@ -537,15 +578,14 @@ ConfigureHardware ( // Check if we want to use LEDs on GPIO if (Flags & HW_CONF_USE_LEDS) { - GpioConf = MmioRead32 (LAN9118_GPIO_CFG); + GpioConf = Lan9118MmioRead32 (LAN9118_GPIO_CFG); // Enable GPIO as LEDs and Config as Push-Pull driver GpioConf |= GPIO_GPIO0_PUSH_PULL | GPIO_GPIO1_PUSH_PULL | GPIO_GPIO2_PUSH_PULL | GPIO_LED1_ENABLE | GPIO_LED2_ENABLE | GPIO_LED3_ENABLE; // Write the configuration - MmioWrite32 (LAN9118_GPIO_CFG, GpioConf); - MemoryFence(); + Lan9118MmioWrite32 (LAN9118_GPIO_CFG, GpioConf); } return EFI_SUCCESS; @@ -574,7 +614,7 @@ AutoNegotiate ( UINT32 PhyControl; UINT32 PhyStatus; UINT32 Features; - UINT32 TimeOut; + UINT32 Retries; // First check that auto-negotiation is supported PhyStatus = IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS); @@ -586,12 +626,11 @@ AutoNegotiate ( // Check that link is up first if ((PhyStatus & PHYSTS_LINK_STS) == 0) { // Wait until it is up or until Time Out - TimeOut = 2000; + Retries = FixedPcdGet32 (PcdLan9118DefaultNegotiationTimeout) / LAN9118_STALL; while ((IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS) & PHYSTS_LINK_STS) == 0) { - MemoryFence(); gBS->Stall (LAN9118_STALL); - TimeOut--; - if (!TimeOut) { + Retries--; + if (!Retries) { DEBUG ((EFI_D_ERROR, "Link timeout in auto-negotiation.\n")); return EFI_TIMEOUT; } @@ -609,6 +648,7 @@ AutoNegotiate ( Features &= ~(PHYANA_PAUSE_OP_MASK); Features |= 3 << 10; } + Features &= FixedPcdGet32 (PcdLan9118NegotiationFeatureMask); // Write the features IndirectPHYWrite32 (PHY_INDEX_AUTO_NEG_ADVERT, Features); @@ -672,10 +712,9 @@ StopTx ( // Check if we want to clear tx if (Flags & STOP_TX_CLEAR) { - TxCfg = MmioRead32 (LAN9118_TX_CFG); + TxCfg = Lan9118MmioRead32 (LAN9118_TX_CFG); TxCfg |= TXCFG_TXS_DUMP | TXCFG_TXD_DUMP; - MmioWrite32 (LAN9118_TX_CFG, TxCfg); - MemoryFence(); + Lan9118MmioWrite32 (LAN9118_TX_CFG, TxCfg); } // Check if already stopped @@ -689,15 +728,14 @@ StopTx ( } if (Flags & STOP_TX_CFG) { - TxCfg = MmioRead32 (LAN9118_TX_CFG); + TxCfg = Lan9118MmioRead32 (LAN9118_TX_CFG); if (TxCfg & TXCFG_TX_ON) { TxCfg |= TXCFG_STOP_TX; - MmioWrite32 (LAN9118_TX_CFG, TxCfg); - MemoryFence(); + Lan9118MmioWrite32 (LAN9118_TX_CFG, TxCfg); // Wait for Tx to finish transmitting - while (MmioRead32 (LAN9118_TX_CFG) & TXCFG_STOP_TX); + while (Lan9118MmioRead32 (LAN9118_TX_CFG) & TXCFG_STOP_TX); } } @@ -726,12 +764,11 @@ StopRx ( // Check if we want to clear receiver FIFOs if (Flags & STOP_RX_CLEAR) { - RxCfg = MmioRead32 (LAN9118_RX_CFG); + RxCfg = Lan9118MmioRead32 (LAN9118_RX_CFG); RxCfg |= RXCFG_RX_DUMP; - MmioWrite32 (LAN9118_RX_CFG, RxCfg); - MemoryFence(); + Lan9118MmioWrite32 (LAN9118_RX_CFG, RxCfg); - while (MmioRead32 (LAN9118_RX_CFG) & RXCFG_RX_DUMP); + while (Lan9118MmioRead32 (LAN9118_RX_CFG) & RXCFG_RX_DUMP); } return EFI_SUCCESS; @@ -752,31 +789,26 @@ StartTx ( // Check if we want to clear tx if (Flags & START_TX_CLEAR) { - TxCfg = MmioRead32 (LAN9118_TX_CFG); + TxCfg = Lan9118MmioRead32 (LAN9118_TX_CFG); TxCfg |= TXCFG_TXS_DUMP | TXCFG_TXD_DUMP; - MmioWrite32 (LAN9118_TX_CFG, TxCfg); - MemoryFence(); + Lan9118MmioWrite32 (LAN9118_TX_CFG, TxCfg); } // Check if tx was started from MAC and enable if not if (Flags & START_TX_MAC) { MacCsr = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR); - MemoryFence(); if ((MacCsr & MACCR_TX_EN) == 0) { MacCsr |= MACCR_TX_EN; IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr); - MemoryFence(); } } // Check if tx was started from TX_CFG and enable if not if (Flags & START_TX_CFG) { - TxCfg = MmioRead32 (LAN9118_TX_CFG); - MemoryFence(); + TxCfg = Lan9118MmioRead32 (LAN9118_TX_CFG); if ((TxCfg & TXCFG_TX_ON) == 0) { TxCfg |= TXCFG_TX_ON; - MmioWrite32 (LAN9118_TX_CFG, TxCfg); - MemoryFence(); + Lan9118MmioWrite32 (LAN9118_TX_CFG, TxCfg); } } @@ -803,17 +835,15 @@ StartRx ( if ((MacCsr & MACCR_RX_EN) == 0) { // Check if we want to clear receiver FIFOs before starting if (Flags & START_RX_CLEAR) { - RxCfg = MmioRead32 (LAN9118_RX_CFG); + RxCfg = Lan9118MmioRead32 (LAN9118_RX_CFG); RxCfg |= RXCFG_RX_DUMP; - MmioWrite32 (LAN9118_RX_CFG, RxCfg); - MemoryFence(); + Lan9118MmioWrite32 (LAN9118_RX_CFG, RxCfg); - while (MmioRead32 (LAN9118_RX_CFG) & RXCFG_RX_DUMP); + while (Lan9118MmioRead32 (LAN9118_RX_CFG) & RXCFG_RX_DUMP); } MacCsr |= MACCR_RX_EN; IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr); - MemoryFence(); } return EFI_SUCCESS; @@ -830,7 +860,7 @@ TxDataFreeSpace ( UINT32 FreeSpace; // Get the amount of free space from information register - TxInf = MmioRead32 (LAN9118_TX_FIFO_INF); + TxInf = Lan9118MmioRead32 (LAN9118_TX_FIFO_INF); FreeSpace = (TxInf & TXFIFOINF_TDFREE_MASK); return FreeSpace; // Value in bytes @@ -847,7 +877,7 @@ TxStatusUsedSpace ( UINT32 UsedSpace; // Get the amount of used space from information register - TxInf = MmioRead32 (LAN9118_TX_FIFO_INF); + TxInf = Lan9118MmioRead32 (LAN9118_TX_FIFO_INF); UsedSpace = (TxInf & TXFIFOINF_TXSUSED_MASK) >> 16; return UsedSpace << 2; // Value in bytes @@ -864,7 +894,7 @@ RxDataUsedSpace ( UINT32 UsedSpace; // Get the amount of used space from information register - RxInf = MmioRead32 (LAN9118_RX_FIFO_INF); + RxInf = Lan9118MmioRead32 (LAN9118_RX_FIFO_INF); UsedSpace = (RxInf & RXFIFOINF_RXDUSED_MASK); return UsedSpace; // Value in bytes (rounded up to nearest DWORD) @@ -881,7 +911,7 @@ RxStatusUsedSpace ( UINT32 UsedSpace; // Get the amount of used space from information register - RxInf = MmioRead32 (LAN9118_RX_FIFO_INF); + RxInf = Lan9118MmioRead32 (LAN9118_RX_FIFO_INF); UsedSpace = (RxInf & RXFIFOINF_RXSUSED_MASK) >> 16; return UsedSpace << 2; // Value in bytes @@ -919,7 +949,7 @@ ChangeFifoAllocation ( // If we use the FIFOs (always use this first) if (Flags & ALLOC_USE_FIFOS) { // Read the current value of allocation - HwConf = MmioRead32 (LAN9118_HW_CFG); + HwConf = Lan9118MmioRead32 (LAN9118_HW_CFG); TxFifoOption = (HwConf >> 16) & 0xF; // Choose the correct size (always use larger than requested if possible) @@ -1002,8 +1032,7 @@ ChangeFifoAllocation ( // Clear and assign the new size option HwConf &= ~(0xF0000); HwConf |= ((TxFifoOption & 0xF) << 16); - MmioWrite32 (LAN9118_HW_CFG, HwConf); - MemoryFence(); + Lan9118MmioWrite32 (LAN9118_HW_CFG, HwConf); return EFI_SUCCESS; }