Date   

Re: USB hub port reset

Tian, Feng <feng.tian@...>
 

Hi, Baranee

Linux wait 10 + 40 ms (TRSTRCY = 10 ms, plus extra 40 ms). Do you mean EDKII should be same with linux to wait more time?

Thanks
Feng

From: Anbazhagan, Baraneedharan [mailto:anbazhagan@...]
Sent: Sunday, November 13, 2016 11:53 AM
To: edk2-devel@...; Tian, Feng <feng.tian@...>
Subject: USB hub port reset

EDK2 have reset recovery time of 10ms for hub port based on port status reset bit but USB spec doesn't mention that port status can be used for t6/reset recovery time. Could you please clarify?

USB vendor mentions EDK2 doesn't have reset recovery time on hub port reset and also highlighting EDK2 hub port reset differs from https://github.com/torvalds/linux/blob/master/drivers/usb/core/hub.c#L2789

-Baranee


Re: [PATCH] MdeModulePkg DxeCore: Show error message on unaligned FvImage issue

Yao, Jiewen
 

Ah, yes. Definitely.

I think it is a good idea to catch such issue as early as possible.

Thank you
Yao Jiewen

From: Kinney, Michael D
Sent: Monday, November 14, 2016 9:41 AM
To: Yao, Jiewen <jiewen.yao@...>; Zeng, Star <star.zeng@...>; edk2-devel@...; Kinney, Michael D <michael.d.kinney@...>
Cc: Yao, Jiewen <jiewen.yao@...>; Gao, Liming <liming.gao@...>; Zeng, Star <star.zeng@...>
Subject: RE: [PATCH] MdeModulePkg DxeCore: Show error message on unaligned FvImage issue

Jiewen,

Do you think it would be a good idea to add a similar DEBUG()
message in the HobLib when an FV HOBs are created? There are
other ways FV HOBs can be created, so I think the DEBUG() message
in this patch is very important, but getting a message when
the an FV HOB is created will make fixing the issue easier.

Thanks,

Mike

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@...] On Behalf Of Yao,
Jiewen
Sent: Sunday, November 13, 2016 5:28 PM
To: Zeng, Star <star.zeng@...<mailto:star.zeng@...>>; edk2-devel@...<mailto:edk2-devel@...>
Cc: Yao, Jiewen <jiewen.yao@...<mailto:jiewen.yao@...>>; Gao, Liming <liming.gao@...<mailto:liming.gao@...>>; Zeng,
Star <star.zeng@...<mailto:star.zeng@...>>
Subject: Re: [edk2] [PATCH] MdeModulePkg DxeCore: Show error message on unaligned
FvImage issue

Reviewed-by: jiewen.yao@...<mailto:jiewen.yao@...>



-----Original Message-----
From: Zeng, Star
Sent: Friday, November 11, 2016 1:59 PM
To: edk2-devel@...<mailto:edk2-devel@...>
Cc: Zeng, Star <star.zeng@...<mailto:star.zeng@...>>; Yao, Jiewen <jiewen.yao@...<mailto:jiewen.yao@...>>;
Gao, Liming <liming.gao@...<mailto:liming.gao@...>>
Subject: [PATCH] MdeModulePkg DxeCore: Show error message on
unaligned FvImage issue

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=205

Cc: Jiewen Yao <jiewen.yao@...<mailto:jiewen.yao@...>>
Cc: Liming Gao <liming.gao@...<mailto:liming.gao@...>>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@...<mailto:star.zeng@...>>
---
MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
b/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
index f031ef110c19..bc7b34140f84 100644
--- a/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
+++ b/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
@@ -4,7 +4,7 @@
It consumes FV HOBs and creates read-only Firmare Volume Block
protocol
instances for each of them.

-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made
available under the terms and conditions of the BSD License which
accompanies this distribution. The full text of the license may be found at
@@ -495,6 +495,13 @@ ProduceFVBProtocolOnBuffer (
//
// FvImage buffer is not at its required alignment.
//
+ DEBUG ((
+ DEBUG_ERROR,
+ "Unaligned FvImage found at 0x%lx:0x%lx, the required
alignment is 0x%x\n",
+ BaseAddress,
+ Length,
+ FvAlignment
+ ));
return EFI_VOLUME_CORRUPTED;
}
}
--
2.7.0.windows.1
_______________________________________________
edk2-devel mailing list
edk2-devel@...<mailto:edk2-devel@...>
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [PATCH v2 0/3] Put AP into safe hlt-loop code on S3 path

Yao, Jiewen
 

Yes. I think it is good to check in because it did fix an existing issue.
I suggest we describe the remaining issue honestly in our checkin log.

Thank you
Yao Jiewen

From: Fan, Jeff
Sent: Sunday, November 13, 2016 8:52 PM
To: Laszlo Ersek <lersek@...>
Cc: edk2-devel@...; Yao, Jiewen <jiewen.yao@...>; Paolo Bonzini <pbonzini@...>
Subject: RE: [edk2] [PATCH v2 0/3] Put AP into safe hlt-loop code on S3 path

Laszlo,

Thanks your testing. It seems that there is still some unknown issue existing.

I suggest to push this serial of patches firstly, because they have big progress to solve the AP crashed issue in https://bugzilla.tianocore.org/show_bug.cgi?id=216.

I could submit another bug to handle "AP lost" issue. Thus, JIewen's or others' patches could be push as long as they have no additional issue except for "AP Lost:".

I could follow up to fix "AP Lost" issue.

Thanks!
Jeff


-----Original Message-----
From: Laszlo Ersek [mailto:lersek@...]
Sent: Saturday, November 12, 2016 3:49 AM
To: Fan, Jeff
Cc: edk2-devel@...<mailto:edk2-devel@...>; Yao, Jiewen; Paolo Bonzini
Subject: Re: [edk2] [PATCH v2 0/3] Put AP into safe hlt-loop code on S3 path

On 11/11/16 06:45, Jeff Fan wrote:
On S3 path, we will wake up APs to restore CPU context in
PiSmmCpuDxeSmm driver. In case, one NMI or SMI happens, APs may exit
from hlt state and execute the instruction after HLT instruction.

But APs are not running on safe code, it leads OVMF S3 boot unstable.

https://bugzilla.tianocore.org/show_bug.cgi?id=216

I tested real platform with 64bit DXE.

v2:
1. Make stack alignment per Laszlo's comment.
2. Trim whitespace at end of end per Laszlo's comment.
3. Update year mark in file header.
4. Enhancement on InterlockedDecrement() per Paolo's comment.

Jeff Fan (3):
UefiCpuPkg/PiSmmCpuDxeSmm: Put AP into safe hlt-loop code on S3 path
UefiCpuPkg/PiSmmCpuDxeSmm: Place AP to 32bit protected mode on S3 path
UefiCpuPkg/PiSmmCpuDxeSmm: Decrease mNumberToFinish in AP safe code

UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c | 33 +++++++++++++-
UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c | 29 +++++++++++-
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h | 15 +++++++
UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c | 63
++++++++++++++++++++++++++-
4 files changed, 136 insertions(+), 4 deletions(-)
Applied this locally to master (ffd6b0b1b65e) for testing. I tested the series with a suspend-resume loop -- not a busy loop, just manually. (So there was always one second or so between adjacent steps.)

No crashes or emulation failures, but the "AP going lost" issue remains present -- sometimes Linux cannot bring up one of the four VCPUs after resume.

In the Ia32 case, this "AP lost" symptom surfaced after the 6th resume.

In the Ia32X64 case, I experienced the symptom after the 89th resume.

Thanks
Laszlo


Re: [PATCH] MdeModulePkg DxeCore: Show error message on unaligned FvImage issue

Michael D Kinney
 

Jiewen,

Do you think it would be a good idea to add a similar DEBUG()
message in the HobLib when an FV HOBs are created? There are
other ways FV HOBs can be created, so I think the DEBUG() message
in this patch is very important, but getting a message when
the an FV HOB is created will make fixing the issue easier.

Thanks,

Mike

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@...] On Behalf Of Yao,
Jiewen
Sent: Sunday, November 13, 2016 5:28 PM
To: Zeng, Star <star.zeng@...>; edk2-devel@...
Cc: Yao, Jiewen <jiewen.yao@...>; Gao, Liming <liming.gao@...>; Zeng,
Star <star.zeng@...>
Subject: Re: [edk2] [PATCH] MdeModulePkg DxeCore: Show error message on unaligned
FvImage issue

Reviewed-by: jiewen.yao@...



-----Original Message-----
From: Zeng, Star
Sent: Friday, November 11, 2016 1:59 PM
To: edk2-devel@...
Cc: Zeng, Star <star.zeng@...>; Yao, Jiewen <jiewen.yao@...>;
Gao, Liming <liming.gao@...>
Subject: [PATCH] MdeModulePkg DxeCore: Show error message on
unaligned FvImage issue

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=205

Cc: Jiewen Yao <jiewen.yao@...>
Cc: Liming Gao <liming.gao@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@...>
---
MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
b/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
index f031ef110c19..bc7b34140f84 100644
--- a/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
+++ b/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
@@ -4,7 +4,7 @@
It consumes FV HOBs and creates read-only Firmare Volume Block
protocol
instances for each of them.

