All of lore.kernel.org
 help / color / mirror / Atom feed
From: Akshay Saraswat <akshay.s@samsung.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2 02/11] Exynos542x: CPU: Power down all secondary cores
Date: Tue, 03 Feb 2015 13:48:51 +0530	[thread overview]
Message-ID: <1422951540-11962-3-git-send-email-akshay.s@samsung.com> (raw)
In-Reply-To: <1422951540-11962-1-git-send-email-akshay.s@samsung.com>

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.
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.kim@samsung.com>
Signed-off-by: Akshay Saraswat <akshay.s@samsung.com>
---
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);
-- 
1.9.1

  parent reply	other threads:[~2015-02-03  8:18 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-02-03  8:18 [U-Boot] [PATCH v2 00/11] Add support for booting multiple cores Akshay Saraswat
2015-02-03  8:18 ` [U-Boot] [PATCH v2 01/11] Exynos542x: Config: Add various configs Akshay Saraswat
2015-02-03  8:18 ` Akshay Saraswat [this message]
2015-02-04 15:00   ` [U-Boot] [PATCH v2 02/11] Exynos542x: CPU: Power down all secondary cores Simon Glass
2015-02-03  8:18 ` [U-Boot] [PATCH v2 03/11] Exynos542x: Add workaround for ARM errata 798870 Akshay Saraswat
2015-02-03  8:18 ` [U-Boot] [PATCH v2 04/11] Exynos542x: Add workaround for ARM errata 799270 Akshay Saraswat
2015-02-03  8:18 ` [U-Boot] [PATCH v2 05/11] Exynos542x: Add workaround for exynos iROM errata Akshay Saraswat
2015-02-03  8:18 ` [U-Boot] [PATCH v2 06/11] Exynos542x: Change ambiguous function name set_l2cache Akshay Saraswat
2015-02-03  8:18 ` [U-Boot] [PATCH v2 07/11] Exynos542x: cache: Disable clean/evict push to external Akshay Saraswat
2015-02-17 11:50   ` Minkyu Kang
2015-02-03  8:18 ` [U-Boot] [PATCH v2 08/11] Exynos542x: add L2 control register configuration Akshay Saraswat
2015-02-17 11:50   ` Minkyu Kang
2015-02-03  8:18 ` [U-Boot] [PATCH v2 09/11] Exynos542x: Fix secondary core booting for thumb Akshay Saraswat
2015-02-03  8:18 ` [U-Boot] [PATCH v2 10/11] Exynos542x: Make A7s boot with thumb-mode U-Boot on warm reset Akshay Saraswat
2015-02-03  8:19 ` [U-Boot] [PATCH v2 11/11] Exynos: Fix L2 cache timings on Exynos5420 and Exynos5800 Akshay Saraswat
2015-02-04 15:01   ` Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1422951540-11962-3-git-send-email-akshay.s@samsung.com \
    --to=akshay.s@samsung.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.