Merge branch 'master' of git://git.denx.de/u-boot
[oweals/u-boot.git] / arch / arm / include / asm / system.h
index 868ea54b4fef2c2d9d9819a986ca58f5e9c7800b..01efc43657f3257b6b3c7c4a4dced0dbc34b1fcb 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef __ASM_ARM_SYSTEM_H
 #define __ASM_ARM_SYSTEM_H
 
+#include <common.h>
+#include <linux/compiler.h>
+#include <asm/barriers.h>
+
 #ifdef CONFIG_ARM64
 
 /*
 #define CR_WXN         (1 << 19)       /* Write Permision Imply XN     */
 #define CR_EE          (1 << 25)       /* Exception (Big) Endian       */
 
-#define PGTABLE_SIZE   (0x10000)
-/* 2MB granularity */
-#define MMU_SECTION_SHIFT      21
+#define ES_TO_AARCH64          1
+#define ES_TO_AARCH32          0
+
+/*
+ * SCR_EL3 bits definitions
+ */
+#define SCR_EL3_RW_AARCH64     (1 << 10) /* Next lower level is AArch64     */
+#define SCR_EL3_RW_AARCH32     (0 << 10) /* Lower lowers level are AArch32  */
+#define SCR_EL3_HCE_EN         (1 << 8)  /* Hypervisor Call enable          */
+#define SCR_EL3_SMD_DIS                (1 << 7)  /* Secure Monitor Call disable     */
+#define SCR_EL3_RES1           (3 << 4)  /* Reserved, RES1                  */
+#define SCR_EL3_NS_EN          (1 << 0)  /* EL0 and EL1 in Non-scure state  */
+
+/*
+ * SPSR_EL3/SPSR_EL2 bits definitions
+ */
+#define SPSR_EL_END_LE         (0 << 9)  /* Exception Little-endian          */
+#define SPSR_EL_DEBUG_MASK     (1 << 9)  /* Debug exception masked           */
+#define SPSR_EL_ASYN_MASK      (1 << 8)  /* Asynchronous data abort masked   */
+#define SPSR_EL_SERR_MASK      (1 << 8)  /* System Error exception masked    */
+#define SPSR_EL_IRQ_MASK       (1 << 7)  /* IRQ exception masked             */
+#define SPSR_EL_FIQ_MASK       (1 << 6)  /* FIQ exception masked             */
+#define SPSR_EL_T_A32          (0 << 5)  /* AArch32 instruction set A32      */
+#define SPSR_EL_M_AARCH64      (0 << 4)  /* Exception taken from AArch64     */
+#define SPSR_EL_M_AARCH32      (1 << 4)  /* Exception taken from AArch32     */
+#define SPSR_EL_M_SVC          (0x3)     /* Exception taken from SVC mode    */
+#define SPSR_EL_M_HYP          (0xa)     /* Exception taken from HYP mode    */
+#define SPSR_EL_M_EL1H         (5)       /* Exception taken from EL1h mode   */
+#define SPSR_EL_M_EL2H         (9)       /* Exception taken from EL2h mode   */
+
+/*
+ * CPTR_EL2 bits definitions
+ */
+#define CPTR_EL2_RES1          (3 << 12 | 0x3ff)           /* Reserved, RES1 */
+
+/*
+ * SCTLR_EL2 bits definitions
+ */
+#define SCTLR_EL2_RES1         (3 << 28 | 3 << 22 | 1 << 18 | 1 << 16 |\
+                                1 << 11 | 3 << 4)          /* Reserved, RES1 */
+#define SCTLR_EL2_EE_LE                (0 << 25) /* Exception Little-endian          */
+#define SCTLR_EL2_WXN_DIS      (0 << 19) /* Write permission is not XN       */
+#define SCTLR_EL2_ICACHE_DIS   (0 << 12) /* Instruction cache disabled       */
+#define SCTLR_EL2_SA_DIS       (0 << 3)  /* Stack Alignment Check disabled   */
+#define SCTLR_EL2_DCACHE_DIS   (0 << 2)  /* Data cache disabled              */
+#define SCTLR_EL2_ALIGN_DIS    (0 << 1)  /* Alignment check disabled         */
+#define SCTLR_EL2_MMU_DIS      (0)       /* MMU disabled                     */
+
+/*
+ * CNTHCTL_EL2 bits definitions
+ */
+#define CNTHCTL_EL2_EL1PCEN_EN (1 << 1)  /* Physical timer regs accessible   */
+#define CNTHCTL_EL2_EL1PCTEN_EN        (1 << 0)  /* Physical counter accessible      */
+
+/*
+ * HCR_EL2 bits definitions
+ */
+#define HCR_EL2_RW_AARCH64     (1 << 31) /* EL1 is AArch64                   */
+#define HCR_EL2_RW_AARCH32     (0 << 31) /* Lower levels are AArch32         */
+#define HCR_EL2_HCD_DIS                (1 << 29) /* Hypervisor Call disabled         */
+
+/*
+ * CPACR_EL1 bits definitions
+ */
+#define CPACR_EL1_FPEN_EN      (3 << 20) /* SIMD and FP instruction enabled  */
+
+/*
+ * SCTLR_EL1 bits definitions
+ */
+#define SCTLR_EL1_RES1         (3 << 28 | 3 << 22 | 1 << 20 |\
+                                1 << 11) /* Reserved, RES1                   */
+#define SCTLR_EL1_UCI_DIS      (0 << 26) /* Cache instruction disabled       */
+#define SCTLR_EL1_EE_LE                (0 << 25) /* Exception Little-endian          */
+#define SCTLR_EL1_WXN_DIS      (0 << 19) /* Write permission is not XN       */
+#define SCTLR_EL1_NTWE_DIS     (0 << 18) /* WFE instruction disabled         */
+#define SCTLR_EL1_NTWI_DIS     (0 << 16) /* WFI instruction disabled         */
+#define SCTLR_EL1_UCT_DIS      (0 << 15) /* CTR_EL0 access disabled          */
+#define SCTLR_EL1_DZE_DIS      (0 << 14) /* DC ZVA instruction disabled      */
+#define SCTLR_EL1_ICACHE_DIS   (0 << 12) /* Instruction cache disabled       */
+#define SCTLR_EL1_UMA_DIS      (0 << 9)  /* User Mask Access disabled        */
+#define SCTLR_EL1_SED_EN       (0 << 8)  /* SETEND instruction enabled       */
+#define SCTLR_EL1_ITD_EN       (0 << 7)  /* IT instruction enabled           */
+#define SCTLR_EL1_CP15BEN_DIS  (0 << 5)  /* CP15 barrier operation disabled  */
+#define SCTLR_EL1_SA0_DIS      (0 << 4)  /* Stack Alignment EL0 disabled     */
+#define SCTLR_EL1_SA_DIS       (0 << 3)  /* Stack Alignment EL1 disabled     */
+#define SCTLR_EL1_DCACHE_DIS   (0 << 2)  /* Data cache disabled              */
+#define SCTLR_EL1_ALIGN_DIS    (0 << 1)  /* Alignment check disabled         */
+#define SCTLR_EL1_MMU_DIS      (0)       /* MMU disabled                     */
 
 #ifndef __ASSEMBLY__
 
