]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c
Save original PCI attributes in start() function and restore it in Stop() for those...
[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_INTERVAL + 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_INTERVAL);
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 EFI_STATUS
372 EhcDisablePeriodSchd (
373 IN USB2_HC_DEV *Ehc,
374 IN UINT32 Timeout
375 )
376 {
377 EFI_STATUS Status;
378
379 EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_PERIOD);
380
381 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_PERIOD_ENABLED, FALSE, Timeout);
382 return Status;
383 }
384
385
386
387 /**
388 Enable asynchrounous schedule
389
390 @param Ehc The EHCI device
391 @param Timeout Time to wait before abort
392
393 @return EFI_SUCCESS : The EHCI asynchronous schedule is enabled
394 @return Others : Failed to enable the asynchronous scheudle
395
396 **/
397 STATIC
398 EFI_STATUS
399 EhcEnableAsyncSchd (
400 IN USB2_HC_DEV *Ehc,
401 IN UINT32 Timeout
402 )
403 {
404 EFI_STATUS Status;
405
406 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_ASYNC);
407
408 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_ASYNC_ENABLED, TRUE, Timeout);
409 return Status;
410 }
411
412
413
414 /**
415 Disable asynchrounous schedule
416
417 @param Ehc The EHCI device
418 @param Timeout Time to wait before abort (in millisecond, ms)
419
420 @return EFI_SUCCESS : The asynchronous schedule is disabled
421 @return Others : Failed to disable the asynchronous schedule
422
423 **/
424 EFI_STATUS
425 EhcDisableAsyncSchd (
426 IN USB2_HC_DEV *Ehc,
427 IN UINT32 Timeout
428 )
429 {
430 EFI_STATUS Status;
431
432 EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_ASYNC);
433
434 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_ASYNC_ENABLED, FALSE, Timeout);
435 return Status;
436 }
437
438
439
440 /**
441 Whether Ehc is halted
442
443 @param Ehc The EHCI device
444
445 @return TRUE : The controller is halted
446 @return FALSE : It isn't halted
447
448 **/
449 BOOLEAN
450 EhcIsHalt (
451 IN USB2_HC_DEV *Ehc
452 )
453 {
454 return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT);
455 }
456
457
458 /**
459 Whether system error occurred
460
461 @param Ehc The EHCI device
462
463 @return TRUE : System error happened
464 @return FALSE : No system error
465
466 **/
467 BOOLEAN
468 EhcIsSysError (
469 IN USB2_HC_DEV *Ehc
470 )
471 {
472 return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR);
473 }
474
475
476 /**
477 Reset the host controller
478
479 @param Ehc The EHCI device
480 @param Timeout Time to wait before abort (in millisecond, ms)
481
482 @return EFI_SUCCESS : The host controller is reset
483 @return Others : Failed to reset the host
484
485 **/
486 EFI_STATUS
487 EhcResetHC (
488 IN USB2_HC_DEV *Ehc,
489 IN UINT32 Timeout
490 )
491 {
492 EFI_STATUS Status;
493
494 //
495 // Host can only be reset when it is halt. If not so, halt it
496 //
497 if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
498 Status = EhcHaltHC (Ehc, Timeout);
499
500 if (EFI_ERROR (Status)) {
501 return Status;
502 }
503 }
504
505 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET);
506 Status = EhcWaitOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET, FALSE, Timeout);
507 return Status;
508 }
509
510
511 /**
512 Halt the host controller
513
514 @param Ehc The EHCI device
515 @param Timeout Time to wait before abort
516
517 @return EFI_SUCCESS : The EHCI is halt
518 @return EFI_TIMEOUT : Failed to halt the controller before Timeout
519
520 **/
521 EFI_STATUS
522 EhcHaltHC (
523 IN USB2_HC_DEV *Ehc,
524 IN UINT32 Timeout
525 )
526 {
527 EFI_STATUS Status;
528
529 EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
530 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, TRUE, Timeout);
531 return Status;
532 }
533
534
535 /**
536 Set the EHCI to run
537
538 @param Ehc The EHCI device
539 @param Timeout Time to wait before abort
540
541 @return EFI_SUCCESS : The EHCI is running
542 @return Others : Failed to set the EHCI to run
543
544 **/
545 EFI_STATUS
546 EhcRunHC (
547 IN USB2_HC_DEV *Ehc,
548 IN UINT32 Timeout
549 )
550 {
551 EFI_STATUS Status;
552
553 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
554 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, FALSE, Timeout);
555 return Status;
556 }
557
558
559 /**
560 Initialize the HC hardware.
561 EHCI spec lists the five things to do to initialize the hardware
562 1. Program CTRLDSSEGMENT
563 2. Set USBINTR to enable interrupts
564 3. Set periodic list base
565 4. Set USBCMD, interrupt threshold, frame list size etc
566 5. Write 1 to CONFIGFLAG to route all ports to EHCI
567
568 @param Ehc The EHCI device
569
570 @return EFI_SUCCESS : The EHCI has come out of halt state
571 @return EFI_TIMEOUT : Time out happened
572
573 **/
574 EFI_STATUS
575 EhcInitHC (
576 IN USB2_HC_DEV *Ehc
577 )
578 {
579 EFI_STATUS Status;
580
581 ASSERT (EhcIsHalt (Ehc));
582
583 //
584 // Allocate the periodic frame and associated memeory
585 // management facilities if not already done.
586 //
587 if (Ehc->PeriodFrame != NULL) {
588 EhcFreeSched (Ehc);
589 }
590
591 Status = EhcInitSched (Ehc);
592
593 if (EFI_ERROR (Status)) {
594 return Status;
595 }
596 //
597 // 1. Program the CTRLDSSEGMENT register with the high 32 bit addr
598 //
599 EhcWriteOpReg (Ehc, EHC_CTRLDSSEG_OFFSET, Ehc->High32bitAddr);
600
601 //
602 // 2. Clear USBINTR to disable all the interrupt. UEFI works by polling
603 //
604 EhcWriteOpReg (Ehc, EHC_USBINTR_OFFSET, 0);
605
606 //
607 // 3. Program periodic frame list, already done in EhcInitSched
608 // 4. Start the Host Controller
609 //
610 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
611
612 //
613 // 5. Set all ports routing to EHC
614 //
615 EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
616
617 //
618 // Wait roothub port power stable
619 //
620 gBS->Stall (EHC_ROOT_PORT_RECOVERY_STALL);
621
622 Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIMEOUT);
623
624 if (EFI_ERROR (Status)) {
625 EHC_ERROR (("EhcInitHC: failed to enable period schedule\n"));
626 return Status;
627 }
628
629 Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIMEOUT);
630
631 if (EFI_ERROR (Status)) {
632 EHC_ERROR (("EhcInitHC: failed to enable async schedule\n"));
633 return Status;
634 }
635
636 return EFI_SUCCESS;
637 }