From 5a62a8b7f19019e7aa8d26d30ed7b7a22fc2a6d0 Mon Sep 17 00:00:00 2001 From: oliviermartin Date: Sat, 11 Jun 2011 11:23:39 +0000 Subject: ArmPlatformPkg: Add PL061 GPIO driver git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11795 6f19259b-4bc3-4df7-8a09-765794883524 --- ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c | 347 +++++++++++++++++++++ .../Drivers/PL061GpioDxe/PL061GpioDxe.inf | 49 +++ 2 files changed, 396 insertions(+) create mode 100644 ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c create mode 100644 ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf (limited to 'ArmPlatformPkg/Drivers') diff --git a/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c new file mode 100644 index 000000000..0e263c03a --- /dev/null +++ b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c @@ -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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 index 000000000..53eebdaec --- /dev/null +++ b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf @@ -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 -- cgit v1.2.3