From: "Wu, Hao A" <hao.a.wu@intel.com>
To: "Wu, Hao A" <hao.a.wu@intel.com>,
Ashish Singhal <ashishsingha@nvidia.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Subject: Re: [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support.
Date: Wed, 2 Jan 2019 06:36:57 +0000 [thread overview]
Message-ID: <B80AF82E9BFB8E4FBD8C89DA810C6A093C8718CB@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <B80AF82E9BFB8E4FBD8C89DA810C6A093C8718AC@SHSMSX104.ccr.corp.intel.com>
Missed one comment for commit message:
"If V4 64 bit address mode is enabled in compatibility register"
->
"If V4 64 bit address mode is supported in capabilities register"
Best Regards,
Hao Wu
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Wu, Hao A
> Sent: Wednesday, January 02, 2019 2:29 PM
> To: Ashish Singhal; edk2-devel@lists.01.org
> Subject: Re: [edk2] [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add
> SDMMC HC v4 and above Support.
>
> Hello,
>
> I have 2 minor comments, please refer to those inline comments.
> Apart from that, the patch is good to me:
> Reviewed-by: Hao Wu <hao.a.wu@intel.com>
>
> If you agree those inline comments, I will directly modify the patch on my
> side and then push it into the repository.
>
> > -----Original Message-----
> > From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> > Ashish Singhal
> > Sent: Wednesday, December 19, 2018 5:29 AM
> > To: edk2-devel@lists.01.org
> > Cc: Ashish Singhal
> > Subject: [edk2] [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC
> > HC v4 and above Support.
>
> Add the Bugzilla tracker information at the start of the commit log message:
>
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1359
>
> >
> > Add SDMA, ADMA2 and 26b data length support.
> >
> > If V4 64 bit address mode is enabled in compatibility register,
> > program controller to enable V4 host mode and use appropriate
> > SDMA registers supporting 64 bit addresses.
> >
> > If V4 64 bit address mode is enabled in compatibility register,
> > program controller to enable V4 host mode and use appropriate
> > ADMA descriptors supporting 64 bit addresses.
> >
> > If host controller version is above V4.0, enable ADMA2 with 26b data
> > length support for better performance. HC 2 register is configured to
> > use 26 bit data lengths and ADMA2 descriptors are configured
> appropriately.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Ashish Singhal <ashishsingha@nvidia.com>
> > ---
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c | 2 +-
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c | 4 +-
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c | 21 +-
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h | 7 +-
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c | 328
> > +++++++++++++++++----
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h | 84 ++++--
> > 6 files changed, 363 insertions(+), 83 deletions(-)
> > mode change 100755 => 100644
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> >
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > old mode 100755
> > new mode 100644
> > index 2d3fb68..0c5646f
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > @@ -707,7 +707,7 @@ EmmcSwitchClockFreq (
> > //
> > // Convert the clock freq unit from MHz to KHz.
> > //
> > - Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> > >BaseClkFreq[Slot]);
> > + Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> > >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > index 68485c8..cdcdfa3 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > @@ -864,7 +864,7 @@ SdCardSetBusMode (
> > return Status;
> > }
> >
> > - Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> > >BaseClkFreq[Slot]);
> > + Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> > >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> > @@ -1064,7 +1064,7 @@ SdCardIdentification (
> > goto Error;
> > }
> >
> > - SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
> > + SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot],
> Private-
> > >ControllerVersion[Slot]);
> >
> > gBS->Stall (1000);
> >
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > index a87f8de..b5bc260 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > @@ -62,7 +62,9 @@ SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate
> =
> > {
> > { // MaxCurrent
> > 0,
> > },
> > - 0 // ControllerVersion
> > + {
> > + 0 // ControllerVersion
> > + }
> > };
> >
> > SD_DEVICE_PATH mSdDpTemplate = {
> > @@ -621,6 +623,14 @@ SdMmcPciHcDriverBindingStart (
> > for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
> > Private->Slot[Slot].Enable = TRUE;
> >
> > + //
> > + // Get SD/MMC Pci Host Controller Version
> > + //
> > + Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private-
> > >ControllerVersion[Slot]);
> > + if (EFI_ERROR (Status)) {
> > + goto Done;
>
> Like other error handling in the for loop:
> Instead of "goto Done;", change to "continue;".
>
>
> Thanks for the patience.
>
> Best Regards,
> Hao Wu
>
> > + }
> > +
> > Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
> > if (EFI_ERROR (Status)) {
> > continue;
> > @@ -649,7 +659,14 @@ SdMmcPciHcDriverBindingStart (
> > Private->BaseClkFreq[Slot]
> > ));
> >
> > - Support64BitDma &= Private->Capability[Slot].SysBus64;
> > + //
> > + // If any of the slots does not support 64b system bus
> > + // do not enable 64b DMA in the PCI layer.
> > + //
> > + if (Private->Capability[Slot].SysBus64V3 == 0 &&
> > + Private->Capability[Slot].SysBus64V4 == 0) {
> > + Support64BitDma = FALSE;
> > + }
> >
> > Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private-
> > >MaxCurrent[Slot]);
> > if (EFI_ERROR (Status)) {
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > index 8c1a589..1bb701a 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > @@ -2,6 +2,7 @@
> >
> > Provides some data structure definitions used by the SD/MMC host
> > controller driver.
> >
> > +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
> > Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
> > This program and the accompanying materials
> > are licensed and made available under the terms and conditions of the
> BSD
> > License
> > @@ -116,8 +117,7 @@ typedef struct {
> > SD_MMC_HC_SLOT Slot[SD_MMC_HC_MAX_SLOT];
> > SD_MMC_HC_SLOT_CAP Capability[SD_MMC_HC_MAX_SLOT];
> > UINT64 MaxCurrent[SD_MMC_HC_MAX_SLOT];
> > -
> > - UINT32 ControllerVersion;
> > + UINT16 ControllerVersion[SD_MMC_HC_MAX_SLOT];
> >
> > //
> > // Some controllers may require to override base clock frequency
> > @@ -150,7 +150,8 @@ typedef struct {
> > BOOLEAN Started;
> > UINT64 Timeout;
> >
> > - SD_MMC_HC_ADMA_DESC_LINE *AdmaDesc;
> > + SD_MMC_HC_ADMA_32_DESC_LINE *Adma32Desc;
> > + SD_MMC_HC_ADMA_64_DESC_LINE *Adma64Desc;
> > EFI_PHYSICAL_ADDRESS AdmaDescPhy;
> > VOID *AdmaMap;
> > UINT32 AdmaPages;
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > index ddf6dcf..6086720 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > @@ -4,6 +4,7 @@
> >
> > It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer
> use.
> >
> > + Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
> > Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> > This program and the accompanying materials
> > are licensed and made available under the terms and conditions of the
> BSD
> > License
> > @@ -45,7 +46,8 @@ DumpCapabilityReg (
> > DEBUG ((DEBUG_INFO, " Voltage 3.3 %a\n", Capability->Voltage33 ?
> > "TRUE" : "FALSE"));
> > DEBUG ((DEBUG_INFO, " Voltage 3.0 %a\n", Capability->Voltage30 ?
> > "TRUE" : "FALSE"));
> > DEBUG ((DEBUG_INFO, " Voltage 1.8 %a\n", Capability->Voltage18 ?
> > "TRUE" : "FALSE"));
> > - DEBUG ((DEBUG_INFO, " 64-bit Sys Bus %a\n", Capability->SysBus64 ?
> > "TRUE" : "FALSE"));
> > + DEBUG ((DEBUG_INFO, " V4 64-bit Sys Bus %a\n", Capability-
> > >SysBus64V4 ? "TRUE" : "FALSE"));
> > + DEBUG ((DEBUG_INFO, " V3 64-bit Sys Bus %a\n", Capability-
> > >SysBus64V3 ? "TRUE" : "FALSE"));
> > DEBUG ((DEBUG_INFO, " Async Interrupt %a\n", Capability->AsyncInt ?
> > "TRUE" : "FALSE"));
> > DEBUG ((DEBUG_INFO, " SlotType "));
> > if (Capability->SlotType == 0x00) {
> > @@ -417,6 +419,36 @@ SdMmcHcWaitMmioSet (
> > }
> >
> > /**
> > + Get the controller version information from the specified slot.
> > +
> > + @param[in] PciIo The PCI IO protocol instance.
> > + @param[in] Slot The slot number of the SD card to send the
> > command to.
> > + @param[out] Version The buffer to store the version information.
> > +
> > + @retval EFI_SUCCESS The operation executes successfully.
> > + @retval Others The operation fails.
> > +
> > +**/
> > +EFI_STATUS
> > +SdMmcHcGetControllerVersion (
> > + IN EFI_PCI_IO_PROTOCOL *PciIo,
> > + IN UINT8 Slot,
> > + OUT UINT16 *Version
> > + )
> > +{
> > + EFI_STATUS Status;
> > +
> > + Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE,
> > sizeof (UINT16), Version);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + *Version &= 0xFF;
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > Software reset the specified SD/MMC host controller and enable all
> > interrupts.
> >
> > @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA
> > instance.
> > @@ -722,6 +754,7 @@ SdMmcHcStopClock (
> > @param[in] Slot The slot number of the SD card to send the
> command
> > to.
> > @param[in] ClockFreq The max clock frequency to be set. The unit is
> KHz.
> > @param[in] BaseClkFreq The base clock frequency of host controller in
> > MHz.
> > + @param[in] ControllerVer The version of host controller.
> >
> > @retval EFI_SUCCESS The clock is supplied successfully.
> > @retval Others The clock isn't supplied successfully.
> > @@ -732,14 +765,14 @@ SdMmcHcClockSupply (
> > IN EFI_PCI_IO_PROTOCOL *PciIo,
> > IN UINT8 Slot,
> > IN UINT64 ClockFreq,
> > - IN UINT32 BaseClkFreq
> > + IN UINT32 BaseClkFreq,
> > + IN UINT16 ControllerVer
> > )
> > {
> > EFI_STATUS Status;
> > UINT32 SettingFreq;
> > UINT32 Divisor;
> > UINT32 Remainder;
> > - UINT16 ControllerVer;
> > UINT16 ClockCtrl;
> >
> > //
> > @@ -775,18 +808,15 @@ SdMmcHcClockSupply (
> >
> > DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d
> > ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));
> >
> > - Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE,
> > sizeof (ControllerVer), &ControllerVer);
> > - if (EFI_ERROR (Status)) {
> > - return Status;
> > - }
> > //
> > // Set SDCLK Frequency Select and Internal Clock Enable fields in Clock
> > Control register.
> > //
> > - if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
> > - ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {
> > + if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&
> > + (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {
> > ASSERT (Divisor <= 0x3FF);
> > ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
> > - } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
> > + } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||
> > + (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {
> > //
> > // Only the most significant bit can be used as divisor.
> > //
> > @@ -934,11 +964,62 @@ SdMmcHcSetBusWidth (
> > }
> >
> > /**
> > + Configure V4 controller enhancements at initialization.
> > +
> > + @param[in] PciIo The PCI IO protocol instance.
> > + @param[in] Slot The slot number of the SD card to send the
> > command to.
> > + @param[in] Capability The capability of the slot.
> > + @param[in] ControllerVer The version of host controller.
> > +
> > + @retval EFI_SUCCESS The clock is supplied successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +SdMmcHcInitV4Enhancements (
> > + IN EFI_PCI_IO_PROTOCOL *PciIo,
> > + IN UINT8 Slot,
> > + IN SD_MMC_HC_SLOT_CAP Capability,
> > + IN UINT16 ControllerVer
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINT16 HostCtrl2;
> > +
> > + //
> > + // Check if controller version V4 or higher
> > + //
> > + if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> > + HostCtrl2 = SD_MMC_HC_V4_EN;
> > + //
> > + // Check if V4 64bit support is available
> > + //
> > + if (Capability.SysBus64V4 != 0) {
> > + HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
> > + DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
> > + }
> > + //
> > + // Check if controller version V4.10 or higher
> > + //
> > + if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
> > + HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
> > + DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA
> > support\n"));
> > + }
> > + Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2,
> sizeof
> > (HostCtrl2), &HostCtrl2);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > + }
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > Supply SD/MMC card with lowest clock frequency at initialization.
> >
> > @param[in] PciIo The PCI IO protocol instance.
> > @param[in] Slot The slot number of the SD card to send the
> command
> > to.
> > @param[in] BaseClkFreq The base clock frequency of host controller in
> > MHz.
> > + @param[in] ControllerVer The version of host controller.
> >
> > @retval EFI_SUCCESS The clock is supplied successfully.
> > @retval Others The clock isn't supplied successfully.
> > @@ -948,7 +1029,8 @@ EFI_STATUS
> > SdMmcHcInitClockFreq (
> > IN EFI_PCI_IO_PROTOCOL *PciIo,
> > IN UINT8 Slot,
> > - IN UINT32 BaseClkFreq
> > + IN UINT32 BaseClkFreq,
> > + IN UINT16 ControllerVer
> > )
> > {
> > EFI_STATUS Status;
> > @@ -970,7 +1052,7 @@ SdMmcHcInitClockFreq (
> > // Supply 400KHz clock frequency at initialization phase.
> > //
> > InitFreq = 400;
> > - Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq);
> > + Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq,
> > ControllerVer);
> > return Status;
> > }
> >
> > @@ -1104,7 +1186,12 @@ SdMmcHcInitHost (
> > PciIo = Private->PciIo;
> > Capability = Private->Capability[Slot];
> >
> > - Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
> > + Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private-
> > >ControllerVersion[Slot]);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot],
> > Private->ControllerVersion[Slot]);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> > @@ -1262,9 +1349,10 @@ SdMmcHcLedOnOff (
> > /**
> > Build ADMA descriptor table for transfer.
> >
> > - Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.
> > + Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.
> >
> > @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.
> > + @param[in] ControllerVer The version of host controller.
> >
> > @retval EFI_SUCCESS The ADMA descriptor table is created
> successfully.
> > @retval Others The ADMA descriptor table isn't created
> successfully.
> > @@ -1272,7 +1360,8 @@ SdMmcHcLedOnOff (
> > **/
> > EFI_STATUS
> > BuildAdmaDescTable (
> > - IN SD_MMC_HC_TRB *Trb
> > + IN SD_MMC_HC_TRB *Trb,
> > + IN UINT16 ControllerVer
> > )
> > {
> > EFI_PHYSICAL_ADDRESS Data;
> > @@ -1280,49 +1369,93 @@ BuildAdmaDescTable (
> > UINT64 Entries;
> > UINT32 Index;
> > UINT64 Remaining;
> > - UINT32 Address;
> > + UINT64 Address;
> > UINTN TableSize;
> > EFI_PCI_IO_PROTOCOL *PciIo;
> > EFI_STATUS Status;
> > UINTN Bytes;
> > + BOOLEAN AddressingMode64;
> > + BOOLEAN DataLength26;
> > + UINT32 AdmaMaxDataPerLine;
> > + UINT32 DescSize;
> > + VOID *AdmaDesc;
> > +
> > + AddressingMode64 = FALSE;
> > + DataLength26 = FALSE;
> > + AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;
> > + DescSize = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
> > + AdmaDesc = NULL;
> >
> > Data = Trb->DataPhy;
> > DataLen = Trb->DataLen;
> > PciIo = Trb->Private->PciIo;
> > +
> > //
> > - // Only support 32bit ADMA Descriptor Table
> > + // Detect whether 64bit addressing is supported.
> > //
> > - if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {
> > + if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
> > + Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> > SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> > + SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> > SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> > + if (!EFI_ERROR (Status)) {
> > + AddressingMode64 = TRUE;
> > + DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);
> > + }
> > + }
> > + //
> > + // Check for valid ranges in 32bit ADMA Descriptor Table
> > + //
> > + if (!AddressingMode64 &&
> > + ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {
> > return EFI_INVALID_PARAMETER;
> > }
> > //
> > - // Address field shall be set on 32-bit boundary (Lower 2-bit is always set
> to
> > 0)
> > - // for 32-bit address descriptor table.
> > + // Check address field alignment
> > //
> > - if ((Data & (BIT0 | BIT1)) != 0) {
> > - DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is
> not
> > aligned to 4 bytes boundary!\n", Data));
> > + if (AddressingMode64) {
> > + //
> > + // Address field shall be set on 64-bit boundary (Lower 3-bit is always
> set
> > to 0)
> > + //
> > + if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {
> > + DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is
> > not aligned to 8 bytes boundary!\n", Data));
> > + }
> > + } else {
> > + //
> > + // Address field shall be set on 32-bit boundary (Lower 2-bit is always
> set
> > to 0)
> > + //
> > + if ((Data & (BIT0 | BIT1)) != 0) {
> > + DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is
> > not aligned to 4 bytes boundary!\n", Data));
> > + }
> > + }
> > + //
> > + // Detect whether 26bit data length is supported.
> > + //
> > + Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> > SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> > + SD_MMC_HC_26_DATA_LEN_ADMA_EN,
> > SD_MMC_HC_26_DATA_LEN_ADMA_EN);
> > + if (!EFI_ERROR (Status)) {
> > + DataLength26 = TRUE;
> > + AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
> > }
> >
> > - Entries = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1),
> > ADMA_MAX_DATA_PER_LINE);
> > - TableSize = (UINTN)MultU64x32 (Entries, sizeof
> > (SD_MMC_HC_ADMA_DESC_LINE));
> > + Entries = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1),
> > AdmaMaxDataPerLine);
> > + TableSize = (UINTN)MultU64x32 (Entries, DescSize);
> > Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);
> > Status = PciIo->AllocateBuffer (
> > PciIo,
> > AllocateAnyPages,
> > EfiBootServicesData,
> > EFI_SIZE_TO_PAGES (TableSize),
> > - (VOID **)&Trb->AdmaDesc,
> > + (VOID **)&AdmaDesc,
> > 0
> > );
> > if (EFI_ERROR (Status)) {
> > return EFI_OUT_OF_RESOURCES;
> > }
> > - ZeroMem (Trb->AdmaDesc, TableSize);
> > + ZeroMem (AdmaDesc, TableSize);
> > Bytes = TableSize;
> > Status = PciIo->Map (
> > PciIo,
> > EfiPciIoOperationBusMasterCommonBuffer,
> > - Trb->AdmaDesc,
> > + AdmaDesc,
> > &Bytes,
> > &Trb->AdmaDescPhy,
> > &Trb->AdmaMap
> > @@ -1335,12 +1468,13 @@ BuildAdmaDescTable (
> > PciIo->FreeBuffer (
> > PciIo,
> > EFI_SIZE_TO_PAGES (TableSize),
> > - Trb->AdmaDesc
> > + AdmaDesc
> > );
> > return EFI_OUT_OF_RESOURCES;
> > }
> >
> > - if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
> > + if ((!AddressingMode64) &&
> > + (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
> > //
> > // The ADMA doesn't support 64bit addressing.
> > //
> > @@ -1351,35 +1485,71 @@ BuildAdmaDescTable (
> > PciIo->FreeBuffer (
> > PciIo,
> > EFI_SIZE_TO_PAGES (TableSize),
> > - Trb->AdmaDesc
> > + AdmaDesc
> > );
> > return EFI_DEVICE_ERROR;
> > }
> >
> > Remaining = DataLen;
> > - Address = (UINT32)Data;
> > + Address = Data;
> > + if (!AddressingMode64) {
> > + Trb->Adma32Desc = AdmaDesc;
> > + Trb->Adma64Desc = NULL;
> > + } else {
> > + Trb->Adma64Desc = AdmaDesc;
> > + Trb->Adma32Desc = NULL;
> > + }
> > for (Index = 0; Index < Entries; Index++) {
> > - if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
> > - Trb->AdmaDesc[Index].Valid = 1;
> > - Trb->AdmaDesc[Index].Act = 2;
> > - Trb->AdmaDesc[Index].Length = (UINT16)Remaining;
> > - Trb->AdmaDesc[Index].Address = Address;
> > - break;
> > + if (!AddressingMode64) {
> > + if (Remaining <= AdmaMaxDataPerLine) {
> > + Trb->Adma32Desc[Index].Valid = 1;
> > + Trb->Adma32Desc[Index].Act = 2;
> > + if (DataLength26) {
> > + Trb->Adma32Desc[Index].UpperLength = (UINT16)(Remaining >> 16);
> > + }
> > + Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining &
> > MAX_UINT16);
> > + Trb->Adma32Desc[Index].Address = (UINT32)Address;
> > + break;
> > + } else {
> > + Trb->Adma32Desc[Index].Valid = 1;
> > + Trb->Adma32Desc[Index].Act = 2;
> > + if (DataLength26) {
> > + Trb->Adma32Desc[Index].UpperLength = 0;
> > + }
> > + Trb->Adma32Desc[Index].LowerLength = 0;
> > + Trb->Adma32Desc[Index].Address = (UINT32)Address;
> > + }
> > } else {
> > - Trb->AdmaDesc[Index].Valid = 1;
> > - Trb->AdmaDesc[Index].Act = 2;
> > - Trb->AdmaDesc[Index].Length = 0;
> > - Trb->AdmaDesc[Index].Address = Address;
> > + if (Remaining <= AdmaMaxDataPerLine) {
> > + Trb->Adma64Desc[Index].Valid = 1;
> > + Trb->Adma64Desc[Index].Act = 2;
> > + if (DataLength26) {
> > + Trb->Adma64Desc[Index].UpperLength = (UINT16)(Remaining >> 16);
> > + }
> > + Trb->Adma64Desc[Index].LowerLength = (UINT16)(Remaining &
> > MAX_UINT16);
> > + Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> > + Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> > + break;
> > + } else {
> > + Trb->Adma64Desc[Index].Valid = 1;
> > + Trb->Adma64Desc[Index].Act = 2;
> > + if (DataLength26) {
> > + Trb->Adma64Desc[Index].UpperLength = 0;
> > + }
> > + Trb->Adma64Desc[Index].LowerLength = 0;
> > + Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
> > + Trb->Adma64Desc[Index].UpperAddress = (UINT32)(Address >> 32);
> > + }
> > }
> >
> > - Remaining -= ADMA_MAX_DATA_PER_LINE;
> > - Address += ADMA_MAX_DATA_PER_LINE;
> > + Remaining -= AdmaMaxDataPerLine;
> > + Address += AdmaMaxDataPerLine;
> > }
> >
> > //
> > // Set the last descriptor line as end of descriptor table
> > //
> > - Trb->AdmaDesc[Index].End = 1;
> > + AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb-
> > >Adma32Desc[Index].End = 1);
> > return EFI_SUCCESS;
> > }
> >
> > @@ -1477,7 +1647,7 @@ SdMmcCreateTrb (
> > Trb->Mode = SdMmcNoData;
> > } else if (Private->Capability[Slot].Adma2 != 0) {
> > Trb->Mode = SdMmcAdmaMode;
> > - Status = BuildAdmaDescTable (Trb);
> > + Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);
> > if (EFI_ERROR (Status)) {
> > PciIo->Unmap (PciIo, Trb->DataMap);
> > goto Error;
> > @@ -1523,11 +1693,18 @@ SdMmcFreeTrb (
> > Trb->AdmaMap
> > );
> > }
> > - if (Trb->AdmaDesc != NULL) {
> > + if (Trb->Adma32Desc != NULL) {
> > + PciIo->FreeBuffer (
> > + PciIo,
> > + Trb->AdmaPages,
> > + Trb->Adma32Desc
> > + );
> > + }
> > + if (Trb->Adma64Desc != NULL) {
> > PciIo->FreeBuffer (
> > PciIo,
> > Trb->AdmaPages,
> > - Trb->AdmaDesc
> > + Trb->Adma64Desc
> > );
> > }
> > if (Trb->DataMap != NULL) {
> > @@ -1667,12 +1844,15 @@ SdMmcExecTrb (
> > UINT16 Cmd;
> > UINT16 IntStatus;
> > UINT32 Argument;
> > - UINT16 BlkCount;
> > + UINT32 BlkCount;
> > UINT16 BlkSize;
> > UINT16 TransMode;
> > UINT8 HostCtrl1;
> > - UINT32 SdmaAddr;
> > + UINT64 SdmaAddr;
> > UINT64 AdmaAddr;
> > + BOOLEAN AddressingMode64;
> > +
> > + AddressingMode64 = FALSE;
> >
> > Packet = Trb->Packet;
> > PciIo = Trb->Private->PciIo;
> > @@ -1705,13 +1885,28 @@ SdMmcExecTrb (
> >
> > SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);
> >
> > + if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400)
> > {
> > + Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot,
> > SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
> > + SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN,
> > SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
> > + if (!EFI_ERROR (Status)) {
> > + AddressingMode64 = TRUE;
> > + }
> > + }
> > +
> > if (Trb->Mode == SdMmcSdmaMode) {
> > - if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
> > + if ((!AddressingMode64) &&
> > + ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
> > return EFI_INVALID_PARAMETER;
> > }
> >
> > - SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
> > - Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> SD_MMC_HC_SDMA_ADDR,
> > FALSE, sizeof (SdmaAddr), &SdmaAddr);
> > + SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;
> > +
> > + if (Private->ControllerVersion[Trb->Slot] >=
> SD_MMC_HC_CTRL_VER_400)
> > {
> > + Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> > SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);
> > + } else {
> > + Status = SdMmcHcRwMmio (PciIo, Trb->Slot,
> > SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);
> > + }
> > +
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> > @@ -1741,9 +1936,13 @@ SdMmcExecTrb (
> > //
> > // Calcuate Block Count.
> > //
> > - BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
> > + BlkCount = (Trb->DataLen / Trb->BlockSize);
> > + }
> > + if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410)
> > {
> > + Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR,
> > FALSE, sizeof (UINT32), &BlkCount);
> > + } else {
> > + Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> > FALSE, sizeof (UINT16), &BlkCount);
> > }
> > - Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT,
> > FALSE, sizeof (BlkCount), &BlkCount);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> > @@ -1839,7 +2038,7 @@ SdMmcCheckTrbResult (
> > EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
> > UINT16 IntStatus;
> > UINT32 Response[4];
> > - UINT32 SdmaAddr;
> > + UINT64 SdmaAddr;
> > UINT8 Index;
> > UINT8 SwReset;
> > UINT32 PioLength;
> > @@ -1963,8 +2162,19 @@ SdMmcCheckTrbResult (
> > //
> > // Update SDMA Address register.
> > //
> > - SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb-
> > >DataPhy, SD_MMC_SDMA_BOUNDARY);
> > - Status = SdMmcHcRwMmio (
> > + SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy,
> > SD_MMC_SDMA_BOUNDARY);
> > +
> > + if (Private->ControllerVersion[Trb->Slot] >=
> SD_MMC_HC_CTRL_VER_400)
> > {
> > + Status = SdMmcHcRwMmio (
> > + Private->PciIo,
> > + Trb->Slot,
> > + SD_MMC_HC_ADMA_SYS_ADDR,
> > + FALSE,
> > + sizeof (UINT64),
> > + &SdmaAddr
> > + );
> > + } else {
> > + Status = SdMmcHcRwMmio (
> > Private->PciIo,
> > Trb->Slot,
> > SD_MMC_HC_SDMA_ADDR,
> > @@ -1972,10 +2182,12 @@ SdMmcCheckTrbResult (
> > sizeof (UINT32),
> > &SdmaAddr
> > );
> > + }
> > +
> > if (EFI_ERROR (Status)) {
> > goto Done;
> > }
> > - Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
> > + Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;
> > }
> >
> > if ((Packet->SdMmcCmdBlk->CommandType !=
> SdMmcCommandTypeAdtc)
> > &&
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > index dd45cbd..d157f2c 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > @@ -2,6 +2,7 @@
> >
> > Provides some data structure definitions used by the SD/MMC host
> > controller driver.
> >
> > +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
> > Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
> > This program and the accompanying materials
> > are licensed and made available under the terms and conditions of the
> BSD
> > License
> > @@ -91,18 +92,38 @@ typedef enum {
> > //
> > // The maximum data length of each descriptor line
> > //
> > -#define ADMA_MAX_DATA_PER_LINE 0x10000
> > +#define ADMA_MAX_DATA_PER_LINE_16B SIZE_64KB
> > +#define ADMA_MAX_DATA_PER_LINE_26B SIZE_64MB
> >
> > +//
> > +// ADMA descriptor for 32b addressing.
> > +//
> > typedef struct {
> > UINT32 Valid:1;
> > UINT32 End:1;
> > UINT32 Int:1;
> > UINT32 Reserved:1;
> > UINT32 Act:2;
> > - UINT32 Reserved1:10;
> > - UINT32 Length:16;
> > + UINT32 UpperLength:10;
> > + UINT32 LowerLength:16;
> > UINT32 Address;
> > -} SD_MMC_HC_ADMA_DESC_LINE;
> > +} SD_MMC_HC_ADMA_32_DESC_LINE;
> > +
> > +//
> > +// ADMA descriptor for 64b addressing.
> > +//
> > +typedef struct {
> > + UINT32 Valid:1;
> > + UINT32 End:1;
> > + UINT32 Int:1;
> > + UINT32 Reserved:1;
> > + UINT32 Act:2;
> > + UINT32 UpperLength:10;
> > + UINT32 LowerLength:16;
> > + UINT32 LowerAddress;
> > + UINT32 UpperAddress;
> > + UINT32 Reserved1;
> > +} SD_MMC_HC_ADMA_64_DESC_LINE;
> >
> > #define SD_MMC_SDMA_BOUNDARY 512 * 1024
> > #define SD_MMC_SDMA_ROUND_UP(x, n) (((x) + n) & ~(n - 1))
> > @@ -129,36 +150,43 @@ typedef struct {
> > UINT32 Voltage33:1; // bit 24
> > UINT32 Voltage30:1; // bit 25
> > UINT32 Voltage18:1; // bit 26
> > - UINT32 Reserved3:1; // bit 27
> > - UINT32 SysBus64:1; // bit 28
> > + UINT32 SysBus64V4:1; // bit 27
> > + UINT32 SysBus64V3:1; // bit 28
> > UINT32 AsyncInt:1; // bit 29
> > UINT32 SlotType:2; // bit 30:31
> > UINT32 Sdr50:1; // bit 32
> > UINT32 Sdr104:1; // bit 33
> > UINT32 Ddr50:1; // bit 34
> > - UINT32 Reserved4:1; // bit 35
> > + UINT32 Reserved3:1; // bit 35
> > UINT32 DriverTypeA:1; // bit 36
> > UINT32 DriverTypeC:1; // bit 37
> > UINT32 DriverTypeD:1; // bit 38
> > UINT32 DriverType4:1; // bit 39
> > UINT32 TimerCount:4; // bit 40:43
> > - UINT32 Reserved5:1; // bit 44
> > + UINT32 Reserved4:1; // bit 44
> > UINT32 TuningSDR50:1; // bit 45
> > UINT32 RetuningMod:2; // bit 46:47
> > UINT32 ClkMultiplier:8; // bit 48:55
> > - UINT32 Reserved6:7; // bit 56:62
> > + UINT32 Reserved5:7; // bit 56:62
> > UINT32 Hs400:1; // bit 63
> > } SD_MMC_HC_SLOT_CAP;
> >
> > //
> > // SD Host controller version
> > //
> > -#define SD_MMC_HC_CTRL_VER_100 0x00
> > -#define SD_MMC_HC_CTRL_VER_200 0x01
> > -#define SD_MMC_HC_CTRL_VER_300 0x02
> > -#define SD_MMC_HC_CTRL_VER_400 0x03
> > -#define SD_MMC_HC_CTRL_VER_410 0x04
> > -#define SD_MMC_HC_CTRL_VER_420 0x05
> > +#define SD_MMC_HC_CTRL_VER_100 0x00
> > +#define SD_MMC_HC_CTRL_VER_200 0x01
> > +#define SD_MMC_HC_CTRL_VER_300 0x02
> > +#define SD_MMC_HC_CTRL_VER_400 0x03
> > +#define SD_MMC_HC_CTRL_VER_410 0x04
> > +#define SD_MMC_HC_CTRL_VER_420 0x05
> > +
> > +//
> > +// SD Host controller V4 enhancements
> > +//
> > +#define SD_MMC_HC_V4_EN BIT12
> > +#define SD_MMC_HC_64_ADDR_EN BIT13
> > +#define SD_MMC_HC_26_DATA_LEN_ADMA_EN BIT10
> >
> > /**
> > Dump the content of SD/MMC host controller's Capability Register.
> > @@ -323,6 +351,24 @@ SdMmcHcWaitMmioSet (
> > );
> >
> > /**
> > + Get the controller version information from the specified slot.
> > +
> > + @param[in] PciIo The PCI IO protocol instance.
> > + @param[in] Slot The slot number of the SD card to send the
> > command to.
> > + @param[out] Version The buffer to store the version information.
> > +
> > + @retval EFI_SUCCESS The operation executes successfully.
> > + @retval Others The operation fails.
> > +
> > +**/
> > +EFI_STATUS
> > +SdMmcHcGetControllerVersion (
> > + IN EFI_PCI_IO_PROTOCOL *PciIo,
> > + IN UINT8 Slot,
> > + OUT UINT16 *Version
> > + );
> > +
> > +/**
> > Set all interrupt status bits in Normal and Error Interrupt Status Enable
> > register.
> >
> > @@ -424,6 +470,7 @@ SdMmcHcStopClock (
> > @param[in] Slot The slot number of the SD card to send the
> command
> > to.
> > @param[in] ClockFreq The max clock frequency to be set. The unit is
> KHz.
> > @param[in] BaseClkFreq The base clock frequency of host controller in
> > MHz.
> > + @param[in] ControllerVer The version of host controller.
> >
> > @retval EFI_SUCCESS The clock is supplied successfully.
> > @retval Others The clock isn't supplied successfully.
> > @@ -434,7 +481,8 @@ SdMmcHcClockSupply (
> > IN EFI_PCI_IO_PROTOCOL *PciIo,
> > IN UINT8 Slot,
> > IN UINT64 ClockFreq,
> > - IN UINT32 BaseClkFreq
> > + IN UINT32 BaseClkFreq,
> > + IN UINT16 ControllerVer
> > );
> >
> > /**
> > @@ -483,6 +531,7 @@ SdMmcHcSetBusWidth (
> > @param[in] PciIo The PCI IO protocol instance.
> > @param[in] Slot The slot number of the SD card to send the
> command
> > to.
> > @param[in] BaseClkFreq The base clock frequency of host controller in
> > MHz.
> > + @param[in] ControllerVer The version of host controller.
> >
> > @retval EFI_SUCCESS The clock is supplied successfully.
> > @retval Others The clock isn't supplied successfully.
> > @@ -492,7 +541,8 @@ EFI_STATUS
> > SdMmcHcInitClockFreq (
> > IN EFI_PCI_IO_PROTOCOL *PciIo,
> > IN UINT8 Slot,
> > - IN UINT32 BaseClkFreq
> > + IN UINT32 BaseClkFreq,
> > + IN UINT16 ControllerVer
> > );
> >
> > /**
> > --
> > 2.7.4
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
next prev parent reply other threads:[~2019-01-02 6:37 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-18 21:29 [PATCH v7] MdeModulePkg/SdMmcPciHcDxe: Add SDMMC HC v4 and above Support Ashish Singhal
2018-12-19 1:46 ` Wu, Hao A
2018-12-19 20:00 ` Ashish Singhal
2018-12-26 21:24 ` Ashish Singhal
2019-01-02 6:28 ` Wu, Hao A
2019-01-02 6:36 ` Wu, Hao A [this message]
2019-01-02 15:47 ` Ashish Singhal
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=B80AF82E9BFB8E4FBD8C89DA810C6A093C8718CB@SHSMSX104.ccr.corp.intel.com \
--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