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