diff mbox

[U-Boot] RFC: am35xx: Rearrange SPL on am35xx

Message ID 1418948481-31124-1-git-send-email-sjg@chromium.org
State RFC
Delegated to: Tom Rini
Headers show

Commit Message

Simon Glass Dec. 19, 2014, 12:21 a.m. UTC
This is an attempt to tidy up the early SPL code in an attempt to pave
the way for driver model in SPL:

- Avoid setting up SDRAM before board_init_f()
- Avoid touching global_data before board_init_f()
- Allow board_init_f() to set up a new stack (seems that the SRAM stack
is not large enough on these boards)

This needs more work but it does boot on Beaglebone Black.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/cpu/armv7/am33xx/board.c  | 60 ++++++++++++++++++++++++++------------
 arch/arm/cpu/armv7/lowlevel_init.S |  4 ---
 arch/arm/include/asm/spl.h         |  3 ++
 arch/arm/lib/crt0.S                |  9 ++++++
 include/configs/ti_armv7_common.h  |  5 ++--
 5 files changed, 56 insertions(+), 25 deletions(-)

Comments

Tom Rini Dec. 19, 2014, 2:40 p.m. UTC | #1
On Thu, Dec 18, 2014 at 05:21:21PM -0700, Simon Glass wrote:

> This is an attempt to tidy up the early SPL code in an attempt to pave
> the way for driver model in SPL:
> 
> - Avoid setting up SDRAM before board_init_f()
> - Avoid touching global_data before board_init_f()
> - Allow board_init_f() to set up a new stack (seems that the SRAM stack
> is not large enough on these boards)
> 
> This needs more work but it does boot on Beaglebone Black.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  arch/arm/cpu/armv7/am33xx/board.c  | 60 ++++++++++++++++++++++++++------------
>  arch/arm/cpu/armv7/lowlevel_init.S |  4 ---
>  arch/arm/include/asm/spl.h         |  3 ++
>  arch/arm/lib/crt0.S                |  9 ++++++
>  include/configs/ti_armv7_common.h  |  5 ++--
>  5 files changed, 56 insertions(+), 25 deletions(-)

This takes things in the wrong direction I think.  Since omap3/4/5 have
the same problem we're going to have to duplicate a bunch of this code.
But we can do omap_save_boot_params a bit later I'm pretty sure we can
shove it into spl_board_init() in
arch/arm/cpu/armv7/omap-common/boot-common.c and I'm going to do my best
to do that today and test it on at least a few boards.
Simon Glass Dec. 19, 2014, 3:32 p.m. UTC | #2
Hi Tom, Albert,

On 19 December 2014 at 07:40, Tom Rini <trini@ti.com> wrote:
> On Thu, Dec 18, 2014 at 05:21:21PM -0700, Simon Glass wrote:
>
>> This is an attempt to tidy up the early SPL code in an attempt to pave
>> the way for driver model in SPL:
>>
>> - Avoid setting up SDRAM before board_init_f()
>> - Avoid touching global_data before board_init_f()
>> - Allow board_init_f() to set up a new stack (seems that the SRAM stack
>> is not large enough on these boards)
>>
>> This needs more work but it does boot on Beaglebone Black.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>
>>  arch/arm/cpu/armv7/am33xx/board.c  | 60 ++++++++++++++++++++++++++------------
>>  arch/arm/cpu/armv7/lowlevel_init.S |  4 ---
>>  arch/arm/include/asm/spl.h         |  3 ++
>>  arch/arm/lib/crt0.S                |  9 ++++++
>>  include/configs/ti_armv7_common.h  |  5 ++--
>>  5 files changed, 56 insertions(+), 25 deletions(-)
>
> This takes things in the wrong direction I think.  Since omap3/4/5 have
> the same problem we're going to have to duplicate a bunch of this code.
> But we can do omap_save_boot_params a bit later I'm pretty sure we can
> shove it into spl_board_init() in
> arch/arm/cpu/armv7/omap-common/boot-common.c and I'm going to do my best
> to do that today and test it on at least a few boards.

I don't have a lot of background on SPL stuff as I only know one
implementation in detail. So these comments may be a bit off.

There seem to be two drivers causing this oddness:

1. The need to save boot params before global_data is available. I
wonder if it is possible to avoid overwriting the boot params, and
save them later, in board_init_f()? If not, then I don't think the
global_data structure should be used. A static local variable in the
data section, with just a few fields in it, could be used instead.
That avoids the temptation to thing that we are creating a global_data
structure before crt0.S does it officially. If the data had just been
stored into the data section, without messing with global_data, then I
don't think we would have this problem.

2. Need for more stack that can be fitted into SRAM. I think the only
sensible option here is to change the stack after board_init_f(). As
Albert says this should be done in crt0.S (in fact that's where I put
my code). Forcing the dram init to before board_init_f() in SPL seems
broken to me.

I think we should try to have the same flow as U-Boot proper:

start.S
lowlevel_init (no stack, no global_data, no dram) - can only use
'data' section to write stuff
crt0.S (sets up stack and global_data, no dram)
board_init_f (sets up dram)
relocate stack if required (but not code)
board_init_r (running with full stack in dram)

Albert, re your comment do you mean that board_init_f() should not
call spl_call_board_init_r() but it should return to crt0.S, which
then calls board_init_r()? I'm not sure as this isn't currently how
things work in U-Boot proper.

Anyway, anything you can do to remove the g_data thing would be great.
Also one more thing - are we trying to unify the init sequence in SPL
and U-Boot?

Regards,
Simon
Tom Rini Dec. 21, 2014, 12:30 p.m. UTC | #3
On Fri, Dec 19, 2014 at 08:32:35AM -0700, Simon Glass wrote:
> Hi Tom, Albert,
> 
> On 19 December 2014 at 07:40, Tom Rini <trini@ti.com> wrote:
> > On Thu, Dec 18, 2014 at 05:21:21PM -0700, Simon Glass wrote:
> >
> >> This is an attempt to tidy up the early SPL code in an attempt to pave
> >> the way for driver model in SPL:
> >>
> >> - Avoid setting up SDRAM before board_init_f()
> >> - Avoid touching global_data before board_init_f()
> >> - Allow board_init_f() to set up a new stack (seems that the SRAM stack
> >> is not large enough on these boards)
> >>
> >> This needs more work but it does boot on Beaglebone Black.
> >>
> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> >> ---
> >>
> >>  arch/arm/cpu/armv7/am33xx/board.c  | 60 ++++++++++++++++++++++++++------------
> >>  arch/arm/cpu/armv7/lowlevel_init.S |  4 ---
> >>  arch/arm/include/asm/spl.h         |  3 ++
> >>  arch/arm/lib/crt0.S                |  9 ++++++
> >>  include/configs/ti_armv7_common.h  |  5 ++--
> >>  5 files changed, 56 insertions(+), 25 deletions(-)
> >
> > This takes things in the wrong direction I think.  Since omap3/4/5 have
> > the same problem we're going to have to duplicate a bunch of this code.
> > But we can do omap_save_boot_params a bit later I'm pretty sure we can
> > shove it into spl_board_init() in
> > arch/arm/cpu/armv7/omap-common/boot-common.c and I'm going to do my best
> > to do that today and test it on at least a few boards.
> 
> I don't have a lot of background on SPL stuff as I only know one
> implementation in detail. So these comments may be a bit off.
> 
> There seem to be two drivers causing this oddness:
> 
> 1. The need to save boot params before global_data is available. I
> wonder if it is possible to avoid overwriting the boot params, and
> save them later, in board_init_f()? If not, then I don't think the
> global_data structure should be used. A static local variable in the
> data section, with just a few fields in it, could be used instead.
> That avoids the temptation to thing that we are creating a global_data
> structure before crt0.S does it officially. If the data had just been
> stored into the data section, without messing with global_data, then I
> don't think we would have this problem.

