]> git.sur5r.net Git - u-boot/blobdiff - arch/arm/cpu/armv8/fsl-layerscape/cpu.c
board: freescale: ls2080a/ls2088a: Enable PPA
[u-boot] / arch / arm / cpu / armv8 / fsl-layerscape / cpu.c
index 368bdcdb883c829851d04639e61ce4567867750e..cebbb0fec5ee054c31fdabf33759819de86cafac 100644 (file)
@@ -89,6 +89,49 @@ static inline void early_mmu_setup(void)
        set_sctlr(get_sctlr() | CR_M);
 }
 
+static void fix_pcie_mmu_map(void)
+{
+#ifdef CONFIG_LS2080A
+       unsigned int i;
+       u32 svr, ver;
+       struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+
+       svr = gur_in32(&gur->svr);
+       ver = SVR_SOC_VER(svr);
+
+       /* Fix PCIE base and size for LS2088A */
+       if ((ver == SVR_LS2088A) || (ver == SVR_LS2084A) ||
+           (ver == SVR_LS2048A) || (ver == SVR_LS2044A)) {
+               for (i = 0; i < ARRAY_SIZE(final_map); i++) {
+                       switch (final_map[i].phys) {
+                       case CONFIG_SYS_PCIE1_PHYS_ADDR:
+                               final_map[i].phys = 0x2000000000ULL;
+                               final_map[i].virt = 0x2000000000ULL;
+                               final_map[i].size = 0x800000000ULL;
+                               break;
+                       case CONFIG_SYS_PCIE2_PHYS_ADDR:
+                               final_map[i].phys = 0x2800000000ULL;
+                               final_map[i].virt = 0x2800000000ULL;
+                               final_map[i].size = 0x800000000ULL;
+                               break;
+                       case CONFIG_SYS_PCIE3_PHYS_ADDR:
+                               final_map[i].phys = 0x3000000000ULL;
+                               final_map[i].virt = 0x3000000000ULL;
+                               final_map[i].size = 0x800000000ULL;
+                               break;
+                       case CONFIG_SYS_PCIE4_PHYS_ADDR:
+                               final_map[i].phys = 0x3800000000ULL;
+                               final_map[i].virt = 0x3800000000ULL;
+                               final_map[i].size = 0x800000000ULL;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+#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
@@ -103,6 +146,9 @@ static inline void final_mmu_setup(void)
        unsigned int el = current_el();
        int index;
 
+       /* fix the final_map before filling in the block entries */
+       fix_pcie_mmu_map();
+
        mem_map = final_map;
 
        /* Update mapping for DDR to actual size */
@@ -181,21 +227,14 @@ static inline void final_mmu_setup(void)
        setup_pgtables();
        gd->arch.tlb_addr = tlb_addr_save;
 
-       /* flush new MMU table */
-       flush_dcache_range(gd->arch.tlb_addr,
-                          gd->arch.tlb_addr + gd->arch.tlb_size);
+       /* Disable cache and MMU */
+       dcache_disable();       /* TLBs are invalidated */
+       invalidate_icache_all();
 
        /* point TTBR to the new table */
        set_ttbr_tcr_mair(el, gd->arch.tlb_addr, get_tcr(el, NULL, NULL),
                          MEMORY_ATTRIBUTES);
-       /*
-        * EL3 MMU is already enabled, just need to invalidate TLB to load the
-        * new table. The new table is compatible with the current table, if
-        * MMU somehow walks through the new table before invalidation TLB,
-        * it still works. So we don't need to turn off MMU here.
-        * When EL2 MMU table is created by calling this function, MMU needs
-        * to be enabled.
-        */
+
        set_sctlr(get_sctlr() | CR_M);
 }
 
@@ -443,7 +482,14 @@ int arch_early_init_r(void)
 #endif
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_A009635
-       erratum_a009635();
+       u32 svr_dev_id;
+       /*
+        * erratum A009635 is valid only for LS2080A SoC and
+        * its personalitiesi
+        */
+       svr_dev_id = get_svr() >> 16;
+       if (svr_dev_id == SVR_DEV_LS2080A)
+               erratum_a009635();
 #endif
 #if defined(CONFIG_SYS_FSL_ERRATUM_A009942) && defined(CONFIG_SYS_FSL_DDR)
        erratum_a009942_check_cpo();
@@ -760,3 +806,79 @@ void efi_add_known_memory(void)
        }
 }
 #endif
+
+/*
+ * Before DDR size is known, early MMU table have DDR mapped as device memory
+ * to avoid speculative access. To relocate U-Boot to DDR, "normal memory"
+ * needs to be set for these mappings.
+ * If a special case configures DDR with holes in the mapping, the holes need
+ * to be marked as invalid. This is not implemented in this function.
+ */
+void update_early_mmu_table(void)
+{
+       if (!gd->arch.tlb_addr)
+               return;
+
+       if (gd->ram_size <= CONFIG_SYS_FSL_DRAM_SIZE1) {
+               mmu_change_region_attr(
+                                       CONFIG_SYS_SDRAM_BASE,
+                                       gd->ram_size,
+                                       PTE_BLOCK_MEMTYPE(MT_NORMAL)    |
+                                       PTE_BLOCK_OUTER_SHARE           |
+                                       PTE_BLOCK_NS                    |
+                                       PTE_TYPE_VALID);
+       } else {
+               mmu_change_region_attr(
+                                       CONFIG_SYS_SDRAM_BASE,
+                                       CONFIG_SYS_DDR_BLOCK1_SIZE,
+                                       PTE_BLOCK_MEMTYPE(MT_NORMAL)    |
+                                       PTE_BLOCK_OUTER_SHARE           |
+                                       PTE_BLOCK_NS                    |
+                                       PTE_TYPE_VALID);
+#ifdef CONFIG_SYS_DDR_BLOCK3_BASE
+#ifndef CONFIG_SYS_DDR_BLOCK2_SIZE
+#error "Missing CONFIG_SYS_DDR_BLOCK2_SIZE"
+#endif
+               if (gd->ram_size - CONFIG_SYS_DDR_BLOCK1_SIZE >
+                   CONFIG_SYS_DDR_BLOCK2_SIZE) {
+                       mmu_change_region_attr(
+                                       CONFIG_SYS_DDR_BLOCK2_BASE,
+                                       CONFIG_SYS_DDR_BLOCK2_SIZE,
+                                       PTE_BLOCK_MEMTYPE(MT_NORMAL)    |
+                                       PTE_BLOCK_OUTER_SHARE           |
+                                       PTE_BLOCK_NS                    |
+                                       PTE_TYPE_VALID);
+                       mmu_change_region_attr(
+                                       CONFIG_SYS_DDR_BLOCK3_BASE,
+                                       gd->ram_size -
+                                       CONFIG_SYS_DDR_BLOCK1_SIZE -
+                                       CONFIG_SYS_DDR_BLOCK2_SIZE,
+                                       PTE_BLOCK_MEMTYPE(MT_NORMAL)    |
+                                       PTE_BLOCK_OUTER_SHARE           |
+                                       PTE_BLOCK_NS                    |
+                                       PTE_TYPE_VALID);
+               } else
+#endif
+               {
+                       mmu_change_region_attr(
+                                       CONFIG_SYS_DDR_BLOCK2_BASE,
+                                       gd->ram_size -
+                                       CONFIG_SYS_DDR_BLOCK1_SIZE,
+                                       PTE_BLOCK_MEMTYPE(MT_NORMAL)    |
+                                       PTE_BLOCK_OUTER_SHARE           |
+                                       PTE_BLOCK_NS                    |
+                                       PTE_TYPE_VALID);
+               }
+       }
+}
+
+__weak int dram_init(void)
+{
+       gd->ram_size = initdram(0);
+#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
+       /* This will break-before-make MMU for DDR */
+       update_early_mmu_table();
+#endif
+
+       return 0;
+}