]>
Commit | Line | Data |
---|---|---|
5a62a8b7 | 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 | } |