This is actually covered today, really.  We do "save_boot_params" first
thing and that function must save a magic register value from ROM (or
whatever) to a "stable" magic location in memory.

> 2. Need for more stack that can be fitted into SRAM. I think the only
> sensible option here is to change the stack after board_init_f(). As
> Albert says this should be done in crt0.S (in fact that's where I put
> my code). Forcing the dram init to before board_init_f() in SPL seems
> broken to me.

This is also covered.  The flow is cpu_init_crit -> lowlevel_init (set
stack to CONFIG_SYS_INIT_SP_ADDR) -> s_init (init DDR) -> _main (set
stack to CONFIG_SPL_STACK, can be in DDR).

> I think we should try to have the same flow as U-Boot proper:
> 
> start.S
> lowlevel_init (no stack, no global_data, no dram) - can only use
> 'data' section to write stuff
> crt0.S (sets up stack and global_data, no dram)
> board_init_f (sets up dram)
> relocate stack if required (but not code)
> board_init_r (running with full stack in dram)

I suppose since old school PowerPC needed i2c to read spd eeproms it's
possible this ordering could work still today where there's a good bit
of stuff neeed in order to bring DDR on some ARM platforms.
Simon Glass Dec. 21, 2014, 6:53 p.m. UTC | #4
Hi Tom,

On 21 December 2014 at 05:30, Tom Rini <trini@ti.com> wrote:
> On Fri, Dec 19, 2014 at 08:32:35AM -0700, Simon Glass wrote:
>> Hi Tom, Albert,
>>
>> On 19 December 2014 at 07:40, Tom Rini <trini@ti.com> wrote:
>> > On Thu, Dec 18, 2014 at 05:21:21PM -0700, Simon Glass wrote:
>> >
>> >> This is an attempt to tidy up the early SPL code in an attempt to pave
>> >> the way for driver model in SPL:
>> >>
>> >> - Avoid setting up SDRAM before board_init_f()
>> >> - Avoid touching global_data before board_init_f()
>> >> - Allow board_init_f() to set up a new stack (seems that the SRAM stack
>> >> is not large enough on these boards)
>> >>
>> >> This needs more work but it does boot on Beaglebone Black.
>> >>
>> >> Signed-off-by: Simon Glass <sjg@chromium.org>
>> >> ---
>> >>
>> >>  arch/arm/cpu/armv7/am33xx/board.c  | 60 ++++++++++++++++++++++++++------------
>> >>  arch/arm/cpu/armv7/lowlevel_init.S |  4 ---
>> >>  arch/arm/include/asm/spl.h         |  3 ++
>> >>  arch/arm/lib/crt0.S                |  9 ++++++
>> >>  include/configs/ti_armv7_common.h  |  5 ++--
>> >>  5 files changed, 56 insertions(+), 25 deletions(-)
>> >
>> > This takes things in the wrong direction I think.  Since omap3/4/5 have
>> > the same problem we're going to have to duplicate a bunch of this code.
>> > But we can do omap_save_boot_params a bit later I'm pretty sure we can
>> > shove it into spl_board_init() in
>> > arch/arm/cpu/armv7/omap-common/boot-common.c and I'm going to do my best
>> > to do that today and test it on at least a few boards.
>>
>> I don't have a lot of background on SPL stuff as I only know one
>> implementation in detail. So these comments may be a bit off.
>>
>> There seem to be two drivers causing this oddness:
>>
>> 1. The need to save boot params before global_data is available. I
>> wonder if it is possible to avoid overwriting the boot params, and
>> save them later, in board_init_f()? If not, then I don't think the
>> global_data structure should be used. A static local variable in the
>> data section, with just a few fields in it, could be used instead.
>> That avoids the temptation to thing that we are creating a global_data
>> structure before crt0.S does it officially. If the data had just been
>> stored into the data section, without messing with global_data, then I
>> don't think we would have this problem.
>
> This is actually covered today, really.  We do "save_boot_params" first
> thing and that function must save a magic register value from ROM (or
> whatever) to a "stable" magic location in memory.

Ah OK. So long as it doesn't save to global_data we are fine. It could
just have a little structure somewhere in the data segment.

>
>> 2. Need for more stack that can be fitted into SRAM. I think the only
>> sensible option here is to change the stack after board_init_f(). As
>> Albert says this should be done in crt0.S (in fact that's where I put
>> my code). Forcing the dram init to before board_init_f() in SPL seems
>> broken to me.
>
> This is also covered.  The flow is cpu_init_crit -> lowlevel_init (set
> stack to CONFIG_SYS_INIT_SP_ADDR) -> s_init (init DDR) -> _main (set
> stack to CONFIG_SPL_STACK, can be in DDR).

Well s_init is a board-specific thing. What I mean is that crt0.S
should set up an initial stack - there should be no stack before that.
Then board_init_f() uses the initial stack, sets up DRAM, then we move
to a second larger stack before board_init_r() is called.

>
>> I think we should try to have the same flow as U-Boot proper:
>>
>> start.S
>> lowlevel_init (no stack, no global_data, no dram) - can only use
>> 'data' section to write stuff
>> crt0.S (sets up stack and global_data, no dram)
>> board_init_f (sets up dram)
>> relocate stack if required (but not code)
>> board_init_r (running with full stack in dram)
>
> I suppose since old school PowerPC needed i2c to read spd eeproms it's
> possible this ordering could work still today where there's a good bit
> of stuff neeed in order to bring DDR on some ARM platforms.

(Note I am talking just about SPL here, as above)

I suppose what I am saying is that there is no point in setting up
DRAM before board_init_f() in SPL. There is no global_data available,
nor is there any console, so any code that happens before
board_init_f() should be absolutely essential for getting to
board_init_f(). I can't think of much that fits in that category,
maybe some clock things?

