/**
 * @file   fcMem.h
 * @brief  Contains common definitions for L1 memory setup
 *
 * <Copyright goes here>
 */

#ifndef __FCMEM_H__
#define __FCMEM_H__


#define L1_BIT_0                    (1U <<  0)
#define   L1_BIT_TYPE_PT              L1_BIT_0 // (pagetable) type page table
#define   L1_BIT_SECTION_PXN          L1_BIT_0 // (section, superSection)
#define L1_BIT_TYPE_SECTION         (1U <<  1) // (section, superSection)
#define L1_BIT_2                    (1U <<  2)
#define   L1_BIT_PT_PXN               L1_BIT_2 // (pagetable)
#define   L1_BIT_SECTION_B            L1_BIT_2 // (section, superSection) bufferable
#define L1_BIT_3                    (1U <<  3) //
#define   L1_BIT_PT_NS                L1_BIT_3 // (pagetable)
#define   L1_BIT_SECTION_C            L1_BIT_3 // (section, superSection) cachable
#define L1_BIT_SECTION_XN           (1U <<  4) // (section, superSection)
// Bit 5-8
//   PT, SECTION: Domain
//   SuperSection: see L1_ADDR_EXT2_MASK_SUPER_SECTION
#define L1_BIT_IMP                  (1U <<  9) // implementation defined
#define   L1_BIT_P                    L1_FLAG_IMP // ECC enabled (no ECC on ARM1176JZ-S)
#define L1_BIT_SECTION_AP0          (1U << 10) // (section, superSection)
#define L1_BIT_SECTION_AP1          (1U << 11) // (section, superSection)
#define L1_BIT_SECTION_TEX0         (1U << 12) // (section, superSection)
#define L1_BIT_SECTION_TEX1         (1U << 13) // (section, superSection)
#define L1_BIT_SECTION_TEX2         (1U << 14) // (section, superSection)
#define L1_BIT_SECTION_AP2          (1U << 15) // (section, superSection)
#define L1_BIT_SECTION_S            (1U << 16) // (section, superSection)
#define L1_BIT_SECTION_NG           (1U << 17) // (section, superSection)
#define L1_BIT_TYPE_SUPER_SECTION   (1U << 18) // (section, superSection) type super section
#define L1_BIT_SECTION_NS           (1U << 19) // (section, superSection)

#define L1_DOMAIN(_dom_)            (((uint32_t)(_dom_)&0xF) << 5) // Bit 5 - 8

#define L1_TYPE_FAULT               0
#define L1_TYPE_PT                  L1_BIT_TYPE_PT // L2 page table
#define L1_TYPE_SECTION             L1_BIT_TYPE_SECTION // 1MB
#define L1_TYPE_SUPER_SECTION       ( L1_BIT_TYPE_SECTION | L1_BIT_TYPE_SUPER_SECTION ) // 16MB

#define IS_L1_TYPE_FAULT(_pte_)             ( L1_TYPE_FAULT == ((_pte_) & (L1_BIT_TYPE_PT | L1_BIT_TYPE_SECTION)) )
#define IS_L1_TYPE_PT(_pte_)                ( L1_TYPE_PT == ((_pte_) & (L1_BIT_TYPE_PT | L1_BIT_TYPE_SECTION)) )
#define IS_L1_TYPE_SECTION(_pte_)           ( L1_TYPE_SECTION == ((_pte_) & (L1_BIT_TYPE_SECTION | L1_BIT_TYPE_SUPER_SECTION)) )
#define IS_L1_TYPE_SUPER_SECTION(_pte_)     ((L1_TYPE_SECTION | L1_TYPE_TYPE_SUPER_SECTION) == ((_pte_) & (L1_BIT_TYPE_SECTION | L1_BIT_TYPE_SUPER_SECTION)) )

#define L1_ADDR_MASK_PT                     0xFFFFFC00 // bits 10-31 hold PTBA[10:31]
#define L1_ADDR_MASK_SECTION                0xFFF00000 // bits 20-31 hold PBA[20:31]
#define L1_ADDR_MASK_SUPER_SECTION          0xFF000000 // bits 24-31 hold PBA[24:31]
#define L1_ADDR_EXT1_MASK_SUPER_SECTION     0x00F00000 // bits 20-23 hold PBA[32:35]
#define L1_ADDR_EXT2_MASK_SUPER_SECTION     0x000001E0 // bits 5-8   hold PBA[36:39]

#define L1_SECTION_TEXCB_NORMAL_IO_WB_WA   (L1_BIT_SECTION_TEX0 | L1_BIT_SECTION_C | L1_BIT_SECTION_B)
#define L2_SMALL_TEXCB_NORMAL_IO_WB_WA     (L2_BIT_SMALL_TEX0 | L2_BIT_C | L2_BIT_B)
#define L2_LARGE_TEXCB_NORMAL_IO_WB_WA     (L2_BIT_LARGE_TEX0 | L2_BIT_C | L2_BIT_B)

#define L1_SECTION_AP_PRW           L1_BIT_SECTION_AP0

#define L1_SECTION_AP_PRW_UR        L1_BIT_SECTION_AP1
#define L1_SECTION_AP_PRW_URW       (L1_BIT_SECTION_AP1 | L1_BIT_SECTION_AP0)

/*
 * For 64 Bit Architecture
*/
#define L1_LONG_TYPE_PT                  (3ULL) // pagetable entry
#define L1_LONG_TYPE_BLOCK               (1ULL) // block entry
#define L1_LONG_BIT_NSTABLE              (1ULL << 63) // (pagetable)

#define L1_LONG_BIT_BLOCK_NS             (1ULL <<  5)
#define L1_LONG_BIT_BLOCK_AP1            (1ULL <<  6)
#define L1_LONG_BIT_BLOCK_AP2            (1ULL <<  7)
#define L1_LONG_BIT_BLOCK_SH0            (1ULL <<  8)
#define L1_LONG_BIT_BLOCK_SH1            (1ULL <<  9)
#define L1_LONG_BIT_BLOCK_AF             (1ULL << 10)
#define L1_LONG_BIT_BLOCK_NG             (1ULL << 11)
#define L1_LONG_BIT_BLOCK_PXN            (1ULL << 53)
#define L1_LONG_BIT_BLOCK_XN             (1ULL << 54)
#define L1_LONG_ADDR_MASK_PT             (((1ULL << 40) - 1) & ~((1ULL << 12) - 1))

#define L1_LONG_BLOCK_AP_PRW_URW         L1_LONG_BIT_BLOCK_AP1
#define L1_LONG_BLOCK_AP_PRW_UR          L1_LONG_BIT_BLOCK_AP1  // Same as previous: we cannot forbid user write only with AP[2:1] access permissions model
#define L1_LONG_BLOCK_AP_PRW             0
#define L1_LONG_BLOCK_AP_PR              L1_LONG_BIT_BLOCK_AP2

#define L1_LONG_BLOCK_SHAREABLE_OS       L1_LONG_BIT_BLOCK_SH1
#define L1_LONG_BLOCK_SHAREABLE_IS       ( L1_LONG_BIT_BLOCK_SH0 | L1_LONG_BIT_BLOCK_SH1)

#define L1_LONG_ATTRINDX_DEVICE          (1ULL << 2)
#define L1_LONG_ATTRINDX_NORMAL_UNCACHED (2ULL << 2)
#define L1_LONG_ATTRINDX_NORMAL_CACHED   (3ULL << 2)


#endif // __FCMEM_H__
