/** @file
Initialize SATA Phy, Serdes, and Controller.
Copyright (c) 2014 - 2016, AMD Inc. All rights reserved.
Copyright (c) 2016, Linaro, Ltd. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "SataRegisters.h"
#include
#include
#include
#include
#include
#include
STATIC
VOID
ResetSataController (
EFI_PHYSICAL_ADDRESS AhciBaseAddr
)
{
// Make a minimal global reset for HBA regiser
MmioOr32 (AhciBaseAddr + EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);
// Clear all interrupts
MmioWrite32 (AhciBaseAddr + EFI_AHCI_PORT_IS, EFI_AHCI_PORT_IS_CLEAR);
// Turn on interrupts and ensure that the HBA is working in AHCI mode
MmioOr32 (AhciBaseAddr + EFI_AHCI_GHC_OFFSET,
EFI_AHCI_GHC_IE | EFI_AHCI_GHC_ENABLE);
}
STATIC
VOID
SetSataCapabilities (
EFI_PHYSICAL_ADDRESS AhciBaseAddr
)
{
UINT32 Capability;
Capability = 0;
if (FixedPcdGetBool (PcdSataSssSupport)) // Staggered Spin-Up Support bit
Capability |= EFI_AHCI_CAP_SSS;
if (FixedPcdGetBool (PcdSataSmpsSupport)) // Mechanical Presence Support bit
Capability |= EFI_AHCI_CAP_SMPS;
MmioOr32 (AhciBaseAddr + EFI_AHCI_CAPABILITY_OFFSET, Capability);
}
STATIC
VOID
InitializeSataPorts (
EFI_PHYSICAL_ADDRESS AhciBaseAddr,
UINTN PortCount
)
{
INTN PortNum;
BOOLEAN IsCpd;
BOOLEAN IsMpsp;
UINT32 PortRegAddr;
UINT32 RegVal;
// Set Ports Implemented (PI)
MmioWrite32 (AhciBaseAddr + EFI_AHCI_PI_OFFSET, (1 << PortCount) - 1);
IsCpd = FixedPcdGetBool (PcdSataPortCpd);
IsMpsp = FixedPcdGetBool (PcdSataPortMpsp);
if (!IsCpd && !IsMpsp) {
return;
}
for (PortNum = 0; PortNum < PortCount; PortNum++) {
PortRegAddr = EFI_AHCI_PORT_OFFSET (PortNum) + EFI_AHCI_PORT_CMD;
RegVal = MmioRead32(AhciBaseAddr + PortRegAddr);
if (IsCpd)
RegVal |= EFI_AHCI_PORT_CMD_CPD;
else
RegVal &= ~EFI_AHCI_PORT_CMD_CPD;
if (IsMpsp)
RegVal |= EFI_AHCI_PORT_CMD_MPSP;
else
RegVal &= ~EFI_AHCI_PORT_CMD_MPSP;
RegVal |= EFI_AHCI_PORT_CMD_HPCP;
MmioWrite32(AhciBaseAddr + PortRegAddr, RegVal);
}
}
STATIC
EFI_STATUS
InitializeSataController (
EFI_PHYSICAL_ADDRESS AhciBaseAddr,
UINTN SataPortCount,
UINTN StartPort
)
{
UINT8 SataChPerSerdes;
UINT32 PortNum;
UINT32 EvenPort;
UINT32 OddPort;
SataChPerSerdes = FixedPcdGet8 (PcdSataNumChPerSerdes);
//
// SataChPerSerdes must be 2 for the Even/Odd logic in the loop below
//
ASSERT(SataChPerSerdes == 2);
for (PortNum = StartPort; PortNum < SataPortCount + StartPort; PortNum += SataChPerSerdes) {
EvenPort = (UINT32)(FixedPcdGet32 (PcdSataPortMode) >> (PortNum * 2)) & 3;
OddPort = (UINT32)(FixedPcdGet32 (PcdSataPortMode) >> ((PortNum+1) * 2)) & 3;
SataPhyInit (PortNum / SataChPerSerdes, EvenPort, OddPort);
}
//
// Reset SATA controller
//
ResetSataController (AhciBaseAddr);
//
// Set SATA capabilities
//
SetSataCapabilities (AhciBaseAddr);
//
// Set and intialize the Sata ports
//
InitializeSataPorts (AhciBaseAddr, SataPortCount);
return RegisterNonDiscoverableMmioDevice (
NonDiscoverableDeviceTypeAhci,
NonDiscoverableDeviceDmaTypeCoherent,
NULL,
NULL,
1,
AhciBaseAddr, SIZE_4KB);
}
EFI_STATUS
EFIAPI
StyxSataPlatformDxeEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
UINT32 PortNum;
EFI_STATUS Status;
//
// Perform SATA workarounds
//
for (PortNum = 0; PortNum < FixedPcdGet8(PcdSata0PortCount); PortNum++) {
SetCwMinSata0 (PortNum);
}
Status = InitializeSataController (FixedPcdGet32(PcdSata0CtrlAxiSlvPort),
FixedPcdGet8(PcdSata0PortCount), 0);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "%a: failed to initialize primary SATA controller!\n",
__FUNCTION__));
return Status;
}
for (PortNum = 0; PortNum < FixedPcdGet8(PcdSata0PortCount); PortNum++) {
SetPrdSingleSata0 (PortNum);
}
//
// Ignore the second SATA controller on pre-B1 silicon
//
if ((PcdGet32 (PcdSocCpuId) & STYX_SOC_VERSION_MASK) < STYX_SOC_VERSION_B1) {
return EFI_SUCCESS;
}
if (FixedPcdGet8(PcdSata1PortCount) > 0) {
for (PortNum = 0; PortNum < FixedPcdGet8(PcdSata1PortCount); PortNum++) {
SetCwMinSata1 (PortNum);
}
Status = InitializeSataController (FixedPcdGet32(PcdSata1CtrlAxiSlvPort),
FixedPcdGet8(PcdSata1PortCount),
FixedPcdGet8(PcdSata0PortCount));
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "%a: failed to initialize secondary SATA controller!\n",
__FUNCTION__));
} else {
for (PortNum = 0; PortNum < FixedPcdGet8(PcdSata1PortCount); PortNum++) {
SetPrdSingleSata1 (PortNum);
}
}
}
return EFI_SUCCESS;
}