Home | History | Annotate | Download | only in DwUsbHostDxe
      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