]> git.sur5r.net Git - u-boot/blobdiff - arch/arm/cpu/armv8/fsl-layerscape/cpu.c
drivers/misc: Share qbman init between archs
[u-boot] / arch / arm / cpu / armv8 / fsl-layerscape / cpu.c
index d446527616c4bb929d6bc247be1f206917762dcf..1e0030cbfbaaadb41600f6292b28240e3013f76f 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2017 NXP
  * Copyright 2014-2015 Freescale Semiconductor, Inc.
  *
  * SPDX-License-Identifier:    GPL-2.0+
 #include <asm/arch/soc.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/speed.h>
-#ifdef CONFIG_MP
+#include <fsl_immap.h>
 #include <asm/arch/mp.h>
-#endif
 #include <efi_loader.h>
 #include <fm_eth.h>
 #include <fsl-mc/fsl_mc.h>
 #ifdef CONFIG_FSL_ESDHC
 #include <fsl_esdhc.h>
 #endif
-#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
 #include <asm/armv8/sec_firmware.h>
-#endif
 #ifdef CONFIG_SYS_FSL_DDR
 #include <fsl_ddr.h>
 #endif
+#include <asm/arch/clock.h>
+#include <hwconfig.h>
+#include <fsl_qbman.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -92,7 +93,7 @@ static inline void early_mmu_setup(void)
 
 static void fix_pcie_mmu_map(void)
 {
-#ifdef CONFIG_LS2080A
+#ifdef CONFIG_ARCH_LS2080A
        unsigned int i;
        u32 svr, ver;
        struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
@@ -102,7 +103,8 @@ static void fix_pcie_mmu_map(void)
 
        /* Fix PCIE base and size for LS2088A */
        if ((ver == SVR_LS2088A) || (ver == SVR_LS2084A) ||
-           (ver == SVR_LS2048A) || (ver == SVR_LS2044A)) {
+           (ver == SVR_LS2048A) || (ver == SVR_LS2044A) ||
+           (ver == SVR_LS2081A) || (ver == SVR_LS2041A)) {
                for (i = 0; i < ARRAY_SIZE(final_map); i++) {
                        switch (final_map[i].phys) {
                        case CONFIG_SYS_PCIE1_PHYS_ADDR:
@@ -246,6 +248,14 @@ u64 get_page_table_size(void)
 
 int arch_cpu_init(void)
 {
+       /*
+        * This function is called before U-Boot relocates itself to speed up
+        * on system running. It is not necessary to run if performance is not
+        * critical. Skip if MMU is already enabled by SPL or other means.
+        */
+       if (get_sctlr() & CR_M)
+               return 0;
+
        icache_enable();
        __asm_invalidate_dcache_all();
        __asm_invalidate_tlb_all();
@@ -466,7 +476,7 @@ int cpu_eth_init(bd_t *bis)
 {
        int error = 0;
 
-#ifdef CONFIG_FSL_MC_ENET
+#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
        error = fsl_mc_ldpaa_init(bis);
 #endif
 #ifdef CONFIG_FMAN_ENET
@@ -475,44 +485,89 @@ int cpu_eth_init(bd_t *bis)
        return error;
 }
 
-int arch_early_init_r(void)
+static inline int check_psci(void)
 {
-#ifdef CONFIG_MP
-       int rv = 1;
-       u32 psci_ver = 0xffffffff;
-#endif
+       unsigned int psci_ver;
+
+       psci_ver = sec_firmware_support_psci_version();
+       if (psci_ver == PSCI_INVALID_VER)
+               return 1;
+
+       return 0;
+}
+
+static void config_core_prefetch(void)
+{
+       char *buf = NULL;
+       char buffer[HWCONFIG_BUFFER_SIZE];
+       const char *prefetch_arg = NULL;
+       size_t arglen;
+       unsigned int mask;
+       struct pt_regs regs;
+
+       if (env_get_f("hwconfig", buffer, sizeof(buffer)) > 0)
+               buf = buffer;
+
+       prefetch_arg = hwconfig_subarg_f("core_prefetch", "disable",
+                                        &arglen, buf);
+
+       if (prefetch_arg) {
+               mask = simple_strtoul(prefetch_arg, NULL, 0) & 0xff;
+               if (mask & 0x1) {
+                       printf("Core0 prefetch can't be disabled\n");
+                       return;
+               }
+
+#define SIP_PREFETCH_DISABLE_64 0xC200FF13
+               regs.regs[0] = SIP_PREFETCH_DISABLE_64;
+               regs.regs[1] = mask;
+               smc_call(&regs);
+
+               if (regs.regs[0])
+                       printf("Prefetch disable config failed for mask ");
+               else
+                       printf("Prefetch disable config passed for mask ");
+               printf("0x%x\n", mask);
+       }
+}
 
+int arch_early_init_r(void)
+{
 #ifdef CONFIG_SYS_FSL_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)
+       svr_dev_id = get_svr();
+       if (IS_SVR_DEV(svr_dev_id, SVR_DEV(SVR_LS2080A)))
                erratum_a009635();
 #endif
 #if defined(CONFIG_SYS_FSL_ERRATUM_A009942) && defined(CONFIG_SYS_FSL_DDR)
        erratum_a009942_check_cpo();
 #endif
-#ifdef CONFIG_MP
-#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && \
-       defined(CONFIG_SEC_FIRMWARE_ARMV8_PSCI)
-       /* Check the psci version to determine if the psci is supported */
-       psci_ver = sec_firmware_support_psci_version();
-#endif
-       if (psci_ver == 0xffffffff) {
-               rv = fsl_layerscape_wake_seconday_cores();
-               if (rv)
+       if (check_psci()) {
+               debug("PSCI: PSCI does not exist.\n");
+
+               /* if PSCI does not exist, boot secondary cores here */
+               if (fsl_layerscape_wake_seconday_cores())
                        printf("Did not wake secondary cores\n");
        }
+
+#ifdef CONFIG_SYS_FSL_HAS_RGMII
+       fsl_rgmii_init();
 #endif
 
+       config_core_prefetch();
+
 #ifdef CONFIG_SYS_HAS_SERDES
        fsl_serdes_init();
 #endif
 #ifdef CONFIG_FMAN_ENET
        fman_enet_init();
+#endif
+#ifdef CONFIG_SYS_DPAA_QBMAN
+       setup_qbman_portals();
 #endif
        return 0;
 }
@@ -523,7 +578,7 @@ int timer_init(void)
 #ifdef CONFIG_FSL_LSCH3
        u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR;
 #endif
-#ifdef CONFIG_LS2080A
+#ifdef CONFIG_ARCH_LS2080A
        u32 __iomem *pctbenr = (u32 *)FSL_PMU_PCTBENR_OFFSET;
        u32 svr_dev_id;
 #endif
@@ -531,7 +586,8 @@ int timer_init(void)
        unsigned long cntfrq = COUNTER_FREQUENCY_REAL;
 
        /* Update with accurate clock frequency */
-       asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory");
+       if (current_el() == 3)
+               asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory");
 #endif
 
 #ifdef CONFIG_FSL_LSCH3
@@ -541,7 +597,7 @@ int timer_init(void)
        out_le32(cltbenr, 0xf);
 #endif
 
-#ifdef CONFIG_LS2080A
+#ifdef CONFIG_ARCH_LS2080A
        /*
         * In certain Layerscape SoCs, the clock for each core's
         * has an enable bit in the PMU Physical Core Time Base Enable
@@ -552,8 +608,8 @@ int timer_init(void)
         * For LS2080A SoC and its personalities, timer controller
         * offset is different
         */
-       svr_dev_id = get_svr() >> 16;
-       if (svr_dev_id == SVR_DEV_LS2080A)
+       svr_dev_id = get_svr();
+       if (IS_SVR_DEV(svr_dev_id, SVR_DEV(SVR_LS2080A)))
                cntcr = (u32 *)SYS_FSL_LS2080A_LS2085A_TIMER_ADDR;
 
 #endif
@@ -605,13 +661,22 @@ void efi_reset_system_init(void)
 
 #endif
 
+/*
+ * Calculate reserved memory with given memory bank
+ * Return aligned memory size on success
+ * Return (ram_size + needed size) for failure
+ */
 phys_size_t board_reserve_ram_top(phys_size_t ram_size)
 {
        phys_size_t ram_top = ram_size;
 
-#ifdef CONFIG_FSL_MC_ENET
+#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
+       ram_top = mc_get_dram_block_size();
+       if (ram_top > ram_size)
+               return ram_size + ram_top;
+
+       ram_top = ram_size - ram_top;
        /* The start address of MC reserved memory needs to be aligned. */
-       ram_top -= mc_get_dram_block_size();
        ram_top &= ~(CONFIG_SYS_MC_RSV_MEM_ALIGN - 1);
 #endif
 
@@ -624,13 +689,14 @@ phys_size_t get_effective_memsize(void)
 
        /*
         * For ARMv8 SoCs, DDR memory is split into two or three regions. The
-        * first region is 2GB space at 0x8000_0000. If the memory extends to
-        * the second region (or the third region if applicable), the secure
-        * memory and Management Complex (MC) memory should be put into the
-        * highest region, i.e. the end of DDR memory. CONFIG_MAX_MEM_MAPPED
-        * is set to the size of first region so U-Boot doesn't relocate itself
-        * into higher address. Should DDR be configured to skip the first
-        * region, this function needs to be adjusted.
+        * first region is 2GB space at 0x8000_0000. Secure memory needs to
+        * allocated from first region. If the memory extends to  the second
+        * region (or the third region if applicable), Management Complex (MC)
+        * memory should be put into the highest region, i.e. the end of DDR
+        * memory. CONFIG_MAX_MEM_MAPPED is set to the size of first region so
+        * U-Boot doesn't relocate itself into higher address. Should DDR be
+        * configured to skip the first region, this function needs to be
+        * adjusted.
         */
        if (gd->ram_size > CONFIG_MAX_MEM_MAPPED) {
                ea_size = CONFIG_MAX_MEM_MAPPED;
@@ -641,22 +707,16 @@ phys_size_t get_effective_memsize(void)
 
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
        /* Check if we have enough space for secure memory */
-       if (rem > CONFIG_SYS_MEM_RESERVE_SECURE) {
-               rem -= CONFIG_SYS_MEM_RESERVE_SECURE;
-       } else {
-               if (ea_size > CONFIG_SYS_MEM_RESERVE_SECURE) {
-                       ea_size -= CONFIG_SYS_MEM_RESERVE_SECURE;
-                       rem = 0;        /* Presume MC requires more memory */
-               } else {
-                       printf("Error: No enough space for secure memory.\n");
-               }
-       }
+       if (ea_size > CONFIG_SYS_MEM_RESERVE_SECURE)
+               ea_size -= CONFIG_SYS_MEM_RESERVE_SECURE;
+       else
+               printf("Error: No enough space for secure memory.\n");
 #endif
        /* Check if we have enough memory for MC */
        if (rem < board_reserve_ram_top(rem)) {
                /* Not enough memory in high region to reserve */
-               if (ea_size > board_reserve_ram_top(rem))
-                       ea_size -= board_reserve_ram_top(rem);
+               if (ea_size > board_reserve_ram_top(ea_size))
+                       ea_size -= board_reserve_ram_top(ea_size);
                else
                        printf("Error: No enough space for reserved memory.\n");
        }
@@ -675,8 +735,19 @@ int dram_init_banksize(void)
         * memory. The DDR extends from low region to high region(s) presuming
         * no hole is created with DDR configuration. gd->arch.secure_ram tracks
         * the location of secure memory. gd->arch.resv_ram tracks the location
-        * of reserved memory for Management Complex (MC).
+        * of reserved memory for Management Complex (MC). Because gd->ram_size
+        * is reduced by this function if secure memory is reserved, checking
+        * gd->arch.secure_ram should be done to avoid running it repeatedly.
         */
+
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+       if (gd->arch.secure_ram & MEM_RESERVE_SECURE_MAINTAINED) {
+               debug("No need to run again, skip %s\n", __func__);
+
+               return 0;
+       }
+#endif
+
        gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
        if (gd->ram_size > CONFIG_SYS_DDR_BLOCK1_SIZE) {
                gd->bd->bi_dram[0].size = CONFIG_SYS_DDR_BLOCK1_SIZE;
@@ -695,36 +766,18 @@ int dram_init_banksize(void)
                gd->bd->bi_dram[0].size = gd->ram_size;
        }
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-#ifdef CONFIG_SYS_DDR_BLOCK3_BASE
-       if (gd->bd->bi_dram[2].size >= CONFIG_SYS_MEM_RESERVE_SECURE) {
-               gd->bd->bi_dram[2].size -= CONFIG_SYS_MEM_RESERVE_SECURE;
-               gd->arch.secure_ram = gd->bd->bi_dram[2].start +
-                                     gd->bd->bi_dram[2].size;
+       if (gd->bd->bi_dram[0].size >
+                               CONFIG_SYS_MEM_RESERVE_SECURE) {
+               gd->bd->bi_dram[0].size -=
+                               CONFIG_SYS_MEM_RESERVE_SECURE;
+               gd->arch.secure_ram = gd->bd->bi_dram[0].start +
+                                     gd->bd->bi_dram[0].size;
                gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
                gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE;
-       } else
-#endif
-       {
-               if (gd->bd->bi_dram[1].size >= CONFIG_SYS_MEM_RESERVE_SECURE) {
-                       gd->bd->bi_dram[1].size -=
-                                       CONFIG_SYS_MEM_RESERVE_SECURE;
-                       gd->arch.secure_ram = gd->bd->bi_dram[1].start +
-                                             gd->bd->bi_dram[1].size;
-                       gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
-                       gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE;
-               } else if (gd->bd->bi_dram[0].size >
-                                       CONFIG_SYS_MEM_RESERVE_SECURE) {
-                       gd->bd->bi_dram[0].size -=
-                                       CONFIG_SYS_MEM_RESERVE_SECURE;
-                       gd->arch.secure_ram = gd->bd->bi_dram[0].start +
-                                             gd->bd->bi_dram[0].size;
-                       gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
-                       gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE;
-               }
        }
 #endif /* CONFIG_SYS_MEM_RESERVE_SECURE */
 
-#ifdef CONFIG_FSL_MC_ENET
+#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
        /* Assign memory for MC */
 #ifdef CONFIG_SYS_DDR_BLOCK3_BASE
        if (gd->bd->bi_dram[2].size >=
@@ -774,6 +827,11 @@ int dram_init_banksize(void)
        }
 #endif
 
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+       debug("%s is called. gd->ram_size is reduced to %lu\n",
+             __func__, (ulong)gd->ram_size);
+#endif
+
        return 0;
 }