3 * Copyright (c) 2011, ARM Limited. All rights reserved.
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #include <Library/BaseLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/BaseMemoryLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/UefiRuntimeServicesTableLib.h>
24 #include <Library/UefiLib.h>
25 #include <Library/IoLib.h>
27 #include <Protocol/EmbeddedGpio.h>
28 #include <ArmPlatform.h>
29 #include <Drivers/PL061Gpio.h>
31 #define LOW_4_BITS 0x0000000F
33 BOOLEAN mPL061Initialized
= FALSE
;
36 Function implementations
44 // Check if this is a PrimeCell Peripheral
45 if( ( MmioRead8( PL061_GPIO_PCELL_ID0
) != 0x0D )
46 || ( MmioRead8( PL061_GPIO_PCELL_ID1
) != 0xF0 )
47 || ( MmioRead8( PL061_GPIO_PCELL_ID2
) != 0x05 )
48 || ( MmioRead8( PL061_GPIO_PCELL_ID3
) != 0xB1 ) ) {
52 // Check if this PrimeCell Peripheral is the PL061 GPIO
53 if( ( MmioRead8( PL061_GPIO_PERIPH_ID0
) != 0x61 )
54 || ( MmioRead8( PL061_GPIO_PERIPH_ID1
) != 0x10 )
55 || ( ( MmioRead8( PL061_GPIO_PERIPH_ID2
) & LOW_4_BITS
) != 0x04 )
56 || ( MmioRead8( PL061_GPIO_PERIPH_ID3
) != 0x00 ) ) {
70 // Check if the PL061 GPIO module exists on board
71 Status
= PL061Identify();
72 if (EFI_ERROR( Status
)) {
73 Status
= EFI_DEVICE_ERROR
;
77 // Do other hardware initialisation things here as required
80 //if( MmioRead8( PL061_GPIO_IE_REG ) != 0 ) {
81 // // Ensure interrupts are disabled
84 mPL061Initialized
= TRUE
;
94 Gets the state of a GPIO pin
98 This - pointer to protocol
99 Gpio - which pin to read
100 Value - state of the pin
104 EFI_SUCCESS - GPIO state returned in Value
105 EFI_INVALID_PARAMETER - Value is NULL pointer or Gpio pin is out of range
110 IN EMBEDDED_GPIO
*This
,
111 IN EMBEDDED_GPIO_PIN Gpio
,
115 EFI_STATUS Status
= EFI_SUCCESS
;
117 if( ( Value
== NULL
)
118 || ( Gpio
> LAST_GPIO_PIN
) )
120 return EFI_INVALID_PARAMETER
;
123 // Initialize the hardware if not already done
124 if( !mPL061Initialized
) {
125 Status
= PL061Initialize();
126 if( EFI_ERROR(Status
) ) {
131 if( MmioRead8( PL061_GPIO_DATA_REG
) & GPIO_PIN_MASK_HIGH_8BIT(Gpio
) ) {
145 Sets the state of a GPIO pin
149 This - pointer to protocol
150 Gpio - which pin to modify
155 EFI_SUCCESS - GPIO set as requested
156 EFI_UNSUPPORTED - Mode is not supported
157 EFI_INVALID_PARAMETER - Gpio pin is out of range
162 IN EMBEDDED_GPIO
*This
,
163 IN EMBEDDED_GPIO_PIN Gpio
,
164 IN EMBEDDED_GPIO_MODE Mode
167 EFI_STATUS Status
= EFI_SUCCESS
;
170 if( Gpio
> LAST_GPIO_PIN
) {
171 Status
= EFI_INVALID_PARAMETER
;
175 // Initialize the hardware if not already done
176 if( !mPL061Initialized
) {
177 Status
= PL061Initialize();
178 if( EFI_ERROR(Status
) ) {
185 case GPIO_MODE_INPUT
:
186 // Set the corresponding direction bit to LOW for input
187 MmioAnd8( PL061_GPIO_DIR_REG
, GPIO_PIN_MASK_LOW_8BIT(Gpio
) );
190 case GPIO_MODE_OUTPUT_0
:
191 // Set the corresponding data bit to LOW for 0
192 MmioAnd8( PL061_GPIO_DATA_REG
, GPIO_PIN_MASK_LOW_8BIT(Gpio
) );
193 // Set the corresponding direction bit to HIGH for output
194 MmioOr8( PL061_GPIO_DIR_REG
, GPIO_PIN_MASK_HIGH_8BIT(Gpio
) );
197 case GPIO_MODE_OUTPUT_1
:
198 // Set the corresponding data bit to HIGH for 1
199 MmioOr8( PL061_GPIO_DATA_REG
, GPIO_PIN_MASK_HIGH_8BIT(Gpio
) );
200 // Set the corresponding direction bit to HIGH for output
201 MmioOr8( PL061_GPIO_DIR_REG
, GPIO_PIN_MASK_HIGH_8BIT(Gpio
) );
205 // Other modes are not supported
206 return EFI_UNSUPPORTED
;
217 Gets the mode (function) of a GPIO pin
221 This - pointer to protocol
223 Mode - pointer to output mode value
227 EFI_SUCCESS - mode value retrieved
228 EFI_INVALID_PARAMETER - Mode is a null pointer or Gpio pin is out of range
234 IN EMBEDDED_GPIO
*This
,
235 IN EMBEDDED_GPIO_PIN Gpio
,
236 OUT EMBEDDED_GPIO_MODE
*Mode
243 || ( Gpio
> LAST_GPIO_PIN
) ) {
244 return EFI_INVALID_PARAMETER
;
247 // Initialize the hardware if not already done
248 if( !mPL061Initialized
) {
249 Status
= PL061Initialize();
250 if( EFI_ERROR(Status
) ) {
255 // Check if it is input or output
256 if( MmioRead8( PL061_GPIO_DIR_REG
) & GPIO_PIN_MASK_HIGH_8BIT(Gpio
) ) {
258 if( MmioRead8( PL061_GPIO_DATA_REG
) & GPIO_PIN_MASK_HIGH_8BIT(Gpio
) ) {
259 *Mode
= GPIO_MODE_OUTPUT_1
;
261 *Mode
= GPIO_MODE_OUTPUT_0
;
265 *Mode
= GPIO_MODE_INPUT
;
275 Sets the pull-up / pull-down resistor of a GPIO pin
279 This - pointer to protocol
281 Direction - pull-up, pull-down, or none
285 EFI_UNSUPPORTED - Can not perform the requested operation
291 IN EMBEDDED_GPIO
*This
,
292 IN EMBEDDED_GPIO_PIN Gpio
,
293 IN EMBEDDED_GPIO_PULL Direction
296 return EFI_UNSUPPORTED
;
300 Protocol variable definition
302 EMBEDDED_GPIO gGpio
= {
310 Initialize the state information for the Embedded Gpio protocol.
312 @param ImageHandle of the loaded driver
313 @param SystemTable Pointer to the System Table
315 @retval EFI_SUCCESS Protocol registered
316 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
317 @retval EFI_DEVICE_ERROR Hardware problems
322 PL061InstallProtocol (
323 IN EFI_HANDLE ImageHandle
,
324 IN EFI_SYSTEM_TABLE
*SystemTable
331 // Make sure the Gpio protocol has not been installed in the system yet.
333 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL
, &gEmbeddedGpioProtocolGuid
);
335 // Install the Embedded GPIO Protocol onto a new handle
337 Status
= gBS
->InstallMultipleProtocolInterfaces(
339 &gEmbeddedGpioProtocolGuid
, &gGpio
,
342 if (EFI_ERROR(Status
)) {
343 Status
= EFI_OUT_OF_RESOURCES
;