On 18 August 2015 at 11:04, Haojian Zhuang <[email protected]> wrote:
> Support multiple PL061 controllers.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Haojian Zhuang <[email protected]>
> ---
> ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c | 107
> ++++++++++++++-------
> .../Drivers/PL061GpioDxe/PL061GpioDxe.inf | 3 +-
> ArmPlatformPkg/Include/Drivers/PL061Gpio.h | 40 ++++----
> 3 files changed, 96 insertions(+), 54 deletions(-)
>
> diff --git a/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c
> b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c
> index e8a2094..3027656 100644
> --- a/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c
> +++ b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c
> @@ -28,6 +28,7 @@
> #include <Drivers/PL061Gpio.h>
>
> BOOLEAN mPL061Initialized = FALSE;
> +PLATFORM_GPIO_CONTROLLER *mPL061PlatformGpio;
>
> /**
> Function implementations
> @@ -38,20 +39,31 @@ PL061Identify (
> VOID
> )
> {
> - // Check if this is a PrimeCell Peripheral
> - if ( (MmioRead8 (PL061_GPIO_PCELL_ID0) != 0x0D)
> - || (MmioRead8 (PL061_GPIO_PCELL_ID1) != 0xF0)
> - || (MmioRead8 (PL061_GPIO_PCELL_ID2) != 0x05)
> - || (MmioRead8 (PL061_GPIO_PCELL_ID3) != 0xB1)) {
> - return EFI_NOT_FOUND;
> + UINTN Index;
> + UINT32 RegisterBase;
Why is this a 32-bit value?
> +
> + if ( (mPL061PlatformGpio->GpioCount == 0)
> + || (mPL061PlatformGpio->GpioControllerCount == 0)) {
> + return EFI_NOT_FOUND;
> }
>
> - // Check if this PrimeCell Peripheral is the PL061 GPIO
> - if ( (MmioRead8 (PL061_GPIO_PERIPH_ID0) != 0x61)
> - || (MmioRead8 (PL061_GPIO_PERIPH_ID1) != 0x10)
> - || ((MmioRead8 (PL061_GPIO_PERIPH_ID2) & 0xF) != 0x04)
> - || (MmioRead8 (PL061_GPIO_PERIPH_ID3) != 0x00)) {
> - return EFI_NOT_FOUND;
> + for (Index = 0; Index < mPL061PlatformGpio->GpioControllerCount; Index++) {
> + RegisterBase = (UINT32)
> mPL061PlatformGpio->GpioController[Index].RegisterBase;
> + // Check if this is a PrimeCell Peripheral
> + if ( (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID0) != 0x0D)
> + || (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID1) != 0xF0)
> + || (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID2) != 0x05)
> + || (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID3) != 0xB1)) {
> + return EFI_NOT_FOUND;
> + }
> +
> + // Check if this PrimeCell Peripheral is the PL061 GPIO
> + if ( (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID0) != 0x61)
> + || (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID1) != 0x10)
> + || ((MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID2) & 0xF) !=
> 0x04)
> + || (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID3) != 0x00)) {
> + return EFI_NOT_FOUND;
> + }
> }
>
> return EFI_SUCCESS;
> @@ -84,6 +96,30 @@ PL061Initialize (
> return Status;
> }
>
> +EFI_STATUS
> +EFIAPI
> +PL061Locate (
> + IN EMBEDDED_GPIO_PIN Gpio,
> + OUT UINT32 *ControllerIndex,
> + OUT UINT32 *ControllerOffset,
> + OUT UINT32 *RegisterBase
> + )
> +{
> + UINT32 Index;
> +
> + for (Index = 0; Index < mPL061PlatformGpio->GpioControllerCount; Index++) {
> + if ( (Gpio >= mPL061PlatformGpio->GpioController[Index].GpioIndex)
> + && (Gpio < mPL061PlatformGpio->GpioController[Index].GpioIndex
> + + mPL061PlatformGpio->GpioController[Index].InternalGpioCount))
> {
> + *ControllerIndex = Index;
> + *ControllerOffset = Gpio %
> mPL061PlatformGpio->GpioController[Index].InternalGpioCount;
Since you are relying on the internal GPIO count to be the same for
all instances, you should probably check that the value is correct in
PL061Identify()
> + *RegisterBase = mPL061PlatformGpio->GpioController[Index].RegisterBase;
> + return EFI_SUCCESS;
> + }
> + }
> + return EFI_INVALID_PARAMETER;
> +}
> +
> /**
>
> Routine Description:
> @@ -110,11 +146,15 @@ Get (
> )
> {
> EFI_STATUS Status = EFI_SUCCESS;
> + UINT32 Index, Offset, RegisterBase;
>
> - if ( (Value == NULL)
> - || (Gpio > LAST_GPIO_PIN))
> - {
> - return EFI_INVALID_PARAMETER;
> + Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase);
> + if (EFI_ERROR (Status))
> + goto EXIT;
> +
> + if (Value == NULL) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> }
>
> // Initialize the hardware if not already done
> @@ -125,7 +165,7 @@ Get (
> }
> }
>
> - if (MmioRead8 (PL061_GPIO_DATA_REG + (GPIO_PIN_MASK(Gpio) << 2))) {
> + if (MmioRead8 (RegisterBase + PL061_GPIO_DATA_REG + (GPIO_PIN_MASK(Offset)
> << 2))) {
> *Value = 1;
> } else {
> *Value = 0;
> @@ -162,12 +202,11 @@ Set (
> )
> {
> EFI_STATUS Status = EFI_SUCCESS;
> + UINT32 Index, Offset, RegisterBase;
>
> - // Check for errors
> - if (Gpio > LAST_GPIO_PIN) {
> - Status = EFI_INVALID_PARAMETER;
> + Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase);
> + if (EFI_ERROR (Status))
> goto EXIT;
> - }
>
> // Initialize the hardware if not already done
> if (!mPL061Initialized) {
> @@ -181,21 +220,21 @@ Set (
> {
> case GPIO_MODE_INPUT:
> // Set the corresponding direction bit to LOW for input
> - MmioAnd8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Gpio));
> + MmioAnd8 (RegisterBase + PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Offset));
> break;
>
> case GPIO_MODE_OUTPUT_0:
> // Set the corresponding data bit to LOW for 0
> - MmioWrite8 (PL061_GPIO_DATA_REG + (GPIO_PIN_MASK(Gpio) << 2),
> GPIO_PIN_MASK(Gpio));
> + MmioWrite8 (RegisterBase + PL061_GPIO_DATA_REG +
> (GPIO_PIN_MASK(Offset) << 2), 0);
> // Set the corresponding direction bit to HIGH for output
> - MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Gpio));
> + MmioOr8 (RegisterBase + PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Offset));
> break;
>
> case GPIO_MODE_OUTPUT_1:
> // Set the corresponding data bit to HIGH for 1
> - MmioWrite8 (PL061_GPIO_DATA_REG + (GPIO_PIN_MASK(Gpio) << 2),
> GPIO_PIN_MASK(Gpio));
> + MmioWrite8 (RegisterBase + PL061_GPIO_DATA_REG +
> (GPIO_PIN_MASK(Offset) << 2), 0xff);
> // Set the corresponding direction bit to HIGH for output
> - MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Gpio));
> + MmioOr8 (RegisterBase + PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Offset));
> break;
>
> default:
> @@ -234,12 +273,11 @@ GetMode (
> )
> {
> EFI_STATUS Status;
> + UINT32 Index, Offset, RegisterBase;
>
> - // Check for errors
> - if ( (Mode == NULL)
> - || (Gpio > LAST_GPIO_PIN)) {
> - return EFI_INVALID_PARAMETER;
> - }
> + Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase);
> + if (EFI_ERROR (Status))
> + return Status;
>
> // Initialize the hardware if not already done
> if (!mPL061Initialized) {
> @@ -250,9 +288,9 @@ GetMode (
> }
>
> // Check if it is input or output
> - if (MmioRead8 (PL061_GPIO_DIR_REG + (GPIO_PIN_MASK(Gpio) << 2))) {
> + if (MmioRead8 (RegisterBase + PL061_GPIO_DIR_REG) & GPIO_PIN_MASK(Offset))
> {
> // Pin set to output
> - if (MmioRead8 (PL061_GPIO_DATA_REG) & GPIO_PIN_MASK(Gpio)) {
> + if (MmioRead8 (RegisterBase + PL061_GPIO_DATA_REG) &
> GPIO_PIN_MASK(Offset)) {
> *Mode = GPIO_MODE_OUTPUT_1;
> } else {
> *Mode = GPIO_MODE_OUTPUT_0;
> @@ -329,6 +367,9 @@ PL061InstallProtocol (
> //
> ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEmbeddedGpioProtocolGuid);
>
> + Status = gBS->LocateProtocol (&gPlatformGpioProtocolGuid, NULL, (VOID
> **)&mPL061PlatformGpio);
> + ASSERT_EFI_ERROR (Status);
> +
We should fall back to using the PCD if the protocol cannot be found.
This way, we won't break existing users.
> // Install the Embedded GPIO Protocol onto a new handle
> Handle = NULL;
> Status = gBS->InstallMultipleProtocolInterfaces(
> diff --git a/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf
> b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf
> index 9d9e4cd..971452c 100644
> --- a/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf
> +++ b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf
> @@ -45,6 +45,7 @@
>
> [Protocols]
> gEmbeddedGpioProtocolGuid
> + gPlatformGpioProtocolGuid
>
> [Depex]
> - TRUE
> + gPlatformGpioProtocolGuid
Likewise, this breaks existing users
> diff --git a/ArmPlatformPkg/Include/Drivers/PL061Gpio.h
> b/ArmPlatformPkg/Include/Drivers/PL061Gpio.h
> index d436fd4..98d7bc2 100644
> --- a/ArmPlatformPkg/Include/Drivers/PL061Gpio.h
> +++ b/ArmPlatformPkg/Include/Drivers/PL061Gpio.h
> @@ -19,26 +19,26 @@
> #include <Protocol/EmbeddedGpio.h>
>
> // PL061 GPIO Registers
> -#define PL061_GPIO_DATA_REG ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0x000)
> -#define PL061_GPIO_DIR_REG ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0x400)
> -#define PL061_GPIO_IS_REG ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0x404)
> -#define PL061_GPIO_IBE_REG ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0x408)
> -#define PL061_GPIO_IEV_REG ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0x40C)
> -#define PL061_GPIO_IE_REG ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0x410)
> -#define PL061_GPIO_RIS_REG ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0x414)
> -#define PL061_GPIO_MIS_REG ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0x410)
> -#define PL061_GPIO_IC_REG ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0x41C)
> -#define PL061_GPIO_AFSEL_REG ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0x420)
> -
> -#define PL061_GPIO_PERIPH_ID0 ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0xFE0)
> -#define PL061_GPIO_PERIPH_ID1 ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0xFE4)
> -#define PL061_GPIO_PERIPH_ID2 ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0xFE8)
> -#define PL061_GPIO_PERIPH_ID3 ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0xFEC)
> -
> -#define PL061_GPIO_PCELL_ID0 ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0xFF0)
> -#define PL061_GPIO_PCELL_ID1 ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0xFF4)
> -#define PL061_GPIO_PCELL_ID2 ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0xFF8)
> -#define PL061_GPIO_PCELL_ID3 ((UINT32)PcdGet32 (PcdPL061GpioBase)
> + 0xFFC)
> +#define PL061_GPIO_DATA_REG 0x000
> +#define PL061_GPIO_DIR_REG 0x400
> +#define PL061_GPIO_IS_REG 0x404
> +#define PL061_GPIO_IBE_REG 0x408
> +#define PL061_GPIO_IEV_REG 0x40C
> +#define PL061_GPIO_IE_REG 0x410
> +#define PL061_GPIO_RIS_REG 0x414
> +#define PL061_GPIO_MIS_REG 0x410
> +#define PL061_GPIO_IC_REG 0x41C
> +#define PL061_GPIO_AFSEL_REG 0x420
> +
> +#define PL061_GPIO_PERIPH_ID0 0xFE0
> +#define PL061_GPIO_PERIPH_ID1 0xFE4
> +#define PL061_GPIO_PERIPH_ID2 0xFE8
> +#define PL061_GPIO_PERIPH_ID3 0xFEC
> +
> +#define PL061_GPIO_PCELL_ID0 0xFF0
> +#define PL061_GPIO_PCELL_ID1 0xFF4
> +#define PL061_GPIO_PCELL_ID2 0xFF8
> +#define PL061_GPIO_PCELL_ID3 0xFFC
>
>
> // GPIO pins are numbered 0..7
> --
> 2.1.4
>
------------------------------------------------------------------------------
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel