From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by mx.groups.io with SMTP id smtpd.web09.5092.1618551268150652000 for ; Thu, 15 Apr 2021 22:34:30 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@intel.onmicrosoft.com header.s=selector2-intel-onmicrosoft-com header.b=khLkWQCG; spf=pass (domain: intel.com, ip: 134.134.136.20, mailfrom: tien.hock.loh@intel.com) IronPort-SDR: v83fIf9hA2+eZfKN3CLJL634XRmlHahsZUfuNkqgyMlNUNQpoYg5SH/4KmLSMm1ryDCiPRgT+K +OND1Qc80XjQ== X-IronPort-AV: E=McAfee;i="6200,9189,9955"; a="182118158" X-IronPort-AV: E=Sophos;i="5.82,226,1613462400"; d="scan'208";a="182118158" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Apr 2021 22:34:17 -0700 IronPort-SDR: TCZqeV7b3g2LwRJCaW7MgGlmQP8KpLH63Spy4V6dDVqrJ1T3ngJ6mIm1OXlEhUWtcGeEGUf5l1 qQkHklaI4Q8w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.82,226,1613462400"; d="scan'208";a="461860562" Received: from orsmsx602.amr.corp.intel.com ([10.22.229.15]) by orsmga001.jf.intel.com with ESMTP; 15 Apr 2021 22:34:17 -0700 Received: from orsmsx610.amr.corp.intel.com (10.22.229.23) by ORSMSX602.amr.corp.intel.com (10.22.229.15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2106.2; Thu, 15 Apr 2021 22:34:16 -0700 Received: from orsmsx610.amr.corp.intel.com (10.22.229.23) by ORSMSX610.amr.corp.intel.com (10.22.229.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2106.2; Thu, 15 Apr 2021 22:34:16 -0700 Received: from ORSEDG601.ED.cps.intel.com (10.7.248.6) by orsmsx610.amr.corp.intel.com (10.22.229.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2106.2 via Frontend Transport; Thu, 15 Apr 2021 22:34:16 -0700 Received: from NAM11-DM6-obe.outbound.protection.outlook.com (104.47.57.176) by edgegateway.intel.com (134.134.137.102) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2106.2; Thu, 15 Apr 2021 22:34:15 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=D+n4esZYvZKTNJFEvMXBjRfztwzJ2xn9b5ngUXyc4sCCWfg+QLbOzM9vEpfLCGEInNbMEot625Rofj2z785jkfvrHJUX3IPh2iB3KpGfXyWyJ1Ek4J6MA3NaTtUzrTfAoBUe6UdAFiZ8+XVklHtZImQkqVjmtO0ozxp08rloZhBPot/MvMcAh8TH+WiELxok7FIlH4UrjgYwUt5+Y+fEvQjyhnXOUwed8/6J7ZmKtaq/PN82tiWH1IJOtK0BvcjJjdNpfDEUhjx5zY70hZut4LytYj4wM5MaD77cUztN4kKQLBRtSjpTYE5/R3daDdj0v7ryZY/TmqksdzWLF7CvMA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=TWvxNJNX2323CU5fbMev+djyIwhwP3Hm7L45PvlNKfs=; b=VRBfQB8SRujP4eDwSiujC4aUAE7VIf2H02goMLFv5bCwEaBenTjRE21U3oKSxFrQ2pCiVD9fU3gb5tvLItUH+cTQ6vlWWkS6qNyk3RlJPub1QjG3fFkZSiEqZAmfcAdNIQBZPE697hrfIO+j99IqGhc+ybdLUJPNt4U6ikLbRy1L/hO1r8WM635nXpGpUf7Prn2mP15PQlalmZaRcmpOyLaVtYyqri7MXAwR/6RMubE9ljehvwyGB/sgkJVZjsTH+9pHF+em+D/dsQtYAskZb3VbdxiZGORk47kvpOCjVj8bwFPof0bhNbwDjgI9aBCIgeAqLZVrC/yBebM5CZIeFA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=intel.onmicrosoft.com; s=selector2-intel-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=TWvxNJNX2323CU5fbMev+djyIwhwP3Hm7L45PvlNKfs=; b=khLkWQCGJi8/dauemBEc60mohl3toWPp7iQe/JYSUf6LEfBrSMXkdF9ZiKf5mULPUzbl2wVIZ5b2ZIVD3c/ozS9bKaJoixJhHVouIv53n1R+jyOWdwsv3LLD2IOUqU/HbCyoQ/WTavvhPSbx8Uj/eHeIZQ6VPQwxoyHJQXrR6mE= Received: from SJ0PR11MB5136.namprd11.prod.outlook.com (2603:10b6:a03:2d1::18) by BYAPR11MB3191.namprd11.prod.outlook.com (2603:10b6:a03:79::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4042.18; Fri, 16 Apr 2021 05:34:10 +0000 Received: from SJ0PR11MB5136.namprd11.prod.outlook.com ([fe80::ac08:c378:ad50:dc67]) by SJ0PR11MB5136.namprd11.prod.outlook.com ([fe80::ac08:c378:ad50:dc67%7]) with mapi id 15.20.4042.016; Fri, 16 Apr 2021 05:34:10 +0000 From: "Loh, Tien Hock" To: "devel@edk2.groups.io" CC: "thloh85@gmail.com" , "Kinney, Michael D" , Leif Lindholm , "Ard Biesheuvel" Subject: Re: [PATCH V5 1/1] EmbeddedPkg: DwMmcHcDxe: Add support for Designware SDMMC driver Thread-Topic: [PATCH V5 1/1] EmbeddedPkg: DwMmcHcDxe: Add support for Designware SDMMC driver Thread-Index: AQHXHsr8+cCyDCxc+UWpketwaiWuOaqPWDKAgAymniCAGsUXQA== Date: Fri, 16 Apr 2021 05:34:10 +0000 Message-ID: References: <20210322032439.9312-1-tien.hock.loh@intel.com> <20210322032439.9312-2-tien.hock.loh@intel.com> In-Reply-To: Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-reaction: no-action dlp-version: 11.5.1.3 dlp-product: dlpe-windows authentication-results: edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=none action=none header.from=intel.com; x-originating-ip: [103.78.32.234] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 3a7bfc7f-6a44-4c0c-fb54-08d90099433a x-ms-traffictypediagnostic: BYAPR11MB3191: x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:10000; x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: Hx58ERIsmCmZI6VrIKcm6HaxbUh4Alj05Wc5SfBMdU9elsMmsJfBvpmtHt8RzZlK6666LldX531rWzNKjpp74Aoj83Zot3KrqaPiWMhzAFnXak/4e9vfX4MqxQM0Ld63wirBC7HR1TTlGt/DTgTwhyG4pnVY+sR89IZs9uaW+ixA+Dqq6H0gvL8o3VQV8snrvSe+dym1+Lusr0Yn92Ch+s7EMwtDKf09rrS12W1IsywqSggJ3xncCBWZUm1rCzTH/gLEYsSE9zVWowsApw15S+xeEhl4nBPCCdQVi0kgKn4x9/6d/V3prga6Ku7LTZYPq6MgPSb17b47x4mfWYandqKdc/oTOz4/J3maoLq0izZltiZmZ0ePBA584xp8E7ggDO1ag7ZmtSU0VYqHEJXtEQJ4GHOF1iMnDGcUUgAxku+pf332EfLXTAewL42IQeRf76UNLNDegZYa0mbqjWh9uXsE1iuWzcWy2xeQF+acqb2uK8j3ugH6dBJFBU9H+ERI45Wsur1HGrdWnwwQuZz7M8c9TYE6y2YbkycLGgZ3ZK1PYbjtneSxRDI8ycaDiASg6bt9ex87JrB5ENLFgdx1NkNUL4n+8mUvgDcIubQqB9FA75Goy3FzX6GpaouE9gPfv1W3QyMjGNv4Nd6m7nn9Kd4e8yj9o1nuh9n0cs4MJ8GIVaqHoVuFtR9xy/MdQavXNC/odjtEwjFrq1HmLWkFyVd1VDDtZa1ivGtn4ksSDMK7iPFFoAjOJzRbM4ovmKnw x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SJ0PR11MB5136.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFS:(6029001)(136003)(396003)(346002)(366004)(39860400002)(376002)(8676002)(55016002)(71200400001)(122000001)(52536014)(53546011)(966005)(38100700002)(26005)(8936002)(316002)(19627235002)(64756008)(2906002)(6916009)(66556008)(86362001)(30864003)(186003)(76116006)(15188155005)(16799955002)(6506007)(54906003)(66476007)(7696005)(9686003)(66446008)(33656002)(5660300002)(478600001)(4326008)(83380400001)(66946007)(290074003)(569008);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata: =?us-ascii?Q?zg1+jvRGxrd2NOBUvBGM+mD0uaFw71/TAVAyibmVtQoFmtVrYge+CZt/ieX2?= =?us-ascii?Q?Ptas2MqUx0amhK8Gev4Q+4hmJj1zN1r0hG/KZWqhRsXJdqd7ZMky0rRbwcAl?= =?us-ascii?Q?fnJoMufmFlSXJApJhmVauFOI/IcDqkfEMQsubZMgoe5X1MaXiWy77bG5cOfn?= =?us-ascii?Q?T0/OvNQUw0BxMpLg4+oI3INStv7/M+kmQ3K8vG0SOBq/t6TrjCdJJKeMTzBF?= =?us-ascii?Q?YZng5b9ucaD/tMOhXSqZ4bRDgzNsI7JYL5GTdko389ZxGcz5Ata4qeNu5gJN?= =?us-ascii?Q?nRg4tMYaWl883Gb4NHi5WmZLkZWTxzLWK+0BJYzNDH2ykIxetrgX4TNNx6s3?= =?us-ascii?Q?AQFzK6pgGg+GJkLMnH1vzs6ylx9vu+rLBnn4MJY2NygvtmJhU8JV21gwg8LL?= =?us-ascii?Q?BxGVF99XhnHlcB9XlgiPp4YD8DWCg4fqN4ndKqiI0SEDI0RdFe+yKIChpxCD?= =?us-ascii?Q?UOBu0cG92n4FU4qQyphIf+H91dpXQZp05MUWIGYtOmd6CfUp4vZHku8otsvT?= =?us-ascii?Q?jMhDW3iaO7ZvafgAvDoVcKbVt8mz5fc+K07QXEGfJ8CYuinUIhW4fkd8uaEy?= =?us-ascii?Q?G8Fg7mxUS+pTRBv2KgQSposff7uEVrdGSk4lUMMm3UE0aHUUNcE1U25SWMiV?= =?us-ascii?Q?UzXxumEjLMv1fG/Gv4N49GypkT0Nu6EX0w1v8g8FGZSs678JKM/lM44EwYVc?= =?us-ascii?Q?0IAisz6O5Qc1pQbume31zwl+sGfk5MHn/O5iAXkwMxKY+KqCaUKfravKVKHw?= =?us-ascii?Q?139Hd1RiX6ngNx3FhV+gfEAiIQ56LO2HQVyQ462lgpBeSSh0yan8untw89KE?= =?us-ascii?Q?mSGnA8UQ0vHYO3ulQlMREjKCIsSMA8aj4buK9lycXTo8Kn1nH2QECqRoP5hY?= =?us-ascii?Q?ME3tCeHClT5iEsacUSUOMw+cPY+o+nsnRTtMuzr2jtCv2gUcwlWIGy4seKfR?= =?us-ascii?Q?MLoyBABtCPmc3XX8qWAtEZgIkaWlPP8pcmPL/9pDHh1kTI4GV6LaXtC4SKA4?= =?us-ascii?Q?jaGJMEH2SGQL5ZPxrnmjKaY2sIu5HErwdgsYjciASJF/L5mkkMGduSwVUQcQ?= =?us-ascii?Q?eLiEqcYjjx1F2mKMZVcwx5eX/Bk+Drzo9oKSMI7AOnLGsPHZuPnQARgbt2k3?= =?us-ascii?Q?u1MsZ5C7YuLG6hFDduc8rhoybuaBPwKY0wgbLyPRW8YgtkwTOGr1OyAdhLYx?= =?us-ascii?Q?j2FKIGabLxUT9nTUAzR/AdAQO40j79YkZy1zLv1jI2KZNWhGpVOPtqfFuh8O?= =?us-ascii?Q?/0D82ZiYQOtGPrfjKCoe0iLCVVdOyGCyXHr3Mifx/P7f8HcH4i+Vrgg7H998?= =?us-ascii?Q?lHh8chFgC1G7SOk0YiqSg0hh?= MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: SJ0PR11MB5136.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 3a7bfc7f-6a44-4c0c-fb54-08d90099433a X-MS-Exchange-CrossTenant-originalarrivaltime: 16 Apr 2021 05:34:10.4982 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: tWgaSgtnuD+PpDNEIa2GXindB87ax9pMpX45zpICbnaJ6JMUNj6kyfvxCkS0QlgLw1arhzqHYyuztsewUN7Iqg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BYAPR11MB3191 Return-Path: tien.hock.loh@intel.com X-OriginatorOrg: intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi all, I've filed a BZ on this: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3= 340, we can have a discussion there if needed.=20 I've tested the driver booting up SoCFPGA platform from SDMMC, read and wri= te to SDMMC's fat partition and all works well. Multiple SD card has been used, Sandisk and Kingston, 8GB and 16GB has been= tested. Thank you. > -----Original Message----- > From: Loh, Tien Hock > Sent: Tuesday, March 30, 2021 12:37 PM > To: devel@edk2.groups.io > Cc: thloh85@gmail.com; Kinney, Michael D ; Le= if > Lindholm ; Ard Biesheuvel > Subject: RE: [PATCH V5 1/1] EmbeddedPkg: DwMmcHcDxe: Add support for > Designware SDMMC driver >=20 > Hi Ard, Leif, Michael, >=20 > Any issues or comments on the patch? >=20 > Thanks >=20 > > -----Original Message----- > > From: Loh, Tien Hock > > Sent: Monday, March 22, 2021 11:25 AM > > To: devel@edk2.groups.io > > Cc: thloh85@gmail.com; Loh, Tien Hock ; Kinney= , > > Michael D ; Leif Lindholm > > ; Ard Biesheuvel > > Subject: [PATCH V5 1/1] EmbeddedPkg: DwMmcHcDxe: Add support for > > Designware SDMMC driver > > > > From: "Tien Hock, Loh" > > > > This adds support for Designware SDMMC driver. The SDMMC driver > > depends on > > MdeModulePkg/Bus/Sd/, and produces > > EFI_SD_MMC_PASS_THRU_PROTOCOL. The > > driver uses MMIO to read/write, and uses > > gEdkiiNonDiscoverableDeviceProtocolGuid. Platform needs to register dev= ice > > with gEdkiiNonDiscoverableDeviceProtocolGuid. > > > > Signed-off-by: Loh Tien Hock > > Cc: Leif Lindholm > > Cc: Ard Biesheuvel > > --- > > EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.dec | 40 + > > EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.inf | 70 + > > EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.h | 817 > > ++++++++++ > > EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.h | 985 > > ++++++++++++ > > EmbeddedPkg/Include/Protocol/PlatformDwMmc.h | 79 + > > EmbeddedPkg/Drivers/DwMmcHcDxe/ComponentName.c | 214 +++ > > EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.c | 1296 > > ++++++++++++++++ > > EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.c | 1602 > > ++++++++++++++++++++ > > EmbeddedPkg/Drivers/DwMmcHcDxe/EmmcDevice.c | 1042 > > +++++++++++++ > > EmbeddedPkg/Drivers/DwMmcHcDxe/SdDevice.c | 1105 > > ++++++++++++++ > > 10 files changed, 7250 insertions(+) > > > > diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.dec > > b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.dec > > new file mode 100644 > > index 000000000000..cf85ccb1a030 > > --- /dev/null > > +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.dec > > @@ -0,0 +1,40 @@ > > +#/** @file > > +# Framework Module Development Environment Industry Standards > > +# > > +# This Package provides headers and libraries that conform to EFI/PI > > Industry standards. > > +# Copyright (c) 2007, Intel Corporation. All rights reserved.
> > +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.
> > +# Copyright (c) 2018, Linaro. All rights reserved.
> > +# > > +# This program and the accompanying materials are licensed and made > > available under > > +# the terms and conditions of the BSD License which accompanies thi= s > > distribution. > > +# The full text of the license may be found at > > +# http://opensource.org/licenses/bsd-license.php > > +# > > +# 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] > > + DEC_SPECIFICATION =3D 0x00010019 > > + PACKAGE_NAME =3D DwMmcHcDxePkg > > + PACKAGE_GUID =3D e73097ce-1fe2-41a6-a930-3136bc6d2= 3ef > > + PACKAGE_VERSION =3D 0.1 > > + > > + > > +######################################################### > > ####################### > > +# > > +# Include Section - list of Include Paths that are provided by this pa= ckage. > > +# Comments are used for Keywords and Module Types. > > +# > > +# Supported Module Types: > > +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER > > DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER > > UEFI_APPLICATION > > +# > > +######################################################### > > ####################### > > + > > +[Guids.common] > > + gDwMmcHcDxeTokenSpaceGuid =3D { 0x576c132e, 0x7d51, 0x4abb, { > 0xbc, > > 0x60, 0x13, 0x08, 0x04, 0x0e, 0x90, 0x92 }} > > + > > +[Protocols.common] > > + gPlatformDwMmcProtocolGuid =3D { 0x1d6dfde5, 0x76a7, 0x4404, { 0x= 85, > > 0x74, 0x7a, 0xdf, 0x1a, 0x8a, 0xa2, 0x0d }} > > diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.inf > > b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.inf > > new file mode 100644 > > index 000000000000..4cd0960ef9c3 > > --- /dev/null > > +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.inf > > @@ -0,0 +1,70 @@ > > +## @file > > +# DwSdMmcHcDxe driver is used to manage those host controllers which > > comply with > > +# Designware SD Host Controller. > > +# > > +# It will produce EFI_SD_MMC_PASS_THRU_PROTOCOL to allow sending > > SD/MMC/eMMC cmds > > +# to specified devices from upper layer. > > +# > > +# Copyright (c) 2015, Intel Corporation. All rights reserved.
> > +# Copyright (C) 2016, Marvell International Ltd. All rights reserved.=
> > +# Copyright (c) 2018, Linaro Ltd. 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 m= ay be > > found at > > +# http://opensource.org/licenses/bsd-license.php > > +# 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 0x00010019 > > + BASE_NAME =3D DwMmcHcDxe > > + MODULE_UNI_FILE =3D DwMmcHcDxe.uni > > + FILE_GUID =3D 9be4d260-208c-4efe-a524-0b5d3bf77= f9d > > + MODULE_TYPE =3D UEFI_DRIVER > > + VERSION_STRING =3D 1.0 > > + ENTRY_POINT =3D InitializeDwMmcHcDxe > > + > > +[Sources] > > + ComponentName.c > > + DwMmcHcDxe.c > > + DwMmcHcDxe.h > > + DwMmcHci.c > > + DwMmcHci.h > > + EmmcDevice.c > > + SdDevice.c > > + > > +[Packages] > > + ArmPkg/ArmPkg.dec > > + EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.dec > > + EmbeddedPkg/EmbeddedPkg.dec > > + MdeModulePkg/MdeModulePkg.dec > > + MdePkg/MdePkg.dec > > + > > +[LibraryClasses] > > + ArmLib > > + BaseLib > > + BaseMemoryLib > > + CacheMaintenanceLib > > + DebugLib > > + DevicePathLib > > + DmaLib > > + MemoryAllocationLib > > + TimerLib > > + UefiBootServicesTableLib > > + UefiDriverEntryPoint > > + UefiLib > > + UefiRuntimeServicesTableLib > > + > > +[Protocols] > > + gEdkiiNonDiscoverableDeviceProtocolGuid > > + gEfiDevicePathProtocolGuid ## TO_START > > + gEfiPciIoProtocolGuid ## TO_START > > + gEfiSdMmcPassThruProtocolGuid ## BY_START > > + gPlatformDwMmcProtocolGuid > > + > > +[UserExtensions.TianoCore."ExtraFiles"] > > + DwMmcHcDxeExtra.uni > > diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.h > > b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.h > > new file mode 100644 > > index 000000000000..b783d9830325 > > --- /dev/null > > +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.h > > @@ -0,0 +1,817 @@ > > +/** @file > > + > > + Provides some data structure definitions used by the Designware SD/M= MC > > + host controller driver. > > + > > + Copyright (c) 2015, Intel Corporation. All rights reserved.
> > + Copyright (C) 2018, Linaro Ltd. All rigths reserved.
> > + > > + This program and the accompanying materials are licensed and made > > available > > + under the terms and conditions of the BSD License which accompanies = this > > + distribution. The full text of the license may be found at > > + http://opensource.org/licenses/bsd-license.php > > + > > + 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 _DW_MMC_HC_DXE_H_ > > +#define _DW_MMC_HC_DXE_H_ > > + > > +#include > > + > > +#include > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "DwMmcHci.h" > > + > > +extern EFI_COMPONENT_NAME_PROTOCOL > > gDwMmcHcComponentName; > > +extern EFI_COMPONENT_NAME2_PROTOCOL > > gDwMmcHcComponentName2; > > +extern EFI_DRIVER_BINDING_PROTOCOL gDwMmcHcDriverBinding; > > + > > +#define DW_MMC_HC_PRIVATE_SIGNATURE SIGNATURE_32 ('d', 'w', 's', > > 'd') > > + > > +#define DW_MMC_HC_PRIVATE_FROM_THIS(a) \ > > + CR(a, DW_MMC_HC_PRIVATE_DATA, PassThru, > > DW_MMC_HC_PRIVATE_SIGNATURE) > > + > > +// > > +// Generic time out value, 1 microsecond as unit. > > +// > > +#define DW_MMC_HC_GENERIC_TIMEOUT (1 * 1000 * 1000) > > + > > +// > > +// SD/MMC async transfer timer interval, set by experience. > > +// The unit is 100us, takes 1ms as interval. > > +// > > +#define DW_MMC_HC_ASYNC_TIMER > > EFI_TIMER_PERIOD_MILLISECONDS(1) > > +// > > +// SD/MMC removable device enumeration timer interval, set by > > experience. > > +// The unit is 100us, takes 100ms as interval. > > +// > > +#define DW_MMC_HC_ENUM_TIMER > > EFI_TIMER_PERIOD_MILLISECONDS(100) > > + > > +typedef struct { > > + BOOLEAN Enable; > > + EFI_SD_MMC_SLOT_TYPE SlotType; > > + BOOLEAN MediaPresent; > > + BOOLEAN Initialized; > > + SD_MMC_CARD_TYPE CardType; > > +} DW_MMC_HC_SLOT; > > + > > +typedef struct { > > + UINTN Signature; > > + > > + EFI_HANDLE ControllerHandle; > > + > > + // Mmio base address > > + UINTN DevBase; > > + > > + EFI_SD_MMC_PASS_THRU_PROTOCOL PassThru; > > + > > + PLATFORM_DW_MMC_PROTOCOL *PlatformDwMmc; > > + // > > + // The field is used to record the previous slot in GetNextSlot(). > > + // > > + UINT8 PreviousSlot; > > + // > > + // For Non-blocking operation. > > + // > > + EFI_EVENT TimerEvent; > > + // > > + // For Sd removable device enumeration. > > + // > > + EFI_EVENT ConnectEvent; > > + LIST_ENTRY Queue; > > + > > + DW_MMC_HC_SLOT Slot[DW_MMC_HC_MAX_SLOT]; > > + DW_MMC_HC_SLOT_CAP Capability[DW_MMC_HC_MAX_SLOT]; > > + UINT64 MaxCurrent[DW_MMC_HC_MAX_SLOT]; > > + > > + UINT32 ControllerVersion; > > +} DW_MMC_HC_PRIVATE_DATA; > > + > > +#define DW_MMC_HC_TRB_SIG SIGNATURE_32 ('D', 'T', 'R', 'B'= ) > > + > > +// > > +// TRB (Transfer Request Block) contains information for the cmd reque= st. > > +// > > +typedef struct { > > + UINT32 Signature; > > + LIST_ENTRY TrbList; > > + > > + UINT8 Slot; > > + UINT16 BlockSize; > > + > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; > > + VOID *Data; > > + UINT32 DataLen; > > + BOOLEAN Read; > > + EFI_PHYSICAL_ADDRESS DataPhy; > > + VOID *DataMap; > > + DW_MMC_HC_TRANSFER_MODE Mode; > > + > > + EFI_EVENT Event; > > + BOOLEAN Started; > > + UINT64 Timeout; > > + > > + DW_MMC_HC_DMA_DESC_LINE *DmaDesc; > > + EFI_PHYSICAL_ADDRESS DmaDescPhy; > > + UINT32 DmaDescPages; > > + VOID *DmaMap; > > + > > + BOOLEAN UseFifo; > > + BOOLEAN UseBE; // Big-e= ndian > > + > > + DW_MMC_HC_PRIVATE_DATA *Private; > > +} DW_MMC_HC_TRB; > > + > > +#define DW_MMC_HC_TRB_FROM_THIS(a) \ > > + CR(a, DW_MMC_HC_TRB, TrbList, DW_MMC_HC_TRB_SIG) > > + > > +// > > +// Task for Non-blocking mode. > > +// > > +typedef struct { > > + UINT32 Signature; > > + LIST_ENTRY Link; > > + > > + UINT8 Slot; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; > > + BOOLEAN IsStart; > > + EFI_EVENT Event; > > + UINT64 RetryTimes; > > + BOOLEAN InfiniteWait; > > + VOID *Map; > > + VOID *MapAddress; > > +} DW_MMC_HC_QUEUE; > > + > > +// > > +// Prototypes > > +// > > +/** > > + Execute card identification procedure. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + > > + @retval EFI_SUCCESS The card is identified correctly. > > + @retval Others The card can't be identified. > > + > > +**/ > > +typedef > > +EFI_STATUS > > +(*DWMMC_CARD_TYPE_DETECT_ROUTINE) ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private > > + ); > > + > > +/** > > + Sends SD command to an SD card that is attached to the SD controller= . > > + > > + The PassThru() function sends the SD command specified by Packet to = the > > SD > > + card specified by Slot. > > + > > + If Packet is successfully sent to the SD card, then EFI_SUCCESS is r= eturned. > > + > > + If a device error occurs while sending the Packet, then EFI_DEVICE_E= RROR > > is > > + returned. > > + > > + If Slot is not in a valid range for the SD controller, then > > + EFI_INVALID_PARAMETER is returned. > > + > > + If Packet defines a data command but both InDataBuffer and > > OutDataBuffer are > > + NULL, EFI_INVALID_PARAMETER is returned. > > + > > + @param[in] This A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Slot The slot number of the SD card to send= the > > + command to. > > + @param[in,out] Packet A pointer to the SD command data struc= ture. > > + @param[in] Event If Event is NULL, blocking I/O is perf= ormed. If > > + Event is not NULL, then nonblocking I/= O is > > + performed, and Event will be signaled = when the > > + Packet completes. > > + > > + @retval EFI_SUCCESS The SD Command Packet was sent by the = host. > > + @retval EFI_DEVICE_ERROR A device error occurred while attempti= ng to > > send > > + the SD command Packet. > > + @retval EFI_INVALID_PARAMETER Packet, Slot, or the contents of the > > Packet is > > + invalid. > > + @retval EFI_INVALID_PARAMETER Packet defines a data command but > > both > > + InDataBuffer and OutDataBuffer are NUL= L. > > + @retval EFI_NO_MEDIA SD Device not present in the Slot. > > + @retval EFI_UNSUPPORTED The command described by the SD > > Command Packet > > + is not supported by the host controlle= r. > > + @retval EFI_BAD_BUFFER_SIZE The InTransferLength or > > OutTransferLength > > + exceeds the limit supported by SD card= ( i.e. if > > + the number of bytes exceed the Last LB= A). > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcPassThruPassThru ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, > > + IN UINT8 Slot, > > + IN OUT EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet, > > + IN EFI_EVENT Event OPTIONAL > > + ); > > + > > +/** > > + Used to retrieve next slot numbers supported by the SD controller. T= he > > + function returns information about all available slots (populated or > > + not-populated). > > + > > + The GetNextSlot() function retrieves the next slot number on an SD > > controller. > > + If on input Slot is 0xFF, then the slot number of the first slot on = the SD > > + controller is returned. > > + > > + If Slot is a slot number that was returned on a previous call to > > + GetNextSlot(), then the slot number of the next slot on the SD contr= oller is > > + returned. > > + > > + If Slot is not 0xFF and Slot was not returned on a previous call to > > + GetNextSlot(), EFI_INVALID_PARAMETER is returned. > > + > > + If Slot is the slot number of the last slot on the SD controller, th= en > > + EFI_NOT_FOUND is returned. > > + > > + @param[in] This A pointer to the > > EFI_SD_MMMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in,out] Slot On input, a pointer to a slot number o= n the SD > > + controller. > > + On output, a pointer to the next slot = number on > > + the SD controller. > > + An input value of 0xFF retrieves the f= irst slot > > + number on the SD controller. > > + > > + @retval EFI_SUCCESS The next slot number on the SD control= ler was > > + returned in Slot. > > + @retval EFI_NOT_FOUND There are no more slots on this SD > > controller. > > + @retval EFI_INVALID_PARAMETER Slot is not 0xFF and Slot was not > > returned on a > > + previous call to GetNextSlot(). > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcPassThruGetNextSlot ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, > > + IN OUT UINT8 *Slot > > + ); > > + > > +/** > > + Used to allocate and build a device path node for an SD card on the = SD > > + controller. > > + > > + The BuildDevicePath() function allocates and builds a single device = node > > + for the SD > > + card specified by Slot. > > + > > + If the SD card specified by Slot is not present on the SD controller= , then > > + EFI_NOT_FOUND is returned. > > + > > + If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned. > > + > > + If there are not enough resources to allocate the device path node, = then > > + EFI_OUT_OF_RESOURCES is returned. > > + > > + Otherwise, DevicePath is allocated with the boot service AllocatePoo= l(), > > the > > + contents of DevicePath are initialized to describe the SD card speci= fied by > > + Slot, and EFI_SUCCESS is returned. > > + > > + @param[in] This A pointer to the > > EFI_SD_MMMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Slot Specifies the slot number of the SD ca= rd for > > + which a device path node is to be allo= cated and > > + built. > > + @param[in,out] DevicePath A pointer to a single device path node= that > > + describes the SD card specified by Slo= t. This > > + function is responsible for allocating= the > > + buffer DevicePath with the boot servic= e > > + AllocatePool(). It is the caller's res= ponsibi- > > + lity to free DevicePath when the calle= r is > > + finished with DevicePath. > > + > > + @retval EFI_SUCCESS The device path node that describes th= e SD > > card > > + specified by Slot was allocated and re= turned in > > + DevicePath. > > + @retval EFI_NOT_FOUND The SD card specified by Slot does not= exist > > on > > + the SD controller. > > + @retval EFI_INVALID_PARAMETER DevicePath is NULL. > > + @retval EFI_OUT_OF_RESOURCES There are not enough resources to > > allocate > > + DevicePath. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcPassThruBuildDevicePath ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, > > + IN UINT8 Slot, > > + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath > > + ); > > + > > +/** > > + This function retrieves an SD card slot number based on the input de= vice > > path. > > + > > + The GetSlotNumber() function retrieves slot number for the SD card > > specified > > + by the DevicePath node. If DevicePath is NULL, EFI_INVALID_PARAMETER > > is > > + returned. > > + > > + If DevicePath is not a device path node type that the SD Pass Thru d= river > > + supports, EFI_UNSUPPORTED is returned. > > + > > + @param[in] This A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] DevicePath A pointer to the device path node that > > describes > > + a SD card on the SD controller. > > + @param[out] Slot On return, points to the slot number o= f an SD > > + card on the SD controller. > > + > > + @retval EFI_SUCCESS SD card slot number is returned in Slo= t. > > + @retval EFI_INVALID_PARAMETER Slot or DevicePath is NULL. > > + @retval EFI_UNSUPPORTED DevicePath is not a device path node t= ype > > that > > + the SD Pass Thru driver supports. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcPassThruGetSlotNumber ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, > > + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, > > + OUT UINT8 *Slot > > + ); > > + > > +/** > > + Resets an SD card that is connected to the SD controller. > > + > > + The ResetDevice() function resets the SD card specified by Slot. > > + > > + If this SD controller does not support a device reset operation, > > + EFI_UNSUPPORTED is returned. > > + > > + If Slot is not in a valid slot number for this SD controller, > > + EFI_INVALID_PARAMETER is returned. > > + > > + If the device reset operation is completed, EFI_SUCCESS is returned. > > + > > + @param[in] This A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Slot Specifies the slot number of the SD ca= rd to be > > + reset. > > + > > + @retval EFI_SUCCESS The SD card specified by Slot was rese= t. > > + @retval EFI_UNSUPPORTED The SD controller does not support a > > device > > + reset operation. > > + @retval EFI_INVALID_PARAMETER Slot number is invalid. > > + @retval EFI_NO_MEDIA SD Device not present in the Slot. > > + @retval EFI_DEVICE_ERROR The reset command failed due to a devi= ce > > error > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcPassThruResetDevice ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, > > + IN UINT8 Slot > > + ); > > + > > +// > > +// Driver model protocol interfaces > > +// > > +/** > > + Tests to see if this driver supports a given controller. If a child = device is > > + provided, it further tests to see if this driver supports creating a= handle > > + for the specified child device. > > + > > + This function checks to see if the driver specified by This supports= the > > + device specified by ControllerHandle. Drivers will typically use the= device > > + path attached to ControllerHandle and/or the services from the bus I= /O > > + abstraction attached to ControllerHandle to determine if the driver > > supports > > + ControllerHandle. This function may be called many times during plat= form > > + initialization. In order to reduce boot times, the tests performed b= y this > > + function must be very small, and take as little time as possible to = execute. > > + This function must not change the state of any hardware devices, and= this > > + function must be aware that the device specified by ControllerHandle= may > > + already be managed by the same driver or a different driver. This fu= nction > > + must match its calls to AllocatePages() with FreePages(), AllocatePo= ol() > > with > > + FreePool(), and OpenProtocol() with CloseProtocol(). > > + Since ControllerHandle may have been previously started by the same > > driver, if > > + a protocol is already in the opened state, then it must not be close= d with > > + CloseProtocol(). This is required to guarantee the state of Controll= erHandle > > + is not modified by this function. > > + > > + @param[in] This A pointer to the > > EFI_DRIVER_BINDING_PROTOCOL > > + instance. > > + @param[in] ControllerHandle The handle of the controller to tes= t. This > > + handle must support a protocol inte= rface that > > + supplies an I/O abstraction to the = driver. > > + @param[in] RemainingDevicePath A pointer to the remaining portion = of a > > + device path. This parameter is ign= ored by > > + device drivers, and is optional for= bus > > + drivers. For bus drivers, if this p= arameter > > + is not NULL, then the bus driver mu= st deter- > > + mine if the bus controller specifie= d by > > + ControllerHandle and the child cont= roller > > + specified by RemainingDevicePath ar= e both > > + supported by this bus driver. > > + > > + @retval EFI_SUCCESS The device specified by ControllerH= andle and > > + RemainingDevicePath is supported by= the > > + driver specified by This. > > + @retval EFI_ALREADY_STARTED The device specified by > > ControllerHandle and > > + RemainingDevicePath is already bein= g managed > > + by the driver specified by This. > > + @retval EFI_ACCESS_DENIED The device specified by ControllerH= andle > > and > > + RemainingDevicePath is already bein= g managed > > + by a different driver or an applica= tion that > > + requires exclusive access. > > + Currently not implemented. > > + @retval EFI_UNSUPPORTED The device specified by ControllerH= andle > > and > > + RemainingDevicePath is not supporte= d by the > > + driver specified by This. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcDriverBindingSupported ( > > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > > + IN EFI_HANDLE Controller, > > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > > + ); > > + > > +/** > > + Starts a device controller or a bus controller. > > + > > + The Start() function is designed to be invoked from the EFI boot ser= vice > > + ConnectController(). > > + As a result, much of the error checking on the parameters to Start()= has > > been > > + moved into this common boot service. It is legal to call Start() fro= m other > > + locations, > > + but the following calling restrictions must be followed or the syste= m > > behavior > > + will not be deterministic. > > + 1. ControllerHandle must be a valid EFI_HANDLE. > > + 2. If RemainingDevicePath is not NULL, then it must be a pointer to = a > > natural- > > + ly aligned EFI_DEVICE_PATH_PROTOCOL. > > + 3. Prior to calling Start(), the Supported() function for the driver= specified > > + by This must have been called with the same calling parameters, a= nd > > + Supported() must have returned EFI_SUCCESS. > > + > > + @param[in] This A pointer to the > > EFI_DRIVER_BINDING_PROTOCOL > > + instance. > > + @param[in] ControllerHandle The handle of the controller to sta= rt. This > > + handle must support a protocol inte= rface that > > + supplies an I/O abstraction to the = driver. > > + @param[in] RemainingDevicePath A pointer to the remaining portion = of a > > + device path. This parameter is ign= ored by > > + device drivers, and is optional for= bus dri- > > + vers. For a bus driver, if this par= ameter is > > + NULL, then handles for all the chil= dren of > > + Controller are created by this driv= er. > > + If this parameter is not NULL and t= he first > > + Device Path Node is not the End of = Device > > + Path Node, then only the handle for= the > > + child device specified by the first= Device > > + Path Node of RemainingDevicePath is= created > > + by this driver. > > + If the first Device Path Node of > > + RemainingDevicePath is the End of D= evice Path > > + Node, no child handle is created by= this > > + driver. > > + > > + @retval EFI_SUCCESS The device was started. > > + @retval EFI_DEVICE_ERROR The device could not be started due= to a > > + device error. Currently not impleme= nted. > > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > > due to a > > + lack of resources. > > + @retval Others The driver failded to start the dev= ice. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcDriverBindingStart ( > > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > > + IN EFI_HANDLE Controller, > > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > > + ); > > + > > +/** > > + Stops a device controller or a bus controller. > > + > > + The Stop() function is designed to be invoked from the EFI boot serv= ice > > + DisconnectController(). > > + As a result, much of the error checking on the parameters to Stop() = has > > been > > + moved into this common boot service. It is legal to call Stop() from= other > > + locations, but the following calling restrictions must be followed o= r the > > + system behavior will not be deterministic. > > + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a > > previous > > + call to this same driver's Start() function. > > + 2. The first NumberOfChildren handles of ChildHandleBuffer must all = be a > > valid > > + EFI_HANDLE. In addition, all of these handles must have been crea= ted in > > + this driver's Start() function, and the Start() function must hav= e called > > + OpenProtocol() on ControllerHandle with an Attribute of > > + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. > > + > > + @param[in] This A pointer to the EFI_DRIVER_BINDING_PR= OTOCOL > > + instance. > > + @param[in] ControllerHandle A handle to the device being stopped. = The > > handle > > + must support a bus specific I/O protoc= ol for the > > + driver to use to stop the device. > > + @param[in] NumberOfChildren The number of child device handles in > > + ChildHandleBuffer. > > + @param[in] ChildHandleBuffer An array of child handles to be freed.= May > > be > > + NULL if NumberOfChildren is 0. > > + > > + @retval EFI_SUCCESS The device was stopped. > > + @retval EFI_DEVICE_ERROR The device could not be stopped due to= a > > device > > + error. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcDriverBindingStop ( > > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > > + IN EFI_HANDLE Controller, > > + IN UINTN NumberOfChildren, > > + IN EFI_HANDLE *ChildHandleBuffer > > + ); > > + > > +// > > +// EFI Component Name Functions > > +// > > +/** > > + Retrieves a Unicode string that is the user readable name of the dri= ver. > > + > > + This function retrieves the user readable name of a driver in the fo= rm of a > > + Unicode string. If the driver specified by This has a user readable = name in > > + the language specified by Language, then a pointer to the driver nam= e is > > + returned in DriverName, and EFI_SUCCESS is returned. If the driver > > specified > > + by This does not support the language specified by Language, > > + then EFI_UNSUPPORTED is returned. > > + > > + @param This[in] A pointer to the > > EFI_COMPONENT_NAME2_PROTOCOL or > > + EFI_COMPONENT_NAME_PROTOCOL instance. > > + > > + @param Language[in] A pointer to a Null-terminated ASCII s= tring > > + array indicating the language. This is= the > > + language of the driver name that the c= aller is > > + requesting, and it must match one of t= he > > + languages specified in SupportedLangua= ges. The > > + number of languages supported by a dri= ver is up > > + to the driver writer. Language is spec= ified > > + in RFC 4646 or ISO 639-2 language code= format. > > + > > + @param DriverName[out] A pointer to the Unicode string to ret= urn. > > + This Unicode string is the name of the > > + driver specified by This in the langua= ge > > + specified by Language. > > + > > + @retval EFI_SUCCESS The Unicode string for the Driver spec= ified by > > + This and the language specified by Lan= guage was > > + returned in DriverName. > > + > > + @retval EFI_INVALID_PARAMETER Language is NULL. > > + > > + @retval EFI_INVALID_PARAMETER DriverName is NULL. > > + > > + @retval EFI_UNSUPPORTED The driver specified by This does not > > support > > + the language specified by Language. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcComponentNameGetDriverName ( > > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > > + IN CHAR8 *Language, > > + OUT CHAR16 **DriverName > > + ); > > + > > +/** > > + Retrieves a Unicode string that is the user readable name of the con= troller > > + that is being managed by a driver. > > + > > + This function retrieves the user readable name of the controller spe= cified > > by > > + ControllerHandle and ChildHandle in the form of a Unicode string. If= the > > + driver specified by This has a user readable name in the language sp= ecified > > by > > + Language, then a pointer to the controller name is returned in > > ControllerName, > > + and EFI_SUCCESS is returned. If the driver specified by This is not= currently > > + managing the controller specified by ControllerHandle and ChildHandl= e, > > + then EFI_UNSUPPORTED is returned. If the driver specified by This d= oes > > not > > + support the language specified by Language, then EFI_UNSUPPORTED is > > returned. > > + > > + @param This[in] A pointer to the > > EFI_COMPONENT_NAME2_PROTOCOL or > > + EFI_COMPONENT_NAME_PROTOCOL instance. > > + > > + @param ControllerHandle[in] The handle of a controller that the dr= iver > > + specified by This is managing. This h= andle > > + specifies the controller whose name is= to be > > + returned. > > + > > + @param ChildHandle[in] The handle of the child controller to = retrieve > > + the name of. This is an optional para= meter that > > + may be NULL. It will be NULL for devi= ce > > + drivers. It will also be NULL for a b= us drivers > > + that wish to retrieve the name of the = bus > > + controller. It will not be NULL for a= bus > > + driver that wishes to retrieve the nam= e of a > > + child controller. > > + > > + @param Language[in] A pointer to a Null-terminated ASCII s= tring > > + array indicating the language. This i= s the > > + language of the driver name that the c= aller is > > + requesting, and it must match one of t= he > > + languages specified in SupportedLangua= ges. The > > + number of languages supported by a dri= ver is up > > + to the driver writer. Language is spec= ified in > > + RFC 4646 or ISO 639-2 language code fo= rmat. > > + > > + @param ControllerName[out] A pointer to the Unicode string to ret= urn. > > + This Unicode string is the name of the > > + controller specified by ControllerHand= le and > > + ChildHandle in the language specified = by > > + Language from the point of view of the= driver > > + specified by This. > > + > > + @retval EFI_SUCCESS The Unicode string for the user readab= le name > > in > > + the language specified by Language for= the > > + driver specified by This was returned = in > > + DriverName. > > + > > + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid > > EFI_HANDLE. > > + > > + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not = a > > valid > > + EFI_HANDLE. > > + > > + @retval EFI_INVALID_PARAMETER Language is NULL. > > + > > + @retval EFI_INVALID_PARAMETER ControllerName is NULL. > > + > > + @retval EFI_UNSUPPORTED The driver specified by This is not cu= rrently > > + managing the controller specified by > > + ControllerHandle and ChildHandle. > > + > > + @retval EFI_UNSUPPORTED The driver specified by This does not > > support > > + the language specified by Language. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcComponentNameGetControllerName ( > > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > > + IN EFI_HANDLE ControllerHandle, > > + IN EFI_HANDLE ChildHandle, OPTIONAL > > + IN CHAR8 *Language, > > + OUT CHAR16 **ControllerName > > + ); > > + > > +/** > > + Create a new TRB for the SD/MMC cmd request. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + @param[in] Slot The slot number of the SD card to send the > > command > > + to. > > + @param[in] Packet A pointer to the SD command data structure= . > > + @param[in] Event If Event is NULL, blocking I/O is performe= d. > > + If Event is not NULL, then nonblocking I/O= is > > + performed, and Event will be signaled when= the > > + Packet completes. > > + > > + @return Created Trb or NULL. > > + > > +**/ > > +DW_MMC_HC_TRB * > > +DwMmcCreateTrb ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN UINT8 Slot, > > + IN EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet, > > + IN EFI_EVENT Event > > + ); > > + > > +/** > > + Free the resource used by the TRB. > > + > > + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance. > > + > > +**/ > > +VOID > > +DwMmcFreeTrb ( > > + IN DW_MMC_HC_TRB *Trb > > + ); > > + > > +/** > > + Check if the env is ready for execute specified TRB. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance. > > + > > + @retval EFI_SUCCESS The env is ready for TRB execution. > > + @retval EFI_NOT_READY The env is not ready for TRB execution. > > + @retval Others Some erros happen. > > + > > +**/ > > +EFI_STATUS > > +DwMmcCheckTrbEnv ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ); > > + > > +/** > > + Wait for the env to be ready for execute specified TRB. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance. > > + > > + @retval EFI_SUCCESS The env is ready for TRB execution. > > + @retval EFI_TIMEOUT The env is not ready for TRB execution in = time. > > + @retval Others Some erros happen. > > + > > +**/ > > +EFI_STATUS > > +DwMmcWaitTrbEnv ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ); > > + > > +/** > > + Execute the specified TRB. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance. > > + > > + @retval EFI_SUCCESS The TRB is sent to host controller success= fully. > > + @retval Others Some erros happen when sending this reques= t to the > > + host controller. > > + > > +**/ > > +EFI_STATUS > > +DwMmcExecTrb ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ); > > + > > +/** > > + Check the TRB execution result. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance. > > + > > + @retval EFI_SUCCESS The TRB is executed successfully. > > + @retval EFI_NOT_READY The TRB is not completed for execution. > > + @retval Others Some erros happen when executing this requ= est. > > + > > +**/ > > +EFI_STATUS > > +DwMmcCheckTrbResult ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ); > > + > > +/** > > + Wait for the TRB execution result. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance. > > + > > + @retval EFI_SUCCESS The TRB is executed successfully. > > + @retval Others Some erros happen when executing this requ= est. > > + > > +**/ > > +EFI_STATUS > > +DwMmcWaitTrbResult ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ); > > + > > +/** > > + Execute EMMC device identification procedure. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + > > + @retval EFI_SUCCESS There is a EMMC card. > > + @retval Others There is not a EMMC card. > > + > > +**/ > > +EFI_STATUS > > +EmmcIdentification ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private > > + ); > > + > > +/** > > + Execute EMMC device identification procedure. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + > > + @retval EFI_SUCCESS There is a EMMC card. > > + @retval Others There is not a EMMC card. > > + > > +**/ > > +EFI_STATUS > > +SdCardIdentification ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private > > + ); > > + > > +#endif /* _DW_MMC_HC_DXE_H_ */ > > diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.h > > b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.h > > new file mode 100644 > > index 000000000000..12ef58a37368 > > --- /dev/null > > +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.h > > @@ -0,0 +1,985 @@ > > +/** @file > > + > > + Provides some data structure definitions used by the SD/MMC host > > controller > > + driver. > > + > > + Copyright (c) 2015, Intel Corporation. All rights reserved.
> > + Copyright (c) 2018, Linaro Ltd. All rights reserved.
> > + > > + This program and the accompanying materials are licensed and made > > available > > + under the terms and conditions of the BSD License which accompanies = this > > + distribution. The full text of the license may be found at > > + http://opensource.org/licenses/bsd-license.php > > + > > + 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 _DW_MMC_HCI_H_ > > +#define _DW_MMC_HCI_H_ > > + > > +#include > > +#include > > + > > +#include > > + > > +// > > +// SD Host Controller SlotInfo Register Offset > > +// > > +#define DW_MMC_HC_SLOT_OFFSET 0x40 > > + > > +#define DW_MMC_HC_MAX_SLOT 1 > > + > > +// > > +// SD Host Controller MMIO Register Offset > > +// > > +#define DW_MMC_CTRL 0x000 > > +#define DW_MMC_PWREN 0x004 > > +#define DW_MMC_CLKDIV 0x008 > > +#define DW_MMC_CLKSRC 0x00c > > +#define DW_MMC_CLKENA 0x010 > > +#define DW_MMC_TMOUT 0x014 > > +#define DW_MMC_CTYPE 0x018 > > +#define DW_MMC_BLKSIZ 0x01c > > +#define DW_MMC_BYTCNT 0x020 > > +#define DW_MMC_INTMASK 0x024 > > +#define DW_MMC_CMDARG 0x028 > > +#define DW_MMC_CMD 0x02c > > +#define DW_MMC_RESP0 0x030 > > +#define DW_MMC_RESP1 0x034 > > +#define DW_MMC_RESP2 0x038 > > +#define DW_MMC_RESP3 0x03c > > +#define DW_MMC_RINTSTS 0x044 > > +#define DW_MMC_STATUS 0x048 > > +#define DW_MMC_FIFOTH 0x04c > > +#define DW_MMC_GPIO 0x058 > > +#define DW_MMC_DEBNCE 0x064 > > +#define DW_MMC_USRID 0x068 > > +#define DW_MMC_VERID 0x06c > > +#define DW_MMC_HCON 0x070 > > +#define DW_MMC_UHSREG 0x074 > > +#define DW_MMC_BMOD 0x080 > > +#define DW_MMC_DBADDR 0x088 > > +#define DW_MMC_IDSTS 0x08c > > +#define DW_MMC_IDINTEN 0x090 > > +#define DW_MMC_DSCADDR 0x094 > > +#define DW_MMC_BUFADDR 0x098 > > +#define DW_MMC_CARDTHRCTL 0x100 > > +#define DW_MMC_UHSREG_EXT 0x108 > > +#define DW_MMC_ENABLE_SHIFT 0x110 > > +#define DW_MMC_FIFO_START 0x200 > > + > > +#define GET_IDSTS_DMAC_FSM(x) (((x) >> 13) & 0xf) > > +#define IDSTS_FSM_DMA_IDLE 0 > > +#define IDSTS_FSM_DMA_SUSPEND 1 > > +#define IDSTS_FSM_DESC_RD 2 > > +#define IDSTS_FSM_DESC_CHK 3 > > +#define IDSTS_FSM_DMA_RD_REQ_WAIT 4 > > +#define IDSTS_FSM_DMA_WR_REQ_WAIT 5 > > +#define IDSTS_FSM_DMA_RD 6 > > +#define IDSTS_FSM_DMA_WR 7 > > +#define IDSTS_FSM_DESC_CLOSE 8 > > +#define IDSTS_FSM_MASK 0xf > > + > > +#define CMD_UPDATE_CLK 0x80202000 > > +#define CMD_START_BIT (1 << 31) > > + > > +#define MMC_8BIT_MODE (1 << 16) > > +#define MMC_4BIT_MODE (1 << 0) > > +#define MMC_1BIT_MODE 0 > > + > > +#define DW_MMC_BLOCK_SIZE 512 > > + > > +#define CMD_INDEX_MASK 0x3F > > +#define BIT_CMD_RESPONSE_EXPECT (1 << 6) > > +#define BIT_CMD_LONG_RESPONSE (1 << 7) > > +#define BIT_CMD_CHECK_RESPONSE_CRC (1 << 8) > > +#define BIT_CMD_DATA_EXPECTED (1 << 9) > > +#define BIT_CMD_READ (0 << 10) > > +#define BIT_CMD_WRITE (1 << 10) > > +#define BIT_CMD_BLOCK_TRANSFER (0 << 11) > > +#define BIT_CMD_STREAM_TRANSFER (1 << 11) > > +#define BIT_CMD_SEND_AUTO_STOP (1 << 12) > > +#define BIT_CMD_WAIT_PRVDATA_COMPLETE (1 << 13) > > +#define BIT_CMD_STOP_ABORT_CMD (1 << 14) > > +#define BIT_CMD_SEND_INIT (1 << 15) > > +#define BIT_CMD_UPDATE_CLOCK_ONLY (1 << 21) > > +#define BIT_CMD_READ_CEATA_DEVICE (1 << 22) > > +#define BIT_CMD_CCS_EXPECTED (1 << 23) > > +#define BIT_CMD_ENABLE_BOOT (1 << 24) > > +#define BIT_CMD_EXPECT_BOOT_ACK (1 << 25) > > +#define BIT_CMD_DISABLE_BOOT (1 << 26) > > +#define BIT_CMD_MANDATORY_BOOT (0 << 27) > > +#define BIT_CMD_ALTERNATE_BOOT (1 << 27) > > +#define BIT_CMD_VOLT_SWITCH (1 << 28) > > +#define BIT_CMD_USE_HOLD_REG (1 << 29) > > +#define BIT_CMD_START (1 << 31) > > + > > +#define CMD_INDEX(x) ((x) & CMD_INDEX_MASK) > > + > > +#define DW_MMC_INT_EBE (1 << 15) /* End= -bit Err */ > > +#define DW_MMC_INT_SBE (1 << 13) /* Sta= rt-bit Err */ > > +#define DW_MMC_INT_HLE (1 << 12) /* Har= dware-lock Err > > */ > > +#define DW_MMC_INT_FRUN (1 << 11) /* FIF= O UN/OV RUN > > */ > > +#define DW_MMC_INT_DRT (1 << 9) /* Dat= a timeout */ > > +#define DW_MMC_INT_RTO (1 << 8) /* Res= ponse timeout > > */ > > +#define DW_MMC_INT_DCRC (1 << 7) /* Dat= a CRC err */ > > +#define DW_MMC_INT_RCRC (1 << 6) /* Res= ponse CRC err > > */ > > +#define DW_MMC_INT_RXDR (1 << 5) /* Rec= eive FIFO data > > request */ > > +#define DW_MMC_INT_TXDR (1 << 4) /* Tra= nsmit FIFO data > > request */ > > +#define DW_MMC_INT_DTO (1 << 3) /* Dat= a trans over */ > > +#define DW_MMC_INT_CMD_DONE (1 << 2) /* Com= mand > > done */ > > +#define DW_MMC_INT_RE (1 << 1) /* Res= ponse error */ > > + > > +#define DW_MMC_IDMAC_DES0_DIC (1 << 1) > > +#define DW_MMC_IDMAC_DES0_LD (1 << 2) > > +#define DW_MMC_IDMAC_DES0_FS (1 << 3) > > +#define DW_MMC_IDMAC_DES0_CH (1 << 4) > > +#define DW_MMC_IDMAC_DES0_ER (1 << 5) > > +#define DW_MMC_IDMAC_DES0_CES (1 << 30) > > +#define DW_MMC_IDMAC_DES0_OWN (1 << 31) > > +#define DW_MMC_IDMAC_DES1_BS1(x) ((x) & 0x1fff) > > +#define DW_MMC_IDMAC_DES2_BS2(x) (((x) & 0x1fff) << 13) > > +#define DW_MMC_IDMAC_SWRESET (1 << 0) > > +#define DW_MMC_IDMAC_FB (1 << 1) > > +#define DW_MMC_IDMAC_ENABLE (1 << 7) > > + > > +#define DW_MMC_CTRL_RESET (1 << 0) > > +#define DW_MMC_CTRL_FIFO_RESET (1 << 1) > > +#define DW_MMC_CTRL_DMA_RESET (1 << 2) > > +#define DW_MMC_CTRL_INT_EN (1 << 4) > > +#define DW_MMC_CTRL_DMA_EN (1 << 5) > > +#define DW_MMC_CTRL_IDMAC_EN (1 << 25) > > +#define DW_MMC_CTRL_RESET_ALL (DW_MMC_CTRL_RESET | > > DW_MMC_CTRL_FIFO_RESET | DW_MMC_CTRL_DMA_RESET) > > + > > +#define DW_MMC_STS_DATA_BUSY (1 << 9) > > +#define DW_MMC_STS_FIFO_COUNT(x) (((x) & 0x1fff) << 17)= /* > > Number of filled locations in FIFO */ > > +#define GET_STS_FIFO_COUNT(x) (((x) >> 17) & 0x1fff) > > +#define DW_MMC_STS_FIFO_FULL(x) (((x) >> 3) & 1) > > + > > +#define DW_MMC_BMOD_SWR (1 << 0) /* So= ftware Reset > > */ > > +#define DW_MMC_BMOD_FB (1 << 1) /* Fi= x Burst */ > > +#define DW_MMC_BMOD_DE (1 << 7) /* ID= MAC Enable */ > > + > > +#define DW_MMC_IDSTS_TI (1 << 0) /* Tr= ansmit Interrupt > > */ > > +#define DW_MMC_IDSTS_RI (1 << 1) /* Re= ceive Interrupt > > */ > > + > > +#define DW_MMC_FIFO_TWMARK(x) ((x) & 0xfff) > > +#define DW_MMC_FIFO_RWMARK(x) (((x) & 0x1ff) << 16) > > +#define DW_MMC_DMA_BURST_SIZE(x) (((x) & 0x7) << 28) > > + > > +#define DW_MMC_CARD_RD_THR(x) (((x) & 0xfff) << 16) > > +#define DW_MMC_CARD_RD_THR_EN (1 << 0) > > + > > +#define UHS_DDR_MODE (1 << 16) > > + > > +#define GENCLK_DIV 7 > > + > > +#define DW_MMC_GPIO_CLK_DIV(x) (((x) & 0xf) << 8) > > +#define DW_MMC_GPIO_USE_SAMPLE_DLY(x) (((x) & 1) << 13) > > +#define DW_MMC_GPIO_CLK_ENABLE BIT16 > > + > > +#define UHSEXT_SAMPLE_PHASE(x) (((x) & 0x1f) << 16) > > +#define UHSEXT_SAMPLE_DRVPHASE(x) (((x) & 0x1f) << 21) > > +#define UHSEXT_SAMPLE_DLY(x) (((x) & 0x1f) << 26) > > + > > +#define DWMMC_DMA_BUF_SIZE (512 * 8) > > +#define DWMMC_FIFO_THRESHOLD 16 > > + > > +#define DWMMC_INIT_CLOCK_FREQ 400 /* KH= z */ > > + > > +// > > +// The transfer modes supported by SD Host Controller > > +// Simplified Spec 3.0 Table 1-2 > > +// > > +typedef enum { > > + SdMmcNoData, > > + SdMmcPioMode, > > + SdMmcSdmaMode, > > + SdMmcAdmaMode > > +} DW_MMC_HC_TRANSFER_MODE; > > + > > +// > > +// The maximum data length of each descriptor line > > +// > > +#define ADMA_MAX_DATA_PER_LINE 0x10000 > > + > > +typedef struct { > > + UINT32 Des0; > > + UINT32 Des1; > > + UINT32 Des2; > > + UINT32 Des3; > > +} DW_MMC_HC_DMA_DESC_LINE; > > + > > +#define SD_MMC_SDMA_BOUNDARY 512 * 1024 > > +#define SD_MMC_SDMA_ROUND_UP(x, n) (((x) + n) & ~(n - 1)) > > + > > +typedef struct { > > + UINT8 FirstBar:3; // bit 0:2 > > + UINT8 Reserved:1; // bit 3 > > + UINT8 SlotNum:3; // bit 4:6 > > + UINT8 Reserved1:1; // bit 7 > > +} DW_MMC_HC_SLOT_INFO; > > + > > +/** > > + Dump the content of SD/MMC host controller's Capability Register. > > + > > + @param[in] Slot The slot number of the SD card to send t= he > > command to. > > + @param[in] Capability The buffer to store the capability data. > > + > > +**/ > > +VOID > > +DumpCapabilityReg ( > > + IN UINT8 Slot, > > + IN DW_MMC_HC_SLOT_CAP *Capability > > + ); > > + > > +#if 0 > > +/** > > + Read SlotInfo register from SD/MMC host controller pci config space. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[out] FirstBar The buffer to store the first BAR value. > > + @param[out] SlotNum The buffer to store the supported slot numb= er. > > + > > + @retval EFI_SUCCESS The operation succeeds. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcGetSlotInfo ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + OUT UINT8 *FirstBar, > > + OUT UINT8 *SlotNum > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Read/Write specified SD/MMC host controller mmio register. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] BarIndex The BAR index of the standard PCI Confi= guration > > + header to use as the base address for t= he memory > > + operation to perform. > > + @param[in] Offset The offset within the selected BAR to s= tart the > > + memory operation. > > + @param[in] Read A boolean to indicate it's read or writ= e operation. > > + @param[in] Count The width of the mmio register in bytes= . > > + Must be 1, 2 , 4 or 8 bytes. > > + @param[in, out] Data For read operations, the destination bu= ffer to > > store > > + the results. For write operations, the = source buffer > > + to write data from. The caller is respo= nsible for > > + having ownership of the data buffer and= ensuring its > > + size not less than Count bytes. > > + > > + @retval EFI_INVALID_PARAMETER The PciIo or Data is NULL or the Count= is > > not valid. > > + @retval EFI_SUCCESS The read/write operation succeeds. > > + @retval Others The read/write operation fails. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcRwMmio ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 BarIndex, > > + IN UINT32 Offset, > > + IN BOOLEAN Read, > > + IN UINT8 Count, > > + IN OUT VOID *Data > > + ); > > +#else > > +/** > > + Read/Write specified SD/MMC host controller mmio register. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Offset The offset within the selected BAR to s= tart the > > + memory operation. > > + @param[in] Read A boolean to indicate it's read or writ= e operation. > > + @param[in] Count The width of the mmio register in bytes= . > > + Must be 1, 2 , 4 or 8 bytes. > > + @param[in, out] Data For read operations, the destination bu= ffer to > > store > > + the results. For write operations, the = source buffer > > + to write data from. The caller is respo= nsible for > > + having ownership of the data buffer and= ensuring its > > + size not less than Count bytes. > > + > > + @retval EFI_INVALID_PARAMETER The PciIo or Data is NULL or the Count= is > > not valid. > > + @retval EFI_SUCCESS The read/write operation succeeds. > > + @retval Others The read/write operation fails. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcRwMmio ( > > + IN UINTN DevBase, > > + IN UINT32 Offset, > > + IN BOOLEAN Read, > > + IN UINT8 Count, > > + IN OUT VOID *Data > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Do OR operation with the value of the specified SD/MMC host controll= er > > mmio register. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] BarIndex The BAR index of the standard PCI Confi= guration > > + header to use as the base address for t= he memory > > + operation to perform. > > + @param[in] Offset The offset within the selected BAR to s= tart the > > + memory operation. > > + @param[in] Count The width of the mmio register in bytes= . > > + Must be 1, 2 , 4 or 8 bytes. > > + @param[in] OrData The pointer to the data used to do OR o= peration. > > + The caller is responsible for having ow= nership of > > + the data buffer and ensuring its size n= ot less than > > + Count bytes. > > + > > + @retval EFI_INVALID_PARAMETER The PciIo or OrData is NULL or the > > Count is not valid. > > + @retval EFI_SUCCESS The OR operation succeeds. > > + @retval Others The OR operation fails. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcOrMmio ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 BarIndex, > > + IN UINT32 Offset, > > + IN UINT8 Count, > > + IN VOID *OrData > > + ); > > +#else > > +/** > > + Do OR operation with the value of the specified SD/MMC host controll= er > > mmio register. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] BarIndex The BAR index of the standard PCI Confi= guration > > + header to use as the base address for t= he memory > > + operation to perform. > > + @param[in] Offset The offset within the selected BAR to s= tart the > > + memory operation. > > + @param[in] Count The width of the mmio register in bytes= . > > + Must be 1, 2 , 4 or 8 bytes. > > + @param[in] OrData The pointer to the data used to do OR o= peration. > > + The caller is responsible for having ow= nership of > > + the data buffer and ensuring its size n= ot less than > > + Count bytes. > > + > > + @retval EFI_INVALID_PARAMETER The PciIo or OrData is NULL or the > > Count is not valid. > > + @retval EFI_SUCCESS The OR operation succeeds. > > + @retval Others The OR operation fails. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcOrMmio ( > > + IN UINTN DevBase, > > + IN UINT32 Offset, > > + IN UINT8 Count, > > + IN VOID *OrData > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Do AND operation with the value of the specified SD/MMC host control= ler > > mmio register. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] BarIndex The BAR index of the standard PCI Confi= guration > > + header to use as the base address for t= he memory > > + operation to perform. > > + @param[in] Offset The offset within the selected BAR to s= tart the > > + memory operation. > > + @param[in] Count The width of the mmio register in bytes= . > > + Must be 1, 2 , 4 or 8 bytes. > > + @param[in] AndData The pointer to the data used to do AND > > operation. > > + The caller is responsible for having ow= nership of > > + the data buffer and ensuring its size n= ot less than > > + Count bytes. > > + > > + @retval EFI_INVALID_PARAMETER The PciIo or AndData is NULL or the > > Count is not valid. > > + @retval EFI_SUCCESS The AND operation succeeds. > > + @retval Others The AND operation fails. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcAndMmio ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 BarIndex, > > + IN UINT32 Offset, > > + IN UINT8 Count, > > + IN VOID *AndData > > + ); > > +#else > > +/** > > + Do AND operation with the value of the specified SD/MMC host control= ler > > mmio register. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Offset The offset within the selected BAR to s= tart the > > + memory operation. > > + @param[in] Count The width of the mmio register in bytes= . > > + Must be 1, 2 , 4 or 8 bytes. > > + @param[in] AndData The pointer to the data used to do AND > > operation. > > + The caller is responsible for having ow= nership of > > + the data buffer and ensuring its size n= ot less than > > + Count bytes. > > + > > + @retval EFI_INVALID_PARAMETER The PciIo or AndData is NULL or the > > Count is not valid. > > + @retval EFI_SUCCESS The AND operation succeeds. > > + @retval Others The AND operation fails. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcAndMmio ( > > + IN UINTN DevBase, > > + IN UINT32 Offset, > > + IN UINT8 Count, > > + IN VOID *AndData > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Wait for the value of the specified MMIO register set to the test va= lue. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] BarIndex The BAR index of the standard PCI Configur= ation > > + header to use as the base address for the = memory > > + operation to perform. > > + @param[in] Offset The offset within the selected BAR to star= t the > > + memory operation. > > + @param[in] Count The width of the mmio register in bytes. > > + Must be 1, 2, 4 or 8 bytes. > > + @param[in] MaskValue The mask value of memory. > > + @param[in] TestValue The test value of memory. > > + @param[in] Timeout The time out value for wait memory set, us= es 1 > > + microsecond as a unit. > > + > > + @retval EFI_TIMEOUT The MMIO register hasn't expected value in > > timeout > > + range. > > + @retval EFI_SUCCESS The MMIO register has expected value. > > + @retval Others The MMIO operation fails. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcWaitMmioSet ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 BarIndex, > > + IN UINT32 Offset, > > + IN UINT8 Count, > > + IN UINT64 MaskValue, > > + IN UINT64 TestValue, > > + IN UINT64 Timeout > > + ); > > +#else > > +/** > > + Wait for the value of the specified MMIO register set to the test va= lue. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Offset The offset within the selected BAR to star= t the > > + memory operation. > > + @param[in] Count The width of the mmio register in bytes. > > + Must be 1, 2, 4 or 8 bytes. > > + @param[in] MaskValue The mask value of memory. > > + @param[in] TestValue The test value of memory. > > + @param[in] Timeout The time out value for wait memory set, us= es 1 > > + microsecond as a unit. > > + > > + @retval EFI_TIMEOUT The MMIO register hasn't expected value in > > timeout > > + range. > > + @retval EFI_SUCCESS The MMIO register has expected value. > > + @retval Others The MMIO operation fails. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcWaitMmioSet ( > > + IN UINTN DevBase, > > + IN UINT32 Offset, > > + IN UINT8 Count, > > + IN UINT64 MaskValue, > > + IN UINT64 TestValue, > > + IN UINT64 Timeout > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Software reset the specified SD/MMC host controller. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + > > + @retval EFI_SUCCESS The software reset executes successfully. > > + @retval Others The software reset fails. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcReset ( > > +fark > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 Slot, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ); > > +#else > > +/** > > + Software reset the specified SD/MMC host controller. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + > > + @retval EFI_SUCCESS The software reset executes successfully. > > + @retval Others The software reset fails. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcReset ( > > + IN UINTN DevBase, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Set all interrupt status bits in Normal and Error Interrupt Status E= nable > > + register. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + > > + @retval EFI_SUCCESS The operation executes successfully. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcEnableInterrupt ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 Slot > > + ); > > +#else > > +/** > > + Set all interrupt status bits in Normal and Error Interrupt Status E= nable > > + register. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + > > + @retval EFI_SUCCESS The operation executes successfully. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcEnableInterrupt ( > > + IN UINTN DevBase > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Get the capability data from the specified slot. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send t= he > > command to. > > + @param[out] Capability The buffer to store the capability data. > > + > > + @retval EFI_SUCCESS The operation executes successfully. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcGetCapability ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN EFI_HANDLE Controller, > > + IN UINT8 Slot, > > + OUT DW_MMC_HC_SLOT_CAP *Capability > > + ); > > +#else > > +/** > > + Get the capability data from the specified slot. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send t= he > > command to. > > + @param[out] Capability The buffer to store the capability data. > > + > > + @retval EFI_SUCCESS The operation executes successfully. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcGetCapability ( > > + IN UINTN DevBase, > > + IN EFI_HANDLE Controller, > > + IN UINT8 Slot, > > + OUT DW_MMC_HC_SLOT_CAP *Capability > > + ); > > +#endif > > + > > +#if 0 > > +/** > > + Get the maximum current capability data from the specified slot. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send t= he > > command to. > > + @param[out] MaxCurrent The buffer to store the maximum current > > capability data. > > + > > + @retval EFI_SUCCESS The operation executes successfully. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcGetMaxCurrent ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 Slot, > > + OUT UINT64 *MaxCurrent > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Detect whether there is a SD/MMC card attached at the specified > > SD/MMC host controller > > + slot. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 3.1 for deta= ils. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + @param[out] MediaPresent The pointer to the media present boolean > > value. > > + > > + @retval EFI_SUCCESS There is no media change happened. > > + @retval EFI_MEDIA_CHANGED There is media change happened. > > + @retval Others The detection fails. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcCardDetect ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN EFI_HANDLE Controller, > > + IN UINT8 Slot, > > + OUT BOOLEAN *MediaPresent > > + ); > > +#else > > +/** > > + Detect whether there is a SD/MMC card attached at the specified > > SD/MMC host controller > > + slot. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 3.1 for deta= ils. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + @param[out] MediaPresent The pointer to the media present boolean > > value. > > + > > + @retval EFI_SUCCESS There is no media change happened. > > + @retval EFI_MEDIA_CHANGED There is media change happened. > > + @retval Others The detection fails. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcCardDetect ( > > + IN UINTN DevBase, > > + IN EFI_HANDLE Controller, > > + IN UINT8 Slot, > > + OUT BOOLEAN *MediaPresent > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Stop SD/MMC card clock. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 3.2.2 for de= tails. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + > > + @retval EFI_SUCCESS Succeed to stop SD/MMC clock. > > + @retval Others Fail to stop SD/MMC clock. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcStopClock ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 Slot > > + ); > > + > > +/** > > + SD/MMC card clock supply. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 3.2.1 for de= tails. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + @param[in] ClockFreq The max clock frequency to be set. The uni= t is > > KHz. > > + @param[in] Capability The capability of the slot. > > + > > + @retval EFI_SUCCESS The clock is supplied successfully. > > + @retval Others The clock isn't supplied successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcClockSupply ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 Slot, > > + IN UINT64 ClockFreq, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ); > > +#else > > +/** > > + Stop SD/MMC card clock. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 3.2.2 for de= tails. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + > > + @retval EFI_SUCCESS Succeed to stop SD/MMC clock. > > + @retval Others Fail to stop SD/MMC clock. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcStopClock ( > > + IN UINTN DevBase > > + ); > > + > > +/** > > + SD/MMC card clock supply. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 3.2.1 for de= tails. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] ClockFreq The max clock frequency to be set. The uni= t is > > KHz. > > + @param[in] Capability The capability of the slot. > > + > > + @retval EFI_SUCCESS The clock is supplied successfully. > > + @retval Others The clock isn't supplied successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcClockSupply ( > > + IN UINTN DevBase, > > + IN UINT64 ClockFreq, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ); > > +#endif > > + > > +#if 0 > > +/** > > + SD/MMC bus power control. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for deta= ils. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + @param[in] PowerCtrl The value setting to the power control reg= ister. > > + > > + @retval TRUE There is a SD/MMC card attached. > > + @retval FALSE There is no a SD/MMC card attached. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcPowerControl ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 Slot, > > + IN UINT8 PowerCtrl > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Set the SD/MMC bus width. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 3.4 for deta= ils. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + @param[in] BusWidth The bus width used by the SD/MMC device, i= t > > must be 1, 4 or 8. > > + > > + @retval EFI_SUCCESS The bus width is set successfully. > > + @retval Others The bus width isn't set successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcSetBusWidth ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 Slot, > > + IN BOOLEAN IsDdr, > > + IN UINT16 BusWidth > > + ); > > +#else > > +/** > > + Set the SD/MMC bus width. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 3.4 for deta= ils. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] BusWidth The bus width used by the SD/MMC device, i= t > > must be 1, 4 or 8. > > + > > + @retval EFI_SUCCESS The bus width is set successfully. > > + @retval Others The bus width isn't set successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcSetBusWidth ( > > + IN UINTN DevBase, > > + IN BOOLEAN IsDdr, > > + IN UINT16 BusWidth > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Supply SD/MMC card with lowest clock frequency at initialization. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + @param[in] Capability The capability of the slot. > > + > > + @retval EFI_SUCCESS The clock is supplied successfully. > > + @retval Others The clock isn't supplied successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcInitClockFreq ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 Slot, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ); > > +#else > > +/** > > + Supply SD/MMC card with lowest clock frequency at initialization. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Capability The capability of the slot. > > + > > + @retval EFI_SUCCESS The clock is supplied successfully. > > + @retval Others The clock isn't supplied successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcInitClockFreq ( > > + IN UINTN DevBase, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Supply SD/MMC card with maximum voltage at initialization. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for deta= ils. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + @param[in] Capability The capability of the slot. > > + > > + @retval EFI_SUCCESS The voltage is supplied successfully. > > + @retval Others The voltage isn't supplied successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcInitPowerVoltage ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 Slot, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ); > > +#else > > +/** > > + Supply SD/MMC card with maximum voltage at initialization. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for deta= ils. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Capability The capability of the slot. > > + > > + @retval EFI_SUCCESS The voltage is supplied successfully. > > + @retval Others The voltage isn't supplied successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcInitPowerVoltage ( > > + IN UINTN DevBase, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Initialize the Timeout Control register with most conservative value= at > > initialization. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 2.2.15 for d= etails. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + > > + @retval EFI_SUCCESS The timeout control register is configured > > successfully. > > + @retval Others The timeout control register isn't configu= red > > successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcInitTimeoutCtrl ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 Slot > > + ); > > +#else > > +/** > > + Initialize the Timeout Control register with most conservative value= at > > initialization. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 2.2.15 for d= etails. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + > > + @retval EFI_SUCCESS The timeout control register is configured > > successfully. > > + @retval Others The timeout control register isn't configu= red > > successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcInitTimeoutCtrl ( > > + IN UINTN DevBase > > + ); > > +#endif > > + > > +#ifdef DWMMC_PCI > > +/** > > + Initial SD/MMC host controller with lowest clock frequency, max powe= r > > and max timeout value > > + at initialization. > > + > > + @param[in] PciIo The PCI IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command to. > > + @param[in] Capability The capability of the slot. > > + > > + @retval EFI_SUCCESS The host controller is initialized success= fully. > > + @retval Others The host controller isn't initialized succ= essfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcInitHost ( > > + IN EFI_PCI_IO_PROTOCOL *PciIo, > > + IN UINT8 Slot, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ); > > +#else > > +/** > > + Initial SD/MMC host controller with lowest clock frequency, max powe= r > > and > > + max timeout value at initialization. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Capability The capability of the slot. > > + > > + @retval EFI_SUCCESS The host controller is initialized success= fully. > > + @retval Others The host controller isn't initialized succ= essfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcInitHost ( > > + IN UINTN DevBase, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ); > > +#endif > > + > > +#endif /* _DW_MMC_HCI_H_ */ > > diff --git a/EmbeddedPkg/Include/Protocol/PlatformDwMmc.h > > b/EmbeddedPkg/Include/Protocol/PlatformDwMmc.h > > new file mode 100644 > > index 000000000000..acbc3e153dac > > --- /dev/null > > +++ b/EmbeddedPkg/Include/Protocol/PlatformDwMmc.h > > @@ -0,0 +1,79 @@ > > +/** @file > > + > > + Copyright (c) 2018, Linaro. All rights reserved. > > + > > + This program and the accompanying materials are licensed and made > > available > > + under the terms and conditions of the BSD License which accompanies = this > > + distribution. The full text of the license may be found at > > + http://opensource.org/licenses/bsd-license.php > > + > > + 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 __PLATFORM_DW_MMC_H__ > > +#define __PLATFORM_DW_MMC_H__ > > + > > +typedef enum { > > + RemovableSlot, > > + EmbeddedSlot, > > + SharedBusSlot, > > + UnknownSlot > > +} EFI_SD_MMC_SLOT_TYPE; > > + > > +typedef enum { > > + UnknownCardType, > > + SdCardType, > > + SdioCardType, > > + MmcCardType, > > + EmmcCardType > > +} SD_MMC_CARD_TYPE; > > + > > +typedef struct { > > + UINT32 DefaultSpeed:1; // bit 0 > > + UINT32 HighSpeed:1; // bit 1 > > + UINT32 Sdr12:1; // bit 2 > > + UINT32 Sdr25:1; // bit 3 > > + UINT32 Sdr50:1; // bit 4 > > + UINT32 Sdr104:1; // bit 5 > > + UINT32 Ddr50:1; // bit 6 > > + UINT32 SysBus64:1; // bit 7 > > + UINT32 BusWidth:4; // bit 11:8 > > + UINT32 SlotType:2; // bit 13:12 > > + UINT32 CardType:3; // bit 16:14 > > + UINT32 Voltage18:1; // bit 17 > > + UINT32 Voltage30:1; // bit 18 > > + UINT32 Voltage33:1; // bit 19 > > + UINT32 BaseClkFreq; > > + EFI_HANDLE Controller; > > +} DW_MMC_HC_SLOT_CAP; > > + > > +// > > +// Protocol interface structure > > +// > > +typedef struct _PLATFORM_DW_MMC_PROTOCOL > > PLATFORM_DW_MMC_PROTOCOL; > > + > > +typedef > > +EFI_STATUS > > +(EFIAPI *PLATFORM_DW_MMC_GET_CAPABILITY) ( > > + IN EFI_HANDLE Controller, > > + IN UINT8 Slot, > > + OUT DW_MMC_HC_SLOT_CAP *Capability > > + ); > > + > > +typedef > > +BOOLEAN > > +(EFIAPI *PLATFORM_DW_MMC_CARD_DETECT) ( > > + IN EFI_HANDLE Controller, > > + IN UINT8 Slot > > + ); > > + > > +struct _PLATFORM_DW_MMC_PROTOCOL { > > + PLATFORM_DW_MMC_GET_CAPABILITY GetCapability; > > + PLATFORM_DW_MMC_CARD_DETECT CardDetect; > > +}; > > + > > +extern EFI_GUID gPlatformDwMmcProtocolGuid; > > + > > +#endif /* __PLATFORM_DW_MMC_H__ */ > > diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/ComponentName.c > > b/EmbeddedPkg/Drivers/DwMmcHcDxe/ComponentName.c > > new file mode 100644 > > index 000000000000..1edade69d091 > > --- /dev/null > > +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/ComponentName.c > > @@ -0,0 +1,214 @@ > > +/** @file > > + UEFI Component Name(2) protocol implementation for Designware > > SD/MMC host > > + controller driver. > > + > > + Copyright (c) 2015, Intel Corporation. All rights reserved.
> > + Copyright (c) 2018, Linaro Ltd. All rights reserved.
> > + > > + This program and the accompanying materials are licensed and made > > available > > + under the terms and conditions of the BSD License which accompanies = this > > + distribution. The full text of the license may be found at > > + http://opensource.org/licenses/bsd-license.php > > + > > + 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 "DwMmcHcDxe.h" > > + > > +// > > +// EFI Component Name Protocol > > +// > > +GLOBAL_REMOVE_IF_UNREFERENCED > > EFI_COMPONENT_NAME_PROTOCOL gDwMmcHcComponentName =3D { > > + DwMmcHcComponentNameGetDriverName, > > + DwMmcHcComponentNameGetControllerName, > > + "eng" > > +}; > > + > > +// > > +// EFI Component Name 2 Protocol > > +// > > +GLOBAL_REMOVE_IF_UNREFERENCED > > EFI_COMPONENT_NAME2_PROTOCOL gDwMmcHcComponentName2 =3D { > > + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) > > DwMmcHcComponentNameGetDriverName, > > + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) > > DwMmcHcComponentNameGetControllerName, > > + "en" > > +}; > > + > > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE > > mDwMmcHcDriverNameTable[] =3D { > > + { "eng;en", L"Designware Sd/Mmc Host Controller Driver" }, > > + { NULL , NULL } > > +}; > > + > > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE > > mDwMmcHcControllerNameTable[] =3D { > > + { "eng;en", L"Designware Sd/Mmc Host Controller" }, > > + { NULL , NULL } > > +}; > > + > > +/** > > + Retrieves a Unicode string that is the user readable name of the dri= ver. > > + > > + This function retrieves the user readable name of a driver in the fo= rm of a > > + Unicode string. If the driver specified by This has a user readable = name in > > + the language specified by Language, then a pointer to the driver nam= e is > > + returned in DriverName, and EFI_SUCCESS is returned. If the driver > > specified > > + by This does not support the language specified by Language, > > + then EFI_UNSUPPORTED is returned. > > + > > + @param This[in] A pointer to the > > EFI_COMPONENT_NAME2_PROTOCOL or > > + EFI_COMPONENT_NAME_PROTOCOL instance. > > + > > + @param Language[in] A pointer to a Null-terminated ASCII s= tring > > + array indicating the language. This is= the > > + language of the driver name that the c= aller is > > + requesting, and it must match one of t= he > > + languages specified in SupportedLangua= ges. The > > + number of languages supported by a dri= ver is up > > + to the driver writer. Language is spec= ified > > + in RFC 4646 or ISO 639-2 language code= format. > > + > > + @param DriverName[out] A pointer to the Unicode string to ret= urn. > > + This Unicode string is the name of the > > + driver specified by This in the langua= ge > > + specified by Language. > > + > > + @retval EFI_SUCCESS The Unicode string for the Driver spec= ified by > > + This and the language specified by Lan= guage was > > + returned in DriverName. > > + > > + @retval EFI_INVALID_PARAMETER Language is NULL. > > + > > + @retval EFI_INVALID_PARAMETER DriverName is NULL. > > + > > + @retval EFI_UNSUPPORTED The driver specified by This does not > > support > > + the language specified by Language. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcComponentNameGetDriverName ( > > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > > + IN CHAR8 *Language, > > + OUT CHAR16 **DriverName > > + ) > > +{ > > + return LookupUnicodeString2 ( > > + Language, > > + This->SupportedLanguages, > > + mDwMmcHcDriverNameTable, > > + DriverName, > > + (BOOLEAN)(This =3D=3D &gDwMmcHcComponentName) > > + ); > > +} > > + > > +/** > > + Retrieves a Unicode string that is the user readable name of the con= troller > > + that is being managed by a driver. > > + > > + This function retrieves the user readable name of the controller spe= cified > > by > > + ControllerHandle and ChildHandle in the form of a Unicode string. If= the > > + driver specified by This has a user readable name in the language sp= ecified > > by > > + Language, then a pointer to the controller name is returned in > > ControllerName, > > + and EFI_SUCCESS is returned. If the driver specified by This is not= currently > > + managing the controller specified by ControllerHandle and ChildHandl= e, > > + then EFI_UNSUPPORTED is returned. If the driver specified by This d= oes > > not > > + support the language specified by Language, then EFI_UNSUPPORTED is > > returned. > > + > > + @param This[in] A pointer to the > > EFI_COMPONENT_NAME2_PROTOCOL or > > + EFI_COMPONENT_NAME_PROTOCOL instance. > > + > > + @param ControllerHandle[in] The handle of a controller that the dr= iver > > + specified by This is managing. This h= andle > > + specifies the controller whose name is= to be > > + returned. > > + > > + @param ChildHandle[in] The handle of the child controller to = retrieve > > + the name of. This is an optional para= meter that > > + may be NULL. It will be NULL for devi= ce > > + drivers. It will also be NULL for a b= us drivers > > + that wish to retrieve the name of the = bus > > + controller. It will not be NULL for a= bus > > + driver that wishes to retrieve the nam= e of a > > + child controller. > > + > > + @param Language[in] A pointer to a Null-terminated ASCII s= tring > > + array indicating the language. This i= s the > > + language of the driver name that the c= aller is > > + requesting, and it must match one of t= he > > + languages specified in SupportedLangua= ges. The > > + number of languages supported by a dri= ver is up > > + to the driver writer. Language is spec= ified in > > + RFC 4646 or ISO 639-2 language code fo= rmat. > > + > > + @param ControllerName[out] A pointer to the Unicode string to ret= urn. > > + This Unicode string is the name of the > > + controller specified by ControllerHand= le and > > + ChildHandle in the language specified = by > > + Language from the point of view of the= driver > > + specified by This. > > + > > + @retval EFI_SUCCESS The Unicode string for the user readab= le name > > in > > + the language specified by Language for= the > > + driver specified by This was returned = in > > + DriverName. > > + > > + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid > > EFI_HANDLE. > > + > > + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not = a > > valid > > + EFI_HANDLE. > > + > > + @retval EFI_INVALID_PARAMETER Language is NULL. > > + > > + @retval EFI_INVALID_PARAMETER ControllerName is NULL. > > + > > + @retval EFI_UNSUPPORTED The driver specified by This is not cu= rrently > > + managing the controller specified by > > + ControllerHandle and ChildHandle. > > + > > + @retval EFI_UNSUPPORTED The driver specified by This does not > > support > > + the language specified by Language. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcComponentNameGetControllerName ( > > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > > + IN EFI_HANDLE ControllerHandle, > > + IN EFI_HANDLE ChildHandle, OPTIONAL > > + IN CHAR8 *Language, > > + OUT CHAR16 **ControllerName > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + if (Language =3D=3D NULL || ControllerName =3D=3D NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // > > + // This is a device driver, so ChildHandle must be NULL. > > + // > > + if (ChildHandle !=3D NULL) { > > + return EFI_UNSUPPORTED; > > + } > > + > > + // > > + // Make sure this driver is currently managing ControllerHandle > > + // > > + Status =3D EfiTestManagedDevice ( > > + ControllerHandle, > > + gDwMmcHcDriverBinding.DriverBindingHandle, > > + &gEfiPciIoProtocolGuid > > + ); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + return LookupUnicodeString2 ( > > + Language, > > + This->SupportedLanguages, > > + mDwMmcHcControllerNameTable, > > + ControllerName, > > + (BOOLEAN)(This =3D=3D &gDwMmcHcComponentName) > > + ); > > +} > > diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.c > > b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.c > > new file mode 100644 > > index 000000000000..aea12170d2cc > > --- /dev/null > > +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHcDxe.c > > @@ -0,0 +1,1296 @@ > > +/** @file > > + This driver is used to manage Designware SD/MMC host controller. > > + > > + It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer > > use. > > + > > + Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved. > > + Copyright (C) 2016 Marvell International Ltd. All rigths reserved. > > + Copyright (C) 2018, Linaro Ltd. All rigths reserved.
> > + > > + This program and the accompanying materials > > + are licensed and made available under the terms and conditions of th= e BSD > > License > > + which accompanies this distribution. The full text of the license m= ay be > > found at > > + http://opensource.org/licenses/bsd-license.php > > + > > + 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 "DwMmcHcDxe.h" > > + > > +// > > +// Driver Global Variables > > +// > > +EFI_DRIVER_BINDING_PROTOCOL gDwMmcHcDriverBinding =3D { > > + DwMmcHcDriverBindingSupported, > > + DwMmcHcDriverBindingStart, > > + DwMmcHcDriverBindingStop, > > + 0x10, > > + NULL, > > + NULL > > +}; > > + > > +// > > +// Template for Designware SD/MMC host controller private data. > > +// > > +DW_MMC_HC_PRIVATE_DATA gDwMmcHcTemplate =3D { > > + DW_MMC_HC_PRIVATE_SIGNATURE, // Signature > > + NULL, // ControllerHandle > > + 0x0, // Mmio base address > > + { // PassThru > > + sizeof (UINT32), > > + DwMmcPassThruPassThru, > > + DwMmcPassThruGetNextSlot, > > + DwMmcPassThruBuildDevicePath, > > + DwMmcPassThruGetSlotNumber, > > + DwMmcPassThruResetDevice > > + }, > > + NULL, // PlatformDwMmc > > + 0, // PreviousSlot > > + NULL, // TimerEvent > > + NULL, // ConnectEvent > > + // Queue > > + INITIALIZE_LIST_HEAD_VARIABLE (gDwMmcHcTemplate.Queue), > > + { // Slot > > + {0, UnknownSlot, 0, 0, 0} > > + }, > > + { // Capability > > + {0} > > + }, > > + { // MaxCurrent > > + 0 > > + }, > > + 0 // ControllerVersion > > +}; > > + > > +SD_DEVICE_PATH mSdDpTemplate =3D { > > + { > > + MESSAGING_DEVICE_PATH, > > + MSG_SD_DP, > > + { > > + (UINT8) (sizeof (SD_DEVICE_PATH)), > > + (UINT8) ((sizeof (SD_DEVICE_PATH)) >> 8) > > + } > > + }, > > + 0 > > +}; > > + > > +EMMC_DEVICE_PATH mEmmcDpTemplate =3D { > > + { > > + MESSAGING_DEVICE_PATH, > > + MSG_EMMC_DP, > > + { > > + (UINT8) (sizeof (EMMC_DEVICE_PATH)), > > + (UINT8) ((sizeof (EMMC_DEVICE_PATH)) >> 8) > > + } > > + }, > > + 0 > > +}; > > + > > +// > > +// Prioritized function list to detect card type. > > +// User could add other card detection logic here. > > +// > > +DWMMC_CARD_TYPE_DETECT_ROUTINE mCardTypeDetectRoutineTable[] > > =3D { > > + EmmcIdentification, > > + SdCardIdentification, > > + NULL > > +}; > > + > > +/** > > + The entry point for SD host controller driver, used to install this = driver on > > the ImageHandle. > > + > > + @param[in] ImageHandle The firmware allocated handle for this dri= ver > > image. > > + @param[in] SystemTable Pointer to the EFI system table. > > + > > + @retval EFI_SUCCESS Driver loaded. > > + @retval other Driver not loaded. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +InitializeDwMmcHcDxe ( > > + IN EFI_HANDLE ImageHandle, > > + IN EFI_SYSTEM_TABLE *SystemTable > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + Status =3D EfiLibInstallDriverBindingComponentName2 ( > > + ImageHandle, > > + SystemTable, > > + &gDwMmcHcDriverBinding, > > + ImageHandle, > > + &gDwMmcHcComponentName, > > + &gDwMmcHcComponentName2 > > + ); > > + ASSERT_EFI_ERROR (Status); > > + > > + return Status; > > +} > > + > > +/** > > + Call back function when the timer event is signaled. > > + > > + @param[in] Event The Event this notify function registered to. > > + @param[in] Context Pointer to the context data registered to the > > + Event. > > + > > +**/ > > +VOID > > +EFIAPI > > +ProcessAsyncTaskList ( > > + IN EFI_EVENT Event, > > + IN VOID* Context > > + ) > > +{ > > + DW_MMC_HC_PRIVATE_DATA *Private; > > + LIST_ENTRY *Link; > > + DW_MMC_HC_TRB *Trb; > > + EFI_STATUS Status; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; > > + BOOLEAN InfiniteWait; > > + EFI_EVENT TrbEvent; > > + > > + Private =3D (DW_MMC_HC_PRIVATE_DATA *)Context; > > + > > + // > > + // Check if the first entry in the async I/O queue is done or not. > > + // > > + Status =3D EFI_SUCCESS; > > + Trb =3D NULL; > > + Link =3D GetFirstNode (&Private->Queue); > > + if (!IsNull (&Private->Queue, Link)) { > > + Trb =3D DW_MMC_HC_TRB_FROM_THIS (Link); > > + if (!Private->Slot[Trb->Slot].MediaPresent) { > > + Status =3D EFI_NO_MEDIA; > > + goto Done; > > + } > > + if (!Trb->Started) { > > + // > > + // Check whether the cmd/data line is ready for transfer. > > + // > > + Status =3D DwMmcCheckTrbEnv (Private, Trb); > > + if (!EFI_ERROR (Status)) { > > + Trb->Started =3D TRUE; > > + Status =3D DwMmcExecTrb (Private, Trb); > > + if (EFI_ERROR (Status)) { > > + goto Done; > > + } > > + } else { > > + goto Done; > > + } > > + } > > + Status =3D DwMmcCheckTrbResult (Private, Trb); > > + } > > + > > +Done: > > + if ((Trb !=3D NULL) && (Status =3D=3D EFI_NOT_READY)) { > > + Packet =3D Trb->Packet; > > + if (Packet->Timeout =3D=3D 0) { > > + InfiniteWait =3D TRUE; > > + } else { > > + InfiniteWait =3D FALSE; > > + } > > + if ((!InfiniteWait) && (Trb->Timeout-- =3D=3D 0)) { > > + RemoveEntryList (Link); > > + Trb->Packet->TransactionStatus =3D EFI_TIMEOUT; > > + TrbEvent =3D Trb->Event; > > + DwMmcFreeTrb (Trb); > > + DEBUG (( > > + DEBUG_VERBOSE, > > + "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT\n", > > + TrbEvent > > + )); > > + gBS->SignalEvent (TrbEvent); > > + return; > > + } > > + } > > + if ((Trb !=3D NULL) && (Status !=3D EFI_NOT_READY)) { > > + RemoveEntryList (Link); > > + Trb->Packet->TransactionStatus =3D Status; > > + TrbEvent =3D Trb->Event; > > + DwMmcFreeTrb (Trb); > > + DEBUG (( > > + DEBUG_VERBOSE, > > + "ProcessAsyncTaskList(): Signal Event %p with %r\n", > > + TrbEvent, > > + Status > > + )); > > + gBS->SignalEvent (TrbEvent); > > + } > > + return; > > +} > > + > > +/** > > + Sd removable device enumeration callback function when the timer eve= nt > > is signaled. > > + > > + @param[in] Event The Event this notify function registered to. > > + @param[in] Context Pointer to the context data registered to the > > + Event. > > + > > +**/ > > +VOID > > +EFIAPI > > +DwMmcHcEnumerateDevice ( > > + IN EFI_EVENT Event, > > + IN VOID* Context > > + ) > > +{ > > + DW_MMC_HC_PRIVATE_DATA *Private; > > + EFI_STATUS Status; > > + BOOLEAN MediaPresent; > > + UINT32 RoutineNum; > > + DWMMC_CARD_TYPE_DETECT_ROUTINE *Routine; > > + UINTN Index; > > + LIST_ENTRY *Link; > > + LIST_ENTRY *NextLink; > > + DW_MMC_HC_TRB *Trb; > > + EFI_TPL OldTpl; > > + > > + Private =3D (DW_MMC_HC_PRIVATE_DATA *)Context; > > + > > + if ((Private->Slot[0].Enable) && > > + (Private->Slot[0].SlotType =3D=3D RemovableSlot)) { > > + Status =3D DwMmcHcCardDetect ( > > + Private->DevBase, > > + Private->ControllerHandle, > > + 0, > > + &MediaPresent > > + ); > > + if ((Status =3D=3D EFI_MEDIA_CHANGED) && !MediaPresent) { > > + DEBUG (( > > + DEBUG_INFO, > > + "DwMmcHcEnumerateDevice: device disconnected at %p\n", > > + Private->DevBase > > + )); > > + Private->Slot[0].MediaPresent =3D FALSE; > > + // > > + // Signal all async task events at the slot with EFI_NO_MEDIA st= atus. > > + // > > + OldTpl =3D gBS->RaiseTPL (TPL_NOTIFY); > > + for (Link =3D GetFirstNode (&Private->Queue); > > + !IsNull (&Private->Queue, Link); > > + Link =3D NextLink) { > > + NextLink =3D GetNextNode (&Private->Queue, Link); > > + Trb =3D DW_MMC_HC_TRB_FROM_THIS (Link); > > + if (Trb->Slot =3D=3D 0) { > > + RemoveEntryList (Link); > > + Trb->Packet->TransactionStatus =3D EFI_NO_MEDIA; > > + gBS->SignalEvent (Trb->Event); > > + DwMmcFreeTrb (Trb); > > + } > > + } > > + gBS->RestoreTPL (OldTpl); > > + // > > + // Notify the upper layer the connect state change through > > + // ReinstallProtocolInterface. > > + // > > + gBS->ReinstallProtocolInterface ( > > + Private->ControllerHandle, > > + &gEfiSdMmcPassThruProtocolGuid, > > + &Private->PassThru, > > + &Private->PassThru > > + ); > > + } > > + if ((Status =3D=3D EFI_MEDIA_CHANGED) && MediaPresent) { > > + DEBUG (( > > + DEBUG_INFO, > > + "DwMmcHcEnumerateDevice: device connected at %p\n", > > + Private->DevBase > > + )); > > + // > > + // Initialize slot and start identification process for the new > > + // attached device > > + // > > + Status =3D DwMmcHcInitHost (Private->DevBase, Private->Capabilit= y[0]); > > + if (EFI_ERROR (Status)) { > > + return; > > + } > > + // > > + // Reset the specified slot of the SD/MMC Pci Host Controller > > + // > > + Status =3D DwMmcHcReset (Private->DevBase, Private->Capability[0= ]); > > + if (EFI_ERROR (Status)) { > > + return; > > + } > > + > > + Private->Slot[0].MediaPresent =3D TRUE; > > + RoutineNum =3D sizeof (mCardTypeDetectRoutineTable) / > > + sizeof (DWMMC_CARD_TYPE_DETECT_ROUTINE); > > + for (Index =3D 0; Index < RoutineNum; Index++) { > > + Routine =3D &mCardTypeDetectRoutineTable[Index]; > > + if (*Routine !=3D NULL) { > > + Status =3D (*Routine) (Private); > > + if (!EFI_ERROR (Status)) { > > + break; > > + } > > + } > > + } > > + // > > + // This card doesn't get initialized correctly. > > + // > > + if (Index =3D=3D RoutineNum) { > > + return; > > + } > > + > > + // > > + // Notify the upper layer the connect state change through > > + // ReinstallProtocolInterface. > > + // > > + gBS->ReinstallProtocolInterface ( > > + Private->ControllerHandle, > > + &gEfiSdMmcPassThruProtocolGuid, > > + &Private->PassThru, > > + &Private->PassThru > > + ); > > + } > > + } > > + > > + return; > > +} > > + > > +/** > > + Reset the specified SD/MMC host controller and enable all interrupts= . > > + > > + @param[in] DevBase The Mmio Device Base Address. > > + > > + @retval EFI_SUCCESS The software reset executes successfully. > > + @retval Others The software reset fails. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcReset ( > > + IN UINTN DevBase, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT32 BlkSize; > > + > > + // > > + // Enable all interrupt after reset all. > > + // > > + Status =3D DwMmcHcEnableInterrupt (DevBase); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "DwMmcHcReset: enable interrupts fail: %r\n", > > Status)); > > + return Status; > > + } > > + Status =3D DwMmcHcInitTimeoutCtrl (DevBase); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + BlkSize =3D DW_MMC_BLOCK_SIZE; > > + MmioWrite32 (DevBase + DW_MMC_BLKSIZ, BlkSize); > > + > > + Status =3D DwMmcHcInitClockFreq (DevBase, Capability); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + Status =3D DwMmcHcSetBusWidth (DevBase, FALSE, 1); > > + > > + return Status; > > +} > > + > > +/** > > + Tests to see if this driver supports a given controller. If a child = device > > + is provided, it further tests to see if this driver supports creatin= g a > > + handle for the specified child device. > > + > > + This function checks to see if the driver specified by This supports= the > > + device specified by ControllerHandle. Drivers will typically use the= device > > + path attached to ControllerHandle and/or the services from the bus I= /O > > + abstraction attached to ControllerHandle to determine if the driver > > supports > > + ControllerHandle. This function may be called many times during plat= form > > + initialization. In order to reduce boot times, the tests performed b= y this > > + function must be very small, and take as little time as possible to = execute. > > + This function must not change the state of any hardware devices, and= this > > + function must be aware that the device specified by ControllerHandle= may > > + already be managed by the same driver or a different driver. This fu= nction > > + must match its calls to AllocatePages() with FreePages(), AllocatePo= ol() > > with > > + FreePool(), and OpenProtocol() with CloseProtocol(). Since > > ControllerHandle > > + may have been previously started by the same driver, if a protocol i= s > > already > > + in the opened state, then it must not be closed with CloseProtocol()= . This is > > + required to guarantee the state of ControllerHandle is not modified = by this > > + function. > > + > > + @param[in] This A pointer to the > > EFI_DRIVER_BINDING_PROTOCOL > > + instance. > > + @param[in] ControllerHandle The handle of the controller to tes= t. This > > + handle must support a protocol inte= rface that > > + supplies an I/O abstraction to the = driver. > > + @param[in] RemainingDevicePath A pointer to the remaining portion = of a > > + device path. This parameter is ign= ored by > > + device drivers, and is optional for= bus > > + drivers. For bus drivers, if this p= arameter > > + is not NULL, then the bus driver mu= st deter- > > + mine if the bus controller specifie= d by > > + ControllerHandle and the child cont= roller > > + specified by RemainingDevicePath ar= e both > > + supported by this bus driver. > > + > > + @retval EFI_SUCCESS The device specified by ControllerH= andle and > > + RemainingDevicePath is supported by= the > > + driver specified by This. > > + @retval EFI_ALREADY_STARTED The device specified by > > ControllerHandle and > > + RemainingDevicePath is already bein= g managed > > + by the driver specified by This. > > + @retval EFI_ACCESS_DENIED The device specified by ControllerH= andle > > and > > + RemainingDevicePath is already bein= g managed > > + by a different driver or an applica= tion that > > + requires exclusive access. > > + Currently not implemented. > > + @retval EFI_UNSUPPORTED The device specified by ControllerH= andle > > and > > + RemainingDevicePath is not supporte= d by the > > + driver specified by This. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcDriverBindingSupported ( > > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > > + IN EFI_HANDLE Controller, > > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; > > + NON_DISCOVERABLE_DEVICE *Dev; > > + PLATFORM_DW_MMC_PROTOCOL *PlatformDwMmc; > > + > > + ParentDevicePath =3D NULL; > > + > > + Status =3D gBS->LocateProtocol ( > > + &gPlatformDwMmcProtocolGuid, > > + NULL, > > + (VOID **) &PlatformDwMmc > > + ); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + Status =3D gBS->OpenProtocol ( > > + Controller, > > + &gEfiDevicePathProtocolGuid, > > + (VOID *) &ParentDevicePath, > > + This->DriverBindingHandle, > > + Controller, > > + EFI_OPEN_PROTOCOL_BY_DRIVER > > + ); > > + if (EFI_ERROR (Status)) { > > + // > > + // EFI_ALREADY_STARTED is also an error. > > + // > > + return Status; > > + } > > + // > > + // Close the protocol because we don't use it here. > > + // > > + gBS->CloseProtocol ( > > + Controller, > > + &gEfiDevicePathProtocolGuid, > > + This->DriverBindingHandle, > > + Controller > > + ); > > + > > + // > > + // Now test the EmbeddedNonDiscoverableIoProtocol. > > + // > > + Status =3D gBS->OpenProtocol ( > > + Controller, > > + &gEdkiiNonDiscoverableDeviceProtocolGuid, > > + (VOID **) &Dev, > > + This->DriverBindingHandle, > > + Controller, > > + EFI_OPEN_PROTOCOL_BY_DRIVER > > + ); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + gBS->CloseProtocol ( > > + Controller, > > + &gEdkiiNonDiscoverableDeviceProtocolGuid, > > + This->DriverBindingHandle, > > + Controller > > + ); > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Starts a device controller or a bus controller. > > + > > + The Start() function is designed to be invoked from the EFI boot ser= vice > > + ConnectController(). > > + As a result, much of the error checking on the parameters to Start()= has > > + been moved into this > > + common boot service. It is legal to call Start() from other location= s, > > + but the following calling restrictions must be followed or the syste= m > > + behavior will not be deterministic. > > + 1. ControllerHandle must be a valid EFI_HANDLE. > > + 2. If RemainingDevicePath is not NULL, then it must be a pointer to = a > > + naturally aligned EFI_DEVICE_PATH_PROTOCOL. > > + 3. Prior to calling Start(), the Supported() function for the driver > > + specified by This must have been called with the same calling > > parameters, > > + and Supported() must have returned EFI_SUCCESS. > > + > > + @param[in] This A pointer to the > > EFI_DRIVER_BINDING_PROTOCOL > > + instance. > > + @param[in] ControllerHandle The handle of the controller to sta= rt. This > > + handle must support a protocol inte= rface > > + that supplies an I/O abstraction to= the > > + driver. > > + @param[in] RemainingDevicePath A pointer to the remaining portion = of a > > + device path. This parameter is ign= ored by > > + device drivers, and is optional for= bus > > + drivers. > > + For a bus driver, if this parameter= is NULL, > > + then handles for all the children o= f > > + Controller are created by this driv= er. > > + If this parameter is not NULL and t= he first > > + Device Path Node is not the End of = Device > > + Path Node, then only the handle for= the > > + child device specified by the first= Device > > + Path Node of RemainingDevicePath is= created > > + by this driver. > > + If the first Device Path Node of > > + RemainingDevicePath is the End of D= evice Path > > + Node, no child handle is created by= this > > + driver. > > + > > + @retval EFI_SUCCESS The device was started. > > + @retval EFI_DEVICE_ERROR The device could not be started due= to a > > + device error. Currently not impleme= nted. > > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > > due to a > > + lack of resources. > > + @retval Others The driver failded to start the dev= ice. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcDriverBindingStart ( > > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > > + IN EFI_HANDLE Controller, > > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > > + ) > > +{ > > + EFI_STATUS Status; > > + DW_MMC_HC_PRIVATE_DATA *Private; > > + > > + NON_DISCOVERABLE_DEVICE *Dev; > > + > > + BOOLEAN MediaPresent; > > + DWMMC_CARD_TYPE_DETECT_ROUTINE *Routine; > > + UINT8 Index; > > + UINT32 RoutineNum; > > + PLATFORM_DW_MMC_PROTOCOL *PlatformDwMmc; > > + > > + Status =3D gBS->LocateProtocol ( > > + &gPlatformDwMmcProtocolGuid, > > + NULL, > > + (VOID **) &PlatformDwMmc > > + ); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "err %d", __LINE__)); > > + return Status; > > + } > > + > > + Status =3D gBS->OpenProtocol ( > > + Controller, > > + &gEdkiiNonDiscoverableDeviceProtocolGuid, > > + (VOID **) &Dev, > > + This->DriverBindingHandle, > > + Controller, > > + EFI_OPEN_PROTOCOL_BY_DRIVER > > + ); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "err %d", __LINE__)); > > + return Status; > > + } > > + > > + Private =3D AllocateCopyPool (sizeof (DW_MMC_HC_PRIVATE_DATA), > > &gDwMmcHcTemplate); > > + if (Private =3D=3D NULL) { > > + DEBUG ((DEBUG_ERROR, "err %d", __LINE__)); > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto Done; > > + } > > + > > + Private->ControllerHandle =3D Controller; > > + Private->DevBase =3D Dev->Resources[0].AddrRangeMin; > > + Private->PlatformDwMmc =3D PlatformDwMmc; > > + InitializeListHead (&Private->Queue); > > + > > + Status =3D Private->PlatformDwMmc->GetCapability (Controller, 0, &Pr= ivate- > > >Capability[0]); > > + > > + if (EFI_ERROR (Status)) { > > + goto Done; > > + } > > + > > + if (Private->Capability[0].BaseClkFreq =3D=3D 0) { > > + goto Done; > > + } > > + > > + DumpCapabilityReg (0, &Private->Capability[0]); > > + > > + MediaPresent =3D FALSE; > > + > > + Status =3D Private->PlatformDwMmc->CardDetect (Controller, 0); > > + Status =3D DwMmcHcCardDetect (Private->DevBase, Controller, 0, > > &MediaPresent); > > + if (MediaPresent =3D=3D FALSE) { > > + goto Done; > > + } > > + > > + // > > + // Initialize slot and start identification process for the new atta= ched device > > + // > > + Status =3D DwMmcHcInitHost (Private->DevBase, Private->Capability[0]= ); > > + if (EFI_ERROR (Status)) { > > + goto Done; > > + } > > + > > + // > > + // Reset HC > > + // > > + Status =3D DwMmcHcReset (Private->DevBase, Private->Capability[0]); > > + if (EFI_ERROR (Status)) { > > + goto Done; > > + } > > + > > + Private->Slot[0].CardType =3D Private->Capability[0].CardType; > > + Private->Slot[0].Enable =3D TRUE; > > + Private->Slot[0].MediaPresent =3D TRUE; > > + > > + RoutineNum =3D sizeof (mCardTypeDetectRoutineTable) / sizeof > > (DWMMC_CARD_TYPE_DETECT_ROUTINE); > > + for (Index =3D 0; Index < RoutineNum; Index++) { > > + Routine =3D &mCardTypeDetectRoutineTable[Index]; > > + if (*Routine !=3D NULL) { > > + Status =3D (*Routine) (Private); > > + if (!EFI_ERROR (Status)) { > > + break; > > + } > > + } > > + } > > + > > + // > > + // Start the asynchronous I/O monitor > > + // > > + Status =3D gBS->CreateEvent ( > > + EVT_TIMER | EVT_NOTIFY_SIGNAL, > > + TPL_NOTIFY, > > + ProcessAsyncTaskList, > > + Private, > > + &Private->TimerEvent > > + ); > > + if (EFI_ERROR (Status)) { > > + goto Done; > > + } > > + > > + Status =3D gBS->SetTimer (Private->TimerEvent, TimerPeriodic, > > DW_MMC_HC_ASYNC_TIMER); > > + if (EFI_ERROR (Status)) { > > + goto Done; > > + } > > + > > + // > > + // Start the Sd removable device connection enumeration > > + // > > + Status =3D gBS->CreateEvent ( > > + EVT_TIMER | EVT_NOTIFY_SIGNAL, > > + TPL_CALLBACK, > > + DwMmcHcEnumerateDevice, > > + Private, > > + &Private->ConnectEvent > > + ); > > + if (EFI_ERROR (Status)) { > > + goto Done; > > + } > > + > > + Status =3D gBS->SetTimer (Private->ConnectEvent, TimerPeriodic, > > DW_MMC_HC_ENUM_TIMER); > > + if (EFI_ERROR (Status)) { > > + goto Done; > > + } > > + > > + Status =3D gBS->InstallMultipleProtocolInterfaces ( > > + &Controller, > > + &gEfiSdMmcPassThruProtocolGuid, > > + &(Private->PassThru), > > + NULL > > + ); > > + > > + DEBUG ((DEBUG_INFO, "DwMmcHcDriverBindingStart: %r End on %x\n", > > Status, Controller)); > > + > > +Done: > > + if (EFI_ERROR (Status)) { > > + if ((Private !=3D NULL) && (Private->TimerEvent !=3D NULL)) { > > + gBS->CloseEvent (Private->TimerEvent); > > + } > > + > > + if ((Private !=3D NULL) && (Private->ConnectEvent !=3D NULL)) { > > + gBS->CloseEvent (Private->ConnectEvent); > > + } > > + > > + if (Private !=3D NULL) { > > + FreePool (Private); > > + } > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Stops a device controller or a bus controller. > > + > > + The Stop() function is designed to be invoked from the EFI boot serv= ice > > + DisconnectController(). > > + As a result, much of the error checking on the parameters to Stop() = has > > been > > + moved into this common boot service. It is legal to call Stop() from= other > > + locations, but the following calling restrictions must be followed o= r the > > + system behavior will not be deterministic. > > + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a > > previous > > + call to this same driver's Start() function. > > + 2. The first NumberOfChildren handles of ChildHandleBuffer must all = be a > > valid > > + EFI_HANDLE. In addition, all of these handles must have been crea= ted in > > + this driver's Start() function, and the Start() function must hav= e called > > + OpenProtocol() on ControllerHandle with an Attribute of > > + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. > > + > > + @param[in] This A pointer to the EFI_DRIVER_BINDING_PR= OTOCOL > > + instance. > > + @param[in] ControllerHandle A handle to the device being stopped. = The > > handle > > + must support a bus specific I/O protoc= ol for the > > + driver to use to stop the device. > > + @param[in] NumberOfChildren The number of child device handles in > > + ChildHandleBuffer. > > + @param[in] ChildHandleBuffer An array of child handles to be freed.= May > > be > > + NULL if NumberOfChildren is 0. > > + > > + @retval EFI_SUCCESS The device was stopped. > > + @retval EFI_DEVICE_ERROR The device could not be stopped due to= a > > device > > + error. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcHcDriverBindingStop ( > > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > > + IN EFI_HANDLE Controller, > > + IN UINTN NumberOfChildren, > > + IN EFI_HANDLE *ChildHandleBuffer > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; > > + DW_MMC_HC_PRIVATE_DATA *Private; > > + LIST_ENTRY *Link; > > + LIST_ENTRY *NextLink; > > + DW_MMC_HC_TRB *Trb; > > + > > + DEBUG ((DEBUG_INFO, "DwMmcHcDriverBindingStop: Start\n")); > > + > > + Status =3D gBS->OpenProtocol ( > > + Controller, > > + &gEfiSdMmcPassThruProtocolGuid, > > + (VOID**) &PassThru, > > + This->DriverBindingHandle, > > + Controller, > > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > > + ); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (PassThru); > > + // > > + // Close Non-Blocking timer and free Task list. > > + // > > + if (Private->TimerEvent !=3D NULL) { > > + gBS->CloseEvent (Private->TimerEvent); > > + Private->TimerEvent =3D NULL; > > + } > > + if (Private->ConnectEvent !=3D NULL) { > > + gBS->CloseEvent (Private->ConnectEvent); > > + Private->ConnectEvent =3D NULL; > > + } > > + // > > + // As the timer is closed, there is no needs to use TPL lock to > > + // protect the critical region "queue". > > + // > > + for (Link =3D GetFirstNode (&Private->Queue); > > + !IsNull (&Private->Queue, Link); > > + Link =3D NextLink) { > > + NextLink =3D GetNextNode (&Private->Queue, Link); > > + RemoveEntryList (Link); > > + Trb =3D DW_MMC_HC_TRB_FROM_THIS (Link); > > + Trb->Packet->TransactionStatus =3D EFI_ABORTED; > > + gBS->SignalEvent (Trb->Event); > > + DwMmcFreeTrb (Trb); > > + } > > + > > + // > > + // Uninstall Block I/O protocol from the device handle > > + // > > + Status =3D gBS->UninstallProtocolInterface ( > > + Controller, > > + &gEfiSdMmcPassThruProtocolGuid, > > + &(Private->PassThru) > > + ); > > + > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + gBS->CloseProtocol ( > > + Controller, > > + &gEfiPciIoProtocolGuid, > > + This->DriverBindingHandle, > > + Controller > > + ); > > + > > + FreePool (Private); > > + > > + DEBUG ((DEBUG_INFO, "DwMmcHcDriverBindingStop: End with %r\n", > > Status)); > > + > > + return Status; > > +} > > + > > +/** > > + Sends SD command to an SD card that is attached to the SD controller= . > > + > > + The PassThru() function sends the SD command specified by Packet to = the > > SD > > + card specified by Slot. > > + > > + If Packet is successfully sent to the SD card, then EFI_SUCCESS is r= eturned. > > + > > + If a device error occurs while sending the Packet, then EFI_DEVICE_E= RROR > > is > > + returned. > > + > > + If Slot is not in a valid range for the SD controller, then > > + EFI_INVALID_PARAMETER is returned. > > + > > + If Packet defines a data command but both InDataBuffer and > > OutDataBuffer are > > + NULL, EFI_INVALID_PARAMETER is returned. > > + > > + @param[in] This A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Slot The slot number of the SD card to send= the > > + command to. > > + @param[in,out] Packet A pointer to the SD command data struc= ture. > > + @param[in] Event If Event is NULL, blocking I/O is perf= ormed. If > > + Event is not NULL, then nonblocking I/= O is > > + performed, and Event will be signaled = when the > > + Packet completes. > > + > > + @retval EFI_SUCCESS The SD Command Packet was sent by the = host. > > + @retval EFI_DEVICE_ERROR A device error occurred while attempti= ng to > > send > > + the SD command Packet. > > + @retval EFI_INVALID_PARAMETER Packet, Slot, or the contents of the > > Packet is > > + invalid. > > + @retval EFI_INVALID_PARAMETER Packet defines a data command but > > both > > + InDataBuffer and OutDataBuffer are NUL= L. > > + @retval EFI_NO_MEDIA SD Device not present in the Slot. > > + @retval EFI_UNSUPPORTED The command described by the SD > > Command Packet > > + is not supported by the host controlle= r. > > + @retval EFI_BAD_BUFFER_SIZE The InTransferLength or > > OutTransferLength > > + exceeds the limit supported by SD card > > + ( i.e. if the number of bytes exceed t= he Last > > + LBA). > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcPassThruPassThru ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, > > + IN UINT8 Slot, > > + IN OUT EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet, > > + IN EFI_EVENT Event OPTIONAL > > + ) > > +{ > > + EFI_STATUS Status; > > + DW_MMC_HC_PRIVATE_DATA *Private; > > + DW_MMC_HC_TRB *Trb; > > + EFI_TPL OldTpl; > > + > > + if ((This =3D=3D NULL) || (Packet =3D=3D NULL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if ((Packet->SdMmcCmdBlk =3D=3D NULL) || (Packet->SdMmcStatusBlk =3D= =3D > > NULL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if ((Packet->OutDataBuffer =3D=3D NULL) && (Packet->OutTransferLengt= h !=3D > > 0)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if ((Packet->InDataBuffer =3D=3D NULL) && (Packet->InTransferLength = !=3D 0)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (This); > > + > > + if (!Private->Slot[Slot].Enable) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (!Private->Slot[Slot].MediaPresent) { > > + return EFI_NO_MEDIA; > > + } > > + > > + Trb =3D DwMmcCreateTrb (Private, Slot, Packet, Event); > > + if (Trb =3D=3D NULL) { > > + return EFI_OUT_OF_RESOURCES; > > + } > > + // > > + // Immediately return for async I/O. > > + // > > + if (Event !=3D NULL) { > > + return EFI_SUCCESS; > > + } > > + > > + // > > + // Wait async I/O list is empty before execute sync I/O operation. > > + // > > + while (TRUE) { > > + OldTpl =3D gBS->RaiseTPL (TPL_NOTIFY); > > + if (IsListEmpty (&Private->Queue)) { > > + gBS->RestoreTPL (OldTpl); > > + break; > > + } > > + gBS->RestoreTPL (OldTpl); > > + } > > + > > + Status =3D DwMmcWaitTrbEnv (Private, Trb); > > + if (EFI_ERROR (Status)) { > > + goto Done; > > + } > > + > > + Status =3D DwMmcExecTrb (Private, Trb); > > + if (EFI_ERROR (Status)) { > > + goto Done; > > + } > > + > > + Status =3D DwMmcWaitTrbResult (Private, Trb); > > + if (EFI_ERROR (Status)) { > > + goto Done; > > + } > > + > > +Done: > > + if (Trb !=3D NULL) { > > + DwMmcFreeTrb (Trb); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Used to retrieve next slot numbers supported by the SD controller. T= he > > + function returns information about all available slots (populated or > > + not-populated). > > + > > + The GetNextSlot() function retrieves the next slot number on an SD > > controller. > > + If on input Slot is 0xFF, then the slot number of the first slot on = the SD > > + controller is returned. > > + > > + If Slot is a slot number that was returned on a previous call to > > + GetNextSlot(), then the slot number of the next slot on the SD contr= oller is > > + returned. > > + > > + If Slot is not 0xFF and Slot was not returned on a previous call to > > + GetNextSlot(), EFI_INVALID_PARAMETER is returned. > > + > > + If Slot is the slot number of the last slot on the SD controller, th= en > > + EFI_NOT_FOUND is returned. > > + > > + @param[in] This A pointer to the > > EFI_SD_MMMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in,out] Slot On input, a pointer to a slot number o= n the SD > > + controller. > > + On output, a pointer to the next slot = number on > > + the SD controller. > > + An input value of 0xFF retrieves the f= irst slot > > + number on the SD controller. > > + > > + @retval EFI_SUCCESS The next slot number on the SD control= ler was > > + returned in Slot. > > + @retval EFI_NOT_FOUND There are no more slots on this SD > > controller. > > + @retval EFI_INVALID_PARAMETER Slot is not 0xFF and Slot was not > > returned on a > > + previous call to GetNextSlot(). > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcPassThruGetNextSlot ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, > > + IN OUT UINT8 *Slot > > + ) > > +{ > > + DW_MMC_HC_PRIVATE_DATA *Private; > > + > > + if ((This =3D=3D NULL) || (Slot =3D=3D NULL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (This); > > + > > + if (*Slot =3D=3D 0xFF) { > > + if (Private->Slot[0].Enable) { > > + *Slot =3D 0; > > + Private->PreviousSlot =3D 0; > > + return EFI_SUCCESS; > > + } > > + return EFI_NOT_FOUND; > > + } else if (*Slot =3D=3D Private->PreviousSlot) { > > + return EFI_NOT_FOUND; > > + } else { > > + return EFI_INVALID_PARAMETER; > > + } > > +} > > + > > +/** > > + Used to allocate and build a device path node for an SD card on the = SD > > + controller. > > + > > + The BuildDevicePath() function allocates and builds a single device = node > > + for the SD card specified by Slot. > > + > > + If the SD card specified by Slot is not present on the SD controller= , then > > + EFI_NOT_FOUND is returned. > > + > > + If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned. > > + > > + If there are not enough resources to allocate the device path node, = then > > + EFI_OUT_OF_RESOURCES is returned. > > + > > + Otherwise, DevicePath is allocated with the boot service AllocatePoo= l(), > > + the contents of DevicePath are initialized to describe the SD card s= pecified > > + by Slot, and EFI_SUCCESS is returned. > > + > > + @param[in] This A pointer to the > > EFI_SD_MMMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Slot Specifies the slot number of the SD ca= rd for > > + which a device path node is to be allo= cated and > > + built. > > + @param[in,out] DevicePath A pointer to a single device path node= that > > + describes the SD card specified by Slo= t. This > > + function is responsible for allocating= the > > + buffer DevicePath with the boot servic= e > > + AllocatePool(). It is the caller's res= ponsi- > > + bility to free DevicePath when the cal= ler is > > + finished with DevicePath. > > + > > + @retval EFI_SUCCESS The device path node that describes th= e SD > > card > > + specified by Slot was allocated and re= turned in > > + DevicePath. > > + @retval EFI_NOT_FOUND The SD card specified by Slot does not= exist > > on > > + the SD controller. > > + @retval EFI_INVALID_PARAMETER DevicePath is NULL. > > + @retval EFI_OUT_OF_RESOURCES There are not enough resources to > > allocate > > + DevicePath. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcPassThruBuildDevicePath ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, > > + IN UINT8 Slot, > > + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath > > + ) > > +{ > > + DW_MMC_HC_PRIVATE_DATA *Private; > > + SD_DEVICE_PATH *SdNode; > > + EMMC_DEVICE_PATH *EmmcNode; > > + > > + if ((This =3D=3D NULL) || (DevicePath =3D=3D NULL) || (Slot >=3D > > DW_MMC_HC_MAX_SLOT)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (This); > > + > > + if ((!Private->Slot[Slot].Enable) || (!Private->Slot[Slot].MediaPres= ent)) { > > + return EFI_NOT_FOUND; > > + } > > + > > + if (Private->Slot[Slot].CardType =3D=3D SdCardType) { > > + SdNode =3D AllocateCopyPool (sizeof (SD_DEVICE_PATH), > > &mSdDpTemplate); > > + if (SdNode =3D=3D NULL) { > > + return EFI_OUT_OF_RESOURCES; > > + } > > + SdNode->SlotNumber =3D Slot; > > + > > + *DevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *) SdNode; > > + } else if (Private->Slot[Slot].CardType =3D=3D EmmcCardType) { > > + EmmcNode =3D AllocateCopyPool (sizeof (EMMC_DEVICE_PATH), > > &mEmmcDpTemplate); > > + if (EmmcNode =3D=3D NULL) { > > + return EFI_OUT_OF_RESOURCES; > > + } > > + EmmcNode->SlotNumber =3D Slot; > > + > > + *DevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *) EmmcNode; > > + } else { > > + // > > + // Currently we only support SD and EMMC two device nodes. > > + // > > + return EFI_NOT_FOUND; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + This function retrieves an SD card slot number based on the input de= vice > > path. > > + > > + The GetSlotNumber() function retrieves slot number for the SD card > > specified > > + by the DevicePath node. If DevicePath is NULL, EFI_INVALID_PARAMETER > > is > > + returned. > > + > > + If DevicePath is not a device path node type that the SD Pass Thru d= river > > + supports, EFI_UNSUPPORTED is returned. > > + > > + @param[in] This A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] DevicePath A pointer to the device path node that > > describes > > + a SD card on the SD controller. > > + @param[out] Slot On return, points to the slot number o= f an SD > > + card on the SD controller. > > + > > + @retval EFI_SUCCESS SD card slot number is returned in Slo= t. > > + @retval EFI_INVALID_PARAMETER Slot or DevicePath is NULL. > > + @retval EFI_UNSUPPORTED DevicePath is not a device path node t= ype > > that > > + the SD Pass Thru driver supports. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcPassThruGetSlotNumber ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, > > + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, > > + OUT UINT8 *Slot > > + ) > > +{ > > + DW_MMC_HC_PRIVATE_DATA *Private; > > + SD_DEVICE_PATH *SdNode; > > + EMMC_DEVICE_PATH *EmmcNode; > > + UINT8 SlotNumber; > > + > > + if ((This =3D=3D NULL) || (DevicePath =3D=3D NULL) || (Slot =3D=3D N= ULL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (This); > > + > > + // > > + // Check whether the DevicePath belongs to SD_DEVICE_PATH or > > EMMC_DEVICE_PATH > > + // > > + if ((DevicePath->Type !=3D MESSAGING_DEVICE_PATH) || > > + ((DevicePath->SubType !=3D MSG_SD_DP) && > > + (DevicePath->SubType !=3D MSG_EMMC_DP)) || > > + (DevicePathNodeLength(DevicePath) !=3D sizeof(SD_DEVICE_PATH)) |= | > > + (DevicePathNodeLength(DevicePath) !=3D sizeof(EMMC_DEVICE_PATH))= ) > > { > > + return EFI_UNSUPPORTED; > > + } > > + > > + if (DevicePath->SubType =3D=3D MSG_SD_DP) { > > + SdNode =3D (SD_DEVICE_PATH *) DevicePath; > > + SlotNumber =3D SdNode->SlotNumber; > > + } else { > > + EmmcNode =3D (EMMC_DEVICE_PATH *) DevicePath; > > + SlotNumber =3D EmmcNode->SlotNumber; > > + } > > + > > + if (SlotNumber >=3D DW_MMC_HC_MAX_SLOT) { > > + return EFI_NOT_FOUND; > > + } > > + > > + if (Private->Slot[SlotNumber].Enable) { > > + *Slot =3D SlotNumber; > > + return EFI_SUCCESS; > > + } else { > > + return EFI_NOT_FOUND; > > + } > > +} > > + > > +/** > > + Resets an SD card that is connected to the SD controller. > > + > > + The ResetDevice() function resets the SD card specified by Slot. > > + > > + If this SD controller does not support a device reset operation, > > + EFI_UNSUPPORTED is returned. > > + > > + If Slot is not in a valid slot number for this SD controller, > > + EFI_INVALID_PARAMETER is returned. > > + > > + If the device reset operation is completed, EFI_SUCCESS is returned. > > + > > + @param[in] This A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Slot Specifies the slot number of the SD ca= rd to be > > + reset. > > + > > + @retval EFI_SUCCESS The SD card specified by Slot was rese= t. > > + @retval EFI_UNSUPPORTED The SD controller does not support a > > device > > + reset operation. > > + @retval EFI_INVALID_PARAMETER Slot number is invalid. > > + @retval EFI_NO_MEDIA SD Device not present in the Slot. > > + @retval EFI_DEVICE_ERROR The reset command failed due to a devi= ce > > error > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DwMmcPassThruResetDevice ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, > > + IN UINT8 Slot > > + ) > > +{ > > + DW_MMC_HC_PRIVATE_DATA *Private; > > + LIST_ENTRY *Link; > > + LIST_ENTRY *NextLink; > > + DW_MMC_HC_TRB *Trb; > > + EFI_TPL OldTpl; > > + > > + if (This =3D=3D NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (This); > > + > > + if (!Private->Slot[Slot].Enable) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (!Private->Slot[Slot].MediaPresent) { > > + return EFI_NO_MEDIA; > > + } > > + > > + // > > + // Free all async I/O requests in the queue > > + // > > + OldTpl =3D gBS->RaiseTPL (TPL_NOTIFY); > > + > > + for (Link =3D GetFirstNode (&Private->Queue); > > + !IsNull (&Private->Queue, Link); > > + Link =3D NextLink) { > > + NextLink =3D GetNextNode (&Private->Queue, Link); > > + RemoveEntryList (Link); > > + Trb =3D DW_MMC_HC_TRB_FROM_THIS (Link); > > + Trb->Packet->TransactionStatus =3D EFI_ABORTED; > > + gBS->SignalEvent (Trb->Event); > > + DwMmcFreeTrb (Trb); > > + } > > + > > + gBS->RestoreTPL (OldTpl); > > + > > + return EFI_SUCCESS; > > +} > > diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.c > > b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.c > > new file mode 100644 > > index 000000000000..b091f9803b2e > > --- /dev/null > > +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/DwMmcHci.c > > @@ -0,0 +1,1602 @@ > > +/** @file > > + This driver is used to manage Designware SD/MMC PCI host controllers= . > > + > > + It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer > > use. > > + > > + Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved. > > + Copyright (c) 2018, Linaro Ltd. All rights reserved.
> > + > > + This program and the accompanying materials are licensed and made > > available > > + under the terms and conditions of the BSD License which accompanies = this > > + distribution. The full text of the license may be found at > > + http://opensource.org/licenses/bsd-license.php > > + > > + 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 "DwMmcHcDxe.h" > > + > > +/** > > + Dump the content of SD/MMC host controller's Capability Register. > > + > > + @param[in] Slot The slot number of the SD card to send t= he > > + command to. > > + @param[in] Capability The buffer to store the capability data. > > + > > +**/ > > +VOID > > +DumpCapabilityReg ( > > + IN UINT8 Slot, > > + IN DW_MMC_HC_SLOT_CAP *Capability > > + ) > > +{ > > + // > > + // Dump Capability Data > > + // > > + DEBUG (( > > + DEBUG_INFO, > > + " =3D=3D Slot [%d] Capability is 0x%x =3D=3D\n", > > + Slot, > > + Capability > > + )); > > + DEBUG (( > > + DEBUG_INFO, > > + " Base Clk Freq %dKHz\n", > > + Capability->BaseClkFreq > > + )); > > + DEBUG (( > > + DEBUG_INFO, > > + " BusWidth %d\n", > > + Capability->BusWidth > > + )); > > + DEBUG (( > > + DEBUG_INFO, > > + " HighSpeed Support %a\n", > > + Capability->HighSpeed ? "TRUE" : "FALSE" > > + )); > > + DEBUG (( > > + DEBUG_INFO, > > + " Voltage 1.8 %a\n", > > + Capability->Voltage18 ? "TRUE" : "FALSE" > > + )); > > + DEBUG (( > > + DEBUG_INFO, > > + " 64-bit Sys Bus %a\n", > > + Capability->SysBus64 ? "TRUE" : "FALSE" > > + )); > > + DEBUG ((DEBUG_INFO, " SlotType ")); > > + if (Capability->SlotType =3D=3D 0x00) { > > + DEBUG ((DEBUG_INFO, "%a\n", "Removable Slot")); > > + } else if (Capability->SlotType =3D=3D 0x01) { > > + DEBUG ((DEBUG_INFO, "%a\n", "Embedded Slot")); > > + } else if (Capability->SlotType =3D=3D 0x02) { > > + DEBUG ((DEBUG_INFO, "%a\n", "Shared Bus Slot")); > > + } else { > > + DEBUG ((DEBUG_INFO, "%a\n", "Reserved")); > > + } > > + DEBUG (( > > + DEBUG_INFO, > > + " SDR50 Support %a\n", > > + Capability->Sdr50 ? "TRUE" : "FALSE" > > + )); > > + DEBUG (( > > + DEBUG_INFO, > > + " SDR104 Support %a\n", > > + Capability->Sdr104 ? "TRUE" : "FALSE" > > + )); > > + DEBUG (( > > + DEBUG_INFO, > > + " DDR50 Support %a\n", > > + Capability->Ddr50 ? "TRUE" : "FALSE" > > + )); > > + return; > > +} > > + > > +/** > > + Set all interrupt status bits in Normal and Error Interrupt Status E= nable > > + register. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + > > + @retval EFI_SUCCESS The operation executes successfully. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcEnableInterrupt ( > > + UINTN DevBase > > + ) > > +{ > > + UINT32 IntStatus; > > + UINT32 IdIntEn; > > + UINT32 IdSts; > > + > > + // > > + // Enable all bits in Interrupt Mask Register > > + // > > + IntStatus =3D 0; > > + MmioWrite32 (DevBase + DW_MMC_INTMASK, IntStatus); > > + > > + // > > + // Clear status in Interrupt Status Register > > + // > > + IntStatus =3D ~0; > > + MmioWrite32 (DevBase + DW_MMC_RINTSTS, IntStatus); > > + > > + IdIntEn =3D ~0; > > + MmioWrite32 (DevBase + DW_MMC_IDINTEN, IdIntEn); > > + > > + IdSts =3D ~0; > > + MmioWrite32 (DevBase + DW_MMC_IDSTS, IdSts); > > + > > + return EFI_SUCCESS; > > +} > > + > > +EFI_STATUS > > +DwMmcHcGetCapability ( > > + IN UINTN DevBase, > > + IN EFI_HANDLE Controller, > > + IN UINT8 Slot, > > + OUT DW_MMC_HC_SLOT_CAP *Capacity > > + ) > > +{ > > + PLATFORM_DW_MMC_PROTOCOL *PlatformDwMmc; > > + EFI_STATUS Status; > > + > > + if (Capacity =3D=3D NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + Status =3D gBS->LocateProtocol ( > > + &gPlatformDwMmcProtocolGuid, > > + NULL, > > + (VOID **) &PlatformDwMmc > > + ); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + Status =3D PlatformDwMmc->GetCapability (Controller, Slot, Capacity)= ; > > + return Status; > > +} > > + > > +/** > > + Detect whether there is a SD/MMC card attached at the specified > > SD/MMC host > > + controller slot. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 3.1 for deta= ils. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command > > + to. > > + @param[out] MediaPresent The pointer to the media present boolean > > value. > > + > > + @retval EFI_SUCCESS There is no media change happened. > > + @retval EFI_MEDIA_CHANGED There is media change happened. > > + @retval Others The detection fails. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcCardDetect ( > > + IN UINTN DevBase, > > + IN EFI_HANDLE Controller, > > + IN UINT8 Slot, > > + OUT BOOLEAN *MediaPresent > > + ) > > +{ > > + PLATFORM_DW_MMC_PROTOCOL *PlatformDwMmc; > > + EFI_STATUS Status; > > + > > + if (MediaPresent =3D=3D NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + Status =3D gBS->LocateProtocol ( > > + &gPlatformDwMmcProtocolGuid, > > + NULL, > > + (VOID **) &PlatformDwMmc > > + ); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + *MediaPresent =3D PlatformDwMmc->CardDetect (Controller, Slot); > > + return EFI_SUCCESS; > > +} > > + > > +STATIC > > +EFI_STATUS > > +DwMmcHcUpdateClock ( > > + IN UINTN DevBase > > + ) > > +{ > > + UINT32 Cmd; > > + UINT32 IntStatus; > > + > > + Cmd =3D BIT_CMD_WAIT_PRVDATA_COMPLETE | > > BIT_CMD_UPDATE_CLOCK_ONLY | > > + BIT_CMD_START; > > + MmioWrite32 (DevBase + DW_MMC_CMD, Cmd); > > + > > + while (1) { > > + Cmd =3D MmioRead32 (DevBase + DW_MMC_CMD); > > + > > + if (!(Cmd & CMD_START_BIT)) { > > + break; > > + } > > + > > + IntStatus =3D MmioRead32 (DevBase + DW_MMC_RINTSTS); > > + > > + if (IntStatus & DW_MMC_INT_HLE) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "DwMmcHcUpdateClock: failed to update mmc clock frequency\n" > > + )); > > + return EFI_DEVICE_ERROR; > > + } > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Stop SD/MMC card clock. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + > > + @retval EFI_SUCCESS Succeed to stop SD/MMC clock. > > + @retval Others Fail to stop SD/MMC clock. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcStopClock ( > > + IN UINTN DevBase > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT32 ClkEna; > > + > > + // > > + // Disable MMC clock first > > + // > > + ClkEna =3D 0; > > + MmioWrite32 (DevBase + DW_MMC_CLKENA, ClkEna); > > + > > + Status =3D DwMmcHcUpdateClock (DevBase); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + return Status; > > +} > > + > > +/** > > + SD/MMC card clock supply. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] ClockFreq The max clock frequency to be set. The uni= t is > > KHz. > > + @param[in] Capability The capability of the slot. > > + > > + @retval EFI_SUCCESS The clock is supplied successfully. > > + @retval Others The clock isn't supplied successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcClockSupply ( > > + IN UINTN DevBase, > > + IN UINT64 ClockFreq, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT32 BaseClkFreq; > > + UINT32 SettingFreq; > > + UINT32 Divisor; > > + UINT32 Remainder; > > + UINT32 MmcStatus; > > + UINT32 ClkEna; > > + UINT32 ClkSrc; > > + > > + // > > + // Calculate a divisor for SD clock frequency > > + // > > + ASSERT (Capability.BaseClkFreq !=3D 0); > > + > > + BaseClkFreq =3D Capability.BaseClkFreq; > > + if (ClockFreq =3D=3D 0) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (ClockFreq > BaseClkFreq) { > > + ClockFreq =3D BaseClkFreq; > > + } > > + > > + // > > + // Calculate the divisor of base frequency. > > + // > > + Divisor =3D 0; > > + SettingFreq =3D BaseClkFreq; > > + while (ClockFreq < SettingFreq) { > > + Divisor++; > > + > > + SettingFreq =3D BaseClkFreq / (2 * Divisor); > > + Remainder =3D BaseClkFreq % (2 * Divisor); > > + if ((ClockFreq =3D=3D SettingFreq) && (Remainder =3D=3D 0)) { > > + break; > > + } > > + if ((ClockFreq =3D=3D SettingFreq) && (Remainder !=3D 0)) { > > + SettingFreq ++; > > + } > > + } > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "BaseClkFreq %dKHz Divisor %d ClockFreq %dKhz\n", > > + BaseClkFreq, > > + Divisor, > > + ClockFreq > > + )); > > + > > + // > > + // Wait until MMC is idle > > + // > > + do { > > + MmcStatus =3D MmioRead32 (DevBase + DW_MMC_STATUS); > > + } while (MmcStatus & DW_MMC_STS_DATA_BUSY); > > + > > + do { > > + Status =3D DwMmcHcStopClock (DevBase); > > + } while (EFI_ERROR (Status)); > > + > > + do { > > + ClkSrc =3D 0; > > + MmioWrite32 (DevBase + DW_MMC_CLKSRC, ClkSrc); > > + // > > + // Set clock divisor > > + // > > + MmioWrite32 (DevBase + DW_MMC_CLKDIV, Divisor); > > + // > > + // Enable MMC clock > > + // > > + ClkEna =3D 1; > > + MmioWrite32 (DevBase + DW_MMC_CLKENA, ClkEna); > > + > > + Status =3D DwMmcHcUpdateClock (DevBase); > > + } while (EFI_ERROR (Status)); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Set the SD/MMC bus width. > > + > > + Refer to SD Host Controller Simplified spec 3.0 Section 3.4 for deta= ils. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] IsDdr A boolean to indicate it's dual data rate = or not. > > + @param[in] BusWidth The bus width used by the SD/MMC device, i= t > > must be > > + 1, 4 or 8. > > + > > + @retval EFI_SUCCESS The bus width is set successfully. > > + @retval Others The bus width isn't set successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcSetBusWidth ( > > + IN UINTN DevBase, > > + IN BOOLEAN IsDdr, > > + IN UINT16 BusWidth > > + ) > > +{ > > + UINT32 Ctype; > > + UINT32 Uhs; > > + > > + switch (BusWidth) { > > + case 1: > > + Ctype =3D MMC_1BIT_MODE; > > + break; > > + case 4: > > + Ctype =3D MMC_4BIT_MODE; > > + break; > > + case 8: > > + Ctype =3D MMC_8BIT_MODE; > > + break; > > + default: > > + return EFI_INVALID_PARAMETER; > > + } > > + MmioWrite32 (DevBase + DW_MMC_CTYPE, Ctype); > > + > > + Uhs =3D MmioRead32 (DevBase + DW_MMC_UHSREG); > > + > > + if (IsDdr) { > > + Uhs |=3D UHS_DDR_MODE; > > + } else { > > + Uhs &=3D ~(UHS_DDR_MODE); > > + } > > + > > + MmioWrite32 (DevBase + DW_MMC_UHSREG, Uhs); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Supply SD/MMC card with lowest clock frequency at initialization. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Capability The capability of the slot. > > + > > + @retval EFI_SUCCESS The clock is supplied successfully. > > + @retval Others The clock isn't supplied successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcInitClockFreq ( > > + IN UINTN DevBase, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT32 InitFreq; > > + > > + // > > + // Calculate a divisor for SD clock frequency > > + // > > + if (Capability.BaseClkFreq =3D=3D 0) { > > + // > > + // Don't support get Base Clock Frequency information via another > > method > > + // > > + return EFI_UNSUPPORTED; > > + } > > + // > > + // Supply 400KHz clock frequency at initialization phase. > > + // > > + InitFreq =3D DWMMC_INIT_CLOCK_FREQ; > > + Status =3D DwMmcHcClockSupply (DevBase, InitFreq, Capability); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + MicroSecondDelay (100); > > + return Status; > > +} > > + > > +/** > > + Supply SD/MMC card with maximum voltage at initialization. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Capability The capability of the slot. > > + > > + @retval EFI_SUCCESS The voltage is supplied successfully. > > + @retval Others The voltage isn't supplied successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcInitPowerVoltage ( > > + IN UINTN DevBase, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ) > > +{ > > + UINT32 Data; > > + UINT32 Timeout; > > + > > + Data =3D 0x1; > > + MmioWrite32 (DevBase + DW_MMC_PWREN, Data); > > + > > + Data =3D DW_MMC_CTRL_RESET_ALL; > > + MmioWrite32 (DevBase + DW_MMC_CTRL, Data); > > + > > + Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + while (Timeout > 0) { > > + Data =3D MmioRead32 (DevBase + DW_MMC_CTRL); > > + > > + if ((Data & DW_MMC_CTRL_RESET_ALL) =3D=3D 0) { > > + break; > > + } > > + gBS->Stall (1); > > + > > + Timeout--; > > + } > > + > > + if (Timeout <=3D 0) { > > + DEBUG ((DEBUG_INFO, > > + "DwMmcHcInitPowerVoltage: reset failed due to timeout")); > > + > > + return EFI_TIMEOUT; > > + } > > + > > + Data =3D DW_MMC_CTRL_INT_EN; > > + MmioWrite32 (DevBase + DW_MMC_CTRL, Data); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Initialize the Timeout Control register with most conservative value= at > > + initialization. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + > > + @retval EFI_SUCCESS The timeout control register is configured > > + successfully. > > + @retval Others The timeout control register isn't configu= red > > + successfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcInitTimeoutCtrl ( > > + IN UINTN DevBase > > + ) > > +{ > > + UINT32 Data; > > + > > + Data =3D ~0; > > + MmioWrite32 (DevBase + DW_MMC_TMOUT, Data); > > + > > + Data =3D 0x00FFFFFF; > > + MmioWrite32 (DevBase + DW_MMC_DEBNCE, Data); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Initial SD/MMC host controller with lowest clock frequency, max powe= r > > and > > + max timeout value at initialization. > > + > > + @param[in] DevIo The DEVICE IO protocol instance. > > + @param[in] Slot The slot number of the SD card to send the > > command > > + to. > > + @param[in] Capability The capability of the slot. > > + > > + @retval EFI_SUCCESS The host controller is initialized success= fully. > > + @retval Others The host controller isn't initialized succ= essfully. > > + > > +**/ > > +EFI_STATUS > > +DwMmcHcInitHost ( > > + IN UINTN DevBase, > > + IN DW_MMC_HC_SLOT_CAP Capability > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + Status =3D DwMmcHcInitPowerVoltage (DevBase, Capability); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + return Status; > > +} > > + > > +EFI_STATUS > > +DwMmcHcStartDma ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ) > > +{ > > + UINTN DevBase; > > + UINT32 Ctrl; > > + UINT32 Bmod; > > + UINT32 Timeout; > > + UINT32 Data; > > + > > +// DevIo =3D Trb->Private->DevIo; > > + DevBase =3D Trb->Private->DevBase; > > + > > + // > > + // Reset DMA > > + // > > + Ctrl =3D DW_MMC_CTRL_DMA_RESET; > > + MmioWrite32 (DevBase + DW_MMC_CTRL, Ctrl); > > + > > + Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + while (Timeout > 0) { > > + Data =3D MmioRead32 (DevBase + DW_MMC_CTRL); > > + > > + if ((Data & DW_MMC_CTRL_DMA_RESET) =3D=3D 0) { > > + break; > > + } > > + gBS->Stall (1); > > + > > + Timeout--; > > + } > > + > > + if (Timeout <=3D 0) { > > + DEBUG ((DEBUG_ERROR, "Timed out waiting for CTRL_DMA_RESET")); > > + > > + return EFI_TIMEOUT; > > + } > > + > > + Bmod =3D DW_MMC_IDMAC_SWRESET | MmioRead32 (DevBase + > > DW_MMC_BMOD); > > + > > + MmioWrite32 (DevBase + DW_MMC_BMOD, Bmod); > > + > > + // > > + // Select IDMAC > > + // > > + Ctrl =3D DW_MMC_CTRL_IDMAC_EN; > > + Ctrl |=3D MmioRead32 (DevBase + DW_MMC_CTRL); > > + MmioWrite32 (DevBase + DW_MMC_CTRL, Ctrl); > > + > > + // > > + // Enable IDMAC > > + // > > + Bmod =3D DW_MMC_IDMAC_ENABLE | DW_MMC_IDMAC_FB; > > + Bmod |=3D MmioRead32 (DevBase + DW_MMC_BMOD); > > + > > + MmioWrite32 (DevBase + DW_MMC_BMOD, Bmod); > > + > > + return EFI_SUCCESS; > > +} > > + > > +EFI_STATUS > > +DwMmcHcStopDma ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ) > > +{ > > + UINTN DevBase; > > + UINT32 Ctrl; > > + UINT32 Bmod; > > + > > + DevBase =3D Trb->Private->DevBase; > > + > > + // > > + // Disable and reset IDMAC > > + // > > + Ctrl =3D MmioRead32 (DevBase + DW_MMC_CTRL); > > + Ctrl &=3D ~DW_MMC_CTRL_IDMAC_EN; > > + Ctrl |=3D DW_MMC_CTRL_DMA_RESET; > > + MmioWrite32 (DevBase + DW_MMC_CTRL, Ctrl); > > + > > + // > > + // Stop IDMAC > > + // > > + Bmod =3D MmioRead32 (DevBase + DW_MMC_BMOD); > > + Bmod &=3D ~(DW_MMC_BMOD_FB | DW_MMC_BMOD_DE); > > + Bmod |=3D DW_MMC_BMOD_SWR; > > + MmioWrite32 (DevBase + DW_MMC_BMOD, Bmod); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Build DMA descriptor table for transfer. > > + > > + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance. > > + > > + @retval EFI_SUCCESS The DMA descriptor table is created succes= sfully. > > + @retval Others The DMA descriptor table isn't created suc= cessfully. > > + > > +**/ > > +EFI_STATUS > > +BuildDmaDescTable ( > > + IN DW_MMC_HC_TRB *Trb > > + ) > > +{ > > + EFI_PHYSICAL_ADDRESS Data; > > + UINT64 DataLen; > > + UINT64 Entries; > > + UINT32 Index; > > + UINT64 Remaining; > > + UINTN TableSize; > > + UINTN DevBase; > > + EFI_STATUS Status; > > + UINTN Bytes; > > + UINTN Blocks; > > + DW_MMC_HC_DMA_DESC_LINE *DmaDesc; > > + UINT32 DmaDescPhy; > > + UINT32 Idsts; > > + UINT32 BytCnt; > > + UINT32 BlkSize; > > + > > + Data =3D Trb->DataPhy; > > + DataLen =3D Trb->DataLen; > > + DevBase =3D Trb->Private->DevBase; > > + // > > + // Only support 32bit DMA Descriptor Table > > + // > > + if ((Data >=3D 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))= { > > + return EFI_INVALID_PARAMETER; > > + } > > + // > > + // Address field shall be set on 32-bit boundary (Lower 2-bit is alw= ays set > > + // to 0) for 32-bit address descriptor table. > > + // > > + if ((Data & (BIT0 | BIT1)) !=3D 0) { > > + DEBUG (( > > + DEBUG_INFO, > > + "The buffer [0x%x] to construct DMA desc is not aligned to 4 byt= es!\n", > > + Data > > + )); > > + } > > + > > + Entries =3D (DataLen + DWMMC_DMA_BUF_SIZE - 1) / > > DWMMC_DMA_BUF_SIZE; > > + TableSize =3D Entries * sizeof (DW_MMC_HC_DMA_DESC_LINE); > > + Blocks =3D (DataLen + DW_MMC_BLOCK_SIZE - 1) / > > DW_MMC_BLOCK_SIZE; > > + > > + Trb->DmaDescPages =3D (UINT32)EFI_SIZE_TO_PAGES (Entries * > > DWMMC_DMA_BUF_SIZE); > > +/* Status =3D DevIo->AllocateBuffer ( > > + DevIo, > > + AllocateAnyPages, > > + EfiBootServicesData, > > + EFI_SIZE_TO_PAGES (TableSize), > > + (EFI_PHYSICAL_ADDRESS *)&Trb->DmaDesc > > + );*/ > > + Status =3D DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES > > (TableSize), > > + (VOID *)&Trb->DmaDesc); > > + if (EFI_ERROR (Status)) { > > + return EFI_OUT_OF_RESOURCES; > > + } > > + > > + ZeroMem (Trb->DmaDesc, TableSize); > > + Bytes =3D TableSize; > > + > > + Status =3D DmaMap (MapOperationBusMasterCommonBuffer, > > + (EFI_PHYSICAL_ADDRESS *)Trb->DmaDesc, > > + &Bytes, &Trb->DmaDescPhy, &Trb->DmaMap); > > +/* Status =3D DevIo->Map ( > > + DevIo, > > + EfiBusMasterCommonBuffer, > > + (EFI_PHYSICAL_ADDRESS *)Trb->DmaDesc, > > + &Bytes, > > + &Trb->DmaDescPhy, > > + &Trb->DmaMap > > + );*/ > > + > > + if (EFI_ERROR (Status) || (Bytes !=3D TableSize)) { > > + // > > + // Map error or unable to map the whole RFis buffer into a contigu= ous > > + // region. > > + // > > +/* DevIo->FreeBuffer ( > > + DevIo, > > + EFI_SIZE_TO_PAGES (TableSize), > > + (EFI_PHYSICAL_ADDRESS)Trb->DmaDesc > > + );*/ > > + return EFI_OUT_OF_RESOURCES; > > + } > > + > > + if ((UINT64)(UINTN)Trb->DmaDescPhy > 0x100000000ul) { > > + // > > + // The DMA doesn't support 64bit addressing. > > + // > > + DmaUnmap (Trb->DmaMap); > > +/* DevIo->Unmap ( > > + DevIo, > > + Trb->DmaMap > > + );*/ > > + return EFI_DEVICE_ERROR; > > + } > > + > > + if (DataLen < DW_MMC_BLOCK_SIZE) { > > + BlkSize =3D DataLen; > > + BytCnt =3D DataLen; > > + Remaining =3D DataLen; > > + } else { > > + BlkSize =3D DW_MMC_BLOCK_SIZE; > > + BytCnt =3D DW_MMC_BLOCK_SIZE * Blocks; > > + Remaining =3D DW_MMC_BLOCK_SIZE * Blocks; > > + } > > + > > + MmioWrite32 (DevBase + DW_MMC_BLKSIZ, BlkSize); > > + MmioWrite32 (DevBase + DW_MMC_BYTCNT, BytCnt); > > + DmaDesc =3D Trb->DmaDesc; > > + for (Index =3D 0; Index < Entries; Index++, DmaDesc++) { > > + DmaDesc->Des0 =3D DW_MMC_IDMAC_DES0_OWN | > > DW_MMC_IDMAC_DES0_CH | > > + DW_MMC_IDMAC_DES0_DIC; > > + DmaDesc->Des1 =3D DW_MMC_IDMAC_DES1_BS1 > > (DWMMC_DMA_BUF_SIZE); > > + // > > + // Buffer Address > > + // > > + DmaDesc->Des2 =3D (UINT32)((UINTN)Trb->DataPhy + > > + (DWMMC_DMA_BUF_SIZE * Index)); > > + // > > + // Next Descriptor Address > > + // > > + DmaDesc->Des3 =3D (UINT32)((UINTN)Trb->DmaDescPhy + > > + sizeof (DW_MMC_HC_DMA_DESC_LINE) * (Index + 1)); > > + Remaining =3D Remaining - DWMMC_DMA_BUF_SIZE; > > + } > > + // > > + // First Descriptor > > + // > > + Trb->DmaDesc[0].Des0 |=3D DW_MMC_IDMAC_DES0_FS; > > + // > > + // Last Descriptor > > + // > > + Trb->DmaDesc[Entries - 1].Des0 &=3D ~(DW_MMC_IDMAC_DES0_CH | > > + DW_MMC_IDMAC_DES0_DIC); > > + Trb->DmaDesc[Entries - 1].Des0 |=3D DW_MMC_IDMAC_DES0_OWN | > > + DW_MMC_IDMAC_DES0_LD; > > + Trb->DmaDesc[Entries - 1].Des1 =3D DW_MMC_IDMAC_DES1_BS1 > > (Remaining + > > + DWMMC_DMA_BUF_SIZE); > > + // > > + // Set the next field of the Last Descriptor > > + // > > + Trb->DmaDesc[Entries - 1].Des3 =3D 0; > > + DmaDescPhy =3D (UINT32)Trb->DmaDescPhy; > > + > > + MmioWrite32 (DevBase + DW_MMC_DBADDR, DmaDescPhy); > > + > > + ArmDataSynchronizationBarrier (); > > + ArmInstructionSynchronizationBarrier (); > > + // > > + // Clear interrupts > > + // > > + Idsts =3D ~0; > > + MmioWrite32 (DevBase + DW_MMC_IDSTS, Idsts); > > + > > + return Status; > > +} > > + > > +EFI_STATUS > > +TransferFifo ( > > + IN DW_MMC_HC_TRB *Trb > > + ) > > +{ > > + UINTN DevBase; > > + UINT32 Data; > > + UINT32 Received; > > + UINT32 Count; > > + UINT32 Intsts; > > + UINT32 Sts; > > + UINT32 FifoCount; > > + UINT32 Index; /* count with bytes */ > > + UINT32 Ascending; > > + UINT32 Descending; > > + > > + DevBase =3D Trb->Private->DevBase; > > + Received =3D 0; > > + Count =3D 0; > > + Index =3D 0; > > + Ascending =3D 0; > > + Descending =3D ((Trb->DataLen + 3) & ~3) - 4; > > + do { > > + Intsts =3D MmioRead32 (DevBase + DW_MMC_RINTSTS); > > + > > + if (Trb->DataLen && (Intsts & DW_MMC_INT_TXDR) && !Trb->Read) { > > + Sts =3D MmioRead32 (DevBase + DW_MMC_STATUS); > > + > > + while (!(DW_MMC_STS_FIFO_FULL(Sts)) > > + && (Received < Trb->DataLen) > > + && (Intsts & DW_MMC_INT_TXDR)) { > > + if (Trb->UseBE) { > > + Data =3D SwapBytes32 (*(UINT32 *)((UINTN)Trb->Data + Descend= ing)); > > + Descending =3D Descending - 4; > > + } else { > > + Data =3D *(UINT32 *)((UINTN)Trb->Data + Ascending); > > + Ascending +=3D 4; > > + } > > + Index +=3D 4; > > + Received +=3D 4; > > + > > + MmioWrite32 (DevBase + DW_MMC_FIFO_START, Data); > > + > > + Intsts =3D DW_MMC_INT_TXDR; > > + MmioWrite32 (DevBase + DW_MMC_RINTSTS, Intsts); > > + > > + Intsts =3D MmioRead32 (DevBase + DW_MMC_RINTSTS); > > + Sts =3D MmioRead32 (DevBase + DW_MMC_STATUS); > > + } > > + continue; > > + } > > + > > + if (Trb->DataLen && ((Intsts & DW_MMC_INT_RXDR) || > > + (Intsts & DW_MMC_INT_DTO)) && Trb->Read) { > > + Sts =3D MmioRead32 (DevBase + DW_MMC_STATUS); > > + // > > + // Convert to bytes > > + // > > + FifoCount =3D GET_STS_FIFO_COUNT (Sts) << 2; > > + if ((FifoCount =3D=3D 0) && (Received < Trb->DataLen)) { > > + continue; > > + } > > + Index =3D 0; > > + Count =3D (MIN (FifoCount, Trb->DataLen) + 3) & ~3; > > + while (Index < Count) { > > + Data =3D MmioRead32 (DevBase + DW_MMC_FIFO_START); > > + > > + if (Trb->UseBE) { > > + *(UINT32 *)((UINTN)Trb->Data + Descending) =3D SwapBytes32 (= Data); > > + Descending =3D Descending - 4; > > + } else { > > + *(UINT32 *)((UINTN)Trb->Data + Ascending) =3D Data; > > + Ascending +=3D 4; > > + } > > + Index +=3D 4; > > + Received +=3D 4; > > + } /* while */ > > + } /* if */ > > + } while (((Intsts & DW_MMC_INT_CMD_DONE) =3D=3D 0) || (Received < Tr= b- > > >DataLen)); > > + // > > + // Clear RINTSTS > > + // > > + Intsts =3D ~0; > > + MmioWrite32 (DevBase + DW_MMC_RINTSTS, Intsts); > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Create a new TRB for the SD/MMC cmd request. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + @param[in] Slot The slot number of the SD card to send the > > command > > + to. > > + @param[in] Packet A pointer to the SD command data structure= . > > + @param[in] Event If Event is NULL, blocking I/O is performe= d. If > > + Event is not NULL, then nonblocking I/O is > > + performed, and Event will be signaled when= the > > + Packet completes. > > + > > + @return Created Trb or NULL. > > + > > +**/ > > +DW_MMC_HC_TRB * > > +DwMmcCreateTrb ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN UINT8 Slot, > > + IN EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet, > > + IN EFI_EVENT Event > > + ) > > +{ > > + DW_MMC_HC_TRB *Trb; > > + EFI_STATUS Status; > > + EFI_TPL OldTpl; > > + EFI_IO_OPERATION_TYPE Flag; > > + UINTN MapLength; > > + > > + Trb =3D AllocateZeroPool (sizeof (DW_MMC_HC_TRB)); > > + if (Trb =3D=3D NULL) { > > + return NULL; > > + } > > + > > + Trb->Signature =3D DW_MMC_HC_TRB_SIG; > > + Trb->Slot =3D Slot; > > + Trb->BlockSize =3D 0x200; > > + Trb->Packet =3D Packet; > > + Trb->Event =3D Event; > > + Trb->Started =3D FALSE; > > + Trb->Timeout =3D Packet->Timeout; > > + Trb->Private =3D Private; > > + > > + if ((Packet->InTransferLength !=3D 0) && (Packet->InDataBuffer !=3D = NULL)) { > > + Trb->Data =3D Packet->InDataBuffer; > > + Trb->DataLen =3D Packet->InTransferLength; > > + Trb->Read =3D TRUE; > > + ZeroMem (Trb->Data, Trb->DataLen); > > + } else if (Packet->OutTransferLength && (Packet->OutDataBuffer !=3D > > NULL)) { > > + Trb->Data =3D Packet->OutDataBuffer; > > + Trb->DataLen =3D Packet->OutTransferLength; > > + Trb->Read =3D FALSE; > > + } else if (!Packet->InTransferLength && !Packet->OutTransferLength) = { > > + Trb->Data =3D NULL; > > + Trb->DataLen =3D 0; > > + } else { > > + goto Error; > > + } > > + > > + if (((Private->Slot[Trb->Slot].CardType =3D=3D EmmcCardType) && > > + (Packet->SdMmcCmdBlk->CommandIndex =3D=3D > > EMMC_SEND_TUNING_BLOCK)) || > > + ((Private->Slot[Trb->Slot].CardType =3D=3D SdCardType) && > > + (Packet->SdMmcCmdBlk->CommandIndex =3D=3D > > SD_SEND_TUNING_BLOCK))) { > > + Trb->Mode =3D SdMmcPioMode; > > + } else { > > + if (Trb->Read) { > > + Flag =3D EfiBusMasterWrite; > > + } else { > > + Flag =3D EfiBusMasterRead; > > + } > > + > > + if (Private->Slot[Trb->Slot].CardType =3D=3D SdCardType) { > > + Trb->UseFifo =3D TRUE; > > + } else { > > + Trb->UseFifo =3D FALSE; > > + if (Trb->DataLen) { > > + MapLength =3D Trb->DataLen; > > + Status =3D DmaMap (Flag, Trb->Data, &MapLength, &Trb->DataPhy,= &Trb- > > >DataMap); > > +/* Status =3D DevIo->Map ( > > + DevIo, > > + Flag, > > + Trb->Data, > > + &MapLength, > > + &Trb->DataPhy, > > + &Trb->DataMap > > + );*/ > > + if (EFI_ERROR (Status) || (Trb->DataLen !=3D MapLength)) { > > + Status =3D EFI_BAD_BUFFER_SIZE; > > + goto Error; > > + } > > + > > + Status =3D BuildDmaDescTable (Trb); > > + if (EFI_ERROR (Status)) { > > + DmaUnmap(Trb->DataMap); > > + goto Error; > > + } > > + Status =3D DwMmcHcStartDma (Private, Trb); > > + if (EFI_ERROR (Status)) { > > + DmaUnmap(Trb->DataMap); > > + goto Error; > > + } > > + } > > + } > > + } /* TuningBlock */ > > + > > + if (Event !=3D NULL) { > > + OldTpl =3D gBS->RaiseTPL (TPL_NOTIFY); > > + InsertTailList (&Private->Queue, &Trb->TrbList); > > + gBS->RestoreTPL (OldTpl); > > + } > > + > > + return Trb; > > + > > +Error: > > + return NULL; > > +} > > + > > +/** > > + Free the resource used by the TRB. > > + > > + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance. > > + > > +**/ > > +VOID > > +DwMmcFreeTrb ( > > + IN DW_MMC_HC_TRB *Trb > > + ) > > +{ > > + if (Trb->DmaMap !=3D NULL) { > > + DmaUnmap (Trb->DmaMap); > > + } > > + if (Trb->DataMap !=3D NULL) { > > + DmaUnmap (Trb->DataMap); > > + } > > + FreePool (Trb); > > +} > > + > > +/** > > + Check if the env is ready for execute specified TRB. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance. > > + > > + @retval EFI_SUCCESS The env is ready for TRB execution. > > + @retval EFI_NOT_READY The env is not ready for TRB execution. > > + @retval Others Some erros happen. > > + > > +**/ > > +EFI_STATUS > > +DwMmcCheckTrbEnv ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ) > > +{ > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Wait for the env to be ready for execute specified TRB. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance. > > + > > + @retval EFI_SUCCESS The env is ready for TRB execution. > > + @retval EFI_TIMEOUT The env is not ready for TRB execution in = time. > > + @retval Others Some erros happen. > > + > > +**/ > > +EFI_STATUS > > +DwMmcWaitTrbEnv ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; > > + UINT64 Timeout; > > + BOOLEAN InfiniteWait; > > + > > + // > > + // Wait Command Complete Interrupt Status bit in Normal Interrupt St= atus > > + // Register > > + // > > + Packet =3D Trb->Packet; > > + Timeout =3D Packet->Timeout; > > + if (Timeout =3D=3D 0) { > > + InfiniteWait =3D TRUE; > > + } else { > > + InfiniteWait =3D FALSE; > > + } > > + > > + while (InfiniteWait || (Timeout > 0)) { > > + // > > + // Check Trb execution result by reading Normal Interrupt Status r= egister. > > + // > > + Status =3D DwMmcCheckTrbEnv (Private, Trb); > > + if (Status !=3D EFI_NOT_READY) { > > + return Status; > > + } > > + // > > + // Stall for 1 microsecond. > > + // > > + gBS->Stall (1); > > + > > + Timeout--; > > + } > > + > > + return EFI_TIMEOUT; > > +} > > + > > +EFI_STATUS > > +DwEmmcExecTrb ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ) > > +{ > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; > > + UINTN DevBase; > > + UINT32 Cmd; > > + UINT32 MmcStatus; > > + UINT32 IntStatus; > > + UINT32 Argument; > > + UINT32 ErrMask; > > + UINT32 Timeout; > > + > > + Packet =3D Trb->Packet; > > + DevBase =3D Trb->Private->DevBase; > > + > > + ArmDataSynchronizationBarrier (); > > + ArmInstructionSynchronizationBarrier (); > > + // > > + // Wait until MMC is idle > > + // > > + do { > > + MmcStatus =3D MmioRead32 (DevBase + DW_MMC_STATUS); > > + } while (MmcStatus & DW_MMC_STS_DATA_BUSY); > > + > > + IntStatus =3D ~0; > > + MmioWrite32 (DevBase + DW_MMC_RINTSTS, IntStatus); > > + Cmd =3D CMD_INDEX (Packet->SdMmcCmdBlk->CommandIndex); > > + if ((Packet->SdMmcCmdBlk->CommandType =3D=3D SdMmcCommandTypeAc) > > || > > + (Packet->SdMmcCmdBlk->CommandType =3D=3D > > SdMmcCommandTypeAdtc)) { > > + switch (Packet->SdMmcCmdBlk->CommandIndex) { > > + case EMMC_SET_RELATIVE_ADDR: > > + Cmd |=3D BIT_CMD_SEND_INIT; > > + break; > > + case EMMC_SEND_STATUS: > > + Cmd |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE; > > + break; > > + case EMMC_STOP_TRANSMISSION: > > + Cmd |=3D BIT_CMD_STOP_ABORT_CMD; > > + break; > > + } > > + if (Packet->InTransferLength) { > > + Cmd |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE | > > BIT_CMD_DATA_EXPECTED | > > + BIT_CMD_READ; > > + } else if (Packet->OutTransferLength) { > > + Cmd |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE | > > BIT_CMD_DATA_EXPECTED | > > + BIT_CMD_WRITE; > > + } > > + Cmd |=3D BIT_CMD_RESPONSE_EXPECT | > > BIT_CMD_CHECK_RESPONSE_CRC; > > + } else { > > + switch (Packet->SdMmcCmdBlk->CommandIndex) { > > + case EMMC_GO_IDLE_STATE: > > + Cmd |=3D BIT_CMD_SEND_INIT; > > + break; > > + case EMMC_SEND_OP_COND: > > + Cmd |=3D BIT_CMD_RESPONSE_EXPECT; > > + break; > > + case EMMC_ALL_SEND_CID: > > + Cmd |=3D BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE | > > + BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_SEND_INIT; > > + break; > > + } > > + } > > + switch (Packet->SdMmcCmdBlk->ResponseType) { > > + case SdMmcResponseTypeR2: > > + Cmd |=3D BIT_CMD_RESPONSE_EXPECT | > > BIT_CMD_CHECK_RESPONSE_CRC | > > + BIT_CMD_LONG_RESPONSE; > > + break; > > + case SdMmcResponseTypeR3: > > + Cmd |=3D BIT_CMD_RESPONSE_EXPECT; > > + break; > > + } > > + Cmd |=3D BIT_CMD_USE_HOLD_REG | BIT_CMD_START; > > + > > + Argument =3D Packet->SdMmcCmdBlk->CommandArgument; > > + MmioWrite32 (DevBase + DW_MMC_CMDARG, Argument); > > + > > + ArmDataSynchronizationBarrier (); > > + ArmInstructionSynchronizationBarrier (); > > + > > + MmioWrite32 (DevBase + DW_MMC_CMD, Cmd); > > + ArmDataSynchronizationBarrier (); > > + ArmInstructionSynchronizationBarrier (); > > + > > + ErrMask =3D DW_MMC_INT_EBE | DW_MMC_INT_HLE | > > DW_MMC_INT_RTO | > > + DW_MMC_INT_RCRC | DW_MMC_INT_RE; > > + ErrMask |=3D DW_MMC_INT_DCRC | DW_MMC_INT_DRT | > > DW_MMC_INT_SBE; > > + do { > > + Timeout =3D 10000; > > + if (--Timeout =3D=3D 0) { > > + break; > > + } > > + IntStatus =3D MmioRead32 (DevBase + DW_MMC_RINTSTS); > > + if (IntStatus & ErrMask) { > > + return EFI_DEVICE_ERROR; > > + } > > + if (Trb->DataLen && ((IntStatus & DW_MMC_INT_DTO) =3D=3D 0)) { > > + // > > + // Transfer Not Done > > + // > > + MicroSecondDelay (10); > > + continue; > > + } > > + MicroSecondDelay (10); > > + } while (!(IntStatus & DW_MMC_INT_CMD_DONE)); > > + switch (Packet->SdMmcCmdBlk->ResponseType) { > > + case SdMmcResponseTypeR1: > > + case SdMmcResponseTypeR1b: > > + case SdMmcResponseTypeR3: > > + case SdMmcResponseTypeR4: > > + case SdMmcResponseTypeR5: > > + Packet->SdMmcStatusBlk->Resp0 =3D MmioRead32 (DevBase + > > DW_MMC_RESP0); > > + break; > > + case SdMmcResponseTypeR2: > > + Packet->SdMmcStatusBlk->Resp0 =3D MmioRead32 (DevBase + > > DW_MMC_RESP0); > > + Packet->SdMmcStatusBlk->Resp1 =3D MmioRead32 (DevBase + > > DW_MMC_RESP1); > > + Packet->SdMmcStatusBlk->Resp2 =3D MmioRead32 (DevBase + > > DW_MMC_RESP2); > > + Packet->SdMmcStatusBlk->Resp3 =3D MmioRead32 (DevBase + > > DW_MMC_RESP3); > > + break; > > + } > > + > > + // > > + // The workaround on EMMC_SEND_CSD is used to be compatible with > > SDHC. > > + // > > + if (Packet->SdMmcCmdBlk->CommandIndex =3D=3D EMMC_SEND_CSD) { > > + { > > + UINT32 Buf[4]; > > + ZeroMem (Buf, sizeof (Buf)); > > + CopyMem ( > > + (UINT8 *)Buf, > > + (UINT8 *)&Packet->SdMmcStatusBlk->Resp0 + 1, > > + sizeof (Buf) - 1 > > + ); > > + CopyMem ( > > + (UINT8 *)&Packet->SdMmcStatusBlk->Resp0, > > + (UINT8 *)Buf, > > + sizeof (Buf) - 1 > > + ); > > + } > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +EFI_STATUS > > +DwSdExecTrb ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ) > > +{ > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; > > + UINTN DevBase; > > + UINT32 Cmd; > > + UINT32 MmcStatus; > > + UINT32 IntStatus; > > + UINT32 Argument; > > + UINT32 ErrMask; > > + UINT32 Timeout; > > + UINT32 Idsts; > > + UINT32 BytCnt; > > + UINT32 BlkSize; > > + EFI_STATUS Status; > > + > > + Packet =3D Trb->Packet; > > + DevBase =3D Trb->Private->DevBase; > > + > > + ArmDataSynchronizationBarrier (); > > + ArmInstructionSynchronizationBarrier (); > > + // > > + // Wait until MMC is idle > > + // > > + do { > > + MmcStatus =3D MmioRead32 (DevBase + DW_MMC_STATUS); > > + } while (MmcStatus & DW_MMC_STS_DATA_BUSY); > > + > > + IntStatus =3D ~0; > > + MmioWrite32 (DevBase + DW_MMC_RINTSTS, IntStatus); > > + Cmd =3D CMD_INDEX (Packet->SdMmcCmdBlk->CommandIndex); > > + if ((Packet->SdMmcCmdBlk->CommandType =3D=3D SdMmcCommandTypeAc) > > || > > + (Packet->SdMmcCmdBlk->CommandType =3D=3D > > SdMmcCommandTypeAdtc)) { > > + switch (Packet->SdMmcCmdBlk->CommandIndex) { > > + case SD_SET_RELATIVE_ADDR: > > + Cmd |=3D BIT_CMD_SEND_INIT; > > + break; > > + case SD_STOP_TRANSMISSION: > > + Cmd |=3D BIT_CMD_STOP_ABORT_CMD; > > + break; > > + case SD_SEND_SCR: > > + Trb->UseBE =3D TRUE; > > + break; > > + } > > + if (Packet->InTransferLength) { > > + Cmd |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE | > > BIT_CMD_DATA_EXPECTED | > > + BIT_CMD_READ; > > + } else if (Packet->OutTransferLength) { > > + Cmd |=3D BIT_CMD_WAIT_PRVDATA_COMPLETE | > > BIT_CMD_DATA_EXPECTED | > > + BIT_CMD_WRITE; > > + } > > + Cmd |=3D BIT_CMD_RESPONSE_EXPECT | > > BIT_CMD_CHECK_RESPONSE_CRC | > > + BIT_CMD_SEND_AUTO_STOP; > > + } else { > > + switch (Packet->SdMmcCmdBlk->CommandIndex) { > > + case SD_GO_IDLE_STATE: > > + Cmd |=3D BIT_CMD_SEND_INIT; > > + break; > > + } > > + } > > + switch (Packet->SdMmcCmdBlk->ResponseType) { > > + case SdMmcResponseTypeR2: > > + Cmd |=3D BIT_CMD_RESPONSE_EXPECT | > > BIT_CMD_CHECK_RESPONSE_CRC | > > + BIT_CMD_LONG_RESPONSE; > > + break; > > + case SdMmcResponseTypeR3: > > + Cmd |=3D BIT_CMD_RESPONSE_EXPECT; > > + break; > > + case SdMmcResponseTypeR1b: > > + case SdMmcResponseTypeR4: > > + case SdMmcResponseTypeR6: > > + case SdMmcResponseTypeR7: > > + Cmd |=3D BIT_CMD_RESPONSE_EXPECT | > > BIT_CMD_CHECK_RESPONSE_CRC; > > + break; > > + } > > + Cmd |=3D BIT_CMD_USE_HOLD_REG | BIT_CMD_START; > > + > > + if (Trb->UseFifo =3D=3D TRUE) { > > + BytCnt =3D Trb->Read ? Packet->InTransferLength : Packet- > > >OutTransferLength; > > + MmioWrite32 (DevBase + DW_MMC_BYTCNT, BytCnt); > > + if (Trb->Read) { > > + if (Packet->InTransferLength > DW_MMC_BLOCK_SIZE) { > > + BlkSize =3D DW_MMC_BLOCK_SIZE; > > + } else { > > + BlkSize =3D Packet->InTransferLength; > > + } > > + } > > + else { > > + if (Packet->OutTransferLength > DW_MMC_BLOCK_SIZE) { > > + BlkSize =3D DW_MMC_BLOCK_SIZE; > > + } else { > > + BlkSize =3D Packet->OutTransferLength; > > + } > > + } > > + > > + MmioWrite32 (DevBase + DW_MMC_BLKSIZ, BlkSize); > > + } > > + > > + Argument =3D Packet->SdMmcCmdBlk->CommandArgument; > > + MmioWrite32 (DevBase + DW_MMC_CMDARG, Argument); > > + ArmDataSynchronizationBarrier (); > > + ArmInstructionSynchronizationBarrier (); > > + MmioWrite32 (DevBase + DW_MMC_CMD, Cmd); > > + ArmDataSynchronizationBarrier (); > > + ArmInstructionSynchronizationBarrier (); > > + > > + ErrMask =3D DW_MMC_INT_EBE | DW_MMC_INT_HLE | > > DW_MMC_INT_RTO | > > + DW_MMC_INT_RCRC | DW_MMC_INT_RE; > > + ErrMask |=3D DW_MMC_INT_DRT | DW_MMC_INT_SBE; > > + if (Packet->InTransferLength || Packet->OutTransferLength) { > > + ErrMask |=3D DW_MMC_INT_DCRC; > > + } > > + if (Trb->UseFifo =3D=3D TRUE) { > > + Status =3D TransferFifo (Trb); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + } else { > > + Timeout =3D 10000; > > + do { > > + if (--Timeout =3D=3D 0) { > > + break; > > + } > > + IntStatus =3D MmioRead32 (DevBase + DW_MMC_RINTSTS); > > + if (IntStatus & ErrMask) { > > + return EFI_DEVICE_ERROR; > > + } > > + if (Trb->DataLen && ((IntStatus & DW_MMC_INT_DTO) =3D=3D 0)) { > > + // > > + // Transfer not Done > > + // > > + MicroSecondDelay (10); > > + continue; > > + } > > + MicroSecondDelay (10); > > + } while (!(IntStatus & DW_MMC_INT_CMD_DONE)); > > + if (Packet->InTransferLength) { > > + do { > > + Idsts =3D MmioRead32 (DevBase + DW_MMC_IDSTS); > > + } while ((Idsts & DW_MMC_IDSTS_RI) =3D=3D 0); > > + Status =3D DwMmcHcStopDma (Private, Trb); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + } else if (Packet->OutTransferLength) { > > + do { > > + Idsts =3D MmioRead32 (DevBase + DW_MMC_IDSTS); > > + } while ((Idsts & DW_MMC_IDSTS_TI) =3D=3D 0); > > + Status =3D DwMmcHcStopDma (Private, Trb); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + } /* Packet->InTransferLength */ > > + } /* UseFifo */ > > + switch (Packet->SdMmcCmdBlk->ResponseType) { > > + case SdMmcResponseTypeR1: > > + case SdMmcResponseTypeR1b: > > + case SdMmcResponseTypeR3: > > + case SdMmcResponseTypeR4: > > + case SdMmcResponseTypeR5: > > + case SdMmcResponseTypeR6: > > + case SdMmcResponseTypeR7: > > + Packet->SdMmcStatusBlk->Resp0 =3D MmioRead32 (DevBase + > > DW_MMC_RESP0); > > + break; > > + case SdMmcResponseTypeR2: > > + Packet->SdMmcStatusBlk->Resp0 =3D MmioRead32 (DevBase + > > DW_MMC_RESP0); > > + Packet->SdMmcStatusBlk->Resp1 =3D MmioRead32 (DevBase + > > DW_MMC_RESP1); > > + Packet->SdMmcStatusBlk->Resp2 =3D MmioRead32 (DevBase + > > DW_MMC_RESP2); > > + Packet->SdMmcStatusBlk->Resp3 =3D MmioRead32 (DevBase + > > DW_MMC_RESP3); > > + break; > > + } > > + > > + // > > + // The workaround on SD_SEND_CSD is used to be compatible with SDHC. > > + // > > + if (Packet->SdMmcCmdBlk->CommandIndex =3D=3D SD_SEND_CSD) { > > + { > > + UINT32 Buf[4]; > > + ZeroMem (Buf, sizeof (Buf)); > > + CopyMem ( > > + (UINT8 *)Buf, > > + (UINT8 *)&Packet->SdMmcStatusBlk->Resp0 + 1, > > + sizeof (Buf) - 1 > > + ); > > + CopyMem ( > > + (UINT8 *)&Packet->SdMmcStatusBlk->Resp0, > > + (UINT8 *)Buf, > > + sizeof (Buf) - 1 > > + ); > > + } > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Execute the specified TRB. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance. > > + > > + @retval EFI_SUCCESS The TRB is sent to host controller success= fully. > > + @retval Others Some erros happen when sending this reques= t to the > > + host controller. > > + > > +**/ > > +EFI_STATUS > > +DwMmcExecTrb ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ) > > +{ > > + EFI_STATUS Status =3D EFI_SUCCESS; > > + UINT32 Slot; > > + > > + Slot =3D Trb->Slot; > > + if (Private->Slot[Slot].CardType =3D=3D EmmcCardType) { > > + Status =3D DwEmmcExecTrb (Private, Trb); > > + } else if (Private->Slot[Slot].CardType =3D=3D SdCardType) { > > + Status =3D DwSdExecTrb (Private, Trb); > > + } else { > > + ASSERT (0); > > + } > > + return Status; > > +} > > + > > +/** > > + Check the TRB execution result. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance. > > + > > + @retval EFI_SUCCESS The TRB is executed successfully. > > + @retval EFI_NOT_READY The TRB is not completed for execution. > > + @retval Others Some erros happen when executing this requ= est. > > + > > +**/ > > +EFI_STATUS > > +DwMmcCheckTrbResult ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ) > > +{ > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; > > + UINT32 Idsts; > > + UINTN DevBase; > > + > > + DevBase =3D Private->DevBase; > > + Packet =3D Trb->Packet; > > + if (Trb->UseFifo =3D=3D TRUE) { > > + return EFI_SUCCESS; > > + } > > + if (Packet->InTransferLength) { > > + do { > > + Idsts =3D MmioRead32 (DevBase + DW_MMC_IDSTS); > > + } while ((Idsts & BIT1) =3D=3D 0); > > + } else if (Packet->OutTransferLength) { > > + do { > > + Idsts =3D MmioRead32 (DevBase + DW_MMC_IDSTS); > > + } while ((Idsts & BIT0) =3D=3D 0); > > + } else { > > + return EFI_SUCCESS; > > + } > > + Idsts =3D ~0; > > + MmioWrite32 (DevBase + DW_MMC_IDSTS, Idsts); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Wait for the TRB execution result. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + @param[in] Trb The pointer to the DW_MMC_HC_TRB instance. > > + > > + @retval EFI_SUCCESS The TRB is executed successfully. > > + @retval Others Some erros happen when executing this requ= est. > > + > > +**/ > > +EFI_STATUS > > +DwMmcWaitTrbResult ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private, > > + IN DW_MMC_HC_TRB *Trb > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; > > + UINT64 Timeout; > > + BOOLEAN InfiniteWait; > > + > > + Packet =3D Trb->Packet; > > + // > > + // Wait Command Complete Interrupt Status bit in Normal Interrupt St= atus > > + // Register > > + // > > + Timeout =3D Packet->Timeout; > > + if (Timeout =3D=3D 0) { > > + InfiniteWait =3D TRUE; > > + } else { > > + InfiniteWait =3D FALSE; > > + } > > + > > + while (InfiniteWait || (Timeout > 0)) { > > + // > > + // Check Trb execution result by reading Normal Interrupt Status r= egister. > > + // > > + Status =3D DwMmcCheckTrbResult (Private, Trb); > > + if (Status !=3D EFI_NOT_READY) { > > + return Status; > > + } > > + // > > + // Stall for 1 microsecond. > > + // > > + gBS->Stall (1); > > + > > + Timeout--; > > + } > > + > > + return EFI_TIMEOUT; > > +} > > diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/EmmcDevice.c > > b/EmbeddedPkg/Drivers/DwMmcHcDxe/EmmcDevice.c > > new file mode 100644 > > index 000000000000..b7a8688c4d2e > > --- /dev/null > > +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/EmmcDevice.c > > @@ -0,0 +1,1042 @@ > > +/** @file > > + This file provides some helper functions which are specific for EMMC > > device. > > + > > + Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved. > > + Copyright (c) 2018, Linaro. All rights reserved.
> > + > > + This program and the accompanying materials are licensed and made > > available > > + under the terms and conditions of the BSD License which accompanies = this > > + distribution. The full text of the license may be found at > > + http://opensource.org/licenses/bsd-license.php > > + > > + 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 "DwMmcHcDxe.h" > > + > > +#define EMMC_GET_STATE(x) (((x) >> 9) & 0xf) > > +#define EMMC_STATE_IDLE 0 > > +#define EMMC_STATE_READY 1 > > +#define EMMC_STATE_IDENT 2 > > +#define EMMC_STATE_STBY 3 > > +#define EMMC_STATE_TRAN 4 > > +#define EMMC_STATE_DATA 5 > > +#define EMMC_STATE_RCV 6 > > +#define EMMC_STATE_PRG 7 > > +#define EMMC_STATE_DIS 8 > > +#define EMMC_STATE_BTST 9 > > +#define EMMC_STATE_SLP 10 > > + > > +#define EMMC_CMD1_CAPACITY_LESS_THAN_2GB 0x00FF8080 // > > Capacity <=3D 2GB, byte addressing used > > +#define EMMC_CMD1_CAPACITY_GREATER_THAN_2GB 0x40FF8080 // > > Capacity > 2GB, 512-byte sector addressing used > > + > > +/** > > + Send command GO_IDLE_STATE (CMD0 with argument of 0x00000000) to > > the device to > > + make it go to Idle State. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Slot The slot number of the SD card to send the > > command > > + to. > > + > > + @retval EFI_SUCCESS The EMMC device is reset correctly. > > + @retval Others The device reset fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcReset ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D EMMC_GO_IDLE_STATE; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBc; > > + SdMmcCmdBlk.ResponseType =3D 0; > > + SdMmcCmdBlk.CommandArgument =3D 0; > > + > > + gBS->Stall (1000); > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Send command SEND_OP_COND to the EMMC device to get the data of > > the OCR > > + register. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in, out] Argument On input, the argument of SEND_OP_COND is > > to send > > + to the device. > > + On output, the argument is the value of OC= R > > + register. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcGetOcr ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN OUT UINT32 *Argument > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D EMMC_SEND_OP_COND; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR3; > > + SdMmcCmdBlk.CommandArgument =3D *Argument; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + if (!EFI_ERROR (Status)) { > > + // > > + // For details, refer to SD Host Controller Simplified Spec 3.0 Ta= ble 2-12. > > + // > > + *Argument =3D SdMmcStatusBlk.Resp0; > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Broadcast command ALL_SEND_CID to the bus to ask all the EMMC device= s > > to send > > + the data of their CID registers. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcGetAllCid ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D EMMC_ALL_SEND_CID; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR2; > > + SdMmcCmdBlk.CommandArgument =3D 0; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Send command SET_RELATIVE_ADDR to the EMMC device to assign a > > Relative device > > + Address (RCA). > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address to be assigned= . > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcSetRca ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D EMMC_SET_RELATIVE_ADDR; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Send command SEND_CSD to the EMMC device to get the data of the CSD > > register. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for detail= s. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address of selected de= vice. > > + @param[out] Csd The buffer to store the content of the CSD= register. > > + Note the caller should ignore the lowest b= yte of > > + this buffer as the content of this byte is > > + meaningless even if the operation succeeds= . > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcGetCsd ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca, > > + OUT EMMC_CSD *Csd > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D EMMC_SEND_CSD; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR2; > > + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + if (!EFI_ERROR (Status)) { > > + // > > + // Copy 128bit data for CSD structure. > > + // > > + CopyMem ((VOID *)Csd + 1, &SdMmcStatusBlk.Resp0, sizeof > > (EMMC_CSD) - 1); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Send command SELECT_DESELECT_CARD to the EMMC device to > > select/deselect it. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for detail= s. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address of selected de= vice. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcSelect ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D EMMC_SELECT_DESELECT_CARD; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Send command SEND_EXT_CSD to the EMMC device to get the data of the > > EXT_CSD > > + register. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for detail= s. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[out] ExtCsd The buffer to store the content of the EXT= _CSD > > + register. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcGetExtCsd ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + OUT EMMC_EXT_CSD *ExtCsd > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D EMMC_SEND_EXT_CSD; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAdtc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + SdMmcCmdBlk.CommandArgument =3D 0x00000000; > > + > > + Packet.InDataBuffer =3D ExtCsd; > > + Packet.InTransferLength =3D sizeof (EMMC_EXT_CSD); > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + return Status; > > +} > > + > > +/** > > + Send command SWITCH to the EMMC device to switch the mode of > > operation of the > > + selected Device or modifies the EXT_CSD registers. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for detail= s. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Access The access mode of SWTICH command. > > + @param[in] Index The offset of the field to be access. > > + @param[in] Value The value to be set to the specified field= of > > + EXT_CSD register. > > + @param[in] CmdSet The value of CmdSet field of EXT_CSD regis= ter. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcSwitch ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT8 Access, > > + IN UINT8 Index, > > + IN UINT8 Value, > > + IN UINT8 CmdSet > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D EMMC_SWITCH; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1b; > > + SdMmcCmdBlk.CommandArgument =3D (Access << 24) | (Index << 16) | \ > > + (Value << 8) | CmdSet; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Send command SEND_STATUS to the addressed EMMC device to get its > > status > > + register. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for detail= s. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address of addressed d= evice. > > + @param[out] DevStatus The returned device status. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcSendStatus ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca, > > + OUT UINT32 *DevStatus > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D EMMC_SEND_STATUS; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + if (!EFI_ERROR (Status)) { > > + *DevStatus =3D SdMmcStatusBlk.Resp0; > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Send command SEND_TUNING_BLOCK to the EMMC device for HS200 > > optimal sampling > > + point detection. > > + > > + It may be sent up to 40 times until the host finishes the tuning pro= cedure. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 for details= . > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] BusWidth The bus width to work. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcSendTuningBlk ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT8 BusWidth > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + UINT8 TuningBlock[128]; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D EMMC_SEND_TUNING_BLOCK; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAdtc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + SdMmcCmdBlk.CommandArgument =3D 0; > > + > > + Packet.InDataBuffer =3D TuningBlock; > > + if (BusWidth =3D=3D 8) { > > + Packet.InTransferLength =3D sizeof (TuningBlock); > > + } else { > > + Packet.InTransferLength =3D 64; > > + } > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Tunning the clock to get HS200 optimal sampling point. > > + > > + Command SEND_TUNING_BLOCK may be sent up to 40 times until the > > host finishes > > + the tuning procedure. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8. > > + > > + @param[in] DevIo A pointer to the EFI_DEVICE_IO_PROTOCOL > > instance. > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] BusWidth The bus width to work. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcTuningClkForHs200 ( > > + IN UINTN DevBase, > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT8 BusWidth > > + ) > > +{ > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Switch the bus width to specified width. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.9. > > + > > + @param[in] DevIo A pointer to the EFI_DEVICE_IO_PROTOCOL > > instance. > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address to be assigned= . > > + @param[in] IsDdr If TRUE, use dual data rate data simpling = method. > > + Otherwise use single data rate data simpli= ng method. > > + @param[in] BusWidth The bus width to be set, it could be 4 or = 8. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcSwitchBusWidth ( > > + IN UINTN DevBase, > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca, > > + IN BOOLEAN IsDdr, > > + IN UINT8 BusWidth > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT8 Access; > > + UINT8 Index; > > + UINT8 Value; > > + UINT8 CmdSet; > > + UINT32 DevStatus; > > + > > + // > > + // Write Byte, the Value field is written into the byte pointed by I= ndex. > > + // > > + Access =3D 0x03; > > + Index =3D OFFSET_OF (EMMC_EXT_CSD, BusWidth); > > + if (BusWidth =3D=3D 1) { > > + Value =3D 0; > > + } else { > > + if (BusWidth =3D=3D 4) { > > + Value =3D 1; > > + } else if (BusWidth =3D=3D 8) { > > + Value =3D 2; > > + } else { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (IsDdr) { > > + Value +=3D 4; > > + } > > + } > > + > > + CmdSet =3D 0; > > + Status =3D EmmcSwitch (PassThru, Access, Index, Value, CmdSet); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "EmmcSwitchBusWidth: Switch to bus width %d fails with %r\n", > > + BusWidth, > > + Status > > + )); > > + return Status; > > + } > > + > > + do { > > + Status =3D EmmcSendStatus (PassThru, Rca, &DevStatus); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "EmmcSwitchBusWidth: Send status fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + // > > + // Check the switch operation is really successful or not. > > + // > > + } while ((DevStatus & 0xf) =3D=3D EMMC_STATE_PRG); > > + > > + Status =3D DwMmcHcSetBusWidth (DevBase, IsDdr, BusWidth); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Switch the clock frequency to the specified value. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6. > > + > > + @param[in] DevIo A pointer to the EFI_DEVICE_IO_PROTOCOL > > instance. > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address to be assigned= . > > + @param[in] HsTiming The value to be written to HS_TIMING field= of > > + EXT_CSD register. > > + @param[in] ClockFreq The max clock frequency to be set, the uni= t is > > MHz. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcSwitchClockFreq ( > > + IN UINTN DevBase, > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca, > > + IN UINT8 HsTiming, > > + IN UINT32 ClockFreq > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT8 Access; > > + UINT8 Index; > > + UINT8 Value; > > + UINT8 CmdSet; > > + UINT32 DevStatus; > > + DW_MMC_HC_PRIVATE_DATA *Private; > > + > > + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (PassThru); > > + // > > + // Write Byte, the Value field is written into the byte pointed by I= ndex. > > + // > > + Access =3D 0x03; > > + Index =3D OFFSET_OF (EMMC_EXT_CSD, HsTiming); > > + Value =3D HsTiming; > > + CmdSet =3D 0; > > + > > + Status =3D EmmcSwitch (PassThru, Access, Index, Value, CmdSet); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "EmmcSwitchClockFreq: Switch to hstiming %d fails with %r\n", > > + HsTiming, > > + Status > > + )); > > + return Status; > > + } > > + > > + Status =3D EmmcSendStatus (PassThru, Rca, &DevStatus); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "EmmcSwitchClockFreq: Send status fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + // > > + // Check the switch operation is really successful or not. > > + // > > + if ((DevStatus & BIT7) !=3D 0) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "EmmcSwitchClockFreq: The switch operation fails as DevStatus > > 0x%08x\n", > > + DevStatus > > + )); > > + return EFI_DEVICE_ERROR; > > + } > > + // > > + // Convert the clock freq unit from MHz to KHz. > > + // > > + Status =3D DwMmcHcClockSupply (DevBase, ClockFreq * 1000, Private- > > >Capability[0]); > > + > > + return Status; > > +} > > + > > +/** > > + Switch to the High Speed timing according to request. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8. > > + > > + @param[in] DevIo A pointer to the EFI_DEVICE_IO_PROTOCOL > > instance. > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address to be assigned= . > > + @param[in] ClockFreq The max clock frequency to be set. > > + @param[in] IsDdr If TRUE, use dual data rate data simpling = method. > > + Otherwise use single data rate data simpli= ng method. > > + @param[in] BusWidth The bus width to be set, it could be 4 or = 8. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcSwitchToHighSpeed ( > > + IN UINTN DevBase, > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca, > > + IN UINT32 ClockFreq, > > + IN BOOLEAN IsDdr, > > + IN UINT8 BusWidth > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT8 HsTiming; > > + > > + HsTiming =3D 1; > > + Status =3D EmmcSwitchClockFreq (DevBase, PassThru, Rca, HsTiming, > > ClockFreq); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + Status =3D EmmcSwitchBusWidth (DevBase, PassThru, Rca, IsDdr, BusWid= th); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Switch to the HS200 timing according to request. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8. > > + > > + @param[in] DevIo A pointer to the EFI_DEVICE_IO_PROTOCOL > > instance. > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address to be assigned= . > > + @param[in] ClockFreq The max clock frequency to be set. > > + @param[in] BusWidth The bus width to be set, it could be 4 or = 8. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcSwitchToHS200 ( > > + IN UINTN DevBase, > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca, > > + IN UINT32 ClockFreq, > > + IN UINT8 BusWidth > > + ) > > +{ > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Switch the high speed timing according to request. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8. > > + > > + @param[in] DevIo A pointer to the EFI_DEVICE_IO_PROTOCOL > > instance. > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address to be assigned= . > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +EmmcSetBusMode ( > > + IN UINTN DevBase, > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca > > + ) > > +{ > > + EFI_STATUS Status; > > + EMMC_CSD Csd; > > + EMMC_EXT_CSD ExtCsd; > > + UINT8 HsTiming; > > + BOOLEAN IsDdr; > > + UINT32 DevStatus; > > + UINT32 ClockFreq; > > + UINT8 BusWidth; > > + DW_MMC_HC_PRIVATE_DATA *Private; > > + > > + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (PassThru); > > + ASSERT (Private->Capability[0].BaseClkFreq !=3D 0); > > + > > + Status =3D EmmcGetCsd (PassThru, Rca, &Csd); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetCsd fails with %r\n", > > Status)); > > + return Status; > > + } > > + > > + Status =3D EmmcSelect (PassThru, Rca); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: Select fails with %r\n", > > Status)); > > + return Status; > > + } > > + > > + do { > > + Status =3D EmmcSendStatus (PassThru, Rca, &DevStatus); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "EmmcSetBusMode: Get Status fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + } while (EMMC_GET_STATE (DevStatus) !=3D EMMC_STATE_TRAN); > > + > > + BusWidth =3D 1; > > + Status =3D EmmcSwitchBusWidth (DevBase, PassThru, Rca, FALSE, > > BusWidth); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + BusWidth =3D Private->Capability[0].BusWidth; > > + // > > + // Get Deivce_Type from EXT_CSD register. > > + // > > + Status =3D EmmcGetExtCsd (PassThru, &ExtCsd); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetExtCsd fails with %r\n", > > Status)); > > + return Status; > > + } > > + > > + // > > + // Calculate supported bus speed/bus width/clock frequency. > > + // > > + HsTiming =3D 0; > > + IsDdr =3D FALSE; > > + ClockFreq =3D 0; > > + if (((ExtCsd.DeviceType & (BIT4 | BIT5)) !=3D 0) && > > + (Private->Capability[0].Sdr104 !=3D 0)) { > > + HsTiming =3D 2; > > + IsDdr =3D FALSE; > > + ClockFreq =3D 200; > > + } else if (((ExtCsd.DeviceType & (BIT2 | BIT3)) !=3D 0) && > > + (Private->Capability[0].Ddr50 !=3D 0)) { > > + HsTiming =3D 1; > > + IsDdr =3D TRUE; > > + ClockFreq =3D 52; > > + } else if (((ExtCsd.DeviceType & BIT1) !=3D 0) && > > + (Private->Capability[0].HighSpeed !=3D 0)) { > > + HsTiming =3D 1; > > + IsDdr =3D FALSE; > > + ClockFreq =3D 52; > > + } else if (((ExtCsd.DeviceType & BIT0) !=3D 0) && > > + (Private->Capability[0].HighSpeed !=3D 0)) { > > + HsTiming =3D 1; > > + IsDdr =3D FALSE; > > + ClockFreq =3D 26; > > + } > > + > > + if ((ClockFreq =3D=3D 0) || (HsTiming =3D=3D 0)) { > > + // > > + // Continue using default setting. > > + // > > + return EFI_SUCCESS; > > + } > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "EmmcSetBusMode: HsTiming %d ClockFreq %d BusWidth %d Ddr %a\n", > > + HsTiming, > > + ClockFreq, > > + BusWidth, > > + IsDdr ? "TRUE" : "FALSE" > > + )); > > + > > + if (HsTiming =3D=3D 2) { > > + // > > + // Execute HS200 timing switch procedure > > + // > > + Status =3D EmmcSwitchToHS200 (DevBase, PassThru, Rca, ClockFreq, > > BusWidth); > > + } else { > > + // > > + // Execute High Speed timing switch procedure > > + // > > + Status =3D EmmcSwitchToHighSpeed ( > > + DevBase, > > + PassThru, > > + Rca, > > + ClockFreq, > > + IsDdr, > > + BusWidth > > + ); > > + } > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "EmmcSetBusMode: Switch to %a %r\n", > > + (HsTiming =3D=3D 3) ? "HS400" : ((HsTiming =3D=3D 2) ? "HS200" : "= HighSpeed"), > > + Status > > + )); > > + > > + return Status; > > +} > > + > > +/** > > + Execute EMMC device identification procedure. > > + > > + Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details. > > + > > + @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA > > instance. > > + > > + @retval EFI_SUCCESS There is a EMMC card. > > + @retval Others There is not a EMMC card. > > + > > +**/ > > +EFI_STATUS > > +EmmcIdentification ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN DevBase; > > + EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; > > + UINT32 Ocr; > > + UINT16 Rca; > > + UINT32 DevStatus; > > + UINT32 Timeout; > > + > > + DevBase =3D Private->DevBase; > > + PassThru =3D &Private->PassThru; > > + > > + Status =3D EmmcReset (PassThru); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_INFO, > > + "EmmcIdentification: Executing Cmd0 fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + > > + Timeout =3D 100; > > + do { > > + Ocr =3D EMMC_CMD1_CAPACITY_GREATER_THAN_2GB; > > + Status =3D EmmcGetOcr (PassThru, &Ocr); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_INFO, > > + "EmmcIdentification: Executing Cmd1 fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + if (--Timeout <=3D 0) { > > + return EFI_DEVICE_ERROR; > > + } > > + MicroSecondDelay (100); > > + } while ((Ocr & BIT31) =3D=3D 0); > > + > > + Status =3D EmmcGetAllCid (PassThru); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_INFO, > > + "EmmcIdentification: Executing Cmd2 fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + // > > + // valid RCA starts from 1. > > + // Here we takes a simple formula to calculate the RCA. > > + // Don't support multiple devices on the slot, that is > > + // shared bus slot feature. > > + // > > + Rca =3D 1; > > + Status =3D EmmcSetRca (PassThru, Rca); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_INFO, > > + "EmmcIdentification: Executing Cmd3 fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + // > > + // Enter Data Tranfer Mode. > > + // > > + DEBUG (( > > + DEBUG_INFO, > > + "EmmcIdentification: Found a EMMC device at RCA [%d]\n", > > + Rca > > + )); > > + Private->Slot[0].CardType =3D EmmcCardType; > > + > > + Status =3D EmmcSetBusMode (DevBase, PassThru, Rca); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + // > > + // Exit DATA Mode. > > + // > > + do { > > + Status =3D EmmcSendStatus (PassThru, Rca, &DevStatus); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_INFO, > > + "EmmcSwitchBusWidth: Send status fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + } while ((DevStatus & 0xf) =3D=3D EMMC_STATE_DATA); > > + > > + return Status; > > +} > > diff --git a/EmbeddedPkg/Drivers/DwMmcHcDxe/SdDevice.c > > b/EmbeddedPkg/Drivers/DwMmcHcDxe/SdDevice.c > > new file mode 100644 > > index 000000000000..63246637b6dd > > --- /dev/null > > +++ b/EmbeddedPkg/Drivers/DwMmcHcDxe/SdDevice.c > > @@ -0,0 +1,1105 @@ > > +/** @file > > + This file provides some helper functions which are specific for SD c= ard > > + device. > > + > > + Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved. > > + Copyright (c) 2018, Linaro. All rights reserved.
> > + > > + This program and the accompanying materials are licensed and made > > available > > + under the terms and conditions of the BSD License which accompanies = this > > + distribution. The full text of the license may be found at > > + http://opensource.org/licenses/bsd-license.php > > + > > + 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 "DwMmcHcDxe.h" > > + > > +/** > > + Send command GO_IDLE_STATE to the device to make it go to Idle State= . > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + > > + @retval EFI_SUCCESS The SD device is reset correctly. > > + @retval Others The device reset fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardReset ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_GO_IDLE_STATE; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBc; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + //Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Send command SEND_IF_COND to the device to inquiry the SD Memory > > Card > > + interface condition. > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] SupplyVoltage The supplied voltage by the host. > > + @param[in] CheckPattern The check pattern to be sent to the device= . > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardVoltageCheck ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT8 SupplyVoltage, > > + IN UINT8 CheckPattern > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_SEND_IF_COND; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR7; > > + SdMmcCmdBlk.CommandArgument =3D (SupplyVoltage << 8) | > > CheckPattern; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + if (!EFI_ERROR (Status)) { > > + if (SdMmcStatusBlk.Resp0 !=3D SdMmcCmdBlk.CommandArgument) { > > + return EFI_DEVICE_ERROR; > > + } > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Send command SDIO_SEND_OP_COND to the device to see whether it is > > SDIO device. > > + > > + Refer to SDIO Simplified Spec 3 Section 3.2 for details. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] VoltageWindow The supply voltage window. > > + @param[in] S18R The boolean to show if it should switch to= 1.8v. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdioSendOpCond ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT32 VoltageWindow, > > + IN BOOLEAN S18R > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + UINT32 Switch; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SDIO_SEND_OP_COND; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR4; > > + > > + Switch =3D S18R ? BIT24 : 0; > > + > > + SdMmcCmdBlk.CommandArgument =3D (VoltageWindow & 0xFFFFFF) | > > Switch; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Send command SD_SEND_OP_COND to the device to see whether it is > > SDIO device. > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address of addressed = device. > > + @param[in] VoltageWindow The supply voltage window. > > + @param[in] S18R The boolean to show if it should switch t= o 1.8v. > > + @param[in] Xpc The boolean to show if it should provide = 0.36w > > + power control. > > + @param[in] Hcs The boolean to show if it support host ca= pacity > > + info. > > + @param[out] Ocr The buffer to store returned OCR register= value. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardSendOpCond ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca, > > + IN UINT32 VoltageWindow, > > + IN BOOLEAN S18R, > > + IN BOOLEAN Xpc, > > + IN BOOLEAN Hcs, > > + OUT UINT32 *Ocr > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + UINT32 Switch; > > + UINT32 MaxPower; > > + UINT32 HostCapacity; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_APP_CMD; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_SEND_OP_COND; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR3; > > + > > + Switch =3D S18R ? BIT24 : 0; > > + MaxPower =3D Xpc ? BIT28 : 0; > > + HostCapacity =3D Hcs ? BIT30 : 0; > > + > > + SdMmcCmdBlk.CommandArgument =3D (VoltageWindow & 0xFFFFFF) | > > Switch | \ > > + MaxPower | HostCapacity; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + if (!EFI_ERROR (Status)) { > > + *Ocr =3D SdMmcStatusBlk.Resp0; > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Broadcast command ALL_SEND_CID to the bus to ask all the SD devices = to > > send > > + the data of their CID registers. > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardAllSendCid ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_ALL_SEND_CID; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR2; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Send command SET_RELATIVE_ADDR to the SD device to assign a Relative > > device > > + Address (RCA). > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[out] Rca The relative device address to assign. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardSetRca ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + OUT UINT16 *Rca > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_SET_RELATIVE_ADDR; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeBcr; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR6; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + if (!EFI_ERROR (Status)) { > > + *Rca =3D (UINT16)(SdMmcStatusBlk.Resp0 >> 16); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Send command SEND_CSD to the SD device to get the data of the CSD > > register. > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address of selected de= vice. > > + @param[out] Csd The buffer to store the content of the CSD= register. > > + Note the caller should ignore the lowest b= yte of > > + this buffer as the content of this byte is= meaning- > > + less even if the operation succeeds. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardGetCsd ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca, > > + OUT SD_CSD *Csd > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_SEND_CSD; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR2; > > + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + if (!EFI_ERROR (Status)) { > > + CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CSD) > > - 1); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Send command SEND_CSD to the SD device to get the data of the CSD > > register. > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address of selected de= vice. > > + @param[out] Scr The buffer to store the content of the SCR= register. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardGetScr ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca, > > + OUT SD_SCR *Scr > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_APP_CMD; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_SEND_SCR; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAdtc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + > > + Packet.InDataBuffer =3D Scr; > > + Packet.InTransferLength =3D sizeof (SD_SCR); > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Send command SELECT_DESELECT_CARD to the SD device to > > select/deselect it. > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address of selected de= vice. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardSelect ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_SELECT_DESELECT_CARD; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; > > + if (Rca !=3D 0) { > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1b; > > + } > > + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Send command VOLTAGE_SWITCH to the SD device to switch the voltage > > of the > > + device. > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardVoltageSwitch ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_VOLTAGE_SWITCH; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + SdMmcCmdBlk.CommandArgument =3D 0; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Send command SET_BUS_WIDTH to the SD device to set the bus width. > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address of addressed d= evice. > > + @param[in] BusWidth The bus width to be set, it could be 1 or = 4. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardSetBusWidth ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca, > > + IN UINT8 BusWidth > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + UINT8 Value; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_APP_CMD; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_SET_BUS_WIDTH; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + > > + if (BusWidth =3D=3D 1) { > > + Value =3D 0; > > + } else if (BusWidth =3D=3D 4) { > > + Value =3D 2; > > + } else { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + SdMmcCmdBlk.CommandArgument =3D Value & 0x3; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + return Status; > > +} > > + > > +/** > > + Send command SWITCH_FUNC to the SD device to check switchable > > function or > > + switch card function. > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] AccessMode The value for access mode group. > > + @param[in] CommandSystem The value for command set group. > > + @param[in] DriveStrength The value for drive length group. > > + @param[in] PowerLimit The value for power limit group. > > + @param[in] Mode Switch or check function. > > + @param[out] SwitchResp The return switch function status. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardSwitch ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT8 AccessMode, > > + IN UINT8 CommandSystem, > > + IN UINT8 DriveStrength, > > + IN UINT8 PowerLimit, > > + IN BOOLEAN Mode, > > + OUT UINT8 *SwitchResp > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + UINT32 ModeValue; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_SWITCH_FUNC; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAdtc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + > > + ModeValue =3D Mode ? BIT31 : 0; > > + SdMmcCmdBlk.CommandArgument =3D (AccessMode & 0xF) | \ > > + ((PowerLimit & 0xF) << 4) | \ > > + ((DriveStrength & 0xF) << 8) | \ > > + ((DriveStrength & 0xF) << 12) | \ > > + ModeValue; > > + > > + Packet.InDataBuffer =3D SwitchResp; > > + Packet.InTransferLength =3D 64; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Send command SEND_STATUS to the addressed SD device to get its statu= s > > + register. > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address of addressed d= evice. > > + @param[out] DevStatus The returned device status. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardSendStatus ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca, > > + OUT UINT32 *DevStatus > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_SEND_STATUS; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + SdMmcCmdBlk.CommandArgument =3D (UINT32)Rca << 16; > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + if (!EFI_ERROR (Status)) { > > + *DevStatus =3D SdMmcStatusBlk.Resp0; > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Send command SEND_TUNING_BLOCK to the SD device for HS200 optimal > > sampling > > + point detection. > > + > > + It may be sent up to 40 times until the host finishes the tuning pro= cedure. > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardSendTuningBlk ( > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru > > + ) > > +{ > > + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; > > + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; > > + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; > > + EFI_STATUS Status; > > + UINT8 TuningBlock[64]; > > + > > + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); > > + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); > > + ZeroMem (&Packet, sizeof (Packet)); > > + > > + Packet.SdMmcCmdBlk =3D &SdMmcCmdBlk; > > + Packet.SdMmcStatusBlk =3D &SdMmcStatusBlk; > > + Packet.Timeout =3D DW_MMC_HC_GENERIC_TIMEOUT; > > + > > + SdMmcCmdBlk.CommandIndex =3D SD_SEND_TUNING_BLOCK; > > + SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAdtc; > > + SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1; > > + SdMmcCmdBlk.CommandArgument =3D 0; > > + > > + Packet.InDataBuffer =3D TuningBlock; > > + Packet.InTransferLength =3D sizeof (TuningBlock); > > + > > + Status =3D PassThru->PassThru (PassThru, 0, &Packet, NULL); > > + > > + return Status; > > +} > > + > > +/** > > + Switch the bus width to specified width. > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and > > + SD Host Controller Simplified Spec 3.0 section Figure 3-7 for detail= s. > > + > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address to be assigned= . > > + @param[in] BusWidth The bus width to be set, it could be 4 or = 8. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardSwitchBusWidth ( > > + IN UINTN DevBase, > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca, > > + IN BOOLEAN IsDdr, > > + IN UINT8 BusWidth > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT32 DevStatus; > > + > > + Status =3D SdCardSetBusWidth (PassThru, Rca, BusWidth); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "SdCardSwitchBusWidth: Switch to bus width %d fails with %r\n", > > + BusWidth, > > + Status > > + )); > > + return Status; > > + } > > + > > + Status =3D SdCardSendStatus (PassThru, Rca, &DevStatus); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "SdCardSwitchBusWidth: Send status fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + // > > + // Check the switch operation is really successful or not. > > + // > > + if ((DevStatus >> 16) !=3D 0) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "SdCardSwitchBusWidth: The switch operation fails as DevStatus > > 0x%08x\n", > > + DevStatus > > + )); > > + return EFI_DEVICE_ERROR; > > + } > > + > > + Status =3D DwMmcHcSetBusWidth (DevBase, IsDdr, BusWidth); > > + > > + return Status; > > +} > > + > > +/** > > + Switch the high speed timing according to request. > > + > > + Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for detai= ls. > > + > > + @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. > > + @param[in] PassThru A pointer to the > > EFI_SD_MMC_PASS_THRU_PROTOCOL > > + instance. > > + @param[in] Rca The relative device address to be assigned= . > > + @param[in] S18A The boolean to show if it's a UHS-I SD car= d. > > + @param[in] BusWidths The bus width of the SD card. > > + > > + @retval EFI_SUCCESS The operation is done correctly. > > + @retval Others The operation fails. > > + > > +**/ > > +EFI_STATUS > > +SdCardSetBusMode ( > > + IN UINTN DevBase, > > + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > > + IN UINT16 Rca, > > + IN BOOLEAN S18A, > > + IN UINT32 BusWidths > > + ) > > +{ > > + EFI_STATUS Status; > > + DW_MMC_HC_SLOT_CAP *Capability; > > + UINT32 ClockFreq; > > + UINT8 AccessMode; > > + UINT8 SwitchResp[64]; > > + DW_MMC_HC_PRIVATE_DATA *Private; > > + BOOLEAN IsDdr; > > + > > + Private =3D DW_MMC_HC_PRIVATE_FROM_THIS (PassThru); > > + > > + Capability =3D &Private->Capability[0]; > > + > > + if ((Capability->BusWidth =3D=3D 1) || (Capability->BusWidth =3D=3D = 4)) { > > + BusWidths &=3D Capability[0].BusWidth; > > + } else { > > + DEBUG (( > > + DEBUG_ERROR, > > + "SdCardSetBusMode: BusWidths (%d) in capability are wrong\n", > > + Capability->BusWidth > > + )); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (BusWidths =3D=3D 0) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "SdCardSetBusMode: Get wrong BusWidths:%d\n", > > + BusWidths > > + )); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (Private->Capability[0].Ddr50) { > > + IsDdr =3D TRUE; > > + } else { > > + IsDdr =3D FALSE; > > + } > > + > > + Status =3D SdCardSwitchBusWidth (DevBase, PassThru, Rca, IsDdr, > > BusWidths); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "SdCardSetBusMode: Executing SdCardSwitchBusWidth fails with %r\= n", > > + Status > > + )); > > + return Status; > > + } > > + > > + // > > + // Get the supported bus speed from SWITCH cmd return data group #1. > > + // > > + Status =3D SdCardSwitch (PassThru, 0xF, 0xF, 0xF, 0xF, FALSE, Switch= Resp); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + // > > + // Calculate supported bus speed/bus width/clock frequency by host a= nd > > device > > + // capability. > > + // > > + ClockFreq =3D 0; > > + if (S18A && (Capability->Sdr104 !=3D 0) && ((SwitchResp[13] & BIT3) = !=3D 0)) { > > + ClockFreq =3D 208; > > + AccessMode =3D 3; > > + } else if (S18A && (Capability->Sdr50 !=3D 0) && > > + ((SwitchResp[13] & BIT2) !=3D 0)) { > > + ClockFreq =3D 100; > > + AccessMode =3D 2; > > + } else if (S18A && (Capability->Ddr50 !=3D 0) && > > + ((SwitchResp[13] & BIT4) !=3D 0)) { > > + ClockFreq =3D 50; > > + AccessMode =3D 4; > > + } else if ((SwitchResp[13] & BIT1) !=3D 0) { > > + ClockFreq =3D 50; > > + AccessMode =3D 1; > > + } else { > > + ClockFreq =3D 25; > > + AccessMode =3D 0; > > + } > > + > > + Status =3D SdCardSwitch (PassThru, AccessMode, 0xF, 0xF, 0xF, TRUE, > > SwitchResp); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + if ((SwitchResp[16] & 0xF) !=3D AccessMode) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d fails! T= he > > Switch response is 0x%1x\n", > > + AccessMode, > > + ClockFreq, > > + SwitchResp[16] & 0xF > > + )); > > + return EFI_DEVICE_ERROR; > > + } > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d \n", > > + AccessMode, > > + ClockFreq > > + )); > > + > > + Status =3D DwMmcHcClockSupply (DevBase, ClockFreq * 1000, *Capabilit= y); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + return Status; > > +} > > + > > +EFI_STATUS > > +SdCardIdentification ( > > + IN DW_MMC_HC_PRIVATE_DATA *Private > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN DevBase; > > + EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; > > + UINT32 Ocr; > > + UINT16 Rca; > > + BOOLEAN Xpc; > > + BOOLEAN S18r; > > + UINT64 MaxCurrent; > > + SD_SCR Scr; > > + SD_CSD Csd; > > + > > + DevBase =3D Private->DevBase; > > + PassThru =3D &Private->PassThru; > > + // > > + // 1. Send Cmd0 to the device > > + // > > + Status =3D SdCardReset (PassThru); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_INFO, > > + "SdCardIdentification: Executing Cmd0 fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + MicroSecondDelay (10000); > > + // > > + // 2. Send Cmd8 to the device > > + // > > + Status =3D SdCardVoltageCheck (PassThru, 0x1, 0xFF); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_INFO, > > + "SdCardIdentification: Executing Cmd8 fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + // > > + // 3. Send Acmd41 with voltage window 0 to the device > > + // > > + Status =3D SdCardSendOpCond (PassThru, 0, 0, FALSE, FALSE, FALSE, &O= cr); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_INFO, > > + "SdCardIdentification: Executing SdCardSendOpCond fails with %r\= n", > > + Status > > + )); > > + return EFI_DEVICE_ERROR; > > + } > > + > > + if (Private->Capability[0].Voltage33 !=3D 0) { > > + // > > + // Support 3.3V > > + // > > + MaxCurrent =3D ((UINT32)Private->MaxCurrent[0] & 0xFF) * 4; > > + S18r =3D FALSE; > > + } else if (Private->Capability[0].Voltage30 !=3D 0) { > > + // > > + // Support 3.0V > > + // > > + MaxCurrent =3D (((UINT32)Private->MaxCurrent[0] >> 8) & 0xFF) * 4; > > + S18r =3D FALSE; > > + } else if (Private->Capability[0].Voltage18 !=3D 0) { > > + // > > + // Support 1.8V > > + // > > + MaxCurrent =3D (((UINT32)Private->MaxCurrent[0] >> 16) & 0xFF) * 4= ; > > + S18r =3D TRUE; > > + } else { > > + ASSERT (FALSE); > > + return EFI_DEVICE_ERROR; > > + } > > + > > + if (MaxCurrent >=3D 150) { > > + Xpc =3D TRUE; > > + } else { > > + Xpc =3D FALSE; > > + } > > + > > + // > > + // 4. Repeatly send Acmd41 with supply voltage window to the device. > > + // Note here we only support the cards complied with SD physical > > + // layer simplified spec version 2.0 and version 3.0 and above. > > + // > > + do { > > + Status =3D SdCardSendOpCond (PassThru, 0, Ocr, S18r, Xpc, TRUE, &O= cr); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "SdCardIdentification: SdCardSendOpCond fails with %r Ocr %x, = S18r > > %x, Xpc %x\n", > > + Status, > > + Ocr, > > + S18r, > > + Xpc > > + )); > > + return EFI_DEVICE_ERROR; > > + } > > + } while ((Ocr & BIT31) =3D=3D 0); > > + > > + Status =3D SdCardAllSendCid (PassThru); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "SdCardIdentification: Executing SdCardAllSendCid fails with %r\= n", > > + Status > > + )); > > + return Status; > > + } > > + > > + Status =3D SdCardSetRca (PassThru, &Rca); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "SdCardIdentification: Executing SdCardSetRca fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + > > + Status =3D SdCardGetCsd (PassThru, Rca, &Csd); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "SdCardIdentification: Executing SdCardGetCsd fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + > > + Status =3D SdCardSelect (PassThru, Rca); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "SdCardIdentification: Selecting card fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + > > + Status =3D SdCardGetScr (PassThru, Rca, &Scr); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "SdCardIdentification: Executing SdCardGetScr fails with %r\n", > > + Status > > + )); > > + return Status; > > + } > > + > > + // > > + // Enter Data Tranfer Mode. > > + // > > + DEBUG ((DEBUG_INFO, "SdCardIdentification: Found a SD device\n")); > > + Private->Slot[0].CardType =3D SdCardType; > > + > > + Status =3D SdCardSetBusMode (DevBase, PassThru, Rca, S18r, > > Scr.SdBusWidths); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + Private->Slot[0].Initialized =3D TRUE; > > + > > + return Status; > > +} > > -- > > 2.12.3