diff --git a/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeHw.h b/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeHw.h index 9e89d27459..11895849a4 100644 --- a/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeHw.h +++ b/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeHw.h @@ -57,6 +57,77 @@ #define LAN9118_E2P_CMD (0x000000B0 + LAN9118_BA) // EEPROM Command #define LAN9118_E2P_DATA (0x000000B4 + LAN9118_BA) // EEPROM Data +/* + * Required delays following write cycles (number of BYTE_TEST reads) + * Taken from Table 6.1 in Revision 1.5 (07-11-08) of the LAN9118 datasheet. + * Where no delay listed, 0 has been assumed. + */ +#define LAN9118_RX_DATA_WR_DELAY 0 +#define LAN9118_RX_STATUS_WR_DELAY 0 +#define LAN9118_RX_STATUS_PEEK_WR_DELAY 0 +#define LAN9118_TX_DATA_WR_DELAY 0 +#define LAN9118_TX_STATUS_WR_DELAY 0 +#define LAN9118_TX_STATUS_PEEK_WR_DELAY 0 +#define LAN9118_ID_REV_WR_DELAY 0 +#define LAN9118_IRQ_CFG_WR_DELAY 3 +#define LAN9118_INT_STS_WR_DELAY 2 +#define LAN9118_INT_EN_WR_DELAY 1 +#define LAN9118_BYTE_TEST_WR_DELAY 0 +#define LAN9118_FIFO_INT_WR_DELAY 1 +#define LAN9118_RX_CFG_WR_DELAY 1 +#define LAN9118_TX_CFG_WR_DELAY 1 +#define LAN9118_HW_CFG_WR_DELAY 1 +#define LAN9118_RX_DP_CTL_WR_DELAY 1 +#define LAN9118_RX_FIFO_INF_WR_DELAY 0 +#define LAN9118_TX_FIFO_INF_WR_DELAY 3 +#define LAN9118_PMT_CTRL_WR_DELAY 7 +#define LAN9118_GPIO_CFG_WR_DELAY 1 +#define LAN9118_GPT_CFG_WR_DELAY 1 +#define LAN9118_GPT_CNT_WR_DELAY 3 +#define LAN9118_WORD_SWAP_WR_DELAY 1 +#define LAN9118_FREE_RUN_WR_DELAY 4 +#define LAN9118_RX_DROP_WR_DELAY 0 +#define LAN9118_MAC_CSR_CMD_WR_DELAY 1 +#define LAN9118_MAC_CSR_DATA_WR_DELAY 1 +#define LAN9118_AFC_CFG_WR_DELAY 1 +#define LAN9118_E2P_CMD_WR_DELAY 1 +#define LAN9118_E2P_DATA_WR_DELAY 1 + +/* + * Required delays following read cycles (number of BYTE_TEST reads) + * Taken from Table 6.2 in Revision 1.5 (07-11-08) of the LAN9118 datasheet. + * Where no delay listed, 0 has been assumed. + */ +#define LAN9118_RX_DATA_RD_DELAY 3 +#define LAN9118_RX_STATUS_RD_DELAY 3 +#define LAN9118_RX_STATUS_PEEK_RD_DELAY 0 +#define LAN9118_TX_DATA_RD_DELAY 0 +#define LAN9118_TX_STATUS_RD_DELAY 3 +#define LAN9118_TX_STATUS_PEEK_RD_DELAY 0 +#define LAN9118_ID_REV_RD_DELAY 0 +#define LAN9118_IRQ_CFG_RD_DELAY 0 +#define LAN9118_INT_STS_RD_DELAY 0 +#define LAN9118_INT_EN_RD_DELAY 0 +#define LAN9118_BYTE_TEST_RD_DELAY 0 +#define LAN9118_FIFO_INT_RD_DELAY 0 +#define LAN9118_RX_CFG_RD_DELAY 0 +#define LAN9118_TX_CFG_RD_DELAY 0 +#define LAN9118_HW_CFG_RD_DELAY 0 +#define LAN9118_RX_DP_CTL_RD_DELAY 0 +#define LAN9118_RX_FIFO_INF_RD_DELAY 0 +#define LAN9118_TX_FIFO_INF_RD_DELAY 0 +#define LAN9118_PMT_CTRL_RD_DELAY 0 +#define LAN9118_GPIO_CFG_RD_DELAY 0 +#define LAN9118_GPT_CFG_RD_DELAY 0 +#define LAN9118_GPT_CNT_RD_DELAY 0 +#define LAN9118_WORD_SWAP_RD_DELAY 0 +#define LAN9118_FREE_RUN_RD_DELAY 0 +#define LAN9118_RX_DROP_RD_DELAY 4 +#define LAN9118_MAC_CSR_CMD_RD_DELAY 0 +#define LAN9118_MAC_CSR_DATA_RD_DELAY 0 +#define LAN9118_AFC_CFG_RD_DELAY 0 +#define LAN9118_E2P_CMD_RD_DELAY 0 +#define LAN9118_E2P_DATA_RD_DELAY 0 // Receiver Status bits #define RXSTATUS_CRC_ERROR BIT1 // Cyclic Redundancy Check Error diff --git a/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.c b/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.c index bd20eebd04..002ea203ae 100644 --- a/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.c +++ b/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.c @@ -115,6 +115,54 @@ IndirectMACRead32 ( return MmioRead32 (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 UINT32 IndirectMACWrite32 ( diff --git a/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.h b/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.h index 424bdc5a85..1a9a940082 100644 --- a/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.h +++ b/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.h @@ -38,6 +38,23 @@ GenEtherCrc32 ( IN UINT32 AddrLen ); +UINT32 +Lan9118RawMmioRead32( + UINTN Address, + UINTN Delay + ); +#define Lan9118MmioRead32(a) \ + Lan9118RawMmioRead32(a, a ## _RD_DELAY) + +UINT32 +Lan9118RawMmioWrite32( + UINTN Address, + UINT32 Value, + UINTN Delay + ); +#define Lan9118MmioWrite32(a, v) \ + Lan9118RawMmioWrite32(a, v, a ## _WR_DELAY) + /* ------------------ MAC CSR Access ------------------- */ // Read from MAC indirect registers