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