diff mbox

[2/4,V2] SMDK5250: Convert lowlevel_init.S to lowlevel_init.c

Message ID 1357564126-13275-3-git-send-email-rajeshwari.s@samsung.com
State New
Headers show

Commit Message

Rajeshwari Shinde Jan. 7, 2013, 1:08 p.m. UTC
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@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

Comments

Simon Glass Jan. 10, 2013, 5:34 p.m. UTC | #1
Hi Rajeshwari,

On Mon, Jan 7, 2013 at 5:08 AM, Rajeshwari Shinde
<rajeshwari.s@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 <rajeshwari.s@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
Minkyu Kang Jan. 11, 2013, 7:54 a.m. UTC | #2
Dear Rajeshwari,

On 07/01/13 22:08, Rajeshwari Shinde 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.
> 
> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@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

Is it SMDK5250 specific?

> +ifdef CONFIG_SPL
> +COBJS  += lowlevel.o

It's a SOBJS.

> +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

please fix this comment.
Maybe this file is not a board specific.

> + *
> + * 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/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/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++;
> +			}
> +		}

indentation error.

> +	*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 (;;)
> +		;
> +}

Thanks,
Minkyu Kang.
Rajeshwari Birje Jan. 11, 2013, 10:10 a.m. UTC | #3
Hi Minkyu Kang,

Thank you for comments.

On Fri, Jan 11, 2013 at 1:24 PM, Minkyu Kang <mk7.kang@samsung.com> wrote:
> Dear Rajeshwari,
>
> On 07/01/13 22:08, Rajeshwari Shinde 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.
>>
>> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@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
>
> Is it SMDK5250 specific?
- Yes, As mentioned in the commit message it is currently been done
only for SMDK5250 and can be also
extended to other SOC in Future.
>
>> +ifdef CONFIG_SPL
>> +COBJS  += lowlevel.o
>
> It's a SOBJS.
- Ok
>
>> +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
>
> please fix this comment.
> Maybe this file is not a board specific.
-Ok
>
>> + *
>> + * 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/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/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++;
>> +                     }
>> +             }
>
> indentation error.
Ok
>
>> +     *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 (;;)
>> +             ;
>> +}
>
> Thanks,
> Minkyu Kang.
>
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
Rajeshwari Birje Jan. 11, 2013, 10:43 a.m. UTC | #4
Hi Simon,

Thank you for comments.

On Thu, Jan 10, 2013 at 11:04 PM, Simon Glass <sjg@chromium.org> wrote:
> Hi Rajeshwari,
>
> On Mon, Jan 7, 2013 at 5:08 AM, Rajeshwari Shinde
> <rajeshwari.s@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?)
-OK
>
>>
>> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@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...?
We do not have a separate directory for exynos5 and exynos4 and if we
add all these files in arch/arm/cpu/armv7/exynos it would break the
compilation for EXYNOS4. Also Later versions of exynos5 have different
memory and timing variants.
>
> 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
- OK
>
>> +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.
So you want to initialise  serial SPL support after mem_ctrl_init and 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);
>
> 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?
Yes it is.
>
>> +
>> +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
Simon Glass Jan. 11, 2013, 2:24 p.m. UTC | #5
Hi Rajeshwari,

On Fri, Jan 11, 2013 at 2:43 AM, Rajeshwari Birje
<rajeshwari.birje@gmail.com> wrote:
> Hi Simon,
>
> Thank you for comments.
>
> On Thu, Jan 10, 2013 at 11:04 PM, Simon Glass <sjg@chromium.org> wrote:
>> Hi Rajeshwari,
>>
>> On Mon, Jan 7, 2013 at 5:08 AM, Rajeshwari Shinde
>> <rajeshwari.s@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?)
> -OK
>>
>>>
>>> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@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...?
> We do not have a separate directory for exynos5 and exynos4 and if we
> add all these files in arch/arm/cpu/armv7/exynos it would break the
> compilation for EXYNOS4. Also Later versions of exynos5 have different
> memory and timing variants.

OK, but is this something you intend to fix, perhaps in a future
series? It seems like you need separate directories sooner rather than
later.I don't think this is board-specific code, but chip-specific.

>>
>> 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
> - OK
>>
>>> +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.
> So you want to initialise  serial SPL support after mem_ctrl_init and tzpc_init?

No, I meant earlier, but please ignore my comment, i was confused. At
present we can't move it earlier because the clocks need to be started
up, and that happens in a big monolithic operation.

What you have here is fine.

>>
>>> +       }
>>> +
>>> +       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?
> Yes it is.
>>
>>> +
>>> +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
>
>
>
> --
> Regards,
> Rajeshwari Shinde
Rajeshwari Birje Jan. 14, 2013, 6:32 a.m. UTC | #6
Hi Minkyu Kang,

>OK, but is this something you intend to fix, perhaps in a future
> series? It seems like you need separate directories sooner rather than
> later.I don't think this is board-specific code, but chip-specific.

Please do let me know your opinion on the above comment.

Regards,
Rajeshwari Shinde.

On Fri, Jan 11, 2013 at 7:54 PM, Simon Glass <sjg@chromium.org> wrote:
> Hi Rajeshwari,
>
> On Fri, Jan 11, 2013 at 2:43 AM, Rajeshwari Birje
> <rajeshwari.birje@gmail.com> wrote:
>> Hi Simon,
>>
>> Thank you for comments.
>>
>> On Thu, Jan 10, 2013 at 11:04 PM, Simon Glass <sjg@chromium.org> wrote:
>>> Hi Rajeshwari,
>>>
>>> On Mon, Jan 7, 2013 at 5:08 AM, Rajeshwari Shinde
>>> <rajeshwari.s@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?)
>> -OK
>>>
>>>>
>>>> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@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...?
>> We do not have a separate directory for exynos5 and exynos4 and if we
>> add all these files in arch/arm/cpu/armv7/exynos it would break the
>> compilation for EXYNOS4. Also Later versions of exynos5 have different
>> memory and timing variants.
>
> OK, but is this something you intend to fix, perhaps in a future
> series? It seems like you need separate directories sooner rather than
> later.I don't think this is board-specific code, but chip-specific.
>
>>>
>>> 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
>> - OK
>>>
>>>> +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.
>> So you want to initialise  serial SPL support after mem_ctrl_init and tzpc_init?
>
> No, I meant earlier, but please ignore my comment, i was confused. At
> present we can't move it earlier because the clocks need to be started
> up, and that happens in a big monolithic operation.
>
> What you have here is fine.
>
>>>
>>>> +       }
>>>> +
>>>> +       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?
>> Yes it is.
>>>
>>>> +
>>>> +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
>>
>>
>>
>> --
>> Regards,
>> Rajeshwari Shinde
Minkyu Kang Jan. 14, 2013, 7:39 a.m. UTC | #7
On 11/01/13 19:10, Rajeshwari Birje wrote:
> Hi Minkyu Kang,
> 
> Thank you for comments.
> 
> On Fri, Jan 11, 2013 at 1:24 PM, Minkyu Kang <mk7.kang@samsung.com> wrote:
>> Dear Rajeshwari,
>>
>> On 07/01/13 22:08, Rajeshwari Shinde 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.
>>>
>>> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@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
>>
>> Is it SMDK5250 specific?
> - Yes, As mentioned in the commit message it is currently been done
> only for SMDK5250 and can be also
> extended to other SOC in Future.
>>

But I think, we don't have to get dependency with the board.

Thanks.
Minkyu Kang.
Minkyu Kang Jan. 14, 2013, 7:44 a.m. UTC | #8
On 14/01/13 15:32, Rajeshwari Birje wrote:
> Hi Minkyu Kang,
> 
>> OK, but is this something you intend to fix, perhaps in a future
>> series? It seems like you need separate directories sooner rather than
>> later.I don't think this is board-specific code, but chip-specific.
> 
> Please do let me know your opinion on the above comment.
> 
> Regards,
> Rajeshwari Shinde.
> 
> On Fri, Jan 11, 2013 at 7:54 PM, Simon Glass <sjg@chromium.org> wrote:
>> Hi Rajeshwari,
>>
>> On Fri, Jan 11, 2013 at 2:43 AM, Rajeshwari Birje
>> <rajeshwari.birje@gmail.com> wrote:
>>> Hi Simon,
>>>
>>> Thank you for comments.
>>>
>>> On Thu, Jan 10, 2013 at 11:04 PM, Simon Glass <sjg@chromium.org> wrote:
>>>> Hi Rajeshwari,
>>>>
>>>> On Mon, Jan 7, 2013 at 5:08 AM, Rajeshwari Shinde
>>>> <rajeshwari.s@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?)
>>> -OK
>>>>
>>>>>
>>>>> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@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...?
>>> We do not have a separate directory for exynos5 and exynos4 and if we
>>> add all these files in arch/arm/cpu/armv7/exynos it would break the
>>> compilation for EXYNOS4. Also Later versions of exynos5 have different
>>> memory and timing variants.
>>
>> OK, but is this something you intend to fix, perhaps in a future
>> series? It seems like you need separate directories sooner rather than
>> later.I don't think this is board-specific code, but chip-specific.
>>

We don't have to separate directory for exynos5 and exynos4.
We can check this by cpu_is_exynos5 or cpu_is_exynos4.
I think each SoCs have different memory and timing but the logic can be same.
If so we can move all of changes to SoC directory.

--
Thanks,
Minkyu Kang.
diff mbox

Patch

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