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