#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/IoLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
#include <Library/PcdLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/UefiLib.h>\r
#include <Protocol/EmbeddedGpio.h>\r
#include <Drivers/PL061Gpio.h>\r
\r
+PLATFORM_GPIO_CONTROLLER *mPL061PlatformGpio;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PL061Locate (\r
+ IN EMBEDDED_GPIO_PIN Gpio,\r
+ OUT UINTN *ControllerIndex,\r
+ OUT UINTN *ControllerOffset,\r
+ OUT UINTN *RegisterBase\r
+ )\r
+{\r
+ UINT32 Index;\r
+\r
+ for (Index = 0; Index < mPL061PlatformGpio->GpioControllerCount; Index++) {\r
+ if ( (Gpio >= mPL061PlatformGpio->GpioController[Index].GpioIndex)\r
+ && (Gpio < mPL061PlatformGpio->GpioController[Index].GpioIndex\r
+ + mPL061PlatformGpio->GpioController[Index].InternalGpioCount)) {\r
+ *ControllerIndex = Index;\r
+ *ControllerOffset = Gpio % mPL061PlatformGpio->GpioController[Index].InternalGpioCount;\r
+ *RegisterBase = mPL061PlatformGpio->GpioController[Index].RegisterBase;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ DEBUG ((EFI_D_ERROR, "%a, failed to locate gpio %d\n", __func__, Gpio));\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
//\r
// The PL061 is a strange beast. The 8-bit data register is aliased across a\r
// region 0x400 bytes in size, with bits [9:2] of the address operating as a\r
VOID\r
)\r
{\r
- // Check if this is a PrimeCell Peripheral\r
- if ( (MmioRead8 (PL061_GPIO_PCELL_ID0) != 0x0D)\r
- || (MmioRead8 (PL061_GPIO_PCELL_ID1) != 0xF0)\r
- || (MmioRead8 (PL061_GPIO_PCELL_ID2) != 0x05)\r
- || (MmioRead8 (PL061_GPIO_PCELL_ID3) != 0xB1)) {\r
- return EFI_NOT_FOUND;\r
+ UINTN Index;\r
+ UINTN RegisterBase;\r
+\r
+ if ( (mPL061PlatformGpio->GpioCount == 0)\r
+ || (mPL061PlatformGpio->GpioControllerCount == 0)) {\r
+ return EFI_NOT_FOUND;\r
}\r
\r
- // Check if this PrimeCell Peripheral is the PL061 GPIO\r
- if ( (MmioRead8 (PL061_GPIO_PERIPH_ID0) != 0x61)\r
- || (MmioRead8 (PL061_GPIO_PERIPH_ID1) != 0x10)\r
- || ((MmioRead8 (PL061_GPIO_PERIPH_ID2) & 0xF) != 0x04)\r
- || (MmioRead8 (PL061_GPIO_PERIPH_ID3) != 0x00)) {\r
- return EFI_NOT_FOUND;\r
+ for (Index = 0; Index < mPL061PlatformGpio->GpioControllerCount; Index++) {\r
+ if (mPL061PlatformGpio->GpioController[Index].InternalGpioCount != PL061_GPIO_PINS) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ RegisterBase = mPL061PlatformGpio->GpioController[Index].RegisterBase;\r
+\r
+ // Check if this is a PrimeCell Peripheral\r
+ if ( (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID0) != 0x0D)\r
+ || (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID1) != 0xF0)\r
+ || (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID2) != 0x05)\r
+ || (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID3) != 0xB1)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ // Check if this PrimeCell Peripheral is the PL061 GPIO\r
+ if ( (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID0) != 0x61)\r
+ || (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID1) != 0x10)\r
+ || ((MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID2) & 0xF) != 0x04)\r
+ || (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID3) != 0x00)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
}\r
\r
return EFI_SUCCESS;\r
OUT UINTN *Value\r
)\r
{\r
- if ( (Value == NULL)\r
- || (Gpio > LAST_GPIO_PIN))\r
- {\r
+ EFI_STATUS Status = EFI_SUCCESS;\r
+ UINTN Index, Offset, RegisterBase;\r
+\r
+ Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if (Value == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (PL061GetPins (PL061_GPIO_DATA_REG, Gpio)) {\r
+ if (PL061GetPins (RegisterBase + PL061_GPIO_DATA_REG, Offset)) {\r
*Value = 1;\r
} else {\r
*Value = 0;\r
)\r
{\r
EFI_STATUS Status = EFI_SUCCESS;\r
+ UINTN Index, Offset, RegisterBase;\r
\r
- // Check for errors\r
- if (Gpio > LAST_GPIO_PIN) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto EXIT;\r
- }\r
+ Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase);\r
+ ASSERT_EFI_ERROR (Status);\r
\r
switch (Mode)\r
{\r
case GPIO_MODE_INPUT:\r
// Set the corresponding direction bit to LOW for input\r
- MmioAnd8 (PL061_GPIO_DIR_REG, ~GPIO_PIN_MASK(Gpio) & 0xFF);\r
+ MmioAnd8 (RegisterBase + PL061_GPIO_DIR_REG,\r
+ ~GPIO_PIN_MASK(Offset) & 0xFF);\r
break;\r
\r
case GPIO_MODE_OUTPUT_0:\r
// Set the corresponding direction bit to HIGH for output\r
- MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Gpio));\r
+ MmioOr8 (RegisterBase + PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Offset));\r
// Set the corresponding data bit to LOW for 0\r
- PL061SetPins (PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Gpio), 0);\r
+ PL061SetPins (RegisterBase + PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Offset), 0);\r
break;\r
\r
case GPIO_MODE_OUTPUT_1:\r
// Set the corresponding direction bit to HIGH for output\r
- MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Gpio));\r
+ MmioOr8 (RegisterBase + PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Offset));\r
// Set the corresponding data bit to HIGH for 1\r
- PL061SetPins (PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Gpio), 0xff);\r
- break;\r
+ PL061SetPins (RegisterBase + PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Offset), 0xff);\r
+ break;\r
\r
default:\r
// Other modes are not supported\r
return EFI_UNSUPPORTED;\r
}\r
\r
-EXIT:\r
- return Status;\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
OUT EMBEDDED_GPIO_MODE *Mode\r
)\r
{\r
+ EFI_STATUS Status = EFI_SUCCESS;\r
+ UINTN Index, Offset, RegisterBase;\r
+\r
+ Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
// Check for errors\r
- if ( (Mode == NULL)\r
- || (Gpio > LAST_GPIO_PIN)) {\r
+ if (Mode == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
// Check if it is input or output\r
- if (MmioRead8 (PL061_GPIO_DIR_REG) & GPIO_PIN_MASK(Gpio)) {\r
+ if (MmioRead8 (RegisterBase + PL061_GPIO_DIR_REG) & GPIO_PIN_MASK(Offset)) {\r
// Pin set to output\r
- if (PL061GetPins (PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Gpio))) {\r
+ if (PL061GetPins (RegisterBase + PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Offset))) {\r
*Mode = GPIO_MODE_OUTPUT_1;\r
} else {\r
*Mode = GPIO_MODE_OUTPUT_0;\r
IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_HANDLE Handle;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+ GPIO_CONTROLLER *GpioController;\r
\r
//\r
// Make sure the Gpio protocol has not been installed in the system yet.\r
//\r
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEmbeddedGpioProtocolGuid);\r
\r
+ Status = gBS->LocateProtocol (&gPlatformGpioProtocolGuid, NULL, (VOID **)&mPL061PlatformGpio);\r
+ if (EFI_ERROR (Status) && (Status == EFI_NOT_FOUND)) {\r
+ // Create the mPL061PlatformGpio\r
+ mPL061PlatformGpio = (PLATFORM_GPIO_CONTROLLER *)AllocateZeroPool (sizeof (PLATFORM_GPIO_CONTROLLER) + sizeof (GPIO_CONTROLLER));\r
+ if (mPL061PlatformGpio == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "%a: failed to allocate PLATFORM_GPIO_CONTROLLER\n", __func__));\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
+ mPL061PlatformGpio->GpioCount = PL061_GPIO_PINS;\r
+ mPL061PlatformGpio->GpioControllerCount = 1;\r
+ mPL061PlatformGpio->GpioController = (GPIO_CONTROLLER *)((UINTN) mPL061PlatformGpio + sizeof (PLATFORM_GPIO_CONTROLLER));\r
+\r
+ GpioController = mPL061PlatformGpio->GpioController;\r
+ GpioController->RegisterBase = (UINTN) PcdGet32 (PcdPL061GpioBase);\r
+ GpioController->GpioIndex = 0;\r
+ GpioController->InternalGpioCount = PL061_GPIO_PINS;\r
+ }\r
+\r
Status = PL061Identify();\r
if (EFI_ERROR(Status)) {\r
return EFI_DEVICE_ERROR;\r
\r
// PL061 GPIO Registers\r
#define PL061_GPIO_DATA_REG_OFFSET ((UINTN) 0x000)\r
-#define PL061_GPIO_DATA_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x000)\r
-#define PL061_GPIO_DIR_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x400)\r
-#define PL061_GPIO_IS_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x404)\r
-#define PL061_GPIO_IBE_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x408)\r
-#define PL061_GPIO_IEV_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x40C)\r
-#define PL061_GPIO_IE_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x410)\r
-#define PL061_GPIO_RIS_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x414)\r
-#define PL061_GPIO_MIS_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x410)\r
-#define PL061_GPIO_IC_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x41C)\r
-#define PL061_GPIO_AFSEL_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x420)\r
-\r
-#define PL061_GPIO_PERIPH_ID0 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFE0)\r
-#define PL061_GPIO_PERIPH_ID1 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFE4)\r
-#define PL061_GPIO_PERIPH_ID2 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFE8)\r
-#define PL061_GPIO_PERIPH_ID3 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFEC)\r
-\r
-#define PL061_GPIO_PCELL_ID0 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFF0)\r
-#define PL061_GPIO_PCELL_ID1 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFF4)\r
-#define PL061_GPIO_PCELL_ID2 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFF8)\r
-#define PL061_GPIO_PCELL_ID3 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFFC)\r
-\r
-\r
-// GPIO pins are numbered 0..7\r
-#define LAST_GPIO_PIN 7\r
+#define PL061_GPIO_DATA_REG 0x000\r
+#define PL061_GPIO_DIR_REG 0x400\r
+#define PL061_GPIO_IS_REG 0x404\r
+#define PL061_GPIO_IBE_REG 0x408\r
+#define PL061_GPIO_IEV_REG 0x40C\r
+#define PL061_GPIO_IE_REG 0x410\r
+#define PL061_GPIO_RIS_REG 0x414\r
+#define PL061_GPIO_MIS_REG 0x410\r
+#define PL061_GPIO_IC_REG 0x41C\r
+#define PL061_GPIO_AFSEL_REG 0x420\r
+\r
+#define PL061_GPIO_PERIPH_ID0 0xFE0\r
+#define PL061_GPIO_PERIPH_ID1 0xFE4\r
+#define PL061_GPIO_PERIPH_ID2 0xFE8\r
+#define PL061_GPIO_PERIPH_ID3 0xFEC\r
+\r
+#define PL061_GPIO_PCELL_ID0 0xFF0\r
+#define PL061_GPIO_PCELL_ID1 0xFF4\r
+#define PL061_GPIO_PCELL_ID2 0xFF8\r
+#define PL061_GPIO_PCELL_ID3 0xFFC\r
+\r
+#define PL061_GPIO_PINS 8\r
\r
// All bits low except one bit high, native bit length\r
#define GPIO_PIN_MASK(Pin) (1UL << ((UINTN)(Pin)))\r