-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made
available under the terms and conditions of the BSD License which
accompanies this distribution. The full text of the license may be found at
@@ -495,6 +495,13 @@ ProduceFVBProtocolOnBuffer (
//
// FvImage buffer is not at its required alignment.
//
+ DEBUG ((
+ DEBUG_ERROR,
+ "Unaligned FvImage found at 0x%lx:0x%lx, the required
alignment is 0x%x\n",
+ BaseAddress,
+ Length,
+ FvAlignment
+ ));
return EFI_VOLUME_CORRUPTED;
}
}
--
2.7.0.windows.1
_______________________________________________
edk2-devel mailing list
edk2-devel@...
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [PATCH 0/2] Place APs to suitable state on Legacy OS boot

Tian, Feng <feng.tian@...>
 

Reviewed-by: Feng Tian <feng.tian@...>

Thanks
Feng

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@...] On Behalf Of Jeff Fan
Sent: Friday, November 11, 2016 7:58 PM
To: edk2-devel@...
Subject: [edk2] [PATCH 0/2] Place APs to suitable state on Legacy OS boot

Currently, DxeMpLib only places APs into specified c-state in Exit Boot Service callback function for UEFI OS boot. We need to put APs into specified c-state for legacy OS boot also.

https://bugzilla.tianocore.org/show_bug.cgi?id=210

Jeff Fan (2):
UefiCpuPkg/DxeMpLib: Rename MpInitExitBootServicesCallback()
UefiCpuPkg/DxeMpLib: Place APs to suitable state on Legacy OS boot

UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 1 +
UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 18 +++++++++++++++---
2 files changed, 16 insertions(+), 3 deletions(-)

--
2.9.3.windows.2

_______________________________________________
edk2-devel mailing list
edk2-devel@...
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [PATCH] MdeModulePkg DxeCore: Show error message on unaligned FvImage issue

Yao, Jiewen
 

Reviewed-by: jiewen.yao@...



-----Original Message-----
From: Zeng, Star
Sent: Friday, November 11, 2016 1:59 PM
To: edk2-devel@...
Cc: Zeng, Star <star.zeng@...>; Yao, Jiewen <jiewen.yao@...>;
Gao, Liming <liming.gao@...>
Subject: [PATCH] MdeModulePkg DxeCore: Show error message on
unaligned FvImage issue

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=205

Cc: Jiewen Yao <jiewen.yao@...>
Cc: Liming Gao <liming.gao@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@...>
---
MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
b/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
index f031ef110c19..bc7b34140f84 100644
--- a/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
+++ b/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
@@ -4,7 +4,7 @@
It consumes FV HOBs and creates read-only Firmare Volume Block
protocol
instances for each of them.

-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made
available under the terms and conditions of the BSD License which
accompanies this distribution. The full text of the license may be found at
@@ -495,6 +495,13 @@ ProduceFVBProtocolOnBuffer (
//
// FvImage buffer is not at its required alignment.
//
+ DEBUG ((
+ DEBUG_ERROR,
+ "Unaligned FvImage found at 0x%lx:0x%lx, the required
alignment is 0x%x\n",
+ BaseAddress,
+ Length,
+ FvAlignment
+ ));
return EFI_VOLUME_CORRUPTED;
}
}
--
2.7.0.windows.1


Re: [PATCH v2 0/3] Put AP into safe hlt-loop code on S3 path

Fan, Jeff <jeff.fan@...>
 

Laszlo,

Thanks your testing. It seems that there is still some unknown issue existing.

I suggest to push this serial of patches firstly, because they have big progress to solve the AP crashed issue in https://bugzilla.tianocore.org/show_bug.cgi?id=216.

I could submit another bug to handle "AP lost" issue. Thus, JIewen's or others' patches could be push as long as they have no additional issue except for "AP Lost:".

I could follow up to fix "AP Lost" issue.

Thanks!
Jeff

-----Original Message-----
From: Laszlo Ersek [mailto:lersek@...]
Sent: Saturday, November 12, 2016 3:49 AM
To: Fan, Jeff
Cc: edk2-devel@...; Yao, Jiewen; Paolo Bonzini
Subject: Re: [edk2] [PATCH v2 0/3] Put AP into safe hlt-loop code on S3 path

On 11/11/16 06:45, Jeff Fan wrote:
On S3 path, we will wake up APs to restore CPU context in
PiSmmCpuDxeSmm driver. In case, one NMI or SMI happens, APs may exit
from hlt state and execute the instruction after HLT instruction.

But APs are not running on safe code, it leads OVMF S3 boot unstable.

https://bugzilla.tianocore.org/show_bug.cgi?id=216

I tested real platform with 64bit DXE.

v2:
1. Make stack alignment per Laszlo's comment.
2. Trim whitespace at end of end per Laszlo's comment.
3. Update year mark in file header.
4. Enhancement on InterlockedDecrement() per Paolo's comment.

Jeff Fan (3):
UefiCpuPkg/PiSmmCpuDxeSmm: Put AP into safe hlt-loop code on S3 path
UefiCpuPkg/PiSmmCpuDxeSmm: Place AP to 32bit protected mode on S3 path
UefiCpuPkg/PiSmmCpuDxeSmm: Decrease mNumberToFinish in AP safe code

UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c | 33 +++++++++++++-
UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c | 29 +++++++++++-
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h | 15 +++++++
UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c | 63
++++++++++++++++++++++++++-
4 files changed, 136 insertions(+), 4 deletions(-)
Applied this locally to master (ffd6b0b1b65e) for testing. I tested the series with a suspend-resume loop -- not a busy loop, just manually. (So there was always one second or so between adjacent steps.)

No crashes or emulation failures, but the "AP going lost" issue remains present -- sometimes Linux cannot bring up one of the four VCPUs after resume.

In the Ia32 case, this "AP lost" symptom surfaced after the 6th resume.

In the Ia32X64 case, I experienced the symptom after the 89th resume.

Thanks
Laszlo


[PATCH v5 9/9] PL180: update for indentifying SD

Haojian Zhuang <haojian.zhuang@...>
 

When CMD6 & ACMD51 are added into indentifying SD process, PL180
should also support CMD6 & ACMD51. Otherwise, it'll hang when
system tries to read expected data.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@...>
Tested-by: Ryan Harkin <ryan.harkin@...>
---
ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c | 29 ++++++++++++++++++++-------
1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
index 5526aac..b2ba4c0 100644
--- a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
+++ b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
@@ -63,11 +63,6 @@ MciIsReadOnly (
return (MmioRead32 (FixedPcdGet32 (PcdPL180SysMciRegAddress)) & SYS_MCI_WPROT);
}

-#if 0
-//Note: This function has been commented out because it is not used yet.
-// This function could be used to remove the hardcoded BlockLen used
-// in MciPrepareDataPath
-
// Convert block size to 2^n
STATIC
UINT32
@@ -87,7 +82,6 @@ GetPow2BlockLen (

return Pow2BlockLen;
}
-#endif

VOID
MciPrepareDataPath (
@@ -126,6 +120,23 @@ MciSendCommand (
MciPrepareDataPath (MCI_DATACTL_CARD_TO_CONT);
} else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {
MciPrepareDataPath (MCI_DATACTL_CONT_TO_CARD);
+ } else if (MmcCmd == MMC_CMD6) {
+ MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);
+ MmioWrite32 (MCI_DATA_LENGTH_REG, 64);
+#ifndef USE_STREAM
+ MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | GetPow2BlockLen (64));
+#else
+ MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | MCI_DATACTL_STREAM_TRANS);
+#endif
+ } else if (MmcCmd == MMC_ACMD51) {
+ MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);
+ /* SCR register is 8 bytes long. */
+ MmioWrite32 (MCI_DATA_LENGTH_REG, 8);
+#ifndef USE_STREAM
+ MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | GetPow2BlockLen (8));
+#else
+ MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | MCI_DATACTL_STREAM_TRANS);
+#endif
}

// Create Command for PL180
@@ -223,7 +234,11 @@ MciReadBlockData (

// Read data from the RX FIFO
Loop = 0;
- Finish = MMCI0_BLOCKLEN / 4;
+ if (Length < MMCI0_BLOCKLEN) {
+ Finish = Length / 4;
+ } else {
+ Finish = MMCI0_BLOCKLEN / 4;
+ }

// Raise the TPL at the highest level to disable Interrupts.
Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
--
2.7.4


[PATCH v5 8/9] MmcDxe: expand to support multiple blocks

Haojian Zhuang <haojian.zhuang@...>
 

Make use of DMA to transfer multiple blocks at one time. It could
improve the performance on MMC/SD driver.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@...>
Tested-by: Ryan Harkin <ryan.harkin@...>
---
EmbeddedPkg/Include/Protocol/MmcHost.h | 6 +
EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c | 177 ++++++++++++++++++++----------
2 files changed, 123 insertions(+), 60 deletions(-)

diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
index 5028045..cd5335a 100644
--- a/EmbeddedPkg/Include/Protocol/MmcHost.h
+++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
@@ -62,6 +62,7 @@ typedef UINT32 MMC_CMD;
#define MMC_CMD20 (MMC_INDX(20) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD23 (MMC_INDX(23) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD24 (MMC_INDX(24) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD25 (MMC_INDX(25) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD55 (MMC_INDX(55) | MMC_CMD_WAIT_RESPONSE)
#define MMC_ACMD41 (MMC_INDX(41) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)
#define MMC_ACMD51 (MMC_INDX(51) | MMC_CMD_WAIT_RESPONSE)
@@ -152,6 +153,10 @@ typedef EFI_STATUS (EFIAPI *MMC_SETIOS) (
IN UINT32 TimingMode
);

+typedef BOOLEAN (EFIAPI *MMC_ISMULTIBLOCK) (
+ IN EFI_MMC_HOST_PROTOCOL *This
+ );
+

struct _EFI_MMC_HOST_PROTOCOL {

@@ -169,6 +174,7 @@ struct _EFI_MMC_HOST_PROTOCOL {
MMC_WRITEBLOCKDATA WriteBlockData;

MMC_SETIOS SetIos;
+ MMC_ISMULTIBLOCK IsMultiBlock;

};

diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c b/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
index 0e1ef57..1fcb3b5 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
@@ -126,6 +126,95 @@ MmcStopTransmission (
#define MMCI0_BLOCKLEN 512
#define MMCI0_TIMEOUT 10000

+STATIC EFI_STATUS
+MmcTransferBlock (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINTN Cmd,
+ IN UINTN Transfer,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN CmdArg;
+ INTN Timeout;
+ UINT32 Response[4];
+ MMC_HOST_INSTANCE *MmcHostInstance;
+ EFI_MMC_HOST_PROTOCOL *MmcHost;
+
+ MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
+ MmcHost = MmcHostInstance->MmcHost;
+
+ //Set command argument based on the card access mode (Byte mode or Block mode)
+ if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {
+ CmdArg = Lba;
+ } else {
+ CmdArg = Lba * This->Media->BlockSize;
+ }
+
+ Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD%d): Error %r\n", __func__, Cmd, Status));
+ return Status;
+ }
+
+ if (Transfer == MMC_IOBLOCKS_READ) {
+ // Read Data
+ Status = MmcHost->ReadBlockData (MmcHost, Lba, BufferSize, Buffer);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_BLKIO, "%a(): Error Read Block Data and Status = %r\n", __func__, Status));
+ MmcStopTransmission (MmcHost);
+ return Status;
+ }
+ Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a() : Error MmcProgrammingState\n", __func__));
+ return Status;
+ }
+ } else {
+ // Write Data
+ Status = MmcHost->WriteBlockData (MmcHost, Lba, BufferSize, Buffer);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_BLKIO, "%a(): Error Write Block Data and Status = %r\n", __func__, Status));
+ MmcStopTransmission (MmcHost);
+ return Status;
+ }
+ }
+
+ // Command 13 - Read status and wait for programming to complete (return to tran)
+ Timeout = MMCI0_TIMEOUT;
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;
+ Response[0] = 0;
+ while(!(Response[0] & MMC_R0_READY_FOR_DATA)
+ && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
+ && Timeout--) {
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
+ if (!EFI_ERROR (Status)) {
+ MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
+ if (Response[0] & MMC_R0_READY_FOR_DATA) {
+ break; // Prevents delay once finished
+ }
+ }
+ gBS->Stall (1);
+ }
+
+ if (BufferSize > This->Media->BlockSize) {
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD12, 0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_BLKIO, "%a(): Error and Status:%r\n", __func__, Status));
+ }
+ }
+
+ Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));
+ return Status;
+ }
+ return Status;
+}
+
EFI_STATUS
MmcIoBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This,
@@ -145,6 +234,7 @@ MmcIoBlocks (
EFI_MMC_HOST_PROTOCOL *MmcHost;
UINTN BytesRemainingToBeTransfered;
UINTN BlockCount;
+ UINTN ConsumeSize;

BlockCount = 1;
MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
@@ -165,6 +255,10 @@ MmcIoBlocks (
return EFI_NO_MEDIA;
}

+ if (MmcHost->IsMultiBlock && MmcHost->IsMultiBlock(MmcHost)) {
+ BlockCount = (BufferSize + This->Media->BlockSize - 1) / This->Media->BlockSize;
+ }
+
// All blocks must be within the device
if ((Lba + (BufferSize / This->Media->BlockSize)) > (This->Media->LastBlock + 1)) {
return EFI_INVALID_PARAMETER;
@@ -196,7 +290,7 @@ MmcIoBlocks (
CmdArg = MmcHostInstance->CardInfo.RCA << 16;
Response[0] = 0;
Timeout = 20;
- while( (!(Response[0] & MMC_R0_READY_FOR_DATA))
+ while(!(Response[0] & MMC_R0_READY_FOR_DATA)
&& (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
&& Timeout--) {
Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
@@ -210,75 +304,38 @@ MmcIoBlocks (
return EFI_NOT_READY;
}

- //Set command argument based on the card access mode (Byte mode or Block mode)
- if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {
- CmdArg = Lba;
- } else {
- CmdArg = Lba * This->Media->BlockSize;
- }
-
if (Transfer == MMC_IOBLOCKS_READ) {
- // Read a single block
- Cmd = MMC_CMD17;
- } else {
- // Write a single block
- Cmd = MMC_CMD24;
- }
- Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "MmcIoBlocks(MMC_CMD%d): Error %r\n", Cmd, Status));
- return Status;
- }
-
- if (Transfer == MMC_IOBLOCKS_READ) {
- // Read one block of Data
- Status = MmcHost->ReadBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Read Block Data and Status = %r\n", Status));
- MmcStopTransmission (MmcHost);
- return Status;
- }
- Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcProgrammingState\n"));
- return Status;
+ if (BlockCount == 1) {
+ // Read a single block
+ Cmd = MMC_CMD17;
+ } else {
+ // Read multiple blocks
+ Cmd = MMC_CMD18;
}
} else {
- // Write one block of Data
- Status = MmcHost->WriteBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Write Block Data and Status = %r\n", Status));
- MmcStopTransmission (MmcHost);
- return Status;
+ if (BlockCount == 1) {
+ // Write a single block
+ Cmd = MMC_CMD24;
+ } else {
+ // Write multiple blocks
+ Cmd = MMC_CMD25;
}
}

- // Command 13 - Read status and wait for programming to complete (return to tran)
- Timeout = MMCI0_TIMEOUT;
- CmdArg = MmcHostInstance->CardInfo.RCA << 16;
- Response[0] = 0;
- while( (!(Response[0] & MMC_R0_READY_FOR_DATA))
- && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
- && Timeout--) {
- Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
- if (!EFI_ERROR (Status)) {
- MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
- if ((Response[0] & MMC_R0_READY_FOR_DATA)) {
- break; // Prevents delay once finished
- }
- }
- gBS->Stall (1);
+ ConsumeSize = BlockCount * This->Media->BlockSize;
+ if (BytesRemainingToBeTransfered < ConsumeSize) {
+ ConsumeSize = BytesRemainingToBeTransfered;
}
-
- Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
+ Status = MmcTransferBlock (This, Cmd, Transfer, MediaId, Lba, ConsumeSize, Buffer);
if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));
- return Status;
+ DEBUG ((EFI_D_ERROR, "%a(): Failed to transfer block and Status:%r\n", __func__, Status));
}

- BytesRemainingToBeTransfered -= This->Media->BlockSize;
- Lba += BlockCount;
- Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
+ BytesRemainingToBeTransfered -= ConsumeSize;
+ if (BytesRemainingToBeTransfered > 0) {
+ Lba += BlockCount;
+ Buffer = (UINT8 *)Buffer + ConsumeSize;
+ }
}

return EFI_SUCCESS;
--
2.7.4


[PATCH v5 7/9] MmcDxe: set iospeed and bus width in SD stack

Haojian Zhuang <haojian.zhuang@...>
 

Add more SD commands to support 4-bit bus width & iospeed. It's not
formal code. And it needs to be updated later.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@...>
Tested-by: Ryan Harkin <ryan.harkin@...>
---
EmbeddedPkg/Include/Protocol/MmcHost.h | 3 +
EmbeddedPkg/Universal/MmcDxe/Mmc.h | 17 +++
EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 138 ++++++++++++++++++++---
3 files changed, 142 insertions(+), 16 deletions(-)

diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
index 01c0bf4..5028045 100644
--- a/EmbeddedPkg/Include/Protocol/MmcHost.h
+++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
@@ -64,11 +64,14 @@ typedef UINT32 MMC_CMD;
#define MMC_CMD24 (MMC_INDX(24) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD55 (MMC_INDX(55) | MMC_CMD_WAIT_RESPONSE)
#define MMC_ACMD41 (MMC_INDX(41) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)
+#define MMC_ACMD51 (MMC_INDX(51) | MMC_CMD_WAIT_RESPONSE)

// Valid responses for CMD1 in eMMC
#define EMMC_CMD1_CAPACITY_LESS_THAN_2GB 0x00FF8080 // Capacity <= 2GB, byte addressing used
#define EMMC_CMD1_CAPACITY_GREATER_THAN_2GB 0x40FF8080 // Capacity > 2GB, 512-byte sector addressing used

