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   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
    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
    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
    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
    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
    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
    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
    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