]>
Commit | Line | Data |
---|---|---|
913cb9dc | 1 | /** @file\r |
2 | \r | |
78c2ffb5 | 3 | The EHCI register operation routines.\r |
4 | \r | |
16f69227 | 5 | Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>\r |
9d510e61 | 6 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
913cb9dc | 7 | \r |
913cb9dc | 8 | **/\r |
9 | \r | |
913cb9dc | 10 | #include "Ehci.h"\r |
11 | \r | |
913cb9dc | 12 | /**\r |
78c2ffb5 | 13 | Read EHCI capability register.\r |
913cb9dc | 14 | \r |
78c2ffb5 | 15 | @param Ehc The EHCI device.\r |
16 | @param Offset Capability register address.\r | |
913cb9dc | 17 | \r |
78c2ffb5 | 18 | @return The register content read.\r |
19 | @retval If err, return 0xffff.\r | |
913cb9dc | 20 | \r |
21 | **/\r | |
22 | UINT32\r | |
23 | EhcReadCapRegister (\r | |
1436aea4 MK |
24 | IN USB2_HC_DEV *Ehc,\r |
25 | IN UINT32 Offset\r | |
913cb9dc | 26 | )\r |
27 | {\r | |
1436aea4 MK |
28 | UINT32 Data;\r |
29 | EFI_STATUS Status;\r | |
913cb9dc | 30 | \r |
31 | Status = Ehc->PciIo->Mem.Read (\r | |
32 | Ehc->PciIo,\r | |
33 | EfiPciIoWidthUint32,\r | |
34 | EHC_BAR_INDEX,\r | |
1436aea4 | 35 | (UINT64)Offset,\r |
913cb9dc | 36 | 1,\r |
37 | &Data\r | |
38 | );\r | |
39 | \r | |
40 | if (EFI_ERROR (Status)) {\r | |
87000d77 | 41 | DEBUG ((DEBUG_ERROR, "EhcReadCapRegister: Pci Io read error - %r at %d\n", Status, Offset));\r |
913cb9dc | 42 | Data = 0xFFFF;\r |
43 | }\r | |
44 | \r | |
45 | return Data;\r | |
46 | }\r | |
47 | \r | |
09943f5e | 48 | /**\r |
49 | Read EHCI debug port register.\r | |
50 | \r | |
51 | @param Ehc The EHCI device.\r | |
52 | @param Offset Debug port register offset.\r | |
53 | \r | |
54 | @return The register content read.\r | |
55 | @retval If err, return 0xffff.\r | |
56 | \r | |
57 | **/\r | |
58 | UINT32\r | |
59 | EhcReadDbgRegister (\r | |
1436aea4 MK |
60 | IN CONST USB2_HC_DEV *Ehc,\r |
61 | IN UINT32 Offset\r | |
09943f5e | 62 | )\r |
63 | {\r | |
1436aea4 MK |
64 | UINT32 Data;\r |
65 | EFI_STATUS Status;\r | |
09943f5e | 66 | \r |
67 | Status = Ehc->PciIo->Mem.Read (\r | |
68 | Ehc->PciIo,\r | |
69 | EfiPciIoWidthUint32,\r | |
70 | Ehc->DebugPortBarNum,\r | |
16f69227 | 71 | Ehc->DebugPortOffset + Offset,\r |
09943f5e | 72 | 1,\r |
73 | &Data\r | |
74 | );\r | |
75 | \r | |
76 | if (EFI_ERROR (Status)) {\r | |
87000d77 | 77 | DEBUG ((DEBUG_ERROR, "EhcReadDbgRegister: Pci Io read error - %r at %d\n", Status, Offset));\r |
09943f5e | 78 | Data = 0xFFFF;\r |
79 | }\r | |
80 | \r | |
81 | return Data;\r | |
82 | }\r | |
83 | \r | |
b48ec0e8 LE |
84 | /**\r |
85 | Check whether the host controller has an in-use debug port.\r | |
86 | \r | |
87 | @param[in] Ehc The Enhanced Host Controller to query.\r | |
88 | \r | |
89 | @param[in] PortNumber If PortNumber is not NULL, then query whether\r | |
90 | PortNumber is an in-use debug port on Ehc. (PortNumber\r | |
91 | is taken in UEFI notation, i.e., zero-based.)\r | |
92 | Otherwise, query whether Ehc has any in-use debug\r | |
93 | port.\r | |
94 | \r | |
95 | @retval TRUE PortNumber is an in-use debug port on Ehc (if PortNumber is\r | |
96 | not NULL), or some port on Ehc is an in-use debug port\r | |
97 | (otherwise).\r | |
98 | \r | |
99 | @retval FALSE PortNumber is not an in-use debug port on Ehc (if PortNumber\r | |
100 | is not NULL), or no port on Ehc is an in-use debug port\r | |
101 | (otherwise).\r | |
102 | **/\r | |
103 | BOOLEAN\r | |
104 | EhcIsDebugPortInUse (\r | |
1436aea4 MK |
105 | IN CONST USB2_HC_DEV *Ehc,\r |
106 | IN CONST UINT8 *PortNumber OPTIONAL\r | |
b48ec0e8 LE |
107 | )\r |
108 | {\r | |
1436aea4 | 109 | UINT32 State;\r |
b48ec0e8 LE |
110 | \r |
111 | if (Ehc->DebugPortNum == 0) {\r | |
112 | //\r | |
113 | // The host controller has no debug port.\r | |
114 | //\r | |
115 | return FALSE;\r | |
116 | }\r | |
117 | \r | |
118 | //\r | |
119 | // The Debug Port Number field in HCSPARAMS is one-based.\r | |
120 | //\r | |
1436aea4 | 121 | if ((PortNumber != NULL) && (*PortNumber != Ehc->DebugPortNum - 1)) {\r |
b48ec0e8 LE |
122 | //\r |
123 | // The caller specified a port, but it's not the debug port of the host\r | |
124 | // controller.\r | |
125 | //\r | |
126 | return FALSE;\r | |
127 | }\r | |
128 | \r | |
129 | //\r | |
130 | // Deduce usage from the Control Register.\r | |
131 | //\r | |
1436aea4 | 132 | State = EhcReadDbgRegister (Ehc, 0);\r |
b48ec0e8 LE |
133 | return (State & USB_DEBUG_PORT_IN_USE_MASK) == USB_DEBUG_PORT_IN_USE_MASK;\r |
134 | }\r | |
135 | \r | |
913cb9dc | 136 | /**\r |
78c2ffb5 | 137 | Read EHCI Operation register.\r |
913cb9dc | 138 | \r |
78c2ffb5 | 139 | @param Ehc The EHCI device.\r |
140 | @param Offset The operation register offset.\r | |
913cb9dc | 141 | \r |
78c2ffb5 | 142 | @return The register content read.\r |
143 | @retval If err, return 0xffff.\r | |
913cb9dc | 144 | \r |
145 | **/\r | |
146 | UINT32\r | |
147 | EhcReadOpReg (\r | |
1436aea4 MK |
148 | IN USB2_HC_DEV *Ehc,\r |
149 | IN UINT32 Offset\r | |
913cb9dc | 150 | )\r |
151 | {\r | |
1436aea4 MK |
152 | UINT32 Data;\r |
153 | EFI_STATUS Status;\r | |
913cb9dc | 154 | \r |
155 | ASSERT (Ehc->CapLen != 0);\r | |
156 | \r | |
157 | Status = Ehc->PciIo->Mem.Read (\r | |
158 | Ehc->PciIo,\r | |
159 | EfiPciIoWidthUint32,\r | |
160 | EHC_BAR_INDEX,\r | |
16f69227 | 161 | Ehc->CapLen + Offset,\r |
913cb9dc | 162 | 1,\r |
163 | &Data\r | |
164 | );\r | |
165 | \r | |
166 | if (EFI_ERROR (Status)) {\r | |
87000d77 | 167 | DEBUG ((DEBUG_ERROR, "EhcReadOpReg: Pci Io Read error - %r at %d\n", Status, Offset));\r |
913cb9dc | 168 | Data = 0xFFFF;\r |
169 | }\r | |
170 | \r | |
171 | return Data;\r | |
172 | }\r | |
173 | \r | |
913cb9dc | 174 | /**\r |
78c2ffb5 | 175 | Write the data to the EHCI operation register.\r |
913cb9dc | 176 | \r |
78c2ffb5 | 177 | @param Ehc The EHCI device.\r |
178 | @param Offset EHCI operation register offset.\r | |
179 | @param Data The data to write.\r | |
913cb9dc | 180 | \r |
913cb9dc | 181 | **/\r |
182 | VOID\r | |
183 | EhcWriteOpReg (\r | |
1436aea4 MK |
184 | IN USB2_HC_DEV *Ehc,\r |
185 | IN UINT32 Offset,\r | |
186 | IN UINT32 Data\r | |
913cb9dc | 187 | )\r |
188 | {\r | |
1436aea4 | 189 | EFI_STATUS Status;\r |
913cb9dc | 190 | \r |
191 | ASSERT (Ehc->CapLen != 0);\r | |
192 | \r | |
193 | Status = Ehc->PciIo->Mem.Write (\r | |
194 | Ehc->PciIo,\r | |
195 | EfiPciIoWidthUint32,\r | |
196 | EHC_BAR_INDEX,\r | |
16f69227 | 197 | Ehc->CapLen + Offset,\r |
913cb9dc | 198 | 1,\r |
199 | &Data\r | |
200 | );\r | |
201 | \r | |
202 | if (EFI_ERROR (Status)) {\r | |
87000d77 | 203 | DEBUG ((DEBUG_ERROR, "EhcWriteOpReg: Pci Io Write error: %r at %d\n", Status, Offset));\r |
913cb9dc | 204 | }\r |
205 | }\r | |
206 | \r | |
913cb9dc | 207 | /**\r |
78c2ffb5 | 208 | Set one bit of the operational register while keeping other bits.\r |
913cb9dc | 209 | \r |
78c2ffb5 | 210 | @param Ehc The EHCI device.\r |
211 | @param Offset The offset of the operational register.\r | |
212 | @param Bit The bit mask of the register to set.\r | |
913cb9dc | 213 | \r |
913cb9dc | 214 | **/\r |
913cb9dc | 215 | VOID\r |
216 | EhcSetOpRegBit (\r | |
1436aea4 MK |
217 | IN USB2_HC_DEV *Ehc,\r |
218 | IN UINT32 Offset,\r | |
219 | IN UINT32 Bit\r | |
913cb9dc | 220 | )\r |
221 | {\r | |
1436aea4 | 222 | UINT32 Data;\r |
913cb9dc | 223 | \r |
224 | Data = EhcReadOpReg (Ehc, Offset);\r | |
225 | Data |= Bit;\r | |
226 | EhcWriteOpReg (Ehc, Offset, Data);\r | |
227 | }\r | |
228 | \r | |
913cb9dc | 229 | /**\r |
78c2ffb5 | 230 | Clear one bit of the operational register while keeping other bits.\r |
913cb9dc | 231 | \r |
78c2ffb5 | 232 | @param Ehc The EHCI device.\r |
233 | @param Offset The offset of the operational register.\r | |
234 | @param Bit The bit mask of the register to clear.\r | |
913cb9dc | 235 | \r |
913cb9dc | 236 | **/\r |
913cb9dc | 237 | VOID\r |
238 | EhcClearOpRegBit (\r | |
1436aea4 MK |
239 | IN USB2_HC_DEV *Ehc,\r |
240 | IN UINT32 Offset,\r | |
241 | IN UINT32 Bit\r | |
913cb9dc | 242 | )\r |
243 | {\r | |
1436aea4 | 244 | UINT32 Data;\r |
913cb9dc | 245 | \r |
246 | Data = EhcReadOpReg (Ehc, Offset);\r | |
247 | Data &= ~Bit;\r | |
248 | EhcWriteOpReg (Ehc, Offset, Data);\r | |
249 | }\r | |
250 | \r | |
913cb9dc | 251 | /**\r |
252 | Wait the operation register's bit as specified by Bit\r | |
78c2ffb5 | 253 | to become set (or clear).\r |
913cb9dc | 254 | \r |
78c2ffb5 | 255 | @param Ehc The EHCI device.\r |
256 | @param Offset The offset of the operation register.\r | |
257 | @param Bit The bit of the register to wait for.\r | |
258 | @param WaitToSet Wait the bit to set or clear.\r | |
259 | @param Timeout The time to wait before abort (in millisecond).\r | |
913cb9dc | 260 | \r |
78c2ffb5 | 261 | @retval EFI_SUCCESS The bit successfully changed by host controller.\r |
262 | @retval EFI_TIMEOUT The time out occurred.\r | |
913cb9dc | 263 | \r |
264 | **/\r | |
913cb9dc | 265 | EFI_STATUS\r |
266 | EhcWaitOpRegBit (\r | |
1436aea4 MK |
267 | IN USB2_HC_DEV *Ehc,\r |
268 | IN UINT32 Offset,\r | |
269 | IN UINT32 Bit,\r | |
270 | IN BOOLEAN WaitToSet,\r | |
271 | IN UINT32 Timeout\r | |
913cb9dc | 272 | )\r |
273 | {\r | |
1436aea4 | 274 | UINT32 Index;\r |
913cb9dc | 275 | \r |
41e8ff27 | 276 | for (Index = 0; Index < Timeout / EHC_SYNC_POLL_INTERVAL + 1; Index++) {\r |
913cb9dc | 277 | if (EHC_REG_BIT_IS_SET (Ehc, Offset, Bit) == WaitToSet) {\r |
278 | return EFI_SUCCESS;\r | |
279 | }\r | |
280 | \r | |
41e8ff27 | 281 | gBS->Stall (EHC_SYNC_POLL_INTERVAL);\r |
913cb9dc | 282 | }\r |
283 | \r | |
284 | return EFI_TIMEOUT;\r | |
285 | }\r | |
286 | \r | |
913cb9dc | 287 | /**\r |
288 | Add support for UEFI Over Legacy (UoL) feature, stop\r | |
78c2ffb5 | 289 | the legacy USB SMI support.\r |
913cb9dc | 290 | \r |
291 | @param Ehc The EHCI device.\r | |
292 | \r | |
913cb9dc | 293 | **/\r |
294 | VOID\r | |
295 | EhcClearLegacySupport (\r | |
1436aea4 | 296 | IN USB2_HC_DEV *Ehc\r |
913cb9dc | 297 | )\r |
298 | {\r | |
1436aea4 MK |
299 | UINT32 ExtendCap;\r |
300 | EFI_PCI_IO_PROTOCOL *PciIo;\r | |
301 | UINT32 Value;\r | |
302 | UINT32 TimeOut;\r | |
913cb9dc | 303 | \r |
87000d77 | 304 | DEBUG ((DEBUG_INFO, "EhcClearLegacySupport: called to clear legacy support\n"));\r |
913cb9dc | 305 | \r |
306 | PciIo = Ehc->PciIo;\r | |
307 | ExtendCap = (Ehc->HcCapParams >> 8) & 0xFF;\r | |
308 | \r | |
309 | PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);\r | |
310 | PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);\r | |
311 | \r | |
312 | PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);\r | |
313 | Value |= (0x1 << 24);\r | |
314 | PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);\r | |
315 | \r | |
316 | TimeOut = 40;\r | |
78c2ffb5 | 317 | while (TimeOut-- != 0) {\r |
913cb9dc | 318 | gBS->Stall (500);\r |
319 | \r | |
320 | PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);\r | |
321 | \r | |
322 | if ((Value & 0x01010000) == 0x01000000) {\r | |
323 | break;\r | |
324 | }\r | |
325 | }\r | |
326 | \r | |
327 | PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);\r | |
328 | PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);\r | |
329 | }\r | |
330 | \r | |
913cb9dc | 331 | /**\r |
332 | Set door bell and wait it to be ACKed by host controller.\r | |
333 | This function is used to synchronize with the hardware.\r | |
334 | \r | |
78c2ffb5 | 335 | @param Ehc The EHCI device.\r |
336 | @param Timeout The time to wait before abort (in millisecond, ms).\r | |
913cb9dc | 337 | \r |
78c2ffb5 | 338 | @retval EFI_SUCCESS Synchronized with the hardware.\r |
339 | @retval EFI_TIMEOUT Time out happened while waiting door bell to set.\r | |
913cb9dc | 340 | \r |
341 | **/\r | |
342 | EFI_STATUS\r | |
343 | EhcSetAndWaitDoorBell (\r | |
1436aea4 MK |
344 | IN USB2_HC_DEV *Ehc,\r |
345 | IN UINT32 Timeout\r | |
913cb9dc | 346 | )\r |
347 | {\r | |
1436aea4 MK |
348 | EFI_STATUS Status;\r |
349 | UINT32 Data;\r | |
913cb9dc | 350 | \r |
351 | EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_IAAD);\r | |
352 | \r | |
353 | Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_IAA, TRUE, Timeout);\r | |
354 | \r | |
355 | //\r | |
356 | // ACK the IAA bit in USBSTS register. Make sure other\r | |
357 | // interrupt bits are not ACKed. These bits are WC (Write Clean).\r | |
358 | //\r | |
359 | Data = EhcReadOpReg (Ehc, EHC_USBSTS_OFFSET);\r | |
360 | Data &= ~USBSTS_INTACK_MASK;\r | |
361 | Data |= USBSTS_IAA;\r | |
362 | \r | |
363 | EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, Data);\r | |
364 | \r | |
365 | return Status;\r | |
366 | }\r | |
367 | \r | |
913cb9dc | 368 | /**\r |
369 | Clear all the interrutp status bits, these bits\r | |
78c2ffb5 | 370 | are Write-Clean.\r |
913cb9dc | 371 | \r |
78c2ffb5 | 372 | @param Ehc The EHCI device.\r |
913cb9dc | 373 | \r |
913cb9dc | 374 | **/\r |
375 | VOID\r | |
376 | EhcAckAllInterrupt (\r | |
1436aea4 | 377 | IN USB2_HC_DEV *Ehc\r |
913cb9dc | 378 | )\r |
379 | {\r | |
380 | EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, USBSTS_INTACK_MASK);\r | |
381 | }\r | |
382 | \r | |
913cb9dc | 383 | /**\r |
384 | Enable the periodic schedule then wait EHC to\r | |
385 | actually enable it.\r | |
386 | \r | |
78c2ffb5 | 387 | @param Ehc The EHCI device.\r |
388 | @param Timeout The time to wait before abort (in millisecond, ms).\r | |
913cb9dc | 389 | \r |
78c2ffb5 | 390 | @retval EFI_SUCCESS The periodical schedule is enabled.\r |
391 | @retval EFI_TIMEOUT Time out happened while enabling periodic schedule.\r | |
913cb9dc | 392 | \r |
393 | **/\r | |
913cb9dc | 394 | EFI_STATUS\r |
395 | EhcEnablePeriodSchd (\r | |
1436aea4 MK |
396 | IN USB2_HC_DEV *Ehc,\r |
397 | IN UINT32 Timeout\r | |
913cb9dc | 398 | )\r |
399 | {\r | |
1436aea4 | 400 | EFI_STATUS Status;\r |
913cb9dc | 401 | \r |
402 | EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_PERIOD);\r | |
403 | \r | |
404 | Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_PERIOD_ENABLED, TRUE, Timeout);\r | |
405 | return Status;\r | |
406 | }\r | |
407 | \r | |
913cb9dc | 408 | /**\r |
78c2ffb5 | 409 | Enable asynchrounous schedule.\r |
913cb9dc | 410 | \r |
78c2ffb5 | 411 | @param Ehc The EHCI device.\r |
412 | @param Timeout Time to wait before abort.\r | |
913cb9dc | 413 | \r |
78c2ffb5 | 414 | @retval EFI_SUCCESS The EHCI asynchronous schedule is enabled.\r |
415 | @return Others Failed to enable the asynchronous scheudle.\r | |
913cb9dc | 416 | \r |
417 | **/\r | |
913cb9dc | 418 | EFI_STATUS\r |
419 | EhcEnableAsyncSchd (\r | |
1436aea4 MK |
420 | IN USB2_HC_DEV *Ehc,\r |
421 | IN UINT32 Timeout\r | |
913cb9dc | 422 | )\r |
423 | {\r | |
1436aea4 | 424 | EFI_STATUS Status;\r |
913cb9dc | 425 | \r |
426 | EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_ASYNC);\r | |
427 | \r | |
428 | Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_ASYNC_ENABLED, TRUE, Timeout);\r | |
429 | return Status;\r | |
430 | }\r | |
431 | \r | |
913cb9dc | 432 | /**\r |
78c2ffb5 | 433 | Whether Ehc is halted.\r |
913cb9dc | 434 | \r |
78c2ffb5 | 435 | @param Ehc The EHCI device.\r |
913cb9dc | 436 | \r |
78c2ffb5 | 437 | @retval TRUE The controller is halted.\r |
438 | @retval FALSE It isn't halted.\r | |
913cb9dc | 439 | \r |
440 | **/\r | |
441 | BOOLEAN\r | |
442 | EhcIsHalt (\r | |
1436aea4 | 443 | IN USB2_HC_DEV *Ehc\r |
913cb9dc | 444 | )\r |
445 | {\r | |
446 | return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT);\r | |
447 | }\r | |
448 | \r | |
913cb9dc | 449 | /**\r |
78c2ffb5 | 450 | Whether system error occurred.\r |
913cb9dc | 451 | \r |
78c2ffb5 | 452 | @param Ehc The EHCI device.\r |
913cb9dc | 453 | \r |
78c2ffb5 | 454 | @return TRUE System error happened.\r |
455 | @return FALSE No system error.\r | |
913cb9dc | 456 | \r |
457 | **/\r | |
458 | BOOLEAN\r | |
459 | EhcIsSysError (\r | |
1436aea4 | 460 | IN USB2_HC_DEV *Ehc\r |
913cb9dc | 461 | )\r |
462 | {\r | |
463 | return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR);\r | |
464 | }\r | |
465 | \r | |
913cb9dc | 466 | /**\r |
78c2ffb5 | 467 | Reset the host controller.\r |
913cb9dc | 468 | \r |
78c2ffb5 | 469 | @param Ehc The EHCI device.\r |
470 | @param Timeout Time to wait before abort (in millisecond, ms).\r | |
913cb9dc | 471 | \r |
78c2ffb5 | 472 | @retval EFI_SUCCESS The host controller is reset.\r |
473 | @return Others Failed to reset the host.\r | |
913cb9dc | 474 | \r |
475 | **/\r | |
476 | EFI_STATUS\r | |
477 | EhcResetHC (\r | |
1436aea4 MK |
478 | IN USB2_HC_DEV *Ehc,\r |
479 | IN UINT32 Timeout\r | |
913cb9dc | 480 | )\r |
481 | {\r | |
1436aea4 | 482 | EFI_STATUS Status;\r |
913cb9dc | 483 | \r |
484 | //\r | |
485 | // Host can only be reset when it is halt. If not so, halt it\r | |
486 | //\r | |
487 | if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {\r | |
488 | Status = EhcHaltHC (Ehc, Timeout);\r | |
489 | \r | |
490 | if (EFI_ERROR (Status)) {\r | |
491 | return Status;\r | |
492 | }\r | |
493 | }\r | |
494 | \r | |
495 | EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET);\r | |
496 | Status = EhcWaitOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET, FALSE, Timeout);\r | |
497 | return Status;\r | |
498 | }\r | |
499 | \r | |
913cb9dc | 500 | /**\r |
78c2ffb5 | 501 | Halt the host controller.\r |
913cb9dc | 502 | \r |
78c2ffb5 | 503 | @param Ehc The EHCI device.\r |
504 | @param Timeout Time to wait before abort.\r | |
913cb9dc | 505 | \r |
78c2ffb5 | 506 | @retval EFI_SUCCESS The EHCI is halt.\r |
507 | @retval EFI_TIMEOUT Failed to halt the controller before Timeout.\r | |
913cb9dc | 508 | \r |
509 | **/\r | |
510 | EFI_STATUS\r | |
511 | EhcHaltHC (\r | |
1436aea4 MK |
512 | IN USB2_HC_DEV *Ehc,\r |
513 | IN UINT32 Timeout\r | |
913cb9dc | 514 | )\r |
515 | {\r | |
1436aea4 | 516 | EFI_STATUS Status;\r |
913cb9dc | 517 | \r |
518 | EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);\r | |
519 | Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, TRUE, Timeout);\r | |
520 | return Status;\r | |
521 | }\r | |
522 | \r | |
913cb9dc | 523 | /**\r |
78c2ffb5 | 524 | Set the EHCI to run.\r |
913cb9dc | 525 | \r |
78c2ffb5 | 526 | @param Ehc The EHCI device.\r |
527 | @param Timeout Time to wait before abort.\r | |
913cb9dc | 528 | \r |
78c2ffb5 | 529 | @retval EFI_SUCCESS The EHCI is running.\r |
530 | @return Others Failed to set the EHCI to run.\r | |
913cb9dc | 531 | \r |
532 | **/\r | |
533 | EFI_STATUS\r | |
534 | EhcRunHC (\r | |
1436aea4 MK |
535 | IN USB2_HC_DEV *Ehc,\r |
536 | IN UINT32 Timeout\r | |
913cb9dc | 537 | )\r |
538 | {\r | |
1436aea4 | 539 | EFI_STATUS Status;\r |
913cb9dc | 540 | \r |
541 | EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);\r | |
542 | Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, FALSE, Timeout);\r | |
543 | return Status;\r | |
544 | }\r | |
545 | \r | |
913cb9dc | 546 | /**\r |
547 | Initialize the HC hardware.\r | |
78c2ffb5 | 548 | EHCI spec lists the five things to do to initialize the hardware:\r |
913cb9dc | 549 | 1. Program CTRLDSSEGMENT\r |
550 | 2. Set USBINTR to enable interrupts\r | |
551 | 3. Set periodic list base\r | |
552 | 4. Set USBCMD, interrupt threshold, frame list size etc\r | |
553 | 5. Write 1 to CONFIGFLAG to route all ports to EHCI\r | |
554 | \r | |
78c2ffb5 | 555 | @param Ehc The EHCI device.\r |
913cb9dc | 556 | \r |
78c2ffb5 | 557 | @return EFI_SUCCESS The EHCI has come out of halt state.\r |
558 | @return EFI_TIMEOUT Time out happened.\r | |
913cb9dc | 559 | \r |
560 | **/\r | |
561 | EFI_STATUS\r | |
562 | EhcInitHC (\r | |
1436aea4 | 563 | IN USB2_HC_DEV *Ehc\r |
913cb9dc | 564 | )\r |
565 | {\r | |
1436aea4 MK |
566 | EFI_STATUS Status;\r |
567 | UINT32 Index;\r | |
568 | UINT32 RegVal;\r | |
913cb9dc | 569 | \r |
f147a39e A |
570 | // This ASSERT crashes the BeagleBoard. There is some issue in the USB stack.\r |
571 | // This ASSERT needs to be removed so the BeagleBoard will boot. When we fix\r | |
572 | // the USB stack we can put this ASSERT back in\r | |
573 | // ASSERT (EhcIsHalt (Ehc));\r | |
913cb9dc | 574 | \r |
575 | //\r | |
576 | // Allocate the periodic frame and associated memeory\r | |
577 | // management facilities if not already done.\r | |
578 | //\r | |
592b87a4 | 579 | if (Ehc->PeriodFrame != NULL) {\r |
913cb9dc | 580 | EhcFreeSched (Ehc);\r |
581 | }\r | |
582 | \r | |
583 | Status = EhcInitSched (Ehc);\r | |
584 | \r | |
585 | if (EFI_ERROR (Status)) {\r | |
586 | return Status;\r | |
587 | }\r | |
913cb9dc | 588 | \r |
589 | //\r | |
592b87a4 | 590 | // 1. Clear USBINTR to disable all the interrupt. UEFI works by polling\r |
913cb9dc | 591 | //\r |
592 | EhcWriteOpReg (Ehc, EHC_USBINTR_OFFSET, 0);\r | |
593 | \r | |
594 | //\r | |
f01219e8 | 595 | // 2. Start the Host Controller\r |
913cb9dc | 596 | //\r |
597 | EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);\r | |
598 | \r | |
599 | //\r | |
f01219e8 | 600 | // 3. Power up all ports if EHCI has Port Power Control (PPC) support\r |
913cb9dc | 601 | //\r |
f01219e8 | 602 | if (Ehc->HcStructParams & HCSP_PPC) {\r |
1436aea4 | 603 | for (Index = 0; Index < (UINT8)(Ehc->HcStructParams & HCSP_NPORTS); Index++) {\r |
d9077743 FT |
604 | //\r |
605 | // Do not clear port status bits on initialization. Otherwise devices will\r | |
606 | // not enumerate properly at startup.\r | |
607 | //\r | |
1436aea4 | 608 | RegVal = EhcReadOpReg (Ehc, (UINT32)(EHC_PORT_STAT_OFFSET + (4 * Index)));\r |
d9077743 FT |
609 | RegVal &= ~PORTSC_CHANGE_MASK;\r |
610 | RegVal |= PORTSC_POWER;\r | |
1436aea4 | 611 | EhcWriteOpReg (Ehc, (UINT32)(EHC_PORT_STAT_OFFSET + (4 * Index)), RegVal);\r |
f01219e8 | 612 | }\r |
613 | }\r | |
913cb9dc | 614 | \r |
41e8ff27 | 615 | //\r |
616 | // Wait roothub port power stable\r | |
617 | //\r | |
618 | gBS->Stall (EHC_ROOT_PORT_RECOVERY_STALL);\r | |
619 | \r | |
f01219e8 | 620 | //\r |
621 | // 4. Set all ports routing to EHC\r | |
622 | //\r | |
623 | EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);\r | |
624 | \r | |
41e8ff27 | 625 | Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIMEOUT);\r |
913cb9dc | 626 | \r |
627 | if (EFI_ERROR (Status)) {\r | |
87000d77 | 628 | DEBUG ((DEBUG_ERROR, "EhcInitHC: failed to enable period schedule\n"));\r |
913cb9dc | 629 | return Status;\r |
630 | }\r | |
631 | \r | |
41e8ff27 | 632 | Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIMEOUT);\r |
913cb9dc | 633 | \r |
634 | if (EFI_ERROR (Status)) {\r | |
87000d77 | 635 | DEBUG ((DEBUG_ERROR, "EhcInitHC: failed to enable async schedule\n"));\r |
913cb9dc | 636 | return Status;\r |
637 | }\r | |
638 | \r | |
639 | return EFI_SUCCESS;\r | |
640 | }\r |