+#define MMC_STATUS_APP_CMD (1 << 5)
+
typedef enum _MMC_STATE {
MmcInvalidState = 0,
MmcHwInitializationState,
diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
index 67f449c..f054bb2 100644
--- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
+++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
@@ -75,6 +75,23 @@ typedef struct {
UINT32 PowerUp: 1; // This bit is set to LOW if the card has not finished the power up routine
} OCR;

+/* For little endian CPU */
+typedef struct {
+ UINT8 SD_SPEC: 4; // SD Memory Card - Spec. Version [59:56]
+ UINT8 SCR_STRUCTURE: 4; // SCR Structure [63:60]
+ UINT8 SD_BUS_WIDTHS: 4; // DAT Bus widths supported [51:48]
+ UINT8 DATA_STAT_AFTER_ERASE: 1; // Data Status after erases [55]
+ UINT8 SD_SECURITY: 3; // CPRM Security Support [54:52]
+ UINT8 EX_SECURITY_1: 1; // Extended Security Support [43]
+ UINT8 SD_SPEC4: 1; // Spec. Version 4.00 or higher [42]
+ UINT8 RESERVED_1: 2; // Reserved [41:40]
+ UINT8 SD_SPEC3: 1; // Spec. Version 3.00 or higher [47]
+ UINT8 EX_SECURITY_2: 3; // Extended Security Support [46:44]
+ UINT8 CMD_SUPPORT: 4; // Command Support bits [35:32]
+ UINT8 RESERVED_2: 4; // Reserved [39:36]
+ UINT32 RESERVED_3; // Manufacturer Usage [31:0]
+} SCR;
+
typedef struct {
UINT32 NOT_USED; // 1 [0:0]
UINT32 CRC; // CRC7 checksum [7:1]
diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index 9a79767..c469dda 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -12,6 +12,9 @@
*
**/

+#include <Library/BaseMemoryLib.h>
+#include <Library/TimerLib.h>
+
#include "Mmc.h"

typedef union {
@@ -41,6 +44,11 @@ typedef union {

#define EMMC_SWITCH_ERROR (1 << 7)

+#define SD_BUS_WIDTH_1BIT (1 << 0)
+#define SD_BUS_WIDTH_4BIT (1 << 2)
+
+#define SD_CCC_SWITCH (1 << 10)
+
#define DEVICE_STATE(x) (((x) >> 9) & 0xf)
typedef enum _EMMC_DEVICE_STATE {
EMMC_IDLE_STATE = 0,
@@ -68,28 +76,30 @@ EmmcGetDeviceState (
{
EFI_MMC_HOST_PROTOCOL *Host;
EFI_STATUS Status;
- UINT32 Data, RCA;
+ UINT32 Rsp[4], RCA;

if (State == NULL)
return EFI_INVALID_PARAMETER;

Host = MmcHostInstance->MmcHost;
RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;
- Status = Host->SendCommand (Host, MMC_CMD13, RCA);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status));
- return Status;
- }
- Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, &Data);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status));
- return Status;
- }
- if (Data & EMMC_SWITCH_ERROR) {
- DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status));
- return EFI_DEVICE_ERROR;
- }
- *State = DEVICE_STATE(Data);
+ do {
+ Status = Host->SendCommand (Host, MMC_CMD13, RCA);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status));
+ return Status;
+ }
+ Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, Rsp);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status));
+ return Status;
+ }
+ if (Rsp[0] & EMMC_SWITCH_ERROR) {
+ DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status));
+ return EFI_DEVICE_ERROR;
+ }
+ } while (!(Rsp[0] & MMC_R0_READY_FOR_DATA));
+ *State = MMC_R0_CURRENTSTATE(Rsp);
return EFI_SUCCESS;
}

@@ -300,9 +310,12 @@ InitializeSdMmcDevice (
{
UINT32 CmdArg;
UINT32 Response[4];
+ UINT32 Buffer[128];
UINTN BlockSize;
UINTN CardSize;
UINTN NumBlocks;
+ BOOLEAN CccSwitch;
+ SCR Scr;
EFI_STATUS Status;
EFI_MMC_HOST_PROTOCOL *MmcHost;

@@ -323,6 +336,10 @@ InitializeSdMmcDevice (
return Status;
}
PrintCSD (Response);
+ if (MMC_CSD_GET_CCC(Response) & SD_CCC_SWITCH)
+ CccSwitch = TRUE;
+ else
+ CccSwitch = FALSE;

if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {
CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response);
@@ -353,6 +370,95 @@ InitializeSdMmcDevice (
return Status;
}

+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
+ return Status;
+ }
+ Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
+ return Status;
+ }
+ if ((Response[0] & MMC_STATUS_APP_CMD) == 0)
+ return EFI_SUCCESS;
+
+ /* SCR */
+ Status = MmcHost->SendCommand (MmcHost, MMC_ACMD51, 0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): Error and Status = %r\n", __func__, Status));
+ return Status;
+ } else {
+ Status = MmcHost->ReadBlockData (MmcHost, 0, 8, Buffer);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): ReadBlockData Error and Status = %r\n", __func__, Status));
+ return Status;
+ }
+ CopyMem (&Scr, Buffer, 8);
+ if (Scr.SD_SPEC == 2) {
+ if (Scr.SD_SPEC3 == 1) {
+ if (Scr.SD_SPEC4 == 1) {
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 4.xx\n"));
+ } else {
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 3.0x\n"));
+ }
+ } else {
+ if (Scr.SD_SPEC4 == 0) {
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 2.0\n"));
+ } else {
+ DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));
+ }
+ }
+ } else {
+ if ((Scr.SD_SPEC3 == 0) && (Scr.SD_SPEC4 == 0)) {
+ if (Scr.SD_SPEC == 1) {
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.10\n"));
+ } else {
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.0\n"));
+ }
+ } else {
+ DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));
+ }
+ }
+ }
+ if (CccSwitch) {
+ /* SD Switch, Mode:1, Group:0, Value:1 */
+ CmdArg = 1 << 31 | 0x00FFFFFF;
+ CmdArg &= ~(0xF << (0 * 4));
+ CmdArg |= 1 << (0 * 4);
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): Error and Status = %r\n", Status));
+ return Status;
+ } else {
+ Status = MmcHost->ReadBlockData (MmcHost, 0, 64, Buffer);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): ReadBlockData Error and Status = %r\n", Status));
+ return Status;
+ }
+ }
+ }
+ if (Scr.SD_BUS_WIDTHS & SD_BUS_WIDTH_4BIT) {
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
+ return Status;
+ }
+ /* Width: 4 */
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, 2);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): Error and Status = %r\n", Status));
+ return Status;
+ }
+ }
+ if (MmcHost->SetIos) {
+ Status = MmcHost->SetIos (MmcHost, 24 * 1000 * 1000, 4, EMMCBACKWARD);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(SetIos): Error and Status = %r\n", Status));
+ return Status;
+ }
+ }
return EFI_SUCCESS;
}

--
2.7.4


[PATCH v5 6/9] MmcDxe: set io bus width before reading EXTCSD

Haojian Zhuang <haojian.zhuang@...>
 

Set io bus width on both MMC controller and EXTCSD. Otherwise, it may
cause unmatched failure case. And support more timing mode, high speed,
HS200 & HS400 mode.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@...>
Tested-by: Ryan Harkin <ryan.harkin@...>
---
EmbeddedPkg/Include/Protocol/MmcHost.h | 16 +-
EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 229 ++++++++++++++++++++---
2 files changed, 221 insertions(+), 24 deletions(-)

diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
index a242291..01c0bf4 100644
--- a/EmbeddedPkg/Include/Protocol/MmcHost.h
+++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
@@ -49,6 +49,7 @@ typedef UINT32 MMC_CMD;
#define MMC_CMD2 (MMC_INDX(2) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)
#define MMC_CMD3 (MMC_INDX(3) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD5 (MMC_INDX(5) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)
+#define MMC_CMD6 (MMC_INDX(6) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD7 (MMC_INDX(7) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD8 (MMC_INDX(8) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD9 (MMC_INDX(9) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)
@@ -82,6 +83,16 @@ typedef enum _MMC_STATE {
MmcDisconnectState,
} MMC_STATE;

