]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciEmulation.c
ArmPlatformPkg/ArmJunoPkg: Added Juno development board support
[mirror_edk2.git] / ArmPlatformPkg / ArmJunoPkg / Drivers / ArmJunoDxe / PciEmulation.c
1 /** @file
2
3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4 Copyright (c) 2013 - 2014, ARM Ltd. All rights reserved.<BR>
5
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 "PciEmulation.h"
17
18 #define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44
19
20 typedef struct {
21 ACPI_HID_DEVICE_PATH AcpiDevicePath;
22 PCI_DEVICE_PATH PciDevicePath;
23 EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
24 } EFI_PCI_IO_DEVICE_PATH;
25
26 typedef struct {
27 UINT32 Signature;
28 EFI_PCI_IO_DEVICE_PATH DevicePath;
29 EFI_PCI_IO_PROTOCOL PciIoProtocol;
30 PCI_TYPE00 *ConfigSpace;
31 PCI_ROOT_BRIDGE RootBridge;
32 UINTN Segment;
33 } EFI_PCI_IO_PRIVATE_DATA;
34
35 #define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o')
36 #define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)
37
38 EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate =
39 {
40 {
41 { ACPI_DEVICE_PATH, ACPI_DP, { sizeof (ACPI_HID_DEVICE_PATH), 0 } },
42 EISA_PNP_ID(0x0A03), // HID
43 0 // UID
44 },
45 {
46 { HARDWARE_DEVICE_PATH, HW_PCI_DP, { sizeof (PCI_DEVICE_PATH), 0 } },
47 0,
48 0
49 },
50 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} }
51 };
52
53 STATIC
54 VOID
55 ConfigureUSBHost (
56 VOID
57 )
58 {
59 }
60
61
62 EFI_STATUS
63 PciIoPollMem (
64 IN EFI_PCI_IO_PROTOCOL *This,
65 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
66 IN UINT8 BarIndex,
67 IN UINT64 Offset,
68 IN UINT64 Mask,
69 IN UINT64 Value,
70 IN UINT64 Delay,
71 OUT UINT64 *Result
72 )
73 {
74 ASSERT (FALSE);
75 return EFI_UNSUPPORTED;
76 }
77
78 EFI_STATUS
79 PciIoPollIo (
80 IN EFI_PCI_IO_PROTOCOL *This,
81 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
82 IN UINT8 BarIndex,
83 IN UINT64 Offset,
84 IN UINT64 Mask,
85 IN UINT64 Value,
86 IN UINT64 Delay,
87 OUT UINT64 *Result
88 )
89 {
90 ASSERT (FALSE);
91 return EFI_UNSUPPORTED;
92 }
93
94 EFI_STATUS
95 PciIoMemRead (
96 IN EFI_PCI_IO_PROTOCOL *This,
97 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
98 IN UINT8 BarIndex,
99 IN UINT64 Offset,
100 IN UINTN Count,
101 IN OUT VOID *Buffer
102 )
103 {
104 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
105
106 return PciRootBridgeIoMemRead (&Private->RootBridge.Io,
107 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
108 Private->ConfigSpace->Device.Bar[BarIndex] + Offset, //Fix me ConfigSpace
109 Count,
110 Buffer
111 );
112 }
113
114 EFI_STATUS
115 PciIoMemWrite (
116 IN EFI_PCI_IO_PROTOCOL *This,
117 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
118 IN UINT8 BarIndex,
119 IN UINT64 Offset,
120 IN UINTN Count,
121 IN OUT VOID *Buffer
122 )
123 {
124 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
125
126 return PciRootBridgeIoMemWrite (&Private->RootBridge.Io,
127 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
128 Private->ConfigSpace->Device.Bar[BarIndex] + Offset, //Fix me ConfigSpace
129 Count,
130 Buffer
131 );
132 }
133
134 EFI_STATUS
135 PciIoIoRead (
136 IN EFI_PCI_IO_PROTOCOL *This,
137 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
138 IN UINT8 BarIndex,
139 IN UINT64 Offset,
140 IN UINTN Count,
141 IN OUT VOID *Buffer
142 )
143 {
144 ASSERT (FALSE);
145 return EFI_UNSUPPORTED;
146 }
147
148 EFI_STATUS
149 PciIoIoWrite (
150 IN EFI_PCI_IO_PROTOCOL *This,
151 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
152 IN UINT8 BarIndex,
153 IN UINT64 Offset,
154 IN UINTN Count,
155 IN OUT VOID *Buffer
156 )
157 {
158 ASSERT (FALSE);
159 return EFI_UNSUPPORTED;
160 }
161
162 EFI_STATUS
163 PciIoPciRead (
164 IN EFI_PCI_IO_PROTOCOL *This,
165 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
166 IN UINT32 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 EFI_STATUS Status;
173
174 Status = PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
175 Count,
176 TRUE,
177 (PTR)(UINTN)Buffer,
178 TRUE,
179 (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset) //Fix me ConfigSpace
180 );
181 return Status;
182 }
183
184 EFI_STATUS
185 PciIoPciWrite (
186 IN EFI_PCI_IO_PROTOCOL *This,
187 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
188 IN UINT32 Offset,
189 IN UINTN Count,
190 IN OUT VOID *Buffer
191 )
192 {
193 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
194
195 return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
196 Count,
197 TRUE,
198 (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset), //Fix me ConfigSpace
199 TRUE,
200 (PTR)(UINTN)Buffer
201 );
202 }
203
204 EFI_STATUS
205 PciIoCopyMem (
206 IN EFI_PCI_IO_PROTOCOL *This,
207 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
208 IN UINT8 DestBarIndex,
209 IN UINT64 DestOffset,
210 IN UINT8 SrcBarIndex,
211 IN UINT64 SrcOffset,
212 IN UINTN Count
213 )
214 {
215 ASSERT (FALSE);
216 return EFI_UNSUPPORTED;
217 }
218
219 EFI_STATUS
220 PciIoMap (
221 IN EFI_PCI_IO_PROTOCOL *This,
222 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
223 IN VOID *HostAddress,
224 IN OUT UINTN *NumberOfBytes,
225 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
226 OUT VOID **Mapping
227 )
228 {
229 DMA_MAP_OPERATION DmaOperation;
230
231 if (Operation == EfiPciIoOperationBusMasterRead) {
232 DmaOperation = MapOperationBusMasterRead;
233 } else if (Operation == EfiPciIoOperationBusMasterWrite) {
234 DmaOperation = MapOperationBusMasterWrite;
235 } else if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
236 DmaOperation = MapOperationBusMasterCommonBuffer;
237 } else {
238 return EFI_INVALID_PARAMETER;
239 }
240 return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
241 }
242
243 EFI_STATUS
244 PciIoUnmap (
245 IN EFI_PCI_IO_PROTOCOL *This,
246 IN VOID *Mapping
247 )
248 {
249 return DmaUnmap (Mapping);
250 }
251
252 EFI_STATUS
253 PciIoAllocateBuffer (
254 IN EFI_PCI_IO_PROTOCOL *This,
255 IN EFI_ALLOCATE_TYPE Type,
256 IN EFI_MEMORY_TYPE MemoryType,
257 IN UINTN Pages,
258 OUT VOID **HostAddress,
259 IN UINT64 Attributes
260 )
261 {
262 if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
263 // Check this
264 return EFI_UNSUPPORTED;
265 }
266
267 return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
268 }
269
270
271 EFI_STATUS
272 PciIoFreeBuffer (
273 IN EFI_PCI_IO_PROTOCOL *This,
274 IN UINTN Pages,
275 IN VOID *HostAddress
276 )
277 {
278 return DmaFreeBuffer (Pages, HostAddress);
279 }
280
281
282 EFI_STATUS
283 PciIoFlush (
284 IN EFI_PCI_IO_PROTOCOL *This
285 )
286 {
287 return EFI_SUCCESS;
288 }
289
290 EFI_STATUS
291 PciIoGetLocation (
292 IN EFI_PCI_IO_PROTOCOL *This,
293 OUT UINTN *SegmentNumber,
294 OUT UINTN *BusNumber,
295 OUT UINTN *DeviceNumber,
296 OUT UINTN *FunctionNumber
297 )
298 {
299 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
300
301 if (SegmentNumber != NULL) {
302 *SegmentNumber = Private->Segment;
303 }
304
305 if (BusNumber != NULL) {
306 *BusNumber = 0xff;
307 }
308
309 if (DeviceNumber != NULL) {
310 *DeviceNumber = 0;
311 }
312
313 if (FunctionNumber != NULL) {
314 *FunctionNumber = 0;
315 }
316
317 return EFI_SUCCESS;
318 }
319
320 EFI_STATUS
321 PciIoAttributes (
322 IN EFI_PCI_IO_PROTOCOL *This,
323 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
324 IN UINT64 Attributes,
325 OUT UINT64 *Result OPTIONAL
326 )
327 {
328 switch (Operation) {
329 case EfiPciIoAttributeOperationGet:
330 case EfiPciIoAttributeOperationSupported:
331 if (Result == NULL) {
332 return EFI_INVALID_PARAMETER;
333 }
334 // We are not a real PCI device so just say things we kind of do
335 *Result = EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_DEVICE_ENABLE;
336 break;
337
338 case EfiPciIoAttributeOperationSet:
339 case EfiPciIoAttributeOperationEnable:
340 case EfiPciIoAttributeOperationDisable:
341 // Since we are not a real PCI device no enable/set or disable operations exist.
342 return EFI_SUCCESS;
343
344 default:
345 ASSERT (FALSE);
346 return EFI_INVALID_PARAMETER;
347 };
348 return EFI_SUCCESS;
349 }
350
351 EFI_STATUS
352 PciIoGetBarAttributes (
353 IN EFI_PCI_IO_PROTOCOL *This,
354 IN UINT8 BarIndex,
355 OUT UINT64 *Supports, OPTIONAL
356 OUT VOID **Resources OPTIONAL
357 )
358 {
359 ASSERT (FALSE);
360 return EFI_UNSUPPORTED;
361 }
362
363 EFI_STATUS
364 PciIoSetBarAttributes (
365 IN EFI_PCI_IO_PROTOCOL *This,
366 IN UINT64 Attributes,
367 IN UINT8 BarIndex,
368 IN OUT UINT64 *Offset,
369 IN OUT UINT64 *Length
370 )
371 {
372 ASSERT (FALSE);
373 return EFI_UNSUPPORTED;
374 }
375
376 EFI_PCI_IO_PROTOCOL PciIoTemplate =
377 {
378 PciIoPollMem,
379 PciIoPollIo,
380 { PciIoMemRead, PciIoMemWrite },
381 { PciIoIoRead, PciIoIoWrite },
382 { PciIoPciRead, PciIoPciWrite },
383 PciIoCopyMem,
384 PciIoMap,
385 PciIoUnmap,
386 PciIoAllocateBuffer,
387 PciIoFreeBuffer,
388 PciIoFlush,
389 PciIoGetLocation,
390 PciIoAttributes,
391 PciIoGetBarAttributes,
392 PciIoSetBarAttributes,
393 0,
394 0
395 };
396
397 EFI_STATUS
398 PciInstallDevice (
399 IN UINTN DeviceId,
400 IN PHYSICAL_ADDRESS MemoryStart,
401 IN UINT64 MemorySize,
402 IN UINTN ClassCode1,
403 IN UINTN ClassCode2,
404 IN UINTN ClassCode3
405 )
406 {
407 EFI_STATUS Status;
408 EFI_HANDLE Handle;
409 EFI_PCI_IO_PRIVATE_DATA *Private;
410
411 // Configure USB host
412 ConfigureUSBHost ();
413
414 // Create a private structure
415 Private = AllocatePool (sizeof (EFI_PCI_IO_PRIVATE_DATA));
416 if (Private == NULL) {
417 Status = EFI_OUT_OF_RESOURCES;
418 return Status;
419 }
420
421 Private->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature
422 Private->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too
423 Private->RootBridge.MemoryStart = MemoryStart; // Get the USB capability register base
424 Private->Segment = 0; // Default to segment zero
425
426 // Calculate the total size of the USB controller (OHCI + EHCI).
427 Private->RootBridge.MemorySize = MemorySize; //CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1));
428
429 // Create fake PCI config space: OHCI + EHCI
430 Private->ConfigSpace = AllocateZeroPool (sizeof (PCI_TYPE00));
431 if (Private->ConfigSpace == NULL) {
432 Status = EFI_OUT_OF_RESOURCES;
433 FreePool (Private);
434 return Status;
435 }
436
437 //
438 // Configure PCI config space: OHCI + EHCI
439 //
440 Private->ConfigSpace->Hdr.VendorId = 0x3530; //TODO: Define one
441 Private->ConfigSpace->Hdr.DeviceId = 0x3530; //TODO: Define one
442 Private->ConfigSpace->Hdr.ClassCode[0] = ClassCode1;
443 Private->ConfigSpace->Hdr.ClassCode[1] = ClassCode2;
444 Private->ConfigSpace->Hdr.ClassCode[2] = ClassCode3;
445 Private->ConfigSpace->Device.Bar[0] = MemoryStart;
446
447 Handle = NULL;
448
449 // Unique device path.
450 CopyMem (&Private->DevicePath, &PciIoDevicePathTemplate, sizeof (PciIoDevicePathTemplate));
451 Private->DevicePath.AcpiDevicePath.UID = 0;
452 Private->DevicePath.PciDevicePath.Device = DeviceId;
453
454 // Copy protocol structure
455 CopyMem (&Private->PciIoProtocol, &PciIoTemplate, sizeof (PciIoTemplate));
456
457 Status = gBS->InstallMultipleProtocolInterfaces (&Handle,
458 &gEfiPciIoProtocolGuid, &Private->PciIoProtocol,
459 &gEfiDevicePathProtocolGuid, &Private->DevicePath,
460 NULL);
461 if (EFI_ERROR (Status)) {
462 DEBUG ((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces () failed.\n"));
463 }
464
465 return Status;
466 }
467
468 EFI_STATUS
469 PciEmulationEntryPoint (
470 VOID
471 )
472 {
473 EFI_STATUS Status;
474
475 Status = PciInstallDevice (0, FixedPcdGet32 (PcdSynopsysUsbOhciBaseAddress), SIZE_64KB, PCI_IF_OHCI, PCI_CLASS_SERIAL_USB, PCI_CLASS_SERIAL);
476 if (EFI_ERROR (Status)) {
477 DEBUG ((EFI_D_ERROR, "PciEmulation: failed to install OHCI device.\n"));
478 }
479
480 Status = PciInstallDevice (1, FixedPcdGet32 (PcdSynopsysUsbEhciBaseAddress), SIZE_64KB, PCI_IF_EHCI, PCI_CLASS_SERIAL_USB, PCI_CLASS_SERIAL);
481 if (EFI_ERROR (Status)) {
482 DEBUG ((EFI_D_ERROR, "PciEmulation: failed to install EHCI device.\n"));
483 }
484
485 return Status;
486 }