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