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