1 /** @file
2 PCH SPI Common 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 
16 #include "PchSpi.h"
17 
18 VOID
FillOutPublicInfoStruct(SPI_INSTANCE * SpiInstance)19 FillOutPublicInfoStruct (
20   SPI_INSTANCE          *SpiInstance
21   )
22 /*++
23 
24 Routine Description:
25 
26   Fillout SpiInstance->InitInfo;
27 
28 Arguments:
29 
30   SpiInstance   - Pointer to SpiInstance to initialize
31 
32 Returns:
33 
34   NONE
35 
36 --*/
37 {
38   UINT8         Index;
39 
40   SpiInstance->InitInfo.InitTable = &SpiInstance->SpiInitTable;
41 
42   //
43   // Give invalid index in case operation not supported.
44   //
45   SpiInstance->InitInfo.JedecIdOpcodeIndex = 0xff;
46   SpiInstance->InitInfo.OtherOpcodeIndex = 0xff;
47   SpiInstance->InitInfo.WriteStatusOpcodeIndex = 0xff;
48   SpiInstance->InitInfo.ProgramOpcodeIndex = 0xff;
49   SpiInstance->InitInfo.ReadOpcodeIndex = 0xff;
50   SpiInstance->InitInfo.EraseOpcodeIndex = 0xff;
51   SpiInstance->InitInfo.ReadStatusOpcodeIndex = 0xff;
52   SpiInstance->InitInfo.FullChipEraseOpcodeIndex = 0xff;
53   for (Index = 0; Index < SPI_NUM_OPCODE; Index++) {
54     if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationJedecId) {
55       SpiInstance->InitInfo.JedecIdOpcodeIndex = Index;
56     }
57     if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationOther) {
58       SpiInstance->InitInfo.OtherOpcodeIndex = Index;
59     }
60     if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationWriteStatus) {
61       SpiInstance->InitInfo.WriteStatusOpcodeIndex = Index;
62     }
63     if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationProgramData_1_Byte ||
64         SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationProgramData_64_Byte) {
65       SpiInstance->InitInfo.ProgramOpcodeIndex = Index;
66     }
67     if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadData ||
68         SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFastRead ||
69         SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDualOutputFastRead) {
70       SpiInstance->InitInfo.ReadOpcodeIndex = Index;
71     }
72     if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_256_Byte ||
73         SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_4K_Byte ||
74         SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_8K_Byte ||
75         SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_64K_Byte) {
76       SpiInstance->InitInfo.EraseOpcodeIndex = Index;
77     }
78     if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadStatus) {
79       SpiInstance->InitInfo.ReadStatusOpcodeIndex = Index;
80     }
81     if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFullChipErase) {
82       SpiInstance->InitInfo.FullChipEraseOpcodeIndex = Index;
83     }
84   }
85 }
86 
87 EFI_STATUS
SpiProtocolConstructor(SPI_INSTANCE * SpiInstance)88 SpiProtocolConstructor (
89   SPI_INSTANCE          *SpiInstance
90   )
91 /*++
92 
93 Routine Description:
94 
95   Initialize an SPI protocol instance.
96   The function will assert in debug if PCH RCBA has not been initialized
97 
98 Arguments:
99 
100   SpiInstance   - Pointer to SpiInstance to initialize
101 
102 Returns:
103 
104   EFI_SUCCESS     The protocol instance was properly initialized
105   EFI_UNSUPPORTED The PCH is not supported by this module
106 
107 --*/
108 {
109   SpiInstance->InitDone = FALSE;  // Indicate NOT READY.
110 
111   //
112   // Check if the current PCH is known and supported by this code
113   //
114   if (!IsQncSupported ()) {
115     DEBUG ((DEBUG_ERROR, "PCH SPI Protocol not supported due to no proper QNC LPC found!\n"));
116     return EFI_UNSUPPORTED;
117   }
118   //
119   // Initialize the SPI protocol instance
120   //
121   SpiInstance->Signature            = PCH_SPI_PRIVATE_DATA_SIGNATURE;
122   SpiInstance->Handle               = NULL;
123   SpiInstance->SpiProtocol.Init     = SpiProtocolInit;
124   SpiInstance->SpiProtocol.Lock     = SpiProtocolLock;
125   SpiInstance->SpiProtocol.Execute  = SpiProtocolExecute;
126   SpiInstance->SpiProtocol.Info     = SpiProtocolInfo;
127 
128   //
129   // Sanity check to ensure PCH RCBA initialization has occurred previously.
130   //
131   SpiInstance->PchRootComplexBar = MmioRead32 (
132                                     PciDeviceMmBase (PCI_BUS_NUMBER_QNC,
133                                     PCI_DEVICE_NUMBER_QNC_LPC,
134                                     PCI_FUNCTION_NUMBER_QNC_LPC) + R_QNC_LPC_RCBA
135                                     ) & B_QNC_LPC_RCBA_MASK;
136   ASSERT (SpiInstance->PchRootComplexBar != 0);
137 
138   return EFI_SUCCESS;
139 }
140 
141 EFI_STATUS
142 EFIAPI
UnlockFlashComponents(IN EFI_SPI_PROTOCOL * This,IN UINT8 UnlockCmdOpcodeIndex)143 UnlockFlashComponents (
144   IN      EFI_SPI_PROTOCOL      *This,
145   IN      UINT8                 UnlockCmdOpcodeIndex
146   )
147 /*++
148 
149 Routine Description:
150 
151   Issue unlock command to disable block protection, this only needs to be done once per SPI power on
152 
153 Arguments:
154 
155   This                      A pointer to "EFI_SPI_PROTOCOL" for issuing commands
156   UnlockCmdOpcodeIndex      The index of the Unlock command
157 
158 Returns:
159 
160   EFI_SUCCESS               UnLock operation succeed.
161   EFI_DEVICE_ERROR          Device error, operation failed.
162 
163 --*/
164 {
165   EFI_STATUS    Status;
166   SPI_INSTANCE  *SpiInstance;
167   UINT8         SpiStatus;
168   UINTN         PchRootComplexBar;
169 
170   if (UnlockCmdOpcodeIndex >= SPI_NUM_OPCODE) {
171     return EFI_UNSUPPORTED;
172   }
173 
174   SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
175   PchRootComplexBar = SpiInstance->PchRootComplexBar;
176 
177   //
178   // Issue unlock command to disable block protection, this only needs to be done once per SPI power on
179   //
180   SpiStatus = 0;
181   //
182   // Issue unlock command to the flash component 1 at first
183   //
184   Status = SpiProtocolExecute (
185             This,
186             UnlockCmdOpcodeIndex,
187             SpiInstance->SpiInitTable.PrefixOpcode[0] == PCH_SPI_COMMAND_WRITE_ENABLE ? 0 : 1,
188             TRUE,
189             TRUE,
190             TRUE,
191             (UINTN) 0,
192             sizeof (SpiStatus),
193             &SpiStatus,
194             EnumSpiRegionAll
195             );
196   if (EFI_ERROR (Status)) {
197     DEBUG ((EFI_D_ERROR, "Unlock flash component 1 fail!\n"));
198     return Status;
199   }
200 
201   return EFI_SUCCESS;
202 }
203 
204 EFI_STATUS
205 EFIAPI
SpiProtocolInit(IN EFI_SPI_PROTOCOL * This,IN SPI_INIT_TABLE * InitTable)206 SpiProtocolInit (
207   IN EFI_SPI_PROTOCOL       *This,
208   IN SPI_INIT_TABLE         *InitTable
209   )
210 /*++
211 
212 Routine Description:
213 
214   Initialize the host controller to execute SPI command.
215 
216 Arguments:
217 
218   This                    Pointer to the EFI_SPI_PROTOCOL instance.
219   InitTable               Initialization data to be programmed into the SPI host controller.
220 
221 Returns:
222 
223   EFI_SUCCESS             Initialization completed.
224   EFI_ACCESS_DENIED       The SPI static configuration interface has been locked-down.
225   EFI_INVALID_PARAMETER   Bad input parameters.
226   EFI_UNSUPPORTED         Can't get Descriptor mode VSCC values
227 --*/
228 {
229   EFI_STATUS    Status;
230   UINT8         Index;
231   UINT16        OpcodeType;
232   SPI_INSTANCE  *SpiInstance;
233   BOOLEAN       MultiPartitionIsSupported;
234   UINTN         PchRootComplexBar;
235   UINT8         SFDPCmdOpcodeIndex;
236   UINT8         UnlockCmdOpcodeIndex;
237   UINT8         ReadDataCmdOpcodeIndex;
238   UINT8         FlashPartId[3];
239 
240   SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
241   PchRootComplexBar = SpiInstance->PchRootComplexBar;
242 
243   if (InitTable != NULL) {
244     //
245     // Copy table into SPI driver Private data structure
246     //
247     CopyMem (
248       &SpiInstance->SpiInitTable,
249       InitTable,
250       sizeof (SPI_INIT_TABLE)
251       );
252   } else {
253     return EFI_INVALID_PARAMETER;
254   }
255   //
256   // Check if the SPI interface has been locked-down.
257   //
258   if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {
259     ASSERT_EFI_ERROR (EFI_ACCESS_DENIED);
260     return EFI_ACCESS_DENIED;
261   }
262   //
263   // Clear all the status bits for status regs.
264   //
265   MmioOr16 (
266     (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS),
267     (UINT16) ((B_QNC_RCRB_SPIS_CDS | B_QNC_RCRB_SPIS_BAS))
268     );
269   MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS);
270 
271   //
272   // Set the Prefix Opcode registers.
273   //
274   MmioWrite16 (
275     PchRootComplexBar + R_QNC_RCRB_SPIPREOP,
276     (SpiInstance->SpiInitTable.PrefixOpcode[1] << 8) | InitTable->PrefixOpcode[0]
277     );
278   MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIPREOP);
279 
280   //
281   // Set Opcode Type Configuration registers.
282   //
283   for (Index = 0, OpcodeType = 0; Index < SPI_NUM_OPCODE; Index++) {
284     switch (SpiInstance->SpiInitTable.OpcodeMenu[Index].Type) {
285     case EnumSpiOpcodeRead:
286       OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_READ << (Index * 2));
287       break;
288     case EnumSpiOpcodeWrite:
289       OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_WRITE << (Index * 2));
290       break;
291     case EnumSpiOpcodeWriteNoAddr:
292       OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_WRITE << (Index * 2));
293       break;
294     default:
295       OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_READ << (Index * 2));
296       break;
297     }
298   }
299   MmioWrite16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE, OpcodeType);
300   MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE);
301 
302   //
303   // Setup the Opcode Menu registers.
304   //
305   ReadDataCmdOpcodeIndex = SPI_NUM_OPCODE;
306   SFDPCmdOpcodeIndex = SPI_NUM_OPCODE;
307   UnlockCmdOpcodeIndex = SPI_NUM_OPCODE;
308   for (Index = 0; Index < SPI_NUM_OPCODE; Index++) {
309     MmioWrite8 (
310       PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index,
311       SpiInstance->SpiInitTable.OpcodeMenu[Index].Code
312       );
313     MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index);
314     if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationJedecId) {
315       Status = SpiProtocolExecute (
316                 This,
317                 Index,
318                 0,
319                 TRUE,
320                 TRUE,
321                 FALSE,
322                 (UINTN) 0,
323                 3,
324                 FlashPartId,
325                 EnumSpiRegionDescriptor
326                 );
327       if (EFI_ERROR (Status)) {
328         return Status;
329       }
330       if (FlashPartId[0] != SpiInstance->SpiInitTable.VendorId  ||
331           FlashPartId[1] != SpiInstance->SpiInitTable.DeviceId0 ||
332           FlashPartId[2] != SpiInstance->SpiInitTable.DeviceId1) {
333         return EFI_INVALID_PARAMETER;
334       }
335     }
336 
337     if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadData ||
338         SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFastRead ||
339         SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDualOutputFastRead) {
340       ReadDataCmdOpcodeIndex = Index;
341     }
342 
343     if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDiscoveryParameters) {
344       SFDPCmdOpcodeIndex = Index;
345     }
346 
347     if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationWriteStatus) {
348       UnlockCmdOpcodeIndex = Index;
349     }
350   }
351 
352   MultiPartitionIsSupported = FALSE;
353 
354   Status = UnlockFlashComponents (
355             This,
356             UnlockCmdOpcodeIndex
357             );
358   if (EFI_ERROR (Status)) {
359     DEBUG ((EFI_D_ERROR, "Unlock flash components fail!\n"));
360   }
361 
362   SpiPhaseInit ();
363   FillOutPublicInfoStruct (SpiInstance);
364   SpiInstance->InitDone = TRUE;
365   return EFI_SUCCESS;
366 }
367 
368 EFI_STATUS
369 EFIAPI
SpiProtocolLock(IN EFI_SPI_PROTOCOL * This)370 SpiProtocolLock (
371   IN EFI_SPI_PROTOCOL     *This
372   )
373 /*++
374 
375 Routine Description:
376 
377   Lock the SPI Static Configuration Interface.
378   Once locked, the interface can not be changed and can only be clear by system reset.
379 
380 Arguments:
381 
382   This      Pointer to the EFI_SPI_PROTOCOL instance.
383 
384 Returns:
385 
386   EFI_SUCCESS             Lock operation succeed.
387   EFI_DEVICE_ERROR        Device error, operation failed.
388   EFI_ACCESS_DENIED       The interface has already been locked.
389 
390 --*/
391 {
392   SPI_INSTANCE  *SpiInstance;
393   UINTN         PchRootComplexBar;
394 
395   SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
396   PchRootComplexBar = SpiInstance->PchRootComplexBar;
397 
398   //
399   // Check if the SPI interface has been locked-down.
400   //
401   if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {
402     return EFI_ACCESS_DENIED;
403   }
404 
405   //
406   // Lock-down the configuration interface.
407   //
408   MmioOr16 ((UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS), (UINT16) (B_QNC_RCRB_SPIS_SCL));
409 
410   //
411   // Verify if it's really locked.
412   //
413   if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) == 0) {
414     return EFI_DEVICE_ERROR;
415   } else {
416     //
417     // Save updated register in S3 Boot script.
418     //
419     S3BootScriptSaveMemWrite (
420       S3BootScriptWidthUint16,
421         (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS),
422         1,
423         (VOID *) (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS)
424         );
425   }
426 
427   return EFI_SUCCESS;
428 }
429 
430 EFI_STATUS
431 EFIAPI
SpiProtocolExecute(IN EFI_SPI_PROTOCOL * This,IN UINT8 OpcodeIndex,IN UINT8 PrefixOpcodeIndex,IN BOOLEAN DataCycle,IN BOOLEAN Atomic,IN BOOLEAN ShiftOut,IN UINTN Address,IN UINT32 DataByteCount,IN OUT UINT8 * Buffer,IN SPI_REGION_TYPE SpiRegionType)432 SpiProtocolExecute (
433   IN     EFI_SPI_PROTOCOL   *This,
434   IN     UINT8              OpcodeIndex,
435   IN     UINT8              PrefixOpcodeIndex,
436   IN     BOOLEAN            DataCycle,
437   IN     BOOLEAN            Atomic,
438   IN     BOOLEAN            ShiftOut,
439   IN     UINTN              Address,
440   IN     UINT32             DataByteCount,
441   IN OUT UINT8              *Buffer,
442   IN     SPI_REGION_TYPE    SpiRegionType
443   )
444 /*++
445 
446 Routine Description:
447 
448   Execute SPI commands from the host controller.
449   This function would be called by runtime driver, please do not use any MMIO marco here
450 
451 Arguments:
452 
453   This              Pointer to the EFI_SPI_PROTOCOL instance.
454   OpcodeIndex       Index of the command in the OpCode Menu.
455   PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
456   DataCycle         TRUE if the SPI cycle contains data
457   Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
458   ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
459   Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
460                     Region, this value specifies the offset from the Region Base; for BIOS Region,
461                     this value specifies the offset from the start of the BIOS Image. In Non
462                     Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
463                     Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
464                     Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
465                     supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
466                     the flash (in Non Descriptor Mode)
467   DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the
468                     data transfer into multiple operations. This function ensures each operation does
469                     not cross 256 byte flash address boundary.
470                     *NOTE: if there is some SPI chip that has a stricter address boundary requirement
471                     (e.g., its write page size is < 256 byte), then the caller cannot rely on this
472                     function to cut the data transfer at proper address boundaries, and it's the
473                     caller's reponsibility to pass in a properly cut DataByteCount parameter.
474   Buffer            Pointer to caller-allocated buffer containing the dada received or sent during the
475                     SPI cycle.
476   SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
477                     EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
478                     Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
479                     and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
480                     to base of the 1st flash device (i.e., it is a Flash Linear Address).
481 
482 Returns:
483 
484   EFI_SUCCESS             Command succeed.
485   EFI_INVALID_PARAMETER   The parameters specified are not valid.
486   EFI_UNSUPPORTED         Command not supported.
487   EFI_DEVICE_ERROR        Device error, command aborts abnormally.
488 
489 --*/
490 {
491   EFI_STATUS  Status;
492   UINT16      BiosCtlSave;
493   UINT32      SmiEnSave;
494 
495   BiosCtlSave = 0;
496   SmiEnSave   = 0;
497 
498   //
499   // Check if the parameters are valid.
500   //
501   if ((OpcodeIndex >= SPI_NUM_OPCODE) || (PrefixOpcodeIndex >= SPI_NUM_PREFIX_OPCODE)) {
502     return EFI_INVALID_PARAMETER;
503   }
504   //
505   // Make sure it's safe to program the command.
506   //
507   if (!WaitForSpiCycleComplete (This, FALSE)) {
508     return EFI_DEVICE_ERROR;
509   }
510 
511   //
512   // Acquire access to the SPI interface is not required any more.
513   //
514   //
515   // Disable SMIs to make sure normal mode flash access is not interrupted by an SMI
516   // whose SMI handler accesses flash (e.g. for error logging)
517   //
518   SmiEnSave = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
519   QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, (SmiEnSave & ~SMI_EN));
520 
521   //
522   // Save BIOS Ctrl register
523   //
524   BiosCtlSave = PciRead16 (
525                   PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,
526                   PCI_DEVICE_NUMBER_QNC_LPC,
527                   PCI_FUNCTION_NUMBER_QNC_LPC,
528                   R_QNC_LPC_BIOS_CNTL)
529                   ) & (B_QNC_LPC_BIOS_CNTL_BCD | B_QNC_LPC_BIOS_CNTL_PFE | B_QNC_LPC_BIOS_CNTL_BIOSWE | B_QNC_LPC_BIOS_CNTL_SMM_BWP);
530 
531   //
532   // Enable flash writing
533   //
534   PciOr16 (
535     PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,
536     PCI_DEVICE_NUMBER_QNC_LPC,
537     PCI_FUNCTION_NUMBER_QNC_LPC,
538     R_QNC_LPC_BIOS_CNTL),
539     (UINT16) (B_QNC_LPC_BIOS_CNTL_BIOSWE | B_QNC_LPC_BIOS_CNTL_SMM_BWP)
540     );
541 
542   //
543   // If shifts the data out, disable Prefetching and Caching.
544   //
545   if (ShiftOut) {
546     PciAndThenOr16 (
547       PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,
548       PCI_DEVICE_NUMBER_QNC_LPC,
549       PCI_FUNCTION_NUMBER_QNC_LPC,
550       R_QNC_LPC_BIOS_CNTL),
551       (UINT16) (~(B_QNC_LPC_BIOS_CNTL_BCD | B_QNC_LPC_BIOS_CNTL_PFE)),
552       (UINT16) ((B_QNC_LPC_BIOS_CNTL_BCD))
553       );
554   }
555   //
556   // Sends the command to the SPI interface to execute.
557   //
558   Status = SendSpiCmd (
559             This,
560             OpcodeIndex,
561             PrefixOpcodeIndex,
562             DataCycle,
563             Atomic,
564             ShiftOut,
565             Address,
566             DataByteCount,
567             Buffer,
568             SpiRegionType
569             );
570 
571   //
572   // Restore BIOS Ctrl register
573   //
574   PciAndThenOr16 (
575     PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,
576     PCI_DEVICE_NUMBER_QNC_LPC,
577     PCI_FUNCTION_NUMBER_QNC_LPC,
578     R_QNC_LPC_BIOS_CNTL),
579     (UINT16) (~(B_QNC_LPC_BIOS_CNTL_BCD | B_QNC_LPC_BIOS_CNTL_PFE | B_QNC_LPC_BIOS_CNTL_BIOSWE | B_QNC_LPC_BIOS_CNTL_SMM_BWP)),
580     (UINT16) (BiosCtlSave)
581       );
582   //
583   // Restore SMIs.
584   //
585   QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, SmiEnSave);
586 
587   return Status;
588 }
589 
590 VOID
SpiOffset2Physical(IN EFI_SPI_PROTOCOL * This,IN UINTN SpiRegionOffset,IN SPI_REGION_TYPE SpiRegionType,OUT UINTN * HardwareSpiAddress,OUT UINTN * BaseAddress,OUT UINTN * LimitAddress)591 SpiOffset2Physical (
592   IN      EFI_SPI_PROTOCOL  *This,
593   IN      UINTN             SpiRegionOffset,
594   IN      SPI_REGION_TYPE   SpiRegionType,
595   OUT     UINTN             *HardwareSpiAddress,
596   OUT     UINTN             *BaseAddress,
597   OUT     UINTN             *LimitAddress
598   )
599 /*++
600 
601 Routine Description:
602 
603   Convert SPI offset to Physical address of SPI hardware
604 
605 Arguments:
606 
607   This               Pointer to the EFI_SPI_PROTOCOL instance.
608   SpiRegionOffset    In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
609                      Region, this value specifies the offset from the Region Base; for BIOS Region,
610                      this value specifies the offset from the start of the BIOS Image. In Non
611                      Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
612                      Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
613                      Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
614                      supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
615                      the flash (in Non Descriptor Mode)
616   BaseAddress        Base Address of the region.
617   SpiRegionType      SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
618                      EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
619                      Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
620                      and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
621                      to base of the 1st flash device (i.e., it is a Flash Linear Address).
622   HardwareSpiAddress Return absolution SPI address (i.e., Flash Linear Address)
623   BaseAddress        Return base address of the region type
624   LimitAddress       Return limit address of the region type
625 
626 Returns:
627 
628   EFI_SUCCESS             Command succeed.
629 
630 --*/
631 {
632   SPI_INSTANCE  *SpiInstance;
633   UINTN         PchRootComplexBar;
634 
635   SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
636   PchRootComplexBar = SpiInstance->PchRootComplexBar;
637 
638   if (SpiRegionType == EnumSpiRegionAll) {
639     //
640     // EnumSpiRegionAll indicates address is relative to flash device (i.e., address is Flash
641     // Linear Address)
642     //
643     *HardwareSpiAddress = SpiRegionOffset;
644   } else {
645     //
646     // Otherwise address is relative to BIOS image
647     //
648     *HardwareSpiAddress = SpiRegionOffset + SpiInstance->SpiInitTable.BiosStartOffset;
649   }
650 }
651 
652 EFI_STATUS
SendSpiCmd(IN EFI_SPI_PROTOCOL * This,IN UINT8 OpcodeIndex,IN UINT8 PrefixOpcodeIndex,IN BOOLEAN DataCycle,IN BOOLEAN Atomic,IN BOOLEAN ShiftOut,IN UINTN Address,IN UINT32 DataByteCount,IN OUT UINT8 * Buffer,IN SPI_REGION_TYPE SpiRegionType)653 SendSpiCmd (
654   IN     EFI_SPI_PROTOCOL   *This,
655   IN     UINT8              OpcodeIndex,
656   IN     UINT8              PrefixOpcodeIndex,
657   IN     BOOLEAN            DataCycle,
658   IN     BOOLEAN            Atomic,
659   IN     BOOLEAN            ShiftOut,
660   IN     UINTN              Address,
661   IN     UINT32             DataByteCount,
662   IN OUT UINT8              *Buffer,
663   IN     SPI_REGION_TYPE    SpiRegionType
664   )
665 /*++
666 
667 Routine Description:
668 
669   This function sends the programmed SPI command to the slave device.
670 
671 Arguments:
672 
673   OpcodeIndex       Index of the command in the OpCode Menu.
674   PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
675   DataCycle         TRUE if the SPI cycle contains data
676   Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
677   ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
678   Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
679                     Region, this value specifies the offset from the Region Base; for BIOS Region,
680                     this value specifies the offset from the start of the BIOS Image. In Non
681                     Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
682                     Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
683                     Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
684                     supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
685                     the flash (in Non Descriptor Mode)
686   DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the
687                     data transfer into multiple operations. This function ensures each operation does
688                     not cross 256 byte flash address boundary.
689                     *NOTE: if there is some SPI chip that has a stricter address boundary requirement
690                     (e.g., its write page size is < 256 byte), then the caller cannot rely on this
691                     function to cut the data transfer at proper address boundaries, and it's the
692                     caller's reponsibility to pass in a properly cut DataByteCount parameter.
693   Buffer            Data received or sent during the SPI cycle.
694   SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
695                     EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
696                     Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
697                     and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
698                     to base of the 1st flash device (i.e., it is a Flash Linear Address).
699 
700 Returns:
701 
702   EFI_SUCCESS             SPI command completes successfully.
703   EFI_DEVICE_ERROR        Device error, the command aborts abnormally.
704   EFI_ACCESS_DENIED       Some unrecognized command encountered in hardware sequencing mode
705   EFI_INVALID_PARAMETER   The parameters specified are not valid.
706 
707 --*/
708 {
709   UINT32        Index;
710   SPI_INSTANCE  *SpiInstance;
711   UINTN         HardwareSpiAddr;
712   UINTN         SpiBiosSize;
713   UINTN         BaseAddress;
714   UINTN         LimitAddress;
715   UINT32        SpiDataCount;
716   UINT8         OpCode;
717   SPI_OPERATION Operation;
718   UINTN         PchRootComplexBar;
719 
720   SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
721   PchRootComplexBar = SpiInstance->PchRootComplexBar;
722   SpiBiosSize       = SpiInstance->SpiInitTable.BiosSize;
723   Operation         = SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex].Operation;
724   OpCode            = MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + OpcodeIndex);
725 
726   //
727   // Check if the value of opcode register is 0 or the BIOS Size of SpiInitTable is 0
728   //
729   if (OpCode == 0 || SpiBiosSize == 0) {
730     ASSERT (FALSE);
731     return EFI_INVALID_PARAMETER;
732   }
733 
734   SpiOffset2Physical (This, Address, SpiRegionType, &HardwareSpiAddr, &BaseAddress, &LimitAddress);
735   //
736   // Have direct access to BIOS region in Descriptor mode,
737   //
738   if (SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex].Type == EnumSpiOpcodeRead &&
739       SpiRegionType == EnumSpiRegionBios) {
740     CopyMem (
741       Buffer,
742       (UINT8 *) ((HardwareSpiAddr - BaseAddress) + (UINT32) (~(SpiBiosSize - 1))),
743       DataByteCount
744       );
745     return EFI_SUCCESS;
746   }
747   //
748   // DEBUG((EFI_D_ERROR, "SPIADDR %x, %x, %x, %x\n", Address, HardwareSpiAddr, BaseAddress,
749   // LimitAddress));
750   //
751   if ((DataCycle == FALSE) && (DataByteCount > 0)) {
752     DataByteCount = 0;
753   }
754 
755   do {
756     //
757     // Trim at 256 byte boundary per operation,
758     // - PCH SPI controller requires trimming at 4KB boundary
759     // - Some SPI chips require trimming at 256 byte boundary for write operation
760     // - Trimming has limited performance impact as we can read / write atmost 64 byte
761     //   per operation
762     //
763     if (HardwareSpiAddr + DataByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {
764       SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);
765     } else {
766       SpiDataCount = DataByteCount;
767     }
768     //
769     // Calculate the number of bytes to shift in/out during the SPI data cycle.
770     // Valid settings for the number of bytes duing each data portion of the
771     // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
772     //
773     if (SpiDataCount >= 64) {
774       SpiDataCount = 64;
775     } else if ((SpiDataCount &~0x07) != 0) {
776       SpiDataCount = SpiDataCount &~0x07;
777     }
778     //
779     // If shifts data out, load data into the SPI data buffer.
780     //
781     if (ShiftOut) {
782       for (Index = 0; Index < SpiDataCount; Index++) {
783         MmioWrite8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index, Buffer[Index]);
784         MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index);
785       }
786     }
787 
788     MmioWrite32 (
789       (PchRootComplexBar + R_QNC_RCRB_SPIA),
790       (UINT32) (HardwareSpiAddr & B_QNC_RCRB_SPIA_MASK)
791       );
792     MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIA);
793 
794     //
795     // Execute the command on the SPI compatible mode
796     //
797 
798     //
799     // Clear error flags
800     //
801     MmioOr16 ((PchRootComplexBar + R_QNC_RCRB_SPIS), B_QNC_RCRB_SPIS_BAS);
802 
803     //
804     // Initialte the SPI cycle
805     //
806     if (DataCycle) {
807       MmioWrite16 (
808         (PchRootComplexBar + R_QNC_RCRB_SPIC),
809         ( (UINT16) (B_QNC_RCRB_SPIC_DC) | (UINT16) (((SpiDataCount - 1) << 8) & B_QNC_RCRB_SPIC_DBC) |
810           (UINT16) ((OpcodeIndex << 4) & B_QNC_RCRB_SPIC_COP) |
811           (UINT16) ((PrefixOpcodeIndex << 3) & B_QNC_RCRB_SPIC_SPOP) |
812           (UINT16) (Atomic ? B_QNC_RCRB_SPIC_ACS : 0) |
813           (UINT16) (B_QNC_RCRB_SPIC_SCGO)));
814     } else {
815       MmioWrite16 (
816         (PchRootComplexBar + R_QNC_RCRB_SPIC),
817         ( (UINT16) ((OpcodeIndex << 4) & B_QNC_RCRB_SPIC_COP) |
818           (UINT16) ((PrefixOpcodeIndex << 3) & B_QNC_RCRB_SPIC_SPOP) |
819           (UINT16) (Atomic ? B_QNC_RCRB_SPIC_ACS : 0) |
820           (UINT16) (B_QNC_RCRB_SPIC_SCGO)));
821     }
822 
823     MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIC);
824 
825     //
826     // end of command execution
827     //
828     // Wait the SPI cycle to complete.
829     //
830     if (!WaitForSpiCycleComplete (This, TRUE)) {
831       return EFI_DEVICE_ERROR;
832     }
833     //
834     // If shifts data in, get data from the SPI data buffer.
835     //
836     if (!ShiftOut) {
837       for (Index = 0; Index < SpiDataCount; Index++) {
838         Buffer[Index] = MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index);
839       }
840     }
841 
842     HardwareSpiAddr += SpiDataCount;
843     Buffer += SpiDataCount;
844     DataByteCount -= SpiDataCount;
845   } while (DataByteCount > 0);
846 
847   return EFI_SUCCESS;
848 }
849 
850 BOOLEAN
WaitForSpiCycleComplete(IN EFI_SPI_PROTOCOL * This,IN BOOLEAN ErrorCheck)851 WaitForSpiCycleComplete (
852   IN     EFI_SPI_PROTOCOL   *This,
853   IN     BOOLEAN            ErrorCheck
854   )
855 /*++
856 
857 Routine Description:
858 
859   Wait execution cycle to complete on the SPI interface. Check both Hardware
860   and Software Sequencing status registers
861 
862 Arguments:
863 
864   This                - The SPI protocol instance
865   UseSoftwareSequence - TRUE if this is a Hardware Sequencing operation
866   ErrorCheck          - TRUE if the SpiCycle needs to do the error check
867 
868 Returns:
869 
870   TRUE       SPI cycle completed on the interface.
871   FALSE      Time out while waiting the SPI cycle to complete.
872              It's not safe to program the next command on the SPI interface.
873 
874 --*/
875 {
876   UINT64        WaitTicks;
877   UINT64        WaitCount;
878   UINT16        Data16;
879   SPI_INSTANCE  *SpiInstance;
880   UINTN         PchRootComplexBar;
881 
882   SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
883   PchRootComplexBar = SpiInstance->PchRootComplexBar;
884 
885   //
886   // Convert the wait period allowed into to tick count
887   //
888   WaitCount = WAIT_TIME / WAIT_PERIOD;
889 
890   //
891   // Wait for the SPI cycle to complete.
892   //
893   for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
894     Data16 = MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS);
895     if ((Data16 & B_QNC_RCRB_SPIS_SCIP) == 0) {
896       MmioWrite16 (PchRootComplexBar + R_QNC_RCRB_SPIS, (B_QNC_RCRB_SPIS_BAS | B_QNC_RCRB_SPIS_CDS));
897       if ((Data16 & B_QNC_RCRB_SPIS_BAS) && (ErrorCheck == TRUE)) {
898         return FALSE;
899       } else {
900         return TRUE;
901       }
902     }
903 
904     MicroSecondDelay (WAIT_PERIOD);
905   }
906 
907   return FALSE;
908 }
909 
910 EFI_STATUS
911 EFIAPI
SpiProtocolInfo(IN EFI_SPI_PROTOCOL * This,OUT SPI_INIT_INFO ** InitInfoPtr)912 SpiProtocolInfo (
913   IN EFI_SPI_PROTOCOL     *This,
914   OUT SPI_INIT_INFO      **InitInfoPtr
915   )
916 /*++
917 
918 Routine Description:
919 
920   Return info about SPI host controller, to help callers usage of Execute
921   service.
922 
923   If 0xff is returned as an opcode index in init info struct
924   then device does not support the operation.
925 
926 Arguments:
927 
928   This                    Pointer to the EFI_SPI_PROTOCOL instance.
929   InitInfoPtr             Pointer to init info written to this memory location.
930 
931 Returns:
932 
933   EFI_SUCCESS             Information returned.
934   EFI_INVALID_PARAMETER   Invalid parameter.
935   EFI_NOT_READY           Required resources not setup.
936   Others                  Unexpected error happened.
937 
938 --*/
939 {
940   SPI_INSTANCE  *SpiInstance;
941 
942   if (This == NULL || InitInfoPtr == NULL) {
943     return EFI_INVALID_PARAMETER;
944   }
945   SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
946   if (SpiInstance->Signature != PCH_SPI_PRIVATE_DATA_SIGNATURE) {
947     return EFI_INVALID_PARAMETER;
948   }
949 
950   if (!SpiInstance->InitDone) {
951     *InitInfoPtr = NULL;
952     return EFI_NOT_READY;
953   }
954   *InitInfoPtr = &SpiInstance->InitInfo;
955   return EFI_SUCCESS;
956 }
957