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
PchSpiVirtualddressChangeEvent(IN EFI_EVENT Event,IN VOID * Context)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
InstallPchSpi(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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
SpiPhaseInit(VOID)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