From 94a242cf05a383fda710c0c9ab5fd9aa9f74f23b Mon Sep 17 00:00:00 2001 From: Doug Cook <45909143+idigdoug@users.noreply.github.com> Date: Tue, 26 Mar 2024 14:50:10 -0700 Subject: [PATCH] New platform: AIO-3588q (#130) --- .github/workflows/build.yml | 1 + README.md | 4 + configs/aio-3588q.conf | 3 + .../Platform/Rockchip/DeviceTree/README.md | 4 +- .../DeviceTree/rk3588-firefly-aio-3588q.dtb | Bin 0 -> 182117 bytes .../AIO-3588Q/AIO-3588Q.Modules.fdf.inc | 18 + .../Platform/Firefly/AIO-3588Q/AIO-3588Q.dsc | 31 ++ .../Firefly/AIO-3588Q/AIO-3588Q.dsc.inc | 134 +++++ .../AIO-3588Q/AcpiTables/AcpiTables.inf | 55 +++ .../Firefly/AIO-3588Q/AcpiTables/Dsdt.asl | 53 ++ .../RockchipPlatformLib/RockchipPlatformLib.c | 460 ++++++++++++++++++ .../RockchipPlatformLib.inf | 38 ++ .../RockchipPlatformLibPcaDepex.inf | 42 ++ 13 files changed, 842 insertions(+), 1 deletion(-) create mode 100644 configs/aio-3588q.conf create mode 100644 edk2-rockchip-non-osi/Platform/Rockchip/DeviceTree/rk3588-firefly-aio-3588q.dtb create mode 100644 edk2-rockchip/Platform/Firefly/AIO-3588Q/AIO-3588Q.Modules.fdf.inc create mode 100644 edk2-rockchip/Platform/Firefly/AIO-3588Q/AIO-3588Q.dsc create mode 100644 edk2-rockchip/Platform/Firefly/AIO-3588Q/AIO-3588Q.dsc.inc create mode 100644 edk2-rockchip/Platform/Firefly/AIO-3588Q/AcpiTables/AcpiTables.inf create mode 100644 edk2-rockchip/Platform/Firefly/AIO-3588Q/AcpiTables/Dsdt.asl create mode 100644 edk2-rockchip/Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLib.c create mode 100644 edk2-rockchip/Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLib.inf create mode 100644 edk2-rockchip/Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLibPcaDepex.inf diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 43f6c29c6..b456b6ba7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,6 +30,7 @@ jobs: - indiedroid-nova - roc-rk3588s-pc - itx-3588j + - aio-3588q - station-m3 - r58x - r58-mini diff --git a/README.md b/README.md index 0a1955a05..d18707b83 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ This repository contains an UEFI firmware implementation based on EDK2 for vario - [Orange Pi 5](http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-5.html) - [Orange Pi 5 Plus](http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-5-plus.html) - [ameriDroid Indiedroid Nova](https://indiedroid.us) +- [Firefly AIO-3588Q](https://en.t-firefly.com/product/industry/aio3588q) +- [Firefly ITX-3588J](https://en.t-firefly.com/product/industry/itx3588j) - [Firefly ROC-RK3588S-PC](https://en.t-firefly.com/product/industry/rocrk3588spc) - [StationPC Station M3](https://www.stationpc.com/product/stationm3) - [Mekotronics R58X](https://www.mekotronics.com/h-pd-75.html) @@ -141,6 +143,8 @@ The paths above are relative to the root of the file system. That is, the `dtb` | Name | Platform | | --------------------------------------- | ----------------------------- | | `rk3588s-9tripod-linux` | Indiedroid Nova | +| `aio-3588q` | Firefly AIO-3588Q | +| `itx-3588j` | Firefly ITX-3588J | | `roc-rk3588s-pc` | ROC-RK3588S-PC / Station M3 | | `rk3588-nanopc-t6` | NanoPC T6 | | `rk3588s-nanopi-r6c` | NanoPi R6C | diff --git a/configs/aio-3588q.conf b/configs/aio-3588q.conf new file mode 100644 index 000000000..f394772ae --- /dev/null +++ b/configs/aio-3588q.conf @@ -0,0 +1,3 @@ +DSC_FILE=edk2-rockchip/Platform/Firefly/AIO-3588Q/AIO-3588Q.dsc +PLATFORM_NAME=AIO-3588Q +SOC=RK3588 diff --git a/edk2-rockchip-non-osi/Platform/Rockchip/DeviceTree/README.md b/edk2-rockchip-non-osi/Platform/Rockchip/DeviceTree/README.md index 33eb353b9..ceacef3db 100644 --- a/edk2-rockchip-non-osi/Platform/Rockchip/DeviceTree/README.md +++ b/edk2-rockchip-non-osi/Platform/Rockchip/DeviceTree/README.md @@ -7,6 +7,8 @@ * itx-3588j: (note: in the dtb given here, the builtin bootargs in the source above were commented out before building. Not sure if that was a necessary step - SS) - + +* rk3588-firefly-aio-3588q: + ## License SPDX-License-Identifier: GPL-2.0-only diff --git a/edk2-rockchip-non-osi/Platform/Rockchip/DeviceTree/rk3588-firefly-aio-3588q.dtb b/edk2-rockchip-non-osi/Platform/Rockchip/DeviceTree/rk3588-firefly-aio-3588q.dtb new file mode 100644 index 0000000000000000000000000000000000000000..f02d0427cdc0a4bc23b84ec33968335c8db2ace6 GIT binary patch literal 182117 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 literal 0 HcmV?d00001 diff --git a/edk2-rockchip/Platform/Firefly/AIO-3588Q/AIO-3588Q.Modules.fdf.inc b/edk2-rockchip/Platform/Firefly/AIO-3588Q/AIO-3588Q.Modules.fdf.inc new file mode 100644 index 000000000..656ef890f --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/AIO-3588Q/AIO-3588Q.Modules.fdf.inc @@ -0,0 +1,18 @@ +## @file +# +# Copyright (c) 2023, Mario Bălănică +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + + # ACPI Support + INF RuleOverride = ACPITABLE Platform/Firefly/AIO-3588Q/AcpiTables/AcpiTables.inf + + # Device Tree Support + FILE FREEFORM = gDtPlatformDefaultDtbFileGuid { + SECTION RAW = Platform/Rockchip/DeviceTree/rk3588-firefly-aio-3588q.dtb + } + + # Splash screen logo + INF $(VENDOR_DIRECTORY)/Drivers/LogoDxe/LogoDxe.inf diff --git a/edk2-rockchip/Platform/Firefly/AIO-3588Q/AIO-3588Q.dsc b/edk2-rockchip/Platform/Firefly/AIO-3588Q/AIO-3588Q.dsc new file mode 100644 index 000000000..a09f125ff --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/AIO-3588Q/AIO-3588Q.dsc @@ -0,0 +1,31 @@ +## @file +# +# Copyright (c) 2014-2018, Linaro Limited. All rights reserved. +# Copyright (c) 2023, Mario Bălănică +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = AIO-3588Q + PLATFORM_VENDOR = Firefly + PLATFORM_GUID = 400f8259-7664-47df-b375-8ba262e4867e + PLATFORM_VERSION = 0.2 + DSC_SPECIFICATION = 0x00010019 + OUTPUT_DIRECTORY = Build/$(PLATFORM_NAME) + VENDOR_DIRECTORY = Platform/$(PLATFORM_VENDOR) + PLATFORM_DIRECTORY = $(VENDOR_DIRECTORY)/$(PLATFORM_NAME) + SUPPORTED_ARCHITECTURES = AARCH64 + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + + # + # Platform based on AIO-3588Q board + # +!include Platform/Firefly/AIO-3588Q/AIO-3588Q.dsc.inc diff --git a/edk2-rockchip/Platform/Firefly/AIO-3588Q/AIO-3588Q.dsc.inc b/edk2-rockchip/Platform/Firefly/AIO-3588Q/AIO-3588Q.dsc.inc new file mode 100644 index 000000000..e14a3e862 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/AIO-3588Q/AIO-3588Q.dsc.inc @@ -0,0 +1,134 @@ +## @file +# +# Copyright (c) 2014-2018, Linaro Limited. All rights reserved. +# Copyright (c) 2023, Mario Bălănică +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + FLASH_DEFINITION = Silicon/Rockchip/RK3588/RK3588.fdf + RK_PLATFORM_FVMAIN_MODULES = Platform/Firefly/AIO-3588Q/AIO-3588Q.Modules.fdf.inc + + # + # HYM8563 RTC support + # I2C location configured by PCDs below. + # + DEFINE RK_RTC8563_ENABLE = TRUE + + # + # PCA9555 GPIO extender support + # I2C location configured by PCDs below. + # + DEFINE RK_PCA9555_ENABLE = TRUE + + # + # RK3588-based platform + # +!include Silicon/Rockchip/RK3588/RK3588Platform.dsc.inc + +################################################################################ +# +# Library Class section - list of all Library Classes needed by this Platform. +# +################################################################################ + +[LibraryClasses.common] + RockchipPlatformLib|Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLib.inf + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform. +# +################################################################################ + +[PcdsFixedAtBuild.common] + # SMBIOS platform config + gRockchipTokenSpaceGuid.PcdPlatformName|"AIO-3588Q" + gRockchipTokenSpaceGuid.PcdPlatformVendorName|"Firefly" + gRockchipTokenSpaceGuid.PcdFamilyName|"AIO" + gRockchipTokenSpaceGuid.PcdProductUrl|"https://en.t-firefly.com/product/core/icore3588q" + gRockchipTokenSpaceGuid.PcdDeviceTreeName|"aio-3588q" + + # I2C + # i2c0: pc9202@3c, rk8602@42, rk8603@43 + # i2c1: rk8602@42 (npu) + # i2c3: es8388@11, XC7160b@1b, gc2053b@37, gc2093b@7e + # i2c6: pca9555@20, pca9555@21, fusb302@22, hym8563@51 + gRockchipTokenSpaceGuid.PcdI2cSlaveAddresses|{ 0x42, 0x43, 0x42, 0x11, 0x51, 0x20, 0x21, 0x22 } + gRockchipTokenSpaceGuid.PcdI2cSlaveBuses|{ 0x0, 0x0, 0x1, 0x3, 0x6, 0x6, 0x6, 0x6 } + gRockchipTokenSpaceGuid.PcdI2cSlaveBusesRuntimeSupport|{ FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE } + gRockchipTokenSpaceGuid.PcdRk860xRegulatorAddresses|{ 0x42, 0x43 } + gRockchipTokenSpaceGuid.PcdRk860xRegulatorBuses|{ 0x0, 0x0 } + gRockchipTokenSpaceGuid.PcdRk860xRegulatorTags|{ $(SCMI_CLK_CPUB01), $(SCMI_CLK_CPUB23) } + gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress|0x51 + gRockchipTokenSpaceGuid.PcdRtc8563Bus|0x6 + gRockchipTokenSpaceGuid.PcdPca9555Address|0x21 + gRockchipTokenSpaceGuid.PcdPca9555Bus|0x6 + + # + # CPU Performance default values + # + gRK3588TokenSpaceGuid.PcdCPULClusterClockPresetDefault|$(CPU_PERF_CLUSTER_CLOCK_PRESET_BOOTDEFAULT) + gRK3588TokenSpaceGuid.PcdCPUB01ClusterClockPresetDefault|$(CPU_PERF_CLUSTER_CLOCK_PRESET_BOOTDEFAULT) + gRK3588TokenSpaceGuid.PcdCPUB23ClusterClockPresetDefault|$(CPU_PERF_CLUSTER_CLOCK_PRESET_BOOTDEFAULT) + + # + # PCIe/SATA/USB Combo PIPE PHY support flags and default values + # + gRK3588TokenSpaceGuid.PcdComboPhy0Switchable|TRUE + gRK3588TokenSpaceGuid.PcdComboPhy1Switchable|TRUE + gRK3588TokenSpaceGuid.PcdComboPhy2Switchable|TRUE + gRK3588TokenSpaceGuid.PcdComboPhy0ModeDefault|$(COMBO_PHY_MODE_PCIE) + gRK3588TokenSpaceGuid.PcdComboPhy1ModeDefault|$(COMBO_PHY_MODE_PCIE) + gRK3588TokenSpaceGuid.PcdComboPhy2ModeDefault|$(COMBO_PHY_MODE_USB3) + + # + # USB/DP Combo PHY support flags and default values + # + gRK3588TokenSpaceGuid.PcdUsbDpPhy0Supported|TRUE + gRK3588TokenSpaceGuid.PcdDp0LaneMux|{ 0x2, 0x3 } + gRK3588TokenSpaceGuid.PcdUsbDpPhy1Supported|TRUE + gRK3588TokenSpaceGuid.PcdDp1LaneMux|{ 0x2, 0x3 } + + # + # GMAC + # + gRK3588TokenSpaceGuid.PcdGmac0Supported|TRUE + gRK3588TokenSpaceGuid.PcdGmac0TxDelay|0x47 + gRK3588TokenSpaceGuid.PcdGmac1Supported|TRUE + gRK3588TokenSpaceGuid.PcdGmac1TxDelay|0x4f + + # + # I2S + # + gRK3588TokenSpaceGuid.PcdI2S0Supported|TRUE + + # + # On-Board fan output + # + gRK3588TokenSpaceGuid.PcdHasOnBoardFanOutput|TRUE + +################################################################################ +# +# Components Section - list of all EDK II Modules needed by this Platform. +# +################################################################################ +[Components.common] + # ACPI Support + Platform/Firefly/AIO-3588Q/AcpiTables/AcpiTables.inf + + # Splash screen logo + $(VENDOR_DIRECTORY)/Drivers/LogoDxe/LogoDxe.inf + + # Hack to enable use of PCA9555 during PCIe initialization. + MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf { + + RockchipPlatformLib|Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLibPcaDepex.inf + } diff --git a/edk2-rockchip/Platform/Firefly/AIO-3588Q/AcpiTables/AcpiTables.inf b/edk2-rockchip/Platform/Firefly/AIO-3588Q/AcpiTables/AcpiTables.inf new file mode 100644 index 000000000..1cfeaf165 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/AIO-3588Q/AcpiTables/AcpiTables.inf @@ -0,0 +1,55 @@ +#/** @file +# +# ACPI table data and ASL sources required to boot the platform. +# +# Copyright (c) 2019-2021, ARM Limited. All rights reserved. +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + INF_VERSION = 0x0001001A + BASE_NAME = AcpiTables + FILE_GUID = 7E374E25-8E01-4FEE-87F2-390C23C606CD + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + RK_COMMON_ACPI_DIR = Silicon/Rockchip/RK3588/AcpiTables + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = AARCH64 +# + +[Sources] + Dsdt.asl + $(RK_COMMON_ACPI_DIR)/Madt.aslc + $(RK_COMMON_ACPI_DIR)/Fadt.aslc + $(RK_COMMON_ACPI_DIR)/Gtdt.aslc + $(RK_COMMON_ACPI_DIR)/Spcr.aslc + $(RK_COMMON_ACPI_DIR)/Mcfg.aslc + $(RK_COMMON_ACPI_DIR)/Dbg2.aslc + $(RK_COMMON_ACPI_DIR)/Pptt.aslc + +[Packages] + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Silicon/Rockchip/RockchipPkg.dec + Silicon/Rockchip/RK3588/RK3588.dec + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmArchTimerIntrNum + gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum + gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum + gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum + gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase + gArmTokenSpaceGuid.PcdGicDistributorBase + gArmTokenSpaceGuid.PcdGicRedistributorsBase + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase + gRK3588TokenSpaceGuid.PcdI2S0Supported + gRK3588TokenSpaceGuid.PcdI2S1Supported diff --git a/edk2-rockchip/Platform/Firefly/AIO-3588Q/AcpiTables/Dsdt.asl b/edk2-rockchip/Platform/Firefly/AIO-3588Q/AcpiTables/Dsdt.asl new file mode 100644 index 000000000..cf2c5d840 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/AIO-3588Q/AcpiTables/Dsdt.asl @@ -0,0 +1,53 @@ +/** @file + * + * Differentiated System Definition Table (DSDT) + * + * Copyright (c) 2020, Pete Batard + * Copyright (c) 2018-2020, Andrey Warkentin + * Copyright (c) Microsoft Corporation. All rights reserved. + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * + **/ + +#include "AcpiTables.h" + +#define BOARD_I2S0_TPLG "i2s-jack" + +#define BOARD_AUDIO_CODEC_HID "ESSX8388" +#define BOARD_CODEC_I2C "\\_SB.I2C3" +#define BOARD_CODEC_I2C_ADDR 0x11 +#define BOARD_CODEC_GPIO "\\_SB.GPI1" +#define BOARD_CODEC_GPIO_PIN GPIO_PIN_PC4 + +DefinitionBlock ("Dsdt.aml", "DSDT", 2, "RKCP ", "RK3588 ", 2) +{ + Scope (\_SB_) + { + include ("Cpu.asl") + + include ("Pcie.asl") + include ("Sata.asl") + include ("Emmc.asl") + include ("Sdhc.asl") + include ("Dma.asl") + include ("Gmac0.asl") + include ("Gmac1.asl") + include ("Gpio.asl") + include ("I2c.asl") + include ("Uart.asl") + // include ("Spi.asl") + + include ("I2s.asl") + + include ("Usb2Host.asl") + include ("Usb3Host0.asl") + include ("Usb3Host1.asl") + include ("Usb3Host2.asl") + + Scope (I2C3) { + include ("Es8388.asl") + } + } +} diff --git a/edk2-rockchip/Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLib.c b/edk2-rockchip/Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLib.c new file mode 100644 index 000000000..8c130adc3 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLib.c @@ -0,0 +1,460 @@ +/** @file +* +* Copyright (c) 2021, Rockchip Limited. All rights reserved. +* +* SPDX-License-Identifier: BSD-2-Clause-Patent +* +**/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static struct regulator_init_data rk806_init_data[] = { + /* Master PMIC */ + RK8XX_VOLTAGE_INIT(MASTER_BUCK1, 750000), + RK8XX_VOLTAGE_INIT(MASTER_BUCK3, 750000), + RK8XX_VOLTAGE_INIT(MASTER_BUCK4, 750000), + RK8XX_VOLTAGE_INIT(MASTER_BUCK5, 850000), + // RK8XX_VOLTAGE_INIT(MASTER_BUCK6, 750000), + RK8XX_VOLTAGE_INIT(MASTER_BUCK7, 2000000), + RK8XX_VOLTAGE_INIT(MASTER_BUCK8, 3300000), + RK8XX_VOLTAGE_INIT(MASTER_BUCK10, 1800000), + + RK8XX_VOLTAGE_INIT(MASTER_NLDO1, 750000), + RK8XX_VOLTAGE_INIT(MASTER_NLDO2, 850000), + RK8XX_VOLTAGE_INIT(MASTER_NLDO3, 750000), + RK8XX_VOLTAGE_INIT(MASTER_NLDO4, 850000), + RK8XX_VOLTAGE_INIT(MASTER_NLDO5, 750000), + + RK8XX_VOLTAGE_INIT(MASTER_PLDO1, 1800000), + RK8XX_VOLTAGE_INIT(MASTER_PLDO2, 1800000), + RK8XX_VOLTAGE_INIT(MASTER_PLDO3, 1200000), + RK8XX_VOLTAGE_INIT(MASTER_PLDO4, 3300000), + RK8XX_VOLTAGE_INIT(MASTER_PLDO5, 3300000), + RK8XX_VOLTAGE_INIT(MASTER_PLDO6, 1800000), + + /* No dual PMICs on this platform */ +}; + +EFI_STATUS +EFIAPI +GetPca9555Protocol ( + IN OUT PCA95XX_PROTOCOL **Pca95xxProtocl + ) +{ + EFI_HANDLE *HandleBuffer; + EFI_STATUS Status; + UINTN HandleCount; + + /* Locate Handles of all PCA95XX_PROTOCOL producers */ + Status = gBS->LocateHandleBuffer (ByProtocol, + &gPca95xxProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Unable to locate handles\n", __FUNCTION__)); + return Status; + } + + DEBUG ((DEBUG_INFO, + "%a: got %d PCA95XX_PROTOCOLs\n", + __FUNCTION__, + HandleCount)); + + /* + * Open Pca95xxProtocl. With EFI_OPEN_PROTOCOL_GET_PROTOCOL attribute + * the consumer is not obliged to call CloseProtocol. + */ + Status = gBS->OpenProtocol (HandleBuffer[0], + &gPca95xxProtocolGuid, + (VOID **)Pca95xxProtocl, + HandleBuffer[0], + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + return Status; +} + +VOID +EFIAPI +SdmmcIoMux ( + VOID + ) +{ + /* sdmmc0 iomux (microSD socket) */ + BUS_IOC->GPIO4D_IOMUX_SEL_L = (0xFFFFUL << 16) | (0x1111); //SDMMC_D0,SDMMC_D1,SDMMC_D2,SDMMC_D3 + BUS_IOC->GPIO4D_IOMUX_SEL_H = (0x00FFUL << 16) | (0x0011); //SDMMC_CLK,SDMMC_CMD + PMU1_IOC->GPIO0A_IOMUX_SEL_H = (0x000FUL << 16) | (0x0001); //SDMMC_DET +} + +VOID +EFIAPI +SdhciEmmcIoMux ( + VOID + ) +{ + /* sdmmc0 iomux */ + /* Do not override, set by earlier boot stages. */ +} + +#define NS_CRU_BASE 0xFD7C0000 +#define CRU_CLKSEL_CON59 0x03EC +#define CRU_CLKSEL_CON78 0x0438 + +VOID +EFIAPI +Rk806SpiIomux ( + VOID + ) +{ + /* io mux */ + //BUS_IOC->GPIO1A_IOMUX_SEL_H = (0xFFFFUL << 16) | 0x8888; + //BUS_IOC->GPIO1B_IOMUX_SEL_L = (0x000FUL << 16) | 0x0008; + PMU1_IOC->GPIO0A_IOMUX_SEL_H = (0x0FF0UL << 16) | 0x0110; + PMU1_IOC->GPIO0B_IOMUX_SEL_L = (0xF0FFUL << 16) | 0x1011; + MmioWrite32(NS_CRU_BASE + CRU_CLKSEL_CON59, (0x00C0UL << 16) | 0x0080); +} + +VOID +EFIAPI +Rk806Configure ( + VOID + ) +{ + UINTN RegCfgIndex; + + RK806Init(); + + for (RegCfgIndex = 0; RegCfgIndex < ARRAY_SIZE(rk806_init_data); RegCfgIndex++) + RK806RegulatorInit(rk806_init_data[RegCfgIndex]); +} + +VOID +EFIAPI +SetCPULittleVoltage ( + IN UINT32 Microvolts + ) +{ + struct regulator_init_data Rk806CpuLittleSupply = + RK8XX_VOLTAGE_INIT(MASTER_BUCK2, Microvolts); + + RK806RegulatorInit(Rk806CpuLittleSupply); +} + +VOID +EFIAPI +NorFspiIomux ( + VOID + ) +{ + /* io mux */ + /* Do not override, set by earlier boot stages. */ +} + +VOID +EFIAPI +GmacIomux ( + IN UINT32 Id + ) +{ + switch (Id) { + case 0: + /* gmac0 iomux */ + BUS_IOC->GPIO2A_IOMUX_SEL_H = (0xFF00UL << 16) | 0x1100; // GMAC0_RXD2, GMAC0_RXD3 + BUS_IOC->GPIO2B_IOMUX_SEL_L = (0xFFFFUL << 16) | 0x1111; // GMAC0_RXCLK, GMAC0_TXD2, GMAC0_TXD3, GMAC0_TXCLK + BUS_IOC->GPIO2B_IOMUX_SEL_H = (0xFF00UL << 16) | 0x1100; // GMAC0_TXD0, GMAC0_TXD1 + BUS_IOC->GPIO2C_IOMUX_SEL_L = (0x0FFFUL << 16) | 0x0111; // GMAC0_TXEN, GMAC0_RXD0, GMAC0_RXD1 + BUS_IOC->GPIO4C_IOMUX_SEL_L = (0xFF00UL << 16) | 0x1100; // GMAC0_RXDV_CRS, GMAC0_MCLKINOUT + BUS_IOC->GPIO4C_IOMUX_SEL_H = (0x00FFUL << 16) | 0x0011; // GMAC0_MDC, GMAC0_MDIO + + /* phy0 reset */ + GpioPinSetDirection (3, GPIO_PIN_PC7, GPIO_PIN_OUTPUT); + break; + case 1: + /* gmac1 iomux */ + BUS_IOC->GPIO3B_IOMUX_SEL_H = (0x0FFFUL << 16) | 0x0111; /* GMAC1_MCLKINOUT, GMAC1_TXEN, GMAC1_TXD1 */ + BUS_IOC->GPIO3A_IOMUX_SEL_L = (0xFFFFUL << 16) | 0x1111; /* GMAC1_RXD3, GMAC1_RXD2, GMAC1_TXD3, GMAC1_TXD2 */ + BUS_IOC->GPIO3B_IOMUX_SEL_L = (0xF0FFUL << 16) | 0x1011; /* GMAC1_TXD0, GMAC1_RXDV_CRS, GMAC1_RXD1 */ + BUS_IOC->GPIO3A_IOMUX_SEL_H = (0xF0FFUL << 16) | 0x1011; /* GMAC1_RXD0, GMAC1_RXCLK, GMAC1_TXCLK */ + BUS_IOC->GPIO3C_IOMUX_SEL_L = (0xFF00UL << 16) | 0x1100; /* GMAC1_MDIO, GMAC1_MDC */ + + /* phy1 reset */ + GpioPinSetDirection (3, GPIO_PIN_PB7, GPIO_PIN_OUTPUT); + break; + default: + break; + } +} + +VOID +EFIAPI +GmacIoPhyReset ( + UINT32 Id, + BOOLEAN Enable + ) +{ + switch (Id) { + case 0: + /* phy0 reset */ + GpioPinWrite (3, GPIO_PIN_PC7, !Enable); + break; + case 1: + /* phy1 reset */ + GpioPinWrite (3, GPIO_PIN_PB7, !Enable); + break; + default: + break; + } +} + +VOID +EFIAPI +NorFspiEnableClock ( + UINT32 *CruBase + ) +{ + UINTN BaseAddr = (UINTN) CruBase; + + MmioWrite32(BaseAddr + 0x087C, 0x0E000000); +} + +VOID +EFIAPI +I2cIomux ( + UINT32 id + ) +{ + switch (id) { + case 0: + GpioPinSetFunction(0, GPIO_PIN_PD1, 3); // I2C0_SCL_M2 + GpioPinSetFunction(0, GPIO_PIN_PD2, 3); // I2C0_SDA_M2 + break; + case 1: + GpioPinSetFunction(0, GPIO_PIN_PD4, 9); // I2C1_SCL_M2 + GpioPinSetFunction(0, GPIO_PIN_PD5, 9); // I2C1_SDA_M2 + break; + case 3: + GpioPinSetFunction(1, GPIO_PIN_PC1, 9); // I2C3_SCL_M0 + GpioPinSetFunction(1, GPIO_PIN_PC0, 9); // I2C3_SDA_M0 + break; + case 6: + GpioPinSetFunction(0, GPIO_PIN_PD0, 9); // I2C6_SCL_M0 + GpioPinSetFunction(0, GPIO_PIN_PC7, 9); // I2C6_SDA_M0 + break; + default: + break; + } +} + +VOID +EFIAPI +UsbPortPowerEnable ( + VOID + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + PCA95XX_PROTOCOL *Pca95xxProtocol; + + /* On Firefly AIO-3588Q this is controlled via the PCA9555. */ + Status = GetPca9555Protocol(&Pca95xxProtocol); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "UsbPortPowerEnable failed to get PCA9555! (%d)\n", Status)); + } else { + /* USB-C */ + Pca95xxProtocol->GpioProtocol.Set( + &Pca95xxProtocol->GpioProtocol, + 12, /* vbus5v0_typec_pwr_en */ + GPIO_MODE_OUTPUT_0 + ); + + gBS->Stall(1200000); + + Pca95xxProtocol->GpioProtocol.Set( + &Pca95xxProtocol->GpioProtocol, + 12, /* vbus5v0_typec_pwr_en */ + GPIO_MODE_OUTPUT_1 + ); + + /* other USB stuff */ + Pca95xxProtocol->GpioProtocol.Set( + &Pca95xxProtocol->GpioProtocol, + 5, /* vcc5v0_host */ + GPIO_MODE_OUTPUT_1 + ); + + Pca95xxProtocol->GpioProtocol.Set( + &Pca95xxProtocol->GpioProtocol, + 4, /* vcc_hub_reset */ + GPIO_MODE_OUTPUT_1 + ); + + Pca95xxProtocol->GpioProtocol.Set( + &Pca95xxProtocol->GpioProtocol, + 6, /* vcc_hub3_reset */ + GPIO_MODE_OUTPUT_1 + ); + + Pca95xxProtocol->GpioProtocol.Set( + &Pca95xxProtocol->GpioProtocol, + 7, /* vcc5v0_host3 */ + GPIO_MODE_OUTPUT_1 + ); + } +} + +VOID +EFIAPI +Usb2PhyResume ( + VOID + ) +{ + MmioWrite32(0xfd5d0008, 0x20000000); + MmioWrite32(0xfd5d4008, 0x20000000); + MmioWrite32(0xfd5d8008, 0x20000000); + MmioWrite32(0xfd5dc008, 0x20000000); + MmioWrite32(0xfd7f0a10, 0x07000700); + MmioWrite32(0xfd7f0a10, 0x07000000); +} + +VOID +EFIAPI +PcieIoInit ( + UINT32 Segment + ) +{ + switch (Segment) { + case PCIE_SEGMENT_PCIE30X4: + GpioPinSetDirection (4, GPIO_PIN_PB6, GPIO_PIN_OUTPUT); // PCIE30X4_PERSTN_M1 + GpioPinSetDirection (4, GPIO_PIN_PC6, GPIO_PIN_OUTPUT); // vcc3v3_pcie30 + break; + case PCIE_SEGMENT_PCIE20L0: + GpioPinSetDirection (1, GPIO_PIN_PB4, GPIO_PIN_OUTPUT); + break; + case PCIE_SEGMENT_PCIE20L1: + break; + case PCIE_SEGMENT_PCIE20L2: + break; + } +} + +VOID +EFIAPI +PciePowerEn ( + UINT32 Segment, + BOOLEAN Enable + ) +{ + switch (Segment) { + case PCIE_SEGMENT_PCIE30X4: + GpioPinWrite (4, GPIO_PIN_PC6, Enable); // vcc3v3_pcie30 + break; + case PCIE_SEGMENT_PCIE20L0: + break; + case PCIE_SEGMENT_PCIE20L1: + break; + case PCIE_SEGMENT_PCIE20L2: + break; + } +} + +VOID +EFIAPI +PciePeReset ( + UINT32 Segment, + BOOLEAN Enable + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + PCA95XX_PROTOCOL *Pca95xxProtocol; + + switch (Segment) { + case PCIE_SEGMENT_PCIE30X4: + GpioPinWrite (4, GPIO_PIN_PB6, !Enable); // PCIE30X4_PERSTN_M1 + break; + case PCIE_SEGMENT_PCIE20L0: + GpioPinWrite (1, GPIO_PIN_PB4, !Enable); + break; + case PCIE_SEGMENT_PCIE20L1: + break; + case PCIE_SEGMENT_PCIE20L2: + Status = GetPca9555Protocol(&Pca95xxProtocol); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "PciePeReset(L2) failed to get PCA9555! (%d)\n", Status)); + } else { + Pca95xxProtocol->GpioProtocol.Set( + &Pca95xxProtocol->GpioProtocol, + 14, /* PCA_IO1_6 */ + Enable ? GPIO_MODE_OUTPUT_0 : GPIO_MODE_OUTPUT_1 + ); + } + break; + } +} + +PWM_DATA pwm_data = { + .ControllerID = PWM_CONTROLLER3, + .ChannelID = PWM_CHANNEL3, + .PeriodNs = 50000, + .DutyNs = 50000, + .Polarity = FALSE, +}; // PWM15 + +VOID +EFIAPI +PwmFanIoSetup ( + VOID + ) +{ + GpioPinSetFunction (1, GPIO_PIN_PC6, 0xB); // PWM15_IR_M2 + RkPwmSetConfig (&pwm_data); + RkPwmEnable (&pwm_data); +} + +VOID +EFIAPI +PwmFanSetSpeed ( + IN UINT32 Percentage + ) +{ + pwm_data.DutyNs = pwm_data.PeriodNs * Percentage / 100; + RkPwmSetConfig (&pwm_data); +} + +VOID +EFIAPI +PlatformInitLeds ( + VOID + ) +{ + GpioPinWrite (3, GPIO_PIN_PB2, FALSE); + GpioPinSetDirection (3, GPIO_PIN_PB2, GPIO_PIN_OUTPUT); +} + +VOID +EFIAPI +PlatformSetStatusLed ( + IN BOOLEAN Enable + ) +{ + GpioPinWrite (3, GPIO_PIN_PB2, Enable); +} + +VOID +EFIAPI +PlatformEarlyInit ( + VOID + ) +{ + GpioPinSetDirection (4, GPIO_PIN_PB0, GPIO_PIN_OUTPUT); // headphone enable + GpioPinWrite (4, GPIO_PIN_PB0, TRUE); + GpioPinSetFunction (1, GPIO_PIN_PC4, 0); // headphone detect +} diff --git a/edk2-rockchip/Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLib.inf b/edk2-rockchip/Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLib.inf new file mode 100644 index 000000000..8becb63ff --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLib.inf @@ -0,0 +1,38 @@ +# +# Copyright (c) 2021, Rockchip Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = RockchipPlatformLib + FILE_GUID = 5178fa86-2fec-11ec-95b4-f42a7dcb925d + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = RockchipPlatformLib + RKPLATLIB_COMMON_DIR = Silicon/Rockchip/RK3588/Library/RockchipPlatformLibCommon + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Silicon/Rockchip/RK3588/RK3588.dec + Silicon/Rockchip/RockchipPkg.dec + +[LibraryClasses] + ArmLib + HobLib + IoLib + MemoryAllocationLib + SerialPortLib + CruLib + GpioLib + PWMLib + +[Protocols] + gPca95xxProtocolGuid + +[Sources.common] + RockchipPlatformLib.c + $(RKPLATLIB_COMMON_DIR)/RK3588CruLib.c diff --git a/edk2-rockchip/Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLibPcaDepex.inf b/edk2-rockchip/Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLibPcaDepex.inf new file mode 100644 index 000000000..6c686c31c --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/AIO-3588Q/Library/RockchipPlatformLib/RockchipPlatformLibPcaDepex.inf @@ -0,0 +1,42 @@ +# +# Copyright (c) 2021, Rockchip Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = RockchipPlatformLib + FILE_GUID = 5178fa86-2fec-11ec-95b4-f42a7dcb925d + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = RockchipPlatformLib + RKPLATLIB_COMMON_DIR = Silicon/Rockchip/RK3588/Library/RockchipPlatformLibCommon + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Silicon/Rockchip/RK3588/RK3588.dec + Silicon/Rockchip/RockchipPkg.dec + +[LibraryClasses] + ArmLib + HobLib + IoLib + MemoryAllocationLib + SerialPortLib + CruLib + GpioLib + PWMLib + +[Protocols] + gPca95xxProtocolGuid + +[Sources.common] + RockchipPlatformLib.c + $(RKPLATLIB_COMMON_DIR)/RK3588CruLib.c + +# Hack to enable use of PCA9555 during PCIe initialization. +[Depex] + gPca95xxProtocolGuid