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