+u64 get_page_table_size(void);
+#define PGTABLE_SIZE   get_page_table_size()
+
+/* 2MB granularity */
+#define MMU_SECTION_SHIFT      21
+#define MMU_SECTION_SIZE       (1 << MMU_SECTION_SHIFT)
+
+/* These constants need to be synced to the MT_ types in asm/armv8/mmu.h */
 enum dcache_option {
-       DCACHE_OFF = 0x3,
+       DCACHE_OFF = 0 << 2,
+       DCACHE_WRITETHROUGH = 3 << 2,
+       DCACHE_WRITEBACK = 4 << 2,
+       DCACHE_WRITEALLOC = 4 << 2,
 };
 
-#define isb()                          \
-       ({asm volatile(                 \
-       "isb" : : : "memory");          \
-       })
-
 #define wfi()                          \
        ({asm volatile(                 \
        "wfi" : : : "memory");          \
@@ -71,15 +166,57 @@ static inline void set_sctlr(unsigned int val)
        asm volatile("isb");
 }
 
+static inline unsigned long read_mpidr(void)
+{
+       unsigned long val;
+
+       asm volatile("mrs %0, mpidr_el1" : "=r" (val));
+
+       return val;
+}
+
+#define BSP_COREID     0
+
 void __asm_flush_dcache_all(void);
 void __asm_invalidate_dcache_all(void);
 void __asm_flush_dcache_range(u64 start, u64 end);
 void __asm_invalidate_tlb_all(void);
 void __asm_invalidate_icache_all(void);
-int __asm_flush_l3_cache(void);
+int __asm_invalidate_l3_dcache(void);
+int __asm_flush_l3_dcache(void);
+int __asm_invalidate_l3_icache(void);
+void __asm_switch_ttbr(u64 new_ttbr);
 
-void armv8_switch_to_el2(void);
-void armv8_switch_to_el1(void);
+/*
+ * Switch from EL3 to EL2 for ARMv8
+ *
+ * @args:        For loading 64-bit OS, fdt address.
+ *               For loading 32-bit OS, zero.
+ * @mach_nr:     For loading 64-bit OS, zero.
+ *               For loading 32-bit OS, machine nr
+ * @fdt_addr:    For loading 64-bit OS, zero.
+ *               For loading 32-bit OS, fdt address.
+ * @entry_point: kernel entry point
+ * @es_flag:     execution state flag, ES_TO_AARCH64 or ES_TO_AARCH32
+ */
+void armv8_switch_to_el2(u64 args, u64 mach_nr, u64 fdt_addr,
+                        u64 entry_point, u64 es_flag);
+/*
+ * Switch from EL2 to EL1 for ARMv8
+ *
+ * @args:        For loading 64-bit OS, fdt address.
+ *               For loading 32-bit OS, zero.
+ * @mach_nr:     For loading 64-bit OS, zero.
+ *               For loading 32-bit OS, machine nr
+ * @fdt_addr:    For loading 64-bit OS, zero.
+ *               For loading 32-bit OS, fdt address.
+ * @entry_point: kernel entry point
+ * @es_flag:     execution state flag, ES_TO_AARCH64 or ES_TO_AARCH32
+ */
+void armv8_switch_to_el1(u64 args, u64 mach_nr, u64 fdt_addr,
+                        u64 entry_point, u64 es_flag);
+void armv8_el2_to_aarch32(u64 args, u64 mach_nr, u64 fdt_addr,
+                         u64 entry_point);
 void gic_init(void);
 void gic_send_sgi(unsigned long sgino);
 void wait_for_wakeup(void);
@@ -88,6 +225,18 @@ void smp_kick_all_cpus(void);
 
 void flush_l3_cache(void);
 
+/*
+ *Issue a secure monitor call in accordance with ARM "SMC Calling convention",
+ * DEN0028A
+ *
+ * @args: input and output arguments
+ *
+ */
+void smc_call(struct pt_regs *args);
+
+void __noreturn psci_system_reset(void);
+void __noreturn psci_system_off(void);
+
 #endif /* __ASSEMBLY__ */
 
 #else /* CONFIG_ARM64 */
@@ -136,7 +285,11 @@ void flush_l3_cache(void);
 #define CR_AFE (1 << 29)       /* Access flag enable                   */
 #define CR_TE  (1 << 30)       /* Thumb exception enable               */
 
+#if defined(CONFIG_ARMV7_LPAE) && !defined(PGTABLE_SIZE)
+#define PGTABLE_SIZE           (4096 * 5)
+#elif !defined(PGTABLE_SIZE)
 #define PGTABLE_SIZE           (4096 * 4)
+#endif
 
 /*
  * This is used to ensure the compiler did actually allocate the register we
@@ -181,7 +334,9 @@ void flush_l3_cache(void);
  */
 void save_boot_params_ret(void);
 
-#define isb() __asm__ __volatile__ ("" : : : "memory")
+#ifdef CONFIG_ARMV7_LPAE
+void switch_to_hypervisor_ret(void);
+#endif
 
 #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
 
@@ -191,17 +346,50 @@ void save_boot_params_ret(void);
 #define wfi()
 #endif
 
+static inline unsigned long get_cpsr(void)
+{
+       unsigned long cpsr;
+
+       asm volatile("mrs %0, cpsr" : "=r"(cpsr): );
+       return cpsr;
+}
+
+static inline int is_hyp(void)
+{
+#ifdef CONFIG_ARMV7_LPAE
+       /* HYP mode requires LPAE ... */
+       return ((get_cpsr() & 0x1f) == 0x1a);
+#else
+       /* ... so without LPAE support we can optimize all hyp code away */
+       return 0;
+#endif
+}
+
 static inline unsigned int get_cr(void)
 {
        unsigned int val;
-       asm("mrc p15, 0, %0, c1, c0, 0  @ get CR" : "=r" (val) : : "cc");
+
+       if (is_hyp())
+               asm volatile("mrc p15, 4, %0, c1, c0, 0 @ get CR" : "=r" (val)
+                                                                 :
+                                                                 : "cc");
+       else
+               asm volatile("mrc p15, 0, %0, c1, c0, 0 @ get CR" : "=r" (val)
+                                                                 :
+                                                                 : "cc");
        return val;
 }
 
 static inline void set_cr(unsigned int val)
 {
-       asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR"
-         : : "r" (val) : "cc");
+       if (is_hyp())
+               asm volatile("mcr p15, 4, %0, c1, c0, 0 @ set CR" :
+                                                                 : "r" (val)
+                                                                 : "cc");
+       else
+               asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR" :
+                                                                 : "r" (val)
+                                                                 : "cc");
        isb();
 }
 
