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