From: Pete Batard <pete@akeo.ie>
To: edk2-devel@lists.01.org
Subject: [PATCH v2 edk2-platforms 12/20] Platform/Broadcom/RPi3: Add SD Host driver
Date: Mon, 10 Dec 2018 12:38:45 +0000 [thread overview]
Message-ID: <20181210123853.4864-13-pete@akeo.ie> (raw)
In-Reply-To: <20181210123853.4864-1-pete@akeo.ie>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Pete Batard <pete@akeo.ie>
---
Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.c | 830 ++++++++++++++++++++
Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.inf | 54 ++
Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836SdHost.h | 92 +++
3 files changed, 976 insertions(+)
diff --git a/Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.c b/Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.c
new file mode 100644
index 000000000000..7dd76098c8a1
--- /dev/null
+++ b/Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.c
@@ -0,0 +1,830 @@
+/** @file
+ *
+ * Copyright (c) 2017, Andrei Warkentin <andrey.warkentin@gmail.com>
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ * This program and the accompanying materials
+ * are licensed and made available under the terms and conditions of the BSD License
+ * which accompanies this distribution. The full text of the license may be found at
+ * http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ *
+ **/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DmaLib.h>
+#include <Library/TimerLib.h>
+
+#include <Protocol/EmbeddedExternalDevice.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PiMmcHost.h>
+#include <Protocol/RaspberryPiFirmware.h>
+
+#include <IndustryStandard/Bcm2836.h>
+#include <IndustryStandard/RpiFirmware.h>
+#include <IndustryStandard/Bcm2836SdHost.h>
+
+#define SDHOST_BLOCK_BYTE_LENGTH 512
+
+// Driver Timing Parameters
+#define CMD_STALL_AFTER_POLL_US 1
+#define CMD_MIN_POLL_TOTAL_TIME_US 100000 // 100ms
+#define CMD_MAX_POLL_COUNT (CMD_MIN_POLL_TOTAL_TIME_US / CMD_STALL_AFTER_POLL_US)
+#define CMD_MAX_RETRY_COUNT 3
+#define CMD_STALL_AFTER_RETRY_US 20 // 20us
+#define FIFO_MAX_POLL_COUNT 1000000
+#define STALL_TO_STABILIZE_US 10000 // 10ms
+
+#define IDENT_MODE_SD_CLOCK_FREQ_HZ 400000 // 400KHz
+
+// Macros adopted from MmcDxe internal header
+#define SDHOST_R0_READY_FOR_DATA BIT8
+#define SDHOST_R0_CURRENTSTATE(Response) ((Response >> 9) & 0xF)
+
+#define DEBUG_MMCHOST_SD DEBUG_VERBOSE
+#define DEBUG_MMCHOST_SD_INFO DEBUG_INFO
+#define DEBUG_MMCHOST_SD_ERROR DEBUG_ERROR
+
+STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol;
+
+// Per Physical Layer Simplified Specs
+#ifndef NDEBUG
+STATIC CONST CHAR8* mStrSdState[] = { "idle", "ready", "ident", "stby",
+ "tran", "data", "rcv", "prg", "dis",
+ "ina" };
+STATIC CONST CHAR8 *mFsmState[] = { "identmode", "datamode", "readdata",
+ "writedata", "readwait", "readcrc",
+ "writecrc", "writewait1", "powerdown",
+ "powerup", "writestart1", "writestart2",
+ "genpulses", "writewait2", "?",
+ "startpowdown" };
+#endif /* NDEBUG */
+STATIC UINT32 mLastGoodCmd = MMC_GET_INDX(MMC_CMD0);
+
+STATIC inline BOOLEAN
+IsAppCmd(
+ VOID
+ )
+{
+ return mLastGoodCmd == MMC_CMD55;
+}
+
+STATIC BOOLEAN
+IsBusyCmd(
+ IN UINT32 MmcCmd
+ )
+{
+ if (IsAppCmd()) {
+ return FALSE;
+ }
+
+ return MmcCmd == MMC_CMD7 || MmcCmd == MMC_CMD12;
+}
+
+STATIC BOOLEAN
+IsWriteCmd(
+ IN UINT32 MmcCmd
+ )
+{
+ if (IsAppCmd()) {
+ return FALSE;
+ }
+
+ return MmcCmd == MMC_CMD24 || MmcCmd == MMC_CMD25;
+}
+
+STATIC BOOLEAN
+IsReadCmd(
+ IN UINT32 MmcCmd,
+ IN UINT32 Argument
+ )
+{
+ if (MmcCmd == MMC_CMD8 && !IsAppCmd()) {
+ if (Argument == CMD8_MMC_ARG) {
+ DEBUG((DEBUG_MMCHOST_SD, "Sending MMC CMD8 variant\n"));
+ return TRUE;
+ } else {
+ ASSERT (Argument == CMD8_SD_ARG);
+ DEBUG((DEBUG_MMCHOST_SD, "Sending SD CMD8 variant\n"));
+ return FALSE;
+ }
+ }
+
+ return
+ (MmcCmd == MMC_CMD6 && !IsAppCmd()) ||
+ (MmcCmd == MMC_CMD17 && !IsAppCmd()) ||
+ (MmcCmd == MMC_CMD18 && !IsAppCmd()) ||
+ (MmcCmd == MMC_CMD13 && IsAppCmd()) ||
+ (MmcCmd == MMC_ACMD22 && IsAppCmd()) ||
+ (MmcCmd == MMC_ACMD51 && IsAppCmd());
+}
+
+STATIC VOID
+SdHostDumpRegisters(
+ VOID
+ )
+{
+ DEBUG((DEBUG_MMCHOST_SD, "SdHost: Registers Dump:\n"));
+ DEBUG((DEBUG_MMCHOST_SD, " CMD: 0x%8.8X\n", MmioRead32(SDHOST_CMD)));
+ DEBUG((DEBUG_MMCHOST_SD, " ARG: 0x%8.8X\n", MmioRead32(SDHOST_ARG)));
+ DEBUG((DEBUG_MMCHOST_SD, " TOUT: 0x%8.8X\n", MmioRead32(SDHOST_TOUT)));
+ DEBUG((DEBUG_MMCHOST_SD, " CDIV: 0x%8.8X\n", MmioRead32(SDHOST_CDIV)));
+ DEBUG((DEBUG_MMCHOST_SD, " RSP0: 0x%8.8X\n", MmioRead32(SDHOST_RSP0)));
+ DEBUG((DEBUG_MMCHOST_SD, " RSP1: 0x%8.8X\n", MmioRead32(SDHOST_RSP1)));
+ DEBUG((DEBUG_MMCHOST_SD, " RSP2: 0x%8.8X\n", MmioRead32(SDHOST_RSP2)));
+ DEBUG((DEBUG_MMCHOST_SD, " RSP3: 0x%8.8X\n", MmioRead32(SDHOST_RSP3)));
+ DEBUG((DEBUG_MMCHOST_SD, " HSTS: 0x%8.8X\n", MmioRead32(SDHOST_HSTS)));
+ DEBUG((DEBUG_MMCHOST_SD, " VDD: 0x%8.8X\n", MmioRead32(SDHOST_VDD)));
+ DEBUG((DEBUG_MMCHOST_SD, " EDM: 0x%8.8X\n", MmioRead32(SDHOST_EDM)));
+ DEBUG((DEBUG_MMCHOST_SD, " HCFG: 0x%8.8X\n", MmioRead32(SDHOST_HCFG)));
+ DEBUG((DEBUG_MMCHOST_SD, " HBCT: 0x%8.8X\n", MmioRead32(SDHOST_HBCT)));
+ DEBUG((DEBUG_MMCHOST_SD, " HBLC: 0x%8.8X\n\n", MmioRead32(SDHOST_HBLC)));
+}
+
+#ifndef NDEBUG
+STATIC EFI_STATUS
+SdHostGetSdStatus(
+ UINT32* SdStatus
+ )
+{
+ ASSERT(SdStatus != NULL);
+
+ // On command completion with R1 or R1b response type
+ // the SDCard status will be in RSP0
+ UINT32 Rsp0 = MmioRead32(SDHOST_RSP0);
+ if (Rsp0 != 0xFFFFFFFF) {
+ *SdStatus = Rsp0;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NO_RESPONSE;
+}
+#endif /* NDEBUG */
+
+STATIC VOID
+SdHostDumpSdCardStatus(
+ VOID
+ )
+{
+#ifndef NDEBUG
+ UINT32 SdCardStatus;
+ EFI_STATUS Status = SdHostGetSdStatus(&SdCardStatus);
+ if (!EFI_ERROR(Status)) {
+ UINT32 CurrState = SDHOST_R0_CURRENTSTATE(SdCardStatus);
+ DEBUG((
+ DEBUG_MMCHOST_SD,
+ "SdHost: SdCardStatus 0x%8.8X: ReadyForData?%d, State[%d]: %a\n",
+ SdCardStatus,
+ ((SdCardStatus & SDHOST_R0_READY_FOR_DATA) ? 1 : 0),
+ CurrState,
+ ((CurrState < (sizeof(mStrSdState) / sizeof(*mStrSdState))) ?
+ mStrSdState[CurrState] : "UNDEF")));
+ }
+#endif /* NDEBUG */
+}
+
+STATIC VOID
+SdHostDumpStatus(
+ VOID
+ )
+{
+ SdHostDumpRegisters();
+
+#ifndef NDEBUG
+ UINT32 Hsts = MmioRead32(SDHOST_HSTS);
+
+ if (Hsts & SDHOST_HSTS_ERROR) {
+ DEBUG((DEBUG_MMCHOST_SD_ERROR,
+ "SdHost: Diagnose HSTS: 0x%8.8X\n", Hsts));
+
+ DEBUG((DEBUG_MMCHOST_SD_ERROR, "SdHost: Last Good CMD = %u\n",
+ MMC_GET_INDX(mLastGoodCmd)));
+ if (Hsts & SDHOST_HSTS_FIFO_ERROR)
+ DEBUG((DEBUG_MMCHOST_SD_ERROR, " - Fifo Error\n"));
+ if (Hsts & SDHOST_HSTS_CRC7_ERROR)
+ DEBUG((DEBUG_MMCHOST_SD_ERROR, " - CRC7 Error\n"));
+ if (Hsts & SDHOST_HSTS_CRC16_ERROR)
+ DEBUG((DEBUG_MMCHOST_SD_ERROR, " - CRC16 Error\n"));
+ if (Hsts & SDHOST_HSTS_CMD_TIME_OUT)
+ DEBUG((DEBUG_MMCHOST_SD_ERROR, " - CMD Timeout (TOUT %x)\n",
+ MmioRead32(SDHOST_TOUT)));
+ if (Hsts & SDHOST_HSTS_REW_TIME_OUT)
+ DEBUG((DEBUG_MMCHOST_SD_ERROR, " - Read/Erase/Write Transfer Timeout\n"));
+ }
+
+ UINT32 Edm = MmioRead32(SDHOST_EDM);
+ DEBUG(((Hsts & SDHOST_HSTS_ERROR) ?
+ DEBUG_MMCHOST_SD_ERROR : DEBUG_MMCHOST_SD,
+ "SdHost: Diagnose EDM: 0x%8.8X\n", Edm));
+ DEBUG(((Hsts & SDHOST_HSTS_ERROR) ?
+ DEBUG_MMCHOST_SD_ERROR : DEBUG_MMCHOST_SD,
+ " - FSM: 0x%x (%a)\n", (Edm & 0xF), mFsmState[Edm & 0xF]));
+ DEBUG(((Hsts & SDHOST_HSTS_ERROR) ?
+ DEBUG_MMCHOST_SD_ERROR : DEBUG_MMCHOST_SD,
+ " - Fifo Count: %d\n", ((Edm >> 4) & 0x1F)));
+ DEBUG(((Hsts & SDHOST_HSTS_ERROR) ?
+ DEBUG_MMCHOST_SD_ERROR : DEBUG_MMCHOST_SD,
+ " - Fifo Write Threshold: %d\n",
+ ((Edm >> SDHOST_EDM_WRITE_THRESHOLD_SHIFT) &
+ SDHOST_EDM_THRESHOLD_MASK)));
+ DEBUG(((Hsts & SDHOST_HSTS_ERROR) ?
+ DEBUG_MMCHOST_SD_ERROR : DEBUG_MMCHOST_SD,
+ " - Fifo Read Threshold: %d\n",
+ ((Edm >> SDHOST_EDM_READ_THRESHOLD_SHIFT) & SDHOST_EDM_THRESHOLD_MASK)));
+#endif
+
+ SdHostDumpSdCardStatus();
+}
+
+STATIC EFI_STATUS
+SdHostSetClockFrequency(
+ IN UINTN TargetSdFreqHz
+ )
+{
+ EFI_STATUS Status;
+ UINT32 CoreClockFreqHz = 0;
+
+ // First figure out the core clock
+ Status = mFwProtocol->GetClockRate(RPI_FW_CLOCK_RATE_CORE, &CoreClockFreqHz);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ ASSERT (CoreClockFreqHz != 0);
+
+ // fSDCLK = fcore_pclk/(ClockDiv+2)
+ UINT32 ClockDiv = (CoreClockFreqHz - (2 * TargetSdFreqHz)) / TargetSdFreqHz;
+ UINT32 ActualSdFreqHz = CoreClockFreqHz / (ClockDiv + 2);
+
+ DEBUG((
+ DEBUG_MMCHOST_SD_INFO,
+ "SdHost: CoreClock=%dHz, CDIV=%d, Requested SdClock=%dHz, Actual SdClock=%dHz\n",
+ CoreClockFreqHz,
+ ClockDiv,
+ TargetSdFreqHz,
+ ActualSdFreqHz));
+
+ MmioWrite32(SDHOST_CDIV, ClockDiv);
+ // Set timeout after 1 second, i.e ActualSdFreqHz SD clock cycles
+ MmioWrite32(SDHOST_TOUT, ActualSdFreqHz);
+
+ gBS->Stall(STALL_TO_STABILIZE_US);
+
+ return Status;
+}
+
+STATIC BOOLEAN
+SdIsCardPresent(
+ IN EFI_MMC_HOST_PROTOCOL *This
+ )
+{
+ return TRUE;
+}
+
+STATIC BOOLEAN
+SdIsReadOnly(
+ IN EFI_MMC_HOST_PROTOCOL *This
+ )
+{
+ return FALSE;
+}
+
+STATIC EFI_STATUS
+SdBuildDevicePath(
+ IN EFI_MMC_HOST_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
+ EFI_GUID DevicePathGuid = EFI_CALLER_ID_GUID;
+
+ DEBUG((DEBUG_MMCHOST_SD, "SdHost: SdBuildDevicePath()\n"));
+
+ NewDevicePathNode = CreateDeviceNode(HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof(VENDOR_DEVICE_PATH));
+ CopyGuid(&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &DevicePathGuid);
+ *DevicePath = NewDevicePathNode;
+
+ return EFI_SUCCESS;
+}
+
+STATIC EFI_STATUS
+SdSendCommand(
+ IN EFI_MMC_HOST_PROTOCOL *This,
+ IN MMC_CMD MmcCmd,
+ IN UINT32 Argument
+ )
+{
+ UINT32 Hsts;
+
+ //
+ // Fail fast, CMD5 (CMD_IO_SEND_OP_COND)
+ // is only valid for SDIO cards and thus
+ // expected to always fail.
+ //
+ if (MmcCmd == MMC_CMD5) {
+ DEBUG((
+ DEBUG_MMCHOST_SD,
+ "SdHost: SdSendCommand(CMD%d, Argument: %08x) ignored\n",
+ MMC_GET_INDX(MmcCmd),
+ Argument));
+ return EFI_UNSUPPORTED;
+ }
+
+ if (MmioRead32(SDHOST_CMD) & SDHOST_CMD_NEW_FLAG) {
+ DEBUG((
+ DEBUG_MMCHOST_SD_ERROR,
+ "SdHost: SdSendCommand(): Failed to execute CMD%d, a CMD is already being executed.\n",
+ MMC_GET_INDX(MmcCmd)));
+ SdHostDumpStatus();
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Write command argument
+ MmioWrite32(SDHOST_ARG, Argument);
+
+ UINT32 SdCmd = 0;
+ {
+ // Set response type
+ if (MmcCmd & MMC_CMD_WAIT_RESPONSE) {
+ if (MmcCmd & MMC_CMD_LONG_RESPONSE) {
+ SdCmd |= SDHOST_CMD_RESPONSE_CMD_LONG_RESP;
+ }
+ } else {
+ SdCmd |= SDHOST_CMD_RESPONSE_CMD_NO_RESP;
+ }
+
+ if (IsBusyCmd(MmcCmd)) {
+ SdCmd |= SDHOST_CMD_BUSY_CMD;
+ }
+
+ if (IsReadCmd(MmcCmd, Argument)) {
+ SdCmd |= SDHOST_CMD_READ_CMD;
+ }
+
+ if (IsWriteCmd(MmcCmd)) {
+ SdCmd |= SDHOST_CMD_WRITE_CMD;
+ }
+
+ SdCmd |= MMC_GET_INDX(MmcCmd);
+ }
+
+ if (IsReadCmd(MmcCmd, Argument) || IsWriteCmd(MmcCmd)) {
+ if (IsAppCmd() && MmcCmd == MMC_ACMD22) {
+ MmioWrite32(SDHOST_HBCT, 0x4);
+ } else if (IsAppCmd() && MmcCmd == MMC_ACMD51) {
+ MmioWrite32(SDHOST_HBCT, 0x8);
+ } else if (!IsAppCmd() && MmcCmd == MMC_CMD6) {
+ MmioWrite32(SDHOST_HBCT, 0x40);
+ } else {
+ MmioWrite32(SDHOST_HBCT, SDHOST_BLOCK_BYTE_LENGTH);
+ }
+ }
+
+ DEBUG((
+ DEBUG_MMCHOST_SD,
+ "SdHost: SdSendCommand(CMD%d, Argument: %08x): BUSY=%d, RESP=%d, WRITE=%d, READ=%d\n",
+ MMC_GET_INDX(MmcCmd),
+ Argument,
+ ((SdCmd & SDHOST_CMD_BUSY_CMD) ? 1 : 0),
+ ((SdCmd & (SDHOST_CMD_RESPONSE_CMD_LONG_RESP | SDHOST_CMD_RESPONSE_CMD_NO_RESP)) >> 9),
+ ((SdCmd & SDHOST_CMD_WRITE_CMD) ? 1 : 0),
+ ((SdCmd & SDHOST_CMD_READ_CMD) ? 1 : 0)));
+
+ UINT32 PollCount = 0;
+ UINT32 RetryCount = 0;
+ BOOLEAN IsCmdExecuted = FALSE;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ // Keep retrying the command until it succeeds.
+ while ((RetryCount < CMD_MAX_RETRY_COUNT) && !IsCmdExecuted) {
+ Status = EFI_SUCCESS;
+
+ // Clear prev cmd status
+ MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_CLEAR);
+
+ if (IsReadCmd(MmcCmd, Argument) || IsWriteCmd(MmcCmd)) {
+ // Flush Fifo if this cmd will start a new transfer in case
+ // there is stale bytes in the Fifo
+ MmioOr32(SDHOST_EDM, SDHOST_EDM_FIFO_CLEAR);
+ }
+
+ if (MmioRead32(SDHOST_CMD) & SDHOST_CMD_NEW_FLAG) {
+ DEBUG((
+ DEBUG_MMCHOST_SD_ERROR,
+ "%a(%u): CMD%d is still being executed after %d trial(s)\n",
+ __FUNCTION__, __LINE__, MMC_GET_INDX(MmcCmd), RetryCount));
+ }
+
+ // Write command and set it to start execution
+ MmioWrite32(SDHOST_CMD, SDHOST_CMD_NEW_FLAG | SdCmd);
+
+ // Poll for the command status until it finishes execution
+ while (PollCount < CMD_MAX_POLL_COUNT) {
+ UINT32 CmdReg = MmioRead32(SDHOST_CMD);
+
+ // Read status of command response
+ if (CmdReg & SDHOST_CMD_FAIL_FLAG) {
+ Status = EFI_DEVICE_ERROR;
+ /*
+ * Must fall-through and wait for the command completion!
+ */
+ }
+
+ // Check if command is completed.
+ if (!(CmdReg & SDHOST_CMD_NEW_FLAG)) {
+ IsCmdExecuted = TRUE;
+ break;
+ }
+
+ ++PollCount;
+ gBS->Stall(CMD_STALL_AFTER_POLL_US);
+ }
+
+ if (!IsCmdExecuted) {
+ ++RetryCount;
+ gBS->Stall(CMD_STALL_AFTER_RETRY_US);
+ }
+ }
+
+ if (RetryCount == CMD_MAX_RETRY_COUNT) {
+ Status = EFI_TIMEOUT;
+ }
+
+ Hsts = MmioRead32(SDHOST_HSTS);
+ if (EFI_ERROR(Status) ||
+ (Hsts & SDHOST_HSTS_ERROR) != 0) {
+ if (MmcCmd == MMC_CMD1 &&
+ (Hsts & SDHOST_HSTS_CRC7_ERROR) != 0) {
+ /*
+ * SdHost seems to have no way to specify
+ * R3 as a transfer type.
+ */
+ IsCmdExecuted = TRUE;
+ Status = EFI_SUCCESS;
+ MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_CLEAR);
+ } else if (MmcCmd == MMC_CMD7 && Argument == 0) {
+ /*
+ * Deselecting the SDCard with CMD7 and RCA=0x0
+ * always timeout on SDHost.
+ */
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG((
+ DEBUG_MMCHOST_SD_ERROR,
+ "%a(%u): CMD%d execution failed after %d trial(s)\n",
+ __FUNCTION__, __LINE__,
+ MMC_GET_INDX(MmcCmd),
+ RetryCount));
+ SdHostDumpStatus();
+ }
+
+ MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_CLEAR);
+ }
+
+ if (IsCmdExecuted && !EFI_ERROR(Status)) {
+ ASSERT(!(MmioRead32(SDHOST_HSTS) & SDHOST_HSTS_ERROR));
+ mLastGoodCmd = MmcCmd;
+ }
+
+ return Status;
+}
+
+STATIC EFI_STATUS
+SdReceiveResponse(
+ IN EFI_MMC_HOST_PROTOCOL *This,
+ IN MMC_RESPONSE_TYPE Type,
+ IN UINT32* Buffer
+ )
+{
+ if (Buffer == NULL) {
+ DEBUG((DEBUG_MMCHOST_SD_ERROR,
+ "SdHost: SdReceiveResponse(): Input Buffer is NULL\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Type == MMC_RESPONSE_TYPE_R1) ||
+ (Type == MMC_RESPONSE_TYPE_R1b) ||
+ (Type == MMC_RESPONSE_TYPE_R3) ||
+ (Type == MMC_RESPONSE_TYPE_R6) ||
+ (Type == MMC_RESPONSE_TYPE_R7)) {
+ Buffer[0] = MmioRead32(SDHOST_RSP0);
+ DEBUG((
+ DEBUG_MMCHOST_SD,
+ "SdHost: SdReceiveResponse(Type: %x), Buffer[0]: %08x\n",
+ Type, Buffer[0]));
+
+ } else if (Type == MMC_RESPONSE_TYPE_R2) {
+ Buffer[0] = MmioRead32(SDHOST_RSP0);
+ Buffer[1] = MmioRead32(SDHOST_RSP1);
+ Buffer[2] = MmioRead32(SDHOST_RSP2);
+ Buffer[3] = MmioRead32(SDHOST_RSP3);
+
+ DEBUG((
+ DEBUG_MMCHOST_SD,
+ "SdHost: SdReceiveResponse(Type: %x), Buffer[0-3]: %08x, %08x, %08x, %08x\n",
+ Type, Buffer[0], Buffer[1], Buffer[2], Buffer[3]));
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC EFI_STATUS
+SdReadBlockData(
+ IN EFI_MMC_HOST_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Length,
+ IN UINT32* Buffer
+ )
+{
+ DEBUG((
+ DEBUG_MMCHOST_SD,
+ "SdHost: SdReadBlockData(LBA: 0x%x, Length: 0x%x, Buffer: 0x%x)\n",
+ (UINT32)Lba, Length, Buffer));
+
+ ASSERT(Buffer != NULL);
+ ASSERT(Length % 4 == 0);
+
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ mFwProtocol->SetLed(TRUE);
+ {
+ UINT32 NumWords = Length / 4;
+ UINT32 WordIdx;
+
+ for (WordIdx = 0; WordIdx < NumWords; ++WordIdx) {
+ UINT32 PollCount = 0;
+ while (PollCount < FIFO_MAX_POLL_COUNT) {
+ UINT32 Hsts = MmioRead32(SDHOST_HSTS);
+ if ((Hsts & SDHOST_HSTS_DATA_FLAG) != 0) {
+ MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_DATA_FLAG);
+ Buffer[WordIdx] = MmioRead32(SDHOST_DATA);
+ break;
+ }
+
+ ++PollCount;
+ gBS->Stall(CMD_STALL_AFTER_RETRY_US);
+ }
+
+ if (PollCount == FIFO_MAX_POLL_COUNT) {
+ DEBUG(
+ (DEBUG_MMCHOST_SD_ERROR,
+ "SdHost: SdReadBlockData(): Block Word%d read poll timed-out\n",
+ WordIdx));
+ SdHostDumpStatus();
+ MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_CLEAR);
+ Status = EFI_TIMEOUT;
+ break;
+ }
+ }
+ }
+ mFwProtocol->SetLed(FALSE);
+
+ return Status;
+}
+
+STATIC EFI_STATUS
+SdWriteBlockData(
+ IN EFI_MMC_HOST_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Length,
+ IN UINT32* Buffer
+ )
+{
+ DEBUG((
+ DEBUG_MMCHOST_SD,
+ "SdHost: SdWriteBlockData(LBA: 0x%x, Length: 0x%x, Buffer: 0x%x)\n",
+ (UINT32)Lba, Length, Buffer));
+
+ ASSERT(Buffer != NULL);
+ ASSERT(Length % SDHOST_BLOCK_BYTE_LENGTH == 0);
+
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ mFwProtocol->SetLed(TRUE);
+ {
+ UINT32 NumWords = Length / 4;
+ UINT32 WordIdx;
+
+ for (WordIdx = 0; WordIdx < NumWords; ++WordIdx) {
+ UINT32 PollCount = 0;
+ while (PollCount < FIFO_MAX_POLL_COUNT) {
+ if (MmioRead32(SDHOST_HSTS) & SDHOST_HSTS_DATA_FLAG) {
+ MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_DATA_FLAG);
+ MmioWrite32(SDHOST_DATA, Buffer[WordIdx]);
+ break;
+ }
+
+ ++PollCount;
+ gBS->Stall(CMD_STALL_AFTER_RETRY_US);
+ }
+
+ if (PollCount == FIFO_MAX_POLL_COUNT) {
+ DEBUG((
+ DEBUG_MMCHOST_SD_ERROR,
+ "SdHost: SdWriteBlockData(): Block Word%d write poll timed-out\n",
+ WordIdx));
+ SdHostDumpStatus();
+ MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_CLEAR);
+ Status = EFI_TIMEOUT;
+ break;
+ }
+ }
+ }
+ mFwProtocol->SetLed(FALSE);
+
+ return Status;
+}
+
+STATIC EFI_STATUS
+SdSetIos (
+ IN EFI_MMC_HOST_PROTOCOL *This,
+ IN UINT32 BusClockFreq,
+ IN UINT32 BusWidth,
+ IN UINT32 TimingMode
+ )
+{
+ if (BusWidth != 0) {
+ UINT32 Hcfg = MmioRead32(SDHOST_HCFG);
+
+ DEBUG((DEBUG_MMCHOST_SD_INFO, "Setting BusWidth %u\n", BusWidth));
+ if (BusWidth == 4) {
+ Hcfg |= SDHOST_HCFG_WIDE_EXT_BUS;
+ } else {
+ Hcfg &= ~SDHOST_HCFG_WIDE_EXT_BUS;
+ }
+
+ Hcfg |= SDHOST_HCFG_WIDE_INT_BUS | SDHOST_HCFG_SLOW_CARD;
+ MmioWrite32(SDHOST_HCFG, Hcfg);
+ }
+
+ if (BusClockFreq != 0) {
+ DEBUG((DEBUG_MMCHOST_SD_INFO, "Setting Freq %u Hz\n", BusClockFreq));
+ SdHostSetClockFrequency(BusClockFreq);
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC EFI_STATUS
+SdNotifyState(
+ IN EFI_MMC_HOST_PROTOCOL *This,
+ IN MMC_STATE State
+ )
+{
+ DEBUG((DEBUG_MMCHOST_SD, "SdHost: SdNotifyState(State: %d) ", State));
+
+ switch (State) {
+ case MmcHwInitializationState:
+ {
+ DEBUG((DEBUG_MMCHOST_SD, "MmcHwInitializationState\n", State));
+
+ // Turn-off SD Card power
+ MmioWrite32(SDHOST_VDD, 0);
+ {
+ // Reset command and arg
+ MmioWrite32(SDHOST_CMD, 0);
+ MmioWrite32(SDHOST_ARG, 0);
+ // Reset clock divider
+ MmioWrite32(SDHOST_CDIV, 0);
+ // Default timeout
+ MmioWrite32(SDHOST_TOUT, 0xffffffff);
+ // Clear status flags
+ MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_CLEAR);;
+ // Reset controller configs
+ MmioWrite32(SDHOST_HCFG, 0);
+ MmioWrite32(SDHOST_HBCT, 0);
+ MmioWrite32(SDHOST_HBLC, 0);
+
+ gBS->Stall(STALL_TO_STABILIZE_US);
+ }
+ // Turn-on SD Card power
+ MmioWrite32(SDHOST_VDD, 1);
+
+ gBS->Stall(STALL_TO_STABILIZE_US);
+
+ // Write controller configs
+ UINT32 Hcfg = 0;
+ Hcfg |= SDHOST_HCFG_WIDE_INT_BUS;
+ Hcfg |= SDHOST_HCFG_SLOW_CARD; // Use all bits of CDIV in DataMode
+ MmioWrite32(SDHOST_HCFG, Hcfg);
+
+ // Set default clock frequency
+ EFI_STATUS Status = SdHostSetClockFrequency(IDENT_MODE_SD_CLOCK_FREQ_HZ);
+ if (EFI_ERROR(Status)) {
+ DEBUG((
+ DEBUG_MMCHOST_SD_ERROR,
+ "SdHost: SdNotifyState(): Fail to initialize SD clock to %dHz\n",
+ IDENT_MODE_SD_CLOCK_FREQ_HZ));
+ SdHostDumpStatus();
+ return Status;
+ }
+ }
+ break;
+ case MmcIdleState:
+ DEBUG((DEBUG_MMCHOST_SD, "MmcIdleState\n", State));
+ break;
+ case MmcReadyState:
+ DEBUG((DEBUG_MMCHOST_SD, "MmcReadyState\n", State));
+ break;
+ case MmcIdentificationState:
+ DEBUG((DEBUG_MMCHOST_SD, "MmcIdentificationState\n", State));
+ break;
+ case MmcStandByState:
+ DEBUG((DEBUG_MMCHOST_SD, "MmcStandByState\n", State));
+ break;
+ case MmcTransferState:
+ DEBUG((DEBUG_MMCHOST_SD, "MmcTransferState\n", State));
+ break;
+ break;
+ case MmcSendingDataState:
+ DEBUG((DEBUG_MMCHOST_SD, "MmcSendingDataState\n", State));
+ break;
+ case MmcReceiveDataState:
+ DEBUG((DEBUG_MMCHOST_SD, "MmcReceiveDataState\n", State));
+ break;
+ case MmcProgrammingState:
+ DEBUG((DEBUG_MMCHOST_SD, "MmcProgrammingState\n", State));
+ break;
+ case MmcDisconnectState:
+ case MmcInvalidState:
+ default:
+ DEBUG((DEBUG_MMCHOST_SD_ERROR,
+ "SdHost: SdNotifyState(): Invalid State: %d\n", State));
+ ASSERT(0);
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+SdIsMultiBlock (
+ IN EFI_MMC_HOST_PROTOCOL *This
+ )
+{
+ return TRUE;
+}
+
+EFI_MMC_HOST_PROTOCOL gMmcHost =
+ {
+ MMC_HOST_PROTOCOL_REVISION,
+ SdIsCardPresent,
+ SdIsReadOnly,
+ SdBuildDevicePath,
+ SdNotifyState,
+ SdSendCommand,
+ SdReceiveResponse,
+ SdReadBlockData,
+ SdWriteBlockData,
+ SdSetIos,
+ SdIsMultiBlock
+ };
+
+EFI_STATUS
+SdHostInitialize(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle = NULL;
+
+ if (PcdGet32 (PcdSdIsArasan)) {
+ DEBUG((DEBUG_INFO, "SD is not routed to SdHost\n"));
+ return EFI_REQUEST_UNLOAD_IMAGE;
+ }
+
+ Status = gBS->LocateProtocol (&gRaspberryPiFirmwareProtocolGuid, NULL,
+ (VOID **)&mFwProtocol);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG((DEBUG_MMCHOST_SD, "SdHost: Initialize\n"));
+ DEBUG((DEBUG_MMCHOST_SD, "Config:\n"));
+ DEBUG((DEBUG_MMCHOST_SD, " - FIFO_MAX_POLL_COUNT=%d\n", FIFO_MAX_POLL_COUNT));
+ DEBUG((DEBUG_MMCHOST_SD, " - CMD_STALL_AFTER_POLL_US=%dus\n", CMD_STALL_AFTER_POLL_US));
+ DEBUG((DEBUG_MMCHOST_SD, " - CMD_MIN_POLL_TOTAL_TIME_US=%dms\n", CMD_MIN_POLL_TOTAL_TIME_US / 1000));
+ DEBUG((DEBUG_MMCHOST_SD, " - CMD_MAX_POLL_COUNT=%d\n", CMD_MAX_POLL_COUNT));
+ DEBUG((DEBUG_MMCHOST_SD, " - CMD_MAX_RETRY_COUNT=%d\n", CMD_MAX_RETRY_COUNT));
+ DEBUG((DEBUG_MMCHOST_SD, " - CMD_STALL_AFTER_RETRY_US=%dus\n", CMD_STALL_AFTER_RETRY_US));
+
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &Handle,
+ &gRaspberryPiMmcHostProtocolGuid, &gMmcHost,
+ NULL
+ );
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
diff --git a/Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.inf
new file mode 100644
index 000000000000..3469b4611cc9
--- /dev/null
+++ b/Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.inf
@@ -0,0 +1,54 @@
+#/** @file
+#
+# Copyright (c) 2017, Andrei Warkentin <andrey.warkentin@gmail.com>
+# Copyright (c) Microsoft Corporation. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SdHost
+ FILE_GUID = 58ABD787-F64D-4CA2-A034-B9AC2D5AD0CF
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = SdHostInitialize
+
+
+[Sources.common]
+ SdHostDxe.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec
+
+[LibraryClasses]
+ PcdLib
+ UefiLib
+ UefiDriverEntryPoint
+ MemoryAllocationLib
+ IoLib
+ DmaLib
+ CacheMaintenanceLib
+
+[Guids]
+
+[Protocols]
+ gRaspberryPiMmcHostProtocolGuid ## PRODUCES
+ gRaspberryPiFirmwareProtocolGuid ## CONSUMES
+
+[Pcd]
+ gRaspberryPiTokenSpaceGuid.PcdSdIsArasan
+
+[Depex]
+ gRaspberryPiFirmwareProtocolGuid AND gRaspberryPiConfigAppliedProtocolGuid
diff --git a/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836SdHost.h b/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836SdHost.h
new file mode 100644
index 000000000000..fb3d6b5ccad3
--- /dev/null
+++ b/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836SdHost.h
@@ -0,0 +1,92 @@
+/** @file
+ *
+ * Copyright (c) 2017, Andrei Warkentin <andrey.warkentin@gmail.com>
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ * This program and the accompanying materials
+ * are licensed and made available under the terms and conditions of the BSD License
+ * which accompanies this distribution. The full text of the license may be found at
+ * http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ *
+ **/
+
+#ifndef __BCM2836SDHOST_H__
+#define __BCM2836SDHOST_H__
+
+#define SDHOST_BASE_ADDRESS (BCM2836_SOC_REGISTERS + 0x00202000)
+#define SDHOST_REG(X) (SDHOST_BASE_ADDRESS + (X))
+#define SDHOST_CMD SDHOST_REG(0x0)
+#define SDHOST_ARG SDHOST_REG(0x4)
+#define SDHOST_TOUT SDHOST_REG(0x8)
+#define SDHOST_CDIV SDHOST_REG(0xC)
+#define SDHOST_RSP0 SDHOST_REG(0x10) // [31:0]
+#define SDHOST_RSP1 SDHOST_REG(0x14) // [63:32]
+#define SDHOST_RSP2 SDHOST_REG(0x18) // [95:64]
+#define SDHOST_RSP3 SDHOST_REG(0x1C) // [127:96]
+#define SDHOST_HSTS SDHOST_REG(0x20)
+#define SDHOST_VDD SDHOST_REG(0x30)
+#define SDHOST_EDM SDHOST_REG(0x34)
+#define SDHOST_HCFG SDHOST_REG(0x38)
+#define SDHOST_HBCT SDHOST_REG(0x3C)
+#define SDHOST_DATA SDHOST_REG(0x40)
+#define SDHOST_HBLC SDHOST_REG(0x50)
+
+//
+// CMD
+//
+#define SDHOST_CMD_READ_CMD BIT6
+#define SDHOST_CMD_WRITE_CMD BIT7
+#define SDHOST_CMD_RESPONSE_CMD_LONG_RESP BIT9
+#define SDHOST_CMD_RESPONSE_CMD_NO_RESP BIT10
+#define SDHOST_CMD_BUSY_CMD BIT11
+#define SDHOST_CMD_FAIL_FLAG BIT14
+#define SDHOST_CMD_NEW_FLAG BIT15
+
+//
+// VDD
+//
+#define SDHOST_VDD_POWER_ON BIT0
+
+//
+// HSTS
+//
+#define SDHOST_HSTS_CLEAR 0x7F8
+#define SDHOST_HSTS_BLOCK_IRPT BIT9
+#define SDHOST_HSTS_REW_TIME_OUT BIT7
+#define SDHOST_HSTS_CMD_TIME_OUT BIT6
+#define SDHOST_HSTS_CRC16_ERROR BIT5
+#define SDHOST_HSTS_CRC7_ERROR BIT4
+#define SDHOST_HSTS_FIFO_ERROR BIT3
+#define SDHOST_HSTS_DATA_FLAG BIT0
+
+#define SDHOST_HSTS_TIMOUT_ERROR (SDHOST_HSTS_CMD_TIME_OUT | SDHOST_HSTS_REW_TIME_OUT)
+#define SDHOST_HSTS_TRANSFER_ERROR (SDHOST_HSTS_FIFO_ERROR | SDHOST_HSTS_CRC7_ERROR | SDHOST_HSTS_CRC16_ERROR)
+#define SDHOST_HSTS_ERROR (SDHOST_HSTS_TIMOUT_ERROR | SDHOST_HSTS_TRANSFER_ERROR)
+
+//
+// HCFG
+//
+#define SDHOST_HCFG_SLOW_CARD BIT3
+#define SDHOST_HCFG_WIDE_EXT_BUS BIT2
+#define SDHOST_HCFG_WIDE_INT_BUS BIT1
+#define SDHOST_HCFG_DATA_IRPT_EN BIT4
+#define SDHOST_HCFG_BLOCK_IRPT_EN BIT8
+#define SDHOST_HCFG_BUSY_IRPT_EN BIT10
+
+//
+// EDM
+//
+#define SDHOST_EDM_FIFO_CLEAR BIT21
+#define SDHOST_EDM_WRITE_THRESHOLD_SHIFT 9
+#define SDHOST_EDM_READ_THRESHOLD_SHIFT 14
+#define SDHOST_EDM_THRESHOLD_MASK 0x1F
+#define SDHOST_EDM_READ_THRESHOLD(X) ((X) << SDHOST_EDM_READ_THRESHOLD_SHIFT)
+#define SDHOST_EDM_WRITE_THRESHOLD(X) ((X) << SDHOST_EDM_WRITE_THRESHOLD_SHIFT)
+
+#define CMD8_SD_ARG (0x0UL << 12 | BIT8 | 0xCEUL << 0)
+#define CMD8_MMC_ARG (0)
+
+#endif //__BCM2836SDHOST_H__
--
2.17.0.windows.1
next prev parent reply other threads:[~2018-12-10 12:39 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-10 12:38 [PATCH v2 edk2-platforms 00/20] Platform/Broadcom: Add Raspberry Pi 3 support Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 01/20] Platform/Broadcom/RPi3: Add Reset and Memory Init libraries Pete Batard
2018-12-12 20:43 ` Ard Biesheuvel
2018-12-13 10:48 ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 02/20] Platform/Broadcom/RPi3: Add Platform library Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 03/20] Platform/Broadcom/RPi3: Add GPIO and RTC libraries Pete Batard
2018-12-12 20:50 ` Ard Biesheuvel
2018-12-13 10:49 ` Pete Batard
2018-12-13 10:55 ` Leif Lindholm
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 04/20] Platform/Broadcom/RPi3: Add ACPI Tables Pete Batard
2018-12-12 20:52 ` Ard Biesheuvel
2018-12-13 10:49 ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 05/20] Platform/Broadcom/RPi3: Add Boot Manager library Pete Batard
2018-12-12 20:56 ` Ard Biesheuvel
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 06/20] Platform/Broadcom/RPi3: Add Interrupt and Device Tree drivers Pete Batard
2018-12-12 21:09 ` Ard Biesheuvel
2018-12-13 10:49 ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 07/20] Platform/Broadcom/RPi3: Add Firmware driver Pete Batard
2018-12-12 21:17 ` Ard Biesheuvel
2018-12-13 10:49 ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 08/20] Platform/Broadcom/RPi3: Add Display driver Pete Batard
2018-12-14 15:06 ` Ard Biesheuvel
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 09/20] Platform/Broadcom/RPi3: Add Graphic Console driver Pete Batard
2018-12-14 15:31 ` Ard Biesheuvel
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 10/20] Platform/Broadcom/RPi3: Add Base MMC driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 11/20] Platform/Broadcom/RPi3: Add Arasan " Pete Batard
2018-12-10 12:38 ` Pete Batard [this message]
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 13/20] Platform/Broadcom/RPi3: Add SMBIOS driver Pete Batard
2018-12-14 15:36 ` Ard Biesheuvel
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 14/20] Platform/Broadcom/RPi3: Add NV Storage driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 15/20] Platform/Broadcom/RPi3: Add Platform Config driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 16/20] Platform/Broadcom/RPi3: Add Raspberry Pi 3 Platform Pete Batard
2018-12-14 15:39 ` Ard Biesheuvel
2018-12-14 16:21 ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 17/20] Platform/Broadcom/RPi3 *NON-OSI*: Add ATF binaries Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 18/20] Platform/Broadcom/RPi3 *NON-OSI*: Add Device Tree binaries Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 19/20] Platform/Broadcom/RPi3 *NON-OSI*: Add USB Host driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 20/20] Platform/Broadcom/RPi3 *NON-OSI*: Add Logo driver Pete Batard
2018-12-11 18:10 ` [PATCH v2 edk2-platforms 00/20] Platform/Broadcom: Add Raspberry Pi 3 support Leif Lindholm
2018-12-11 20:16 ` Pete Batard
2018-12-11 21:20 ` Ard Biesheuvel
2018-12-12 18:32 ` Leif Lindholm
2018-12-12 19:53 ` Pete Batard
2018-12-12 20:01 ` Leif Lindholm
2018-12-14 16:14 ` Philippe Mathieu-Daudé
2018-12-14 16:36 ` Leif Lindholm
2018-12-14 17:08 ` Pete Batard
2018-12-14 18:41 ` Leif Lindholm
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181210123853.4864-13-pete@akeo.ie \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox