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