@@ -219,12 +407,59 @@ static inline void set_dacr(unsigned int val)
        isb();
 }
 
-#ifdef CONFIG_ARMV7
+#ifdef CONFIG_ARMV7_LPAE
+/* Long-Descriptor Translation Table Level 1/2 Bits */
+#define TTB_SECT_XN_MASK       (1ULL << 54)
+#define TTB_SECT_NG_MASK       (1 << 11)
+#define TTB_SECT_AF            (1 << 10)
+#define TTB_SECT_SH_MASK       (3 << 8)
+#define TTB_SECT_NS_MASK       (1 << 5)
+#define TTB_SECT_AP            (1 << 6)
+/* Note: TTB AP bits are set elsewhere */
+#define TTB_SECT_MAIR(x)       ((x & 0x7) << 2) /* Index into MAIR */
+#define TTB_SECT               (1 << 0)
+#define TTB_PAGETABLE          (3 << 0)
+
+/* TTBCR flags */
+#define TTBCR_EAE              (1 << 31)
+#define TTBCR_T0SZ(x)          ((x) << 0)
+#define TTBCR_T1SZ(x)          ((x) << 16)
+#define TTBCR_USING_TTBR0      (TTBCR_T0SZ(0) | TTBCR_T1SZ(0))
+#define TTBCR_IRGN0_NC         (0 << 8)
+#define TTBCR_IRGN0_WBWA       (1 << 8)
+#define TTBCR_IRGN0_WT         (2 << 8)
+#define TTBCR_IRGN0_WBNWA      (3 << 8)
+#define TTBCR_IRGN0_MASK       (3 << 8)
+#define TTBCR_ORGN0_NC         (0 << 10)
+#define TTBCR_ORGN0_WBWA       (1 << 10)
+#define TTBCR_ORGN0_WT         (2 << 10)
+#define TTBCR_ORGN0_WBNWA      (3 << 10)
+#define TTBCR_ORGN0_MASK       (3 << 10)
+#define TTBCR_SHARED_NON       (0 << 12)
+#define TTBCR_SHARED_OUTER     (2 << 12)
+#define TTBCR_SHARED_INNER     (3 << 12)
+#define TTBCR_EPD0             (0 << 7)
+
+/*
+ * Memory types
+ */
+#define MEMORY_ATTRIBUTES      ((0x00 << (0 * 8)) | (0x88 << (1 * 8)) | \
+                                (0xcc << (2 * 8)) | (0xff << (3 * 8)))
+
+/* options available for data cache on each page */
+enum dcache_option {
+       DCACHE_OFF = TTB_SECT | TTB_SECT_MAIR(0) | TTB_SECT_XN_MASK,
+       DCACHE_WRITETHROUGH = TTB_SECT | TTB_SECT_MAIR(1),
+       DCACHE_WRITEBACK = TTB_SECT | TTB_SECT_MAIR(2),
+       DCACHE_WRITEALLOC = TTB_SECT | TTB_SECT_MAIR(3),
+};
+#elif defined(CONFIG_CPU_V7)
 /* Short-Descriptor Translation Table Level 1 Bits */
 #define TTB_SECT_NS_MASK       (1 << 19)
 #define TTB_SECT_NG_MASK       (1 << 17)
 #define TTB_SECT_S_MASK                (1 << 16)
 /* Note: TTB AP bits are set elsewhere */
+#define TTB_SECT_AP            (3 << 10)
 #define TTB_SECT_TEX(x)                ((x & 0x7) << 12)
 #define TTB_SECT_DOMAIN(x)     ((x & 0xf) << 5)
 #define TTB_SECT_XN_MASK       (1 << 4)
@@ -234,13 +469,13 @@ static inline void set_dacr(unsigned int val)
 
 /* options available for data cache on each page */
 enum dcache_option {
-       DCACHE_OFF = TTB_SECT_S_MASK | TTB_SECT_DOMAIN(0) |
-                                       TTB_SECT_XN_MASK | TTB_SECT,
+       DCACHE_OFF = TTB_SECT_DOMAIN(0) | TTB_SECT_XN_MASK | TTB_SECT,
        DCACHE_WRITETHROUGH = DCACHE_OFF | TTB_SECT_C_MASK,
        DCACHE_WRITEBACK = DCACHE_WRITETHROUGH | TTB_SECT_B_MASK,
        DCACHE_WRITEALLOC = DCACHE_WRITEBACK | TTB_SECT_TEX(1),
 };
 #else
+#define TTB_SECT_AP            (3 << 10)
 /* options available for data cache on each page */
 enum dcache_option {
        DCACHE_OFF = 0x12,
@@ -252,11 +487,15 @@ enum dcache_option {
 
 /* Size of an MMU section */
 enum {
-       MMU_SECTION_SHIFT       = 20,
+#ifdef CONFIG_ARMV7_LPAE
+       MMU_SECTION_SHIFT       = 21, /* 2MB */
+#else
+       MMU_SECTION_SHIFT       = 20, /* 1MB */
+#endif
        MMU_SECTION_SIZE        = 1 << MMU_SECTION_SHIFT,
 };
 
-#ifdef CONFIG_ARMV7
+#ifdef CONFIG_CPU_V7
 /* TTBR0 bits */
 #define TTBR0_BASE_ADDR_MASK   0xFFFFC000
 #define TTBR0_RGN_NC                   (0 << 3)
@@ -278,11 +517,6 @@ enum {
  */
 void mmu_page_table_flush(unsigned long start, unsigned long stop);
 
-#ifdef CONFIG_SYS_NONCACHED_MEMORY
-void noncached_init(void);
-phys_addr_t noncached_alloc(size_t size, size_t align);
-#endif /* CONFIG_SYS_NONCACHED_MEMORY */
-
 #endif /* __ASSEMBLY__ */
 
 #define arch_align_stack(x) (x)
@@ -302,6 +536,11 @@ phys_addr_t noncached_alloc(size_t size, size_t align);
 void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
                                     enum dcache_option option);
 
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+void noncached_init(void);
+phys_addr_t noncached_alloc(size_t size, size_t align);
+#endif /* CONFIG_SYS_NONCACHED_MEMORY */
+
 #endif /* __ASSEMBLY__ */
 
 #endif