From patchwork Fri May 6 17:19:07 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Rutland X-Patchwork-Id: 67287 Delivered-To: patch@linaro.org Received: by 10.140.92.199 with SMTP id b65csp428842qge; Fri, 6 May 2016 10:19:34 -0700 (PDT) X-Received: by 10.66.1.99 with SMTP id 3mr29679773pal.26.1462555173363; Fri, 06 May 2016 10:19:33 -0700 (PDT) Return-Path: Received: from ml01.01.org (ml01.01.org. [2001:19d0:306:5::1]) by mx.google.com with ESMTPS id to9si19373809pab.69.2016.05.06.10.19.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 06 May 2016 10:19:33 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 as permitted sender) client-ip=2001:19d0:306:5::1; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id D52531A1F33; Fri, 6 May 2016 10:19:32 -0700 (PDT) X-Original-To: edk2-devel@lists.01.org Delivered-To: edk2-devel@lists.01.org Received: from foss.arm.com (foss.arm.com [217.140.101.70]) by ml01.01.org (Postfix) with ESMTP id 406671A1F33 for ; Fri, 6 May 2016 10:19:31 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 60F9D49; Fri, 6 May 2016 10:19:39 -0700 (PDT) Received: from leverpostej.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 403A63F246; Fri, 6 May 2016 10:19:30 -0700 (PDT) From: Mark Rutland To: edk2-devel@lists.01.org Date: Fri, 6 May 2016 18:19:07 +0100 Message-Id: <1462555149-18136-3-git-send-email-mark.rutland@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1462555149-18136-1-git-send-email-mark.rutland@arm.com> References: <1462555149-18136-1-git-send-email-mark.rutland@arm.com> Subject: [edk2] [PATCH 2/4] EmbeddedPkg/Lan9118Dxe: add LAN9118 MMIO wrappers X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: ryan.harkin@linaro.org, leif.lindholm@linaro.org, ard.biesheuvel@linaro.org MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" 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 Cc: Leif Lindholm Cc: Ryan Harkin Signed-off-by: Mark Rutland 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 --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