summaryrefslogtreecommitdiff
path: root/Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c')
-rw-r--r--Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c b/Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c
new file mode 100644
index 0000000000..1958d918d9
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c
@@ -0,0 +1,201 @@
+/** @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);
+}
+
+#define STYX_SOC_VERSION_MASK 0xFFF
+#define STYX_SOC_VERSION_A0 0x000
+#define STYX_SOC_VERSION_B0 0x010
+#define STYX_SOC_VERSION_B1 0x011
+
+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;
+}