blob: 5c651ed5246d28973966d0cfe7b2a7e7cdde865c [file] [log] [blame]
/** @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;
}