public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
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



  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