/** @file
 *
 *  Processor Properties Topology Table (PPTT)
 *
 *  Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
 *
 *  SPDX-License-Identifier: BSD-2-Clause-Patent
 *
 **/

#include <IndustryStandard/Acpi.h>

#include "AcpiTables.h"

#define NUM_CORES                           4
#define NUM_CLUSTERS                        1

#if (RPI_MODEL == 3)
#define CORTEX_L1D_SIZE                     SIZE_16KB
#define CORTEX_L1D_SETS                     64
#define CORTEX_L1D_ASSC                     4
#define CORTEX_L1I_SIZE                     SIZE_16KB
#define CORTEX_L1I_SETS                     128
#define CORTEX_L1I_ASSC                     2
#define CORTEX_L2_SIZE                      SIZE_512KB
#define CORTEX_L2_SETS                      512
#define CORTEX_L2_ASSC                      16
#elif (RPI_MODEL == 4)
#define CORTEX_L1D_SIZE                     SIZE_32KB
#define CORTEX_L1D_SETS                     256
#define CORTEX_L1D_ASSC                     2
#define CORTEX_L1I_SIZE                     (3*SIZE_16KB)
#define CORTEX_L1I_SETS                     256
#define CORTEX_L1I_ASSC                     3
#define CORTEX_L2_SIZE                      SIZE_1MB
#define CORTEX_L2_SETS                      1024
#define CORTEX_L2_ASSC                      16
#endif

#define FIELD_OFFSET(type, name)            __builtin_offsetof(type, name)

#pragma pack(1)
typedef struct {
  EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR                     Core;
  UINT32                                                    Offset[2];
  EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE                         DCache;
  EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE                         ICache;
} ACPI_6_3_PPTT_CORE;

typedef struct {
  EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR                     Cluster;
  UINT32                                                    Offset[1];
  EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE                         L2Cache;
  ACPI_6_3_PPTT_CORE                                        Cores[NUM_CORES];
} ACPI_6_3_PPTT_CLUSTER;

typedef struct {
  EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER   Pptt;
  ACPI_6_3_PPTT_CLUSTER                                     Packages[NUM_CLUSTERS];
} ACPI_6_3_PPTT_STRUCTURE;
#pragma pack()

#define PPTT_CORE(pid, cid, id) {                                              \
  {                                                                            \
    EFI_ACPI_6_3_PPTT_TYPE_PROCESSOR,                                          \
    FIELD_OFFSET (ACPI_6_3_PPTT_CORE, DCache),                                 \
    {},                                                                        \
    {                                                                          \
      EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL,     /* Not PhysicalPackage */    \
      EFI_ACPI_6_3_PPTT_PROCESSOR_ID_VALID,       /* AcpiProcessorIdValid */   \
      EFI_ACPI_6_3_PPTT_PROCESSOR_IS_NOT_THREAD,  /* Is not a Thread */        \
      EFI_ACPI_6_3_PPTT_NODE_IS_LEAF,             /* Leaf */                   \
      EFI_ACPI_6_3_PPTT_IMPLEMENTATION_IDENTICAL, /* identical ignored */      \
    },                                                                         \
    FIELD_OFFSET (ACPI_6_3_PPTT_STRUCTURE,                                     \
                  Packages[pid]),               /* Parent */                   \
    256 * (cid) + (id),                         /* AcpiProcessorId */          \
    2,                                          /* NumberOfPrivateResources */ \
  }, {                                                                         \
    FIELD_OFFSET (ACPI_6_3_PPTT_STRUCTURE,                                     \
                  Packages[pid].Cores[id].DCache),                             \
    FIELD_OFFSET (ACPI_6_3_PPTT_STRUCTURE,                                     \
                  Packages[pid].Cores[id].ICache),                             \
  }, {                                                                         \
    EFI_ACPI_6_3_PPTT_TYPE_CACHE,                                              \
    sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE),                                \
    {},                                                                        \
    {                                                                          \
      1,          /* SizePropertyValid */                                      \
      1,          /* NumberOfSetsValid */                                      \
      1,          /* AssociativityValid */                                     \
      1,          /* AllocationTypeValid */                                    \
      1,          /* CacheTypeValid */                                         \
      1,          /* WritePolicyValid */                                       \
      1,          /* LineSizeValid */                                          \
    },                                                                         \
    0,            /* NextLevelOfCache */                                       \
    CORTEX_L1D_SIZE,  /* Size */                                               \
    CORTEX_L1D_SETS,  /* NumberOfSets */                                       \
    CORTEX_L1D_ASSC,  /* Associativity */                                      \
    {                                                                          \
      EFI_ACPI_6_3_CACHE_ATTRIBUTES_ALLOCATION_READ_WRITE,                     \
      EFI_ACPI_6_3_CACHE_ATTRIBUTES_CACHE_TYPE_DATA,                           \
      EFI_ACPI_6_3_CACHE_ATTRIBUTES_WRITE_POLICY_WRITE_BACK,                   \
    },                                                                         \
    64            /* LineSize */                                               \
  }, {                                                                         \
    EFI_ACPI_6_3_PPTT_TYPE_CACHE,                                              \
    sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE),                                \
    {},                                                                        \
    {                                                                          \
      1,          /* SizePropertyValid */                                      \
      1,          /* NumberOfSetsValid */                                      \
      1,          /* AssociativityValid */                                     \
      1,          /* AllocationTypeValid */                                    \
      1,          /* CacheTypeValid */                                         \
      0,          /* WritePolicyValid */                                       \
      1,          /* LineSizeValid */                                          \
    },                                                                         \
    0,            /* NextLevelOfCache */                                       \
    CORTEX_L1I_SIZE,  /* Size */                                               \
    CORTEX_L1I_SETS,  /* NumberOfSets */                                       \
    CORTEX_L1I_ASSC,  /* Associativity */                                      \
    {                                                                          \
      EFI_ACPI_6_3_CACHE_ATTRIBUTES_ALLOCATION_READ,    /* AllocationType */   \
      EFI_ACPI_6_3_CACHE_ATTRIBUTES_CACHE_TYPE_INSTRUCTION,                    \
      0,                                                /* WritePolicy */      \
    },                                                                         \
    64            /* LineSize */                                               \
  }                                                                            \
}

#define PPTT_CLUSTER(pid, cid) {                                                 \
  {                                                                              \
    EFI_ACPI_6_3_PPTT_TYPE_PROCESSOR,                                            \
    FIELD_OFFSET (ACPI_6_3_PPTT_CLUSTER, L2Cache),                               \
    {},                                                                          \
    {                                                                            \
      EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL,         /* PhysicalPackage */          \
      EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID,     /* AcpiProcessorIdValid */     \
      EFI_ACPI_6_3_PPTT_PROCESSOR_IS_NOT_THREAD,  /* Is not a Thread */          \
      EFI_ACPI_6_3_PPTT_NODE_IS_NOT_LEAF,         /* not Leaf */                 \
      EFI_ACPI_6_3_PPTT_IMPLEMENTATION_IDENTICAL, /* identical cores */          \
    },                                                                           \
    0,                                        /* Parent */                       \
    0,                                        /* AcpiProcessorId */              \
    1,                                        /* NumberOfPrivateResources */     \
  }, {                                                                           \
    FIELD_OFFSET (ACPI_6_3_PPTT_STRUCTURE, Packages[pid].L2Cache),  \
  }, {                                                                           \
    EFI_ACPI_6_3_PPTT_TYPE_CACHE,                                                \
    sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE),                                  \
    {},                                                                          \
    {                                                                            \
      1,          /* SizePropertyValid */                                        \
      1,          /* NumberOfSetsValid */                                        \
      1,          /* AssociativityValid */                                       \
      1,          /* AllocationTypeValid */                                      \
      1,          /* CacheTypeValid */                                           \
      1,          /* WritePolicyValid */                                         \
      1,          /* LineSizeValid */                                            \
    },                                                                           \
    0,            /* NextLevelOfCache */                                         \
    CORTEX_L2_SIZE,  /* Size */                                                  \
    CORTEX_L2_SETS,  /* NumberOfSets */                                          \
    CORTEX_L2_ASSC,  /* Associativity */                                         \
    {                                                                            \
      EFI_ACPI_6_3_CACHE_ATTRIBUTES_ALLOCATION_READ_WRITE,                       \
      EFI_ACPI_6_3_CACHE_ATTRIBUTES_CACHE_TYPE_UNIFIED,                          \
      EFI_ACPI_6_3_CACHE_ATTRIBUTES_WRITE_POLICY_WRITE_BACK,                     \
    },                                                                           \
    64            /* LineSize */                                                 \
  }, {                                                                           \
    PPTT_CORE(pid, cid, 0),                                                      \
    PPTT_CORE(pid, cid, 1),                                                      \
    PPTT_CORE(pid, cid, 2),                                                      \
    PPTT_CORE(pid, cid, 3),                                                      \
  }                                                                              \
}

ACPI_6_3_PPTT_STRUCTURE Pptt = {
  {
    ACPI_HEADER(EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE,
                ACPI_6_3_PPTT_STRUCTURE,
                EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_REVISION),
  }, {
    PPTT_CLUSTER (0, 0),
  }
};

VOID * CONST ReferenceAcpiTable = &Pptt;
