Message ID | 1498791777-16122-2-git-send-email-jun.nie@linaro.org |
---|---|
State | New |
Headers | show |
Series | [Linaro-uefi,1/2] Drivers/Mmc/DwEmmc: limit max clock for platform | expand |
2017-06-30 11:02 GMT+08:00 Jun Nie <jun.nie@linaro.org>: > Adjust FIFO threshold according to FIFO depth. Skip > the adjustment if we do not have FIFO depth info. Just find that DwEmmc is already merged to mainline. I already post patches to edk2 mainline in another thread list and please ignore this thread. Jun > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Jun Nie <jun.nie@linaro.org> > --- > Drivers/Mmc/DwEmmcDxe/DwEmmc.h | 6 +++++ > Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.c | 54 +++++++++++++++++++++++++++++++++++++ > Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.dec | 1 + > Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.inf | 1 + > 4 files changed, 62 insertions(+) > > diff --git a/Drivers/Mmc/DwEmmcDxe/DwEmmc.h b/Drivers/Mmc/DwEmmcDxe/DwEmmc.h > index 055f1e0..2b41539 100644 > --- a/Drivers/Mmc/DwEmmcDxe/DwEmmc.h > +++ b/Drivers/Mmc/DwEmmcDxe/DwEmmc.h > @@ -38,7 +38,10 @@ > #define DWEMMC_RINTSTS ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x044) > #define DWEMMC_STATUS ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x048) > #define DWEMMC_FIFOTH ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x04c) > +#define DWEMMC_TCBCNT ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x05c) > +#define DWEMMC_TBBCNT ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x060) > #define DWEMMC_DEBNCE ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x064) > +#define DWEMMC_HCON ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x070) > #define DWEMMC_UHSREG ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x074) > #define DWEMMC_BMOD ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x080) > #define DWEMMC_DBADDR ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x088) > @@ -47,6 +50,7 @@ > #define DWEMMC_DSCADDR ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x094) > #define DWEMMC_BUFADDR ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x098) > #define DWEMMC_CARDTHRCTL ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0X100) > +#define DWEMMC_DATA ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0X200) > > #define CMD_UPDATE_CLK 0x80202000 > #define CMD_START_BIT (1 << 31) > @@ -124,4 +128,6 @@ > #define DWEMMC_CARD_RD_THR(x) ((x & 0xfff) << 16) > #define DWEMMC_CARD_RD_THR_EN (1 << 0) > > +#define DWEMMC_GET_HDATA_WIDTH(x) (((x)>>7) & 0x7) > + > #endif // __DWEMMC_H__ > diff --git a/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.c b/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.c > index c67dd0d..8299c13 100644 > --- a/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.c > +++ b/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.c > @@ -415,6 +415,59 @@ DwEmmcReceiveResponse ( > return EFI_SUCCESS; > } > > +VOID DwEmmcAdjustFifoth( > + VOID > + ) > +{ > + const UINT32 Mszs[] = {1, 4, 8, 16, 32, 64, 128, 256}; > + UINT32 BlkSizeDepth, Fifoth, FifoWidth, FifoDepth; > + UINT32 BlkSize = 512, Msize = 0, RxWmark = 1, TxWmark, TxWmarkInvers; > + UINT32 Idx = ARRAY_SIZE(Mszs) - 1; > + > + /* Skip FIFO adjustment if we do not have platform FIFO depth info */ > + FifoDepth = PcdGet32 (PcdDwEmmcDxeFifoDepth); > + if (!FifoDepth) > + return; > + > + TxWmark = FifoDepth / 2; > + TxWmarkInvers = FifoDepth - TxWmark; > + > + FifoWidth = DWEMMC_GET_HDATA_WIDTH(MmioRead32 (DWEMMC_HCON)); > + if (!FifoWidth) { > + FifoWidth = 2; > + } else if (FifoWidth == 2) { > + FifoWidth = 8; > + } else { > + FifoWidth = 4; > + } > + > + BlkSizeDepth = BlkSize / FifoWidth; > + > + /* > + * MSIZE is '1', > + * if BlkSize is not a multiple of the FIFO width > + */ > + if (BlkSize % FifoWidth) { > + goto done; > + } > + > + do { > + if (!((BlkSizeDepth % Mszs[Idx]) || (TxWmarkInvers % Mszs[Idx]))) { > + Msize = Idx; > + RxWmark = Mszs[Idx] - 1; > + break; > + } > + } while (--Idx > 0); > + /* > + * If Idx is '0', it won't be tried > + * Thus, initial values are uesed > + */ > + done: > + Fifoth = DWEMMC_DMA_BURST_SIZE(Msize) | DWEMMC_FIFO_TWMARK(TxWmark) > + | DWEMMC_FIFO_RWMARK(RxWmark); > + MmioWrite32 (DWEMMC_FIFOTH, Fifoth); > + } > + > EFI_STATUS > PrepareDmaData ( > IN DWEMMC_IDMAC_DESCRIPTOR* IdmacDesc, > @@ -632,6 +685,7 @@ DwEmmcDxeInitialize ( > > Handle = NULL; > > + DwEmmcAdjustFifoth(); > gpIdmacDesc = (DWEMMC_IDMAC_DESCRIPTOR *)AllocatePages (DWEMMC_MAX_DESC_PAGES); > if (gpIdmacDesc == NULL) { > return EFI_BUFFER_TOO_SMALL; > diff --git a/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.dec b/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.dec > index 7b84a9a..503899c 100644 > --- a/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.dec > +++ b/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.dec > @@ -41,3 +41,4 @@ > gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeBaseAddress|0x0|UINT32|0x00000001 > gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeClockFrequencyInHz|0x0|UINT32|0x00000002 > gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeMaxClockFrequencyInHz|0x0|UINT32|52000000 > + gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeFifoDepth|0x0|UINT32|0 > diff --git a/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.inf b/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.inf > index 99176f1..7872c52 100644 > --- a/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.inf > +++ b/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.inf > @@ -50,6 +50,7 @@ > gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeBaseAddress > gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeClockFrequencyInHz > gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeMaxClockFrequencyInHz > + gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeFifoDepth > > [Depex] > TRUE > -- > 1.9.1 >
diff --git a/Drivers/Mmc/DwEmmcDxe/DwEmmc.h b/Drivers/Mmc/DwEmmcDxe/DwEmmc.h index 055f1e0..2b41539 100644 --- a/Drivers/Mmc/DwEmmcDxe/DwEmmc.h +++ b/Drivers/Mmc/DwEmmcDxe/DwEmmc.h @@ -38,7 +38,10 @@ #define DWEMMC_RINTSTS ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x044) #define DWEMMC_STATUS ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x048) #define DWEMMC_FIFOTH ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x04c) +#define DWEMMC_TCBCNT ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x05c) +#define DWEMMC_TBBCNT ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x060) #define DWEMMC_DEBNCE ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x064) +#define DWEMMC_HCON ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x070) #define DWEMMC_UHSREG ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x074) #define DWEMMC_BMOD ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x080) #define DWEMMC_DBADDR ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x088) @@ -47,6 +50,7 @@ #define DWEMMC_DSCADDR ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x094) #define DWEMMC_BUFADDR ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x098) #define DWEMMC_CARDTHRCTL ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0X100) +#define DWEMMC_DATA ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0X200) #define CMD_UPDATE_CLK 0x80202000 #define CMD_START_BIT (1 << 31) @@ -124,4 +128,6 @@ #define DWEMMC_CARD_RD_THR(x) ((x & 0xfff) << 16) #define DWEMMC_CARD_RD_THR_EN (1 << 0) +#define DWEMMC_GET_HDATA_WIDTH(x) (((x)>>7) & 0x7) + #endif // __DWEMMC_H__ diff --git a/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.c b/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.c index c67dd0d..8299c13 100644 --- a/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.c +++ b/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.c @@ -415,6 +415,59 @@ DwEmmcReceiveResponse ( return EFI_SUCCESS; } +VOID DwEmmcAdjustFifoth( + VOID + ) +{ + const UINT32 Mszs[] = {1, 4, 8, 16, 32, 64, 128, 256}; + UINT32 BlkSizeDepth, Fifoth, FifoWidth, FifoDepth; + UINT32 BlkSize = 512, Msize = 0, RxWmark = 1, TxWmark, TxWmarkInvers; + UINT32 Idx = ARRAY_SIZE(Mszs) - 1; + + /* Skip FIFO adjustment if we do not have platform FIFO depth info */ + FifoDepth = PcdGet32 (PcdDwEmmcDxeFifoDepth); + if (!FifoDepth) + return; + + TxWmark = FifoDepth / 2; + TxWmarkInvers = FifoDepth - TxWmark; + + FifoWidth = DWEMMC_GET_HDATA_WIDTH(MmioRead32 (DWEMMC_HCON)); + if (!FifoWidth) { + FifoWidth = 2; + } else if (FifoWidth == 2) { + FifoWidth = 8; + } else { + FifoWidth = 4; + } + + BlkSizeDepth = BlkSize / FifoWidth; + + /* + * MSIZE is '1', + * if BlkSize is not a multiple of the FIFO width + */ + if (BlkSize % FifoWidth) { + goto done; + } + + do { + if (!((BlkSizeDepth % Mszs[Idx]) || (TxWmarkInvers % Mszs[Idx]))) { + Msize = Idx; + RxWmark = Mszs[Idx] - 1; + break; + } + } while (--Idx > 0); + /* + * If Idx is '0', it won't be tried + * Thus, initial values are uesed + */ + done: + Fifoth = DWEMMC_DMA_BURST_SIZE(Msize) | DWEMMC_FIFO_TWMARK(TxWmark) + | DWEMMC_FIFO_RWMARK(RxWmark); + MmioWrite32 (DWEMMC_FIFOTH, Fifoth); + } + EFI_STATUS PrepareDmaData ( IN DWEMMC_IDMAC_DESCRIPTOR* IdmacDesc, @@ -632,6 +685,7 @@ DwEmmcDxeInitialize ( Handle = NULL; + DwEmmcAdjustFifoth(); gpIdmacDesc = (DWEMMC_IDMAC_DESCRIPTOR *)AllocatePages (DWEMMC_MAX_DESC_PAGES); if (gpIdmacDesc == NULL) { return EFI_BUFFER_TOO_SMALL; diff --git a/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.dec b/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.dec index 7b84a9a..503899c 100644 --- a/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.dec +++ b/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.dec @@ -41,3 +41,4 @@ gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeBaseAddress|0x0|UINT32|0x00000001 gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeClockFrequencyInHz|0x0|UINT32|0x00000002 gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeMaxClockFrequencyInHz|0x0|UINT32|52000000 + gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeFifoDepth|0x0|UINT32|0 diff --git a/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.inf b/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.inf index 99176f1..7872c52 100644 --- a/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.inf +++ b/Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.inf @@ -50,6 +50,7 @@ gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeBaseAddress gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeClockFrequencyInHz gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeMaxClockFrequencyInHz + gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeFifoDepth [Depex] TRUE
Adjust FIFO threshold according to FIFO depth. Skip the adjustment if we do not have FIFO depth info. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jun Nie <jun.nie@linaro.org> --- Drivers/Mmc/DwEmmcDxe/DwEmmc.h | 6 +++++ Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.c | 54 +++++++++++++++++++++++++++++++++++++ Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.dec | 1 + Drivers/Mmc/DwEmmcDxe/DwEmmcDxe.inf | 1 + 4 files changed, 62 insertions(+)