Hi, all The following modifications are made to enable EDK Driver Support BH720 CHIP.
--- /c/yx/edk2/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c 2019-01-21 15:36:12.188734400 -0800 +++ /c/MyWorkspace/edk2-vUDK2018/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c 2018-08-13 22:40:04.802226200 -0700 @@ -1,7 +1,6 @@ /** @file This file provides some helper functions which are specific for SD card device. - Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. Copyright (c) 2015 - 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 @@ -319,9 +318,116 @@ SdCardSetRca ( return Status; } +/** + Send command SEND_CSD to the SD device to get the data of the CSD register. + + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. + + @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 of selected device. + @param[out] Csd The buffer to store the content of the CSD register. + Note the caller should ignore the lowest byte of this + buffer as the content of this byte is meaningless even + if the operation succeeds. + + @retval EFI_SUCCESS The operation is done correctly. + @retval Others The operation fails. + +**/ +EFI_STATUS +SdCardGetCsd ( + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, + IN UINT8 Slot, + IN UINT16 Rca, + OUT SD_CSD *Csd + ) +{ + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; + EFI_STATUS Status; + + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); + ZeroMem (&Packet, sizeof (Packet)); + Packet.SdMmcCmdBlk = &SdMmcCmdBlk; + Packet.SdMmcStatusBlk = &SdMmcStatusBlk; + Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT; + SdMmcCmdBlk.CommandIndex = SD_SEND_CSD; + SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; + SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2; + SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16; + Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); + if (!EFI_ERROR (Status)) { + // + // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12. + // + CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CSD) - 1); + } + + return Status; +} + +/** + Send command SEND_CSD to the SD device to get the data of the CSD register. + + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. + + @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 of selected device. + @param[out] Scr The buffer to store the content of the SCR register. + + @retval EFI_SUCCESS The operation is done correctly. + @retval Others The operation fails. + +**/ +EFI_STATUS +SdCardGetScr ( + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, + IN UINT8 Slot, + IN UINT16 Rca, + OUT SD_SCR *Scr + ) +{ + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; + EFI_STATUS Status; + + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); + ZeroMem (&Packet, sizeof (Packet)); + + Packet.SdMmcCmdBlk = &SdMmcCmdBlk; + Packet.SdMmcStatusBlk = &SdMmcStatusBlk; + Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT; + + SdMmcCmdBlk.CommandIndex = SD_APP_CMD; + SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; + SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; + SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16; + + Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + SdMmcCmdBlk.CommandIndex = SD_SEND_SCR; + SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc; + SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; + + Packet.InDataBuffer = Scr; + Packet.InTransferLength = sizeof (SD_SCR); + + Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); + + return Status; +} /** Send command SELECT_DESELECT_CARD to the SD device to select/deselect it. @@ -785,8 +891,8 @@ SdCardSetBusMode ( UINT8 BusWidth; UINT8 AccessMode; UINT8 HostCtrl1; + UINT8 HostCtrl2; UINT8 SwitchResp[64]; - SD_MMC_BUS_MODE Timing; SD_MMC_HC_PRIVATE_DATA *Private; Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru); @@ -818,23 +924,18 @@ SdCardSetBusMode ( 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; } Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp); @@ -860,32 +961,20 @@ SdCardSetBusMode ( } } - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing); + HostCtrl2 = (UINT8)~0x7; + Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); if (EFI_ERROR (Status)) { return Status; } - - Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]); + HostCtrl2 = AccessMode; + Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); if (EFI_ERROR (Status)) { return Status; } - if (mOverride != NULL && mOverride->NotifyPhase != NULL) { - Status = mOverride->NotifyPhase ( - Private->ControllerHandle, - Slot, - EdkiiSdMmcSwitchClockFreqPost, - &Timing - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "%a: SD/MMC switch clock freq post notifier callback failed - %r\n", - __FUNCTION__, - Status - )); - return Status; - } + Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, *Capability); + if (EFI_ERROR (Status)) { + return Status; } if ((AccessMode == 3) || ((AccessMode == 2) && (Capability->TuningSDR50 != 0))) { @@ -996,10 +1085,9 @@ SdCardIdentification ( return Status; } - if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) && - ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) { + if (((ControllerVer & 0xFF) == 2) || ((ControllerVer & 0xFF) == 3)) { S18r = TRUE; - } else if (((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_100) || ((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_200)) { + } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) { S18r = FALSE; } else { ASSERT (FALSE); @@ -1065,7 +1153,7 @@ SdCardIdentification ( goto Error; } - SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]); + SdMmcHcInitClockFreq (PciIo, Slot, Private->Capability[Slot]); gBS->Stall (1000); please check it! Br, Mike From: Mike Li (WH) Sent: 2019年1月23日 18:39 To: Mike Li (WH); Xiaoguang Yu (WH); Ernest Zhang(WH); Andy Dai (WH) Cc: Shirley Her (SC); edk2-devel@lists.01.org Subject: RE: [edk2] [patch_2] make EDK Driver Support BH720+EMMC chip Hi, all The following modifications are made to enable EDK Driver Support BH720 CHIP. --- /c/yx/edk2/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c 2019-01-21 15:36:12.186739600 -0800 +++ /c/MyWorkspace/edk2-vUDK2018/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c 2019-01-10 14:34:23.072538900 -0800 @@ -1,7 +1,6 @@ /** @file This file provides some helper functions which are specific for EMMC device. - Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. Copyright (c) 2015 - 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 @@ -527,17 +526,35 @@ EmmcTuningClkForHs200 ( if (EFI_ERROR (Status)) { return Status; } + + if(BhtHostPciSupport(PciIo)){ + //set data transfer with 4bit + Status = SdMmcHcSetBusWidth (PciIo, Slot, 4); + //enable hardware tuning + HostCtrl2 = (~0x10); + Status = SdMmcHcAndMmio (PciIo, Slot, 0x110,sizeof (HostCtrl2), &HostCtrl2); + + Status = EmmcSendTuningBlk (PassThru, Slot, 4); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status)); + return Status; + } + + } // // Ask the device to send a sequence of tuning blocks till the tuning procedure is done. // Retry = 0; do { - Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status)); - return Status; - } - + if(!BhtHostPciSupport(PciIo)){ + Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status)); + return Status; + } + } else { + gBS->Stall(5000); + } Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2); if (EFI_ERROR (Status)) { return Status; @@ -548,6 +565,10 @@ EmmcTuningClkForHs200 ( } if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) { + if(BhtHostPciSupport(PciIo)){ + //set data transfer with default + Status = SdMmcHcSetBusWidth (PciIo, Slot, BusWidth); + } return EFI_SUCCESS; } } while (++Retry < 40); @@ -652,7 +673,6 @@ EmmcSwitchBusWidth ( @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. @retval EFI_SUCCESS The operation is done correctly. @@ -666,7 +686,6 @@ EmmcSwitchClockFreq ( IN UINT8 Slot, IN UINT16 Rca, IN UINT8 HsTiming, - IN SD_MMC_BUS_MODE Timing, IN UINT32 ClockFreq ) { @@ -708,28 +727,7 @@ EmmcSwitchClockFreq ( // // Convert the clock freq unit from MHz to KHz. // - Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]); - if (EFI_ERROR (Status)) { - return Status; - } - - if (mOverride != NULL && mOverride->NotifyPhase != NULL) { - Status = mOverride->NotifyPhase ( - Private->ControllerHandle, - Slot, - EdkiiSdMmcSwitchClockFreqPost, - &Timing - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "%a: SD/MMC switch clock freq post notifier callback failed - %r\n", - __FUNCTION__, - Status - )); - return Status; - } - } + Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->Capability[Slot]); return Status; } @@ -764,13 +762,10 @@ EmmcSwitchToHighSpeed ( IN UINT8 BusWidth ) { - EFI_STATUS Status; - UINT8 HsTiming; - UINT8 HostCtrl1; - SD_MMC_BUS_MODE Timing; - SD_MMC_HC_PRIVATE_DATA *Private; - - Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru); + EFI_STATUS Status; + UINT8 HsTiming; + UINT8 HostCtrl1; + UINT8 HostCtrl2; Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth); if (EFI_ERROR (Status)) { @@ -785,21 +780,31 @@ EmmcSwitchToHighSpeed ( return Status; } + // + // Clean UHS Mode Select field of Host Control 2 reigster before update + // + HostCtrl2 = (UINT8)~0x7; + Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Set UHS Mode Select field of Host Control 2 reigster to SDR12/25/50 + // if (IsDdr) { - Timing = SdMmcMmcHsDdr; + HostCtrl2 = BIT2; } else if (ClockFreq == 52) { - Timing = SdMmcMmcHsSdr; + HostCtrl2 = BIT0; } else { - Timing = SdMmcMmcLegacy; + HostCtrl2 = 0; } - - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing); + Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); if (EFI_ERROR (Status)) { return Status; } HsTiming = 1; - Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq); + Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq); return Status; } @@ -831,13 +836,10 @@ EmmcSwitchToHS200 ( IN UINT8 BusWidth ) { - 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); + EFI_STATUS Status; + UINT8 HsTiming; + UINT8 HostCtrl2; + UINT16 ClockCtrl; if ((BusWidth != 4) && (BusWidth != 8)) { return EFI_INVALID_PARAMETER; @@ -857,29 +859,60 @@ EmmcSwitchToHS200 ( if (EFI_ERROR (Status)) { return Status; } - - Timing = SdMmcMmcHs200; - - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing); + // + // Clean UHS Mode Select field of Host Control 2 reigster before update + // + HostCtrl2 = (UINT8)~0x7; + Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Set UHS Mode Select field of Host Control 2 reigster to SDR104 + // + HostCtrl2 = BIT0 | BIT1; + Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); if (EFI_ERROR (Status)) { return Status; } - // // Wait Internal Clock Stable in the Clock Control register to be 1 before set SD Clock Enable bit // - Status = SdMmcHcWaitMmioSet ( - PciIo, - Slot, - SD_MMC_HC_CLOCK_CTRL, - sizeof (ClockCtrl), - BIT1, - BIT1, - SD_MMC_HC_GENERIC_TIMEOUT + if (BhtHostPciSupport(PciIo)) { + Status = SdMmcHcWaitMmioSet ( + PciIo, + Slot, + 0x1cc, + sizeof (ClockCtrl), + BIT14, + BIT14, + SD_MMC_HC_GENERIC_TIMEOUT + ); + } + else { + Status = SdMmcHcWaitMmioSet ( + PciIo, + Slot, + SD_MMC_HC_CLOCK_CTRL, + sizeof (ClockCtrl), + BIT1, + BIT1, + SD_MMC_HC_GENERIC_TIMEOUT ); + } if (EFI_ERROR (Status)) { return Status; } + + if (BhtHostPciSupport(PciIo)){ + //Wait 2nd Card Detect debounce Finished by wait twice of debounce max time + UINT32 value32; + while (1) { + Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32); + if (((value32 >> 18) & 0x01) == ((value32 >> 16) & 0x01)) + break; + } + } // // Set SD Clock Enable in the Clock Control register to 1 // @@ -887,12 +920,33 @@ EmmcSwitchToHS200 ( Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl); HsTiming = 2; - Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq); + Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq); if (EFI_ERROR (Status)) { return Status; } - Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth); + if (BhtHostPciSupport(PciIo)){ + Status = SdMmcHcWaitMmioSet ( + PciIo, + Slot, + 0x1cc, + sizeof (ClockCtrl), + BIT11, + BIT11, + SD_MMC_CLOCK_STABLE_TIMEOUT + ); + if (EFI_ERROR(Status)) { + DbgMsg(L"Wait Clock Stable timeout, ClockFreq=%d\n", ClockFreq); + return Status; + } + } + + if (EFI_ERROR(Status)) { + DbgMsg(L"Emmc tuning failed\n"); + return Status; + } + + return Status; } @@ -922,12 +976,9 @@ EmmcSwitchToHS400 ( IN UINT32 ClockFreq ) { - EFI_STATUS Status; - UINT8 HsTiming; - SD_MMC_BUS_MODE Timing; - SD_MMC_HC_PRIVATE_DATA *Private; - - Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru); + EFI_STATUS Status; + UINT8 HsTiming; + UINT8 HostCtrl2; Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, 8); if (EFI_ERROR (Status)) { @@ -937,7 +988,7 @@ EmmcSwitchToHS400 ( // Set to Hight Speed timing and set the clock frequency to a value less than 52MHz. // HsTiming = 1; - Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, SdMmcMmcHsSdr, 52); + Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, 52); if (EFI_ERROR (Status)) { return Status; } @@ -948,16 +999,25 @@ EmmcSwitchToHS400 ( if (EFI_ERROR (Status)) { return Status; } - - Timing = SdMmcMmcHs400; - - Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing); + // + // Clean UHS Mode Select field of Host Control 2 reigster before update + // + HostCtrl2 = (UINT8)~0x7; + Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Set UHS Mode Select field of Host Control 2 reigster to HS400 + // + HostCtrl2 = BIT0 | BIT2; + Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); if (EFI_ERROR (Status)) { return Status; } HsTiming = 3; - Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq); + Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq); return Status; } @@ -1008,7 +1068,7 @@ EmmcSetBusMode ( return Status; } - ASSERT (Private->BaseClkFreq[Slot] != 0); + ASSERT (Private->Capability[Slot].BaseClkFreq != 0); // // Check if the Host Controller support 8bits bus width. // @@ -1080,6 +1140,42 @@ EmmcSetBusMode ( // Execute HS200 timing switch procedure // Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth); + if (EFI_ERROR(Status)) { + if (BhtHostPciSupport(PciIo)) { + UINT32 val32; + DbgMsg(L"switch to HS200 200MHZ failed, freq decrease to 100MHz\n"); + ClockFreq = 100; + + SdMmcHcRwMmio (PciIo, Slot, 0x3C, TRUE, sizeof(val32), &val32); + val32 &= ~BIT22; + SdMmcHcRwMmio (PciIo, Slot, 0x3C, FALSE, sizeof(val32), &val32); + val32 = (BIT26 | BIT25); + SdMmcHcOrMmio (PciIo, Slot, 0x2C, sizeof(val32), &val32); + + Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth); + if (EFI_ERROR(Status)) { + if (((ExtCsd.DeviceType & BIT1) != 0) && (Private->Capability[Slot].HighSpeed != 0)) { + DbgMsg(L"switch to HS200 100MHZ failed, mode decrease to HS 50MHz\n"); + + HsTiming = 1; + IsDdr = FALSE; + ClockFreq = 52; + Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth); + } + else if (((ExtCsd.DeviceType & BIT0) != 0) && (Private->Capability[Slot].HighSpeed != 0)) { + DbgMsg(L"switch to HS200 100MHZ failed, mode decrease to HS 25MHz\n"); + + HsTiming = 1; + IsDdr = FALSE; + ClockFreq = 26; + Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth); + } + else { + DbgMsg(L"switch to HS200 100MHZ failed, but emmc chip didn't support hs mode\n"); + } + } + } + } } else { // // Execute High Speed timing switch procedure Please check it! Br, Mike From: Mike Li (WH) Sent: 2019年1月23日 17:29 To: Xiaoguang Yu (WH); Ernest Zhang(WH); Andy Dai (WH) Cc: Shirley Her (SC); 'edk2-devel@lists.01.org' Subject: [edk2] [patch_1] make EDK Driver Support BH720+EMMC chip Hi, all The following modifications are made to enable EDK Driver Support BH720 CHIP. --- /c/MyWorkspace/edk2-vUDK2018/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c 2019-01-10 14:35:21.342736200 -0800 +++ /c/yx/edk2/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c 2019-01-21 15:36:12.195715300 -0800 @@ -4,6 +4,7 @@ It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use. + Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR> This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -16,8 +17,6 @@ **/ #include "SdMmcPciHcDxe.h" -int g_deviceId = 0; - /** Dump the content of SD/MMC host controller's Capability Register. @@ -47,7 +46,8 @@ DumpCapabilityReg ( DEBUG ((DEBUG_INFO, " Voltage 3.3 %a\n", Capability->Voltage33 ? "TRUE" : "FALSE")); DEBUG ((DEBUG_INFO, " Voltage 3.0 %a\n", Capability->Voltage30 ? "TRUE" : "FALSE")); DEBUG ((DEBUG_INFO, " Voltage 1.8 %a\n", Capability->Voltage18 ? "TRUE" : "FALSE")); - DEBUG ((DEBUG_INFO, " 64-bit Sys Bus %a\n", Capability->SysBus64 ? "TRUE" : "FALSE")); + DEBUG ((DEBUG_INFO, " V4 64-bit Sys Bus %a\n", Capability->SysBus64V4 ? "TRUE" : "FALSE")); + DEBUG ((DEBUG_INFO, " V3 64-bit Sys Bus %a\n", Capability->SysBus64V3 ? "TRUE" : "FALSE")); DEBUG ((DEBUG_INFO, " Async Interrupt %a\n", Capability->AsyncInt ? "TRUE" : "FALSE")); DEBUG ((DEBUG_INFO, " SlotType ")); if (Capability->SlotType == 0x00) { @@ -419,9 +419,39 @@ SdMmcHcWaitMmioSet ( } /** + Get the controller version information from the specified slot. + + @param[in] PciIo The PCI IO protocol instance. + @param[in] Slot The slot number of the SD card to send the command to. + @param[out] Version The buffer to store the version information. + + @retval EFI_SUCCESS The operation executes successfully. + @retval Others The operation fails. + +**/ +EFI_STATUS +SdMmcHcGetControllerVersion ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 Slot, + OUT UINT16 *Version + ) +{ + EFI_STATUS Status; + + Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (UINT16), Version); + if (EFI_ERROR (Status)) { + return Status; + } + + *Version &= 0xFF; + + return EFI_SUCCESS; +} + +/** Software reset the specified SD/MMC host controller and enable all interrupts. - @param[in] PciIo The PCI IO protocol instance. + @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance. @param[in] Slot The slot number of the SD card to send the command to. @retval EFI_SUCCESS The software reset executes successfully. @@ -430,18 +460,38 @@ SdMmcHcWaitMmioSet ( **/ EFI_STATUS SdMmcHcReset ( - IN EFI_PCI_IO_PROTOCOL *PciIo, + IN SD_MMC_HC_PRIVATE_DATA *Private, IN UINT8 Slot ) { EFI_STATUS Status; UINT8 SwReset; + EFI_PCI_IO_PROTOCOL *PciIo; + + // + // Notify the SD/MMC override protocol that we are about to reset + // the SD/MMC host controller. + // + if (mOverride != NULL && mOverride->NotifyPhase != NULL) { + Status = mOverride->NotifyPhase ( + Private->ControllerHandle, + Slot, + EdkiiSdMmcResetPre, + NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, + "%a: SD/MMC pre reset notifier callback failed - %r\n", + __FUNCTION__, Status)); + return Status; + } + } - SwReset = 0xFF; - Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_SW_RST, FALSE, sizeof (SwReset), &SwReset); + PciIo = Private->PciIo; + SwReset = BIT0; + Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_SW_RST, sizeof (SwReset), &SwReset); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "SdMmcHcReset: write full 1 fails: %r\n", Status)); + DEBUG ((DEBUG_ERROR, "SdMmcHcReset: write SW Reset for All fails: %r\n", Status)); return Status; } @@ -450,7 +500,7 @@ SdMmcHcReset ( Slot, SD_MMC_HC_SW_RST, sizeof (SwReset), - 0xFF, + BIT0, 0x00, SD_MMC_HC_GENERIC_TIMEOUT ); @@ -458,10 +508,33 @@ SdMmcHcReset ( DEBUG ((DEBUG_INFO, "SdMmcHcReset: reset done with %r\n", Status)); return Status; } + // // Enable all interrupt after reset all. // Status = SdMmcHcEnableInterrupt (PciIo, Slot); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "SdMmcHcReset: SdMmcHcEnableInterrupt done with %r\n", + Status)); + return Status; + } + + // + // Notify the SD/MMC override protocol that we have just reset + // the SD/MMC host controller. + // + if (mOverride != NULL && mOverride->NotifyPhase != NULL) { + Status = mOverride->NotifyPhase ( + Private->ControllerHandle, + Slot, + EdkiiSdMmcResetPost, + NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, + "%a: SD/MMC post reset notifier callback failed - %r\n", + __FUNCTION__, Status)); + } + } return Status; } @@ -680,7 +753,8 @@ SdMmcHcStopClock ( @param[in] PciIo The PCI IO protocol instance. @param[in] Slot The slot number of the SD card to send the command to. @param[in] ClockFreq The max clock frequency to be set. The unit is KHz. - @param[in] Capability The capability of the slot. + @param[in] BaseClkFreq The base clock frequency of host controller in MHz. + @param[in] ControllerVer The version of host controller. @retval EFI_SUCCESS The clock is supplied successfully. @retval Others The clock isn't supplied successfully. @@ -691,23 +765,21 @@ SdMmcHcClockSupply ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Slot, IN UINT64 ClockFreq, - IN SD_MMC_HC_SLOT_CAP Capability + IN UINT32 BaseClkFreq, + IN UINT16 ControllerVer ) { EFI_STATUS Status; - UINT32 BaseClkFreq; UINT32 SettingFreq; UINT32 Divisor; UINT32 Remainder; - UINT16 ControllerVer; UINT16 ClockCtrl; // // Calculate a divisor for SD clock frequency // - ASSERT (Capability.BaseClkFreq != 0); + ASSERT (BaseClkFreq != 0); - BaseClkFreq = Capability.BaseClkFreq; if (ClockFreq == 0) { return EFI_INVALID_PARAMETER; } @@ -736,17 +808,15 @@ SdMmcHcClockSupply ( DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq)); - Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer); - if (EFI_ERROR (Status)) { - return Status; - } // // Set SDCLK Frequency Select and Internal Clock Enable fields in Clock Control register. // - if (((ControllerVer & 0xFF) == 2) || ((ControllerVer & 0xFF) == 3)) { + if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) && + (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) { ASSERT (Divisor <= 0x3FF); ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2); - } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) { + } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) || + (ControllerVer == SD_MMC_HC_CTRL_VER_200)) { // // Only the most significant bit can be used as divisor. // @@ -894,11 +964,62 @@ SdMmcHcSetBusWidth ( } /** - Supply SD/MMC card with lowest clock frequency at initialization. + Configure V4 controller enhancements at initialization. @param[in] PciIo The PCI IO protocol instance. @param[in] Slot The slot number of the SD card to send the command to. @param[in] Capability The capability of the slot. + @param[in] ControllerVer The version of host controller. + + @retval EFI_SUCCESS The clock is supplied successfully. + +**/ +EFI_STATUS +SdMmcHcInitV4Enhancements ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 Slot, + IN SD_MMC_HC_SLOT_CAP Capability, + IN UINT16 ControllerVer + ) +{ + EFI_STATUS Status; + UINT16 HostCtrl2; + + // + // Check if controller version V4 or higher + // + if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) { + HostCtrl2 = SD_MMC_HC_V4_EN; + // + // Check if V4 64bit support is available + // + if (Capability.SysBus64V4 != 0) { + HostCtrl2 |= SD_MMC_HC_64_ADDR_EN; + DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n")); + } + // + // Check if controller version V4.10 or higher + // + if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) { + HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN; + DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA support\n")); + } + Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} + +/** + Supply SD/MMC card with lowest clock frequency at initialization. + + @param[in] PciIo The PCI IO protocol instance. + @param[in] Slot The slot number of the SD card to send the command to. + @param[in] BaseClkFreq The base clock frequency of host controller in MHz. + @param[in] ControllerVer The version of host controller. @retval EFI_SUCCESS The clock is supplied successfully. @retval Others The clock isn't supplied successfully. @@ -908,16 +1029,20 @@ EFI_STATUS SdMmcHcInitClockFreq ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Slot, - IN SD_MMC_HC_SLOT_CAP Capability + IN UINT32 BaseClkFreq, + IN UINT16 ControllerVer ) { EFI_STATUS Status; UINT32 InitFreq; // - // Calculate a divisor for SD clock frequency + // According to SDHCI specification ver. 4.2, BaseClkFreq field value of + // the Capability Register 1 can be zero, which means a need for obtaining + // the clock frequency via another method. Fail in case it is not updated + // by SW at this point. // - if (Capability.BaseClkFreq == 0) { + if (BaseClkFreq == 0) { // // Don't support get Base Clock Frequency information via another method // @@ -927,7 +1052,7 @@ SdMmcHcInitClockFreq ( // Supply 400KHz clock frequency at initialization phase. // InitFreq = 400; - Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, Capability); + Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq, ControllerVer); return Status; } @@ -988,15 +1113,6 @@ SdMmcHcInitPowerVoltage ( // Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register // Status = SdMmcHcPowerControl (PciIo, Slot, MaxVoltage); - if (BhtHostPciSupport(PciIo)){ - // 1.8V signaling enable - HostCtrl2 = BIT3; - Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); - gBS->Stall (5000); - if (EFI_ERROR (Status)) { - return Status; - } - } return Status; } @@ -1032,9 +1148,8 @@ SdMmcHcInitTimeoutCtrl ( Initial SD/MMC host controller with lowest clock frequency, max power and max timeout value at initialization. - @param[in] PciIo The PCI IO protocol instance. + @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance. @param[in] Slot The slot number of the SD card to send the command to. - @param[in] Capability The capability of the slot. @retval EFI_SUCCESS The host controller is initialized successfully. @retval Others The host controller isn't initialized successfully. @@ -1042,96 +1157,164 @@ SdMmcHcInitTimeoutCtrl ( **/ EFI_STATUS SdMmcHcInitHost ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT8 Slot, - IN SD_MMC_HC_SLOT_CAP Capability + IN SD_MMC_HC_PRIVATE_DATA *Private, + IN UINT8 Slot ) { - EFI_STATUS Status; - UINT32 value32; - - if (BhtHostPciSupport(PciIo)){ - - DbgMsg(L"find bht emmc chip\n"); - /* FET on */ - PciBhtOr32(PciIo, 0xEC, 0x3); - /* Led on */ - //PciBhtAnd32(PciIo, 0x334, (UINT32)~BIT13); - PciBhtOr32(PciIo, 0xD4, BIT6); - /* Set 1.8v emmc signaling flag */ - PciBhtOr32(PciIo, 0x308, BIT4); - /* Set 200MBaseClock */ - value32 = PciBhtRead32(PciIo, 0x304); - value32 &= 0x0000FFFF; - value32 |= 0x25100000; - PciBhtWrite32(PciIo, 0x304, value32); - PciBhtOr32(PciIo, 0x3E4, BIT22); - PciBhtWrite32(PciIo, 0x300, 0x21400033); - - //enable internal clk - value32 = BIT0; - Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL,sizeof(value32), &value32); - - //reset pll start - Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32); - value32 |= BIT12; - Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32); - gBS->Stall(1); - - //reset pll end - Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE,sizeof(value32), &value32); - value32 &= ~BIT12; - value32 |= BIT18; - Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32); - - //wait BaseClk stable 0x1CC bit14 - Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32); - while(!(value32&BIT14)){ - gBS->Stall(100); - Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32); - DbgMsg(L"1CC=0x%08x\n", value32); - } - - if (value32 & BIT18) - { - //Wait 2nd Card Detect debounce Finished by wait twice of debounce max time - while (1) { - Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32); - if (((value32 >> 16) & 0x01) == ((value32 >> 18) & 0x01)) - break; - } - //force pll active end - Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32); - value32 &= ~BIT18; - Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32); - } - - Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability); - if (EFI_ERROR (Status)) { - DbgMsg(L"emmc host init failure\n"); - return Status; - } - - - } - - Status = SdMmcHcInitClockFreq (PciIo, Slot, Capability); - if (EFI_ERROR (Status)) { - return Status; - } - - if (!BhtHostPciSupport(PciIo)){ - Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability); - if (EFI_ERROR (Status)) { - return Status; - } + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + SD_MMC_HC_SLOT_CAP Capability; + + // + // Notify the SD/MMC override protocol that we are about to initialize + // the SD/MMC host controller. + // + if (mOverride != NULL && mOverride->NotifyPhase != NULL) { + Status = mOverride->NotifyPhase ( + Private->ControllerHandle, + Slot, + EdkiiSdMmcInitHostPre, + NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, + "%a: SD/MMC pre init notifier callback failed - %r\n", + __FUNCTION__, Status)); + return Status; + } + } + + PciIo = Private->PciIo; + Capability = Private->Capability[Slot]; + + Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private->ControllerVersion[Slot]); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]); + if (EFI_ERROR (Status)) { + return Status; } - + + Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability); + if (EFI_ERROR (Status)) { + return Status; + } + Status = SdMmcHcInitTimeoutCtrl (PciIo, Slot); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Notify the SD/MMC override protocol that we are have just initialized + // the SD/MMC host controller. + // + if (mOverride != NULL && mOverride->NotifyPhase != NULL) { + Status = mOverride->NotifyPhase ( + Private->ControllerHandle, + Slot, + EdkiiSdMmcInitHostPost, + NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, + "%a: SD/MMC post init notifier callback failed - %r\n", + __FUNCTION__, Status)); + } + } return Status; } /** + Set SD Host Controler control 2 registry according to selected speed. + + @param[in] ControllerHandle The handle of the controller. + @param[in] PciIo The PCI IO protocol instance. + @param[in] Slot The slot number of the SD card to send the command to. + @param[in] Timing The timing to select. + + @retval EFI_SUCCESS The timing is set successfully. + @retval Others The timing isn't set successfully. +**/ +EFI_STATUS +SdMmcHcUhsSignaling ( + IN EFI_HANDLE ControllerHandle, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 Slot, + IN SD_MMC_BUS_MODE Timing + ) +{ + EFI_STATUS Status; + UINT8 HostCtrl2; + + HostCtrl2 = (UINT8)~SD_MMC_HC_CTRL_UHS_MASK; + Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); + if (EFI_ERROR (Status)) { + return Status; + } + + switch (Timing) { + case SdMmcUhsSdr12: + HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR12; + break; + case SdMmcUhsSdr25: + HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR25; + break; + case SdMmcUhsSdr50: + HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR50; + break; + case SdMmcUhsSdr104: + HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR104; + break; + case SdMmcUhsDdr50: + HostCtrl2 = SD_MMC_HC_CTRL_UHS_DDR50; + break; + case SdMmcMmcLegacy: + HostCtrl2 = SD_MMC_HC_CTRL_MMC_LEGACY; + break; + case SdMmcMmcHsSdr: + HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_SDR; + break; + case SdMmcMmcHsDdr: + HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_DDR; + break; + case SdMmcMmcHs200: + HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS200; + break; + case SdMmcMmcHs400: + HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS400; + break; + default: + HostCtrl2 = 0; + break; + } + Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); + if (EFI_ERROR (Status)) { + return Status; + } + + if (mOverride != NULL && mOverride->NotifyPhase != NULL) { + Status = mOverride->NotifyPhase ( + ControllerHandle, + Slot, + EdkiiSdMmcUhsSignaling, + &Timing + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: SD/MMC uhs signaling notifier callback failed - %r\n", + __FUNCTION__, + Status + )); + return Status; + } + } + + return EFI_SUCCESS; +} + +/** Turn on/off LED. @param[in] PciIo The PCI IO protocol instance. @@ -1166,9 +1349,10 @@ SdMmcHcLedOnOff ( /** Build ADMA descriptor table for transfer. - Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details. + Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details. @param[in] Trb The pointer to the SD_MMC_HC_TRB instance. + @param[in] ControllerVer The version of host controller. @retval EFI_SUCCESS The ADMA descriptor table is created successfully. @retval Others The ADMA descriptor table isn't created successfully. @@ -1176,7 +1360,8 @@ SdMmcHcLedOnOff ( **/ EFI_STATUS BuildAdmaDescTable ( - IN SD_MMC_HC_TRB *Trb + IN SD_MMC_HC_TRB *Trb, + IN UINT16 ControllerVer ) { EFI_PHYSICAL_ADDRESS Data; @@ -1184,49 +1369,93 @@ BuildAdmaDescTable ( UINT64 Entries; UINT32 Index; UINT64 Remaining; - UINT32 Address; + UINT64 Address; UINTN TableSize; EFI_PCI_IO_PROTOCOL *PciIo; EFI_STATUS Status; UINTN Bytes; + BOOLEAN AddressingMode64; + BOOLEAN DataLength26; + UINT32 AdmaMaxDataPerLine; + UINT32 DescSize; + VOID *AdmaDesc; + + AddressingMode64 = FALSE; + DataLength26 = FALSE; + AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B; + DescSize = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE); + AdmaDesc = NULL; Data = Trb->DataPhy; DataLen = Trb->DataLen; PciIo = Trb->Private->PciIo; + // - // Only support 32bit ADMA Descriptor Table + // Detect whether 64bit addressing is supported. // - if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) { + if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) { + Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16), + SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN); + if (!EFI_ERROR (Status)) { + AddressingMode64 = TRUE; + DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE); + } + } + // + // Check for valid ranges in 32bit ADMA Descriptor Table + // + if (!AddressingMode64 && + ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) { return EFI_INVALID_PARAMETER; } // - // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0) - // for 32-bit address descriptor table. + // Check address field alignment // - if ((Data & (BIT0 | BIT1)) != 0) { - DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data)); + if (AddressingMode64) { + // + // Address field shall be set on 64-bit boundary (Lower 3-bit is always set to 0) + // + if ((Data & (BIT0 | BIT1 | BIT2)) != 0) { + DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 8 bytes boundary!\n", Data)); + } + } else { + // + // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0) + // + if ((Data & (BIT0 | BIT1)) != 0) { + DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data)); + } + } + // + // Detect whether 26bit data length is supported. + // + Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16), + SD_MMC_HC_26_DATA_LEN_ADMA_EN, SD_MMC_HC_26_DATA_LEN_ADMA_EN); + if (!EFI_ERROR (Status)) { + DataLength26 = TRUE; + AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B; } - Entries = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1), ADMA_MAX_DATA_PER_LINE); - TableSize = (UINTN)MultU64x32 (Entries, sizeof (SD_MMC_HC_ADMA_DESC_LINE)); + Entries = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1), AdmaMaxDataPerLine); + TableSize = (UINTN)MultU64x32 (Entries, DescSize); Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize); Status = PciIo->AllocateBuffer ( PciIo, AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES (TableSize), - (VOID **)&Trb->AdmaDesc, + (VOID **)&AdmaDesc, 0 ); if (EFI_ERROR (Status)) { return EFI_OUT_OF_RESOURCES; } - ZeroMem (Trb->AdmaDesc, TableSize); + ZeroMem (AdmaDesc, TableSize); Bytes = TableSize; Status = PciIo->Map ( PciIo, EfiPciIoOperationBusMasterCommonBuffer, - Trb->AdmaDesc, + AdmaDesc, &Bytes, &Trb->AdmaDescPhy, &Trb->AdmaMap @@ -1239,12 +1468,13 @@ BuildAdmaDescTable ( PciIo->FreeBuffer ( PciIo, EFI_SIZE_TO_PAGES (TableSize), - Trb->AdmaDesc + AdmaDesc ); return EFI_OUT_OF_RESOURCES; } - if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) { + if ((!AddressingMode64) && + (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) { // // The ADMA doesn't support 64bit addressing. // @@ -1255,35 +1485,71 @@ BuildAdmaDescTable ( PciIo->FreeBuffer ( PciIo, EFI_SIZE_TO_PAGES (TableSize), - Trb->AdmaDesc + AdmaDesc ); return EFI_DEVICE_ERROR; } Remaining = DataLen; - Address = (UINT32)Data; + Address = Data; + if (!AddressingMode64) { + Trb->Adma32Desc = AdmaDesc; + Trb->Adma64Desc = NULL; + } else { + Trb->Adma64Desc = AdmaDesc; + Trb->Adma32Desc = NULL; + } for (Index = 0; Index < Entries; Index++) { - if (Remaining <= ADMA_MAX_DATA_PER_LINE) { - Trb->AdmaDesc[Index].Valid = 1; - Trb->AdmaDesc[Index].Act = 2; - Trb->AdmaDesc[Index].Length = (UINT16)Remaining; - Trb->AdmaDesc[Index].Address = Address; - break; + if (!AddressingMode64) { + if (Remaining <= AdmaMaxDataPerLine) { + Trb->Adma32Desc[Index].Valid = 1; + Trb->Adma32Desc[Index].Act = 2; + if (DataLength26) { + Trb->Adma32Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16); + } + Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16); + Trb->Adma32Desc[Index].Address = (UINT32)Address; + break; + } else { + Trb->Adma32Desc[Index].Valid = 1; + Trb->Adma32Desc[Index].Act = 2; + if (DataLength26) { + Trb->Adma32Desc[Index].UpperLength = 0; + } + Trb->Adma32Desc[Index].LowerLength = 0; + Trb->Adma32Desc[Index].Address = (UINT32)Address; + } } else { - Trb->AdmaDesc[Index].Valid = 1; - Trb->AdmaDesc[Index].Act = 2; - Trb->AdmaDesc[Index].Length = 0; - Trb->AdmaDesc[Index].Address = Address; + if (Remaining <= AdmaMaxDataPerLine) { + Trb->Adma64Desc[Index].Valid = 1; + Trb->Adma64Desc[Index].Act = 2; + if (DataLength26) { + Trb->Adma64Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16); + } + Trb->Adma64Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16); + Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address; + Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32); + break; + } else { + Trb->Adma64Desc[Index].Valid = 1; + Trb->Adma64Desc[Index].Act = 2; + if (DataLength26) { + Trb->Adma64Desc[Index].UpperLength = 0; + } + Trb->Adma64Desc[Index].LowerLength = 0; + Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address; + Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32); + } } - Remaining -= ADMA_MAX_DATA_PER_LINE; - Address += ADMA_MAX_DATA_PER_LINE; + Remaining -= AdmaMaxDataPerLine; + Address += AdmaMaxDataPerLine; } // // Set the last descriptor line as end of descriptor table // - Trb->AdmaDesc[Index].End = 1; + AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb->Adma32Desc[Index].End = 1); return EFI_SUCCESS; } @@ -1381,7 +1647,7 @@ SdMmcCreateTrb ( Trb->Mode = SdMmcNoData; } else if (Private->Capability[Slot].Adma2 != 0) { Trb->Mode = SdMmcAdmaMode; - Status = BuildAdmaDescTable (Trb); + Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]); if (EFI_ERROR (Status)) { PciIo->Unmap (PciIo, Trb->DataMap); goto Error; @@ -1427,11 +1693,18 @@ SdMmcFreeTrb ( Trb->AdmaMap ); } - if (Trb->AdmaDesc != NULL) { + if (Trb->Adma32Desc != NULL) { + PciIo->FreeBuffer ( + PciIo, + Trb->AdmaPages, + Trb->Adma32Desc + ); + } + if (Trb->Adma64Desc != NULL) { PciIo->FreeBuffer ( PciIo, Trb->AdmaPages, - Trb->AdmaDesc + Trb->Adma64Desc ); } if (Trb->DataMap != NULL) { @@ -1571,12 +1844,15 @@ SdMmcExecTrb ( UINT16 Cmd; UINT16 IntStatus; UINT32 Argument; - UINT16 BlkCount; + UINT32 BlkCount; UINT16 BlkSize; UINT16 TransMode; UINT8 HostCtrl1; - UINT32 SdmaAddr; + UINT64 SdmaAddr; UINT64 AdmaAddr; + BOOLEAN AddressingMode64; + + AddressingMode64 = FALSE; Packet = Trb->Packet; PciIo = Trb->Private->PciIo; @@ -1609,13 +1885,28 @@ SdMmcExecTrb ( SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE); + if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) { + Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16), + SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN); + if (!EFI_ERROR (Status)) { + AddressingMode64 = TRUE; + } + } + if (Trb->Mode == SdMmcSdmaMode) { - if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) { + if ((!AddressingMode64) && + ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) { return EFI_INVALID_PARAMETER; } - SdmaAddr = (UINT32)(UINTN)Trb->DataPhy; - Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (SdmaAddr), &SdmaAddr); + SdmaAddr = (UINT64)(UINTN)Trb->DataPhy; + + if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) { + Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr); + } else { + Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr); + } + if (EFI_ERROR (Status)) { return Status; } @@ -1645,9 +1936,13 @@ SdMmcExecTrb ( // // Calcuate Block Count. // - BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize); + BlkCount = (Trb->DataLen / Trb->BlockSize); + } + if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410) { + Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &BlkCount); + } else { + Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (UINT16), &BlkCount); } - Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount); if (EFI_ERROR (Status)) { return Status; } @@ -1743,7 +2038,7 @@ SdMmcCheckTrbResult ( EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; UINT16 IntStatus; UINT32 Response[4]; - UINT32 SdmaAddr; + UINT64 SdmaAddr; UINT8 Index; UINT8 SwReset; UINT32 PioLength; @@ -1867,8 +2162,19 @@ SdMmcCheckTrbResult ( // // Update SDMA Address register. // - SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY); - Status = SdMmcHcRwMmio ( + SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY); + + if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) { + Status = SdMmcHcRwMmio ( + Private->PciIo, + Trb->Slot, + SD_MMC_HC_ADMA_SYS_ADDR, + FALSE, + sizeof (UINT64), + &SdmaAddr + ); + } else { + Status = SdMmcHcRwMmio ( Private->PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, @@ -1876,10 +2182,12 @@ SdMmcCheckTrbResult ( sizeof (UINT32), &SdmaAddr ); + } + if (EFI_ERROR (Status)) { goto Done; } - Trb->DataPhy = (UINT32)(UINTN)SdmaAddr; + Trb->DataPhy = (UINT64)(UINTN)SdmaAddr; } if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) && @@ -2000,281 +2308,3 @@ SdMmcWaitTrbResult ( return EFI_TIMEOUT; } -BOOLEAN BhtHostPciSupport(EFI_PCI_IO_PROTOCOL *PciIo) -{ - PCI_TYPE00 Pci; - - PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, - 0, sizeof Pci / sizeof (UINT32), &Pci); - - DEBUG ((DEBUG_INFO, "check device %04x:%04x\n", Pci.Hdr.VendorId, Pci.Hdr.DeviceId)); - - if (Pci.Hdr.VendorId != 0x1217) - goto end; - - switch (Pci.Hdr.DeviceId) - { - case 0x8420: //PCI_DEV_ID_SDS0 - case 0x8421: //PCI_DEV_ID_SDS1 - case 0x8520: //PCI_DEV_ID_FJ2 - case 0x8620: //PCI_DEV_ID_SB0 - case 0x8621: //PCI_DEV_ID_SB1 - g_deviceId = Pci.Hdr.DeviceId; - return 1; - default: - break; - } - - end: - return 0; -} - -void DbgNull(IN CONST CHAR16 * fmt, ...) -{ -} - -UINT32 bht_readl(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset) -{ - UINT32 arg; - PciIo->Mem.Read(PciIo,EfiPciIoWidthUint32,1,offset,1,&arg); - return arg; -} - -void bht_writel(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value) -{ - PciIo->Mem.Write(PciIo,EfiPciIoWidthUint32,1,offset,1,&value); -} - - -UINT32 PciBhtRead32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset) -{ - UINT32 i = 0; - UINT32 tmp[3] = {0}; - - if((g_deviceId == PCI_DEV_ID_SDS0) || - (g_deviceId == PCI_DEV_ID_SDS1) || - (g_deviceId == PCI_DEV_ID_FJ2) || - (g_deviceId == PCI_DEV_ID_SB0) || - (g_deviceId == PCI_DEV_ID_SB1)) - { - // For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg. - // Enable mapping - - // Check function conflict - if((g_deviceId == PCI_DEV_ID_SDS0) || - (g_deviceId == PCI_DEV_ID_FJ2) || - (g_deviceId == PCI_DEV_ID_SB0) || - (g_deviceId == PCI_DEV_ID_SB1)) - { - i = 0; - bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000); - while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0) - { - if(i == 5) - { - //DbgMsg((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__)); - goto RD_DIS_MAPPING; - } - gBS->Stall(1000); - i++; - bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000); - - } - } - else if(g_deviceId == PCI_DEV_ID_SDS1) - { - i = 0; - bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000); - while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0) - { - if(i == 5) - { - //DbgErr((DRIVERNAME " - %s() function 1 can't lock!\n", __FUNCTION__)); - goto RD_DIS_MAPPING; - } - gBS->Stall(1000); - i++; - bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000); - } - } - - // Check last operation is complete - i = 0; - while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000) - { - if(i == 5) - { - //DbgErr((DRIVERNAME " - [204] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingCtl))); - //DbgErr((DRIVERNAME " - [208] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingEn))); - //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__)); - goto RD_DIS_MAPPING; - } - gBS->Stall(1000); - i += 1; - } - - // Set register address - tmp[0] |= 0x40000000; - tmp[0] |= offset; - bht_writel(PciIo, BHT_PCIRMappingCtl, tmp[0]); - - // Check read is complete - i = 0; - while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x40000000) - { - if(i == 5) - { - //DbgErr((DRIVERNAME " - %s() check read operation complete timeout!!!\n", __FUNCTION__)); - goto RD_DIS_MAPPING; - } - gBS->Stall(1000); - i += 1; - } - - // Get PCIR value - tmp[1] = bht_readl(PciIo, BHT_PCIRMappingVal); - -RD_DIS_MAPPING: - // Disable mapping - bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000); - - //DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[1]); - return tmp[1]; - } - - //DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[0]); - return tmp[0]; -} - -void PciBhtWrite32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value) -{ - UINT32 tmp = 0; - UINT32 i = 0; - - if((g_deviceId == PCI_DEV_ID_SDS0) || - (g_deviceId == PCI_DEV_ID_SDS1) || - (g_deviceId == PCI_DEV_ID_FJ2) || - (g_deviceId == PCI_DEV_ID_SB0) || - (g_deviceId == PCI_DEV_ID_SB1)) - { - // For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg. - // Upper caller doesn't need to set 0xD0. - - // Enable mapping - - // Check function conflict - if((g_deviceId == PCI_DEV_ID_SDS0) || - (g_deviceId == PCI_DEV_ID_FJ2) || - (g_deviceId == PCI_DEV_ID_SB0) || - (g_deviceId == PCI_DEV_ID_SB1)) - { - i = 0; - bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000); - while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0) - { - if(i == 5) - { - //DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__)); - goto WR_DIS_MAPPING; - } - - gBS->Stall(1000); - i++; - bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000); - } - } - else if(g_deviceId == PCI_DEV_ID_SDS1) - { - i = 0; - bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000); - - while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0) - { - if(i == 5) - { - //DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__)); - goto WR_DIS_MAPPING; - } - - gBS->Stall(1000); - i++; - bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000); - } - } - - // Enable MEM access - bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000000); - bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0); - - // Check last operation is complete - i = 0; - while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000) - { - if(i == 5) - { - //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__)); - goto WR_DIS_MAPPING; - } - gBS->Stall(1000); - i += 1; - } - - // Set write value - bht_writel(PciIo, BHT_PCIRMappingVal, value); - // Set register address - tmp |= 0x80000000; - tmp |= offset; - bht_writel(PciIo, BHT_PCIRMappingCtl, tmp); - - // Check write is complete - i = 0; - while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x80000000) - { - if(i == 5) - { - //DbgErr((DRIVERNAME " - %s() check write operation complete timeout!!!\n", __FUNCTION__)); - goto WR_DIS_MAPPING; - } - gBS->Stall(1000); - i += 1; - } - -WR_DIS_MAPPING: - // Disable MEM access - bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000001); - bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0); - - // Check last operation is complete - i = 0; - while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000) - { - if(i == 5) - { - //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__)); - break; - } - gBS->Stall(1000); - i += 1; - } - - // Disable function conflict - - // Disable mapping - bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000); - } -} - -void PciBhtOr32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value) -{ - UINT32 arg; - arg = PciBhtRead32(PciIo, offset); - PciBhtWrite32(PciIo, offset, value | arg); -} - -void PciBhtAnd32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value) -{ - UINT32 arg; - arg = PciBhtRead32(PciIo, offset); - PciBhtWrite32(PciIo, offset, value & arg); -} - Please check it! Br, Mike _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel