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