alder_lake_bios/Insyde/InsydeModulePkg/Universal/Recovery/PciResourceInitPei/SdInit.c

205 lines
6.2 KiB
C

/** @file
;******************************************************************************
;* Copyright (c) 2019 - 2020, Insyde Software Corporation. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "SdInit.h"
PEI_SD_CONTROLLER_PPI mSdControllerPpi = {
GetSdhcController
};
EFI_PEI_PPI_DESCRIPTOR mSdhcPpiList = {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gPeiSdControllerPpiGuid,
NULL
};
EFI_PEI_NOTIFY_DESCRIPTOR mSdhcNotifyList = {
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiEndOfPeiSignalPpiGuid,
SdhcEndOfPeiPpiNotifyCallback
};
/**
Retrieve SDHC controller information.
@param [in] PeiServices Pointer to the PEI Services Table.
@param [in] This Pointer to PEI_SD_CONTROLLER_PPI
@param [in] SdControllerId SDHC Controller ID
@param [out] ControllerType Result SDHC controller type
@param [out] PciCfgAddress Result SDHC base address
@retval EFI_SUCCESS SDHC controller information is retrieved successfully
@retval EFI_INVALID_PARAMETER Invalid SdControllerId is given
@retval Others Operation failed
**/
EFI_STATUS
EFIAPI
GetSdhcController (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_SD_CONTROLLER_PPI *This,
IN UINT8 SdControllerId,
OUT UINTN *ControllerType,
OUT UINT64 *PciCfgAddress
)
{
PEI_SDHC_DEVICE *PeiSdhcDev;
PeiSdhcDev = PEI_SDHC_DEVICE_FROM_THIS (This);
if (SdControllerId >= PeiSdhcDev->TotalControllers) {
return EFI_INVALID_PARAMETER;
}
*ControllerType = PEI_SDHC_CONTROLLER;
//
// Convert PciLibAddress to PciCfgAddress
//
*PciCfgAddress = PCILIB_ADDRESS_TO_PCICFG_ADDRESS (PeiSdhcDev->PciAddress);
return EFI_SUCCESS;
}
/**
Register notify ppi to reset the SDHC.
@param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
@param[in] NotifyDescriptor Address of the notification descriptor data structure
@param[in] Ppi Address of the PPI that was installed
@retval EFI_SUCCESS Operation completed successfully
@retval Others Operation failed
**/
EFI_STATUS
EFIAPI
SdhcEndOfPeiPpiNotifyCallback (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
)
{
PEI_SDHC_DEVICE *PeiSdhcDev;
PeiSdhcDev = PEI_SDHC_DEVICE_FROM_NOTIFY_DESC (NotifyDescriptor);
//
// Reset the host
//
MmioOr8 (PeiSdhcDev->BaseAddress + SOFT_RESET_REGISTER, BIT0);
MicroSecondDelay (1);
//
// Disable SDHC
//
PciAnd16 (
PeiSdhcDev->PciAddress | PCI_COMMAND_OFFSET,
(UINT16)~(EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE)
);
return EFI_SUCCESS;
}
/**
Init SD controller.
@param [in] PeiServices Pointer to the PEI Services Table.
@param [in] Bus PCI Bus number
@param [in] Device PCI Device number
@param [in] Function PCI Function number
@param [in] BaseAddress MMIO base address
@retval EFI_SUCCESS Operation completed successfully.
@retval Others Operation was unsuccessful.
**/
EFI_STATUS
InitSdController (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN PCI_RESOURCE_DATA *PciRes
)
{
EFI_STATUS Status;
PEI_SDHC_DEVICE *PeiSdhcDev;
UINT8 SlotInfo;
UINT8 SlotNum;
UINT8 FirstBar;
UINT8 Index;
UINT8 Slot;
UINT8 SubClass;
UINT8 BaseClass;
UINT32 Bus;
UINT32 Device;
UINT32 Function;
Bus = PciRes->Bus;
Device = PciRes->Device;
Function = PciRes->Function;
SubClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_CLASSCODE_OFFSET + 1));
BaseClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_CLASSCODE_OFFSET + 2));
if ((SubClass != PCI_SUBCLASS_SD_HOST_CONTROLLER) || (BaseClass != PCI_CLASS_SYSTEM_PERIPHERAL)) {
return EFI_UNSUPPORTED;
}
Status = ProgramBar (PciRes);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get the SD/MMC Pci host controller's Slot Info.
//
SlotInfo = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, SD_MMC_HC_PEI_SLOT_OFFSET));
SlotNum = ((SlotInfo & 0x70) >> 4) + 1;
FirstBar = SlotInfo & 0x07;
for (Index = 0, Slot = FirstBar; Slot < (FirstBar + SlotNum); Index++, Slot++) {
PeiSdhcDev = (PEI_SDHC_DEVICE *)AllocateZeroPool (sizeof (PEI_SDHC_DEVICE));
ASSERT (PeiSdhcDev != NULL);
if (PeiSdhcDev == NULL) {
return EFI_OUT_OF_RESOURCES;
}
PeiSdhcDev->Signature = PEI_SDHC_SIGNATURE;
PeiSdhcDev->ControllerPpi = mSdControllerPpi;
PeiSdhcDev->PpiList = mSdhcPpiList;
PeiSdhcDev->PpiList.Ppi = &PeiSdhcDev->ControllerPpi;
PeiSdhcDev->NotifyList = mSdhcNotifyList;
PeiSdhcDev->TotalControllers = 1;
PeiSdhcDev->BaseAddress = PciRes->PciBar[Index];
PeiSdhcDev->PciAddress = PCI_LIB_ADDRESS (Bus, Device, Function, 0);
//
// Install notification in order to reset the SDHC
//
Status = PeiServicesNotifyPpi (&PeiSdhcDev->NotifyList);
if (EFI_ERROR(Status)) {
return Status;
}
//
// Install SD Controller PPI
//
Status = PeiServicesInstallPpi (&PeiSdhcDev->PpiList);
DEBUG ((DEBUG_ERROR | DEBUG_INFO, "InstallPpi :%r\n",Status));
if (EFI_ERROR(Status)) {
return Status;
}
}
DEBUG ((DEBUG_ERROR | DEBUG_INFO, "End InitSdController !\n"));
return EFI_SUCCESS;
}