EFI_STATUS EFIAPI UnlockFlashComponents ( IN EFI_SPI_PROTOCOL *This, IN UINT8 UnlockCmdOpcodeIndex ) /*++ Routine Description: Issue unlock command to disable block protection, this only needs to be done once per SPI power on Arguments: This A pointer to "EFI_SPI_PROTOCOL" for issuing commands UnlockCmdOpcodeIndex The index of the Unlock command Returns: EFI_SUCCESS UnLock operation succeed. EFI_DEVICE_ERROR Device error, operation failed. --*/ { EFI_STATUS Status; SPI_INSTANCE *SpiInstance; UINT8 SpiStatus; if (UnlockCmdOpcodeIndex >= SPI_NUM_OPCODE) { return EFI_UNSUPPORTED; } SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); // // Issue unlock command to disable block protection, this only needs to be done once per SPI power on // SpiStatus = 0; // // Issue unlock command to the flash component 1 at first // Status = SpiProtocolExecute ( This, UnlockCmdOpcodeIndex, SpiInstance->SpiInitTable.PrefixOpcode[0] == PCH_SPI_COMMAND_WRITE_ENABLE ? 0 : 1, TRUE, TRUE, TRUE, (UINTN) 0, sizeof (SpiStatus), &SpiStatus, EnumSpiRegionAll ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Unlock flash component 1 fail!\n")); return Status; } return EFI_SUCCESS; }
EFI_STATUS EFIAPI SpiProtocolInit ( IN EFI_SPI_PROTOCOL *This, IN SPI_INIT_TABLE *InitTable ) /*++ Routine Description: Initialize the host controller to execute SPI command. Arguments: This Pointer to the EFI_SPI_PROTOCOL instance. InitTable Initialization data to be programmed into the SPI host controller. Returns: EFI_SUCCESS Initialization completed. EFI_ACCESS_DENIED The SPI static configuration interface has been locked-down. EFI_INVALID_PARAMETER Bad input parameters. EFI_UNSUPPORTED Can't get Descriptor mode VSCC values --*/ { EFI_STATUS Status; UINT8 Index; UINT16 OpcodeType; SPI_INSTANCE *SpiInstance; BOOLEAN MultiPartitionIsSupported; UINTN PchRootComplexBar; UINT8 SFDPCmdOpcodeIndex; UINT8 UnlockCmdOpcodeIndex; UINT8 ReadDataCmdOpcodeIndex; UINT8 FlashPartId[3]; SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); PchRootComplexBar = SpiInstance->PchRootComplexBar; if (InitTable != NULL) { // // Copy table into SPI driver Private data structure // CopyMem ( &SpiInstance->SpiInitTable, InitTable, sizeof (SPI_INIT_TABLE) ); } else { return EFI_INVALID_PARAMETER; } // // Check if the SPI interface has been locked-down. // if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) { ASSERT_EFI_ERROR (EFI_ACCESS_DENIED); return EFI_ACCESS_DENIED; } // // Clear all the status bits for status regs. // MmioOr16 ( (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS), (UINT16) ((B_QNC_RCRB_SPIS_CDS | B_QNC_RCRB_SPIS_BAS)) ); MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS); // // Set the Prefix Opcode registers. // MmioWrite16 ( PchRootComplexBar + R_QNC_RCRB_SPIPREOP, (SpiInstance->SpiInitTable.PrefixOpcode[1] << 8) | InitTable->PrefixOpcode[0] ); MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIPREOP); // // Set Opcode Type Configuration registers. // for (Index = 0, OpcodeType = 0; Index < SPI_NUM_OPCODE; Index++) { switch (SpiInstance->SpiInitTable.OpcodeMenu[Index].Type) { case EnumSpiOpcodeRead: OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_READ << (Index * 2)); break; case EnumSpiOpcodeWrite: OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_WRITE << (Index * 2)); break; case EnumSpiOpcodeWriteNoAddr: OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_WRITE << (Index * 2)); break; default: OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_READ << (Index * 2)); break; } } MmioWrite16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE, OpcodeType); MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE); // // Setup the Opcode Menu registers. // ReadDataCmdOpcodeIndex = SPI_NUM_OPCODE; SFDPCmdOpcodeIndex = SPI_NUM_OPCODE; UnlockCmdOpcodeIndex = SPI_NUM_OPCODE; for (Index = 0; Index < SPI_NUM_OPCODE; Index++) { MmioWrite8 ( PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index, SpiInstance->SpiInitTable.OpcodeMenu[Index].Code ); MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index); if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationJedecId) { Status = SpiProtocolExecute ( This, Index, 0, TRUE, TRUE, FALSE, (UINTN) 0, 3, FlashPartId, EnumSpiRegionDescriptor ); if (EFI_ERROR (Status)) { return Status; } if (FlashPartId[0] != SpiInstance->SpiInitTable.VendorId || FlashPartId[1] != SpiInstance->SpiInitTable.DeviceId0 || FlashPartId[2] != SpiInstance->SpiInitTable.DeviceId1) { return EFI_INVALID_PARAMETER; } } if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadData || SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFastRead || SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDualOutputFastRead) { ReadDataCmdOpcodeIndex = Index; } if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDiscoveryParameters) { SFDPCmdOpcodeIndex = Index; } if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationWriteStatus) { UnlockCmdOpcodeIndex = Index; } } MultiPartitionIsSupported = FALSE; Status = UnlockFlashComponents ( This, UnlockCmdOpcodeIndex ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Unlock flash components fail!\n")); } SpiPhaseInit (); FillOutPublicInfoStruct (SpiInstance); SpiInstance->InitDone = TRUE; return EFI_SUCCESS; }