/** @file

  Multiple APIC Description Table (MADT)

  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
  Copyright (C) 2018, Marvell International Ltd. and its affiliates.<BR>

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

**/

#include <Library/AcpiLib.h>

#include "AcpiHeader.h"

#define GICC_BASE                 FixedPcdGet64 (PcdGicInterruptInterfaceBase)
#define GICD_BASE                 FixedPcdGet64 (PcdGicDistributorBase)
#define GICH_BASE                 0xF0240000
#define GICV_BASE                 0xF0260000
#define VGIC_MAINT_INT            25 // SPI #9

#define GIC_MSI_FRAME0            0xF0280000
#define GIC_MSI_FRAME1            0xF0290000
#define GIC_MSI_FRAME2            0xF02A0000
#define GIC_MSI_FRAME3            0xF02B0000

#define PMU_INTERRUPT_CPU0        130
#define PMU_INTERRUPT_CPU1        131
#define PMU_INTERRUPT_CPU2        132
#define PMU_INTERRUPT_CPU3        133

#define PMU_INTERRUPT_FLAG        EFI_ACPI_6_0_GIC_ENABLED | EFI_ACPI_6_0_PERFORMANCE_INTERRUPT_MODEL

#pragma pack(push, 1)
typedef struct {
  EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER Header;
  EFI_ACPI_6_0_GIC_STRUCTURE                          GicC[4];
  EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE              GicD;
  EFI_ACPI_6_0_GIC_MSI_FRAME_STRUCTURE                GicM[4];
} ACPI_6_0_MADT_STRUCTURE;
#pragma pack(pop)


ACPI_6_0_MADT_STRUCTURE Madt = {
  {
    __ACPI_HEADER (EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
                   ACPI_6_0_MADT_STRUCTURE,
                   EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION),
    0,      // UINT32  LocalApicAddress
    0       // UINT32  Flags
  },
  {
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT(0,                         // GicId
                                     0x000,                     // AcpiCpuUid
                                     0x000,                     // Mpidr
                                     PMU_INTERRUPT_FLAG,        // Flags
                                     PMU_INTERRUPT_CPU0,        // PmuIrq
                                     GICC_BASE,                 // GicBase
                                     GICV_BASE,                 // GicVBase
                                     GICH_BASE,                 // GicHBase
                                     VGIC_MAINT_INT,            // GsivId
                                     0,                         // GicRBase
                                     0                          // Efficiency
                                     ),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT(1,                         // GicId
                                     0x001,                     // AcpiCpuUid
                                     0x001,                     // Mpidr
                                     PMU_INTERRUPT_FLAG,        // Flags
                                     PMU_INTERRUPT_CPU1,        // PmuIrq
                                     GICC_BASE,                 // GicBase
                                     GICV_BASE,                 // GicVBase
                                     GICH_BASE,                 // GicHBase
                                     VGIC_MAINT_INT,            // GsivId
                                     0,                         // GicRBase
                                     0                          // Efficiency
                                     ),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT(2,                         // GicId
                                     0x100,                     // AcpiCpuUid
                                     0x100,                     // Mpidr
                                     PMU_INTERRUPT_FLAG,        // Flags
                                     PMU_INTERRUPT_CPU2,        // PmuIrq
                                     GICC_BASE,                 // GicBase
                                     GICV_BASE,                 // GicVBase
                                     GICH_BASE,                 // GicHBase
                                     VGIC_MAINT_INT,            // GsivId
                                     0,                         // GicRBase
                                     0                          // Efficiency
                                     ),
    EFI_ACPI_6_0_GICC_STRUCTURE_INIT(3,                         // GicId
                                     0x101,                     // AcpiCpuUid
                                     0x101,                     // Mpidr
                                     PMU_INTERRUPT_FLAG,        // Flags
                                     PMU_INTERRUPT_CPU3,        // PmuIrq
                                     GICC_BASE,                 // GicBase
                                     GICV_BASE,                 // GicVBase
                                     GICH_BASE,                 // GicHBase
                                     VGIC_MAINT_INT,            // GsivId
                                     0,                         // GicRBase
                                     0                          // Efficiency
                                     ),
  },
  EFI_ACPI_6_0_GIC_DISTRIBUTOR_INIT(0x0,                        // GicDistHwId
                                    GICD_BASE,                  // GicDistBase
                                    0x0,                        // GicDistVector
                                    EFI_ACPI_6_0_GIC_V2         // GicVersion
                                    ),
  {
    EFI_ACPI_6_0_GIC_MSI_FRAME_INIT(0x0,                        // GicMsiFrameId
                                    GIC_MSI_FRAME0,             // BaseAddress
                                    0,                          // Flags
                                    0,                          // SPICount
                                    0                           // SPIBase
                                    ),
    EFI_ACPI_6_0_GIC_MSI_FRAME_INIT(0x1,                        // GicMsiFrameId
                                    GIC_MSI_FRAME1,             // BaseAddress
                                    0,                          // Flags
                                    0,                          // SPICount
                                    0                           // SPIBase
                                    ),
    EFI_ACPI_6_0_GIC_MSI_FRAME_INIT(0x2,                        // GicMsiFrameId
                                    GIC_MSI_FRAME2,             // BaseAddress
                                    0,                          // Flags
                                    0,                          // SPICount
                                    0                           // SPIBase
                                    ),
    EFI_ACPI_6_0_GIC_MSI_FRAME_INIT(0x3,                        // GicMsiFrameId
                                    GIC_MSI_FRAME3,             // BaseAddress
                                    0,                          // Flags
                                    0,                          // SPICount
                                    0                           // SPIBase
                                    ),
  }
};

VOID CONST * CONST ReferenceAcpiTable = &Madt;
