]> git.proxmox.com Git - mirror_edk2.git/blob - Omap35xxPkg/PciEmulation/PciEmulation.c
ARM Packages: Fixed missing braces (the warning was disabled by GCC)
[mirror_edk2.git] / Omap35xxPkg / PciEmulation / PciEmulation.c
1 /** @file
2
3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "PciEmulation.h"
16
17 EMBEDDED_EXTERNAL_DEVICE *gTPS65950;
18
19 #define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44
20
21 typedef struct {
22 ACPI_HID_DEVICE_PATH AcpiDevicePath;
23 PCI_DEVICE_PATH PciDevicePath;
24 EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
25 } EFI_PCI_IO_DEVICE_PATH;
26
27 typedef struct {
28 UINT32 Signature;
29 EFI_PCI_IO_DEVICE_PATH DevicePath;
30 EFI_PCI_IO_PROTOCOL PciIoProtocol;
31 PCI_TYPE00 *ConfigSpace;
32 PCI_ROOT_BRIDGE RootBridge;
33 UINTN Segment;
34 } EFI_PCI_IO_PRIVATE_DATA;
35
36 #define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o')
37 #define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)
38
39 EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate =
40 {
41 {
42 { ACPI_DEVICE_PATH, ACPI_DP, { sizeof (ACPI_HID_DEVICE_PATH), 0 } },
43 EISA_PNP_ID(0x0A03), // HID
44 0 // UID
45 },
46 {
47 { HARDWARE_DEVICE_PATH, HW_PCI_DP, { sizeof (PCI_DEVICE_PATH), 0 } },
48 0,
49 0
50 },
51 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} }
52 };
53
54 STATIC
55 VOID
56 ConfigureUSBHost (
57 VOID
58 )
59 {
60 EFI_STATUS Status;
61 UINT8 Data = 0;
62
63 // Take USB host out of force-standby mode
64 MmioWrite32 (UHH_SYSCONFIG, UHH_SYSCONFIG_MIDLEMODE_NO_STANDBY
65 | UHH_SYSCONFIG_CLOCKACTIVITY_ON
66 | UHH_SYSCONFIG_SIDLEMODE_NO_STANDBY
67 | UHH_SYSCONFIG_ENAWAKEUP_ENABLE
68 | UHH_SYSCONFIG_AUTOIDLE_ALWAYS_RUN);
69 MmioWrite32 (UHH_HOSTCONFIG, UHH_HOSTCONFIG_P3_CONNECT_STATUS_DISCONNECT
70 | UHH_HOSTCONFIG_P2_CONNECT_STATUS_DISCONNECT
71 | UHH_HOSTCONFIG_P1_CONNECT_STATUS_DISCONNECT
72 | UHH_HOSTCONFIG_ENA_INCR_ALIGN_DISABLE
73 | UHH_HOSTCONFIG_ENA_INCR16_ENABLE
74 | UHH_HOSTCONFIG_ENA_INCR8_ENABLE
75 | UHH_HOSTCONFIG_ENA_INCR4_ENABLE
76 | UHH_HOSTCONFIG_AUTOPPD_ON_OVERCUR_EN_ON
77 | UHH_HOSTCONFIG_P1_ULPI_BYPASS_ULPI_MODE);
78
79 // USB reset (GPIO 147 - Port 5 pin 19) output high
80 MmioAnd32 (GPIO5_BASE + GPIO_OE, ~BIT19);
81 MmioWrite32 (GPIO5_BASE + GPIO_SETDATAOUT, BIT19);
82
83 // Get the Power IC protocol
84 Status = gBS->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);
85 ASSERT_EFI_ERROR (Status);
86
87 // Power the USB PHY
88 Data = VAUX_DEV_GRP_P1;
89 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VAUX2_DEV_GRP), 1, &Data);
90 ASSERT_EFI_ERROR(Status);
91
92 Data = VAUX_DEDICATED_18V;
93 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VAUX2_DEDICATED), 1, &Data);
94 ASSERT_EFI_ERROR (Status);
95
96 // Enable power to the USB hub
97 Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data);
98 ASSERT_EFI_ERROR (Status);
99
100 // LEDAON controls the power to the USB host, PWM is disabled
101 Data &= ~LEDAPWM;
102 Data |= LEDAON;
103
104 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data);
105 ASSERT_EFI_ERROR (Status);
106 }
107
108
109 EFI_STATUS
110 PciIoPollMem (
111 IN EFI_PCI_IO_PROTOCOL *This,
112 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
113 IN UINT8 BarIndex,
114 IN UINT64 Offset,
115 IN UINT64 Mask,
116 IN UINT64 Value,
117 IN UINT64 Delay,
118 OUT UINT64 *Result
119 )
120 {
121 ASSERT (FALSE);
122 return EFI_UNSUPPORTED;
123 }
124
125 EFI_STATUS
126 PciIoPollIo (
127 IN EFI_PCI_IO_PROTOCOL *This,
128 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
129 IN UINT8 BarIndex,
130 IN UINT64 Offset,
131 IN UINT64 Mask,
132 IN UINT64 Value,
133 IN UINT64 Delay,
134 OUT UINT64 *Result
135 )
136 {
137 ASSERT (FALSE);
138 return EFI_UNSUPPORTED;
139 }
140
141 EFI_STATUS
142 PciIoMemRead (
143 IN EFI_PCI_IO_PROTOCOL *This,
144 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
145 IN UINT8 BarIndex,
146 IN UINT64 Offset,
147 IN UINTN Count,
148 IN OUT VOID *Buffer
149 )
150 {
151 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
152
153 return PciRootBridgeIoMemRead (&Private->RootBridge.Io,
154 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
155 Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
156 Count,
157 Buffer
158 );
159 }
160
161 EFI_STATUS
162 PciIoMemWrite (
163 IN EFI_PCI_IO_PROTOCOL *This,
164 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
165 IN UINT8 BarIndex,
166 IN UINT64 Offset,
167 IN UINTN Count,
168 IN OUT VOID *Buffer
169 )
170 {
171 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
172
173 return PciRootBridgeIoMemWrite (&Private->RootBridge.Io,
174 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
175 Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
176 Count,
177 Buffer
178 );
179 }
180
181 EFI_STATUS
182 PciIoIoRead (
183 IN EFI_PCI_IO_PROTOCOL *This,
184 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
185 IN UINT8 BarIndex,
186 IN UINT64 Offset,
187 IN UINTN Count,
188 IN OUT VOID *Buffer
189 )
190 {
191 ASSERT (FALSE);
192 return EFI_UNSUPPORTED;
193 }
194
195 EFI_STATUS
196 PciIoIoWrite (
197 IN EFI_PCI_IO_PROTOCOL *This,
198 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
199 IN UINT8 BarIndex,
200 IN UINT64 Offset,
201 IN UINTN Count,
202 IN OUT VOID *Buffer
203 )
204 {
205 ASSERT (FALSE);
206 return EFI_UNSUPPORTED;
207 }
208
209 EFI_STATUS
210 PciIoPciRead (
211 IN EFI_PCI_IO_PROTOCOL *This,
212 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
213 IN UINT32 Offset,
214 IN UINTN Count,
215 IN OUT VOID *Buffer
216 )
217 {
218 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
219
220 return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
221 Count,
222 TRUE,
223 (PTR)(UINTN)Buffer,
224 TRUE,
225 (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset)
226 );
227 }
228
229 EFI_STATUS
230 PciIoPciWrite (
231 IN EFI_PCI_IO_PROTOCOL *This,
232 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
233 IN UINT32 Offset,
234 IN UINTN Count,
235 IN OUT VOID *Buffer
236 )
237 {
238 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
239
240 return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
241 Count,
242 TRUE,
243 (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset),
244 TRUE,
245 (PTR)(UINTN)Buffer
246 );
247 }
248
249 EFI_STATUS
250 PciIoCopyMem (
251 IN EFI_PCI_IO_PROTOCOL *This,
252 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
253 IN UINT8 DestBarIndex,
254 IN UINT64 DestOffset,
255 IN UINT8 SrcBarIndex,
256 IN UINT64 SrcOffset,
257 IN UINTN Count
258 )
259 {
260 ASSERT (FALSE);
261 return EFI_UNSUPPORTED;
262 }
263
264 EFI_STATUS
265 PciIoMap (
266 IN EFI_PCI_IO_PROTOCOL *This,
267 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
268 IN VOID *HostAddress,
269 IN OUT UINTN *NumberOfBytes,
270 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
271 OUT VOID **Mapping
272 )
273 {
274 DMA_MAP_OPERATION DmaOperation;
275
276 if (Operation == EfiPciIoOperationBusMasterRead) {
277 DmaOperation = MapOperationBusMasterRead;
278 } else if (Operation == EfiPciIoOperationBusMasterWrite) {
279 DmaOperation = MapOperationBusMasterWrite;
280 } else if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
281 DmaOperation = MapOperationBusMasterCommonBuffer;
282 } else {
283 return EFI_INVALID_PARAMETER;
284 }
285 return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
286 }
287
288 EFI_STATUS
289 PciIoUnmap (
290 IN EFI_PCI_IO_PROTOCOL *This,
291 IN VOID *Mapping
292 )
293 {
294 return DmaUnmap (Mapping);
295 }
296
297 EFI_STATUS
298 PciIoAllocateBuffer (
299 IN EFI_PCI_IO_PROTOCOL *This,
300 IN EFI_ALLOCATE_TYPE Type,
301 IN EFI_MEMORY_TYPE MemoryType,
302 IN UINTN Pages,
303 OUT VOID **HostAddress,
304 IN UINT64 Attributes
305 )
306 {
307 if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
308 // Check this
309 return EFI_UNSUPPORTED;
310 }
311
312 return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
313 }
314
315
316 EFI_STATUS
317 PciIoFreeBuffer (
318 IN EFI_PCI_IO_PROTOCOL *This,
319 IN UINTN Pages,
320 IN VOID *HostAddress
321 )
322 {
323 return DmaFreeBuffer (Pages, HostAddress);
324 }
325
326
327 EFI_STATUS
328 PciIoFlush (
329 IN EFI_PCI_IO_PROTOCOL *This
330 )
331 {
332 return EFI_SUCCESS;
333 }
334
335 EFI_STATUS
336 PciIoGetLocation (
337 IN EFI_PCI_IO_PROTOCOL *This,
338 OUT UINTN *SegmentNumber,
339 OUT UINTN *BusNumber,
340 OUT UINTN *DeviceNumber,
341 OUT UINTN *FunctionNumber
342 )
343 {
344 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
345
346 if (SegmentNumber != NULL) {
347 *SegmentNumber = Private->Segment;
348 }
349
350 if (BusNumber != NULL) {
351 *BusNumber = 0xff;
352 }
353
354 if (DeviceNumber != NULL) {
355 *DeviceNumber = 0;
356 }
357
358 if (FunctionNumber != NULL) {
359 *FunctionNumber = 0;
360 }
361
362 return EFI_SUCCESS;
363 }
364
365 EFI_STATUS
366 PciIoAttributes (
367 IN EFI_PCI_IO_PROTOCOL *This,
368 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
369 IN UINT64 Attributes,
370 OUT UINT64 *Result OPTIONAL
371 )
372 {
373 switch (Operation) {
374 case EfiPciIoAttributeOperationGet:
375 case EfiPciIoAttributeOperationSupported:
376 if (Result == NULL) {
377 return EFI_INVALID_PARAMETER;
378 }
379 // We are not a real PCI device so just say things we kind of do
380 *Result = EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_DEVICE_ENABLE;
381 break;
382
383 case EfiPciIoAttributeOperationSet:
384 case EfiPciIoAttributeOperationEnable:
385 case EfiPciIoAttributeOperationDisable:
386 // Since we are not a real PCI device no enable/set or disable operations exist.
387 return EFI_SUCCESS;
388
389 default:
390 ASSERT (FALSE);
391 return EFI_INVALID_PARAMETER;
392 };
393 return EFI_SUCCESS;
394 }
395
396 EFI_STATUS
397 PciIoGetBarAttributes (
398 IN EFI_PCI_IO_PROTOCOL *This,
399 IN UINT8 BarIndex,
400 OUT UINT64 *Supports, OPTIONAL
401 OUT VOID **Resources OPTIONAL
402 )
403 {
404 ASSERT (FALSE);
405 return EFI_UNSUPPORTED;
406 }
407
408 EFI_STATUS
409 PciIoSetBarAttributes (
410 IN EFI_PCI_IO_PROTOCOL *This,
411 IN UINT64 Attributes,
412 IN UINT8 BarIndex,
413 IN OUT UINT64 *Offset,
414 IN OUT UINT64 *Length
415 )
416 {
417 ASSERT (FALSE);
418 return EFI_UNSUPPORTED;
419 }
420
421 EFI_PCI_IO_PROTOCOL PciIoTemplate =
422 {
423 PciIoPollMem,
424 PciIoPollIo,
425 { PciIoMemRead, PciIoMemWrite },
426 { PciIoIoRead, PciIoIoWrite },
427 { PciIoPciRead, PciIoPciWrite },
428 PciIoCopyMem,
429 PciIoMap,
430 PciIoUnmap,
431 PciIoAllocateBuffer,
432 PciIoFreeBuffer,
433 PciIoFlush,
434 PciIoGetLocation,
435 PciIoAttributes,
436 PciIoGetBarAttributes,
437 PciIoSetBarAttributes,
438 0,
439 0
440 };
441
442 EFI_STATUS
443 EFIAPI
444 PciEmulationEntryPoint (
445 IN EFI_HANDLE ImageHandle,
446 IN EFI_SYSTEM_TABLE *SystemTable
447 )
448 {
449 EFI_STATUS Status;
450 EFI_HANDLE Handle;
451 EFI_PCI_IO_PRIVATE_DATA *Private;
452 UINT8 CapabilityLength;
453 UINT8 PhysicalPorts;
454 UINTN Count;
455
456
457 //Configure USB host for OMAP3530.
458 ConfigureUSBHost();
459
460 // Create a private structure
461 Private = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA));
462 if (Private == NULL) {
463 Status = EFI_OUT_OF_RESOURCES;
464 return Status;
465 }
466
467 Private->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature
468 Private->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too
469 Private->RootBridge.MemoryStart = USB_EHCI_HCCAPBASE; // Get the USB capability register base
470 Private->Segment = 0; // Default to segment zero
471
472 // Find out the capability register length and number of physical ports.
473 CapabilityLength = MmioRead8(Private->RootBridge.MemoryStart);
474 PhysicalPorts = (MmioRead32 (Private->RootBridge.MemoryStart + 0x4)) & 0x0000000F;
475
476 // Calculate the total size of the USB registers.
477 Private->RootBridge.MemorySize = CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1));
478
479 // Enable Port Power bit in Port status and control registers in EHCI register space.
480 // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates
481 // host controller implementation includes port power control.
482 for (Count = 0; Count < PhysicalPorts; Count++) {
483 MmioOr32 ((Private->RootBridge.MemoryStart + CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE + 4*Count), 0x00001000);
484 }
485
486 // Create fake PCI config space.
487 Private->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00));
488 if (Private->ConfigSpace == NULL) {
489 Status = EFI_OUT_OF_RESOURCES;
490 FreePool(Private);
491 return Status;
492 }
493
494 // Configure PCI config space
495 Private->ConfigSpace->Hdr.VendorId = 0x3530;
496 Private->ConfigSpace->Hdr.DeviceId = 0x3530;
497 Private->ConfigSpace->Hdr.ClassCode[0] = 0x20;
498 Private->ConfigSpace->Hdr.ClassCode[1] = 0x03;
499 Private->ConfigSpace->Hdr.ClassCode[2] = 0x0C;
500 Private->ConfigSpace->Device.Bar[0] = Private->RootBridge.MemoryStart;
501
502 Handle = NULL;
503
504 // Unique device path.
505 CopyMem(&Private->DevicePath, &PciIoDevicePathTemplate, sizeof(PciIoDevicePathTemplate));
506 Private->DevicePath.AcpiDevicePath.UID = 0;
507
508 // Copy protocol structure
509 CopyMem(&Private->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate));
510
511 Status = gBS->InstallMultipleProtocolInterfaces(&Handle,
512 &gEfiPciIoProtocolGuid, &Private->PciIoProtocol,
513 &gEfiDevicePathProtocolGuid, &Private->DevicePath,
514 NULL);
515 if (EFI_ERROR(Status)) {
516 DEBUG((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n"));
517 }
518
519 return Status;
520 }
521