Regards,
Simon
Tom Rini Dec. 21, 2014, 7:29 p.m. UTC | #5
On Sun, Dec 21, 2014 at 11:53:21AM -0700, Simon Glass wrote:
> Hi Tom,
> 
> On 21 December 2014 at 05:30, Tom Rini <trini@ti.com> wrote:
> > On Fri, Dec 19, 2014 at 08:32:35AM -0700, Simon Glass wrote:
> >> Hi Tom, Albert,
> >>
> >> On 19 December 2014 at 07:40, Tom Rini <trini@ti.com> wrote:
> >> > On Thu, Dec 18, 2014 at 05:21:21PM -0700, Simon Glass wrote:
> >> >
> >> >> This is an attempt to tidy up the early SPL code in an attempt to pave
> >> >> the way for driver model in SPL:
> >> >>
> >> >> - Avoid setting up SDRAM before board_init_f()
> >> >> - Avoid touching global_data before board_init_f()
> >> >> - Allow board_init_f() to set up a new stack (seems that the SRAM stack
> >> >> is not large enough on these boards)
> >> >>
> >> >> This needs more work but it does boot on Beaglebone Black.
> >> >>
> >> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> >> >> ---
> >> >>
> >> >>  arch/arm/cpu/armv7/am33xx/board.c  | 60 ++++++++++++++++++++++++++------------
> >> >>  arch/arm/cpu/armv7/lowlevel_init.S |  4 ---
> >> >>  arch/arm/include/asm/spl.h         |  3 ++
> >> >>  arch/arm/lib/crt0.S                |  9 ++++++
> >> >>  include/configs/ti_armv7_common.h  |  5 ++--
> >> >>  5 files changed, 56 insertions(+), 25 deletions(-)
> >> >
> >> > This takes things in the wrong direction I think.  Since omap3/4/5 have
> >> > the same problem we're going to have to duplicate a bunch of this code.
> >> > But we can do omap_save_boot_params a bit later I'm pretty sure we can
> >> > shove it into spl_board_init() in
> >> > arch/arm/cpu/armv7/omap-common/boot-common.c and I'm going to do my best
> >> > to do that today and test it on at least a few boards.
> >>
> >> I don't have a lot of background on SPL stuff as I only know one
> >> implementation in detail. So these comments may be a bit off.
> >>
> >> There seem to be two drivers causing this oddness:
> >>
> >> 1. The need to save boot params before global_data is available. I
> >> wonder if it is possible to avoid overwriting the boot params, and
> >> save them later, in board_init_f()? If not, then I don't think the
> >> global_data structure should be used. A static local variable in the
> >> data section, with just a few fields in it, could be used instead.
> >> That avoids the temptation to thing that we are creating a global_data
> >> structure before crt0.S does it officially. If the data had just been
> >> stored into the data section, without messing with global_data, then I
> >> don't think we would have this problem.
> >
> > This is actually covered today, really.  We do "save_boot_params" first
> > thing and that function must save a magic register value from ROM (or
> > whatever) to a "stable" magic location in memory.
> 
> Ah OK. So long as it doesn't save to global_data we are fine. It could
> just have a little structure somewhere in the data segment.
> 
> >
> >> 2. Need for more stack that can be fitted into SRAM. I think the only
> >> sensible option here is to change the stack after board_init_f(). As
> >> Albert says this should be done in crt0.S (in fact that's where I put
> >> my code). Forcing the dram init to before board_init_f() in SPL seems
> >> broken to me.
> >
> > This is also covered.  The flow is cpu_init_crit -> lowlevel_init (set
> > stack to CONFIG_SYS_INIT_SP_ADDR) -> s_init (init DDR) -> _main (set
> > stack to CONFIG_SPL_STACK, can be in DDR).
> 
> Well s_init is a board-specific thing. What I mean is that crt0.S
> should set up an initial stack - there should be no stack before that.
> Then board_init_f() uses the initial stack, sets up DRAM, then we move
> to a second larger stack before board_init_r() is called.

I'd like to see someone re-jigger all of the code here.  It could work
but most armv7 SoCs have a lot of things going on in s_init and I'm not
sure how much of it we can delay all that much.  We can (and do) use an
initial stack pointing elsewhere so maybe we could delay relocating the
main stack.

> >> I think we should try to have the same flow as U-Boot proper:
> >>
> >> start.S
> >> lowlevel_init (no stack, no global_data, no dram) - can only use
> >> 'data' section to write stuff
> >> crt0.S (sets up stack and global_data, no dram)
> >> board_init_f (sets up dram)
> >> relocate stack if required (but not code)
> >> board_init_r (running with full stack in dram)
> >
> > I suppose since old school PowerPC needed i2c to read spd eeproms it's
> > possible this ordering could work still today where there's a good bit
> > of stuff neeed in order to bring DDR on some ARM platforms.
> 
> (Note I am talking just about SPL here, as above)
> 
> I suppose what I am saying is that there is no point in setting up
> DRAM before board_init_f() in SPL. There is no global_data available,
> nor is there any console, so any code that happens before
> board_init_f() should be absolutely essential for getting to
> board_init_f(). I can't think of much that fits in that category,
> maybe some clock things?

Clock and pinmux.  It could work...
Simon Glass Dec. 21, 2014, 11:15 p.m. UTC | #6
Hi Tom,

On 21 December 2014 at 12:29, Tom Rini <trini@ti.com> wrote:
> On Sun, Dec 21, 2014 at 11:53:21AM -0700, Simon Glass wrote:
>> Hi Tom,
>>
>> On 21 December 2014 at 05:30, Tom Rini <trini@ti.com> wrote:
>> > On Fri, Dec 19, 2014 at 08:32:35AM -0700, Simon Glass wrote:
>> >> Hi Tom, Albert,
>> >>
>> >> On 19 December 2014 at 07:40, Tom Rini <trini@ti.com> wrote:
>> >> > On Thu, Dec 18, 2014 at 05:21:21PM -0700, Simon Glass wrote:
>> >> >
>> >> >> This is an attempt to tidy up the early SPL code in an attempt to pave
>> >> >> the way for driver model in SPL:
>> >> >>
>> >> >> - Avoid setting up SDRAM before board_init_f()
>> >> >> - Avoid touching global_data before board_init_f()
>> >> >> - Allow board_init_f() to set up a new stack (seems that the SRAM stack
>> >> >> is not large enough on these boards)
>> >> >>
>> >> >> This needs more work but it does boot on Beaglebone Black.
>> >> >>
>> >> >> Signed-off-by: Simon Glass <sjg@chromium.org>
>> >> >> ---
>> >> >>
>> >> >>  arch/arm/cpu/armv7/am33xx/board.c  | 60 ++++++++++++++++++++++++++------------
>> >> >>  arch/arm/cpu/armv7/lowlevel_init.S |  4 ---
>> >> >>  arch/arm/include/asm/spl.h         |  3 ++
>> >> >>  arch/arm/lib/crt0.S                |  9 ++++++
>> >> >>  include/configs/ti_armv7_common.h  |  5 ++--
>> >> >>  5 files changed, 56 insertions(+), 25 deletions(-)
>> >> >
>> >> > This takes things in the wrong direction I think.  Since omap3/4/5 have
>> >> > the same problem we're going to have to duplicate a bunch of this code.
>> >> > But we can do omap_save_boot_params a bit later I'm pretty sure we can
>> >> > shove it into spl_board_init() in
>> >> > arch/arm/cpu/armv7/omap-common/boot-common.c and I'm going to do my best
>> >> > to do that today and test it on at least a few boards.
>> >>
>> >> I don't have a lot of background on SPL stuff as I only know one
>> >> implementation in detail. So these comments may be a bit off.
>> >>
>> >> There seem to be two drivers causing this oddness:
>> >>
>> >> 1. The need to save boot params before global_data is available. I
>> >> wonder if it is possible to avoid overwriting the boot params, and
>> >> save them later, in board_init_f()? If not, then I don't think the
>> >> global_data structure should be used. A static local variable in the
>> >> data section, with just a few fields in it, could be used instead.
>> >> That avoids the temptation to thing that we are creating a global_data
>> >> structure before crt0.S does it officially. If the data had just been
>> >> stored into the data section, without messing with global_data, then I
>> >> don't think we would have this problem.
>> >
>> > This is actually covered today, really.  We do "save_boot_params" first
>> > thing and that function must save a magic register value from ROM (or
>> > whatever) to a "stable" magic location in memory.
>>
>> Ah OK. So long as it doesn't save to global_data we are fine. It could
>> just have a little structure somewhere in the data segment.
>>
>> >
>> >> 2. Need for more stack that can be fitted into SRAM. I think the only
>> >> sensible option here is to change the stack after board_init_f(). As
>> >> Albert says this should be done in crt0.S (in fact that's where I put
>> >> my code). Forcing the dram init to before board_init_f() in SPL seems
>> >> broken to me.
>> >
>> > This is also covered.  The flow is cpu_init_crit -> lowlevel_init (set
>> > stack to CONFIG_SYS_INIT_SP_ADDR) -> s_init (init DDR) -> _main (set
>> > stack to CONFIG_SPL_STACK, can be in DDR).
>>
>> Well s_init is a board-specific thing. What I mean is that crt0.S
>> should set up an initial stack - there should be no stack before that.
>> Then board_init_f() uses the initial stack, sets up DRAM, then we move
>> to a second larger stack before board_init_r() is called.
>
> I'd like to see someone re-jigger all of the code here.  It could work
> but most armv7 SoCs have a lot of things going on in s_init and I'm not
> sure how much of it we can delay all that much.  We can (and do) use an
> initial stack pointing elsewhere so maybe we could delay relocating the
> main stack.

Yes I've had a bit of a look around. I feel that s_init() should be
for very limited purposes and is being abused. There is a tendency for
everything to just keep moving earlier!

>
>> >> I think we should try to have the same flow as U-Boot proper:
>> >>
>> >> start.S
>> >> lowlevel_init (no stack, no global_data, no dram) - can only use
>> >> 'data' section to write stuff
>> >> crt0.S (sets up stack and global_data, no dram)
>> >> board_init_f (sets up dram)
>> >> relocate stack if required (but not code)
>> >> board_init_r (running with full stack in dram)
>> >
>> > I suppose since old school PowerPC needed i2c to read spd eeproms it's
>> > possible this ordering could work still today where there's a good bit
>> > of stuff neeed in order to bring DDR on some ARM platforms.
>>
>> (Note I am talking just about SPL here, as above)
>>
>> I suppose what I am saying is that there is no point in setting up
>> DRAM before board_init_f() in SPL. There is no global_data available,
>> nor is there any console, so any code that happens before
>> board_init_f() should be absolutely essential for getting to
>> board_init_f(). I can't think of much that fits in that category,
>> maybe some clock things?
>
> Clock and pinmux.  It could work...

Now that you have omap sorted there are only a few that use gdata - I
think iMX, sunxi and zynq. I'm having a bit of a look at sunxi.

Regards,
Simon
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/am33xx/board.c b/arch/arm/cpu/armv7/am33xx/board.c
index 29b1d73..eeea81a 100644
--- a/arch/arm/cpu/armv7/am33xx/board.c
+++ b/arch/arm/cpu/armv7/am33xx/board.c
@@ -275,24 +275,11 @@  static void watchdog_disable(void)
 		;
 }
 
-void s_init(void)
+static gd_t tmp_gdata __attribute__ ((section(".data")));
+
+void board_init_f(ulong dummy)
 {
-	/*
-	 * The ROM will only have set up sufficient pinmux to allow for the
-	 * first 4KiB NOR to be read, we must finish doing what we know of
-	 * the NOR mux in this space in order to continue.
-	 */
-#ifdef CONFIG_NOR_BOOT
-	enable_norboot_pin_mux();
-#endif
-	/*
-	 * Save the boot parameters passed from romcode.
-	 * We cannot delay the saving further than this,
-	 * to prevent overwrites.
-	 */
-#ifdef CONFIG_SPL_BUILD
-	save_omap_boot_params();
-#endif
+	gd->arch.omap_boot_params = tmp_gdata.arch.omap_boot_params;
 	watchdog_disable();
 	timer_init();
 	set_uart_mux_conf();
@@ -303,7 +290,6 @@  void s_init(void)
 	serial_init();
 	gd->have_console = 1;
 #elif defined(CONFIG_SPL_BUILD)
-	gd = &gdata;
 	preloader_console_init();
 #endif
 #if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC)
@@ -314,5 +300,43 @@  void s_init(void)
 	board_early_init_f();
 	sdram_init();
 #endif
+	/* Clear the BSS. */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+#ifdef CONFIG_SPL_STACK_R
+	unsigned long start_addr_sp;
+
+	start_addr_sp = CONFIG_SPL_STACK_R - sizeof(gd_t);
+	/* 8-byte alignment for ARM ABI compliance */
+	start_addr_sp &= ~0x07;
+	memcpy((void *)start_addr_sp, (void *)gd, sizeof(gd_t));
+	spl_call_board_init_r(start_addr_sp, dummy, board_init_r);
+#else
+	board_init_r(NULL, 0);
+#endif
+}
+
+void s_init(void)
+{
+	gd_t *old_gd;
+
+	/*
+	 * The ROM will only have set up sufficient pinmux to allow for the
+	 * first 4KiB NOR to be read, we must finish doing what we know of
+	 * the NOR mux in this space in order to continue.
+	 */
+#ifdef CONFIG_NOR_BOOT
+	enable_norboot_pin_mux();
+#endif
+	old_gd = (gd_t *)gd;
+	gd = &tmp_gdata;
+	/*
+	 * Save the boot parameters passed from romcode.
+	 * We cannot delay the saving further than this,
+	 * to prevent overwrites.
+	 */
+#ifdef CONFIG_SPL_BUILD
+	save_omap_boot_params();
+#endif
+	gd = &old_gd;
 }
 #endif
diff --git a/arch/arm/cpu/armv7/lowlevel_init.S b/arch/arm/cpu/armv7/lowlevel_init.S
index f1aea05..e294db9 100644
--- a/arch/arm/cpu/armv7/lowlevel_init.S
+++ b/arch/arm/cpu/armv7/lowlevel_init.S
@@ -21,13 +21,9 @@  ENTRY(lowlevel_init)
 	 */
 	ldr	sp, =CONFIG_SYS_INIT_SP_ADDR
 	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */
-#ifdef CONFIG_SPL_BUILD
-	ldr	r9, =gdata
-#else
 	sub	sp, sp, #GD_SIZE
 	bic	sp, sp, #7
 	mov	r9, sp
-#endif
 	/*
 	 * Save the old lr(passed in ip) and the current lr to stack
 	 */
diff --git a/arch/arm/include/asm/spl.h b/arch/arm/include/asm/spl.h
index 8acd7cd..66d983a 100644
--- a/arch/arm/include/asm/spl.h
+++ b/arch/arm/include/asm/spl.h
@@ -35,4 +35,7 @@  extern char __bss_start[], __bss_end[];
 
 extern gd_t gdata;
 
+void spl_call_board_init_r(ulong start_addr_sp, ulong boot_flags,
+			   void (*board_init_r)(gd_t *new_gd, ulong dest_addr));
+
 #endif
diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
index 22df3e5..be25fde 100644
--- a/arch/arm/lib/crt0.S
+++ b/arch/arm/lib/crt0.S
@@ -138,3 +138,12 @@  clbss_l:cmp	r0, r1			/* while not at end of BSS */
 #endif
 
 ENDPROC(_main)
+
+/*
+ * spl_call_board_init_r(start_addr_sp, dummy, board_init_r)
+ */
+ENTRY(spl_call_board_init_r)
+	mov	sp, r0
+	mov	r9, r0
+	bx	r2
+ENDPROC(spl_call_board_init_r)
diff --git a/include/configs/ti_armv7_common.h b/include/configs/ti_armv7_common.h
index bc75172..38c0e63 100644
--- a/include/configs/ti_armv7_common.h
+++ b/include/configs/ti_armv7_common.h
@@ -76,8 +76,7 @@ 
 #define CONFIG_NR_DRAM_BANKS		1
 #endif
 #define CONFIG_SYS_SDRAM_BASE		0x80000000
-#define CONFIG_SYS_INIT_SP_ADDR         (NON_SECURE_SRAM_END - \
-						GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR         NON_SECURE_SRAM_END
 
 /* Timer information. */
 #define CONFIG_SYS_PTV			2	/* Divisor: 2^(PTV+1) => 8 */
@@ -214,7 +213,7 @@ 
  * end of the BSS area.  We place our stack at 32MiB after the start of
  * DRAM to allow room for all of the above.
  */
-#define CONFIG_SPL_STACK		(CONFIG_SYS_SDRAM_BASE + (32 << 20))
+#define CONFIG_SPL_STACK_R		(CONFIG_SYS_SDRAM_BASE + (32 << 20))
 #ifndef CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_TEXT_BASE		0x80800000
 #endif