DynamicTablesPkg: Add SSDT CMN-600 Table generator
The Generic ACPI for Arm Components 1.0 Platform Design Document, s2.6.4 "ASL code examples" provides information to describe an Arm CoreLink CMN-600 Coherent Mesh Network using an ASL definition block table. The SSDT CMN-600 Table Generator uses the Configuration Manager protocol to obtain the following information about the CMN-600 device on the platform: - the PERIPHBASE address location and address range; - the ROOTNODEBASE address location; - the number of Debug and Trace Controller (DTC) and their respective interrupt number; The CMN-600 mesh is described using the CM_ARM_CMN_600_INFO and CM_ARM_EXTENDED_INTERRUPT structures in the Configuration Manager. The SSDT CMN-600 Table generator: - gets the CMN-600 hardware information from the configuration manager. - uses the AmlLib interfaces to parse the AML template BLOB and construct an AML tree. - uses the AmlLib to update: - the "_UID" value; - the address location and range of the PERIPHBASE; - the address location of the ROOTNODEBASE; - the number of Debug and Trace Controller (DTC) and their respective interrupt number; - serializes the AML tree to an output buffer. This output buffer contains the fixed-up AML code, which is then installed as an ACPI SSDT table. Signed-off-by: Pierre Gondois <pierre.gondois@arm.com> Co-authored-by: Sami Mujawar <sami.mujawar@arm.com> Reviewed-by: Alexei Fedorov <Alexei.Fedorov@arm.com>
This commit is contained in:
parent
aa49066fe6
commit
375683654d
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
# AML Fixup
|
# AML Fixup
|
||||||
DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
|
DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
|
||||||
|
DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf
|
||||||
|
|
||||||
#
|
#
|
||||||
# Dynamic Table Factory Dxe
|
# Dynamic Table Factory Dxe
|
||||||
|
@ -53,6 +54,7 @@
|
||||||
|
|
||||||
# AML Fixup
|
# AML Fixup
|
||||||
NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
|
NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
|
||||||
|
NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -70,6 +70,7 @@
|
||||||
# in matching files
|
# in matching files
|
||||||
"ExtendWords": [
|
"ExtendWords": [
|
||||||
"ARMHB", # ARMHB000
|
"ARMHB", # ARMHB000
|
||||||
|
"ARMHC", # ARMHC600
|
||||||
"ARMLTD",
|
"ARMLTD",
|
||||||
"AMLDBG",
|
"AMLDBG",
|
||||||
"EISAID",
|
"EISAID",
|
||||||
|
@ -82,8 +83,11 @@
|
||||||
"lgreater",
|
"lgreater",
|
||||||
"lless",
|
"lless",
|
||||||
"MPIDR",
|
"MPIDR",
|
||||||
|
"PERIPHBASE",
|
||||||
"pytool",
|
"pytool",
|
||||||
"Roadmap",
|
"Roadmap",
|
||||||
|
"ROOTNODEBASE",
|
||||||
|
"ssdtcmn",
|
||||||
"ssdtserialporttemplate",
|
"ssdtserialporttemplate",
|
||||||
"SMMUV",
|
"SMMUV",
|
||||||
"standardised",
|
"standardised",
|
||||||
|
|
|
@ -59,6 +59,10 @@ The Dynamic Tables Framework implements the following ACPI table generators:
|
||||||
The SSDT Serial generator collates the Serial port information
|
The SSDT Serial generator collates the Serial port information
|
||||||
from the Configuration Manager and patches the SSDT Serial Port
|
from the Configuration Manager and patches the SSDT Serial Port
|
||||||
template to build the SSDT Serial port table.
|
template to build the SSDT Serial port table.
|
||||||
|
- SSDT CMN-600:
|
||||||
|
The SSDT CMN-600 generator collates the CMN-600 information
|
||||||
|
from the Configuration Manager and patches the SSDT CMN-600
|
||||||
|
template to build the SSDT CMN-600 table.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
|
/** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
|
||||||
|
@ -83,6 +87,7 @@ typedef enum StdAcpiTableId {
|
||||||
EStdAcpiTableIdPptt, ///< PPTT Generator
|
EStdAcpiTableIdPptt, ///< PPTT Generator
|
||||||
EStdAcpiTableIdSrat, ///< SRAT Generator
|
EStdAcpiTableIdSrat, ///< SRAT Generator
|
||||||
EStdAcpiTableIdSsdtSerialPort, ///< SSDT Serial-Port Generator
|
EStdAcpiTableIdSsdtSerialPort, ///< SSDT Serial-Port Generator
|
||||||
|
EStdAcpiTableIdSsdtCmn600, ///< SSDT Cmn-600 Generator
|
||||||
EStdAcpiTableIdMax
|
EStdAcpiTableIdMax
|
||||||
} ESTD_ACPI_TABLE_ID;
|
} ESTD_ACPI_TABLE_ID;
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ typedef enum ArmObjectID {
|
||||||
EArmObjDeviceHandlePci, ///< 33 - Device Handle Pci
|
EArmObjDeviceHandlePci, ///< 33 - Device Handle Pci
|
||||||
EArmObjGenericInitiatorAffinityInfo, ///< 34 - Generic Initiator Affinity
|
EArmObjGenericInitiatorAffinityInfo, ///< 34 - Generic Initiator Affinity
|
||||||
EArmObjSerialPortInfo, ///< 35 - Generic Serial Port Info
|
EArmObjSerialPortInfo, ///< 35 - Generic Serial Port Info
|
||||||
|
EArmObjCmn600Info, ///< 36 - CMN-600 Info
|
||||||
EArmObjMax
|
EArmObjMax
|
||||||
} EARM_OBJECT_ID;
|
} EARM_OBJECT_ID;
|
||||||
|
|
||||||
|
@ -653,18 +654,37 @@ typedef struct CmArmIdMapping {
|
||||||
UINT32 Flags;
|
UINT32 Flags;
|
||||||
} CM_ARM_ID_MAPPING;
|
} CM_ARM_ID_MAPPING;
|
||||||
|
|
||||||
/** A structure that describes the
|
/** A structure that describes the Arm
|
||||||
SMMU interrupts for the Platform.
|
Generic Interrupts.
|
||||||
|
|
||||||
ID: EArmObjSmmuInterruptArray
|
|
||||||
*/
|
*/
|
||||||
typedef struct CmArmSmmuInterrupt {
|
typedef struct CmArmGenericInterrupt {
|
||||||
/// Interrupt number
|
/// Interrupt number
|
||||||
UINT32 Interrupt;
|
UINT32 Interrupt;
|
||||||
|
|
||||||
/// Flags
|
/// Flags
|
||||||
UINT32 Flags;
|
UINT32 Flags;
|
||||||
} CM_ARM_SMMU_INTERRUPT;
|
} CM_ARM_GENERIC_INTERRUPT;
|
||||||
|
|
||||||
|
/** A structure that describes the SMMU interrupts for the Platform.
|
||||||
|
|
||||||
|
Interrupt Interrupt number.
|
||||||
|
Flags Interrupt flags as defined for SMMU node.
|
||||||
|
|
||||||
|
ID: EArmObjSmmuInterruptArray
|
||||||
|
*/
|
||||||
|
typedef CM_ARM_GENERIC_INTERRUPT CM_ARM_SMMU_INTERRUPT;
|
||||||
|
|
||||||
|
/** A structure that describes the AML Extended Interrupts.
|
||||||
|
|
||||||
|
Interrupt Interrupt number.
|
||||||
|
Flags Interrupt flags as defined by the Interrupt
|
||||||
|
Vector Flags (Byte 3) of the Extended Interrupt
|
||||||
|
resource descriptor.
|
||||||
|
See EFI_ACPI_EXTENDED_INTERRUPT_FLAG_xxx in Acpi10.h
|
||||||
|
|
||||||
|
ID: EArmObjExtendedInterruptInfo
|
||||||
|
*/
|
||||||
|
typedef CM_ARM_GENERIC_INTERRUPT CM_ARM_EXTENDED_INTERRUPT;
|
||||||
|
|
||||||
/** A structure that describes the Processor Hierarchy Node (Type 0) in PPTT
|
/** A structure that describes the Processor Hierarchy Node (Type 0) in PPTT
|
||||||
|
|
||||||
|
@ -825,6 +845,38 @@ typedef struct CmArmGenericInitiatorAffinityInfo {
|
||||||
CM_OBJECT_TOKEN DeviceHandleToken;
|
CM_OBJECT_TOKEN DeviceHandleToken;
|
||||||
} CM_ARM_GENERIC_INITIATOR_AFFINITY_INFO;
|
} CM_ARM_GENERIC_INITIATOR_AFFINITY_INFO;
|
||||||
|
|
||||||
|
/** A structure that describes the CMN-600 hardware.
|
||||||
|
|
||||||
|
ID: EArmObjCmn600Info
|
||||||
|
*/
|
||||||
|
typedef struct CmArmCmn600Info {
|
||||||
|
/// The PERIPHBASE address.
|
||||||
|
/// Corresponds to the Configuration Node Region (CFGR) base address.
|
||||||
|
UINT64 PeriphBaseAddress;
|
||||||
|
|
||||||
|
/// The PERIPHBASE address length.
|
||||||
|
/// Corresponds to the CFGR base address length.
|
||||||
|
UINT64 PeriphBaseAddressLength;
|
||||||
|
|
||||||
|
/// The ROOTNODEBASE address.
|
||||||
|
/// Corresponds to the Root node (ROOT) base address.
|
||||||
|
UINT64 RootNodeBaseAddress;
|
||||||
|
|
||||||
|
/// The Debug and Trace Logic Controller (DTC) count.
|
||||||
|
/// CMN-600 can have maximum 4 DTCs.
|
||||||
|
UINT8 DtcCount;
|
||||||
|
|
||||||
|
/// DTC Interrupt list.
|
||||||
|
/// The first interrupt resource descriptor pertains to
|
||||||
|
/// DTC[0], the second to DTC[1] and so on.
|
||||||
|
/// DtcCount determines the number of DTC Interrupts that
|
||||||
|
/// are populated. If DTC count is 2 then DtcInterrupt[2]
|
||||||
|
/// and DtcInterrupt[3] are ignored.
|
||||||
|
/// Note: The size of CM_ARM_CMN_600_INFO structure remains
|
||||||
|
/// constant and does not vary with the DTC count.
|
||||||
|
CM_ARM_EXTENDED_INTERRUPT DtcInterrupt[4];
|
||||||
|
} CM_ARM_CMN_600_INFO;
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
#endif // ARM_NAMESPACE_OBJECTS_H_
|
#endif // ARM_NAMESPACE_OBJECTS_H_
|
||||||
|
|
|
@ -0,0 +1,708 @@
|
||||||
|
/** @file
|
||||||
|
SSDT CMN-600 AML Table Generator.
|
||||||
|
|
||||||
|
Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
@par Reference(s):
|
||||||
|
- Arm CoreLink CMN-600 Coherent Mesh Network Technical Reference Manual r3p0
|
||||||
|
- Generic ACPI for Arm Components 1.0 Platform Design Document
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <IndustryStandard/DebugPort2Table.h>
|
||||||
|
#include <Library/AcpiLib.h>
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
#include <Protocol/AcpiTable.h>
|
||||||
|
|
||||||
|
// Module specific include files.
|
||||||
|
#include <AcpiTableGenerator.h>
|
||||||
|
#include <ConfigurationManagerObject.h>
|
||||||
|
#include <ConfigurationManagerHelper.h>
|
||||||
|
#include <Library/AmlLib/AmlLib.h>
|
||||||
|
#include <Library/TableHelperLib.h>
|
||||||
|
#include <Protocol/ConfigurationManagerProtocol.h>
|
||||||
|
#include "SsdtCmn600Generator.h"
|
||||||
|
|
||||||
|
/** C array containing the compiled AML template.
|
||||||
|
This symbol is defined in the auto generated C file
|
||||||
|
containing the AML bytecode array.
|
||||||
|
*/
|
||||||
|
extern CHAR8 ssdtcmn600template_aml_code[];
|
||||||
|
|
||||||
|
/** SSDT CMN-600 Table Generator.
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
The following Configuration Manager Object(s) are required by
|
||||||
|
this Generator:
|
||||||
|
- EArmObjCmn600Info
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** This macro expands to a function that retrieves the CMN-600
|
||||||
|
Information from the Configuration Manager.
|
||||||
|
*/
|
||||||
|
GET_OBJECT_LIST (
|
||||||
|
EObjNameSpaceArm,
|
||||||
|
EArmObjCmn600Info,
|
||||||
|
CM_ARM_CMN_600_INFO
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Check the CMN-600 Information.
|
||||||
|
|
||||||
|
@param [in] Cmn600InfoList Array of CMN-600 information structure.
|
||||||
|
@param [in] Cmn600Count Count of CMN-600 information structure.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The function completed successfully.
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ValidateCmn600Info (
|
||||||
|
IN CONST CM_ARM_CMN_600_INFO * Cmn600InfoList,
|
||||||
|
IN CONST UINT32 Cmn600Count
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 Index;
|
||||||
|
UINT32 DtcIndex;
|
||||||
|
CONST CM_ARM_CMN_600_INFO * Cmn600Info;
|
||||||
|
CONST CM_ARM_GENERIC_INTERRUPT * DtcInterrupt;
|
||||||
|
|
||||||
|
if ((Cmn600InfoList == NULL) ||
|
||||||
|
(Cmn600Count == 0)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate each Cmn600Info structure.
|
||||||
|
for (Index = 0; Index < Cmn600Count; Index++) {
|
||||||
|
Cmn600Info = &Cmn600InfoList[Index];
|
||||||
|
|
||||||
|
// At least one DTC is required.
|
||||||
|
if ((Cmn600Info->DtcCount == 0) ||
|
||||||
|
(Cmn600Info->DtcCount > MAX_DTC_COUNT)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: Invalid DTC configuration:\n"
|
||||||
|
));
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check PERIPHBASE and ROOTNODEBASE address spaces are initialized.
|
||||||
|
if ((Cmn600Info->PeriphBaseAddress == 0) ||
|
||||||
|
(Cmn600Info->RootNodeBaseAddress == 0)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: Invalid PERIPHBASE or ROOTNODEBASE.\n"
|
||||||
|
));
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The PERIPHBASE address must be 64MB aligned for a (X < 4) && (Y < 4)
|
||||||
|
// dimension mesh, and 256MB aligned otherwise.
|
||||||
|
// Check it is a least 64MB aligned.
|
||||||
|
if ((Cmn600Info->PeriphBaseAddress &
|
||||||
|
(PERIPHBASE_MIN_ADDRESS_LENGTH - 1)) != 0) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: PERIPHBASE address must be 64MB aligned.\n"
|
||||||
|
));
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The PERIPHBASE address is at most 64MB for a (X < 4) && (Y < 4)
|
||||||
|
// dimension mesh, and 256MB otherwise. Check it is not more than 256MB.
|
||||||
|
if (Cmn600Info->PeriphBaseAddressLength > PERIPHBASE_MAX_ADDRESS_LENGTH) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: PERIPHBASE address range must be < 256MB.\n"
|
||||||
|
));
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the 16 KB alignment of the ROOTNODEBASE address.
|
||||||
|
if ((Cmn600Info->PeriphBaseAddress &
|
||||||
|
(ROOTNODEBASE_ADDRESS_LENGTH - 1)) != 0) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: Root base address must be 16KB aligned.\n"
|
||||||
|
));
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The ROOTNODEBASE address space should be included in the PERIPHBASE
|
||||||
|
// address space.
|
||||||
|
if ((Cmn600Info->PeriphBaseAddress > Cmn600Info->RootNodeBaseAddress) ||
|
||||||
|
((Cmn600Info->PeriphBaseAddress + Cmn600Info->PeriphBaseAddressLength) <
|
||||||
|
(Cmn600Info->RootNodeBaseAddress + ROOTNODEBASE_ADDRESS_LENGTH))) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600:"
|
||||||
|
" ROOTNODEBASE address space not in PERIPHBASE address space.\n"
|
||||||
|
));
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DtcIndex = 0; DtcIndex < Cmn600Info->DtcCount; DtcIndex++) {
|
||||||
|
DtcInterrupt = &Cmn600Info->DtcInterrupt[DtcIndex];
|
||||||
|
if (((DtcInterrupt->Flags &
|
||||||
|
EFI_ACPI_EXTENDED_INTERRUPT_FLAG_PRODUCER_CONSUMER_MASK) == 0)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: DTC Interrupt must be consumer.\n"
|
||||||
|
));
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
} // for DTC Interrupt
|
||||||
|
|
||||||
|
} //for Cmn600InfoList
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
error_handler:
|
||||||
|
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"PeriphBaseAddress = 0x%llx\n"
|
||||||
|
"PeriphBaseAddressLength = 0x%llx\n"
|
||||||
|
"RootNodeBaseAddress = 0x%llx\n"
|
||||||
|
"DtcCount = %u\n",
|
||||||
|
Cmn600Info->PeriphBaseAddress,
|
||||||
|
Cmn600Info->PeriphBaseAddressLength,
|
||||||
|
Cmn600Info->RootNodeBaseAddress,
|
||||||
|
Cmn600Info->DtcCount
|
||||||
|
));
|
||||||
|
|
||||||
|
DEBUG_CODE (
|
||||||
|
for (DtcIndex = 0; DtcIndex < Cmn600Info->DtcCount; DtcIndex++) {
|
||||||
|
DtcInterrupt = &Cmn600Info->DtcInterrupt[DtcIndex];
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
" DTC[%d]:\n",
|
||||||
|
DtcIndex
|
||||||
|
));
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
" Interrupt = 0x%lx\n",
|
||||||
|
DtcInterrupt->Interrupt
|
||||||
|
));
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
" Flags = 0x%lx\n",
|
||||||
|
DtcInterrupt->Flags
|
||||||
|
));
|
||||||
|
} // for
|
||||||
|
);
|
||||||
|
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Build a SSDT table describing the CMN-600 device.
|
||||||
|
|
||||||
|
The table created by this function must be freed by FreeSsdtCmn600Table.
|
||||||
|
|
||||||
|
@param [in] Cmn600Info Pointer to a Cmn600 structure.
|
||||||
|
@param [in] Name The Name to give to the Device.
|
||||||
|
Must be a NULL-terminated ASL NameString
|
||||||
|
e.g.: "DEV0", "DV15.DEV0", etc.
|
||||||
|
@param [in] Uid UID for the CMN600 device.
|
||||||
|
@param [out] Table If success, pointer to the created SSDT table.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Table generated successfully.
|
||||||
|
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||||
|
@retval EFI_NOT_FOUND Could not find information.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Could not allocate memory.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FixupCmn600Info (
|
||||||
|
IN CONST CM_ARM_CMN_600_INFO * Cmn600Info,
|
||||||
|
IN CONST CHAR8 * Name,
|
||||||
|
IN CONST UINT64 Uid,
|
||||||
|
OUT EFI_ACPI_DESCRIPTION_HEADER ** Table
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_STATUS Status1;
|
||||||
|
UINT8 Index;
|
||||||
|
CONST CM_ARM_GENERIC_INTERRUPT * DtcInt;
|
||||||
|
|
||||||
|
EFI_ACPI_DESCRIPTION_HEADER * SsdtCmn600Template;
|
||||||
|
AML_ROOT_NODE_HANDLE RootNodeHandle;
|
||||||
|
AML_OBJECT_NODE_HANDLE NameOpIdNode;
|
||||||
|
AML_OBJECT_NODE_HANDLE NameOpCrsNode;
|
||||||
|
AML_DATA_NODE_HANDLE CmnPeriphBaseRdNode;
|
||||||
|
AML_DATA_NODE_HANDLE CmnRootNodeBaseRdNode;
|
||||||
|
AML_OBJECT_NODE_HANDLE DeviceNode;
|
||||||
|
|
||||||
|
// Parse the Ssdt CMN-600 Template.
|
||||||
|
SsdtCmn600Template = (EFI_ACPI_DESCRIPTION_HEADER*)
|
||||||
|
ssdtcmn600template_aml_code;
|
||||||
|
|
||||||
|
RootNodeHandle = NULL;
|
||||||
|
Status = AmlParseDefinitionBlock (
|
||||||
|
SsdtCmn600Template,
|
||||||
|
&RootNodeHandle
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: Failed to parse SSDT CMN-600 Template."
|
||||||
|
" Status = %r\n",
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the _UID NameOp object defined by the "Name ()" statement,
|
||||||
|
// and update its value.
|
||||||
|
Status = AmlFindNode (
|
||||||
|
RootNodeHandle,
|
||||||
|
"\\_SB_.CMN0._UID",
|
||||||
|
&NameOpIdNode
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = AmlNameOpUpdateInteger (NameOpIdNode, (UINT64)Uid);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the _CRS object defined by the "Name ()" statement.
|
||||||
|
Status = AmlFindNode (
|
||||||
|
RootNodeHandle,
|
||||||
|
"\\_SB.CMN0._CRS",
|
||||||
|
&NameOpCrsNode
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the first Rd node in the "_CRS" object.
|
||||||
|
// This is the PERIPHBASE node.
|
||||||
|
Status = AmlNameOpCrsGetFirstRdNode (NameOpCrsNode, &CmnPeriphBaseRdNode);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CmnPeriphBaseRdNode == NULL) {
|
||||||
|
Status = EFI_INVALID_PARAMETER;
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the PERIPHBASE base address and length.
|
||||||
|
Status = AmlUpdateRdQWord (
|
||||||
|
CmnPeriphBaseRdNode,
|
||||||
|
Cmn600Info->PeriphBaseAddress,
|
||||||
|
Cmn600Info->PeriphBaseAddressLength
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the QWord node corresponding to the ROOTNODEBASE.
|
||||||
|
// It is the second Resource Data element in the BufferNode's
|
||||||
|
// variable list of arguments.
|
||||||
|
Status = AmlNameOpCrsGetNextRdNode (
|
||||||
|
CmnPeriphBaseRdNode,
|
||||||
|
&CmnRootNodeBaseRdNode
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CmnRootNodeBaseRdNode == NULL) {
|
||||||
|
Status = EFI_INVALID_PARAMETER;
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the ROOTNODEBASE base address and length.
|
||||||
|
Status = AmlUpdateRdQWord (
|
||||||
|
CmnRootNodeBaseRdNode,
|
||||||
|
Cmn600Info->RootNodeBaseAddress,
|
||||||
|
ROOTNODEBASE_ADDRESS_LENGTH
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the Interrupt node(s).
|
||||||
|
// Generate Resource Data node(s) corresponding to the "Interrupt ()"
|
||||||
|
// ASL function and add it at the last position in the list of
|
||||||
|
// Resource Data nodes.
|
||||||
|
for (Index = 0; Index < Cmn600Info->DtcCount; Index++) {
|
||||||
|
DtcInt = &Cmn600Info->DtcInterrupt[Index];
|
||||||
|
Status = AmlCodeGenCrsAddRdInterrupt (
|
||||||
|
NameOpCrsNode,
|
||||||
|
((DtcInt->Flags &
|
||||||
|
EFI_ACPI_EXTENDED_INTERRUPT_FLAG_PRODUCER_CONSUMER_MASK) != 0),
|
||||||
|
((DtcInt->Flags &
|
||||||
|
EFI_ACPI_EXTENDED_INTERRUPT_FLAG_MODE_MASK) != 0),
|
||||||
|
((DtcInt->Flags &
|
||||||
|
EFI_ACPI_EXTENDED_INTERRUPT_FLAG_POLARITY_MASK) != 0),
|
||||||
|
((DtcInt->Flags &
|
||||||
|
EFI_ACPI_EXTENDED_INTERRUPT_FLAG_SHARABLE_MASK) != 0),
|
||||||
|
(UINT32*)&DtcInt->Interrupt,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
} // for
|
||||||
|
|
||||||
|
// Fixup the CMN600 device name.
|
||||||
|
// This MUST be done at the end, otherwise AML paths won't be valid anymore.
|
||||||
|
// Get the CMN0 variable defined by the "Device ()" statement.
|
||||||
|
Status = AmlFindNode (RootNodeHandle, "\\_SB_.CMN0", &DeviceNode);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the CMN600 Device's name.
|
||||||
|
Status = AmlDeviceOpUpdateName (DeviceNode, (CHAR8*)Name);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialise the definition block
|
||||||
|
Status = AmlSerializeDefinitionBlock (
|
||||||
|
RootNodeHandle,
|
||||||
|
Table
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: Failed to Serialize SSDT Table Data."
|
||||||
|
" Status = %r\n",
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
error_handler:
|
||||||
|
// Cleanup
|
||||||
|
if (RootNodeHandle != NULL) {
|
||||||
|
Status1 = AmlDeleteTree (RootNodeHandle);
|
||||||
|
if (EFI_ERROR (Status1)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: Failed to cleanup AML tree."
|
||||||
|
" Status = %r\n",
|
||||||
|
Status1
|
||||||
|
));
|
||||||
|
// If Status was success but we failed to delete the AML Tree
|
||||||
|
// return Status1 else return the original error code, i.e. Status.
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
return Status1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Free any resources allocated for constructing the SSDT tables for CMN-600.
|
||||||
|
|
||||||
|
@param [in] This Pointer to the ACPI table generator.
|
||||||
|
@param [in] AcpiTableInfo Pointer to the ACPI Table Info.
|
||||||
|
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||||
|
Protocol Interface.
|
||||||
|
@param [in, out] Table Pointer to an array of pointers
|
||||||
|
to ACPI Table(s).
|
||||||
|
@param [in] TableCount Number of ACPI table(s).
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The resources were freed successfully.
|
||||||
|
@retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FreeSsdtCmn600TableResourcesEx (
|
||||||
|
IN CONST ACPI_TABLE_GENERATOR * CONST This,
|
||||||
|
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
|
||||||
|
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
|
||||||
|
IN OUT EFI_ACPI_DESCRIPTION_HEADER *** CONST Table,
|
||||||
|
IN CONST UINTN TableCount
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_ACPI_DESCRIPTION_HEADER ** TableList;
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
ASSERT (This != NULL);
|
||||||
|
ASSERT (AcpiTableInfo != NULL);
|
||||||
|
ASSERT (CfgMgrProtocol != NULL);
|
||||||
|
ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
|
||||||
|
ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
|
||||||
|
|
||||||
|
if ((Table == NULL) ||
|
||||||
|
(*Table == NULL) ||
|
||||||
|
(TableCount == 0)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "ERROR: SSDT-CMN-600: Invalid Table Pointer\n"));
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
TableList = *Table;
|
||||||
|
|
||||||
|
for (Index = 0; Index < TableCount; Index++) {
|
||||||
|
if ((TableList[Index] != NULL) &&
|
||||||
|
(TableList[Index]->Signature ==
|
||||||
|
EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) {
|
||||||
|
FreePool (TableList[Index]);
|
||||||
|
} else {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: Could not free SSDT table at index %d."
|
||||||
|
" Status = %r\n",
|
||||||
|
Index,
|
||||||
|
EFI_INVALID_PARAMETER
|
||||||
|
));
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
} //for
|
||||||
|
|
||||||
|
// Free the table list.
|
||||||
|
FreePool (*Table);
|
||||||
|
*Table = NULL;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct SSDT tables for describing CMN-600 meshes.
|
||||||
|
|
||||||
|
This function invokes the Configuration Manager protocol interface
|
||||||
|
to get the required hardware information for generating the ACPI
|
||||||
|
table.
|
||||||
|
|
||||||
|
If this function allocates any resources then they must be freed
|
||||||
|
in the FreeXXXXTableResourcesEx function.
|
||||||
|
|
||||||
|
@param [in] This Pointer to the ACPI table generator.
|
||||||
|
@param [in] AcpiTableInfo Pointer to the ACPI table information.
|
||||||
|
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||||
|
Protocol interface.
|
||||||
|
@param [out] Table Pointer to a list of generated ACPI table(s).
|
||||||
|
@param [out] TableCount Number of generated ACPI table(s).
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Table generated successfully.
|
||||||
|
@retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
|
||||||
|
Manager is less than the Object size for
|
||||||
|
the requested object.
|
||||||
|
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||||
|
@retval EFI_NOT_FOUND Could not find information.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Could not allocate memory.
|
||||||
|
@retval EFI_UNSUPPORTED Unsupported configuration.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
BuildSsdtCmn600TableEx (
|
||||||
|
IN CONST ACPI_TABLE_GENERATOR * This,
|
||||||
|
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
|
||||||
|
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
|
||||||
|
OUT EFI_ACPI_DESCRIPTION_HEADER *** Table,
|
||||||
|
OUT UINTN * CONST TableCount
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT64 Index;
|
||||||
|
CM_ARM_CMN_600_INFO * Cmn600Info;
|
||||||
|
UINT32 Cmn600Count;
|
||||||
|
CHAR8 NewName[5];
|
||||||
|
EFI_ACPI_DESCRIPTION_HEADER ** TableList;
|
||||||
|
|
||||||
|
ASSERT (This != NULL);
|
||||||
|
ASSERT (AcpiTableInfo != NULL);
|
||||||
|
ASSERT (CfgMgrProtocol != NULL);
|
||||||
|
ASSERT (Table != NULL);
|
||||||
|
ASSERT (TableCount != NULL);
|
||||||
|
ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
|
||||||
|
ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
|
||||||
|
|
||||||
|
*Table = NULL;
|
||||||
|
|
||||||
|
// Get CMN-600 information.
|
||||||
|
Status = GetEArmObjCmn600Info (
|
||||||
|
CfgMgrProtocol,
|
||||||
|
CM_NULL_TOKEN,
|
||||||
|
&Cmn600Info,
|
||||||
|
&Cmn600Count
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: Failed to get the CMN-600 information."
|
||||||
|
" Status = %r\n",
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Cmn600Count == 0) || (Cmn600Count > MAX_CMN600_DEVICES_SUPPORTED)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: CMN600 peripheral count = %d."
|
||||||
|
" This must be between 1 to 16.\n",
|
||||||
|
Cmn600Count
|
||||||
|
));
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CMN-600 Info.
|
||||||
|
Status = ValidateCmn600Info (Cmn600Info, Cmn600Count);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: Invalid CMN600 information. Status = %r\n",
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a table to store pointers to the SSDT tables.
|
||||||
|
TableList = (EFI_ACPI_DESCRIPTION_HEADER**)
|
||||||
|
AllocateZeroPool (
|
||||||
|
(sizeof (EFI_ACPI_DESCRIPTION_HEADER*) * Cmn600Count)
|
||||||
|
);
|
||||||
|
if (TableList == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: Failed to allocate memory for Table List."
|
||||||
|
" Status = %r\n",
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the table list early so that that appropriate cleanup
|
||||||
|
// can be done in case of failure.
|
||||||
|
*Table = TableList;
|
||||||
|
|
||||||
|
NewName[0] = 'C';
|
||||||
|
NewName[1] = 'M';
|
||||||
|
NewName[2] = 'N';
|
||||||
|
NewName[4] = '\0';
|
||||||
|
for (Index = 0; Index < Cmn600Count; Index++) {
|
||||||
|
NewName[3] = AsciiFromHex ((UINT8)(Index));
|
||||||
|
|
||||||
|
// Build a SSDT table describing the CMN600 device.
|
||||||
|
Status = FixupCmn600Info (
|
||||||
|
&Cmn600Info[Index],
|
||||||
|
NewName,
|
||||||
|
Index,
|
||||||
|
&TableList[Index]
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"ERROR: SSDT-CMN-600: Failed to build associated SSDT table."
|
||||||
|
" Status = %r\n",
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the table count here so that appropriate clean-up
|
||||||
|
// can be done in case of failure.
|
||||||
|
*TableCount += 1;
|
||||||
|
} // for
|
||||||
|
|
||||||
|
// Note: Table list and CMN600 device count has been setup. The
|
||||||
|
// framework will invoke FreeSsdtCmn600TableResourcesEx() even
|
||||||
|
// on failure, so appropriate clean-up will be done.
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This macro defines the Raw Generator revision.
|
||||||
|
*/
|
||||||
|
#define SSDT_CMN_600_GENERATOR_REVISION CREATE_REVISION (1, 0)
|
||||||
|
|
||||||
|
/** The interface for the Raw Table Generator.
|
||||||
|
*/
|
||||||
|
STATIC
|
||||||
|
CONST
|
||||||
|
ACPI_TABLE_GENERATOR SsdtCmn600Generator = {
|
||||||
|
// Generator ID
|
||||||
|
CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtCmn600),
|
||||||
|
// Generator Description
|
||||||
|
L"ACPI.STD.SSDT.CMN600.GENERATOR",
|
||||||
|
// ACPI Table Signature
|
||||||
|
EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
|
||||||
|
// ACPI Table Revision - Unused
|
||||||
|
0,
|
||||||
|
// Minimum ACPI Table Revision - Unused
|
||||||
|
0,
|
||||||
|
// Creator ID
|
||||||
|
TABLE_GENERATOR_CREATOR_ID_ARM,
|
||||||
|
// Creator Revision
|
||||||
|
SSDT_CMN_600_GENERATOR_REVISION,
|
||||||
|
// Build table function. Use the extended version instead.
|
||||||
|
NULL,
|
||||||
|
// Free table function. Use the extended version instead.
|
||||||
|
NULL,
|
||||||
|
// Build Table function
|
||||||
|
BuildSsdtCmn600TableEx,
|
||||||
|
// Free Resource function
|
||||||
|
FreeSsdtCmn600TableResourcesEx
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Register the Generator with the ACPI Table Factory.
|
||||||
|
|
||||||
|
@param [in] ImageHandle The handle to the image.
|
||||||
|
@param [in] SystemTable Pointer to the System Table.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The Generator is registered.
|
||||||
|
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||||
|
@retval EFI_ALREADY_STARTED The Generator for the Table ID
|
||||||
|
is already registered.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
AcpiSsdtCmn600LibConstructor (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE * SystemTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
Status = RegisterAcpiTableGenerator (&SsdtCmn600Generator);
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
"SSDT-CMN-600: Register Generator. Status = %r\n",
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Deregister the Generator from the ACPI Table Factory.
|
||||||
|
|
||||||
|
@param [in] ImageHandle The handle to the image.
|
||||||
|
@param [in] SystemTable Pointer to the System Table.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The Generator is deregistered.
|
||||||
|
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||||
|
@retval EFI_NOT_FOUND The Generator is not registered.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
AcpiSsdtCmn600LibDestructor (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE * SystemTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
Status = DeregisterAcpiTableGenerator (&SsdtCmn600Generator);
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
"SSDT-CMN-600: Deregister Generator. Status = %r\n",
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
return Status;
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/** @file
|
||||||
|
|
||||||
|
Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
@par Glossary:
|
||||||
|
- Cm or CM - Configuration Manager
|
||||||
|
- Obj or OBJ - Object
|
||||||
|
- Std or STD - Standard
|
||||||
|
|
||||||
|
@par Reference(s):
|
||||||
|
- Arm CoreLink CMN-600 Coherent Mesh Network Technical Reference Manual r3p0
|
||||||
|
- Generic ACPI for Arm Components 1.0 Platform Design Document
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef SSDT_CMN600_GENERATOR_H_
|
||||||
|
#define SSDT_CMN600_GENERATOR_H_
|
||||||
|
|
||||||
|
/** PeriphBase maximum address length is 256MB (0x10000000)
|
||||||
|
for a (X >= 4) || (Y >= 4) dimensions mesh.
|
||||||
|
*/
|
||||||
|
#define PERIPHBASE_MAX_ADDRESS_LENGTH SIZE_256MB
|
||||||
|
|
||||||
|
/** PeriphBase minimum address length is 64MB (0x04000000)
|
||||||
|
for a (X < 4) && (Y < 4) dimensions mesh.
|
||||||
|
*/
|
||||||
|
#define PERIPHBASE_MIN_ADDRESS_LENGTH SIZE_64MB
|
||||||
|
|
||||||
|
/** RootNodeBase address length is 16KB (0x00004000).
|
||||||
|
*/
|
||||||
|
#define ROOTNODEBASE_ADDRESS_LENGTH SIZE_16KB
|
||||||
|
|
||||||
|
/** Maximum number of CMN-600 Debug and Trace Logic Controllers (DTC).
|
||||||
|
*/
|
||||||
|
#define MAX_DTC_COUNT 4
|
||||||
|
|
||||||
|
/** Starting value for the UID to represent the CMN600 devices.
|
||||||
|
*/
|
||||||
|
#define CMN600_DEVICE_START_UID 0
|
||||||
|
|
||||||
|
/** Maximum CMN-600 devices supported by this generator.
|
||||||
|
This generator supports a maximum of 16 CMN-600 devices.
|
||||||
|
Note: This is not a hard limitation and can be extended if needed.
|
||||||
|
Corresponding changes would be needed to support the Name and
|
||||||
|
UID fields describing the serial port.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#define MAX_CMN600_DEVICES_SUPPORTED 16
|
||||||
|
|
||||||
|
#endif // SSDT_CMN600_GENERATOR_H_
|
|
@ -0,0 +1,34 @@
|
||||||
|
## @file
|
||||||
|
# Ssdt CMN-600 Table Generator
|
||||||
|
#
|
||||||
|
# Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x0001001B
|
||||||
|
BASE_NAME = SsdtCmn600LibArm
|
||||||
|
FILE_GUID = CEDB450D-8F0E-4ACC-8FB7-F72EC7D216A4
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
MODULE_TYPE = DXE_DRIVER
|
||||||
|
LIBRARY_CLASS = NULL|DXE_DRIVER
|
||||||
|
CONSTRUCTOR = AcpiSsdtCmn600LibConstructor
|
||||||
|
DESTRUCTOR = AcpiSsdtCmn600LibDestructor
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
SsdtCmn600Generator.c
|
||||||
|
SsdtCmn600Generator.h
|
||||||
|
SsdtCmn600Template.asl
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
EmbeddedPkg/EmbeddedPkg.dec
|
||||||
|
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||||
|
DynamicTablesPkg/DynamicTablesPkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
AmlLib
|
||||||
|
BaseLib
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/** @file
|
||||||
|
SSDT CMN-600 Template
|
||||||
|
|
||||||
|
Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
@par Reference(s):
|
||||||
|
- Arm CoreLink CMN-600 Coherent Mesh Network Technical Reference Manual r3p0
|
||||||
|
- Generic ACPI for Arm Components 1.0 Platform Design Document
|
||||||
|
|
||||||
|
@par Glossary:
|
||||||
|
- {template} - Data fixed up using AML Fixup APIs.
|
||||||
|
- {codegen} - Data generated using AML Codegen APIs.
|
||||||
|
**/
|
||||||
|
|
||||||
|
DefinitionBlock ("SsdtCmn600.aml", "SSDT", 2, "ARMLTD", "CMN-600", 1) {
|
||||||
|
Scope (_SB) {
|
||||||
|
// CMN-600 device object for a X * Y mesh, where (X >= 4) || (Y >= 4).
|
||||||
|
Device (CMN0) { // {template}
|
||||||
|
Name (_HID, "ARMHC600")
|
||||||
|
Name (_UID, 0x0) // {template}
|
||||||
|
|
||||||
|
Name (_CRS, ResourceTemplate () {
|
||||||
|
// Descriptor for 256 MB of the CFG region at offset PERIPHBASE.
|
||||||
|
QWordMemory (
|
||||||
|
ResourceConsumer, // bit 0 of general flags is 0.
|
||||||
|
PosDecode,
|
||||||
|
MinFixed, // Range is fixed.
|
||||||
|
MaxFixed, // Range is Fixed.
|
||||||
|
NonCacheable,
|
||||||
|
ReadWrite,
|
||||||
|
0x00000000, // Granularity
|
||||||
|
0xA0000000, // MinAddress // {template}
|
||||||
|
0xAFFFFFFF, // MaxAddress // {template}
|
||||||
|
0x00000000, // Translation
|
||||||
|
0x10000000, // RangeLength // {template}
|
||||||
|
, // ResourceSourceIndex
|
||||||
|
, // ResourceSource
|
||||||
|
CFGR // DescriptorName
|
||||||
|
) // QWordMemory
|
||||||
|
|
||||||
|
// Descriptor for the root node. This is a 16 KB region at offset
|
||||||
|
// ROOTNODEBASE. In this example, ROOTNODEBASE starts at the 16 KB
|
||||||
|
// aligned offset of PERIPHBASE.
|
||||||
|
QWordMemory (
|
||||||
|
ResourceConsumer, // bit 0 of general flags is 0.
|
||||||
|
PosDecode,
|
||||||
|
MinFixed, // Range is fixed.
|
||||||
|
MaxFixed, // Range is Fixed.
|
||||||
|
NonCacheable,
|
||||||
|
ReadWrite,
|
||||||
|
0x00000000, // Granularity
|
||||||
|
0xA0000000, // MinAddress // {template}
|
||||||
|
0xAFFFFFFF, // MaxAddress // {template}
|
||||||
|
0x00000000, // Translation
|
||||||
|
0x10000000, // RangeLength // {template}
|
||||||
|
, // ResourceSourceIndex
|
||||||
|
, // ResourceSource
|
||||||
|
ROOT // DescriptorName
|
||||||
|
) // QWordMemory
|
||||||
|
|
||||||
|
// The Interrupt information is generated using AmlCodegen.
|
||||||
|
// Interrupt on PMU0 overflow, attached to DTC [0], with GSIV = <gsiv0>.
|
||||||
|
//
|
||||||
|
// Interrupt ( // {codegen}
|
||||||
|
// ResourceConsumer, // ResourceUsage
|
||||||
|
// Level, // EdgeLevel
|
||||||
|
// ActiveHigh, // ActiveLevel
|
||||||
|
// Exclusive, // Shared
|
||||||
|
// , // ResourceSourceIndex
|
||||||
|
// , // ResourceSource
|
||||||
|
// // DescriptorName
|
||||||
|
// ) {
|
||||||
|
// 0xA5 // <gsiv0 >
|
||||||
|
// } // Interrupt
|
||||||
|
|
||||||
|
}) // Name
|
||||||
|
} // Device
|
||||||
|
} // _SB
|
||||||
|
} // DefinitionBlock
|
Loading…
Reference in New Issue