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