From nobody Mon Sep 16 19:58:28 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+114600+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1706274797935741.5172795620591; Fri, 26 Jan 2024 05:13:17 -0800 (PST) Return-Path: DKIM-Signature: a=rsa-sha256; bh=B09ATNKc3kWE0grz/yDPrWCaarQCVgLdA0XK/6s/Z1E=; c=relaxed/simple; d=groups.io; h=ARC-Seal:ARC-Message-Signature:ARC-Authentication-Results:Received-SPF:From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding:Content-Type; s=20140610; t=1706274797; v=1; b=J9kyiE8n2d4zWSA4NmOGiw3XQc0JhYnQYwkTz3c4tE3PdfnudJ81eQ84+Lx2kH6oTccrdQf1 DeJU6rqWdaKRsGqYAqyjkR2YyKqMZsqYfBQ98fmoWEH7Bl1c78FKlCiqE5Nn9fw2Xj2koeHAp0n C90iaXrjN+UnCw6ZQXoEpq8U= X-Received: by 127.0.0.2 with SMTP id QZFTYY1788612xmJkOeEzHxI; Fri, 26 Jan 2024 05:13:17 -0800 X-Received: from NAM12-DM6-obe.outbound.protection.outlook.com (NAM12-DM6-obe.outbound.protection.outlook.com [40.107.243.54]) by mx.groups.io with SMTP id smtpd.web10.15502.1706274796918102093 for ; Fri, 26 Jan 2024 05:13:17 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=RI3R74e2PgsWP0vdNnxbBtFkzs5NR9DV+WVPayeF8vLueHYxYhnAljSzqaF54mD96q/bEW9ZmNHVr2JHeeftAERV5uWB4bkQU9s1ZvfSgt59HF0xGxSrnaQv8+5TH+7j/HwZ/6E5sFHbCgwDi0yb727F0ZYhNEnccIsaQ7vaNAVAxN7vylMnpvx/draLQf9Hsj7RmR/ofBp+cO1m1LVBrXYSJw9uPj/GKgbg80a1LzTOcC+haHtnFJIua8+YlXDB4MEzeydAMSpvX3isL9hcFJncDm8RGSwkmQcMQBd0BUFTlXAY63qstA+sEakkLwh6wCM8yHqeFBNcNV/NgAMbvg== 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-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=hHXb8pyp0Pw6JLDAHCMaunNMSoQ81vk3dNwVTUrT/Yc=; b=mMIl5RGtPVRpVTay6KMhgf6y+BzSKjfquMv+qxigJSS8QH2IIwD5ADqqjZKIOPq7Gpf72tSDSjcdJmmAH8okWYYKnaZkFVdWZ4IRKXwQIgESC0yGfOFpO5IiQzabTHNlaX/7WvkMEvSR89I7yn2HYeIcdnXHPUcguiQU0+Eh3MnY/KmXDgffg4AEJg0l7Z5ARv1WmJOD709EoeJ+7sldEj1MLNLk5C/fhvQgU+nWzWA0xzcHba/U2gEJETIIBK0jiXKvlUWLQ5I6wcmLTA2M4m5FqHY5F2ITzFwCY0zqlTSnTa0dSQdmfzm1irxXlsPCQD4erycIsMlJIeOsU+oEPg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) X-Received: from CYZPR05CA0016.namprd05.prod.outlook.com (2603:10b6:930:89::28) by DS0PR12MB7655.namprd12.prod.outlook.com (2603:10b6:8:11e::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7228.27; Fri, 26 Jan 2024 13:13:12 +0000 X-Received: from CY4PEPF0000E9D3.namprd03.prod.outlook.com (2603:10b6:930:89:cafe::f9) by CYZPR05CA0016.outlook.office365.com (2603:10b6:930:89::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7249.15 via Frontend Transport; Fri, 26 Jan 2024 13:13:12 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+114600+1787277+3901457@groups.io; helo=mail02.groups.io; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C X-Received: from SATLEXMB04.amd.com (165.204.84.17) by CY4PEPF0000E9D3.mail.protection.outlook.com (10.167.241.146) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.7228.16 via Frontend Transport; Fri, 26 Jan 2024 13:13:12 +0000 X-Received: from SHA-LX-MINGXZHA.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.34; Fri, 26 Jan 2024 07:13:10 -0600 From: "Zhai, MingXin (Duke) via groups.io" To: CC: Eric Xing , Ken Yao , Igniculus Fu , Abner Chang Subject: [edk2-devel] [PATCH V3 24/32] AMD/VanGoghBoard: Check in FchSpi module Date: Fri, 26 Jan 2024 21:11:17 +0800 Message-ID: <20240126131125.1881-25-duke.zhai@amd.com> In-Reply-To: <20240126131125.1881-1-duke.zhai@amd.com> References: <20240126131125.1881-1-duke.zhai@amd.com> MIME-Version: 1.0 X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CY4PEPF0000E9D3:EE_|DS0PR12MB7655:EE_ X-MS-Office365-Filtering-Correlation-Id: 1756b73e-6754-43fa-ae2e-08dc1e708cd8 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Message-Info: RifkIuhdicf4TcLDkze70ZF7EM8LWdo5ZRePpAl0Vyht9W3DAAf+pZ9L03Csgzh/NT7yFB0JJ7uHbHdkMahm5YdHVJTDpsaofRayWfh3JgSGUphG8eYHUYLMV1oG/+iXNIlN87q2a90MDMtO3pAZBd9Ug97Jr+VZkEnUpXt5jaFekoVe9qIc7tzXUKWsE7hXwyTfIFNnHj8hg1kNi3tQwUlzUuigZrduvUpFvZhBDq7bdQ9YxQPB/RjyFJUw8YBysakvJ9rLXMpsw8XyqsmNQbqFXFcXqbNE7ALhikLFxDTXwN9Ozn3ugsabaBNHNyFWtBMQYSzEtjrNRf6risJKJn9LeOjZpAPF7SchOwQI7SC11CoFyk9bagXZaCt40L0li/DOHn0S0jvaVfHXAy8p9S9UDCE71HhuYnllYdFn0BfDsGBHx0+1Fsu6yOTo9iOLez0dzRIyI+OBNFl1c7NZaofKHs5pkY6WlIa2XqBNJg/2zpUz/xx3NmngizS8fRe/6A38SrlJs1lQRL+7T3Nqf93yz8R+I1kUpL06CCN5X5mk7HNaJlP648oRDUuJzTM87dI9KpLdqPkACdNzYTueiBCV2hn0nA4LYnR2kgUG7CZHu+NAr8V0Q82GWi6CTDS0N9HgF1q+1sywn/fGzuExoaQ+Ty4OUCiI3NZqDd0zJ7ptT3NdhaBjfSWMuGoPKQb8zbHrc5WUlRPulxj6aQ16mC/GzXYkN149/gJjRBEyuSIkSQp2E9+lcWjKhSynvpqAcRULo3/SWAMgY+RhTYRQZdQJWkVC+SFZN2CnffsQVo8= X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Jan 2024 13:13:12.7011 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 1756b73e-6754-43fa-ae2e-08dc1e708cd8 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CY4PEPF0000E9D3.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DS0PR12MB7655 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,duke.zhai@amd.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: C8uMWoczCHrtCS6GQ2gJ2i0ox1787277AA= Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1706274800190100035 Content-Type: text/plain; charset="utf-8" From: Duke Zhai BZ #:4640 In V3: Improve coding style follow edk2 C coding standard. 1.Remove macro definition extra underscores. 2.Putting some AMD copyright in the right place. In V2: Improve coding style. 1.Remove the leading underscore and use double underscore at trailing in = C header files. 2.Remove old tianocore licenses and redundant license description. 3.Improve coding style. For example: remove space between @param. In V1: Initial FchSpi module. FCH SPI Common Driver implements the SPI Host Controller Compatibility Interface. Signed-off-by: Duke Zhai Cc: Eric Xing Cc: Ken Yao Cc: Igniculus Fu Cc: Abner Chang --- .../Universal/FchSpi/FchSpiProtect.c | 67 ++ .../Universal/FchSpi/FchSpiProtect.h | 38 + .../Universal/FchSpi/FchSpiRuntimeDxe.c | 163 ++++ .../Universal/FchSpi/FchSpiRuntimeDxe.h | 49 ++ .../Universal/FchSpi/FchSpiRuntimeDxe.inf | 84 ++ .../VanGoghBoard/Universal/FchSpi/FchSpiSmm.c | 112 +++ .../VanGoghBoard/Universal/FchSpi/FchSpiSmm.h | 32 + .../Universal/FchSpi/FchSpiSmm.inf | 94 +++ .../VanGoghBoard/Universal/FchSpi/SpiCommon.c | 790 ++++++++++++++++++ .../VanGoghBoard/Universal/FchSpi/SpiInfo.h | 24 + 10 files changed, 1453 insertions(+) create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtec= t.c create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtec= t.h create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntim= eDxe.c create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntim= eDxe.h create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntim= eDxe.inf create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.c b/P= latform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.c new file mode 100644 index 0000000000..658d9b063d --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.c @@ -0,0 +1,67 @@ +/** @file + Implements FchSpiProtect.c + + 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 "FchSpiProtect.h" + +/** + + Fch Spi Protect Lock + + @param SpiMmioBase + +**/ +EFI_STATUS +EFIAPI +FchSpiProtect_Lock ( + IN UINTN SpiMmioBase + ) +{ + if (!(MmioRead8 (SpiMmioBase + 2) & 0xC0)) { + // Check BIT7+BIT6 + return EFI_SUCCESS; + } else { + MmioWrite8 (SpiMmioBase + 9, 0x6); // P= refixOpCode WRITE_ENABLE + MmioWrite8 (SpiMmioBase + 2, MmioRead8 (SpiMmioBase + 2) & 0x3F); // C= lear BIT7+BIT6 + if (MmioRead8 (SpiMmioBase + 2) & 0xC0) { + return EFI_DEVICE_ERROR; + } + } + + return EFI_SUCCESS; +} + +/** + + Fch Spi Protect UnLock + + @param SpiMmioBase + +**/ +EFI_STATUS +EFIAPI +FchSpiProtect_UnLock ( + IN UINTN SpiMmioBase + ) +{ + if ((MmioRead8 (SpiMmioBase + 2) & 0xC0) || (6 !=3D MmioRead8 (SpiMmioBa= se + 9))) { + return EFI_SUCCESS; + } else { + MmioWrite8 (SpiMmioBase + 9, 0x0); + MmioWrite8 (SpiMmioBase + 2, MmioRead8 (SpiMmioBase + 2) | 0xC0); // S= et BIT7+BIT6 + } + + return EFI_SUCCESS; +} diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.h b/P= latform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.h new file mode 100644 index 0000000000..e46a1a066a --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.h @@ -0,0 +1,38 @@ +/** @file + Implements FchSpiProtect.h + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef FCH_SPI_PROTECT_H_ +#define FCH_SPI_PROTECT_H_ + +/** + + Fch Spi Protect Lock + + @param UINTN SpiMmioBase + +**/ +EFI_STATUS +EFIAPI +FchSpiProtect_Lock ( + IN UINTN SpiMmioBase + ); + +/** + + Fch Spi Protect UnLock + + @param UINTN SpiMmioBase + +**/ +EFI_STATUS +EFIAPI +FchSpiProtect_UnLock ( + IN UINTN SpiMmioBase + ); + +#endif diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.c = b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.c new file mode 100644 index 0000000000..7bb402402c --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.c @@ -0,0 +1,163 @@ +/** @file +PCH SPI Runtime Driver implements the SPI Host Controller Compatibility In= terface. + +Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+Copyright (c) 2013-2015 Intel Corporation. + +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifdef _MSC_VER + #pragma optimize( "", off ) +#endif + +#ifdef __GNUC__ + #ifndef __clang__ + #pragma GCC push_options + #pragma GCC optimize ("O0") + #else + #pragma clang optimize off + #endif +#endif + +#include "FchSpiRuntimeDxe.h" + +extern EFI_GUID gEfiEventVirtualAddressChangeGuid; +CONST BOOLEAN gInSmm =3D FALSE; + +// +// Global variables +// +SPI_INSTANCE *mSpiInstance; + +/** + + Fixup internal data pointers so that the services can be called in virtu= al mode. + + @param Event The event registered. + @param Context Event context. Not used in this event handler. + + @retval None + +**/ +VOID +EFIAPI +FchSpiVirtualddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance->SpiBa= r)); + gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance->SpiPr= otocol.Init)); + gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance->SpiPr= otocol.Lock)); + gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance->SpiPr= otocol.Execute)); + gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance)); +} + +/** + + Entry point for the SPI host controller driver. + + @param ImageHandle Image handle of this driver. + @param SystemTable Global system service table. + + @retval EFI_SUCCESS Initialization complete. + @retval EFI_UNSUPPORTED The chipset is unsupported by this driver. + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize= the driver. + @retval EFI_DEVICE_ERROR Device error, driver exits abnormally. + +**/ +EFI_STATUS +EFIAPI +InstallFchSpiRuntimeDxe ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT64 BaseAddress; + UINT64 Length; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdMemorySpaceDescriptor; + UINT64 Attributes; + EFI_EVENT Event; + + DEBUG ((DEBUG_INFO, "InstallFchSpiRuntimeDxe() Start\n")); + + // + // Allocate Runtime memory for the SPI protocol instance. + // + mSpiInstance =3D AllocateRuntimeZeroPool (sizeof (SPI_INSTANCE)); + if (mSpiInstance =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Initialize the SPI protocol instance + // + Status =3D SpiProtocolConstructor (mSpiInstance); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Install the EFI_SPI_PROTOCOL interface + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &(mSpiInstance->Handle), + &gEfiSpiProtocolGuid, + &(mSpiInstance->SpiProtocol), + NULL + ); + if (EFI_ERROR (Status)) { + FreePool (mSpiInstance); + return EFI_DEVICE_ERROR; + } + + Status =3D mSpiInstance->SpiProtocol.Init (&(mSpiInstance->SpiProtocol)); + ASSERT_EFI_ERROR (Status); + + // + // Set Spi space in GCD to be RUNTIME so that the range will be supporte= d in + // virtual address mode in EFI aware OS runtime. + // It will assert if Spi Memory Space is not allocated + // The caller is responsible for the existence and allocation of the Spi= Memory Spaces + // + BaseAddress =3D (EFI_PHYSICAL_ADDRESS)(mSpiInstance->SpiBar); + Length =3D 0x1000; + + Status =3D gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdMemorySpaceDe= scriptor); + ASSERT_EFI_ERROR (Status); + + Attributes =3D GcdMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME; + + Status =3D gDS->SetMemorySpaceAttributes ( + BaseAddress, + Length, + Attributes + ); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + FchSpiVirtualddressChangeEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &Event + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "InstallFchSpiRuntimeDxe() End\n")); + + return EFI_SUCCESS; +} + +#ifdef _MSC_VER + #pragma optimize( "", on ) +#endif +#ifdef __GNUC__ + #ifndef __clang__ + #pragma GCC pop_options + #endif +#endif diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.h = b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.h new file mode 100644 index 0000000000..929e821294 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.h @@ -0,0 +1,49 @@ +/** @file +Header file for the PCH SPI Runtime Driver. + +Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+Copyright (c) 2013-2015 Intel Corporation. + +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef FCH_SPI_RUNTIME_DXE_H_ +#define FCH_SPI_RUNTIME_DXE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define EFI_INTERNAL_POINTER 0x00000004 + +/** + + Fixup internal data pointers so that the services can be called in virtu= al mode. + + @param Event The event registered. + @param Context Event context. Not used in this event handler. + + @retval None + +**/ +VOID +EFIAPI +FchSpiVirtualddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +#endif diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.in= f b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.inf new file mode 100644 index 0000000000..c2af195d05 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.inf @@ -0,0 +1,84 @@ +## @file +# Component description file for the SPI Runtime driver. +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+# Copyright (c) 2013-2015 Intel Corporation. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +##########################################################################= ###### +# +# Defines Section - statements that will be processed to create a Makefile. +# +##########################################################################= ###### +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D FchSpiRuntimeDxe + FILE_GUID =3D B9B0740A-B4E9-46FF-AAC7-C632BAC15834 + MODULE_TYPE =3D DXE_RUNTIME_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D InstallFchSpiRuntimeDxe + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 EBC +##########################################################################= ###### +# +# Sources Section - list of files that are required for the build to succe= ed. +# +##########################################################################= ###### +[Sources] + FchSpiRuntimeDxe.c + FchSpiRuntimeDxe.h + FchSpiProtect.c + FchSpiProtect.h + SpiCommon.c + +##########################################################################= ###### +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +##########################################################################= ###### +[Packages] + MdePkg/MdePkg.dec + ChachaniBoardPkg/Project.dec + VanGoghCommonPkg/AmdCommonPkg.dec + +##########################################################################= ###### +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +##########################################################################= ###### +[LibraryClasses] + UefiRuntimeServicesTableLib + UefiRuntimeLib + UefiBootServicesTableLib + UefiDriverEntryPoint + TimerLib + DxeServicesTableLib + UefiLib + DebugLib + MemoryAllocationLib + PciExpressLib + SpiFlashDeviceLib + +##########################################################################= ###### +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +##########################################################################= ###### +[Protocols] + gEfiSpiProtocolGuid + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize + +[Depex] + TRUE diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c b/Platf= orm/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c new file mode 100644 index 0000000000..1f842685a8 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c @@ -0,0 +1,112 @@ +/** @file + +PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interf= ace. + +Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+Copyright (c) 2013-2015 Intel Corporation. + +SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ +#ifdef _MSC_VER + #pragma optimize( "", off ) +#endif + +#ifdef __GNUC__ + #ifndef __clang__ + #pragma GCC push_options + #pragma GCC optimize ("O0") + #else + #pragma clang optimize off + #endif +#endif + +#include "FchSpiSmm.h" + +CONST BOOLEAN gInSmm =3D TRUE; + +// +// Global variables +// +SPI_INSTANCE *mSpiInstance; + +/** + + Entry point for the SPI host controller driver. + + @param ImageHandle Image handle of this driver. + @param SystemTable Global system service table. + + @retval EFI_SUCCESS Initialization complete. + @retval EFI_UNSUPPORTED The chipset is unsupported by this driver. + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize= the driver. + @retval EFI_DEVICE_ERROR Device error, driver exits abnormally. + +**/ +EFI_STATUS +EFIAPI +InstallFchSpiSmm ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // VOID *SmmReadyToBootRegistration; + + DEBUG ((DEBUG_INFO, "InstallFchSpiSmm() Start\n")); + + Status =3D gSmst->SmmAllocatePool ( + EfiRuntimeServicesData, + sizeof (SPI_INSTANCE), + (VOID **)&mSpiInstance + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (mSpiInstance, sizeof (SPI_INSTANCE)); + + if (mSpiInstance =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Initialize the SPI protocol instance + // + Status =3D SpiProtocolConstructor (mSpiInstance); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Install the EFI_SPI_PROTOCOL interface + // + Status =3D gSmst->SmmInstallProtocolInterface ( + &(mSpiInstance->Handle), + &gEfiSmmSpiProtocolGuid, + EFI_NATIVE_INTERFACE, + &(mSpiInstance->SpiProtocol) + ); + if (EFI_ERROR (Status)) { + FreePool (mSpiInstance); + return EFI_DEVICE_ERROR; + } + + Status =3D mSpiInstance->SpiProtocol.Init (&(mSpiInstance->SpiProtocol)); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "InstallFchSpiSmm() End\n")); + + return EFI_SUCCESS; +} + +#ifdef _MSC_VER + #pragma optimize( "", on ) +#endif +#ifdef __GNUC__ + #ifndef __clang__ + #pragma GCC pop_options + #endif +#endif diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h b/Platf= orm/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h new file mode 100644 index 0000000000..e7e9ed6033 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h @@ -0,0 +1,32 @@ +/** @file +Header file for the PCH SPI SMM Driver. + +Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+Copyright (c) 2013-2015 Intel Corporation. + +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef FCH_SPI_SMM_H_ +#define FCH_SPI_SMM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#endif diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf b/Pla= tform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf new file mode 100644 index 0000000000..b30a17119d --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf @@ -0,0 +1,94 @@ +## @file +# Spi smm driver +# +# Component description file for the SPI SMM driver. +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+# Copyright (c) 2013-2015 Intel Corporation. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + + +##########################################################################= ###### +# +# Defines Section - statements that will be processed to create a Makefile. +# +##########################################################################= ###### +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D FchSpiSmm + FILE_GUID =3D 9D63F99F-609D-4EB3-A9D1-5ACE2E25792A + MODULE_TYPE =3D DXE_SMM_DRIVER + VERSION_STRING =3D 1.1 + PI_SPECIFICATION_VERSION =3D 0x0001000A + ENTRY_POINT =3D InstallFchSpiSmm + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 EBC +##########################################################################= ###### +# +# Sources Section - list of files that are required for the build to succe= ed. +# +##########################################################################= ###### +[Sources] + FchSpiSmm.c + FchSpiSmm.h + FchSpiProtect.c + FchSpiProtect.h + SpiCommon.c + +[sources.ia32] + +[sources.x64] +##########################################################################= ###### +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +##########################################################################= ###### +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + VanGoghCommonPkg/AmdCommonPkg.dec + ChachaniBoardPkg/Project.dec + +##########################################################################= ###### +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +##########################################################################= ###### +[LibraryClasses] + BaseLib + UefiBootServicesTableLib + UefiDriverEntryPoint + TimerLib + DxeServicesTableLib + UefiLib + DebugLib + MemoryAllocationLib + PciExpressLib + SmmServicesTableLib + SpiFlashDeviceLib + +##########################################################################= ###### +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +##########################################################################= ###### +[Protocols] + gEfiSmmSpiProtocolGuid + gEfiSmmBase2ProtocolGuid + gEdkiiSmmReadyToBootProtocolGuid + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize + +[Depex] + gEfiSmmBase2ProtocolGuid diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c b/Platf= orm/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c new file mode 100644 index 0000000000..4aab7294cb --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c @@ -0,0 +1,790 @@ +/** @file +PCH SPI Common Driver implements the SPI Host Controller Compatibility Int= erface. + +Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+Copyright (c) 2013-2015 Intel Corporation. + +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifdef _MSC_VER + #pragma optimize( "", off ) +#endif + +#ifdef __GNUC__ + #ifndef __clang__ + #pragma GCC push_options + #pragma GCC optimize ("O0") + #else + #pragma clang optimize off + #endif +#endif + +#include "FchSpiProtect.h" +#include "SpiInfo.h" +#include +#include +#include +#include +#include +#include +#include + +#define SPI_WREN_INDEX 0 // Prefix Opcode 0: SPI_COMM= AND_WRITE_ENABLE +#define SPI_EWSR_INDEX 1 // Prefix Opcode 1: SPI_COMM= AND_WRITE_S_EN + +#define FCH_SPI_MMIO_REG48_TXBYTECOUNT 0x48 +#define FCH_SPI_MMIO_REG4B_RXBYTECOUNT 0x4B +#define FCH_SPI_MMIO_REG80_FIFO 0x80 +#define FCH_SPI_MMIO_REG50_ADDR32CTRL0 0x50 +#define FCH_SPI_MMIO_REG5C_ADDR32CTRL3 0x5C + +volatile UINTN mFchSpiProtect_LOCKED_ReadyToBoot =3D FALSE; +volatile UINTN mSpiMmioBase; +extern CONST BOOLEAN gInSmm; +volatile BOOLEAN mSupport4ByteAddrFlag =3D FALSE; + +STATIC +EFI_STATUS +WaitForSpiDeviceWriteEnabled ( + IN EFI_SPI_PROTOCOL *This + ); + +/** + + Initialize an SPI protocol instance. + The function will assert in debug if FCH SPI has not been initialized + + @param SpiInstance - Pointer to SpiInstance to initialize + + @retval EFI_SUCCESS The protocol instance was properly initialized + @retval EFI_UNSUPPORTED The FCH is not supported by this module + +**/ +EFI_STATUS +SpiProtocolConstructor ( + SPI_INSTANCE *SpiInstance + ) +{ + DEBUG ((DEBUG_INFO, "SpiProtocolConstructor enter!\n")); + + SpiInstance->InitDone =3D FALSE; // Indicate NOT READY. + // + // Initialize the SPI protocol instance + // + SpiInstance->Signature =3D FCH_SPI_PRIVATE_DATA_SIGNATURE; + SpiInstance->Handle =3D NULL; + SpiInstance->SpiProtocol.Init =3D SpiProtocolInit; + SpiInstance->SpiProtocol.Lock =3D SpiProtocolLock; + SpiInstance->SpiProtocol.Execute =3D SpiProtocolExecute; + + // + // Sanity check to ensure FCH SPI initialization has occurred previously. + // + SpiInstance->SpiBar =3D (EFI_PHYSICAL_ADDRESS)PciRead32 ( + PCI_LIB_ADDRESS ( + 0, + 20, + 3, + 0xA0 + ) + )&0x00000000FFFFFFE0; + ASSERT (SpiInstance->SpiBar !=3D 0); + mSpiMmioBase =3D SpiInstance->SpiBar; + + DEBUG ((DEBUG_VERBOSE, "SpiInstance->SpiBar =3D 0x%x\n", SpiInstance->Sp= iBar)); + return EFI_SUCCESS; +} + +/** + + Initialize the host controller to execute SPI command. + + @param This Pointer to the EFI_SPI_PROTOCOL instance. + + @retval EFI_SUCCESS Initialization completed. + @retval EFI_ACCESS_DENIED The SPI static configuration interface h= as been locked-down. + @retval EFI_INVALID_PARAMETER Bad input parameters. + @retval EFI_UNSUPPORTED Can't get Descriptor mode VSCC values + +**/ +EFI_STATUS +EFIAPI +SpiProtocolInit ( + IN EFI_SPI_PROTOCOL *This + ) +{ + EFI_STATUS Status; + SPI_INSTANCE *SpiInstance; + UINT8 FlashPartId[3]; + UINT8 FlashIndex; + + DEBUG ((DEBUG_INFO, "SpiProtocolInit enter!\n")); + + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This); + CopyMem (&SpiInstance->SpiInitTable, &mSpiInitTable[0], sizeof (SPI_INIT= _TABLE)); + + Status =3D SpiProtocolExecute ( + This, + SPI_OPCODE_JEDEC_ID_INDEX, + 0, + TRUE, + TRUE, + FALSE, + (UINTN)0, + 3, + FlashPartId, + EnumSpiRegionDescriptor + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (FlashIndex =3D 0; FlashIndex < mNumSpiFlashMax; FlashIndex++) { + CopyMem (&SpiInstance->SpiInitTable, &mSpiInitTable[FlashIndex], sizeo= f (SPI_INIT_TABLE)); + + if ((FlashPartId[0] !=3D SpiInstance->SpiInitTable.VendorId) || + (FlashPartId[1] !=3D SpiInstance->SpiInitTable.DeviceId0) || + (FlashPartId[2] !=3D SpiInstance->SpiInitTable.DeviceId1)) + { + DEBUG (( + DEBUG_INFO, + "SpiProtocolInit() Target SPI Flash Device [VendorID 0x%02x, Dev= iceID 0x%02x%02x] ", + FlashPartId[0], + FlashPartId[1], + FlashPartId[2] + )); + DEBUG (( + DEBUG_INFO, + "but Current SPI Flash device [VendorId 0x%02x, DeviceID 0x%02x%02= x]!\n", + SpiInstance->SpiInitTable.VendorId, + SpiInstance->SpiInitTable.DeviceId0, + SpiInstance->SpiInitTable.DeviceId1 + ) + ); + } else { + DEBUG (( + DEBUG_INFO, + "Smm Mode: Supported SPI Flash device found, Vendor Id: 0x%02x, De= vice ID: 0x%02x%02x!\n", + FlashPartId[0], + FlashPartId[1], + FlashPartId[2] + )); + break; + } + } + + if (FlashIndex >=3D mNumSpiFlashMax) { + Status =3D EFI_UNSUPPORTED; + DEBUG (( + DEBUG_ERROR, + "ERROR - Unknown SPI Flash Device, Vendor Id: 0x%02x, Device ID: 0x%= 02x%02x!\n", + FlashPartId[0], + FlashPartId[1], + FlashPartId[2] + )); + ASSERT_EFI_ERROR (Status); + } + + SpiInstance->InitDone =3D TRUE; + + return EFI_SUCCESS; +} + +/** + + Lock the SPI Static Configuration Interface. + Once locked, the interface can not be changed and can only be clear by s= ystem reset. + + @param This Pointer to the EFI_SPI_PROTOCOL instance. + + @retval EFI_SUCCESS Lock operation succeed. + @retval EFI_DEVICE_ERROR Device error, operation failed. + @retval EFI_ACCESS_DENIED The interface has already been locked. + +**/ +EFI_STATUS +EFIAPI +SpiProtocolLock ( + IN EFI_SPI_PROTOCOL *This + ) +{ + if (gInSmm) { + // Trigger FCH SPI Protect/Lock + if (EFI_SUCCESS =3D=3D FchSpiProtect_Lock (mSpiMmioBase)) { + mFchSpiProtect_LOCKED_ReadyToBoot =3D TRUE; + DEBUG ((DEBUG_INFO, "Set FchSpiProtect to LOCK SUCCESS! \n")); + } else { + DEBUG ((DEBUG_INFO, "Set FchSpiProtect to LOCK FAILED!!! \n")); + } + } + + return EFI_SUCCESS; +} + +/** + + Execute SPI commands from the host controller. + This function would be called by runtime driver, please do not use any M= MIO marco here + + @param This Pointer to the EFI_SPI_PROTOCOL instance. + @param OpcodeIndex Index of the command in the OpCode Menu. + @param PrefixOpcodeIndex Index of the first command to run when in an at= omic cycle sequence. + @param DataCycle TRUE if the SPI cycle contains data + @param Atomic TRUE if the SPI cycle is atomic and interleave = cycles are not allowed. + @param ShiftOut If DataByteCount is not zero, TRUE to shift dat= a out and FALSE to shift data in. + @param Address In Descriptor Mode, for Descriptor Region, GbE = Region, ME Region and Platform + Region, this value specifies the offset from the Regio= n Base; for BIOS Region, + this value specifies the offset from the start of the = BIOS Image. In Non + Descriptor Mode, this value specifies the offset from = the start of the BIOS Image. + Please note BIOS Image size may be smaller than BIOS R= egion size (in Descriptor + Mode) or the flash size (in Non Descriptor Mode), and = in this case, BIOS Image is + supposed to be placed at the top end of the BIOS Regio= n (in Descriptor Mode) or + the flash (in Non Descriptor Mode) + @param DataByteCount Number of bytes in the data portion of the SPI = cycle. This function may break the + data transfer into multiple operations. This function = ensures each operation does + not cross 256 byte flash address boundary. + *NOTE: if there is some SPI chip that has a stricter a= ddress boundary requirement + (e.g., its write page size is < 256 byte), then the ca= ller cannot rely on this + function to cut the data transfer at proper address bo= undaries, and it's the + caller's reponsibility to pass in a properly cut DataB= yteCount parameter. + @param Buffer Pointer to caller-allocated buffer containing t= he dada received or sent during the + SPI cycle. + @param SpiRegionType SPI Region type. Values EnumSpiRegionBios, Enum= SpiRegionGbE, EnumSpiRegionMe, + EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData= are only applicable in + Descriptor mode. Value EnumSpiRegionAll is applicable = to both Descriptor Mode + and Non Descriptor Mode, which indicates "SpiRegionOff= set" is actually relative + to base of the 1st flash device (i.e., it is a Flash L= inear Address). + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_UNSUPPORTED Command not supported. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. + +**/ +EFI_STATUS +EFIAPI +SpiProtocolExecute ( + IN EFI_SPI_PROTOCOL *This, + IN UINT8 OpcodeIndex, + IN UINT8 PrefixOpcodeIndex, + IN BOOLEAN DataCycle, + IN BOOLEAN Atomic, + IN BOOLEAN ShiftOut, + IN UINTN Address, + IN UINT32 DataByteCount, + IN OUT UINT8 *Buffer, + IN SPI_REGION_TYPE SpiRegionType + ) +{ + EFI_STATUS Status; + UINT8 SpiStatus; + + // + // Check if the parameters are valid. + // + if ((OpcodeIndex >=3D SPI_NUM_OPCODE) || (PrefixOpcodeIndex >=3D SPI_NUM= _PREFIX_OPCODE)) { + return EFI_INVALID_PARAMETER; + } + + if (gInSmm) { + if (mFchSpiProtect_LOCKED_ReadyToBoot) { + FchSpiProtect_UnLock (mSpiMmioBase); + DEBUG ((DEBUG_INFO, "FchSpiProtect UnLock!\n")); + } + } + + SendSpiCmd ( + This, + SPI_OPCODE_READ_S_INDEX, + 0, + TRUE, + FALSE, + FALSE, + 0, + 1, + &SpiStatus, + EnumSpiRegionAll + ); + if ((SpiStatus & 1) !=3D 0) { + if ((OpcodeIndex =3D=3D SPI_OPCODE_ERASE_INDEX) && (ShiftOut =3D=3D FA= LSE)) { + return EFI_ALREADY_STARTED; + } + + DEBUG ((DEBUG_INFO, "SPI Busy, WaitForSpiCycleComplete\n")); + WaitForSpiCycleComplete (This); + } + + // + // Enter 4 bytes address + // + if (MmioRead8 (mSpiMmioBase+FCH_SPI_MMIO_REG50_ADDR32CTRL0) & BIT0) { + DEBUG ((DEBUG_INFO, "Enter 4-Byte address mode\n")); + mSupport4ByteAddrFlag =3D TRUE; + Status =3D SendSpiCmd ( + This, + SPI_COMMAND_Enter_4Byte_Addr_INDEX, + SPI_WREN_INDEX, + FALSE, + TRUE, + FALSE, + 0, + 0, + NULL, + EnumSpiRegionDescriptor + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Enter 4-Byte address mode fail\n")); + goto Exit; + } + } + + // + // Sends the command to the SPI interface to execute. + // + Status =3D SendSpiCmd ( + This, + OpcodeIndex, + PrefixOpcodeIndex, + DataCycle, + Atomic, + ShiftOut, + Address, + DataByteCount, + Buffer, + SpiRegionType + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Operate SPI Flash fail\n")); + goto Exit; + } + + // + // Exit 32-bit address + // + if (mSupport4ByteAddrFlag) { + mSupport4ByteAddrFlag =3D FALSE; + Status =3D SendSpiCmd ( + This, + SPI_COMMAND_Exit_4Byte_Addr_INDEX, + SPI_WREN_INDEX, + FALSE, + TRUE, + FALSE, + 0, + 0, + NULL, + EnumSpiRegionDescriptor + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Exit 4-Byte address mode fail\n")); + goto Exit; + } + } + +Exit: + if (gInSmm) { + if (mFchSpiProtect_LOCKED_ReadyToBoot) { + FchSpiProtect_Lock (mSpiMmioBase); + DEBUG ((DEBUG_INFO, "FchSpiProtect Lock again!\n")); + } + } + + return Status; +} + +/** + + Waits for SPI device not busy + + @param SpiBar The SPI Bar Address + + @retval EFI_SUCCESS Function successfully returned + @retval EFI_TIMEOUT timeout, SPI device busy more than 6s. + +**/ +EFI_STATUS +FchSpiControllerNotBusy ( + UINTN SpiBar + ) +{ + volatile UINT32 SpiStatus; + UINT64 WaitTicks; + UINT64 WaitCount; + + // + // Convert the wait period allowed into to tick count + // + WaitCount =3D WAIT_TIME / WAIT_PERIOD; + // + // Wait until SPI Conroller Not Busy + // + for (WaitTicks =3D 0; WaitTicks < WaitCount; WaitTicks++) { + SpiStatus =3D MmioRead32 (SpiBar + FCH_SPI_MMIO_REG4C); + if (SpiStatus & FCH_SPI_BUSY) { + MicroSecondDelay (WAIT_PERIOD); + } else { + return EFI_SUCCESS; + } + } + + return EFI_TIMEOUT; +} + +STATIC +EFI_STATUS +ResetFifoIndex ( + SPI_INSTANCE *SpiInstance + ) +{ + return EFI_SUCCESS; +} + +/** + + This function sends the programmed SPI command to the slave device. + + @param OpcodeIndex Index of the command in the OpCode Menu. + @param PrefixOpcodeIndex Index of the first command to run when in an at= omic cycle sequence. + @param DataCycle TRUE if the SPI cycle contains data + @param Atomic TRUE if the SPI cycle is atomic and interleave = cycles are not allowed. + @param ShiftOut If DataByteCount is not zero, TRUE to shift dat= a out and FALSE to shift data in. + @param Address In Descriptor Mode, for Descriptor Region, GbE = Region, ME Region and Platform + Region, this value specifies the offset from th= e Region Base; for BIOS Region, + this value specifies the offset from the start = of the BIOS Image. In Non + Descriptor Mode, this value specifies the offse= t from the start of the BIOS Image. + Please note BIOS Image size may be smaller than= BIOS Region size (in Descriptor + Mode) or the flash size (in Non Descriptor Mode= ), and in this case, BIOS Image is + supposed to be placed at the top end of the BIO= S Region (in Descriptor Mode) or + the flash (in Non Descriptor Mode) + @param DataByteCount Number of bytes in the data portion of the SPI = cycle. This function may break the + data transfer into multiple operations. This fu= nction ensures each operation does + not cross 256 byte flash address boundary. + *NOTE: if there is some SPI chip that has a str= icter address boundary requirement + (e.g., its write page size is < 256 byte), then= the caller cannot rely on this + function to cut the data transfer at proper add= ress boundaries, and it's the + caller's reponsibility to pass in a properly cu= t DataByteCount parameter. + @param Buffer Data received or sent during the SPI cycle. + @param SpiRegionType SPI Region type. Values EnumSpiRegionBios, Enum= SpiRegionGbE, EnumSpiRegionMe, + EnumSpiRegionDescriptor, and EnumSpiRegionPlatf= ormData are only applicable in + Descriptor mode. Value EnumSpiRegionAll is appl= icable to both Descriptor Mode + and Non Descriptor Mode, which indicates "SpiRe= gionOffset" is actually relative + to base of the 1st flash device (i.e., it is a = Flash Linear Address). + + @retval EFI_SUCCESS SPI command completes successfully. + @retval EFI_DEVICE_ERROR Device error, the command aborts abnorma= lly. + @retval EFI_ACCESS_DENIED Some unrecognized command encountered in= hardware sequencing mode + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + +**/ +EFI_STATUS +SendSpiCmd ( + IN EFI_SPI_PROTOCOL *This, + IN UINT8 OpcodeIndex, + IN UINT8 PrefixOpcodeIndex, + IN BOOLEAN DataCycle, + IN BOOLEAN Atomic, + IN BOOLEAN ShiftOut, + IN UINTN Address, + IN UINT32 DataByteCount, + IN OUT UINT8 *Buffer, + IN SPI_REGION_TYPE SpiRegionType + ) +{ + SPI_INSTANCE *SpiInstance; + UINTN SpiBiosSize; + UINT32 SpiDataCount; + UINT32 TxByteCount; + UINT32 RxByteCount; + UINTN Addr, Retry; + INTN Index, CountIndex; + UINTN SpiBar; + BOOLEAN WriteFlag; + BOOLEAN AddressFlag; + UINT8 PrefixOpcode; + SPI_OPCODE_MENU_ENTRY OPCodeMenu; + UINT8 Dummy; + UINT8 AddressByteNum; + + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This); + SpiBiosSize =3D SpiInstance->SpiInitTable.BiosSize; + OPCodeMenu =3D SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex]; + PrefixOpcode =3D SpiInstance->SpiInitTable.PrefixOpcode[PrefixOpcodeIn= dex]; + SpiBar =3D SpiInstance->SpiBar; + Dummy =3D 0; + AddressByteNum =3D 3; + + AddressFlag =3D (OPCodeMenu.Type =3D=3D EnumSpiOpcodeWrite); + WriteFlag =3D AddressFlag; + AddressFlag |=3D (OPCodeMenu.Type =3D=3D EnumSpiOpcodeRead); + WriteFlag |=3D (OPCodeMenu.Type =3D=3D EnumSpiOpcodeWriteNoAddr); + + // + // Check if the value of opcode register is 0 or the BIOS Size of SpiIni= tTable is 0 + // + if (SpiBiosSize =3D=3D 0) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + if ((DataCycle =3D=3D FALSE) && (DataByteCount > 0)) { + DataByteCount =3D 0; + } + + do { + SpiDataCount =3D DataByteCount; + TxByteCount =3D 0; + RxByteCount =3D 0; + + // + // Calculate the number of bytes to shift in/out during the SPI data c= ycle. + // Valid settings for the number of bytes duing each data portion of t= he + // FCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, = 56, 64 + // + if ((Address & 0xFF) =3D=3D 0) { + SpiDataCount =3D (DataByteCount > 0x100) ? 0x100 : DataByteCount; + } else { + SpiDataCount =3D (DataByteCount > ((~Address + 1) & 0xFF)) ? ((~Addr= ess + 1) & 0xFF) : DataByteCount; + } + + SpiDataCount =3D (SpiDataCount > 64) ? 64 : SpiDataCount; + + if (Atomic) { + Retry =3D 0; + do { + MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG45, PrefixOpcode); + MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG48_TXBYTECOUNT, 0); + MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG4B_RXBYTECOUNT, 0); + MmioOr8 (SpiBar + FCH_SPI_MMIO_REG47, FCH_SPI_EXEC_OPCODE); + if (EFI_ERROR (FchSpiControllerNotBusy (SpiBar))) { + return EFI_DEVICE_ERROR; + } + + if (PrefixOpcodeIndex =3D=3D SPI_WREN_INDEX) { + if (WaitForSpiDeviceWriteEnabled (This) =3D=3D EFI_SUCCESS) { + Retry =3D 0; + } else { + Retry++; + if (Retry >=3D 3) { + return EFI_DEVICE_ERROR; + } + } + } + } while (Retry); + } + + Index =3D 0; + // + // Check Address Mode + // + if (AddressFlag) { + ResetFifoIndex (SpiInstance); + Addr =3D (UINTN)Address; + // if not SPI_COMMAND_READ_SFDP and 32bit address + if ((OPCodeMenu.Code !=3D SPI_COMMAND_READ_SFDP) && mSupport4ByteAdd= rFlag) { + AddressByteNum =3D 4; + Addr =3D Addr | (UINT32)((MmioRead8 (SpiBar+FCH_SPI_MMIO= _REG5C_ADDR32CTRL3) & BIT0) << 24); + } + + for (CountIndex =3D 0; CountIndex < AddressByteNum; CountIndex++) { + MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG80_FIFO + Index, (UINT8)((Add= r >> (AddressByteNum - CountIndex - 1) * 8) & 0xff)); + Index++; + } + + TxByteCount +=3D AddressByteNum; + } + + if ((OPCodeMenu.Code =3D=3D SPI_COMMAND_READ_SFDP) || (OPCodeMenu.Code= =3D=3D SPI_COMMAND_RPMC_OP2)) { + MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG80_FIFO + Index, Dummy); + Index++; + TxByteCount +=3D 1; + } + + if (DataCycle) { + // + // Check Read/Write Mode + // + if (WriteFlag) { + TxByteCount +=3D SpiDataCount; + for (CountIndex =3D 0; CountIndex < (INTN)(SpiDataCount); CountInd= ex++) { + MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG80_FIFO + Index, Buffer[Cou= ntIndex]); + Index++; + } + } else { + RxByteCount =3D SpiDataCount; + } + } + + // Set SPI Command + MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG45, OPCodeMenu.Code); + MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG48_TXBYTECOUNT, (UINT8)TxByteCoun= t); + MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG4B_RXBYTECOUNT, (UINT8)RxByteCoun= t); + MmioOr8 (SpiBar + FCH_SPI_MMIO_REG47, FCH_SPI_EXEC_OPCODE); + if (EFI_ERROR (FchSpiControllerNotBusy (SpiBar))) { + return EFI_DEVICE_ERROR; + } + + if (ShiftOut) { + Retry =3D 0; + do { + if (WaitForSpiCycleComplete (This)) { + Retry =3D 0; + } else { + Retry++; + if (Retry >=3D FCH_SPI_RETRY_TIMES) { + return EFI_DEVICE_ERROR; + } + } + } while (Retry); + } + + if (DataCycle && RxByteCount) { + // + // Reset Fifo Ptr + // + ResetFifoIndex (SpiInstance); + + for (CountIndex =3D 0; CountIndex < (INTN)(SpiDataCount); CountIndex= ++) { + Buffer[CountIndex] =3D MmioRead8 (SpiBar + FCH_SPI_MMIO_REG80_FIFO= + Index); + Index++; + } + } + + // + // If shifts data in, get data from the SPI data buffer. + // + Address +=3D SpiDataCount; + Buffer +=3D SpiDataCount; + DataByteCount -=3D SpiDataCount; + } while (DataByteCount > 0); + + return EFI_SUCCESS; +} + +/** + + Wait execution cycle to complete on the SPI interface. Check both Hardwa= re + and Software Sequencing status registers + + @param This The SPI protocol instance + + @retval TRUE SPI cycle completed on the interface. + @retval FALSE Time out while waiting the SPI cycle to complete. + It's not safe to program the next command on the SPI interfac= e. + +**/ +BOOLEAN +WaitForSpiCycleComplete ( + IN EFI_SPI_PROTOCOL *This + ) +{ + UINT8 SpiStatus; + UINT64 WaitTicks; + UINT64 WaitCount; + + // + // Convert the wait period allowed into to tick count + // + WaitCount =3D WAIT_TIME / WAIT_PERIOD; + + // + // Wait for the SPI cycle to complete. + // + for (WaitTicks =3D 0; WaitTicks < WaitCount; WaitTicks++) { + // + // Execute Read Status Command + // + SendSpiCmd ( + This, + SPI_OPCODE_READ_S_INDEX, + 0, + TRUE, + FALSE, + FALSE, + 0, + 1, + &SpiStatus, + EnumSpiRegionAll + ); + + if ((SpiStatus & 1) !=3D 0) { + MicroSecondDelay (WAIT_PERIOD); + } else { + return TRUE; + } + } + + DEBUG ((DEBUG_VERBOSE, "WaitForSpiCycleComplete() Timeout\n")); + return FALSE; +} + +/** + + Wait execution cycle to complete on the SPI interface. Check both Hardwa= re + and Software Sequencing status registers + + @param This The SPI protocol instance + + @retval EFI_SUCCESS SPI cycle completed on the interface. + @retval EFI_TIMEOUT Time out while waiting the SPI cycle to complete. + It's not safe to program the next command on the SPI interfac= e. + +**/ +STATIC +EFI_STATUS +WaitForSpiDeviceWriteEnabled ( + IN EFI_SPI_PROTOCOL *This + ) +{ + UINT8 SpiStatus; + UINT64 WaitTicks; + UINT64 WaitCount; + + DEBUG ((DEBUG_VERBOSE, "WaitForSpiDeviceWriteEnabled() Enter!\n")); + + // + // Convert the wait period allowed into to tick count + // + WaitCount =3D WAIT_TIME / WAIT_PERIOD; + + // + // Wait for the SPI cycle to complete. + // + for (WaitTicks =3D 0; WaitTicks < WaitCount; WaitTicks++) { + // + // Execute Read Status Command + // + SendSpiCmd ( + This, + SPI_OPCODE_READ_S_INDEX, + 0, + TRUE, + FALSE, + FALSE, + 0, + 1, + &SpiStatus, + EnumSpiRegionAll + ); + + if ((SpiStatus & 2) =3D=3D 0) { + MicroSecondDelay (WAIT_PERIOD); + } else { + DEBUG ((DEBUG_VERBOSE, "WaitForSpiCycleComplete() Exit\n")); + return EFI_SUCCESS; + } + } + + DEBUG ((DEBUG_VERBOSE, "WaitForSpiDeviceWriteEnabled() Exit Timeout !\n"= )); + return EFI_TIMEOUT; +} + +#ifdef _MSC_VER + #pragma optimize( "", on ) +#endif +#ifdef __GNUC__ + #ifndef __clang__ + #pragma GCC pop_options + #endif +#endif diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h b/Platfor= m/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h new file mode 100644 index 0000000000..28b67ea991 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h @@ -0,0 +1,24 @@ +/** @file + Implements SpiInfo.h + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SPI_INFO_H_ +#define SPI_INFO_H_ + +#include +#include + +#ifdef FCH_SPI_EXEC_OPCODE + #undef FCH_SPI_EXEC_OPCODE +#define FCH_SPI_EXEC_OPCODE BIT7 +#endif + +#define FCH_SPI_MMIO_REG45 0x45 // OpCode Access +#define FCH_SPI_MMIO_REG47 0x47 // Execute Access +#define FCH_SPI_MMIO_REG4C 0x4C // SPI Status + +#endif --=20 2.31.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 (#114600): https://edk2.groups.io/g/devel/message/114600 Mute This Topic: https://groups.io/mt/103975480/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-