Support multiple PL061 controllers.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhu...@linaro.org>
---
 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;
+
+  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;
+      *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);
+
   // 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
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
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to