]> git.proxmox.com Git - mirror_edk2.git/blob - Omap35xxPkg/PciEmulation/PciEmulation.c
Clean up OMAP DMA lib and split into generic DMA lib based on PCI_IO DMA abstractions...
[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 //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
98
99 EFI_STATUS
100 PciIoPollMem (
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
115 EFI_STATUS
116 PciIoPollIo (
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
131 EFI_STATUS
132 PciIoMemRead (
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
151 EFI_STATUS
152 PciIoMemWrite (
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
171 EFI_STATUS
172 PciIoIoRead (
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
185 EFI_STATUS
186 PciIoIoWrite (
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
199 EFI_STATUS
200 PciIoPciRead (
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
219 EFI_STATUS
220 PciIoPciWrite (
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
239 EFI_STATUS
240 PciIoCopyMem (
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
254 EFI_STATUS
255 PciIoMap (
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 {
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 {
273 return EFI_INVALID_PARAMETER;
274 }
275 return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
276 }
277
278 EFI_STATUS
279 PciIoUnmap (
280 IN EFI_PCI_IO_PROTOCOL *This,
281 IN VOID *Mapping
282 )
283 {
284 return DmaUnmap (Mapping);
285 }
286
287 EFI_STATUS
288 PciIoAllocateBuffer (
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) {
298 // Check this
299 return EFI_UNSUPPORTED;
300 }
301
302 return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
303 }
304
305
306 EFI_STATUS
307 PciIoFreeBuffer (
308 IN EFI_PCI_IO_PROTOCOL *This,
309 IN UINTN Pages,
310 IN VOID *HostAddress
311 )
312 {
313 return DmaFreeBuffer (Pages, HostAddress);
314 }
315
316
317 EFI_STATUS
318 PciIoFlush (
319 IN EFI_PCI_IO_PROTOCOL *This
320 )
321 {
322 return EFI_SUCCESS;
323 }
324
325 EFI_STATUS
326 PciIoGetLocation (
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
355 EFI_STATUS
356 PciIoAttributes (
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
386 EFI_STATUS
387 PciIoGetBarAttributes (
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
398 EFI_STATUS
399 PciIoSetBarAttributes (
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
411 EFI_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
435 EFI_STATUS
436 EFIAPI
437 PciEmulationEntryPoint (
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
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);
467 PhysicalPorts = (MmioRead32 (Private->RootBridge.MemoryStart + 0x4)) & 0x0000000F;
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++) {
476 MmioOr32 ((Private->RootBridge.MemoryStart + CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE + 4*Count), 0x00001000);
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