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
Wait4Bit(IN UINT32 Reg,IN UINT32 Mask,IN BOOLEAN Set)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
Wait4Chhltd(IN DWUSB_OTGHC_DEV * DwHc,IN UINT32 * Sub,IN UINT32 * Toggle,IN BOOLEAN IgnoreAck)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
DwOtgHcInit(IN DWUSB_OTGHC_DEV * DwHc,IN UINT8 HcNum,IN UINT8 DevAddr,IN UINT8 Endpoint,IN UINT8 EpDir,IN UINT8 EpType,IN UINT16 MaxPacket)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
DwCoreReset(IN DWUSB_OTGHC_DEV * DwHc)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
DwHcTransfer(IN DWUSB_OTGHC_DEV * DwHc,IN UINT8 DeviceAddress,IN UINTN MaximumPacketLength,IN OUT UINT32 * Pid,IN UINT32 TransferDirection,IN OUT VOID * Data,IN OUT UINTN * DataLength,IN UINT32 EpAddress,IN UINT32 EpType,OUT UINT32 * TransferResult,IN BOOLEAN IgnoreAck)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
DwHcGetCapability(IN EFI_USB2_HC_PROTOCOL * This,OUT UINT8 * MaxSpeed,OUT UINT8 * PortNumber,OUT UINT8 * Is64BitCapable)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
DwHcReset(IN EFI_USB2_HC_PROTOCOL * This,IN UINT16 Attributes)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
DwHcGetState(IN EFI_USB2_HC_PROTOCOL * This,OUT EFI_USB_HC_STATE * State)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
DwHcSetState(IN EFI_USB2_HC_PROTOCOL * This,IN EFI_USB_HC_STATE State)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
DwHcGetRootHubPortStatus(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 PortNumber,OUT EFI_USB_PORT_STATUS * PortStatus)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
DwHcSetRootHubPortFeature(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 PortNumber,IN EFI_USB_PORT_FEATURE PortFeature)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
DwHcClearRootHubPortFeature(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 PortNumber,IN EFI_USB_PORT_FEATURE PortFeature)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
DwHcControlTransfer(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN EFI_USB_DEVICE_REQUEST * Request,IN EFI_USB_DATA_DIRECTION TransferDirection,IN OUT VOID * Data,IN OUT UINTN * DataLength,IN UINTN TimeOut,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * TransferResult)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
DwHcBulkTransfer(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN UINT8 DataBuffersNumber,IN OUT VOID * Data[EFI_USB_MAX_BULK_BUFFER_NUM],IN OUT UINTN * DataLength,IN OUT UINT8 * DataToggle,IN UINTN TimeOut,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * TransferResult)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
DwHcAsyncInterruptTransfer(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN BOOLEAN IsNewTransfer,IN OUT UINT8 * DataToggle,IN UINTN PollingInterval,IN UINTN DataLength,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,IN VOID * Context OPTIONAL)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
DwHcSyncInterruptTransfer(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN OUT VOID * Data,IN OUT UINTN * DataLength,IN OUT UINT8 * DataToggle,IN UINTN TimeOut,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * TransferResult)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
DwHcIsochronousTransfer(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN UINT8 DataBuffersNumber,IN OUT VOID * Data[EFI_USB_MAX_ISO_BUFFER_NUM],IN UINTN DataLength,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * TransferResult)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
DwHcAsyncIsochronousTransfer(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN UINT8 DataBuffersNumber,IN OUT VOID * Data[EFI_USB_MAX_ISO_BUFFER_NUM],IN UINTN DataLength,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,IN VOID * Context)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
InitFslspClkSel(IN DWUSB_OTGHC_DEV * DwHc)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
DwFlushTxFifo(IN DWUSB_OTGHC_DEV * DwHc,IN INT32 Num)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
DwFlushRxFifo(IN DWUSB_OTGHC_DEV * DwHc)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
DwHcInit(IN DWUSB_OTGHC_DEV * DwHc)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
DwCoreInit(IN DWUSB_OTGHC_DEV * DwHc)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 *
CreateDwUsbHc(VOID)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
DwUsbHcExitBootService(EFI_EVENT Event,VOID * Context)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
DwUsbHostEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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
DwUsbHostExitPoint(IN EFI_HANDLE ImageHandle)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