/** @file
*  Multiple APIC Description Table (MADT)
*
*  Copyright (c) 2012 - 2016, ARM Limited. All rights reserved.
*  Copyright (c) 2018, Linaro Limited. All rights reserved.
*
*  SPDX-License-Identifier: BSD-2-Clause-Patent
*
**/

#include <Library/AcpiLib.h>
#include <Library/ArmLib.h>
#include <Library/PcdLib.h>
#include <IndustryStandard/Acpi.h>

#include "AcpiTables.h"

#define CORES           (FixedPcdGet32 (PcdClusterCount) * \
                         FixedPcdGet32 (PcdCoreCount))
//
// Multiple APIC Description Table
//
#pragma pack (1)

typedef struct {
  EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER   Header;
  EFI_ACPI_6_0_GIC_STRUCTURE                            GicInterfaces[CORES];
  EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE                GicDistributor;
  EFI_ACPI_6_0_GICR_STRUCTURE                           GicRedistributor;
  EFI_ACPI_6_0_GIC_ITS_STRUCTURE                        GicIts;
} EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE;

#pragma pack ()

EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE Madt = {
  {
    __ACPI_HEADER (
      EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
      EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE,
      EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
    ),
    //
    // MADT specific fields
    //
    0, // LocalApicAddress
    0, // Flags
  },
  {
    // Format: EFI_ACPI_6_0_GICC_STRUCTURE_INIT(GicId, AcpiCpuUid, Mpidr, Flags,
    //                                          PmuIrq, GicBase, GicVBase,
    //                                          GicHBase, GsivId, GicRBase)
    // Note: The GIC Structure of the primary CPU must be the first entry
    // (see note in 5.2.12.14 GICC Structure of ACPI v6.0).
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-0
        0, 0, GET_MPID(0, 0), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-1
        0, 1, GET_MPID(0, 1), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),

    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-2
        0, 2, GET_MPID(1, 0), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-3
        0, 3, GET_MPID(1, 1), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),

    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-4
        0, 4, GET_MPID(2, 0), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-5
        0, 5, GET_MPID(2, 1), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),

    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-6
        0, 6, GET_MPID(3, 0), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-7
        0, 7, GET_MPID(3, 1), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),

    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-8
        0, 8, GET_MPID(4, 0), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-9
        0, 9, GET_MPID(4, 1), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),

    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-10
        0, 10, GET_MPID(5, 0), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-11
        0, 11, GET_MPID(5, 1), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),

    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-12
        0, 12, GET_MPID(6, 0), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-13
        0, 13, GET_MPID(6, 1), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),

    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-14
        0, 14, GET_MPID(7, 0), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-15
        0, 15, GET_MPID(7, 1), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),

    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-16
        0, 16, GET_MPID(8, 0), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-17
        0, 17, GET_MPID(8, 1), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),

    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-18
        0, 18, GET_MPID(9, 0), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-19
        0, 19, GET_MPID(9, 1), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),

    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-20
        0, 20, GET_MPID(10, 0), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-21
        0, 21, GET_MPID(10, 1), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),

    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-22
        0, 22, GET_MPID(11, 0), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT( // A53-23
        0, 23, GET_MPID(11, 1), EFI_ACPI_6_0_GIC_ENABLED, 23,
        FixedPcdGet32 (PcdGicDistributorBase),
        0x2c020000, 0x2c010000, 25, 0 /* GicRBase */, 0 /* Efficiency */),
  },
  // GIC Distributor Entry
  EFI_ACPI_6_0_GIC_DISTRIBUTOR_INIT (0, FixedPcdGet32 (PcdGicDistributorBase),
                                     0, 3),
  // GIC Redistributor
  EFI_ACPI_6_0_GIC_REDISTRIBUTOR_INIT (FixedPcdGet32 (PcdGicRedistributorsBase),
                                       0x300000),
  // GIC ITS
  EFI_ACPI_6_0_GIC_ITS_FRAME_INIT(0, 0x30020000)
};

//
// Reference the table being generated to prevent the optimizer
// from removing the data structure from the executable
//
VOID* CONST ReferenceAcpiTable = &Madt;
