]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPlatformPkg: Add PL061 GPIO driver
authoroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 11 Jun 2011 11:23:39 +0000 (11:23 +0000)
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 11 Jun 2011 11:23:39 +0000 (11:23 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11795 6f19259b-4bc3-4df7-8a09-765794883524

ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c [new file with mode: 0644]
ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf [new file with mode: 0644]
ArmPlatformPkg/Include/Drivers/PL061Gpio.h [new file with mode: 0644]

diff --git a/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c
new file mode 100644 (file)
index 0000000..0e263c0
--- /dev/null
@@ -0,0 +1,347 @@
+/** @file
+*
+*  Copyright (c) 2011, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+
+#include <Base.h>
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/IoLib.h>
+
+#include <Protocol/EmbeddedGpio.h>
+#include <ArmPlatform.h>
+#include <Drivers/PL061Gpio.h>
+
+#define LOW_4_BITS                              0x0000000F
+
+BOOLEAN     mPL061Initialized = FALSE;
+
+/**
+  Function implementations
+**/
+
+EFI_STATUS
+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;
+  }
+
+  // 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 ) & LOW_4_BITS ) != 0x04 )
+      || ( MmioRead8( PL061_GPIO_PERIPH_ID3 ) != 0x00 ) ) {
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PL061Initialize (
+VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  // Check if the PL061 GPIO module exists on board
+  Status = PL061Identify();
+  if (EFI_ERROR( Status )) {
+    Status = EFI_DEVICE_ERROR;
+    goto EXIT;
+  }
+
+  // Do other hardware initialisation things here as required
+
+  // Disable Interrupts
+  //if( MmioRead8( PL061_GPIO_IE_REG ) != 0 ) {
+  //   // Ensure interrupts are disabled
+  //}
+
+  mPL061Initialized = TRUE;
+
+  EXIT:
+  return Status;
+}
+
+/**
+
+Routine Description:
+
+  Gets the state of a GPIO pin
+
+Arguments:
+
+  This  - pointer to protocol
+  Gpio  - which pin to read
+  Value - state of the pin
+
+Returns:
+
+  EFI_SUCCESS           - GPIO state returned in Value
+  EFI_INVALID_PARAMETER - Value is NULL pointer or Gpio pin is out of range
+**/
+EFI_STATUS
+EFIAPI
+Get (
+  IN  EMBEDDED_GPIO     *This,
+  IN  EMBEDDED_GPIO_PIN Gpio,
+  OUT UINTN             *Value
+  )
+{
+  EFI_STATUS    Status = EFI_SUCCESS;
+
+  if(    ( Value == NULL )
+      || ( Gpio > LAST_GPIO_PIN ) )
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Initialize the hardware if not already done
+  if( !mPL061Initialized ) {
+    Status = PL061Initialize();
+    if( EFI_ERROR(Status) ) {
+      goto EXIT;
+    }
+  }
+
+  if( MmioRead8( PL061_GPIO_DATA_REG ) & GPIO_PIN_MASK_HIGH_8BIT(Gpio) ) {
+    *Value = 1;
+  } else {
+    *Value = 0;
+  }
+
+  EXIT:
+  return Status;
+}
+
+/**
+
+Routine Description:
+
+  Sets the state of a GPIO pin
+
+Arguments:
+
+  This  - pointer to protocol
+  Gpio  - which pin to modify
+  Mode  - mode to set
+
+Returns:
+
+  EFI_SUCCESS           - GPIO set as requested
+  EFI_UNSUPPORTED       - Mode is not supported
+  EFI_INVALID_PARAMETER - Gpio pin is out of range
+**/
+EFI_STATUS
+EFIAPI
+Set (
+  IN  EMBEDDED_GPIO       *This,
+  IN  EMBEDDED_GPIO_PIN   Gpio,
+  IN  EMBEDDED_GPIO_MODE  Mode
+  )
+{
+  EFI_STATUS    Status = EFI_SUCCESS;
+
+  // Check for errors
+  if( Gpio > LAST_GPIO_PIN ) {
+    Status = EFI_INVALID_PARAMETER;
+    goto EXIT;
+  }
+
+  // Initialize the hardware if not already done
+  if( !mPL061Initialized ) {
+    Status = PL061Initialize();
+    if( EFI_ERROR(Status) ) {
+      goto EXIT;
+    }
+  }
+
+  switch (Mode)
+  {
+    case GPIO_MODE_INPUT:
+      // Set the corresponding direction bit to LOW for input
+      MmioAnd8( PL061_GPIO_DIR_REG, GPIO_PIN_MASK_LOW_8BIT(Gpio) );
+      break;
+
+    case GPIO_MODE_OUTPUT_0:
+      // Set the corresponding data bit to LOW for 0
+      MmioAnd8( PL061_GPIO_DATA_REG, GPIO_PIN_MASK_LOW_8BIT(Gpio) );
+      // Set the corresponding direction bit to HIGH for output
+      MmioOr8( PL061_GPIO_DIR_REG, GPIO_PIN_MASK_HIGH_8BIT(Gpio) );
+      break;
+
+    case GPIO_MODE_OUTPUT_1:
+      // Set the corresponding data bit to HIGH for 1
+      MmioOr8( PL061_GPIO_DATA_REG, GPIO_PIN_MASK_HIGH_8BIT(Gpio) );
+      // Set the corresponding direction bit to HIGH for output
+      MmioOr8( PL061_GPIO_DIR_REG, GPIO_PIN_MASK_HIGH_8BIT(Gpio) );
+      break;
+
+    default:
+      // Other modes are not supported
+      return EFI_UNSUPPORTED;
+  }
+
+EXIT:
+  return Status;
+}
+
+/**
+
+Routine Description:
+
+  Gets the mode (function) of a GPIO pin
+
+Arguments:
+
+  This  - pointer to protocol
+  Gpio  - which pin
+  Mode  - pointer to output mode value
+
+Returns:
+
+  EFI_SUCCESS           - mode value retrieved
+  EFI_INVALID_PARAMETER - Mode is a null pointer or Gpio pin is out of range
+
+**/
+EFI_STATUS
+EFIAPI
+GetMode (
+  IN  EMBEDDED_GPIO       *This,
+  IN  EMBEDDED_GPIO_PIN   Gpio,
+  OUT EMBEDDED_GPIO_MODE  *Mode
+  )
+{
+  EFI_STATUS Status;
+
+  // Check for errors
+  if(    ( Mode == NULL )
+      || ( Gpio > LAST_GPIO_PIN ) ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Initialize the hardware if not already done
+  if( !mPL061Initialized ) {
+    Status = PL061Initialize();
+    if( EFI_ERROR(Status) ) {
+      return Status;
+    }
+  }
+
+  // Check if it is input or output
+  if( MmioRead8( PL061_GPIO_DIR_REG ) & GPIO_PIN_MASK_HIGH_8BIT(Gpio) ) {
+    // Pin set to output
+    if( MmioRead8( PL061_GPIO_DATA_REG ) & GPIO_PIN_MASK_HIGH_8BIT(Gpio) ) {
+      *Mode = GPIO_MODE_OUTPUT_1;
+    } else {
+      *Mode = GPIO_MODE_OUTPUT_0;
+    }
+  } else {
+    // Pin set to input
+    *Mode = GPIO_MODE_INPUT;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+Routine Description:
+
+  Sets the pull-up / pull-down resistor of a GPIO pin
+
+Arguments:
+
+  This  - pointer to protocol
+  Gpio  - which pin
+  Direction - pull-up, pull-down, or none
+
+Returns:
+
+  EFI_UNSUPPORTED - Can not perform the requested operation
+
+**/
+EFI_STATUS
+EFIAPI
+SetPull (
+  IN  EMBEDDED_GPIO       *This,
+  IN  EMBEDDED_GPIO_PIN   Gpio,
+  IN  EMBEDDED_GPIO_PULL  Direction
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+ Protocol variable definition
+ **/
+EMBEDDED_GPIO gGpio = {
+  Get,
+  Set,
+  GetMode,
+  SetPull
+};
+
+/**
+  Initialize the state information for the Embedded Gpio protocol.
+
+  @param  ImageHandle   of the loaded driver
+  @param  SystemTable   Pointer to the System Table
+
+  @retval EFI_SUCCESS           Protocol registered
+  @retval EFI_OUT_OF_RESOURCES  Cannot allocate protocol data structure
+  @retval EFI_DEVICE_ERROR      Hardware problems
+
+**/
+EFI_STATUS
+EFIAPI
+PL061InstallProtocol (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  EFI_HANDLE  Handle;
+
+  //
+  // Make sure the Gpio protocol has not been installed in the system yet.
+  //
+  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEmbeddedGpioProtocolGuid);
+
+  // Install the Embedded GPIO Protocol onto a new handle
+  Handle = NULL;
+  Status = gBS->InstallMultipleProtocolInterfaces(
+                  &Handle,
+                  &gEmbeddedGpioProtocolGuid, &gGpio,
+                  NULL
+                  );
+  if (EFI_ERROR(Status)) {
+    Status = EFI_OUT_OF_RESOURCES;
+  }
+
+  return Status;
+}
diff --git a/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf
new file mode 100644 (file)
index 0000000..53eebda
--- /dev/null
@@ -0,0 +1,49 @@
+/** @file
+*
+*  Copyright (c) 2011, ARM Limited. All rights reserved.
+*  
+*  This program and the accompanying materials                          
+*  are licensed and made available under the terms and conditions of the BSD License         
+*  which accompanies this distribution.  The full text of the license may be found at        
+*  http://opensource.org/licenses/bsd-license.php                                            
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+*
+**/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PL061GpioDxe
+  FILE_GUID                      = 5c1997d7-8d45-4f21-af3c-2206b8ed8bec
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = PL061InstallProtocol
+[Sources.common]
+  PL061Gpio.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  UefiRuntimeServicesTableLib
+  UefiLib
+  UefiBootServicesTableLib
+  BaseMemoryLib
+  DebugLib
+  UefiDriverEntryPoint
+  IoLib
+
+[Guids]
+
+[Protocols]
+  gEmbeddedGpioProtocolGuid  
+
+
+[Depex]
+TRUE
diff --git a/ArmPlatformPkg/Include/Drivers/PL061Gpio.h b/ArmPlatformPkg/Include/Drivers/PL061Gpio.h
new file mode 100644 (file)
index 0000000..4daabff
--- /dev/null
@@ -0,0 +1,56 @@
+/** @file\r
+*\r
+*  Copyright (c) 2011, ARM Limited. All rights reserved.\r
+*\r
+*  This program and the accompanying materials\r
+*  are licensed and made available under the terms and conditions of the BSD License\r
+*  which accompanies this distribution.  The full text of the license may be found at\r
+*  http://opensource.org/licenses/bsd-license.php\r
+*\r
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+*\r
+**/\r
+\r
+\r
+#ifndef __PL061_GPIO_H__\r
+#define __PL061_GPIO_H__\r
+\r
+#include <Base.h>\r
+#include <Protocol/EmbeddedGpio.h>\r
+#include <ArmPlatform.h>\r
+\r
+// SP805 Watchdog Registers\r
+#define PL061_GPIO_DATA_REG             (PL061_GPIO_BASE + 0x000)\r
+#define PL061_GPIO_DIR_REG              (PL061_GPIO_BASE + 0x400)\r
+#define PL061_GPIO_IS_REG               (PL061_GPIO_BASE + 0x404)\r
+#define PL061_GPIO_IBE_REG              (PL061_GPIO_BASE + 0x408)\r
+#define PL061_GPIO_IEV_REG              (PL061_GPIO_BASE + 0x40C)\r
+#define PL061_GPIO_IE_REG               (PL061_GPIO_BASE + 0x410)\r
+#define PL061_GPIO_RIS_REG              (PL061_GPIO_BASE + 0x414)\r
+#define PL061_GPIO_MIS_REG              (PL061_GPIO_BASE + 0x410)\r
+#define PL061_GPIO_IC_REG               (PL061_GPIO_BASE + 0x41C)\r
+#define PL061_GPIO_AFSEL_REG            (PL061_GPIO_BASE + 0x420)\r
+\r
+#define PL061_GPIO_PERIPH_ID0           (PL061_GPIO_BASE + 0xFE0)\r
+#define PL061_GPIO_PERIPH_ID1           (PL061_GPIO_BASE + 0xFE4)\r
+#define PL061_GPIO_PERIPH_ID2           (PL061_GPIO_BASE + 0xFE8)\r
+#define PL061_GPIO_PERIPH_ID3           (PL061_GPIO_BASE + 0xFEC)\r
+\r
+#define PL061_GPIO_PCELL_ID0            (PL061_GPIO_BASE + 0xFF0)\r
+#define PL061_GPIO_PCELL_ID1            (PL061_GPIO_BASE + 0xFF4)\r
+#define PL061_GPIO_PCELL_ID2            (PL061_GPIO_BASE + 0xFF8)\r
+#define PL061_GPIO_PCELL_ID3            (PL061_GPIO_BASE + 0xFFC)\r
+\r
+\r
+// GPIO pins are numbered 0..7\r
+#define LAST_GPIO_PIN                   7\r
+\r
+// All bits low except one bit high, native bit lenght\r
+#define GPIO_PIN_MASK(Pin)              (1UL << ((UINTN)(Pin)))\r
+// All bits low except one bit high, restricted to 8 bits (i.e. ensures zeros above 8bits)\r
+#define GPIO_PIN_MASK_HIGH_8BIT(Pin)    (GPIO_PIN_MASK(Pin) && 0xFF)\r
+// All bits high except one bit low, restricted to 8 bits (i.e. ensures zeros above 8bits)\r
+#define GPIO_PIN_MASK_LOW_8BIT(Pin)     ((~GPIO_PIN_MASK(Pin)) && 0xFF)\r
+\r
+#endif  // __PL061_GPIO_H__\r