diff mbox

[edk2,2/4] EmbeddedPkg/Lan9118Dxe: add LAN9118 MMIO wrappers

Message ID 1462555149-18136-3-git-send-email-mark.rutland@arm.com
State Accepted
Commit 73683a2464e2f81b7b9dfb9b84b537290235bbe1
Headers show

Commit Message

Mark Rutland May 6, 2016, 5:19 p.m. UTC
As described in the LAN9118 datasheet, delays are necessary after some
reads and writes in order to ensure subsequent reads do not see stale
data.

This patch adds helpers to provide these delays automatically, by
performing dummy reads of the BYTE_TEST register (as recommended in the
LAN9118 datasheet). This approach allows the device register file itself
to provide the required delay, avoiding issues with early write
acknowledgement, or re-ordering of MMIO accesses aganist other
instructions (e.g. the delay loop).

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Ryan Harkin <ryan.harkin@linaro.org>
Signed-off-by: Mark Rutland <mark.rutland@arm.com>

Contributed-under: TianoCore Contribution Agreement 1.0
---
 EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeHw.h   | 71 +++++++++++++++++++++++++
 EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.c | 48 +++++++++++++++++
 EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.h | 17 ++++++
 3 files changed, 136 insertions(+)

-- 
1.9.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
diff mbox

Patch

diff --git a/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeHw.h b/EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeHw.h
index 9e89d27..1189584 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 bd20eeb..002ea20 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 424bdc5..1a9a940 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