[U-Boot] [PATCH 2/4 V2] SMDK5250: Convert lowlevel_init.S to lowlevel_init.c

Rajeshwari Shinde rajeshwari.s at samsung.com
Mon Jan 7 14:08:44 CET 2013


This patch converts lowlevel_init.S to lowlevel_init_c.c for
SMDK5250.
Lowlevel.S as of now added only for SMDK5250 and same can be 
extended to other SOC in future.

Signed-off-by: Rajeshwari Shinde <rajeshwari.s at samsung.com>
---
Changes in V2:
	- Renamed lowlevel_init.S to lowlevel.S and moved to 
	arch/arm/cpu/armv7/exynos/
	- Moved power mode defines to power.h
	- Added early serial support.
	- Renamed mem_reset to reset.	
 arch/arm/cpu/armv7/exynos/Makefile       |    6 ++
 arch/arm/cpu/armv7/exynos/lowlevel.S     |   35 ++++++++
 arch/arm/include/asm/arch-exynos/power.h |    8 ++
 board/samsung/smdk5250/Makefile          |    2 +-
 board/samsung/smdk5250/dmc_common.c      |    4 +-
 board/samsung/smdk5250/dmc_init_ddr3.c   |    6 +-
 board/samsung/smdk5250/lowlevel_init.S   |   96 --------------------
 board/samsung/smdk5250/lowlevel_init.c   |   81 +++++++++++++++++
 board/samsung/smdk5250/setup.h           |   19 ++++-
 board/samsung/smdk5250/spl_boot.c        |  140 +++++++++++++++++++++++++++--
 spl/Makefile                             |    4 +
 11 files changed, 288 insertions(+), 113 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/exynos/lowlevel.S
 delete mode 100644 board/samsung/smdk5250/lowlevel_init.S
 create mode 100644 board/samsung/smdk5250/lowlevel_init.c

diff --git a/arch/arm/cpu/armv7/exynos/Makefile b/arch/arm/cpu/armv7/exynos/Makefile
index 9119961..2aa2722 100644
--- a/arch/arm/cpu/armv7/exynos/Makefile
+++ b/arch/arm/cpu/armv7/exynos/Makefile
@@ -22,6 +22,12 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(SOC).o
 
+ifdef CONFIG_SMDK5250
+ifdef CONFIG_SPL
+COBJS  += lowlevel.o
+endif
+endif
+
 COBJS	+= clock.o power.o soc.o system.o pinmux.o
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
diff --git a/arch/arm/cpu/armv7/exynos/lowlevel.S b/arch/arm/cpu/armv7/exynos/lowlevel.S
new file mode 100644
index 0000000..7307959
--- /dev/null
+++ b/arch/arm/cpu/armv7/exynos/lowlevel.S
@@ -0,0 +1,35 @@
+/*
+ * Lowlevel setup for SMDK5250 board based on S5PC520
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <asm/arch/cpu.h>
+
+	.globl lowlevel_init
+lowlevel_init:
+	/*
+	 * Set the stack pointer, although it will be overwritten by the caller
+	 * It seems we will not boot if this function is empty.
+	 */
+	ldr	sp, =CONFIG_IRAM_STACK
+	mov	pc, lr
diff --git a/arch/arm/include/asm/arch-exynos/power.h b/arch/arm/include/asm/arch-exynos/power.h
index f6d0278..d6fd29e 100644
--- a/arch/arm/include/asm/arch-exynos/power.h
+++ b/arch/arm/include/asm/arch-exynos/power.h
@@ -874,4 +874,12 @@ void power_ps_hold_setup(void);
 
 /* Read the resume function and call it */
 void power_exit_wakeup(void);
+
+
+/* Power Down Modes
+ * User defined values in inform1 register
+ */
+#define EXYNOS_CHECK_SLEEP	0x00000BAD
+#define EXYNOS_CHECK_DIDLE	0xBAD00000
+#define EXYNOS_CHECK_LPA	0xABAD0000
 #endif
diff --git a/board/samsung/smdk5250/Makefile b/board/samsung/smdk5250/Makefile
index 47c6a5a..7eaef09 100644
--- a/board/samsung/smdk5250/Makefile
+++ b/board/samsung/smdk5250/Makefile
@@ -24,7 +24,6 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).o
 
-SOBJS	:= lowlevel_init.o
 
 COBJS	:= clock_init.o
 COBJS	+= dmc_common.o dmc_init_ddr3.o
@@ -37,6 +36,7 @@ endif
 
 ifdef CONFIG_SPL_BUILD
 COBJS	+= spl_boot.o
+COBJS	+= lowlevel_init.o
 endif
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
diff --git a/board/samsung/smdk5250/dmc_common.c b/board/samsung/smdk5250/dmc_common.c
index 109602a..f637bf9 100644
--- a/board/samsung/smdk5250/dmc_common.c
+++ b/board/samsung/smdk5250/dmc_common.c
@@ -175,7 +175,7 @@ void dmc_config_memory(struct mem_timings *mem, struct exynos5_dmc *dmc)
 	writel(DMC_MEMBASECONFIG1_VAL, &dmc->membaseconfig1);
 }
 
-void mem_ctrl_init()
+void mem_ctrl_init(int reset)
 {
 	struct spl_machine_param *param = spl_get_machine_params();
 	struct mem_timings *mem;
@@ -185,7 +185,7 @@ void mem_ctrl_init()
 
 	/* If there are any other memory variant, add their init call below */
 	if (param->mem_type == DDR_MODE_DDR3) {
-		ret = ddr3_mem_ctrl_init(mem, param->mem_iv_size);
+		ret = ddr3_mem_ctrl_init(mem, param->mem_iv_size, reset);
 		if (ret) {
 			/* will hang if failed to init memory control */
 			while (1)
diff --git a/board/samsung/smdk5250/dmc_init_ddr3.c b/board/samsung/smdk5250/dmc_init_ddr3.c
index e050790..a5a70df 100644
--- a/board/samsung/smdk5250/dmc_init_ddr3.c
+++ b/board/samsung/smdk5250/dmc_init_ddr3.c
@@ -40,7 +40,8 @@ static void reset_phy_ctrl(void)
 	writel(DDR3PHY_CTRL_PHY_RESET, &clk->lpddr3phy_ctrl);
 }
 
-int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size)
+int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size,
+			int reset)
 {
 	unsigned int val;
 	struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl;
@@ -51,7 +52,8 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size)
 	phy1_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY1_BASE;
 	dmc = (struct exynos5_dmc *)EXYNOS5_DMC_CTRL_BASE;
 
-	reset_phy_ctrl();
+	if (reset)
+		reset_phy_ctrl();
 
 	/* Set Impedance Output Driver */
 	val = (mem->impedance << CA_CK_DRVR_DS_OFFSET) |
diff --git a/board/samsung/smdk5250/lowlevel_init.S b/board/samsung/smdk5250/lowlevel_init.S
deleted file mode 100644
index bc6cb6f..0000000
--- a/board/samsung/smdk5250/lowlevel_init.S
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Lowlevel setup for SMDK5250 board based on S5PC520
- *
- * Copyright (C) 2012 Samsung Electronics
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#include <config.h>
-#include <version.h>
-#include <asm/arch/cpu.h>
-
-_TEXT_BASE:
-	.word	CONFIG_SYS_TEXT_BASE
-
-	.globl lowlevel_init
-lowlevel_init:
-
-	/* use iRAM stack in bl2 */
-	ldr	sp, =CONFIG_IRAM_STACK
-	stmdb	r13!, {ip,lr}
-
-	/* check reset status */
-	ldr	r0, =(EXYNOS5_POWER_BASE + INFORM1_OFFSET)
-	ldr	r1, [r0]
-
-	/* AFTR wakeup reset */
-	ldr	r2, =S5P_CHECK_DIDLE
-	cmp	r1, r2
-	beq	exit_wakeup
-
-	/* LPA wakeup reset */
-	ldr	r2, =S5P_CHECK_LPA
-	cmp	r1, r2
-	beq	exit_wakeup
-
-	/* Sleep wakeup reset */
-	ldr	r2, =S5P_CHECK_SLEEP
-	cmp	r1, r2
-	beq	wakeup_reset
-
-	/*
-	 * If U-boot is already running in RAM, no need to relocate U-Boot.
-	 * Memory controller must be configured before relocating U-Boot
-	 * in ram.
-	 */
-	ldr	r0, =0x0ffffff		/* r0 <- Mask Bits*/
-	bic	r1, pc, r0		/* pc <- current addr of code */
-					/* r1 <- unmasked bits of pc */
-	ldr	r2, _TEXT_BASE		/* r2 <- original base addr in ram */
-	bic	r2, r2, r0		/* r2 <- unmasked bits of r2*/
-	cmp	r1, r2			/* compare r1, r2 */
-	beq	1f			/* r0 == r1 then skip sdram init */
-
-	/* init system clock */
-	bl	system_clock_init
-
-	/* Memory initialize */
-	bl	mem_ctrl_init
-
-1:
-	bl	tzpc_init
-	ldmia	r13!, {ip,pc}
-
-wakeup_reset:
-	bl	system_clock_init
-	bl	mem_ctrl_init
-	bl	tzpc_init
-
-exit_wakeup:
-	/* Load return address and jump to kernel */
-	ldr	r0, =(EXYNOS5_POWER_BASE + INFORM0_OFFSET)
-
-	/* r1 = physical address of exynos5_cpu_resume function*/
-	ldr	r1, [r0]
-
-	/* Jump to kernel */
-	mov	pc, r1
-	nop
-	nop
diff --git a/board/samsung/smdk5250/lowlevel_init.c b/board/samsung/smdk5250/lowlevel_init.c
new file mode 100644
index 0000000..22bdd2b
--- /dev/null
+++ b/board/samsung/smdk5250/lowlevel_init.c
@@ -0,0 +1,81 @@
+/*
+ * Lowlevel setup for SMDK5250 board based on S5PC520
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Copyright (c) 2012 The Chromium OS Authors.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/dmc.h>
+#include <asm/arch/power.h>
+#include <asm/arch/tzpc.h>
+#include <asm/arch/periph.h>
+#include <asm/arch/pinmux.h>
+#include "setup.h"
+
+/* These are the things we can do during low-level init */
+enum {
+	DO_WAKEUP	= 1 << 0,
+	DO_CLOCKS	= 1 << 1,
+	DO_MEM_RESET	= 1 << 2,
+	DO_UART		= 1 << 3,
+};
+
+int do_lowlevel_init(void)
+{
+	uint32_t reset_status;
+	int actions = 0;
+
+	arch_cpu_init();
+
+	reset_status = power_read_reset_status();
+
+	switch (reset_status) {
+	case EXYNOS_CHECK_SLEEP:
+		actions = DO_CLOCKS | DO_WAKEUP;
+		break;
+	case EXYNOS_CHECK_DIDLE:
+	case EXYNOS_CHECK_LPA:
+		actions = DO_WAKEUP;
+		break;
+	default:
+		/* This is a normal boot (not a wake from sleep) */
+		actions = DO_CLOCKS | DO_MEM_RESET | DO_UART;
+	}
+
+	if (actions & DO_CLOCKS)
+		system_clock_init();
+
+	if (actions & DO_UART) {
+		exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
+		serial_init();
+		timer_init();
+	}
+
+	if (actions & DO_CLOCKS) {
+		mem_ctrl_init(actions & DO_MEM_RESET);
+		tzpc_init();
+	}
+
+	return actions & DO_WAKEUP;
+}
diff --git a/board/samsung/smdk5250/setup.h b/board/samsung/smdk5250/setup.h
index a159601..f1d9f79 100644
--- a/board/samsung/smdk5250/setup.h
+++ b/board/samsung/smdk5250/setup.h
@@ -537,9 +537,11 @@ enum {
  *			which the DMC uses to decide how to split a memory
  *			chunk into smaller chunks to support concurrent
  *			accesses; may vary across boards.
+ * @param reset		Reset DDR PHY during initialization.
  * @return 0 if ok, SETUP_ERR_... if there is a problem
  */
-int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size);
+int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size,
+			int reset);
 
 /*
  * Configure ZQ I/O interface
@@ -587,8 +589,21 @@ void dmc_config_memory(struct mem_timings *mem, struct exynos5_dmc *dmc);
  */
 void update_reset_dll(struct exynos5_dmc *, enum ddr_mode);
 
+/*
+ * Memory initialization
+ *
+ * @param reset     Reset PHY during initialization.
+ */
+void mem_ctrl_init(int reset);
+
 void sdelay(unsigned long);
-void mem_ctrl_init(void);
 void system_clock_init(void);
 void tzpc_init(void);
+
+/**
+ * Init subsystems according to the reset status
+ *
+ * @return 0 for a normal boot, non-zero for a resume
+ */
+int do_lowlevel_init(void);
 #endif
diff --git a/board/samsung/smdk5250/spl_boot.c b/board/samsung/smdk5250/spl_boot.c
index d8f3c1e..a1c8d3d 100644
--- a/board/samsung/smdk5250/spl_boot.c
+++ b/board/samsung/smdk5250/spl_boot.c
@@ -20,18 +20,16 @@
  * MA 02111-1307 USA
  */
 
-#include<common.h>
-#include<config.h>
+#include <common.h>
+#include <config.h>
+#include <asm/arch/spl.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/power.h>
+#include "setup.h"
 
-enum boot_mode {
-	BOOT_MODE_MMC = 4,
-	BOOT_MODE_SERIAL = 20,
-	/* Boot based on Operating Mode pin settings */
-	BOOT_MODE_OM = 32,
-	BOOT_MODE_USB,	/* Boot using USB download */
-};
+DECLARE_GLOBAL_DATA_PTR;
 
-	typedef u32 (*spi_copy_func_t)(u32 offset, u32 nblock, u32 dst);
+typedef u32 (*spi_copy_func_t)(u32 offset, u32 nblock, u32 dst);
 
 /*
 * Copy U-boot from mmc to RAM:
@@ -62,15 +60,49 @@ void copy_uboot_to_ram(void)
 	}
 }
 
+void memzero(void *s, size_t n)
+{
+	char *ptr = s;
+	size_t i;
+
+	for (i = 0; i < n; i++)
+		*ptr++ = '\0';
+}
+
+/**
+ * Set up the U-Boot global_data pointer
+ *
+ * This sets the address of the global data, and sets up basic values.
+ *
+ * @param gdp   Value to give to gd
+ */
+static void setup_global_data(gd_t *gdp)
+{
+	gd = gdp;
+	memzero((void *)gd, sizeof(gd_t));
+	gd->flags |= GD_FLG_RELOC;
+	gd->baudrate = CONFIG_BAUDRATE;
+	gd->have_console = 1;
+}
+
 void board_init_f(unsigned long bootflag)
 {
+	__attribute__((aligned(8))) gd_t local_gd;
 	__attribute__((noreturn)) void (*uboot)(void);
+
+	setup_global_data(&local_gd);
+
+	if (do_lowlevel_init())
+		power_exit_wakeup();
+
 	copy_uboot_to_ram();
 
 	/* Jump to U-Boot image */
 	uboot = (void *)CONFIG_SYS_TEXT_BASE;
 	(*uboot)();
+
 	/* Never returns Here */
+	panic("%s: u-boot jump failed", __func__);
 }
 
 /* Place Holders */
@@ -83,3 +115,91 @@ void board_init_r(gd_t *id, ulong dest_addr)
 }
 
 void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) {}
+
+/*
+ * The following functions are required when linking console library to SPL.
+ *
+ * Enabling UART in SPL u-boot requires console library. But some
+ * functions we needed in the console library depends on a bunch
+ * of library in libgeneric, like lib/ctype.o, lib/div64.o, lib/string.o,
+ * and lib/vsprintf.o. Adding them makes the SPL u-boot too large and not
+ * fit into the expected size.
+ *
+ * So we mock these functions in SPL, i.e. vsprintf(), panic(), etc.,
+ * in order to cut its dependency.
+ */
+static int _vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+	char *str = buf, *s;
+	char *end = str + size - 1;
+	ulong u;
+
+	if (size == 0)
+		return -1;
+
+	/*
+	 * We won't implement all full functions of vsprintf().
+	 * We only implement %s and %u, and ignore others and directly use
+	 * the original format string as its result.
+	 */
+
+	while (*fmt && (str < end)) {
+		if (*fmt != '%') {
+			*str++ = *fmt++;
+			continue;
+		}
+		fmt++;
+		switch (*fmt) {
+		case '%':
+			*str++ = *fmt++;
+			break;
+		case 's':
+			fmt++;
+			s = va_arg(args, char *);
+			while (*s && (str < end))
+				*str++ = *s++;
+			break;
+		case 'u':
+			fmt++;
+			u = va_arg(args, ulong);
+			s = simple_itoa(u);
+				while (*s && (str < end))
+					*str++ = *s++;
+				break;
+		default:
+			/* Print the original string for unsupported formats */
+			*str++ = '%';
+			if  (str < end)
+				*str++ = *fmt++;
+			}
+		}
+	*str = '\0';
+	return str - buf;
+}
+
+/* Implement vsprintf in case someone doesn't have CONFIG_SYS_VSNPRINTF */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+	return _vscnprintf(buf, CONFIG_SYS_PBSIZE, fmt, args);
+}
+
+char *simple_itoa(ulong i)
+{
+	/* 21 digits plus null terminator, good for 64-bit or smaller ints */
+	static char local[22] __attribute__((section(".data")));
+	char *p = &local[21];
+
+	*p-- = '\0';
+	do {
+		*p-- = '0' + i % 10;
+		i /= 10;
+	} while (i > 0);
+	return p + 1;
+}
+
+void hang(void)
+{
+	puts("### ERROR ### Please RESET the board ###\n");
+	for (;;)
+		;
+}
diff --git a/spl/Makefile b/spl/Makefile
index 6dbb105..3aab466 100644
--- a/spl/Makefile
+++ b/spl/Makefile
@@ -86,6 +86,10 @@ ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)
 LIBS-y += $(CPUDIR)/omap-common/libomap-common.o
 endif
 
+ifneq ($(CONFIG_EXYNOS4)$(CONFIG_EXYNOS5),)
+LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o
+endif
+
 ifeq ($(SOC),tegra20)
 LIBS-y += arch/$(ARCH)/cpu/$(SOC)-common/lib$(SOC)-common.o
 LIBS-y += arch/$(ARCH)/cpu/tegra-common/libcputegra-common.o
-- 
1.7.4.4



More information about the U-Boot mailing list