]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/UhciDxe/UhciReg.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UhciDxe / UhciReg.c
1 /** @file
2
3 The UHCI register operation routines.
4
5 Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "Uhci.h"
11
12 /**
13 Read a UHCI register.
14
15 @param PciIo The EFI_PCI_IO_PROTOCOL to use.
16 @param Offset Register offset to USB_BAR_INDEX.
17
18 @return Content of register.
19
20 **/
21 UINT16
22 UhciReadReg (
23 IN EFI_PCI_IO_PROTOCOL *PciIo,
24 IN UINT32 Offset
25 )
26 {
27 UINT16 Data;
28 EFI_STATUS Status;
29
30 Status = PciIo->Io.Read (
31 PciIo,
32 EfiPciIoWidthUint16,
33 USB_BAR_INDEX,
34 Offset,
35 1,
36 &Data
37 );
38
39 if (EFI_ERROR (Status)) {
40 DEBUG ((DEBUG_ERROR, "UhciReadReg: PciIo Io.Read error: %r at offset %d\n", Status, Offset));
41
42 Data = 0xFFFF;
43 }
44
45 return Data;
46 }
47
48 /**
49 Write data to UHCI register.
50
51 @param PciIo The EFI_PCI_IO_PROTOCOL to use.
52 @param Offset Register offset to USB_BAR_INDEX.
53 @param Data Data to write.
54
55 **/
56 VOID
57 UhciWriteReg (
58 IN EFI_PCI_IO_PROTOCOL *PciIo,
59 IN UINT32 Offset,
60 IN UINT16 Data
61 )
62 {
63 EFI_STATUS Status;
64
65 Status = PciIo->Io.Write (
66 PciIo,
67 EfiPciIoWidthUint16,
68 USB_BAR_INDEX,
69 Offset,
70 1,
71 &Data
72 );
73
74 if (EFI_ERROR (Status)) {
75 DEBUG ((DEBUG_ERROR, "UhciWriteReg: PciIo Io.Write error: %r at offset %d\n", Status, Offset));
76 }
77 }
78
79 /**
80 Set a bit of the UHCI Register.
81
82 @param PciIo The EFI_PCI_IO_PROTOCOL to use.
83 @param Offset Register offset to USB_BAR_INDEX.
84 @param Bit The bit to set.
85
86 **/
87 VOID
88 UhciSetRegBit (
89 IN EFI_PCI_IO_PROTOCOL *PciIo,
90 IN UINT32 Offset,
91 IN UINT16 Bit
92 )
93 {
94 UINT16 Data;
95
96 Data = UhciReadReg (PciIo, Offset);
97 Data = (UINT16)(Data |Bit);
98 UhciWriteReg (PciIo, Offset, Data);
99 }
100
101 /**
102 Clear a bit of the UHCI Register.
103
104 @param PciIo The PCI_IO protocol to access the PCI.
105 @param Offset Register offset to USB_BAR_INDEX.
106 @param Bit The bit to clear.
107
108 **/
109 VOID
110 UhciClearRegBit (
111 IN EFI_PCI_IO_PROTOCOL *PciIo,
112 IN UINT32 Offset,
113 IN UINT16 Bit
114 )
115 {
116 UINT16 Data;
117
118 Data = UhciReadReg (PciIo, Offset);
119 Data = (UINT16)(Data & ~Bit);
120 UhciWriteReg (PciIo, Offset, Data);
121 }
122
123 /**
124 Clear all the interrutp status bits, these bits
125 are Write-Clean.
126
127 @param Uhc The UHCI device.
128
129 **/
130 VOID
131 UhciAckAllInterrupt (
132 IN USB_HC_DEV *Uhc
133 )
134 {
135 UhciWriteReg (Uhc->PciIo, USBSTS_OFFSET, 0x3F);
136
137 //
138 // If current HC is halted, re-enable it. Host Controller Process Error
139 // is a temporary error status.
140 //
141 if (!UhciIsHcWorking (Uhc->PciIo)) {
142 DEBUG ((DEBUG_ERROR, "UhciAckAllInterrupt: re-enable the UHCI from system error\n"));
143 Uhc->Usb2Hc.SetState (&Uhc->Usb2Hc, EfiUsbHcStateOperational);
144 }
145 }
146
147 /**
148 Stop the host controller.
149
150 @param Uhc The UHCI device.
151 @param Timeout Max time allowed.
152
153 @retval EFI_SUCCESS The host controller is stopped.
154 @retval EFI_TIMEOUT Failed to stop the host controller.
155
156 **/
157 EFI_STATUS
158 UhciStopHc (
159 IN USB_HC_DEV *Uhc,
160 IN UINTN Timeout
161 )
162 {
163 UINT16 UsbSts;
164 UINTN Index;
165
166 UhciClearRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_RS);
167
168 //
169 // ensure the HC is in halt status after send the stop command
170 // Timeout is in us unit.
171 //
172 for (Index = 0; Index < (Timeout / 50) + 1; Index++) {
173 UsbSts = UhciReadReg (Uhc->PciIo, USBSTS_OFFSET);
174
175 if ((UsbSts & USBSTS_HCH) == USBSTS_HCH) {
176 return EFI_SUCCESS;
177 }
178
179 gBS->Stall (50);
180 }
181
182 return EFI_TIMEOUT;
183 }
184
185 /**
186 Check whether the host controller operates well.
187
188 @param PciIo The PCI_IO protocol to use.
189
190 @retval TRUE Host controller is working.
191 @retval FALSE Host controller is halted or system error.
192
193 **/
194 BOOLEAN
195 UhciIsHcWorking (
196 IN EFI_PCI_IO_PROTOCOL *PciIo
197 )
198 {
199 UINT16 UsbSts;
200
201 UsbSts = UhciReadReg (PciIo, USBSTS_OFFSET);
202
203 if ((UsbSts & (USBSTS_HCPE | USBSTS_HSE | USBSTS_HCH)) != 0) {
204 DEBUG ((DEBUG_ERROR, "UhciIsHcWorking: current USB state is %x\n", UsbSts));
205 return FALSE;
206 }
207
208 return TRUE;
209 }
210
211 /**
212 Set the UHCI frame list base address. It can't use
213 UhciWriteReg which access memory in UINT16.
214
215 @param PciIo The EFI_PCI_IO_PROTOCOL to use.
216 @param Addr Address to set.
217
218 **/
219 VOID
220 UhciSetFrameListBaseAddr (
221 IN EFI_PCI_IO_PROTOCOL *PciIo,
222 IN VOID *Addr
223 )
224 {
225 EFI_STATUS Status;
226 UINT32 Data;
227
228 Data = (UINT32)((UINTN)Addr & 0xFFFFF000);
229
230 Status = PciIo->Io.Write (
231 PciIo,
232 EfiPciIoWidthUint32,
233 USB_BAR_INDEX,
234 (UINT64)USB_FRAME_BASE_OFFSET,
235 1,
236 &Data
237 );
238
239 if (EFI_ERROR (Status)) {
240 DEBUG ((DEBUG_ERROR, "UhciSetFrameListBaseAddr: PciIo Io.Write error: %r\n", Status));
241 }
242 }
243
244 /**
245 Disable USB Emulation.
246
247 @param PciIo The EFI_PCI_IO_PROTOCOL protocol to use.
248
249 **/
250 VOID
251 UhciTurnOffUsbEmulation (
252 IN EFI_PCI_IO_PROTOCOL *PciIo
253 )
254 {
255 UINT16 Command;
256
257 Command = 0;
258
259 PciIo->Pci.Write (
260 PciIo,
261 EfiPciIoWidthUint16,
262 USB_EMULATION_OFFSET,
263 1,
264 &Command
265 );
266 }