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