+#define EMMCBACKWARD (0)
+#define EMMCHS26 (1 << 0) // High-Speed @26MHz at rated device voltages
+#define EMMCHS52 (1 << 1) // High-Speed @52MHz at rated device voltages
+#define EMMCHS52DDR1V8 (1 << 2) // High-Speed Dual Data Rate @52MHz 1.8V or 3V I/O
+#define EMMCHS52DDR1V2 (1 << 3) // High-Speed Dual Data Rate @52MHz 1.2V I/O
+#define EMMCHS200SDR1V8 (1 << 4) // HS200 Single Data Rate @200MHz 1.8V I/O
+#define EMMCHS200SDR1V2 (1 << 5) // HS200 Single Data Rate @200MHz 1.2V I/O
+#define EMMCHS400DDR1V8 (1 << 6) // HS400 Dual Data Rate @400MHz 1.8V I/O
+#define EMMCHS400DDR1V2 (1 << 7) // HS400 Dual Data Rate @400MHz 1.2V I/O
+
///
/// Forward declaration for EFI_MMC_HOST_PROTOCOL
///
@@ -133,8 +144,9 @@ typedef EFI_STATUS (EFIAPI *MMC_WRITEBLOCKDATA) (

typedef EFI_STATUS (EFIAPI *MMC_SETIOS) (
IN EFI_MMC_HOST_PROTOCOL *This,
- IN UINT32 BusClockRate,
- IN UINT32 BusWidth
+ IN UINT32 BusClockFreq,
+ IN UINT32 BusWidth,
+ IN UINT32 TimingMode
);


diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index 378e438..9a79767 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -25,11 +25,109 @@ typedef union {
#define EMMC_CARD_SIZE 512
#define EMMC_ECSD_SIZE_OFFSET 53

+#define EXTCSD_BUS_WIDTH 183
+#define EXTCSD_HS_TIMING 185
+
+#define EMMC_TIMING_BACKWARD 0
+#define EMMC_TIMING_HS 1
+#define EMMC_TIMING_HS200 2
+#define EMMC_TIMING_HS400 3
+
+#define EMMC_BUS_WIDTH_1BIT 0
+#define EMMC_BUS_WIDTH_4BIT 1
+#define EMMC_BUS_WIDTH_8BIT 2
+#define EMMC_BUS_WIDTH_DDR_4BIT 5
+#define EMMC_BUS_WIDTH_DDR_8BIT 6
+
+#define EMMC_SWITCH_ERROR (1 << 7)
+
+#define DEVICE_STATE(x) (((x) >> 9) & 0xf)
+typedef enum _EMMC_DEVICE_STATE {
+ EMMC_IDLE_STATE = 0,
+ EMMC_READY_STATE,
+ EMMC_IDENT_STATE,
+ EMMC_STBY_STATE,
+ EMMC_TRAN_STATE,
+ EMMC_DATA_STATE,
+ EMMC_RCV_STATE,
+ EMMC_PRG_STATE,
+ EMMC_DIS_STATE,
+ EMMC_BTST_STATE,
+ EMMC_SLP_STATE
+} EMMC_DEVICE_STATE;
+
UINT32 mEmmcRcaCount = 0;

STATIC
EFI_STATUS
EFIAPI
+EmmcGetDeviceState (
+ IN MMC_HOST_INSTANCE *MmcHostInstance,
+ OUT EMMC_DEVICE_STATE *State
+ )
+{
+ EFI_MMC_HOST_PROTOCOL *Host;
+ EFI_STATUS Status;
+ UINT32 Data, RCA;
+
+ if (State == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ Host = MmcHostInstance->MmcHost;
+ RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;
+ Status = Host->SendCommand (Host, MMC_CMD13, RCA);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status));
+ return Status;
+ }
+ Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, &Data);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status));
+ return Status;
+ }
+ if (Data & EMMC_SWITCH_ERROR) {
+ DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status));
+ return EFI_DEVICE_ERROR;
+ }
+ *State = DEVICE_STATE(Data);
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+EmmcSetEXTCSD (
+ IN MMC_HOST_INSTANCE *MmcHostInstance,
+ UINT32 ExtCmdIndex,
+ UINT32 Value
+ )
+{
+ EFI_MMC_HOST_PROTOCOL *Host;
+ EMMC_DEVICE_STATE State;
+ EFI_STATUS Status;
+ UINT32 Argument;
+
+ Host = MmcHostInstance->MmcHost;
+ Argument = (3 << 24) | ((ExtCmdIndex & 0xff) << 16) | ((Value & 0xff) << 8) | 1;
+ Status = Host->SendCommand (Host, MMC_CMD6, Argument);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcSetEXTCSD(): Failed to send CMD6, Status=%r.\n", Status));
+ return Status;
+ }
+ // Make sure device exiting prog mode
+ do {
+ Status = EmmcGetDeviceState (MmcHostInstance, &State);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcSetEXTCSD(): Failed to get device state, Status=%r.\n", Status));
+ return Status;
+ }
+ } while (State == EMMC_PRG_STATE);
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
EmmcIdentificationMode (
IN MMC_HOST_INSTANCE *MmcHostInstance,
IN OCR_RESPONSE Response
@@ -37,6 +135,7 @@ EmmcIdentificationMode (
{
EFI_MMC_HOST_PROTOCOL *Host;
EFI_BLOCK_IO_MEDIA *Media;
+ EMMC_DEVICE_STATE State;
EFI_STATUS Status;
UINT32 RCA;

@@ -84,35 +183,117 @@ EmmcIdentificationMode (
DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Card selection error, Status=%r.\n", Status));
}

- // Fetch ECSD
- Status = Host->SendCommand (Host, MMC_CMD8, RCA);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));
- }
-
- Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)&(MmcHostInstance->CardInfo.ECSDData));
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));
- return Status;
- }
-
+ // MMC v4 specific
+ if (MmcHostInstance->CardInfo.CSDData.SPEC_VERS == 4) {
+ if (Host->SetIos) {
+ // Set 1-bit bus width
+ Status = Host->SetIos (Host, 0, 1, EMMCBACKWARD);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set 1-bit bus width error, Status=%r.\n", Status));
+ return Status;
+ }
+
+ // Set 1-bit bus width for EXTCSD
+ Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_1BIT);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set extcsd bus width error, Status=%r.\n", Status));
+ return Status;
+ }
+ }
+
+ // Fetch ECSD
+ Status = Host->SendCommand (Host, MMC_CMD8, RCA);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));
+ }
+ Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)&(MmcHostInstance->CardInfo.ECSDData));
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));
+ return Status;
+ }
+
+ // Make sure device exiting data mode
+ do {
+ Status = EmmcGetDeviceState (MmcHostInstance, &State);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to get device state, Status=%r.\n", Status));
+ return Status;
+ }
+ } while (State == EMMC_DATA_STATE);
+
+ // Compute last block using bits [215:212] of the ECSD
+ Media->LastBlock = MmcHostInstance->CardInfo.ECSDData.SECTOR_COUNT - 1; // eMMC isn't supposed to report this for
+ // Cards <2GB in size, but the model does.
+
+ // Setup card type
+ MmcHostInstance->CardInfo.CardType = EMMC_CARD;
+ }
// Set up media
Media->BlockSize = EMMC_CARD_SIZE; // 512-byte support is mandatory for eMMC cards
Media->MediaId = MmcHostInstance->CardInfo.CIDData.PSN;
Media->ReadOnly = MmcHostInstance->CardInfo.CSDData.PERM_WRITE_PROTECT;
Media->LogicalBlocksPerPhysicalBlock = 1;
Media->IoAlign = 4;
- // Compute last block using bits [215:212] of the ECSD
- Media->LastBlock = MmcHostInstance->CardInfo.ECSDData.SECTOR_COUNT - 1; // eMMC isn't supposed to report this for
- // Cards <2GB in size, but the model does.
-
- // Setup card type
- MmcHostInstance->CardInfo.CardType = EMMC_CARD;
return EFI_SUCCESS;
}

STATIC
EFI_STATUS
+InitializeEmmcDevice (
+ IN MMC_HOST_INSTANCE *MmcHostInstance
+ )
+{
+ EFI_MMC_HOST_PROTOCOL *Host;
+ EFI_STATUS Status = EFI_SUCCESS;
+ ECSD *ECSDData;
+ BOOLEAN Found = FALSE;
+ UINT32 BusClockFreq, Idx;
+ UINT32 TimingMode[4] = {EMMCHS52DDR1V2, EMMCHS52DDR1V8, EMMCHS52, EMMCHS26};
+
+ Host = MmcHostInstance->MmcHost;
+ if (MmcHostInstance->CardInfo.CSDData.SPEC_VERS < 4)
+ return EFI_SUCCESS;
+ ECSDData = &MmcHostInstance->CardInfo.ECSDData;
+ if (ECSDData->DEVICE_TYPE == EMMCBACKWARD)
+ return EFI_SUCCESS;
+
+ if (Host->SetIos) {
+ Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_HS_TIMING, EMMC_TIMING_HS);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to switch high speed mode, Status:%r.\n", Status));
+ return Status;
+ }
+
+ for (Idx = 0; Idx < 4; Idx++) {
+ switch (TimingMode[Idx]) {
+ case EMMCHS52DDR1V2:
+ case EMMCHS52DDR1V8:
+ case EMMCHS52:
+ BusClockFreq = 52000000;
+ break;
+ case EMMCHS26:
+ BusClockFreq = 26000000;
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ Status = Host->SetIos (Host, BusClockFreq, 8, TimingMode[Idx]);
+ if (!EFI_ERROR (Status)) {
+ Found = TRUE;
+ break;
+ }
+ }
+ if (Found) {
+ Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_DDR_8BIT);
+ if (EFI_ERROR (Status))
+ DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to set EXTCSD bus width, Status:%r\n", Status));
+ }
+ }
+ return Status;
+}
+
+STATIC
+EFI_STATUS
InitializeSdMmcDevice (
IN MMC_HOST_INSTANCE *MmcHostInstance
)
@@ -429,11 +610,15 @@ InitializeMmcDevice (
return Status;
}

