Hi Rajeshwari, On Mon, Jan 7, 2013 at 5:08 AM, Rajeshwari Shinde <rajeshwar...@samsung.com> wrote: > 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.
Should perhaps also mention new feature (controllable memory reset for resume?) > > Signed-off-by: Rajeshwari Shinde <rajeshwar...@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 +++++++++++++++++ Any change we could move all of this to arch/arm/cpu/armv7/exynos...? It really doesn't relate to this board alone, but to the chip. > 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 Could do: COBJS-$(CONFIG_SPL) += lowlevel.o and remove the inner ifdef > +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 Can you use this form instead of ifdef here? COBJS-$(CONFIG_SPL) += 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(); I think serial SPL support is coming later. > + } > + > + 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); What is happening with thsi file? I think there is another patch which changes things here. > > /* > * 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); > +} This is ready for use by SPL serial support, right? > + > +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 > Regards, Simon _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot