]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciDxe / EhciReg.c
CommitLineData
913cb9dc 1/** @file\r
2\r
78c2ffb5 3 The EHCI register operation routines.\r
4\r
16f69227 5Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>\r
9d510e61 6SPDX-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
22UINT32\r
23EhcReadCapRegister (\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
58UINT32\r
59EhcReadDbgRegister (\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
103BOOLEAN\r
104EhcIsDebugPortInUse (\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
146UINT32\r
147EhcReadOpReg (\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
182VOID\r
183EhcWriteOpReg (\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 215VOID\r
216EhcSetOpRegBit (\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 237VOID\r
238EhcClearOpRegBit (\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 265EFI_STATUS\r
266EhcWaitOpRegBit (\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
294VOID\r
295EhcClearLegacySupport (\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
342EFI_STATUS\r
343EhcSetAndWaitDoorBell (\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
375VOID\r
376EhcAckAllInterrupt (\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 394EFI_STATUS\r
395EhcEnablePeriodSchd (\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 418EFI_STATUS\r
419EhcEnableAsyncSchd (\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
441BOOLEAN\r
442EhcIsHalt (\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
458BOOLEAN\r
459EhcIsSysError (\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
476EFI_STATUS\r
477EhcResetHC (\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
510EFI_STATUS\r
511EhcHaltHC (\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
533EFI_STATUS\r
534EhcRunHC (\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
561EFI_STATUS\r
562EhcInitHC (\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