On Tue, Nov 01, 2016 at 05:25:09PM +0000, Ard Biesheuvel wrote:
Create a new Styx platform driver StyxSataPlatformDxe which contains the existing platform specific SATA initialization code, but uses the new platform PCI I/O driver to register the platform AHCI devices.
This has two advantages:
- we can use generic drivers for the platform PCI I/O emulation, and for the AHCI support built on top of it,
- we can register both SATA devices, allowing us to use all 14 ports on Overdrive B1
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org
Platforms/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c | 181 ++++++++++++++++++++ Platforms/AMD/Styx/Drivers/StyxSataPlatformDxe/SataRegisters.h | 180 +++++++++++++++++++ Platforms/AMD/Styx/Drivers/StyxSataPlatformDxe/StyxSataPlatformDxe.inf | 61 +++++++ 3 files changed, 422 insertions(+)
diff --git a/Platforms/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c b/Platforms/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c new file mode 100644 index 000000000000..e9cc1f9d52c7 --- /dev/null +++ b/Platforms/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c @@ -0,0 +1,181 @@ +/** @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/PlatformPciIoDeviceRegistrationLib.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 PlatformPciIoRegisterDevice (AhciBaseAddr, PlatformPciIoDeviceAhci,
PlatformPciIoDmaCoherent, NULL, NULL);
+}
+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(PcdSataPortCount); PortNum++) {
SetCwMinSata0 (PortNum);
- }
- Status = InitializeSataController (FixedPcdGet32(PcdSataCtrlAxiSlvPort),
FixedPcdGet8(PcdSataPortCount), 0);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_WARN, "%a: failed to initialize primary SATA controller!\n",
__FUNCTION__));
- return Status;
- }
- for (PortNum = 0; PortNum < FixedPcdGet8(PcdSataPortCount); PortNum++) {
SetPrdSingleSata0 (PortNum);
- }
- if (FixedPcdGet8(PcdSata1PortCount) > 0) {
OK, I realise now that this has been in AmdStyx.dec all along, but I didn't spot it before. Could we rename the PCDs so we have PcdSata0* and PcdSata1* instead of PcdSata/PcdSata1?
- for (PortNum = 0; PortNum < FixedPcdGet8(PcdSata1PortCount); PortNum++) {
SetCwMinSata1 (PortNum);
- }
- Status = InitializeSataController (FixedPcdGet32(PcdSata1CtrlAxiSlvPort),
FixedPcdGet8(PcdSata1PortCount), FixedPcdGet8(PcdSataPortCount));
- 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;
+} diff --git a/Platforms/AMD/Styx/Drivers/StyxSataPlatformDxe/SataRegisters.h b/Platforms/AMD/Styx/Drivers/StyxSataPlatformDxe/SataRegisters.h new file mode 100644 index 000000000000..ff78f4ac3c67 --- /dev/null +++ b/Platforms/AMD/Styx/Drivers/StyxSataPlatformDxe/SataRegisters.h
Is this a straight copy of Drivers/SataControllerDxe/SataRegisters.h ? If so, worth stating in commit message?
@@ -0,0 +1,180 @@ +/** @file
- Header file for AHCI mode of ATA host controller.
- Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2014 - 2016, AMD Inc. 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.
+**/ +#ifndef __SATA_REGISTERS_H__ +#define __SATA_REGISTERS_H__
+#define EFI_AHCI_BAR_INDEX 0x05
+#define EFI_AHCI_CAPABILITY_OFFSET 0x0000 +#define EFI_AHCI_CAP_SSS BIT27 +#define EFI_AHCI_CAP_SMPS BIT28 +#define EFI_AHCI_CAP_S64A BIT31 +#define EFI_AHCI_GHC_OFFSET 0x0004 +#define EFI_AHCI_GHC_RESET BIT0 +#define EFI_AHCI_GHC_IE BIT1 +#define EFI_AHCI_GHC_ENABLE BIT31 +#define EFI_AHCI_IS_OFFSET 0x0008 +#define EFI_AHCI_PI_OFFSET 0x000C
+#define EFI_AHCI_MAX_PORTS 32
+// +// Refer SATA1.0a spec section 5.2, the Phy detection time should be less than 10ms. +// +#define EFI_AHCI_BUS_PHY_DETECT_TIMEOUT 10 +// +// Refer SATA1.0a spec, the FIS enable time should be less than 500ms. +// +#define EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT EFI_TIMER_PERIOD_MILLISECONDS(500) +// +// Refer SATA1.0a spec, the bus reset time should be less than 1s. +// +#define EFI_AHCI_BUS_RESET_TIMEOUT EFI_TIMER_PERIOD_SECONDS(1)
+#define EFI_AHCI_ATAPI_DEVICE_SIG 0xEB140000 +#define EFI_AHCI_ATA_DEVICE_SIG 0x00000000 +#define EFI_AHCI_PORT_MULTIPLIER_SIG 0x96690000 +#define EFI_AHCI_ATAPI_SIG_MASK 0xFFFF0000
+// +// Each PRDT entry can point to a memory block up to 4M byte +// +#define EFI_AHCI_MAX_DATA_PER_PRDT 0x400000
+#define EFI_AHCI_FIS_REGISTER_H2D 0x27 //Register FIS - Host to Device +#define EFI_AHCI_FIS_REGISTER_H2D_LENGTH 20 +#define EFI_AHCI_FIS_REGISTER_D2H 0x34 //Register FIS - Device to Host +#define EFI_AHCI_FIS_REGISTER_D2H_LENGTH 20 +#define EFI_AHCI_FIS_DMA_ACTIVATE 0x39 //DMA Activate FIS - Device to Host +#define EFI_AHCI_FIS_DMA_ACTIVATE_LENGTH 4 +#define EFI_AHCI_FIS_DMA_SETUP 0x41 //DMA Setup FIS - Bi-directional +#define EFI_AHCI_FIS_DMA_SETUP_LENGTH 28 +#define EFI_AHCI_FIS_DATA 0x46 //Data FIS - Bi-directional +#define EFI_AHCI_FIS_BIST 0x58 //BIST Activate FIS - Bi-directional +#define EFI_AHCI_FIS_BIST_LENGTH 12 +#define EFI_AHCI_FIS_PIO_SETUP 0x5F //PIO Setup FIS - Device to Host +#define EFI_AHCI_FIS_PIO_SETUP_LENGTH 20 +#define EFI_AHCI_FIS_SET_DEVICE 0xA1 //Set Device Bits FIS - Device to Host +#define EFI_AHCI_FIS_SET_DEVICE_LENGTH 8
+#define EFI_AHCI_D2H_FIS_OFFSET 0x40 +#define EFI_AHCI_DMA_FIS_OFFSET 0x00 +#define EFI_AHCI_PIO_FIS_OFFSET 0x20 +#define EFI_AHCI_SDB_FIS_OFFSET 0x58 +#define EFI_AHCI_FIS_TYPE_MASK 0xFF +#define EFI_AHCI_U_FIS_OFFSET 0x60
+// +// Port register +// +#define EFI_AHCI_PORT_START 0x0100 +#define EFI_AHCI_PORT_REG_WIDTH 0x0080 +#define EFI_AHCI_PORT_CLB 0x0000 +#define EFI_AHCI_PORT_CLBU 0x0004 +#define EFI_AHCI_PORT_FB 0x0008 +#define EFI_AHCI_PORT_FBU 0x000C +#define EFI_AHCI_PORT_IS 0x0010 +#define EFI_AHCI_PORT_IS_DHRS BIT0 +#define EFI_AHCI_PORT_IS_PSS BIT1 +#define EFI_AHCI_PORT_IS_SSS BIT2 +#define EFI_AHCI_PORT_IS_SDBS BIT3 +#define EFI_AHCI_PORT_IS_UFS BIT4 +#define EFI_AHCI_PORT_IS_DPS BIT5 +#define EFI_AHCI_PORT_IS_PCS BIT6 +#define EFI_AHCI_PORT_IS_DIS BIT7 +#define EFI_AHCI_PORT_IS_PRCS BIT22 +#define EFI_AHCI_PORT_IS_IPMS BIT23 +#define EFI_AHCI_PORT_IS_OFS BIT24 +#define EFI_AHCI_PORT_IS_INFS BIT26 +#define EFI_AHCI_PORT_IS_IFS BIT27 +#define EFI_AHCI_PORT_IS_HBDS BIT28 +#define EFI_AHCI_PORT_IS_HBFS BIT29 +#define EFI_AHCI_PORT_IS_TFES BIT30 +#define EFI_AHCI_PORT_IS_CPDS BIT31 +#define EFI_AHCI_PORT_IS_CLEAR 0xFFFFFFFF +#define EFI_AHCI_PORT_IS_FIS_CLEAR 0x0000000F
+#define EFI_AHCI_PORT_OFFSET(PortNum) \
(EFI_AHCI_PORT_START + ((PortNum) * EFI_AHCI_PORT_REG_WIDTH))
+#define EFI_AHCI_PORT_IE 0x0014 +#define EFI_AHCI_PORT_CMD 0x0018 +#define EFI_AHCI_PORT_CMD_ST_MASK 0xFFFFFFFE +#define EFI_AHCI_PORT_CMD_ST BIT0 +#define EFI_AHCI_PORT_CMD_SUD BIT1 +#define EFI_AHCI_PORT_CMD_POD BIT2 +#define EFI_AHCI_PORT_CMD_CLO BIT3 +#define EFI_AHCI_PORT_CMD_CR BIT15 +#define EFI_AHCI_PORT_CMD_FRE BIT4 +#define EFI_AHCI_PORT_CMD_FR BIT14 +#define EFI_AHCI_PORT_CMD_MASK ~(EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_FRE | EFI_AHCI_PORT_CMD_COL) +#define EFI_AHCI_PORT_CMD_PMA BIT17 +#define EFI_AHCI_PORT_CMD_HPCP BIT18 +#define EFI_AHCI_PORT_CMD_MPSP BIT19 +#define EFI_AHCI_PORT_CMD_CPD BIT20 +#define EFI_AHCI_PORT_CMD_ESP BIT21 +#define EFI_AHCI_PORT_CMD_ATAPI BIT24 +#define EFI_AHCI_PORT_CMD_DLAE BIT25 +#define EFI_AHCI_PORT_CMD_ALPE BIT26 +#define EFI_AHCI_PORT_CMD_ASP BIT27 +#define EFI_AHCI_PORT_CMD_ICC_MASK (BIT28 | BIT29 | BIT30 | BIT31) +#define EFI_AHCI_PORT_CMD_ACTIVE (1 << 28 ) +#define EFI_AHCI_PORT_TFD 0x0020 +#define EFI_AHCI_PORT_TFD_MASK (BIT7 | BIT3 | BIT0) +#define EFI_AHCI_PORT_TFD_BSY BIT7 +#define EFI_AHCI_PORT_TFD_DRQ BIT3 +#define EFI_AHCI_PORT_TFD_ERR BIT0 +#define EFI_AHCI_PORT_TFD_ERR_MASK 0x00FF00 +#define EFI_AHCI_PORT_SIG 0x0024 +#define EFI_AHCI_PORT_SSTS 0x0028 +#define EFI_AHCI_PORT_SSTS_DET_MASK 0x000F +#define EFI_AHCI_PORT_SSTS_DET 0x0001 +#define EFI_AHCI_PORT_SSTS_DET_PCE 0x0003 +#define EFI_AHCI_PORT_SSTS_SPD_MASK 0x00F0 +#define EFI_AHCI_PORT_SCTL 0x002C +#define EFI_AHCI_PORT_SCTL_DET_MASK 0x000F +#define EFI_AHCI_PORT_SCTL_MASK (~EFI_AHCI_PORT_SCTL_DET_MASK) +#define EFI_AHCI_PORT_SCTL_DET_INIT 0x0001 +#define EFI_AHCI_PORT_SCTL_DET_PHYCOMM 0x0003 +#define EFI_AHCI_PORT_SCTL_SPD_MASK 0x00F0 +#define EFI_AHCI_PORT_SCTL_IPM_MASK 0x0F00 +#define EFI_AHCI_PORT_SCTL_IPM_INIT 0x0300 +#define EFI_AHCI_PORT_SCTL_IPM_PSD 0x0100 +#define EFI_AHCI_PORT_SCTL_IPM_SSD 0x0200 +#define EFI_AHCI_PORT_SERR 0x0030 +#define EFI_AHCI_PORT_SERR_RDIE BIT0 +#define EFI_AHCI_PORT_SERR_RCE BIT1 +#define EFI_AHCI_PORT_SERR_TDIE BIT8 +#define EFI_AHCI_PORT_SERR_PCDIE BIT9 +#define EFI_AHCI_PORT_SERR_PE BIT10 +#define EFI_AHCI_PORT_SERR_IE BIT11 +#define EFI_AHCI_PORT_SERR_PRC BIT16 +#define EFI_AHCI_PORT_SERR_PIE BIT17 +#define EFI_AHCI_PORT_SERR_CW BIT18 +#define EFI_AHCI_PORT_SERR_BDE BIT19 +#define EFI_AHCI_PORT_SERR_DE BIT20 +#define EFI_AHCI_PORT_SERR_CRCE BIT21 +#define EFI_AHCI_PORT_SERR_HE BIT22 +#define EFI_AHCI_PORT_SERR_LSE BIT23 +#define EFI_AHCI_PORT_SERR_TSTE BIT24 +#define EFI_AHCI_PORT_SERR_UFT BIT25 +#define EFI_AHCI_PORT_SERR_EX BIT26 +#define EFI_AHCI_PORT_ERR_CLEAR 0xFFFFFFFF +#define EFI_AHCI_PORT_SACT 0x0034 +#define EFI_AHCI_PORT_CI 0x0038 +#define EFI_AHCI_PORT_SNTF 0x003C
+#endif diff --git a/Platforms/AMD/Styx/Drivers/StyxSataPlatformDxe/StyxSataPlatformDxe.inf b/Platforms/AMD/Styx/Drivers/StyxSataPlatformDxe/StyxSataPlatformDxe.inf new file mode 100644 index 000000000000..da9e667da1ab --- /dev/null +++ b/Platforms/AMD/Styx/Drivers/StyxSataPlatformDxe/StyxSataPlatformDxe.inf @@ -0,0 +1,61 @@ +## @file +# +# Component description file for the Styx SATA platform driver. +# +# 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. +# +##
+[Defines]
- INF_VERSION = 0x00010005
<random coment>
- BASE_NAME = StyxSataPlatformDxe
- FILE_GUID = 4703fac4-9de9-4010-87d1-11402894296a
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.0
- ENTRY_POINT = StyxSataPlatformDxeEntryPoint
+[Sources]
- InitController.c
+[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
- EmbeddedPkg/EmbeddedPkg.dec
- AmdModulePkg/AmdModulePkg.dec
- OpenPlatformPkg/Platforms/AMD/Styx/AmdStyx.dec
+[LibraryClasses]
- AmdSataInit
- UefiDriverEntryPoint
- DebugLib
- BaseLib
- PlatformPciIoDeviceRegistrationLib
- UefiBootServicesTableLib
Could the LibraryClasses and Packages be OCD sorted, or is there a particular reason to have them in this order?
/ Leif
+[FixedPcd]
- gAmdModulePkgTokenSpaceGuid.PcdSataSerdesBase
- gAmdModulePkgTokenSpaceGuid.PcdSataSerdesOffset
- gAmdModulePkgTokenSpaceGuid.PcdSataNumChPerSerdes
- gAmdStyxTokenSpaceGuid.PcdSataCtrlAxiSlvPort
- gAmdStyxTokenSpaceGuid.PcdSataPortCount
- gAmdStyxTokenSpaceGuid.PcdSataPortMode
- gAmdStyxTokenSpaceGuid.PcdSataSmpsSupport
- gAmdStyxTokenSpaceGuid.PcdSataSssSupport
- gAmdStyxTokenSpaceGuid.PcdSataPortCpd
- gAmdStyxTokenSpaceGuid.PcdSataPortMpsp
- gAmdStyxTokenSpaceGuid.PcdSata1CtrlAxiSlvPort
- gAmdStyxTokenSpaceGuid.PcdSata1PortCount
+[Depex]
- TRUE
-- 2.7.4