/** @file | |
Initialize SATA Phy, Serdes, and Controller. | |
Copyright (c) 2014 - 2016, AMD Inc. All rights reserved.<BR> | |
Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR> | |
This program and the accompanying materials are licensed and made available | |
under the terms and conditions of the BSD License which accompanies this | |
distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
**/ | |
#include "SataRegisters.h" | |
#include <Library/AmdSataInitLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/IoLib.h> | |
#include <Library/NonDiscoverableDeviceRegistrationLib.h> | |
#include <Protocol/NonDiscoverableDevice.h> | |
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); | |
for (PortNum = 0; PortNum < SataPortCount; PortNum += SataChPerSerdes) { | |
EvenPort = (UINT32)(FixedPcdGet16 (PcdSataPortMode) >> (PortNum * 2)) & 3; | |
OddPort = (UINT32)(FixedPcdGet16 (PcdSataPortMode) >> ((PortNum+1) * 2)) & 3; | |
SataPhyInit ((StartPort + 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); | |
} | |
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; | |
} |