diff --git a/configs/itx-3588j.conf b/configs/itx-3588j.conf new file mode 100644 index 000000000..f7c6aa981 --- /dev/null +++ b/configs/itx-3588j.conf @@ -0,0 +1,3 @@ +DSC_FILE=edk2-rockchip/Platform/Firefly/ITX-3588J/ITX-3588J.dsc +PLATFORM_NAME=ITX-3588J +SOC=RK3588 diff --git a/edk2-rockchip-non-osi/Platform/Rockchip/DeviceTree/itx-3588j.dtb b/edk2-rockchip-non-osi/Platform/Rockchip/DeviceTree/itx-3588j.dtb new file mode 100644 index 000000000..7b2e01690 Binary files /dev/null and b/edk2-rockchip-non-osi/Platform/Rockchip/DeviceTree/itx-3588j.dtb differ diff --git a/edk2-rockchip/Platform/Firefly/Drivers/Pca9555Dxe/Pca9555Dxe.c b/edk2-rockchip/Platform/Firefly/Drivers/Pca9555Dxe/Pca9555Dxe.c new file mode 100644 index 000000000..845aec434 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/Drivers/Pca9555Dxe/Pca9555Dxe.c @@ -0,0 +1,869 @@ +/** @file + * + * PCA9555 GPIO driver for Rockchip platforms. + * + * Contribs: + * + * Copyright (c) 2018, Marvell International Ltd. All rights reserved. + * Copyright (c) 2023, Mario Bălănică + * Copyright (c) 2023, Shimrra Shai + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * + **/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Pca9555Dxe.h" + +STATIC CONST EFI_GUID I2cGuid = I2C_GUID; + +/* Much of the driver below is ripped from the Marvell version, with + * some adaptation. + */ + +/* --- Low-level Methods --- */ + +EFI_STATUS +EFIAPI +Pca95xxI2cTransfer ( + IN EFI_I2C_IO_PROTOCOL *I2cIo, + IN UINT8 Address, + IN UINT8 *Buffer, + IN BOOLEAN Read + ) +{ + EFI_I2C_REQUEST_PACKET *RequestPacket; + UINTN RequestPacketSize; + UINT8 AddressBuffer; + UINT8 WritePacketBuffer[2]; + EFI_STATUS Status; + UINTN NumOps; + + if (Read) { + NumOps = 2; + } else { + NumOps = 1; + } + + RequestPacketSize = sizeof (UINTN) + + sizeof (EFI_I2C_OPERATION) * NumOps; + RequestPacket = AllocateZeroPool (RequestPacketSize); + if (RequestPacket == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + /* Operations contain address and payload, consecutively. */ + /* Note: in the Rockchip I2C driver, a special control byte is sent with + * each operation *implicitly*. PCA9555 expects this only ONCE. So + * unlike the Marvell driver, we should encode the whole operation + * on a single buffer. + */ + if (Read) { + RequestPacket->OperationCount = NumOps; + RequestPacket->Operation[0].LengthInBytes = 1; + RequestPacket->Operation[0].Buffer = &AddressBuffer; + RequestPacket->Operation[0].Buffer[0] = Address & MAX_UINT8; + RequestPacket->Operation[0].Flags = 0; + + RequestPacket->Operation[1].LengthInBytes = 1; + RequestPacket->Operation[1].Buffer = Buffer; + RequestPacket->Operation[1].Flags = I2C_FLAG_READ; + } else { + RequestPacket->OperationCount = NumOps; + RequestPacket->Operation[0].LengthInBytes = 2; + RequestPacket->Operation[0].Buffer = WritePacketBuffer; + RequestPacket->Operation[0].Buffer[0] = Address & MAX_UINT8; + RequestPacket->Operation[0].Buffer[1] = Buffer[0]; + RequestPacket->Operation[0].Flags = 0; + } + + Status = I2cIo->QueueRequest (I2cIo, 0, NULL, RequestPacket, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "%a: transmission error: 0x%d\n", + __FUNCTION__, + Status)); + } + + gBS->FreePool(RequestPacket); + + return Status; +} + +STATIC +EFI_STATUS +Pca95xxReadRegs ( + IN EFI_I2C_IO_PROTOCOL *I2cIo, + IN UINT8 Reg, + OUT UINT8 *RegVal + ) +{ + return Pca95xxI2cTransfer (I2cIo, Reg, RegVal, TRUE); +} + +STATIC +EFI_STATUS +Pca95xxWriteRegs ( + IN EFI_I2C_IO_PROTOCOL *I2cIo, + IN UINTN Reg, + IN UINT8 RegVal + ) +{ + return Pca95xxI2cTransfer (I2cIo, Reg, &RegVal, FALSE); +} + +#if 0 +VOID +EFIAPI +DumpRegs ( + IN EFI_I2C_IO_PROTOCOL *I2cIo + ) +{ + UINT8 Regs[6]; + Pca95xxReadRegs(I2cIo, 0x0, &Regs[0]); + Pca95xxReadRegs(I2cIo, 0x1, &Regs[1]); + Pca95xxReadRegs(I2cIo, 0x2, &Regs[2]); + Pca95xxReadRegs(I2cIo, 0x3, &Regs[3]); + Pca95xxReadRegs(I2cIo, 0x4, &Regs[4]); + Pca95xxReadRegs(I2cIo, 0x5, &Regs[5]); + Pca95xxReadRegs(I2cIo, 0x6, &Regs[6]); + Pca95xxReadRegs(I2cIo, 0x7, &Regs[7]); + + DEBUG ((DEBUG_INFO, "PCA9555 state:\n")); + DEBUG ((DEBUG_INFO, "reg 0 = 0x%02X\n", Regs[0])); + DEBUG ((DEBUG_INFO, "reg 1 = 0x%02X\n", Regs[1])); + DEBUG ((DEBUG_INFO, "reg 2 = 0x%02X\n", Regs[2])); + DEBUG ((DEBUG_INFO, "reg 3 = 0x%02X\n", Regs[3])); + DEBUG ((DEBUG_INFO, "reg 4 = 0x%02X\n", Regs[4])); + DEBUG ((DEBUG_INFO, "reg 5 = 0x%02X\n", Regs[5])); + DEBUG ((DEBUG_INFO, "reg 6 = 0x%02X\n", Regs[6])); + DEBUG ((DEBUG_INFO, "reg 7 = 0x%02X\n", Regs[7])); + DEBUG ((DEBUG_INFO, "\n")); +} +#endif + +/* ------------------------- */ + +/* --- Driver Methods --- */ +STATIC PCA9555_CONTEXT *mPca9555Context = NULL; + +/* Probe the device, bringing it up. */ +EFI_STATUS +EFIAPI +Pca9555Probe ( + IN EFI_I2C_IO_PROTOCOL *I2c + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT8 Zero = 0x00; + UINTN Index; + + if (mPca9555Context != NULL) { + /* The device has already been brought online. Nothing to do. */ + return EFI_SUCCESS; + } + + mPca9555Context = AllocateZeroPool (sizeof(PCA9555_CONTEXT)); + if (mPca9555Context == NULL) { + DEBUG ((DEBUG_ERROR, "%a: context allocation failed\n", __func__)); + Status = EFI_OUT_OF_RESOURCES; + goto fail; + } + + mPca9555Context->Signature = PCA95XX_SIGNATURE; + + mPca9555Context->I2cAddress = PcdGet8 (PcdPca9555Address); + mPca9555Context->I2cBus = PcdGet8 (PcdPca9555Bus); + + /* Device setup: disable polarity inversion on all pins */ + for (Index = 0; Index < PCA9555_NUM_BANKS; ++Index) { + Status = Pca95xxWriteRegs(I2c, PCA9555_INVERSION_REG_BASE + Index, Zero); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: setup failed!\n", __FUNCTION__)); + goto fail; + } + } + + /* and preset all outputs to 0 */ + for (Index = 0; Index < PCA9555_NUM_BANKS; ++Index) { + Status = Pca95xxWriteRegs(I2c, PCA9555_OUTPUT_REG_BASE + Index, Zero); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: setup failed!\n", __FUNCTION__)); + goto fail; + } + } + + DEBUG ((DEBUG_INFO, + "%a: PCA9555 bound at I2C addr 0x%02X, bus 0x%02X\n", + __FUNCTION__, + mPca9555Context->I2cAddress, + mPca9555Context->I2cBus + )); + + return EFI_SUCCESS; +fail: + if (mPca9555Context != NULL) { + FreePool (mPca9555Context); + mPca9555Context = NULL; + } + + return Status; +} + +/* Shut down the device */ +EFI_STATUS +EFIAPI +Pca9555Unprobe ( + IN EFI_I2C_IO_PROTOCOL *I2c +) +{ + if (mPca9555Context != NULL) { + FreePool (mPca9555Context); + mPca9555Context = NULL; + + DEBUG ((DEBUG_INFO, "%a: PCA9555 has been shut down.", __FUNCTION__)); + } + + return EFI_SUCCESS; +} + +/* Read a pin register */ +EFI_STATUS +EFIAPI +Pca9555ReadPinReg ( + IN EFI_I2C_IO_PROTOCOL *I2c, + IN UINT8 BaseReg, + IN UINTN GpioPin, + OUT UINTN *Value + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINTN Bank; + UINT8 RegVal = 0x00; + + if (mPca9555Context == NULL) { + DEBUG ((DEBUG_ERROR, "%a: device not probed", __FUNCTION__)); + return EFI_UNSUPPORTED; + } + + Bank = GpioPin / PCA95XX_BANK_SIZE; + Status = Pca95xxReadRegs (I2c, BaseReg + Bank, &RegVal); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "%a: read failure", __FUNCTION__)); + return Status; + } + + if (RegVal & (1 << (GpioPin % PCA95XX_BANK_SIZE))) { + *Value = 1; + } else { + *Value = 0; + } + + return EFI_SUCCESS; +} + +/* Write the output pin register */ +EFI_STATUS +EFIAPI +Pca9555WritePinOutReg ( + IN EFI_I2C_IO_PROTOCOL *I2c, + IN UINTN GpioPin, + IN UINTN Value + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINTN Bank; + UINT8 RegVal = 0x00; + + if (mPca9555Context == NULL) { + DEBUG ((DEBUG_ERROR, "%a: device not probed", __FUNCTION__)); + return EFI_UNSUPPORTED; + } + + Bank = GpioPin / PCA95XX_BANK_SIZE; + + Status = Pca95xxReadRegs (I2c, + PCA9555_OUTPUT_REG_BASE + Bank, + &RegVal + ); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "%a: read failure", __FUNCTION__)); + return Status; + } + + if (Value) { + RegVal |= (1 << (GpioPin % PCA95XX_BANK_SIZE)); + } else { + RegVal &= ~(1 << (GpioPin % PCA95XX_BANK_SIZE)); + } + + Status = Pca95xxWriteRegs (I2c, + PCA9555_OUTPUT_REG_BASE + Bank, + RegVal + ); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "%a: write failure", __FUNCTION__)); + return Status; + } + + return EFI_SUCCESS; +} + +/* Write the pin control register */ +EFI_STATUS +EFIAPI +Pca9555WritePinCtrlReg ( + IN EFI_I2C_IO_PROTOCOL *I2c, + IN UINTN GpioPin, + IN UINTN Value + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINTN Bank; + UINT8 RegVal = 0x00; + + if (mPca9555Context == NULL) { + DEBUG ((DEBUG_ERROR, "%a: device not probed", __FUNCTION__)); + return EFI_UNSUPPORTED; + } + + Bank = GpioPin / PCA95XX_BANK_SIZE; + + Status = Pca95xxReadRegs (I2c, + PCA9555_CONTROL_REG_BASE + Bank, + &RegVal); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "%a: read failure", __FUNCTION__)); + return Status; + } + + if (Value) { + RegVal |= (1 << (GpioPin % PCA95XX_BANK_SIZE)); + } else { + RegVal &= ~(1 << (GpioPin % PCA95XX_BANK_SIZE)); + } + + Status = Pca95xxWriteRegs (I2c, + PCA9555_CONTROL_REG_BASE + Bank, + RegVal); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "%a: write failure", __FUNCTION__)); + return Status; + } + + return EFI_SUCCESS; +} + +/* ---------------------- */ + +/* --- Embedded GPIO Protocol --- */ + +/* Get the I2C */ +EFI_STATUS +EFIAPI +Pca9555GetI2c ( + IN OUT EFI_I2C_IO_PROTOCOL **I2cIo + ) +{ + UINTN I2cBus, I2cAddress; + UINTN HandleCount, Index; + EFI_HANDLE *HandleBuffer; + EFI_STATUS Status; + + if (mPca9555Context == NULL) { + DEBUG ((DEBUG_ERROR, "%a: device not probed\n", __FUNCTION__)); + return EFI_UNSUPPORTED; + } + + I2cBus = mPca9555Context->I2cBus; + I2cAddress = mPca9555Context->I2cAddress; + + /* Locate Handles of all EfiI2cIoProtocol producers */ + Status = gBS->LocateHandleBuffer (ByProtocol, + &gEfiI2cIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Unable to locate handles\n", __FUNCTION__)); + return Status; + } + + /* Iterate over all protocol producers and pick one upon DeviceIndex match */ + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->OpenProtocol (HandleBuffer[Index], + &gEfiI2cIoProtocolGuid, + (VOID **)I2cIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Unable to open protocol\n", __FUNCTION__)); + gBS->FreePool (HandleBuffer); + return Status; + } + if ((*I2cIo)->DeviceIndex == I2C_DEVICE_INDEX (I2cBus, I2cAddress)) { + gBS->FreePool (HandleBuffer); + return EFI_SUCCESS; + } + } + + gBS->FreePool (HandleBuffer); + + return EFI_NOT_FOUND; +} + +#if !defined(MDEPKG_NDEBUG) +/* A validator; unlike Marvell version we only assume 1 chip */ +STATIC +EFI_STATUS +Pca9555ValidatePin ( + IN UINTN GpioPin + ) +{ + UINTN ControllerId; + + if (GpioPin >= PCA9555_NUM_GPIO) { + DEBUG ((DEBUG_ERROR, + "%a: GPIO pin #%d not available\n", + __FUNCTION__, + GpioPin)); + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} +#endif + +/** + +Routine Description: + + Gets the state of a GPIO pin + +Arguments: + + This - pointer to protocol + Gpio - which pin to read + Value - state of the pin + +Returns: + + EFI_SUCCESS - GPIO state returned in Value + EFI_INVALID_PARAMETER - Value is NULL pointer or Gpio pin is out of range +**/ +STATIC +EFI_STATUS +Pca9555Get ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + OUT UINTN *Value + ) +{ + EFI_I2C_IO_PROTOCOL *I2cIo; + EFI_STATUS Status; + UINTN GpioPin; + UINT8 RegVal; + UINTN Bank; + + GpioPin = GPIO_PIN (Gpio); + + ASSERT_EFI_ERROR (Pca9555ValidatePin (GpioPin)); + + Status = Pca9555GetI2c (&I2cIo); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: fail to get I2C protocol\n", __FUNCTION__)); + return Status; + } + + Status = Pca9555ReadPinReg(I2cIo, PCA9555_INPUT_REG_BASE, Gpio, Value); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: register read failure\n", __FUNCTION__)); + return Status; + } + + return EFI_SUCCESS; +} + +/** + +Routine Description: + + Sets the state of a GPIO pin + +Arguments: + + This - pointer to protocol + Gpio - which pin to modify + Mode - mode to set + +Returns: + + EFI_SUCCESS - GPIO set as requested + EFI_UNSUPPORTED - Mode is not supported + EFI_INVALID_PARAMETER - Gpio pin is out of range +**/ +STATIC +EFI_STATUS +Pca9555Set ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + IN EMBEDDED_GPIO_MODE Mode + ) +{ + EFI_I2C_IO_PROTOCOL *I2cIo; + EFI_STATUS Status; + UINTN GpioPin; + UINTN Bit; + + GpioPin = GPIO_PIN (Gpio); + + ASSERT_EFI_ERROR (Pca9555ValidatePin (GpioPin)); + + Status = Pca9555GetI2c (&I2cIo); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: fail to get I2C protocol\n", __FUNCTION__)); + return Status; + } + +#if 0 + DEBUG ((DEBUG_INFO, "Status before set of pin %d to mode 0x%02X:\n", Gpio, Mode)); + DumpRegs(I2cIo); +#endif + + switch (Mode) { + case GPIO_MODE_OUTPUT_0: + case GPIO_MODE_OUTPUT_1: + if (Mode == GPIO_MODE_OUTPUT_0) { + Bit = 0; + } else { + Bit = 1; + } + + Status = Pca9555WritePinOutReg (I2cIo, GpioPin, Bit); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: fail to set ouput value\n", __FUNCTION__)); + return Status; + } + + Status = Pca9555WritePinCtrlReg (I2cIo, GpioPin, 0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: fail to set direction\n", __FUNCTION__)); + return Status; + } + + break; + case GPIO_MODE_INPUT: + Status = Pca9555WritePinCtrlReg (I2cIo, GpioPin, 1); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: fail to set direction\n", __FUNCTION__)); + return Status; + } + break; + + default: + return EFI_UNSUPPORTED; + } + +#if 0 + DEBUG ((DEBUG_INFO, "Status after set:\n")); + DumpRegs(I2cIo); +#endif + + return EFI_SUCCESS; +} + +/** + +Routine Description: + + Gets the mode (function) of a GPIO pin + +Arguments: + + This - pointer to protocol + Gpio - which pin + Mode - pointer to output mode value + +Returns: + + EFI_SUCCESS - mode value retrieved + EFI_INVALID_PARAMETER - Mode is a null pointer or Gpio pin is out of range + +**/ +STATIC +EFI_STATUS +Pca9555GetMode ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + OUT EMBEDDED_GPIO_MODE *Mode + ) +{ + EFI_I2C_IO_PROTOCOL *I2cIo; + EFI_STATUS Status; + UINTN GpioPin; + UINTN RegVal; + + GpioPin = GPIO_PIN (Gpio); + + ASSERT_EFI_ERROR (Pca9555ValidatePin (GpioPin)); + + Status = Pca9555GetI2c (&I2cIo); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: fail to get I2C protocol\n", __FUNCTION__)); + return Status; + } + + Status = Pca9555ReadPinReg(I2cIo, PCA9555_CONTROL_REG_BASE, Gpio, &RegVal); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: register read failure\n", __FUNCTION__)); + return Status; + } + + if (RegVal == 0) { + /* output modes */ + Status = Pca9555ReadPinReg(I2cIo, PCA9555_OUTPUT_REG_BASE, Gpio, &RegVal); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: register read failure\n", __FUNCTION__)); + return Status; + } + + if (RegVal) { + *Mode = GPIO_MODE_OUTPUT_1; + } else { + *Mode = GPIO_MODE_OUTPUT_0; + } + } else { + /* input mode */ + *Mode = GPIO_MODE_INPUT; + } + + return EFI_SUCCESS; +} + +/** + +Routine Description: + + Sets the pull-up / pull-down resistor of a GPIO pin + +Arguments: + + This - pointer to protocol + Gpio - which pin + Direction - pull-up, pull-down, or none + +Returns: + + EFI_UNSUPPORTED - Can not perform the requested operation + +**/ +EFI_STATUS +EFIAPI +Pca9555SetPull ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + IN EMBEDDED_GPIO_PULL Direction + ) +{ + return EFI_UNSUPPORTED; +} + +PCA95XX_PROTOCOL mPca95xxProtocol = { + .GpioProtocol = { + .Get = Pca9555Get, + .Set = Pca9555Set, + .GetMode = Pca9555GetMode, + .SetPull = Pca9555SetPull, + }, +}; + +/* ------------------------------ */ + +/* --- Binding Protocol --- */ +EFI_DRIVER_BINDING_PROTOCOL mDriverBindingProtocol = { + Pca9555Supported, + Pca9555Start, + Pca9555Stop, +}; + +EFI_STATUS +EFIAPI +Pca9555Supported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + EFI_STATUS Status = EFI_UNSUPPORTED; + EFI_I2C_IO_PROTOCOL *TmpI2cIo; + UINT8 Pca9555Address = 0x00; + UINT8 Pca9555Bus = 0x00; + UINTN i; + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiI2cIoProtocolGuid, + (VOID **) &TmpI2cIo, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR(Status)) { + return EFI_UNSUPPORTED; + } + + Pca9555Address = PcdGet8 (PcdPca9555Address); + Pca9555Bus = PcdGet8 (PcdPca9555Bus); + + DEBUG ((DEBUG_INFO, + "%a: addr = 0x%02X, bus = 0x%02X\n", + __FUNCTION__, + Pca9555Address, + Pca9555Bus)); + + if (CompareGuid(TmpI2cIo->DeviceGuid, &I2cGuid) && + TmpI2cIo->DeviceIndex == I2C_DEVICE_INDEX(Pca9555Bus, Pca9555Address)) { + DEBUG ((DEBUG_INFO, "%a: PCA9555 device is supported\n", __FUNCTION__)); + Status = EFI_SUCCESS; + } + +/*out:*/ + gBS->CloseProtocol ( + ControllerHandle, + &gEfiI2cIoProtocolGuid, + gImageHandle, + ControllerHandle + ); + + return Status; +} + +EFI_STATUS +EFIAPI +Pca9555Start ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + EFI_I2C_IO_PROTOCOL *TmpI2cIo; + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiI2cIoProtocolGuid, + (VOID **) &TmpI2cIo, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR(Status)) { + return EFI_UNSUPPORTED; + } + + Status = Pca9555Probe (TmpI2cIo); + if (EFI_ERROR (Status)) { + goto fail; + } + + Status = gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gPca95xxProtocolGuid, + &mPca95xxProtocol, + NULL); + if (EFI_ERROR (Status)) { + goto fail; + } + + Status = EFI_SUCCESS; + +fail: + gBS->CloseProtocol ( + ControllerHandle, + &gEfiI2cIoProtocolGuid, + gImageHandle, + ControllerHandle + ); + + return Status; +} + +EFI_STATUS +EFIAPI +Pca9555Stop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + + gBS->UninstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gPca95xxProtocolGuid, &mPca95xxProtocol, + &gEfiDriverBindingProtocolGuid, &mDriverBindingProtocol, + NULL + ); + + /* (SS) is this necessary? */ + + /* + Status = Pca9555Unprobe(); + gBS->CloseProtocol ( + ControllerHandle, + &gEfiI2cIoProtocolGuid, + gImageHandle, + ControllerHandle + ); + */ + + return EFI_SUCCESS; +} +/* ------------------------ */ + +EFI_STATUS +EFIAPI +Pca9555DxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiDriverBindingProtocolGuid, &mDriverBindingProtocol, + NULL + ); + + return Status; +} diff --git a/edk2-rockchip/Platform/Firefly/Drivers/Pca9555Dxe/Pca9555Dxe.h b/edk2-rockchip/Platform/Firefly/Drivers/Pca9555Dxe/Pca9555Dxe.h new file mode 100644 index 000000000..530978e57 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/Drivers/Pca9555Dxe/Pca9555Dxe.h @@ -0,0 +1,76 @@ +/** @file +* +* Copyright (c) 2023, Mario Bălănică +* Copyright (c) 2023, Shimrra Shai +* +* SPDX-License-Identifier: BSD-2-Clause-Patent +* +**/ + +#ifndef __PCA9555_DXE_H__ +#define __PCA9555_DXE_H__ + +#include + +#define PCA95XX_SIGNATURE SIGNATURE_32 ('P', '9', '5', 'X') + +#define I2C_GUID \ + { \ + 0xadc1901b, 0xb83c, 0x4831, { 0x8f, 0x59, 0x70, 0x89, 0x8f, 0x26, 0x57, 0x1e } \ + } + +/* NB: Only PCA9555 is supported now. This driver can/should be generalized to + * whole PCA95XX family. + */ +#define PCA9555_INPUT_REG_BASE 0x00 +#define PCA9555_OUTPUT_REG_BASE 0x02 +#define PCA9555_INVERSION_REG_BASE 0x04 +#define PCA9555_CONTROL_REG_BASE 0x06 + +#define PCA9555_NUM_GPIO 16 +#define PCA9555_NUM_BANKS 2 + +#define PCA95XX_BANK_SIZE 8 /* bits */ +#define PCA95XX_MAX_BANK 5 + +typedef struct { + UINT32 Signature; + + UINT8 I2cAddress; + UINT8 I2cBus; +} PCA9555_CONTEXT; + +/* --- Method Prototypes --- */ +EFI_STATUS +EFIAPI +Pca9555Supported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +EFI_STATUS +EFIAPI +Pca9555Start ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +EFI_STATUS +EFIAPI +Pca9555Stop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ); + +EFI_STATUS +EFIAPI +Pca9555DxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#endif // __PCA9555_DXE_H__ diff --git a/edk2-rockchip/Platform/Firefly/Drivers/Pca9555Dxe/Pca9555Dxe.inf b/edk2-rockchip/Platform/Firefly/Drivers/Pca9555Dxe/Pca9555Dxe.inf new file mode 100644 index 000000000..43eee8dda --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/Drivers/Pca9555Dxe/Pca9555Dxe.inf @@ -0,0 +1,49 @@ +#/** @file +# +# PCA9555 GPIO initializer for Rockchip platforms. +# +# Copyright (c) 2023, Mario Bălănică +# Copyright (c) 2023, Shimrra Shai +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = Pca9555Dxe + FILE_GUID = 2ee8d685-8066-4f37-ae0e-5235730b9cc7 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = Pca9555DxeInitialize + +[Sources.common] + Pca9555Dxe.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Platform/Firefly/FireflyPkg.dec + Silicon/Rockchip/RockchipPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiLib + UefiBootServicesTableLib + MemoryAllocationLib + DebugLib + +[Protocols] + gEfiDriverBindingProtocolGuid + gEfiI2cIoProtocolGuid ## CONSUMES + gPca95xxProtocolGuid ## PRODUCES + gRockchipI2cMasterProtocolGuid + +[Pcd] + gFireflyTokenSpaceGuid.PcdPca9555Address + gFireflyTokenSpaceGuid.PcdPca9555Bus + +[Depex] + TRUE + diff --git a/edk2-rockchip/Platform/Firefly/FireflyPkg.dec b/edk2-rockchip/Platform/Firefly/FireflyPkg.dec new file mode 100644 index 000000000..263cb1fa4 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/FireflyPkg.dec @@ -0,0 +1,27 @@ +## @file +# +# Copyright (c) 2023, Mario Bălănică +# Copyright (c) 2023, Shimrra Shai +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = FireflyPkg + PACKAGE_GUID = af4ed3c6-c9de-489f-b72a-ec849b51dbda + PACKAGE_VERSION = 0.1 + +[Includes] + Include + +[Protocols] + gPca95xxProtocolGuid = { 0x7e91391b, 0xa23c, 0x4a51, { 0x9d, 0xf7, 0xf6, 0x74, 0xef, 0x1d, 0x51, 0x1b } } + +[Guids] + gFireflyTokenSpaceGuid = { 0x3d05ddc7, 0x0f61, 0x4190, { 0x95, 0xf9, 0x6d, 0x36, 0x51, 0x35, 0x4f, 0x98 } } + +[PcdsFixedAtBuild] + gFireflyTokenSpaceGuid.PcdPca9555Address|0|UINT8|0x00000001 + gFireflyTokenSpaceGuid.PcdPca9555Bus|0|UINT8|0x00000002 diff --git a/edk2-rockchip/Platform/Firefly/ITX-3588J/AcpiTables/AcpiTables.inf b/edk2-rockchip/Platform/Firefly/ITX-3588J/AcpiTables/AcpiTables.inf new file mode 100644 index 000000000..c9100a7d6 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/ITX-3588J/AcpiTables/AcpiTables.inf @@ -0,0 +1,61 @@ +#/** @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 + $(RK_COMMON_ACPI_DIR)/Pcie3x4.asl + $(RK_COMMON_ACPI_DIR)/Pcie3x2.asl + $(RK_COMMON_ACPI_DIR)/Pcie2x1l0.asl + $(RK_COMMON_ACPI_DIR)/Pcie2x1l1.asl + $(RK_COMMON_ACPI_DIR)/Pcie2x1l2.asl + $(RK_COMMON_ACPI_DIR)/Sata0.asl + $(RK_COMMON_ACPI_DIR)/Sata1.asl + $(RK_COMMON_ACPI_DIR)/Sata2.asl + $(RK_COMMON_ACPI_DIR)/Usb2Host.asl + +[Packages] + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Silicon/Rockchip/RockchipPkg.dec + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmArchTimerIntrNum + gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum + gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum + gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum + gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase + gArmTokenSpaceGuid.PcdGicDistributorBase + gArmTokenSpaceGuid.PcdGicRedistributorsBase + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase diff --git a/edk2-rockchip/Platform/Firefly/ITX-3588J/AcpiTables/Dsdt.asl b/edk2-rockchip/Platform/Firefly/ITX-3588J/AcpiTables/Dsdt.asl new file mode 100644 index 000000000..fd9f529a1 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/ITX-3588J/AcpiTables/Dsdt.asl @@ -0,0 +1,37 @@ +/** @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" + +DefinitionBlock ("Dsdt.aml", "DSDT", 2, "RKCP ", "RK3588 ", 2) +{ + Scope (\_SB_) + { + include ("Cpu.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 ("Usb1Host.asl") + include ("Usb3Host0.asl") + include ("Usb3Host1.asl") + include ("Usb3Host2.asl") + } +} diff --git a/edk2-rockchip/Platform/Firefly/ITX-3588J/ITX-3588J.Modules.fdf.inc b/edk2-rockchip/Platform/Firefly/ITX-3588J/ITX-3588J.Modules.fdf.inc new file mode 100644 index 000000000..f5b083264 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/ITX-3588J/ITX-3588J.Modules.fdf.inc @@ -0,0 +1,22 @@ +## @file +# +# Copyright (c) 2023, Mario Bălănică +# Copyright (c) 2023, Shimrra Shai +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + + # ACPI Support + INF RuleOverride = ACPITABLE Platform/Firefly/ITX-3588J/AcpiTables/AcpiTables.inf + + # Device Tree Support + FILE FREEFORM = gDtPlatformDefaultDtbFileGuid { + SECTION RAW = Platform/Rockchip/DeviceTree/itx-3588j.dtb + } + + # PCA9555 GPIO chipset + INF $(VENDOR_DIRECTORY)/Drivers/Pca9555Dxe/Pca9555Dxe.inf + + # Splash screen logo + INF $(VENDOR_DIRECTORY)/Drivers/LogoDxe/LogoDxe.inf diff --git a/edk2-rockchip/Platform/Firefly/ITX-3588J/ITX-3588J.dsc b/edk2-rockchip/Platform/Firefly/ITX-3588J/ITX-3588J.dsc new file mode 100644 index 000000000..272e8861a --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/ITX-3588J/ITX-3588J.dsc @@ -0,0 +1,34 @@ +## @file +# +# Copyright (c) 2014-2018, Linaro Limited. All rights reserved. +# Copyright (c) 2023, Mario Bălănică +# Copyright (c) 2023, Shimrra Shai +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = ITX-3588J + PLATFORM_VENDOR = Firefly + PLATFORM_GUID = db88a604-ec99-4d39-84d4-af4fa5b5e757 + 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 ITX-3588J board + # +!include Platform/Firefly/ITX-3588J/ITX-3588J.dsc.inc + + diff --git a/edk2-rockchip/Platform/Firefly/ITX-3588J/ITX-3588J.dsc.inc b/edk2-rockchip/Platform/Firefly/ITX-3588J/ITX-3588J.dsc.inc new file mode 100644 index 000000000..ebaec00d1 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/ITX-3588J/ITX-3588J.dsc.inc @@ -0,0 +1,117 @@ +## @file +# +# Copyright (c) 2014-2018, Linaro Limited. All rights reserved. +# Copyright (c) 2023, Mario Bălănică +# Copyright (c) 2023, Shimrra Shai +# +# 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/ITX-3588J/ITX-3588J.Modules.fdf.inc + + # + # HYM8563 RTC support + # I2C location configured by PCDs below. + # + DEFINE RK_RTC8563_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/ITX-3588J/Library/RockchipPlatformLib/RockchipPlatformLib.inf + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform. +# +################################################################################ + +[PcdsFixedAtBuild.common] + # SMBIOS platform config + gRockchipTokenSpaceGuid.PcdPlatformName|"ITX-3588J" + gRockchipTokenSpaceGuid.PcdPlatformVendorName|"Firefly" + gRockchipTokenSpaceGuid.PcdFamilyName|"ITX" + gRockchipTokenSpaceGuid.PcdProductUrl|"https://en.t-firefly.com/product/industry/itx3588j" + gRockchipTokenSpaceGuid.PcdDeviceTreeName|"itx-3588j" + + # I2C + gRockchipTokenSpaceGuid.PcdI2cSlaveAddresses|{ 0x42, 0x43, 0x51, 0x21, 0x22 } + gRockchipTokenSpaceGuid.PcdI2cSlaveBuses|{ 0x0, 0x0, 0x6, 0x6, 0x6 } + gRockchipTokenSpaceGuid.PcdI2cSlaveBusesRuntimeSupport|{ FALSE, FALSE, TRUE, FALSE, FALSE } + gRockchipTokenSpaceGuid.PcdRk860xRegulatorAddresses|{ 0x42, 0x43 } + gRockchipTokenSpaceGuid.PcdRk860xRegulatorBuses|{ 0x0, 0x0 } + gRockchipTokenSpaceGuid.PcdRk860xRegulatorTags|{ $(SCMI_CLK_CPUB01), $(SCMI_CLK_CPUB23) } + gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress|0x51 + gRockchipTokenSpaceGuid.PcdRtc8563Bus|0x6 + gFireflyTokenSpaceGuid.PcdPca9555Address|0x21 + gFireflyTokenSpaceGuid.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_SATA) + 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.PcdUsbDpPhy1Supported|TRUE + gRK3588TokenSpaceGuid.PcdDp1LaneMux|{ 0x2, 0x3 } + + # + # GMAC + # + gRK3588TokenSpaceGuid.PcdGmac0Supported|TRUE + gRK3588TokenSpaceGuid.PcdGmac0TxDelay|0x45 + gRK3588TokenSpaceGuid.PcdGmac1Supported|TRUE + gRK3588TokenSpaceGuid.PcdGmac1TxDelay|0x42 + + # + # 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/ITX-3588J/AcpiTables/AcpiTables.inf + + # PCA9555 chipset + $(VENDOR_DIRECTORY)/Drivers/Pca9555Dxe/Pca9555Dxe.inf + + # Splash screen logo + $(VENDOR_DIRECTORY)/Drivers/LogoDxe/LogoDxe.inf + diff --git a/edk2-rockchip/Platform/Firefly/ITX-3588J/Library/RockchipPlatformLib/RockchipPlatformLib.c b/edk2-rockchip/Platform/Firefly/ITX-3588J/Library/RockchipPlatformLib/RockchipPlatformLib.c new file mode 100644 index 000000000..cea6bd3b9 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/ITX-3588J/Library/RockchipPlatformLib/RockchipPlatformLib.c @@ -0,0 +1,511 @@ +/** @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; + UINTN Index; + + /* 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 */ + BUS_IOC->GPIO2A_IOMUX_SEL_L = (0xFFFFUL << 16) | (0x1111); //EMMC_CMD,EMMC_CLKOUT,EMMC_DATASTROBE,EMMC_RSTN + BUS_IOC->GPIO2D_IOMUX_SEL_L = (0xFFFFUL << 16) | (0x1111); //EMMC_D0,EMMC_D1,EMMC_D2,EMMC_D3 + BUS_IOC->GPIO2D_IOMUX_SEL_H = (0xFFFFUL << 16) | (0x1111); //EMMC_D4,EMMC_D5,EMMC_D6,EMMC_D7 +} + +#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 */ + MmioWrite32(NS_CRU_BASE + CRU_CLKSEL_CON78, + (((0x3 << 12) | (0x3f << 6)) << 16) | (0x0 << 12) | (0x3f << 6)); +#define FSPI_M1 +#if defined(FSPI_M0) + /*FSPI M0*/ + BUS_IOC->GPIO2A_IOMUX_SEL_L = ((0xF << 0) << 16) | (2 << 0); //FSPI_CLK_M0 + BUS_IOC->GPIO2D_IOMUX_SEL_L = (0xFFFFUL << 16) | (0x2222); //FSPI_D0_M0,FSPI_D1_M0,FSPI_D2_M0,FSPI_D3_M0 + BUS_IOC->GPIO2D_IOMUX_SEL_H = ((0xF << 8) << 16) | (0x2 << 8); //FSPI_CS0N_M0 +#elif defined(FSPI_M1) + /*FSPI M1*/ + BUS_IOC->GPIO2A_IOMUX_SEL_H = (0xFF00UL << 16) | (0x3300); //FSPI_D0_M1,FSPI_D1_M1 + BUS_IOC->GPIO2B_IOMUX_SEL_L = (0xF0FFUL << 16) | (0x3033); //FSPI_D2_M1,FSPI_D3_M1,FSPI_CLK_M1 + BUS_IOC->GPIO2B_IOMUX_SEL_H = (0xF << 16) | (0x3); //FSPI_CS0N_M1 +#else + /*FSPI M2*/ + BUS_IOC->GPIO3A_IOMUX_SEL_L = (0xFFFFUL << 16) | (0x5555); //[FSPI_D0_M2-FSPI_D3_M2] + BUS_IOC->GPIO3A_IOMUX_SEL_H = (0xF0UL << 16) | (0x50); //FSPI_CLK_M2 + BUS_IOC->GPIO3C_IOMUX_SEL_H = (0xF << 16) | (0x2); //FSPI_CS0_M2 +#endif +} + +VOID +EFIAPI +GmacIomux ( + IN UINT32 Id + ) +{ + switch (Id) { + case 0: + /* gmac0 iomux */ + BUS_IOC->GPIO2A_IOMUX_SEL_H = (0xFF00UL << 16) | 0x1100; + BUS_IOC->GPIO2B_IOMUX_SEL_L = (0xFFFFUL << 16) | 0x1111; + BUS_IOC->GPIO2B_IOMUX_SEL_H = (0xFF00UL << 16) | 0x1100; + BUS_IOC->GPIO2C_IOMUX_SEL_L = (0x0FFFUL << 16) | 0x0111; + BUS_IOC->GPIO4C_IOMUX_SEL_L = (0xFF00UL << 16) | 0x1100; + BUS_IOC->GPIO4C_IOMUX_SEL_H = (0x00FFUL << 16) | 0x0011; + + /* 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: + /* io mux M2 */ + PMU2_IOC->GPIO0D_IOMUX_SEL_L = (0x0F00UL << 16) | 0x0300; + PMU2_IOC->GPIO0D_IOMUX_SEL_L = (0x00F0UL << 16) | 0x0030; + break; + case 1: + /* io mux */ + //BUS_IOC->GPIO0B_IOMUX_SEL_H = (0x0FF0UL << 16) | 0x0990; + //PMU2_IOC->GPIO0B_IOMUX_SEL_H = (0x0FF0UL << 16) | 0x0880; + break; + case 2: + /* io mux */ + BUS_IOC->GPIO0B_IOMUX_SEL_H = (0xF000UL << 16) | 0x9000; + BUS_IOC->GPIO0C_IOMUX_SEL_L = (0x000FUL << 16) | 0x0009; + PMU2_IOC->GPIO0B_IOMUX_SEL_H = (0xF000UL << 16) | 0x8000; + PMU2_IOC->GPIO0C_IOMUX_SEL_L = (0x000FUL << 16) | 0x0008; + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + /* io mux M0 */ + BUS_IOC->GPIO0C_IOMUX_SEL_H = (0xF000UL << 16) | 0x9000; + BUS_IOC->GPIO0D_IOMUX_SEL_L = (0x000FUL << 16) | 0x0009; + PMU2_IOC->GPIO0C_IOMUX_SEL_H = (0xF000UL << 16) | 0x8000; + PMU2_IOC->GPIO0D_IOMUX_SEL_L = (0x000FUL << 16) | 0x0008; + break; + default: + break; + } +} + +VOID +EFIAPI +UsbPortPowerEnable ( + VOID + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + PCA95XX_PROTOCOL *Pca95xxProtocol; + + /* On Firefly ITX-3588J this is controlled via the PCA9555. */ + Status = GetPca9555Protocol(&Pca95xxProtocol); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "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 + ) +{ + /* Set reset and power IO to gpio output mode */ + if(Segment == PCIE_SEGMENT_PCIE30X4) { + /* reset */ + GpioPinSetDirection (4, GPIO_PIN_PB6, GPIO_PIN_OUTPUT); + /* vcc3v3_pcie30 */ + GpioPinSetDirection (2, GPIO_PIN_PC5, GPIO_PIN_OUTPUT); + } +} + +VOID +EFIAPI +PciePowerEn ( + UINT32 Segment, + BOOLEAN Enable + ) +{ + if(Segment == PCIE_SEGMENT_PCIE30X4) { + /* vcc3v3_pcie30 */ + GpioPinWrite (2, GPIO_PIN_PC5, Enable); + } +} + +VOID +EFIAPI +PciePeReset ( + UINT32 Segment, + BOOLEAN Enable + ) +{ + if(Segment == PCIE_SEGMENT_PCIE30X4) { + GpioPinWrite (4, GPIO_PIN_PB6, !Enable); + } +} + +PWM_DATA pwm_data = { + .ControllerID = PWM_CONTROLLER2, + .ChannelID = PWM_CHANNEL3, + .PeriodNs = 50000, + .DutyNs = 50000, + .Polarity = TRUE, +}; // PWM2_CH3 + +VOID +EFIAPI +PwmFanIoSetup ( + VOID + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + PCA95XX_PROTOCOL *Pca95xxProtocol; + + Status = GetPca9555Protocol(&Pca95xxProtocol); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "Failed to get PCA9555! (%d)\n", Status)); + } else { + Pca95xxProtocol->GpioProtocol.Set( + &Pca95xxProtocol->GpioProtocol, + 11, /* vcc_fan_pwr_en */ + GPIO_MODE_OUTPUT_1 + ); + } +} + +VOID +EFIAPI +PwmFanSetSpeed ( + IN UINT32 Percentage + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + PCA95XX_PROTOCOL *Pca95xxProtocol; + + Status = GetPca9555Protocol(&Pca95xxProtocol); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "Failed to get PCA9555! (%d)\n", Status)); + } else { + /* (SS) NB: (TBA?) It doesn't *appear* we can regulate the fan speed, + * only power up/down, but I could be wrong + */ + Pca95xxProtocol->GpioProtocol.Set( + &Pca95xxProtocol->GpioProtocol, + 11, /* vcc_fan_pwr_en */ + (Percentage > 0) ? GPIO_MODE_OUTPUT_1 : GPIO_MODE_OUTPUT_0 + ); + } +} + +VOID +EFIAPI +PlatformInitLeds ( + VOID + ) +{ + /* Activate power LED only */ + GpioPinWrite (1, GPIO_PIN_PB3, TRUE); + GpioPinSetDirection (1, GPIO_PIN_PB3, GPIO_PIN_OUTPUT); + +#if 0 + /* Red off, Green for status, Blue for power */ + GpioPinWrite (3, GPIO_PIN_PB2, FALSE); + GpioPinSetDirection (3, GPIO_PIN_PB2, GPIO_PIN_OUTPUT); + GpioPinWrite (3, GPIO_PIN_PC0, FALSE); + GpioPinSetDirection (3, GPIO_PIN_PC0, GPIO_PIN_OUTPUT); + GpioPinWrite (1, GPIO_PIN_PD5, TRUE); + GpioPinSetDirection (1, GPIO_PIN_PD5, GPIO_PIN_OUTPUT); +#endif +} + +VOID +EFIAPI +PlatformSetStatusLed ( + IN BOOLEAN Enable + ) +{ + /* (SS) does not seem to work and causes errors on I2C complaining + * about something being too high + */ +#if 0 + EFI_STATUS Status = EFI_SUCCESS; + PCA95XX_PROTOCOL *Pca95xxProtocol; + + /* On Firefly ITX-3588J this is controlled via the PCA9555. */ + Status = GetPca9555Protocol(&Pca95xxProtocol); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "Failed to get PCA9555! (%d)\n", Status)); + } else { + Pca95xxProtocol->GpioProtocol.Set( + &Pca95xxProtocol->GpioProtocol, + 3, /* user_led */ + Enable ? GPIO_MODE_OUTPUT_1 : GPIO_MODE_OUTPUT_0 + ); + } +#endif +} + +VOID +EFIAPI +PlatformEarlyInit ( + VOID + ) +{ + +} diff --git a/edk2-rockchip/Platform/Firefly/ITX-3588J/Library/RockchipPlatformLib/RockchipPlatformLib.inf b/edk2-rockchip/Platform/Firefly/ITX-3588J/Library/RockchipPlatformLib/RockchipPlatformLib.inf new file mode 100644 index 000000000..c62129506 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/ITX-3588J/Library/RockchipPlatformLib/RockchipPlatformLib.inf @@ -0,0 +1,39 @@ +# +# 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 + Platform/Firefly/FireflyPkg.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/Include/Protocol/Pca9555.h b/edk2-rockchip/Platform/Firefly/Include/Protocol/Pca9555.h new file mode 100644 index 000000000..141218c19 --- /dev/null +++ b/edk2-rockchip/Platform/Firefly/Include/Protocol/Pca9555.h @@ -0,0 +1,28 @@ +/** @file + * + * Copyright (c) 2023, Mario Bălănică + * Copyright (c) 2023, Shimrra Shai + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * + **/ + +#ifndef __PCA9555_H__ +#define __PCA9555_H__ + +#include + +#include + +#define PCA95XX_PROTOCOL_GUID \ + { 0x7e91391b, 0xa23c, 0x4a51, { 0x9d, 0xf7, 0xf6, 0x74, 0xef, 0x1d, 0x51, 0x1b } } + +typedef struct _PCA95XX_PROTOCOL PCA95XX_PROTOCOL; + +struct _PCA95XX_PROTOCOL { + EMBEDDED_GPIO GpioProtocol; +}; + +extern EFI_GUID gPca95xxProtocolGuid; + +#endif // __PCA9555_H__