Home | History | Annotate | Download | only in RuntimeDxe
      1 /** @file
      2 PCH SPI Runtime Driver implements the SPI Host Controller Compatibility Interface.
      3 
      4 Copyright (c) 2013-2015 Intel Corporation.
      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 #include "PchSpi.h"
     16 
     17 extern EFI_GUID gEfiEventVirtualAddressChangeGuid;
     18 
     19 //
     20 // Global variables
     21 //
     22 SPI_INSTANCE  *mSpiInstance;
     23 CONST UINT32 mSpiRegister[] = {
     24   R_QNC_RCRB_SPIS,
     25   R_QNC_RCRB_SPIPREOP,
     26   R_QNC_RCRB_SPIOPMENU,
     27   R_QNC_RCRB_SPIOPMENU + 4
     28   };
     29 
     30 //
     31 // Function implementations
     32 //
     33 VOID
     34 PchSpiVirtualddressChangeEvent (
     35   IN EFI_EVENT        Event,
     36   IN VOID             *Context
     37   )
     38 /*++
     39 
     40 Routine Description:
     41 
     42   Fixup internal data pointers so that the services can be called in virtual mode.
     43 
     44 Arguments:
     45 
     46   Event     The event registered.
     47   Context   Event context. Not used in this event handler.
     48 
     49 Returns:
     50 
     51   None.
     52 
     53 --*/
     54 {
     55   gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->PchRootComplexBar));
     56   gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Init));
     57   gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Lock));
     58   gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Execute));
     59   gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance));
     60 }
     61 
     62 EFI_STATUS
     63 EFIAPI
     64 InstallPchSpi (
     65   IN EFI_HANDLE            ImageHandle,
     66   IN EFI_SYSTEM_TABLE      *SystemTable
     67   )
     68 /*++
     69 
     70 Routine Description:
     71 
     72   Entry point for the SPI host controller driver.
     73 
     74 Arguments:
     75 
     76   ImageHandle       Image handle of this driver.
     77   SystemTable       Global system service table.
     78 
     79 Returns:
     80 
     81   EFI_SUCCESS           Initialization complete.
     82   EFI_UNSUPPORTED       The chipset is unsupported by this driver.
     83   EFI_OUT_OF_RESOURCES  Do not have enough resources to initialize the driver.
     84   EFI_DEVICE_ERROR      Device error, driver exits abnormally.
     85 
     86 --*/
     87 {
     88   EFI_STATUS                      Status;
     89   UINT64                          BaseAddress;
     90   UINT64                          Length;
     91   EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdMemorySpaceDescriptor;
     92   UINT64                          Attributes;
     93   EFI_EVENT                       Event;
     94 
     95   DEBUG ((DEBUG_INFO, "InstallPchSpi() Start\n"));
     96 
     97   //
     98   // Allocate Runtime memory for the SPI protocol instance.
     99   //
    100   mSpiInstance = AllocateRuntimeZeroPool (sizeof (SPI_INSTANCE));
    101   if (mSpiInstance == NULL) {
    102     return EFI_OUT_OF_RESOURCES;
    103   }
    104   //
    105   // Initialize the SPI protocol instance
    106   //
    107   Status = SpiProtocolConstructor (mSpiInstance);
    108   if (EFI_ERROR (Status)) {
    109     return Status;
    110   }
    111   //
    112   // Install the EFI_SPI_PROTOCOL interface
    113   //
    114   Status = gBS->InstallMultipleProtocolInterfaces (
    115                   &(mSpiInstance->Handle),
    116                   &gEfiSpiProtocolGuid,
    117                   &(mSpiInstance->SpiProtocol),
    118                   NULL
    119                   );
    120   if (EFI_ERROR (Status)) {
    121     FreePool (mSpiInstance);
    122     return EFI_DEVICE_ERROR;
    123   }
    124   //
    125   // Set RCBA space in GCD to be RUNTIME so that the range will be supported in
    126   // virtual address mode in EFI aware OS runtime.
    127   // It will assert if RCBA Memory Space is not allocated
    128   // The caller is responsible for the existence and allocation of the RCBA Memory Spaces
    129   //
    130   BaseAddress = (EFI_PHYSICAL_ADDRESS) (mSpiInstance->PchRootComplexBar);
    131   Length      = PcdGet64 (PcdRcbaMmioSize);
    132 
    133   Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdMemorySpaceDescriptor);
    134   ASSERT_EFI_ERROR (Status);
    135 
    136   Attributes = GcdMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME;
    137 
    138   Status = gDS->AddMemorySpace (
    139                   EfiGcdMemoryTypeMemoryMappedIo,
    140                   BaseAddress,
    141                   Length,
    142                   EFI_MEMORY_RUNTIME | EFI_MEMORY_UC
    143                   );
    144   ASSERT_EFI_ERROR(Status);
    145 
    146   Status = gDS->SetMemorySpaceAttributes (
    147                   BaseAddress,
    148                   Length,
    149                   Attributes
    150                   );
    151   ASSERT_EFI_ERROR (Status);
    152 
    153   Status = gBS->CreateEventEx (
    154                   EVT_NOTIFY_SIGNAL,
    155                   TPL_NOTIFY,
    156                   PchSpiVirtualddressChangeEvent,
    157                   NULL,
    158                   &gEfiEventVirtualAddressChangeGuid,
    159                   &Event
    160                   );
    161   ASSERT_EFI_ERROR (Status);
    162 
    163   DEBUG ((DEBUG_INFO, "InstallPchSpi() End\n"));
    164 
    165   return EFI_SUCCESS;
    166 }
    167 
    168 VOID
    169 EFIAPI
    170 SpiPhaseInit (
    171   VOID
    172   )
    173 /*++
    174 Routine Description:
    175 
    176   This function is a a hook for Spi Dxe phase specific initialization
    177 
    178 Arguments:
    179 
    180   None
    181 
    182 Returns:
    183 
    184   None
    185 
    186 --*/
    187 {
    188   UINTN  Index;
    189 
    190   //
    191   // Disable SMM BIOS write protect if it's not a SMM protocol
    192   //
    193   MmioAnd8 (
    194     PciDeviceMmBase (PCI_BUS_NUMBER_QNC,
    195     PCI_DEVICE_NUMBER_QNC_LPC,
    196     PCI_FUNCTION_NUMBER_QNC_LPC) + R_QNC_LPC_BIOS_CNTL,
    197     (UINT8) (~B_QNC_LPC_BIOS_CNTL_SMM_BWP)
    198     );
    199 
    200     //
    201     // Save SPI Registers for S3 resume usage
    202     //
    203     for (Index = 0; Index < sizeof (mSpiRegister) / sizeof (UINT32); Index++) {
    204     S3BootScriptSaveMemWrite (
    205       S3BootScriptWidthUint32,
    206         (UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index]),
    207         1,
    208         (VOID *) (UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index])
    209         );
    210     }
    211 }
    212