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