]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c
Add a blank line in the end of file.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciDxe / EhciReg.c
1 /** @file
2
3 The EHCI register operation routines.
4
5 Copyright (c) 2007 - 2009, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16
17 #include "Ehci.h"
18
19
20 /**
21 Read EHCI capability register.
22
23 @param Ehc The EHCI device.
24 @param Offset Capability register address.
25
26 @return The register content read.
27 @retval If err, return 0xffff.
28
29 **/
30 UINT32
31 EhcReadCapRegister (
32 IN USB2_HC_DEV *Ehc,
33 IN UINT32 Offset
34 )
35 {
36 UINT32 Data;
37 EFI_STATUS Status;
38
39 Status = Ehc->PciIo->Mem.Read (
40 Ehc->PciIo,
41 EfiPciIoWidthUint32,
42 EHC_BAR_INDEX,
43 (UINT64) Offset,
44 1,
45 &Data
46 );
47
48 if (EFI_ERROR (Status)) {
49 DEBUG ((EFI_D_ERROR, "EhcReadCapRegister: Pci Io read error - %r at %d\n", Status, Offset));
50 Data = 0xFFFF;
51 }
52
53 return Data;
54 }
55
56
57 /**
58 Read EHCI Operation register.
59
60 @param Ehc The EHCI device.
61 @param Offset The operation register offset.
62
63 @return The register content read.
64 @retval If err, return 0xffff.
65
66 **/
67 UINT32
68 EhcReadOpReg (
69 IN USB2_HC_DEV *Ehc,
70 IN UINT32 Offset
71 )
72 {
73 UINT32 Data;
74 EFI_STATUS Status;
75
76 ASSERT (Ehc->CapLen != 0);
77
78 Status = Ehc->PciIo->Mem.Read (
79 Ehc->PciIo,
80 EfiPciIoWidthUint32,
81 EHC_BAR_INDEX,
82 (UINT64) (Ehc->CapLen + Offset),
83 1,
84 &Data
85 );
86
87 if (EFI_ERROR (Status)) {
88 DEBUG ((EFI_D_ERROR, "EhcReadOpReg: Pci Io Read error - %r at %d\n", Status, Offset));
89 Data = 0xFFFF;
90 }
91
92 return Data;
93 }
94
95
96 /**
97 Write the data to the EHCI operation register.
98
99 @param Ehc The EHCI device.
100 @param Offset EHCI operation register offset.
101 @param Data The data to write.
102
103 **/
104 VOID
105 EhcWriteOpReg (
106 IN USB2_HC_DEV *Ehc,
107 IN UINT32 Offset,
108 IN UINT32 Data
109 )
110 {
111 EFI_STATUS Status;
112
113 ASSERT (Ehc->CapLen != 0);
114
115 Status = Ehc->PciIo->Mem.Write (
116 Ehc->PciIo,
117 EfiPciIoWidthUint32,
118 EHC_BAR_INDEX,
119 (UINT64) (Ehc->CapLen + Offset),
120 1,
121 &Data
122 );
123
124 if (EFI_ERROR (Status)) {
125 DEBUG ((EFI_D_ERROR, "EhcWriteOpReg: Pci Io Write error: %r at %d\n", Status, Offset));
126 }
127 }
128
129
130 /**
131 Set one bit of the operational register while keeping other bits.
132
133 @param Ehc The EHCI device.
134 @param Offset The offset of the operational register.
135 @param Bit The bit mask of the register to set.
136
137 **/
138 VOID
139 EhcSetOpRegBit (
140 IN USB2_HC_DEV *Ehc,
141 IN UINT32 Offset,
142 IN UINT32 Bit
143 )
144 {
145 UINT32 Data;
146
147 Data = EhcReadOpReg (Ehc, Offset);
148 Data |= Bit;
149 EhcWriteOpReg (Ehc, Offset, Data);
150 }
151
152
153 /**
154 Clear one bit of the operational register while keeping other bits.
155
156 @param Ehc The EHCI device.
157 @param Offset The offset of the operational register.
158 @param Bit The bit mask of the register to clear.
159
160 **/
161 VOID
162 EhcClearOpRegBit (
163 IN USB2_HC_DEV *Ehc,
164 IN UINT32 Offset,
165 IN UINT32 Bit
166 )
167 {
168 UINT32 Data;
169
170 Data = EhcReadOpReg (Ehc, Offset);
171 Data &= ~Bit;
172 EhcWriteOpReg (Ehc, Offset, Data);
173 }
174
175
176 /**
177 Wait the operation register's bit as specified by Bit
178 to become set (or clear).
179
180 @param Ehc The EHCI device.
181 @param Offset The offset of the operation register.
182 @param Bit The bit of the register to wait for.
183 @param WaitToSet Wait the bit to set or clear.
184 @param Timeout The time to wait before abort (in millisecond).
185
186 @retval EFI_SUCCESS The bit successfully changed by host controller.
187 @retval EFI_TIMEOUT The time out occurred.
188
189 **/
190 EFI_STATUS
191 EhcWaitOpRegBit (
192 IN USB2_HC_DEV *Ehc,
193 IN UINT32 Offset,
194 IN UINT32 Bit,
195 IN BOOLEAN WaitToSet,
196 IN UINT32 Timeout
197 )
198 {
199 UINT32 Index;
200
201 for (Index = 0; Index < Timeout / EHC_SYNC_POLL_INTERVAL + 1; Index++) {
202 if (EHC_REG_BIT_IS_SET (Ehc, Offset, Bit) == WaitToSet) {
203 return EFI_SUCCESS;
204 }
205
206 gBS->Stall (EHC_SYNC_POLL_INTERVAL);
207 }
208
209 return EFI_TIMEOUT;
210 }
211
212
213 /**
214 Add support for UEFI Over Legacy (UoL) feature, stop
215 the legacy USB SMI support.
216
217 @param Ehc The EHCI device.
218
219 **/
220 VOID
221 EhcClearLegacySupport (
222 IN USB2_HC_DEV *Ehc
223 )
224 {
225 UINT32 ExtendCap;
226 EFI_PCI_IO_PROTOCOL *PciIo;
227 UINT32 Value;
228 UINT32 TimeOut;
229
230 DEBUG ((EFI_D_INFO, "EhcClearLegacySupport: called to clear legacy support\n"));
231
232 PciIo = Ehc->PciIo;
233 ExtendCap = (Ehc->HcCapParams >> 8) & 0xFF;
234
235 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
236 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);
237
238 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
239 Value |= (0x1 << 24);
240 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
241
242 TimeOut = 40;
243 while (TimeOut-- != 0) {
244 gBS->Stall (500);
245
246 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
247
248 if ((Value & 0x01010000) == 0x01000000) {
249 break;
250 }
251 }
252
253 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
254 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);
255 }
256
257
258
259 /**
260 Set door bell and wait it to be ACKed by host controller.
261 This function is used to synchronize with the hardware.
262
263 @param Ehc The EHCI device.
264 @param Timeout The time to wait before abort (in millisecond, ms).
265
266 @retval EFI_SUCCESS Synchronized with the hardware.
267 @retval EFI_TIMEOUT Time out happened while waiting door bell to set.
268
269 **/
270 EFI_STATUS
271 EhcSetAndWaitDoorBell (
272 IN USB2_HC_DEV *Ehc,
273 IN UINT32 Timeout
274 )
275 {
276 EFI_STATUS Status;
277 UINT32 Data;
278
279 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_IAAD);
280
281 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_IAA, TRUE, Timeout);
282
283 //
284 // ACK the IAA bit in USBSTS register. Make sure other
285 // interrupt bits are not ACKed. These bits are WC (Write Clean).
286 //
287 Data = EhcReadOpReg (Ehc, EHC_USBSTS_OFFSET);
288 Data &= ~USBSTS_INTACK_MASK;
289 Data |= USBSTS_IAA;
290
291 EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, Data);
292
293 return Status;
294 }
295
296
297 /**
298 Clear all the interrutp status bits, these bits
299 are Write-Clean.
300
301 @param Ehc The EHCI device.
302
303 **/
304 VOID
305 EhcAckAllInterrupt (
306 IN USB2_HC_DEV *Ehc
307 )
308 {
309 EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, USBSTS_INTACK_MASK);
310 }
311
312
313 /**
314 Enable the periodic schedule then wait EHC to
315 actually enable it.
316
317 @param Ehc The EHCI device.
318 @param Timeout The time to wait before abort (in millisecond, ms).
319
320 @retval EFI_SUCCESS The periodical schedule is enabled.
321 @retval EFI_TIMEOUT Time out happened while enabling periodic schedule.
322
323 **/
324 EFI_STATUS
325 EhcEnablePeriodSchd (
326 IN USB2_HC_DEV *Ehc,
327 IN UINT32 Timeout
328 )
329 {
330 EFI_STATUS Status;
331
332 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_PERIOD);
333
334 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_PERIOD_ENABLED, TRUE, Timeout);
335 return Status;
336 }
337
338
339 /**
340 Disable periodic schedule.
341
342 @param Ehc The EHCI device.
343 @param Timeout Time to wait before abort (in millisecond, ms).
344
345 @retval EFI_SUCCESS Periodic schedule is disabled.
346 @retval EFI_DEVICE_ERROR Fail to disable periodic schedule.
347
348 **/
349 EFI_STATUS
350 EhcDisablePeriodSchd (
351 IN USB2_HC_DEV *Ehc,
352 IN UINT32 Timeout
353 )
354 {
355 EFI_STATUS Status;
356
357 EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_PERIOD);
358
359 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_PERIOD_ENABLED, FALSE, Timeout);
360 return Status;
361 }
362
363
364
365 /**
366 Enable asynchrounous schedule.
367
368 @param Ehc The EHCI device.
369 @param Timeout Time to wait before abort.
370
371 @retval EFI_SUCCESS The EHCI asynchronous schedule is enabled.
372 @return Others Failed to enable the asynchronous scheudle.
373
374 **/
375 EFI_STATUS
376 EhcEnableAsyncSchd (
377 IN USB2_HC_DEV *Ehc,
378 IN UINT32 Timeout
379 )
380 {
381 EFI_STATUS Status;
382
383 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_ASYNC);
384
385 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_ASYNC_ENABLED, TRUE, Timeout);
386 return Status;
387 }
388
389
390
391 /**
392 Disable asynchrounous schedule.
393
394 @param Ehc The EHCI device.
395 @param Timeout Time to wait before abort (in millisecond, ms).
396
397 @retval EFI_SUCCESS The asynchronous schedule is disabled.
398 @return Others Failed to disable the asynchronous schedule.
399
400 **/
401 EFI_STATUS
402 EhcDisableAsyncSchd (
403 IN USB2_HC_DEV *Ehc,
404 IN UINT32 Timeout
405 )
406 {
407 EFI_STATUS Status;
408
409 EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_ASYNC);
410
411 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_ASYNC_ENABLED, FALSE, Timeout);
412 return Status;
413 }
414
415
416
417 /**
418 Whether Ehc is halted.
419
420 @param Ehc The EHCI device.
421
422 @retval TRUE The controller is halted.
423 @retval FALSE It isn't halted.
424
425 **/
426 BOOLEAN
427 EhcIsHalt (
428 IN USB2_HC_DEV *Ehc
429 )
430 {
431 return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT);
432 }
433
434
435 /**
436 Whether system error occurred.
437
438 @param Ehc The EHCI device.
439
440 @return TRUE System error happened.
441 @return FALSE No system error.
442
443 **/
444 BOOLEAN
445 EhcIsSysError (
446 IN USB2_HC_DEV *Ehc
447 )
448 {
449 return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR);
450 }
451
452
453 /**
454 Reset the host controller.
455
456 @param Ehc The EHCI device.
457 @param Timeout Time to wait before abort (in millisecond, ms).
458
459 @retval EFI_SUCCESS The host controller is reset.
460 @return Others Failed to reset the host.
461
462 **/
463 EFI_STATUS
464 EhcResetHC (
465 IN USB2_HC_DEV *Ehc,
466 IN UINT32 Timeout
467 )
468 {
469 EFI_STATUS Status;
470
471 //
472 // Host can only be reset when it is halt. If not so, halt it
473 //
474 if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
475 Status = EhcHaltHC (Ehc, Timeout);
476
477 if (EFI_ERROR (Status)) {
478 return Status;
479 }
480 }
481
482 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET);
483 Status = EhcWaitOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET, FALSE, Timeout);
484 return Status;
485 }
486
487
488 /**
489 Halt the host controller.
490
491 @param Ehc The EHCI device.
492 @param Timeout Time to wait before abort.
493
494 @retval EFI_SUCCESS The EHCI is halt.
495 @retval EFI_TIMEOUT Failed to halt the controller before Timeout.
496
497 **/
498 EFI_STATUS
499 EhcHaltHC (
500 IN USB2_HC_DEV *Ehc,
501 IN UINT32 Timeout
502 )
503 {
504 EFI_STATUS Status;
505
506 EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
507 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, TRUE, Timeout);
508 return Status;
509 }
510
511
512 /**
513 Set the EHCI to run.
514
515 @param Ehc The EHCI device.
516 @param Timeout Time to wait before abort.
517
518 @retval EFI_SUCCESS The EHCI is running.
519 @return Others Failed to set the EHCI to run.
520
521 **/
522 EFI_STATUS
523 EhcRunHC (
524 IN USB2_HC_DEV *Ehc,
525 IN UINT32 Timeout
526 )
527 {
528 EFI_STATUS Status;
529
530 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
531 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, FALSE, Timeout);
532 return Status;
533 }
534
535
536 /**
537 Initialize the HC hardware.
538 EHCI spec lists the five things to do to initialize the hardware:
539 1. Program CTRLDSSEGMENT
540 2. Set USBINTR to enable interrupts
541 3. Set periodic list base
542 4. Set USBCMD, interrupt threshold, frame list size etc
543 5. Write 1 to CONFIGFLAG to route all ports to EHCI
544
545 @param Ehc The EHCI device.
546
547 @return EFI_SUCCESS The EHCI has come out of halt state.
548 @return EFI_TIMEOUT Time out happened.
549
550 **/
551 EFI_STATUS
552 EhcInitHC (
553 IN USB2_HC_DEV *Ehc
554 )
555 {
556 EFI_STATUS Status;
557
558 // This ASSERT crashes the BeagleBoard. There is some issue in the USB stack.
559 // This ASSERT needs to be removed so the BeagleBoard will boot. When we fix
560 // the USB stack we can put this ASSERT back in
561 // ASSERT (EhcIsHalt (Ehc));
562
563 //
564 // Allocate the periodic frame and associated memeory
565 // management facilities if not already done.
566 //
567 if (Ehc->PeriodFrame != NULL) {
568 EhcFreeSched (Ehc);
569 }
570
571 Status = EhcInitSched (Ehc);
572
573 if (EFI_ERROR (Status)) {
574 return Status;
575 }
576
577 //
578 // 1. Clear USBINTR to disable all the interrupt. UEFI works by polling
579 //
580 EhcWriteOpReg (Ehc, EHC_USBINTR_OFFSET, 0);
581
582 //
583 // 2. Program periodic frame list, already done in EhcInitSched
584 // 3. Start the Host Controller
585 //
586 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
587
588 //
589 // 4. Set all ports routing to EHC
590 //
591 EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
592
593 //
594 // Wait roothub port power stable
595 //
596 gBS->Stall (EHC_ROOT_PORT_RECOVERY_STALL);
597
598 Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIMEOUT);
599
600 if (EFI_ERROR (Status)) {
601 DEBUG ((EFI_D_ERROR, "EhcInitHC: failed to enable period schedule\n"));
602 return Status;
603 }
604
605 Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIMEOUT);
606
607 if (EFI_ERROR (Status)) {
608 DEBUG ((EFI_D_ERROR, "EhcInitHC: failed to enable async schedule\n"));
609 return Status;
610 }
611
612 return EFI_SUCCESS;
613 }