/*
+ * 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;
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);
/* 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:
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();
{
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
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(®s);
+
+ 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;
}
#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
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
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
* 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
#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
/*
* 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;
#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");
}
* 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;
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 >=
}
#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;
}