From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=104.47.37.114; helo=nam02-cy1-obe.outbound.protection.outlook.com; envelope-from=christopher.co@microsoft.com; receiver=edk2-devel@lists.01.org Received: from NAM02-CY1-obe.outbound.protection.outlook.com (mail-cys01nam02on0114.outbound.protection.outlook.com [104.47.37.114]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 12F04210D5133 for ; Wed, 1 Aug 2018 16:59:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=HmYD9ulGWz9sZLvg8LB53TA6eeBYDK8Q9NXh8WJZv8c=; b=DxdcNTxBHjaB4Rep1BOMndPP1xvj1GXzn915oTDkkyI0GCmCqT8rjzCFYRPoIXa/CUSFA0aY+L76JwhB/brWQjwyKaz5U/hxPZ1w3uiBgTsdDx6ta5CYa3bk8nTrSHpeM12TKi3s2tqyopMPpcSm5mAKvIZ17C9ffPv2l+UPzp8= Received: from DM5PR2101MB1128.namprd21.prod.outlook.com (52.132.133.20) by DM5PR2101MB0968.namprd21.prod.outlook.com (52.132.133.26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1038.6; Wed, 1 Aug 2018 23:59:22 +0000 Received: from DM5PR2101MB1128.namprd21.prod.outlook.com ([fe80::95a8:6c24:9ca4:e80e]) by DM5PR2101MB1128.namprd21.prod.outlook.com ([fe80::95a8:6c24:9ca4:e80e%3]) with mapi id 15.20.1038.003; Wed, 1 Aug 2018 23:59:22 +0000 From: Chris Co To: Leif Lindholm CC: "edk2-devel@lists.01.org" , Ard Biesheuvel , Michael D Kinney Thread-Topic: [PATCH edk2-platforms 1/7] Silicon/NXP: Add support for iMX SDHC Thread-Index: AQHUHxaKKE2XqFnFn0SByyM3CCUcDKSrJ3MAgAB983A= Date: Wed, 1 Aug 2018 23:59:21 +0000 Message-ID: References: <20180719041103.9072-1-christopher.co@microsoft.com> <20180719041103.9072-2-christopher.co@microsoft.com> <20180801161508.uvfzsbbntzwtiv2d@bivouac.eciton.net> In-Reply-To: <20180801161508.uvfzsbbntzwtiv2d@bivouac.eciton.net> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: msip_labels: MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Enabled=True; MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_SiteId=72f988bf-86f1-41af-91ab-2d7cd011db47; MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Owner=chrco@microsoft.com; MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_SetDate=2018-08-01T23:59:19.9103787Z; MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Name=General; MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Application=Microsoft Azure Information Protection; MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Extended_MSFT_Method=Automatic; Sensitivity=General x-originating-ip: [2001:4898:80e8:0:c95d:632a:42fc:503e] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; DM5PR2101MB0968; 6:PjoRMfsOdJcXuLuj2u9wY6p84Rnj5ARiHGBzDskgT8V9D2gLNCAAs7lljtzNg0M1vzp6RsHgzS+R8Vf+Z2mYOe9aB0+XWJZgH/QggeYvDlv5+2s9nTrdnaQf2KSoJwxH2wHfv+qAcPDRmPt2q93sKxPl0d1oEC9eOLFQXikjlKV0p9mbOpQ/yAcvj40l9eQDYUFompLiQSvNCoqzwHugplzV+mA1v/Kw7agHpUlyNIAFNcqURcZ43oXbnI7a1ny2wuf2cWWOvi19grN+Ho2TLm50cqJpmaxBJzktJNpIBKf/TIcYznpoOqEtEDgYhseTGPgC9s6v4McqmmAeF/2eUD6WZ3sdOOGWd5ylhdeLijfy/GCwVLFWXe5zOHb2gQHNFp05n9KYKxUgKDywDv8Ll6KfLBVfJx8P5PZ/aj8WqtvhRHC53BSAUQubnr+dUv2za6JGpArd+D7kDf8G6kLSWQ==; 5:huNGrTWLV0AN14Rivg2Oxl5Tf8yh6o7DwRTzPUPRXp4m4nCe6q/1OubiQ7WWY/HFldIcC+v1kOuJ8a0YRH9LdX0S6xkQAkmp3VqNGEDPR9MDdfNOexKJ8/62bzfi0sl5JiiHuqADnEudLmbkecNCJm3ZgS3opDesoAp2iDEH3xI=; 7:iIY5Wr7scu262QEsCsvYCs11R6DAIzHUczrFzCkyQGUQVsulY/+cg3enfpZxnWgdOqTZbc39+hJijJSoWQ8X3aEKnW2wY80Kc2yK+mA5VcUXljrpOCg76y9lYm2X7R/JtBCl4nhMSeYQY1i590tciwG3SwUT0cc37kaZP8lDITUnnfJ14AKk3KtTUFQs0hpsfJvSERFdK84py3cYLuMIeuA15i8xeCbFNNYH53ZgyRu4M1g/sSwTJG2MQm5MNEfX x-ms-exchange-antispam-srfa-diagnostics: SOS; x-ms-office365-filtering-correlation-id: 350041b3-1a83-4d14-4bb8-08d5f80acd48 x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: BCL:0; PCL:0; RULEID:(7020095)(4652040)(8989117)(4534165)(4627221)(201703031133081)(201702281549075)(8990107)(5600074)(711020)(4618075)(2017052603328)(7193020); SRVR:DM5PR2101MB0968; x-ms-traffictypediagnostic: DM5PR2101MB0968: authentication-results: spf=none (sender IP is ) smtp.mailfrom=Christopher.Co@microsoft.com; x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(28532068793085)(89211679590171)(189930954265078)(162533806227266)(219752817060721)(228905959029699); x-ms-exchange-senderadcheck: 1 x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(3002001)(3231311)(944501410)(52105095)(2018427008)(10201501046)(93006095)(93001095)(6055026)(149027)(150027)(6041310)(20161123562045)(20161123560045)(20161123558120)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123564045)(6072148)(201708071742011)(7699016); SRVR:DM5PR2101MB0968; BCL:0; PCL:0; RULEID:; SRVR:DM5PR2101MB0968; x-forefront-prvs: 0751474A44 x-forefront-antispam-report: SFV:NSPM; SFS:(10019020)(346002)(366004)(396003)(376002)(39860400002)(136003)(199004)(189003)(13464003)(81156014)(81166006)(10090500001)(16200700003)(8990500004)(53946003)(6506007)(33656002)(2906002)(53546011)(8936002)(229853002)(53936002)(102836004)(6246003)(6306002)(74316002)(7736002)(305945005)(6116002)(4326008)(9686003)(105586002)(345774005)(106356001)(478600001)(55016002)(6916009)(16799955002)(8676002)(14454004)(6436002)(72206003)(966005)(10290500003)(5660300001)(5250100002)(25786009)(7696005)(486006)(256004)(76176011)(46003)(68736007)(97736004)(476003)(86612001)(575784001)(86362001)(54906003)(45954006)(19627235002)(186003)(99286004)(22452003)(14444005)(316002)(2900100001)(446003)(11346002)(559001)(569006); DIR:OUT; SFP:1102; SCL:1; SRVR:DM5PR2101MB0968; H:DM5PR2101MB1128.namprd21.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: microsoft.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: Za/nrie0RntYyl5FnK4S2plnLYvy6E1WJIaWc5/SYNwgejcyjHBC6HOXjUzK51lWl6u9kZROo6ZyTFiAZX9qMbJ2jryF8f/gyCwe0G1xws4CPlCJ0EV5ii5eKVvDFR2EAdus1qMy9eat9TSl2ZW9fOSFRnYisDdhUs1a+YcPAFiP5mikfK8bPzQwai8anfYPtpQyf2ipkQWja5mjWwCpYrvlLcyudtGYfiXVeaH7+gDm34ojycDIloi14wLUTNKP9aRiwCMv+nfil/ZXeao4JyEMwdbymTDElIsR7crRuAStNskHWmtbQaLCBoZ5msUpHxxGdMko8gi2UH5Is6QrTrZ11dczYuadKBL8RJ2oWK0= spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM MIME-Version: 1.0 X-OriginatorOrg: microsoft.com X-MS-Exchange-CrossTenant-Network-Message-Id: 350041b3-1a83-4d14-4bb8-08d5f80acd48 X-MS-Exchange-CrossTenant-originalarrivaltime: 01 Aug 2018 23:59:21.8659 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 72f988bf-86f1-41af-91ab-2d7cd011db47 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR2101MB0968 Subject: Re: [PATCH edk2-platforms 1/7] Silicon/NXP: Add support for iMX SDHC X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 01 Aug 2018 23:59:25 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Leif, Thank you for the initial feedback. I will address the items on all the pa= tches and resubmit as one set. Chris > -----Original Message----- > From: Leif Lindholm > Sent: Wednesday, August 1, 2018 9:15 AM > To: Chris Co > Cc: edk2-devel@lists.01.org; Ard Biesheuvel ; > Michael D Kinney > Subject: Re: [PATCH edk2-platforms 1/7] Silicon/NXP: Add support for iMX > SDHC >=20 > On Thu, Jul 19, 2018 at 04:11:18AM +0000, Chris Co wrote: > > This adds support for using the SD host controller on > > NXP i.MX platforms. > > > > Contributed-under: TianoCore Contribution Agreement 1.1 > > Signed-off-by: Christopher Co > > Cc: Ard Biesheuvel > > Cc: Leif Lindholm > > Cc: Michael D Kinney >=20 > Trying to build the code[1] in this patch throws up issues due to > (initially) a missing dependency on a iMXIoMuxLib mapping. Which is > not introduced in this set at all. >=20 > Could you bring these sets together into a single (huge) one, > ensuring that code is introduced in dependency order? >=20 > It will be no more unwieldy (I can push patches from the front as they > merit it), and will make my life a _lot_ easier. >=20 > If you can also address the items I point out as "address throughout" > below, for all the patches, that will reduce churn. >=20 > [1] By hacking the .inf into EmbeddedPkg/EmbeddedPkg.dsc, since the > i.MX one is also not included in this set. >=20 > > --- > > Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c | 1356 > ++++++++++++++++++++ > > Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf | 67 + > > Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h | 101 ++ > > Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h | 277 ++++ > > 4 files changed, 1801 insertions(+) > > > > diff --git a/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c > b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c > > new file mode 100644 > > index 000000000000..5f087f8a28b9 > > --- /dev/null > > +++ b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.c > > @@ -0,0 +1,1356 @@ > > +/** @file > > +* > > +* Copyright (c) Microsoft Corporation. All rights reserved. >=20 > Please add copyright year throughout all patches. >=20 > > +* > > +* This program and the accompanying materials > > +* are licensed and made available under the terms and conditions of t= he > BSD License > > +* which accompanies this distribution. The full text of the license = may be > found at > > +* > https://na01.safelinks.protection.outlook.com/?url=3Dhttp%3A%2F%2Fopenso > urce.org%2Flicenses%2Fbsd- > license.php&data=3D02%7C01%7CChristopher.Co%40microsoft.com%7Cc0 > f078beab2c4534017c08d5f7c9f5f5%7C72f988bf86f141af91ab2d7cd011db47%7 > C1%7C0%7C636687369157661520&sdata=3DnoPZDlLAGlOgwhpiKbfxZk%2B > OPT6KNdeBtEi8VELsugQ%3D&reserved=3D0 > > +* > > +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > > +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > > +* > > +**/ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > +#include >=20 > Please sort includes alphabetically. >=20 > > + > > +#include > > +#include > > + > > +typedef struct { > > + UINT32 IoNumber; > > + IMX_GPIO_BANK Bank; > > +} IMX_GPIO_PIN; > > + > > +#define PCD_GPIO_PIN_IO_NUMBER(X) ((X) & 0xFF) > > +#define PCD_GPIO_PIN_BANK(X) (((X) >> 8) & 0xFF) > > + > > +// > > +// A special value to indicate that GPIO is not the signal source for = either > > +// CardDetect or WriteProtect > > +// > > +typedef enum { > > + USDHC_SIGNAL_GPIO_START =3D 0x000, > > + USDHC_SIGNAL_GPIO_END =3D 0xFF00, > > + USDHC_SIGNAL_OVERRIDE_PIN_LOW =3D 0xFF00, >=20 > Are the above two lines intentionally assigning the same value? >=20 > > + USDHC_SIGNAL_OVERRIDE_PIN_HIGH =3D 0xFF01, > > + USDHC_SIGNAL_INTERNAL_PIN =3D 0xFFFF > > +} USDHC_SIGNAL_SOURCE; > > + > > +#define USDHC_IS_GPIO_SIGNAL_SOURCE(X) \ > > + (((X) >=3D USDHC_SIGNAL_GPIO_START) && ((X) < > USDHC_SIGNAL_GPIO_END)) > > + > > +typedef struct { > > + UINT32 SdhcId; > > + EFI_HANDLE SdhcProtocolHandle; > > + USDHC_REGISTERS *RegistersBase; > > + USDHC_SIGNAL_SOURCE CardDetectSignal; > > + USDHC_SIGNAL_SOURCE WriteProtectSignal; > > + IMX_GPIO_PIN CardDetectGpioPin; > > + IMX_GPIO_PIN WriteProtectGpioPin; > > +} USDHC_PRIVATE_CONTEXT; > > + > > +#define LOG_FMT_HELPER(FMT, ...) \ > > + "SDHC%d:" FMT "%a\n", ((SdhcCtx !=3D NULL) ? SdhcCtx->SdhcId : -1)= , > __VA_ARGS__ > > + > > +#define LOG_INFO(...) \ > > + DEBUG((DEBUG_INFO | DEBUG_BLKIO, > LOG_FMT_HELPER(__VA_ARGS__, ""))) > > + > > +#define LOG_TRACE(...) \ > > + DEBUG((DEBUG_VERBOSE | DEBUG_BLKIO, > LOG_FMT_HELPER(__VA_ARGS__, ""))) > > + > > +#define LOG_ERROR(...) \ > > + DEBUG((DEBUG_ERROR | DEBUG_BLKIO, > LOG_FMT_HELPER(__VA_ARGS__, ""))) > > + > > +#define LOG_ASSERT(TXT) \ > > + ASSERT(!"Sdhc: " TXT "\n") > > + > > +#ifdef MIN > > +#undef MIN > > +#define MIN(x,y) ((x) > (y) ? (y) : (x)) > > +#endif // MIN >=20 > Please remove - the MIN macro has existed in Base.h since at least > 2007. It does not need local redefinition. >=20 > > + > > +// > > +// uSDHC read/write FIFO is 128x32-bit > > +// > > +#define USDHC_FIFO_MAX_WORD_COUNT 128 > > + > > +// > > +// Max block count allowed in a single transfer > > +// > > +#define USDHC_MAX_BLOCK_COUNT 0xFFFF > > + > > +// > > +// Number of register maximum polls > > +// > > +#define USDHC_POLL_RETRY_COUNT 100000 > > + > > +// > > +// Waits between each registry poll > > +// > > +#define USDHC_POLL_WAIT_US 20 > > + > > +// > > +// uSDHC input clock. Ideally, should query it from clock manager > > +// > > +#define USDHC_BASE_CLOCK_FREQ_HZ 198000000 > > + > > +#define USDHC_BLOCK_LENGTH_BYTES 512 > > + >=20 > Can all of the above #defines, enums and structs be moved to a local > "SdhcDxe.h"? >=20 > > +VOID > > +DumpState( > > + IN USDHC_PRIVATE_CONTEXT *SdhcCtx > > + ) >=20 > Base indentation is always 2 spaces. (applies throughout) >=20 > > +{ > > +DEBUG_CODE_BEGIN (); > > + > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + > > + USDHC_BLK_ATT_REG BlkAtt; BlkAtt.AsUint32 =3D > MmioRead32((UINTN)&Reg->BLK_ATT); >=20 > Please never put multiple statements on same line. (applies throughout) >=20 > Space between function name and opening parentheses (applies > throughout). >=20 > > + UINT32 CmdArg; CmdArg =3D MmioRead32((UINTN)&Reg->CMD_ARG); > > + USDHC_CMD_XFR_TYP_REG CmdXfrTyp; CmdXfrTyp.AsUint32 =3D > MmioRead32((UINTN)&Reg->CMD_XFR_TYP); > > + USDHC_PROT_CTRL_REG ProtCtrl; ProtCtrl.AsUint32 =3D > MmioRead32((UINTN)&Reg->PROT_CTRL); > > + USDHC_WTMK_LVL_REG WtmkLvl; WtmkLvl.AsUint32 =3D > MmioRead32((UINTN)&Reg->WTMK_LVL); > > + USDHC_MIX_CTRL_REG MixCtrl; MixCtrl.AsUint32 =3D > MmioRead32((UINTN)&Reg->MIX_CTRL); > > + UINT32 IntStatusEn =3D MmioRead32((UINTN)&Reg->INT_STATUS_EN); > > + UINT32 IntSignalEn =3D MmioRead32((UINTN)&Reg->INT_SIGNAL_EN); > > + UINT32 VendSpec =3D MmioRead32((UINTN)&Reg->VEND_SPEC); > > + UINT32 MmcBoot =3D MmioRead32((UINTN)&Reg->MMC_BOOT); > > + UINT32 VendSpec2 =3D MmioRead32((UINTN)&Reg->VEND_SPEC2); > > + USDHC_INT_STATUS_REG IntStatus; IntStatus.AsUint32 =3D > MmioRead32((UINTN)&Reg->INT_STATUS); > > + USDHC_PRES_STATE_REG PresState; PresState.AsUint32 =3D > MmioRead32((UINTN)&Reg->PRES_STATE); > > + > > + LOG_INFO( > > + " - BLK_ATT\t:0x%08x BLKSIZE:0x%x BLKCNT:0x%08x", > > + BlkAtt.AsUint32, > > + BlkAtt.Fields.BLKSIZE, > > + BlkAtt.Fields.BLKCNT); > > + > > + LOG_INFO(" - CMD_ARG\t:0x%08x", CmdArg); > > + > > + LOG_INFO( > > + " - CMD_XFR_TYP\t:0x%08x RSPTYP:%d CCCEN:%d CICEN:%d > DPSEL:%d CMDTYP:%d CMDINX:%d", > > + CmdXfrTyp.AsUint32, > > + CmdXfrTyp.Fields.RSPTYP, > > + CmdXfrTyp.Fields.CCCEN, > > + CmdXfrTyp.Fields.CICEN, > > + CmdXfrTyp.Fields.DPSEL, > > + CmdXfrTyp.Fields.CMDTYP, > > + CmdXfrTyp.Fields.CMDINX); > > + > > + LOG_INFO( > > + " - PROT_CTRL\t:0x%08x DTW:%d D3CD:%d CDSS:%d EMODE:%d > DMASEL:%d SABGREQ:%d BURST_LEN_EN:%d", > > + ProtCtrl.AsUint32, > > + ProtCtrl.Fields.DTW, > > + ProtCtrl.Fields.D3CD, > > + ProtCtrl.Fields.CDSS, > > + ProtCtrl.Fields.EMODE, > > + ProtCtrl.Fields.DMASEL, > > + ProtCtrl.Fields.SABGREQ, > > + ProtCtrl.Fields.BURST_LEN_EN); > > + > > + LOG_INFO( > > + " - WTMK_LVL\t:0x%08x RD_WML:%d RD_BRST_LEN:%d > WR_WML:%d WR_BRST_LEN:%d", > > + WtmkLvl.AsUint32, > > + WtmkLvl.Fields.RD_WML, > > + WtmkLvl.Fields.RD_BRST_LEN, > > + WtmkLvl.Fields.WR_WML, > > + WtmkLvl.Fields.WR_BRST_LEN); > > + > > + LOG_INFO( > > + " - MIX_CTRL\t:0x%08x DMAEN:%d BCEN:%d AC12EN:%d DTDSEL:%d > MSBSEL:%d AC23EN:%d FBCLK_SEL:%d", > > + MixCtrl.AsUint32, > > + MixCtrl.Fields.DMAEN, > > + MixCtrl.Fields.BCEN, > > + MixCtrl.Fields.AC12EN, > > + MixCtrl.Fields.DTDSEL, > > + MixCtrl.Fields.MSBSEL, > > + MixCtrl.Fields.AC23EN, > > + MixCtrl.Fields.FBCLK_SEL); > > + > > + LOG_INFO(" - INT_STATUS_EN\t:0x%08x", IntStatusEn); > > + LOG_INFO(" - INT_SIGNAL_EN\t:0x%08x", IntSignalEn); > > + LOG_INFO(" - VEND_SPEC\t:0x%08x", VendSpec); > > + LOG_INFO(" - MMC_BOOT\t:0x%08x", MmcBoot); > > + LOG_INFO(" - VEND_SPEC2\t:0x%08x", VendSpec2); > > + > > + LOG_INFO( > > + " - INT_STATUS\t:0x%08x CC:%d TC:%d BWR:%d BRR:%d CTOE:%d > CCE:%d CEBE:%d CIE:%d DTOE:%d DCE:%d DEBE:%d", > > + IntStatus.AsUint32, > > + IntStatus.Fields.CC, > > + IntStatus.Fields.TC, > > + IntStatus.Fields.BWR, > > + IntStatus.Fields.BRR, > > + IntStatus.Fields.CTOE, > > + IntStatus.Fields.CCE, > > + IntStatus.Fields.CEBE, > > + IntStatus.Fields.CIE, > > + IntStatus.Fields.DTOE, > > + IntStatus.Fields.DCE, > > + IntStatus.Fields.DEBE); > > + > > + LOG_INFO( > > + " - PRES_STATE\t:0x%08x CIHB:%d CDIHB:%d DLA:%d WTA:%d RTA:%d > BWEN:%d BREN:%d CINST:%d DLSL:0x%x", > > + PresState.AsUint32, > > + PresState.Fields.CIHB, > > + PresState.Fields.CDIHB, > > + PresState.Fields.DLA, > > + PresState.Fields.WTA, > > + PresState.Fields.RTA, > > + PresState.Fields.BWEN, > > + PresState.Fields.BREN, > > + PresState.Fields.CINST, > > + PresState.Fields.DLSL); > > + > > +DEBUG_CODE_END (); > > +} > > + > > +EFI_STATUS > > +WaitForReadFifo( > > + IN USDHC_PRIVATE_CONTEXT *SdhcCtx > > + ) > > +{ > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + USDHC_INT_STATUS_REG IntStatus; IntStatus.AsUint32 =3D > MmioRead32((UINTN)&Reg->INT_STATUS); > > + UINT32 Retry =3D USDHC_POLL_RETRY_COUNT; > > + > > + while (!IntStatus.Fields.BRR && > > + !(IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) && > > + Retry) { >=20 > Would looke better with all tests horizontally aligned. >=20 > > + --Retry; > > + gBS->Stall(USDHC_POLL_WAIT_US); > > + IntStatus.AsUint32 =3D MmioRead32((UINTN)&Reg->INT_STATUS); > > + } > > + > > + if (IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) { > > + LOG_ERROR("Error detected"); > > + DumpState(SdhcCtx); > > + return EFI_DEVICE_ERROR; > > + } else if (IntStatus.Fields.BRR) { > > + MmioWrite32((UINTN)&Reg->INT_STATUS, IntStatus.AsUint32); > > + return EFI_SUCCESS; > > + } else { > > + ASSERT(!Retry); > > + LOG_ERROR("Time-out waiting on read FIFO"); > > + DumpState(SdhcCtx); > > + return EFI_TIMEOUT; > > + } > > +} > > + > > +EFI_STATUS > > +WaitForWriteFifo( > > + IN USDHC_PRIVATE_CONTEXT *SdhcCtx > > + ) > > +{ > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + USDHC_INT_STATUS_REG IntStatus; IntStatus.AsUint32 =3D > MmioRead32((UINTN)&Reg->INT_STATUS) ; > > + UINT32 Retry =3D USDHC_POLL_RETRY_COUNT; > > + > > + while (!IntStatus.Fields.BWR && > > + !(IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) && > > + Retry) { > > + --Retry; > > + gBS->Stall(USDHC_POLL_WAIT_US); > > + IntStatus.AsUint32 =3D MmioRead32((UINTN)&Reg->INT_STATUS); > > + } > > + > > + if (IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) { > > + LOG_ERROR("Error detected"); > > + DumpState(SdhcCtx); > > + return EFI_DEVICE_ERROR; > > + } else if (IntStatus.Fields.BWR) { > > + MmioWrite32((UINTN)&Reg->INT_STATUS, IntStatus.AsUint32); > > + return EFI_SUCCESS; > > + } else { > > + ASSERT(!Retry); > > + LOG_ERROR("Time-out waiting on write FIFO"); > > + DumpState(SdhcCtx); > > + return EFI_TIMEOUT; > > + } > > +} > > + > > +EFI_STATUS > > +WaitForCmdAndOrDataLine( > > + IN USDHC_PRIVATE_CONTEXT *SdhcCtx, > > + IN const SD_COMMAND *Cmd > > + ) > > +{ > > + BOOLEAN WaitForDataLine; > > + > > + // > > + // Waiting on the DATA lines is the default behavior if no CMD is > specified > > + // > > + if (Cmd =3D=3D NULL) { > > + WaitForDataLine =3D TRUE; > > + } else { > > + // > > + // Per datasheet, the SDHC can isssue CMD0, CMD12, CMD13 and > CMD52 > > + // when the DATA lines are busy during a data transfer. Other > commands > > + // should wait on the DATA lines before issuing > > + // > > + switch (Cmd->Index) { > > + case 0: > > + case 12: > > + case 13: > > + case 52: > > + WaitForDataLine =3D FALSE; > > + break; > > + default: > > + WaitForDataLine =3D TRUE; > > + } > > + } > > + > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + USDHC_PRES_STATE_REG PresState; PresState.AsUint32 =3D > MmioRead32((UINTN)&Reg->PRES_STATE); > > + USDHC_INT_STATUS_REG IntStatus; IntStatus.AsUint32 =3D > MmioRead32((UINTN)&Reg->INT_STATUS) ; > > + UINT32 Retry =3D USDHC_POLL_RETRY_COUNT; > > + > > + while (PresState.Fields.CIHB && > > + (!WaitForDataLine || PresState.Fields.CDIHB) && > > + !(IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) && > > + Retry) { > > + gBS->Stall(USDHC_POLL_WAIT_US); > > + --Retry; > > + PresState.AsUint32 =3D MmioRead32((UINTN)&Reg->PRES_STATE); > > + IntStatus.AsUint32 =3D MmioRead32((UINTN)&Reg->INT_STATUS); > > + } > > + > > + if (IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) { > > + LOG_ERROR("Error detected"); > > + DumpState(SdhcCtx); > > + return EFI_DEVICE_ERROR; > > + } else if (!(PresState.Fields.CIHB && > > + (!WaitForDataLine || PresState.Fields.CDIHB))) { > > + return EFI_SUCCESS; > > + } else { > > + ASSERT(!Retry); > > + LOG_ERROR("Time-out waiting on CMD and/or DATA lines"); > > + DumpState(SdhcCtx); > > + return EFI_TIMEOUT; > > + } > > +} > > + > > +EFI_STATUS > > +WaitForCmdResponse( > > + IN USDHC_PRIVATE_CONTEXT *SdhcCtx > > + ) > > +{ > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + USDHC_INT_STATUS_REG IntStatus; IntStatus.AsUint32 =3D > MmioRead32((UINTN)&Reg->INT_STATUS) ; > > + UINT32 Retry =3D USDHC_POLL_RETRY_COUNT; > > + > > + // > > + // Wait for command to finish execution either with success or fai= lure > > + // > > + while (!IntStatus.Fields.CC && > > + !(IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) && > > + Retry) { > > + gBS->Stall(USDHC_POLL_WAIT_US); > > + --Retry; > > + IntStatus.AsUint32 =3D MmioRead32((UINTN)&Reg->INT_STATUS); > > + } > > + > > + if (IntStatus.AsUint32 & USDHC_INT_STATUS_ERROR) { > > + LOG_ERROR("Error detected"); > > + DumpState(SdhcCtx); > > + return EFI_DEVICE_ERROR; > > + } else if (IntStatus.Fields.CC) { > > + MmioWrite32((UINTN)&Reg->INT_STATUS, IntStatus.AsUint32); > > + return EFI_SUCCESS; > > + } else { > > + ASSERT(!Retry); > > + LOG_ERROR("Time-out waiting on command completion"); > > + DumpState(SdhcCtx); > > + return EFI_TIMEOUT; > > + } > > +} > > + > > +EFI_STATUS > > +SdhcSetBusWidth( > > + IN EFI_SDHC_PROTOCOL *This, > > + IN SD_BUS_WIDTH BusWidth > > + ) > > +{ > > + USDHC_PRIVATE_CONTEXT *SdhcCtx =3D > (USDHC_PRIVATE_CONTEXT*)This->PrivateContext; > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + USDHC_PROT_CTRL_REG ProtCtrl; ProtCtrl.AsUint32 =3D > MmioRead32((UINTN)&Reg->PROT_CTRL); > > + > > + LOG_TRACE("SdhcSetBusWidth(%d)", BusWidth); > > + > > + switch (BusWidth) { > > + case SdBusWidth1Bit: > > + ProtCtrl.Fields.DTW =3D USDHC_PROT_CTRL_DTW_1BIT; > > + break; > > + case SdBusWidth4Bit: > > + ProtCtrl.Fields.DTW =3D USDHC_PROT_CTRL_DTW_4BIT; > > + break; > > + case SdBusWidth8Bit: > > + ProtCtrl.Fields.DTW =3D USDHC_PROT_CTRL_DTW_8BIT; > > + break; > > + default: > > + LOG_ASSERT("Invalid bus width"); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + MmioWrite32((UINTN)&Reg->PROT_CTRL, ProtCtrl.AsUint32); > > + > > + return EFI_SUCCESS; > > +} > > + > > +EFI_STATUS > > +SdhcSetClock( > > + IN EFI_SDHC_PROTOCOL *This, > > + IN UINT32 TargetFreqHz > > + ) > > +{ > > + USDHC_PRIVATE_CONTEXT *SdhcCtx =3D > (USDHC_PRIVATE_CONTEXT*)This->PrivateContext; > > + > > + LOG_TRACE("SdhcSetClock(%dHz)", TargetFreqHz); > > + > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + USDHC_SYS_CTRL_REG SysCtrl; SysCtrl.AsUint32 =3D > MmioRead32((UINTN)&Reg->SYS_CTRL); > > + > > + // > > + // SDCLK =3D (Base Clock) / (prescaler x divisor) > > + // > > + UINT32 Prescaler; > > + UINT32 Divisor; > > + UINT32 SDCLK; > > + > > + USDHC_MIX_CTRL_REG MixCtrl; MixCtrl.AsUint32 =3D > MmioRead32((UINTN)&Reg->MIX_CTRL); > > + > > + // > > + // Bruteforce to find the best prescaler and divisor that result > > + // in SDCLK less than or equal to the requested frequency > > + // > > + // Allowed |Base clock divided By > > + // SDCLKFS |DDR_EN=3D0 |DDR_EN=3D1 > > + // 80h 256 512 > > + // 40h 128 256 > > + // 20h 64 128 > > + // 10h 32 64 > > + // 08h 16 32 > > + // 04h 8 16 > > + // 02h 4 8 > > + // 01h 2 4 > > + // 00h 1 2 > > + // > > + const UINT32 PRESCALER_MIN =3D (MixCtrl.Fields.DDR_EN ? 2 : 1); > > + const UINT32 PRESCALER_MAX =3D (MixCtrl.Fields.DDR_EN ? 512 : 256)= ;; > > + const UINT32 DIVISOR_MIN =3D 1; > > + const UINT32 DIVISOR_MAX =3D 16; >=20 > CONST >=20 > > + UINT32 MinFreqDistance =3D 0xFFFFFFFF; >=20 > MAX_UINT32? >=20 > > + UINT32 FreqDistance; > > + UINT32 BestPrescaler =3D 0; > > + UINT32 BestDivisor =3D 0; > > + > > + // > > + // Bruteforce to find the best prescaler and divisor that result > > + // in SDCLK less than or equal to the requested frequency > > + // > > + for (Prescaler =3D PRESCALER_MAX; Prescaler >=3D PRESCALER_MIN; > Prescaler /=3D 2) { > > + for (Divisor =3D DIVISOR_MIN; Divisor <=3D DIVISOR_MAX; ++Divi= sor) { > > + SDCLK =3D USDHC_BASE_CLOCK_FREQ_HZ / (Prescaler * Divisor)= ; > > + > > + // > > + // We are not willing to choose clocks higher than the tar= get one > > + // to avoid exceeding device limits > > + // > > + if (SDCLK > TargetFreqHz) { > > + continue; > > + } else if (SDCLK =3D=3D TargetFreqHz) { > > + BestPrescaler =3D Prescaler; > > + BestDivisor =3D Divisor; > > + break; > > + } else { > > + FreqDistance =3D TargetFreqHz - SDCLK; > > + if (FreqDistance < MinFreqDistance) { > > + MinFreqDistance =3D FreqDistance; > > + BestPrescaler =3D Prescaler; > > + BestDivisor =3D Divisor; > > + } > > + } > > + } > > + } > > + > > + // > > + // Wait for clock to become stable before any modifications > > + // > > + USDHC_PRES_STATE_REG PresState; PresState.AsUint32 =3D > MmioRead32((UINTN)&Reg->PRES_STATE); > > + UINT32 Retry =3D USDHC_POLL_RETRY_COUNT; > > + > > + while (!PresState.Fields.SDSTB && > > + Retry) { > > + gBS->Stall(USDHC_POLL_WAIT_US); > > + --Retry; > > + PresState.AsUint32 =3D MmioRead32((UINTN)&Reg->PRES_STATE); > > + } > > + > > + if (!PresState.Fields.SDSTB) { > > + ASSERT(!Retry); > > + LOG_ERROR("Time-out waiting on SD clock to stabilize"); > > + DumpState(SdhcCtx); > > + return EFI_TIMEOUT; > > + } > > + > > + SysCtrl.AsUint32 =3D MmioRead32((UINTN)&Reg->SYS_CTRL); > > + SysCtrl.Fields.SDCLKFS =3D BestPrescaler / (MixCtrl.Fields.DDR_EN = ? 4 : 2); > > + SysCtrl.Fields.DVS =3D BestDivisor - 1; > > + > > + MmioWrite32((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32); > > + > > + SDCLK =3D USDHC_BASE_CLOCK_FREQ_HZ / (BestPrescaler * BestDivisor)= ; > > + > > + LOG_TRACE( > > + "Current SDCLK:%dHz SDCLKFS:0x%x DVS:0x%x", > > + SDCLK, > > + (UINT32)SysCtrl.Fields.SDCLKFS, > > + (UINT32)SysCtrl.Fields.DVS); > > + > > + return EFI_SUCCESS; > > +} > > + > > +BOOLEAN > > +SdhcIsCardPresent( > > + IN EFI_SDHC_PROTOCOL *This > > + ) > > +{ > > + USDHC_PRIVATE_CONTEXT *SdhcCtx =3D > (USDHC_PRIVATE_CONTEXT*)This->PrivateContext; > > + BOOLEAN IsCardPresent; > > + > > + if (SdhcCtx->CardDetectSignal =3D=3D USDHC_SIGNAL_INTERNAL_PIN) { > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + USDHC_PRES_STATE_REG PresState; PresState.AsUint32 =3D > MmioRead32((UINTN)&Reg->PRES_STATE); > > + IsCardPresent =3D (PresState.Fields.CINST =3D=3D 1); > > + } else { > > + IMX_GPIO_VALUE CardDetectLevel; > > + if (USDHC_IS_GPIO_SIGNAL_SOURCE(SdhcCtx->CardDetectSignal)) { > > + // > > + //Read the state of CD_B pin for the card socket > > + // > > + CardDetectLevel =3D > > + ImxGpioRead( > > + SdhcCtx->CardDetectGpioPin.Bank, > > + SdhcCtx->CardDetectGpioPin.IoNumber); > > + } else if (SdhcCtx->CardDetectSignal =3D=3D > USDHC_SIGNAL_OVERRIDE_PIN_LOW) { > > + CardDetectLevel =3D IMX_GPIO_LOW; > > + } else if (SdhcCtx->CardDetectSignal =3D=3D > USDHC_SIGNAL_OVERRIDE_PIN_HIGH) { > > + CardDetectLevel =3D IMX_GPIO_HIGH; > > + } else { > > + ASSERT(!"Invalid CardDetect signal source"); > > + CardDetectLevel =3D IMX_GPIO_LOW; > > + } > > + > > + // > > + // When no card is present, CD_B is pulled-high, and the SDCa= rd > when > > + // inserted will pull CD_B low > > + // CD_B=3D0 means card present, while CD_B=3D1 means card not = present > > + // > > + IsCardPresent =3D (CardDetectLevel =3D=3D IMX_GPIO_LOW); > > + } > > + > > + // Enable if needed while trace debugging, otherwise this will flood= the > debug > > + // console due to being called periodically every second for each SD= HC > > +#if 0 > > + LOG_TRACE("SdhcIsCardPresent(): %d", IsCardPresent); > > +#endif >=20 > That sounds like something to be filtered by setting it to > DEBUG_VERBOSE, which LOG_TRACE already does. >=20 > > + > > + return IsCardPresent; > > +} > > + > > +BOOLEAN > > +SdhcIsReadOnly( > > + IN EFI_SDHC_PROTOCOL *This > > + ) > > +{ > > + USDHC_PRIVATE_CONTEXT *SdhcCtx =3D > (USDHC_PRIVATE_CONTEXT*)This->PrivateContext; > > + BOOLEAN IsReadOnly; > > + > > + if (SdhcCtx->WriteProtectSignal =3D=3D USDHC_SIGNAL_INTERNAL_PIN) = { > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + USDHC_PRES_STATE_REG PresState; PresState.AsUint32 =3D > MmioRead32((UINTN)&Reg->PRES_STATE); > > + IsReadOnly =3D (PresState.Fields.WPSPL =3D=3D 0); > > + } else { > > + IMX_GPIO_VALUE WriteProtectLevel; > > + if (USDHC_IS_GPIO_SIGNAL_SOURCE(SdhcCtx->WriteProtectSignal)) > { > > + // > > + //Read the state of WP pin for the card socket > > + // > > + WriteProtectLevel =3D > > + ImxGpioRead( > > + SdhcCtx->WriteProtectGpioPin.Bank, > > + SdhcCtx->WriteProtectGpioPin.IoNumber); > > + } else if (SdhcCtx->WriteProtectSignal =3D=3D > USDHC_SIGNAL_OVERRIDE_PIN_LOW) { > > + WriteProtectLevel =3D IMX_GPIO_LOW; > > + } else if (SdhcCtx->WriteProtectSignal =3D=3D > USDHC_SIGNAL_OVERRIDE_PIN_HIGH) { > > + WriteProtectLevel =3D IMX_GPIO_HIGH; > > + } else { > > + ASSERT(!"Invalid WriteProtect signal source"); > > + WriteProtectLevel =3D IMX_GPIO_LOW; > > + } > > + > > + // > > + // When no card is present, WP is pulled-high, and the SDCard= when > > + // inserted will pull WP low if WP switch is configured to wri= te enable > > + // the SDCard, otherwise it WP will stay pulled-high > > + // WP=3D0 means write enabled, while WP=3D1 means write protec= ted > > + // > > + IsReadOnly =3D (WriteProtectLevel !=3D IMX_GPIO_LOW); >=20 > Indentation (relative to comment). >=20 > > + } > > + > > + LOG_TRACE("SdhcIsReadOnly(): %d", IsReadOnly); > > + return IsReadOnly; > > +} > > + > > +EFI_STATUS > > +SdhcSendCommand( > > + IN EFI_SDHC_PROTOCOL *This, > > + IN const SD_COMMAND *Cmd, > > + IN UINT32 Argument, > > + IN OPTIONAL const SD_COMMAND_XFR_INFO *XfrInfo > > + ) > > +{ > > + EFI_STATUS Status; > > + USDHC_PRIVATE_CONTEXT *SdhcCtx =3D > (USDHC_PRIVATE_CONTEXT*)This->PrivateContext; > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + > > + LOG_TRACE( > > + "SdhcSendCommand(%cCMD%d, %08x)", > > + ((Cmd->Class =3D=3D SdCommandClassApp) ? 'A' : ' '), > > + (UINT32)Cmd->Index, > > + Argument); > > + > > + Status =3D WaitForCmdAndOrDataLine(SdhcCtx, Cmd); > > + if (Status !=3D EFI_SUCCESS) { > > + LOG_ERROR("SdhcWaitForCmdAndDataLine failed"); > > + return Status; > > + } > > + > > + // > > + // Clear Interrupt status > > + // > > + MmioWrite32((UINTN)&Reg->INT_STATUS, (UINT32)~0); > > + > > + // > > + // Setup data transfer command > > + // > > + if (XfrInfo) { > > + if (XfrInfo->BlockCount > USDHC_MAX_BLOCK_COUNT) { > > + LOG_ERROR( > > + "Provided %d block count while SDHC max block count is= %d", > > + XfrInfo->BlockCount, > > + USDHC_MAX_BLOCK_COUNT); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // > > + // Set block size and count > > + // > > + USDHC_BLK_ATT_REG BlkAtt =3D { 0 }; > > + BlkAtt.Fields.BLKSIZE =3D XfrInfo->BlockSize; > > + ASSERT (XfrInfo->BlockCount > 0); > > + BlkAtt.Fields.BLKCNT =3D XfrInfo->BlockCount; > > + MmioWrite32((UINTN)&Reg->BLK_ATT, BlkAtt.AsUint32); > > + > > + // > > + // Set transfer parameters > > + // > > + USDHC_MIX_CTRL_REG MixCtrl =3D { 0 }; > > + if (Cmd->TransferDirection =3D=3D SdTransferDirectionRead) { > > + MixCtrl.Fields.DTDSEL =3D 1; > > + } > > + > > + if (XfrInfo->BlockCount > 1) { > > + ASSERT((Cmd->TransferType =3D=3D SdTransferTypeMultiBlock)= || > > + (Cmd->TransferType =3D=3D SdTransferTypeMultiBlockNoSt= op)); > > + MixCtrl.Fields.MSBSEL =3D 1; > > + MixCtrl.Fields.BCEN =3D 1; > > + } > > + > > + MmioWrite32((UINTN)&Reg->MIX_CTRL, MixCtrl.AsUint32); > > + > > + USDHC_WTMK_LVL_REG WtmkLvl =3D { 0 }; > > + > > +#if 0 >=20 > No #if 0 upstream. >=20 > > + // > > + // Set FIFO watermarks > > + // > > + // Configure FIFO watermark levels to 1/2 the FIFO capacity fo= r read, > > + // and 1/3 the FIFO capacity for write. > > + // In case the whole transfer can fit in the FIFO, then use > > + // the whole transfer length as the FIFO threshold, so we do > > + // the read/write in one-shot > > + // > > + > > + UINT32 FifoThresholdWordCount; > > + if (Cmd->TransferDirection =3D=3D SdTransferDirectionRead) { > > + FifoThresholdWordCount =3D USDHC_FIFO_MAX_WORD_COUNT / 2; > > + } else { > > + FifoThresholdWordCount =3D USDHC_FIFO_MAX_WORD_COUNT / 3; > > + } > > + > > + ASSERT(XfrInfo->BlockSize % sizeof(UINT32) =3D=3D 0); > > + UINT32 TransferByteLength =3D XfrInfo->BlockSize * XfrInfo- > >BlockCount; > > + const UINT32 TransferWordCount =3D TransferByteLength / > sizeof(UINT32); > > + FifoThresholdWordCount =3D MIN(TransferWordCount, > FifoThresholdWordCount); > > + > > + ASSERT(FifoThresholdWordCount <=3D 0xFFFF); > > + const UINT16 Wml =3D (UINT16)FifoThresholdWordCount; > > + ASSERT(Wml <=3D USDHC_FIFO_MAX_WORD_COUNT); > > + > > + if (Cmd->TransferDirection =3D=3D SdTransferDirectionRead) { > > + WtmkLvl.Fields.RD_WML =3D (UINT8)Wml; > > + WtmkLvl.Fields.RD_BRST_LEN =3D MIN(Wml, 8); > > + } else { > > + WtmkLvl.Fields.WR_WML =3D (UINT8)Wml; > > + WtmkLvl.Fields.WR_BRST_LEN =3D MIN(Wml, 8);; > > + } > > +#endif > > + > > +#if 0 > > + WtmkLvl.Fields.RD_WML =3D 64; > > + WtmkLvl.Fields.RD_BRST_LEN =3D 16; > > + WtmkLvl.Fields.WR_WML =3D 64; > > + WtmkLvl.Fields.WR_BRST_LEN =3D 16; > > +#endif > > + > > + UINT32 WtmkThreshold =3D USDHC_BLOCK_LENGTH_BYTES / 4; > > + if (Cmd->TransferDirection =3D=3D SdTransferDirectionRead) { > > + if (WtmkThreshold > USDHC_WTMK_RD_WML_MAX_VAL) { > > + WtmkThreshold =3D USDHC_WTMK_RD_WML_MAX_VAL; > > + } > > + WtmkLvl.Fields.RD_WML =3D WtmkThreshold; > > + } else { > > + if (WtmkThreshold > USDHC_WTMK_WR_WML_MAX_VAL) { > > + WtmkThreshold =3D USDHC_WTMK_WR_WML_MAX_VAL; > > + } > > + WtmkLvl.Fields.WR_WML =3D WtmkThreshold; > > + } > > + > > + MmioWrite32((UINTN)&Reg->WTMK_LVL, WtmkLvl.AsUint32); > > + } > > + > > + // > > + // Set CMD parameters > > + // > > + USDHC_CMD_XFR_TYP_REG CmdXfrTyp =3D { 0 }; > > + CmdXfrTyp.Fields.CMDINX =3D Cmd->Index; > > + > > + switch (Cmd->ResponseType) { > > + case SdResponseTypeNone: > > + break; > > + > > + case SdResponseTypeR1: > > + case SdResponseTypeR5: > > + case SdResponseTypeR6: > > + CmdXfrTyp.Fields.RSPTYP =3D USDHC_CMD_XFR_TYP_RSPTYP_RSP_48; > > + CmdXfrTyp.Fields.CICEN =3D 1; > > + CmdXfrTyp.Fields.CCCEN =3D 1; > > + break; > > + > > + case SdResponseTypeR1B: > > + case SdResponseTypeR5B: > > + CmdXfrTyp.Fields.RSPTYP =3D > USDHC_CMD_XFR_TYP_RSPTYP_RSP_48_CHK_BSY; > > + CmdXfrTyp.Fields.CICEN =3D 1; > > + CmdXfrTyp.Fields.CCCEN =3D 1; > > + break; > > + > > + case SdResponseTypeR2: > > + CmdXfrTyp.Fields.RSPTYP =3D > USDHC_CMD_XFR_TYP_RSPTYP_RSP_136; > > + CmdXfrTyp.Fields.CCCEN =3D 1; > > + break; > > + > > + case SdResponseTypeR3: > > + case SdResponseTypeR4: > > + CmdXfrTyp.Fields.RSPTYP =3D USDHC_CMD_XFR_TYP_RSPTYP_RSP_48; > > + break; > > + > > + default: > > + LOG_ASSERT("SdhcSendCommand(): Invalid response type"); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (Cmd->Type =3D=3D SdCommandTypeAbort) { > > + CmdXfrTyp.Fields.CMDTYP =3D > USDHC_CMD_XFR_TYP_CMDTYP_ABORT; > > + } > > + > > + if (XfrInfo) { > > + CmdXfrTyp.Fields.DPSEL =3D 1; > > + } > > + > > + // > > + // Send command and wait for response > > + // > > + MmioWrite32((UINTN)&Reg->CMD_ARG, Argument); > > + MmioWrite32((UINTN)&Reg->CMD_XFR_TYP, CmdXfrTyp.AsUint32); > > + > > + Status =3D WaitForCmdResponse(SdhcCtx); > > + if (EFI_ERROR(Status)) { > > + LOG_ERROR("WaitForCmdResponse() failed. %r", Status); > > + return Status; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +EFI_STATUS > > +SdhcReceiveResponse( > > + IN EFI_SDHC_PROTOCOL *This, > > + IN const SD_COMMAND *Cmd, > > + OUT UINT32 *Buffer > > + ) > > +{ > > + > > + USDHC_PRIVATE_CONTEXT *SdhcCtx =3D > (USDHC_PRIVATE_CONTEXT*)This->PrivateContext; > > + > > + if (Buffer =3D=3D NULL) { > > + LOG_ERROR("Input Buffer is NULL"); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + > > + switch (Cmd->ResponseType) { > > + case SdResponseTypeNone: > > + break; > > + case SdResponseTypeR1: > > + case SdResponseTypeR1B: > > + case SdResponseTypeR3: > > + case SdResponseTypeR4: > > + case SdResponseTypeR5: > > + case SdResponseTypeR5B: > > + case SdResponseTypeR6: > > + Buffer[0] =3D MmioRead32((UINTN)&Reg->CMD_RSP0); > > + LOG_TRACE( > > + "SdhcReceiveResponse(Type: %x), Buffer[0]: %08x", > > + Cmd->ResponseType, > > + Buffer[0]); > > + break; > > + case SdResponseTypeR2: > > + Buffer[0] =3D MmioRead32((UINTN)&Reg->CMD_RSP0); > > + Buffer[1] =3D MmioRead32((UINTN)&Reg->CMD_RSP1); > > + Buffer[2] =3D MmioRead32((UINTN)&Reg->CMD_RSP2); > > + Buffer[3] =3D MmioRead32((UINTN)&Reg->CMD_RSP3); > > + > > + LOG_TRACE( > > + "SdhcReceiveResponse(Type: %x), Buffer[0-3]: %08x, %08x, %= 08x, > %08x", > > + Cmd->ResponseType, > > + Buffer[0], > > + Buffer[1], > > + Buffer[2], > > + Buffer[3]); > > + break; > > + default: > > + LOG_ASSERT("SdhcReceiveResponse(): Invalid response type"); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +EFI_STATUS > > +SdhcReadBlockData( > > + IN EFI_SDHC_PROTOCOL *This, > > + IN UINTN LengthInBytes, > > + OUT UINT32* Buffer > > + ) > > +{ > > + USDHC_PRIVATE_CONTEXT *SdhcCtx =3D > (USDHC_PRIVATE_CONTEXT*)This->PrivateContext; > > + > > + LOG_TRACE( > > + "SdhcReadBlockData(LengthInBytes: 0x%x, Buffer: 0x%x)", > > + LengthInBytes, > > + Buffer); > > + > > + ASSERT(Buffer !=3D NULL); > > + ASSERT(LengthInBytes % sizeof(UINT32) =3D=3D 0); > > + > > + UINTN WordIdx =3D 0; > > + UINTN NumWords =3D LengthInBytes / sizeof(UINT32); > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + USDHC_WTMK_LVL_REG WtmkLvl; WtmkLvl.AsUint32 =3D > MmioRead32((UINTN)&Reg->WTMK_LVL); > > + UINT32 FifoWords; > > + EFI_STATUS Status; > > + > > + ASSERT(WtmkLvl.Fields.RD_WML > 0); > > + > > + while (WordIdx < NumWords) { > > + Status =3D WaitForReadFifo(SdhcCtx); > > + if (EFI_ERROR(Status)) { > > + LOG_ERROR( > > + "WaitForReadFifo() failed at Word%d. %r", > > + (UINT32)WordIdx, > > + Status); > > + return Status; > > + } > > + > > + FifoWords =3D WtmkLvl.Fields.RD_WML; > > + while (WordIdx < NumWords && FifoWords--) { > > + Buffer[WordIdx] =3D MmioRead32((UINTN)&Reg- > >DATA_BUFF_ACC_PORT); > > + ++WordIdx; > > + } > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +EFI_STATUS > > +SdhcWriteBlockData( > > + IN EFI_SDHC_PROTOCOL *This, > > + IN UINTN LengthInBytes, > > + IN const UINT32* Buffer > > + ) > > +{ > > + USDHC_PRIVATE_CONTEXT *SdhcCtx =3D > (USDHC_PRIVATE_CONTEXT*)This->PrivateContext; > > + > > + LOG_TRACE( > > + "SdhcWriteBlockData(LengthInBytes: 0x%x, Buffer: 0x%x)", > > + LengthInBytes, > > + Buffer); > > + > > + ASSERT(Buffer !=3D NULL); > > + ASSERT(LengthInBytes % USDHC_BLOCK_LENGTH_BYTES =3D=3D 0); > > + > > + const UINTN BlockWordCount =3D USDHC_BLOCK_LENGTH_BYTES / > sizeof(UINT32); > > + UINTN NumBlocks =3D LengthInBytes / USDHC_BLOCK_LENGTH_BYTES; > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + USDHC_INT_STATUS_REG IntStatus; > > + USDHC_PRES_STATE_REG PresState; > > + INT32 Timeout =3D 100000; // Nothing special about that constant >=20 > More of a retry than a timeout? >=20 > > + > > + while (NumBlocks > 0) { > > + UINTN RemainingWords =3D BlockWordCount; > > + IntStatus.AsUint32 =3D MmioRead32((UINTN)&Reg->INT_STATUS); > > + PresState.AsUint32 =3D MmioRead32((UINTN)&Reg->PRES_STATE); > > + while (!PresState.Fields.BWEN && --Timeout); >=20 > Does this need a MemoryFence()? >=20 > > + if (Timeout <=3D 0) { > > + LOG_ERROR ("Timeout waiting for FIFO PRES_STATE.BWEN flag"= ); > > + return EFI_TIMEOUT; > > + } > > + > > + while (RemainingWords > 0 && !IntStatus.Fields.TC) { > > + MicroSecondDelay (100); >=20 > Does this need a MemoryFence()? >=20 > > + IntStatus.AsUint32 =3D MmioRead32((UINTN)&Reg->INT_STATUS)= ; > > + MmioWrite32((UINTN)&Reg->DATA_BUFF_ACC_PORT, *Buffer); > > + Buffer++; > > + RemainingWords--; > > + } > > + NumBlocks--; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +EFI_STATUS > > +SdhcSoftwareReset( > > + IN EFI_SDHC_PROTOCOL *This, > > + IN SDHC_RESET_TYPE ResetType > > + ) > > +{ > > + USDHC_PRIVATE_CONTEXT *SdhcCtx =3D > (USDHC_PRIVATE_CONTEXT*)This->PrivateContext; > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + > > + UINT32 Retry; > > + > > + if (ResetType =3D=3D SdhcResetTypeAll) { > > + LOG_TRACE("SdhcSoftwareReset(ALL)"); > > + // > > + // Software reset for ALL > > + // > > + USDHC_SYS_CTRL_REG SysCtrl; SysCtrl.AsUint32 =3D > MmioRead32((UINTN)&Reg->SYS_CTRL); > > + SysCtrl.Fields.RSTA =3D 1; > > + MmioWrite32((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32); > > + Retry =3D USDHC_POLL_RETRY_COUNT; > > + // > > + // Wait for reset to complete > > + // > > + while (SysCtrl.Fields.RSTA && Retry) { > > + --Retry; > > + gBS->Stall(USDHC_POLL_WAIT_US); > > + SysCtrl.AsUint32 =3D MmioRead32((UINTN)&Reg->SYS_CTRL); > > + } > > + > > + if (SysCtrl.Fields.RSTA) { > > + ASSERT(!Retry); > > + LOG_ERROR("Time-out waiting on RSTA for self-clear"); > > + return EFI_TIMEOUT; > > + } > > + > > + // > > + // Disconnect interrupt signals between SDHC and GIC > > + // > > + MmioWrite32((UINTN)&Reg->INT_SIGNAL_EN, 0); > > + > > + // > > + // Clear and Enable all interrupts > > + // > > + MmioWrite32((UINTN)&Reg->INT_STATUS, (UINT32)~0); > > + MmioWrite32((UINTN)&Reg->INT_STATUS_EN, (UINT32)~0); > > + > > + LOG_TRACE("Waiting for CMD and DATA lines"); > > + > > + // > > + // Wait for CMD and DATA lines to become available > > + // > > + EFI_STATUS Status =3D WaitForCmdAndOrDataLine(SdhcCtx, NULL); > > + if (Status !=3D EFI_SUCCESS) { > > + LOG_ERROR("SdhcWaitForCmdAndDataLine() failed. %r", Status= ); > > + return Status; > > + } > > + > > + // > > + // Send 80 clock ticks to power-up the card > > + // > > + SysCtrl.AsUint32 =3D MmioRead32((UINTN)&Reg->SYS_CTRL); > > + SysCtrl.Fields.INITA =3D 1; > > + MmioWrite32((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32); > > + Retry =3D USDHC_POLL_RETRY_COUNT; > > + > > + // > > + // Wait for the 80 clock ticks to complete > > + // > > + while (SysCtrl.Fields.INITA && Retry) { > > + --Retry; > > + gBS->Stall(USDHC_POLL_WAIT_US); > > + SysCtrl.AsUint32 =3D MmioRead32((UINTN)&Reg->SYS_CTRL); > > + } > > + > > + if (SysCtrl.Fields.INITA) { > > + ASSERT(!Retry); > > + LOG_ERROR("Time-out waiting on INITA for self-clear"); > > + return EFI_TIMEOUT; > > + } > > + > > + LOG_TRACE("Card power-up complete"); > > + > > + // > > + // Set max data-timout counter value > > + // > > + SysCtrl.AsUint32 =3D MmioRead32((UINTN)&Reg->SYS_CTRL); > > + SysCtrl.Fields.DTOCV =3D 0xF; > > + MmioWrite32((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32); > > + > > + // > > + // Reset Mixer Control > > + // > > + MmioWrite32((UINTN)&Reg->MIX_CTRL, 0); > > + > > + USDHC_PROT_CTRL_REG ProtCtrl =3D { 0 }; > > + ProtCtrl.Fields.EMODE =3D > USDHC_PROT_CTRL_EMODE_LITTLE_ENDIAN; > > + ProtCtrl.Fields.LCTL =3D 1; > > + MmioWrite32((UINTN)&Reg->PROT_CTRL, ProtCtrl.AsUint32); > > + > > + LOG_TRACE("Reset ALL complete"); > > + > > + }else if (ResetType =3D=3D SdhcResetTypeCmd) { > > + LOG_TRACE("SdhcSoftwareReset(CMD)"); > > + // > > + // Software reset for CMD > > + // > > + USDHC_SYS_CTRL_REG SysCtrl; SysCtrl.AsUint32 =3D > MmioRead32((UINTN)&Reg->SYS_CTRL); > > + SysCtrl.Fields.RSTC =3D 1; > > + MmioWrite32((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32); > > + Retry =3D USDHC_POLL_RETRY_COUNT; > > + > > + // > > + // Wait for reset to complete > > + // > > + while (SysCtrl.Fields.RSTC && Retry) { > > + --Retry; > > + gBS->Stall(USDHC_POLL_WAIT_US); > > + SysCtrl.AsUint32 =3D MmioRead32((UINTN)&Reg->SYS_CTRL); > > + } > > + > > + if (SysCtrl.Fields.RSTC) { > > + ASSERT(!Retry); > > + LOG_ERROR("Time-out waiting on RSTC for self-clear"); > > + return EFI_TIMEOUT; > > + } > > + > > + MmioWrite32((UINTN)&Reg->INT_STATUS, (UINT32)~0); > > + > > + LOG_TRACE("Reset CMD complete"); > > + > > + } else if (ResetType =3D=3D SdhcResetTypeData) { > > + LOG_TRACE("SdhcSoftwareReset(DAT)"); > > + // > > + // Software reset for DAT > > + // > > + USDHC_SYS_CTRL_REG SysCtrl; SysCtrl.AsUint32 =3D > MmioRead32((UINTN)&Reg->SYS_CTRL); > > + SysCtrl.Fields.RSTD =3D 1; > > + MmioWrite32((UINTN)&Reg->SYS_CTRL, SysCtrl.AsUint32); > > + Retry =3D USDHC_POLL_RETRY_COUNT; > > + > > + // > > + // Wait for reset to complete > > + // > > + while (SysCtrl.Fields.RSTD && Retry) { > > + --Retry; > > + gBS->Stall(USDHC_POLL_WAIT_US); > > + SysCtrl.AsUint32 =3D MmioRead32((UINTN)&Reg->SYS_CTRL); > > + } > > + > > + if (SysCtrl.Fields.RSTD) { > > + ASSERT(!Retry); > > + LOG_ERROR("Time-out waiting on RSTD for self-clear"); > > + return EFI_TIMEOUT; > > + } > > + > > + MmioWrite32((UINTN)&Reg->INT_STATUS, (UINT32)~0); > > + > > + LOG_TRACE("Reset DAT complete"); > > + > > + } else { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +VOID > > +SdhcCleanup( > > + IN EFI_SDHC_PROTOCOL *This > > + ) > > +{ > > + if (This->PrivateContext !=3D NULL) { > > + FreePool(This->PrivateContext); > > + This->PrivateContext =3D NULL; > > + } > > + > > + FreePool(This); > > + > > + // > > + // Any SDHC protocol call to this instance is illegal beyond this = point > > + // > > +} > > + > > +VOID > > +SdhcGetCapabilities( > > + IN EFI_SDHC_PROTOCOL *This, > > + OUT SDHC_CAPABILITIES *Capabilities > > + ) > > +{ > > + USDHC_PRIVATE_CONTEXT *SdhcCtx =3D > (USDHC_PRIVATE_CONTEXT*)This->PrivateContext; > > + USDHC_REGISTERS *Reg =3D SdhcCtx->RegistersBase; > > + > > + USDHC_HOST_CTRL_CAP_REG Caps; Caps.AsUint32 =3D > MmioRead32((UINTN)&Reg->HOST_CTRL_CAP); > > + > > + Capabilities->MaximumBlockSize =3D (UINT32)(512 << Caps.Fields.MBL= ); > > + Capabilities->MaximumBlockCount =3D 0xFFFF; // UINT16_MAX > > +} > > + > > + > > +EFI_SDHC_PROTOCOL gSdhcProtocolTemplate =3D >=20 > g - is this really supposed to be globally visible to external > modules? Or could this be m for module-level visibility? >=20 > It looks like it is only used in this file in fact, so could it be STATIC= ? >=20 > > +{ >=20 > On previous line? >=20 > > + SDHC_PROTOCOL_INTERFACE_REVISION, // Revision > > + 0, // DeviceId > > + NULL, // PrivateContext > > + SdhcGetCapabilities, > > + SdhcSoftwareReset, > > + SdhcSetClock, > > + SdhcSetBusWidth, > > + SdhcIsCardPresent, > > + SdhcIsReadOnly, > > + SdhcSendCommand, > > + SdhcReceiveResponse, > > + SdhcReadBlockData, > > + SdhcWriteBlockData, > > + SdhcCleanup > > +}; > > + > > +EFI_STATUS > > +uSdhcDeviceRegister( > > + IN EFI_HANDLE ImageHandle, > > + IN UINT32 SdhcId, > > + IN VOID* RegistersBase, > > + IN USDHC_SIGNAL_SOURCE CardDetectSignal, > > + IN USDHC_SIGNAL_SOURCE WriteProtectSignal > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_SDHC_PROTOCOL *SdhcProtocol =3D NULL; > > + USDHC_PRIVATE_CONTEXT *SdhcCtx =3D NULL; > > + > > + if (ImageHandle =3D=3D NULL || > > + RegistersBase =3D=3D NULL) { > > + Status =3D EFI_INVALID_PARAMETER; > > + goto Exit; > > + } > > + > > + // > > + // Allocate per-device SDHC protocol and private context storage > > + // > > + > > + SdhcProtocol =3D AllocateCopyPool(sizeof(EFI_SDHC_PROTOCOL), > &gSdhcProtocolTemplate); >=20 > Some very long lines in this function. > Please break at 80 characters (where readability is not obviously > improved by keeping longer line - such as for keeping output strings > searchable). >=20 > > + if (SdhcProtocol =3D=3D NULL) { > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto Exit; > > + } > > + SdhcProtocol->SdhcId =3D SdhcId; > > + SdhcProtocol->PrivateContext =3D > AllocateZeroPool(sizeof(USDHC_PRIVATE_CONTEXT)); > > + if (SdhcProtocol->PrivateContext =3D=3D NULL) { > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto Exit; > > + } > > + > > + SdhcCtx =3D (USDHC_PRIVATE_CONTEXT*)SdhcProtocol->PrivateContext; > > + SdhcCtx->SdhcId =3D SdhcId; > > + SdhcCtx->RegistersBase =3D (USDHC_REGISTERS*)RegistersBase; > > + SdhcCtx->CardDetectSignal =3D CardDetectSignal; > > + if (USDHC_IS_GPIO_SIGNAL_SOURCE(SdhcCtx->CardDetectSignal)) { > > + SdhcCtx->CardDetectGpioPin.IoNumber =3D > PCD_GPIO_PIN_IO_NUMBER((UINT16)CardDetectSignal); > > + SdhcCtx->CardDetectGpioPin.Bank =3D > PCD_GPIO_PIN_BANK(CardDetectSignal); > > + } > > + > > + SdhcCtx->WriteProtectSignal=3D WriteProtectSignal; > > + if (USDHC_IS_GPIO_SIGNAL_SOURCE(SdhcCtx->WriteProtectSignal)) { > > + SdhcCtx->WriteProtectGpioPin.IoNumber =3D > PCD_GPIO_PIN_IO_NUMBER((UINT16)WriteProtectSignal); > > + SdhcCtx->WriteProtectGpioPin.Bank =3D > PCD_GPIO_PIN_BANK(WriteProtectSignal); > > + } > > + > > + LOG_INFO( > > + "Initializing uSDHC%d @%p GPIO CD?:%d WP?:%d", > > + SdhcId, > > + RegistersBase, > > + (USDHC_IS_GPIO_SIGNAL_SOURCE(SdhcCtx->CardDetectSignal) ? 1 : > 0), > > + (USDHC_IS_GPIO_SIGNAL_SOURCE(SdhcCtx->WriteProtectSignal) ? 1 > : 0)); > > + > > + if (USDHC_IS_GPIO_SIGNAL_SOURCE(SdhcCtx->CardDetectSignal)) { > > + LOG_INFO( > > + "Using GPIO%d_IO%d for CardDetect", > > + SdhcCtx->CardDetectGpioPin.Bank, > > + SdhcCtx->CardDetectGpioPin.IoNumber); > > + } > > + > > + if (USDHC_IS_GPIO_SIGNAL_SOURCE(SdhcCtx->WriteProtectSignal)) { > > + LOG_INFO( > > + "Using GPIO%d_IO%d for WriteProtect", > > + SdhcCtx->WriteProtectGpioPin.Bank, > > + SdhcCtx->WriteProtectGpioPin.IoNumber); > > + } > > + > > + Status =3D gBS->InstallMultipleProtocolInterfaces( > > + &SdhcCtx->SdhcProtocol= Handle, > > + &gEfiSdhcProtocolGuid, > > + SdhcProtocol, > > + NULL); > > + if (EFI_ERROR(Status)) { > > + LOG_ERROR("InstallMultipleProtocolInterfaces failed. %r", Stat= us); > > + goto Exit; > > + } > > + > > +Exit: > > + if (EFI_ERROR(Status)) { > > + LOG_ERROR("Failed to register and initialize uSDHC%d", SdhcId)= ; > > + > > + if (SdhcProtocol !=3D NULL && SdhcProtocol->PrivateContext != =3D NULL) { > > + FreePool(SdhcProtocol->PrivateContext); > > + SdhcProtocol->PrivateContext =3D NULL; > > + } > > + > > + if (SdhcProtocol !=3D NULL) { > > + FreePool(SdhcProtocol); > > + SdhcProtocol =3D NULL; > > + } > > + } > > + > > + return Status; > > +} > > + > > +EFI_STATUS > > +SdhcInitialize( > > + IN EFI_HANDLE ImageHandle, > > + IN EFI_SYSTEM_TABLE *SystemTable > > + ) > > +{ > > + EFI_STATUS Status =3D EFI_SUCCESS; > > + UINT32 uSdhcRegisteredCount =3D 0; > > + > > + // > > + // Register uSDHC1 through uSDHC4 if their base address is non-zer= o > > + // >=20 > Can this hardwiring be moved out of the driver and into platform init > code using NonDiscoverableDeviceRegistrationLib, as per this > (unrelated) thread from earlier this year: > https://na01.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Flists.= 01 > .org%2Fpipermail%2Fedk2-devel%2F2018- > April%2F023922.html&data=3D02%7C01%7CChristopher.Co%40microsoft.c > om%7Cc0f078beab2c4534017c08d5f7c9f5f5%7C72f988bf86f141af91ab2d7cd0 > 11db47%7C1%7C0%7C636687369157661520&sdata=3DXJZ6%2BU7ZlTuv8f7 > 5Si5LLthif2Q4bnBbF13Gdbu6sXY%3D&reserved=3D0 > ? >=20 > > + > > + // > > + // uSDHC1 > > + // > > + if (FixedPcdGet32(PcdSdhc1Enable)) { > > + Status =3D uSdhcDeviceRegister( > > + ImageHandle, > > + 1, > > + (VOID*)FixedPcdGet32(PcdSdhc1Base), > > + FixedPcdGet32(PcdSdhc1CardDetectSignal), > > + FixedPcdGet32(PcdSdhc1WriteProtectSignal)); > > + if (!EFI_ERROR(Status)) { > > + ++uSdhcRegisteredCount; > > + } > > + } > > + > > + // > > + // uSDHC2 > > + // > > + if (FixedPcdGet32(PcdSdhc2Enable)) { > > + Status =3D uSdhcDeviceRegister( > > + ImageHandle, > > + 2, > > + (VOID*)FixedPcdGet32(PcdSdhc2Base), > > + FixedPcdGet32(PcdSdhc2CardDetectSignal), > > + FixedPcdGet32(PcdSdhc2WriteProtectSignal)); > > + if (!EFI_ERROR(Status)) { > > + ++uSdhcRegisteredCount; > > + } > > + } > > + > > + // > > + // uSDHC3 > > + // > > + if (FixedPcdGet32(PcdSdhc3Enable)) { > > + Status =3D uSdhcDeviceRegister( > > + ImageHandle, > > + 3, > > + (VOID*)FixedPcdGet32(PcdSdhc3Base), > > + FixedPcdGet32(PcdSdhc3CardDetectSignal), > > + FixedPcdGet32(PcdSdhc3WriteProtectSignal)); > > + if (!EFI_ERROR(Status)) { > > + ++uSdhcRegisteredCount; > > + } > > + } > > + > > + // > > + // uSDHC4 > > + // > > + if (FixedPcdGet32(PcdSdhc4Enable)) { > > + Status =3D uSdhcDeviceRegister( > > + ImageHandle, > > + 4, > > + (VOID*)FixedPcdGet32(PcdSdhc4Base), > > + FixedPcdGet32(PcdSdhc4CardDetectSignal), > > + FixedPcdGet32(PcdSdhc4WriteProtectSignal)); > > + if (!EFI_ERROR(Status)) { > > + ++uSdhcRegisteredCount; > > + } > > + } > > + > > + // > > + // Succeed driver loading if at least one enabled uSDHC got regist= ered > successfully > > + // > > + if ((Status !=3D EFI_SUCCESS) && (uSdhcRegisteredCount > 0)) { > > + Status =3D EFI_SUCCESS; > > + } > > + > > + return Status; > > +} > > diff --git a/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf > b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf > > new file mode 100644 > > index 000000000000..5aee8b2ffbde > > --- /dev/null > > +++ b/Silicon/NXP/iMXPlatformPkg/Drivers/SdhcDxe/SdhcDxe.inf > > @@ -0,0 +1,67 @@ > > +## @file > > +# > > +# Copyright (c) Microsoft Corporation. All rights reserved. > > +# > > +# This program and the accompanying materials > > +# are licensed and made available under the terms and conditions of t= he > BSD License > > +# which accompanies this distribution. The full text of the license = may be > found at > > +# > https://na01.safelinks.protection.outlook.com/?url=3Dhttp%3A%2F%2Fopenso > urce.org%2Flicenses%2Fbsd- > license.php&data=3D02%7C01%7CChristopher.Co%40microsoft.com%7Cc0 > f078beab2c4534017c08d5f7c9f5f5%7C72f988bf86f141af91ab2d7cd011db47%7 > C1%7C0%7C636687369157661520&sdata=3DnoPZDlLAGlOgwhpiKbfxZk%2B > OPT6KNdeBtEi8VELsugQ%3D&reserved=3D0 > > +# > > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > > +# > > +## > > + > > +[Defines] > > + INF_VERSION =3D 0x00010005 >=20 > 0x0001001a >=20 > > + BASE_NAME =3D SdhcDxe > > + FILE_GUID =3D A9945BAB-78C9-43C9-9175-F576CA189= 870 > > + MODULE_TYPE =3D DXE_DRIVER > > + VERSION_STRING =3D 1.0 > > + ENTRY_POINT =3D SdhcInitialize > > + > > +[Sources.common] > > + SdhcDxe.c > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + EmbeddedPkg/EmbeddedPkg.dec > > + Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec > > + Platform/Microsoft/MsPkg.dec >=20 > Sorted alphabetically, please. >=20 > > + > > +[LibraryClasses] > > + PcdLib > > + UefiLib > > + UefiDriverEntryPoint > > + MemoryAllocationLib > > + IoLib > > + iMXIoMuxLib >=20 > Sorted alphabetically, please. >=20 > > + > > +[Guids] > > + > > +[Protocols] > > + gEfiSdhcProtocolGuid > > + > > +[Pcd] > > + giMXPlatformTokenSpaceGuid.PcdSdhc1Base > > + giMXPlatformTokenSpaceGuid.PcdSdhc2Base > > + giMXPlatformTokenSpaceGuid.PcdSdhc3Base > > + giMXPlatformTokenSpaceGuid.PcdSdhc4Base > > + giMXPlatformTokenSpaceGuid.PcdSdhc1Enable > > + giMXPlatformTokenSpaceGuid.PcdSdhc2Enable > > + giMXPlatformTokenSpaceGuid.PcdSdhc3Enable > > + giMXPlatformTokenSpaceGuid.PcdSdhc4Enable > > + giMXPlatformTokenSpaceGuid.PcdSdhc1CardDetectSignal > > + giMXPlatformTokenSpaceGuid.PcdSdhc1WriteProtectSignal > > + giMXPlatformTokenSpaceGuid.PcdSdhc2CardDetectSignal > > + giMXPlatformTokenSpaceGuid.PcdSdhc2WriteProtectSignal > > + giMXPlatformTokenSpaceGuid.PcdSdhc3CardDetectSignal > > + giMXPlatformTokenSpaceGuid.PcdSdhc3WriteProtectSignal > > + giMXPlatformTokenSpaceGuid.PcdSdhc4CardDetectSignal > > + giMXPlatformTokenSpaceGuid.PcdSdhc4WriteProtectSignal > > + > > +[FixedPcd] > > + giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange > > + > > +[depex] > > + TRUE > > diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h > b/Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h > > new file mode 100644 > > index 000000000000..c75b543c8bb4 > > --- /dev/null > > +++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXGpio.h > > @@ -0,0 +1,101 @@ > > +/** @file > > +* > > +* Copyright (c) Microsoft Corporation. All rights reserved. > > +* > > +* This program and the accompanying materials > > +* are licensed and made available under the terms and conditions of t= he > BSD License > > +* which accompanies this distribution. The full text of the license = may be > found at > > +* > https://na01.safelinks.protection.outlook.com/?url=3Dhttp%3A%2F%2Fopenso > urce.org%2Flicenses%2Fbsd- > license.php&data=3D02%7C01%7CChristopher.Co%40microsoft.com%7Cc0 > f078beab2c4534017c08d5f7c9f5f5%7C72f988bf86f141af91ab2d7cd011db47%7 > C1%7C0%7C636687369157661520&sdata=3DnoPZDlLAGlOgwhpiKbfxZk%2B > OPT6KNdeBtEi8VELsugQ%3D&reserved=3D0 > > +* > > +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > > +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > > +* > > +**/ > > + > > +#ifndef _IMX_GPIO_H_ > > +#define _IMX_GPIO_H_ > > + > > +#include > > + > > +#ifndef C_ASSERT > > +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] > > +#endif // C_ASSERT >=20 > What's wrong with normal ASSERT? >=20 > > + > > +typedef enum { > > + IMX_GPIO_LOW =3D 0, > > + IMX_GPIO_HIGH =3D 1 > > +} IMX_GPIO_VALUE; > > + > > +typedef enum { > > + IMX_GPIO_DIR_INPUT, > > + IMX_GPIO_DIR_OUTPUT > > +} IMX_GPIO_DIR; > > + > > +typedef enum { > > + IMX_GPIO_BANK1 =3D 1, > > + IMX_GPIO_BANK2, > > + IMX_GPIO_BANK3, > > + IMX_GPIO_BANK4, > > + IMX_GPIO_BANK5, > > + IMX_GPIO_BANK6, > > + IMX_GPIO_BANK7, > > +} IMX_GPIO_BANK; > > + > > +#pragma pack(push, 1) > > + > > +// > > +// GPIO reserved size is based on total size minus 8 DWORD of standard > GPIO reg > > +// > > +C_ASSERT((FixedPcdGet32(PcdGpioBankMemoryRange) % 4) =3D=3D 0); > > + > > +#define GPIO_RESERVED_SIZE \ > > + ((FixedPcdGet32(PcdGpioBankMemoryRange) / 4) - 8) > > + > > +typedef struct { > > + UINT32 DR; // 0x00 GPIO data register (= GPIO1_DR) > > + UINT32 GDIR; // 0x04 GPIO direction regis= ter (GPIO1_GDIR) > > + UINT32 PSR; // 0x08 GPIO pad status regi= ster (GPIO1_PSR) > > + UINT32 ICR1; // 0x0C GPIO interrupt confi= guration register1 > (GPIO1_ICR1) > > + UINT32 ICR2; // 0x10 GPIO interrupt confi= guration register2 > (GPIO1_ICR2) > > + UINT32 IMR; // 0x14 GPIO interrupt mask = register > (GPIO1_IMR) > > + UINT32 ISR; // 0x18 GPIO interrupt statu= s register > (GPIO1_ISR) > > + UINT32 EDGE_SEL; // 0x1C GPIO edge select reg= ister > (GPIO1_EDGE_SEL) > > + UINT32 reserved[GPIO_RESERVED_SIZE]; > > +} IMX_GPIO_BANK_REGISTERS; > > + > > +#pragma pack(pop) > > + > > +typedef struct { > > + IMX_GPIO_BANK_REGISTERS Banks[7]; > > +} IMX_GPIO_REGISTERS; > > + > > +/** > > + Set the specified GPIO to the specified direction. > > +**/ > > +VOID > > +ImxGpioDirection ( > > + IMX_GPIO_BANK Bank, > > + UINT32 IoNumber, > > + IMX_GPIO_DIR Direction > > + ); > > + > > +/** > > + Write a value to a GPIO pin. > > +**/ > > +VOID > > +ImxGpioWrite ( > > + IMX_GPIO_BANK Bank, > > + UINT32 IoNumber, > > + IMX_GPIO_VALUE Value > > + ); > > + > > +/** > > + Read a GPIO pin input value. > > +**/ > > +IMX_GPIO_VALUE > > +ImxGpioRead ( > > + IMX_GPIO_BANK Bank, > > + UINT32 IoNumber > > + ); > > + > > +#endif > > diff --git a/Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h > b/Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h > > new file mode 100644 > > index 000000000000..acdbcd324631 > > --- /dev/null > > +++ b/Silicon/NXP/iMXPlatformPkg/Include/iMXuSdhc.h > > @@ -0,0 +1,277 @@ > > +/** @file > > +* > > +* Copyright (c) Microsoft Corporation. All rights reserved. > > +* > > +* This program and the accompanying materials > > +* are licensed and made available under the terms and conditions of t= he > BSD License > > +* which accompanies this distribution. The full text of the license = may be > found at > > +* > https://na01.safelinks.protection.outlook.com/?url=3Dhttp%3A%2F%2Fopenso > urce.org%2Flicenses%2Fbsd- > license.php&data=3D02%7C01%7CChristopher.Co%40microsoft.com%7Cc0 > f078beab2c4534017c08d5f7c9f5f5%7C72f988bf86f141af91ab2d7cd011db47%7 > C1%7C0%7C636687369157661520&sdata=3DnoPZDlLAGlOgwhpiKbfxZk%2B > OPT6KNdeBtEi8VELsugQ%3D&reserved=3D0 > > +* > > +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > > +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > > +* > > +**/ > > + > > +#ifndef __IMX_USDHC_H__ > > +#define __IMX_USDHC_H__ > > + > > +// > > +// uSDHCx Registers Layout > > +// > > +typedef struct { > > + UINT32 DS_ADDR; > > + UINT32 BLK_ATT; > > + UINT32 CMD_ARG; > > + UINT32 CMD_XFR_TYP; > > + UINT32 CMD_RSP0; > > + UINT32 CMD_RSP1; > > + UINT32 CMD_RSP2; > > + UINT32 CMD_RSP3; > > + UINT32 DATA_BUFF_ACC_PORT; > > + UINT32 PRES_STATE; > > + UINT32 PROT_CTRL; > > + UINT32 SYS_CTRL; > > + UINT32 INT_STATUS; > > + UINT32 INT_STATUS_EN; > > + UINT32 INT_SIGNAL_EN; > > + UINT32 AUTOCMD12_ERR_STATUS; > > + UINT32 HOST_CTRL_CAP; > > + UINT32 WTMK_LVL; > > + UINT32 MIX_CTRL; > > + UINT32 _pad0; > > + UINT32 FORCE_EVENT; > > + UINT32 ADMA_ERR_STATUS; > > + UINT32 ADMA_SYS_ADDR; > > + UINT32 _pad1; > > + UINT32 DLL_CTRL; > > + UINT32 DLL_STATUS; > > + UINT32 CLK_TUNE_CTRL_STATUS; > > + UINT32 _pad2[21]; > > + UINT32 VEND_SPEC; > > + UINT32 MMC_BOOT; > > + UINT32 VEND_SPEC2; > > +} USDHC_REGISTERS; > > + > > +// > > +// Block Attributes uSDHCx_BLK_ATT fields > > +// > > +typedef union { > > + UINT32 AsUint32; > > + struct { > > + UINT32 BLKSIZE : 13; // 0:12 > > + UINT32 _reserved0 : 3; // 13:15 > > + UINT32 BLKCNT : 16; // 16:31 > > + } Fields; > > +} USDHC_BLK_ATT_REG; > > + > > +// > > +// Command Transfer Type uSDHCx_CMD_XFR_TYP fields > > +// > > +typedef union { > > + UINT32 AsUint32; > > + struct { > > + UINT32 _reserved0 : 16; // 0:15 > > + UINT32 RSPTYP : 2; // 16:17 > > + UINT32 _reserved1 : 1; // 18 > > + UINT32 CCCEN : 1; // 19 > > + UINT32 CICEN : 1; // 20 > > + UINT32 DPSEL : 1; // 21 > > + UINT32 CMDTYP : 2; // 22:23 > > + UINT32 CMDINX : 6; // 24:29 > > + UINT32 _reserved2 : 2; // 30:31 > > + } Fields; > > +} USDHC_CMD_XFR_TYP_REG; > > + > > +#define USDHC_CMD_XFR_TYP_RSPTYP_NO_RSP 0 > > +#define USDHC_CMD_XFR_TYP_RSPTYP_RSP_136 1 > > +#define USDHC_CMD_XFR_TYP_RSPTYP_RSP_48 2 > > +#define USDHC_CMD_XFR_TYP_RSPTYP_RSP_48_CHK_BSY 3 > > +#define USDHC_CMD_XFR_TYP_CMDTYP_ABORT 3 > > + > > +// > > +// System Control uSDHCx_SYS_CTRL fields > > +// > > +typedef union { > > + UINT32 AsUint32; > > + struct { > > + UINT32 _reserved0 : 4; // 0:3 > > + UINT32 DVS : 4; // 4:7 > > + UINT32 SDCLKFS : 8; // 8:15 > > + UINT32 DTOCV : 4; // 16:19 > > + UINT32 _reserved1 : 3; // 20:22 > > + UINT32 IPP_RST_N : 1; // 23 > > + UINT32 RSTA : 1; // 24 > > + UINT32 RSTC : 1; // 25 > > + UINT32 RSTD : 1; // 26 > > + UINT32 INITA : 1; // 27 > > + UINT32 _reserved2 : 4; // 28-31 > > + } Fields; > > +} USDHC_SYS_CTRL_REG; > > + > > +// > > +// Host Controller Capabilities Register uSDHCx_HOST_CTRL_CAP fields > > +// > > +typedef union { > > + UINT32 AsUint32; > > + struct { > > + UINT32 _reserved0 : 16; // 0:15 > > + UINT32 MBL : 3; // 16:18 > > + UINT32 _reserved1 : 1; // 19 > > + UINT32 ADMAS : 1; // 20 > > + UINT32 HSS : 1; // 21 > > + UINT32 DMAS : 1; // 22 > > + UINT32 SRS : 1; // 23 > > + UINT32 VS33 : 1; // 24 > > + UINT32 VS30 : 1; // 25 > > + UINT32 VS18 : 1; // 26 > > + UINT32 _reserved2 : 5; // 27:31 > > + } Fields; > > +} USDHC_HOST_CTRL_CAP_REG; > > + > > +// > > +// Watermark Level uSDHCx_WTMK_LVL > > +// > > +typedef union { > > + UINT32 AsUint32; > > + struct { > > + UINT32 RD_WML : 8; // 0:7 > > + UINT32 RD_BRST_LEN : 5; // 8:12 > > + UINT32 _reserved0 : 3; // 13:15 > > + UINT32 WR_WML : 8; // 16:23 > > + UINT32 WR_BRST_LEN : 5; // 24:28 > > + UINT32 _reserved1 : 3; // 29:31 > > + } Fields; > > +} USDHC_WTMK_LVL_REG; > > + > > +#define USDHC_WTMK_RD_WML_MAX_VAL 0x10 > > +#define USDHC_WTMK_WR_WML_MAX_VAL 0x80 > > + > > +// > > +// Mixer Control uSDHCx_MIX_CTRL fields > > +// > > +typedef union { > > + UINT32 AsUint32; > > + struct { > > + UINT32 DMAEN : 1; // 0 > > + UINT32 BCEN : 1; // 1 > > + UINT32 AC12EN : 1; // 2 > > + UINT32 DDR_EN : 1; // 3 > > + UINT32 DTDSEL : 1; // 4 > > + UINT32 MSBSEL : 1; // 5 > > + UINT32 NIBBLE_POS : 1; // 6 > > + UINT32 AC23EN : 1; // 7 > > + UINT32 _reserved0 : 14; // 8:21 > > + UINT32 EXE_TUNE : 1; // 22 > > + UINT32 SMP_CLK_SEL : 1; // 23 > > + UINT32 AUTO_TUNE_EN : 1; //24 > > + UINT32 FBCLK_SEL : 1; // 25 > > + UINT32 _reserved1 : 6; // 26-31 > > + } Fields; > > +} USDHC_MIX_CTRL_REG; > > + > > +// > > +// Present State uSDHCx_PRES_STATE fields > > +// > > +typedef union { > > + UINT32 AsUint32; > > + struct { > > + UINT32 CIHB : 1; // 0 > > + UINT32 CDIHB : 1; // 1 > > + UINT32 DLA : 1; // 2 > > + UINT32 SDSTB : 1; // 3 > > + UINT32 IPGOFF : 1; // 4 > > + UINT32 HCKOFF : 1; // 5 > > + UINT32 PEROFF : 1; // 6 > > + UINT32 SDOFF : 1; // 7 > > + UINT32 WTA : 1; // 8 > > + UINT32 RTA : 1; // 9 > > + UINT32 BWEN : 1; // 10 > > + UINT32 BREN : 1; // 11 > > + UINT32 PTR : 1; // 12 > > + UINT32 _reserved0 : 3; // 13:15 > > + UINT32 CINST : 1; // 16 > > + UINT32 _reserved1 : 1; // 17 > > + UINT32 CDPL : 1; // 18 > > + UINT32 WPSPL : 1; // 19 > > + UINT32 _reserved2 : 3; // 20:22 > > + UINT32 CLSL : 1; // 23 > > + UINT32 DLSL : 8; // 24:31 > > + } Fields; > > +} USDHC_PRES_STATE_REG; > > + > > +// > > +// Present State uSDHCx_PROT_CTRL fields > > +// > > +typedef union { > > + UINT32 AsUint32; > > + struct { > > + UINT32 LCTL : 1; // 0 > > + UINT32 DTW : 2; // 1:2 > > + UINT32 D3CD : 1; // 3 > > + UINT32 EMODE : 2; // 4:5 > > + UINT32 CDTL : 1; // 6 > > + UINT32 CDSS : 1; // 7 > > + UINT32 DMASEL : 2; // 8:9 > > + UINT32 _reserved0 : 6; // 10:15 > > + UINT32 SABGREQ : 1; // 16 > > + UINT32 CREQ : 1; // 17 > > + UINT32 RWCTL : 1; // 18 > > + UINT32 IABG : 1; // 19 > > + UINT32 RD_DONE_NO_8CLK : 1; // 20 > > + UINT32 _reserved1 : 3; // 21:23 > > + UINT32 WECINT : 1; // 24 > > + UINT32 WECINS : 1; // 25 > > + UINT32 WECRM : 1; // 26 > > + UINT32 BURST_LEN_EN : 3; // 27:29 > > + UINT32 NON_EXACT_BLK_RD : 1; // 30 > > + UINT32 _reserved2 : 1; // 31 > > + } Fields; > > +} USDHC_PROT_CTRL_REG; > > + > > +#define USDHC_PROT_CTRL_DTW_1BIT 0x0 > > +#define USDHC_PROT_CTRL_DTW_4BIT 0x1 > > +#define USDHC_PROT_CTRL_DTW_8BIT 0x2 > > +#define USDHC_PROT_CTRL_EMODE_LITTLE_ENDIAN 0x2 > > + > > +// > > +// Interrupt Status uSDHCx_INT_STATUS fields > > +// > > +typedef union { > > + UINT32 AsUint32; > > + struct { > > + UINT32 CC : 1; // 0 > > + UINT32 TC : 1; // 1 > > + UINT32 BGE : 1; // 2 > > + UINT32 DINT : 1; // 3 > > + UINT32 BWR : 1; // 4 > > + UINT32 BRR : 1; // 5 > > + UINT32 CINS : 1; // 6 > > + UINT32 CRM : 1; // 7 > > + UINT32 CINT : 1; // 8 > > + UINT32 _reserved0 : 3; // 9:11 > > + UINT32 RTE : 1; // 12 > > + UINT32 _reserved1 : 1; // 13 > > + UINT32 TP : 1; // 14 > > + UINT32 _reserved2 : 1; // 15 > > + UINT32 CTOE : 1; // 16 > > + UINT32 CCE : 1; // 17 > > + UINT32 CEBE : 1; // 18 > > + UINT32 CIE : 1; // 19 > > + UINT32 DTOE : 1; // 20 > > + UINT32 DCE : 1; // 21 > > + UINT32 DEBE : 1; // 22 > > + UINT32 _reserved3 : 1; // 23 > > + UINT32 AC12E : 1; // 24 > > + UINT32 _reserved4 : 1; // 25 > > + UINT32 TNE : 1; // 26 > > + UINT32 _reserved5 : 1; // 27 > > + UINT32 DMAE : 1; // 28 > > + UINT32 _reserved6 : 3; // 29:31 > > + } Fields; > > +} USDHC_INT_STATUS_REG; > > + > > +#define USDHC_INT_STATUS_CMD_ERROR (BIT16 | BIT17 | BIT18 | > BIT19) > > +#define USDHC_INT_STATUS_DATA_ERROR (BIT20 | BIT21 | BIT22) > > +#define USDHC_INT_STATUS_ERROR > (USDHC_INT_STATUS_CMD_ERROR | USDHC_INT_STATUS_DATA_ERROR) > > + > > +#endif // __IMX_USDHC_H__ > > -- > > 2.16.2.gvfs.1.33.gf5370f1 > >