- if (MmcHostInstance->CardInfo.CardType != EMMC_CARD) {
- Status = InitializeSdMmcDevice (MmcHostInstance);
- if (EFI_ERROR (Status)) {
- return Status;
+ if (MmcHostInstance->CardInfo.CardType == EMMC_CARD) {
+ if (MmcHost->SetIos) {
+ Status = InitializeEmmcDevice (MmcHostInstance);
}
+ } else {
+ Status = InitializeSdMmcDevice (MmcHostInstance);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
}

// Set Block Length
--
2.7.4


[PATCH v5 5/9] MmcDxe: add interface to change io width and speed

Haojian Zhuang <haojian.zhuang@...>
 

By default, MMC is initialized with 1-bit mode and less than 400KHz bus
clock. It causes MMC working inefficiently.

Add the interface to change the bus width and speed.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@...>
Tested-by: Ryan Harkin <ryan.harkin@...>
---
EmbeddedPkg/Include/Protocol/MmcHost.h | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
index 89f2e80..a242291 100644
--- a/EmbeddedPkg/Include/Protocol/MmcHost.h
+++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
@@ -131,6 +131,12 @@ typedef EFI_STATUS (EFIAPI *MMC_WRITEBLOCKDATA) (
IN UINT32 *Buffer
);

+typedef EFI_STATUS (EFIAPI *MMC_SETIOS) (
+ IN EFI_MMC_HOST_PROTOCOL *This,
+ IN UINT32 BusClockRate,
+ IN UINT32 BusWidth
+ );
+

struct _EFI_MMC_HOST_PROTOCOL {

@@ -147,6 +153,8 @@ struct _EFI_MMC_HOST_PROTOCOL {
MMC_READBLOCKDATA ReadBlockData;
MMC_WRITEBLOCKDATA WriteBlockData;

+ MMC_SETIOS SetIos;
+
};

#define MMC_HOST_PROTOCOL_REVISION 0x00010001 // 1.1
--
2.7.4


[PATCH v5 4/9] MmcDxe: add SPEC_VERS field in CSD structure

Haojian Zhuang <haojian.zhuang@...>
 

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@...>
Tested-by: Ryan Harkin <ryan.harkin@...>
Reviewed-by: Leif Lindholm <leif.lindholm@...>
---
EmbeddedPkg/Universal/MmcDxe/Mmc.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
index 25c69ae..67f449c 100644
--- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
+++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
@@ -128,7 +128,8 @@ typedef struct {
UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
UINT8 TAAC ; // Data read access-time 1 [119:112]

- UINT8 RESERVED_5: 6; // Reserved [125:120]
+ UINT8 RESERVED_5: 2; // Reserved [121:120]
+ UINT8 SPEC_VERS: 4; // System specification version [125:122]
UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]
} CSD;

--
2.7.4


[PATCH v5 3/9] MmcDxe: declare ECSD structure

Haojian Zhuang <haojian.zhuang@...>
 

Declare fields in ECSD structure. And drop the original 128 words
arrary.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@...>
Tested-by: Ryan Harkin <ryan.harkin@...>
Reviewed-by: Leif Lindholm <leif.lindholm@...>
---
EmbeddedPkg/Universal/MmcDxe/Mmc.h | 157 ++++++++++++++++++++++-
EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 4 +-
2 files changed, 158 insertions(+), 3 deletions(-)

diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
index 4f132c6..25c69ae 100644
--- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
+++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
@@ -132,13 +132,168 @@ typedef struct {
UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]
} CSD;

+typedef struct {
+ UINT8 RESERVED_1[16]; // Reserved [15:0]
+ UINT8 SECURE_REMOVAL_TYPE; // Secure Removal Type [16:16]
+ UINT8 PRODUCT_STATE_AWARENESS_ENABLEMENT; // Product state awareness enablement [17:17]
+ UINT8 MAX_PRE_LOADING_DATA_SIZE[4]; // MAX pre loading data size [21:18]
+ UINT8 PRE_LOADING_DATA_SIZE[4]; // Pre loading data size [25:22]
+ UINT8 FFU_STATUS; // FFU Status [26:26]
+ UINT8 RESERVED_2[2]; // Reserved [28:27]
+ UINT8 MODE_OPERATION_CODES; // Mode operation codes [29:29]
+ UINT8 MODE_CONFIG; // Mode config [30:30]
+ UINT8 RESERVED_3; // Reserved [31:31]
+ UINT8 FLUSH_CACHE; // Flushing of the cache [32:32]
+ UINT8 CACHE_CTRL; // Control to turn the cache ON/OFF [33:33]
+ UINT8 POWER_OFF_NOTIFICATION; // Power Off Notification [34:34]
+ UINT8 PACKED_FAILURE_INDEX; // Packed command failure index [35:35]
+ UINT8 PACKED_COMMAND_STATUS; // Packed command status [36:36]
+ UINT8 CONTEXT_CONF[15]; // Context configuration [51:37]
+ UINT8 EXT_PARTITIONS_ATTRIBUTE[2]; // Extended partitions attribute [53:52]
+ UINT8 EXCEPTION_EVENTS_STATUS[2]; // Exception events status [55:54]
+ UINT8 EXCEPTION_EVENTS_CTRL[2]; // Exception events control [57:56]
+ UINT8 DYNCAP_NEEDED; // Number of addressed group to be released [58:58]
+ UINT8 CLASS_6_CTRL; // Class 6 commands control [59:59]
+ UINT8 INI_TIMEOUT_EMU; // 1st initialization after disabling sector size emulation [60:60]
+ UINT8 DATA_SECTOR_SIZE; // Sector size [61:61]
+ UINT8 USE_NATIVE_SECTOR; // Sector size emulation [62:62]
+ UINT8 NATIVE_SECTOR_SIZE; // Native sector size [63:63]
+ UINT8 VENDOR_SPECIFIC_FIELD[64]; // Vendor specific fields [127:64]
+ UINT8 RESERVED_4[2]; // Reserved [129:128]
+ UINT8 PROGRAM_CID_CSD_DDR_SUPPORT; // Program CID/CSD in DDR mode support [130:130]
+ UINT8 PERIODIC_WAKEUP; // Periodic wake-up [131:131]
+ UINT8 TCASE_SUPPORT; // Package case temperature is controlled [132:132]
+ UINT8 PRODUCTION_STATE_AWARENESS; // Production state awareness [133:133]
+ UINT8 SECTOR_BAD_BLK_MGMNT; // Bad block management mode [134:134]
+ UINT8 RESERVED_5; // Reserved [135:135]
+ UINT8 ENH_START_ADDR[4]; // Enhanced user data start address [139:136]
+ UINT8 ENH_SIZE_MULT[3]; // Enhanced user data area size [142:140]
+ UINT8 GP_SIZE_MULT[12]; // General purpose partition size [154:143]
+ UINT8 PARTITION_SETTING_COMPLETED; // Partitioning setting [155:155]
+ UINT8 PARTITIONS_ATTRIBUTE; // Partitions attribute [156:156]
+ UINT8 MAX_ENH_SIZE_MULT[3]; // Max enhanced area size [159:157]
+ UINT8 PARTITIONING_SUPPORT; // Partitioning [160:160]
+ UINT8 HPI_MGMT; // HPI management [161:161]
+ UINT8 RST_N_FUNCTION; // H/W reset function [162:162]
+ UINT8 BKOPS_EN; // Enable background operations handshake [163:163]
+ UINT8 BKOPS_START; // Manually start background operations [164:164]
+ UINT8 SANITIZE_START; // Start sanitize operation [165:165]
+ UINT8 WR_REL_PARAM; // Write reliability parameter register [166:166]
+ UINT8 WR_REL_SET; // Write reliability setting register [167:167]
+ UINT8 RPMB_SIZE_MULT; // RPMB size [168:168]
+ UINT8 FW_CONFIG; // FW configuration [169:169]
+ UINT8 RESERVED_6; // Reserved [170:170]
+ UINT8 USER_WP; // User area write protection register [171:171]
+ UINT8 RESERVED_7; // Reserved [172:172]
+ UINT8 BOOT_WP; // Boot area write protection register [173:173]
+ UINT8 BOOT_WP_STATUS; // Boot write protection register [174:174]
+ UINT8 ERASE_GROUP_DEF; // High-density erase group definition [175:175]
+ UINT8 RESERVED_8; // Reserved [176:176]
+ UINT8 BOOT_BUS_CONDITIONS; // Boot bus conditions [177:177]
+ UINT8 BOOT_CONFIG_PROT; // Boot config protection [178:178]
+ UINT8 PARTITION_CONFIG; // Partition config [179:179]
+ UINT8 RESERVED_9; // Reserved [180:180]
+ UINT8 ERASED_MEM_CONT; // Erased memory content [181:181]
+ UINT8 RESERVED_10; // Reserved [182:182]
+ UINT8 BUS_WIDTH; // Bus width mode [183:183]
+ UINT8 RESERVED_11; // Reserved [184:184]
+ UINT8 HS_TIMING; // High-speed interface timing [185:185]
+ UINT8 RESERVED_12; // Reserved [186:186]
+ UINT8 POWER_CLASS; // Power class [187:187]
+ UINT8 RESERVED_13; // Reserved [188:188]
+ UINT8 CMD_SET_REV; // Command set revision [189:189]
+ UINT8 RESERVED_14; // Reserved [190:190]
+ UINT8 CMD_SET; // Command set [191:191]
+ UINT8 EXT_CSD_REV; // Extended CSD revision [192:192]
+ UINT8 RESERVED_15; // Reserved [193:193]
+ UINT8 CSD_STRUCTURE; // CSD Structure [194:194]
+ UINT8 RESERVED_16; // Reserved [195:195]
+ UINT8 DEVICE_TYPE; // Device type [196:196]
+ UINT8 DRIVER_STRENGTH; // I/O Driver strength [197:197]
+ UINT8 OUT_OF_INTERRUPT_TIME; // Out-of-interrupt busy timing [198:198]
+ UINT8 PARTITION_SWITCH_TIME; // Partition switching timing [199:199]
+ UINT8 PWR_CL_52_195; // Power class for 52MHz at 1.95V 1 R [200:200]
+ UINT8 PWR_CL_26_195; // Power class for 26MHz at 1.95V 1 R [201:201]
+ UINT8 PWR_CL_52_360; // Power class for 52MHz at 3.6V 1 R [202:202]
+ UINT8 PWR_CL_26_360; // Power class for 26MHz at 3.6V 1 R [203:203]
+ UINT8 RESERVED_17; // Reserved [204:204]
+ UINT8 MIN_PERF_R_4_26; // Minimum read performance for 4bit at 26MHz [205:205]
+ UINT8 MIN_PERF_W_4_26; // Minimum write performance for 4bit at 26MHz [206:206]
+ UINT8 MIN_PERF_R_8_26_4_52; // Minimum read performance for 8bit at 26MHz, for 4bit at 52MHz [207:207]
+ UINT8 MIN_PERF_W_8_26_4_52; // Minimum write performance for 8bit at 26MHz, for 4bit at 52MHz [208:208]
+ UINT8 MIN_PERF_R_8_52; // Minimum read performance for 8bit at 52MHz [209:209]
+ UINT8 MIN_PERF_W_8_52; // Minimum write performance for 8bit at 52MHz [210:210]
+ UINT8 RESERVED_18; // Reserved [211:211]
+ UINT32 SECTOR_COUNT; // Sector count [215:212]
+ UINT8 SLEEP_NOTIFICATION_TIME; // Sleep notification timout [216:216]
+ UINT8 S_A_TIMEOUT; // Sleep/awake timeout [217:217]
+ UINT8 PRODUCTION_STATE_AWARENESS_TIMEOUT; // Production state awareness timeout [218:218]
+ UINT8 S_C_VCCQ; // Sleep current (VCCQ) [219:219]
+ UINT8 S_C_VCC; // Sleep current (VCC) [220:220]
+ UINT8 HC_WP_GRP_SIZE; // High-capacity write protect group size [221:221]
+ UINT8 REL_WR_SECTOR_C; // Reliable write sector count [222:222]
+ UINT8 ERASE_TIMEOUT_MULT; // High-capacity erase timeout [223:223]
+ UINT8 HC_ERASE_GRP_SIZE; // High-capacity erase unit size [224:224]
+ UINT8 ACC_SIZE; // Access size [225:225]
+ UINT8 BOOT_SIZE_MULTI; // Boot partition size [226:226]
+ UINT8 RESERVED_19; // Reserved [227:227]
+ UINT8 BOOT_INFO; // Boot information [228:228]
+ UINT8 SECURE_TRIM_MULT; // Secure TRIM Multiplier [229:229]
+ UINT8 SECURE_ERASE_MULT; // Secure Erase Multiplier [230:230]
+ UINT8 SECURE_FEATURE_SUPPORT; // Secure Feature Support [231:231]
+ UINT8 TRIM_MULT; // TRIM Multiplier [232:232]
+ UINT8 RESERVED_20; // Reserved [233:233]
+ UINT8 MIN_PREF_DDR_R_8_52; // Minimum read performance for 8bit at 52MHz in DDR mode [234:234]
+ UINT8 MIN_PREF_DDR_W_8_52; // Minimum write performance for 8bit at 52MHz in DDR mode [235:235]
+ UINT8 PWR_CL_200_130; // Power class for 200MHz at VCCQ=1.3V, VCC=3.6V [236:236]
+ UINT8 PWR_CL_200_195; // Power class for 200MHz at VCCQ=1.95V, VCC=3.6V [237:237]
+ UINT8 PWR_CL_DDR_52_195; // Power class for 52MHz, DDR at 1.95V [238:238]
+ UINT8 PWR_CL_DDR_52_360; // Power class for 52Mhz, DDR at 3.6V [239:239]
+ UINT8 RESERVED_21; // Reserved [240:240]
+ UINT8 INI_TIMEOUT_AP; // 1st initialization time after partitioning [241:241]
+ UINT8 CORRECTLY_PRG_SECTORS_NUM[4]; // Number of correctly programmed sectors [245:242]
+ UINT8 BKOPS_STATUS; // Background operations status [246:246]
+ UINT8 POWER_OFF_LONG_TIME; // Power off notification (long) timeout [247:247]
+ UINT8 GENERIC_CMD6_TIME; // Generic CMD6 timeout [248:248]
+ UINT8 CACHE_SIZE[4]; // Cache size [252:249]
+ UINT8 PWR_CL_DDR_200_360; // Power class for 200MHz, DDR at VCC=3.6V [253:253]
+ UINT8 FIRMWARE_VERSION[8]; // Firmware version [261:254]
+ UINT8 DEVICE_VERSION[2]; // Device version [263:262]
+ UINT8 OPTIMAL_TRIM_UNIT_SIZE; // Optimal trim unit size [264:264]
+ UINT8 OPTIMAL_WRITE_SIZE; // Optimal write size [265:265]
+ UINT8 OPTIMAL_READ_SIZE; // Optimal read size [266:266]
+ UINT8 PRE_EOL_INFO; // Pre EOL information [267:267]
+ UINT8 DEVICE_LIFE_TIME_EST_TYP_A; // Device life time estimation type A [268:268]
+ UINT8 DEVICE_LIFE_TIME_EST_TYP_B; // Device life time estimation type B [269:269]
+ UINT8 VENDOR_PROPRIETARY_HEALTH_REPORT[32]; // Vendor proprietary health report [301:270]
+ UINT8 NUMBER_OF_FW_SECTORS_CORRECTLY_PROGRAMMED[4]; // Number of FW sectors correctly programmed [305:302]
+ UINT8 RESERVED_22[181]; // Reserved [486:306]
+ UINT8 FFU_ARG[4]; // FFU argument [490:487]
+ UINT8 OPERATION_CODE_TIMEOUT; // Operation codes timeout [491:491]
+ UINT8 FFU_FEATURES; // FFU features [492:492]
+ UINT8 SUPPORTED_MODES; // Supported modes [493:493]
+ UINT8 EXT_SUPPORT; // Extended partitions attribute support [494:494]
+ UINT8 LARGE_UNIT_SIZE_M1; // Large unit size [495:495]
+ UINT8 CONTEXT_CAPABILITIES; // Context management capabilities [496:496]
+ UINT8 TAG_RES_SIZE; // Tag resource size [497:497]
+ UINT8 TAG_UNIT_SIZE; // Tag unit size [498:498]
+ UINT8 DATA_TAG_SUPPORT; // Data tag support [499:499]
+ UINT8 MAX_PACKED_WRITES; // Max packed write commands [500:500]
+ UINT8 MAX_PACKED_READS; // Max packed read commands [501:501]
+ UINT8 BKOPS_SUPPORT; // Background operations support [502:502]
+ UINT8 HPI_FEATURES; // HPI features [503:503]
+ UINT8 S_CMD_SET; // Supported command sets [504:504]
+ UINT8 EXT_SECURITY_ERR; // Extended security commands error [505:505]
+ UINT8 RESERVED_23[6]; // Reserved [511:506]
+} ECSD;
+
typedef struct {
UINT16 RCA;
CARD_TYPE CardType;
OCR OCRData;
CID CIDData;
CSD CSDData;
- UINT32 ECSD[128]; // MMC V4 extended card specific
+ ECSD ECSDData; // MMC V4 extended card specific
} CARD_INFO;

typedef struct _MMC_HOST_INSTANCE {
diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index 578fcb6..378e438 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -90,7 +90,7 @@ EmmcIdentificationMode (
DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));
}

- Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)&(MmcHostInstance->CardInfo.ECSD));
+ Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)&(MmcHostInstance->CardInfo.ECSDData));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));
return Status;
@@ -103,7 +103,7 @@ EmmcIdentificationMode (
Media->LogicalBlocksPerPhysicalBlock = 1;
Media->IoAlign = 4;
// Compute last block using bits [215:212] of the ECSD
- Media->LastBlock = MmcHostInstance->CardInfo.ECSD[EMMC_ECSD_SIZE_OFFSET] - 1; // eMMC isn't supposed to report this for
+ Media->LastBlock = MmcHostInstance->CardInfo.ECSDData.SECTOR_COUNT - 1; // eMMC isn't supposed to report this for
// Cards <2GB in size, but the model does.

// Setup card type
--
2.7.4


[PATCH v5 2/9] MmcDxe: move ECSD into CardInfo structure

Haojian Zhuang <haojian.zhuang@...>
 

Since ECSD also describes the information of card, move it into
structure CardInfo.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@...>
Tested-by: Ryan Harkin <ryan.harkin@...>
Reviewed-by: Leif Lindholm <leif.lindholm@...>
---
EmbeddedPkg/Universal/MmcDxe/Mmc.h | 1 +
EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 5 ++---
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
index 46a156c..4f132c6 100644
--- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
+++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
@@ -138,6 +138,7 @@ typedef struct {
OCR OCRData;
CID CIDData;
CSD CSDData;
+ UINT32 ECSD[128]; // MMC V4 extended card specific
} CARD_INFO;

typedef struct _MMC_HOST_INSTANCE {
diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index 3f72b7f..578fcb6 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -39,7 +39,6 @@ EmmcIdentificationMode (
EFI_BLOCK_IO_MEDIA *Media;
EFI_STATUS Status;
UINT32 RCA;
- UINT32 ECSD[128];

Host = MmcHostInstance->MmcHost;
Media = MmcHostInstance->BlockIo.Media;
@@ -91,7 +90,7 @@ EmmcIdentificationMode (
DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));
}

- Status = Host->ReadBlockData (Host, 0, 512, ECSD);
+ Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)&(MmcHostInstance->CardInfo.ECSD));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));
return Status;
@@ -104,7 +103,7 @@ EmmcIdentificationMode (
Media->LogicalBlocksPerPhysicalBlock = 1;
Media->IoAlign = 4;
// Compute last block using bits [215:212] of the ECSD
- Media->LastBlock = ECSD[EMMC_ECSD_SIZE_OFFSET] - 1; // eMMC isn't supposed to report this for
+ Media->LastBlock = MmcHostInstance->CardInfo.ECSD[EMMC_ECSD_SIZE_OFFSET] - 1; // eMMC isn't supposed to report this for
// Cards <2GB in size, but the model does.

// Setup card type
--
2.7.4


[PATCH v5 1/9] MmcDxe: wait OCR busy bit free

Haojian Zhuang <haojian.zhuang@...>
 

According to eMMC spec, OCR.PowerUp bit is also busy bit. If the busy
bit is '0', CMD1 should be sent and OCR should be fetched again. And add
a timeout counter on the repeated steps.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@...>
Tested-by: Ryan Harkin <ryan.harkin@...>
Reviewed-by: Leif Lindholm <leif.lindholm@...>
---
EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index 2d8038f..3f72b7f 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -222,14 +222,19 @@ MmcIdentificationMode (

// Send CMD1 to get OCR (MMC)
// This command only valid for MMC and eMMC
- Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, EMMC_CMD1_CAPACITY_GREATER_THAN_2GB);
- if (Status == EFI_SUCCESS) {
+ Timeout = MAX_RETRY_COUNT;
+ do {
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, EMMC_CMD1_CAPACITY_GREATER_THAN_2GB);
+ if (EFI_ERROR (Status))
+ break;
Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, (UINT32 *)&OcrResponse);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));
return Status;
}
-
+ Timeout--;
+ } while (!OcrResponse.Ocr.PowerUp && (Timeout > 0));
+ if (Status == EFI_SUCCESS) {
if (!OcrResponse.Ocr.PowerUp) {
DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD1): Card initialisation failure, Status=%r.\n", Status));
return EFI_DEVICE_ERROR;
--
2.7.4


[PATCH v5 0/9] enhance MMC

Haojian Zhuang <haojian.zhuang@...>
 

v5:
* Remove patch on MediaId.
* Squash two PL180 patches together.

v4:
* Fix PL180 hang in some cases. Since the proper variable length
isn't set for CMD6 & ACMD51.

v3:
* Fix PL180 hang because of CMD6 & ACMD51 not supported.

v2:
* Fix print error with missing parameter.
* Change CMD51 to ACMD51.
* Add the protection after CMD55 for SD. If there's no
response of CMD55, skip to send ACMD51.

v1:
* Wait OCR busy bit free according to eMMC spec.
* Define ECSD structure.
* Add interface to set IO bus width and speed.
* Support to access multiple blocks.

Haojian Zhuang (9):
MmcDxe: wait OCR busy bit free
MmcDxe: move ECSD into CardInfo structure
MmcDxe: declare ECSD structure
MmcDxe: add SPEC_VERS field in CSD structure
MmcDxe: add interface to change io width and speed
MmcDxe: set io bus width before reading EXTCSD
MmcDxe: set iospeed and bus width in SD stack
MmcDxe: expand to support multiple blocks
PL180: update for indentifying SD

ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c | 29 +-
EmbeddedPkg/Include/Protocol/MmcHost.h | 29 ++
EmbeddedPkg/Universal/MmcDxe/Mmc.h | 176 +++++++++++-
EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c | 177 ++++++++----
EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 347 +++++++++++++++++++++--
5 files changed, 664 insertions(+), 94 deletions(-)

--
2.7.4


Re: [PATCH v4 07/11] MmcDxe: Fix uninitialized mediaid for SD

Haojian Zhuang <haojian.zhuang@...>
 

On 9 November 2016 at 07:59, Leif Lindholm <leif.lindholm@...> wrote:
On Tue, Nov 08, 2016 at 11:21:12PM +0800, Haojian Zhuang wrote:
When SD card is used, mediaid is not initialized and used directly. So
fix it.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@...>
---
EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index cefc2b6..5b802c0 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -57,6 +57,7 @@ typedef enum _EMMC_DEVICE_STATE {
} EMMC_DEVICE_STATE;

UINT32 mEmmcRcaCount = 0;
+UINT32 CurrentMediaId = 0;
Should have an 'm' prefix.


STATIC
EFI_STATUS
@@ -231,6 +232,10 @@ EmmcIdentificationMode (
// Set up media
Media->BlockSize = EMMC_CARD_SIZE; // 512-byte support is mandatory for eMMC cards
Media->MediaId = MmcHostInstance->CardInfo.CIDData.PSN;
I spent some time digging through this code in order to understand
what is going on below. I think this could do with a comment
explaining the logic. Also, always use {} with if/else.

+ if (CurrentMediaId > Media->MediaId)
+ Media->MediaId = ++CurrentMediaId;
+ else
+ CurrentMediaId = Media->MediaId;
I will give my interpretation of how this works, and you can confirm
or deny it.

When this Media entity is created, it is based on mMmcMediaTemplate.
mMmcMediaTemplate (ab)uses the MediaId field as a Signature - "mmco",
meaning any new MMC device starts with a MediaId of 0x6d6d626f (or
0x6f626d6d if I got the endianness wrong).

So the value is initialised, just to the same for every MMC media in
the system.

Since the module-global (m)CurrentMediaId is initialised to 0, the
first time MmcIdentificationMode() is called for the first eMMC
device, (m)CurrentMediaId will be set to 0x6d6d6270 (or 0x6f626d6e).

Does this not leave it uninitialised for MMC and other media types?

I guess it's not a huge deal if the MediaID clashes for different
devices, because it is mainly meant to indicate a removable media has
changed. But that also means there should not have been a problem in
the first place.

So can you describe in the commit message what failure mode this patch
gets rid of?
System won't crash with the patch removed. Let's remove this patch first.

Best Regards
Haojian

Regardless, I think the code would be more clear in what it is doing
if it did:
if (Media->MediaId == SIGNATURE_32('m','m','c','o')) {
Media->MediaId = ++CurrentMediaId;
} else {
CurrentMediaId = Media->MediaId;
}


USB hub port reset

Anbazhagan, Baraneedharan
 

EDK2 have reset recovery time of 10ms for hub port based on port status reset bit but USB spec doesn't mention that port status can be used for t6/reset recovery time. Could you please clarify?

USB vendor mentions EDK2 doesn't have reset recovery time on hub port reset and also highlighting EDK2 hub port reset differs from https://github.com/torvalds/linux/blob/master/drivers/usb/core/hub.c#L2789

-Baranee


Re: [PATCH 0/2] MdeModulePkg/EbcDxe: add EBC Debugger

Pete Batard
 

Hi Jiewen,

On 2016.11.12 21:44, Yao, Jiewen wrote:
I realize that the side-effect of library solution is that: we need
update DSC file to add Library instance.
Yes. I started looking at the library option, and I'm kind of wondering if we really want to put code in a library when it's unlikely that any of the hooks will be used anywhere but once, and in the very specific locations we have now.

I still don't mind going that route if that's what we decide, but creating a non-generic library, that is only going to be used to build a single application seems a bit like an overkill.

Now I am thinking the third options:
3.1.3) 2 INF without MACRO.
3.1.3.A) Remove EFI_EBC_DEBUGGER_CODE
3.1.3.B) EBC driver always calls EbcDebuggerHookXXX.
3.1.3.C) Create a EbcDebuggerHookNull.c and add it to EbcDxe.inf.
So that no change is needed for a platform, and no PCD is introduced.
This sound like a more elegant solution.

I like this option better than the others so far, so that's what I'll go with for v2.

3.1.3.F) I still suggest we remove EbcInit.h and EbcExecute.h from
Edb.h. The common definition should be in a better place.
Agreed.

I'll try to move the common parts to MdePkg\Include\Protocol\Ebc.h in the new proposal, if that's still okay with you.

Regards,

/Pete