On Wed, May 26, 2021 at 17:06:58 +0700, Nhi Pham wrote: > From: Vu Nguyen <vungu...@os.amperecomputing.com> > > The DwGpioLib library provides basic functions to control the GPIO > controller on Ampere Altra processor. > > Cc: Thang Nguyen <th...@os.amperecomputing.com> > Cc: Chuong Tran <chu...@os.amperecomputing.com> > Cc: Phong Vo <ph...@os.amperecomputing.com> > Cc: Leif Lindholm <l...@nuviainc.com> > Cc: Michael D Kinney <michael.d.kin...@intel.com> > Cc: Ard Biesheuvel <ardb+tianoc...@kernel.org> > Cc: Nate DeSimone <nathaniel.l.desim...@intel.com> > > Signed-off-by: Vu Nguyen <vungu...@os.amperecomputing.com>
Reviewed-by: Leif Lindholm <l...@nuviainc.com> / Leif > --- > Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec | 3 + > Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.inf | 33 ++ > Silicon/Ampere/AmpereAltraPkg/Include/Library/GpioLib.h | 76 +++++ > Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.c | 314 > ++++++++++++++++++++ > 4 files changed, 426 insertions(+) > > diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > index 8be6a329bb26..be827dd19a96 100644 > --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > @@ -31,6 +31,9 @@ [LibraryClasses] > ## @libraryclass Defines a set of methods to read/write to I2C devices. > I2cLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/I2cLib.h > > + ## @libraryclass Defines a set of methods to get/set GPIO. > + GpioLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/GpioLib.h > + > ## @libraryclass Defines a set of methods to communicate with secure > parition over MM interface. > > MmCommunicationLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/MmCommunicationLib.h > > diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.inf > b/Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.inf > new file mode 100644 > index 000000000000..36ce0c3be2c8 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.inf > @@ -0,0 +1,33 @@ > +## @file > +# Component description for DwGpioLib library for the Designware GPIO > controller. > +# > +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR> > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001B > + BASE_NAME = DwGpioLib > + FILE_GUID = E7D9CAE1-6930-46E3-BDF9-0027446E7DF2 > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = GpioLib > + > +[Sources.common] > + DwGpioLib.c > + > +[Packages] > + ArmPkg/ArmPkg.dec > + ArmPlatformPkg/ArmPlatformPkg.dec > + MdePkg/MdePkg.dec > + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > + > +[LibraryClasses] > + BaseLib > + BaseMemoryLib > + IoLib > + > +[Guids] > + gEfiEventVirtualAddressChangeGuid > diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Library/GpioLib.h > b/Silicon/Ampere/AmpereAltraPkg/Include/Library/GpioLib.h > new file mode 100755 > index 000000000000..cb201bc98322 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Include/Library/GpioLib.h > @@ -0,0 +1,76 @@ > +/** @file > + Library implementation for the Designware GPIO controller. > + > + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef GPIO_LIB_H_ > +#define GPIO_LIB_H_ > + > +enum SocGpioConfigMode { > + GPIO_CONFIG_OUT_LOW = 0, > + GPIO_CONFIG_OUT_HI, > + GPIO_CONFIG_OUT_LOW_TO_HIGH, > + GPIO_CONFIG_OUT_HIGH_TO_LOW, > + GPIO_CONFIG_IN, > + MAX_GPIO_CONFIG_MODE > +}; > + > +/* > + * GpioWriteBit: Use to Set/Clear GPIOs > + * Input: > + * Pin : Pin Identification > + * Val : 1 to Set, 0 to Clear > + */ > +VOID > +EFIAPI > +GpioWriteBit ( > + IN UINT32 Pin, > + IN UINT32 Val > + ); > + > +/* > + * GpioReadBit: > + * Input: > + * Pin : Pin Identification > + * Return: > + * 1 : On/High > + * 0 : Off/Low > + */ > +UINTN > +EFIAPI > +GpioReadBit ( > + IN UINT32 Pin > + ); > + > +/* > + * GpioModeConfig: Use to configure GPIOs as Input/Output > + * Input: > + * Pin : Pin Identification > + * InOut : GPIO_OUT/1 as Output > + * GPIO_IN/0 as Input > + */ > +EFI_STATUS > +EFIAPI > +GpioModeConfig ( > + UINT8 Pin, > + UINTN Mode > + ); > + > +/* > + * Setup a controller that to be used in runtime service. > + * Input: > + * Pin: Pin belongs to the controller. > + * return: 0 for success. > + * Otherwise, error code. > + */ > +EFI_STATUS > +EFIAPI > +GpioSetupRuntime ( > + IN UINT32 Pin > + ); > + > +#endif /* GPIO_LIB_H_ */ > diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.c > b/Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.c > new file mode 100644 > index 000000000000..dbb53f7d57d2 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.c > @@ -0,0 +1,314 @@ > +/** @file > + > + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include <PiDxe.h> > +#include <Uefi.h> > + > +#include <Library/DebugLib.h> > +#include <Library/GpioLib.h> > +#include <Library/DxeServicesTableLib.h> > +#include <Library/IoLib.h> > +#include <Library/TimerLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/UefiRuntimeLib.h> > +#include <Platform/Ac01.h> > + > +/* Runtime needs to be 64K alignment */ > +#define RUNTIME_ADDRESS_MASK (~(SIZE_64KB - 1)) > +#define RUNTIME_ADDRESS_LENGTH SIZE_64KB > + > +#define GPIO_MUX_VAL(Gpio) (0x00000001 << (Gpio)) > +#define GPIO_IN 0 > +#define GPIO_OUT 1 > + > +/* Address GPIO_REG Registers */ > +#define GPIO_SWPORTA_DR_ADDR 0x00000000 > +#define GPIO_SWPORTA_DDR_ADDR 0x00000004 > +#define GPIO_EXT_PORTA_ADDR 0x00000050 > + > +STATIC UINT64 GpioBaseAddr[] = { GPIO_DWAPB_BASE_ADDR }; > +STATIC UINT64 GpiBaseAddr[] = { GPI_DWAPB_BASE_ADDR }; > +STATIC BOOLEAN GpioRuntimeEnableArray[sizeof (GpioBaseAddr) / sizeof > (GpioBaseAddr[0])] = { FALSE }; > +STATIC EFI_EVENT mVirtualAddressChangeEvent = NULL; > + > +UINT64 > +GetBaseAddr ( > + IN UINT32 Pin > + ) > +{ > + UINT32 NumberOfControllers = sizeof (GpioBaseAddr) / sizeof > (GpioBaseAddr[0]); > + UINT32 TotalPins = GPIO_DWAPB_PINS_PER_CONTROLLER * NumberOfControllers; > + > + if (NumberOfControllers == 0 || Pin >= TotalPins) { > + return 0; > + } > + > + return GpioBaseAddr[Pin / GPIO_DWAPB_PINS_PER_CONTROLLER]; > +} > + > +VOID > +GpioWrite ( > + IN UINT64 Base, > + IN UINT32 Val > + ) > +{ > + MmioWrite32 ((UINTN)Base, Val); > +} > + > +VOID > +GpioRead ( > + IN UINT64 Base, > + OUT UINT32 *Val > + ) > +{ > + ASSERT (Val != NULL); > + *Val = MmioRead32 (Base); > +} > + > +VOID > +EFIAPI > +GpioWriteBit ( > + IN UINT32 Pin, > + IN UINT32 Val > + ) > +{ > + UINT64 Reg; > + UINT32 GpioPin; > + UINT32 ReadVal; > + > + Reg = GetBaseAddr (Pin); > + if (Reg == 0) { > + return; > + } > + > + GpioPin = Pin % GPIO_DWAPB_PINS_PER_CONTROLLER; > + > + Reg += GPIO_SWPORTA_DR_ADDR; > + GpioRead (Reg, &ReadVal); > + > + if (Val != 0) { > + GpioWrite (Reg, ReadVal | GPIO_MUX_VAL (GpioPin)); > + } else { > + GpioWrite (Reg, ReadVal & ~GPIO_MUX_VAL (GpioPin)); > + } > +} > + > +UINTN > +EFIAPI > +GpioReadBit ( > + IN UINT32 Pin > + ) > +{ > + UINT64 Reg; > + UINT32 Val; > + UINT32 GpioPin; > + UINT8 Index; > + UINT32 MaxIndex; > + > + Reg = GetBaseAddr (Pin); > + if (Reg == 0) { > + return 0; > + } > + > + GpioPin = Pin % GPIO_DWAPB_PINS_PER_CONTROLLER; > + > + /* Check if a base address is GPI */ > + MaxIndex = sizeof (GpiBaseAddr) / sizeof (GpiBaseAddr[0]); > + for (Index = 0; Index < MaxIndex; Index++) { > + if (Reg == GpiBaseAddr[Index]) { > + break; > + } > + } > + if (Index == MaxIndex) { > + /* Only GPIO has GPIO_EXT_PORTA register, not for GPI */ > + Reg += GPIO_EXT_PORTA_ADDR; > + } > + > + GpioRead (Reg, &Val); > + > + return Val & GPIO_MUX_VAL (GpioPin) ? 1 : 0; > +} > + > +EFI_STATUS > +GpioConfig ( > + IN UINT32 Pin, > + IN UINT32 InOut > + ) > +{ > + INTN GpioPin; > + UINT32 Val; > + UINT64 Reg; > + > + /* > + * Caculate GPIO Pin Number for Direction Register > + * GPIO_SWPORTA_DDR for GPIO[31...0] > + * GPIO_SWPORTB_DDR for GPIO[51...32] > + */ > + > + Reg = GetBaseAddr (Pin); > + if (Reg == 0) { > + return EFI_UNSUPPORTED; > + } > + > + Reg += GPIO_SWPORTA_DDR_ADDR; > + GpioPin = Pin % GPIO_DWAPB_PINS_PER_CONTROLLER; > + GpioRead (Reg, &Val); > + > + if (InOut == GPIO_OUT) { > + Val |= GPIO_MUX_VAL (GpioPin); > + } else { > + Val &= ~GPIO_MUX_VAL (GpioPin); > + } > + GpioWrite (Reg, Val); > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +EFIAPI > +GpioModeConfig ( > + UINT8 Pin, > + UINTN Mode > + ) > +{ > + UINT32 NumberOfControllers = sizeof (GpioBaseAddr) / sizeof (UINT64); > + UINT32 NumersOfPins = NumberOfControllers * GPIO_DWAPB_PINS_PER_CONTROLLER; > + UINT32 Delay = 10; > + > + if (Mode < GPIO_CONFIG_OUT_LOW > + || Mode >= MAX_GPIO_CONFIG_MODE > + || Pin > NumersOfPins - 1 > + || Pin < 0) > + { > + return EFI_INVALID_PARAMETER; > + } > + > + switch (Mode) { > + case GPIO_CONFIG_OUT_LOW: > + GpioConfig (Pin, GPIO_OUT); > + GpioWriteBit (Pin, 0); > + DEBUG ((DEBUG_INFO, "GPIO pin %d configured as output low\n", Pin)); > + break; > + > + case GPIO_CONFIG_OUT_HI: > + GpioConfig (Pin, GPIO_OUT); > + GpioWriteBit (Pin, 1); > + DEBUG ((DEBUG_INFO, "GPIO pin %d configured as output high\n", Pin)); > + break; > + > + case GPIO_CONFIG_OUT_LOW_TO_HIGH: > + GpioConfig (Pin, GPIO_OUT); > + GpioWriteBit (Pin, 0); > + MicroSecondDelay (1000 * Delay); > + GpioWriteBit (Pin, 1); > + DEBUG ((DEBUG_INFO, "GPIO pin %d configured as output low->high\n", > Pin)); > + break; > + > + case GPIO_CONFIG_OUT_HIGH_TO_LOW: > + GpioConfig (Pin, GPIO_OUT); > + GpioWriteBit (Pin, 1); > + MicroSecondDelay (1000 * Delay); > + GpioWriteBit (Pin, 0); > + DEBUG ((DEBUG_INFO, "GPIO pin %d configured as output high->low\n", > Pin)); > + break; > + > + case GPIO_CONFIG_IN: > + GpioConfig (Pin, GPIO_IN); > + DEBUG ((DEBUG_INFO, "GPIO pin %d configured as input\n", Pin)); > + break; > + > + default: > + break; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + * Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE. > + * > + * This is a notification function registered on > EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event. > + * It convers pointer to new virtual address. > + * > + * @param Event Event whose notification function is being invoked. > + * @param Context Pointer to the notification function's context. > + */ > +VOID > +EFIAPI > +GpioVirtualAddressChangeEvent ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + UINTN Count; > + > + EfiConvertPointer (0x0, (VOID **)&GpioBaseAddr); > + for (Count = 0; Count < sizeof (GpioBaseAddr) / sizeof (GpioBaseAddr[0]); > Count++) { > + if (!GpioRuntimeEnableArray[Count]) { > + continue; > + } > + EfiConvertPointer (0x0, (VOID **)&GpioBaseAddr[Count]); > + } > +} > + > +/** > + Setup a controller that to be used in runtime service. > + > + @Bus: Bus ID. > + @return: 0 for success. > + Otherwise, error code. > + **/ > +EFI_STATUS > +EFIAPI > +GpioSetupRuntime ( > + IN UINT32 Pin > + ) > +{ > + EFI_STATUS Status; > + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; > + > + if (GetBaseAddr (Pin) == 0) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (mVirtualAddressChangeEvent == NULL) { > + /* > + * Register for the virtual address change event > + */ > + Status = gBS->CreateEventEx ( > + EVT_NOTIFY_SIGNAL, > + TPL_NOTIFY, > + GpioVirtualAddressChangeEvent, > + NULL, > + &gEfiEventVirtualAddressChangeGuid, > + &mVirtualAddressChangeEvent > + ); > + ASSERT_EFI_ERROR (Status); > + } > + > + Status = gDS->GetMemorySpaceDescriptor ( > + GetBaseAddr (Pin) & RUNTIME_ADDRESS_MASK, > + &Descriptor > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = gDS->SetMemorySpaceAttributes ( > + GetBaseAddr (Pin) & RUNTIME_ADDRESS_MASK, > + RUNTIME_ADDRESS_LENGTH, > + Descriptor.Attributes | EFI_MEMORY_RUNTIME > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + GpioRuntimeEnableArray[Pin / GPIO_DWAPB_PINS_PER_CONTROLLER] = TRUE; > + > + return Status; > +} > -- > 2.17.1 > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#76087): https://edk2.groups.io/g/devel/message/76087 Mute This Topic: https://groups.io/mt/83097100/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-