]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c
0e263c03a779f392ab721ad24fadad08c8d78a5c
[mirror_edk2.git] / ArmPlatformPkg / Drivers / PL061GpioDxe / PL061Gpio.c
1 /** @file
2 *
3 * Copyright (c) 2011, ARM Limited. All rights reserved.
4 *
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
9 *
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.
12 *
13 **/
14
15
16 #include <Base.h>
17 #include <PiDxe.h>
18
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>
26
27 #include <Protocol/EmbeddedGpio.h>
28 #include <ArmPlatform.h>
29 #include <Drivers/PL061Gpio.h>
30
31 #define LOW_4_BITS 0x0000000F
32
33 BOOLEAN mPL061Initialized = FALSE;
34
35 /**
36 Function implementations
37 **/
38
39 EFI_STATUS
40 PL061Identify (
41 VOID
42 )
43 {
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 ) ) {
49 return EFI_NOT_FOUND;
50 }
51
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 ) ) {
57 return EFI_NOT_FOUND;
58 }
59
60 return EFI_SUCCESS;
61 }
62
63 EFI_STATUS
64 PL061Initialize (
65 VOID
66 )
67 {
68 EFI_STATUS Status;
69
70 // Check if the PL061 GPIO module exists on board
71 Status = PL061Identify();
72 if (EFI_ERROR( Status )) {
73 Status = EFI_DEVICE_ERROR;
74 goto EXIT;
75 }
76
77 // Do other hardware initialisation things here as required
78
79 // Disable Interrupts
80 //if( MmioRead8( PL061_GPIO_IE_REG ) != 0 ) {
81 // // Ensure interrupts are disabled
82 //}
83
84 mPL061Initialized = TRUE;
85
86 EXIT:
87 return Status;
88 }
89
90 /**
91
92 Routine Description:
93
94 Gets the state of a GPIO pin
95
96 Arguments:
97
98 This - pointer to protocol
99 Gpio - which pin to read
100 Value - state of the pin
101
102 Returns:
103
104 EFI_SUCCESS - GPIO state returned in Value
105 EFI_INVALID_PARAMETER - Value is NULL pointer or Gpio pin is out of range
106 **/
107 EFI_STATUS
108 EFIAPI
109 Get (
110 IN EMBEDDED_GPIO *This,
111 IN EMBEDDED_GPIO_PIN Gpio,
112 OUT UINTN *Value
113 )
114 {
115 EFI_STATUS Status = EFI_SUCCESS;
116
117 if( ( Value == NULL )
118 || ( Gpio > LAST_GPIO_PIN ) )
119 {
120 return EFI_INVALID_PARAMETER;
121 }
122
123 // Initialize the hardware if not already done
124 if( !mPL061Initialized ) {
125 Status = PL061Initialize();
126 if( EFI_ERROR(Status) ) {
127 goto EXIT;
128 }
129 }
130
131 if( MmioRead8( PL061_GPIO_DATA_REG ) & GPIO_PIN_MASK_HIGH_8BIT(Gpio) ) {
132 *Value = 1;
133 } else {
134 *Value = 0;
135 }
136
137 EXIT:
138 return Status;
139 }
140
141 /**
142
143 Routine Description:
144
145 Sets the state of a GPIO pin
146
147 Arguments:
148
149 This - pointer to protocol
150 Gpio - which pin to modify
151 Mode - mode to set
152
153 Returns:
154
155 EFI_SUCCESS - GPIO set as requested
156 EFI_UNSUPPORTED - Mode is not supported
157 EFI_INVALID_PARAMETER - Gpio pin is out of range
158 **/
159 EFI_STATUS
160 EFIAPI
161 Set (
162 IN EMBEDDED_GPIO *This,
163 IN EMBEDDED_GPIO_PIN Gpio,
164 IN EMBEDDED_GPIO_MODE Mode
165 )
166 {
167 EFI_STATUS Status = EFI_SUCCESS;
168
169 // Check for errors
170 if( Gpio > LAST_GPIO_PIN ) {
171 Status = EFI_INVALID_PARAMETER;
172 goto EXIT;
173 }
174
175 // Initialize the hardware if not already done
176 if( !mPL061Initialized ) {
177 Status = PL061Initialize();
178 if( EFI_ERROR(Status) ) {
179 goto EXIT;
180 }
181 }
182
183 switch (Mode)
184 {
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) );
188 break;
189
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) );
195 break;
196
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) );
202 break;
203
204 default:
205 // Other modes are not supported
206 return EFI_UNSUPPORTED;
207 }
208
209 EXIT:
210 return Status;
211 }
212
213 /**
214
215 Routine Description:
216
217 Gets the mode (function) of a GPIO pin
218
219 Arguments:
220
221 This - pointer to protocol
222 Gpio - which pin
223 Mode - pointer to output mode value
224
225 Returns:
226
227 EFI_SUCCESS - mode value retrieved
228 EFI_INVALID_PARAMETER - Mode is a null pointer or Gpio pin is out of range
229
230 **/
231 EFI_STATUS
232 EFIAPI
233 GetMode (
234 IN EMBEDDED_GPIO *This,
235 IN EMBEDDED_GPIO_PIN Gpio,
236 OUT EMBEDDED_GPIO_MODE *Mode
237 )
238 {
239 EFI_STATUS Status;
240
241 // Check for errors
242 if( ( Mode == NULL )
243 || ( Gpio > LAST_GPIO_PIN ) ) {
244 return EFI_INVALID_PARAMETER;
245 }
246
247 // Initialize the hardware if not already done
248 if( !mPL061Initialized ) {
249 Status = PL061Initialize();
250 if( EFI_ERROR(Status) ) {
251 return Status;
252 }
253 }
254
255 // Check if it is input or output
256 if( MmioRead8( PL061_GPIO_DIR_REG ) & GPIO_PIN_MASK_HIGH_8BIT(Gpio) ) {
257 // Pin set to output
258 if( MmioRead8( PL061_GPIO_DATA_REG ) & GPIO_PIN_MASK_HIGH_8BIT(Gpio) ) {
259 *Mode = GPIO_MODE_OUTPUT_1;
260 } else {
261 *Mode = GPIO_MODE_OUTPUT_0;
262 }
263 } else {
264 // Pin set to input
265 *Mode = GPIO_MODE_INPUT;
266 }
267
268 return EFI_SUCCESS;
269 }
270
271 /**
272
273 Routine Description:
274
275 Sets the pull-up / pull-down resistor of a GPIO pin
276
277 Arguments:
278
279 This - pointer to protocol
280 Gpio - which pin
281 Direction - pull-up, pull-down, or none
282
283 Returns:
284
285 EFI_UNSUPPORTED - Can not perform the requested operation
286
287 **/
288 EFI_STATUS
289 EFIAPI
290 SetPull (
291 IN EMBEDDED_GPIO *This,
292 IN EMBEDDED_GPIO_PIN Gpio,
293 IN EMBEDDED_GPIO_PULL Direction
294 )
295 {
296 return EFI_UNSUPPORTED;
297 }
298
299 /**
300 Protocol variable definition
301 **/
302 EMBEDDED_GPIO gGpio = {
303 Get,
304 Set,
305 GetMode,
306 SetPull
307 };
308
309 /**
310 Initialize the state information for the Embedded Gpio protocol.
311
312 @param ImageHandle of the loaded driver
313 @param SystemTable Pointer to the System Table
314
315 @retval EFI_SUCCESS Protocol registered
316 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
317 @retval EFI_DEVICE_ERROR Hardware problems
318
319 **/
320 EFI_STATUS
321 EFIAPI
322 PL061InstallProtocol (
323 IN EFI_HANDLE ImageHandle,
324 IN EFI_SYSTEM_TABLE *SystemTable
325 )
326 {
327 EFI_STATUS Status;
328 EFI_HANDLE Handle;
329
330 //
331 // Make sure the Gpio protocol has not been installed in the system yet.
332 //
333 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEmbeddedGpioProtocolGuid);
334
335 // Install the Embedded GPIO Protocol onto a new handle
336 Handle = NULL;
337 Status = gBS->InstallMultipleProtocolInterfaces(
338 &Handle,
339 &gEmbeddedGpioProtocolGuid, &gGpio,
340 NULL
341 );
342 if (EFI_ERROR(Status)) {
343 Status = EFI_OUT_OF_RESOURCES;
344 }
345
346 return Status;
347 }