From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail05.groups.io (mail05.groups.io [45.79.224.7]) by spool.mail.gandi.net (Postfix) with ESMTPS id 1793B740467 for ; Thu, 2 May 2024 04:24:29 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=oSmshS8x36YIIHcicVLV3Ydu5i9+OFJvOEFzA9i0cF8=; c=relaxed/simple; d=groups.io; h=From:To:CC:Subject:Thread-Topic:Thread-Index:Date:Message-ID:References:In-Reply-To:Accept-Language:msip_labels:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Resent-Date:Resent-From:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Language:Content-Type:Content-Transfer-Encoding; s=20240206; t=1714623868; v=1; b=q5gSk986CN32CiUCiAcs/HrfOw81Ordlzu/g2/KvfzJ8WhkNcd36m3G+GWrurEl8kZ+XPI8R SvETEHBvlCO9naPGnPSvmIhJy5FE4Y2p2EZBrsk39gvlPBAYc2vjGLFBa3FHMdXGCmwASw+47vB WphzMBQDkP2lanFmDr26tYH6GmVRtxXCaq1/+5GHCua7qLgRc/2MMwOfVxpz5QvEWIOMF+BxhVT KBROK2fk/4CHw94KaFfZeUo0mknUrllxumajDVaUlwtIbTU25eCD+JMKpK03Xy/zYGhvpBi9yzq 5OXMQZeJqx6C0vlGDH6mQVPnRVqUwnqV+nXK/8UnXSJPg== X-Received: by 127.0.0.2 with SMTP id bX2OYY7687511xg05aEsmNPX; Wed, 01 May 2024 21:24:28 -0700 X-Received: from NAM10-MW2-obe.outbound.protection.outlook.com (NAM10-MW2-obe.outbound.protection.outlook.com [40.107.94.51]) by mx.groups.io with SMTP id smtpd.web11.5785.1714623867499231287 for ; Wed, 01 May 2024 21:24:27 -0700 X-Received: from LV8PR12MB9452.namprd12.prod.outlook.com (2603:10b6:408:200::8) by PH8PR12MB7279.namprd12.prod.outlook.com (2603:10b6:510:221::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7519.40; Thu, 2 May 2024 04:24:22 +0000 X-Received: from LV8PR12MB9452.namprd12.prod.outlook.com ([fe80::e006:4173:de2c:aca0]) by LV8PR12MB9452.namprd12.prod.outlook.com ([fe80::e006:4173:de2c:aca0%5]) with mapi id 15.20.7519.031; Thu, 2 May 2024 04:24:22 +0000 From: "Chang, Abner via groups.io" To: "Chesley, Brit" , "devel@edk2.groups.io" CC: "Attar, AbdulLateef (Abdul Lateef)" Subject: Re: [edk2-devel] [PATCH v1 2/6] MdeModulePkg/Bus/Spi/SpiBus: Adding SpiBus Drivers Thread-Topic: [PATCH v1 2/6] MdeModulePkg/Bus/Spi/SpiBus: Adding SpiBus Drivers Thread-Index: AQHam/qVIsptcjcgcEyOhTb02sqffLGDWQcg Date: Thu, 2 May 2024 04:24:22 +0000 Message-ID: References: <20240501190527.200937-1-brit.chesley@amd.com> <20240501190527.200937-3-brit.chesley@amd.com> In-Reply-To: <20240501190527.200937-3-brit.chesley@amd.com> Accept-Language: en-US, zh-CN X-MS-Has-Attach: X-MS-TNEF-Correlator: msip_labels: MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_ActionId=3d093d85-d8d9-499f-94dc-a6274b680f7c;MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_ContentBits=0;MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_Enabled=true;MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_Method=Standard;MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_Name=General;MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_SetDate=2024-05-02T04:23:32Z;MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_SiteId=3dd8961f-e488-4e60-8e11-a82d994e183d; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: LV8PR12MB9452:EE_|PH8PR12MB7279:EE_ x-ms-office365-filtering-correlation-id: 71147ab1-4798-4b43-9a4d-08dc6a5fbe3b x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam-message-info: =?us-ascii?Q?x3/9HBbQFIiOoz0qiudQe2Lno6DBr8o8qfPXlf71RPp8nXe8Cejm+bCQMJlc?= =?us-ascii?Q?mCQ6oybzBtj6yKl6w8h8vxd/ueVRrLkrbD945zt/vkDXC4W1YkiSXij/MWMI?= =?us-ascii?Q?oEM8QTp1Lg7bTiaBu6YyWSHsMNVO5YAqJb7J2VOzhLuaSZkT1z8hA5AVXZxr?= =?us-ascii?Q?MpjHselAyKvWdFtvw1voEE9vZXEOFHOXeb5Q2sBOex0wacwpk2aQB8MDSWK1?= =?us-ascii?Q?4UWXzF9MF5NMxAqLtCMDqX7TSU7JuoETxzYpS2QI9X8GoZBjRYAUEeM1tGIj?= =?us-ascii?Q?o6q8i8TGYMiOtR6L7QMXphOJM8EEPf6kK4Drg2OtBh+WmJjx9kxrOc0glM7I?= =?us-ascii?Q?UEKv7mdDfXFyTkUEw93ayKAAN2WLRHuzwNiuR+5/bgBXiaWjuQgZck6UwCtZ?= =?us-ascii?Q?CDNQVqDLBBBg+aQEMJclku/VbMHRuxC+4HCKoogQg8tG35iHe4bO6dtWoPOF?= =?us-ascii?Q?oxDoVIuaaCD/p70mMvALp7uajVw6JxnrUpjsw3czkgti/yH3TdHhBHCUvndS?= =?us-ascii?Q?zY6D3zD2V8nZ3u/cMBOhGgPqzIfD8lJWYsp0nMXwYR9TU1mU0w0es8zfsVuq?= =?us-ascii?Q?rGRJX/wJQeSUXfCTJQcc7xa8jKJA4Ku0ZcQSYnpMmo7k9CssUsteS47yNeTW?= =?us-ascii?Q?3ya3HULCnY/L38XRScnB2IJ6pF6tbl3/SMd9wGEPOWA9hstpkkYTTufq53ml?= =?us-ascii?Q?UenwIYd8ays2oRQmn9x4WcpSFVlXKJ4oit0Qnp/99a4mo9tXq4c58HKHUaXL?= =?us-ascii?Q?PUVYDzzmtCvuQm5/yH3m0SqmAskfq5jJ3g91zQ5j/BAxTXB8kWB3wuckUm8k?= =?us-ascii?Q?TNYuiRMD+q724mx9YqYNojSpFNFXp4/SmbQ98qUfwXzarb0pqtz4ScQKITMz?= =?us-ascii?Q?9D0eCu3pFUcAYYPNoIMbX1+nCUJfHhmnvm2gEY088BORvGCM6u6eQPqSsXfz?= =?us-ascii?Q?9XH+F2Vz8kXYVeqe2/zYFmBLOzFCQ25ozvBos37jYjdA4DvYmwF/QfGDp6fZ?= =?us-ascii?Q?1KV5AEV75ojVnTUIcYMci0z67WPwg6J9DoKSnKXOd/Z2zBNHQY2LjVRqBzct?= =?us-ascii?Q?YuECX9fD84fPQ929+AQajB8LZxzylVoP4jiNjvbzye4cwFtO5i7BxwJ57hny?= =?us-ascii?Q?reKBJDn/8XIy+62UTgTKSNWSMx50GbIOhrFl3caXbROr48b4h72CloKLS7VF?= =?us-ascii?Q?lUKkZNLE6Z1au1cZK+8+dasyXlVQh6it7hPePnfLvOrSScVZBjvji+49RHnk?= =?us-ascii?Q?seqRLV5NXv8TxJRlaek3kZl6gYdXJIBWfhIx8b6NoJWrncH1TdyZvgmvwnph?= =?us-ascii?Q?6JB6o1uPAPrttwEP/9E+Sq22v4Mt3J3kMB/DVI81+B6EBg=3D=3D?= x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?yeuEGk5is2zHRGFOA3h6UIJC0RFTgEzRvAZnnz3fNcX4ugwOGW8YoXWdmQvB?= =?us-ascii?Q?rgG9niNWWewKPZtSe6R9n9P7QC+OXmm8T7/uc+ut7+u/eCh6FryBy3Beoq6W?= =?us-ascii?Q?+UB3c2a0YDopHkhXYlXVedRxLFl/AnMA9wxNJhbtqGVgXr6t4YY0n2bKWqTL?= =?us-ascii?Q?sqWa2Vmjp3KTqHS9QDuBnBbXsefuJZvLmBnD6YUKh5RlgCuuiFtxmVmX9bZ7?= =?us-ascii?Q?gHBnR61A4Kg/biarfFs5APuVE9k6uVzO6elC7EvIT4m/kMrWRTM5fhYQXceQ?= =?us-ascii?Q?9bn2kfG3IZTEHg4VnRk4Zy2H1SC18DmIbm87vj9DIcV/+0DFQp9m6X9f8uP/?= =?us-ascii?Q?p+kcof9osflLCP3/1fQ3EBzh6bDVB/T3joVY5oar9dIZD/e/H5doyEgeEJZL?= =?us-ascii?Q?5IVGdxxEEXtEGotdlHvb6M06a3o2z0svt8xyODgdpPT0fJECejSFFu1rPAXl?= =?us-ascii?Q?3An5Yw9/AxdGhoIRyTDt1mdnboznVulGGZYG+2vwE8zZjhnNObyiIqgoZWDl?= =?us-ascii?Q?+u2Qqmr/IVKIf9v/VFa6IoGU/6F34Dfq2q0BvwkemSxPASnkGqRwWSTb223A?= =?us-ascii?Q?mOzRravF05/g4dWz9cptkgIODExJPdsVp9S+KLyKSNmGjO+NUWEe30ibPpiK?= =?us-ascii?Q?x8Cip63+CXj5ridVIjxkvUub2Z+A/11MYungyhV3np7mZE9suhKrImOwLv/o?= =?us-ascii?Q?RNoAvRsm4pj90NzDExzYNJPYDMyBellYZke7xIdzy0LkH5+2q3y3QzjdBd89?= =?us-ascii?Q?sf3FYwFRER5ikIJ5WTRWE8mzfjX9Cidk1i7xandaRXJhW6loVsneT8Gnn3dU?= =?us-ascii?Q?wlPZbpAz2Hm9becchVezhzAXFZ2C4H+qfdMOdS2vVb1dY6SEF0wQGbnrrwQw?= =?us-ascii?Q?i0dZUk1YoqmSSsdWDjdxSFpNaXFw2IwEzZEiKsYqj2w4519vkmpKRaprSbIR?= =?us-ascii?Q?TyJBfFtcVAUo52jHjhAPOxLnlyhujj0f54ly4YZIBMIjIXhY05FOFwEOs3UB?= =?us-ascii?Q?Agxv9jaDu3cVJFR2mHHs5ncZdtJIrxIaT7pX/54SXwNHxkPXokuQapAEz2vV?= =?us-ascii?Q?aHZhwTc1l/BGBczVgagIgN0m+ag/HRV0bXaA3pdQFDoVhZ6XQ/aKjfOHDo0W?= =?us-ascii?Q?yvi/IGTnO1iW9pn47jElhf9jkqRgz0tzxa8kpnk1nm3oRwdNuMFW3g/HQdKM?= =?us-ascii?Q?DhPIfsugJRbiwulWVJyQ/t0H09H//jBoBeBoNTamOq5680vDiWPF+Glr8fbA?= =?us-ascii?Q?ks13B3YJtJ1d0gfpaRXAWntOqzVYEq96pDcC2oVEz5Et1Koupj+HU6wDBjk0?= =?us-ascii?Q?lLtdzFLx2H0Un0TchmTjGGARtD9HiYvMgPOyJppnyLbATZ3LYhMMF2a/L8TC?= =?us-ascii?Q?mjfSpeX/p70jbeaFWW+lWAcfG9Yo0YrKrVnaSvqH1QJh46Wq+lRqxFDFLh2K?= =?us-ascii?Q?7LBJySqCuexfy7KuNZuZnsduTqGl7sJgqxaAnsqvkv54BNTOf6Al0+yNPgIK?= =?us-ascii?Q?ndMpuW0gDLxrrIptpRN3NO3ROUpzFGBXtL4qDfTUIjJl5d/0cySIWIgL0prw?= =?us-ascii?Q?3vJzuzZVaptM2lSnpjM=3D?= MIME-Version: 1.0 X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: LV8PR12MB9452.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 71147ab1-4798-4b43-9a4d-08dc6a5fbe3b X-MS-Exchange-CrossTenant-originalarrivaltime: 02 May 2024 04:24:22.5542 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: alYDL+nPTjLotbzJfjm2PKBFDb+GRGYiajQ6Bf4OT4NeeSYTHX1NKNpZR/C0gzI7vkuKuOn/AlUHqmmT+RdZew== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH8PR12MB7279 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Resent-Date: Wed, 01 May 2024 21:24:27 -0700 Resent-From: abner.chang@amd.com Reply-To: devel@edk2.groups.io,abner.chang@amd.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: Bq1NYot80wrGjkukWqo1eGSkx7686176AA= Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20240206 header.b=q5gSk986; dmarc=pass (policy=none) header.from=groups.io; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 45.79.224.7 as permitted sender) smtp.mailfrom=bounce@groups.io [AMD Official Use Only - General] We had reviewed this patch internally before sending this to community. Reviewed-by: Abner Chang > -----Original Message----- > From: Chesley, Brit > Sent: Thursday, May 2, 2024 3:05 AM > To: devel@edk2.groups.io > Cc: Chang, Abner ; Attar, AbdulLateef (Abdul > Lateef) > Subject: [PATCH v1 2/6] MdeModulePkg/Bus/Spi/SpiBus: Adding SpiBus > Drivers > > From: Brit Chesley > > Added SpiBus DXE and SMM drivers. This code translates SPI requests from > the application layer into SPI Bus transactions on the SPI host > controller. The code is responsible for checking if the transaction is > valid, then setting up the SPI clock and chip select properly before > passing the bus transaction to the host controller. > > Platform Initialization Spec 1.7 volume 5 section 18.1.6 > > Bugzilla #4753 > > Cc: Abner Chang > Cc: Abdul Lateef Attar > Signed-off-by: Brit Chesley > --- > MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf | 41 ++ > MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf | 41 ++ > MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h | 167 +++++++++ > MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c | 433 > ++++++++++++++++++++++ > MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c | 198 ++++++++++ > MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c | 162 ++++++++ > MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni | 10 + > 7 files changed, 1052 insertions(+) > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni > > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf > new file mode 100644 > index 000000000000..3e2cc2daba1c > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf > @@ -0,0 +1,41 @@ > +## @file > +# Component description for the SPI BUS DXE module > +# > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<= BR> > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > +[Defines] > + INF_VERSION =3D 1.27 > + BASE_NAME =3D SpiBusDxe > + FILE_GUID =3D 25CE038C-5C3A-4A9B-A111-90DF5897E058 > + MODULE_TYPE =3D DXE_DRIVER > + VERSION_STRING =3D 0.1 > + PI_SPECIFICATION_VERSION =3D 0x0001000A > + ENTRY_POINT =3D SpiBusEntry > + > +[Packages] > + MdePkg/MdePkg.dec > + > +[LibraryClasses] > + DebugLib > + DevicePathLib > + MemoryAllocationLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + > +[Sources] > + SpiBusDxe.c > + SpiBus.c > + SpiBus.h > + > +[Protocols] > + gEfiSpiConfigurationProtocolGuid ## CONSUMES > + gEfiSpiHcProtocolGuid ## CONSUMES > + > +[Depex] > + gEfiSpiConfigurationProtocolGuid AND > + gEfiSpiHcProtocolGuid > + > +[UserExtensions.TianoCore."ExtraFiles"] > + SpiBus.uni > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf > new file mode 100644 > index 000000000000..9e3a5aae7d87 > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf > @@ -0,0 +1,41 @@ > +## @file > +# Component description for the SPI BUS SMM module > +# > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<= BR> > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > +[Defines] > + INF_VERSION =3D 1.27 > + BASE_NAME =3D SpiBusSmm > + FILE_GUID =3D 5DBB52E1-3D78-4C9C-A9D7-A43E79E93AC0 > + MODULE_TYPE =3D DXE_SMM_DRIVER > + VERSION_STRING =3D 0.1 > + PI_SPECIFICATION_VERSION =3D 0x0001000A > + ENTRY_POINT =3D SpiBusEntry > + > +[Packages] > + MdePkg/MdePkg.dec > + > +[LibraryClasses] > + DebugLib > + DevicePathLib > + MemoryAllocationLib > + MmServicesTableLib > + UefiDriverEntryPoint > + > +[Sources] > + SpiBus.h > + SpiBus.c > + SpiBusSmm.c > + > +[Protocols] > + gEfiSpiSmmConfigurationProtocolGuid ## CONSU= MES > + gEfiSpiSmmHcProtocolGuid ## CONSU= MES > + > +[Depex] > + gEfiSpiSmmConfigurationProtocolGuid AND > + gEfiSpiSmmHcProtocolGuid > + > +[UserExtensions.TianoCore."ExtraFiles"] > + SpiBus.uni > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h > new file mode 100644 > index 000000000000..7a43f66ac750 > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h > @@ -0,0 +1,167 @@ > +/** @file > + > + SPI bus driver > + > + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef SPI_BUS_H_ > +#define SPI_BUS_H_ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define SPI_IO_SIGNATURE SIGNATURE_32 ('s', 'i', 'o', 'c') > + > +typedef struct { > + UINTN Signature; > + EFI_HANDLE Handle; > + EFI_SPI_IO_PROTOCOL Protocol; > + EFI_SPI_BUS_TRANSACTION BusTransaction; > + EFI_SPI_CONFIGURATION_PROTOCOL *SpiConfig; > + EFI_SPI_HC_PROTOCOL *SpiHc; > + EFI_SPI_BUS *SpiBus; > +} SPI_IO_CHIP; > + > +#define SPI_IO_CHIP_FROM_THIS(a) \ > + CR (a, SPI_IO_CHIP, Protocol, \ > + SPI_IO_SIGNATURE) > + > +/** > + Checks if two device paths are the same > + > + @param[in] DevicePath1 First device path to compare > + @param[in] DevicePath2 Second device path to compare > + > + @retval TRUE The device paths share the same nodes and va= lues > + @retval FALSE The device paths differ > +**/ > +BOOLEAN > +EFIAPI > +DevicePathsAreEqual ( > + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath1, > + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath2 > + ); > + > +/** > + Initiate a SPI transaction between the host and a SPI peripheral. > + > + This routine must be called at or below TPL_NOTIFY. > + This routine works with the SPI bus layer to pass the SPI transaction = to the > + SPI controller for execution on the SPI bus. There are four types of > + supported transactions supported by this routine: > + * Full Duplex: WriteBuffer and ReadBuffer are the same size. > + * Write Only: WriteBuffer contains data for SPI peripheral, ReadBytes = =3D 0 > + * Read Only: ReadBuffer to receive data from SPI peripheral, WriteByte= s =3D 0 > + * Write Then Read: WriteBuffer contains control data to write to SPI > + peripheral before data is placed into the ReadBuffe= r. > + Both WriteBytes and ReadBytes must be non-zero. > + > + @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL struct= ure. > + @param[in] TransactionType Type of SPI transaction. > + @param[in] DebugTransaction Set TRUE only when debugging is desired. > + Debugging may be turned on for a single = SPI > + transaction. Only this transaction will = display > + debugging messages. All other transactio= ns with > + this value set to FALSE will not display= any > + debugging messages. > + @param[in] ClockHz Specify the ClockHz value as zero (0) to= use > + the maximum clock frequency supported by= the > + SPI controller and part. Specify a non-z= ero > + value only when a specific SPI transacti= on > + requires a reduced clock rate. > + @param[in] BusWidth Width of the SPI bus in bits: 1, 2, 4 > + @param[in] FrameSize Frame size in bits, range: 1 - 32 > + @param[in] WriteBytes The length of the WriteBuffer in bytes. > + Specify zero for read-only operations. > + @param[in] WriteBuffer The buffer containing data to be sent fr= om the > + host to the SPI chip. Specify NULL for r= ead > + only operations. > + * Frame sizes 1-8 bits: UINT8 (one byte)= per > + frame > + * Frame sizes 7-16 bits: UINT16 (two byt= es) per > + frame > + * Frame sizes 17-32 bits: UINT32 (four b= ytes) > + per frame The transmit frame is in the= least > + significant N bits. > + @param[in] ReadBytes The length of the ReadBuffer in bytes. > + Specify zero for write-only operations. > + @param[out] ReadBuffer The buffer to receeive data from the SPI= chip > + during the transaction. Specify NULL for= write > + only operations. > + * Frame sizes 1-8 bits: UINT8 (one byte)= per > + frame > + * Frame sizes 7-16 bits: UINT16 (two byt= es) per > + frame > + * Frame sizes 17-32 bits: UINT32 (four b= ytes) > + per frame The received frame is in the= least > + significant N bits. > + > + @retval EFI_SUCCESS The SPI transaction completed successfu= lly > + @retval EFI_BAD_BUFFER_SIZE The writeBytes value was invalid > + @retval EFI_BAD_BUFFER_SIZE The ReadBytes value was invalid > + @retval EFI_INVALID_PARAMETER TransactionType is not valid, > + or BusWidth not supported by SPI periph= eral or > + SPI host controller, > + or WriteBytes non-zero and WriteBuffer = is > + NULL, > + or ReadBytes non-zero and ReadBuffer is= NULL, > + or ReadBuffer !=3D WriteBuffer for full= -duplex > + type, > + or WriteBuffer was NULL, > + or TPL is too high > + @retval EFI_OUT_OF_RESOURCES Insufficient memory for SPI transaction > + @retval EFI_UNSUPPORTED The FrameSize is not supported by the S= PI > bus > + layer or the SPI host controller > + @retval EFI_UNSUPPORTED The SPI controller was not able to supp= ort > + > +**/ > +EFI_STATUS > +EFIAPI > +Transaction ( > + IN CONST EFI_SPI_IO_PROTOCOL *This, > + IN EFI_SPI_TRANSACTION_TYPE TransactionType, > + IN BOOLEAN DebugTransaction, > + IN UINT32 ClockHz OPTIONAL, > + IN UINT32 BusWidth, > + IN UINT32 FrameSize, > + IN UINT32 WriteBytes, > + IN UINT8 *WriteBuffer, > + IN UINT32 ReadBytes, > + OUT UINT8 *ReadBuffer > + ); > + > +/** > + Update the SPI peripheral associated with this SPI 10 instance. > + > + Support socketed SPI parts by allowing the SPI peripheral driver to re= place > + the SPI peripheral after the connection is made. An example use is soc= keted > + SPI NOR flash parts, where the size and parameters change depending up= on > + device is in the socket. > + > + @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure. > + @param[in] SpiPeripheral Pointer to an EFI_SPI_PERIPHERAL structure. > + > + @retval EFI_SUCCESS The SPI peripheral was updated successf= ully > + @retval EFI_INVALID_PARAMETER The SpiPeripheral value is NULL, > + or the SpiPeripheral->SpiBus is NULL, > + or the SpiPeripheral->SpiBus pointing a= t > + wrong bus, or the SpiPeripheral->SpiPar= t is NULL > + > +**/ > +EFI_STATUS > +EFIAPI > +UpdateSpiPeripheral ( > + IN CONST EFI_SPI_IO_PROTOCOL *This, > + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral > + ); > + > +#endif //SPI_BUS_H_ > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c > new file mode 100644 > index 000000000000..b183ca182cab > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c > @@ -0,0 +1,433 @@ > +/** @file > + > + SpiBus driver > + > + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > +#include > +#include > +#include > +#include > +#include > +#include > +#include "SpiBus.h" > + > +/** > + Checks if two device paths are the same. > + > + @param[in] DevicePath1 First device path to compare > + @param[in] DevicePath2 Second device path to compare > + > + @retval TRUE The device paths share the same nodes and va= lues > + @retval FALSE The device paths differ > +**/ > +BOOLEAN > +EFIAPI > +DevicePathsAreEqual ( > + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath1, > + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath2 > + ) > +{ > + UINTN Size1; > + UINTN Size2; > + > + Size1 =3D GetDevicePathSize (DevicePath1); > + Size2 =3D GetDevicePathSize (DevicePath2); > + > + if (Size1 !=3D Size2) { > + return FALSE; > + } > + > + if (CompareMem (DevicePath1, DevicePath2, Size1) !=3D 0) { > + return FALSE; > + } > + > + return TRUE; > +} > + > +/** > + Calls the SpiPeripherals ChipSelect if it is not null, otherwise > + calls the Host Controllers ChipSelect function. > + > + @param[in] SpiChip The SpiChip to place on the bus via assertin= g its chip > select > + @param[in] PinValue Value to place on the chip select pin > + > + @retval EFI_SUCCESS Chip select pin was placed at requ= ested level > + @retval EFI_INVALID_PARAMETER Invalid parameters passed into > ChipSelect function > +**/ > +EFI_STATUS > +EFIAPI > +SpiChipSelect ( > + IN CONST SPI_IO_CHIP *SpiChip, > + IN BOOLEAN PinValue > + ) > +{ > + EFI_STATUS Status; > + > + // Check which chip select function to use > + if (SpiChip->Protocol.SpiPeripheral->ChipSelect !=3D NULL) { > + Status =3D SpiChip->Protocol.SpiPeripheral->ChipSelect ( > + SpiChip->BusTransaction.= SpiPeripheral, > + PinValue > + ); > + } else { > + Status =3D SpiChip->SpiHc->ChipSelect ( > + SpiChip->SpiHc, > + SpiChip->BusTransaction.SpiPeripheral, > + PinValue > + ); > + } > + > + return Status; > +} > + > +/** > + Checks the SpiChip's BusTransaction attributes to ensure its a valid S= PI > transaction. > + > + @param[in] SpiChip The SpiChip where a bus transaction is reque= sted > + > + @retval EFI_SUCCESS This is a valid SPI bus transaction > + @retval EFI_BAD_BUFFER_SIZE The WriteBytes value was invalid > + @retval EFI_BAD_BUFFER_SIZE The ReadBytes value was invalid > + @retval EFI_INVALID_PARAMETER TransactionType is not valid, > + or BusWidth not supported by SPI periph= eral or > + SPI host controller, > + or WriteBytes non-zero and WriteBuffer = is > + NULL, > + or ReadBytes non-zero and ReadBuffer is= NULL, > + or ReadBuffer !=3D WriteBuffer for full= -duplex > + type, > + or WriteBuffer was NULL, > + or TPL is too high > + @retval EFI_OUT_OF_RESOURCES Insufficient memory for SPI transaction > + @retval EFI_UNSUPPORTED The FrameSize is not supported by the S= PI > bus > + layer or the SPI host controller > + @retval EFI_UNSUPPORTED The SPI controller was not able to supp= ort > +**/ > +EFI_STATUS > +EFIAPI > +IsValidSpiTransaction ( > + IN SPI_IO_CHIP *SpiChip > + ) > +{ > + // Error checking > + if (SpiChip->BusTransaction.TransactionType > > SPI_TRANSACTION_WRITE_THEN_READ) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (((SpiChip->BusTransaction.BusWidth !=3D 1) && (SpiChip- > >BusTransaction.BusWidth !=3D 2) && (SpiChip->BusTransaction.BusWidth != =3D 4) > && > + (SpiChip->BusTransaction.BusWidth !=3D 8)) || (SpiChip- > >BusTransaction.FrameSize =3D=3D 0)) > + { > + return EFI_INVALID_PARAMETER; > + } > + > + if ((SpiChip->BusTransaction.BusWidth =3D=3D 8) && (((SpiChip- > >Protocol.Attributes & SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH) !=3D > SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH) || > + ((SpiChip->BusTransact= ion.SpiPeripheral->Attributes > & SPI_PART_SUPPORTS_8_BIT_DATA_BUS_WIDTH) !=3D > SPI_PART_SUPPORTS_8_BIT_DATA_BUS_WIDTH))) > + { > + return EFI_INVALID_PARAMETER; > + } else if ((SpiChip->BusTransaction.BusWidth =3D=3D 4) && (((SpiChip- > >Protocol.Attributes & SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) !=3D > SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) || > + ((SpiChip->BusT= ransaction.SpiPeripheral- > >Attributes & SPI_PART_SUPPORTS_4_BIT_DATA_BUS_WIDTH) !=3D > SPI_PART_SUPPORTS_4_BIT_DATA_BUS_WIDTH))) > + { > + return EFI_INVALID_PARAMETER; > + } else if ((SpiChip->BusTransaction.BusWidth =3D=3D 2) && (((SpiChip- > >Protocol.Attributes & SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) !=3D > SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) || > + ((SpiChip->BusT= ransaction.SpiPeripheral- > >Attributes & SPI_PART_SUPPORTS_2_BIT_DATA_BUS_WIDTH) !=3D > SPI_PART_SUPPORTS_2_BIT_DATA_BUS_WIDTH))) > + { > + return EFI_INVALID_PARAMETER; > + } > + > + if (((SpiChip->BusTransaction.WriteBytes > 0) && (SpiChip- > >BusTransaction.WriteBuffer =3D=3D NULL)) || ((SpiChip- > >BusTransaction.ReadBytes > 0) && (SpiChip->BusTransaction.ReadBuffer =3D= =3D > NULL))) { > + return EFI_INVALID_PARAMETER; > + } > + > + if ((SpiChip->BusTransaction.TransactionType =3D=3D > SPI_TRANSACTION_FULL_DUPLEX) && (SpiChip- > >BusTransaction.ReadBytes !=3D SpiChip->BusTransaction.WriteBytes)) { > + return EFI_INVALID_PARAMETER; > + } > + > + // Check frame size, passed parameter is in bits > + if ((SpiChip->Protocol.FrameSizeSupportMask & (1<<(SpiChip- > >BusTransaction.FrameSize-1))) =3D=3D 0) { > + return EFI_UNSUPPORTED; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Initiate a SPI transaction between the host and a SPI peripheral. > + > + This routine must be called at or below TPL_NOTIFY. > + This routine works with the SPI bus layer to pass the SPI transaction = to the > + SPI controller for execution on the SPI bus. There are four types of > + supported transactions supported by this routine: > + * Full Duplex: WriteBuffer and ReadBuffer are the same size. > + * Write Only: WriteBuffer contains data for SPI peripheral, ReadBytes = =3D 0 > + * Read Only: ReadBuffer to receive data from SPI peripheral, WriteByte= s =3D 0 > + * Write Then Read: WriteBuffer contains control data to write to SPI > + peripheral before data is placed into the ReadBuffe= r. > + Both WriteBytes and ReadBytes must be non-zero. > + > + @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL struct= ure. > + @param[in] TransactionType Type of SPI transaction. > + @param[in] DebugTransaction Set TRUE only when debugging is desired. > + Debugging may be turned on for a single = SPI > + transaction. Only this transaction will = display > + debugging messages. All other transactio= ns with > + this value set to FALSE will not display= any > + debugging messages. > + @param[in] ClockHz Specify the ClockHz value as zero (0) to= use > + the maximum clock frequency supported by= the > + SPI controller and part. Specify a non-z= ero > + value only when a specific SPI transacti= on > + requires a reduced clock rate. > + @param[in] BusWidth Width of the SPI bus in bits: 1, 2, 4 > + @param[in] FrameSize Frame size in bits, range: 1 - 32 > + @param[in] WriteBytes The length of the WriteBuffer in bytes. > + Specify zero for read-only operations. > + @param[in] WriteBuffer The buffer containing data to be sent fr= om the > + host to the SPI chip. Specify NULL for r= ead > + only operations. > + * Frame sizes 1-8 bits: UINT8 (one byte)= per > + frame > + * Frame sizes 7-16 bits: UINT16 (two byt= es) per > + frame > + * Frame sizes 17-32 bits: UINT32 (four b= ytes) > + per frame The transmit frame is in the= least > + significant N bits. > + @param[in] ReadBytes The length of the ReadBuffer in bytes. > + Specify zero for write-only operations. > + @param[out] ReadBuffer The buffer to receeive data from the SPI= chip > + during the transaction. Specify NULL for= write > + only operations. > + * Frame sizes 1-8 bits: UINT8 (one byte)= per > + frame > + * Frame sizes 7-16 bits: UINT16 (two byt= es) per > + frame > + * Frame sizes 17-32 bits: UINT32 (four b= ytes) > + per frame The received frame is in the= least > + significant N bits. > + > + @retval EFI_SUCCESS The SPI transaction completed successfu= lly > + @retval EFI_BAD_BUFFER_SIZE The WriteBytes value was invalid > + @retval EFI_BAD_BUFFER_SIZE The ReadBytes value was invalid > + @retval EFI_INVALID_PARAMETER TransactionType is not valid, > + or BusWidth not supported by SPI periph= eral or > + SPI host controller, > + or WriteBytes non-zero and WriteBuffer = is > + NULL, > + or ReadBytes non-zero and ReadBuffer is= NULL, > + or ReadBuffer !=3D WriteBuffer for full= -duplex > + type, > + or WriteBuffer was NULL, > + or TPL is too high > + @retval EFI_OUT_OF_RESOURCES Insufficient memory for SPI transaction > + @retval EFI_UNSUPPORTED The FrameSize is not supported by the S= PI > bus > + layer or the SPI host controller > + @retval EFI_UNSUPPORTED The SPI controller was not able to supp= ort > + > +**/ > +EFI_STATUS > +EFIAPI > +Transaction ( > + IN CONST EFI_SPI_IO_PROTOCOL *This, > + IN EFI_SPI_TRANSACTION_TYPE TransactionType, > + IN BOOLEAN DebugTransaction, > + IN UINT32 ClockHz OPTIONAL, > + IN UINT32 BusWidth, > + IN UINT32 FrameSize, > + IN UINT32 WriteBytes, > + IN UINT8 *WriteBuffer, > + IN UINT32 ReadBytes, > + OUT UINT8 *ReadBuffer > + ) > +{ > + EFI_STATUS Status; > + SPI_IO_CHIP *SpiChip; > + UINT32 MaxClockHz; > + UINT8 *DummyReadBuffer; > + UINT8 *DummyWriteBuffer; > + > + SpiChip =3D SPI_IO_CHIP_FROM_THIS (This)= ; > + SpiChip->BusTransaction.SpiPeripheral =3D > + (EFI_SPI_PERIPHERAL *)SpiChip->Protocol.SpiPeripheral; > + SpiChip->BusTransaction.TransactionType =3D TransactionType; > + SpiChip->BusTransaction.DebugTransaction =3D DebugTransaction; > + SpiChip->BusTransaction.BusWidth =3D BusWidth; > + SpiChip->BusTransaction.FrameSize =3D FrameSize; > + SpiChip->BusTransaction.WriteBytes =3D WriteBytes; > + SpiChip->BusTransaction.WriteBuffer =3D WriteBuffer; > + SpiChip->BusTransaction.ReadBytes =3D ReadBytes; > + SpiChip->BusTransaction.ReadBuffer =3D ReadBuffer; > + > + // Ensure valid spi transaction parameters > + Status =3D IsValidSpiTransaction (SpiChip); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Setup the proper clock frequency > + if (SpiChip->BusTransaction.SpiPeripheral->MaxClockHz !=3D 0) { > + MaxClockHz =3D SpiChip->BusTransaction.SpiPeripheral->MaxClockHz; > + } else { > + MaxClockHz =3D SpiChip->BusTransaction.SpiPeripheral->SpiPart- > >MaxClockHz; > + } > + > + // Call proper clock function > + if (SpiChip->Protocol.SpiPeripheral->SpiBus->Clock !=3D NULL) { > + Status =3D SpiChip->Protocol.SpiPeripheral->SpiBus->Clock ( > + SpiChip->BusTran= saction.SpiPeripheral, > + &MaxClockHz > + ); > + } else { > + Status =3D SpiChip->SpiHc->Clock ( > + SpiChip->SpiHc, > + SpiChip->BusTransaction.SpiPeripheral, > + &MaxClockHz > + ); > + } > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D SpiChipSelect (SpiChip, SpiChip->BusTransaction.SpiPeripher= al- > >SpiPart->ChipSelectPolarity); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Check transaction types and match to HC capabilities > + if ((TransactionType =3D=3D SPI_TRANSACTION_WRITE_ONLY) && > + ((SpiChip->SpiHc->Attributes & > HC_SUPPORTS_WRITE_ONLY_OPERATIONS) !=3D > HC_SUPPORTS_WRITE_ONLY_OPERATIONS)) > + { > + // Convert to full duplex transaction > + SpiChip->BusTransaction.ReadBytes =3D SpiChip- > >BusTransaction.WriteBytes; > + SpiChip->BusTransaction.ReadBuffer =3D AllocateZeroPool (SpiChip- > >BusTransaction.ReadBytes); > + > + Status =3D SpiChip->SpiHc->Transaction ( > + SpiChip->SpiHc, > + &SpiChip->BusTransaction > + ); > + > + SpiChip->BusTransaction.ReadBytes =3D ReadBytes; // assign to passed > parameter > + FreePool (SpiChip->BusTransaction.ReadBuffer); // Free temporary buf= fer > + } else if ((TransactionType =3D=3D SPI_TRANSACTION_READ_ONLY) && > + ((SpiChip->SpiHc->Attributes & > HC_SUPPORTS_READ_ONLY_OPERATIONS) !=3D > HC_SUPPORTS_READ_ONLY_OPERATIONS)) > + { > + // Convert to full duplex transaction > + SpiChip->BusTransaction.WriteBytes =3D SpiChip- > >BusTransaction.WriteBytes; > + SpiChip->BusTransaction.WriteBuffer =3D AllocateZeroPool (SpiChip- > >BusTransaction.WriteBytes); > + > + Status =3D SpiChip->SpiHc->Transaction ( > + SpiChip->SpiHc, > + &SpiChip->BusTransaction > + ); > + > + SpiChip->BusTransaction.WriteBytes =3D WriteBytes; > + FreePool (SpiChip->BusTransaction.WriteBuffer); > + } else if ((TransactionType =3D=3D SPI_TRANSACTION_WRITE_THEN_READ) && > + ((SpiChip->SpiHc->Attributes & > HC_SUPPORTS_WRITE_THEN_READ_OPERATIONS) !=3D > HC_SUPPORTS_WRITE_THEN_READ_OPERATIONS)) > + { > + // Convert to full duplex transaction > + DummyReadBuffer =3D AllocateZeroPool (WriteBytes)= ; > + DummyWriteBuffer =3D AllocateZeroPool (ReadBytes); > + SpiChip->BusTransaction.ReadBuffer =3D DummyReadBuffer; > + SpiChip->BusTransaction.ReadBytes =3D WriteBytes; > + > + Status =3D SpiChip->SpiHc->Transaction ( > + SpiChip->SpiHc, > + &SpiChip->BusTransaction > + ); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Write is done, now need to read, restore passed in read buffer in= fo > + SpiChip->BusTransaction.ReadBuffer =3D ReadBuffer; > + SpiChip->BusTransaction.ReadBytes =3D ReadBytes; > + > + SpiChip->BusTransaction.WriteBuffer =3D DummyWriteBuffer; > + SpiChip->BusTransaction.WriteBytes =3D ReadBytes; > + > + Status =3D SpiChip->SpiHc->Transaction ( > + SpiChip->SpiHc, > + &SpiChip->BusTransaction > + ); > + // Restore write data > + SpiChip->BusTransaction.WriteBuffer =3D WriteBuffer; > + SpiChip->BusTransaction.WriteBytes =3D WriteBytes; > + > + FreePool (DummyReadBuffer); > + FreePool (DummyWriteBuffer); > + } else { > + // Supported transaction type, just pass info the SPI HC Protocol > Transaction > + Status =3D SpiChip->SpiHc->Transaction ( > + SpiChip->SpiHc, > + &SpiChip->BusTransaction > + ); > + } > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D SpiChipSelect (SpiChip, !SpiChip->BusTransaction.SpiPeriphe= ral- > >SpiPart->ChipSelectPolarity); > + > + return Status; > +} > + > +/** > + Update the SPI peripheral associated with this SPI 10 SpiChip. > + > + Support socketed SPI parts by allowing the SPI peripheral driver to re= place > + the SPI peripheral after the connection is made. An example use is soc= keted > + SPI NOR flash parts, where the size and parameters change depending up= on > + device is in the socket. > + > + @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure. > + @param[in] SpiPeripheral Pointer to an EFI_SPI_PERIPHERAL structure. > + > + @retval EFI_SUCCESS The SPI peripheral was updated successf= ully > + @retval EFI_INVALID_PARAMETER The SpiPeripheral value is NULL, > + or the SpiPeripheral->SpiBus is NULL, > + or the SpiPeripheral->SpiBus pointing a= t > + wrong bus, or the SpiPeripheral->SpiPar= t is NULL > +**/ > +EFI_STATUS > +EFIAPI > +UpdateSpiPeripheral ( > + IN CONST EFI_SPI_IO_PROTOCOL *This, > + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral > + ) > +{ > + EFI_STATUS Status; > + SPI_IO_CHIP *SpiChip; > + > + DEBUG ((DEBUG_VERBOSE, "%a: SPI Bus - Entry\n", __func__)); > + > + SpiChip =3D SPI_IO_CHIP_FROM_THIS (This); > + > + if ((SpiPeripheral =3D=3D NULL) || (SpiPeripheral->SpiBus =3D=3D NULL)= || > + (SpiPeripheral->SpiPart =3D=3D NULL)) > + { > + return EFI_INVALID_PARAMETER; > + } > + > + // EFI_INVALID_PARAMETER if SpiPeripheral->SpiBus is pointing at wrong > bus > + if (!DevicePathsAreEqual (SpiPeripheral->SpiBus->ControllerPath, SpiCh= ip- > >SpiBus->ControllerPath)) { > + return EFI_INVALID_PARAMETER; > + } > + > + SpiChip->Protocol.OriginalSpiPeripheral =3D SpiChip->Protocol.SpiPerip= heral; > + SpiChip->Protocol.SpiPeripheral =3D SpiPeripheral; > + > + Status =3D EFI_SUCCESS; > + DEBUG (( > + DEBUG_VERBOSE, > + "%a: SPI Bus - Exit Status=3D%r\n", > + __func__, > + Status > + )); > + return Status; > +} > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c > new file mode 100644 > index 000000000000..cd0a2c99a27b > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c > @@ -0,0 +1,198 @@ > +/** @file > + > + SPI bus DXE driver > + > + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "SpiBus.h" > + > +/** > + Entry point of the Spi Bus layer > + > + @param[in] ImageHandle Image handle of this driver. > + @param[in] SystemTable Pointer to standard EFI system table. > + > + @retval EFI_SUCCESS Succeed. > + @retval EFI_DEVICE_ERROR SpiPeripheral is NULL. > + @retval EFI_NOT_FOUND Fail to locate SpiHcProtocol or > SpiIoConfigurationProtocol > + @retval EFI_OUT_OF_RESOURCES Failed to allocate SpiIoChip > +**/ > +EFI_STATUS > +EFIAPI > +SpiBusEntry ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + SPI_IO_CHIP *SpiChip; > + EFI_SPI_HC_PROTOCOL *SpiHc; > + EFI_SPI_CONFIGURATION_PROTOCOL *SpiConfiguration; > + EFI_SPI_PERIPHERAL *SpiPeripheral; > + EFI_SPI_BUS *Bus; > + UINTN BusIndex; > + UINTN HcIndex; > + EFI_HANDLE *SpiHcHandles; > + UINTN HandleCount; > + EFI_DEVICE_PATH_PROTOCOL *SpiHcDevicePath; > + > + DEBUG ((DEBUG_VERBOSE, "%a - ENTRY\n", __func__)); > + > + // Get all SPI HC protocols, could be multiple SPI HC's on a single pl= atform > + Status =3D gBS->LocateHandleBuffer ( > + ByProtocol, > + &gEfiSpiHcProtocolGuid, > + NULL, > + &HandleCount, > + &SpiHcHandles > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "No SpiHcProtocol is found\n")); > + Status =3D EFI_NOT_FOUND; > + goto Exit; > + } > + > + // Locate the SPI Configuration Protocol > + Status =3D gBS->LocateProtocol ( > + &gEfiSpiConfigurationProtocolGuid, > + NULL, > + (VOID **)&SpiConfiguration > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "No SpiConfigurationProtocol is found\n")); > + Status =3D EFI_NOT_FOUND; > + goto Exit; > + } > + > + // Parse through Hc protocols, find correct device path > + for (HcIndex =3D 0; HcIndex < HandleCount; HcIndex++) { > + Status =3D gBS->HandleProtocol ( > + SpiHcHandles[HcIndex], > + &gEfiDevicePathProtocolGuid, > + (VOID **)&SpiHcDevicePath > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "Error locating EFI device path for this SP= I > controller, status=3D%r \n", Status)); > + continue; // Continue searching > + } > + > + // Parse through SpiConfiguration's SpiBuses, find matching devicepa= th for > SpiHc > + for (BusIndex =3D 0; BusIndex < SpiConfiguration->BusCount; BusIndex= ++) { > + Bus =3D (EFI_SPI_BUS *)SpiConfiguration->Buslist[BusIndex]; > + if (!DevicePathsAreEqual (SpiHcDevicePath, Bus->ControllerPath)) { > + DEBUG ((DEBUG_VERBOSE, "SpiHc and SpiConfig device paths dont > match, continue parsing\n")); > + continue; > + } > + > + DEBUG (( > + DEBUG_VERBOSE, > + "%a: Found matching device paths, Enumerating SPI BUS: %s with > DevicePath: %s\n", > + __func__, > + Bus->FriendlyName, > + ConvertDevicePathToText (SpiHcDevicePath, FALSE, FALSE) > + )); > + > + // Get SpiHc from the SpiHcHandles > + Status =3D gBS->HandleProtocol ( > + SpiHcHandles[HcIndex], > + &gEfiDevicePathProtocolGuid, > + (VOID **)&SpiHc > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "%a - Error getting SpiHc from Handle\n", > __func__)); > + goto Exit; > + } > + > + SpiPeripheral =3D (EFI_SPI_PERIPHERAL *)Bus->Peripherallist; > + if (SpiPeripheral !=3D NULL) { > + do { > + DEBUG (( > + DEBUG_VERBOSE, > + "%a: Installing SPI IO protocol for %s, by %s, PN=3D%s\n", > + __func__, > + SpiPeripheral->FriendlyName, > + SpiPeripheral->SpiPart->Vendor, > + SpiPeripheral->SpiPart->PartNumber > + )); > + // Allocate the SPI IO Device > + SpiChip =3D AllocateZeroPool (sizeof (SPI_IO_CHIP)); > + ASSERT (SpiChip !=3D NULL); > + if (SpiChip !=3D NULL) { > + // Fill in the SpiChip > + SpiChip->Signature =3D SPI_IO_SIGNATURE= ; > + SpiChip->SpiConfig =3D SpiConfiguration= ; > + SpiChip->SpiHc =3D SpiHc; > + SpiChip->SpiBus =3D Bus; > + SpiChip->Protocol.SpiPeripheral =3D SpiPeripheral; > + SpiChip->Protocol.OriginalSpiPeripheral =3D SpiPeripheral; > + SpiChip->Protocol.FrameSizeSupportMask =3D SpiHc- > >FrameSizeSupportMask; > + SpiChip->Protocol.MaximumTransferBytes =3D SpiHc- > >MaximumTransferBytes; > + if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_ADDRESS) = !=3D > 0) { > + SpiChip->Protocol.Attributes |=3D > SPI_IO_TRANSFER_SIZE_INCLUDES_ADDRESS; > + } > + > + if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_OPCODE) != =3D 0) > { > + SpiChip->Protocol.Attributes |=3D > SPI_IO_TRANSFER_SIZE_INCLUDES_OPCODE; > + } > + > + if ((SpiHc->Attributes & HC_SUPPORTS_8_BIT_DATA_BUS_WIDTH) != =3D > 0) { > + SpiChip->Protocol.Attributes |=3D > SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH; > + } > + > + if ((SpiHc->Attributes & HC_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != =3D > 0) { > + SpiChip->Protocol.Attributes |=3D > SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH; > + } > + > + if ((SpiHc->Attributes & HC_SUPPORTS_2_BIT_DATA_BUS_WIDTH) != =3D > 0) { > + SpiChip->Protocol.Attributes |=3D > SPI_IO_SUPPORTS_2_BIT_DATA_BUS_WIDTH; > + } > + > + SpiChip->Protocol.Transaction =3D Transaction; > + SpiChip->Protocol.UpdateSpiPeripheral =3D UpdateSpiPeriphera= l; > + // Install the SPI IO Protocol > + Status =3D gBS->InstallProtocolInterface ( > + &SpiChip->Handle, > + (GUID *)SpiPeripheral->SpiPeripheralDriverGu= id, > + EFI_NATIVE_INTERFACE, > + &SpiChip->Protocol > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "%a - Error installing SpiIoProtoco= l\n", > __func__)); > + continue; > + } > + } else { > + Status =3D EFI_OUT_OF_RESOURCES; > + DEBUG (( > + DEBUG_ERROR, > + "%a: Out of Memory resources\n", > + __func__ > + )); > + break; > + } > + > + SpiPeripheral =3D (EFI_SPI_PERIPHERAL *)SpiPeripheral- > >NextSpiPeripheral; > + } while (SpiPeripheral !=3D NULL); > + } else { > + Status =3D EFI_DEVICE_ERROR; > + } > + } > + } > + > +Exit: > + DEBUG ((DEBUG_VERBOSE, "%a - EXIT (Status =3D %r)\n", __func__, Status= )); > + return Status; > +} > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c > new file mode 100644 > index 000000000000..d9189b984835 > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c > @@ -0,0 +1,162 @@ > +/** @file > + > + SPI bus SMM driver > + > + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "SpiBus.h" > + > +/** > + Entry point of the Spi Bus layer > + > + @param[in] ImageHandle Image handle of this driver. > + @param[in] SystemTable Pointer to standard EFI system table. > + > + @retval EFI_SUCCESS Succeed. > + @retval EFI_DEVICE_ERROR Fail to install EFI_SPI_HC_PROTOCOL protocol= . > + @retval EFI_NOT_FOUND fail to locate SpiHcProtocol or > SpiIoConfigurationProtocol > + @retval EFI_OUT_OF_RESOURCES Failed to allocate SpiIoChip > +**/ > +EFI_STATUS > +EFIAPI > +SpiBusEntry ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + SPI_IO_CHIP *SpiChip; > + EFI_SPI_HC_PROTOCOL *SpiHc; > + EFI_SPI_CONFIGURATION_PROTOCOL *SpiConfiguration; > + EFI_SPI_PERIPHERAL *SpiPeripheral; > + EFI_SPI_BUS *Bus; > + > + DEBUG ((DEBUG_VERBOSE, "%a - ENTRY\n", __func__)); > + > + // Only a single Spi HC protocol in SMM > + Status =3D gMmst->MmLocateProtocol ( > + &gEfiSpiSmmHcProtocolGuid, > + NULL, > + (VOID **)&SpiHc > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "No SpiHcProtocol is found\n")); > + Status =3D EFI_NOT_FOUND; > + goto Exit; > + } > + > + // Locate the SPI Configuration Protocol > + Status =3D gMmst->MmLocateProtocol ( > + &gEfiSpiSmmConfigurationProtocolGuid, > + NULL, > + (VOID **)&SpiConfiguration > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "No SpiConfigurationProtocol is found\n")); > + Status =3D EFI_NOT_FOUND; > + goto Exit; > + } > + > + // Only one SpiBus supported in SMM > + if (SpiConfiguration->BusCount !=3D 1) { > + DEBUG ((DEBUG_VERBOSE, "Only one SPI Bus supported in SMM\n")); > + Status =3D EFI_UNSUPPORTED; > + goto Exit; > + } > + > + Bus =3D (EFI_SPI_BUS *)SpiConfiguration->Buslist[0]; > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "%a - Error getting SpiHc from Handle\n", > __func__)); > + goto Exit; > + } > + > + SpiPeripheral =3D (EFI_SPI_PERIPHERAL *)Bus->Peripherallist; > + if (SpiPeripheral !=3D NULL) { > + do { > + DEBUG (( > + DEBUG_VERBOSE, > + "%a: Installing SPI IO protocol for %s, by %s, PN=3D%s\n", > + __func__, > + SpiPeripheral->FriendlyName, > + SpiPeripheral->SpiPart->Vendor, > + SpiPeripheral->SpiPart->PartNumber > + )); > + // Allocate the SPI IO Device > + SpiChip =3D AllocateZeroPool (sizeof (SPI_IO_CHIP)); > + ASSERT (SpiChip !=3D NULL); > + if (SpiChip !=3D NULL) { > + // Fill in the SpiChip > + SpiChip->Signature =3D SPI_IO_SIGNATURE; > + SpiChip->SpiConfig =3D SpiConfiguration; > + SpiChip->SpiHc =3D SpiHc; > + SpiChip->SpiBus =3D Bus; > + SpiChip->Protocol.SpiPeripheral =3D SpiPeripheral; > + SpiChip->Protocol.OriginalSpiPeripheral =3D SpiPeripheral; > + SpiChip->Protocol.FrameSizeSupportMask =3D SpiHc- > >FrameSizeSupportMask; > + SpiChip->Protocol.MaximumTransferBytes =3D SpiHc- > >MaximumTransferBytes; > + if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_ADDRESS) !=3D= 0) { > + SpiChip->Protocol.Attributes |=3D > SPI_IO_TRANSFER_SIZE_INCLUDES_ADDRESS; > + } > + > + if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_OPCODE) !=3D = 0) { > + SpiChip->Protocol.Attributes |=3D > SPI_IO_TRANSFER_SIZE_INCLUDES_OPCODE; > + } > + > + if ((SpiHc->Attributes & HC_SUPPORTS_8_BIT_DATA_BUS_WIDTH) !=3D = 0) { > + SpiChip->Protocol.Attributes |=3D > SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH; > + } > + > + if ((SpiHc->Attributes & HC_SUPPORTS_4_BIT_DATA_BUS_WIDTH) !=3D = 0) { > + SpiChip->Protocol.Attributes |=3D > SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH; > + } > + > + if ((SpiHc->Attributes & HC_SUPPORTS_2_BIT_DATA_BUS_WIDTH) !=3D = 0) { > + SpiChip->Protocol.Attributes |=3D > SPI_IO_SUPPORTS_2_BIT_DATA_BUS_WIDTH; > + } > + > + SpiChip->Protocol.Transaction =3D Transaction; > + SpiChip->Protocol.UpdateSpiPeripheral =3D UpdateSpiPeripheral; > + // Install the SPI IO Protocol > + Status =3D gMmst->MmInstallProtocolInterface ( > + &SpiChip->Handle, > + (GUID *)SpiPeripheral->SpiPeripheralDriverGuid= , > + EFI_NATIVE_INTERFACE, > + &SpiChip->Protocol > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "%a - Error installing SpiIoProtocol\n"= , > __func__)); > + continue; > + } > + } else { > + Status =3D EFI_OUT_OF_RESOURCES; > + DEBUG (( > + DEBUG_ERROR, > + "%a: Out of Memory resources\n", > + __func__ > + )); > + break; > + } > + > + SpiPeripheral =3D (EFI_SPI_PERIPHERAL *)SpiPeripheral->NextSpiPeri= pheral; > + } while (SpiPeripheral !=3D NULL); > + } else { > + Status =3D EFI_DEVICE_ERROR; > + } > + > +Exit: > + DEBUG ((DEBUG_VERBOSE, "%a - EXIT (Status =3D %r)\n", __func__, Status= )); > + return Status; > +} > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni > new file mode 100644 > index 000000000000..0d913bdbae39 > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni > @@ -0,0 +1,10 @@ > +// /** @file > +// > +// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<= BR> > +// > +// SPDX-License-Identifier: BSD-2-Clause-Patent > +// > +// **/ > + > +#string STR_PROPERTIES_MODULE_NAME > +#language en-US "SPI Bus driver" > -- > 2.42.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#118493): https://edk2.groups.io/g/devel/message/118493 Mute This Topic: https://groups.io/mt/105849135/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-