From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id 28FC5AC117B for ; Fri, 15 Sep 2023 14:25:38 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=KR3o6AUx3kh+oV/QfVSUaqwr7z694rvfJ03xHxWUhAM=; c=relaxed/simple; d=groups.io; h=Date:From:To:CC:Subject:Message-ID:References:MIME-Version:In-Reply-To:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Type:Content-Disposition; s=20140610; t=1694787937; v=1; b=X3ebyNMFBcFqNR1N9nMoLvsedc2tPrzoJwN++P4Q91K90YxfwhK9k3gFe3YhNri/6bTAUJCH HmpcDsfB85SIqKlho3rt7hsLEC5bt3b3BWbYQFUOxffL5HA/3vDQY8gf5SIKBc3i+tOsepfsz5j DnqME8WK56O9+fKJmYwepU3A= X-Received: by 127.0.0.2 with SMTP id fptOYY7687511xGbwr7JbGjW; Fri, 15 Sep 2023 07:25:37 -0700 X-Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) by mx.groups.io with SMTP id smtpd.web10.21885.1694787936997599009 for ; Fri, 15 Sep 2023 07:25:37 -0700 X-Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38FD75pl012572; Fri, 15 Sep 2023 14:25:33 GMT X-Received: from nasanppmta01.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3t4g5th4e9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 15 Sep 2023 14:25:33 +0000 X-Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA01.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 38FEPWQJ015133 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 15 Sep 2023 14:25:32 GMT X-Received: from qc-i7.hemma.eciton.net (10.80.80.8) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.36; Fri, 15 Sep 2023 07:25:29 -0700 Date: Fri, 15 Sep 2023 15:25:26 +0100 From: "Leif Lindholm" To: CC: , , , Subject: Re: [edk2-devel] [PATCH v3 4/8] Sophgo/SG2042Pkg: Add base MMC driver. Message-ID: References: MIME-Version: 1.0 In-Reply-To: X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-ORIG-GUID: mDY-a2Q7udgAXKHBG9d5E7HTwvJ6ir_F X-Proofpoint-GUID: mDY-a2Q7udgAXKHBG9d5E7HTwvJ6ir_F Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,quic_llindhol@quicinc.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: m6nqkahsS82cdDjoSI8G2wwEx7686176AA= Content-Type: text/plain; charset="us-ascii" Content-Disposition: inline X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b=X3ebyNMF; dmarc=fail reason="SPF not aligned (relaxed), DKIM not aligned (relaxed)" header.from=quicinc.com (policy=none); spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io On Thu, Sep 07, 2023 at 18:25:47 +0800, caiyuqing_hz@163.com wrote: > From: caiyuqing379 <202235273@mail.sdu.edu.cn> > > This driver implements the MMC Host protocol, which is used by SD > interface driver that the Sophgo SG2042 EVB supports. Add this driver > in Sophgo/SG2042Pkg leveraging the one form Embedded Package. > > Signed-off-by: caiyuqing379 <202235273@mail.sdu.edu.cn> > Co-authored-by: USER0FISH > Cc: dahogn > Cc: meng-cz > Cc: yli147 > Cc: ChaiEvan > Cc: Sunil V L > Cc: Leif Lindholm > --- > .../SG2042Pkg/Drivers/MmcDxe/MmcDxe.inf | 46 ++ > Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/Mmc.h | 513 +++++++++++++ > Silicon/Sophgo/SG2042Pkg/Include/MmcHost.h | 225 ++++++ > .../SG2042Pkg/Drivers/MmcDxe/ComponentName.c | 156 ++++ > .../SG2042Pkg/Drivers/MmcDxe/Diagnostics.c | 323 ++++++++ > Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/Mmc.c | 527 +++++++++++++ > .../SG2042Pkg/Drivers/MmcDxe/MmcBlockIo.c | 643 ++++++++++++++++ > .../SG2042Pkg/Drivers/MmcDxe/MmcDebug.c | 194 +++++ > .../Drivers/MmcDxe/MmcIdentification.c | 719 ++++++++++++++++++ > 9 files changed, 3346 insertions(+) > create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcDxe.inf > create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/Mmc.h > create mode 100644 Silicon/Sophgo/SG2042Pkg/Include/MmcHost.h > create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/ComponentName.c > create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/Diagnostics.c > create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/Mmc.c > create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcBlockIo.c > create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcDebug.c > create mode 100644 Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcIdentification.c > > diff --git a/Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcIdentification.c b/Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcIdentification.c > new file mode 100644 > index 000000000000..855b45b794a7 > --- /dev/null > +++ b/Silicon/Sophgo/SG2042Pkg/Drivers/MmcDxe/MmcIdentification.c > @@ -0,0 +1,719 @@ > +/** @file > + Define a simple and generic interface to access SD-card devices. > + > + Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. > + Copyright (c) 2023, Academy of Intelligent Innovation, Shandong Universiy, China.P.R. All rights reserved.
> + > + SPDX-License-Identifier: BSD-3-Clause Again, this is not the license this project is under. / Leif > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "Mmc.h" > + > +#define MMC_DEFAULT_MAX_RETRIES 5 > +#define SEND_OP_COND_MAX_RETRIES 100 > + > +#define MULT_BY_512K_SHIFT 19 > + > +STATIC UINT32 MmcOCR; > +STATIC CSD MmcCsd; > +STATIC UINT8 MmcExtCsd[512] __attribute__ ((aligned(16))); > +STATIC UINT32 MmcRCA; > +STATIC UINT32 MmcSCR[2] __attribute__ ((aligned(16))) = { 0 }; > + > +typedef enum _MMC_DEVICE_TYPE { > + MMC_IS_EMMC, > + MMC_IS_SD, > + MMC_IS_SD_HC, > +} MMC_DEVICE_TYPE; > + > +typedef struct { > + UINT64 DeviceSize; /* Size of device in bytes */ > + UINT32 BlockSize; /* Block size in bytes */ > + UINT32 MaxBusFreq; /* Max bus freq in Hz */ > + UINT32 OCRVoltage; /* OCR voltage */ > + MMC_DEVICE_TYPE MmcDevType; /* Type of MMC */ > +} MMC_DEVICE_INFO; > + > +STATIC MMC_DEVICE_INFO MmcDevInfo = { > + .MmcDevType = MMC_IS_SD_HC, > + .OCRVoltage = 0x00300000, // OCR 3.2~3.3 3.3~3.4 > +}; > + > +STATIC CONST UINT8 TranSpeedBase[16] = { > + 0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80 > +}; > + > +STATIC CONST UINT8 SdTranSpeedBase[16] = { > + 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 > +}; > + > +/** > + Get the current state of the MMC device. > + > + @param[in] MmcHostInstance Pointer to the MMC_HOST_INSTANCE structure. > + @param[out] State Pointer to the variable to store the device state. > + > + @retval EFI_SUCCESS The device state was retrieved successfully. > + @retval EFI_DEVICE_ERROR Failed to retrieve the device state. > + > +**/ > +STATIC > +EFI_STATUS > +MmcDeviceState ( > + IN MMC_HOST_INSTANCE *MmcHostInstance, > + IN UINT32 *State > + ) > +{ > + EFI_STATUS Status; > + INT32 RetryCount; > + UINT32 Response[4]; > + > + RetryCount = MMC_DEFAULT_MAX_RETRIES; > + > + do { > + if (RetryCount == 0) { > + DEBUG ((DEBUG_ERROR, "%a: CMD13 failed after %d retries\n", __func__, MMC_DEFAULT_MAX_RETRIES)); > + return EFI_DEVICE_ERROR; > + } > + > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD13, MmcRCA << RCA_SHIFT_OFFSET, > + MMC_RESPONSE_R1, Response); > + if (EFI_ERROR (Status)) { > + RetryCount--; > + continue; > + } > + > + if ((Response[0] & MMC_R0_SWITCH_ERROR) != 0U) { > + return EFI_DEVICE_ERROR; > + } > + > + RetryCount--; > + } while ((Response[0] & MMC_R0_READY_FOR_DATA) == 0U); > + > + // DEBUG ((DEBUG_INFO, "%a: sd state %x\n", __func__, MMC_R0_CURRENTSTATE(Response))); > + *State = MMC_R0_CURRENTSTATE (Response); > + > + return EFI_SUCCESS; > +} > + > +/** > + Set the value of the specified MMC extended CSD register. > + > + @param[in] MmcHostInstance Pointer to the MMC_HOST_INSTANCE structure. > + @param[in] ExtCmd The extended CSD command. > + @param[in] Value The value to set. > + > + @retval EFI_SUCCESS The value was successfully set. > + @retval Other An error occurred while setting the value. > + > +**/ > +STATIC > +EFI_STATUS > +MmcSetExtCsd ( > + IN MMC_HOST_INSTANCE *MmcHostInstance, > + IN UINT32 ExtCmd, > + IN UINT32 Value > + ) > +{ > + EFI_STATUS Status; > + UINT32 State; > + > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD6, > + EXTCSD_WRITE_BYTES | EXTCSD_CMD(ExtCmd) | > + EXTCSD_VALUE(Value) | EXTCSD_CMD_SET_NORMAL, > + MMC_RESPONSE_R1B, NULL); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + do { > + Status = MmcDeviceState (MmcHostInstance, &State); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } while (State == MMC_R0_STATE_PROG); > + > + return EFI_SUCCESS; > +} > + > +/** > + Perform an SD switch to set the bus width for the MMC/SD device. > + > + @param[in] MmcHostInstance Pointer to the MMC_HOST_INSTANCE structure. > + @param[in] BusWidth The desired bus width. > + > + @retval EFI_SUCCESS The bus width was successfully set. > + @retval Other An error occurred while setting the bus width. > + > +**/ > +STATIC > +EFI_STATUS > +MmcSdSwitch ( > + IN MMC_HOST_INSTANCE *MmcHostInstance, > + IN UINT32 BusWidth > + ) > +{ > + EFI_STATUS Status; > + UINT32 State; > + INT32 RetryCount; > + UINT32 BusWidthArg; > + > + RetryCount = MMC_DEFAULT_MAX_RETRIES; > + BusWidthArg = 0; > + > + Status = MmcHostInstance->MmcHost->Prepare (MmcHostInstance->MmcHost, 0, sizeof(MmcSCR), (UINTN)&MmcSCR); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // CMD55: Application Specific Command > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD55, MmcRCA << RCA_SHIFT_OFFSET, > + MMC_RESPONSE_R5, NULL); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // ACMD51: SEND_SCR > + do { > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_ACMD51, 0, MMC_RESPONSE_R1, NULL); > + if ((EFI_ERROR (Status)) && (RetryCount == 0)) { > + DEBUG ((DEBUG_ERROR, "%a: ACMD51 failed after %d retries (Status=%r)\n", __func__, MMC_DEFAULT_MAX_RETRIES, Status)); > + return Status; > + } > + > + RetryCount--; > + } while (EFI_ERROR (Status)); > + > + Status = MmcHostInstance->MmcHost->ReadBlockData (MmcHostInstance->MmcHost, 0, sizeof(MmcSCR), MmcSCR); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (((MmcSCR[0] & SD_SCR_BUS_WIDTH_4) != 0U) && (BusWidth == MMC_BUS_WIDTH_4)) { > + BusWidthArg = 2; > + } > + > + // CMD55: Application Specific Command > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD55, MmcRCA << RCA_SHIFT_OFFSET, > + MMC_RESPONSE_R5, NULL); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // ACMD6: SET_BUS_WIDTH > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD6, BusWidthArg, MMC_RESPONSE_R1, NULL); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + do { > + Status = MmcDeviceState (MmcHostInstance, &State); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } while (State == MMC_R0_STATE_PROG); > + > + return EFI_SUCCESS; > +} > + > +/** > + Set the I/O settings for the MMC/SD device. > + > + @param[in] MmcHostInstance Pointer to the MMC_HOST_INSTANCE structure. > + @param[in] Clk The desired clock frequency. > + @param[in] BusWidth The desired bus width. > + > + @retval EFI_SUCCESS The I/O settings were successfully set. > + @retval Other An error occurred while setting the I/O settings. > + > +**/ > +STATIC > +EFI_STATUS > +MmcSetIos ( > + IN MMC_HOST_INSTANCE *MmcHostInstance, > + IN UINT32 Clk, > + IN UINT32 BusWidth > + ) > +{ > + EFI_STATUS Status; > + UINT32 Width; > + > + Width = BusWidth; > + > + if (MmcDevInfo.MmcDevType != MMC_IS_EMMC) { > + if (Width == MMC_BUS_WIDTH_8) { > + DEBUG ((DEBUG_INFO, "%a: Wrong bus config for SD-card, force to 4\n", __func__)); > + Width = MMC_BUS_WIDTH_4; > + } > + > + Status = MmcSdSwitch (MmcHostInstance, Width); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } else if (MmcCsd.SPEC_VERS == 4U) { > + Status = MmcSetExtCsd (MmcHostInstance, CMD_EXTCSD_BUS_WIDTH, (UINT32)Width); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } else { > + DEBUG ((DEBUG_INFO, "%a: Wrong MMC type or spec version\n", __func__)); > + } > + > + return MmcHostInstance->MmcHost->SetIos (MmcHostInstance->MmcHost, Clk, Width); > +} > + > +/** > + Fill the MMC device information. > + > + @param[in] MmcHostInstance Pointer to the MMC_HOST_INSTANCE structure. > + > + @retval EFI_SUCCESS The MMC device information was successfully filled. > + @retval EFI_DEVICE_ERROR Failed to fill the MMC device information. > + @retval Other An error occurred while filling the MMC device information. > + > +**/ > +STATIC > +EFI_STATUS > +MmcFillDeviceInfo ( > + IN MMC_HOST_INSTANCE *MmcHostInstance > + ) > +{ > + EFI_STATUS Status; > + UINTN CardSize; > + UINT32 SpeedIdx; > + UINT32 NumBlocks; > + UINT32 FreqUnit; > + UINT32 State; > + ECSD *CsdSdV2; > + > + Status = EFI_SUCCESS; > + > + switch (MmcDevInfo.MmcDevType) { > + case MMC_IS_EMMC: > + MmcDevInfo.BlockSize = MMC_BLOCK_SIZE; > + > + Status = MmcHostInstance->MmcHost->Prepare (MmcHostInstance->MmcHost, 0, sizeof(MmcExtCsd), (UINTN)&MmcExtCsd); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + /* MMC CMD8: SEND_EXT_CSD */ > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD8, 0, MMC_RESPONSE_R1, NULL); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = MmcHostInstance->MmcHost->ReadBlockData (MmcHostInstance->MmcHost, 0, sizeof(MmcExtCsd), (UINT32*)MmcExtCsd); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + do { > + Status = MmcDeviceState (MmcHostInstance, &State); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } while (State != MMC_R0_STATE_TRAN); > + > + NumBlocks = (MmcExtCsd[CMD_EXTCSD_SEC_CNT] << 0) | > + (MmcExtCsd[CMD_EXTCSD_SEC_CNT + 1] << 8) | > + (MmcExtCsd[CMD_EXTCSD_SEC_CNT + 2] << 16) | > + (MmcExtCsd[CMD_EXTCSD_SEC_CNT + 3] << 24); > + > + MmcDevInfo.DeviceSize = (UINT64)NumBlocks * MmcDevInfo.BlockSize; > + > + break; > + > + case MMC_IS_SD: > + /* > + * Use the same MmcCsd struct, as required fields here > + * (READ_BL_LEN, C_SIZE, CSIZE_MULT) are common with eMMC. > + */ > + MmcDevInfo.BlockSize = BIT_32(MmcCsd.READ_BL_LEN); > + > + CardSize = ((UINT64)MmcCsd.C_SIZEHigh10 << 2U) | > + (UINT64)MmcCsd.C_SIZELow2; > + ASSERT(CardSize != 0xFFFU); > + > + MmcDevInfo.DeviceSize = (CardSize + 1U) * > + BIT_64(MmcCsd.C_SIZE_MULT + 2U) * > + MmcDevInfo.BlockSize; > + > + break; > + > + case MMC_IS_SD_HC: > + MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH; > + > + ASSERT (MmcCsd.CSD_STRUCTURE == 1U); > + > + MmcDevInfo.BlockSize = MMC_BLOCK_SIZE; > + > + /* Need to use ECSD struct */ > + CsdSdV2 = (ECSD *)&MmcCsd; > + CardSize = ((UINT64)CsdSdV2->C_SIZEHigh6 << 16) | > + (UINT64)CsdSdV2->C_SIZELow16; > + > + MmcDevInfo.DeviceSize = (CardSize + 1U) << MULT_BY_512K_SHIFT; > + break; > + > + default: > + Status = EFI_DEVICE_ERROR; > + break; > + } > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + SpeedIdx = (MmcCsd.TRAN_SPEED & CSD_TRAN_SPEED_MULT_MASK) >> > + CSD_TRAN_SPEED_MULT_SHIFT; > + > + ASSERT (SpeedIdx > 0U); > + > + if (MmcDevInfo.MmcDevType == MMC_IS_EMMC) { > + MmcDevInfo.MaxBusFreq = TranSpeedBase[SpeedIdx]; > + } else { > + MmcDevInfo.MaxBusFreq = SdTranSpeedBase[SpeedIdx]; > + } > + > + FreqUnit = MmcCsd.TRAN_SPEED & CSD_TRAN_SPEED_UNIT_MASK; > + while (FreqUnit != 0U) { > + MmcDevInfo.MaxBusFreq *= 10U; > + --FreqUnit; > + } > + > + MmcDevInfo.MaxBusFreq *= 10000U; > + > + return EFI_SUCCESS; > +} > + > +/** > + Send the SD_SEND_OP_COND command to initialize the SD card. > + > + @param[in] MmcHostInstance Pointer to the MMC_HOST_INSTANCE structure. > + > + @retval EFI_SUCCESS The SD_SEND_OP_COND command was successfully sent. > + @retval EFI_DEVICE_ERROR Failed to send the SD_SEND_OP_COND command. > + @retval Other An error occurred while sending the SD_SEND_OP_COND command. > + > +**/ > +STATIC > +EFI_STATUS > +SdSendOpCond ( > + IN MMC_HOST_INSTANCE *MmcHostInstance > + ) > +{ > + EFI_STATUS Status; > + INT32 I; > + UINT32 Response[4]; > + > + for (I = 0; I < SEND_OP_COND_MAX_RETRIES; I++) { > + // CMD55: Application Specific Command > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD55, 0, MMC_RESPONSE_R1, NULL); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // ACMD41: SD_SEND_OP_COND > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_ACMD41, OCR_HCS | > + MmcDevInfo.OCRVoltage, MMC_RESPONSE_R3, Response); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if ((Response[0] & MMC_OCR_POWERUP) != 0U) { > + MmcOCR = Response[0]; > + > + if ((MmcOCR & OCR_HCS) != 0U) { > + MmcDevInfo.MmcDevType = MMC_IS_SD_HC; > + MmcHostInstance->CardInfo.OCRData.AccessMode = 0x2; > + } else { > + MmcDevInfo.MmcDevType = MMC_IS_SD; > + MmcHostInstance->CardInfo.OCRData.AccessMode = 0x0; > + } > + > + return EFI_SUCCESS; > + } > + > + gBS->Stall (10000); > + } > + > + DEBUG ((DEBUG_ERROR, "%a: ACMD41 failed after %d retries\n", __func__, SEND_OP_COND_MAX_RETRIES)); > + > + return EFI_DEVICE_ERROR; > +} > + > +/** > + Reset the MMC/SD card to the idle state. > + > + @param[in] MmcHostInstance Pointer to the MMC_HOST_INSTANCE structure. > + > + @retval EFI_SUCCESS The MMC/SD card was successfully reset to the idle state. > + @retval Other An error occurred while resetting the MMC/SD card to the idle state. > + > +**/ > +STATIC > +EFI_STATUS > +MmcResetToIdle( > + IN MMC_HOST_INSTANCE *MmcHostInstance > + ) > +{ > + EFI_STATUS Status; > + > + /* CMD0: reset to IDLE */ > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD0, 0, 0, NULL); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + gBS->Stall (2000); > + > + return EFI_SUCCESS; > +} > + > +/** > + Send the Operation Condition (CMD1) to the MMC/SD card. > + > + @param[in] MmcHostInstance Pointer to the MMC_HOST_INSTANCE structure. > + > + @retval EFI_SUCCESS The Operation Condition was successfully sent to the MMC/SD card. > + @retval EFI_DEVICE_ERROR Failed to send the Operation Condition to the MMC/SD card. > + @retval Other An error occurred while sending the Operation Condition to the MMC/SD card. > + > +**/ > +STATIC > +EFI_STATUS > +MmcSendOpCond ( > + IN MMC_HOST_INSTANCE *MmcHostInstance > + ) > +{ > + INT32 I; > + EFI_STATUS Status; > + UINT32 Response[4]; > + > + Status = MmcResetToIdle (MmcHostInstance); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + for (I = 0; I < SEND_OP_COND_MAX_RETRIES; I++) { > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD1, OCR_SECTOR_MODE | > + OCR_VDD_MIN_2V7 | OCR_VDD_MIN_1V7, > + MMC_RESPONSE_R3, Response); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if ((Response[0] & MMC_OCR_POWERUP) != 0U) { > + MmcOCR = Response[0]; > + return EFI_SUCCESS; > + } > + > + gBS->Stall (10000); > + } > + > + DEBUG ((DEBUG_ERROR, "%a: CMD1 failed after %d retries\n", __func__, SEND_OP_COND_MAX_RETRIES)); > + > + return EFI_DEVICE_ERROR; > +} > + > +/** > + Enumerate and initialize the MMC/SD card. > + > + @param[in] MmcHostInstance Pointer to the MMC_HOST_INSTANCE structure. > + @param[in] Clk Clock frequency for the MMC/SD card. > + @param[in] BusWidth Bus width for the MMC/SD card. > + > + @retval EFI_SUCCESS The MMC/SD card was successfully enumerated and initialized. > + @retval Other An error occurred while enumerating and initializing the MMC/SD card. > + > +**/ > +STATIC > +EFI_STATUS > +MmcEnumerte ( > + IN MMC_HOST_INSTANCE *MmcHostInstance, > + IN UINT32 Clk, > + IN UINT32 BusWidth > + ) > +{ > + EFI_STATUS Status; > + UINT32 State; > + UINT32 Response[4]; > + > + Status = MmcResetToIdle (MmcHostInstance); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (MmcDevInfo.MmcDevType == MMC_IS_EMMC) { > + Status = MmcSendOpCond (MmcHostInstance); > + } else { > + // CMD8: Send Interface Condition Command > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD8, VHS_2_7_3_6_V | CMD8_CHECK_PATTERN, > + MMC_RESPONSE_R5, Response); > + > + if ((Status == EFI_SUCCESS) && ((Response[0] & 0xffU) == CMD8_CHECK_PATTERN)) { > + Status = SdSendOpCond (MmcHostInstance); > + } > + } > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // CMD2: Card Identification > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD2, 0, MMC_RESPONSE_R2, NULL); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // CMD3: Set Relative Address > + if (MmcDevInfo.MmcDevType == MMC_IS_EMMC) { > + MmcRCA = MMC_FIX_RCA; > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD3, MmcRCA << RCA_SHIFT_OFFSET, > + MMC_RESPONSE_R1, NULL); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } else { > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD3, 0, > + MMC_RESPONSE_R6, Response); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + MmcRCA = (Response[0] & 0xFFFF0000U) >> 16; > + } > + > + // CMD9: CSD Register > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD9, MmcRCA << RCA_SHIFT_OFFSET, > + MMC_RESPONSE_R2, Response); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + CopyMem(&MmcCsd, &Response, sizeof(Response)); > + > + // CMD7: Select Card > + Status = MmcHostInstance->MmcHost->SendCommand (MmcHostInstance->MmcHost, MMC_CMD7, MmcRCA << RCA_SHIFT_OFFSET, > + MMC_RESPONSE_R1, NULL); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + do { > + Status = MmcDeviceState (MmcHostInstance, &State); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } while (State != MMC_R0_STATE_TRAN); > + > + Status = MmcSetIos (MmcHostInstance, Clk, BusWidth); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + return MmcFillDeviceInfo (MmcHostInstance); > +} > + > +/** > + Perform the MMC Identification Mode. > + > + @param[in] MmcHostInstance Pointer to the MMC_HOST_INSTANCE structure. > + > + @retval EFI_SUCCESS The MMC Identification Mode was performed successfully. > + @retval EFI_INVALID_PARAMETER MmcHost is NULL. > + @retval Other An error occurred while performing the MMC Identification Mode. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +MmcIdentificationMode ( > + IN MMC_HOST_INSTANCE *MmcHostInstance > + ) > +{ > + EFI_STATUS Status; > + UINTN CmdArg; > + BOOLEAN IsHCS; > + EFI_MMC_HOST_PROTOCOL *MmcHost; > + > + MmcHost = MmcHostInstance->MmcHost; > + CmdArg = 0; > + IsHCS = FALSE; > + > + if (MmcHost == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + // We can get into this function if we restart the identification mode > + if (MmcHostInstance->State == MmcHwInitializationState) { > + // Initialize the MMC Host HW > + Status = MmcNotifyState (MmcHostInstance, MmcHwInitializationState); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcHwInitializationState, Status=%r.\n", Status)); > + return Status; > + } > + } > + > + Status = MmcEnumerte (MmcHostInstance, 50 * 1000 * 1000, MMC_BUS_WIDTH_4); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcEnumerte, Status=%r.\n", Status)); > + return Status; > + } > + > + MmcHostInstance->CardInfo.RCA = MmcRCA; > + MmcHostInstance->BlockIo.Media->LastBlock = ((MmcDevInfo.DeviceSize >> 9) - 1); > + MmcHostInstance->BlockIo.Media->BlockSize = MmcDevInfo.BlockSize; > + MmcHostInstance->BlockIo.Media->ReadOnly = MmcHost->IsReadOnly (MmcHost); > + MmcHostInstance->BlockIo.Media->MediaPresent = TRUE; > + MmcHostInstance->BlockIo.Media->MediaId++; > + > + return EFI_SUCCESS; > +} > + > +/** > + Initialize the MMC device. > + > + @param[in] MmcHostInstance MMC host instance > + > + @retval EFI_SUCCESS MMC device initialized successfully > + @retval Other MMC device initialization failed > + > +**/ > +EFI_STATUS > +InitializeMmcDevice ( > + IN MMC_HOST_INSTANCE *MmcHostInstance > + ) > +{ > + EFI_STATUS Status; > + EFI_MMC_HOST_PROTOCOL *MmcHost; > + UINTN BlockCount; > + > + BlockCount = 1; > + MmcHost = MmcHostInstance->MmcHost; > + > + Status = MmcIdentificationMode (MmcHostInstance); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "InitializeMmcDevice(): Error in Identification Mode, Status=%r\n", Status)); > + return Status; > + } > + > + Status = MmcNotifyState (MmcHostInstance, MmcTransferState); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "InitializeMmcDevice(): Error MmcTransferState, Status=%r\n", Status)); > + return Status; > + } > + > + return EFI_SUCCESS; > +} > -- > 2.34.1 > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108730): https://edk2.groups.io/g/devel/message/108730 Mute This Topic: https://groups.io/mt/101213495/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/leave/12367111/7686176/1913456212/xyzzy [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-