Hi Lukasz, >Hi Akshay, > >> This patch adds code to shutdown secondary cores. >> When U-boot comes up, all secondary cores appear powered on, >> which is undesirable and causes side effects while >> initializing these cores in kernel. >> >> Secondary core power down happens in following steps: >> >> Step-1: After Exynos power-on, primary core starts executing first. >> Step-2: In iROM code every core has to check 2 flags i.e. >> addresses 0x02020028 & 0x02020004. > >Could you provide exact names of those registers? I'm familiar with >Samsung SoCs but I cannot recall which one those are. >
As I have written in Step-2, these are addresses (SRAM) and not registers. Our iROM code has a part where it reads 0x02020028 for a specific vlaue FCBA0D10. If CPU finds that value then it extracts jump address from 0x02020004, else it follows normal boot path. >It would provide more readability to this commit message. Please fix it >globally. > >> Step-3: Initially 0x02020028 is 0 for all cores and 0x02020004 has a >> jump address for primary core and 0 for all secondary cores. >> Step-4: Therefore, primary core follows normal iROM execution and >> jumps to BL1 eventually, whereas all secondary cores enter WFE. >> Step-5: When primary core comes into function >> secondary_cores_configure, it puts pointer to function >> power_down_core into 0x02020004 and provides DSB and SEV for all >> cores so that they may come out of WFE and jump to power_down_core >> function. Step-6: And ultimately because of power_down_core all >> secondary cores shut-down. >> >> Signed-off-by: Kimoon Kim <kimoon....@samsung.com> >> Signed-off-by: Akshay Saraswat <aksha...@samsung.com> >> --- >> Changes since v2: >> - No change. >> >> Changes since v1: >> - Removed unnecessary macros. >> - Changed names of few macros for better understanding. >> - Added MPIDR bit assignment info comment in power_down_core. >> >> arch/arm/cpu/armv7/exynos/exynos5_setup.h | 3 ++ >> arch/arm/cpu/armv7/exynos/lowlevel_init.c | 69 >> ++++++++++++++++++++++++ arch/arm/include/asm/arch-exynos/cpu.h | >> 5 ++ arch/arm/include/asm/arch-exynos/system.h | 87 >> +++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+) >> >> diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h >> b/arch/arm/cpu/armv7/exynos/exynos5_setup.h index 2eea48a..9073f50 >> 100644 --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h >> +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h >> @@ -700,6 +700,9 @@ >> #define CLK_DIV_CPERI1_VAL NOT_AVAILABLE >> >> #else >> + >> +#define CPU_CONFIG_STATUS_OFFSET 0x80 >> +#define CPU_RST_FLAG_VAL 0xFCBA0D10 >> #define PAD_RETENTION_DRAM_COREBLK_VAL 0x10000000 >> >> /* APLL_CON1 */ >> diff --git a/arch/arm/cpu/armv7/exynos/lowlevel_init.c >> b/arch/arm/cpu/armv7/exynos/lowlevel_init.c index 83e1dcf..e36f2fa >> 100644 --- a/arch/arm/cpu/armv7/exynos/lowlevel_init.c >> +++ b/arch/arm/cpu/armv7/exynos/lowlevel_init.c >> @@ -31,7 +31,9 @@ >> #include <asm/arch/tzpc.h> >> #include <asm/arch/periph.h> >> #include <asm/arch/pinmux.h> >> +#include <asm/arch/system.h> >> #include "common_setup.h" >> +#include "exynos5_setup.h" >> >> /* These are the things we can do during low-level init */ >> enum { >> @@ -42,6 +44,68 @@ enum { >> DO_POWER = 1 << 4, >> }; >> >> +#ifdef CONFIG_EXYNOS5420 >> +/* >> + * Pointer to this function is stored in iRam which is used >> + * for jump and power down of a specific core. >> + */ >> +static void power_down_core(void) >> +{ >> + uint32_t tmp, core_id, core_config; >> + >> + /* Get the unique core id */ >> + /* >> + * Multiprocessor Affinity Register >> + * [11:8] Cluster ID >> + * [1:0] CPU ID >> + */ >> + mrc_mpafr(core_id); >> + tmp = core_id & 0x3; >> + core_id = (core_id >> 6) & ~3; >> + core_id |= tmp; >> + core_id &= 0x3f; >> + >> + /* Set the status of the core to low */ >> + core_config = (core_id * CPU_CONFIG_STATUS_OFFSET); >> + core_config += EXYNOS5420_CPU_CONFIG_BASE; >> + writel(0x0, core_config); >> + >> + /* Core enter WFI */ >> + wfi(); >> +} >> + >> +/* >> + * Configurations for secondary cores are inapt at this stage. >> + * Reconfigure secondary cores. Shutdown and change the status >> + * of all cores except the primary core. >> + */ >> +static void secondary_cores_configure(void) >> +{ >> + uint32_t core_id; >> + >> + /* Store jump address for power down of secondary cores */ >> + writel((uint32_t)&power_down_core, CONFIG_PHY_IRAM_BASE + >> 0x4); + >> + /* Need all core power down check */ >> + dsb(); >> + sev(); >> + >> + /* >> + * Power down all cores(secondary) while primary core must >> + * wait for all cores to go down. >> + */ >> + for (core_id = 1; core_id != CONFIG_CORE_COUNT; core_id++) { >> + while ((readl(EXYNOS5420_CPU_STATUS_BASE >> + + (core_id * CPU_CONFIG_STATUS_OFFSET)) >> + & 0xff) != 0x0) { >> + isb(); >> + sev(); >> + } >> + isb(); >> + } >> +} >> +#endif >> + >> int do_lowlevel_init(void) >> { >> uint32_t reset_status; >> @@ -49,6 +113,11 @@ int do_lowlevel_init(void) >> >> arch_cpu_init(); >> >> +#ifdef CONFIG_EXYNOS5420 >> + /* Reconfigure secondary cores */ >> + secondary_cores_configure(); >> +#endif >> + >> reset_status = get_reset_status(); >> >> switch (reset_status) { >> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h >> b/arch/arm/include/asm/arch-exynos/cpu.h index 29674ad..e739520 100644 >> --- a/arch/arm/include/asm/arch-exynos/cpu.h >> +++ b/arch/arm/include/asm/arch-exynos/cpu.h >> @@ -153,6 +153,10 @@ >> #define EXYNOS5420_CLOCK_BASE 0x10010000 >> #define EXYNOS5420_POWER_BASE 0x10040000 >> #define EXYNOS5420_SWRESET 0x10040400 >> +#define EXYNOS5420_INFORM_BASE 0x10040800 >> +#define EXYNOS5420_SPARE_BASE 0x10040900 >> +#define EXYNOS5420_CPU_CONFIG_BASE 0x10042000 >> +#define EXYNOS5420_CPU_STATUS_BASE 0x10042004 >> #define EXYNOS5420_SYSREG_BASE 0x10050000 >> #define EXYNOS5420_TZPC_BASE 0x100E0000 >> #define EXYNOS5420_WATCHDOG_BASE 0x101D0000 >> @@ -186,6 +190,7 @@ >> #define EXYNOS5420_USB3PHY_BASE DEVICE_NOT_AVAILABLE >> #define EXYNOS5420_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE >> >> + >> #ifndef __ASSEMBLY__ >> #include <asm/io.h> >> /* CPU detection macros */ >> diff --git a/arch/arm/include/asm/arch-exynos/system.h >> b/arch/arm/include/asm/arch-exynos/system.h index 4968d3d..86903c3 >> 100644 --- a/arch/arm/include/asm/arch-exynos/system.h >> +++ b/arch/arm/include/asm/arch-exynos/system.h >> @@ -37,6 +37,93 @@ struct exynos5_sysreg { >> >> #define USB20_PHY_CFG_HOST_LINK_EN (1 << 0) >> >> +#ifdef CONFIG_EXYNOS5420 >> +/* >> + * Data Synchronization Barrier acts as a special kind of memory >> barrier. >> + * No instruction in program order after this instruction executes >> until >> + * this instruction completes. This instruction completes when: >> + * - All explicit memory accesses before this instruction complete. >> + * - All Cache, Branch predictor and TLB maintenance operations >> before >> + * this instruction complete. >> + */ >> +#define dsb() __asm__ __volatile__ ("dsb\n\t" : : ); >> + >> +/* >> + * This instruction causes an event to be signaled to all cores >> + * within a multiprocessor system. If SEV is implemented, >> + * WFE must also be implemented. >> + */ >> +#define sev() __asm__ __volatile__ ("sev\n\t" : : ); >> +/* >> + * If the Event Register is not set, WFE suspends execution until >> + * one of the following events occurs: >> + * - an IRQ interrupt, unless masked by the CPSR I-bit >> + * - an FIQ interrupt, unless masked by the CPSR F-bit >> + * - an Imprecise Data abort, unless masked by the CPSR A-bit >> + * - a Debug Entry request, if Debug is enabled >> + * - an Event signaled by another processor using the SEV >> instruction. >> + * If the Event Register is set, WFE clears it and returns >> immediately. >> + * If WFE is implemented, SEV must also be implemented. >> + */ >> +#define wfe() __asm__ __volatile__ ("wfe\n\t" : : ); >> + >> +/* Move 0xd3 value to CPSR register to enable SVC mode */ >> +#define svc32_mode_en() __asm__ >> __volatile__ \ >> + ("@ I&F disable, Mode: 0x13 - >> SVC\n\t" \ >> + "msr cpsr_c, #0x13|0xC0\n\t" : : ) >> + >> +/* Set program counter with the given value */ >> +#define set_pc(x) __asm__ __volatile__ ("mov pc, %0\n\t" : : >> "r"(x)) + >> +/* Read Main Id register */ >> +#define mrc_midr(x) __asm__ __volatile__ \ >> + ("mrc p15, 0, %0, c0, c0, 0\n\t" : >> "=r"(x) : ) + >> +/* Read Multiprocessor Affinity Register */ >> +#define mrc_mpafr(x) __asm__ __volatile__ \ >> + ("mrc p15, 0, %0, c0, c0, 5\n\t" : >> "=r"(x) : ) + >> +/* Read System Control Register */ >> +#define mrc_sctlr(x) __asm__ __volatile__ \ >> + ("mrc p15, 0, %0, c1, c0, 0\n\t" : >> "=r"(x) : ) + >> +/* Read Auxiliary Control Register */ >> +#define mrc_auxr(x) __asm__ __volatile__ \ >> + ("mrc p15, 0, %0, c1, c0, 1\n\t" : >> "=r"(x) : ) + >> +/* Read L2 Control register */ >> +#define mrc_l2_ctlr(x) __asm__ __volatile__ \ >> + ("mrc p15, 1, %0, c9, c0, 2\n\t" : >> "=r"(x) : ) + >> +/* Read L2 Auxilliary Control register */ >> +#define mrc_l2_aux_ctlr(x) __asm__ __volatile__ \ >> + ("mrc p15, 1, %0, c15, c0, 0\n\t" : >> "=r"(x) : ) + >> +/* Write System Control Register */ >> +#define mcr_sctlr(x) __asm__ __volatile__ \ >> + ("mcr p15, 0, %0, c1, c0, 0\n\t" : : >> "r"(x)) + >> +/* Write Auxiliary Control Register */ >> +#define mcr_auxr(x) __asm__ __volatile__ \ >> + ("mcr p15, 0, %0, c1, c0, 1\n\t" : : >> "r"(x)) + >> +/* Invalidate all instruction caches to PoU */ >> +#define mcr_icache(x) __asm__ __volatile__ \ >> + ("mcr p15, 0, %0, c7, c5, 0\n\t" : : >> "r"(x)) + >> +/* Invalidate unified TLB */ >> +#define mcr_tlb(x) __asm__ __volatile__ \ >> + ("mcr p15, 0, %0, c8, c7, 0\n\t" : : >> "r"(x)) + >> +/* Write L2 Control register */ >> +#define mcr_l2_ctlr(x) __asm__ __volatile__ \ >> + ("mcr p15, 1, %0, c9, c0, 2\n\t" : : >> "r"(x)) + >> +/* Write L2 Auxilliary Control register */ >> +#define mcr_l2_aux_ctlr(x) __asm__ __volatile__ \ >> + ("mcr p15, 1, %0, c15, c0, 0\n\t" : : >> "r"(x)) +#endif >> + >> void set_usbhost_mode(unsigned int mode); >> void set_system_display_ctrl(void); >> int exynos_lcd_early_init(const void *blob); > >-- >Best regards, > >Lukasz Majewski > >Samsung R&D Institute Poland (SRPOL) | Linux Platform Group Regards, Akshay Saraswat _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot