armv8: fsl-layerscape: Remove unnecessary flushing dcache
[platform/kernel/u-boot.git] / arch / arm / cpu / armv8 / fsl-layerscape / cpu.c
index 571ee7b..9a5a6b5 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static struct mm_region layerscape_mem_map[] = {
+       {
+               /* List terminator */
+               0,
+       }
+};
+struct mm_region *mem_map = layerscape_mem_map;
+
 void cpu_name(char *name)
 {
        struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
@@ -48,6 +56,25 @@ void cpu_name(char *name)
 }
 
 #ifndef CONFIG_SYS_DCACHE_OFF
+static void set_pgtable_section(u64 *page_table, u64 index, u64 section,
+                       u64 memory_type, u64 attribute)
+{
+       u64 value;
+
+       value = section | PTE_TYPE_BLOCK | PTE_BLOCK_AF;
+       value |= PMD_ATTRINDX(memory_type);
+       value |= attribute;
+       page_table[index] = value;
+}
+
+static void set_pgtable_table(u64 *page_table, u64 index, u64 *table_addr)
+{
+       u64 value;
+
+       value = (u64)table_addr | PTE_TYPE_TABLE;
+       page_table[index] = value;
+}
+
 /*
  * Set the block entries according to the information of the table.
  */
@@ -114,10 +141,10 @@ static int find_table(const struct sys_mmu_table *list,
 
                temp_base -= block_size;
 
-               if ((level_table[index - 1] & PMD_TYPE_MASK) ==
-                   PMD_TYPE_TABLE) {
+               if ((level_table[index - 1] & PTE_TYPE_MASK) ==
+                   PTE_TYPE_TABLE) {
                        level_table = (u64 *)(level_table[index - 1] &
-                                     ~PMD_TYPE_MASK);
+                                     ~PTE_TYPE_MASK);
                        level++;
                        continue;
                } else {
@@ -206,11 +233,65 @@ static inline void early_mmu_setup(void)
        set_sctlr(get_sctlr() | CR_M);
 }
 
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+/*
+ * Called from final mmu setup. The phys_addr is new, non-existing
+ * address. A new sub table is created @level2_table_secure to cover
+ * size of CONFIG_SYS_MEM_RESERVE_SECURE memory.
+ */
+static inline int final_secure_ddr(u64 *level0_table,
+                                  u64 *level2_table_secure,
+                                  phys_addr_t phys_addr)
+{
+       int ret = -EINVAL;
+       struct table_info table = {};
+       struct sys_mmu_table ddr_entry = {
+               0, 0, BLOCK_SIZE_L1, MT_NORMAL,
+               PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+       };
+       u64 index;
+
+       /* Need to create a new table */
+       ddr_entry.virt_addr = phys_addr & ~(BLOCK_SIZE_L1 - 1);
+       ddr_entry.phys_addr = phys_addr & ~(BLOCK_SIZE_L1 - 1);
+       ret = find_table(&ddr_entry, &table, level0_table);
+       if (ret)
+               return ret;
+       index = (ddr_entry.virt_addr - table.table_base) >> SECTION_SHIFT_L1;
+       set_pgtable_table(table.ptr, index, level2_table_secure);
+       table.ptr = level2_table_secure;
+       table.table_base = ddr_entry.virt_addr;
+       table.entry_size = BLOCK_SIZE_L2;
+       ret = set_block_entry(&ddr_entry, &table);
+       if (ret) {
+               printf("MMU error: could not fill non-secure ddr block entries\n");
+               return ret;
+       }
+       ddr_entry.virt_addr = phys_addr;
+       ddr_entry.phys_addr = phys_addr;
+       ddr_entry.size = CONFIG_SYS_MEM_RESERVE_SECURE;
+       ddr_entry.attribute = PTE_BLOCK_OUTER_SHARE;
+       ret = find_table(&ddr_entry, &table, level0_table);
+       if (ret) {
+               printf("MMU error: could not find secure ddr table\n");
+               return ret;
+       }
+       ret = set_block_entry(&ddr_entry, &table);
+       if (ret)
+               printf("MMU error: could not set secure ddr block entry\n");
+
+       return ret;
+}
+#endif
+
 /*
  * The final tables look similar to early tables, but different in detail.
  * These tables are in DRAM. Sub tables are added to enable cache for
  * QBMan and OCRAM.
  *
+ * Put the MMU table in secure memory if gd->secure_ram is valid.
+ * OCRAM will be not used for this purpose so gd->secure_ram can't be 0.
+ *
  * Level 1 table 0 contains 512 entries for each 1GB from 0 to 512GB.
  * Level 1 table 1 contains 512 entries for each 1GB from 512GB to 1TB.
  * Level 2 table 0 contains 512 entries for each 2MB from 0 to 1GB.
@@ -223,18 +304,40 @@ static inline void early_mmu_setup(void)
  */
 static inline void final_mmu_setup(void)
 {
-       unsigned int el, i;
+       unsigned int el = current_el();
+       unsigned int i;
        u64 *level0_table = (u64 *)gd->arch.tlb_addr;
-       u64 *level1_table0 = (u64 *)(gd->arch.tlb_addr + 0x1000);
-       u64 *level1_table1 = (u64 *)(gd->arch.tlb_addr + 0x2000);
-       u64 *level2_table0 = (u64 *)(gd->arch.tlb_addr + 0x3000);
-#ifdef CONFIG_FSL_LSCH3
-       u64 *level2_table1 = (u64 *)(gd->arch.tlb_addr + 0x4000);
-#elif defined(CONFIG_FSL_LSCH2)
-       u64 *level2_table1 = (u64 *)(gd->arch.tlb_addr + 0x4000);
-       u64 *level2_table2 = (u64 *)(gd->arch.tlb_addr + 0x5000);
+       u64 *level1_table0;
+       u64 *level1_table1;
+       u64 *level2_table0;
+       u64 *level2_table1;
+#ifdef CONFIG_FSL_LSCH2
+       u64 *level2_table2;
 #endif
-       struct table_info table = {level0_table, 0, BLOCK_SIZE_L0};
+       struct table_info table = {NULL, 0, BLOCK_SIZE_L0};
+
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+       u64 *level2_table_secure;
+
+       if (el == 3) {
+               /*
+                * Only use gd->secure_ram if the address is recalculated
+                * Align to 4KB for MMU table
+                */
+               if (gd->secure_ram & MEM_RESERVE_SECURE_MAINTAINED)
+                       level0_table = (u64 *)(gd->secure_ram & ~0xfff);
+               else
+                       printf("MMU warning: gd->secure_ram is not maintained, disabled.\n");
+       }
+#endif
+       level1_table0 = level0_table + 512;
+       level1_table1 = level1_table0 + 512;
+       level2_table0 = level1_table1 + 512;
+       level2_table1 = level2_table0 + 512;
+#ifdef CONFIG_FSL_LSCH2
+       level2_table2 = level2_table1 + 512;
+#endif
+       table.ptr = level0_table;
 
        /* Invalidate all table entries */
        memset(level0_table, 0, PGTABLE_SIZE);
@@ -269,17 +372,31 @@ static inline void final_mmu_setup(void)
                               &final_mmu_table[i]);
                }
        }
+       /* Set the secure memory to secure in MMU */
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+       if (el == 3 && gd->secure_ram & MEM_RESERVE_SECURE_MAINTAINED) {
+#ifdef CONFIG_FSL_LSCH3
+               level2_table_secure = level2_table1 + 512;
+#elif defined(CONFIG_FSL_LSCH2)
+               level2_table_secure = level2_table2 + 512;
+#endif
+               if (!final_secure_ddr(level0_table,
+                                     level2_table_secure,
+                                     gd->secure_ram & ~0x3)) {
+                       gd->secure_ram |= MEM_RESERVE_SECURE_SECURED;
+                       debug("Now MMU table is in secured memory at 0x%llx\n",
+                             gd->secure_ram & ~0x3);
+               } else {
+                       printf("MMU warning: Failed to secure DDR\n");
+               }
+       }
+#endif
 
        /* flush new MMU table */
-       flush_dcache_range(gd->arch.tlb_addr,
-                          gd->arch.tlb_addr + gd->arch.tlb_size);
+       flush_dcache_range((ulong)level0_table,
+                          (ulong)level0_table + gd->arch.tlb_size);
 
-#ifdef CONFIG_SYS_DPAA_FMAN
-       flush_dcache_all();
-#endif
        /* point TTBR to the new table */
-       el = current_el();
-
        set_ttbr_tcr_mair(el, (u64)level0_table, LAYERSCAPE_TCR_FINAL,
                          MEMORY_ATTRIBUTES);
        /*
@@ -290,6 +407,11 @@ static inline void final_mmu_setup(void)
         */
 }
 
+u64 get_page_table_size(void)
+{
+       return 0x10000;
+}
+
 int arch_cpu_init(void)
 {
        icache_enable();
@@ -413,12 +535,12 @@ int print_cpuinfo(void)
        struct sys_info sysinfo;
        char buf[32];
        unsigned int i, core;
-       u32 type, rcw;
+       u32 type, rcw, svr = gur_in32(&gur->svr);
 
        puts("SoC: ");
 
        cpu_name(buf);
-       printf(" %s (0x%x)\n", buf, gur_in32(&gur->svr));
+       printf(" %s (0x%x)\n", buf, svr);
        memset((u8 *)buf, 0x00, ARRAY_SIZE(buf));
        get_sys_info(&sysinfo);
        puts("Clock Configuration:");
@@ -439,7 +561,10 @@ int print_cpuinfo(void)
        printf("  FMAN:     %-4s MHz", strmhz(buf, sysinfo.freq_fman[0]));
 #endif
 #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
-       printf("     DP-DDR:   %-4s MT/s", strmhz(buf, sysinfo.freq_ddrbus2));
+       if (soc_has_dp_ddr()) {
+               printf("     DP-DDR:   %-4s MT/s",
+                      strmhz(buf, sysinfo.freq_ddrbus2));
+       }
 #endif
        puts("\n");
 
@@ -484,7 +609,13 @@ int arch_early_init_r(void)
 {
 #ifdef CONFIG_MP
        int rv = 1;
+#endif
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009635
+       erratum_a009635();
+#endif
 
+#ifdef CONFIG_MP
        rv = fsl_layerscape_wake_seconday_cores();
        if (rv)
                printf("Did not wake secondary cores\n");
@@ -537,3 +668,24 @@ void reset_cpu(ulong addr)
        val |= 0x02;
        scfg_out32(rstcr, val);
 }
+
+phys_size_t board_reserve_ram_top(phys_size_t ram_size)
+{
+       phys_size_t ram_top = ram_size;
+
+#ifdef CONFIG_SYS_MEM_TOP_HIDE
+#error CONFIG_SYS_MEM_TOP_HIDE not to be used together with this function
+#endif
+/* Carve the Debug Server private DRAM block from the end of DRAM */
+#ifdef CONFIG_FSL_DEBUG_SERVER
+       ram_top -= debug_server_get_dram_block_size();
+#endif
+
+/* Carve the MC private DRAM block from the end of DRAM */
+#ifdef CONFIG_FSL_MC_ENET
+       ram_top -= mc_get_dram_block_size();
+       ram_top &= ~(CONFIG_SYS_MC_RSV_MEM_ALIGN - 1);
+#endif
+
+       return ram_top;
+}