/** @file
  ACPI IO Remapping Table (IORT) as specified in ARM spec DEN0049D

  http://infocenter.arm.com/help/topic/com.arm.doc.den0049d/DEN0049D_IO_Remapping_Table.pdf

  Copyright (c) 2017, Linaro Limited. All rights reserved.<BR>
  Copyright (c) 2018, ARM Limited. All rights reserved.<BR>

  SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#ifndef __IO_REMAPPING_TABLE_H__
#define __IO_REMAPPING_TABLE_H__

#include <IndustryStandard/Acpi.h>

#define EFI_ACPI_IO_REMAPPING_TABLE_REVISION  0x0

#define EFI_ACPI_IORT_TYPE_ITS_GROUP     0x0
#define EFI_ACPI_IORT_TYPE_NAMED_COMP    0x1
#define EFI_ACPI_IORT_TYPE_ROOT_COMPLEX  0x2
#define EFI_ACPI_IORT_TYPE_SMMUv1v2      0x3
#define EFI_ACPI_IORT_TYPE_SMMUv3        0x4
#define EFI_ACPI_IORT_TYPE_PMCG          0x5

#define EFI_ACPI_IORT_MEM_ACCESS_PROP_CCA  BIT0

#define EFI_ACPI_IORT_MEM_ACCESS_PROP_AH_TR   BIT0
#define EFI_ACPI_IORT_MEM_ACCESS_PROP_AH_WA   BIT1
#define EFI_ACPI_IORT_MEM_ACCESS_PROP_AH_RA   BIT2
#define EFI_ACPI_IORT_MEM_ACCESS_PROP_AH_AHO  BIT3

#define EFI_ACPI_IORT_MEM_ACCESS_FLAGS_CPM   BIT0
#define EFI_ACPI_IORT_MEM_ACCESS_FLAGS_DACS  BIT1

#define EFI_ACPI_IORT_SMMUv1v2_MODEL_v1             0x0
#define EFI_ACPI_IORT_SMMUv1v2_MODEL_v2             0x1
#define EFI_ACPI_IORT_SMMUv1v2_MODEL_MMU400         0x2
#define EFI_ACPI_IORT_SMMUv1v2_MODEL_MMU500         0x3
#define EFI_ACPI_IORT_SMMUv1v2_MODEL_MMU401         0x4
#define EFI_ACPI_IORT_SMMUv1v2_MODEL_CAVIUM_THX_v2  0x5

#define EFI_ACPI_IORT_SMMUv1v2_FLAG_DVM       BIT0
#define EFI_ACPI_IORT_SMMUv1v2_FLAG_COH_WALK  BIT1

#define EFI_ACPI_IORT_SMMUv1v2_INT_FLAG_LEVEL  0x0
#define EFI_ACPI_IORT_SMMUv1v2_INT_FLAG_EDGE   0x1

#define EFI_ACPI_IORT_SMMUv3_FLAG_COHAC_OVERRIDE    BIT0
#define EFI_ACPI_IORT_SMMUv3_FLAG_HTTU_OVERRIDE     BIT1
#define EFI_ACPI_IORT_SMMUv3_FLAG_PROXIMITY_DOMAIN  BIT3

#define EFI_ACPI_IORT_SMMUv3_MODEL_GENERIC           0x0
#define EFI_ACPI_IORT_SMMUv3_MODEL_HISILICON_HI161X  0x1
#define EFI_ACPI_IORT_SMMUv3_MODEL_CAVIUM_CN99XX     0x2

#define EFI_ACPI_IORT_ROOT_COMPLEX_ATS_UNSUPPORTED  0x0
#define EFI_ACPI_IORT_ROOT_COMPLEX_ATS_SUPPORTED    0x1

#define EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE  BIT0

#pragma pack(1)

///
/// Table header
///
typedef struct {
  EFI_ACPI_DESCRIPTION_HEADER    Header;
  UINT32                         NumNodes;
  UINT32                         NodeOffset;
  UINT32                         Reserved;
} EFI_ACPI_6_0_IO_REMAPPING_TABLE;

///
/// Definition for ID mapping table shared by all node types
///
typedef struct {
  UINT32    InputBase;
  UINT32    NumIds;
  UINT32    OutputBase;
  UINT32    OutputReference;
  UINT32    Flags;
} EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE;

///
/// Node header definition shared by all node types
///
typedef struct {
  UINT8     Type;
  UINT16    Length;
  UINT8     Revision;
  UINT32    Reserved;
  UINT32    NumIdMappings;
  UINT32    IdReference;
} EFI_ACPI_6_0_IO_REMAPPING_NODE;

///
/// Node type 0: ITS node
///
typedef struct {
  EFI_ACPI_6_0_IO_REMAPPING_NODE    Node;

  UINT32                            NumItsIdentifiers;
  // UINT32                                  ItsIdentifiers[NumItsIdentifiers];
} EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE;

///
/// Node type 1: root complex node
///
typedef struct {
  EFI_ACPI_6_0_IO_REMAPPING_NODE    Node;

  UINT32                            CacheCoherent;
  UINT8                             AllocationHints;
  UINT16                            Reserved;
  UINT8                             MemoryAccessFlags;

  UINT32                            AtsAttribute;
  UINT32                            PciSegmentNumber;
  UINT8                             MemoryAddressSize;
  UINT8                             Reserved1[3];
} EFI_ACPI_6_0_IO_REMAPPING_RC_NODE;

///
/// Node type 2: named component node
///
typedef struct {
  EFI_ACPI_6_0_IO_REMAPPING_NODE    Node;

  UINT32                            Flags;
  UINT32                            CacheCoherent;
  UINT8                             AllocationHints;
  UINT16                            Reserved;
  UINT8                             MemoryAccessFlags;
  UINT8                             AddressSizeLimit;
  // UINT8                                   ObjectName[];
} EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE;

///
/// Node type 3: SMMUv1 or SMMUv2 node
///
typedef struct {
  UINT32    Interrupt;
  UINT32    InterruptFlags;
} EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT;

typedef struct {
  EFI_ACPI_6_0_IO_REMAPPING_NODE    Node;

  UINT64                            Base;
  UINT64                            Span;
  UINT32                            Model;
  UINT32                            Flags;
  UINT32                            GlobalInterruptArrayRef;
  UINT32                            NumContextInterrupts;
  UINT32                            ContextInterruptArrayRef;
  UINT32                            NumPmuInterrupts;
  UINT32                            PmuInterruptArrayRef;

  UINT32                            SMMU_NSgIrpt;
  UINT32                            SMMU_NSgIrptFlags;
  UINT32                            SMMU_NSgCfgIrpt;
  UINT32                            SMMU_NSgCfgIrptFlags;

  // EFI_ACPI_6_0_IO_REMAPPING_SMMU_CTX_INT  ContextInterrupt[NumContextInterrupts];
  // EFI_ACPI_6_0_IO_REMAPPING_SMMU_CTX_INT  PmuInterrupt[NumPmuInterrupts];
} EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE;

///
/// Node type 4: SMMUv3 node
///
typedef struct {
  EFI_ACPI_6_0_IO_REMAPPING_NODE    Node;

  UINT64                            Base;
  UINT32                            Flags;
  UINT32                            Reserved;
  UINT64                            VatosAddress;
  UINT32                            Model;
  UINT32                            Event;
  UINT32                            Pri;
  UINT32                            Gerr;
  UINT32                            Sync;
  UINT32                            ProximityDomain;
  UINT32                            DeviceIdMappingIndex;
} EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE;

///
/// Node type 5: PMCG node
///
typedef struct {
  EFI_ACPI_6_0_IO_REMAPPING_NODE    Node;

  UINT64                            Base;
  UINT32                            OverflowInterruptGsiv;
  UINT32                            NodeReference;
  UINT64                            Page1Base;
  // EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE      OverflowInterruptMsiMapping[1];
} EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE;

#pragma pack()

#endif
