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