3 * Copyright (c) 2011, ARM Limited. All rights reserved.
4 * Copyright (c) 2016, Linaro Limited. All rights reserved.
6 * This program and the accompanying materials
7 * are licensed and made available under the terms and conditions of the BSD
8 * License which accompanies this distribution. The full text of the license
9 * may be found at http://opensource.org/licenses/bsd-license.php
11 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #include <Library/BaseLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/IoLib.h>
23 #include <Library/PcdLib.h>
24 #include <Library/UefiBootServicesTableLib.h>
25 #include <Library/UefiLib.h>
26 #include <Library/UefiRuntimeServicesTableLib.h>
28 #include <Protocol/EmbeddedGpio.h>
29 #include <Drivers/PL061Gpio.h>
33 Function implementations
41 // Check if this is a PrimeCell Peripheral
42 if ( (MmioRead8 (PL061_GPIO_PCELL_ID0
) != 0x0D)
43 || (MmioRead8 (PL061_GPIO_PCELL_ID1
) != 0xF0)
44 || (MmioRead8 (PL061_GPIO_PCELL_ID2
) != 0x05)
45 || (MmioRead8 (PL061_GPIO_PCELL_ID3
) != 0xB1)) {
49 // Check if this PrimeCell Peripheral is the PL061 GPIO
50 if ( (MmioRead8 (PL061_GPIO_PERIPH_ID0
) != 0x61)
51 || (MmioRead8 (PL061_GPIO_PERIPH_ID1
) != 0x10)
52 || ((MmioRead8 (PL061_GPIO_PERIPH_ID2
) & 0xF) != 0x04)
53 || (MmioRead8 (PL061_GPIO_PERIPH_ID3
) != 0x00)) {
67 // Check if the PL061 GPIO module exists on board
68 Status
= PL061Identify();
69 if (EFI_ERROR (Status
)) {
70 Status
= EFI_DEVICE_ERROR
;
74 // Do other hardware initialisation things here as required
77 //if (MmioRead8 (PL061_GPIO_IE_REG) != 0) {
78 // // Ensure interrupts are disabled
89 Gets the state of a GPIO pin
93 This - pointer to protocol
94 Gpio - which pin to read
95 Value - state of the pin
99 EFI_SUCCESS - GPIO state returned in Value
100 EFI_INVALID_PARAMETER - Value is NULL pointer or Gpio pin is out of range
105 IN EMBEDDED_GPIO
*This
,
106 IN EMBEDDED_GPIO_PIN Gpio
,
111 || (Gpio
> LAST_GPIO_PIN
))
113 return EFI_INVALID_PARAMETER
;
116 if (MmioRead8 (PL061_GPIO_DATA_REG
) & GPIO_PIN_MASK_HIGH_8BIT(Gpio
)) {
129 Sets the state of a GPIO pin
133 This - pointer to protocol
134 Gpio - which pin to modify
139 EFI_SUCCESS - GPIO set as requested
140 EFI_UNSUPPORTED - Mode is not supported
141 EFI_INVALID_PARAMETER - Gpio pin is out of range
146 IN EMBEDDED_GPIO
*This
,
147 IN EMBEDDED_GPIO_PIN Gpio
,
148 IN EMBEDDED_GPIO_MODE Mode
151 EFI_STATUS Status
= EFI_SUCCESS
;
154 if (Gpio
> LAST_GPIO_PIN
) {
155 Status
= EFI_INVALID_PARAMETER
;
161 case GPIO_MODE_INPUT
:
162 // Set the corresponding direction bit to LOW for input
163 MmioAnd8 (PL061_GPIO_DIR_REG
, GPIO_PIN_MASK_LOW_8BIT(Gpio
));
166 case GPIO_MODE_OUTPUT_0
:
167 // Set the corresponding data bit to LOW for 0
168 MmioAnd8 (PL061_GPIO_DATA_REG
, GPIO_PIN_MASK_LOW_8BIT(Gpio
));
169 // Set the corresponding direction bit to HIGH for output
170 MmioOr8 (PL061_GPIO_DIR_REG
, GPIO_PIN_MASK_HIGH_8BIT(Gpio
));
173 case GPIO_MODE_OUTPUT_1
:
174 // Set the corresponding data bit to HIGH for 1
175 MmioOr8 (PL061_GPIO_DATA_REG
, GPIO_PIN_MASK_HIGH_8BIT(Gpio
));
176 // Set the corresponding direction bit to HIGH for output
177 MmioOr8 (PL061_GPIO_DIR_REG
, GPIO_PIN_MASK_HIGH_8BIT(Gpio
));
181 // Other modes are not supported
182 return EFI_UNSUPPORTED
;
193 Gets the mode (function) of a GPIO pin
197 This - pointer to protocol
199 Mode - pointer to output mode value
203 EFI_SUCCESS - mode value retrieved
204 EFI_INVALID_PARAMETER - Mode is a null pointer or Gpio pin is out of range
210 IN EMBEDDED_GPIO
*This
,
211 IN EMBEDDED_GPIO_PIN Gpio
,
212 OUT EMBEDDED_GPIO_MODE
*Mode
217 || (Gpio
> LAST_GPIO_PIN
)) {
218 return EFI_INVALID_PARAMETER
;
221 // Check if it is input or output
222 if (MmioRead8 (PL061_GPIO_DIR_REG
) & GPIO_PIN_MASK_HIGH_8BIT(Gpio
)) {
224 if (MmioRead8 (PL061_GPIO_DATA_REG
) & GPIO_PIN_MASK_HIGH_8BIT(Gpio
)) {
225 *Mode
= GPIO_MODE_OUTPUT_1
;
227 *Mode
= GPIO_MODE_OUTPUT_0
;
231 *Mode
= GPIO_MODE_INPUT
;
241 Sets the pull-up / pull-down resistor of a GPIO pin
245 This - pointer to protocol
247 Direction - pull-up, pull-down, or none
251 EFI_UNSUPPORTED - Can not perform the requested operation
257 IN EMBEDDED_GPIO
*This
,
258 IN EMBEDDED_GPIO_PIN Gpio
,
259 IN EMBEDDED_GPIO_PULL Direction
262 return EFI_UNSUPPORTED
;
266 Protocol variable definition
268 EMBEDDED_GPIO gGpio
= {
276 Initialize the state information for the Embedded Gpio protocol.
278 @param ImageHandle of the loaded driver
279 @param SystemTable Pointer to the System Table
281 @retval EFI_SUCCESS Protocol registered
282 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
283 @retval EFI_DEVICE_ERROR Hardware problems
288 PL061InstallProtocol (
289 IN EFI_HANDLE ImageHandle
,
290 IN EFI_SYSTEM_TABLE
*SystemTable
297 // Make sure the Gpio protocol has not been installed in the system yet.
299 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL
, &gEmbeddedGpioProtocolGuid
);
301 Status
= PL061Initialize();
302 if (EFI_ERROR(Status
)) {
303 return EFI_DEVICE_ERROR
;
306 // Install the Embedded GPIO Protocol onto a new handle
308 Status
= gBS
->InstallMultipleProtocolInterfaces(
310 &gEmbeddedGpioProtocolGuid
, &gGpio
,
313 if (EFI_ERROR(Status
)) {
314 Status
= EFI_OUT_OF_RESOURCES
;