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