* Re: [PATCH 0/2] Add GetOperatingParam notify phase to SdMmcOverride protocol
[not found] ` <B80AF82E9BFB8E4FBD8C89DA810C6A093C8E4722@SHSMSX104.ccr.corp.intel.com>
@ 2019-06-13 13:43 ` mateusz.albecki
2019-06-14 1:46 ` Wu, Hao A
0 siblings, 1 reply; 9+ messages in thread
From: mateusz.albecki @ 2019-06-13 13:43 UTC (permalink / raw)
To: devel@edk2.groups.io; +Cc: Wu, Hao A
[-- Attachment #1: Type: text/plain, Size: 5509 bytes --]
Resending to group.
From: Wu, Hao A
Sent: Monday, June 10, 2019 5:18 AM
To: Albecki, Mateusz <mateusz.albecki@intel.com>
Subject: RE: [PATCH 0/2] Add GetOperatingParam notify phase to SdMmcOverride protocol
Hello Mateusz,
Thanks for the patch series and sorry for the delayed response.
One question first, I did not see the patches being sent to the mailing list
'devel@edk2.groups.io'. We have recently switched to this new mailing list back
to early April, the old one 'edk2-devel@lists.01.org' is no longer being used.
In case that you have not registered the new list, you can sign up at:
https://edk2.groups.io/g/devel
or email:
devel+subscribe@edk2.groups.io<mailto:devel+subscribe@edk2.groups.io>
to get registered in the new mailing list.
Or you can send me the patch files and I will help to send them to the mailing list.
Below are some general level feedbacks (Other patch-specific feedbacks will be replied in other mails):
* Could you help to add the below Bugzilla tracker reference in the commit log message?
https://bugzilla.tianocore.org/show_bug.cgi?id=1882
* Could you help to run the script 'BaseTools/Scripts/PatchCheck.py' and resolve its report on the commit log format issues?
Checking git commit: 6e3f64aeb4
The commit message format is not valid:
* Contributed-under! (Note: this must be removed by the code contributor!)
* Add quotes (") around name with a comma: Albecki, Mateusz
* Email format is invalid: hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>
* Line 15 of commit message is too long.
https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format
The code passed all checks.
Checking git commit: 91595ae911
The commit message format is not valid:
* Contributed-under! (Note: this must be removed by the code contributor!)
* Add quotes (") around name with a comma: Albecki, Mateusz
* Email format is invalid: hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>
https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format
The code passed all checks.
* Could you help to resolve the typo 'Prefered' to 'Preferred' in the naming of some variables?
* Could you help to use lowercase 'static' (instead of using the uppercase one) for the new functions?
Also, I only verified the build of the patch series. Please grant me some time
to verify on the HW on my side. Maybe your updated patches arrive first and I
will then verify the update ones.
Best Regards,
Hao Wu
> -----Original Message-----
> From: Albecki, Mateusz
> Sent: Monday, June 03, 2019 7:34 PM
> Cc: Albecki, Mateusz; Wu, Hao A
> Subject: [PATCH 0/2] Add GetOperatingParam notify phase to
> SdMmcOverride protocol
>
> To allow platform greater control over the bus settings for SD card and
> eMMC card
> we have added a new notify phase to SdMmcOverrideProtocol called
> GetOperatingParam.
> This phase is signaled before SD card/eMMC initialization and allows platform
> to tweak
> the values in new structure called
> EDKII_SD_MMC_OPERATING_PARAMETERS which allows to configure
> bus width, clock frequency and driver strength. Other bus parameters can be
> configured by
> overriding host controller capabilities.
>
> Tests:
> - OS boot from eMMC without SdMmcOverride protocol installed
> - OS boot from eMMC with SdMmcOverride installed and clock frequency
> lowered to 100MHz in HS200
> - OS boot from eMMC with driver strength changed to Type1
> - SD card enumeration in UEFI shell on default speed and high speed(non
> UHS-I) with SdMmcOverride installed and UHS-I disabled in capability
>
>
> Cc: hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>
>
> Albecki, Mateusz (2):
> MdeModulePkg/SdMmcOverride: Add GetOperatingParam notify phase
> MdeModulePkg/SdMmcHcDxe: Implement revision 3 of
> SdMmcOverrideProtocol
>
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c | 522
> +++++++++++++++------
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c | 381
> ++++++++++++---
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c | 52 +-
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h | 18 +-
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c | 8 +-
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h | 8 +-
> MdeModulePkg/Include/Protocol/SdMmcOverride.h | 58 ++-
> 7 files changed, 802 insertions(+), 245 deletions(-)
>
> --
> 2.14.1.windows.1
--------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek
przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by
others is strictly prohibited.
[-- Attachment #2: Type: text/html, Size: 19982 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] MdeModulePkg/SdMmcOverride: Add GetOperatingParam notify phase
[not found] ` <B80AF82E9BFB8E4FBD8C89DA810C6A093C8E4729@SHSMSX104.ccr.corp.intel.com>
@ 2019-06-13 13:56 ` Albecki, Mateusz
0 siblings, 0 replies; 9+ messages in thread
From: Albecki, Mateusz @ 2019-06-13 13:56 UTC (permalink / raw)
To: devel@edk2.groups.io; +Cc: Wu, Hao A
Resending to group.
> -----Original Message-----
> From: Wu, Hao A
> Sent: Monday, June 10, 2019 5:19 AM
> To: Albecki, Mateusz <mateusz.albecki@intel.com>
> Subject: RE: [PATCH 1/2] MdeModulePkg/SdMmcOverride: Add
> GetOperatingParam notify phase
>
> Thanks Mateusz,
>
> Please refer to the comments in patch 2/2 for the reorder in definition
> 'SD_MMC_BUS_MODE'.
>
> Also, some inline comments below:
>
> Best Regards,
> Hao Wu
>
>
> > -----Original Message-----
> > From: Albecki, Mateusz
> > Sent: Monday, June 03, 2019 7:34 PM
> > Cc: Albecki, Mateusz; Wu, Hao A; Albecki
> > Subject: [PATCH 1/2] MdeModulePkg/SdMmcOverride: Add
> GetOperatingParam
> > notify phase
> >
> > The new notify phase allows platform to configure additional bus
> > parameters in addition to parameters that can already be configured
> > with capability override. Specifically we allow to configure bus
> > width, clock frequency and driver strength. If platform doesn't wish
> > to configure some of the parameters it can left it on default values
> > and driver will assume it's standard behavior with respect to those
> parameters.
> > The definition of the SD_MMC_BUS_MODE has been extended to
> incorporate
> > SD card default speed and high speed.
> >
> > Cc: hao.a.wu@intel.com
> > Signed-off-by: Albecki, Mateusz <mateusz.albecki@intel.com>
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > ---
> > MdeModulePkg/Include/Protocol/SdMmcOverride.h | 58
> > ++++++++++++++++++++++++---
> > 1 file changed, 52 insertions(+), 6 deletions(-)
> >
> > diff --git a/MdeModulePkg/Include/Protocol/SdMmcOverride.h
> > b/MdeModulePkg/Include/Protocol/SdMmcOverride.h
> > index 9c8bf37efd..bb9545c80c 100644
> > --- a/MdeModulePkg/Include/Protocol/SdMmcOverride.h
> > +++ b/MdeModulePkg/Include/Protocol/SdMmcOverride.h
> > @@ -16,14 +16,61 @@
> > #define EDKII_SD_MMC_OVERRIDE_PROTOCOL_GUID \
> > { 0xeaf9e3c1, 0xc9cd, 0x46db, { 0xa5, 0xe5, 0x5a, 0x12, 0x4c, 0x83,
> > 0x23,
> > 0x23 } }
> >
> > -#define EDKII_SD_MMC_OVERRIDE_PROTOCOL_VERSION 0x2
> > +#define EDKII_SD_MMC_OVERRIDE_PROTOCOL_VERSION 0x3
> >
> > typedef struct _EDKII_SD_MMC_OVERRIDE EDKII_SD_MMC_OVERRIDE;
> >
> > -//
> > -// Bus timing modes
> > -//
> > +#define EDKII_SD_MMC_BUS_WIDTH_IGNORE MAX_UINT16 #define
> > +EDKII_SD_MMC_CLOCK_FREQ_IGNORE MAX_UINT32 #define
> > +EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE MAX_UINT8
> > +
> > +typedef enum {
> > + SdDriverStrengthTypeB = 0,
> > + SdDriverStrengthTypeA,
> > + SdDriverStrengthTypeC,
> > + SdDriverStrengthTypeD,
> > + SdDriverStrengthIgnore = EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE
> > +} SD_DRIVER_STRENGTH_TYPE;
> > +
> > typedef enum {
> > + EmmcDriverStrengthType0 = 0,
> > + EmmcDriverStrengthType1,
> > + EmmcDriverStrengthType2,
> > + EmmcDriverStrengthType3,
> > + EmmcDriverStrengthType4,
> > + EmmcDriverStrengthIgnore =
> > EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE
> > +} EMMC_DRIVER_STRENGTH_TYPE;
> > +
> > +typedef union {
> > + SD_DRIVER_STRENGTH_TYPE Sd;
> > + EMMC_DRIVER_STRENGTH_TYPE Emmc;
> > +} EDKII_SD_MMC_DRIVER_STRENGTH;
> > +
> > +typedef struct {
> > + //
> > + // The target width of the bus. If user tells driver to ignore it
> > + // or specifies unsuportted width driver will choose highest
> > +supported
>
>
> unsuportted -> unsupported
>
>
> > + // bus width for a given mode.
> > + //
> > + UINT16 BusWidth;
>
>
> After seeing some type changes (from UINT8 to UINT16) for some variables
> in the 2nd patch, I realize that the 'BusWidth' type should be UINT8 here and
> the 'EDKII_SD_MMC_BUS_WIDTH_IGNORE' definition should be
> MAX_UINT8.
>
> I am really sorry for the typo I made in the foil sent to you.
>
>
> > + //
> > + // The target clock frequency of the bus in MHz. If user tells
> > + driver to
> > ignore
> > + // it or specifies unsupported frequency driver will choose highest
> > supported
> > + // clock frequency for a given mode.
> > + //
> > + UINT32 ClockFreq;
> > + //
> > + // The target driver strength of the bus. If user tells driver to
> > + // ignore it or specifies unsupported driver strength, driver will
> > + // default to Type0 for eMMC cards and TypeB for SD cards. Driver
> > strength
> > + // setting is only considered if choosen bus timing supports them.
>
>
> choosen -> chosen
>
> Best Regards,
> Hao Wu
>
>
> > + //
> > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength; }
> > +EDKII_SD_MMC_OPERATING_PARAMETERS;
> > +
> > +typedef enum {
> > + SdMmcSdDs,
> > + SdMmcSdHs,
> > SdMmcUhsSdr12,
> > SdMmcUhsSdr25,
> > SdMmcUhsSdr50,
> > @@ -43,10 +90,10 @@ typedef enum {
> > EdkiiSdMmcInitHostPost,
> > EdkiiSdMmcUhsSignaling,
> > EdkiiSdMmcSwitchClockFreqPost,
> > + EdkiiSdMmcGetOperatingParam
> > } EDKII_SD_MMC_PHASE_TYPE;
> >
> > /**
> > -
> > Override function for SDHCI capability bits
> >
> > @param[in] ControllerHandle The EFI_HANDLE of the controller.
> > @@ -70,7 +117,6 @@ EFI_STATUS
> > );
> >
> > /**
> > -
> > Override function for SDHCI controller operations
> >
> > @param[in] ControllerHandle The EFI_HANDLE of the controller.
> > --
> > 2.14.1.windows.1
--------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek
przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by
others is strictly prohibited.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement revision 3 of SdMmcOverrideProtocol
[not found] ` <B80AF82E9BFB8E4FBD8C89DA810C6A093C8E473C@SHSMSX104.ccr.corp.intel.com>
@ 2019-06-13 14:38 ` Albecki, Mateusz
2019-06-14 3:14 ` Wu, Hao A
[not found] ` <15A7C8F163ADE317.25258@groups.io>
1 sibling, 1 reply; 9+ messages in thread
From: Albecki, Mateusz @ 2019-06-13 14:38 UTC (permalink / raw)
To: devel@edk2.groups.io; +Cc: Wu, Hao A
Resending to group. Inline reply to some of the comments.
As for the mapping between eMMC driver strength and SD controller driver strength should we use this one:
SD controller -> eMMC card
B -> Type 0
A -> Type 1
C -> Type 2
D -> Type 3
(none) -> Type4
And Type 4 would be identified by bit 39 in capability register which is currently marked as reserved in SD controller specification. This is current capability register definition in the driver.
Thanks,
Mateusz
> -----Original Message-----
> From: Wu, Hao A
> Sent: Monday, June 10, 2019 5:19 AM
> To: Albecki, Mateusz <mateusz.albecki@intel.com>
> Subject: RE: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement revision
> 3 of SdMmcOverrideProtocol
>
> Hello Mateusz,
>
> Some inline comments below:
>
> > -----Original Message-----
> > From: Albecki, Mateusz
> > Sent: Monday, June 03, 2019 7:34 PM
> > Cc: Albecki, Mateusz; Wu, Hao A; Albecki
> > Subject: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement revision 3
> > of SdMmcOverrideProtocol
> >
> > Implement support for GetOperatingParamters notify phase
> > in SdMmcHcDxe driver. GetOperatingParameters notify phase
> > is signaled before we start card detection and initialization.
> > Code has been updated for both eMMC and SD card controllers to
> > take into consideration those new parameters. Initialization process
> > has been divided into 2 steps. In the first step we bring the link
> > up to the point where we can get card identification data(Extended
> > CSD in eMMC case and SWITCH command response in SD card case). This
> > data is later used along with controller capabilities and operating
> > parameters passed in GetOperatingParameters phase to choose preferred
> > bus settings in GetTargetBusSettings function. Those settings are later
> > on to start bus training to high speeds. If user passes incompatible
> > setting with selected bus timing driver will assume it's standard behavior
> with
> > respect to that setting. For instance if HS400 has been selected as a
> > target bus timing due to card and controller support bus width setting of
> > 4 and 1 bit won't be respected and 8 bit setting will be chosen instead.
> >
> >
> > Cc: hao.a.wu@intel.com
> > Signed-off-by: Albecki, Mateusz <mateusz.albecki@intel.com>
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > ---
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c | 522
> > +++++++++++++++------
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c | 381
> > ++++++++++++---
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c | 52 +-
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h | 18 +-
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c | 8 +-
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h | 8 +-
> > 6 files changed, 750 insertions(+), 239 deletions(-)
> >
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > index deaf4468c9..1a81f6d250 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > @@ -449,7 +449,7 @@ EFI_STATUS
> > EmmcSendTuningBlk (
> > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > IN UINT8 Slot,
> > - IN UINT8 BusWidth
> > + IN UINT16 BusWidth
> > )
> > {
> > EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
> > @@ -506,7 +506,7 @@ EmmcTuningClkForHs200 (
> > IN EFI_PCI_IO_PROTOCOL *PciIo,
> > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > IN UINT8 Slot,
> > - IN UINT8 BusWidth
> > + IN UINT16 BusWidth
> > )
> > {
> > EFI_STATUS Status;
> > @@ -583,7 +583,7 @@ EmmcSwitchBusWidth (
> > IN UINT8 Slot,
> > IN UINT16 Rca,
> > IN BOOLEAN IsDdr,
> > - IN UINT8 BusWidth
> > + IN UINT16 BusWidth
> > )
> > {
> > EFI_STATUS Status;
> > @@ -641,13 +641,13 @@ EmmcSwitchBusWidth (
> > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6 and SD Host
> > Controller
> > Simplified Spec 3.0 Figure 3-3 for details.
> >
> > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
> > - @param[in] PassThru A pointer to the
> > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > - @param[in] Slot The slot number of the SD card to send the
> command
> > to.
> > - @param[in] Rca The relative device address to be assigned.
> > - @param[in] HsTiming The value to be written to HS_TIMING field of
> > EXT_CSD register.
> > - @param[in] Timing The bus mode timing indicator.
> > - @param[in] ClockFreq The max clock frequency to be set, the unit is
> > MHz.
> > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
> > + @param[in] PassThru A pointer to the
> > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > + @param[in] Slot The slot number of the SD card to send the
> > command to.
> > + @param[in] Rca The relative device address to be assigned.
> > + @param[in] DriverStrength Driver strength to set for speed modes that
> > support it.
> > + @param[in] Timing The bus mode timing indicator.
>
>
> Please help to update the parameter comment to reflect the name change
> from
> 'Timing' to 'BusTiming'.
>
>
> > + @param[in] ClockFreq The max clock frequency to be set, the unit is
> > MHz.
> >
> > @retval EFI_SUCCESS The operation is done correctly.
> > @retval Others The operation fails.
> > @@ -659,8 +659,8 @@ EmmcSwitchBusTiming (
> > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > IN UINT8 Slot,
> > IN UINT16 Rca,
> > - IN UINT8 HsTiming,
> > - IN SD_MMC_BUS_MODE Timing,
> > + IN EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength,
> > + IN SD_MMC_BUS_MODE BusTiming,
> > IN UINT32 ClockFreq
> > )
> > {
> > @@ -678,12 +678,29 @@ EmmcSwitchBusTiming (
> > //
> > Access = 0x03;
> > Index = OFFSET_OF (EMMC_EXT_CSD, HsTiming);
> > - Value = HsTiming;
> > CmdSet = 0;
> > + switch (BusTiming) {
> > + case SdMmcMmcHs400:
> > + Value = (UINT8)((DriverStrength.Emmc << 4) | 3);
> > + break;
> > + case SdMmcMmcHs200:
> > + Value = (UINT8)((DriverStrength.Emmc << 4) | 2);
> > + break;
> > + case SdMmcMmcHsSdr:
> > + case SdMmcMmcHsDdr:
> > + Value = 1;
> > + break;
> > + case SdMmcMmcLegacy:
> > + Value = 0;
> > + break;
> > + default:
> > + DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Unsupported
> > BusTiming(%d\n)", BusTiming));
> > + return EFI_INVALID_PARAMETER;
> > + }
> >
> > Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);
> > if (EFI_ERROR (Status)) {
> > - DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to hstiming %d
> > fails with %r\n", HsTiming, Status));
> > + DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to bus
> > timing %d fails with %r\n", BusTiming, Status));
> > return Status;
> > }
> >
> > @@ -713,7 +730,7 @@ EmmcSwitchBusTiming (
> > Private->ControllerHandle,
> > Slot,
> > EdkiiSdMmcSwitchClockFreqPost,
> > - &Timing
> > + &BusTiming
> > );
> > if (EFI_ERROR (Status)) {
> > DEBUG ((
> > @@ -754,25 +771,34 @@ EmmcSwitchToHighSpeed (
>
>
> Please help to update the function comments for
> EmmcSwitchToHighSpeed() after
> the parameter changes.
>
>
> > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > IN UINT8 Slot,
> > IN UINT16 Rca,
> > - IN UINT32 ClockFreq,
> > - IN BOOLEAN IsDdr,
> > - IN UINT8 BusWidth
> > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > )
> > {
> > EFI_STATUS Status;
> > - UINT8 HsTiming;
> > UINT8 HostCtrl1;
> > - SD_MMC_BUS_MODE Timing;
> > SD_MMC_HC_PRIVATE_DATA *Private;
> > + BOOLEAN IsDdr;
> >
> > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> >
> > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr,
> BusWidth);
> > + if ((BusMode->BusTiming != SdMmcMmcHsSdr && BusMode-
> > >BusTiming != SdMmcMmcHsDdr) ||
> > + BusMode->ClockFreq > 52) {
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + if (BusMode->BusTiming == SdMmcMmcHsDdr) {
> > + IsDdr = TRUE;
> > + } else {
> > + IsDdr = FALSE;
> > + }
> > +
> > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr,
> BusMode-
> > >BusWidth);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> > +
> > //
> > - // Set to Hight Speed timing
> > + // Set to High Speed timing
> > //
> > HostCtrl1 = BIT2;
> > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, sizeof
> > (HostCtrl1), &HostCtrl1);
> > @@ -780,37 +806,27 @@ EmmcSwitchToHighSpeed (
> > return Status;
> > }
> >
> > - if (IsDdr) {
> > - Timing = SdMmcMmcHsDdr;
> > - } else if (ClockFreq == 52) {
> > - Timing = SdMmcMmcHsSdr;
> > - } else {
> > - Timing = SdMmcMmcLegacy;
> > - }
> > -
> > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > Timing);
> > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > BusMode->BusTiming);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> >
> > - HsTiming = 1;
> > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> Timing,
> > ClockFreq);
> > -
> > - return Status;
> > + return EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
> > }
> >
> > /**
> > - Switch to the HS200 timing according to request.
> > + Switch to the HS200 timing. This function assumes that eMMC bus is still
> in
> > legacy mode.
> >
> > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host
> > Controller
> > Simplified Spec 3.0 Figure 2-29 for details.
> >
> > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
> > - @param[in] PassThru A pointer to the
> > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > - @param[in] Slot The slot number of the SD card to send the
> command
> > to.
> > - @param[in] Rca The relative device address to be assigned.
> > - @param[in] ClockFreq The max clock frequency to be set.
> > - @param[in] BusWidth The bus width to be set, it could be 4 or 8.
> > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
> > + @param[in] PassThru A pointer to the
> > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > + @param[in] Slot The slot number of the SD card to send the
> > command to.
> > + @param[in] Rca The relative device address to be assigned.
> > + @param[in] DriverStrength The driver strength to be selected.
> > + @param[in] ClockFreq The max clock frequency to be set.
> > + @param[in] BusWidth The bus width to be set, it could be 4 or 8.
> >
> > @retval EFI_SUCCESS The operation is done correctly.
> > @retval Others The operation fails.
> > @@ -822,30 +838,25 @@ EmmcSwitchToHS200 (
>
>
> Please help to update the function comments for EmmcSwitchToHS200()
> after the
> parameter changes.
>
>
> > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > IN UINT8 Slot,
> > IN UINT16 Rca,
> > - IN UINT32 ClockFreq,
> > - IN UINT8 BusWidth
> > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > )
> > {
> > EFI_STATUS Status;
> > - UINT8 HsTiming;
> > UINT16 ClockCtrl;
> > - SD_MMC_BUS_MODE Timing;
> > SD_MMC_HC_PRIVATE_DATA *Private;
> >
> > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> >
> > - if ((BusWidth != 4) && (BusWidth != 8)) {
> > + if (BusMode->BusTiming != SdMmcMmcHs200 ||
> > + (BusMode->BusWidth != 4 && BusMode->BusWidth != 8)) {
> > return EFI_INVALID_PARAMETER;
> > }
> >
> > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE,
> BusWidth);
> > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE,
> > BusMode->BusWidth);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> > //
> > - // Set to HS200/SDR104 timing
> > - //
> > - //
> > // Stop bus clock at first
> > //
> > Status = SdMmcHcStopClock (PciIo, Slot);
> > @@ -853,9 +864,7 @@ EmmcSwitchToHS200 (
> > return Status;
> > }
> >
> > - Timing = SdMmcMmcHs200;
> > -
> > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > Timing);
> > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > BusMode->BusTiming);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> > @@ -881,28 +890,27 @@ EmmcSwitchToHS200 (
> > ClockCtrl = BIT2;
> > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof
> > (ClockCtrl), &ClockCtrl);
> >
> > - HsTiming = 2;
> > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> Timing,
> > ClockFreq);
> > + Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
>
>
> After the proposed change, the preferred bus timing and driver strength
> value
> will be set for the device through the EMMC_SWITCH command.
>
> However, on the host controller side, only the bus timing value is also
> updated
> in the Host Control 2 Register of the SD HC (via function
> SdMmcHcUhsSignaling()).
> It seems to me that the driver strength value does not get updated in this
> register.
>
> I think the SD case has a similar issue.
For SD I agree that there is an issue but for eMMC there is no clear mapping between
eMMC defined driver strength types and SD defined driver strength types. The controller
I happen to be working with seems to ignore the values in this register. If we can agree on
one mapping that will be able to service majority of the eMMC controllers on market I don't
mind adding that. We can maybe add driver strength setting to SdMmcHcUhsSignaling so that
platform has an opportunity to correct core driver during EdkiiSdMmcUhsSignaling notify.
>
>
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> >
> > - Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth);
> > + Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusMode-
> > >BusWidth);
> >
> > return Status;
> > }
> >
> > /**
> > - Switch to the HS400 timing according to request.
> > + Switch to the HS400 timing. This function assumes that eMMC bus is still
> in
> > legacy mode.
> >
> > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host
> > Controller
> > Simplified Spec 3.0 Figure 2-29 for details.
> >
> > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
> > - @param[in] PassThru A pointer to the
> > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > - @param[in] Slot The slot number of the SD card to send the
> command
> > to.
> > - @param[in] Rca The relative device address to be assigned.
> > - @param[in] ClockFreq The max clock frequency to be set.
> > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
> > + @param[in] PassThru A pointer to the
> > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > + @param[in] Slot The slot number of the SD card to send the
> > command to.
> > + @param[in] Rca The relative device address to be assigned.
> > + @param[in] ClockFreq The max clock frequency to be set.
>
>
> Please help to update the function comments for EmmcSwitchToHS400()
> after the
> parameter changes.
>
>
> >
> > @retval EFI_SUCCESS The operation is done correctly.
> > @retval Others The operation fails.
> > @@ -914,47 +922,321 @@ EmmcSwitchToHS400 (
> > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > IN UINT8 Slot,
> > IN UINT16 Rca,
> > - IN UINT32 ClockFreq
> > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > )
> > {
> > EFI_STATUS Status;
> > - UINT8 HsTiming;
> > - SD_MMC_BUS_MODE Timing;
> > SD_MMC_HC_PRIVATE_DATA *Private;
> > + EDKII_SD_MMC_BUS_MODE Hs200BusMode;
> > + UINT32 HsFreq;
> > +
> > + if (BusMode->BusTiming != SdMmcMmcHs400 ||
> > + BusMode->BusWidth != 8) {
> > + return EFI_INVALID_PARAMETER;
> > + }
> >
> > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > + Hs200BusMode.BusTiming = SdMmcMmcHs200;
> > + Hs200BusMode.BusWidth = BusMode->BusWidth;
> > + Hs200BusMode.ClockFreq = BusMode->ClockFreq;
> > + Hs200BusMode.DriverStrength = BusMode->DriverStrength;
> >
> > - Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, 8);
> > + Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca,
> &Hs200BusMode);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> > +
> > //
> > - // Set to Hight Speed timing and set the clock frequency to a value less
> than
> > 52MHz.
> > + // Set to High Speed timing and set the clock frequency to a value less
> than
> > or equal to 52MHz.
> > + // This step is necessary to be able to switch Bus into 8 bit DDR mode
> which
> > is unsupported in HS200.
> > //
> > - HsTiming = 1;
> > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > SdMmcMmcHsSdr, 52);
> > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > SdMmcMmcHsSdr);
>
>
> The above SdMmcHcUhsSignaling() is newly added, is this a bug for the origin
> code?
>
> I searched the eMMC spec, it seems to me the spec does not explicitly
> mention
> the Host Control 2 Register at all, I am not very sure if such change will
> bring any effect to devices. Did you have a try without adding such change?
>
This is aligned to the behavior of EmmcSwitchToHighSpeed function. My eMMC
controller doesn't need this register to be programmed for switch to high speed
but calling SdMmcUhsSignaling here gives override protocol a chance to finish
switch to high speed for eMMC controllers that need such tweaking.
>
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> > - //
> > - // HS400 mode must use 8 data lines.
> > - //
> > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, TRUE, 8);
> > +
> > + HsFreq = BusMode->ClockFreq < 52 ? BusMode->ClockFreq : 52;
> > + Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > >DriverStrength, SdMmcMmcHsSdr, HsFreq);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> >
> > - Timing = SdMmcMmcHs400;
> > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, TRUE,
> BusMode-
> > >BusWidth);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> >
> > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > Timing);
> > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > BusMode->BusTiming);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> >
> > - HsTiming = 3;
> > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> Timing,
> > ClockFreq);
> > + return EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
>
>
> After the proposed change, the preferred bus timing and driver strength
> value
> will be set for the device through the EMMC_SWITCH command.
>
> However, on the host controller side, only the bus timing value is also
> updated
> in the Host Control 2 Register of the SD HC (via function
> SdMmcHcUhsSignaling()).
> It seems to me that the driver strength value does not get updated in this
> register.
>
> I think the SD case has a similar issue.
>
>
> > +}
> >
> > - return Status;
> > +/**
> > + Check if passed BusTiming is supported in both controller and card.
> > +
> > + @param[in] Private Pointer to controller private data
> > + @param[in] SlotIndex Index of the slot in the controller
> > + @param[in] ExtCsd Pointer to the card's extended CSD
> > + @param[in] BusTiming Bus timing to check
> > +
> > + @retval TRUE Both card and controller support given BusTiming
> > + @retval FALSE Card or controller doesn't support given BusTiming
> > +**/
> > +STATIC
> > +BOOLEAN
> > +IsBusTimingSupported (
>
>
> How about renaming it to EmmcIsBusTimingSupported()?
>
>
> > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > + IN UINT8 SlotIndex,
> > + IN EMMC_EXT_CSD *ExtCsd,
> > + IN SD_MMC_BUS_MODE BusTiming
> > + )
> > +{
> > + BOOLEAN Supported;
> > + SD_MMC_HC_SLOT_CAP *Capabilities;
> > +
> > + Capabilities = &Private->Capability[SlotIndex];
> > +
> > + Supported = FALSE;
> > + switch (BusTiming) {
> > + case SdMmcMmcHs400:
> > + if ((((ExtCsd->DeviceType & (BIT6 | BIT7)) != 0) && (Capabilities-
> > >Hs400 != 0)) && Capabilities->BusWidth8) {
> > + Supported = TRUE;
> > + }
> > + break;
> > + case SdMmcMmcHs200:
> > + if ((((ExtCsd->DeviceType & (BIT4 | BIT5)) != 0) && (Capabilities-
> > >Sdr104 != 0))) {
> > + Supported = TRUE;
> > + }
> > + break;
> > + case SdMmcMmcHsDdr:
> > + if ((((ExtCsd->DeviceType & (BIT2 | BIT3)) != 0) && (Capabilities-
> > >Ddr50 != 0))) {
> > + Supported = TRUE;
> > + }
> > + break;
> > + case SdMmcMmcHsSdr:
> > + if ((((ExtCsd->DeviceType & BIT1) != 0) && (Capabilities->HighSpeed !=
> > 0))) {
> > + Supported = TRUE;
> > + } else if ((((ExtCsd->DeviceType & BIT0) != 0) && (Capabilities-
> > >HighSpeed != 0))) {
>
>
> For this case, I think the bus timing should be classified to SdMmcMmcLegacy.
> Since under this timing, the maximum frequency allowed is 26Mhz. If set to
> SdMmcMmcHsSdr the driver will try to set the frequency to 52Mhz later in
> EmmcGetTargetClockFreq().
>
>
> > + Supported = TRUE;
> > + }
> > + break;
> > + case SdMmcMmcLegacy:
> > + Supported = TRUE;
> > + break;
> > + default:
> > + ASSERT (FALSE);
> > + }
> > +
> > + return Supported;
> > +}
> > +
> > +/**
> > + Get the target bus timing to set on the link. This function
> > + will try to select highest bus timing supported by card, controller
> > + and the driver.
> > +
> > + @param[in] Private Pointer to controller private data
> > + @param[in] SlotIndex Index of the slot in the controller
> > + @param[in] ExtCsd Pointer to the card's extended CSD
> > +
> > + @return Bus timing value that should be set on link
> > +**/
> > +STATIC
> > +SD_MMC_BUS_MODE
> > +EmmcGetTargetBusTiming (
> > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > + IN UINT8 SlotIndex,
> > + IN EMMC_EXT_CSD *ExtCsd
> > + )
> > +{
> > + SD_MMC_BUS_MODE BusTiming;
> > +
> > + //
> > + // We start with highest bus timing that this driver currently support and
> > + // return as soon as we find supported timing.
> > + //
> > + BusTiming = SdMmcMmcHs400;
> > + while (BusTiming > SdMmcMmcLegacy) {
> > + if (IsBusTimingSupported (Private, SlotIndex, ExtCsd, BusTiming)) {
> > + break;
> > + }
> > + BusTiming--;
> > + }
> > +
> > + return BusTiming;
> > +}
> > +
> > +/**
> > + Check if the passed bus width is supported by controller and card.
> > +
> > + @param[in] Private Pointer to controller private data
> > + @param[in] SlotIndex Index of the slot in the controller
> > + @param[in] BusTiming Bus timing set on the link
> > + @param[in] BusWidth Bus width to check
> > +
> > + @retval TRUE Passed bus width is supported in current bus
> configuration
> > + @retval FALSE Passed bus width is not supported in current bus
> > configuration
> > +**/
> > +STATIC
> > +BOOLEAN
> > +IsBusWidthSupported (
> > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > + IN UINT8 SlotIndex,
> > + IN SD_MMC_BUS_MODE BusTiming,
> > + IN UINT16 BusWidth
> > + )
> > +{
> > + if (BusWidth == 8 && Private->Capability[SlotIndex].BusWidth8) {
> > + return TRUE;
> > + } else if (BusWidth == 4 && BusTiming != SdMmcMmcHs400) {
> > + return TRUE;
> > + } else if (BusWidth == 1 && (BusTiming == SdMmcMmcHsSdr ||
> BusTiming
> > == SdMmcMmcLegacy)) {
> > + return TRUE;
> > + }
> > +
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Get the target bus width to be set on the bus.
> > +
> > + @param[in] Private Pointer to controller private data
> > + @param[in] SlotIndex Index of the slot in the controller
> > + @param[in] ExtCsd Pointer to card's extended CSD
> > + @param[in] BusTiming Bus timing set on the bus
> > +
> > + @return Bus width to be set on the bus
> > +**/
> > +STATIC
> > +UINT16
> > +EmmcGetTargetBusWidth (
> > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > + IN UINT8 SlotIndex,
> > + IN EMMC_EXT_CSD *ExtCsd,
> > + IN SD_MMC_BUS_MODE BusTiming
> > + )
> > +{
> > + UINT16 BusWidth;
> > + UINT16 PreferedBusWidth;
> > +
> > + PreferedBusWidth = Private-
> > >Slot[SlotIndex].OperatingParameters.BusWidth;
> > +
> > + if (PreferedBusWidth != EDKII_SD_MMC_BUS_WIDTH_IGNORE &&
> > + IsBusWidthSupported (Private, SlotIndex, BusTiming,
> > PreferedBusWidth)) {
> > + BusWidth = PreferedBusWidth;
> > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 8)) {
> > + BusWidth = 8;
> > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 4)) {
> > + BusWidth = 4;
> > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 1)) {
> > + BusWidth = 1;
> > + }
> > +
> > + return BusWidth;
> > +}
> > +
> > +/**
> > + Get the target clock frequency to be set on the bus.
> > +
> > + @param[in] Private Pointer to controller private data
> > + @param[in] SlotIndex Index of the slot in the controller
> > + @param[in] ExtCsd Pointer to card's extended CSD
> > + @param[in] BusTiming Bus timing to be set on the bus
> > +
> > + @return Value of the clock frequency to be set on bus in MHz
> > +**/
> > +STATIC
> > +UINT32
> > +EmmcGetTargetClockFreq (
> > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > + IN UINT8 SlotIndex,
> > + IN EMMC_EXT_CSD *ExtCsd,
> > + IN SD_MMC_BUS_MODE BusTiming
> > + )
> > +{
> > + UINT32 PreferedClockFreq;
> > + UINT32 MaxClockFreq;
> > +
> > + PreferedClockFreq = Private-
> > >Slot[SlotIndex].OperatingParameters.ClockFreq;
> > +
> > + switch (BusTiming) {
> > + case SdMmcMmcHs400:
> > + case SdMmcMmcHs200:
> > + MaxClockFreq = 200;
> > + break;
> > + case SdMmcMmcHsSdr:
> > + case SdMmcMmcHsDdr:
> > + MaxClockFreq = 52;
> > + break;
> > + default:
> > + MaxClockFreq = 26;
> > + break;
> > + }
> > +
> > + if (PreferedClockFreq != EDKII_SD_MMC_CLOCK_FREQ_IGNORE &&
> > PreferedClockFreq < MaxClockFreq) {
> > + return PreferedClockFreq;
> > + } else {
> > + return MaxClockFreq;
> > + }
> > +}
> > +
> > +/**
> > + Get the driver strength to be set on bus
>
> Please help to append a '.' character for the above line.
> It is required for the edk2 coding style.
>
>
> > +
> > + @param[in] Private Pointer to controller private data
> > + @param[in] SlotIndex Index of the slot in the controller
> > + @param[in] ExtCsd Pointer to card's extended CSD
> > + @param[in] BusTiming Bus timing set on the bus
> > +
> > + @return Value of the driver strength to be set on the bus
> > +**/
> > +STATIC
> > +EDKII_SD_MMC_DRIVER_STRENGTH
> > +EmmcGetTargetDriverStrength (
> > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > + IN UINT8 SlotIndex,
> > + IN EMMC_EXT_CSD *ExtCsd,
> > + IN SD_MMC_BUS_MODE BusTiming
> > + )
> > +{
> > + EDKII_SD_MMC_DRIVER_STRENGTH PreferedDriverStrength;
> > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > +
> > + PreferedDriverStrength = Private-
> > >Slot[SlotIndex].OperatingParameters.DriverStrength;
> > + DriverStrength.Emmc = EmmcDriverStrengthType0;
> > +
> > + if (PreferedDriverStrength.Emmc !=
> > EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE &&
> > + (ExtCsd->DriverStrength & (BIT0 << PreferedDriverStrength.Emmc))) {
>
>
> The host controller also has a capability for different types of driver strength.
> (Capabilities Register, bit 36~38)
>
> The check should take it into consideration as well.
For SD it should. For eMMC it's not as obvious since as I mentioned we don't have a mapping defined.
If we agree on one we can add this and for all eMMC controllers that won't follow it I guess we can
leave it to the platform code to override capabilities.
>
>
> > + DriverStrength.Emmc = PreferedDriverStrength.Emmc;
> > + }
> > +
> > + return DriverStrength;
> > +}
> > +
> > +/**
> > + Get the target settings for the bus mode.
> > +
> > + @param[in] Private Pointer to controller private data
> > + @param[in] SlotIndex Index of the slot in the controller
> > + @param[in] ExtCsd Pointer to card's extended CSD
> > + @param[out] BusMode Target configuration of the bus
> > +**/
> > +STATIC
> > +VOID
> > +EmmcGetTargetBusMode (
> > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > + IN UINT8 SlotIndex,
> > + IN EMMC_EXT_CSD *ExtCsd,
> > + OUT EDKII_SD_MMC_BUS_MODE *BusMode
> > + )
> > +{
> > + BusMode->BusTiming = EmmcGetTargetBusTiming (Private, SlotIndex,
> > ExtCsd);
> > + BusMode->BusWidth = EmmcGetTargetBusWidth (Private, SlotIndex,
> > ExtCsd, BusMode->BusTiming);
> > + BusMode->ClockFreq = EmmcGetTargetClockFreq (Private, SlotIndex,
> > ExtCsd, BusMode->BusTiming);
> > + BusMode->DriverStrength = EmmcGetTargetDriverStrength (Private,
> > SlotIndex, ExtCsd, BusMode->BusTiming);
> > }
> >
> > /**
> > @@ -983,10 +1265,7 @@ EmmcSetBusMode (
> > EFI_STATUS Status;
> > EMMC_CSD Csd;
> > EMMC_EXT_CSD ExtCsd;
> > - UINT8 HsTiming;
> > - BOOLEAN IsDdr;
> > - UINT32 ClockFreq;
> > - UINT8 BusWidth;
> > + EDKII_SD_MMC_BUS_MODE BusMode;
> > SD_MMC_HC_PRIVATE_DATA *Private;
> >
> > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > @@ -1004,85 +1283,30 @@ EmmcSetBusMode (
> > }
> >
> > ASSERT (Private->BaseClkFreq[Slot] != 0);
> > +
> > //
> > - // Check if the Host Controller support 8bits bus width.
> > - //
> > - if (Private->Capability[Slot].BusWidth8 != 0) {
> > - BusWidth = 8;
> > - } else {
> > - BusWidth = 4;
> > - }
> > - //
> > - // Get Deivce_Type from EXT_CSD register.
> > + // Get Device_Type from EXT_CSD register.
> > //
> > Status = EmmcGetExtCsd (PassThru, Slot, &ExtCsd);
> > if (EFI_ERROR (Status)) {
> > DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetExtCsd fails
> with %r\n",
> > Status));
> > return Status;
> > }
> > - //
> > - // Calculate supported bus speed/bus width/clock frequency.
> > - //
> > - HsTiming = 0;
> > - IsDdr = FALSE;
> > - ClockFreq = 0;
> > - if (((ExtCsd.DeviceType & (BIT4 | BIT5)) != 0) && (Private-
> > >Capability[Slot].Sdr104 != 0)) {
> > - HsTiming = 2;
> > - IsDdr = FALSE;
> > - ClockFreq = 200;
> > - } else if (((ExtCsd.DeviceType & (BIT2 | BIT3)) != 0) && (Private-
> > >Capability[Slot].Ddr50 != 0)) {
> > - HsTiming = 1;
> > - IsDdr = TRUE;
> > - ClockFreq = 52;
> > - } else if (((ExtCsd.DeviceType & BIT1) != 0) && (Private-
> > >Capability[Slot].HighSpeed != 0)) {
> > - HsTiming = 1;
> > - IsDdr = FALSE;
> > - ClockFreq = 52;
> > - } else if (((ExtCsd.DeviceType & BIT0) != 0) && (Private-
> > >Capability[Slot].HighSpeed != 0)) {
> > - HsTiming = 1;
> > - IsDdr = FALSE;
> > - ClockFreq = 26;
> > - }
> > - //
> > - // Check if both of the device and the host controller support HS400 DDR
> > mode.
> > - //
> > - if (((ExtCsd.DeviceType & (BIT6 | BIT7)) != 0) && (Private-
> > >Capability[Slot].Hs400 != 0)) {
> > - //
> > - // The host controller supports 8bits bus.
> > - //
> > - ASSERT (BusWidth == 8);
> > - HsTiming = 3;
> > - IsDdr = TRUE;
> > - ClockFreq = 200;
> > - }
> >
> > - if ((ClockFreq == 0) || (HsTiming == 0)) {
> > - //
> > - // Continue using default setting.
> > - //
> > - return EFI_SUCCESS;
> > - }
> > + EmmcGetTargetBusMode (Private, Slot, &ExtCsd, &BusMode);
> >
> > - DEBUG ((DEBUG_INFO, "EmmcSetBusMode: HsTiming %d ClockFreq %d
> > BusWidth %d Ddr %a\n", HsTiming, ClockFreq, BusWidth, IsDdr ?
> > "TRUE":"FALSE"));
> > + DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Target bus mode: timing
> > = %d, width = %d, clock freq = %d, driver strength = %d\n",
> > + BusMode.BusTiming, BusMode.BusWidth,
> BusMode.ClockFreq,
> > BusMode.DriverStrength.Emmc));
> >
> > - if (HsTiming == 3) {
> > - //
> > - // Execute HS400 timing switch procedure
> > - //
> > - Status = EmmcSwitchToHS400 (PciIo, PassThru, Slot, Rca, ClockFreq);
> > - } else if (HsTiming == 2) {
> > - //
> > - // Execute HS200 timing switch procedure
> > - //
> > - Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq,
> > BusWidth);
> > + if (BusMode.BusTiming == SdMmcMmcHs400) {
> > + Status = EmmcSwitchToHS400 (PciIo, PassThru, Slot, Rca, &BusMode);
> > + } else if (BusMode.BusTiming == SdMmcMmcHs200) {
> > + Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, &BusMode);
> > } else {
> > - //
> > - // Execute High Speed timing switch procedure
> > - //
> > - Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq,
> > IsDdr, BusWidth);
> > + Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca,
> &BusMode);
> > }
> >
> > - DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n",
> (HsTiming
> > == 3) ? "HS400" : ((HsTiming == 2) ? "HS200" : "HighSpeed"), Status));
> > + DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n",
> > (BusMode.BusTiming == SdMmcMmcHs400) ? "HS400" :
> > ((BusMode.BusTiming == SdMmcMmcHs200) ? "HS200" : "HighSpeed"),
> > Status));
> >
> > return Status;
> > }
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > index 17936a5492..36d2b487df 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > @@ -313,10 +313,6 @@ SdCardSetRca (
> > return Status;
> > }
> >
> > -
> > -
> > -
> > -
> > /**
> > Send command SELECT_DESELECT_CARD to the SD device to
> > select/deselect it.
> >
> > @@ -422,7 +418,7 @@ SdCardSetBusWidth (
> > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > IN UINT8 Slot,
> > IN UINT16 Rca,
> > - IN UINT8 BusWidth
> > + IN UINT16 BusWidth
> > )
> > {
> > EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
> > @@ -476,7 +472,7 @@ SdCardSetBusWidth (
> > @param[in] Slot The slot number of the SD card to send the
> command
> > to.
> > @param[in] AccessMode The value for access mode group.
>
>
> Please help to update the parameter comment to reflect the function
> interface changes.
>
>
> > @param[in] CommandSystem The value for command set group.
> > - @param[in] DriveStrength The value for drive length group.
> > + @param[in] DriveStrength The value for driver strength group.
>
>
> Please help to update the parameter name in the above comment from
> 'DriveStrength' to 'DriverStrength'.
>
>
> > @param[in] PowerLimit The value for power limit group.
> > @param[in] Mode Switch or check function.
> > @param[out] SwitchResp The return switch function status.
> > @@ -489,9 +485,9 @@ EFI_STATUS
> > SdCardSwitch (
> > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > IN UINT8 Slot,
> > - IN UINT8 AccessMode,
> > + IN SD_MMC_BUS_MODE BusTiming,
> > IN UINT8 CommandSystem,
> > - IN UINT8 DriveStrength,
> > + IN SD_DRIVER_STRENGTH_TYPE DriverStrength,
> > IN UINT8 PowerLimit,
> > IN BOOLEAN Mode,
> > OUT UINT8 *SwitchResp
> > @@ -502,6 +498,7 @@ SdCardSwitch (
> > EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
> > EFI_STATUS Status;
> > UINT32 ModeValue;
> > + UINT8 AccessMode;
> >
> > ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
> > ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
> > @@ -516,8 +513,31 @@ SdCardSwitch (
> > SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
> >
> > ModeValue = Mode ? BIT31 : 0;
> > - SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) |
> ((PowerLimit
> > & 0xF) << 4) | \
> > - ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) <<
> 12)
> > | \
> > +
> > + switch (BusTiming) {
> > + case SdMmcUhsDdr50:
> > + AccessMode = 0x4;
> > + break;
> > + case SdMmcUhsSdr104:
> > + AccessMode = 0x3;
> > + break;
> > + case SdMmcUhsSdr50:
> > + AccessMode = 0x2;
> > + break;
> > + case SdMmcUhsSdr25:
> > + case SdMmcSdHs:
> > + AccessMode = 0x1;
> > + break;
> > + case SdMmcUhsSdr12:
> > + case SdMmcSdDs:
> > + AccessMode = 0;
> > + break;
> > + default:
> > + AccessMode = 0xF;
> > + }
> > +
> > + SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) |
> > ((CommandSystem & 0xF) << 4) | \
> > + ((DriverStrength & 0xF) << 8) | ((PowerLimit & 0xF) << 12)
> |
> > \
> > ModeValue;
> >
> > Packet.InDataBuffer = SwitchResp;
> > @@ -718,7 +738,7 @@ SdCardSwitchBusWidth (
> > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > IN UINT8 Slot,
> > IN UINT16 Rca,
> > - IN UINT8 BusWidth
> > + IN UINT16 BusWidth
> > )
> > {
> > EFI_STATUS Status;
> > @@ -748,6 +768,261 @@ SdCardSwitchBusWidth (
> > return Status;
> > }
> >
> > +/**
> > + Check if passed BusTiming is supported in both controller and card.
> > +
> > + @param[in] Private Pointer to controller private data
> > + @param[in] SlotIndex Index of the slot in the controller
> > + @param[in] CardSupportedBusTimings Bitmask indicating which bus
> > timings are supported by card
> > + @param[in] IsInUhsI Flag indicating if link is in UHS-I
> > +
> > + @retval TRUE Both card and controller support given BusTiming
> > + @retval FALSE Card or controller doesn't support given BusTiming
> > +**/
> > +STATIC
> > +BOOLEAN
> > +SdIsBusTimingSupported (
> > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > + IN UINT8 SlotIndex,
> > + IN UINT8 CardSupportedBusTimings,
> > + IN BOOLEAN IsInUhsI,
> > + IN SD_MMC_BUS_MODE BusTiming
> > + )
> > +{
> > + SD_MMC_HC_SLOT_CAP *Capability;
> > +
> > + Capability = &Private->Capability[SlotIndex];
> > +
> > + if (IsInUhsI) {
> > + switch (BusTiming) {
>
>
> Please help to add a 'default' handle for this 'switch' statement, the
> proposed
> code will cause a GCC5 build failure.
>
>
> > + case SdMmcUhsSdr104:
> > + if (Capability->Sdr104 && ((CardSupportedBusTimings & BIT3) != 0)) {
> > + return TRUE;
> > + }
> > + break;
> > + case SdMmcUhsDdr50:
> > + if (Capability->Ddr50 && ((CardSupportedBusTimings & BIT4) != 0)) {
> > + return TRUE;
> > + }
> > + break;
> > + case SdMmcUhsSdr50:
> > + if (Capability->Sdr50 && ((CardSupportedBusTimings & BIT2) != 0)) {
> > + return TRUE;
> > + }
> > + break;
> > + case SdMmcUhsSdr25:
> > + if ((CardSupportedBusTimings & BIT1) != 0) {
> > + return TRUE;
> > + }
> > + break;
> > + case SdMmcUhsSdr12:
> > + if ((CardSupportedBusTimings & BIT0) != 0) {
> > + return TRUE;
> > + }
> > + break;
> > + }
> > + } else {
> > + switch (BusTiming) {
>
>
> Please help to add a 'default' handle for this 'switch' statement, the
> proposed
> code will cause a GCC5 build failure.
>
>
> > + case SdMmcSdHs:
> > + if (Capability->HighSpeed && (CardSupportedBusTimings & BIT1) != 0)
> {
> > + return TRUE;
> > + }
> > + break;
> > + case SdMmcSdDs:
> > + if ((CardSupportedBusTimings & BIT0) != 0) {
> > + return TRUE;
> > + }
> > + break;
> > + }
> > + }
> > +
> > + return FALSE;
> > +}
> > +
> > +/**
> > + Get the target bus timing to set on the link. This function
> > + will try to select highest bus timing supported by card, controller
> > + and the driver.
> > +
> > + @param[in] Private Pointer to controller private data
> > + @param[in] SlotIndex Index of the slot in the controller
> > + @param[in] CardSupportedBusTimings Bitmask indicating which bus
> > timings are supported by card
> > + @param[in] IsInUhsI Flag indicating if link is in UHS-I
> > +
> > + @return Bus timing value that should be set on link
> > +**/
> > +STATIC
> > +SD_MMC_BUS_MODE
> > +SdGetTargetBusTiming (
> > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > + IN UINT8 SlotIndex,
> > + IN UINT8 CardSupportedBusTimings,
> > + IN BOOLEAN IsInUhsI
> > + )
> > +{
> > + SD_MMC_BUS_MODE BusTiming;
> > +
> > + if (IsInUhsI) {
> > + BusTiming = SdMmcUhsSdr104;
> > + } else {
> > + BusTiming = SdMmcSdHs;
> > + }
> > +
> > + while (BusTiming > SdMmcSdDs) {
> > + if (SdIsBusTimingSupported (Private, SlotIndex,
> > CardSupportedBusTimings, IsInUhsI, BusTiming)) {
> > + break;
> > + }
> > + BusTiming--;
> > + }
>
>
> The origin logic has the below preference when selecting bus timing
> (if supported):
>
> SdMmcUhsSdr104
> SdMmcUhsSdr50
> SdMmcUhsDdr50
> SdMmcUhsSdr25
> SdMmcUhsSdr12
>
> So we need to reorder the types in 'SD_MMC_BUS_MODE' to:
>
> typedef enum {
> SdMmcSdDs,
> SdMmcSdHs,
> SdMmcUhsSdr12,
> SdMmcUhsSdr25,
> SdMmcUhsDdr50,
> SdMmcUhsSdr50,
> SdMmcUhsSdr104,
> ...
> } SD_MMC_BUS_MODE;
>
> Otherwise, the Ddr50 mode will never be selected.
>
>
> > +
> > + return BusTiming;
> > +}
> > +
> > +/**
> > + Get the target bus width to be set on the bus.
> > +
> > + @param[in] Private Pointer to controller private data
> > + @param[in] SlotIndex Index of the slot in the controller
> > + @param[in] BusTiming Bus timing set on the bus
> > +
> > + @return Bus width to be set on the bus
> > +**/
> > +STATIC
> > +UINT16
> > +SdGetTargetBusWidth (
> > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > + IN UINT8 SlotIndex,
> > + IN SD_MMC_BUS_MODE BusTiming
> > + )
> > +{
> > + UINT16 BusWidth;
> > + UINT16 PreferedBusWidth;
> > +
> > + PreferedBusWidth = Private-
> > >Slot[SlotIndex].OperatingParameters.BusWidth;
> > +
> > + if (BusTiming == SdMmcSdDs || BusTiming == SdMmcSdHs) {
> > + if (PreferedBusWidth != EDKII_SD_MMC_BUS_WIDTH_IGNORE) {
> > + BusWidth = PreferedBusWidth;
>
>
> The supported bus width is either 1 or 4 bit for 3.3V signal cards.
> I think we need a more strict check here.
>
>
> > + } else {
> > + BusWidth = 4;
> > + }
> > + } else {
> > + //
> > + // UHS-I modes support only 4-bit width.
> > + // Switch to 4-bit has been done before calling this function anyway so
> > + // this is purely informational.
> > + //
> > + BusWidth = 4;
> > + }
> > +
> > + return BusWidth;
> > +}
> > +
> > +/**
> > + Get the target clock frequency to be set on the bus.
> > +
> > + @param[in] Private Pointer to controller private data
> > + @param[in] SlotIndex Index of the slot in the controller
> > + @param[in] BusTiming Bus timing to be set on the bus
> > +
> > + @return Value of the clock frequency to be set on bus in MHz
> > +**/
> > +STATIC
> > +UINT32
> > +SdGetTargetBusClockFreq (
> > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > + IN UINT8 SlotIndex,
> > + IN SD_MMC_BUS_MODE BusTiming
> > + )
> > +{
> > + UINT32 PreferedClockFreq;
> > + UINT32 MaxClockFreq;
> > +
> > + PreferedClockFreq = Private-
> > >Slot[SlotIndex].OperatingParameters.ClockFreq;
> > +
> > + switch (BusTiming) {
> > + case SdMmcUhsSdr104:
> > + MaxClockFreq = 208;
> > + break;
> > + case SdMmcUhsSdr50:
> > + MaxClockFreq = 100;
> > + break;
> > + case SdMmcUhsDdr50:
> > + case SdMmcUhsSdr25:
> > + case SdMmcSdHs:
> > + MaxClockFreq = 50;
> > + break;
> > + case SdMmcUhsSdr12:
> > + case SdMmcSdDs:
> > + default:
> > + MaxClockFreq = 25;
>
>
> Minor comment, need an extra space for the above line.
>
>
> > + }
> > +
> > + if (PreferedClockFreq != EDKII_SD_MMC_CLOCK_FREQ_IGNORE &&
> > PreferedClockFreq < MaxClockFreq) {
> > + return PreferedClockFreq;
> > + } else {
> > + return MaxClockFreq;
> > + }
> > +}
> > +
> > +/**
> > + Get the driver strength to be set on bus
>
>
> Please help to append a '.' character for the above line.
> It is required for the edk2 coding style.
>
>
> > +
> > + @param[in] Private Pointer to controller private data
> > + @param[in] SlotIndex Index of the slot in the controller
> > + @param[in] CardSupportedDriverStrengths Bitmask indicating which
> > driver strengths are supported on the card
> > + @param[in] BusTiming Bus timing set on the bus
> > +
> > + @return Value of the driver strength to be set on the bus
> > +**/
> > +STATIC
> > +EDKII_SD_MMC_DRIVER_STRENGTH
> > +SdGetTargetDriverStrength (
> > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > + IN UINT8 SlotIndex,
> > + IN UINT8 CardSupportedDriverStrengths,
> > + IN SD_MMC_BUS_MODE BusTiming
> > + )
>
>
> One question here, the driver strength configuration is only for UHS-I cards.
> Does the check on 'CardSupportedDriverStrengths' enough to ensure the
> above
> requirement or a boolean input parameter 'IsInUhsI' is needed here?
>
I think we can leave it to the code that actually sets the bus parameters
to simply skip driver strength programming for legacy and select driver strength here
based only on HW support and platform preference. The alternative is to return
SdDriverStrengthIgnore here and handle that in code that actually sets driver strength.
>
> > +{
> > + EDKII_SD_MMC_DRIVER_STRENGTH PreferedDriverStrength;
> > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > +
> > + PreferedDriverStrength = Private-
> > >Slot[SlotIndex].OperatingParameters.DriverStrength;
> > + DriverStrength.Sd = SdDriverStrengthTypeB;
> > +
> > + if (PreferedDriverStrength.Sd !=
> > EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE &&
> > + (CardSupportedDriverStrengths & (BIT0 <<
> PreferedDriverStrength.Sd)))
>
>
> The host controller also has a capability for different types of driver strength.
> (Capabilities Register, bit 36~38)
>
> The check should take it into consideration as well.
>
>
> > {
> > + DriverStrength.Sd = PreferedDriverStrength.Sd;
> > + }
> > +
> > + return DriverStrength;
> > +}
> > +
> > +/**
> > + Get the target settings for the bus mode.
> > +
> > + @param[in] Private Pointer to controller private data
> > + @param[in] SlotIndex Index of the slot in the controller
> > + @param[in] SwitchQueryResp Pointer to switch query response
> > + @param[in] IsInUhsI Flag indicating if link is in UHS-I mode
> > + @param[out] BusMode Target configuration of the bus
> > +**/
> > +STATIC
> > +VOID
> > +SdGetTargetBusMode (
> > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > + IN UINT8 SlotIndex,
> > + IN UINT8 *SwitchQueryResp,
> > + IN BOOLEAN IsInUhsI,
> > + OUT EDKII_SD_MMC_BUS_MODE *BusMode
> > + )
> > +{
> > + BusMode->BusTiming = SdGetTargetBusTiming (Private, SlotIndex,
> > SwitchQueryResp[13], IsInUhsI);
> > + BusMode->BusWidth = SdGetTargetBusWidth (Private, SlotIndex,
> > BusMode->BusTiming);
> > + BusMode->ClockFreq = SdGetTargetBusClockFreq (Private, SlotIndex,
> > BusMode->BusTiming);
> > + BusMode->DriverStrength = SdGetTargetDriverStrength (Private,
> > SlotIndex, SwitchQueryResp[9], BusMode->BusTiming);
> > +}
> > +
> > /**
> > Switch the high speed timing according to request.
> >
> > @@ -775,13 +1050,10 @@ SdCardSetBusMode (
> > {
> > EFI_STATUS Status;
> > SD_MMC_HC_SLOT_CAP *Capability;
> > - UINT32 ClockFreq;
> > - UINT8 BusWidth;
> > - UINT8 AccessMode;
> > UINT8 HostCtrl1;
> > UINT8 SwitchResp[64];
> > - SD_MMC_BUS_MODE Timing;
> > SD_MMC_HC_PRIVATE_DATA *Private;
> > + EDKII_SD_MMC_BUS_MODE BusMode;
> >
> > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> >
> > @@ -792,61 +1064,46 @@ SdCardSetBusMode (
> > return Status;
> > }
> >
> > - BusWidth = 4;
> > -
> > - Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, BusWidth);
> > - if (EFI_ERROR (Status)) {
> > - return Status;
> > + if (S18A) {
> > + //
> > + // For UHS-I speed modes 4-bit data bus is requiered so we
> > + // switch here irrespective of platform preference.
> > + //
> > + Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, 4);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > }
> > +
> > //
> > // Get the supported bus speed from SWITCH cmd return data group #1.
> > //
> > - Status = SdCardSwitch (PassThru, Slot, 0xF, 0xF, 0xF, 0xF, FALSE,
> > SwitchResp);
> > + Status = SdCardSwitch (PassThru, Slot, 0xFF, 0xF, SdDriverStrengthIgnore,
> > 0xF, FALSE, SwitchResp);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> > - //
> > - // Calculate supported bus speed/bus width/clock frequency by host and
> > device capability.
> > - //
> > - ClockFreq = 0;
> > - if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {
> > - ClockFreq = 208;
> > - AccessMode = 3;
> > - Timing = SdMmcUhsSdr104;
> > - } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] & BIT2) !=
> 0))
> > {
> > - ClockFreq = 100;
> > - AccessMode = 2;
> > - Timing = SdMmcUhsSdr50;
> > - } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] & BIT4) !=
> > 0)) {
> > - ClockFreq = 50;
> > - AccessMode = 4;
> > - Timing = SdMmcUhsDdr50;
> > - } else if ((SwitchResp[13] & BIT1) != 0) {
> > - ClockFreq = 50;
> > - AccessMode = 1;
> > - Timing = SdMmcUhsSdr25;
> > - } else {
> > - ClockFreq = 25;
> > - AccessMode = 0;
> > - Timing = SdMmcUhsSdr12;
> > +
> > + SdGetTargetBusMode (Private, Slot, SwitchResp, S18A, &BusMode);
> > +
> > + DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Target bus mode: bus
> timing
> > = %d, bus width = %d, clock freq[MHz] = %d, driver strength = %d\n",
> > + BusMode.BusTiming, BusMode.BusWidth,
> BusMode.ClockFreq,
> > BusMode.DriverStrength.Sd));
> > +
> > + if (!S18A) {
> > + Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca,
> > BusMode.BusWidth);
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > }
>
>
> Is it feasible to set the bus width for the 3.3V signaled cards & the UHS-I
> cards together here? I think the SdGetTargetBusWidth() already handles the
> UHS-I cards case well by always setting the bus width to 4.
>
So basically to skip if (!S18A) condition and do bus width switch unconditionally?
I am not sure how the bus will react to additional bus width switch for UHS-I case
and I am not able to test it locally as I only have controller with legacy support available for tests.
I guess I will give it a try and we will revert it if it causes any problems.
>
> >
> > - Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE,
> > SwitchResp);
> > + Status = SdCardSwitch (PassThru, Slot, BusMode.BusTiming, 0xF,
> > BusMode.DriverStrength.Sd, 0xF, TRUE, SwitchResp);
>
>
> After the proposed change, the preferred bus timing and driver strength
> value
> will be set for the device through the SD_SWITCH command.
>
> However, on the host controller side, only the bus timing value is also
> updated
> in the Host Control 2 Register of the SD HC (via function
> SdMmcHcUhsSignaling()).
> It seems to me that the driver strength value does not get updated in this
> register.
>
> I think the eMMC case has a similar issue.
>
>
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> >
> > - if ((SwitchResp[16] & 0xF) != AccessMode) {
> > - DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: Switch to
> AccessMode %d
> > ClockFreq %d BusWidth %d fails! The Switch response is 0x%1x\n",
> > AccessMode, ClockFreq, BusWidth, SwitchResp[16] & 0xF));
> > - return EFI_DEVICE_ERROR;
> > - }
>
>
> The above check may still be needed. Also, the whether the target driver
> strength is successfully set needs to be checked as well.
>
> How about adding checks in function SdCardSwitch() for mode 1 of the
> switch
> command?
>
>
> > -
> > - DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Switch to AccessMode %d
> > ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));
> > -
> > //
> > - // Set to Hight Speed timing
> > + // Set to High Speed timing
> > //
> > - if (AccessMode == 1) {
> > + if (BusMode.BusTiming == SdMmcSdHs) {
> > HostCtrl1 = BIT2;
> > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1,
> sizeof
> > (HostCtrl1), &HostCtrl1);
> > if (EFI_ERROR (Status)) {
> > @@ -854,12 +1111,12 @@ SdCardSetBusMode (
> > }
> > }
> >
> > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > Timing);
> > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > BusMode.BusTiming);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> >
> > - Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> > >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> > + Status = SdMmcHcClockSupply (PciIo, Slot, BusMode.ClockFreq * 1000,
> > Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> > @@ -869,7 +1126,7 @@ SdCardSetBusMode (
> > Private->ControllerHandle,
> > Slot,
> > EdkiiSdMmcSwitchClockFreqPost,
> > - &Timing
> > + &BusMode.BusTiming
> > );
> > if (EFI_ERROR (Status)) {
> > DEBUG ((
> > @@ -882,7 +1139,7 @@ SdCardSetBusMode (
> > }
> > }
> >
> > - if ((AccessMode == 3) || ((AccessMode == 2) && (Capability-
> > >TuningSDR50 != 0))) {
> > + if ((BusMode.BusTiming == SdMmcUhsSdr104) || ((BusMode.BusTiming
> > == SdMmcUhsSdr50) && (Capability->TuningSDR50 != 0))) {
> > Status = SdCardTuningClock (PciIo, PassThru, Slot);
> > if (EFI_ERROR (Status)) {
> > return Status;
> > @@ -1025,10 +1282,8 @@ SdCardIdentification (
> > // (One of support bits is set to 1: SDR50, SDR104 or DDR50 in the
> > // Capabilities register), switch its voltage to 1.8V.
> > //
> > - if ((Private->Capability[Slot].Sdr50 != 0 ||
> > - Private->Capability[Slot].Sdr104 != 0 ||
> > - Private->Capability[Slot].Ddr50 != 0) &&
> > - ((Ocr & BIT24) != 0)) {
> > + if ((Private->Capability[Slot].Sdr50 || Private->Capability[Slot].Ddr50 ||
> > Private->Capability[Slot].Sdr104) &&
> > + ((Ocr & BIT24) != 0)) {
>
>
> Minor comment, for:
> Private->Capability[Slot].Sdr50
> Private->Capability[Slot].Ddr50
> Private->Capability[Slot].Sdr104
>
> They are of type UINT32, should use operators '==' or '!=' in condition
> statement. I think the origin logic is good here.
>
>
> > Status = SdCardVoltageSwitch (PassThru, Slot);
> > if (EFI_ERROR (Status)) {
> > DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing
> > SdCardVoltageSwitch fails with %r\n", Status));
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > index 4881ee44cc..8f49954b7f 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > @@ -28,6 +28,11 @@ EFI_DRIVER_BINDING_PROTOCOL
> > gSdMmcPciHcDriverBinding = {
> > NULL
> > };
> >
> > +#define SLOT_INIT_TEMPLATE {0, UnknownSlot, 0, 0, 0, \
> > + {EDKII_SD_MMC_BUS_WIDTH_IGNORE,\
> > + EDKII_SD_MMC_CLOCK_FREQ_IGNORE,\
> > + EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE}}
>
>
> Please help to update the above definition to:
> #define SLOT_INIT_TEMPLATE {0, UnknownSlot, 0, 0, 0, \
> {EDKII_SD_MMC_BUS_WIDTH_IGNORE,\
> EDKII_SD_MMC_CLOCK_FREQ_IGNORE,\
> {EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE}}}
>
> The proposed one will cause GCC5 build failure.
>
>
> > +
> > //
> > // Template for SD/MMC host controller private data.
> > //
> > @@ -50,8 +55,12 @@ SD_MMC_HC_PRIVATE_DATA
> gSdMmcPciHcTemplate
> > = {
> > // Queue
> > INITIALIZE_LIST_HEAD_VARIABLE (gSdMmcPciHcTemplate.Queue),
> > { // Slot
> > - {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0,
> > 0},
> > - {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0,
> > 0}
> > + SLOT_INIT_TEMPLATE,
> > + SLOT_INIT_TEMPLATE,
> > + SLOT_INIT_TEMPLATE,
> > + SLOT_INIT_TEMPLATE,
> > + SLOT_INIT_TEMPLATE,
> > + SLOT_INIT_TEMPLATE
> > },
> > { // Capability
> > {0},
> > @@ -328,6 +337,7 @@ SdMmcPciHcEnumerateDevice (
> >
> > return;
> > }
> > +
> > /**
> > Tests to see if this driver supports a given controller. If a child device is
> > provided,
> > it further tests to see if this driver supports creating a handle for the
> > specified child device.
> > @@ -619,7 +629,6 @@ SdMmcPciHcDriverBindingStart (
> > Support64BitDma = TRUE;
> > for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
> > Private->Slot[Slot].Enable = TRUE;
> > -
> > //
> > // Get SD/MMC Pci Host Controller Version
> > //
> > @@ -635,19 +644,34 @@ SdMmcPciHcDriverBindingStart (
> >
> > Private->BaseClkFreq[Slot] = Private->Capability[Slot].BaseClkFreq;
> >
> > - if (mOverride != NULL && mOverride->Capability != NULL) {
> > - Status = mOverride->Capability (
> > - Controller,
> > - Slot,
> > - &Private->Capability[Slot],
> > - &Private->BaseClkFreq[Slot]
> > - );
> > - if (EFI_ERROR (Status)) {
> > - DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",
> > - __FUNCTION__, Status));
> > - continue;
> > + if (mOverride != NULL) {
> > + if (mOverride->Capability != NULL) {
> > + Status = mOverride->Capability (
> > + Controller,
> > + Slot,
> > + &Private->Capability[Slot],
> > + &Private->BaseClkFreq[Slot]
> > + );
> > + if (EFI_ERROR (Status)) {
> > + DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",
> > + __FUNCTION__, Status));
> > + continue;
> > + }
> > + }
> > +
> > + if (mOverride->NotifyPhase != NULL) {
> > + Status = mOverride->NotifyPhase (
> > + Controller,
> > + Slot,
> > + EdkiiSdMmcGetOperatingParam,
> > + (VOID*)&Private->Slot[Slot].OperatingParameters
> > + );
> > + if (EFI_ERROR (Status)) {
> > + DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters,
> > using defaults\n" __FUNCTION__));
>
>
> Please update the above line to (missed one ',' before '__FUNCTION__'):
> DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters, using
> defaults\n", __FUNCTION__));
>
> It will cause GCC5 build failure for the proposed change.
>
>
> > + }
> > }
> > }
> > +
> > DumpCapabilityReg (Slot, &Private->Capability[Slot]);
> > DEBUG ((
> > DEBUG_INFO,
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > index 77bbf83b76..b768f3942f 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > @@ -78,11 +78,12 @@ typedef enum {
> > } EFI_SD_MMC_SLOT_TYPE;
> >
> > typedef struct {
> > - BOOLEAN Enable;
> > - EFI_SD_MMC_SLOT_TYPE SlotType;
> > - BOOLEAN MediaPresent;
> > - BOOLEAN Initialized;
> > - SD_MMC_CARD_TYPE CardType;
> > + BOOLEAN Enable;
> > + EFI_SD_MMC_SLOT_TYPE SlotType;
> > + BOOLEAN MediaPresent;
> > + BOOLEAN Initialized;
> > + SD_MMC_CARD_TYPE CardType;
> > + EDKII_SD_MMC_OPERATING_PARAMETERS OperatingParameters;
> > } SD_MMC_HC_SLOT;
> >
> > typedef struct {
> > @@ -120,6 +121,13 @@ typedef struct {
> > UINT32 BaseClkFreq[SD_MMC_HC_MAX_SLOT];
> > } SD_MMC_HC_PRIVATE_DATA;
> >
> > +typedef struct {
> > + EDKII_SD_MMC_BUS_TIMING BusTiming;
>
>
> Should be:
> SD_MMC_BUS_MODE BusTiming;
>
>
> > + UINT16 BusWidth;
> > + UINT32 ClockFreq;
> > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > +} EDKII_SD_MMC_BUS_MODE;
>
>
> Since the above structure is a driver internal one, I prefer dropping the
> prefix 'EDKII_'. But unfortunately, SD_MMC_BUS_MODE is already used in
> Protocol/SdMmcOverride.h, so how about SD_MMC_BUS_SETTINGS?
>
>
> > +
> > #define SD_MMC_HC_TRB_SIG SIGNATURE_32 ('T', 'R', 'B', 'T')
> >
> > //
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > index 5d1f977e55..863ae3db34 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > @@ -1263,10 +1263,10 @@ SdMmcHcInitHost (
> > **/
> > EFI_STATUS
> > SdMmcHcUhsSignaling (
> > - IN EFI_HANDLE ControllerHandle,
> > - IN EFI_PCI_IO_PROTOCOL *PciIo,
> > - IN UINT8 Slot,
> > - IN SD_MMC_BUS_MODE Timing
> > + IN EFI_HANDLE ControllerHandle,
> > + IN EFI_PCI_IO_PROTOCOL *PciIo,
> > + IN UINT8 Slot,
> > + IN SD_MMC_BUS_MODE Timing
> > )
>
>
> I think the changes made here (space indentation) can be dropped.
>
>
> > {
> > EFI_STATUS Status;
> > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > index 0b0d415256..c4d4aef73a 100644
> > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > @@ -611,10 +611,10 @@ SdMmcHcInitTimeoutCtrl (
> > **/
> > EFI_STATUS
> > SdMmcHcUhsSignaling (
> > - IN EFI_HANDLE ControllerHandle,
> > - IN EFI_PCI_IO_PROTOCOL *PciIo,
> > - IN UINT8 Slot,
> > - IN SD_MMC_BUS_MODE Timing
> > + IN EFI_HANDLE ControllerHandle,
> > + IN EFI_PCI_IO_PROTOCOL *PciIo,
> > + IN UINT8 Slot,
> > + IN SD_MMC_BUS_MODE Timing
>
>
> I think the changes made here (space indentation) can be dropped.
>
> Best Regards,
> Hao Wu
>
>
> > );
> >
> > #endif
> > --
> > 2.14.1.windows.1
--------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek
przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by
others is strictly prohibited.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/2] Add GetOperatingParam notify phase to SdMmcOverride protocol
2019-06-13 13:43 ` [PATCH 0/2] Add GetOperatingParam notify phase to SdMmcOverride protocol mateusz.albecki
@ 2019-06-14 1:46 ` Wu, Hao A
2019-06-14 18:44 ` Marcin Wojtas
0 siblings, 1 reply; 9+ messages in thread
From: Wu, Hao A @ 2019-06-14 1:46 UTC (permalink / raw)
To: devel@edk2.groups.io, Ard Biesheuvel, mw@semihalf.com; +Cc: Albecki, Mateusz
[-- Attachment #1: Type: text/plain, Size: 5383 bytes --]
Loop in Ard and Marcin.
Hello Ard and Marcin,
We are proposing to make an extension to the SDMMC Override protocol to
more customization for platforms during the SD/eMMC device/controller
initialization process.
For convenience, the series is available at:
https://github.com/hwu25/edk2/tree/sdmmc_override_extension_v1
I only verified the change will not break the build for platforms
(in edk2-platform repo). Could you help provide feedbacks for this series?
Thanks in advance.
Best Regards,
Hao Wu
From: Albecki, Mateusz
Sent: Thursday, June 13, 2019 9:44 PM
To: devel@edk2.groups.io
Cc: Wu, Hao A
Subject: RE: [PATCH 0/2] Add GetOperatingParam notify phase to SdMmcOverride protocol
Resending to group.
From: Wu, Hao A
Sent: Monday, June 10, 2019 5:18 AM
To: Albecki, Mateusz <mateusz.albecki@intel.com>
Subject: RE: [PATCH 0/2] Add GetOperatingParam notify phase to SdMmcOverride protocol
Hello Mateusz,
Thanks for the patch series and sorry for the delayed response.
One question first, I did not see the patches being sent to the mailing list
'devel@edk2.groups.io'. We have recently switched to this new mailing list back
to early April, the old one 'edk2-devel@lists.01.org' is no longer being used.
In case that you have not registered the new list, you can sign up at:
https://edk2.groups.io/g/devel
or email:
devel+subscribe@edk2.groups.io<mailto:devel+subscribe@edk2.groups.io>
to get registered in the new mailing list.
Or you can send me the patch files and I will help to send them to the mailing list.
Below are some general level feedbacks (Other patch-specific feedbacks will be replied in other mails):
* Could you help to add the below Bugzilla tracker reference in the commit log message?
https://bugzilla.tianocore.org/show_bug.cgi?id=1882
* Could you help to run the script 'BaseTools/Scripts/PatchCheck.py' and resolve its report on the commit log format issues?
Checking git commit: 6e3f64aeb4
The commit message format is not valid:
* Contributed-under! (Note: this must be removed by the code contributor!)
* Add quotes (") around name with a comma: Albecki, Mateusz
* Email format is invalid: hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>
* Line 15 of commit message is too long.
https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format
The code passed all checks.
Checking git commit: 91595ae911
The commit message format is not valid:
* Contributed-under! (Note: this must be removed by the code contributor!)
* Add quotes (") around name with a comma: Albecki, Mateusz
* Email format is invalid: hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>
https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format
The code passed all checks.
* Could you help to resolve the typo 'Prefered' to 'Preferred' in the naming of some variables?
* Could you help to use lowercase 'static' (instead of using the uppercase one) for the new functions?
Also, I only verified the build of the patch series. Please grant me some time
to verify on the HW on my side. Maybe your updated patches arrive first and I
will then verify the update ones.
Best Regards,
Hao Wu
> -----Original Message-----
> From: Albecki, Mateusz
> Sent: Monday, June 03, 2019 7:34 PM
> Cc: Albecki, Mateusz; Wu, Hao A
> Subject: [PATCH 0/2] Add GetOperatingParam notify phase to
> SdMmcOverride protocol
>
> To allow platform greater control over the bus settings for SD card and
> eMMC card
> we have added a new notify phase to SdMmcOverrideProtocol called
> GetOperatingParam.
> This phase is signaled before SD card/eMMC initialization and allows platform
> to tweak
> the values in new structure called
> EDKII_SD_MMC_OPERATING_PARAMETERS which allows to configure
> bus width, clock frequency and driver strength. Other bus parameters can be
> configured by
> overriding host controller capabilities.
>
> Tests:
> - OS boot from eMMC without SdMmcOverride protocol installed
> - OS boot from eMMC with SdMmcOverride installed and clock frequency
> lowered to 100MHz in HS200
> - OS boot from eMMC with driver strength changed to Type1
> - SD card enumeration in UEFI shell on default speed and high speed(non
> UHS-I) with SdMmcOverride installed and UHS-I disabled in capability
>
>
> Cc: hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>
>
> Albecki, Mateusz (2):
> MdeModulePkg/SdMmcOverride: Add GetOperatingParam notify phase
> MdeModulePkg/SdMmcHcDxe: Implement revision 3 of
> SdMmcOverrideProtocol
>
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c | 522
> +++++++++++++++------
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c | 381
> ++++++++++++---
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c | 52 +-
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h | 18 +-
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c | 8 +-
> MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h | 8 +-
> MdeModulePkg/Include/Protocol/SdMmcOverride.h | 58 ++-
> 7 files changed, 802 insertions(+), 245 deletions(-)
>
> --
> 2.14.1.windows.1
[-- Attachment #2: Type: text/html, Size: 38052 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement revision 3 of SdMmcOverrideProtocol
2019-06-13 14:38 ` [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement revision 3 of SdMmcOverrideProtocol Albecki, Mateusz
@ 2019-06-14 3:14 ` Wu, Hao A
2019-06-18 15:14 ` Albecki, Mateusz
0 siblings, 1 reply; 9+ messages in thread
From: Wu, Hao A @ 2019-06-14 3:14 UTC (permalink / raw)
To: Albecki, Mateusz, devel@edk2.groups.io, mw@semihalf.com
> -----Original Message-----
> From: Albecki, Mateusz
> Sent: Thursday, June 13, 2019 10:39 PM
> To: devel@edk2.groups.io
> Cc: Wu, Hao A
> Subject: RE: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement revision
> 3 of SdMmcOverrideProtocol
>
> Resending to group. Inline reply to some of the comments.
>
> As for the mapping between eMMC driver strength and SD controller driver
> strength should we use this one:
>
> SD controller -> eMMC card
> B -> Type 0
> A -> Type 1
> C -> Type 2
> D -> Type 3
> (none) -> Type4
Yes, I think this matching is fine. Inspecting the SD & eMMC specs:
For SD Physical Layer Specification:
Driver Type Nominal Driving
Impedance Capability
A 33Ω x1.5
B 50Ω x1
C 66Ω x0.75
D 100Ω x0.5
For Embedded Multi-Media Card (e.MMC) Electrical Standard:
Driver Type Nominal Approximated driver capability
Values Impedance compared to Type-0
0x0 50Ω x1
0x1 33Ω x1.5
0x2 66Ω x0.75
0x3 100Ω x0.5
0x4 40Ω x1.2
The above mapping is consistent with regard to the Nominal Impedance &
Driving Capability parameters.
>
> And Type 4 would be identified by bit 39 in capability register which is
> currently marked as reserved in SD controller specification. This is current
> capability register definition in the driver.
I am not sure if the bit39 in the capability register works for all SD
host controller (because it is not documented in specs, as far as I know).
I suggest we just ignore the HC capability when setting driver strength
type 4 for eMMC devices.
Response to other inline comments below:
>
> Thanks,
> Mateusz
>
> > -----Original Message-----
> > From: Wu, Hao A
> > Sent: Monday, June 10, 2019 5:19 AM
> > To: Albecki, Mateusz <mateusz.albecki@intel.com>
> > Subject: RE: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement
> revision
> > 3 of SdMmcOverrideProtocol
> >
> > Hello Mateusz,
> >
> > Some inline comments below:
> >
> > > -----Original Message-----
> > > From: Albecki, Mateusz
> > > Sent: Monday, June 03, 2019 7:34 PM
> > > Cc: Albecki, Mateusz; Wu, Hao A; Albecki
> > > Subject: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement revision
> 3
> > > of SdMmcOverrideProtocol
> > >
> > > Implement support for GetOperatingParamters notify phase
> > > in SdMmcHcDxe driver. GetOperatingParameters notify phase
> > > is signaled before we start card detection and initialization.
> > > Code has been updated for both eMMC and SD card controllers to
> > > take into consideration those new parameters. Initialization process
> > > has been divided into 2 steps. In the first step we bring the link
> > > up to the point where we can get card identification data(Extended
> > > CSD in eMMC case and SWITCH command response in SD card case). This
> > > data is later used along with controller capabilities and operating
> > > parameters passed in GetOperatingParameters phase to choose
> preferred
> > > bus settings in GetTargetBusSettings function. Those settings are later
> > > on to start bus training to high speeds. If user passes incompatible
> > > setting with selected bus timing driver will assume it's standard behavior
> > with
> > > respect to that setting. For instance if HS400 has been selected as a
> > > target bus timing due to card and controller support bus width setting of
> > > 4 and 1 bit won't be respected and 8 bit setting will be chosen instead.
> > >
> > >
> > > Cc: hao.a.wu@intel.com
> > > Signed-off-by: Albecki, Mateusz <mateusz.albecki@intel.com>
> > > Contributed-under: TianoCore Contribution Agreement 1.1
> > > ---
> > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c | 522
> > > +++++++++++++++------
> > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c | 381
> > > ++++++++++++---
> > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c | 52 +-
> > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h | 18 +-
> > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c | 8 +-
> > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h | 8 +-
> > > 6 files changed, 750 insertions(+), 239 deletions(-)
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > index deaf4468c9..1a81f6d250 100644
> > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > @@ -449,7 +449,7 @@ EFI_STATUS
> > > EmmcSendTuningBlk (
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > - IN UINT8 BusWidth
> > > + IN UINT16 BusWidth
> > > )
> > > {
> > > EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
> > > @@ -506,7 +506,7 @@ EmmcTuningClkForHs200 (
> > > IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > - IN UINT8 BusWidth
> > > + IN UINT16 BusWidth
> > > )
> > > {
> > > EFI_STATUS Status;
> > > @@ -583,7 +583,7 @@ EmmcSwitchBusWidth (
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > IN BOOLEAN IsDdr,
> > > - IN UINT8 BusWidth
> > > + IN UINT16 BusWidth
> > > )
> > > {
> > > EFI_STATUS Status;
> > > @@ -641,13 +641,13 @@ EmmcSwitchBusWidth (
> > > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6 and SD Host
> > > Controller
> > > Simplified Spec 3.0 Figure 3-3 for details.
> > >
> > > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
> > > - @param[in] PassThru A pointer to the
> > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > - @param[in] Slot The slot number of the SD card to send the
> > command
> > > to.
> > > - @param[in] Rca The relative device address to be assigned.
> > > - @param[in] HsTiming The value to be written to HS_TIMING field of
> > > EXT_CSD register.
> > > - @param[in] Timing The bus mode timing indicator.
> > > - @param[in] ClockFreq The max clock frequency to be set, the unit is
> > > MHz.
> > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> instance.
> > > + @param[in] PassThru A pointer to the
> > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > + @param[in] Slot The slot number of the SD card to send the
> > > command to.
> > > + @param[in] Rca The relative device address to be assigned.
> > > + @param[in] DriverStrength Driver strength to set for speed modes
> that
> > > support it.
> > > + @param[in] Timing The bus mode timing indicator.
> >
> >
> > Please help to update the parameter comment to reflect the name change
> > from
> > 'Timing' to 'BusTiming'.
> >
> >
> > > + @param[in] ClockFreq The max clock frequency to be set, the unit is
> > > MHz.
> > >
> > > @retval EFI_SUCCESS The operation is done correctly.
> > > @retval Others The operation fails.
> > > @@ -659,8 +659,8 @@ EmmcSwitchBusTiming (
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > - IN UINT8 HsTiming,
> > > - IN SD_MMC_BUS_MODE Timing,
> > > + IN EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength,
> > > + IN SD_MMC_BUS_MODE BusTiming,
> > > IN UINT32 ClockFreq
> > > )
> > > {
> > > @@ -678,12 +678,29 @@ EmmcSwitchBusTiming (
> > > //
> > > Access = 0x03;
> > > Index = OFFSET_OF (EMMC_EXT_CSD, HsTiming);
> > > - Value = HsTiming;
> > > CmdSet = 0;
> > > + switch (BusTiming) {
> > > + case SdMmcMmcHs400:
> > > + Value = (UINT8)((DriverStrength.Emmc << 4) | 3);
> > > + break;
> > > + case SdMmcMmcHs200:
> > > + Value = (UINT8)((DriverStrength.Emmc << 4) | 2);
> > > + break;
> > > + case SdMmcMmcHsSdr:
> > > + case SdMmcMmcHsDdr:
> > > + Value = 1;
> > > + break;
> > > + case SdMmcMmcLegacy:
> > > + Value = 0;
> > > + break;
> > > + default:
> > > + DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Unsupported
> > > BusTiming(%d\n)", BusTiming));
> > > + return EFI_INVALID_PARAMETER;
> > > + }
> > >
> > > Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);
> > > if (EFI_ERROR (Status)) {
> > > - DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to
> hstiming %d
> > > fails with %r\n", HsTiming, Status));
> > > + DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to bus
> > > timing %d fails with %r\n", BusTiming, Status));
> > > return Status;
> > > }
> > >
> > > @@ -713,7 +730,7 @@ EmmcSwitchBusTiming (
> > > Private->ControllerHandle,
> > > Slot,
> > > EdkiiSdMmcSwitchClockFreqPost,
> > > - &Timing
> > > + &BusTiming
> > > );
> > > if (EFI_ERROR (Status)) {
> > > DEBUG ((
> > > @@ -754,25 +771,34 @@ EmmcSwitchToHighSpeed (
> >
> >
> > Please help to update the function comments for
> > EmmcSwitchToHighSpeed() after
> > the parameter changes.
> >
> >
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > - IN UINT32 ClockFreq,
> > > - IN BOOLEAN IsDdr,
> > > - IN UINT8 BusWidth
> > > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > > )
> > > {
> > > EFI_STATUS Status;
> > > - UINT8 HsTiming;
> > > UINT8 HostCtrl1;
> > > - SD_MMC_BUS_MODE Timing;
> > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > + BOOLEAN IsDdr;
> > >
> > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > >
> > > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr,
> > BusWidth);
> > > + if ((BusMode->BusTiming != SdMmcMmcHsSdr && BusMode-
> > > >BusTiming != SdMmcMmcHsDdr) ||
> > > + BusMode->ClockFreq > 52) {
> > > + return EFI_INVALID_PARAMETER;
> > > + }
> > > +
> > > + if (BusMode->BusTiming == SdMmcMmcHsDdr) {
> > > + IsDdr = TRUE;
> > > + } else {
> > > + IsDdr = FALSE;
> > > + }
> > > +
> > > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr,
> > BusMode-
> > > >BusWidth);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > +
> > > //
> > > - // Set to Hight Speed timing
> > > + // Set to High Speed timing
> > > //
> > > HostCtrl1 = BIT2;
> > > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1,
> sizeof
> > > (HostCtrl1), &HostCtrl1);
> > > @@ -780,37 +806,27 @@ EmmcSwitchToHighSpeed (
> > > return Status;
> > > }
> > >
> > > - if (IsDdr) {
> > > - Timing = SdMmcMmcHsDdr;
> > > - } else if (ClockFreq == 52) {
> > > - Timing = SdMmcMmcHsSdr;
> > > - } else {
> > > - Timing = SdMmcMmcLegacy;
> > > - }
> > > -
> > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > Timing);
> > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > BusMode->BusTiming);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > >
> > > - HsTiming = 1;
> > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > Timing,
> > > ClockFreq);
> > > -
> > > - return Status;
> > > + return EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
> > > }
> > >
> > > /**
> > > - Switch to the HS200 timing according to request.
> > > + Switch to the HS200 timing. This function assumes that eMMC bus is
> still
> > in
> > > legacy mode.
> > >
> > > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host
> > > Controller
> > > Simplified Spec 3.0 Figure 2-29 for details.
> > >
> > > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
> > > - @param[in] PassThru A pointer to the
> > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > - @param[in] Slot The slot number of the SD card to send the
> > command
> > > to.
> > > - @param[in] Rca The relative device address to be assigned.
> > > - @param[in] ClockFreq The max clock frequency to be set.
> > > - @param[in] BusWidth The bus width to be set, it could be 4 or 8.
> > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> instance.
> > > + @param[in] PassThru A pointer to the
> > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > + @param[in] Slot The slot number of the SD card to send the
> > > command to.
> > > + @param[in] Rca The relative device address to be assigned.
> > > + @param[in] DriverStrength The driver strength to be selected.
> > > + @param[in] ClockFreq The max clock frequency to be set.
> > > + @param[in] BusWidth The bus width to be set, it could be 4 or 8.
> > >
> > > @retval EFI_SUCCESS The operation is done correctly.
> > > @retval Others The operation fails.
> > > @@ -822,30 +838,25 @@ EmmcSwitchToHS200 (
> >
> >
> > Please help to update the function comments for EmmcSwitchToHS200()
> > after the
> > parameter changes.
> >
> >
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > - IN UINT32 ClockFreq,
> > > - IN UINT8 BusWidth
> > > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > > )
> > > {
> > > EFI_STATUS Status;
> > > - UINT8 HsTiming;
> > > UINT16 ClockCtrl;
> > > - SD_MMC_BUS_MODE Timing;
> > > SD_MMC_HC_PRIVATE_DATA *Private;
> > >
> > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > >
> > > - if ((BusWidth != 4) && (BusWidth != 8)) {
> > > + if (BusMode->BusTiming != SdMmcMmcHs200 ||
> > > + (BusMode->BusWidth != 4 && BusMode->BusWidth != 8)) {
> > > return EFI_INVALID_PARAMETER;
> > > }
> > >
> > > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE,
> > BusWidth);
> > > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE,
> > > BusMode->BusWidth);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > //
> > > - // Set to HS200/SDR104 timing
> > > - //
> > > - //
> > > // Stop bus clock at first
> > > //
> > > Status = SdMmcHcStopClock (PciIo, Slot);
> > > @@ -853,9 +864,7 @@ EmmcSwitchToHS200 (
> > > return Status;
> > > }
> > >
> > > - Timing = SdMmcMmcHs200;
> > > -
> > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > Timing);
> > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > BusMode->BusTiming);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > @@ -881,28 +890,27 @@ EmmcSwitchToHS200 (
> > > ClockCtrl = BIT2;
> > > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL,
> sizeof
> > > (ClockCtrl), &ClockCtrl);
> > >
> > > - HsTiming = 2;
> > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > Timing,
> > > ClockFreq);
> > > + Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
> >
> >
> > After the proposed change, the preferred bus timing and driver strength
> > value
> > will be set for the device through the EMMC_SWITCH command.
> >
> > However, on the host controller side, only the bus timing value is also
> > updated
> > in the Host Control 2 Register of the SD HC (via function
> > SdMmcHcUhsSignaling()).
> > It seems to me that the driver strength value does not get updated in this
> > register.
> >
> > I think the SD case has a similar issue.
>
> For SD I agree that there is an issue but for eMMC there is no clear mapping
> between
> eMMC defined driver strength types and SD defined driver strength types.
> The controller
> I happen to be working with seems to ignore the values in this register. If we
> can agree on
> one mapping that will be able to service majority of the eMMC controllers on
> market I don't
> mind adding that. We can maybe add driver strength setting to
> SdMmcHcUhsSignaling so that
> platform has an opportunity to correct core driver during
> EdkiiSdMmcUhsSignaling notify.
How about using the mapping at the beginning of the thread to set the HC2
register and ignore this step for eMMC driver type 4?
>
> >
> >
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > >
> > > - Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth);
> > > + Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusMode-
> > > >BusWidth);
> > >
> > > return Status;
> > > }
> > >
> > > /**
> > > - Switch to the HS400 timing according to request.
> > > + Switch to the HS400 timing. This function assumes that eMMC bus is
> still
> > in
> > > legacy mode.
> > >
> > > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host
> > > Controller
> > > Simplified Spec 3.0 Figure 2-29 for details.
> > >
> > > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
> > > - @param[in] PassThru A pointer to the
> > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > - @param[in] Slot The slot number of the SD card to send the
> > command
> > > to.
> > > - @param[in] Rca The relative device address to be assigned.
> > > - @param[in] ClockFreq The max clock frequency to be set.
> > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> instance.
> > > + @param[in] PassThru A pointer to the
> > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > + @param[in] Slot The slot number of the SD card to send the
> > > command to.
> > > + @param[in] Rca The relative device address to be assigned.
> > > + @param[in] ClockFreq The max clock frequency to be set.
> >
> >
> > Please help to update the function comments for EmmcSwitchToHS400()
> > after the
> > parameter changes.
> >
> >
> > >
> > > @retval EFI_SUCCESS The operation is done correctly.
> > > @retval Others The operation fails.
> > > @@ -914,47 +922,321 @@ EmmcSwitchToHS400 (
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > - IN UINT32 ClockFreq
> > > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > > )
> > > {
> > > EFI_STATUS Status;
> > > - UINT8 HsTiming;
> > > - SD_MMC_BUS_MODE Timing;
> > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > + EDKII_SD_MMC_BUS_MODE Hs200BusMode;
> > > + UINT32 HsFreq;
> > > +
> > > + if (BusMode->BusTiming != SdMmcMmcHs400 ||
> > > + BusMode->BusWidth != 8) {
> > > + return EFI_INVALID_PARAMETER;
> > > + }
> > >
> > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > + Hs200BusMode.BusTiming = SdMmcMmcHs200;
> > > + Hs200BusMode.BusWidth = BusMode->BusWidth;
> > > + Hs200BusMode.ClockFreq = BusMode->ClockFreq;
> > > + Hs200BusMode.DriverStrength = BusMode->DriverStrength;
> > >
> > > - Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, 8);
> > > + Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca,
> > &Hs200BusMode);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > +
> > > //
> > > - // Set to Hight Speed timing and set the clock frequency to a value less
> > than
> > > 52MHz.
> > > + // Set to High Speed timing and set the clock frequency to a value less
> > than
> > > or equal to 52MHz.
> > > + // This step is necessary to be able to switch Bus into 8 bit DDR mode
> > which
> > > is unsupported in HS200.
> > > //
> > > - HsTiming = 1;
> > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > > SdMmcMmcHsSdr, 52);
> > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > SdMmcMmcHsSdr);
> >
> >
> > The above SdMmcHcUhsSignaling() is newly added, is this a bug for the
> origin
> > code?
> >
> > I searched the eMMC spec, it seems to me the spec does not explicitly
> > mention
> > the Host Control 2 Register at all, I am not very sure if such change will
> > bring any effect to devices. Did you have a try without adding such change?
> >
>
> This is aligned to the behavior of EmmcSwitchToHighSpeed function. My
> eMMC
> controller doesn't need this register to be programmed for switch to high
> speed
> but calling SdMmcUhsSignaling here gives override protocol a chance to finish
> switch to high speed for eMMC controllers that need such tweaking.
Hello Marcin,
Do you see any concern for this specific change?
>
> >
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > - //
> > > - // HS400 mode must use 8 data lines.
> > > - //
> > > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, TRUE, 8);
> > > +
> > > + HsFreq = BusMode->ClockFreq < 52 ? BusMode->ClockFreq : 52;
> > > + Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > >DriverStrength, SdMmcMmcHsSdr, HsFreq);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > >
> > > - Timing = SdMmcMmcHs400;
> > > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, TRUE,
> > BusMode-
> > > >BusWidth);
> > > + if (EFI_ERROR (Status)) {
> > > + return Status;
> > > + }
> > >
> > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > Timing);
> > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > BusMode->BusTiming);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > >
> > > - HsTiming = 3;
> > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > Timing,
> > > ClockFreq);
> > > + return EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
> >
> >
> > After the proposed change, the preferred bus timing and driver strength
> > value
> > will be set for the device through the EMMC_SWITCH command.
> >
> > However, on the host controller side, only the bus timing value is also
> > updated
> > in the Host Control 2 Register of the SD HC (via function
> > SdMmcHcUhsSignaling()).
> > It seems to me that the driver strength value does not get updated in this
> > register.
> >
> > I think the SD case has a similar issue.
> >
> >
> > > +}
> > >
> > > - return Status;
> > > +/**
> > > + Check if passed BusTiming is supported in both controller and card.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] ExtCsd Pointer to the card's extended CSD
> > > + @param[in] BusTiming Bus timing to check
> > > +
> > > + @retval TRUE Both card and controller support given BusTiming
> > > + @retval FALSE Card or controller doesn't support given BusTiming
> > > +**/
> > > +STATIC
> > > +BOOLEAN
> > > +IsBusTimingSupported (
> >
> >
> > How about renaming it to EmmcIsBusTimingSupported()?
> >
> >
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN EMMC_EXT_CSD *ExtCsd,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + BOOLEAN Supported;
> > > + SD_MMC_HC_SLOT_CAP *Capabilities;
> > > +
> > > + Capabilities = &Private->Capability[SlotIndex];
> > > +
> > > + Supported = FALSE;
> > > + switch (BusTiming) {
> > > + case SdMmcMmcHs400:
> > > + if ((((ExtCsd->DeviceType & (BIT6 | BIT7)) != 0) && (Capabilities-
> > > >Hs400 != 0)) && Capabilities->BusWidth8) {
> > > + Supported = TRUE;
> > > + }
> > > + break;
> > > + case SdMmcMmcHs200:
> > > + if ((((ExtCsd->DeviceType & (BIT4 | BIT5)) != 0) && (Capabilities-
> > > >Sdr104 != 0))) {
> > > + Supported = TRUE;
> > > + }
> > > + break;
> > > + case SdMmcMmcHsDdr:
> > > + if ((((ExtCsd->DeviceType & (BIT2 | BIT3)) != 0) && (Capabilities-
> > > >Ddr50 != 0))) {
> > > + Supported = TRUE;
> > > + }
> > > + break;
> > > + case SdMmcMmcHsSdr:
> > > + if ((((ExtCsd->DeviceType & BIT1) != 0) && (Capabilities-
> >HighSpeed !=
> > > 0))) {
> > > + Supported = TRUE;
> > > + } else if ((((ExtCsd->DeviceType & BIT0) != 0) && (Capabilities-
> > > >HighSpeed != 0))) {
> >
> >
> > For this case, I think the bus timing should be classified to
> SdMmcMmcLegacy.
> > Since under this timing, the maximum frequency allowed is 26Mhz. If set to
> > SdMmcMmcHsSdr the driver will try to set the frequency to 52Mhz later in
> > EmmcGetTargetClockFreq().
> >
> >
> > > + Supported = TRUE;
> > > + }
> > > + break;
> > > + case SdMmcMmcLegacy:
> > > + Supported = TRUE;
> > > + break;
> > > + default:
> > > + ASSERT (FALSE);
> > > + }
> > > +
> > > + return Supported;
> > > +}
> > > +
> > > +/**
> > > + Get the target bus timing to set on the link. This function
> > > + will try to select highest bus timing supported by card, controller
> > > + and the driver.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] ExtCsd Pointer to the card's extended CSD
> > > +
> > > + @return Bus timing value that should be set on link
> > > +**/
> > > +STATIC
> > > +SD_MMC_BUS_MODE
> > > +EmmcGetTargetBusTiming (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN EMMC_EXT_CSD *ExtCsd
> > > + )
> > > +{
> > > + SD_MMC_BUS_MODE BusTiming;
> > > +
> > > + //
> > > + // We start with highest bus timing that this driver currently support
> and
> > > + // return as soon as we find supported timing.
> > > + //
> > > + BusTiming = SdMmcMmcHs400;
> > > + while (BusTiming > SdMmcMmcLegacy) {
> > > + if (IsBusTimingSupported (Private, SlotIndex, ExtCsd, BusTiming)) {
> > > + break;
> > > + }
> > > + BusTiming--;
> > > + }
> > > +
> > > + return BusTiming;
> > > +}
> > > +
> > > +/**
> > > + Check if the passed bus width is supported by controller and card.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] BusTiming Bus timing set on the link
> > > + @param[in] BusWidth Bus width to check
> > > +
> > > + @retval TRUE Passed bus width is supported in current bus
> > configuration
> > > + @retval FALSE Passed bus width is not supported in current bus
> > > configuration
> > > +**/
> > > +STATIC
> > > +BOOLEAN
> > > +IsBusWidthSupported (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN SD_MMC_BUS_MODE BusTiming,
> > > + IN UINT16 BusWidth
> > > + )
> > > +{
> > > + if (BusWidth == 8 && Private->Capability[SlotIndex].BusWidth8) {
> > > + return TRUE;
> > > + } else if (BusWidth == 4 && BusTiming != SdMmcMmcHs400) {
> > > + return TRUE;
> > > + } else if (BusWidth == 1 && (BusTiming == SdMmcMmcHsSdr ||
> > BusTiming
> > > == SdMmcMmcLegacy)) {
> > > + return TRUE;
> > > + }
> > > +
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Get the target bus width to be set on the bus.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > + @param[in] BusTiming Bus timing set on the bus
> > > +
> > > + @return Bus width to be set on the bus
> > > +**/
> > > +STATIC
> > > +UINT16
> > > +EmmcGetTargetBusWidth (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN EMMC_EXT_CSD *ExtCsd,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + UINT16 BusWidth;
> > > + UINT16 PreferedBusWidth;
> > > +
> > > + PreferedBusWidth = Private-
> > > >Slot[SlotIndex].OperatingParameters.BusWidth;
> > > +
> > > + if (PreferedBusWidth != EDKII_SD_MMC_BUS_WIDTH_IGNORE &&
> > > + IsBusWidthSupported (Private, SlotIndex, BusTiming,
> > > PreferedBusWidth)) {
> > > + BusWidth = PreferedBusWidth;
> > > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 8)) {
> > > + BusWidth = 8;
> > > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 4)) {
> > > + BusWidth = 4;
> > > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 1)) {
> > > + BusWidth = 1;
> > > + }
> > > +
> > > + return BusWidth;
> > > +}
> > > +
> > > +/**
> > > + Get the target clock frequency to be set on the bus.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > + @param[in] BusTiming Bus timing to be set on the bus
> > > +
> > > + @return Value of the clock frequency to be set on bus in MHz
> > > +**/
> > > +STATIC
> > > +UINT32
> > > +EmmcGetTargetClockFreq (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN EMMC_EXT_CSD *ExtCsd,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + UINT32 PreferedClockFreq;
> > > + UINT32 MaxClockFreq;
> > > +
> > > + PreferedClockFreq = Private-
> > > >Slot[SlotIndex].OperatingParameters.ClockFreq;
> > > +
> > > + switch (BusTiming) {
> > > + case SdMmcMmcHs400:
> > > + case SdMmcMmcHs200:
> > > + MaxClockFreq = 200;
> > > + break;
> > > + case SdMmcMmcHsSdr:
> > > + case SdMmcMmcHsDdr:
> > > + MaxClockFreq = 52;
> > > + break;
> > > + default:
> > > + MaxClockFreq = 26;
> > > + break;
> > > + }
> > > +
> > > + if (PreferedClockFreq != EDKII_SD_MMC_CLOCK_FREQ_IGNORE &&
> > > PreferedClockFreq < MaxClockFreq) {
> > > + return PreferedClockFreq;
> > > + } else {
> > > + return MaxClockFreq;
> > > + }
> > > +}
> > > +
> > > +/**
> > > + Get the driver strength to be set on bus
> >
> > Please help to append a '.' character for the above line.
> > It is required for the edk2 coding style.
> >
> >
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > + @param[in] BusTiming Bus timing set on the bus
> > > +
> > > + @return Value of the driver strength to be set on the bus
> > > +**/
> > > +STATIC
> > > +EDKII_SD_MMC_DRIVER_STRENGTH
> > > +EmmcGetTargetDriverStrength (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN EMMC_EXT_CSD *ExtCsd,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + EDKII_SD_MMC_DRIVER_STRENGTH PreferedDriverStrength;
> > > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > > +
> > > + PreferedDriverStrength = Private-
> > > >Slot[SlotIndex].OperatingParameters.DriverStrength;
> > > + DriverStrength.Emmc = EmmcDriverStrengthType0;
> > > +
> > > + if (PreferedDriverStrength.Emmc !=
> > > EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE &&
> > > + (ExtCsd->DriverStrength & (BIT0 << PreferedDriverStrength.Emmc)))
> {
> >
> >
> > The host controller also has a capability for different types of driver
> strength.
> > (Capabilities Register, bit 36~38)
> >
> > The check should take it into consideration as well.
>
> For SD it should. For eMMC it's not as obvious since as I mentioned we don't
> have a mapping defined.
> If we agree on one we can add this and for all eMMC controllers that won't
> follow it I guess we can
> leave it to the platform code to override capabilities.
Similar as one comment above, the mapping of eMMC driver type 0~3 looks
consistent to SD driver type A~D. As for eMMC driver type 4, I think just
checking the capability of the device is enough.
>
> >
> >
> > > + DriverStrength.Emmc = PreferedDriverStrength.Emmc;
> > > + }
> > > +
> > > + return DriverStrength;
> > > +}
> > > +
> > > +/**
> > > + Get the target settings for the bus mode.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > + @param[out] BusMode Target configuration of the bus
> > > +**/
> > > +STATIC
> > > +VOID
> > > +EmmcGetTargetBusMode (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN EMMC_EXT_CSD *ExtCsd,
> > > + OUT EDKII_SD_MMC_BUS_MODE *BusMode
> > > + )
> > > +{
> > > + BusMode->BusTiming = EmmcGetTargetBusTiming (Private, SlotIndex,
> > > ExtCsd);
> > > + BusMode->BusWidth = EmmcGetTargetBusWidth (Private, SlotIndex,
> > > ExtCsd, BusMode->BusTiming);
> > > + BusMode->ClockFreq = EmmcGetTargetClockFreq (Private, SlotIndex,
> > > ExtCsd, BusMode->BusTiming);
> > > + BusMode->DriverStrength = EmmcGetTargetDriverStrength (Private,
> > > SlotIndex, ExtCsd, BusMode->BusTiming);
> > > }
> > >
> > > /**
> > > @@ -983,10 +1265,7 @@ EmmcSetBusMode (
> > > EFI_STATUS Status;
> > > EMMC_CSD Csd;
> > > EMMC_EXT_CSD ExtCsd;
> > > - UINT8 HsTiming;
> > > - BOOLEAN IsDdr;
> > > - UINT32 ClockFreq;
> > > - UINT8 BusWidth;
> > > + EDKII_SD_MMC_BUS_MODE BusMode;
> > > SD_MMC_HC_PRIVATE_DATA *Private;
> > >
> > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > @@ -1004,85 +1283,30 @@ EmmcSetBusMode (
> > > }
> > >
> > > ASSERT (Private->BaseClkFreq[Slot] != 0);
> > > +
> > > //
> > > - // Check if the Host Controller support 8bits bus width.
> > > - //
> > > - if (Private->Capability[Slot].BusWidth8 != 0) {
> > > - BusWidth = 8;
> > > - } else {
> > > - BusWidth = 4;
> > > - }
> > > - //
> > > - // Get Deivce_Type from EXT_CSD register.
> > > + // Get Device_Type from EXT_CSD register.
> > > //
> > > Status = EmmcGetExtCsd (PassThru, Slot, &ExtCsd);
> > > if (EFI_ERROR (Status)) {
> > > DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetExtCsd fails
> > with %r\n",
> > > Status));
> > > return Status;
> > > }
> > > - //
> > > - // Calculate supported bus speed/bus width/clock frequency.
> > > - //
> > > - HsTiming = 0;
> > > - IsDdr = FALSE;
> > > - ClockFreq = 0;
> > > - if (((ExtCsd.DeviceType & (BIT4 | BIT5)) != 0) && (Private-
> > > >Capability[Slot].Sdr104 != 0)) {
> > > - HsTiming = 2;
> > > - IsDdr = FALSE;
> > > - ClockFreq = 200;
> > > - } else if (((ExtCsd.DeviceType & (BIT2 | BIT3)) != 0) && (Private-
> > > >Capability[Slot].Ddr50 != 0)) {
> > > - HsTiming = 1;
> > > - IsDdr = TRUE;
> > > - ClockFreq = 52;
> > > - } else if (((ExtCsd.DeviceType & BIT1) != 0) && (Private-
> > > >Capability[Slot].HighSpeed != 0)) {
> > > - HsTiming = 1;
> > > - IsDdr = FALSE;
> > > - ClockFreq = 52;
> > > - } else if (((ExtCsd.DeviceType & BIT0) != 0) && (Private-
> > > >Capability[Slot].HighSpeed != 0)) {
> > > - HsTiming = 1;
> > > - IsDdr = FALSE;
> > > - ClockFreq = 26;
> > > - }
> > > - //
> > > - // Check if both of the device and the host controller support HS400
> DDR
> > > mode.
> > > - //
> > > - if (((ExtCsd.DeviceType & (BIT6 | BIT7)) != 0) && (Private-
> > > >Capability[Slot].Hs400 != 0)) {
> > > - //
> > > - // The host controller supports 8bits bus.
> > > - //
> > > - ASSERT (BusWidth == 8);
> > > - HsTiming = 3;
> > > - IsDdr = TRUE;
> > > - ClockFreq = 200;
> > > - }
> > >
> > > - if ((ClockFreq == 0) || (HsTiming == 0)) {
> > > - //
> > > - // Continue using default setting.
> > > - //
> > > - return EFI_SUCCESS;
> > > - }
> > > + EmmcGetTargetBusMode (Private, Slot, &ExtCsd, &BusMode);
> > >
> > > - DEBUG ((DEBUG_INFO, "EmmcSetBusMode: HsTiming %d
> ClockFreq %d
> > > BusWidth %d Ddr %a\n", HsTiming, ClockFreq, BusWidth, IsDdr ?
> > > "TRUE":"FALSE"));
> > > + DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Target bus mode: timing
> > > = %d, width = %d, clock freq = %d, driver strength = %d\n",
> > > + BusMode.BusTiming, BusMode.BusWidth,
> > BusMode.ClockFreq,
> > > BusMode.DriverStrength.Emmc));
> > >
> > > - if (HsTiming == 3) {
> > > - //
> > > - // Execute HS400 timing switch procedure
> > > - //
> > > - Status = EmmcSwitchToHS400 (PciIo, PassThru, Slot, Rca, ClockFreq);
> > > - } else if (HsTiming == 2) {
> > > - //
> > > - // Execute HS200 timing switch procedure
> > > - //
> > > - Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq,
> > > BusWidth);
> > > + if (BusMode.BusTiming == SdMmcMmcHs400) {
> > > + Status = EmmcSwitchToHS400 (PciIo, PassThru, Slot, Rca, &BusMode);
> > > + } else if (BusMode.BusTiming == SdMmcMmcHs200) {
> > > + Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, &BusMode);
> > > } else {
> > > - //
> > > - // Execute High Speed timing switch procedure
> > > - //
> > > - Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca,
> ClockFreq,
> > > IsDdr, BusWidth);
> > > + Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca,
> > &BusMode);
> > > }
> > >
> > > - DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n",
> > (HsTiming
> > > == 3) ? "HS400" : ((HsTiming == 2) ? "HS200" : "HighSpeed"), Status));
> > > + DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n",
> > > (BusMode.BusTiming == SdMmcMmcHs400) ? "HS400" :
> > > ((BusMode.BusTiming == SdMmcMmcHs200) ? "HS200" : "HighSpeed"),
> > > Status));
> > >
> > > return Status;
> > > }
> > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > index 17936a5492..36d2b487df 100644
> > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > @@ -313,10 +313,6 @@ SdCardSetRca (
> > > return Status;
> > > }
> > >
> > > -
> > > -
> > > -
> > > -
> > > /**
> > > Send command SELECT_DESELECT_CARD to the SD device to
> > > select/deselect it.
> > >
> > > @@ -422,7 +418,7 @@ SdCardSetBusWidth (
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > - IN UINT8 BusWidth
> > > + IN UINT16 BusWidth
> > > )
> > > {
> > > EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
> > > @@ -476,7 +472,7 @@ SdCardSetBusWidth (
> > > @param[in] Slot The slot number of the SD card to send the
> > command
> > > to.
> > > @param[in] AccessMode The value for access mode group.
> >
> >
> > Please help to update the parameter comment to reflect the function
> > interface changes.
> >
> >
> > > @param[in] CommandSystem The value for command set group.
> > > - @param[in] DriveStrength The value for drive length group.
> > > + @param[in] DriveStrength The value for driver strength group.
> >
> >
> > Please help to update the parameter name in the above comment from
> > 'DriveStrength' to 'DriverStrength'.
> >
> >
> > > @param[in] PowerLimit The value for power limit group.
> > > @param[in] Mode Switch or check function.
> > > @param[out] SwitchResp The return switch function status.
> > > @@ -489,9 +485,9 @@ EFI_STATUS
> > > SdCardSwitch (
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > - IN UINT8 AccessMode,
> > > + IN SD_MMC_BUS_MODE BusTiming,
> > > IN UINT8 CommandSystem,
> > > - IN UINT8 DriveStrength,
> > > + IN SD_DRIVER_STRENGTH_TYPE DriverStrength,
> > > IN UINT8 PowerLimit,
> > > IN BOOLEAN Mode,
> > > OUT UINT8 *SwitchResp
> > > @@ -502,6 +498,7 @@ SdCardSwitch (
> > > EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
> > > EFI_STATUS Status;
> > > UINT32 ModeValue;
> > > + UINT8 AccessMode;
> > >
> > > ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
> > > ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
> > > @@ -516,8 +513,31 @@ SdCardSwitch (
> > > SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
> > >
> > > ModeValue = Mode ? BIT31 : 0;
> > > - SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) |
> > ((PowerLimit
> > > & 0xF) << 4) | \
> > > - ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) <<
> > 12)
> > > | \
> > > +
> > > + switch (BusTiming) {
> > > + case SdMmcUhsDdr50:
> > > + AccessMode = 0x4;
> > > + break;
> > > + case SdMmcUhsSdr104:
> > > + AccessMode = 0x3;
> > > + break;
> > > + case SdMmcUhsSdr50:
> > > + AccessMode = 0x2;
> > > + break;
> > > + case SdMmcUhsSdr25:
> > > + case SdMmcSdHs:
> > > + AccessMode = 0x1;
> > > + break;
> > > + case SdMmcUhsSdr12:
> > > + case SdMmcSdDs:
> > > + AccessMode = 0;
> > > + break;
> > > + default:
> > > + AccessMode = 0xF;
> > > + }
> > > +
> > > + SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) |
> > > ((CommandSystem & 0xF) << 4) | \
> > > + ((DriverStrength & 0xF) << 8) | ((PowerLimit & 0xF) <<
> 12)
> > |
> > > \
> > > ModeValue;
> > >
> > > Packet.InDataBuffer = SwitchResp;
> > > @@ -718,7 +738,7 @@ SdCardSwitchBusWidth (
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > - IN UINT8 BusWidth
> > > + IN UINT16 BusWidth
> > > )
> > > {
> > > EFI_STATUS Status;
> > > @@ -748,6 +768,261 @@ SdCardSwitchBusWidth (
> > > return Status;
> > > }
> > >
> > > +/**
> > > + Check if passed BusTiming is supported in both controller and card.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] CardSupportedBusTimings Bitmask indicating which bus
> > > timings are supported by card
> > > + @param[in] IsInUhsI Flag indicating if link is in UHS-I
> > > +
> > > + @retval TRUE Both card and controller support given BusTiming
> > > + @retval FALSE Card or controller doesn't support given BusTiming
> > > +**/
> > > +STATIC
> > > +BOOLEAN
> > > +SdIsBusTimingSupported (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN UINT8 CardSupportedBusTimings,
> > > + IN BOOLEAN IsInUhsI,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + SD_MMC_HC_SLOT_CAP *Capability;
> > > +
> > > + Capability = &Private->Capability[SlotIndex];
> > > +
> > > + if (IsInUhsI) {
> > > + switch (BusTiming) {
> >
> >
> > Please help to add a 'default' handle for this 'switch' statement, the
> > proposed
> > code will cause a GCC5 build failure.
> >
> >
> > > + case SdMmcUhsSdr104:
> > > + if (Capability->Sdr104 && ((CardSupportedBusTimings & BIT3) != 0))
> {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + case SdMmcUhsDdr50:
> > > + if (Capability->Ddr50 && ((CardSupportedBusTimings & BIT4) != 0)) {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + case SdMmcUhsSdr50:
> > > + if (Capability->Sdr50 && ((CardSupportedBusTimings & BIT2) != 0)) {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + case SdMmcUhsSdr25:
> > > + if ((CardSupportedBusTimings & BIT1) != 0) {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + case SdMmcUhsSdr12:
> > > + if ((CardSupportedBusTimings & BIT0) != 0) {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + }
> > > + } else {
> > > + switch (BusTiming) {
> >
> >
> > Please help to add a 'default' handle for this 'switch' statement, the
> > proposed
> > code will cause a GCC5 build failure.
> >
> >
> > > + case SdMmcSdHs:
> > > + if (Capability->HighSpeed && (CardSupportedBusTimings & BIT1) !=
> 0)
> > {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + case SdMmcSdDs:
> > > + if ((CardSupportedBusTimings & BIT0) != 0) {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + }
> > > + }
> > > +
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Get the target bus timing to set on the link. This function
> > > + will try to select highest bus timing supported by card, controller
> > > + and the driver.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] CardSupportedBusTimings Bitmask indicating which bus
> > > timings are supported by card
> > > + @param[in] IsInUhsI Flag indicating if link is in UHS-I
> > > +
> > > + @return Bus timing value that should be set on link
> > > +**/
> > > +STATIC
> > > +SD_MMC_BUS_MODE
> > > +SdGetTargetBusTiming (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN UINT8 CardSupportedBusTimings,
> > > + IN BOOLEAN IsInUhsI
> > > + )
> > > +{
> > > + SD_MMC_BUS_MODE BusTiming;
> > > +
> > > + if (IsInUhsI) {
> > > + BusTiming = SdMmcUhsSdr104;
> > > + } else {
> > > + BusTiming = SdMmcSdHs;
> > > + }
> > > +
> > > + while (BusTiming > SdMmcSdDs) {
> > > + if (SdIsBusTimingSupported (Private, SlotIndex,
> > > CardSupportedBusTimings, IsInUhsI, BusTiming)) {
> > > + break;
> > > + }
> > > + BusTiming--;
> > > + }
> >
> >
> > The origin logic has the below preference when selecting bus timing
> > (if supported):
> >
> > SdMmcUhsSdr104
> > SdMmcUhsSdr50
> > SdMmcUhsDdr50
> > SdMmcUhsSdr25
> > SdMmcUhsSdr12
> >
> > So we need to reorder the types in 'SD_MMC_BUS_MODE' to:
> >
> > typedef enum {
> > SdMmcSdDs,
> > SdMmcSdHs,
> > SdMmcUhsSdr12,
> > SdMmcUhsSdr25,
> > SdMmcUhsDdr50,
> > SdMmcUhsSdr50,
> > SdMmcUhsSdr104,
> > ...
> > } SD_MMC_BUS_MODE;
> >
> > Otherwise, the Ddr50 mode will never be selected.
> >
> >
> > > +
> > > + return BusTiming;
> > > +}
> > > +
> > > +/**
> > > + Get the target bus width to be set on the bus.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] BusTiming Bus timing set on the bus
> > > +
> > > + @return Bus width to be set on the bus
> > > +**/
> > > +STATIC
> > > +UINT16
> > > +SdGetTargetBusWidth (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + UINT16 BusWidth;
> > > + UINT16 PreferedBusWidth;
> > > +
> > > + PreferedBusWidth = Private-
> > > >Slot[SlotIndex].OperatingParameters.BusWidth;
> > > +
> > > + if (BusTiming == SdMmcSdDs || BusTiming == SdMmcSdHs) {
> > > + if (PreferedBusWidth != EDKII_SD_MMC_BUS_WIDTH_IGNORE) {
> > > + BusWidth = PreferedBusWidth;
> >
> >
> > The supported bus width is either 1 or 4 bit for 3.3V signal cards.
> > I think we need a more strict check here.
> >
> >
> > > + } else {
> > > + BusWidth = 4;
> > > + }
> > > + } else {
> > > + //
> > > + // UHS-I modes support only 4-bit width.
> > > + // Switch to 4-bit has been done before calling this function anyway so
> > > + // this is purely informational.
> > > + //
> > > + BusWidth = 4;
> > > + }
> > > +
> > > + return BusWidth;
> > > +}
> > > +
> > > +/**
> > > + Get the target clock frequency to be set on the bus.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] BusTiming Bus timing to be set on the bus
> > > +
> > > + @return Value of the clock frequency to be set on bus in MHz
> > > +**/
> > > +STATIC
> > > +UINT32
> > > +SdGetTargetBusClockFreq (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + UINT32 PreferedClockFreq;
> > > + UINT32 MaxClockFreq;
> > > +
> > > + PreferedClockFreq = Private-
> > > >Slot[SlotIndex].OperatingParameters.ClockFreq;
> > > +
> > > + switch (BusTiming) {
> > > + case SdMmcUhsSdr104:
> > > + MaxClockFreq = 208;
> > > + break;
> > > + case SdMmcUhsSdr50:
> > > + MaxClockFreq = 100;
> > > + break;
> > > + case SdMmcUhsDdr50:
> > > + case SdMmcUhsSdr25:
> > > + case SdMmcSdHs:
> > > + MaxClockFreq = 50;
> > > + break;
> > > + case SdMmcUhsSdr12:
> > > + case SdMmcSdDs:
> > > + default:
> > > + MaxClockFreq = 25;
> >
> >
> > Minor comment, need an extra space for the above line.
> >
> >
> > > + }
> > > +
> > > + if (PreferedClockFreq != EDKII_SD_MMC_CLOCK_FREQ_IGNORE &&
> > > PreferedClockFreq < MaxClockFreq) {
> > > + return PreferedClockFreq;
> > > + } else {
> > > + return MaxClockFreq;
> > > + }
> > > +}
> > > +
> > > +/**
> > > + Get the driver strength to be set on bus
> >
> >
> > Please help to append a '.' character for the above line.
> > It is required for the edk2 coding style.
> >
> >
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] CardSupportedDriverStrengths Bitmask indicating which
> > > driver strengths are supported on the card
> > > + @param[in] BusTiming Bus timing set on the bus
> > > +
> > > + @return Value of the driver strength to be set on the bus
> > > +**/
> > > +STATIC
> > > +EDKII_SD_MMC_DRIVER_STRENGTH
> > > +SdGetTargetDriverStrength (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN UINT8 CardSupportedDriverStrengths,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> >
> >
> > One question here, the driver strength configuration is only for UHS-I cards.
> > Does the check on 'CardSupportedDriverStrengths' enough to ensure the
> > above
> > requirement or a boolean input parameter 'IsInUhsI' is needed here?
> >
>
> I think we can leave it to the code that actually sets the bus parameters
> to simply skip driver strength programming for legacy and select driver
> strength here
> based only on HW support and platform preference. The alternative is to
> return
> SdDriverStrengthIgnore here and handle that in code that actually sets driver
> strength.
Either approach is okay to me, since both of them need extra handling in
SdCardSwitch() & SdMmcHcUhsSignaling() when setting driver strength.
I slightly prefer the 1st option, since the logic is a bit more straight-
forward.
>
> >
> > > +{
> > > + EDKII_SD_MMC_DRIVER_STRENGTH PreferedDriverStrength;
> > > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > > +
> > > + PreferedDriverStrength = Private-
> > > >Slot[SlotIndex].OperatingParameters.DriverStrength;
> > > + DriverStrength.Sd = SdDriverStrengthTypeB;
> > > +
> > > + if (PreferedDriverStrength.Sd !=
> > > EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE &&
> > > + (CardSupportedDriverStrengths & (BIT0 <<
> > PreferedDriverStrength.Sd)))
> >
> >
> > The host controller also has a capability for different types of driver
> strength.
> > (Capabilities Register, bit 36~38)
> >
> > The check should take it into consideration as well.
> >
> >
> > > {
> > > + DriverStrength.Sd = PreferedDriverStrength.Sd;
> > > + }
> > > +
> > > + return DriverStrength;
> > > +}
> > > +
> > > +/**
> > > + Get the target settings for the bus mode.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] SwitchQueryResp Pointer to switch query response
> > > + @param[in] IsInUhsI Flag indicating if link is in UHS-I mode
> > > + @param[out] BusMode Target configuration of the bus
> > > +**/
> > > +STATIC
> > > +VOID
> > > +SdGetTargetBusMode (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN UINT8 *SwitchQueryResp,
> > > + IN BOOLEAN IsInUhsI,
> > > + OUT EDKII_SD_MMC_BUS_MODE *BusMode
> > > + )
> > > +{
> > > + BusMode->BusTiming = SdGetTargetBusTiming (Private, SlotIndex,
> > > SwitchQueryResp[13], IsInUhsI);
> > > + BusMode->BusWidth = SdGetTargetBusWidth (Private, SlotIndex,
> > > BusMode->BusTiming);
> > > + BusMode->ClockFreq = SdGetTargetBusClockFreq (Private, SlotIndex,
> > > BusMode->BusTiming);
> > > + BusMode->DriverStrength = SdGetTargetDriverStrength (Private,
> > > SlotIndex, SwitchQueryResp[9], BusMode->BusTiming);
> > > +}
> > > +
> > > /**
> > > Switch the high speed timing according to request.
> > >
> > > @@ -775,13 +1050,10 @@ SdCardSetBusMode (
> > > {
> > > EFI_STATUS Status;
> > > SD_MMC_HC_SLOT_CAP *Capability;
> > > - UINT32 ClockFreq;
> > > - UINT8 BusWidth;
> > > - UINT8 AccessMode;
> > > UINT8 HostCtrl1;
> > > UINT8 SwitchResp[64];
> > > - SD_MMC_BUS_MODE Timing;
> > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > + EDKII_SD_MMC_BUS_MODE BusMode;
> > >
> > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > >
> > > @@ -792,61 +1064,46 @@ SdCardSetBusMode (
> > > return Status;
> > > }
> > >
> > > - BusWidth = 4;
> > > -
> > > - Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, BusWidth);
> > > - if (EFI_ERROR (Status)) {
> > > - return Status;
> > > + if (S18A) {
> > > + //
> > > + // For UHS-I speed modes 4-bit data bus is requiered so we
> > > + // switch here irrespective of platform preference.
> > > + //
> > > + Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, 4);
> > > + if (EFI_ERROR (Status)) {
> > > + return Status;
> > > + }
> > > }
> > > +
> > > //
> > > // Get the supported bus speed from SWITCH cmd return data group #1.
> > > //
> > > - Status = SdCardSwitch (PassThru, Slot, 0xF, 0xF, 0xF, 0xF, FALSE,
> > > SwitchResp);
> > > + Status = SdCardSwitch (PassThru, Slot, 0xFF, 0xF,
> SdDriverStrengthIgnore,
> > > 0xF, FALSE, SwitchResp);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > - //
> > > - // Calculate supported bus speed/bus width/clock frequency by host
> and
> > > device capability.
> > > - //
> > > - ClockFreq = 0;
> > > - if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0))
> {
> > > - ClockFreq = 208;
> > > - AccessMode = 3;
> > > - Timing = SdMmcUhsSdr104;
> > > - } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] &
> BIT2) !=
> > 0))
> > > {
> > > - ClockFreq = 100;
> > > - AccessMode = 2;
> > > - Timing = SdMmcUhsSdr50;
> > > - } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] &
> BIT4) !=
> > > 0)) {
> > > - ClockFreq = 50;
> > > - AccessMode = 4;
> > > - Timing = SdMmcUhsDdr50;
> > > - } else if ((SwitchResp[13] & BIT1) != 0) {
> > > - ClockFreq = 50;
> > > - AccessMode = 1;
> > > - Timing = SdMmcUhsSdr25;
> > > - } else {
> > > - ClockFreq = 25;
> > > - AccessMode = 0;
> > > - Timing = SdMmcUhsSdr12;
> > > +
> > > + SdGetTargetBusMode (Private, Slot, SwitchResp, S18A, &BusMode);
> > > +
> > > + DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Target bus mode: bus
> > timing
> > > = %d, bus width = %d, clock freq[MHz] = %d, driver strength = %d\n",
> > > + BusMode.BusTiming, BusMode.BusWidth,
> > BusMode.ClockFreq,
> > > BusMode.DriverStrength.Sd));
> > > +
> > > + if (!S18A) {
> > > + Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca,
> > > BusMode.BusWidth);
> > > + if (EFI_ERROR (Status)) {
> > > + return Status;
> > > + }
> > > }
> >
> >
> > Is it feasible to set the bus width for the 3.3V signaled cards & the UHS-I
> > cards together here? I think the SdGetTargetBusWidth() already handles
> the
> > UHS-I cards case well by always setting the bus width to 4.
> >
>
> So basically to skip if (!S18A) condition and do bus width switch
> unconditionally?
> I am not sure how the bus will react to additional bus width switch for UHS-I
> case
> and I am not able to test it locally as I only have controller with legacy support
> available for tests.
> I guess I will give it a try and we will revert it if it causes any problems.
Sorry for not being clear.
I suggest to just remove the below codes:
if (S18A) {
//
// For UHS-I speed modes 4-bit data bus is requiered so we
// switch here irrespective of platform preference.
//
Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, 4);
if (EFI_ERROR (Status)) {
return Status;
}
}
And set the bus width in one place after SdGetTargetBusMode().
(Also remove the 'if' condition - if (!S18A), do it together for UHS-I &
3.3V signaling cards.)
Best Regards,
Hao Wu
>
> >
> > >
> > > - Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE,
> > > SwitchResp);
> > > + Status = SdCardSwitch (PassThru, Slot, BusMode.BusTiming, 0xF,
> > > BusMode.DriverStrength.Sd, 0xF, TRUE, SwitchResp);
> >
> >
> > After the proposed change, the preferred bus timing and driver strength
> > value
> > will be set for the device through the SD_SWITCH command.
> >
> > However, on the host controller side, only the bus timing value is also
> > updated
> > in the Host Control 2 Register of the SD HC (via function
> > SdMmcHcUhsSignaling()).
> > It seems to me that the driver strength value does not get updated in this
> > register.
> >
> > I think the eMMC case has a similar issue.
> >
> >
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > >
> > > - if ((SwitchResp[16] & 0xF) != AccessMode) {
> > > - DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: Switch to
> > AccessMode %d
> > > ClockFreq %d BusWidth %d fails! The Switch response is 0x%1x\n",
> > > AccessMode, ClockFreq, BusWidth, SwitchResp[16] & 0xF));
> > > - return EFI_DEVICE_ERROR;
> > > - }
> >
> >
> > The above check may still be needed. Also, the whether the target driver
> > strength is successfully set needs to be checked as well.
> >
> > How about adding checks in function SdCardSwitch() for mode 1 of the
> > switch
> > command?
> >
> >
> > > -
> > > - DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Switch to
> AccessMode %d
> > > ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));
> > > -
> > > //
> > > - // Set to Hight Speed timing
> > > + // Set to High Speed timing
> > > //
> > > - if (AccessMode == 1) {
> > > + if (BusMode.BusTiming == SdMmcSdHs) {
> > > HostCtrl1 = BIT2;
> > > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1,
> > sizeof
> > > (HostCtrl1), &HostCtrl1);
> > > if (EFI_ERROR (Status)) {
> > > @@ -854,12 +1111,12 @@ SdCardSetBusMode (
> > > }
> > > }
> > >
> > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > Timing);
> > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > BusMode.BusTiming);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > >
> > > - Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> > > >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> > > + Status = SdMmcHcClockSupply (PciIo, Slot, BusMode.ClockFreq * 1000,
> > > Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > @@ -869,7 +1126,7 @@ SdCardSetBusMode (
> > > Private->ControllerHandle,
> > > Slot,
> > > EdkiiSdMmcSwitchClockFreqPost,
> > > - &Timing
> > > + &BusMode.BusTiming
> > > );
> > > if (EFI_ERROR (Status)) {
> > > DEBUG ((
> > > @@ -882,7 +1139,7 @@ SdCardSetBusMode (
> > > }
> > > }
> > >
> > > - if ((AccessMode == 3) || ((AccessMode == 2) && (Capability-
> > > >TuningSDR50 != 0))) {
> > > + if ((BusMode.BusTiming == SdMmcUhsSdr104) ||
> ((BusMode.BusTiming
> > > == SdMmcUhsSdr50) && (Capability->TuningSDR50 != 0))) {
> > > Status = SdCardTuningClock (PciIo, PassThru, Slot);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > @@ -1025,10 +1282,8 @@ SdCardIdentification (
> > > // (One of support bits is set to 1: SDR50, SDR104 or DDR50 in the
> > > // Capabilities register), switch its voltage to 1.8V.
> > > //
> > > - if ((Private->Capability[Slot].Sdr50 != 0 ||
> > > - Private->Capability[Slot].Sdr104 != 0 ||
> > > - Private->Capability[Slot].Ddr50 != 0) &&
> > > - ((Ocr & BIT24) != 0)) {
> > > + if ((Private->Capability[Slot].Sdr50 || Private->Capability[Slot].Ddr50 ||
> > > Private->Capability[Slot].Sdr104) &&
> > > + ((Ocr & BIT24) != 0)) {
> >
> >
> > Minor comment, for:
> > Private->Capability[Slot].Sdr50
> > Private->Capability[Slot].Ddr50
> > Private->Capability[Slot].Sdr104
> >
> > They are of type UINT32, should use operators '==' or '!=' in condition
> > statement. I think the origin logic is good here.
> >
> >
> > > Status = SdCardVoltageSwitch (PassThru, Slot);
> > > if (EFI_ERROR (Status)) {
> > > DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing
> > > SdCardVoltageSwitch fails with %r\n", Status));
> > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > index 4881ee44cc..8f49954b7f 100644
> > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > @@ -28,6 +28,11 @@ EFI_DRIVER_BINDING_PROTOCOL
> > > gSdMmcPciHcDriverBinding = {
> > > NULL
> > > };
> > >
> > > +#define SLOT_INIT_TEMPLATE {0, UnknownSlot, 0, 0, 0, \
> > > + {EDKII_SD_MMC_BUS_WIDTH_IGNORE,\
> > > + EDKII_SD_MMC_CLOCK_FREQ_IGNORE,\
> > > + EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE}}
> >
> >
> > Please help to update the above definition to:
> > #define SLOT_INIT_TEMPLATE {0, UnknownSlot, 0, 0, 0, \
> > {EDKII_SD_MMC_BUS_WIDTH_IGNORE,\
> > EDKII_SD_MMC_CLOCK_FREQ_IGNORE,\
> > {EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE}}}
> >
> > The proposed one will cause GCC5 build failure.
> >
> >
> > > +
> > > //
> > > // Template for SD/MMC host controller private data.
> > > //
> > > @@ -50,8 +55,12 @@ SD_MMC_HC_PRIVATE_DATA
> > gSdMmcPciHcTemplate
> > > = {
> > > // Queue
> > > INITIALIZE_LIST_HEAD_VARIABLE (gSdMmcPciHcTemplate.Queue),
> > > { // Slot
> > > - {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0,
> 0,
> > > 0},
> > > - {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0,
> 0,
> > > 0}
> > > + SLOT_INIT_TEMPLATE,
> > > + SLOT_INIT_TEMPLATE,
> > > + SLOT_INIT_TEMPLATE,
> > > + SLOT_INIT_TEMPLATE,
> > > + SLOT_INIT_TEMPLATE,
> > > + SLOT_INIT_TEMPLATE
> > > },
> > > { // Capability
> > > {0},
> > > @@ -328,6 +337,7 @@ SdMmcPciHcEnumerateDevice (
> > >
> > > return;
> > > }
> > > +
> > > /**
> > > Tests to see if this driver supports a given controller. If a child device is
> > > provided,
> > > it further tests to see if this driver supports creating a handle for the
> > > specified child device.
> > > @@ -619,7 +629,6 @@ SdMmcPciHcDriverBindingStart (
> > > Support64BitDma = TRUE;
> > > for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
> > > Private->Slot[Slot].Enable = TRUE;
> > > -
> > > //
> > > // Get SD/MMC Pci Host Controller Version
> > > //
> > > @@ -635,19 +644,34 @@ SdMmcPciHcDriverBindingStart (
> > >
> > > Private->BaseClkFreq[Slot] = Private->Capability[Slot].BaseClkFreq;
> > >
> > > - if (mOverride != NULL && mOverride->Capability != NULL) {
> > > - Status = mOverride->Capability (
> > > - Controller,
> > > - Slot,
> > > - &Private->Capability[Slot],
> > > - &Private->BaseClkFreq[Slot]
> > > - );
> > > - if (EFI_ERROR (Status)) {
> > > - DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",
> > > - __FUNCTION__, Status));
> > > - continue;
> > > + if (mOverride != NULL) {
> > > + if (mOverride->Capability != NULL) {
> > > + Status = mOverride->Capability (
> > > + Controller,
> > > + Slot,
> > > + &Private->Capability[Slot],
> > > + &Private->BaseClkFreq[Slot]
> > > + );
> > > + if (EFI_ERROR (Status)) {
> > > + DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",
> > > + __FUNCTION__, Status));
> > > + continue;
> > > + }
> > > + }
> > > +
> > > + if (mOverride->NotifyPhase != NULL) {
> > > + Status = mOverride->NotifyPhase (
> > > + Controller,
> > > + Slot,
> > > + EdkiiSdMmcGetOperatingParam,
> > > + (VOID*)&Private->Slot[Slot].OperatingParameters
> > > + );
> > > + if (EFI_ERROR (Status)) {
> > > + DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters,
> > > using defaults\n" __FUNCTION__));
> >
> >
> > Please update the above line to (missed one ',' before '__FUNCTION__'):
> > DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters, using
> > defaults\n", __FUNCTION__));
> >
> > It will cause GCC5 build failure for the proposed change.
> >
> >
> > > + }
> > > }
> > > }
> > > +
> > > DumpCapabilityReg (Slot, &Private->Capability[Slot]);
> > > DEBUG ((
> > > DEBUG_INFO,
> > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > index 77bbf83b76..b768f3942f 100644
> > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > @@ -78,11 +78,12 @@ typedef enum {
> > > } EFI_SD_MMC_SLOT_TYPE;
> > >
> > > typedef struct {
> > > - BOOLEAN Enable;
> > > - EFI_SD_MMC_SLOT_TYPE SlotType;
> > > - BOOLEAN MediaPresent;
> > > - BOOLEAN Initialized;
> > > - SD_MMC_CARD_TYPE CardType;
> > > + BOOLEAN Enable;
> > > + EFI_SD_MMC_SLOT_TYPE SlotType;
> > > + BOOLEAN MediaPresent;
> > > + BOOLEAN Initialized;
> > > + SD_MMC_CARD_TYPE CardType;
> > > + EDKII_SD_MMC_OPERATING_PARAMETERS OperatingParameters;
> > > } SD_MMC_HC_SLOT;
> > >
> > > typedef struct {
> > > @@ -120,6 +121,13 @@ typedef struct {
> > > UINT32 BaseClkFreq[SD_MMC_HC_MAX_SLOT];
> > > } SD_MMC_HC_PRIVATE_DATA;
> > >
> > > +typedef struct {
> > > + EDKII_SD_MMC_BUS_TIMING BusTiming;
> >
> >
> > Should be:
> > SD_MMC_BUS_MODE BusTiming;
> >
> >
> > > + UINT16 BusWidth;
> > > + UINT32 ClockFreq;
> > > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > > +} EDKII_SD_MMC_BUS_MODE;
> >
> >
> > Since the above structure is a driver internal one, I prefer dropping the
> > prefix 'EDKII_'. But unfortunately, SD_MMC_BUS_MODE is already used in
> > Protocol/SdMmcOverride.h, so how about SD_MMC_BUS_SETTINGS?
> >
> >
> > > +
> > > #define SD_MMC_HC_TRB_SIG SIGNATURE_32 ('T', 'R', 'B', 'T')
> > >
> > > //
> > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > index 5d1f977e55..863ae3db34 100644
> > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > @@ -1263,10 +1263,10 @@ SdMmcHcInitHost (
> > > **/
> > > EFI_STATUS
> > > SdMmcHcUhsSignaling (
> > > - IN EFI_HANDLE ControllerHandle,
> > > - IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > - IN UINT8 Slot,
> > > - IN SD_MMC_BUS_MODE Timing
> > > + IN EFI_HANDLE ControllerHandle,
> > > + IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > + IN UINT8 Slot,
> > > + IN SD_MMC_BUS_MODE Timing
> > > )
> >
> >
> > I think the changes made here (space indentation) can be dropped.
> >
> >
> > > {
> > > EFI_STATUS Status;
> > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > index 0b0d415256..c4d4aef73a 100644
> > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > @@ -611,10 +611,10 @@ SdMmcHcInitTimeoutCtrl (
> > > **/
> > > EFI_STATUS
> > > SdMmcHcUhsSignaling (
> > > - IN EFI_HANDLE ControllerHandle,
> > > - IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > - IN UINT8 Slot,
> > > - IN SD_MMC_BUS_MODE Timing
> > > + IN EFI_HANDLE ControllerHandle,
> > > + IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > + IN UINT8 Slot,
> > > + IN SD_MMC_BUS_MODE Timing
> >
> >
> > I think the changes made here (space indentation) can be dropped.
> >
> > Best Regards,
> > Hao Wu
> >
> >
> > > );
> > >
> > > #endif
> > > --
> > > 2.14.1.windows.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/2] Add GetOperatingParam notify phase to SdMmcOverride protocol
2019-06-14 1:46 ` Wu, Hao A
@ 2019-06-14 18:44 ` Marcin Wojtas
0 siblings, 0 replies; 9+ messages in thread
From: Marcin Wojtas @ 2019-06-14 18:44 UTC (permalink / raw)
To: Wu, Hao A; +Cc: devel@edk2.groups.io, Ard Biesheuvel, Albecki, Mateusz
[-- Attachment #1: Type: text/plain, Size: 6206 bytes --]
Hi Hao,
Please give me some time to try and review - I hope to find some slot next
week.
Best regards,
Marcin
pt., 14 cze 2019 o 03:46 Wu, Hao A <hao.a.wu@intel.com> napisał(a):
> Loop in Ard and Marcin.
>
>
>
>
>
> Hello Ard and Marcin,
>
>
>
> We are proposing to make an extension to the SDMMC Override protocol to
>
> more customization for platforms during the SD/eMMC device/controller
>
> initialization process.
>
>
>
> For convenience, the series is available at:
>
> https://github.com/hwu25/edk2/tree/sdmmc_override_extension_v1
>
>
>
> I only verified the change will not break the build for platforms
>
> (in edk2-platform repo). Could you help provide feedbacks for this series?
>
> Thanks in advance.
>
>
>
> Best Regards,
>
> Hao Wu
>
>
>
> *From:* Albecki, Mateusz
> *Sent:* Thursday, June 13, 2019 9:44 PM
> *To:* devel@edk2.groups.io
> *Cc:* Wu, Hao A
> *Subject:* RE: [PATCH 0/2] Add GetOperatingParam notify phase to
> SdMmcOverride protocol
>
>
>
> Resending to group.
>
>
>
> *From:* Wu, Hao A
> *Sent:* Monday, June 10, 2019 5:18 AM
> *To:* Albecki, Mateusz <mateusz.albecki@intel.com>
> *Subject:* RE: [PATCH 0/2] Add GetOperatingParam notify phase to
> SdMmcOverride protocol
>
>
>
> Hello Mateusz,
>
>
>
> Thanks for the patch series and sorry for the delayed response.
>
>
>
> One question first, I did not see the patches being sent to the mailing
> list
>
> 'devel@edk2.groups.io'. We have recently switched to this new mailing
> list back
>
> to early April, the old one 'edk2-devel@lists.01.org' is no longer being
> used.
>
>
>
> In case that you have not registered the new list, you can sign up at:
>
> https://edk2.groups.io/g/devel
>
> or email:
>
> devel+subscribe@edk2.groups.io
>
> to get registered in the new mailing list.
>
>
>
> Or you can send me the patch files and I will help to send them to the
> mailing list.
>
>
>
>
>
> Below are some general level feedbacks (Other patch-specific feedbacks
> will be replied in other mails):
>
> · *Could you help to add the below Bugzilla tracker reference in
> the commit log message?*
>
> https://bugzilla.tianocore.org/show_bug.cgi?id=1882
>
>
>
> · *Could you help to run the script
> ‘BaseTools/Scripts/PatchCheck.py’ and resolve its report on the commit log
> format issues?*
>
> *Checking git commit: 6e3f64aeb4*
>
> *The commit message format is not valid:*
>
> ** Contributed-under! (Note: this must be removed by the code
> contributor!)*
>
> ** Add quotes (") around name with a comma: Albecki, Mateusz*
>
> ** Email format is invalid: hao.a.wu@intel.com <hao.a.wu@intel.com>*
>
> ** Line 15 of commit message is too long.*
>
> *https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format
> <https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format>*
>
> *The code passed all checks.*
>
>
>
> *Checking git commit: 91595ae911*
>
> *The commit message format is not valid:*
>
> ** Contributed-under! (Note: this must be removed by the code
> contributor!)*
>
> ** Add quotes (") around name with a comma: Albecki, Mateusz*
>
> ** Email format is invalid: hao.a.wu@intel.com <hao.a.wu@intel.com>*
>
> *https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format
> <https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format>*
>
> *The code passed all checks.*
>
>
>
> · *Could you help to resolve the typo ‘Prefered’ to ‘Preferred’
> in the naming of some variables?*
>
>
>
> · *Could you help to use lowercase ‘static’ (instead of using the
> uppercase one) for the new functions?*
>
>
>
>
>
> Also, I only verified the build of the patch series. Please grant me some
> time
>
> to verify on the HW on my side. Maybe your updated patches arrive first
> and I
>
> will then verify the update ones.
>
>
>
>
>
> Best Regards,
>
> Hao Wu
>
>
>
> > -----Original Message-----
>
> > From: Albecki, Mateusz
>
> > Sent: Monday, June 03, 2019 7:34 PM
>
> > Cc: Albecki, Mateusz; Wu, Hao A
>
> > Subject: [PATCH 0/2] Add GetOperatingParam notify phase to
>
> > SdMmcOverride protocol
>
> >
>
> > To allow platform greater control over the bus settings for SD card and
>
> > eMMC card
>
> > we have added a new notify phase to SdMmcOverrideProtocol called
>
> > GetOperatingParam.
>
> > This phase is signaled before SD card/eMMC initialization and allows
> platform
>
> > to tweak
>
> > the values in new structure called
>
> > EDKII_SD_MMC_OPERATING_PARAMETERS which allows to configure
>
> > bus width, clock frequency and driver strength. Other bus parameters can
> be
>
> > configured by
>
> > overriding host controller capabilities.
>
> >
>
> > Tests:
>
> > - OS boot from eMMC without SdMmcOverride protocol installed
>
> > - OS boot from eMMC with SdMmcOverride installed and clock frequency
>
> > lowered to 100MHz in HS200
>
> > - OS boot from eMMC with driver strength changed to Type1
>
> > - SD card enumeration in UEFI shell on default speed and high speed(non
>
> > UHS-I) with SdMmcOverride installed and UHS-I disabled in capability
>
> >
>
> >
>
> > Cc: hao.a.wu@intel.com
>
> >
>
> > Albecki, Mateusz (2):
>
> > MdeModulePkg/SdMmcOverride: Add GetOperatingParam notify phase
>
> > MdeModulePkg/SdMmcHcDxe: Implement revision 3 of
>
> > SdMmcOverrideProtocol
>
> >
>
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c | 522
>
> > +++++++++++++++------
>
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c | 381
>
> > ++++++++++++---
>
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c | 52 +-
>
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h | 18 +-
>
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c | 8 +-
>
> > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h | 8 +-
>
> > MdeModulePkg/Include/Protocol/SdMmcOverride.h | 58 ++-
>
> > 7 files changed, 802 insertions(+), 245 deletions(-)
>
> >
>
> > --
>
> > 2.14.1.windows.1
>
>
>
[-- Attachment #2: Type: text/html, Size: 18903 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [edk2-devel] [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement revision 3 of SdMmcOverrideProtocol
[not found] ` <15A7C8F163ADE317.25258@groups.io>
@ 2019-06-17 15:11 ` Albecki, Mateusz
2019-06-18 3:23 ` Wu, Hao A
0 siblings, 1 reply; 9+ messages in thread
From: Albecki, Mateusz @ 2019-06-17 15:11 UTC (permalink / raw)
To: devel@edk2.groups.io, Albecki, Mateusz; +Cc: Wu, Hao A
Actually I would like to back out of the proposed solution with mapping SD driver strength to eMMC driver strength. Since SD specification doesn't even specify enough space in driver strength field in host control 2 register to cover for all 5 driver strength types defined by eMMC specification and I also don't know about any controller that would use the mapping below. The controller I am working on currently just ignores controller side of the driver strength setting altogether so for now I would like to leave the driver strength setting for eMMC as is(check card capability and platform selection) and update only SD case.
Thanks,
Mateusz
> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> Albecki, Mateusz
> Sent: Thursday, June 13, 2019 4:39 PM
> To: devel@edk2.groups.io
> Cc: Wu, Hao A <hao.a.wu@intel.com>
> Subject: Re: [edk2-devel] [PATCH 2/2] MdeModulePkg/SdMmcHcDxe:
> Implement revision 3 of SdMmcOverrideProtocol
>
> Resending to group. Inline reply to some of the comments.
>
> As for the mapping between eMMC driver strength and SD controller driver
> strength should we use this one:
>
> SD controller -> eMMC card
> B -> Type 0
> A -> Type 1
> C -> Type 2
> D -> Type 3
> (none) -> Type4
>
> And Type 4 would be identified by bit 39 in capability register which is
> currently marked as reserved in SD controller specification. This is current
> capability register definition in the driver.
>
> Thanks,
> Mateusz
>
> > -----Original Message-----
> > From: Wu, Hao A
> > Sent: Monday, June 10, 2019 5:19 AM
> > To: Albecki, Mateusz <mateusz.albecki@intel.com>
> > Subject: RE: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement
> revision
> > 3 of SdMmcOverrideProtocol
> >
> > Hello Mateusz,
> >
> > Some inline comments below:
> >
> > > -----Original Message-----
> > > From: Albecki, Mateusz
> > > Sent: Monday, June 03, 2019 7:34 PM
> > > Cc: Albecki, Mateusz; Wu, Hao A; Albecki
> > > Subject: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement revision
> 3
> > > of SdMmcOverrideProtocol
> > >
> > > Implement support for GetOperatingParamters notify phase
> > > in SdMmcHcDxe driver. GetOperatingParameters notify phase
> > > is signaled before we start card detection and initialization.
> > > Code has been updated for both eMMC and SD card controllers to
> > > take into consideration those new parameters. Initialization process
> > > has been divided into 2 steps. In the first step we bring the link
> > > up to the point where we can get card identification data(Extended
> > > CSD in eMMC case and SWITCH command response in SD card case). This
> > > data is later used along with controller capabilities and operating
> > > parameters passed in GetOperatingParameters phase to choose
> preferred
> > > bus settings in GetTargetBusSettings function. Those settings are later
> > > on to start bus training to high speeds. If user passes incompatible
> > > setting with selected bus timing driver will assume it's standard behavior
> > with
> > > respect to that setting. For instance if HS400 has been selected as a
> > > target bus timing due to card and controller support bus width setting of
> > > 4 and 1 bit won't be respected and 8 bit setting will be chosen instead.
> > >
> > >
> > > Cc: hao.a.wu@intel.com
> > > Signed-off-by: Albecki, Mateusz <mateusz.albecki@intel.com>
> > > Contributed-under: TianoCore Contribution Agreement 1.1
> > > ---
> > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c | 522
> > > +++++++++++++++------
> > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c | 381
> > > ++++++++++++---
> > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c | 52 +-
> > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h | 18 +-
> > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c | 8 +-
> > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h | 8 +-
> > > 6 files changed, 750 insertions(+), 239 deletions(-)
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > index deaf4468c9..1a81f6d250 100644
> > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > @@ -449,7 +449,7 @@ EFI_STATUS
> > > EmmcSendTuningBlk (
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > - IN UINT8 BusWidth
> > > + IN UINT16 BusWidth
> > > )
> > > {
> > > EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
> > > @@ -506,7 +506,7 @@ EmmcTuningClkForHs200 (
> > > IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > - IN UINT8 BusWidth
> > > + IN UINT16 BusWidth
> > > )
> > > {
> > > EFI_STATUS Status;
> > > @@ -583,7 +583,7 @@ EmmcSwitchBusWidth (
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > IN BOOLEAN IsDdr,
> > > - IN UINT8 BusWidth
> > > + IN UINT16 BusWidth
> > > )
> > > {
> > > EFI_STATUS Status;
> > > @@ -641,13 +641,13 @@ EmmcSwitchBusWidth (
> > > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6 and SD Host
> > > Controller
> > > Simplified Spec 3.0 Figure 3-3 for details.
> > >
> > > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
> > > - @param[in] PassThru A pointer to the
> > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > - @param[in] Slot The slot number of the SD card to send the
> > command
> > > to.
> > > - @param[in] Rca The relative device address to be assigned.
> > > - @param[in] HsTiming The value to be written to HS_TIMING field of
> > > EXT_CSD register.
> > > - @param[in] Timing The bus mode timing indicator.
> > > - @param[in] ClockFreq The max clock frequency to be set, the unit is
> > > MHz.
> > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> instance.
> > > + @param[in] PassThru A pointer to the
> > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > + @param[in] Slot The slot number of the SD card to send the
> > > command to.
> > > + @param[in] Rca The relative device address to be assigned.
> > > + @param[in] DriverStrength Driver strength to set for speed modes
> that
> > > support it.
> > > + @param[in] Timing The bus mode timing indicator.
> >
> >
> > Please help to update the parameter comment to reflect the name change
> > from
> > 'Timing' to 'BusTiming'.
> >
> >
> > > + @param[in] ClockFreq The max clock frequency to be set, the unit is
> > > MHz.
> > >
> > > @retval EFI_SUCCESS The operation is done correctly.
> > > @retval Others The operation fails.
> > > @@ -659,8 +659,8 @@ EmmcSwitchBusTiming (
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > - IN UINT8 HsTiming,
> > > - IN SD_MMC_BUS_MODE Timing,
> > > + IN EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength,
> > > + IN SD_MMC_BUS_MODE BusTiming,
> > > IN UINT32 ClockFreq
> > > )
> > > {
> > > @@ -678,12 +678,29 @@ EmmcSwitchBusTiming (
> > > //
> > > Access = 0x03;
> > > Index = OFFSET_OF (EMMC_EXT_CSD, HsTiming);
> > > - Value = HsTiming;
> > > CmdSet = 0;
> > > + switch (BusTiming) {
> > > + case SdMmcMmcHs400:
> > > + Value = (UINT8)((DriverStrength.Emmc << 4) | 3);
> > > + break;
> > > + case SdMmcMmcHs200:
> > > + Value = (UINT8)((DriverStrength.Emmc << 4) | 2);
> > > + break;
> > > + case SdMmcMmcHsSdr:
> > > + case SdMmcMmcHsDdr:
> > > + Value = 1;
> > > + break;
> > > + case SdMmcMmcLegacy:
> > > + Value = 0;
> > > + break;
> > > + default:
> > > + DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Unsupported
> > > BusTiming(%d\n)", BusTiming));
> > > + return EFI_INVALID_PARAMETER;
> > > + }
> > >
> > > Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);
> > > if (EFI_ERROR (Status)) {
> > > - DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to
> hstiming %d
> > > fails with %r\n", HsTiming, Status));
> > > + DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to bus
> > > timing %d fails with %r\n", BusTiming, Status));
> > > return Status;
> > > }
> > >
> > > @@ -713,7 +730,7 @@ EmmcSwitchBusTiming (
> > > Private->ControllerHandle,
> > > Slot,
> > > EdkiiSdMmcSwitchClockFreqPost,
> > > - &Timing
> > > + &BusTiming
> > > );
> > > if (EFI_ERROR (Status)) {
> > > DEBUG ((
> > > @@ -754,25 +771,34 @@ EmmcSwitchToHighSpeed (
> >
> >
> > Please help to update the function comments for
> > EmmcSwitchToHighSpeed() after
> > the parameter changes.
> >
> >
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > - IN UINT32 ClockFreq,
> > > - IN BOOLEAN IsDdr,
> > > - IN UINT8 BusWidth
> > > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > > )
> > > {
> > > EFI_STATUS Status;
> > > - UINT8 HsTiming;
> > > UINT8 HostCtrl1;
> > > - SD_MMC_BUS_MODE Timing;
> > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > + BOOLEAN IsDdr;
> > >
> > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > >
> > > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr,
> > BusWidth);
> > > + if ((BusMode->BusTiming != SdMmcMmcHsSdr && BusMode-
> > > >BusTiming != SdMmcMmcHsDdr) ||
> > > + BusMode->ClockFreq > 52) {
> > > + return EFI_INVALID_PARAMETER;
> > > + }
> > > +
> > > + if (BusMode->BusTiming == SdMmcMmcHsDdr) {
> > > + IsDdr = TRUE;
> > > + } else {
> > > + IsDdr = FALSE;
> > > + }
> > > +
> > > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr,
> > BusMode-
> > > >BusWidth);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > +
> > > //
> > > - // Set to Hight Speed timing
> > > + // Set to High Speed timing
> > > //
> > > HostCtrl1 = BIT2;
> > > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1,
> sizeof
> > > (HostCtrl1), &HostCtrl1);
> > > @@ -780,37 +806,27 @@ EmmcSwitchToHighSpeed (
> > > return Status;
> > > }
> > >
> > > - if (IsDdr) {
> > > - Timing = SdMmcMmcHsDdr;
> > > - } else if (ClockFreq == 52) {
> > > - Timing = SdMmcMmcHsSdr;
> > > - } else {
> > > - Timing = SdMmcMmcLegacy;
> > > - }
> > > -
> > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > Timing);
> > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > BusMode->BusTiming);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > >
> > > - HsTiming = 1;
> > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > Timing,
> > > ClockFreq);
> > > -
> > > - return Status;
> > > + return EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
> > > }
> > >
> > > /**
> > > - Switch to the HS200 timing according to request.
> > > + Switch to the HS200 timing. This function assumes that eMMC bus is
> still
> > in
> > > legacy mode.
> > >
> > > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host
> > > Controller
> > > Simplified Spec 3.0 Figure 2-29 for details.
> > >
> > > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
> > > - @param[in] PassThru A pointer to the
> > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > - @param[in] Slot The slot number of the SD card to send the
> > command
> > > to.
> > > - @param[in] Rca The relative device address to be assigned.
> > > - @param[in] ClockFreq The max clock frequency to be set.
> > > - @param[in] BusWidth The bus width to be set, it could be 4 or 8.
> > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> instance.
> > > + @param[in] PassThru A pointer to the
> > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > + @param[in] Slot The slot number of the SD card to send the
> > > command to.
> > > + @param[in] Rca The relative device address to be assigned.
> > > + @param[in] DriverStrength The driver strength to be selected.
> > > + @param[in] ClockFreq The max clock frequency to be set.
> > > + @param[in] BusWidth The bus width to be set, it could be 4 or 8.
> > >
> > > @retval EFI_SUCCESS The operation is done correctly.
> > > @retval Others The operation fails.
> > > @@ -822,30 +838,25 @@ EmmcSwitchToHS200 (
> >
> >
> > Please help to update the function comments for EmmcSwitchToHS200()
> > after the
> > parameter changes.
> >
> >
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > - IN UINT32 ClockFreq,
> > > - IN UINT8 BusWidth
> > > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > > )
> > > {
> > > EFI_STATUS Status;
> > > - UINT8 HsTiming;
> > > UINT16 ClockCtrl;
> > > - SD_MMC_BUS_MODE Timing;
> > > SD_MMC_HC_PRIVATE_DATA *Private;
> > >
> > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > >
> > > - if ((BusWidth != 4) && (BusWidth != 8)) {
> > > + if (BusMode->BusTiming != SdMmcMmcHs200 ||
> > > + (BusMode->BusWidth != 4 && BusMode->BusWidth != 8)) {
> > > return EFI_INVALID_PARAMETER;
> > > }
> > >
> > > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE,
> > BusWidth);
> > > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE,
> > > BusMode->BusWidth);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > //
> > > - // Set to HS200/SDR104 timing
> > > - //
> > > - //
> > > // Stop bus clock at first
> > > //
> > > Status = SdMmcHcStopClock (PciIo, Slot);
> > > @@ -853,9 +864,7 @@ EmmcSwitchToHS200 (
> > > return Status;
> > > }
> > >
> > > - Timing = SdMmcMmcHs200;
> > > -
> > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > Timing);
> > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > BusMode->BusTiming);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > @@ -881,28 +890,27 @@ EmmcSwitchToHS200 (
> > > ClockCtrl = BIT2;
> > > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL,
> sizeof
> > > (ClockCtrl), &ClockCtrl);
> > >
> > > - HsTiming = 2;
> > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > Timing,
> > > ClockFreq);
> > > + Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
> >
> >
> > After the proposed change, the preferred bus timing and driver strength
> > value
> > will be set for the device through the EMMC_SWITCH command.
> >
> > However, on the host controller side, only the bus timing value is also
> > updated
> > in the Host Control 2 Register of the SD HC (via function
> > SdMmcHcUhsSignaling()).
> > It seems to me that the driver strength value does not get updated in this
> > register.
> >
> > I think the SD case has a similar issue.
>
> For SD I agree that there is an issue but for eMMC there is no clear mapping
> between
> eMMC defined driver strength types and SD defined driver strength types.
> The controller
> I happen to be working with seems to ignore the values in this register. If we
> can agree on
> one mapping that will be able to service majority of the eMMC controllers on
> market I don't
> mind adding that. We can maybe add driver strength setting to
> SdMmcHcUhsSignaling so that
> platform has an opportunity to correct core driver during
> EdkiiSdMmcUhsSignaling notify.
>
> >
> >
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > >
> > > - Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth);
> > > + Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusMode-
> > > >BusWidth);
> > >
> > > return Status;
> > > }
> > >
> > > /**
> > > - Switch to the HS400 timing according to request.
> > > + Switch to the HS400 timing. This function assumes that eMMC bus is
> still
> > in
> > > legacy mode.
> > >
> > > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host
> > > Controller
> > > Simplified Spec 3.0 Figure 2-29 for details.
> > >
> > > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
> > > - @param[in] PassThru A pointer to the
> > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > - @param[in] Slot The slot number of the SD card to send the
> > command
> > > to.
> > > - @param[in] Rca The relative device address to be assigned.
> > > - @param[in] ClockFreq The max clock frequency to be set.
> > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> instance.
> > > + @param[in] PassThru A pointer to the
> > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > + @param[in] Slot The slot number of the SD card to send the
> > > command to.
> > > + @param[in] Rca The relative device address to be assigned.
> > > + @param[in] ClockFreq The max clock frequency to be set.
> >
> >
> > Please help to update the function comments for EmmcSwitchToHS400()
> > after the
> > parameter changes.
> >
> >
> > >
> > > @retval EFI_SUCCESS The operation is done correctly.
> > > @retval Others The operation fails.
> > > @@ -914,47 +922,321 @@ EmmcSwitchToHS400 (
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > - IN UINT32 ClockFreq
> > > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > > )
> > > {
> > > EFI_STATUS Status;
> > > - UINT8 HsTiming;
> > > - SD_MMC_BUS_MODE Timing;
> > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > + EDKII_SD_MMC_BUS_MODE Hs200BusMode;
> > > + UINT32 HsFreq;
> > > +
> > > + if (BusMode->BusTiming != SdMmcMmcHs400 ||
> > > + BusMode->BusWidth != 8) {
> > > + return EFI_INVALID_PARAMETER;
> > > + }
> > >
> > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > + Hs200BusMode.BusTiming = SdMmcMmcHs200;
> > > + Hs200BusMode.BusWidth = BusMode->BusWidth;
> > > + Hs200BusMode.ClockFreq = BusMode->ClockFreq;
> > > + Hs200BusMode.DriverStrength = BusMode->DriverStrength;
> > >
> > > - Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, 8);
> > > + Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca,
> > &Hs200BusMode);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > +
> > > //
> > > - // Set to Hight Speed timing and set the clock frequency to a value less
> > than
> > > 52MHz.
> > > + // Set to High Speed timing and set the clock frequency to a value less
> > than
> > > or equal to 52MHz.
> > > + // This step is necessary to be able to switch Bus into 8 bit DDR mode
> > which
> > > is unsupported in HS200.
> > > //
> > > - HsTiming = 1;
> > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > > SdMmcMmcHsSdr, 52);
> > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > SdMmcMmcHsSdr);
> >
> >
> > The above SdMmcHcUhsSignaling() is newly added, is this a bug for the
> origin
> > code?
> >
> > I searched the eMMC spec, it seems to me the spec does not explicitly
> > mention
> > the Host Control 2 Register at all, I am not very sure if such change will
> > bring any effect to devices. Did you have a try without adding such change?
> >
>
> This is aligned to the behavior of EmmcSwitchToHighSpeed function. My
> eMMC
> controller doesn't need this register to be programmed for switch to high
> speed
> but calling SdMmcUhsSignaling here gives override protocol a chance to finish
> switch to high speed for eMMC controllers that need such tweaking.
>
> >
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > - //
> > > - // HS400 mode must use 8 data lines.
> > > - //
> > > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, TRUE, 8);
> > > +
> > > + HsFreq = BusMode->ClockFreq < 52 ? BusMode->ClockFreq : 52;
> > > + Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > >DriverStrength, SdMmcMmcHsSdr, HsFreq);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > >
> > > - Timing = SdMmcMmcHs400;
> > > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, TRUE,
> > BusMode-
> > > >BusWidth);
> > > + if (EFI_ERROR (Status)) {
> > > + return Status;
> > > + }
> > >
> > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > Timing);
> > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > BusMode->BusTiming);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > >
> > > - HsTiming = 3;
> > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > Timing,
> > > ClockFreq);
> > > + return EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
> >
> >
> > After the proposed change, the preferred bus timing and driver strength
> > value
> > will be set for the device through the EMMC_SWITCH command.
> >
> > However, on the host controller side, only the bus timing value is also
> > updated
> > in the Host Control 2 Register of the SD HC (via function
> > SdMmcHcUhsSignaling()).
> > It seems to me that the driver strength value does not get updated in this
> > register.
> >
> > I think the SD case has a similar issue.
> >
> >
> > > +}
> > >
> > > - return Status;
> > > +/**
> > > + Check if passed BusTiming is supported in both controller and card.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] ExtCsd Pointer to the card's extended CSD
> > > + @param[in] BusTiming Bus timing to check
> > > +
> > > + @retval TRUE Both card and controller support given BusTiming
> > > + @retval FALSE Card or controller doesn't support given BusTiming
> > > +**/
> > > +STATIC
> > > +BOOLEAN
> > > +IsBusTimingSupported (
> >
> >
> > How about renaming it to EmmcIsBusTimingSupported()?
> >
> >
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN EMMC_EXT_CSD *ExtCsd,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + BOOLEAN Supported;
> > > + SD_MMC_HC_SLOT_CAP *Capabilities;
> > > +
> > > + Capabilities = &Private->Capability[SlotIndex];
> > > +
> > > + Supported = FALSE;
> > > + switch (BusTiming) {
> > > + case SdMmcMmcHs400:
> > > + if ((((ExtCsd->DeviceType & (BIT6 | BIT7)) != 0) && (Capabilities-
> > > >Hs400 != 0)) && Capabilities->BusWidth8) {
> > > + Supported = TRUE;
> > > + }
> > > + break;
> > > + case SdMmcMmcHs200:
> > > + if ((((ExtCsd->DeviceType & (BIT4 | BIT5)) != 0) && (Capabilities-
> > > >Sdr104 != 0))) {
> > > + Supported = TRUE;
> > > + }
> > > + break;
> > > + case SdMmcMmcHsDdr:
> > > + if ((((ExtCsd->DeviceType & (BIT2 | BIT3)) != 0) && (Capabilities-
> > > >Ddr50 != 0))) {
> > > + Supported = TRUE;
> > > + }
> > > + break;
> > > + case SdMmcMmcHsSdr:
> > > + if ((((ExtCsd->DeviceType & BIT1) != 0) && (Capabilities-
> >HighSpeed !=
> > > 0))) {
> > > + Supported = TRUE;
> > > + } else if ((((ExtCsd->DeviceType & BIT0) != 0) && (Capabilities-
> > > >HighSpeed != 0))) {
> >
> >
> > For this case, I think the bus timing should be classified to
> SdMmcMmcLegacy.
> > Since under this timing, the maximum frequency allowed is 26Mhz. If set to
> > SdMmcMmcHsSdr the driver will try to set the frequency to 52Mhz later in
> > EmmcGetTargetClockFreq().
> >
> >
> > > + Supported = TRUE;
> > > + }
> > > + break;
> > > + case SdMmcMmcLegacy:
> > > + Supported = TRUE;
> > > + break;
> > > + default:
> > > + ASSERT (FALSE);
> > > + }
> > > +
> > > + return Supported;
> > > +}
> > > +
> > > +/**
> > > + Get the target bus timing to set on the link. This function
> > > + will try to select highest bus timing supported by card, controller
> > > + and the driver.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] ExtCsd Pointer to the card's extended CSD
> > > +
> > > + @return Bus timing value that should be set on link
> > > +**/
> > > +STATIC
> > > +SD_MMC_BUS_MODE
> > > +EmmcGetTargetBusTiming (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN EMMC_EXT_CSD *ExtCsd
> > > + )
> > > +{
> > > + SD_MMC_BUS_MODE BusTiming;
> > > +
> > > + //
> > > + // We start with highest bus timing that this driver currently support
> and
> > > + // return as soon as we find supported timing.
> > > + //
> > > + BusTiming = SdMmcMmcHs400;
> > > + while (BusTiming > SdMmcMmcLegacy) {
> > > + if (IsBusTimingSupported (Private, SlotIndex, ExtCsd, BusTiming)) {
> > > + break;
> > > + }
> > > + BusTiming--;
> > > + }
> > > +
> > > + return BusTiming;
> > > +}
> > > +
> > > +/**
> > > + Check if the passed bus width is supported by controller and card.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] BusTiming Bus timing set on the link
> > > + @param[in] BusWidth Bus width to check
> > > +
> > > + @retval TRUE Passed bus width is supported in current bus
> > configuration
> > > + @retval FALSE Passed bus width is not supported in current bus
> > > configuration
> > > +**/
> > > +STATIC
> > > +BOOLEAN
> > > +IsBusWidthSupported (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN SD_MMC_BUS_MODE BusTiming,
> > > + IN UINT16 BusWidth
> > > + )
> > > +{
> > > + if (BusWidth == 8 && Private->Capability[SlotIndex].BusWidth8) {
> > > + return TRUE;
> > > + } else if (BusWidth == 4 && BusTiming != SdMmcMmcHs400) {
> > > + return TRUE;
> > > + } else if (BusWidth == 1 && (BusTiming == SdMmcMmcHsSdr ||
> > BusTiming
> > > == SdMmcMmcLegacy)) {
> > > + return TRUE;
> > > + }
> > > +
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Get the target bus width to be set on the bus.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > + @param[in] BusTiming Bus timing set on the bus
> > > +
> > > + @return Bus width to be set on the bus
> > > +**/
> > > +STATIC
> > > +UINT16
> > > +EmmcGetTargetBusWidth (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN EMMC_EXT_CSD *ExtCsd,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + UINT16 BusWidth;
> > > + UINT16 PreferedBusWidth;
> > > +
> > > + PreferedBusWidth = Private-
> > > >Slot[SlotIndex].OperatingParameters.BusWidth;
> > > +
> > > + if (PreferedBusWidth != EDKII_SD_MMC_BUS_WIDTH_IGNORE &&
> > > + IsBusWidthSupported (Private, SlotIndex, BusTiming,
> > > PreferedBusWidth)) {
> > > + BusWidth = PreferedBusWidth;
> > > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 8)) {
> > > + BusWidth = 8;
> > > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 4)) {
> > > + BusWidth = 4;
> > > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 1)) {
> > > + BusWidth = 1;
> > > + }
> > > +
> > > + return BusWidth;
> > > +}
> > > +
> > > +/**
> > > + Get the target clock frequency to be set on the bus.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > + @param[in] BusTiming Bus timing to be set on the bus
> > > +
> > > + @return Value of the clock frequency to be set on bus in MHz
> > > +**/
> > > +STATIC
> > > +UINT32
> > > +EmmcGetTargetClockFreq (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN EMMC_EXT_CSD *ExtCsd,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + UINT32 PreferedClockFreq;
> > > + UINT32 MaxClockFreq;
> > > +
> > > + PreferedClockFreq = Private-
> > > >Slot[SlotIndex].OperatingParameters.ClockFreq;
> > > +
> > > + switch (BusTiming) {
> > > + case SdMmcMmcHs400:
> > > + case SdMmcMmcHs200:
> > > + MaxClockFreq = 200;
> > > + break;
> > > + case SdMmcMmcHsSdr:
> > > + case SdMmcMmcHsDdr:
> > > + MaxClockFreq = 52;
> > > + break;
> > > + default:
> > > + MaxClockFreq = 26;
> > > + break;
> > > + }
> > > +
> > > + if (PreferedClockFreq != EDKII_SD_MMC_CLOCK_FREQ_IGNORE &&
> > > PreferedClockFreq < MaxClockFreq) {
> > > + return PreferedClockFreq;
> > > + } else {
> > > + return MaxClockFreq;
> > > + }
> > > +}
> > > +
> > > +/**
> > > + Get the driver strength to be set on bus
> >
> > Please help to append a '.' character for the above line.
> > It is required for the edk2 coding style.
> >
> >
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > + @param[in] BusTiming Bus timing set on the bus
> > > +
> > > + @return Value of the driver strength to be set on the bus
> > > +**/
> > > +STATIC
> > > +EDKII_SD_MMC_DRIVER_STRENGTH
> > > +EmmcGetTargetDriverStrength (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN EMMC_EXT_CSD *ExtCsd,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + EDKII_SD_MMC_DRIVER_STRENGTH PreferedDriverStrength;
> > > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > > +
> > > + PreferedDriverStrength = Private-
> > > >Slot[SlotIndex].OperatingParameters.DriverStrength;
> > > + DriverStrength.Emmc = EmmcDriverStrengthType0;
> > > +
> > > + if (PreferedDriverStrength.Emmc !=
> > > EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE &&
> > > + (ExtCsd->DriverStrength & (BIT0 << PreferedDriverStrength.Emmc)))
> {
> >
> >
> > The host controller also has a capability for different types of driver
> strength.
> > (Capabilities Register, bit 36~38)
> >
> > The check should take it into consideration as well.
>
> For SD it should. For eMMC it's not as obvious since as I mentioned we don't
> have a mapping defined.
> If we agree on one we can add this and for all eMMC controllers that won't
> follow it I guess we can
> leave it to the platform code to override capabilities.
>
> >
> >
> > > + DriverStrength.Emmc = PreferedDriverStrength.Emmc;
> > > + }
> > > +
> > > + return DriverStrength;
> > > +}
> > > +
> > > +/**
> > > + Get the target settings for the bus mode.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > + @param[out] BusMode Target configuration of the bus
> > > +**/
> > > +STATIC
> > > +VOID
> > > +EmmcGetTargetBusMode (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN EMMC_EXT_CSD *ExtCsd,
> > > + OUT EDKII_SD_MMC_BUS_MODE *BusMode
> > > + )
> > > +{
> > > + BusMode->BusTiming = EmmcGetTargetBusTiming (Private, SlotIndex,
> > > ExtCsd);
> > > + BusMode->BusWidth = EmmcGetTargetBusWidth (Private, SlotIndex,
> > > ExtCsd, BusMode->BusTiming);
> > > + BusMode->ClockFreq = EmmcGetTargetClockFreq (Private, SlotIndex,
> > > ExtCsd, BusMode->BusTiming);
> > > + BusMode->DriverStrength = EmmcGetTargetDriverStrength (Private,
> > > SlotIndex, ExtCsd, BusMode->BusTiming);
> > > }
> > >
> > > /**
> > > @@ -983,10 +1265,7 @@ EmmcSetBusMode (
> > > EFI_STATUS Status;
> > > EMMC_CSD Csd;
> > > EMMC_EXT_CSD ExtCsd;
> > > - UINT8 HsTiming;
> > > - BOOLEAN IsDdr;
> > > - UINT32 ClockFreq;
> > > - UINT8 BusWidth;
> > > + EDKII_SD_MMC_BUS_MODE BusMode;
> > > SD_MMC_HC_PRIVATE_DATA *Private;
> > >
> > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > @@ -1004,85 +1283,30 @@ EmmcSetBusMode (
> > > }
> > >
> > > ASSERT (Private->BaseClkFreq[Slot] != 0);
> > > +
> > > //
> > > - // Check if the Host Controller support 8bits bus width.
> > > - //
> > > - if (Private->Capability[Slot].BusWidth8 != 0) {
> > > - BusWidth = 8;
> > > - } else {
> > > - BusWidth = 4;
> > > - }
> > > - //
> > > - // Get Deivce_Type from EXT_CSD register.
> > > + // Get Device_Type from EXT_CSD register.
> > > //
> > > Status = EmmcGetExtCsd (PassThru, Slot, &ExtCsd);
> > > if (EFI_ERROR (Status)) {
> > > DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetExtCsd fails
> > with %r\n",
> > > Status));
> > > return Status;
> > > }
> > > - //
> > > - // Calculate supported bus speed/bus width/clock frequency.
> > > - //
> > > - HsTiming = 0;
> > > - IsDdr = FALSE;
> > > - ClockFreq = 0;
> > > - if (((ExtCsd.DeviceType & (BIT4 | BIT5)) != 0) && (Private-
> > > >Capability[Slot].Sdr104 != 0)) {
> > > - HsTiming = 2;
> > > - IsDdr = FALSE;
> > > - ClockFreq = 200;
> > > - } else if (((ExtCsd.DeviceType & (BIT2 | BIT3)) != 0) && (Private-
> > > >Capability[Slot].Ddr50 != 0)) {
> > > - HsTiming = 1;
> > > - IsDdr = TRUE;
> > > - ClockFreq = 52;
> > > - } else if (((ExtCsd.DeviceType & BIT1) != 0) && (Private-
> > > >Capability[Slot].HighSpeed != 0)) {
> > > - HsTiming = 1;
> > > - IsDdr = FALSE;
> > > - ClockFreq = 52;
> > > - } else if (((ExtCsd.DeviceType & BIT0) != 0) && (Private-
> > > >Capability[Slot].HighSpeed != 0)) {
> > > - HsTiming = 1;
> > > - IsDdr = FALSE;
> > > - ClockFreq = 26;
> > > - }
> > > - //
> > > - // Check if both of the device and the host controller support HS400
> DDR
> > > mode.
> > > - //
> > > - if (((ExtCsd.DeviceType & (BIT6 | BIT7)) != 0) && (Private-
> > > >Capability[Slot].Hs400 != 0)) {
> > > - //
> > > - // The host controller supports 8bits bus.
> > > - //
> > > - ASSERT (BusWidth == 8);
> > > - HsTiming = 3;
> > > - IsDdr = TRUE;
> > > - ClockFreq = 200;
> > > - }
> > >
> > > - if ((ClockFreq == 0) || (HsTiming == 0)) {
> > > - //
> > > - // Continue using default setting.
> > > - //
> > > - return EFI_SUCCESS;
> > > - }
> > > + EmmcGetTargetBusMode (Private, Slot, &ExtCsd, &BusMode);
> > >
> > > - DEBUG ((DEBUG_INFO, "EmmcSetBusMode: HsTiming %d
> ClockFreq %d
> > > BusWidth %d Ddr %a\n", HsTiming, ClockFreq, BusWidth, IsDdr ?
> > > "TRUE":"FALSE"));
> > > + DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Target bus mode: timing
> > > = %d, width = %d, clock freq = %d, driver strength = %d\n",
> > > + BusMode.BusTiming, BusMode.BusWidth,
> > BusMode.ClockFreq,
> > > BusMode.DriverStrength.Emmc));
> > >
> > > - if (HsTiming == 3) {
> > > - //
> > > - // Execute HS400 timing switch procedure
> > > - //
> > > - Status = EmmcSwitchToHS400 (PciIo, PassThru, Slot, Rca, ClockFreq);
> > > - } else if (HsTiming == 2) {
> > > - //
> > > - // Execute HS200 timing switch procedure
> > > - //
> > > - Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq,
> > > BusWidth);
> > > + if (BusMode.BusTiming == SdMmcMmcHs400) {
> > > + Status = EmmcSwitchToHS400 (PciIo, PassThru, Slot, Rca, &BusMode);
> > > + } else if (BusMode.BusTiming == SdMmcMmcHs200) {
> > > + Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, &BusMode);
> > > } else {
> > > - //
> > > - // Execute High Speed timing switch procedure
> > > - //
> > > - Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca,
> ClockFreq,
> > > IsDdr, BusWidth);
> > > + Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca,
> > &BusMode);
> > > }
> > >
> > > - DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n",
> > (HsTiming
> > > == 3) ? "HS400" : ((HsTiming == 2) ? "HS200" : "HighSpeed"), Status));
> > > + DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n",
> > > (BusMode.BusTiming == SdMmcMmcHs400) ? "HS400" :
> > > ((BusMode.BusTiming == SdMmcMmcHs200) ? "HS200" : "HighSpeed"),
> > > Status));
> > >
> > > return Status;
> > > }
> > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > index 17936a5492..36d2b487df 100644
> > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > @@ -313,10 +313,6 @@ SdCardSetRca (
> > > return Status;
> > > }
> > >
> > > -
> > > -
> > > -
> > > -
> > > /**
> > > Send command SELECT_DESELECT_CARD to the SD device to
> > > select/deselect it.
> > >
> > > @@ -422,7 +418,7 @@ SdCardSetBusWidth (
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > - IN UINT8 BusWidth
> > > + IN UINT16 BusWidth
> > > )
> > > {
> > > EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
> > > @@ -476,7 +472,7 @@ SdCardSetBusWidth (
> > > @param[in] Slot The slot number of the SD card to send the
> > command
> > > to.
> > > @param[in] AccessMode The value for access mode group.
> >
> >
> > Please help to update the parameter comment to reflect the function
> > interface changes.
> >
> >
> > > @param[in] CommandSystem The value for command set group.
> > > - @param[in] DriveStrength The value for drive length group.
> > > + @param[in] DriveStrength The value for driver strength group.
> >
> >
> > Please help to update the parameter name in the above comment from
> > 'DriveStrength' to 'DriverStrength'.
> >
> >
> > > @param[in] PowerLimit The value for power limit group.
> > > @param[in] Mode Switch or check function.
> > > @param[out] SwitchResp The return switch function status.
> > > @@ -489,9 +485,9 @@ EFI_STATUS
> > > SdCardSwitch (
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > - IN UINT8 AccessMode,
> > > + IN SD_MMC_BUS_MODE BusTiming,
> > > IN UINT8 CommandSystem,
> > > - IN UINT8 DriveStrength,
> > > + IN SD_DRIVER_STRENGTH_TYPE DriverStrength,
> > > IN UINT8 PowerLimit,
> > > IN BOOLEAN Mode,
> > > OUT UINT8 *SwitchResp
> > > @@ -502,6 +498,7 @@ SdCardSwitch (
> > > EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
> > > EFI_STATUS Status;
> > > UINT32 ModeValue;
> > > + UINT8 AccessMode;
> > >
> > > ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
> > > ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
> > > @@ -516,8 +513,31 @@ SdCardSwitch (
> > > SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
> > >
> > > ModeValue = Mode ? BIT31 : 0;
> > > - SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) |
> > ((PowerLimit
> > > & 0xF) << 4) | \
> > > - ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) <<
> > 12)
> > > | \
> > > +
> > > + switch (BusTiming) {
> > > + case SdMmcUhsDdr50:
> > > + AccessMode = 0x4;
> > > + break;
> > > + case SdMmcUhsSdr104:
> > > + AccessMode = 0x3;
> > > + break;
> > > + case SdMmcUhsSdr50:
> > > + AccessMode = 0x2;
> > > + break;
> > > + case SdMmcUhsSdr25:
> > > + case SdMmcSdHs:
> > > + AccessMode = 0x1;
> > > + break;
> > > + case SdMmcUhsSdr12:
> > > + case SdMmcSdDs:
> > > + AccessMode = 0;
> > > + break;
> > > + default:
> > > + AccessMode = 0xF;
> > > + }
> > > +
> > > + SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) |
> > > ((CommandSystem & 0xF) << 4) | \
> > > + ((DriverStrength & 0xF) << 8) | ((PowerLimit & 0xF) <<
> 12)
> > |
> > > \
> > > ModeValue;
> > >
> > > Packet.InDataBuffer = SwitchResp;
> > > @@ -718,7 +738,7 @@ SdCardSwitchBusWidth (
> > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > IN UINT8 Slot,
> > > IN UINT16 Rca,
> > > - IN UINT8 BusWidth
> > > + IN UINT16 BusWidth
> > > )
> > > {
> > > EFI_STATUS Status;
> > > @@ -748,6 +768,261 @@ SdCardSwitchBusWidth (
> > > return Status;
> > > }
> > >
> > > +/**
> > > + Check if passed BusTiming is supported in both controller and card.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] CardSupportedBusTimings Bitmask indicating which bus
> > > timings are supported by card
> > > + @param[in] IsInUhsI Flag indicating if link is in UHS-I
> > > +
> > > + @retval TRUE Both card and controller support given BusTiming
> > > + @retval FALSE Card or controller doesn't support given BusTiming
> > > +**/
> > > +STATIC
> > > +BOOLEAN
> > > +SdIsBusTimingSupported (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN UINT8 CardSupportedBusTimings,
> > > + IN BOOLEAN IsInUhsI,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + SD_MMC_HC_SLOT_CAP *Capability;
> > > +
> > > + Capability = &Private->Capability[SlotIndex];
> > > +
> > > + if (IsInUhsI) {
> > > + switch (BusTiming) {
> >
> >
> > Please help to add a 'default' handle for this 'switch' statement, the
> > proposed
> > code will cause a GCC5 build failure.
> >
> >
> > > + case SdMmcUhsSdr104:
> > > + if (Capability->Sdr104 && ((CardSupportedBusTimings & BIT3) != 0))
> {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + case SdMmcUhsDdr50:
> > > + if (Capability->Ddr50 && ((CardSupportedBusTimings & BIT4) != 0)) {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + case SdMmcUhsSdr50:
> > > + if (Capability->Sdr50 && ((CardSupportedBusTimings & BIT2) != 0)) {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + case SdMmcUhsSdr25:
> > > + if ((CardSupportedBusTimings & BIT1) != 0) {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + case SdMmcUhsSdr12:
> > > + if ((CardSupportedBusTimings & BIT0) != 0) {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + }
> > > + } else {
> > > + switch (BusTiming) {
> >
> >
> > Please help to add a 'default' handle for this 'switch' statement, the
> > proposed
> > code will cause a GCC5 build failure.
> >
> >
> > > + case SdMmcSdHs:
> > > + if (Capability->HighSpeed && (CardSupportedBusTimings & BIT1) !=
> 0)
> > {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + case SdMmcSdDs:
> > > + if ((CardSupportedBusTimings & BIT0) != 0) {
> > > + return TRUE;
> > > + }
> > > + break;
> > > + }
> > > + }
> > > +
> > > + return FALSE;
> > > +}
> > > +
> > > +/**
> > > + Get the target bus timing to set on the link. This function
> > > + will try to select highest bus timing supported by card, controller
> > > + and the driver.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] CardSupportedBusTimings Bitmask indicating which bus
> > > timings are supported by card
> > > + @param[in] IsInUhsI Flag indicating if link is in UHS-I
> > > +
> > > + @return Bus timing value that should be set on link
> > > +**/
> > > +STATIC
> > > +SD_MMC_BUS_MODE
> > > +SdGetTargetBusTiming (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN UINT8 CardSupportedBusTimings,
> > > + IN BOOLEAN IsInUhsI
> > > + )
> > > +{
> > > + SD_MMC_BUS_MODE BusTiming;
> > > +
> > > + if (IsInUhsI) {
> > > + BusTiming = SdMmcUhsSdr104;
> > > + } else {
> > > + BusTiming = SdMmcSdHs;
> > > + }
> > > +
> > > + while (BusTiming > SdMmcSdDs) {
> > > + if (SdIsBusTimingSupported (Private, SlotIndex,
> > > CardSupportedBusTimings, IsInUhsI, BusTiming)) {
> > > + break;
> > > + }
> > > + BusTiming--;
> > > + }
> >
> >
> > The origin logic has the below preference when selecting bus timing
> > (if supported):
> >
> > SdMmcUhsSdr104
> > SdMmcUhsSdr50
> > SdMmcUhsDdr50
> > SdMmcUhsSdr25
> > SdMmcUhsSdr12
> >
> > So we need to reorder the types in 'SD_MMC_BUS_MODE' to:
> >
> > typedef enum {
> > SdMmcSdDs,
> > SdMmcSdHs,
> > SdMmcUhsSdr12,
> > SdMmcUhsSdr25,
> > SdMmcUhsDdr50,
> > SdMmcUhsSdr50,
> > SdMmcUhsSdr104,
> > ...
> > } SD_MMC_BUS_MODE;
> >
> > Otherwise, the Ddr50 mode will never be selected.
> >
> >
> > > +
> > > + return BusTiming;
> > > +}
> > > +
> > > +/**
> > > + Get the target bus width to be set on the bus.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] BusTiming Bus timing set on the bus
> > > +
> > > + @return Bus width to be set on the bus
> > > +**/
> > > +STATIC
> > > +UINT16
> > > +SdGetTargetBusWidth (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + UINT16 BusWidth;
> > > + UINT16 PreferedBusWidth;
> > > +
> > > + PreferedBusWidth = Private-
> > > >Slot[SlotIndex].OperatingParameters.BusWidth;
> > > +
> > > + if (BusTiming == SdMmcSdDs || BusTiming == SdMmcSdHs) {
> > > + if (PreferedBusWidth != EDKII_SD_MMC_BUS_WIDTH_IGNORE) {
> > > + BusWidth = PreferedBusWidth;
> >
> >
> > The supported bus width is either 1 or 4 bit for 3.3V signal cards.
> > I think we need a more strict check here.
> >
> >
> > > + } else {
> > > + BusWidth = 4;
> > > + }
> > > + } else {
> > > + //
> > > + // UHS-I modes support only 4-bit width.
> > > + // Switch to 4-bit has been done before calling this function anyway so
> > > + // this is purely informational.
> > > + //
> > > + BusWidth = 4;
> > > + }
> > > +
> > > + return BusWidth;
> > > +}
> > > +
> > > +/**
> > > + Get the target clock frequency to be set on the bus.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] BusTiming Bus timing to be set on the bus
> > > +
> > > + @return Value of the clock frequency to be set on bus in MHz
> > > +**/
> > > +STATIC
> > > +UINT32
> > > +SdGetTargetBusClockFreq (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> > > +{
> > > + UINT32 PreferedClockFreq;
> > > + UINT32 MaxClockFreq;
> > > +
> > > + PreferedClockFreq = Private-
> > > >Slot[SlotIndex].OperatingParameters.ClockFreq;
> > > +
> > > + switch (BusTiming) {
> > > + case SdMmcUhsSdr104:
> > > + MaxClockFreq = 208;
> > > + break;
> > > + case SdMmcUhsSdr50:
> > > + MaxClockFreq = 100;
> > > + break;
> > > + case SdMmcUhsDdr50:
> > > + case SdMmcUhsSdr25:
> > > + case SdMmcSdHs:
> > > + MaxClockFreq = 50;
> > > + break;
> > > + case SdMmcUhsSdr12:
> > > + case SdMmcSdDs:
> > > + default:
> > > + MaxClockFreq = 25;
> >
> >
> > Minor comment, need an extra space for the above line.
> >
> >
> > > + }
> > > +
> > > + if (PreferedClockFreq != EDKII_SD_MMC_CLOCK_FREQ_IGNORE &&
> > > PreferedClockFreq < MaxClockFreq) {
> > > + return PreferedClockFreq;
> > > + } else {
> > > + return MaxClockFreq;
> > > + }
> > > +}
> > > +
> > > +/**
> > > + Get the driver strength to be set on bus
> >
> >
> > Please help to append a '.' character for the above line.
> > It is required for the edk2 coding style.
> >
> >
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] CardSupportedDriverStrengths Bitmask indicating which
> > > driver strengths are supported on the card
> > > + @param[in] BusTiming Bus timing set on the bus
> > > +
> > > + @return Value of the driver strength to be set on the bus
> > > +**/
> > > +STATIC
> > > +EDKII_SD_MMC_DRIVER_STRENGTH
> > > +SdGetTargetDriverStrength (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN UINT8 CardSupportedDriverStrengths,
> > > + IN SD_MMC_BUS_MODE BusTiming
> > > + )
> >
> >
> > One question here, the driver strength configuration is only for UHS-I cards.
> > Does the check on 'CardSupportedDriverStrengths' enough to ensure the
> > above
> > requirement or a boolean input parameter 'IsInUhsI' is needed here?
> >
>
> I think we can leave it to the code that actually sets the bus parameters
> to simply skip driver strength programming for legacy and select driver
> strength here
> based only on HW support and platform preference. The alternative is to
> return
> SdDriverStrengthIgnore here and handle that in code that actually sets driver
> strength.
>
> >
> > > +{
> > > + EDKII_SD_MMC_DRIVER_STRENGTH PreferedDriverStrength;
> > > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > > +
> > > + PreferedDriverStrength = Private-
> > > >Slot[SlotIndex].OperatingParameters.DriverStrength;
> > > + DriverStrength.Sd = SdDriverStrengthTypeB;
> > > +
> > > + if (PreferedDriverStrength.Sd !=
> > > EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE &&
> > > + (CardSupportedDriverStrengths & (BIT0 <<
> > PreferedDriverStrength.Sd)))
> >
> >
> > The host controller also has a capability for different types of driver
> strength.
> > (Capabilities Register, bit 36~38)
> >
> > The check should take it into consideration as well.
> >
> >
> > > {
> > > + DriverStrength.Sd = PreferedDriverStrength.Sd;
> > > + }
> > > +
> > > + return DriverStrength;
> > > +}
> > > +
> > > +/**
> > > + Get the target settings for the bus mode.
> > > +
> > > + @param[in] Private Pointer to controller private data
> > > + @param[in] SlotIndex Index of the slot in the controller
> > > + @param[in] SwitchQueryResp Pointer to switch query response
> > > + @param[in] IsInUhsI Flag indicating if link is in UHS-I mode
> > > + @param[out] BusMode Target configuration of the bus
> > > +**/
> > > +STATIC
> > > +VOID
> > > +SdGetTargetBusMode (
> > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > + IN UINT8 SlotIndex,
> > > + IN UINT8 *SwitchQueryResp,
> > > + IN BOOLEAN IsInUhsI,
> > > + OUT EDKII_SD_MMC_BUS_MODE *BusMode
> > > + )
> > > +{
> > > + BusMode->BusTiming = SdGetTargetBusTiming (Private, SlotIndex,
> > > SwitchQueryResp[13], IsInUhsI);
> > > + BusMode->BusWidth = SdGetTargetBusWidth (Private, SlotIndex,
> > > BusMode->BusTiming);
> > > + BusMode->ClockFreq = SdGetTargetBusClockFreq (Private, SlotIndex,
> > > BusMode->BusTiming);
> > > + BusMode->DriverStrength = SdGetTargetDriverStrength (Private,
> > > SlotIndex, SwitchQueryResp[9], BusMode->BusTiming);
> > > +}
> > > +
> > > /**
> > > Switch the high speed timing according to request.
> > >
> > > @@ -775,13 +1050,10 @@ SdCardSetBusMode (
> > > {
> > > EFI_STATUS Status;
> > > SD_MMC_HC_SLOT_CAP *Capability;
> > > - UINT32 ClockFreq;
> > > - UINT8 BusWidth;
> > > - UINT8 AccessMode;
> > > UINT8 HostCtrl1;
> > > UINT8 SwitchResp[64];
> > > - SD_MMC_BUS_MODE Timing;
> > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > + EDKII_SD_MMC_BUS_MODE BusMode;
> > >
> > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > >
> > > @@ -792,61 +1064,46 @@ SdCardSetBusMode (
> > > return Status;
> > > }
> > >
> > > - BusWidth = 4;
> > > -
> > > - Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, BusWidth);
> > > - if (EFI_ERROR (Status)) {
> > > - return Status;
> > > + if (S18A) {
> > > + //
> > > + // For UHS-I speed modes 4-bit data bus is requiered so we
> > > + // switch here irrespective of platform preference.
> > > + //
> > > + Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, 4);
> > > + if (EFI_ERROR (Status)) {
> > > + return Status;
> > > + }
> > > }
> > > +
> > > //
> > > // Get the supported bus speed from SWITCH cmd return data group #1.
> > > //
> > > - Status = SdCardSwitch (PassThru, Slot, 0xF, 0xF, 0xF, 0xF, FALSE,
> > > SwitchResp);
> > > + Status = SdCardSwitch (PassThru, Slot, 0xFF, 0xF,
> SdDriverStrengthIgnore,
> > > 0xF, FALSE, SwitchResp);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > - //
> > > - // Calculate supported bus speed/bus width/clock frequency by host
> and
> > > device capability.
> > > - //
> > > - ClockFreq = 0;
> > > - if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0))
> {
> > > - ClockFreq = 208;
> > > - AccessMode = 3;
> > > - Timing = SdMmcUhsSdr104;
> > > - } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] &
> BIT2) !=
> > 0))
> > > {
> > > - ClockFreq = 100;
> > > - AccessMode = 2;
> > > - Timing = SdMmcUhsSdr50;
> > > - } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] &
> BIT4) !=
> > > 0)) {
> > > - ClockFreq = 50;
> > > - AccessMode = 4;
> > > - Timing = SdMmcUhsDdr50;
> > > - } else if ((SwitchResp[13] & BIT1) != 0) {
> > > - ClockFreq = 50;
> > > - AccessMode = 1;
> > > - Timing = SdMmcUhsSdr25;
> > > - } else {
> > > - ClockFreq = 25;
> > > - AccessMode = 0;
> > > - Timing = SdMmcUhsSdr12;
> > > +
> > > + SdGetTargetBusMode (Private, Slot, SwitchResp, S18A, &BusMode);
> > > +
> > > + DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Target bus mode: bus
> > timing
> > > = %d, bus width = %d, clock freq[MHz] = %d, driver strength = %d\n",
> > > + BusMode.BusTiming, BusMode.BusWidth,
> > BusMode.ClockFreq,
> > > BusMode.DriverStrength.Sd));
> > > +
> > > + if (!S18A) {
> > > + Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca,
> > > BusMode.BusWidth);
> > > + if (EFI_ERROR (Status)) {
> > > + return Status;
> > > + }
> > > }
> >
> >
> > Is it feasible to set the bus width for the 3.3V signaled cards & the UHS-I
> > cards together here? I think the SdGetTargetBusWidth() already handles
> the
> > UHS-I cards case well by always setting the bus width to 4.
> >
>
> So basically to skip if (!S18A) condition and do bus width switch
> unconditionally?
> I am not sure how the bus will react to additional bus width switch for UHS-I
> case
> and I am not able to test it locally as I only have controller with legacy support
> available for tests.
> I guess I will give it a try and we will revert it if it causes any problems.
>
> >
> > >
> > > - Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE,
> > > SwitchResp);
> > > + Status = SdCardSwitch (PassThru, Slot, BusMode.BusTiming, 0xF,
> > > BusMode.DriverStrength.Sd, 0xF, TRUE, SwitchResp);
> >
> >
> > After the proposed change, the preferred bus timing and driver strength
> > value
> > will be set for the device through the SD_SWITCH command.
> >
> > However, on the host controller side, only the bus timing value is also
> > updated
> > in the Host Control 2 Register of the SD HC (via function
> > SdMmcHcUhsSignaling()).
> > It seems to me that the driver strength value does not get updated in this
> > register.
> >
> > I think the eMMC case has a similar issue.
> >
> >
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > >
> > > - if ((SwitchResp[16] & 0xF) != AccessMode) {
> > > - DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: Switch to
> > AccessMode %d
> > > ClockFreq %d BusWidth %d fails! The Switch response is 0x%1x\n",
> > > AccessMode, ClockFreq, BusWidth, SwitchResp[16] & 0xF));
> > > - return EFI_DEVICE_ERROR;
> > > - }
> >
> >
> > The above check may still be needed. Also, the whether the target driver
> > strength is successfully set needs to be checked as well.
> >
> > How about adding checks in function SdCardSwitch() for mode 1 of the
> > switch
> > command?
> >
> >
> > > -
> > > - DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Switch to
> AccessMode %d
> > > ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));
> > > -
> > > //
> > > - // Set to Hight Speed timing
> > > + // Set to High Speed timing
> > > //
> > > - if (AccessMode == 1) {
> > > + if (BusMode.BusTiming == SdMmcSdHs) {
> > > HostCtrl1 = BIT2;
> > > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1,
> > sizeof
> > > (HostCtrl1), &HostCtrl1);
> > > if (EFI_ERROR (Status)) {
> > > @@ -854,12 +1111,12 @@ SdCardSetBusMode (
> > > }
> > > }
> > >
> > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > Timing);
> > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > BusMode.BusTiming);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > >
> > > - Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> > > >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> > > + Status = SdMmcHcClockSupply (PciIo, Slot, BusMode.ClockFreq * 1000,
> > > Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > }
> > > @@ -869,7 +1126,7 @@ SdCardSetBusMode (
> > > Private->ControllerHandle,
> > > Slot,
> > > EdkiiSdMmcSwitchClockFreqPost,
> > > - &Timing
> > > + &BusMode.BusTiming
> > > );
> > > if (EFI_ERROR (Status)) {
> > > DEBUG ((
> > > @@ -882,7 +1139,7 @@ SdCardSetBusMode (
> > > }
> > > }
> > >
> > > - if ((AccessMode == 3) || ((AccessMode == 2) && (Capability-
> > > >TuningSDR50 != 0))) {
> > > + if ((BusMode.BusTiming == SdMmcUhsSdr104) ||
> ((BusMode.BusTiming
> > > == SdMmcUhsSdr50) && (Capability->TuningSDR50 != 0))) {
> > > Status = SdCardTuningClock (PciIo, PassThru, Slot);
> > > if (EFI_ERROR (Status)) {
> > > return Status;
> > > @@ -1025,10 +1282,8 @@ SdCardIdentification (
> > > // (One of support bits is set to 1: SDR50, SDR104 or DDR50 in the
> > > // Capabilities register), switch its voltage to 1.8V.
> > > //
> > > - if ((Private->Capability[Slot].Sdr50 != 0 ||
> > > - Private->Capability[Slot].Sdr104 != 0 ||
> > > - Private->Capability[Slot].Ddr50 != 0) &&
> > > - ((Ocr & BIT24) != 0)) {
> > > + if ((Private->Capability[Slot].Sdr50 || Private->Capability[Slot].Ddr50 ||
> > > Private->Capability[Slot].Sdr104) &&
> > > + ((Ocr & BIT24) != 0)) {
> >
> >
> > Minor comment, for:
> > Private->Capability[Slot].Sdr50
> > Private->Capability[Slot].Ddr50
> > Private->Capability[Slot].Sdr104
> >
> > They are of type UINT32, should use operators '==' or '!=' in condition
> > statement. I think the origin logic is good here.
> >
> >
> > > Status = SdCardVoltageSwitch (PassThru, Slot);
> > > if (EFI_ERROR (Status)) {
> > > DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing
> > > SdCardVoltageSwitch fails with %r\n", Status));
> > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > index 4881ee44cc..8f49954b7f 100644
> > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > @@ -28,6 +28,11 @@ EFI_DRIVER_BINDING_PROTOCOL
> > > gSdMmcPciHcDriverBinding = {
> > > NULL
> > > };
> > >
> > > +#define SLOT_INIT_TEMPLATE {0, UnknownSlot, 0, 0, 0, \
> > > + {EDKII_SD_MMC_BUS_WIDTH_IGNORE,\
> > > + EDKII_SD_MMC_CLOCK_FREQ_IGNORE,\
> > > + EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE}}
> >
> >
> > Please help to update the above definition to:
> > #define SLOT_INIT_TEMPLATE {0, UnknownSlot, 0, 0, 0, \
> > {EDKII_SD_MMC_BUS_WIDTH_IGNORE,\
> > EDKII_SD_MMC_CLOCK_FREQ_IGNORE,\
> > {EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE}}}
> >
> > The proposed one will cause GCC5 build failure.
> >
> >
> > > +
> > > //
> > > // Template for SD/MMC host controller private data.
> > > //
> > > @@ -50,8 +55,12 @@ SD_MMC_HC_PRIVATE_DATA
> > gSdMmcPciHcTemplate
> > > = {
> > > // Queue
> > > INITIALIZE_LIST_HEAD_VARIABLE (gSdMmcPciHcTemplate.Queue),
> > > { // Slot
> > > - {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0,
> 0,
> > > 0},
> > > - {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0,
> 0,
> > > 0}
> > > + SLOT_INIT_TEMPLATE,
> > > + SLOT_INIT_TEMPLATE,
> > > + SLOT_INIT_TEMPLATE,
> > > + SLOT_INIT_TEMPLATE,
> > > + SLOT_INIT_TEMPLATE,
> > > + SLOT_INIT_TEMPLATE
> > > },
> > > { // Capability
> > > {0},
> > > @@ -328,6 +337,7 @@ SdMmcPciHcEnumerateDevice (
> > >
> > > return;
> > > }
> > > +
> > > /**
> > > Tests to see if this driver supports a given controller. If a child device is
> > > provided,
> > > it further tests to see if this driver supports creating a handle for the
> > > specified child device.
> > > @@ -619,7 +629,6 @@ SdMmcPciHcDriverBindingStart (
> > > Support64BitDma = TRUE;
> > > for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
> > > Private->Slot[Slot].Enable = TRUE;
> > > -
> > > //
> > > // Get SD/MMC Pci Host Controller Version
> > > //
> > > @@ -635,19 +644,34 @@ SdMmcPciHcDriverBindingStart (
> > >
> > > Private->BaseClkFreq[Slot] = Private->Capability[Slot].BaseClkFreq;
> > >
> > > - if (mOverride != NULL && mOverride->Capability != NULL) {
> > > - Status = mOverride->Capability (
> > > - Controller,
> > > - Slot,
> > > - &Private->Capability[Slot],
> > > - &Private->BaseClkFreq[Slot]
> > > - );
> > > - if (EFI_ERROR (Status)) {
> > > - DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",
> > > - __FUNCTION__, Status));
> > > - continue;
> > > + if (mOverride != NULL) {
> > > + if (mOverride->Capability != NULL) {
> > > + Status = mOverride->Capability (
> > > + Controller,
> > > + Slot,
> > > + &Private->Capability[Slot],
> > > + &Private->BaseClkFreq[Slot]
> > > + );
> > > + if (EFI_ERROR (Status)) {
> > > + DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",
> > > + __FUNCTION__, Status));
> > > + continue;
> > > + }
> > > + }
> > > +
> > > + if (mOverride->NotifyPhase != NULL) {
> > > + Status = mOverride->NotifyPhase (
> > > + Controller,
> > > + Slot,
> > > + EdkiiSdMmcGetOperatingParam,
> > > + (VOID*)&Private->Slot[Slot].OperatingParameters
> > > + );
> > > + if (EFI_ERROR (Status)) {
> > > + DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters,
> > > using defaults\n" __FUNCTION__));
> >
> >
> > Please update the above line to (missed one ',' before '__FUNCTION__'):
> > DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters, using
> > defaults\n", __FUNCTION__));
> >
> > It will cause GCC5 build failure for the proposed change.
> >
> >
> > > + }
> > > }
> > > }
> > > +
> > > DumpCapabilityReg (Slot, &Private->Capability[Slot]);
> > > DEBUG ((
> > > DEBUG_INFO,
> > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > index 77bbf83b76..b768f3942f 100644
> > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > @@ -78,11 +78,12 @@ typedef enum {
> > > } EFI_SD_MMC_SLOT_TYPE;
> > >
> > > typedef struct {
> > > - BOOLEAN Enable;
> > > - EFI_SD_MMC_SLOT_TYPE SlotType;
> > > - BOOLEAN MediaPresent;
> > > - BOOLEAN Initialized;
> > > - SD_MMC_CARD_TYPE CardType;
> > > + BOOLEAN Enable;
> > > + EFI_SD_MMC_SLOT_TYPE SlotType;
> > > + BOOLEAN MediaPresent;
> > > + BOOLEAN Initialized;
> > > + SD_MMC_CARD_TYPE CardType;
> > > + EDKII_SD_MMC_OPERATING_PARAMETERS OperatingParameters;
> > > } SD_MMC_HC_SLOT;
> > >
> > > typedef struct {
> > > @@ -120,6 +121,13 @@ typedef struct {
> > > UINT32 BaseClkFreq[SD_MMC_HC_MAX_SLOT];
> > > } SD_MMC_HC_PRIVATE_DATA;
> > >
> > > +typedef struct {
> > > + EDKII_SD_MMC_BUS_TIMING BusTiming;
> >
> >
> > Should be:
> > SD_MMC_BUS_MODE BusTiming;
> >
> >
> > > + UINT16 BusWidth;
> > > + UINT32 ClockFreq;
> > > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > > +} EDKII_SD_MMC_BUS_MODE;
> >
> >
> > Since the above structure is a driver internal one, I prefer dropping the
> > prefix 'EDKII_'. But unfortunately, SD_MMC_BUS_MODE is already used in
> > Protocol/SdMmcOverride.h, so how about SD_MMC_BUS_SETTINGS?
> >
> >
> > > +
> > > #define SD_MMC_HC_TRB_SIG SIGNATURE_32 ('T', 'R', 'B', 'T')
> > >
> > > //
> > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > index 5d1f977e55..863ae3db34 100644
> > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > @@ -1263,10 +1263,10 @@ SdMmcHcInitHost (
> > > **/
> > > EFI_STATUS
> > > SdMmcHcUhsSignaling (
> > > - IN EFI_HANDLE ControllerHandle,
> > > - IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > - IN UINT8 Slot,
> > > - IN SD_MMC_BUS_MODE Timing
> > > + IN EFI_HANDLE ControllerHandle,
> > > + IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > + IN UINT8 Slot,
> > > + IN SD_MMC_BUS_MODE Timing
> > > )
> >
> >
> > I think the changes made here (space indentation) can be dropped.
> >
> >
> > > {
> > > EFI_STATUS Status;
> > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > index 0b0d415256..c4d4aef73a 100644
> > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > @@ -611,10 +611,10 @@ SdMmcHcInitTimeoutCtrl (
> > > **/
> > > EFI_STATUS
> > > SdMmcHcUhsSignaling (
> > > - IN EFI_HANDLE ControllerHandle,
> > > - IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > - IN UINT8 Slot,
> > > - IN SD_MMC_BUS_MODE Timing
> > > + IN EFI_HANDLE ControllerHandle,
> > > + IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > + IN UINT8 Slot,
> > > + IN SD_MMC_BUS_MODE Timing
> >
> >
> > I think the changes made here (space indentation) can be dropped.
> >
> > Best Regards,
> > Hao Wu
> >
> >
> > > );
> > >
> > > #endif
> > > --
> > > 2.14.1.windows.1
>
> --------------------------------------------------------------------
>
> Intel Technology Poland sp. z o.o.
> ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII
> Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-
> 07-52-316 | Kapital zakladowy 200.000 PLN.
>
> Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego
> adresata i moze zawierac informacje poufne. W razie przypadkowego
> otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale
> jej usuniecie; jakiekolwiek
> przegladanie lub rozpowszechnianie jest zabronione.
> This e-mail and any attachments may contain confidential material for the
> sole use of the intended recipient(s). If you are not the intended recipient,
> please contact the sender and delete all copies; any review or distribution by
> others is strictly prohibited.
>
>
>
--------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek
przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by
others is strictly prohibited.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [edk2-devel] [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement revision 3 of SdMmcOverrideProtocol
2019-06-17 15:11 ` [edk2-devel] " Albecki, Mateusz
@ 2019-06-18 3:23 ` Wu, Hao A
0 siblings, 0 replies; 9+ messages in thread
From: Wu, Hao A @ 2019-06-18 3:23 UTC (permalink / raw)
To: Albecki, Mateusz, devel@edk2.groups.io
Cc: Ard Biesheuvel, 'mw@semihalf.com'
> -----Original Message-----
> From: Albecki, Mateusz
> Sent: Monday, June 17, 2019 11:12 PM
> To: devel@edk2.groups.io; Albecki, Mateusz
> Cc: Wu, Hao A
> Subject: RE: [edk2-devel] [PATCH 2/2] MdeModulePkg/SdMmcHcDxe:
> Implement revision 3 of SdMmcOverrideProtocol
>
> Actually I would like to back out of the proposed solution with mapping SD
> driver strength to eMMC driver strength. Since SD specification doesn't even
> specify enough space in driver strength field in host control 2 register to
> cover for all 5 driver strength types defined by eMMC specification and I also
> don't know about any controller that would use the mapping below. The
> controller I am working on currently just ignores controller side of the driver
> strength setting altogether so for now I would like to leave the driver
> strength setting for eMMC as is(check card capability and platform selection)
> and update only SD case.
I am fine with this approach.
Best Regards,
Hao Wu
>
> Thanks,
> Mateusz
>
> > -----Original Message-----
> > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> > Albecki, Mateusz
> > Sent: Thursday, June 13, 2019 4:39 PM
> > To: devel@edk2.groups.io
> > Cc: Wu, Hao A <hao.a.wu@intel.com>
> > Subject: Re: [edk2-devel] [PATCH 2/2] MdeModulePkg/SdMmcHcDxe:
> > Implement revision 3 of SdMmcOverrideProtocol
> >
> > Resending to group. Inline reply to some of the comments.
> >
> > As for the mapping between eMMC driver strength and SD controller
> driver
> > strength should we use this one:
> >
> > SD controller -> eMMC card
> > B -> Type 0
> > A -> Type 1
> > C -> Type 2
> > D -> Type 3
> > (none) -> Type4
> >
> > And Type 4 would be identified by bit 39 in capability register which is
> > currently marked as reserved in SD controller specification. This is current
> > capability register definition in the driver.
> >
> > Thanks,
> > Mateusz
> >
> > > -----Original Message-----
> > > From: Wu, Hao A
> > > Sent: Monday, June 10, 2019 5:19 AM
> > > To: Albecki, Mateusz <mateusz.albecki@intel.com>
> > > Subject: RE: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement
> > revision
> > > 3 of SdMmcOverrideProtocol
> > >
> > > Hello Mateusz,
> > >
> > > Some inline comments below:
> > >
> > > > -----Original Message-----
> > > > From: Albecki, Mateusz
> > > > Sent: Monday, June 03, 2019 7:34 PM
> > > > Cc: Albecki, Mateusz; Wu, Hao A; Albecki
> > > > Subject: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement
> revision
> > 3
> > > > of SdMmcOverrideProtocol
> > > >
> > > > Implement support for GetOperatingParamters notify phase
> > > > in SdMmcHcDxe driver. GetOperatingParameters notify phase
> > > > is signaled before we start card detection and initialization.
> > > > Code has been updated for both eMMC and SD card controllers to
> > > > take into consideration those new parameters. Initialization process
> > > > has been divided into 2 steps. In the first step we bring the link
> > > > up to the point where we can get card identification data(Extended
> > > > CSD in eMMC case and SWITCH command response in SD card case).
> This
> > > > data is later used along with controller capabilities and operating
> > > > parameters passed in GetOperatingParameters phase to choose
> > preferred
> > > > bus settings in GetTargetBusSettings function. Those settings are later
> > > > on to start bus training to high speeds. If user passes incompatible
> > > > setting with selected bus timing driver will assume it's standard
> behavior
> > > with
> > > > respect to that setting. For instance if HS400 has been selected as a
> > > > target bus timing due to card and controller support bus width setting
> of
> > > > 4 and 1 bit won't be respected and 8 bit setting will be chosen instead.
> > > >
> > > >
> > > > Cc: hao.a.wu@intel.com
> > > > Signed-off-by: Albecki, Mateusz <mateusz.albecki@intel.com>
> > > > Contributed-under: TianoCore Contribution Agreement 1.1
> > > > ---
> > > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c | 522
> > > > +++++++++++++++------
> > > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c | 381
> > > > ++++++++++++---
> > > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c | 52 +-
> > > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h | 18 +-
> > > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c | 8 +-
> > > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h | 8 +-
> > > > 6 files changed, 750 insertions(+), 239 deletions(-)
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > > index deaf4468c9..1a81f6d250 100644
> > > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > > @@ -449,7 +449,7 @@ EFI_STATUS
> > > > EmmcSendTuningBlk (
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > - IN UINT8 BusWidth
> > > > + IN UINT16 BusWidth
> > > > )
> > > > {
> > > > EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
> > > > @@ -506,7 +506,7 @@ EmmcTuningClkForHs200 (
> > > > IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > - IN UINT8 BusWidth
> > > > + IN UINT16 BusWidth
> > > > )
> > > > {
> > > > EFI_STATUS Status;
> > > > @@ -583,7 +583,7 @@ EmmcSwitchBusWidth (
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > IN BOOLEAN IsDdr,
> > > > - IN UINT8 BusWidth
> > > > + IN UINT16 BusWidth
> > > > )
> > > > {
> > > > EFI_STATUS Status;
> > > > @@ -641,13 +641,13 @@ EmmcSwitchBusWidth (
> > > > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6 and SD Host
> > > > Controller
> > > > Simplified Spec 3.0 Figure 3-3 for details.
> > > >
> > > > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> instance.
> > > > - @param[in] PassThru A pointer to the
> > > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > > - @param[in] Slot The slot number of the SD card to send the
> > > command
> > > > to.
> > > > - @param[in] Rca The relative device address to be assigned.
> > > > - @param[in] HsTiming The value to be written to HS_TIMING field
> of
> > > > EXT_CSD register.
> > > > - @param[in] Timing The bus mode timing indicator.
> > > > - @param[in] ClockFreq The max clock frequency to be set, the unit
> is
> > > > MHz.
> > > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> > instance.
> > > > + @param[in] PassThru A pointer to the
> > > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > > + @param[in] Slot The slot number of the SD card to send the
> > > > command to.
> > > > + @param[in] Rca The relative device address to be assigned.
> > > > + @param[in] DriverStrength Driver strength to set for speed modes
> > that
> > > > support it.
> > > > + @param[in] Timing The bus mode timing indicator.
> > >
> > >
> > > Please help to update the parameter comment to reflect the name
> change
> > > from
> > > 'Timing' to 'BusTiming'.
> > >
> > >
> > > > + @param[in] ClockFreq The max clock frequency to be set, the unit
> is
> > > > MHz.
> > > >
> > > > @retval EFI_SUCCESS The operation is done correctly.
> > > > @retval Others The operation fails.
> > > > @@ -659,8 +659,8 @@ EmmcSwitchBusTiming (
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > - IN UINT8 HsTiming,
> > > > - IN SD_MMC_BUS_MODE Timing,
> > > > + IN EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength,
> > > > + IN SD_MMC_BUS_MODE BusTiming,
> > > > IN UINT32 ClockFreq
> > > > )
> > > > {
> > > > @@ -678,12 +678,29 @@ EmmcSwitchBusTiming (
> > > > //
> > > > Access = 0x03;
> > > > Index = OFFSET_OF (EMMC_EXT_CSD, HsTiming);
> > > > - Value = HsTiming;
> > > > CmdSet = 0;
> > > > + switch (BusTiming) {
> > > > + case SdMmcMmcHs400:
> > > > + Value = (UINT8)((DriverStrength.Emmc << 4) | 3);
> > > > + break;
> > > > + case SdMmcMmcHs200:
> > > > + Value = (UINT8)((DriverStrength.Emmc << 4) | 2);
> > > > + break;
> > > > + case SdMmcMmcHsSdr:
> > > > + case SdMmcMmcHsDdr:
> > > > + Value = 1;
> > > > + break;
> > > > + case SdMmcMmcLegacy:
> > > > + Value = 0;
> > > > + break;
> > > > + default:
> > > > + DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Unsupported
> > > > BusTiming(%d\n)", BusTiming));
> > > > + return EFI_INVALID_PARAMETER;
> > > > + }
> > > >
> > > > Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);
> > > > if (EFI_ERROR (Status)) {
> > > > - DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to
> > hstiming %d
> > > > fails with %r\n", HsTiming, Status));
> > > > + DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to bus
> > > > timing %d fails with %r\n", BusTiming, Status));
> > > > return Status;
> > > > }
> > > >
> > > > @@ -713,7 +730,7 @@ EmmcSwitchBusTiming (
> > > > Private->ControllerHandle,
> > > > Slot,
> > > > EdkiiSdMmcSwitchClockFreqPost,
> > > > - &Timing
> > > > + &BusTiming
> > > > );
> > > > if (EFI_ERROR (Status)) {
> > > > DEBUG ((
> > > > @@ -754,25 +771,34 @@ EmmcSwitchToHighSpeed (
> > >
> > >
> > > Please help to update the function comments for
> > > EmmcSwitchToHighSpeed() after
> > > the parameter changes.
> > >
> > >
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > - IN UINT32 ClockFreq,
> > > > - IN BOOLEAN IsDdr,
> > > > - IN UINT8 BusWidth
> > > > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > > > )
> > > > {
> > > > EFI_STATUS Status;
> > > > - UINT8 HsTiming;
> > > > UINT8 HostCtrl1;
> > > > - SD_MMC_BUS_MODE Timing;
> > > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > > + BOOLEAN IsDdr;
> > > >
> > > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > >
> > > > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr,
> > > BusWidth);
> > > > + if ((BusMode->BusTiming != SdMmcMmcHsSdr && BusMode-
> > > > >BusTiming != SdMmcMmcHsDdr) ||
> > > > + BusMode->ClockFreq > 52) {
> > > > + return EFI_INVALID_PARAMETER;
> > > > + }
> > > > +
> > > > + if (BusMode->BusTiming == SdMmcMmcHsDdr) {
> > > > + IsDdr = TRUE;
> > > > + } else {
> > > > + IsDdr = FALSE;
> > > > + }
> > > > +
> > > > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr,
> > > BusMode-
> > > > >BusWidth);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > +
> > > > //
> > > > - // Set to Hight Speed timing
> > > > + // Set to High Speed timing
> > > > //
> > > > HostCtrl1 = BIT2;
> > > > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1,
> > sizeof
> > > > (HostCtrl1), &HostCtrl1);
> > > > @@ -780,37 +806,27 @@ EmmcSwitchToHighSpeed (
> > > > return Status;
> > > > }
> > > >
> > > > - if (IsDdr) {
> > > > - Timing = SdMmcMmcHsDdr;
> > > > - } else if (ClockFreq == 52) {
> > > > - Timing = SdMmcMmcHsSdr;
> > > > - } else {
> > > > - Timing = SdMmcMmcLegacy;
> > > > - }
> > > > -
> > > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > > Timing);
> > > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo,
> Slot,
> > > > BusMode->BusTiming);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > >
> > > > - HsTiming = 1;
> > > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > > Timing,
> > > > ClockFreq);
> > > > -
> > > > - return Status;
> > > > + return EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
> > > > }
> > > >
> > > > /**
> > > > - Switch to the HS200 timing according to request.
> > > > + Switch to the HS200 timing. This function assumes that eMMC bus is
> > still
> > > in
> > > > legacy mode.
> > > >
> > > > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host
> > > > Controller
> > > > Simplified Spec 3.0 Figure 2-29 for details.
> > > >
> > > > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> instance.
> > > > - @param[in] PassThru A pointer to the
> > > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > > - @param[in] Slot The slot number of the SD card to send the
> > > command
> > > > to.
> > > > - @param[in] Rca The relative device address to be assigned.
> > > > - @param[in] ClockFreq The max clock frequency to be set.
> > > > - @param[in] BusWidth The bus width to be set, it could be 4 or 8.
> > > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> > instance.
> > > > + @param[in] PassThru A pointer to the
> > > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > > + @param[in] Slot The slot number of the SD card to send the
> > > > command to.
> > > > + @param[in] Rca The relative device address to be assigned.
> > > > + @param[in] DriverStrength The driver strength to be selected.
> > > > + @param[in] ClockFreq The max clock frequency to be set.
> > > > + @param[in] BusWidth The bus width to be set, it could be 4 or 8.
> > > >
> > > > @retval EFI_SUCCESS The operation is done correctly.
> > > > @retval Others The operation fails.
> > > > @@ -822,30 +838,25 @@ EmmcSwitchToHS200 (
> > >
> > >
> > > Please help to update the function comments for EmmcSwitchToHS200()
> > > after the
> > > parameter changes.
> > >
> > >
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > - IN UINT32 ClockFreq,
> > > > - IN UINT8 BusWidth
> > > > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > > > )
> > > > {
> > > > EFI_STATUS Status;
> > > > - UINT8 HsTiming;
> > > > UINT16 ClockCtrl;
> > > > - SD_MMC_BUS_MODE Timing;
> > > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > >
> > > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > >
> > > > - if ((BusWidth != 4) && (BusWidth != 8)) {
> > > > + if (BusMode->BusTiming != SdMmcMmcHs200 ||
> > > > + (BusMode->BusWidth != 4 && BusMode->BusWidth != 8)) {
> > > > return EFI_INVALID_PARAMETER;
> > > > }
> > > >
> > > > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE,
> > > BusWidth);
> > > > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE,
> > > > BusMode->BusWidth);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > //
> > > > - // Set to HS200/SDR104 timing
> > > > - //
> > > > - //
> > > > // Stop bus clock at first
> > > > //
> > > > Status = SdMmcHcStopClock (PciIo, Slot);
> > > > @@ -853,9 +864,7 @@ EmmcSwitchToHS200 (
> > > > return Status;
> > > > }
> > > >
> > > > - Timing = SdMmcMmcHs200;
> > > > -
> > > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > > Timing);
> > > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo,
> Slot,
> > > > BusMode->BusTiming);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > @@ -881,28 +890,27 @@ EmmcSwitchToHS200 (
> > > > ClockCtrl = BIT2;
> > > > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL,
> > sizeof
> > > > (ClockCtrl), &ClockCtrl);
> > > >
> > > > - HsTiming = 2;
> > > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > > Timing,
> > > > ClockFreq);
> > > > + Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
> > >
> > >
> > > After the proposed change, the preferred bus timing and driver strength
> > > value
> > > will be set for the device through the EMMC_SWITCH command.
> > >
> > > However, on the host controller side, only the bus timing value is also
> > > updated
> > > in the Host Control 2 Register of the SD HC (via function
> > > SdMmcHcUhsSignaling()).
> > > It seems to me that the driver strength value does not get updated in this
> > > register.
> > >
> > > I think the SD case has a similar issue.
> >
> > For SD I agree that there is an issue but for eMMC there is no clear mapping
> > between
> > eMMC defined driver strength types and SD defined driver strength types.
> > The controller
> > I happen to be working with seems to ignore the values in this register. If
> we
> > can agree on
> > one mapping that will be able to service majority of the eMMC controllers
> on
> > market I don't
> > mind adding that. We can maybe add driver strength setting to
> > SdMmcHcUhsSignaling so that
> > platform has an opportunity to correct core driver during
> > EdkiiSdMmcUhsSignaling notify.
> >
> > >
> > >
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > >
> > > > - Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth);
> > > > + Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusMode-
> > > > >BusWidth);
> > > >
> > > > return Status;
> > > > }
> > > >
> > > > /**
> > > > - Switch to the HS400 timing according to request.
> > > > + Switch to the HS400 timing. This function assumes that eMMC bus is
> > still
> > > in
> > > > legacy mode.
> > > >
> > > > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host
> > > > Controller
> > > > Simplified Spec 3.0 Figure 2-29 for details.
> > > >
> > > > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> instance.
> > > > - @param[in] PassThru A pointer to the
> > > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > > - @param[in] Slot The slot number of the SD card to send the
> > > command
> > > > to.
> > > > - @param[in] Rca The relative device address to be assigned.
> > > > - @param[in] ClockFreq The max clock frequency to be set.
> > > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> > instance.
> > > > + @param[in] PassThru A pointer to the
> > > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > > + @param[in] Slot The slot number of the SD card to send the
> > > > command to.
> > > > + @param[in] Rca The relative device address to be assigned.
> > > > + @param[in] ClockFreq The max clock frequency to be set.
> > >
> > >
> > > Please help to update the function comments for EmmcSwitchToHS400()
> > > after the
> > > parameter changes.
> > >
> > >
> > > >
> > > > @retval EFI_SUCCESS The operation is done correctly.
> > > > @retval Others The operation fails.
> > > > @@ -914,47 +922,321 @@ EmmcSwitchToHS400 (
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > - IN UINT32 ClockFreq
> > > > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > > > )
> > > > {
> > > > EFI_STATUS Status;
> > > > - UINT8 HsTiming;
> > > > - SD_MMC_BUS_MODE Timing;
> > > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > > + EDKII_SD_MMC_BUS_MODE Hs200BusMode;
> > > > + UINT32 HsFreq;
> > > > +
> > > > + if (BusMode->BusTiming != SdMmcMmcHs400 ||
> > > > + BusMode->BusWidth != 8) {
> > > > + return EFI_INVALID_PARAMETER;
> > > > + }
> > > >
> > > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > > + Hs200BusMode.BusTiming = SdMmcMmcHs200;
> > > > + Hs200BusMode.BusWidth = BusMode->BusWidth;
> > > > + Hs200BusMode.ClockFreq = BusMode->ClockFreq;
> > > > + Hs200BusMode.DriverStrength = BusMode->DriverStrength;
> > > >
> > > > - Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, 8);
> > > > + Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca,
> > > &Hs200BusMode);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > +
> > > > //
> > > > - // Set to Hight Speed timing and set the clock frequency to a value
> less
> > > than
> > > > 52MHz.
> > > > + // Set to High Speed timing and set the clock frequency to a value less
> > > than
> > > > or equal to 52MHz.
> > > > + // This step is necessary to be able to switch Bus into 8 bit DDR mode
> > > which
> > > > is unsupported in HS200.
> > > > //
> > > > - HsTiming = 1;
> > > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > > > SdMmcMmcHsSdr, 52);
> > > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo,
> Slot,
> > > > SdMmcMmcHsSdr);
> > >
> > >
> > > The above SdMmcHcUhsSignaling() is newly added, is this a bug for the
> > origin
> > > code?
> > >
> > > I searched the eMMC spec, it seems to me the spec does not explicitly
> > > mention
> > > the Host Control 2 Register at all, I am not very sure if such change will
> > > bring any effect to devices. Did you have a try without adding such
> change?
> > >
> >
> > This is aligned to the behavior of EmmcSwitchToHighSpeed function. My
> > eMMC
> > controller doesn't need this register to be programmed for switch to high
> > speed
> > but calling SdMmcUhsSignaling here gives override protocol a chance to
> finish
> > switch to high speed for eMMC controllers that need such tweaking.
> >
> > >
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > - //
> > > > - // HS400 mode must use 8 data lines.
> > > > - //
> > > > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, TRUE, 8);
> > > > +
> > > > + HsFreq = BusMode->ClockFreq < 52 ? BusMode->ClockFreq : 52;
> > > > + Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > > >DriverStrength, SdMmcMmcHsSdr, HsFreq);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > >
> > > > - Timing = SdMmcMmcHs400;
> > > > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, TRUE,
> > > BusMode-
> > > > >BusWidth);
> > > > + if (EFI_ERROR (Status)) {
> > > > + return Status;
> > > > + }
> > > >
> > > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > > Timing);
> > > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo,
> Slot,
> > > > BusMode->BusTiming);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > >
> > > > - HsTiming = 3;
> > > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > > Timing,
> > > > ClockFreq);
> > > > + return EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
> > >
> > >
> > > After the proposed change, the preferred bus timing and driver strength
> > > value
> > > will be set for the device through the EMMC_SWITCH command.
> > >
> > > However, on the host controller side, only the bus timing value is also
> > > updated
> > > in the Host Control 2 Register of the SD HC (via function
> > > SdMmcHcUhsSignaling()).
> > > It seems to me that the driver strength value does not get updated in this
> > > register.
> > >
> > > I think the SD case has a similar issue.
> > >
> > >
> > > > +}
> > > >
> > > > - return Status;
> > > > +/**
> > > > + Check if passed BusTiming is supported in both controller and card.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] ExtCsd Pointer to the card's extended CSD
> > > > + @param[in] BusTiming Bus timing to check
> > > > +
> > > > + @retval TRUE Both card and controller support given BusTiming
> > > > + @retval FALSE Card or controller doesn't support given BusTiming
> > > > +**/
> > > > +STATIC
> > > > +BOOLEAN
> > > > +IsBusTimingSupported (
> > >
> > >
> > > How about renaming it to EmmcIsBusTimingSupported()?
> > >
> > >
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN EMMC_EXT_CSD *ExtCsd,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + BOOLEAN Supported;
> > > > + SD_MMC_HC_SLOT_CAP *Capabilities;
> > > > +
> > > > + Capabilities = &Private->Capability[SlotIndex];
> > > > +
> > > > + Supported = FALSE;
> > > > + switch (BusTiming) {
> > > > + case SdMmcMmcHs400:
> > > > + if ((((ExtCsd->DeviceType & (BIT6 | BIT7)) != 0) && (Capabilities-
> > > > >Hs400 != 0)) && Capabilities->BusWidth8) {
> > > > + Supported = TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcMmcHs200:
> > > > + if ((((ExtCsd->DeviceType & (BIT4 | BIT5)) != 0) && (Capabilities-
> > > > >Sdr104 != 0))) {
> > > > + Supported = TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcMmcHsDdr:
> > > > + if ((((ExtCsd->DeviceType & (BIT2 | BIT3)) != 0) && (Capabilities-
> > > > >Ddr50 != 0))) {
> > > > + Supported = TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcMmcHsSdr:
> > > > + if ((((ExtCsd->DeviceType & BIT1) != 0) && (Capabilities-
> > >HighSpeed !=
> > > > 0))) {
> > > > + Supported = TRUE;
> > > > + } else if ((((ExtCsd->DeviceType & BIT0) != 0) && (Capabilities-
> > > > >HighSpeed != 0))) {
> > >
> > >
> > > For this case, I think the bus timing should be classified to
> > SdMmcMmcLegacy.
> > > Since under this timing, the maximum frequency allowed is 26Mhz. If set
> to
> > > SdMmcMmcHsSdr the driver will try to set the frequency to 52Mhz later
> in
> > > EmmcGetTargetClockFreq().
> > >
> > >
> > > > + Supported = TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcMmcLegacy:
> > > > + Supported = TRUE;
> > > > + break;
> > > > + default:
> > > > + ASSERT (FALSE);
> > > > + }
> > > > +
> > > > + return Supported;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target bus timing to set on the link. This function
> > > > + will try to select highest bus timing supported by card, controller
> > > > + and the driver.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] ExtCsd Pointer to the card's extended CSD
> > > > +
> > > > + @return Bus timing value that should be set on link
> > > > +**/
> > > > +STATIC
> > > > +SD_MMC_BUS_MODE
> > > > +EmmcGetTargetBusTiming (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN EMMC_EXT_CSD *ExtCsd
> > > > + )
> > > > +{
> > > > + SD_MMC_BUS_MODE BusTiming;
> > > > +
> > > > + //
> > > > + // We start with highest bus timing that this driver currently support
> > and
> > > > + // return as soon as we find supported timing.
> > > > + //
> > > > + BusTiming = SdMmcMmcHs400;
> > > > + while (BusTiming > SdMmcMmcLegacy) {
> > > > + if (IsBusTimingSupported (Private, SlotIndex, ExtCsd, BusTiming)) {
> > > > + break;
> > > > + }
> > > > + BusTiming--;
> > > > + }
> > > > +
> > > > + return BusTiming;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the passed bus width is supported by controller and card.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] BusTiming Bus timing set on the link
> > > > + @param[in] BusWidth Bus width to check
> > > > +
> > > > + @retval TRUE Passed bus width is supported in current bus
> > > configuration
> > > > + @retval FALSE Passed bus width is not supported in current bus
> > > > configuration
> > > > +**/
> > > > +STATIC
> > > > +BOOLEAN
> > > > +IsBusWidthSupported (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN SD_MMC_BUS_MODE BusTiming,
> > > > + IN UINT16 BusWidth
> > > > + )
> > > > +{
> > > > + if (BusWidth == 8 && Private->Capability[SlotIndex].BusWidth8) {
> > > > + return TRUE;
> > > > + } else if (BusWidth == 4 && BusTiming != SdMmcMmcHs400) {
> > > > + return TRUE;
> > > > + } else if (BusWidth == 1 && (BusTiming == SdMmcMmcHsSdr ||
> > > BusTiming
> > > > == SdMmcMmcLegacy)) {
> > > > + return TRUE;
> > > > + }
> > > > +
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target bus width to be set on the bus.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > > + @param[in] BusTiming Bus timing set on the bus
> > > > +
> > > > + @return Bus width to be set on the bus
> > > > +**/
> > > > +STATIC
> > > > +UINT16
> > > > +EmmcGetTargetBusWidth (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN EMMC_EXT_CSD *ExtCsd,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + UINT16 BusWidth;
> > > > + UINT16 PreferedBusWidth;
> > > > +
> > > > + PreferedBusWidth = Private-
> > > > >Slot[SlotIndex].OperatingParameters.BusWidth;
> > > > +
> > > > + if (PreferedBusWidth != EDKII_SD_MMC_BUS_WIDTH_IGNORE &&
> > > > + IsBusWidthSupported (Private, SlotIndex, BusTiming,
> > > > PreferedBusWidth)) {
> > > > + BusWidth = PreferedBusWidth;
> > > > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 8)) {
> > > > + BusWidth = 8;
> > > > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 4)) {
> > > > + BusWidth = 4;
> > > > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 1)) {
> > > > + BusWidth = 1;
> > > > + }
> > > > +
> > > > + return BusWidth;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target clock frequency to be set on the bus.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > > + @param[in] BusTiming Bus timing to be set on the bus
> > > > +
> > > > + @return Value of the clock frequency to be set on bus in MHz
> > > > +**/
> > > > +STATIC
> > > > +UINT32
> > > > +EmmcGetTargetClockFreq (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN EMMC_EXT_CSD *ExtCsd,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + UINT32 PreferedClockFreq;
> > > > + UINT32 MaxClockFreq;
> > > > +
> > > > + PreferedClockFreq = Private-
> > > > >Slot[SlotIndex].OperatingParameters.ClockFreq;
> > > > +
> > > > + switch (BusTiming) {
> > > > + case SdMmcMmcHs400:
> > > > + case SdMmcMmcHs200:
> > > > + MaxClockFreq = 200;
> > > > + break;
> > > > + case SdMmcMmcHsSdr:
> > > > + case SdMmcMmcHsDdr:
> > > > + MaxClockFreq = 52;
> > > > + break;
> > > > + default:
> > > > + MaxClockFreq = 26;
> > > > + break;
> > > > + }
> > > > +
> > > > + if (PreferedClockFreq != EDKII_SD_MMC_CLOCK_FREQ_IGNORE &&
> > > > PreferedClockFreq < MaxClockFreq) {
> > > > + return PreferedClockFreq;
> > > > + } else {
> > > > + return MaxClockFreq;
> > > > + }
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the driver strength to be set on bus
> > >
> > > Please help to append a '.' character for the above line.
> > > It is required for the edk2 coding style.
> > >
> > >
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > > + @param[in] BusTiming Bus timing set on the bus
> > > > +
> > > > + @return Value of the driver strength to be set on the bus
> > > > +**/
> > > > +STATIC
> > > > +EDKII_SD_MMC_DRIVER_STRENGTH
> > > > +EmmcGetTargetDriverStrength (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN EMMC_EXT_CSD *ExtCsd,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + EDKII_SD_MMC_DRIVER_STRENGTH PreferedDriverStrength;
> > > > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > > > +
> > > > + PreferedDriverStrength = Private-
> > > > >Slot[SlotIndex].OperatingParameters.DriverStrength;
> > > > + DriverStrength.Emmc = EmmcDriverStrengthType0;
> > > > +
> > > > + if (PreferedDriverStrength.Emmc !=
> > > > EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE &&
> > > > + (ExtCsd->DriverStrength & (BIT0 <<
> PreferedDriverStrength.Emmc)))
> > {
> > >
> > >
> > > The host controller also has a capability for different types of driver
> > strength.
> > > (Capabilities Register, bit 36~38)
> > >
> > > The check should take it into consideration as well.
> >
> > For SD it should. For eMMC it's not as obvious since as I mentioned we
> don't
> > have a mapping defined.
> > If we agree on one we can add this and for all eMMC controllers that won't
> > follow it I guess we can
> > leave it to the platform code to override capabilities.
> >
> > >
> > >
> > > > + DriverStrength.Emmc = PreferedDriverStrength.Emmc;
> > > > + }
> > > > +
> > > > + return DriverStrength;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target settings for the bus mode.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > > + @param[out] BusMode Target configuration of the bus
> > > > +**/
> > > > +STATIC
> > > > +VOID
> > > > +EmmcGetTargetBusMode (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN EMMC_EXT_CSD *ExtCsd,
> > > > + OUT EDKII_SD_MMC_BUS_MODE *BusMode
> > > > + )
> > > > +{
> > > > + BusMode->BusTiming = EmmcGetTargetBusTiming (Private,
> SlotIndex,
> > > > ExtCsd);
> > > > + BusMode->BusWidth = EmmcGetTargetBusWidth (Private, SlotIndex,
> > > > ExtCsd, BusMode->BusTiming);
> > > > + BusMode->ClockFreq = EmmcGetTargetClockFreq (Private, SlotIndex,
> > > > ExtCsd, BusMode->BusTiming);
> > > > + BusMode->DriverStrength = EmmcGetTargetDriverStrength (Private,
> > > > SlotIndex, ExtCsd, BusMode->BusTiming);
> > > > }
> > > >
> > > > /**
> > > > @@ -983,10 +1265,7 @@ EmmcSetBusMode (
> > > > EFI_STATUS Status;
> > > > EMMC_CSD Csd;
> > > > EMMC_EXT_CSD ExtCsd;
> > > > - UINT8 HsTiming;
> > > > - BOOLEAN IsDdr;
> > > > - UINT32 ClockFreq;
> > > > - UINT8 BusWidth;
> > > > + EDKII_SD_MMC_BUS_MODE BusMode;
> > > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > >
> > > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > > @@ -1004,85 +1283,30 @@ EmmcSetBusMode (
> > > > }
> > > >
> > > > ASSERT (Private->BaseClkFreq[Slot] != 0);
> > > > +
> > > > //
> > > > - // Check if the Host Controller support 8bits bus width.
> > > > - //
> > > > - if (Private->Capability[Slot].BusWidth8 != 0) {
> > > > - BusWidth = 8;
> > > > - } else {
> > > > - BusWidth = 4;
> > > > - }
> > > > - //
> > > > - // Get Deivce_Type from EXT_CSD register.
> > > > + // Get Device_Type from EXT_CSD register.
> > > > //
> > > > Status = EmmcGetExtCsd (PassThru, Slot, &ExtCsd);
> > > > if (EFI_ERROR (Status)) {
> > > > DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetExtCsd fails
> > > with %r\n",
> > > > Status));
> > > > return Status;
> > > > }
> > > > - //
> > > > - // Calculate supported bus speed/bus width/clock frequency.
> > > > - //
> > > > - HsTiming = 0;
> > > > - IsDdr = FALSE;
> > > > - ClockFreq = 0;
> > > > - if (((ExtCsd.DeviceType & (BIT4 | BIT5)) != 0) && (Private-
> > > > >Capability[Slot].Sdr104 != 0)) {
> > > > - HsTiming = 2;
> > > > - IsDdr = FALSE;
> > > > - ClockFreq = 200;
> > > > - } else if (((ExtCsd.DeviceType & (BIT2 | BIT3)) != 0) && (Private-
> > > > >Capability[Slot].Ddr50 != 0)) {
> > > > - HsTiming = 1;
> > > > - IsDdr = TRUE;
> > > > - ClockFreq = 52;
> > > > - } else if (((ExtCsd.DeviceType & BIT1) != 0) && (Private-
> > > > >Capability[Slot].HighSpeed != 0)) {
> > > > - HsTiming = 1;
> > > > - IsDdr = FALSE;
> > > > - ClockFreq = 52;
> > > > - } else if (((ExtCsd.DeviceType & BIT0) != 0) && (Private-
> > > > >Capability[Slot].HighSpeed != 0)) {
> > > > - HsTiming = 1;
> > > > - IsDdr = FALSE;
> > > > - ClockFreq = 26;
> > > > - }
> > > > - //
> > > > - // Check if both of the device and the host controller support HS400
> > DDR
> > > > mode.
> > > > - //
> > > > - if (((ExtCsd.DeviceType & (BIT6 | BIT7)) != 0) && (Private-
> > > > >Capability[Slot].Hs400 != 0)) {
> > > > - //
> > > > - // The host controller supports 8bits bus.
> > > > - //
> > > > - ASSERT (BusWidth == 8);
> > > > - HsTiming = 3;
> > > > - IsDdr = TRUE;
> > > > - ClockFreq = 200;
> > > > - }
> > > >
> > > > - if ((ClockFreq == 0) || (HsTiming == 0)) {
> > > > - //
> > > > - // Continue using default setting.
> > > > - //
> > > > - return EFI_SUCCESS;
> > > > - }
> > > > + EmmcGetTargetBusMode (Private, Slot, &ExtCsd, &BusMode);
> > > >
> > > > - DEBUG ((DEBUG_INFO, "EmmcSetBusMode: HsTiming %d
> > ClockFreq %d
> > > > BusWidth %d Ddr %a\n", HsTiming, ClockFreq, BusWidth, IsDdr ?
> > > > "TRUE":"FALSE"));
> > > > + DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Target bus mode:
> timing
> > > > = %d, width = %d, clock freq = %d, driver strength = %d\n",
> > > > + BusMode.BusTiming, BusMode.BusWidth,
> > > BusMode.ClockFreq,
> > > > BusMode.DriverStrength.Emmc));
> > > >
> > > > - if (HsTiming == 3) {
> > > > - //
> > > > - // Execute HS400 timing switch procedure
> > > > - //
> > > > - Status = EmmcSwitchToHS400 (PciIo, PassThru, Slot, Rca, ClockFreq);
> > > > - } else if (HsTiming == 2) {
> > > > - //
> > > > - // Execute HS200 timing switch procedure
> > > > - //
> > > > - Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq,
> > > > BusWidth);
> > > > + if (BusMode.BusTiming == SdMmcMmcHs400) {
> > > > + Status = EmmcSwitchToHS400 (PciIo, PassThru, Slot, Rca,
> &BusMode);
> > > > + } else if (BusMode.BusTiming == SdMmcMmcHs200) {
> > > > + Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca,
> &BusMode);
> > > > } else {
> > > > - //
> > > > - // Execute High Speed timing switch procedure
> > > > - //
> > > > - Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca,
> > ClockFreq,
> > > > IsDdr, BusWidth);
> > > > + Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca,
> > > &BusMode);
> > > > }
> > > >
> > > > - DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n",
> > > (HsTiming
> > > > == 3) ? "HS400" : ((HsTiming == 2) ? "HS200" : "HighSpeed"), Status));
> > > > + DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n",
> > > > (BusMode.BusTiming == SdMmcMmcHs400) ? "HS400" :
> > > > ((BusMode.BusTiming == SdMmcMmcHs200) ? "HS200" : "HighSpeed"),
> > > > Status));
> > > >
> > > > return Status;
> > > > }
> > > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > > index 17936a5492..36d2b487df 100644
> > > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > > @@ -313,10 +313,6 @@ SdCardSetRca (
> > > > return Status;
> > > > }
> > > >
> > > > -
> > > > -
> > > > -
> > > > -
> > > > /**
> > > > Send command SELECT_DESELECT_CARD to the SD device to
> > > > select/deselect it.
> > > >
> > > > @@ -422,7 +418,7 @@ SdCardSetBusWidth (
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > - IN UINT8 BusWidth
> > > > + IN UINT16 BusWidth
> > > > )
> > > > {
> > > > EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
> > > > @@ -476,7 +472,7 @@ SdCardSetBusWidth (
> > > > @param[in] Slot The slot number of the SD card to send the
> > > command
> > > > to.
> > > > @param[in] AccessMode The value for access mode group.
> > >
> > >
> > > Please help to update the parameter comment to reflect the function
> > > interface changes.
> > >
> > >
> > > > @param[in] CommandSystem The value for command set group.
> > > > - @param[in] DriveStrength The value for drive length group.
> > > > + @param[in] DriveStrength The value for driver strength group.
> > >
> > >
> > > Please help to update the parameter name in the above comment from
> > > 'DriveStrength' to 'DriverStrength'.
> > >
> > >
> > > > @param[in] PowerLimit The value for power limit group.
> > > > @param[in] Mode Switch or check function.
> > > > @param[out] SwitchResp The return switch function status.
> > > > @@ -489,9 +485,9 @@ EFI_STATUS
> > > > SdCardSwitch (
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > - IN UINT8 AccessMode,
> > > > + IN SD_MMC_BUS_MODE BusTiming,
> > > > IN UINT8 CommandSystem,
> > > > - IN UINT8 DriveStrength,
> > > > + IN SD_DRIVER_STRENGTH_TYPE DriverStrength,
> > > > IN UINT8 PowerLimit,
> > > > IN BOOLEAN Mode,
> > > > OUT UINT8 *SwitchResp
> > > > @@ -502,6 +498,7 @@ SdCardSwitch (
> > > > EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
> > > > EFI_STATUS Status;
> > > > UINT32 ModeValue;
> > > > + UINT8 AccessMode;
> > > >
> > > > ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
> > > > ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
> > > > @@ -516,8 +513,31 @@ SdCardSwitch (
> > > > SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
> > > >
> > > > ModeValue = Mode ? BIT31 : 0;
> > > > - SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) |
> > > ((PowerLimit
> > > > & 0xF) << 4) | \
> > > > - ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF)
> <<
> > > 12)
> > > > | \
> > > > +
> > > > + switch (BusTiming) {
> > > > + case SdMmcUhsDdr50:
> > > > + AccessMode = 0x4;
> > > > + break;
> > > > + case SdMmcUhsSdr104:
> > > > + AccessMode = 0x3;
> > > > + break;
> > > > + case SdMmcUhsSdr50:
> > > > + AccessMode = 0x2;
> > > > + break;
> > > > + case SdMmcUhsSdr25:
> > > > + case SdMmcSdHs:
> > > > + AccessMode = 0x1;
> > > > + break;
> > > > + case SdMmcUhsSdr12:
> > > > + case SdMmcSdDs:
> > > > + AccessMode = 0;
> > > > + break;
> > > > + default:
> > > > + AccessMode = 0xF;
> > > > + }
> > > > +
> > > > + SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) |
> > > > ((CommandSystem & 0xF) << 4) | \
> > > > + ((DriverStrength & 0xF) << 8) | ((PowerLimit & 0xF) <<
> > 12)
> > > |
> > > > \
> > > > ModeValue;
> > > >
> > > > Packet.InDataBuffer = SwitchResp;
> > > > @@ -718,7 +738,7 @@ SdCardSwitchBusWidth (
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > - IN UINT8 BusWidth
> > > > + IN UINT16 BusWidth
> > > > )
> > > > {
> > > > EFI_STATUS Status;
> > > > @@ -748,6 +768,261 @@ SdCardSwitchBusWidth (
> > > > return Status;
> > > > }
> > > >
> > > > +/**
> > > > + Check if passed BusTiming is supported in both controller and card.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] CardSupportedBusTimings Bitmask indicating which bus
> > > > timings are supported by card
> > > > + @param[in] IsInUhsI Flag indicating if link is in UHS-I
> > > > +
> > > > + @retval TRUE Both card and controller support given BusTiming
> > > > + @retval FALSE Card or controller doesn't support given BusTiming
> > > > +**/
> > > > +STATIC
> > > > +BOOLEAN
> > > > +SdIsBusTimingSupported (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN UINT8 CardSupportedBusTimings,
> > > > + IN BOOLEAN IsInUhsI,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + SD_MMC_HC_SLOT_CAP *Capability;
> > > > +
> > > > + Capability = &Private->Capability[SlotIndex];
> > > > +
> > > > + if (IsInUhsI) {
> > > > + switch (BusTiming) {
> > >
> > >
> > > Please help to add a 'default' handle for this 'switch' statement, the
> > > proposed
> > > code will cause a GCC5 build failure.
> > >
> > >
> > > > + case SdMmcUhsSdr104:
> > > > + if (Capability->Sdr104 && ((CardSupportedBusTimings & BIT3) != 0))
> > {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcUhsDdr50:
> > > > + if (Capability->Ddr50 && ((CardSupportedBusTimings & BIT4) != 0))
> {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcUhsSdr50:
> > > > + if (Capability->Sdr50 && ((CardSupportedBusTimings & BIT2) != 0))
> {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcUhsSdr25:
> > > > + if ((CardSupportedBusTimings & BIT1) != 0) {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcUhsSdr12:
> > > > + if ((CardSupportedBusTimings & BIT0) != 0) {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + }
> > > > + } else {
> > > > + switch (BusTiming) {
> > >
> > >
> > > Please help to add a 'default' handle for this 'switch' statement, the
> > > proposed
> > > code will cause a GCC5 build failure.
> > >
> > >
> > > > + case SdMmcSdHs:
> > > > + if (Capability->HighSpeed && (CardSupportedBusTimings &
> BIT1) !=
> > 0)
> > > {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcSdDs:
> > > > + if ((CardSupportedBusTimings & BIT0) != 0) {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + }
> > > > + }
> > > > +
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target bus timing to set on the link. This function
> > > > + will try to select highest bus timing supported by card, controller
> > > > + and the driver.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] CardSupportedBusTimings Bitmask indicating which bus
> > > > timings are supported by card
> > > > + @param[in] IsInUhsI Flag indicating if link is in UHS-I
> > > > +
> > > > + @return Bus timing value that should be set on link
> > > > +**/
> > > > +STATIC
> > > > +SD_MMC_BUS_MODE
> > > > +SdGetTargetBusTiming (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN UINT8 CardSupportedBusTimings,
> > > > + IN BOOLEAN IsInUhsI
> > > > + )
> > > > +{
> > > > + SD_MMC_BUS_MODE BusTiming;
> > > > +
> > > > + if (IsInUhsI) {
> > > > + BusTiming = SdMmcUhsSdr104;
> > > > + } else {
> > > > + BusTiming = SdMmcSdHs;
> > > > + }
> > > > +
> > > > + while (BusTiming > SdMmcSdDs) {
> > > > + if (SdIsBusTimingSupported (Private, SlotIndex,
> > > > CardSupportedBusTimings, IsInUhsI, BusTiming)) {
> > > > + break;
> > > > + }
> > > > + BusTiming--;
> > > > + }
> > >
> > >
> > > The origin logic has the below preference when selecting bus timing
> > > (if supported):
> > >
> > > SdMmcUhsSdr104
> > > SdMmcUhsSdr50
> > > SdMmcUhsDdr50
> > > SdMmcUhsSdr25
> > > SdMmcUhsSdr12
> > >
> > > So we need to reorder the types in 'SD_MMC_BUS_MODE' to:
> > >
> > > typedef enum {
> > > SdMmcSdDs,
> > > SdMmcSdHs,
> > > SdMmcUhsSdr12,
> > > SdMmcUhsSdr25,
> > > SdMmcUhsDdr50,
> > > SdMmcUhsSdr50,
> > > SdMmcUhsSdr104,
> > > ...
> > > } SD_MMC_BUS_MODE;
> > >
> > > Otherwise, the Ddr50 mode will never be selected.
> > >
> > >
> > > > +
> > > > + return BusTiming;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target bus width to be set on the bus.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] BusTiming Bus timing set on the bus
> > > > +
> > > > + @return Bus width to be set on the bus
> > > > +**/
> > > > +STATIC
> > > > +UINT16
> > > > +SdGetTargetBusWidth (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + UINT16 BusWidth;
> > > > + UINT16 PreferedBusWidth;
> > > > +
> > > > + PreferedBusWidth = Private-
> > > > >Slot[SlotIndex].OperatingParameters.BusWidth;
> > > > +
> > > > + if (BusTiming == SdMmcSdDs || BusTiming == SdMmcSdHs) {
> > > > + if (PreferedBusWidth != EDKII_SD_MMC_BUS_WIDTH_IGNORE) {
> > > > + BusWidth = PreferedBusWidth;
> > >
> > >
> > > The supported bus width is either 1 or 4 bit for 3.3V signal cards.
> > > I think we need a more strict check here.
> > >
> > >
> > > > + } else {
> > > > + BusWidth = 4;
> > > > + }
> > > > + } else {
> > > > + //
> > > > + // UHS-I modes support only 4-bit width.
> > > > + // Switch to 4-bit has been done before calling this function anyway
> so
> > > > + // this is purely informational.
> > > > + //
> > > > + BusWidth = 4;
> > > > + }
> > > > +
> > > > + return BusWidth;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target clock frequency to be set on the bus.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] BusTiming Bus timing to be set on the bus
> > > > +
> > > > + @return Value of the clock frequency to be set on bus in MHz
> > > > +**/
> > > > +STATIC
> > > > +UINT32
> > > > +SdGetTargetBusClockFreq (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + UINT32 PreferedClockFreq;
> > > > + UINT32 MaxClockFreq;
> > > > +
> > > > + PreferedClockFreq = Private-
> > > > >Slot[SlotIndex].OperatingParameters.ClockFreq;
> > > > +
> > > > + switch (BusTiming) {
> > > > + case SdMmcUhsSdr104:
> > > > + MaxClockFreq = 208;
> > > > + break;
> > > > + case SdMmcUhsSdr50:
> > > > + MaxClockFreq = 100;
> > > > + break;
> > > > + case SdMmcUhsDdr50:
> > > > + case SdMmcUhsSdr25:
> > > > + case SdMmcSdHs:
> > > > + MaxClockFreq = 50;
> > > > + break;
> > > > + case SdMmcUhsSdr12:
> > > > + case SdMmcSdDs:
> > > > + default:
> > > > + MaxClockFreq = 25;
> > >
> > >
> > > Minor comment, need an extra space for the above line.
> > >
> > >
> > > > + }
> > > > +
> > > > + if (PreferedClockFreq != EDKII_SD_MMC_CLOCK_FREQ_IGNORE &&
> > > > PreferedClockFreq < MaxClockFreq) {
> > > > + return PreferedClockFreq;
> > > > + } else {
> > > > + return MaxClockFreq;
> > > > + }
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the driver strength to be set on bus
> > >
> > >
> > > Please help to append a '.' character for the above line.
> > > It is required for the edk2 coding style.
> > >
> > >
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] CardSupportedDriverStrengths Bitmask indicating which
> > > > driver strengths are supported on the card
> > > > + @param[in] BusTiming Bus timing set on the bus
> > > > +
> > > > + @return Value of the driver strength to be set on the bus
> > > > +**/
> > > > +STATIC
> > > > +EDKII_SD_MMC_DRIVER_STRENGTH
> > > > +SdGetTargetDriverStrength (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN UINT8 CardSupportedDriverStrengths,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > >
> > >
> > > One question here, the driver strength configuration is only for UHS-I
> cards.
> > > Does the check on 'CardSupportedDriverStrengths' enough to ensure the
> > > above
> > > requirement or a boolean input parameter 'IsInUhsI' is needed here?
> > >
> >
> > I think we can leave it to the code that actually sets the bus parameters
> > to simply skip driver strength programming for legacy and select driver
> > strength here
> > based only on HW support and platform preference. The alternative is to
> > return
> > SdDriverStrengthIgnore here and handle that in code that actually sets
> driver
> > strength.
> >
> > >
> > > > +{
> > > > + EDKII_SD_MMC_DRIVER_STRENGTH PreferedDriverStrength;
> > > > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > > > +
> > > > + PreferedDriverStrength = Private-
> > > > >Slot[SlotIndex].OperatingParameters.DriverStrength;
> > > > + DriverStrength.Sd = SdDriverStrengthTypeB;
> > > > +
> > > > + if (PreferedDriverStrength.Sd !=
> > > > EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE &&
> > > > + (CardSupportedDriverStrengths & (BIT0 <<
> > > PreferedDriverStrength.Sd)))
> > >
> > >
> > > The host controller also has a capability for different types of driver
> > strength.
> > > (Capabilities Register, bit 36~38)
> > >
> > > The check should take it into consideration as well.
> > >
> > >
> > > > {
> > > > + DriverStrength.Sd = PreferedDriverStrength.Sd;
> > > > + }
> > > > +
> > > > + return DriverStrength;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target settings for the bus mode.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] SwitchQueryResp Pointer to switch query response
> > > > + @param[in] IsInUhsI Flag indicating if link is in UHS-I mode
> > > > + @param[out] BusMode Target configuration of the bus
> > > > +**/
> > > > +STATIC
> > > > +VOID
> > > > +SdGetTargetBusMode (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN UINT8 *SwitchQueryResp,
> > > > + IN BOOLEAN IsInUhsI,
> > > > + OUT EDKII_SD_MMC_BUS_MODE *BusMode
> > > > + )
> > > > +{
> > > > + BusMode->BusTiming = SdGetTargetBusTiming (Private, SlotIndex,
> > > > SwitchQueryResp[13], IsInUhsI);
> > > > + BusMode->BusWidth = SdGetTargetBusWidth (Private, SlotIndex,
> > > > BusMode->BusTiming);
> > > > + BusMode->ClockFreq = SdGetTargetBusClockFreq (Private, SlotIndex,
> > > > BusMode->BusTiming);
> > > > + BusMode->DriverStrength = SdGetTargetDriverStrength (Private,
> > > > SlotIndex, SwitchQueryResp[9], BusMode->BusTiming);
> > > > +}
> > > > +
> > > > /**
> > > > Switch the high speed timing according to request.
> > > >
> > > > @@ -775,13 +1050,10 @@ SdCardSetBusMode (
> > > > {
> > > > EFI_STATUS Status;
> > > > SD_MMC_HC_SLOT_CAP *Capability;
> > > > - UINT32 ClockFreq;
> > > > - UINT8 BusWidth;
> > > > - UINT8 AccessMode;
> > > > UINT8 HostCtrl1;
> > > > UINT8 SwitchResp[64];
> > > > - SD_MMC_BUS_MODE Timing;
> > > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > > + EDKII_SD_MMC_BUS_MODE BusMode;
> > > >
> > > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > >
> > > > @@ -792,61 +1064,46 @@ SdCardSetBusMode (
> > > > return Status;
> > > > }
> > > >
> > > > - BusWidth = 4;
> > > > -
> > > > - Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, BusWidth);
> > > > - if (EFI_ERROR (Status)) {
> > > > - return Status;
> > > > + if (S18A) {
> > > > + //
> > > > + // For UHS-I speed modes 4-bit data bus is requiered so we
> > > > + // switch here irrespective of platform preference.
> > > > + //
> > > > + Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, 4);
> > > > + if (EFI_ERROR (Status)) {
> > > > + return Status;
> > > > + }
> > > > }
> > > > +
> > > > //
> > > > // Get the supported bus speed from SWITCH cmd return data group
> #1.
> > > > //
> > > > - Status = SdCardSwitch (PassThru, Slot, 0xF, 0xF, 0xF, 0xF, FALSE,
> > > > SwitchResp);
> > > > + Status = SdCardSwitch (PassThru, Slot, 0xFF, 0xF,
> > SdDriverStrengthIgnore,
> > > > 0xF, FALSE, SwitchResp);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > - //
> > > > - // Calculate supported bus speed/bus width/clock frequency by host
> > and
> > > > device capability.
> > > > - //
> > > > - ClockFreq = 0;
> > > > - if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) !=
> 0))
> > {
> > > > - ClockFreq = 208;
> > > > - AccessMode = 3;
> > > > - Timing = SdMmcUhsSdr104;
> > > > - } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] &
> > BIT2) !=
> > > 0))
> > > > {
> > > > - ClockFreq = 100;
> > > > - AccessMode = 2;
> > > > - Timing = SdMmcUhsSdr50;
> > > > - } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] &
> > BIT4) !=
> > > > 0)) {
> > > > - ClockFreq = 50;
> > > > - AccessMode = 4;
> > > > - Timing = SdMmcUhsDdr50;
> > > > - } else if ((SwitchResp[13] & BIT1) != 0) {
> > > > - ClockFreq = 50;
> > > > - AccessMode = 1;
> > > > - Timing = SdMmcUhsSdr25;
> > > > - } else {
> > > > - ClockFreq = 25;
> > > > - AccessMode = 0;
> > > > - Timing = SdMmcUhsSdr12;
> > > > +
> > > > + SdGetTargetBusMode (Private, Slot, SwitchResp, S18A, &BusMode);
> > > > +
> > > > + DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Target bus mode: bus
> > > timing
> > > > = %d, bus width = %d, clock freq[MHz] = %d, driver strength = %d\n",
> > > > + BusMode.BusTiming, BusMode.BusWidth,
> > > BusMode.ClockFreq,
> > > > BusMode.DriverStrength.Sd));
> > > > +
> > > > + if (!S18A) {
> > > > + Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca,
> > > > BusMode.BusWidth);
> > > > + if (EFI_ERROR (Status)) {
> > > > + return Status;
> > > > + }
> > > > }
> > >
> > >
> > > Is it feasible to set the bus width for the 3.3V signaled cards & the UHS-I
> > > cards together here? I think the SdGetTargetBusWidth() already handles
> > the
> > > UHS-I cards case well by always setting the bus width to 4.
> > >
> >
> > So basically to skip if (!S18A) condition and do bus width switch
> > unconditionally?
> > I am not sure how the bus will react to additional bus width switch for UHS-I
> > case
> > and I am not able to test it locally as I only have controller with legacy
> support
> > available for tests.
> > I guess I will give it a try and we will revert it if it causes any problems.
> >
> > >
> > > >
> > > > - Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF,
> TRUE,
> > > > SwitchResp);
> > > > + Status = SdCardSwitch (PassThru, Slot, BusMode.BusTiming, 0xF,
> > > > BusMode.DriverStrength.Sd, 0xF, TRUE, SwitchResp);
> > >
> > >
> > > After the proposed change, the preferred bus timing and driver strength
> > > value
> > > will be set for the device through the SD_SWITCH command.
> > >
> > > However, on the host controller side, only the bus timing value is also
> > > updated
> > > in the Host Control 2 Register of the SD HC (via function
> > > SdMmcHcUhsSignaling()).
> > > It seems to me that the driver strength value does not get updated in this
> > > register.
> > >
> > > I think the eMMC case has a similar issue.
> > >
> > >
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > >
> > > > - if ((SwitchResp[16] & 0xF) != AccessMode) {
> > > > - DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: Switch to
> > > AccessMode %d
> > > > ClockFreq %d BusWidth %d fails! The Switch response is 0x%1x\n",
> > > > AccessMode, ClockFreq, BusWidth, SwitchResp[16] & 0xF));
> > > > - return EFI_DEVICE_ERROR;
> > > > - }
> > >
> > >
> > > The above check may still be needed. Also, the whether the target driver
> > > strength is successfully set needs to be checked as well.
> > >
> > > How about adding checks in function SdCardSwitch() for mode 1 of the
> > > switch
> > > command?
> > >
> > >
> > > > -
> > > > - DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Switch to
> > AccessMode %d
> > > > ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));
> > > > -
> > > > //
> > > > - // Set to Hight Speed timing
> > > > + // Set to High Speed timing
> > > > //
> > > > - if (AccessMode == 1) {
> > > > + if (BusMode.BusTiming == SdMmcSdHs) {
> > > > HostCtrl1 = BIT2;
> > > > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1,
> > > sizeof
> > > > (HostCtrl1), &HostCtrl1);
> > > > if (EFI_ERROR (Status)) {
> > > > @@ -854,12 +1111,12 @@ SdCardSetBusMode (
> > > > }
> > > > }
> > > >
> > > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > > Timing);
> > > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo,
> Slot,
> > > > BusMode.BusTiming);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > >
> > > > - Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> > > > >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> > > > + Status = SdMmcHcClockSupply (PciIo, Slot, BusMode.ClockFreq *
> 1000,
> > > > Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > @@ -869,7 +1126,7 @@ SdCardSetBusMode (
> > > > Private->ControllerHandle,
> > > > Slot,
> > > > EdkiiSdMmcSwitchClockFreqPost,
> > > > - &Timing
> > > > + &BusMode.BusTiming
> > > > );
> > > > if (EFI_ERROR (Status)) {
> > > > DEBUG ((
> > > > @@ -882,7 +1139,7 @@ SdCardSetBusMode (
> > > > }
> > > > }
> > > >
> > > > - if ((AccessMode == 3) || ((AccessMode == 2) && (Capability-
> > > > >TuningSDR50 != 0))) {
> > > > + if ((BusMode.BusTiming == SdMmcUhsSdr104) ||
> > ((BusMode.BusTiming
> > > > == SdMmcUhsSdr50) && (Capability->TuningSDR50 != 0))) {
> > > > Status = SdCardTuningClock (PciIo, PassThru, Slot);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > @@ -1025,10 +1282,8 @@ SdCardIdentification (
> > > > // (One of support bits is set to 1: SDR50, SDR104 or DDR50 in the
> > > > // Capabilities register), switch its voltage to 1.8V.
> > > > //
> > > > - if ((Private->Capability[Slot].Sdr50 != 0 ||
> > > > - Private->Capability[Slot].Sdr104 != 0 ||
> > > > - Private->Capability[Slot].Ddr50 != 0) &&
> > > > - ((Ocr & BIT24) != 0)) {
> > > > + if ((Private->Capability[Slot].Sdr50 || Private->Capability[Slot].Ddr50
> ||
> > > > Private->Capability[Slot].Sdr104) &&
> > > > + ((Ocr & BIT24) != 0)) {
> > >
> > >
> > > Minor comment, for:
> > > Private->Capability[Slot].Sdr50
> > > Private->Capability[Slot].Ddr50
> > > Private->Capability[Slot].Sdr104
> > >
> > > They are of type UINT32, should use operators '==' or '!=' in condition
> > > statement. I think the origin logic is good here.
> > >
> > >
> > > > Status = SdCardVoltageSwitch (PassThru, Slot);
> > > > if (EFI_ERROR (Status)) {
> > > > DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing
> > > > SdCardVoltageSwitch fails with %r\n", Status));
> > > > diff --git
> a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > > index 4881ee44cc..8f49954b7f 100644
> > > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > > @@ -28,6 +28,11 @@ EFI_DRIVER_BINDING_PROTOCOL
> > > > gSdMmcPciHcDriverBinding = {
> > > > NULL
> > > > };
> > > >
> > > > +#define SLOT_INIT_TEMPLATE {0, UnknownSlot, 0, 0, 0, \
> > > > + {EDKII_SD_MMC_BUS_WIDTH_IGNORE,\
> > > > + EDKII_SD_MMC_CLOCK_FREQ_IGNORE,\
> > > > + EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE}}
> > >
> > >
> > > Please help to update the above definition to:
> > > #define SLOT_INIT_TEMPLATE {0, UnknownSlot, 0, 0, 0, \
> > > {EDKII_SD_MMC_BUS_WIDTH_IGNORE,\
> > > EDKII_SD_MMC_CLOCK_FREQ_IGNORE,\
> > > {EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE}}}
> > >
> > > The proposed one will cause GCC5 build failure.
> > >
> > >
> > > > +
> > > > //
> > > > // Template for SD/MMC host controller private data.
> > > > //
> > > > @@ -50,8 +55,12 @@ SD_MMC_HC_PRIVATE_DATA
> > > gSdMmcPciHcTemplate
> > > > = {
> > > > // Queue
> > > > INITIALIZE_LIST_HEAD_VARIABLE (gSdMmcPciHcTemplate.Queue),
> > > > { // Slot
> > > > - {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot,
> 0,
> > 0,
> > > > 0},
> > > > - {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot,
> 0,
> > 0,
> > > > 0}
> > > > + SLOT_INIT_TEMPLATE,
> > > > + SLOT_INIT_TEMPLATE,
> > > > + SLOT_INIT_TEMPLATE,
> > > > + SLOT_INIT_TEMPLATE,
> > > > + SLOT_INIT_TEMPLATE,
> > > > + SLOT_INIT_TEMPLATE
> > > > },
> > > > { // Capability
> > > > {0},
> > > > @@ -328,6 +337,7 @@ SdMmcPciHcEnumerateDevice (
> > > >
> > > > return;
> > > > }
> > > > +
> > > > /**
> > > > Tests to see if this driver supports a given controller. If a child device is
> > > > provided,
> > > > it further tests to see if this driver supports creating a handle for the
> > > > specified child device.
> > > > @@ -619,7 +629,6 @@ SdMmcPciHcDriverBindingStart (
> > > > Support64BitDma = TRUE;
> > > > for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
> > > > Private->Slot[Slot].Enable = TRUE;
> > > > -
> > > > //
> > > > // Get SD/MMC Pci Host Controller Version
> > > > //
> > > > @@ -635,19 +644,34 @@ SdMmcPciHcDriverBindingStart (
> > > >
> > > > Private->BaseClkFreq[Slot] = Private->Capability[Slot].BaseClkFreq;
> > > >
> > > > - if (mOverride != NULL && mOverride->Capability != NULL) {
> > > > - Status = mOverride->Capability (
> > > > - Controller,
> > > > - Slot,
> > > > - &Private->Capability[Slot],
> > > > - &Private->BaseClkFreq[Slot]
> > > > - );
> > > > - if (EFI_ERROR (Status)) {
> > > > - DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",
> > > > - __FUNCTION__, Status));
> > > > - continue;
> > > > + if (mOverride != NULL) {
> > > > + if (mOverride->Capability != NULL) {
> > > > + Status = mOverride->Capability (
> > > > + Controller,
> > > > + Slot,
> > > > + &Private->Capability[Slot],
> > > > + &Private->BaseClkFreq[Slot]
> > > > + );
> > > > + if (EFI_ERROR (Status)) {
> > > > + DEBUG ((DEBUG_WARN, "%a: Failed to override capability -
> %r\n",
> > > > + __FUNCTION__, Status));
> > > > + continue;
> > > > + }
> > > > + }
> > > > +
> > > > + if (mOverride->NotifyPhase != NULL) {
> > > > + Status = mOverride->NotifyPhase (
> > > > + Controller,
> > > > + Slot,
> > > > + EdkiiSdMmcGetOperatingParam,
> > > > + (VOID*)&Private->Slot[Slot].OperatingParameters
> > > > + );
> > > > + if (EFI_ERROR (Status)) {
> > > > + DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters,
> > > > using defaults\n" __FUNCTION__));
> > >
> > >
> > > Please update the above line to (missed one ',' before '__FUNCTION__'):
> > > DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters, using
> > > defaults\n", __FUNCTION__));
> > >
> > > It will cause GCC5 build failure for the proposed change.
> > >
> > >
> > > > + }
> > > > }
> > > > }
> > > > +
> > > > DumpCapabilityReg (Slot, &Private->Capability[Slot]);
> > > > DEBUG ((
> > > > DEBUG_INFO,
> > > > diff --git
> a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > > index 77bbf83b76..b768f3942f 100644
> > > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > > @@ -78,11 +78,12 @@ typedef enum {
> > > > } EFI_SD_MMC_SLOT_TYPE;
> > > >
> > > > typedef struct {
> > > > - BOOLEAN Enable;
> > > > - EFI_SD_MMC_SLOT_TYPE SlotType;
> > > > - BOOLEAN MediaPresent;
> > > > - BOOLEAN Initialized;
> > > > - SD_MMC_CARD_TYPE CardType;
> > > > + BOOLEAN Enable;
> > > > + EFI_SD_MMC_SLOT_TYPE SlotType;
> > > > + BOOLEAN MediaPresent;
> > > > + BOOLEAN Initialized;
> > > > + SD_MMC_CARD_TYPE CardType;
> > > > + EDKII_SD_MMC_OPERATING_PARAMETERS OperatingParameters;
> > > > } SD_MMC_HC_SLOT;
> > > >
> > > > typedef struct {
> > > > @@ -120,6 +121,13 @@ typedef struct {
> > > > UINT32 BaseClkFreq[SD_MMC_HC_MAX_SLOT];
> > > > } SD_MMC_HC_PRIVATE_DATA;
> > > >
> > > > +typedef struct {
> > > > + EDKII_SD_MMC_BUS_TIMING BusTiming;
> > >
> > >
> > > Should be:
> > > SD_MMC_BUS_MODE BusTiming;
> > >
> > >
> > > > + UINT16 BusWidth;
> > > > + UINT32 ClockFreq;
> > > > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > > > +} EDKII_SD_MMC_BUS_MODE;
> > >
> > >
> > > Since the above structure is a driver internal one, I prefer dropping the
> > > prefix 'EDKII_'. But unfortunately, SD_MMC_BUS_MODE is already used
> in
> > > Protocol/SdMmcOverride.h, so how about SD_MMC_BUS_SETTINGS?
> > >
> > >
> > > > +
> > > > #define SD_MMC_HC_TRB_SIG SIGNATURE_32 ('T', 'R', 'B', 'T')
> > > >
> > > > //
> > > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > > index 5d1f977e55..863ae3db34 100644
> > > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > > @@ -1263,10 +1263,10 @@ SdMmcHcInitHost (
> > > > **/
> > > > EFI_STATUS
> > > > SdMmcHcUhsSignaling (
> > > > - IN EFI_HANDLE ControllerHandle,
> > > > - IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > > - IN UINT8 Slot,
> > > > - IN SD_MMC_BUS_MODE Timing
> > > > + IN EFI_HANDLE ControllerHandle,
> > > > + IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > > + IN UINT8 Slot,
> > > > + IN SD_MMC_BUS_MODE Timing
> > > > )
> > >
> > >
> > > I think the changes made here (space indentation) can be dropped.
> > >
> > >
> > > > {
> > > > EFI_STATUS Status;
> > > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > > index 0b0d415256..c4d4aef73a 100644
> > > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > > @@ -611,10 +611,10 @@ SdMmcHcInitTimeoutCtrl (
> > > > **/
> > > > EFI_STATUS
> > > > SdMmcHcUhsSignaling (
> > > > - IN EFI_HANDLE ControllerHandle,
> > > > - IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > > - IN UINT8 Slot,
> > > > - IN SD_MMC_BUS_MODE Timing
> > > > + IN EFI_HANDLE ControllerHandle,
> > > > + IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > > + IN UINT8 Slot,
> > > > + IN SD_MMC_BUS_MODE Timing
> > >
> > >
> > > I think the changes made here (space indentation) can be dropped.
> > >
> > > Best Regards,
> > > Hao Wu
> > >
> > >
> > > > );
> > > >
> > > > #endif
> > > > --
> > > > 2.14.1.windows.1
> >
> > --------------------------------------------------------------------
> >
> > Intel Technology Poland sp. z o.o.
> > ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII
> > Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP
> 957-
> > 07-52-316 | Kapital zakladowy 200.000 PLN.
> >
> > Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego
> > adresata i moze zawierac informacje poufne. W razie przypadkowego
> > otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale
> > jej usuniecie; jakiekolwiek
> > przegladanie lub rozpowszechnianie jest zabronione.
> > This e-mail and any attachments may contain confidential material for the
> > sole use of the intended recipient(s). If you are not the intended recipient,
> > please contact the sender and delete all copies; any review or distribution
> by
> > others is strictly prohibited.
> >
> >
> >
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement revision 3 of SdMmcOverrideProtocol
2019-06-14 3:14 ` Wu, Hao A
@ 2019-06-18 15:14 ` Albecki, Mateusz
0 siblings, 0 replies; 9+ messages in thread
From: Albecki, Mateusz @ 2019-06-18 15:14 UTC (permalink / raw)
To: Wu, Hao A, devel@edk2.groups.io, mw@semihalf.com
Response inline to the bus width switch before SWITCH command in UHS-I mode. As I mentioned in forked message mapping SD driver strength to eMMC driver strength seems like a bad idea right now as I don't know of any eMMC host controller that would actually follow this map and would require any host programming.
Thanks,
Mateusz
> -----Original Message-----
> From: Wu, Hao A
> Sent: Friday, June 14, 2019 5:15 AM
> To: Albecki, Mateusz <mateusz.albecki@intel.com>; devel@edk2.groups.io;
> mw@semihalf.com
> Subject: RE: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement revision
> 3 of SdMmcOverrideProtocol
>
> > -----Original Message-----
> > From: Albecki, Mateusz
> > Sent: Thursday, June 13, 2019 10:39 PM
> > To: devel@edk2.groups.io
> > Cc: Wu, Hao A
> > Subject: RE: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement
> revision
> > 3 of SdMmcOverrideProtocol
> >
> > Resending to group. Inline reply to some of the comments.
> >
> > As for the mapping between eMMC driver strength and SD controller
> driver
> > strength should we use this one:
> >
> > SD controller -> eMMC card
> > B -> Type 0
> > A -> Type 1
> > C -> Type 2
> > D -> Type 3
> > (none) -> Type4
>
>
> Yes, I think this matching is fine. Inspecting the SD & eMMC specs:
>
> For SD Physical Layer Specification:
> Driver Type Nominal Driving
> Impedance Capability
> A 33Ω x1.5
> B 50Ω x1
> C 66Ω x0.75
> D 100Ω x0.5
>
> For Embedded Multi-Media Card (e.MMC) Electrical Standard:
> Driver Type Nominal Approximated driver capability
> Values Impedance compared to Type-0
> 0x0 50Ω x1
> 0x1 33Ω x1.5
> 0x2 66Ω x0.75
> 0x3 100Ω x0.5
> 0x4 40Ω x1.2
>
> The above mapping is consistent with regard to the Nominal Impedance &
> Driving Capability parameters.
>
>
> >
> > And Type 4 would be identified by bit 39 in capability register which is
> > currently marked as reserved in SD controller specification. This is current
> > capability register definition in the driver.
>
>
> I am not sure if the bit39 in the capability register works for all SD
> host controller (because it is not documented in specs, as far as I know).
> I suggest we just ignore the HC capability when setting driver strength
> type 4 for eMMC devices.
>
> Response to other inline comments below:
>
>
> >
> > Thanks,
> > Mateusz
> >
> > > -----Original Message-----
> > > From: Wu, Hao A
> > > Sent: Monday, June 10, 2019 5:19 AM
> > > To: Albecki, Mateusz <mateusz.albecki@intel.com>
> > > Subject: RE: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement
> > revision
> > > 3 of SdMmcOverrideProtocol
> > >
> > > Hello Mateusz,
> > >
> > > Some inline comments below:
> > >
> > > > -----Original Message-----
> > > > From: Albecki, Mateusz
> > > > Sent: Monday, June 03, 2019 7:34 PM
> > > > Cc: Albecki, Mateusz; Wu, Hao A; Albecki
> > > > Subject: [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement
> revision
> > 3
> > > > of SdMmcOverrideProtocol
> > > >
> > > > Implement support for GetOperatingParamters notify phase
> > > > in SdMmcHcDxe driver. GetOperatingParameters notify phase
> > > > is signaled before we start card detection and initialization.
> > > > Code has been updated for both eMMC and SD card controllers to
> > > > take into consideration those new parameters. Initialization process
> > > > has been divided into 2 steps. In the first step we bring the link
> > > > up to the point where we can get card identification data(Extended
> > > > CSD in eMMC case and SWITCH command response in SD card case).
> This
> > > > data is later used along with controller capabilities and operating
> > > > parameters passed in GetOperatingParameters phase to choose
> > preferred
> > > > bus settings in GetTargetBusSettings function. Those settings are later
> > > > on to start bus training to high speeds. If user passes incompatible
> > > > setting with selected bus timing driver will assume it's standard
> behavior
> > > with
> > > > respect to that setting. For instance if HS400 has been selected as a
> > > > target bus timing due to card and controller support bus width setting
> of
> > > > 4 and 1 bit won't be respected and 8 bit setting will be chosen instead.
> > > >
> > > >
> > > > Cc: hao.a.wu@intel.com
> > > > Signed-off-by: Albecki, Mateusz <mateusz.albecki@intel.com>
> > > > Contributed-under: TianoCore Contribution Agreement 1.1
> > > > ---
> > > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c | 522
> > > > +++++++++++++++------
> > > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c | 381
> > > > ++++++++++++---
> > > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c | 52 +-
> > > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h | 18 +-
> > > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c | 8 +-
> > > > MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h | 8 +-
> > > > 6 files changed, 750 insertions(+), 239 deletions(-)
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > > index deaf4468c9..1a81f6d250 100644
> > > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
> > > > @@ -449,7 +449,7 @@ EFI_STATUS
> > > > EmmcSendTuningBlk (
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > - IN UINT8 BusWidth
> > > > + IN UINT16 BusWidth
> > > > )
> > > > {
> > > > EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
> > > > @@ -506,7 +506,7 @@ EmmcTuningClkForHs200 (
> > > > IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > - IN UINT8 BusWidth
> > > > + IN UINT16 BusWidth
> > > > )
> > > > {
> > > > EFI_STATUS Status;
> > > > @@ -583,7 +583,7 @@ EmmcSwitchBusWidth (
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > IN BOOLEAN IsDdr,
> > > > - IN UINT8 BusWidth
> > > > + IN UINT16 BusWidth
> > > > )
> > > > {
> > > > EFI_STATUS Status;
> > > > @@ -641,13 +641,13 @@ EmmcSwitchBusWidth (
> > > > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6 and SD Host
> > > > Controller
> > > > Simplified Spec 3.0 Figure 3-3 for details.
> > > >
> > > > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> instance.
> > > > - @param[in] PassThru A pointer to the
> > > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > > - @param[in] Slot The slot number of the SD card to send the
> > > command
> > > > to.
> > > > - @param[in] Rca The relative device address to be assigned.
> > > > - @param[in] HsTiming The value to be written to HS_TIMING field
> of
> > > > EXT_CSD register.
> > > > - @param[in] Timing The bus mode timing indicator.
> > > > - @param[in] ClockFreq The max clock frequency to be set, the unit
> is
> > > > MHz.
> > > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> > instance.
> > > > + @param[in] PassThru A pointer to the
> > > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > > + @param[in] Slot The slot number of the SD card to send the
> > > > command to.
> > > > + @param[in] Rca The relative device address to be assigned.
> > > > + @param[in] DriverStrength Driver strength to set for speed modes
> > that
> > > > support it.
> > > > + @param[in] Timing The bus mode timing indicator.
> > >
> > >
> > > Please help to update the parameter comment to reflect the name
> change
> > > from
> > > 'Timing' to 'BusTiming'.
> > >
> > >
> > > > + @param[in] ClockFreq The max clock frequency to be set, the unit
> is
> > > > MHz.
> > > >
> > > > @retval EFI_SUCCESS The operation is done correctly.
> > > > @retval Others The operation fails.
> > > > @@ -659,8 +659,8 @@ EmmcSwitchBusTiming (
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > - IN UINT8 HsTiming,
> > > > - IN SD_MMC_BUS_MODE Timing,
> > > > + IN EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength,
> > > > + IN SD_MMC_BUS_MODE BusTiming,
> > > > IN UINT32 ClockFreq
> > > > )
> > > > {
> > > > @@ -678,12 +678,29 @@ EmmcSwitchBusTiming (
> > > > //
> > > > Access = 0x03;
> > > > Index = OFFSET_OF (EMMC_EXT_CSD, HsTiming);
> > > > - Value = HsTiming;
> > > > CmdSet = 0;
> > > > + switch (BusTiming) {
> > > > + case SdMmcMmcHs400:
> > > > + Value = (UINT8)((DriverStrength.Emmc << 4) | 3);
> > > > + break;
> > > > + case SdMmcMmcHs200:
> > > > + Value = (UINT8)((DriverStrength.Emmc << 4) | 2);
> > > > + break;
> > > > + case SdMmcMmcHsSdr:
> > > > + case SdMmcMmcHsDdr:
> > > > + Value = 1;
> > > > + break;
> > > > + case SdMmcMmcLegacy:
> > > > + Value = 0;
> > > > + break;
> > > > + default:
> > > > + DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Unsupported
> > > > BusTiming(%d\n)", BusTiming));
> > > > + return EFI_INVALID_PARAMETER;
> > > > + }
> > > >
> > > > Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);
> > > > if (EFI_ERROR (Status)) {
> > > > - DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to
> > hstiming %d
> > > > fails with %r\n", HsTiming, Status));
> > > > + DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to bus
> > > > timing %d fails with %r\n", BusTiming, Status));
> > > > return Status;
> > > > }
> > > >
> > > > @@ -713,7 +730,7 @@ EmmcSwitchBusTiming (
> > > > Private->ControllerHandle,
> > > > Slot,
> > > > EdkiiSdMmcSwitchClockFreqPost,
> > > > - &Timing
> > > > + &BusTiming
> > > > );
> > > > if (EFI_ERROR (Status)) {
> > > > DEBUG ((
> > > > @@ -754,25 +771,34 @@ EmmcSwitchToHighSpeed (
> > >
> > >
> > > Please help to update the function comments for
> > > EmmcSwitchToHighSpeed() after
> > > the parameter changes.
> > >
> > >
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > - IN UINT32 ClockFreq,
> > > > - IN BOOLEAN IsDdr,
> > > > - IN UINT8 BusWidth
> > > > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > > > )
> > > > {
> > > > EFI_STATUS Status;
> > > > - UINT8 HsTiming;
> > > > UINT8 HostCtrl1;
> > > > - SD_MMC_BUS_MODE Timing;
> > > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > > + BOOLEAN IsDdr;
> > > >
> > > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > >
> > > > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr,
> > > BusWidth);
> > > > + if ((BusMode->BusTiming != SdMmcMmcHsSdr && BusMode-
> > > > >BusTiming != SdMmcMmcHsDdr) ||
> > > > + BusMode->ClockFreq > 52) {
> > > > + return EFI_INVALID_PARAMETER;
> > > > + }
> > > > +
> > > > + if (BusMode->BusTiming == SdMmcMmcHsDdr) {
> > > > + IsDdr = TRUE;
> > > > + } else {
> > > > + IsDdr = FALSE;
> > > > + }
> > > > +
> > > > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr,
> > > BusMode-
> > > > >BusWidth);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > +
> > > > //
> > > > - // Set to Hight Speed timing
> > > > + // Set to High Speed timing
> > > > //
> > > > HostCtrl1 = BIT2;
> > > > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1,
> > sizeof
> > > > (HostCtrl1), &HostCtrl1);
> > > > @@ -780,37 +806,27 @@ EmmcSwitchToHighSpeed (
> > > > return Status;
> > > > }
> > > >
> > > > - if (IsDdr) {
> > > > - Timing = SdMmcMmcHsDdr;
> > > > - } else if (ClockFreq == 52) {
> > > > - Timing = SdMmcMmcHsSdr;
> > > > - } else {
> > > > - Timing = SdMmcMmcLegacy;
> > > > - }
> > > > -
> > > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > > Timing);
> > > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo,
> Slot,
> > > > BusMode->BusTiming);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > >
> > > > - HsTiming = 1;
> > > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > > Timing,
> > > > ClockFreq);
> > > > -
> > > > - return Status;
> > > > + return EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
> > > > }
> > > >
> > > > /**
> > > > - Switch to the HS200 timing according to request.
> > > > + Switch to the HS200 timing. This function assumes that eMMC bus is
> > still
> > > in
> > > > legacy mode.
> > > >
> > > > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host
> > > > Controller
> > > > Simplified Spec 3.0 Figure 2-29 for details.
> > > >
> > > > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> instance.
> > > > - @param[in] PassThru A pointer to the
> > > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > > - @param[in] Slot The slot number of the SD card to send the
> > > command
> > > > to.
> > > > - @param[in] Rca The relative device address to be assigned.
> > > > - @param[in] ClockFreq The max clock frequency to be set.
> > > > - @param[in] BusWidth The bus width to be set, it could be 4 or 8.
> > > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> > instance.
> > > > + @param[in] PassThru A pointer to the
> > > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > > + @param[in] Slot The slot number of the SD card to send the
> > > > command to.
> > > > + @param[in] Rca The relative device address to be assigned.
> > > > + @param[in] DriverStrength The driver strength to be selected.
> > > > + @param[in] ClockFreq The max clock frequency to be set.
> > > > + @param[in] BusWidth The bus width to be set, it could be 4 or 8.
> > > >
> > > > @retval EFI_SUCCESS The operation is done correctly.
> > > > @retval Others The operation fails.
> > > > @@ -822,30 +838,25 @@ EmmcSwitchToHS200 (
> > >
> > >
> > > Please help to update the function comments for EmmcSwitchToHS200()
> > > after the
> > > parameter changes.
> > >
> > >
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > - IN UINT32 ClockFreq,
> > > > - IN UINT8 BusWidth
> > > > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > > > )
> > > > {
> > > > EFI_STATUS Status;
> > > > - UINT8 HsTiming;
> > > > UINT16 ClockCtrl;
> > > > - SD_MMC_BUS_MODE Timing;
> > > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > >
> > > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > >
> > > > - if ((BusWidth != 4) && (BusWidth != 8)) {
> > > > + if (BusMode->BusTiming != SdMmcMmcHs200 ||
> > > > + (BusMode->BusWidth != 4 && BusMode->BusWidth != 8)) {
> > > > return EFI_INVALID_PARAMETER;
> > > > }
> > > >
> > > > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE,
> > > BusWidth);
> > > > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE,
> > > > BusMode->BusWidth);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > //
> > > > - // Set to HS200/SDR104 timing
> > > > - //
> > > > - //
> > > > // Stop bus clock at first
> > > > //
> > > > Status = SdMmcHcStopClock (PciIo, Slot);
> > > > @@ -853,9 +864,7 @@ EmmcSwitchToHS200 (
> > > > return Status;
> > > > }
> > > >
> > > > - Timing = SdMmcMmcHs200;
> > > > -
> > > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > > Timing);
> > > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo,
> Slot,
> > > > BusMode->BusTiming);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > @@ -881,28 +890,27 @@ EmmcSwitchToHS200 (
> > > > ClockCtrl = BIT2;
> > > > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL,
> > sizeof
> > > > (ClockCtrl), &ClockCtrl);
> > > >
> > > > - HsTiming = 2;
> > > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > > Timing,
> > > > ClockFreq);
> > > > + Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
> > >
> > >
> > > After the proposed change, the preferred bus timing and driver strength
> > > value
> > > will be set for the device through the EMMC_SWITCH command.
> > >
> > > However, on the host controller side, only the bus timing value is also
> > > updated
> > > in the Host Control 2 Register of the SD HC (via function
> > > SdMmcHcUhsSignaling()).
> > > It seems to me that the driver strength value does not get updated in this
> > > register.
> > >
> > > I think the SD case has a similar issue.
> >
> > For SD I agree that there is an issue but for eMMC there is no clear mapping
> > between
> > eMMC defined driver strength types and SD defined driver strength types.
> > The controller
> > I happen to be working with seems to ignore the values in this register. If
> we
> > can agree on
> > one mapping that will be able to service majority of the eMMC controllers
> on
> > market I don't
> > mind adding that. We can maybe add driver strength setting to
> > SdMmcHcUhsSignaling so that
> > platform has an opportunity to correct core driver during
> > EdkiiSdMmcUhsSignaling notify.
>
>
> How about using the mapping at the beginning of the thread to set the HC2
> register and ignore this step for eMMC driver type 4?
>
>
> >
> > >
> > >
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > >
> > > > - Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth);
> > > > + Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusMode-
> > > > >BusWidth);
> > > >
> > > > return Status;
> > > > }
> > > >
> > > > /**
> > > > - Switch to the HS400 timing according to request.
> > > > + Switch to the HS400 timing. This function assumes that eMMC bus is
> > still
> > > in
> > > > legacy mode.
> > > >
> > > > Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host
> > > > Controller
> > > > Simplified Spec 3.0 Figure 2-29 for details.
> > > >
> > > > - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> instance.
> > > > - @param[in] PassThru A pointer to the
> > > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > > - @param[in] Slot The slot number of the SD card to send the
> > > command
> > > > to.
> > > > - @param[in] Rca The relative device address to be assigned.
> > > > - @param[in] ClockFreq The max clock frequency to be set.
> > > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL
> > instance.
> > > > + @param[in] PassThru A pointer to the
> > > > EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
> > > > + @param[in] Slot The slot number of the SD card to send the
> > > > command to.
> > > > + @param[in] Rca The relative device address to be assigned.
> > > > + @param[in] ClockFreq The max clock frequency to be set.
> > >
> > >
> > > Please help to update the function comments for EmmcSwitchToHS400()
> > > after the
> > > parameter changes.
> > >
> > >
> > > >
> > > > @retval EFI_SUCCESS The operation is done correctly.
> > > > @retval Others The operation fails.
> > > > @@ -914,47 +922,321 @@ EmmcSwitchToHS400 (
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > - IN UINT32 ClockFreq
> > > > + IN EDKII_SD_MMC_BUS_MODE *BusMode
> > > > )
> > > > {
> > > > EFI_STATUS Status;
> > > > - UINT8 HsTiming;
> > > > - SD_MMC_BUS_MODE Timing;
> > > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > > + EDKII_SD_MMC_BUS_MODE Hs200BusMode;
> > > > + UINT32 HsFreq;
> > > > +
> > > > + if (BusMode->BusTiming != SdMmcMmcHs400 ||
> > > > + BusMode->BusWidth != 8) {
> > > > + return EFI_INVALID_PARAMETER;
> > > > + }
> > > >
> > > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > > + Hs200BusMode.BusTiming = SdMmcMmcHs200;
> > > > + Hs200BusMode.BusWidth = BusMode->BusWidth;
> > > > + Hs200BusMode.ClockFreq = BusMode->ClockFreq;
> > > > + Hs200BusMode.DriverStrength = BusMode->DriverStrength;
> > > >
> > > > - Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq,
> 8);
> > > > + Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca,
> > > &Hs200BusMode);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > +
> > > > //
> > > > - // Set to Hight Speed timing and set the clock frequency to a value
> less
> > > than
> > > > 52MHz.
> > > > + // Set to High Speed timing and set the clock frequency to a value less
> > > than
> > > > or equal to 52MHz.
> > > > + // This step is necessary to be able to switch Bus into 8 bit DDR mode
> > > which
> > > > is unsupported in HS200.
> > > > //
> > > > - HsTiming = 1;
> > > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > > > SdMmcMmcHsSdr, 52);
> > > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo,
> Slot,
> > > > SdMmcMmcHsSdr);
> > >
> > >
> > > The above SdMmcHcUhsSignaling() is newly added, is this a bug for the
> > origin
> > > code?
> > >
> > > I searched the eMMC spec, it seems to me the spec does not explicitly
> > > mention
> > > the Host Control 2 Register at all, I am not very sure if such change will
> > > bring any effect to devices. Did you have a try without adding such
> change?
> > >
> >
> > This is aligned to the behavior of EmmcSwitchToHighSpeed function. My
> > eMMC
> > controller doesn't need this register to be programmed for switch to high
> > speed
> > but calling SdMmcUhsSignaling here gives override protocol a chance to
> finish
> > switch to high speed for eMMC controllers that need such tweaking.
>
>
> Hello Marcin,
> Do you see any concern for this specific change?
>
>
> >
> > >
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > - //
> > > > - // HS400 mode must use 8 data lines.
> > > > - //
> > > > - Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, TRUE, 8);
> > > > +
> > > > + HsFreq = BusMode->ClockFreq < 52 ? BusMode->ClockFreq : 52;
> > > > + Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > > >DriverStrength, SdMmcMmcHsSdr, HsFreq);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > >
> > > > - Timing = SdMmcMmcHs400;
> > > > + Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, TRUE,
> > > BusMode-
> > > > >BusWidth);
> > > > + if (EFI_ERROR (Status)) {
> > > > + return Status;
> > > > + }
> > > >
> > > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > > Timing);
> > > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo,
> Slot,
> > > > BusMode->BusTiming);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > >
> > > > - HsTiming = 3;
> > > > - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming,
> > > Timing,
> > > > ClockFreq);
> > > > + return EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode-
> > > > >DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
> > >
> > >
> > > After the proposed change, the preferred bus timing and driver strength
> > > value
> > > will be set for the device through the EMMC_SWITCH command.
> > >
> > > However, on the host controller side, only the bus timing value is also
> > > updated
> > > in the Host Control 2 Register of the SD HC (via function
> > > SdMmcHcUhsSignaling()).
> > > It seems to me that the driver strength value does not get updated in this
> > > register.
> > >
> > > I think the SD case has a similar issue.
> > >
> > >
> > > > +}
> > > >
> > > > - return Status;
> > > > +/**
> > > > + Check if passed BusTiming is supported in both controller and card.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] ExtCsd Pointer to the card's extended CSD
> > > > + @param[in] BusTiming Bus timing to check
> > > > +
> > > > + @retval TRUE Both card and controller support given BusTiming
> > > > + @retval FALSE Card or controller doesn't support given BusTiming
> > > > +**/
> > > > +STATIC
> > > > +BOOLEAN
> > > > +IsBusTimingSupported (
> > >
> > >
> > > How about renaming it to EmmcIsBusTimingSupported()?
> > >
> > >
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN EMMC_EXT_CSD *ExtCsd,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + BOOLEAN Supported;
> > > > + SD_MMC_HC_SLOT_CAP *Capabilities;
> > > > +
> > > > + Capabilities = &Private->Capability[SlotIndex];
> > > > +
> > > > + Supported = FALSE;
> > > > + switch (BusTiming) {
> > > > + case SdMmcMmcHs400:
> > > > + if ((((ExtCsd->DeviceType & (BIT6 | BIT7)) != 0) && (Capabilities-
> > > > >Hs400 != 0)) && Capabilities->BusWidth8) {
> > > > + Supported = TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcMmcHs200:
> > > > + if ((((ExtCsd->DeviceType & (BIT4 | BIT5)) != 0) && (Capabilities-
> > > > >Sdr104 != 0))) {
> > > > + Supported = TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcMmcHsDdr:
> > > > + if ((((ExtCsd->DeviceType & (BIT2 | BIT3)) != 0) && (Capabilities-
> > > > >Ddr50 != 0))) {
> > > > + Supported = TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcMmcHsSdr:
> > > > + if ((((ExtCsd->DeviceType & BIT1) != 0) && (Capabilities-
> > >HighSpeed !=
> > > > 0))) {
> > > > + Supported = TRUE;
> > > > + } else if ((((ExtCsd->DeviceType & BIT0) != 0) && (Capabilities-
> > > > >HighSpeed != 0))) {
> > >
> > >
> > > For this case, I think the bus timing should be classified to
> > SdMmcMmcLegacy.
> > > Since under this timing, the maximum frequency allowed is 26Mhz. If set
> to
> > > SdMmcMmcHsSdr the driver will try to set the frequency to 52Mhz later
> in
> > > EmmcGetTargetClockFreq().
> > >
> > >
> > > > + Supported = TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcMmcLegacy:
> > > > + Supported = TRUE;
> > > > + break;
> > > > + default:
> > > > + ASSERT (FALSE);
> > > > + }
> > > > +
> > > > + return Supported;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target bus timing to set on the link. This function
> > > > + will try to select highest bus timing supported by card, controller
> > > > + and the driver.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] ExtCsd Pointer to the card's extended CSD
> > > > +
> > > > + @return Bus timing value that should be set on link
> > > > +**/
> > > > +STATIC
> > > > +SD_MMC_BUS_MODE
> > > > +EmmcGetTargetBusTiming (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN EMMC_EXT_CSD *ExtCsd
> > > > + )
> > > > +{
> > > > + SD_MMC_BUS_MODE BusTiming;
> > > > +
> > > > + //
> > > > + // We start with highest bus timing that this driver currently support
> > and
> > > > + // return as soon as we find supported timing.
> > > > + //
> > > > + BusTiming = SdMmcMmcHs400;
> > > > + while (BusTiming > SdMmcMmcLegacy) {
> > > > + if (IsBusTimingSupported (Private, SlotIndex, ExtCsd, BusTiming)) {
> > > > + break;
> > > > + }
> > > > + BusTiming--;
> > > > + }
> > > > +
> > > > + return BusTiming;
> > > > +}
> > > > +
> > > > +/**
> > > > + Check if the passed bus width is supported by controller and card.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] BusTiming Bus timing set on the link
> > > > + @param[in] BusWidth Bus width to check
> > > > +
> > > > + @retval TRUE Passed bus width is supported in current bus
> > > configuration
> > > > + @retval FALSE Passed bus width is not supported in current bus
> > > > configuration
> > > > +**/
> > > > +STATIC
> > > > +BOOLEAN
> > > > +IsBusWidthSupported (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN SD_MMC_BUS_MODE BusTiming,
> > > > + IN UINT16 BusWidth
> > > > + )
> > > > +{
> > > > + if (BusWidth == 8 && Private->Capability[SlotIndex].BusWidth8) {
> > > > + return TRUE;
> > > > + } else if (BusWidth == 4 && BusTiming != SdMmcMmcHs400) {
> > > > + return TRUE;
> > > > + } else if (BusWidth == 1 && (BusTiming == SdMmcMmcHsSdr ||
> > > BusTiming
> > > > == SdMmcMmcLegacy)) {
> > > > + return TRUE;
> > > > + }
> > > > +
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target bus width to be set on the bus.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > > + @param[in] BusTiming Bus timing set on the bus
> > > > +
> > > > + @return Bus width to be set on the bus
> > > > +**/
> > > > +STATIC
> > > > +UINT16
> > > > +EmmcGetTargetBusWidth (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN EMMC_EXT_CSD *ExtCsd,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + UINT16 BusWidth;
> > > > + UINT16 PreferedBusWidth;
> > > > +
> > > > + PreferedBusWidth = Private-
> > > > >Slot[SlotIndex].OperatingParameters.BusWidth;
> > > > +
> > > > + if (PreferedBusWidth != EDKII_SD_MMC_BUS_WIDTH_IGNORE &&
> > > > + IsBusWidthSupported (Private, SlotIndex, BusTiming,
> > > > PreferedBusWidth)) {
> > > > + BusWidth = PreferedBusWidth;
> > > > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 8)) {
> > > > + BusWidth = 8;
> > > > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 4)) {
> > > > + BusWidth = 4;
> > > > + } else if (IsBusWidthSupported (Private, SlotIndex, BusTiming, 1)) {
> > > > + BusWidth = 1;
> > > > + }
> > > > +
> > > > + return BusWidth;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target clock frequency to be set on the bus.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > > + @param[in] BusTiming Bus timing to be set on the bus
> > > > +
> > > > + @return Value of the clock frequency to be set on bus in MHz
> > > > +**/
> > > > +STATIC
> > > > +UINT32
> > > > +EmmcGetTargetClockFreq (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN EMMC_EXT_CSD *ExtCsd,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + UINT32 PreferedClockFreq;
> > > > + UINT32 MaxClockFreq;
> > > > +
> > > > + PreferedClockFreq = Private-
> > > > >Slot[SlotIndex].OperatingParameters.ClockFreq;
> > > > +
> > > > + switch (BusTiming) {
> > > > + case SdMmcMmcHs400:
> > > > + case SdMmcMmcHs200:
> > > > + MaxClockFreq = 200;
> > > > + break;
> > > > + case SdMmcMmcHsSdr:
> > > > + case SdMmcMmcHsDdr:
> > > > + MaxClockFreq = 52;
> > > > + break;
> > > > + default:
> > > > + MaxClockFreq = 26;
> > > > + break;
> > > > + }
> > > > +
> > > > + if (PreferedClockFreq != EDKII_SD_MMC_CLOCK_FREQ_IGNORE &&
> > > > PreferedClockFreq < MaxClockFreq) {
> > > > + return PreferedClockFreq;
> > > > + } else {
> > > > + return MaxClockFreq;
> > > > + }
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the driver strength to be set on bus
> > >
> > > Please help to append a '.' character for the above line.
> > > It is required for the edk2 coding style.
> > >
> > >
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > > + @param[in] BusTiming Bus timing set on the bus
> > > > +
> > > > + @return Value of the driver strength to be set on the bus
> > > > +**/
> > > > +STATIC
> > > > +EDKII_SD_MMC_DRIVER_STRENGTH
> > > > +EmmcGetTargetDriverStrength (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN EMMC_EXT_CSD *ExtCsd,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + EDKII_SD_MMC_DRIVER_STRENGTH PreferedDriverStrength;
> > > > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > > > +
> > > > + PreferedDriverStrength = Private-
> > > > >Slot[SlotIndex].OperatingParameters.DriverStrength;
> > > > + DriverStrength.Emmc = EmmcDriverStrengthType0;
> > > > +
> > > > + if (PreferedDriverStrength.Emmc !=
> > > > EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE &&
> > > > + (ExtCsd->DriverStrength & (BIT0 <<
> PreferedDriverStrength.Emmc)))
> > {
> > >
> > >
> > > The host controller also has a capability for different types of driver
> > strength.
> > > (Capabilities Register, bit 36~38)
> > >
> > > The check should take it into consideration as well.
> >
> > For SD it should. For eMMC it's not as obvious since as I mentioned we
> don't
> > have a mapping defined.
> > If we agree on one we can add this and for all eMMC controllers that won't
> > follow it I guess we can
> > leave it to the platform code to override capabilities.
>
>
> Similar as one comment above, the mapping of eMMC driver type 0~3 looks
> consistent to SD driver type A~D. As for eMMC driver type 4, I think just
> checking the capability of the device is enough.
>
>
> >
> > >
> > >
> > > > + DriverStrength.Emmc = PreferedDriverStrength.Emmc;
> > > > + }
> > > > +
> > > > + return DriverStrength;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target settings for the bus mode.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] ExtCsd Pointer to card's extended CSD
> > > > + @param[out] BusMode Target configuration of the bus
> > > > +**/
> > > > +STATIC
> > > > +VOID
> > > > +EmmcGetTargetBusMode (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN EMMC_EXT_CSD *ExtCsd,
> > > > + OUT EDKII_SD_MMC_BUS_MODE *BusMode
> > > > + )
> > > > +{
> > > > + BusMode->BusTiming = EmmcGetTargetBusTiming (Private,
> SlotIndex,
> > > > ExtCsd);
> > > > + BusMode->BusWidth = EmmcGetTargetBusWidth (Private, SlotIndex,
> > > > ExtCsd, BusMode->BusTiming);
> > > > + BusMode->ClockFreq = EmmcGetTargetClockFreq (Private, SlotIndex,
> > > > ExtCsd, BusMode->BusTiming);
> > > > + BusMode->DriverStrength = EmmcGetTargetDriverStrength (Private,
> > > > SlotIndex, ExtCsd, BusMode->BusTiming);
> > > > }
> > > >
> > > > /**
> > > > @@ -983,10 +1265,7 @@ EmmcSetBusMode (
> > > > EFI_STATUS Status;
> > > > EMMC_CSD Csd;
> > > > EMMC_EXT_CSD ExtCsd;
> > > > - UINT8 HsTiming;
> > > > - BOOLEAN IsDdr;
> > > > - UINT32 ClockFreq;
> > > > - UINT8 BusWidth;
> > > > + EDKII_SD_MMC_BUS_MODE BusMode;
> > > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > >
> > > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > > @@ -1004,85 +1283,30 @@ EmmcSetBusMode (
> > > > }
> > > >
> > > > ASSERT (Private->BaseClkFreq[Slot] != 0);
> > > > +
> > > > //
> > > > - // Check if the Host Controller support 8bits bus width.
> > > > - //
> > > > - if (Private->Capability[Slot].BusWidth8 != 0) {
> > > > - BusWidth = 8;
> > > > - } else {
> > > > - BusWidth = 4;
> > > > - }
> > > > - //
> > > > - // Get Deivce_Type from EXT_CSD register.
> > > > + // Get Device_Type from EXT_CSD register.
> > > > //
> > > > Status = EmmcGetExtCsd (PassThru, Slot, &ExtCsd);
> > > > if (EFI_ERROR (Status)) {
> > > > DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetExtCsd fails
> > > with %r\n",
> > > > Status));
> > > > return Status;
> > > > }
> > > > - //
> > > > - // Calculate supported bus speed/bus width/clock frequency.
> > > > - //
> > > > - HsTiming = 0;
> > > > - IsDdr = FALSE;
> > > > - ClockFreq = 0;
> > > > - if (((ExtCsd.DeviceType & (BIT4 | BIT5)) != 0) && (Private-
> > > > >Capability[Slot].Sdr104 != 0)) {
> > > > - HsTiming = 2;
> > > > - IsDdr = FALSE;
> > > > - ClockFreq = 200;
> > > > - } else if (((ExtCsd.DeviceType & (BIT2 | BIT3)) != 0) && (Private-
> > > > >Capability[Slot].Ddr50 != 0)) {
> > > > - HsTiming = 1;
> > > > - IsDdr = TRUE;
> > > > - ClockFreq = 52;
> > > > - } else if (((ExtCsd.DeviceType & BIT1) != 0) && (Private-
> > > > >Capability[Slot].HighSpeed != 0)) {
> > > > - HsTiming = 1;
> > > > - IsDdr = FALSE;
> > > > - ClockFreq = 52;
> > > > - } else if (((ExtCsd.DeviceType & BIT0) != 0) && (Private-
> > > > >Capability[Slot].HighSpeed != 0)) {
> > > > - HsTiming = 1;
> > > > - IsDdr = FALSE;
> > > > - ClockFreq = 26;
> > > > - }
> > > > - //
> > > > - // Check if both of the device and the host controller support HS400
> > DDR
> > > > mode.
> > > > - //
> > > > - if (((ExtCsd.DeviceType & (BIT6 | BIT7)) != 0) && (Private-
> > > > >Capability[Slot].Hs400 != 0)) {
> > > > - //
> > > > - // The host controller supports 8bits bus.
> > > > - //
> > > > - ASSERT (BusWidth == 8);
> > > > - HsTiming = 3;
> > > > - IsDdr = TRUE;
> > > > - ClockFreq = 200;
> > > > - }
> > > >
> > > > - if ((ClockFreq == 0) || (HsTiming == 0)) {
> > > > - //
> > > > - // Continue using default setting.
> > > > - //
> > > > - return EFI_SUCCESS;
> > > > - }
> > > > + EmmcGetTargetBusMode (Private, Slot, &ExtCsd, &BusMode);
> > > >
> > > > - DEBUG ((DEBUG_INFO, "EmmcSetBusMode: HsTiming %d
> > ClockFreq %d
> > > > BusWidth %d Ddr %a\n", HsTiming, ClockFreq, BusWidth, IsDdr ?
> > > > "TRUE":"FALSE"));
> > > > + DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Target bus mode:
> timing
> > > > = %d, width = %d, clock freq = %d, driver strength = %d\n",
> > > > + BusMode.BusTiming, BusMode.BusWidth,
> > > BusMode.ClockFreq,
> > > > BusMode.DriverStrength.Emmc));
> > > >
> > > > - if (HsTiming == 3) {
> > > > - //
> > > > - // Execute HS400 timing switch procedure
> > > > - //
> > > > - Status = EmmcSwitchToHS400 (PciIo, PassThru, Slot, Rca, ClockFreq);
> > > > - } else if (HsTiming == 2) {
> > > > - //
> > > > - // Execute HS200 timing switch procedure
> > > > - //
> > > > - Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq,
> > > > BusWidth);
> > > > + if (BusMode.BusTiming == SdMmcMmcHs400) {
> > > > + Status = EmmcSwitchToHS400 (PciIo, PassThru, Slot, Rca,
> &BusMode);
> > > > + } else if (BusMode.BusTiming == SdMmcMmcHs200) {
> > > > + Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca,
> &BusMode);
> > > > } else {
> > > > - //
> > > > - // Execute High Speed timing switch procedure
> > > > - //
> > > > - Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca,
> > ClockFreq,
> > > > IsDdr, BusWidth);
> > > > + Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca,
> > > &BusMode);
> > > > }
> > > >
> > > > - DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n",
> > > (HsTiming
> > > > == 3) ? "HS400" : ((HsTiming == 2) ? "HS200" : "HighSpeed"), Status));
> > > > + DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n",
> > > > (BusMode.BusTiming == SdMmcMmcHs400) ? "HS400" :
> > > > ((BusMode.BusTiming == SdMmcMmcHs200) ? "HS200" : "HighSpeed"),
> > > > Status));
> > > >
> > > > return Status;
> > > > }
> > > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > > index 17936a5492..36d2b487df 100644
> > > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
> > > > @@ -313,10 +313,6 @@ SdCardSetRca (
> > > > return Status;
> > > > }
> > > >
> > > > -
> > > > -
> > > > -
> > > > -
> > > > /**
> > > > Send command SELECT_DESELECT_CARD to the SD device to
> > > > select/deselect it.
> > > >
> > > > @@ -422,7 +418,7 @@ SdCardSetBusWidth (
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > - IN UINT8 BusWidth
> > > > + IN UINT16 BusWidth
> > > > )
> > > > {
> > > > EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
> > > > @@ -476,7 +472,7 @@ SdCardSetBusWidth (
> > > > @param[in] Slot The slot number of the SD card to send the
> > > command
> > > > to.
> > > > @param[in] AccessMode The value for access mode group.
> > >
> > >
> > > Please help to update the parameter comment to reflect the function
> > > interface changes.
> > >
> > >
> > > > @param[in] CommandSystem The value for command set group.
> > > > - @param[in] DriveStrength The value for drive length group.
> > > > + @param[in] DriveStrength The value for driver strength group.
> > >
> > >
> > > Please help to update the parameter name in the above comment from
> > > 'DriveStrength' to 'DriverStrength'.
> > >
> > >
> > > > @param[in] PowerLimit The value for power limit group.
> > > > @param[in] Mode Switch or check function.
> > > > @param[out] SwitchResp The return switch function status.
> > > > @@ -489,9 +485,9 @@ EFI_STATUS
> > > > SdCardSwitch (
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > - IN UINT8 AccessMode,
> > > > + IN SD_MMC_BUS_MODE BusTiming,
> > > > IN UINT8 CommandSystem,
> > > > - IN UINT8 DriveStrength,
> > > > + IN SD_DRIVER_STRENGTH_TYPE DriverStrength,
> > > > IN UINT8 PowerLimit,
> > > > IN BOOLEAN Mode,
> > > > OUT UINT8 *SwitchResp
> > > > @@ -502,6 +498,7 @@ SdCardSwitch (
> > > > EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
> > > > EFI_STATUS Status;
> > > > UINT32 ModeValue;
> > > > + UINT8 AccessMode;
> > > >
> > > > ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
> > > > ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
> > > > @@ -516,8 +513,31 @@ SdCardSwitch (
> > > > SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
> > > >
> > > > ModeValue = Mode ? BIT31 : 0;
> > > > - SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) |
> > > ((PowerLimit
> > > > & 0xF) << 4) | \
> > > > - ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF)
> <<
> > > 12)
> > > > | \
> > > > +
> > > > + switch (BusTiming) {
> > > > + case SdMmcUhsDdr50:
> > > > + AccessMode = 0x4;
> > > > + break;
> > > > + case SdMmcUhsSdr104:
> > > > + AccessMode = 0x3;
> > > > + break;
> > > > + case SdMmcUhsSdr50:
> > > > + AccessMode = 0x2;
> > > > + break;
> > > > + case SdMmcUhsSdr25:
> > > > + case SdMmcSdHs:
> > > > + AccessMode = 0x1;
> > > > + break;
> > > > + case SdMmcUhsSdr12:
> > > > + case SdMmcSdDs:
> > > > + AccessMode = 0;
> > > > + break;
> > > > + default:
> > > > + AccessMode = 0xF;
> > > > + }
> > > > +
> > > > + SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) |
> > > > ((CommandSystem & 0xF) << 4) | \
> > > > + ((DriverStrength & 0xF) << 8) | ((PowerLimit & 0xF) <<
> > 12)
> > > |
> > > > \
> > > > ModeValue;
> > > >
> > > > Packet.InDataBuffer = SwitchResp;
> > > > @@ -718,7 +738,7 @@ SdCardSwitchBusWidth (
> > > > IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
> > > > IN UINT8 Slot,
> > > > IN UINT16 Rca,
> > > > - IN UINT8 BusWidth
> > > > + IN UINT16 BusWidth
> > > > )
> > > > {
> > > > EFI_STATUS Status;
> > > > @@ -748,6 +768,261 @@ SdCardSwitchBusWidth (
> > > > return Status;
> > > > }
> > > >
> > > > +/**
> > > > + Check if passed BusTiming is supported in both controller and card.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] CardSupportedBusTimings Bitmask indicating which bus
> > > > timings are supported by card
> > > > + @param[in] IsInUhsI Flag indicating if link is in UHS-I
> > > > +
> > > > + @retval TRUE Both card and controller support given BusTiming
> > > > + @retval FALSE Card or controller doesn't support given BusTiming
> > > > +**/
> > > > +STATIC
> > > > +BOOLEAN
> > > > +SdIsBusTimingSupported (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN UINT8 CardSupportedBusTimings,
> > > > + IN BOOLEAN IsInUhsI,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + SD_MMC_HC_SLOT_CAP *Capability;
> > > > +
> > > > + Capability = &Private->Capability[SlotIndex];
> > > > +
> > > > + if (IsInUhsI) {
> > > > + switch (BusTiming) {
> > >
> > >
> > > Please help to add a 'default' handle for this 'switch' statement, the
> > > proposed
> > > code will cause a GCC5 build failure.
> > >
> > >
> > > > + case SdMmcUhsSdr104:
> > > > + if (Capability->Sdr104 && ((CardSupportedBusTimings & BIT3) !=
> 0))
> > {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcUhsDdr50:
> > > > + if (Capability->Ddr50 && ((CardSupportedBusTimings & BIT4) != 0))
> {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcUhsSdr50:
> > > > + if (Capability->Sdr50 && ((CardSupportedBusTimings & BIT2) != 0))
> {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcUhsSdr25:
> > > > + if ((CardSupportedBusTimings & BIT1) != 0) {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcUhsSdr12:
> > > > + if ((CardSupportedBusTimings & BIT0) != 0) {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + }
> > > > + } else {
> > > > + switch (BusTiming) {
> > >
> > >
> > > Please help to add a 'default' handle for this 'switch' statement, the
> > > proposed
> > > code will cause a GCC5 build failure.
> > >
> > >
> > > > + case SdMmcSdHs:
> > > > + if (Capability->HighSpeed && (CardSupportedBusTimings &
> BIT1) !=
> > 0)
> > > {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + case SdMmcSdDs:
> > > > + if ((CardSupportedBusTimings & BIT0) != 0) {
> > > > + return TRUE;
> > > > + }
> > > > + break;
> > > > + }
> > > > + }
> > > > +
> > > > + return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target bus timing to set on the link. This function
> > > > + will try to select highest bus timing supported by card, controller
> > > > + and the driver.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] CardSupportedBusTimings Bitmask indicating which bus
> > > > timings are supported by card
> > > > + @param[in] IsInUhsI Flag indicating if link is in UHS-I
> > > > +
> > > > + @return Bus timing value that should be set on link
> > > > +**/
> > > > +STATIC
> > > > +SD_MMC_BUS_MODE
> > > > +SdGetTargetBusTiming (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN UINT8 CardSupportedBusTimings,
> > > > + IN BOOLEAN IsInUhsI
> > > > + )
> > > > +{
> > > > + SD_MMC_BUS_MODE BusTiming;
> > > > +
> > > > + if (IsInUhsI) {
> > > > + BusTiming = SdMmcUhsSdr104;
> > > > + } else {
> > > > + BusTiming = SdMmcSdHs;
> > > > + }
> > > > +
> > > > + while (BusTiming > SdMmcSdDs) {
> > > > + if (SdIsBusTimingSupported (Private, SlotIndex,
> > > > CardSupportedBusTimings, IsInUhsI, BusTiming)) {
> > > > + break;
> > > > + }
> > > > + BusTiming--;
> > > > + }
> > >
> > >
> > > The origin logic has the below preference when selecting bus timing
> > > (if supported):
> > >
> > > SdMmcUhsSdr104
> > > SdMmcUhsSdr50
> > > SdMmcUhsDdr50
> > > SdMmcUhsSdr25
> > > SdMmcUhsSdr12
> > >
> > > So we need to reorder the types in 'SD_MMC_BUS_MODE' to:
> > >
> > > typedef enum {
> > > SdMmcSdDs,
> > > SdMmcSdHs,
> > > SdMmcUhsSdr12,
> > > SdMmcUhsSdr25,
> > > SdMmcUhsDdr50,
> > > SdMmcUhsSdr50,
> > > SdMmcUhsSdr104,
> > > ...
> > > } SD_MMC_BUS_MODE;
> > >
> > > Otherwise, the Ddr50 mode will never be selected.
> > >
> > >
> > > > +
> > > > + return BusTiming;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target bus width to be set on the bus.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] BusTiming Bus timing set on the bus
> > > > +
> > > > + @return Bus width to be set on the bus
> > > > +**/
> > > > +STATIC
> > > > +UINT16
> > > > +SdGetTargetBusWidth (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + UINT16 BusWidth;
> > > > + UINT16 PreferedBusWidth;
> > > > +
> > > > + PreferedBusWidth = Private-
> > > > >Slot[SlotIndex].OperatingParameters.BusWidth;
> > > > +
> > > > + if (BusTiming == SdMmcSdDs || BusTiming == SdMmcSdHs) {
> > > > + if (PreferedBusWidth != EDKII_SD_MMC_BUS_WIDTH_IGNORE) {
> > > > + BusWidth = PreferedBusWidth;
> > >
> > >
> > > The supported bus width is either 1 or 4 bit for 3.3V signal cards.
> > > I think we need a more strict check here.
> > >
> > >
> > > > + } else {
> > > > + BusWidth = 4;
> > > > + }
> > > > + } else {
> > > > + //
> > > > + // UHS-I modes support only 4-bit width.
> > > > + // Switch to 4-bit has been done before calling this function anyway
> so
> > > > + // this is purely informational.
> > > > + //
> > > > + BusWidth = 4;
> > > > + }
> > > > +
> > > > + return BusWidth;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target clock frequency to be set on the bus.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] BusTiming Bus timing to be set on the bus
> > > > +
> > > > + @return Value of the clock frequency to be set on bus in MHz
> > > > +**/
> > > > +STATIC
> > > > +UINT32
> > > > +SdGetTargetBusClockFreq (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > > > +{
> > > > + UINT32 PreferedClockFreq;
> > > > + UINT32 MaxClockFreq;
> > > > +
> > > > + PreferedClockFreq = Private-
> > > > >Slot[SlotIndex].OperatingParameters.ClockFreq;
> > > > +
> > > > + switch (BusTiming) {
> > > > + case SdMmcUhsSdr104:
> > > > + MaxClockFreq = 208;
> > > > + break;
> > > > + case SdMmcUhsSdr50:
> > > > + MaxClockFreq = 100;
> > > > + break;
> > > > + case SdMmcUhsDdr50:
> > > > + case SdMmcUhsSdr25:
> > > > + case SdMmcSdHs:
> > > > + MaxClockFreq = 50;
> > > > + break;
> > > > + case SdMmcUhsSdr12:
> > > > + case SdMmcSdDs:
> > > > + default:
> > > > + MaxClockFreq = 25;
> > >
> > >
> > > Minor comment, need an extra space for the above line.
> > >
> > >
> > > > + }
> > > > +
> > > > + if (PreferedClockFreq != EDKII_SD_MMC_CLOCK_FREQ_IGNORE &&
> > > > PreferedClockFreq < MaxClockFreq) {
> > > > + return PreferedClockFreq;
> > > > + } else {
> > > > + return MaxClockFreq;
> > > > + }
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the driver strength to be set on bus
> > >
> > >
> > > Please help to append a '.' character for the above line.
> > > It is required for the edk2 coding style.
> > >
> > >
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] CardSupportedDriverStrengths Bitmask indicating which
> > > > driver strengths are supported on the card
> > > > + @param[in] BusTiming Bus timing set on the bus
> > > > +
> > > > + @return Value of the driver strength to be set on the bus
> > > > +**/
> > > > +STATIC
> > > > +EDKII_SD_MMC_DRIVER_STRENGTH
> > > > +SdGetTargetDriverStrength (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN UINT8 CardSupportedDriverStrengths,
> > > > + IN SD_MMC_BUS_MODE BusTiming
> > > > + )
> > >
> > >
> > > One question here, the driver strength configuration is only for UHS-I
> cards.
> > > Does the check on 'CardSupportedDriverStrengths' enough to ensure the
> > > above
> > > requirement or a boolean input parameter 'IsInUhsI' is needed here?
> > >
> >
> > I think we can leave it to the code that actually sets the bus parameters
> > to simply skip driver strength programming for legacy and select driver
> > strength here
> > based only on HW support and platform preference. The alternative is to
> > return
> > SdDriverStrengthIgnore here and handle that in code that actually sets
> driver
> > strength.
>
>
> Either approach is okay to me, since both of them need extra handling in
> SdCardSwitch() & SdMmcHcUhsSignaling() when setting driver strength.
>
> I slightly prefer the 1st option, since the logic is a bit more straight-
> forward.
>
> >
> > >
> > > > +{
> > > > + EDKII_SD_MMC_DRIVER_STRENGTH PreferedDriverStrength;
> > > > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > > > +
> > > > + PreferedDriverStrength = Private-
> > > > >Slot[SlotIndex].OperatingParameters.DriverStrength;
> > > > + DriverStrength.Sd = SdDriverStrengthTypeB;
> > > > +
> > > > + if (PreferedDriverStrength.Sd !=
> > > > EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE &&
> > > > + (CardSupportedDriverStrengths & (BIT0 <<
> > > PreferedDriverStrength.Sd)))
> > >
> > >
> > > The host controller also has a capability for different types of driver
> > strength.
> > > (Capabilities Register, bit 36~38)
> > >
> > > The check should take it into consideration as well.
> > >
> > >
> > > > {
> > > > + DriverStrength.Sd = PreferedDriverStrength.Sd;
> > > > + }
> > > > +
> > > > + return DriverStrength;
> > > > +}
> > > > +
> > > > +/**
> > > > + Get the target settings for the bus mode.
> > > > +
> > > > + @param[in] Private Pointer to controller private data
> > > > + @param[in] SlotIndex Index of the slot in the controller
> > > > + @param[in] SwitchQueryResp Pointer to switch query response
> > > > + @param[in] IsInUhsI Flag indicating if link is in UHS-I mode
> > > > + @param[out] BusMode Target configuration of the bus
> > > > +**/
> > > > +STATIC
> > > > +VOID
> > > > +SdGetTargetBusMode (
> > > > + IN SD_MMC_HC_PRIVATE_DATA *Private,
> > > > + IN UINT8 SlotIndex,
> > > > + IN UINT8 *SwitchQueryResp,
> > > > + IN BOOLEAN IsInUhsI,
> > > > + OUT EDKII_SD_MMC_BUS_MODE *BusMode
> > > > + )
> > > > +{
> > > > + BusMode->BusTiming = SdGetTargetBusTiming (Private, SlotIndex,
> > > > SwitchQueryResp[13], IsInUhsI);
> > > > + BusMode->BusWidth = SdGetTargetBusWidth (Private, SlotIndex,
> > > > BusMode->BusTiming);
> > > > + BusMode->ClockFreq = SdGetTargetBusClockFreq (Private, SlotIndex,
> > > > BusMode->BusTiming);
> > > > + BusMode->DriverStrength = SdGetTargetDriverStrength (Private,
> > > > SlotIndex, SwitchQueryResp[9], BusMode->BusTiming);
> > > > +}
> > > > +
> > > > /**
> > > > Switch the high speed timing according to request.
> > > >
> > > > @@ -775,13 +1050,10 @@ SdCardSetBusMode (
> > > > {
> > > > EFI_STATUS Status;
> > > > SD_MMC_HC_SLOT_CAP *Capability;
> > > > - UINT32 ClockFreq;
> > > > - UINT8 BusWidth;
> > > > - UINT8 AccessMode;
> > > > UINT8 HostCtrl1;
> > > > UINT8 SwitchResp[64];
> > > > - SD_MMC_BUS_MODE Timing;
> > > > SD_MMC_HC_PRIVATE_DATA *Private;
> > > > + EDKII_SD_MMC_BUS_MODE BusMode;
> > > >
> > > > Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
> > > >
> > > > @@ -792,61 +1064,46 @@ SdCardSetBusMode (
> > > > return Status;
> > > > }
> > > >
> > > > - BusWidth = 4;
> > > > -
> > > > - Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, BusWidth);
> > > > - if (EFI_ERROR (Status)) {
> > > > - return Status;
> > > > + if (S18A) {
> > > > + //
> > > > + // For UHS-I speed modes 4-bit data bus is requiered so we
> > > > + // switch here irrespective of platform preference.
> > > > + //
> > > > + Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, 4);
> > > > + if (EFI_ERROR (Status)) {
> > > > + return Status;
> > > > + }
> > > > }
> > > > +
> > > > //
> > > > // Get the supported bus speed from SWITCH cmd return data group
> #1.
> > > > //
> > > > - Status = SdCardSwitch (PassThru, Slot, 0xF, 0xF, 0xF, 0xF, FALSE,
> > > > SwitchResp);
> > > > + Status = SdCardSwitch (PassThru, Slot, 0xFF, 0xF,
> > SdDriverStrengthIgnore,
> > > > 0xF, FALSE, SwitchResp);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > - //
> > > > - // Calculate supported bus speed/bus width/clock frequency by host
> > and
> > > > device capability.
> > > > - //
> > > > - ClockFreq = 0;
> > > > - if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) !=
> 0))
> > {
> > > > - ClockFreq = 208;
> > > > - AccessMode = 3;
> > > > - Timing = SdMmcUhsSdr104;
> > > > - } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] &
> > BIT2) !=
> > > 0))
> > > > {
> > > > - ClockFreq = 100;
> > > > - AccessMode = 2;
> > > > - Timing = SdMmcUhsSdr50;
> > > > - } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] &
> > BIT4) !=
> > > > 0)) {
> > > > - ClockFreq = 50;
> > > > - AccessMode = 4;
> > > > - Timing = SdMmcUhsDdr50;
> > > > - } else if ((SwitchResp[13] & BIT1) != 0) {
> > > > - ClockFreq = 50;
> > > > - AccessMode = 1;
> > > > - Timing = SdMmcUhsSdr25;
> > > > - } else {
> > > > - ClockFreq = 25;
> > > > - AccessMode = 0;
> > > > - Timing = SdMmcUhsSdr12;
> > > > +
> > > > + SdGetTargetBusMode (Private, Slot, SwitchResp, S18A, &BusMode);
> > > > +
> > > > + DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Target bus mode: bus
> > > timing
> > > > = %d, bus width = %d, clock freq[MHz] = %d, driver strength = %d\n",
> > > > + BusMode.BusTiming, BusMode.BusWidth,
> > > BusMode.ClockFreq,
> > > > BusMode.DriverStrength.Sd));
> > > > +
> > > > + if (!S18A) {
> > > > + Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca,
> > > > BusMode.BusWidth);
> > > > + if (EFI_ERROR (Status)) {
> > > > + return Status;
> > > > + }
> > > > }
> > >
> > >
> > > Is it feasible to set the bus width for the 3.3V signaled cards & the UHS-I
> > > cards together here? I think the SdGetTargetBusWidth() already handles
> > the
> > > UHS-I cards case well by always setting the bus width to 4.
> > >
> >
> > So basically to skip if (!S18A) condition and do bus width switch
> > unconditionally?
> > I am not sure how the bus will react to additional bus width switch for UHS-I
> > case
> > and I am not able to test it locally as I only have controller with legacy
> support
> > available for tests.
> > I guess I will give it a try and we will revert it if it causes any problems.
>
>
> Sorry for not being clear.
> I suggest to just remove the below codes:
>
> if (S18A) {
> //
> // For UHS-I speed modes 4-bit data bus is requiered so we
> // switch here irrespective of platform preference.
> //
> Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, 4);
> if (EFI_ERROR (Status)) {
> return Status;
> }
> }
>
> And set the bus width in one place after SdGetTargetBusMode().
> (Also remove the 'if' condition - if (!S18A), do it together for UHS-I &
> 3.3V signaling cards.)
>
> Best Regards,
> Hao Wu
I am not sure if that would work. My understanding is that SWITCH command needs to be executed on 4-bit mode as that includes data transfer with DAT lanes so that bus width switch beforehand is necessary.
>
>
> >
> > >
> > > >
> > > > - Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF,
> TRUE,
> > > > SwitchResp);
> > > > + Status = SdCardSwitch (PassThru, Slot, BusMode.BusTiming, 0xF,
> > > > BusMode.DriverStrength.Sd, 0xF, TRUE, SwitchResp);
> > >
> > >
> > > After the proposed change, the preferred bus timing and driver strength
> > > value
> > > will be set for the device through the SD_SWITCH command.
> > >
> > > However, on the host controller side, only the bus timing value is also
> > > updated
> > > in the Host Control 2 Register of the SD HC (via function
> > > SdMmcHcUhsSignaling()).
> > > It seems to me that the driver strength value does not get updated in this
> > > register.
> > >
> > > I think the eMMC case has a similar issue.
> > >
> > >
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > >
> > > > - if ((SwitchResp[16] & 0xF) != AccessMode) {
> > > > - DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: Switch to
> > > AccessMode %d
> > > > ClockFreq %d BusWidth %d fails! The Switch response is 0x%1x\n",
> > > > AccessMode, ClockFreq, BusWidth, SwitchResp[16] & 0xF));
> > > > - return EFI_DEVICE_ERROR;
> > > > - }
> > >
> > >
> > > The above check may still be needed. Also, the whether the target driver
> > > strength is successfully set needs to be checked as well.
> > >
> > > How about adding checks in function SdCardSwitch() for mode 1 of the
> > > switch
> > > command?
> > >
> > >
> > > > -
> > > > - DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Switch to
> > AccessMode %d
> > > > ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));
> > > > -
> > > > //
> > > > - // Set to Hight Speed timing
> > > > + // Set to High Speed timing
> > > > //
> > > > - if (AccessMode == 1) {
> > > > + if (BusMode.BusTiming == SdMmcSdHs) {
> > > > HostCtrl1 = BIT2;
> > > > Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1,
> > > sizeof
> > > > (HostCtrl1), &HostCtrl1);
> > > > if (EFI_ERROR (Status)) {
> > > > @@ -854,12 +1111,12 @@ SdCardSetBusMode (
> > > > }
> > > > }
> > > >
> > > > - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot,
> > > > Timing);
> > > > + Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo,
> Slot,
> > > > BusMode.BusTiming);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > >
> > > > - Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private-
> > > > >BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> > > > + Status = SdMmcHcClockSupply (PciIo, Slot, BusMode.ClockFreq *
> 1000,
> > > > Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > }
> > > > @@ -869,7 +1126,7 @@ SdCardSetBusMode (
> > > > Private->ControllerHandle,
> > > > Slot,
> > > > EdkiiSdMmcSwitchClockFreqPost,
> > > > - &Timing
> > > > + &BusMode.BusTiming
> > > > );
> > > > if (EFI_ERROR (Status)) {
> > > > DEBUG ((
> > > > @@ -882,7 +1139,7 @@ SdCardSetBusMode (
> > > > }
> > > > }
> > > >
> > > > - if ((AccessMode == 3) || ((AccessMode == 2) && (Capability-
> > > > >TuningSDR50 != 0))) {
> > > > + if ((BusMode.BusTiming == SdMmcUhsSdr104) ||
> > ((BusMode.BusTiming
> > > > == SdMmcUhsSdr50) && (Capability->TuningSDR50 != 0))) {
> > > > Status = SdCardTuningClock (PciIo, PassThru, Slot);
> > > > if (EFI_ERROR (Status)) {
> > > > return Status;
> > > > @@ -1025,10 +1282,8 @@ SdCardIdentification (
> > > > // (One of support bits is set to 1: SDR50, SDR104 or DDR50 in the
> > > > // Capabilities register), switch its voltage to 1.8V.
> > > > //
> > > > - if ((Private->Capability[Slot].Sdr50 != 0 ||
> > > > - Private->Capability[Slot].Sdr104 != 0 ||
> > > > - Private->Capability[Slot].Ddr50 != 0) &&
> > > > - ((Ocr & BIT24) != 0)) {
> > > > + if ((Private->Capability[Slot].Sdr50 || Private->Capability[Slot].Ddr50
> ||
> > > > Private->Capability[Slot].Sdr104) &&
> > > > + ((Ocr & BIT24) != 0)) {
> > >
> > >
> > > Minor comment, for:
> > > Private->Capability[Slot].Sdr50
> > > Private->Capability[Slot].Ddr50
> > > Private->Capability[Slot].Sdr104
> > >
> > > They are of type UINT32, should use operators '==' or '!=' in condition
> > > statement. I think the origin logic is good here.
> > >
> > >
> > > > Status = SdCardVoltageSwitch (PassThru, Slot);
> > > > if (EFI_ERROR (Status)) {
> > > > DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing
> > > > SdCardVoltageSwitch fails with %r\n", Status));
> > > > diff --git
> a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > > index 4881ee44cc..8f49954b7f 100644
> > > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
> > > > @@ -28,6 +28,11 @@ EFI_DRIVER_BINDING_PROTOCOL
> > > > gSdMmcPciHcDriverBinding = {
> > > > NULL
> > > > };
> > > >
> > > > +#define SLOT_INIT_TEMPLATE {0, UnknownSlot, 0, 0, 0, \
> > > > + {EDKII_SD_MMC_BUS_WIDTH_IGNORE,\
> > > > + EDKII_SD_MMC_CLOCK_FREQ_IGNORE,\
> > > > + EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE}}
> > >
> > >
> > > Please help to update the above definition to:
> > > #define SLOT_INIT_TEMPLATE {0, UnknownSlot, 0, 0, 0, \
> > > {EDKII_SD_MMC_BUS_WIDTH_IGNORE,\
> > > EDKII_SD_MMC_CLOCK_FREQ_IGNORE,\
> > > {EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE}}}
> > >
> > > The proposed one will cause GCC5 build failure.
> > >
> > >
> > > > +
> > > > //
> > > > // Template for SD/MMC host controller private data.
> > > > //
> > > > @@ -50,8 +55,12 @@ SD_MMC_HC_PRIVATE_DATA
> > > gSdMmcPciHcTemplate
> > > > = {
> > > > // Queue
> > > > INITIALIZE_LIST_HEAD_VARIABLE (gSdMmcPciHcTemplate.Queue),
> > > > { // Slot
> > > > - {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot,
> 0,
> > 0,
> > > > 0},
> > > > - {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot,
> 0,
> > 0,
> > > > 0}
> > > > + SLOT_INIT_TEMPLATE,
> > > > + SLOT_INIT_TEMPLATE,
> > > > + SLOT_INIT_TEMPLATE,
> > > > + SLOT_INIT_TEMPLATE,
> > > > + SLOT_INIT_TEMPLATE,
> > > > + SLOT_INIT_TEMPLATE
> > > > },
> > > > { // Capability
> > > > {0},
> > > > @@ -328,6 +337,7 @@ SdMmcPciHcEnumerateDevice (
> > > >
> > > > return;
> > > > }
> > > > +
> > > > /**
> > > > Tests to see if this driver supports a given controller. If a child device is
> > > > provided,
> > > > it further tests to see if this driver supports creating a handle for the
> > > > specified child device.
> > > > @@ -619,7 +629,6 @@ SdMmcPciHcDriverBindingStart (
> > > > Support64BitDma = TRUE;
> > > > for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
> > > > Private->Slot[Slot].Enable = TRUE;
> > > > -
> > > > //
> > > > // Get SD/MMC Pci Host Controller Version
> > > > //
> > > > @@ -635,19 +644,34 @@ SdMmcPciHcDriverBindingStart (
> > > >
> > > > Private->BaseClkFreq[Slot] = Private->Capability[Slot].BaseClkFreq;
> > > >
> > > > - if (mOverride != NULL && mOverride->Capability != NULL) {
> > > > - Status = mOverride->Capability (
> > > > - Controller,
> > > > - Slot,
> > > > - &Private->Capability[Slot],
> > > > - &Private->BaseClkFreq[Slot]
> > > > - );
> > > > - if (EFI_ERROR (Status)) {
> > > > - DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",
> > > > - __FUNCTION__, Status));
> > > > - continue;
> > > > + if (mOverride != NULL) {
> > > > + if (mOverride->Capability != NULL) {
> > > > + Status = mOverride->Capability (
> > > > + Controller,
> > > > + Slot,
> > > > + &Private->Capability[Slot],
> > > > + &Private->BaseClkFreq[Slot]
> > > > + );
> > > > + if (EFI_ERROR (Status)) {
> > > > + DEBUG ((DEBUG_WARN, "%a: Failed to override capability -
> %r\n",
> > > > + __FUNCTION__, Status));
> > > > + continue;
> > > > + }
> > > > + }
> > > > +
> > > > + if (mOverride->NotifyPhase != NULL) {
> > > > + Status = mOverride->NotifyPhase (
> > > > + Controller,
> > > > + Slot,
> > > > + EdkiiSdMmcGetOperatingParam,
> > > > + (VOID*)&Private->Slot[Slot].OperatingParameters
> > > > + );
> > > > + if (EFI_ERROR (Status)) {
> > > > + DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters,
> > > > using defaults\n" __FUNCTION__));
> > >
> > >
> > > Please update the above line to (missed one ',' before '__FUNCTION__'):
> > > DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters, using
> > > defaults\n", __FUNCTION__));
> > >
> > > It will cause GCC5 build failure for the proposed change.
> > >
> > >
> > > > + }
> > > > }
> > > > }
> > > > +
> > > > DumpCapabilityReg (Slot, &Private->Capability[Slot]);
> > > > DEBUG ((
> > > > DEBUG_INFO,
> > > > diff --git
> a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > > index 77bbf83b76..b768f3942f 100644
> > > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
> > > > @@ -78,11 +78,12 @@ typedef enum {
> > > > } EFI_SD_MMC_SLOT_TYPE;
> > > >
> > > > typedef struct {
> > > > - BOOLEAN Enable;
> > > > - EFI_SD_MMC_SLOT_TYPE SlotType;
> > > > - BOOLEAN MediaPresent;
> > > > - BOOLEAN Initialized;
> > > > - SD_MMC_CARD_TYPE CardType;
> > > > + BOOLEAN Enable;
> > > > + EFI_SD_MMC_SLOT_TYPE SlotType;
> > > > + BOOLEAN MediaPresent;
> > > > + BOOLEAN Initialized;
> > > > + SD_MMC_CARD_TYPE CardType;
> > > > + EDKII_SD_MMC_OPERATING_PARAMETERS OperatingParameters;
> > > > } SD_MMC_HC_SLOT;
> > > >
> > > > typedef struct {
> > > > @@ -120,6 +121,13 @@ typedef struct {
> > > > UINT32 BaseClkFreq[SD_MMC_HC_MAX_SLOT];
> > > > } SD_MMC_HC_PRIVATE_DATA;
> > > >
> > > > +typedef struct {
> > > > + EDKII_SD_MMC_BUS_TIMING BusTiming;
> > >
> > >
> > > Should be:
> > > SD_MMC_BUS_MODE BusTiming;
> > >
> > >
> > > > + UINT16 BusWidth;
> > > > + UINT32 ClockFreq;
> > > > + EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;
> > > > +} EDKII_SD_MMC_BUS_MODE;
> > >
> > >
> > > Since the above structure is a driver internal one, I prefer dropping the
> > > prefix 'EDKII_'. But unfortunately, SD_MMC_BUS_MODE is already used
> in
> > > Protocol/SdMmcOverride.h, so how about SD_MMC_BUS_SETTINGS?
> > >
> > >
> > > > +
> > > > #define SD_MMC_HC_TRB_SIG SIGNATURE_32 ('T', 'R', 'B', 'T')
> > > >
> > > > //
> > > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > > index 5d1f977e55..863ae3db34 100644
> > > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
> > > > @@ -1263,10 +1263,10 @@ SdMmcHcInitHost (
> > > > **/
> > > > EFI_STATUS
> > > > SdMmcHcUhsSignaling (
> > > > - IN EFI_HANDLE ControllerHandle,
> > > > - IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > > - IN UINT8 Slot,
> > > > - IN SD_MMC_BUS_MODE Timing
> > > > + IN EFI_HANDLE ControllerHandle,
> > > > + IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > > + IN UINT8 Slot,
> > > > + IN SD_MMC_BUS_MODE Timing
> > > > )
> > >
> > >
> > > I think the changes made here (space indentation) can be dropped.
> > >
> > >
> > > > {
> > > > EFI_STATUS Status;
> > > > diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > > b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > > index 0b0d415256..c4d4aef73a 100644
> > > > --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > > +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
> > > > @@ -611,10 +611,10 @@ SdMmcHcInitTimeoutCtrl (
> > > > **/
> > > > EFI_STATUS
> > > > SdMmcHcUhsSignaling (
> > > > - IN EFI_HANDLE ControllerHandle,
> > > > - IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > > - IN UINT8 Slot,
> > > > - IN SD_MMC_BUS_MODE Timing
> > > > + IN EFI_HANDLE ControllerHandle,
> > > > + IN EFI_PCI_IO_PROTOCOL *PciIo,
> > > > + IN UINT8 Slot,
> > > > + IN SD_MMC_BUS_MODE Timing
> > >
> > >
> > > I think the changes made here (space indentation) can be dropped.
> > >
> > > Best Regards,
> > > Hao Wu
> > >
> > >
> > > > );
> > > >
> > > > #endif
> > > > --
> > > > 2.14.1.windows.1
--------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek
przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by
others is strictly prohibited.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2019-06-18 15:14 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20190603113346.1288-1-mateusz.albecki@intel.com>
[not found] ` <B80AF82E9BFB8E4FBD8C89DA810C6A093C8E4722@SHSMSX104.ccr.corp.intel.com>
2019-06-13 13:43 ` [PATCH 0/2] Add GetOperatingParam notify phase to SdMmcOverride protocol mateusz.albecki
2019-06-14 1:46 ` Wu, Hao A
2019-06-14 18:44 ` Marcin Wojtas
[not found] ` <20190603113346.1288-2-mateusz.albecki@intel.com>
[not found] ` <B80AF82E9BFB8E4FBD8C89DA810C6A093C8E4729@SHSMSX104.ccr.corp.intel.com>
2019-06-13 13:56 ` [PATCH 1/2] MdeModulePkg/SdMmcOverride: Add GetOperatingParam notify phase Albecki, Mateusz
[not found] ` <20190603113346.1288-3-mateusz.albecki@intel.com>
[not found] ` <B80AF82E9BFB8E4FBD8C89DA810C6A093C8E473C@SHSMSX104.ccr.corp.intel.com>
2019-06-13 14:38 ` [PATCH 2/2] MdeModulePkg/SdMmcHcDxe: Implement revision 3 of SdMmcOverrideProtocol Albecki, Mateusz
2019-06-14 3:14 ` Wu, Hao A
2019-06-18 15:14 ` Albecki, Mateusz
[not found] ` <15A7C8F163ADE317.25258@groups.io>
2019-06-17 15:11 ` [edk2-devel] " Albecki, Mateusz
2019-06-18 3:23 ` Wu, Hao A
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox