1 /** @file 2 3 Copyright (c) 2015-2016, Linaro Limited. All rights reserved. 4 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "DwUsbHostDxe.h" 16 #include "DwcHw.h" 17 18 EFI_USB_PCIIO_DEVICE_PATH DwHcDevicePath = 19 { 20 { 21 { ACPI_DEVICE_PATH, ACPI_DP, { sizeof (ACPI_HID_DEVICE_PATH), 0 } }, 22 EISA_PNP_ID(0x0A03), // HID 23 0 // UID 24 }, 25 { 26 { HARDWARE_DEVICE_PATH, HW_PCI_DP, { sizeof (PCI_DEVICE_PATH), 0 } }, 27 0, 28 0 29 }, 30 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} } 31 }; 32 33 VOID DwHcInit (IN DWUSB_OTGHC_DEV *DwHc); 34 VOID DwCoreInit (IN DWUSB_OTGHC_DEV *DwHc); 35 36 STATIC DW_USB_PROTOCOL *DwUsb; 37 38 UINT32 39 Wait4Bit ( 40 IN UINT32 Reg, 41 IN UINT32 Mask, 42 IN BOOLEAN Set 43 ) 44 { 45 UINT32 Timeout = 1000000; 46 UINT32 Value; 47 48 while (--Timeout) { 49 Value = MmioRead32 (Reg); 50 if (!Set) 51 Value = ~Value; 52 53 if ((Value & Mask) == Mask) 54 return 0; 55 56 MicroSecondDelay (1); 57 } 58 59 DEBUG ((EFI_D_ERROR, "Wait4Bit: Timeout (Reg:0x%x, mask:0x%x, wait_set:%d)\n", Reg, Mask, Set)); 60 61 return 1; 62 } 63 64 UINT32 65 Wait4Chhltd ( 66 IN DWUSB_OTGHC_DEV *DwHc, 67 IN UINT32 *Sub, 68 IN UINT32 *Toggle, 69 IN BOOLEAN IgnoreAck 70 ) 71 { 72 UINT32 HcintCompHltAck = DWC2_HCINT_XFERCOMP | DWC2_HCINT_CHHLTD; 73 INT32 Ret; 74 UINT32 Hcint, Hctsiz; 75 76 MicroSecondDelay (100); 77 Ret = Wait4Bit (DwHc->DwUsbBase + HCINT(DWC2_HC_CHANNEL), DWC2_HCINT_CHHLTD, 1); 78 if (Ret) 79 return Ret; 80 81 MicroSecondDelay (100); 82 Hcint = MmioRead32 (DwHc->DwUsbBase + HCINT(DWC2_HC_CHANNEL)); 83 if (Hcint & (DWC2_HCINT_NAK | DWC2_HCINT_FRMOVRUN)) { 84 DEBUG ((EFI_D_INFO, "Wait4Chhltd: ERROR\n")); 85 return 1; 86 } 87 88 if (IgnoreAck) 89 Hcint &= ~DWC2_HCINT_ACK; 90 else 91 HcintCompHltAck |= DWC2_HCINT_ACK; 92 93 if (Hcint != HcintCompHltAck) { 94 DEBUG ((EFI_D_ERROR, "Wait4Chhltd: HCINT Error 0x%x\n", Hcint)); 95 return 1; 96 } 97 98 Hctsiz = MmioRead32 (DwHc->DwUsbBase + HCTSIZ(DWC2_HC_CHANNEL)); 99 *Sub = (Hctsiz & DWC2_HCTSIZ_XFERSIZE_MASK) >> DWC2_HCTSIZ_XFERSIZE_OFFSET; 100 *Toggle = (Hctsiz & DWC2_HCTSIZ_PID_MASK) >> DWC2_HCTSIZ_PID_OFFSET; 101 102 return 0; 103 } 104 105 VOID 106 DwOtgHcInit ( 107 IN DWUSB_OTGHC_DEV *DwHc, 108 IN UINT8 HcNum, 109 IN UINT8 DevAddr, 110 IN UINT8 Endpoint, 111 IN UINT8 EpDir, 112 IN UINT8 EpType, 113 IN UINT16 MaxPacket 114 ) 115 { 116 UINT32 Hcchar = (DevAddr << DWC2_HCCHAR_DEVADDR_OFFSET) | 117 (Endpoint << DWC2_HCCHAR_EPNUM_OFFSET) | 118 (EpDir << DWC2_HCCHAR_EPDIR_OFFSET) | 119 (EpType << DWC2_HCCHAR_EPTYPE_OFFSET) | 120 (MaxPacket << DWC2_HCCHAR_MPS_OFFSET); 121 122 MmioWrite32 (DwHc->DwUsbBase + HCINT(HcNum), 0x3FFF); 123 124 MmioWrite32 (DwHc->DwUsbBase + HCCHAR(HcNum), Hcchar); 125 126 MmioWrite32 (DwHc->DwUsbBase + HCSPLT(HcNum), 0); 127 } 128 129 VOID 130 DwCoreReset ( 131 IN DWUSB_OTGHC_DEV *DwHc 132 ) 133 { 134 UINT32 Status; 135 136 Status = Wait4Bit (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_AHBIDLE, 1); 137 if (Status) 138 DEBUG ((EFI_D_ERROR, "DwCoreReset: Timeout!\n")); 139 140 MmioWrite32 (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_CSFTRST); 141 142 Status = Wait4Bit (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_CSFTRST, 0); 143 if (Status) 144 DEBUG ((EFI_D_ERROR, "DwCoreReset: Timeout!\n")); 145 146 MicroSecondDelay (100000); 147 } 148 149 EFI_STATUS 150 DwHcTransfer ( 151 IN DWUSB_OTGHC_DEV *DwHc, 152 IN UINT8 DeviceAddress, 153 IN UINTN MaximumPacketLength, 154 IN OUT UINT32 *Pid, 155 IN UINT32 TransferDirection, 156 IN OUT VOID *Data, 157 IN OUT UINTN *DataLength, 158 IN UINT32 EpAddress, 159 IN UINT32 EpType, 160 OUT UINT32 *TransferResult, 161 IN BOOLEAN IgnoreAck 162 ) 163 { 164 UINT32 TxferLen; 165 UINT32 Done = 0; 166 UINT32 NumPackets; 167 UINT32 Sub; 168 UINT32 Ret = 0; 169 UINT32 StopTransfer = 0; 170 EFI_STATUS Status = EFI_SUCCESS; 171 172 do { 173 DwOtgHcInit (DwHc, DWC2_HC_CHANNEL, DeviceAddress, EpAddress, TransferDirection, EpType, MaximumPacketLength); 174 175 TxferLen = *DataLength - Done; 176 if (TxferLen > DWC2_MAX_TRANSFER_SIZE) 177 TxferLen = DWC2_MAX_TRANSFER_SIZE - MaximumPacketLength + 1; 178 if (TxferLen > DWC2_DATA_BUF_SIZE) 179 TxferLen = DWC2_DATA_BUF_SIZE - MaximumPacketLength + 1; 180 181 if (TxferLen > 0) { 182 NumPackets = (TxferLen + MaximumPacketLength - 1) / MaximumPacketLength; 183 if (NumPackets > DWC2_MAX_PACKET_COUNT) { 184 NumPackets = DWC2_MAX_PACKET_COUNT; 185 TxferLen = NumPackets * MaximumPacketLength; 186 } 187 } else { 188 NumPackets = 1; 189 } 190 191 if (TransferDirection) 192 TxferLen = NumPackets * MaximumPacketLength; 193 194 MmioWrite32 (DwHc->DwUsbBase + HCTSIZ(DWC2_HC_CHANNEL), (TxferLen << DWC2_HCTSIZ_XFERSIZE_OFFSET) | 195 (NumPackets << DWC2_HCTSIZ_PKTCNT_OFFSET) | 196 (*Pid << DWC2_HCTSIZ_PID_OFFSET)); 197 198 if (!TransferDirection) { 199 CopyMem (DwHc->AlignedBuffer, Data+Done, *DataLength); 200 } 201 202 MmioWrite32 (DwHc->DwUsbBase + HCDMA(DWC2_HC_CHANNEL), (UINTN)DwHc->AlignedBuffer); 203 204 MmioAndThenOr32 (DwHc->DwUsbBase + HCCHAR(DWC2_HC_CHANNEL), ~(DWC2_HCCHAR_MULTICNT_MASK | 205 DWC2_HCCHAR_CHEN | 206 DWC2_HCCHAR_CHDIS), 207 ((1 << DWC2_HCCHAR_MULTICNT_OFFSET) | 208 DWC2_HCCHAR_CHEN)); 209 210 Ret = Wait4Chhltd (DwHc, &Sub, Pid, IgnoreAck); 211 if (Ret) { 212 *TransferResult = EFI_USB_ERR_STALL; 213 Status = EFI_DEVICE_ERROR; 214 break; 215 } 216 217 if (TransferDirection) { 218 TxferLen -= Sub; 219 CopyMem (Data+Done, DwHc->AlignedBuffer, TxferLen); 220 if (Sub) 221 StopTransfer = 1; 222 } 223 224 Done += TxferLen; 225 } while (Done < *DataLength && !StopTransfer); 226 227 MmioWrite32 (DwHc->DwUsbBase + HCINTMSK(DWC2_HC_CHANNEL), 0); 228 MmioWrite32 (DwHc->DwUsbBase + HCINT(DWC2_HC_CHANNEL), 0xFFFFFFFF); 229 230 *DataLength = Done; 231 232 return Status; 233 } 234 235 /** 236 EFI_USB2_HC_PROTOCOL APIs 237 **/ 238 239 EFI_STATUS 240 EFIAPI 241 DwHcGetCapability ( 242 IN EFI_USB2_HC_PROTOCOL *This, 243 OUT UINT8 *MaxSpeed, 244 OUT UINT8 *PortNumber, 245 OUT UINT8 *Is64BitCapable 246 ) 247 { 248 if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) { 249 return EFI_INVALID_PARAMETER; 250 } 251 252 *MaxSpeed = EFI_USB_SPEED_HIGH; 253 *PortNumber = 1; 254 *Is64BitCapable = 1; 255 256 return EFI_SUCCESS; 257 } 258 259 EFI_STATUS 260 EFIAPI 261 DwHcReset ( 262 IN EFI_USB2_HC_PROTOCOL *This, 263 IN UINT16 Attributes 264 ) 265 { 266 DWUSB_OTGHC_DEV *DwHc; 267 EFI_STATUS Status; 268 UINT8 UsbMode; 269 270 DwHc = DWHC_FROM_THIS (This); 271 272 //Mode: 1 for device, 0 for Host 273 UsbMode = USB_HOST_MODE; 274 Status = DwUsb->PhyInit(UsbMode); 275 if (EFI_ERROR(Status)) { 276 return Status; 277 } 278 279 DwCoreInit(DwHc); 280 DwHcInit(DwHc); 281 282 MmioAndThenOr32 (DwHc->DwUsbBase + HPRT0, 283 ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | 284 DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG), 285 DWC2_HPRT0_PRTRST); 286 287 MicroSecondDelay (50000); 288 289 MmioAnd32 (DwHc->DwUsbBase + HPRT0, ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | 290 DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG | 291 DWC2_HPRT0_PRTRST)); 292 293 return EFI_SUCCESS; 294 } 295 296 EFI_STATUS 297 EFIAPI 298 DwHcGetState ( 299 IN EFI_USB2_HC_PROTOCOL *This, 300 OUT EFI_USB_HC_STATE *State 301 ) 302 { 303 DWUSB_OTGHC_DEV *DwHc; 304 305 DwHc = DWHC_FROM_THIS (This); 306 307 *State = DwHc->DwHcState; 308 309 return EFI_SUCCESS; 310 } 311 312 EFI_STATUS 313 EFIAPI 314 DwHcSetState ( 315 IN EFI_USB2_HC_PROTOCOL *This, 316 IN EFI_USB_HC_STATE State 317 ) 318 { 319 DWUSB_OTGHC_DEV *DwHc; 320 321 DwHc = DWHC_FROM_THIS (This); 322 323 DwHc->DwHcState = State; 324 325 return EFI_SUCCESS; 326 } 327 328 EFI_STATUS 329 EFIAPI 330 DwHcGetRootHubPortStatus ( 331 IN EFI_USB2_HC_PROTOCOL *This, 332 IN UINT8 PortNumber, 333 OUT EFI_USB_PORT_STATUS *PortStatus 334 ) 335 { 336 DWUSB_OTGHC_DEV *DwHc; 337 UINT32 Hprt0; 338 339 if (PortNumber > DWC2_HC_CHANNEL) 340 return EFI_INVALID_PARAMETER; 341 342 if (PortStatus == NULL) 343 return EFI_INVALID_PARAMETER; 344 345 DwHc = DWHC_FROM_THIS (This); 346 347 PortStatus->PortStatus = 0; 348 PortStatus->PortChangeStatus = 0; 349 Hprt0 = MmioRead32 (DwHc->DwUsbBase + HPRT0); 350 351 if (Hprt0 & DWC2_HPRT0_PRTCONNSTS) { 352 PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION; 353 } 354 355 if (Hprt0 & DWC2_HPRT0_PRTENA) { 356 PortStatus->PortStatus |= USB_PORT_STAT_ENABLE; 357 } 358 359 if (Hprt0 & DWC2_HPRT0_PRTSUSP) { 360 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND; 361 } 362 363 if (Hprt0 & DWC2_HPRT0_PRTOVRCURRACT) { 364 PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT; 365 } 366 367 if (Hprt0 & DWC2_HPRT0_PRTRST) { 368 PortStatus->PortStatus |= USB_PORT_STAT_RESET; 369 } 370 371 if (Hprt0 & DWC2_HPRT0_PRTPWR) { 372 PortStatus->PortStatus |= USB_PORT_STAT_POWER; 373 } 374 375 PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED; 376 377 if (Hprt0 & DWC2_HPRT0_PRTENCHNG) { 378 // PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE; 379 } 380 381 if (Hprt0 & DWC2_HPRT0_PRTCONNDET) { 382 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION; 383 } 384 385 if (Hprt0 & DWC2_HPRT0_PRTOVRCURRCHNG) { 386 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT; 387 } 388 389 return EFI_SUCCESS; 390 } 391 392 EFI_STATUS 393 EFIAPI 394 DwHcSetRootHubPortFeature ( 395 IN EFI_USB2_HC_PROTOCOL *This, 396 IN UINT8 PortNumber, 397 IN EFI_USB_PORT_FEATURE PortFeature 398 ) 399 { 400 DWUSB_OTGHC_DEV *DwHc; 401 UINT32 Hprt0; 402 EFI_STATUS Status = EFI_SUCCESS; 403 404 if (PortNumber > DWC2_HC_CHANNEL) { 405 Status = EFI_INVALID_PARAMETER; 406 goto End; 407 } 408 409 DwHc = DWHC_FROM_THIS (This); 410 411 switch (PortFeature) { 412 case EfiUsbPortEnable: 413 break; 414 case EfiUsbPortSuspend: 415 Hprt0 = MmioRead32 (DwHc->DwUsbBase + HPRT0); 416 Hprt0 &= ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | 417 DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); 418 Hprt0 |= DWC2_HPRT0_PRTSUSP; 419 MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); 420 break; 421 case EfiUsbPortReset: 422 MmioAndThenOr32 (DwHc->DwUsbBase + HPRT0, 423 ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | 424 DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG), 425 DWC2_HPRT0_PRTRST); 426 MicroSecondDelay (50000); 427 MmioAnd32 (DwHc->DwUsbBase + HPRT0, ~DWC2_HPRT0_PRTRST); 428 break; 429 case EfiUsbPortPower: 430 Hprt0 = MmioRead32 (DwHc->DwUsbBase + HPRT0); 431 Hprt0 &= ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | 432 DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); 433 Hprt0 |= DWC2_HPRT0_PRTPWR; 434 MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); 435 break; 436 case EfiUsbPortOwner: 437 break; 438 default: 439 Status = EFI_INVALID_PARAMETER; 440 break; 441 } 442 443 End: 444 return Status; 445 } 446 447 EFI_STATUS 448 EFIAPI 449 DwHcClearRootHubPortFeature ( 450 IN EFI_USB2_HC_PROTOCOL *This, 451 IN UINT8 PortNumber, 452 IN EFI_USB_PORT_FEATURE PortFeature 453 ) 454 { 455 DWUSB_OTGHC_DEV *DwHc; 456 UINT32 Hprt0; 457 EFI_STATUS Status = EFI_SUCCESS; 458 459 if (PortNumber > DWC2_HC_CHANNEL) { 460 Status = EFI_INVALID_PARAMETER; 461 goto End; 462 } 463 464 DwHc = DWHC_FROM_THIS (This); 465 466 switch (PortFeature) { 467 case EfiUsbPortEnable: 468 Hprt0 = MmioRead32 (DwHc->DwUsbBase + HPRT0); 469 Hprt0 &= ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | 470 DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); 471 Hprt0 |= DWC2_HPRT0_PRTENA; 472 MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); 473 break; 474 case EfiUsbPortReset: 475 MmioAndThenOr32 (DwHc->DwUsbBase + HPRT0, 476 ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | 477 DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG), 478 DWC2_HPRT0_PRTRST); 479 MicroSecondDelay (50000); 480 MmioAnd32 (DwHc->DwUsbBase + HPRT0, ~DWC2_HPRT0_PRTRST); 481 break; 482 case EfiUsbPortSuspend: 483 MmioWrite32 (DwHc->DwUsbBase + PCGCCTL, 0); 484 MicroSecondDelay (40000); 485 Hprt0 = MmioRead32 (DwHc->DwUsbBase + HPRT0); 486 Hprt0 &= ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | 487 DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); 488 Hprt0 |= DWC2_HPRT0_PRTRES; 489 MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); 490 Hprt0 &= ~DWC2_HPRT0_PRTSUSP; 491 MicroSecondDelay (150000); 492 Hprt0 &= ~DWC2_HPRT0_PRTRES; 493 MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); 494 break; 495 case EfiUsbPortPower: 496 Hprt0 = MmioRead32 (DwHc->DwUsbBase + HPRT0); 497 Hprt0 &= ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | 498 DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); 499 Hprt0 &= ~DWC2_HPRT0_PRTPWR; 500 MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); 501 break; 502 case EfiUsbPortOwner: 503 break; 504 case EfiUsbPortConnectChange: 505 Hprt0 = MmioRead32 (DwHc->DwUsbBase + HPRT0); 506 Hprt0 &= ~DWC2_HPRT0_PRTCONNDET; 507 MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); 508 break; 509 case EfiUsbPortResetChange: 510 break; 511 case EfiUsbPortEnableChange: 512 Hprt0 = MmioRead32 (DwHc->DwUsbBase + HPRT0); 513 Hprt0 &= ~DWC2_HPRT0_PRTENCHNG; 514 MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); 515 break; 516 case EfiUsbPortSuspendChange: 517 break; 518 case EfiUsbPortOverCurrentChange: 519 Hprt0 = MmioRead32 (DwHc->DwUsbBase + HPRT0); 520 Hprt0 &= ~DWC2_HPRT0_PRTOVRCURRCHNG; 521 MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); 522 break; 523 default: 524 Status = EFI_INVALID_PARAMETER; 525 break; 526 } 527 528 End: 529 return Status; 530 } 531 532 EFI_STATUS 533 EFIAPI 534 DwHcControlTransfer ( 535 IN EFI_USB2_HC_PROTOCOL *This, 536 IN UINT8 DeviceAddress, 537 IN UINT8 DeviceSpeed, 538 IN UINTN MaximumPacketLength, 539 IN EFI_USB_DEVICE_REQUEST *Request, 540 IN EFI_USB_DATA_DIRECTION TransferDirection, 541 IN OUT VOID *Data, 542 IN OUT UINTN *DataLength, 543 IN UINTN TimeOut, 544 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, 545 OUT UINT32 *TransferResult 546 ) 547 { 548 DWUSB_OTGHC_DEV *DwHc; 549 EFI_STATUS Status; 550 UINT32 Pid; 551 UINTN Length; 552 EFI_USB_DATA_DIRECTION StatusDirection; 553 UINT32 Direction; 554 555 if ((Request == NULL) || (TransferResult == NULL)) { 556 return EFI_INVALID_PARAMETER; 557 } 558 559 if ((TransferDirection != EfiUsbDataIn) && 560 (TransferDirection != EfiUsbDataOut) && 561 (TransferDirection != EfiUsbNoData)) { 562 return EFI_INVALID_PARAMETER; 563 } 564 565 if ((TransferDirection == EfiUsbNoData) && 566 ((Data != NULL) || (*DataLength != 0))) { 567 return EFI_INVALID_PARAMETER; 568 } 569 570 if ((TransferDirection != EfiUsbNoData) && 571 ((Data == NULL) || (*DataLength == 0))) { 572 return EFI_INVALID_PARAMETER; 573 } 574 575 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) && 576 (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) { 577 return EFI_INVALID_PARAMETER; 578 } 579 580 if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) { 581 return EFI_INVALID_PARAMETER; 582 } 583 584 DwHc = DWHC_FROM_THIS(This); 585 586 *TransferResult = EFI_USB_ERR_SYSTEM; 587 Status = EFI_DEVICE_ERROR; 588 589 Pid = DWC2_HC_PID_SETUP; 590 Length = 8; 591 Status = DwHcTransfer (DwHc, DeviceAddress, MaximumPacketLength, &Pid, 0, Request, &Length, 592 0, DWC2_HCCHAR_EPTYPE_CONTROL, TransferResult, 1); 593 594 if (EFI_ERROR(Status)) { 595 DEBUG ((EFI_D_ERROR, "DwHcControlTransfer: Setup Stage Error\n")); 596 goto EXIT; 597 } 598 599 if (Data) { 600 Pid = DWC2_HC_PID_DATA1; 601 602 if (TransferDirection == EfiUsbDataIn) 603 Direction = 1; 604 else 605 Direction = 0; 606 607 Status = DwHcTransfer (DwHc, DeviceAddress, MaximumPacketLength, &Pid, Direction, 608 Data, DataLength, 0, DWC2_HCCHAR_EPTYPE_CONTROL, TransferResult, 0); 609 610 if (EFI_ERROR(Status)) { 611 DEBUG ((EFI_D_ERROR, "DwHcControlTransfer: Data Stage Error\n")); 612 goto EXIT; 613 } 614 } 615 616 if ((TransferDirection == EfiUsbDataOut) || (TransferDirection == EfiUsbNoData)) 617 StatusDirection = 1; 618 else 619 StatusDirection = 0; 620 621 Pid = DWC2_HC_PID_DATA1; 622 Length = 0; 623 Status = DwHcTransfer (DwHc, DeviceAddress, MaximumPacketLength, &Pid, StatusDirection, DwHc->StatusBuffer, 624 &Length, 0, DWC2_HCCHAR_EPTYPE_CONTROL, TransferResult, 0); 625 626 if (EFI_ERROR(Status)) { 627 DEBUG ((EFI_D_ERROR, "DwHcControlTransfer: Status Stage Error\n")); 628 goto EXIT; 629 } 630 631 EXIT: 632 return Status; 633 } 634 635 EFI_STATUS 636 EFIAPI 637 DwHcBulkTransfer ( 638 IN EFI_USB2_HC_PROTOCOL *This, 639 IN UINT8 DeviceAddress, 640 IN UINT8 EndPointAddress, 641 IN UINT8 DeviceSpeed, 642 IN UINTN MaximumPacketLength, 643 IN UINT8 DataBuffersNumber, 644 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], 645 IN OUT UINTN *DataLength, 646 IN OUT UINT8 *DataToggle, 647 IN UINTN TimeOut, 648 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, 649 OUT UINT32 *TransferResult 650 ) 651 { 652 DWUSB_OTGHC_DEV *DwHc; 653 EFI_STATUS Status; 654 UINT8 TransferDirection; 655 UINT8 EpAddress; 656 UINT32 Pid; 657 658 if ((Data == NULL) || (Data[0] == NULL) || 659 (DataLength == NULL) || (*DataLength == 0) || 660 (TransferResult == NULL)) { 661 return EFI_INVALID_PARAMETER; 662 } 663 664 if ((*DataToggle != 0) && (*DataToggle != 1)) 665 return EFI_INVALID_PARAMETER; 666 667 if ((DeviceSpeed == EFI_USB_SPEED_LOW) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) 668 return EFI_INVALID_PARAMETER; 669 670 if (((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) || 671 ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 512))) 672 return EFI_INVALID_PARAMETER; 673 674 DwHc = DWHC_FROM_THIS (This); 675 676 *TransferResult = EFI_USB_ERR_SYSTEM; 677 Status = EFI_DEVICE_ERROR; 678 TransferDirection = (EndPointAddress >> 7) & 0x01; 679 EpAddress = EndPointAddress & 0x0F; 680 Pid = (*DataToggle << 1); 681 682 Status = DwHcTransfer (DwHc, DeviceAddress, MaximumPacketLength, &Pid, TransferDirection, Data[0], DataLength, 683 EpAddress, DWC2_HCCHAR_EPTYPE_BULK, TransferResult, 1); 684 685 *DataToggle = (Pid >> 1); 686 687 return Status; 688 } 689 690 EFI_STATUS 691 EFIAPI 692 DwHcAsyncInterruptTransfer ( 693 IN EFI_USB2_HC_PROTOCOL *This, 694 IN UINT8 DeviceAddress, 695 IN UINT8 EndPointAddress, 696 IN UINT8 DeviceSpeed, 697 IN UINTN MaximumPacketLength, 698 IN BOOLEAN IsNewTransfer, 699 IN OUT UINT8 *DataToggle, 700 IN UINTN PollingInterval, 701 IN UINTN DataLength, 702 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, 703 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, 704 IN VOID *Context OPTIONAL 705 ) 706 { 707 DWUSB_OTGHC_DEV *DwHc; 708 VOID *Data; 709 EFI_STATUS Status; 710 UINT32 TransferResult; 711 UINT32 Pid; 712 UINT8 TransferDirection; 713 UINT8 EpAddress; 714 715 if (!(EndPointAddress & USB_ENDPOINT_DIR_IN)) 716 return EFI_INVALID_PARAMETER; 717 718 if (IsNewTransfer) { 719 if (DataLength == 0) 720 return EFI_INVALID_PARAMETER; 721 722 if ((*DataToggle != 1) && (*DataToggle != 0)) 723 return EFI_INVALID_PARAMETER; 724 725 if ((PollingInterval > 255) || (PollingInterval < 1)) 726 return EFI_INVALID_PARAMETER; 727 } 728 729 DwHc = DWHC_FROM_THIS (This); 730 731 if (!IsNewTransfer) 732 return EFI_SUCCESS; 733 734 Data = AllocateZeroPool (DataLength); 735 if (Data == NULL) { 736 DEBUG ((EFI_D_ERROR, "DwHcAsyncInterruptTransfer: failed to allocate buffer\n")); 737 Status = EFI_OUT_OF_RESOURCES; 738 goto EXIT; 739 } 740 741 Status = EFI_SUCCESS; 742 TransferResult = EFI_USB_NOERROR; 743 EpAddress = EndPointAddress & 0x0F; 744 TransferDirection = (EndPointAddress >> 7) & 0x01; 745 Pid = (*DataToggle << 1); 746 747 748 Status = DwHcTransfer (DwHc, DeviceAddress, MaximumPacketLength, &Pid, TransferDirection, Data, &DataLength, 749 EpAddress, DWC2_HCCHAR_EPTYPE_INTR, &TransferResult, 1); 750 751 *DataToggle = (Pid >> 1); 752 753 if (CallBackFunction != NULL) 754 CallBackFunction (Data, DataLength, Context, TransferResult); 755 756 EXIT: 757 return Status; 758 } 759 760 EFI_STATUS 761 EFIAPI 762 DwHcSyncInterruptTransfer ( 763 IN EFI_USB2_HC_PROTOCOL *This, 764 IN UINT8 DeviceAddress, 765 IN UINT8 EndPointAddress, 766 IN UINT8 DeviceSpeed, 767 IN UINTN MaximumPacketLength, 768 IN OUT VOID *Data, 769 IN OUT UINTN *DataLength, 770 IN OUT UINT8 *DataToggle, 771 IN UINTN TimeOut, 772 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, 773 OUT UINT32 *TransferResult 774 ) 775 { 776 return EFI_UNSUPPORTED; 777 } 778 779 EFI_STATUS 780 EFIAPI 781 DwHcIsochronousTransfer ( 782 IN EFI_USB2_HC_PROTOCOL *This, 783 IN UINT8 DeviceAddress, 784 IN UINT8 EndPointAddress, 785 IN UINT8 DeviceSpeed, 786 IN UINTN MaximumPacketLength, 787 IN UINT8 DataBuffersNumber, 788 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], 789 IN UINTN DataLength, 790 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, 791 OUT UINT32 *TransferResult 792 ) 793 { 794 return EFI_UNSUPPORTED; 795 } 796 797 EFI_STATUS 798 EFIAPI 799 DwHcAsyncIsochronousTransfer ( 800 IN EFI_USB2_HC_PROTOCOL *This, 801 IN UINT8 DeviceAddress, 802 IN UINT8 EndPointAddress, 803 IN UINT8 DeviceSpeed, 804 IN UINTN MaximumPacketLength, 805 IN UINT8 DataBuffersNumber, 806 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], 807 IN UINTN DataLength, 808 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, 809 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, 810 IN VOID *Context 811 ) 812 { 813 return EFI_UNSUPPORTED; 814 } 815 816 /** 817 Supported Functions 818 **/ 819 820 VOID 821 InitFslspClkSel ( 822 IN DWUSB_OTGHC_DEV *DwHc 823 ) 824 { 825 UINT32 PhyClk; 826 827 PhyClk = DWC2_HCFG_FSLSPCLKSEL_30_60_MHZ; 828 829 MmioAndThenOr32 (DwHc->DwUsbBase + HCFG, 830 ~DWC2_HCFG_FSLSPCLKSEL_MASK, 831 PhyClk << DWC2_HCFG_FSLSPCLKSEL_OFFSET); 832 } 833 834 VOID 835 DwFlushTxFifo ( 836 IN DWUSB_OTGHC_DEV *DwHc, 837 IN INT32 Num 838 ) 839 { 840 UINT32 Status; 841 842 MmioWrite32 (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_TXFFLSH | (Num << DWC2_GRSTCTL_TXFNUM_OFFSET)); 843 844 Status = Wait4Bit (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_TXFFLSH, 0); 845 if (Status) 846 DEBUG ((EFI_D_ERROR, "DwFlushTxFifo: Timeout!\n")); 847 848 MicroSecondDelay (1); 849 } 850 851 VOID 852 DwFlushRxFifo ( 853 IN DWUSB_OTGHC_DEV *DwHc 854 ) 855 { 856 UINT32 Status; 857 858 MmioWrite32 (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_RXFFLSH); 859 860 Status = Wait4Bit (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_RXFFLSH, 0); 861 if (Status) 862 DEBUG ((EFI_D_ERROR, "DwFlushRxFifo: Timeout!\n")); 863 864 MicroSecondDelay (1); 865 } 866 867 VOID 868 DwHcInit ( 869 IN DWUSB_OTGHC_DEV *DwHc 870 ) 871 { 872 UINT32 NpTxFifoSz = 0; 873 UINT32 pTxFifoSz = 0; 874 UINT32 Hprt0 = 0; 875 INT32 i, Status, NumChannels; 876 877 MmioWrite32 (DwHc->DwUsbBase + PCGCCTL, 0); 878 879 InitFslspClkSel (DwHc); 880 881 MmioWrite32 (DwHc->DwUsbBase + GRXFSIZ, DWC2_HOST_RX_FIFO_SIZE); 882 883 NpTxFifoSz |= DWC2_HOST_NPERIO_TX_FIFO_SIZE << DWC2_FIFOSIZE_DEPTH_OFFSET; 884 NpTxFifoSz |= DWC2_HOST_RX_FIFO_SIZE << DWC2_FIFOSIZE_STARTADDR_OFFSET; 885 MmioWrite32 (DwHc->DwUsbBase + GNPTXFSIZ, NpTxFifoSz); 886 887 pTxFifoSz |= DWC2_HOST_PERIO_TX_FIFO_SIZE << DWC2_FIFOSIZE_DEPTH_OFFSET; 888 pTxFifoSz |= (DWC2_HOST_RX_FIFO_SIZE + DWC2_HOST_NPERIO_TX_FIFO_SIZE) << 889 DWC2_FIFOSIZE_STARTADDR_OFFSET; 890 MmioWrite32 (DwHc->DwUsbBase + HPTXFSIZ, pTxFifoSz); 891 892 MmioAnd32 (DwHc->DwUsbBase + GOTGCTL, ~(DWC2_GOTGCTL_HSTSETHNPEN)); 893 894 DwFlushTxFifo (DwHc, 0x10); 895 DwFlushRxFifo (DwHc); 896 897 NumChannels = MmioRead32 (DwHc->DwUsbBase + GHWCFG2); 898 NumChannels &= DWC2_HWCFG2_NUM_HOST_CHAN_MASK; 899 NumChannels >>= DWC2_HWCFG2_NUM_HOST_CHAN_OFFSET; 900 NumChannels += 1; 901 902 for (i=0; i<NumChannels; i++) 903 MmioAndThenOr32 (DwHc->DwUsbBase + HCCHAR(i), 904 ~(DWC2_HCCHAR_CHEN | DWC2_HCCHAR_EPDIR), 905 DWC2_HCCHAR_CHDIS); 906 907 for (i=0; i<NumChannels; i++) { 908 MmioAndThenOr32 (DwHc->DwUsbBase + HCCHAR(i), 909 ~DWC2_HCCHAR_EPDIR, 910 (DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS)); 911 Status = Wait4Bit (DwHc->DwUsbBase + HCCHAR(i), DWC2_HCCHAR_CHEN, 0); 912 if (Status) 913 DEBUG ((EFI_D_ERROR, "DwHcInit: Timeout!\n")); 914 } 915 916 if (MmioRead32 (DwHc->DwUsbBase + GINTSTS) & DWC2_GINTSTS_CURMODE_HOST) { 917 Hprt0 = MmioRead32 (DwHc->DwUsbBase + HPRT0); 918 Hprt0 &= ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET); 919 Hprt0 &= ~(DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); 920 921 if (!(Hprt0 & DWC2_HPRT0_PRTPWR)) { 922 Hprt0 |= DWC2_HPRT0_PRTPWR; 923 MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); 924 } 925 } 926 } 927 928 VOID 929 DwCoreInit ( 930 IN DWUSB_OTGHC_DEV *DwHc 931 ) 932 { 933 UINT32 AhbCfg = 0; 934 UINT32 UsbCfg = 0; 935 936 UsbCfg = MmioRead32 (DwHc->DwUsbBase + GUSBCFG); 937 938 UsbCfg |= DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV; 939 UsbCfg &= ~DWC2_GUSBCFG_TERM_SEL_DL_PULSE; 940 941 MmioWrite32 (DwHc->DwUsbBase + GUSBCFG, UsbCfg); 942 943 DwCoreReset (DwHc); 944 945 UsbCfg &= ~(DWC2_GUSBCFG_ULPI_UTMI_SEL | DWC2_GUSBCFG_PHYIF); 946 UsbCfg |= CONFIG_DWC2_PHY_TYPE << DWC2_GUSBCFG_ULPI_UTMI_SEL_OFFSET; 947 948 UsbCfg &= ~DWC2_GUSBCFG_DDRSEL; 949 950 MmioWrite32 (DwHc->DwUsbBase + GUSBCFG, UsbCfg); 951 952 DwCoreReset (DwHc); 953 954 UsbCfg = MmioRead32 (DwHc->DwUsbBase + GUSBCFG); 955 UsbCfg &= ~(DWC2_GUSBCFG_ULPI_FSLS | DWC2_GUSBCFG_ULPI_CLK_SUS_M); 956 MmioWrite32 (DwHc->DwUsbBase + GUSBCFG, UsbCfg); 957 958 AhbCfg |= DWC2_GAHBCFG_HBURSTLEN_INCR4; 959 AhbCfg |= DWC2_GAHBCFG_DMAENABLE; 960 961 MmioWrite32 (DwHc->DwUsbBase + GAHBCFG, AhbCfg); 962 MmioOr32 (DwHc->DwUsbBase + GUSBCFG, DWC2_GUSBCFG_HNPCAP | DWC2_GUSBCFG_SRPCAP); 963 } 964 965 DWUSB_OTGHC_DEV * 966 CreateDwUsbHc ( 967 VOID 968 ) 969 { 970 DWUSB_OTGHC_DEV *DwHc; 971 UINT32 Pages; 972 973 DwHc = AllocateZeroPool (sizeof(DWUSB_OTGHC_DEV)); 974 975 if (DwHc == NULL) { 976 return NULL; 977 } 978 979 DwHc->Signature = DWUSB_OTGHC_DEV_SIGNATURE; 980 DwHc->DwUsbOtgHc.GetCapability = DwHcGetCapability; 981 DwHc->DwUsbOtgHc.Reset = DwHcReset; 982 DwHc->DwUsbOtgHc.GetState = DwHcGetState; 983 DwHc->DwUsbOtgHc.SetState = DwHcSetState; 984 DwHc->DwUsbOtgHc.ControlTransfer = DwHcControlTransfer; 985 DwHc->DwUsbOtgHc.BulkTransfer = DwHcBulkTransfer; 986 DwHc->DwUsbOtgHc.AsyncInterruptTransfer = DwHcAsyncInterruptTransfer; 987 DwHc->DwUsbOtgHc.SyncInterruptTransfer = DwHcSyncInterruptTransfer; 988 DwHc->DwUsbOtgHc.IsochronousTransfer = DwHcIsochronousTransfer; 989 DwHc->DwUsbOtgHc.AsyncIsochronousTransfer = DwHcAsyncIsochronousTransfer; 990 DwHc->DwUsbOtgHc.GetRootHubPortStatus = DwHcGetRootHubPortStatus; 991 DwHc->DwUsbOtgHc.SetRootHubPortFeature = DwHcSetRootHubPortFeature; 992 DwHc->DwUsbOtgHc.ClearRootHubPortFeature = DwHcClearRootHubPortFeature; 993 DwHc->DwUsbOtgHc.MajorRevision = 0x02; 994 DwHc->DwUsbOtgHc.MinorRevision = 0x00; 995 DwHc->DwUsbBase = FixedPcdGet32 (PcdDwUsbDxeBaseAddress); 996 997 CopyMem (&DwHc->DevicePath, &DwHcDevicePath, sizeof(DwHcDevicePath)); 998 999 Pages = EFI_SIZE_TO_PAGES (DWC2_STATUS_BUF_SIZE); 1000 DwHc->StatusBuffer = UncachedAllocatePages (Pages); 1001 if (DwHc->StatusBuffer == NULL) { 1002 DEBUG ((EFI_D_ERROR, "CreateDwUsbHc: No page availablefor StatusBuffer\n")); 1003 return NULL; 1004 } 1005 1006 Pages = EFI_SIZE_TO_PAGES (DWC2_DATA_BUF_SIZE); 1007 DwHc->AlignedBuffer = UncachedAllocatePages (Pages); 1008 if (DwHc->AlignedBuffer == NULL) { 1009 DEBUG ((EFI_D_ERROR, "CreateDwUsbHc: No page availablefor AlignedBuffer\n")); 1010 return NULL; 1011 } 1012 1013 return DwHc; 1014 } 1015 1016 VOID 1017 EFIAPI 1018 DwUsbHcExitBootService ( 1019 EFI_EVENT Event, 1020 VOID *Context 1021 ) 1022 { 1023 DWUSB_OTGHC_DEV *DwHc; 1024 1025 DwHc = (DWUSB_OTGHC_DEV *) Context; 1026 1027 MmioAndThenOr32 (DwHc->DwUsbBase + HPRT0, 1028 ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | 1029 DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG), 1030 DWC2_HPRT0_PRTRST); 1031 1032 MicroSecondDelay (50000); 1033 1034 DwCoreReset (DwHc); 1035 } 1036 1037 /** 1038 UEFI Driver Entry Point API 1039 1040 @param ImageHandle EFI_HANDLE. 1041 @param SystemTable EFI_SYSTEM_TABLE. 1042 1043 @return EFI_SUCCESS Success. 1044 EFI_DEVICE_ERROR Fail. 1045 **/ 1046 1047 EFI_STATUS 1048 EFIAPI 1049 DwUsbHostEntryPoint ( 1050 IN EFI_HANDLE ImageHandle, 1051 IN EFI_SYSTEM_TABLE *SystemTable 1052 ) 1053 { 1054 EFI_STATUS Status; 1055 DWUSB_OTGHC_DEV *DwHc; 1056 UINT32 Pages; 1057 1058 Status = EFI_SUCCESS; 1059 1060 DwHc = CreateDwUsbHc (); 1061 1062 if (DwHc == NULL) { 1063 Status = EFI_OUT_OF_RESOURCES; 1064 goto EXIT; 1065 } 1066 1067 Status = gBS->LocateProtocol (&gDwUsbProtocolGuid, NULL, (VOID **) &DwUsb); 1068 if (EFI_ERROR (Status)) { 1069 return Status; 1070 } 1071 1072 Status = gBS->InstallMultipleProtocolInterfaces ( 1073 &DwHc->DeviceHandle, 1074 &gEfiUsb2HcProtocolGuid, &DwHc->DwUsbOtgHc, 1075 &gEfiDevicePathProtocolGuid, &DwHc->DevicePath, 1076 NULL 1077 ); 1078 1079 if (EFI_ERROR (Status)) { 1080 goto FREE_DWUSBHC; 1081 } 1082 1083 Status = gBS->CreateEventEx ( 1084 EVT_NOTIFY_SIGNAL, 1085 TPL_NOTIFY, 1086 DwUsbHcExitBootService, 1087 DwHc, 1088 &gEfiEventExitBootServicesGuid, 1089 &DwHc->ExitBootServiceEvent 1090 ); 1091 1092 if (EFI_ERROR (Status)) { 1093 goto UNINSTALL_PROTOCOL; 1094 } 1095 1096 return Status; 1097 1098 UNINSTALL_PROTOCOL: 1099 gBS->UninstallMultipleProtocolInterfaces ( 1100 &DwHc->DeviceHandle, 1101 &gEfiUsb2HcProtocolGuid, &DwHc->DwUsbOtgHc, 1102 &gEfiDevicePathProtocolGuid, &DwHc->DevicePath, 1103 NULL 1104 ); 1105 FREE_DWUSBHC: 1106 Pages = EFI_SIZE_TO_PAGES (DWC2_STATUS_BUF_SIZE); 1107 UncachedFreePages (DwHc->StatusBuffer, Pages); 1108 Pages = EFI_SIZE_TO_PAGES (DWC2_DATA_BUF_SIZE); 1109 UncachedFreePages (DwHc->AlignedBuffer, Pages); 1110 gBS->FreePool (DwHc); 1111 EXIT: 1112 return Status; 1113 } 1114 1115 EFI_STATUS 1116 EFIAPI 1117 DwUsbHostExitPoint ( 1118 IN EFI_HANDLE ImageHandle 1119 ) 1120 { 1121 EFI_STATUS Status; 1122 EFI_USB2_HC_PROTOCOL *DwUsbHc; 1123 DWUSB_OTGHC_DEV *DwHc; 1124 UINT32 Pages; 1125 1126 Status = EFI_SUCCESS; 1127 1128 Status = gBS->LocateProtocol (&gEfiUsb2HcProtocolGuid, NULL, (VOID **) &DwUsbHc); 1129 1130 if (EFI_ERROR (Status)) { 1131 return Status; 1132 } 1133 1134 DwHc = DWHC_FROM_THIS(DwUsbHc); 1135 1136 if (DwHc->ExitBootServiceEvent != NULL) { 1137 gBS->CloseEvent (DwHc->ExitBootServiceEvent); 1138 } 1139 1140 gBS->UninstallMultipleProtocolInterfaces ( 1141 &DwHc->DeviceHandle, 1142 &gEfiUsb2HcProtocolGuid, &DwHc->DwUsbOtgHc, 1143 &gEfiDevicePathProtocolGuid, &DwHc->DevicePath, 1144 NULL 1145 ); 1146 1147 if (EFI_ERROR (Status)) { 1148 return Status; 1149 } 1150 1151 Pages = EFI_SIZE_TO_PAGES (DWC2_STATUS_BUF_SIZE); 1152 UncachedFreePages (DwHc->StatusBuffer, Pages); 1153 Pages = EFI_SIZE_TO_PAGES (DWC2_DATA_BUF_SIZE); 1154 UncachedFreePages (DwHc->AlignedBuffer, Pages); 1155 FreePool (DwHc); 1156 1157 return Status; 1158 } 1159