From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) by mx.groups.io with SMTP id smtpd.web11.6337.1622848944697254898 for ; Fri, 04 Jun 2021 16:22:25 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20150623.gappssmtp.com header.s=20150623 header.b=QM83dZI6; spf=pass (domain: nuviainc.com, ip: 209.85.128.45, mailfrom: leif@nuviainc.com) Received: by mail-wm1-f45.google.com with SMTP id p13-20020a05600c358db029019f44afc845so6407797wmq.3 for ; Fri, 04 Jun 2021 16:22:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=ZJl9lc5wpA217oq6P/RLz584qUu9d7kZoQZ2kTckNPs=; b=QM83dZI62Hrc1iJrBHImE+QvYRZkq+Ova6OnzVHAHs2/+B7vN1uiczDFqiLGRbPISJ aVnaF3J9TlBFsnGT76Gh/H+DHxFKCND7KFVjKB3A01GQKPka7hx7nsDQFLkutOrcDZ0F TeHRhLibT/i8CmLkmNacCf7jNh1XWah5+x+HqaTWJPSxym3kllzNoBEm67uMJ96Ohrbz VSbeSVMr7HOVkP9iLD3YWW0js8ruJ8Ncpc3jenVdwLT1dGIXXCO7Z635aa3CM4gQBtQo BSMJy4pQKfkEWJ+qQwrWkwUV1bf7cKuYFM7p+2DK+A3/H58F5V7mFzbsUAi9IsAF1nkl j0xQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=ZJl9lc5wpA217oq6P/RLz584qUu9d7kZoQZ2kTckNPs=; b=tmUZsoNvjCjmC6bmtLThmP/X+vFU9OX1AGeR6xfPunF97KI/os0MQHTbjFMWYP3s6u FEPdJSAfJSx6yvS+RlMrdFzRwPb0r7nlU1Jx8yjLop4jxsIXxWuq3WGjk115zfpaTnCG VCZHHA5DwrfjMxPs4UbT9zpoofP2hZrXV+xH/Y9E5uXnKHtxAQ9eCkyHiWaf05U+TR7h JSMeYozb0jAlPZ8vapMgYcmyPM7ZvPCGy94kwuKjfAX6rrKUf0m/lmQr0nzgBaMASLZS N53Je4Bn8xr0LYq+sAtyWFnMOtAwgA79PeMPdovp/tpD0ViDJNkvXd9Be+ybpVDiZM7V 6YTw== X-Gm-Message-State: AOAM530/PYYNpROwpyRHpvJGzAPWYBqfgbL5k70m4dBM9RVoPkIA9hwd ob5z8u8B0wLGdIeZ8g6GChe/+Q== X-Google-Smtp-Source: ABdhPJxyiKAwrDk1pFtjoJiJUmG9W9flGgzW7Z+JE3lewECgjKd2BGIoP7uf82H1JJqS6+76AbM+lA== X-Received: by 2002:a05:600c:4b87:: with SMTP id e7mr5679457wmp.101.1622848943300; Fri, 04 Jun 2021 16:22:23 -0700 (PDT) Return-Path: Received: from leviathan (cpc1-cmbg19-2-0-cust915.5-4.cable.virginm.net. [82.27.183.148]) by smtp.gmail.com with ESMTPSA id a1sm9004625wrg.92.2021.06.04.16.22.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Jun 2021 16:22:22 -0700 (PDT) Date: Sat, 5 Jun 2021 00:22:21 +0100 From: "Leif Lindholm" To: Nhi Pham Cc: devel@edk2.groups.io, Vu Nguyen , Thang Nguyen , Chuong Tran , Phong Vo , Michael D Kinney , Ard Biesheuvel , Nate DeSimone Subject: Re: [edk2-platforms][PATCH v2 06/32] AmpereAltraPkg: Add DwGpioLib library Message-ID: <20210604232221.av4j7vscoyss7u3g@leviathan> References: <20210526100724.5359-1-nhi@os.amperecomputing.com> <20210526100724.5359-8-nhi@os.amperecomputing.com> MIME-Version: 1.0 In-Reply-To: <20210526100724.5359-8-nhi@os.amperecomputing.com> Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Wed, May 26, 2021 at 17:06:58 +0700, Nhi Pham wrote: > From: Vu Nguyen > > The DwGpioLib library provides basic functions to control the GPIO > controller on Ampere Altra processor. > > Cc: Thang Nguyen > Cc: Chuong Tran > Cc: Phong Vo > Cc: Leif Lindholm > Cc: Michael D Kinney > Cc: Ard Biesheuvel > Cc: Nate DeSimone > > Signed-off-by: Vu Nguyen Reviewed-by: Leif Lindholm / 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.
> +# > +# 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.
> + > + 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.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* 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 >