diff mbox

[U-Boot,12/12] imx: ventana: switch to SPL

Message ID 1398716258-8420-13-git-send-email-tharvey@gateworks.com
State Changes Requested
Delegated to: Stefano Babic
Headers show

Commit Message

Tim Harvey April 28, 2014, 8:17 p.m. UTC
Switch to an SPL image. The SPL for Ventana does the following:
 - setup i2c and read the factory programmed EEPROM to obtain DRAM config
   and model for board-specific calibration data
 - configure DRAM per CPU/size/layout/devices/calibration
 - load u-boot.img from NAND or MTD depending on boot device  and jump to it

This allows for a single SPL+u-boot.img to replace the previous multiple board
configurations.

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
v2:
- remove missing/unnecessary include
- revert mtdparts change
- use imx_ddr_size() which uses MMDC configuration to determine mem size
  explicitly
- add support for MX6SOLO and MX6DUAL
- set CS0_END for 4GB so get_ram_size() works
- updated DDR3 calibration values for ventana boards
- fixed build issue - only compile spl if doing spl build
- fixed line length issue in README
- remove CONFIG_SPL* conditions and conditionally compile instead
- removed prints for CPU type and DRAM size/width - uboot will print these later
- removed unused gw_ventana_spl.cfg
- use common read_eeprom function
- added MMC support to SPL
---
 board/gateworks/gw_ventana/Makefile         |   1 +
 board/gateworks/gw_ventana/README           |  92 ++++---
 board/gateworks/gw_ventana/gw_ventana.c     |   9 +-
 board/gateworks/gw_ventana/gw_ventana.cfg   |  15 -
 board/gateworks/gw_ventana/gw_ventana_spl.c | 407 ++++++++++++++++++++++++++++
 boards.cfg                                  |   6 +-
 include/configs/gw_ventana.h                |  11 +
 7 files changed, 485 insertions(+), 56 deletions(-)
 create mode 100644 board/gateworks/gw_ventana/gw_ventana_spl.c

Comments

Tim Harvey May 6, 2014, 6:18 p.m. UTC | #1
On Mon, Apr 28, 2014 at 1:17 PM, Tim Harvey <tharvey@gateworks.com> wrote:
>
> Switch to an SPL image. The SPL for Ventana does the following:
>  - setup i2c and read the factory programmed EEPROM to obtain DRAM config
>    and model for board-specific calibration data
>  - configure DRAM per CPU/size/layout/devices/calibration
>  - load u-boot.img from NAND or MTD depending on boot device  and jump to it
>
> This allows for a single SPL+u-boot.img to replace the previous multiple board
> configurations.
>
<snip>
> +
> +static void i2c_setup_iomux(void)
> +{
> +       if (is_cpu_type(MXC_CPU_MX6Q))
> +               setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6q_i2c_pad_info0);
> +       else
> +               setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6dl_i2c_pad_info0);
> +}
> +
<snip>
> +
> +/*
> + * called from C runtime startup code (arch/arm/lib/crt0.S:_main)
> + * - we have a stack and a place to store GD, both in SRAM
> + * - no variable global data is available
> + */
> +void board_init_f(ulong dummy)
> +{
> +       struct ventana_board_info ventana_info;
> +       int board_model;
> +
> +       /* iomux and setup of i2c */
> +       i2c_setup_iomux();
> +       timer_init();
> +       board_model = read_eeprom(I2C_GSC, &ventana_info);
> +
> +       /* provide some some default: 32bit 128MB */
> +       if (GW_UNKNOWN == board_model) {
> +               ventana_info.sdram_width = 2;
> +               ventana_info.sdram_size = 3;
> +       }
> +       spl_dram_init(8 << ventana_info.sdram_width,
> +                     16 << ventana_info.sdram_size,
> +                     board_model);
> +
> +       arch_cpu_init();
> +
> +       /* Clear the BSS. */
> +       memset(__bss_start, 0, __bss_end - __bss_start);
> +
> +       /* Set global data pointer. */
> +       gd = &gdata;
> +
> +       board_early_init_f();
> +
> +       preloader_console_init();
> +
> +       board_init_r(NULL, 0);
> +}

Stefano / York,

While preparing for a v3 patch series of my IMX6 SPL bootloader, I
find that commit dec1861be90c948ea9fb771927d3d26a994d2e20 [1] breaks
the above code because gd is now needed within setup_i2c.

I've always been a bit fuzzy on the order of the above calls so I dug
through the code and I think I understand things better. Please
correct any wrong assumptions I'm making below:
 - assignment to gd should 'always' be first (before anything needs
it, so why not do it first)
 - arch_cpu_init() should go next as this sets up very low level
CPU/SoC resources (in this case AIPS config and watchdog disable)
 - board_early_init_f() should be next as that sets up any board-specific iomux
 - any additional iomux necessary for SPL should go next (I take care
of i2c iomux and setup here)
 - timer_init() next as you need a timer for UART and mxc i2c (for
delays and busy checks)
 - preloader_console_init() next as we are now able to send something
over the UART (this gives me early debug for sdram config now too!)
 - sdram setup goes next
 - after sdram is setup, the bss can be cleared
 - board_init_r - pass over to generic SPL code which will load/call
an image based on boot device

So, if the above is correct, I should rework the above function as follows:

void board_init_f(ulong dummy)
{
        struct ventana_board_info ventana_info;
        int board_model;

        /* Set global data pointer. */
        gd = &gdata;

        /* setup AIPS and disable watchdog */
        arch_cpu_init();

        /* iomux and setup of i2c */
        board_early_init_f();
        i2c_setup_iomux();

        /* setup GP timer */
        timer_init();

        /* UART clocks enabled and gd valid - init serial console */
        preloader_console_init();

        /* read/validate EEPROM info to determine board model and SDRAM cfg */
        board_model = read_eeprom(I2C_GSC, &ventana_info);

        /* provide some some default: 32bit 128MB */
        if (GW_UNKNOWN == board_model) {
                ventana_info.sdram_width = 2;
                ventana_info.sdram_size = 3;
        }

        /* configure MMDC for SDRAM width/size and per-model calibration */
        spl_dram_init(8 << ventana_info.sdram_width,
                      16 << ventana_info.sdram_size,
                      board_model);

        /* Clear the BSS. */
        memset(__bss_start, 0, __bss_end - __bss_start);

        /* load/boot image from boot device */
        board_init_r(NULL, 0);
}

Does this make sense?

Thanks,

Tim

[1] - http://git.denx.de/?p=u-boot.git;a=commitdiff;h=dec1861be90c948ea9fb771927d3d26a994d2e20

> +
> +void reset_cpu(ulong addr)
> +{
> +}
> diff --git a/boards.cfg b/boards.cfg
> index c83aff3..9119e24 100644
> --- a/boards.cfg
> +++ b/boards.cfg
> @@ -322,11 +322,7 @@ Active  arm         armv7          mx6         freescale       mx6qsabreauto
>  Active  arm         armv7          mx6         freescale       mx6sabresd          mx6dlsabresd                         mx6sabresd:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6dl.cfg,MX6DL                                                             Fabio Estevam <fabio.estevam@freescale.com>
>  Active  arm         armv7          mx6         freescale       mx6sabresd          mx6qsabresd                          mx6sabresd:IMX_CONFIG=board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg,MX6Q                                                           Fabio Estevam <fabio.estevam@freescale.com>
>  Active  arm         armv7          mx6         freescale       mx6slevk            mx6slevk                             mx6slevk:IMX_CONFIG=board/freescale/mx6slevk/imximage.cfg,MX6SL                                                                   Fabio Estevam <fabio.estevam@freescale.com>
> -Active  arm         armv7          mx6         gateworks       gw_ventana          gwventanadl                          gw_ventana:IMX_CONFIG=board/gateworks/gw_ventana/gw_ventana.cfg,MX6DL,DDR_MB=512                                                  Tim Harvey <tharvey@gateworks.com>
> -Active  arm         armv7          mx6         gateworks       gw_ventana          gwventanadl1g                        gw_ventana:IMX_CONFIG=board/gateworks/gw_ventana/gw_ventana.cfg,MX6DL,DDR_MB=1024                                                 Tim Harvey <tharvey@gateworks.com>
> -Active  arm         armv7          mx6         gateworks       gw_ventana          gwventanaq                           gw_ventana:IMX_CONFIG=board/gateworks/gw_ventana/gw_ventana.cfg,MX6Q,DDR_MB=512                                                   Tim Harvey <tharvey@gateworks.com>
> -Active  arm         armv7          mx6         gateworks       gw_ventana          gwventanaq1g                         gw_ventana:IMX_CONFIG=board/gateworks/gw_ventana/gw_ventana.cfg,MX6Q,DDR_MB=1024                                                  Tim Harvey <tharvey@gateworks.com>
> -Active  arm         armv7          mx6         gateworks       gw_ventana          gwventanaq1gspi                      gw_ventana:IMX_CONFIG=board/gateworks/gw_ventana/gw_ventana.cfg,MX6Q,DDR_MB=1024,SPI_FLASH                                        Tim Harvey <tharvey@gateworks.com>
> +Active  arm         armv7          mx6         gateworks       gw_ventana          gwventana                            gw_ventana:IMX_CONFIG=board/gateworks/gw_ventana/gw_ventana.cfg,MX6QDL,SPL                                                  Tim Harvey <tharvey@gateworks.com>
>  Active  arm         armv7          mx6         solidrun        hummingboard        hummingboard_solo                    hummingboard:IMX_CONFIG=board/solidrun/hummingboard/solo.cfg,MX6S,DDR_MB=512                                                      Jon Nettleton <jon.nettleton@gmail.com>
>  Active  arm         armv7          omap3       -               overo               omap3_overo                          -                                                                                                                                 Steve Sakoman <sakoman@gmail.com>
>  Active  arm         armv7          omap3       -               pandora             omap3_pandora                        -                                                                                                                                 Grazvydas Ignotas <notasas@gmail.com>
> diff --git a/include/configs/gw_ventana.h b/include/configs/gw_ventana.h
> index 3398390..cd53737 100644
> --- a/include/configs/gw_ventana.h
> +++ b/include/configs/gw_ventana.h
> @@ -7,6 +7,17 @@
>  #ifndef __CONFIG_H
>  #define __CONFIG_H
>
> +/* SPL */
> +#define CONFIG_SPL_NAND_SUPPORT
> +#define CONFIG_SPL_MMC_SUPPORT
> +#define CONFIG_SPL_FAT_SUPPORT
> +/*
> +#define CONFIG_SPL_SATA_SUPPORT
> +*/
> +/* Location in NAND to read U-Boot from */
> +#define CONFIG_SYS_NAND_U_BOOT_OFFS     (14 * 1024 * 1024)
> +
> +#include "imx6_spl.h"                  /* common IMX6 SPL configuration */
>  #include "mx6_common.h"
>  #define CONFIG_MX6
>  #define CONFIG_DISPLAY_CPUINFO         /* display cpu info */
> --
> 1.8.3.2
>
York Sun May 6, 2014, 6:45 p.m. UTC | #2
On 05/06/2014 11:18 AM, Tim Harvey wrote:
> On Mon, Apr 28, 2014 at 1:17 PM, Tim Harvey <tharvey@gateworks.com> wrote:
>>
>> Switch to an SPL image. The SPL for Ventana does the following:
>>  - setup i2c and read the factory programmed EEPROM to obtain DRAM config
>>    and model for board-specific calibration data
>>  - configure DRAM per CPU/size/layout/devices/calibration
>>  - load u-boot.img from NAND or MTD depending on boot device  and jump to it
>>
>> This allows for a single SPL+u-boot.img to replace the previous multiple board
>> configurations.
>>
> <snip>
>> +
>> +static void i2c_setup_iomux(void)
>> +{
>> +       if (is_cpu_type(MXC_CPU_MX6Q))
>> +               setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6q_i2c_pad_info0);
>> +       else
>> +               setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6dl_i2c_pad_info0);
>> +}
>> +
> <snip>
>> +
>> +/*
>> + * called from C runtime startup code (arch/arm/lib/crt0.S:_main)
>> + * - we have a stack and a place to store GD, both in SRAM
>> + * - no variable global data is available
>> + */
>> +void board_init_f(ulong dummy)
>> +{
>> +       struct ventana_board_info ventana_info;
>> +       int board_model;
>> +
>> +       /* iomux and setup of i2c */
>> +       i2c_setup_iomux();
>> +       timer_init();
>> +       board_model = read_eeprom(I2C_GSC, &ventana_info);
>> +
>> +       /* provide some some default: 32bit 128MB */
>> +       if (GW_UNKNOWN == board_model) {
>> +               ventana_info.sdram_width = 2;
>> +               ventana_info.sdram_size = 3;
>> +       }
>> +       spl_dram_init(8 << ventana_info.sdram_width,
>> +                     16 << ventana_info.sdram_size,
>> +                     board_model);
>> +
>> +       arch_cpu_init();
>> +
>> +       /* Clear the BSS. */
>> +       memset(__bss_start, 0, __bss_end - __bss_start);
>> +
>> +       /* Set global data pointer. */
>> +       gd = &gdata;
>> +
>> +       board_early_init_f();
>> +
>> +       preloader_console_init();
>> +
>> +       board_init_r(NULL, 0);
>> +}
> 
> Stefano / York,
> 
> While preparing for a v3 patch series of my IMX6 SPL bootloader, I
> find that commit dec1861be90c948ea9fb771927d3d26a994d2e20 [1] breaks
> the above code because gd is now needed within setup_i2c.
> 
> I've always been a bit fuzzy on the order of the above calls so I dug
> through the code and I think I understand things better. Please
> correct any wrong assumptions I'm making below:
>  - assignment to gd should 'always' be first (before anything needs
> it, so why not do it first)
>  - arch_cpu_init() should go next as this sets up very low level
> CPU/SoC resources (in this case AIPS config and watchdog disable)
>  - board_early_init_f() should be next as that sets up any board-specific iomux
>  - any additional iomux necessary for SPL should go next (I take care
> of i2c iomux and setup here)
>  - timer_init() next as you need a timer for UART and mxc i2c (for
> delays and busy checks)
>  - preloader_console_init() next as we are now able to send something
> over the UART (this gives me early debug for sdram config now too!)
>  - sdram setup goes next
>  - after sdram is setup, the bss can be cleared
>  - board_init_r - pass over to generic SPL code which will load/call
> an image based on boot device
> 
> So, if the above is correct, I should rework the above function as follows:
> 
> void board_init_f(ulong dummy)
> {
>         struct ventana_board_info ventana_info;
>         int board_model;
> 
>         /* Set global data pointer. */
>         gd = &gdata;
> 
>         /* setup AIPS and disable watchdog */
>         arch_cpu_init();
> 
>         /* iomux and setup of i2c */
>         board_early_init_f();
>         i2c_setup_iomux();
> 
>         /* setup GP timer */
>         timer_init();
> 
>         /* UART clocks enabled and gd valid - init serial console */
>         preloader_console_init();
> 
>         /* read/validate EEPROM info to determine board model and SDRAM cfg */
>         board_model = read_eeprom(I2C_GSC, &ventana_info);
> 
>         /* provide some some default: 32bit 128MB */
>         if (GW_UNKNOWN == board_model) {
>                 ventana_info.sdram_width = 2;
>                 ventana_info.sdram_size = 3;
>         }
> 
>         /* configure MMDC for SDRAM width/size and per-model calibration */
>         spl_dram_init(8 << ventana_info.sdram_width,
>                       16 << ventana_info.sdram_size,
>                       board_model);
> 
>         /* Clear the BSS. */
>         memset(__bss_start, 0, __bss_end - __bss_start);
> 
>         /* load/boot image from boot device */
>         board_init_r(NULL, 0);
> }
> 
> Does this make sense?
>

Tim,

I agree gd should be set first if the memory is available. My previous change to
this i2c driver was to make sure it works without DRAM. Since it uses a data
structure, it has no other place to go.

York
Jeroen Hofstee May 6, 2014, 7:11 p.m. UTC | #3
Hello Tim,

On di, 2014-05-06 at 11:18 -0700, Tim Harvey wrote:
> On Mon, Apr 28, 2014 at 1:17 PM, Tim Harvey <tharvey@gateworks.com> wrote:

> 
> void board_init_f(ulong dummy)
> {
>         struct ventana_board_info ventana_info;
>         int board_model;
> 
>         /* Set global data pointer. */
>         gd = &gdata;
> 
>         /* setup AIPS and disable watchdog */
>         arch_cpu_init();
> 
>         /* iomux and setup of i2c */
>         board_early_init_f();
>         i2c_setup_iomux();
> 
>         /* setup GP timer */
>         timer_init();
> 
>         /* UART clocks enabled and gd valid - init serial console */
>         preloader_console_init();
> 
>         /* read/validate EEPROM info to determine board model and SDRAM cfg */
>         board_model = read_eeprom(I2C_GSC, &ventana_info);
> 
>         /* provide some some default: 32bit 128MB */
>         if (GW_UNKNOWN == board_model) {
>                 ventana_info.sdram_width = 2;
>                 ventana_info.sdram_size = 3;
>         }
> 
>         /* configure MMDC for SDRAM width/size and per-model calibration */
>         spl_dram_init(8 << ventana_info.sdram_width,
>                       16 << ventana_info.sdram_size,
>                       board_model);
> 
>         /* Clear the BSS. */
>         memset(__bss_start, 0, __bss_end - __bss_start);
> 
>         /* load/boot image from boot device */
>         board_init_r(NULL, 0);
> }
> 
> Does this make sense?

Since Crt0.S already created gd on the stack before calling
board_init_f, can't the assignment of gd not simply be removed?
Is there anything special about gdata?

Regards,
Jeroen
Tim Harvey May 6, 2014, 11:35 p.m. UTC | #4
On Tue, May 6, 2014 at 12:11 PM, Jeroen Hofstee <dasuboot@myspectrum.nl> wrote:
> Hello Tim,
>
> On di, 2014-05-06 at 11:18 -0700, Tim Harvey wrote:
>> On Mon, Apr 28, 2014 at 1:17 PM, Tim Harvey <tharvey@gateworks.com> wrote:
>
>>
>> void board_init_f(ulong dummy)
>> {
>>         struct ventana_board_info ventana_info;
>>         int board_model;
>>
>>         /* Set global data pointer. */
>>         gd = &gdata;
>>
>>         /* setup AIPS and disable watchdog */
>>         arch_cpu_init();
>>
>>         /* iomux and setup of i2c */
>>         board_early_init_f();
>>         i2c_setup_iomux();
>>
>>         /* setup GP timer */
>>         timer_init();
>>
>>         /* UART clocks enabled and gd valid - init serial console */
>>         preloader_console_init();
>>
>>         /* read/validate EEPROM info to determine board model and SDRAM cfg */
>>         board_model = read_eeprom(I2C_GSC, &ventana_info);
>>
>>         /* provide some some default: 32bit 128MB */
>>         if (GW_UNKNOWN == board_model) {
>>                 ventana_info.sdram_width = 2;
>>                 ventana_info.sdram_size = 3;
>>         }
>>
>>         /* configure MMDC for SDRAM width/size and per-model calibration */
>>         spl_dram_init(8 << ventana_info.sdram_width,
>>                       16 << ventana_info.sdram_size,
>>                       board_model);
>>
>>         /* Clear the BSS. */
>>         memset(__bss_start, 0, __bss_end - __bss_start);
>>
>>         /* load/boot image from boot device */
>>         board_init_r(NULL, 0);
>> }
>>
>> Does this make sense?
>
> Since Crt0.S already created gd on the stack before calling
> board_init_f, can't the assignment of gd not simply be removed?
> Is there anything special about gdata?
>
> Regards,
> Jeroen
>
>

Jeroen,

That does make sense, but what I find is that York's ocmmit
dec1861be90c948ea9fb771927d3d26a994d2e20 requires that gd be blanked
and its not. This causes bus_i2c_init to skip its initialization
because p->base is not zero.

York, does this make sense? Your patch creates a dependence on
gd->srdata being blank which isn't the case with the SRAM when booting
from the IMX6 boot rom.

Tim
Stefano Babic May 7, 2014, 9:29 a.m. UTC | #5
Hi Tim,

On 06/05/2014 20:18, Tim Harvey wrote:
> 
> Stefano / York,
> 
> While preparing for a v3 patch series of my IMX6 SPL bootloader, I
> find that commit dec1861be90c948ea9fb771927d3d26a994d2e20 [1] breaks
> the above code because gd is now needed within setup_i2c.
> 
> I've always been a bit fuzzy on the order of the above calls so I dug
> through the code and I think I understand things better. Please
> correct any wrong assumptions I'm making below:
>  - assignment to gd should 'always' be first (before anything needs
> it, so why not do it first)
>  - arch_cpu_init() should go next as this sets up very low level
> CPU/SoC resources (in this case AIPS config and watchdog disable)
>  - board_early_init_f() should be next as that sets up any board-specific iomux
>  - any additional iomux necessary for SPL should go next (I take care
> of i2c iomux and setup here)
>  - timer_init() next as you need a timer for UART and mxc i2c (for
> delays and busy checks)
>  - preloader_console_init() next as we are now able to send something
> over the UART (this gives me early debug for sdram config now too!)
>  - sdram setup goes next
>  - after sdram is setup, the bss can be cleared
>  - board_init_r - pass over to generic SPL code which will load/call
> an image based on boot device

I think your analyses is correct.

> 
> So, if the above is correct, I should rework the above function as follows:
> 
> void board_init_f(ulong dummy)
> {
>         struct ventana_board_info ventana_info;
>         int board_model;
> 
>         /* Set global data pointer. */
>         gd = &gdata;
> 
>         /* setup AIPS and disable watchdog */
>         arch_cpu_init();
> 
>         /* iomux and setup of i2c */
>         board_early_init_f();
>         i2c_setup_iomux();
> 
>         /* setup GP timer */
>         timer_init();
> 
>         /* UART clocks enabled and gd valid - init serial console */
>         preloader_console_init();
> 
>         /* read/validate EEPROM info to determine board model and SDRAM cfg */
>         board_model = read_eeprom(I2C_GSC, &ventana_info);
> 
>         /* provide some some default: 32bit 128MB */
>         if (GW_UNKNOWN == board_model) {
>                 ventana_info.sdram_width = 2;
>                 ventana_info.sdram_size = 3;
>         }
> 
>         /* configure MMDC for SDRAM width/size and per-model calibration */
>         spl_dram_init(8 << ventana_info.sdram_width,
>                       16 << ventana_info.sdram_size,
>                       board_model);
> 
>         /* Clear the BSS. */
>         memset(__bss_start, 0, __bss_end - __bss_start);
> 
>         /* load/boot image from boot device */
>         board_init_r(NULL, 0);
> }

It seems reasonable, go on this way.

Regards,
Stefano
York Sun May 7, 2014, 4:14 p.m. UTC | #6
On 05/06/2014 04:35 PM, Tim Harvey wrote:
> On Tue, May 6, 2014 at 12:11 PM, Jeroen Hofstee <dasuboot@myspectrum.nl> wrote:
>> Hello Tim,
>>
<snip>
>>
>> Since Crt0.S already created gd on the stack before calling
>> board_init_f, can't the assignment of gd not simply be removed?
>> Is there anything special about gdata?
>>
>> Regards,
>> Jeroen
>>
>>
> 
> Jeroen,
> 
> That does make sense, but what I find is that York's ocmmit
> dec1861be90c948ea9fb771927d3d26a994d2e20 requires that gd be blanked
> and its not. This causes bus_i2c_init to skip its initialization
> because p->base is not zero.
> 
> York, does this make sense? Your patch creates a dependence on
> gd->srdata being blank which isn't the case with the SRAM when booting
> from the IMX6 boot rom.
> 

GD should be cleared (zeroed). Then we don't have this problem. Whoever sets up
gd (board_int_f, cpu_init_f, or others) should make sure gd is cleared. Why
isn't it the case for IMX6 boot rom?

York
Jeroen Hofstee May 7, 2014, 6:43 p.m. UTC | #7
Hi,

On wo, 2014-05-07 at 09:14 -0700, York Sun wrote:

> <snip>
> >>
> >> Since Crt0.S already created gd on the stack before calling
> >> board_init_f, can't the assignment of gd not simply be removed?
> >> Is there anything special about gdata?
> > 
> > That does make sense, but what I find is that York's ocmmit
> > dec1861be90c948ea9fb771927d3d26a994d2e20 requires that gd be blanked
> > and its not. This causes bus_i2c_init to skip its initialization
> > because p->base is not zero.
> > 
> > York, does this make sense? Your patch creates a dependence on
> > gd->srdata being blank which isn't the case with the SRAM when booting
> > from the IMX6 boot rom.
> > 
> 
> GD should be cleared (zeroed). Then we don't have this problem. Whoever sets up
> gd (board_int_f, cpu_init_f, or others) should make sure gd is cleared. Why
> isn't it the case for IMX6 boot rom?
> 

Seems fine to me. Albert, any objection against zeroing gd out in
crt0.S?

And if not, shouldn't the same be done for arm64.

Jeroen
Tim Harvey May 7, 2014, 8:27 p.m. UTC | #8
On Wed, May 7, 2014 at 9:14 AM, York Sun <yorksun@freescale.com> wrote:
> On 05/06/2014 04:35 PM, Tim Harvey wrote:
>> On Tue, May 6, 2014 at 12:11 PM, Jeroen Hofstee <dasuboot@myspectrum.nl> wrote:
>>> Hello Tim,
>>>
> <snip>
>>>
>>> Since Crt0.S already created gd on the stack before calling
>>> board_init_f, can't the assignment of gd not simply be removed?
>>> Is there anything special about gdata?
>>>
>>> Regards,
>>> Jeroen
>>>
>>>
>>
>> Jeroen,
>>
>> That does make sense, but what I find is that York's ocmmit
>> dec1861be90c948ea9fb771927d3d26a994d2e20 requires that gd be blanked
>> and its not. This causes bus_i2c_init to skip its initialization
>> because p->base is not zero.
>>
>> York, does this make sense? Your patch creates a dependence on
>> gd->srdata being blank which isn't the case with the SRAM when booting
>> from the IMX6 boot rom.
>>
>
> GD should be cleared (zeroed). Then we don't have this problem. Whoever sets up
> gd (board_int_f, cpu_init_f, or others) should make sure gd is cleared. Why
> isn't it the case for IMX6 boot rom?
>
> York
>

York,

crt0.S is mapping gd to where the SPL stack pointer is defined, which
is where Freescale says its stack pointer is for its firmware BOOT
ROM, so its initial data will be dependent on what the BOOT ROM did.

I think the right solution is to have crt0.S zero it out.

Tim
York Sun May 7, 2014, 8:29 p.m. UTC | #9
On 05/07/2014 01:27 PM, Tim Harvey wrote:
> On Wed, May 7, 2014 at 9:14 AM, York Sun <yorksun@freescale.com> wrote:
>> On 05/06/2014 04:35 PM, Tim Harvey wrote:
>>> On Tue, May 6, 2014 at 12:11 PM, Jeroen Hofstee <dasuboot@myspectrum.nl> wrote:
>>>> Hello Tim,
>>>>
>> <snip>
>>>>
>>>> Since Crt0.S already created gd on the stack before calling
>>>> board_init_f, can't the assignment of gd not simply be removed?
>>>> Is there anything special about gdata?
>>>>
>>>> Regards,
>>>> Jeroen
>>>>
>>>>
>>>
>>> Jeroen,
>>>
>>> That does make sense, but what I find is that York's ocmmit
>>> dec1861be90c948ea9fb771927d3d26a994d2e20 requires that gd be blanked
>>> and its not. This causes bus_i2c_init to skip its initialization
>>> because p->base is not zero.
>>>
>>> York, does this make sense? Your patch creates a dependence on
>>> gd->srdata being blank which isn't the case with the SRAM when booting
>>> from the IMX6 boot rom.
>>>
>>
>> GD should be cleared (zeroed). Then we don't have this problem. Whoever sets up
>> gd (board_int_f, cpu_init_f, or others) should make sure gd is cleared. Why
>> isn't it the case for IMX6 boot rom?
>>
>> York
>>
> 
> York,
> 
> crt0.S is mapping gd to where the SPL stack pointer is defined, which
> is where Freescale says its stack pointer is for its firmware BOOT
> ROM, so its initial data will be dependent on what the BOOT ROM did.
> 
> I think the right solution is to have crt0.S zero it out.
>

Either crt0.S, or somewhere before gd is used for the first time. Can it be done
in board_init_f()?

York
Tim Harvey May 7, 2014, 8:35 p.m. UTC | #10
On Wed, May 7, 2014 at 1:29 PM, York Sun <yorksun@freescale.com> wrote:
> On 05/07/2014 01:27 PM, Tim Harvey wrote:
>> On Wed, May 7, 2014 at 9:14 AM, York Sun <yorksun@freescale.com> wrote:
>>> On 05/06/2014 04:35 PM, Tim Harvey wrote:
>>>> On Tue, May 6, 2014 at 12:11 PM, Jeroen Hofstee <dasuboot@myspectrum.nl> wrote:
>>>>> Hello Tim,
>>>>>
>>> <snip>
>>>>>
>>>>> Since Crt0.S already created gd on the stack before calling
>>>>> board_init_f, can't the assignment of gd not simply be removed?
>>>>> Is there anything special about gdata?
>>>>>
>>>>> Regards,
>>>>> Jeroen
>>>>>
>>>>>
>>>>
>>>> Jeroen,
>>>>
>>>> That does make sense, but what I find is that York's ocmmit
>>>> dec1861be90c948ea9fb771927d3d26a994d2e20 requires that gd be blanked
>>>> and its not. This causes bus_i2c_init to skip its initialization
>>>> because p->base is not zero.
>>>>
>>>> York, does this make sense? Your patch creates a dependence on
>>>> gd->srdata being blank which isn't the case with the SRAM when booting
>>>> from the IMX6 boot rom.
>>>>
>>>
>>> GD should be cleared (zeroed). Then we don't have this problem. Whoever sets up
>>> gd (board_int_f, cpu_init_f, or others) should make sure gd is cleared. Why
>>> isn't it the case for IMX6 boot rom?
>>>
>>> York
>>>
>>
>> York,
>>
>> crt0.S is mapping gd to where the SPL stack pointer is defined, which
>> is where Freescale says its stack pointer is for its firmware BOOT
>> ROM, so its initial data will be dependent on what the BOOT ROM did.
>>
>> I think the right solution is to have crt0.S zero it out.
>>
>
> Either crt0.S, or somewhere before gd is used for the first time. Can it be done
> in board_init_f()?
>
> York
>
>

It makes more sense to do it in crt0.S so that all boards don't have
to do it and can make the assumption that it is cleared.

Tim
York Sun May 7, 2014, 8:36 p.m. UTC | #11
On 05/07/2014 01:35 PM, Tim Harvey wrote:
> On Wed, May 7, 2014 at 1:29 PM, York Sun <yorksun@freescale.com> wrote:
>> On 05/07/2014 01:27 PM, Tim Harvey wrote:
>>> On Wed, May 7, 2014 at 9:14 AM, York Sun <yorksun@freescale.com> wrote:
>>>> On 05/06/2014 04:35 PM, Tim Harvey wrote:
>>>>> On Tue, May 6, 2014 at 12:11 PM, Jeroen Hofstee <dasuboot@myspectrum.nl> wrote:
>>>>>> Hello Tim,
>>>>>>
>>>> <snip>
>>>>>>
>>>>>> Since Crt0.S already created gd on the stack before calling
>>>>>> board_init_f, can't the assignment of gd not simply be removed?
>>>>>> Is there anything special about gdata?
>>>>>>
>>>>>> Regards,
>>>>>> Jeroen
>>>>>>
>>>>>>
>>>>>
>>>>> Jeroen,
>>>>>
>>>>> That does make sense, but what I find is that York's ocmmit
>>>>> dec1861be90c948ea9fb771927d3d26a994d2e20 requires that gd be blanked
>>>>> and its not. This causes bus_i2c_init to skip its initialization
>>>>> because p->base is not zero.
>>>>>
>>>>> York, does this make sense? Your patch creates a dependence on
>>>>> gd->srdata being blank which isn't the case with the SRAM when booting
>>>>> from the IMX6 boot rom.
>>>>>
>>>>
>>>> GD should be cleared (zeroed). Then we don't have this problem. Whoever sets up
>>>> gd (board_int_f, cpu_init_f, or others) should make sure gd is cleared. Why
>>>> isn't it the case for IMX6 boot rom?
>>>>
>>>> York
>>>>
>>>
>>> York,
>>>
>>> crt0.S is mapping gd to where the SPL stack pointer is defined, which
>>> is where Freescale says its stack pointer is for its firmware BOOT
>>> ROM, so its initial data will be dependent on what the BOOT ROM did.
>>>
>>> I think the right solution is to have crt0.S zero it out.
>>>
>>
>> Either crt0.S, or somewhere before gd is used for the first time. Can it be done
>> in board_init_f()?
>>
>> York
>>
>>
> 
> It makes more sense to do it in crt0.S so that all boards don't have
> to do it and can make the assumption that it is cleared.
> 

No objection as far as it is cleared.

York
Tim Harvey May 14, 2014, 4:58 a.m. UTC | #12
On Wed, May 7, 2014 at 2:29 AM, Stefano Babic <sbabic@denx.de> wrote:
> Hi Tim,
>
> On 06/05/2014 20:18, Tim Harvey wrote:
>>
>> Stefano / York,
>>
>> While preparing for a v3 patch series of my IMX6 SPL bootloader, I
>> find that commit dec1861be90c948ea9fb771927d3d26a994d2e20 [1] breaks
>> the above code because gd is now needed within setup_i2c.
>>
>> I've always been a bit fuzzy on the order of the above calls so I dug
>> through the code and I think I understand things better. Please
>> correct any wrong assumptions I'm making below:
>>  - assignment to gd should 'always' be first (before anything needs
>> it, so why not do it first)
>>  - arch_cpu_init() should go next as this sets up very low level
>> CPU/SoC resources (in this case AIPS config and watchdog disable)
>>  - board_early_init_f() should be next as that sets up any board-specific iomux
>>  - any additional iomux necessary for SPL should go next (I take care
>> of i2c iomux and setup here)
>>  - timer_init() next as you need a timer for UART and mxc i2c (for
>> delays and busy checks)
>>  - preloader_console_init() next as we are now able to send something
>> over the UART (this gives me early debug for sdram config now too!)
>>  - sdram setup goes next
>>  - after sdram is setup, the bss can be cleared
>>  - board_init_r - pass over to generic SPL code which will load/call
>> an image based on boot device
>
> I think your analyses is correct.
>
>>
>> So, if the above is correct, I should rework the above function as follows:
>>
>> void board_init_f(ulong dummy)
>> {
>>         struct ventana_board_info ventana_info;
>>         int board_model;
>>
>>         /* Set global data pointer. */
>>         gd = &gdata;
>>
>>         /* setup AIPS and disable watchdog */
>>         arch_cpu_init();
>>
>>         /* iomux and setup of i2c */
>>         board_early_init_f();
>>         i2c_setup_iomux();
>>
>>         /* setup GP timer */
>>         timer_init();
>>
>>         /* UART clocks enabled and gd valid - init serial console */
>>         preloader_console_init();
>>
>>         /* read/validate EEPROM info to determine board model and SDRAM cfg */
>>         board_model = read_eeprom(I2C_GSC, &ventana_info);
>>
>>         /* provide some some default: 32bit 128MB */
>>         if (GW_UNKNOWN == board_model) {
>>                 ventana_info.sdram_width = 2;
>>                 ventana_info.sdram_size = 3;
>>         }
>>
>>         /* configure MMDC for SDRAM width/size and per-model calibration */
>>         spl_dram_init(8 << ventana_info.sdram_width,
>>                       16 << ventana_info.sdram_size,
>>                       board_model);
>>
>>         /* Clear the BSS. */
>>         memset(__bss_start, 0, __bss_end - __bss_start);
>>
>>         /* load/boot image from boot device */
>>         board_init_r(NULL, 0);
>> }
>
> It seems reasonable, go on this way.
>
> Regards,
> Stefano
>

Stefano,

I've just found that one of my boards fails with the above re-org.
Strangely a board which has the same mem layout, mem width/size, CPU
and nand does not fail.

If I make the following change:
diff mbox

Patch

diff --git a/board/gateworks/gw_ventana/Makefile b/board/gateworks/gw_ventana/Makefile
index 03bd1fd..33a1788 100644
--- a/board/gateworks/gw_ventana/Makefile
+++ b/board/gateworks/gw_ventana/Makefile
@@ -7,4 +7,5 @@ 
 #
 
 obj-y  := gw_ventana.o gsc.o eeprom.o
+obj-$(CONFIG_SPL_BUILD) += gw_ventana_spl.o
 
diff --git a/board/gateworks/gw_ventana/README b/board/gateworks/gw_ventana/README
index 9e697d6..888657c 100644
--- a/board/gateworks/gw_ventana/README
+++ b/board/gateworks/gw_ventana/README
@@ -3,53 +3,81 @@  U-Boot for the Gateworks Ventana Product Family boards
 This file contains information for the port of U-Boot to the Gateworks
 Ventana Product family boards.
 
-1. Boot source, boot from NAND
+1. Secondary Program Loader (SPL)
+---------------------------------
+
+The i.MX6 has a BOOT ROM PPL (Primary Program Loader) which supports loading
+an executable image from various boot devices.
+
+The Gateworks Ventana board config uses an SPL build configuration. This
+will build the following artifacts from u-boot source:
+ - SPL - Secondary Program Loader that the i.MX6 BOOT ROM (Primary Program
+         Loader) boots.  This detects CPU/DRAM configuration, configures
+         The DRAM controller, loads u-boot.img from the detected boot device,
+         and jumps to it.  As this is booted from the PPL, it has an IVT/DCD
+         table.
+ - u-boot.img - The main u-boot core which is u-boot.bin with a image header.
+
+
+2. Build
+--------
+
+To build U-Boot for the Gateworks Ventana product family:
+
+ make gwventana_config
+ make
+
+
+3. Boot source, boot from NAND
 ------------------------------
 
 The i.MX6 BOOT ROM expects some structures that provide details of NAND layout
 and bad block information (referred to as 'bootstreams') which are replicated
-multiple times in NAND. The number of replications is configurable through
-board strapping options and eFUSE settings.  The Freescale 'kobs-ng'
-application from the Freescale LTIB BSP, which runs under Linux, must be used
-to program the bootstream in order to setup the replicated headers correctly.
+multiple times in NAND. The number of replications and their spacing (referred
+to as search stride) is configurable through board strapping options and/or
+eFUSE settings (BOOT_SEARCH_COUNT / Pages in block from BOOT_CFG2). In
+addition, the i.MX6 BOOT ROM Flash Configuration Block (FCB) supports two
+copies of a bootloader in flash in the case that a bad block has corrupted one.
+The Freescale 'kobs-ng' application from the Freescale LTIB BSP, which runs
+under Linux and operates on an MTD partition, must be used to program the
+bootstream in order to setup this flash structure correctly.
 
 The Gateworks Ventana boards with NAND flash have been factory programmed
 such that their eFUSE settings expect 2 copies of the boostream (this is
 specified by providing kobs-ng with the --search_exponent=1 argument). Once in
-Linux with MTD support for the NAND on /dev/mtd0 you can program the boostream
+Linux with MTD support for the NAND on /dev/mtd0 you can program the SPL
 with:
 
-kobs-ng init -v -x --search_exponent=1 u-boot.imx
+kobs-ng init -v -x --search_exponent=1 SPL
 
-The kobs-ng application uses an imximage (u-boot.imx) which contains the
-Image Vector Table (IVT) and Device Configuration Data (DCD) structures that
-the i.MX6 BOOT ROM requires to boot.  The kobs-ng adds the Firmware
-Configuration Block (FCB) and Discovered Bad Block Table (DBBT).
+The kobs-ng application uses an imximage which contains the Image Vector Table
+(IVT) and Device Configuration Data (DCD) structures that the i.MX6 BOOT ROM
+requires to boot.  The kobs-ng adds the Firmware Configuration Block (FCB) and
+Discovered Bad Block Table (DBBT).  The SPL build artifact from u-boot is
+an imximage.
 
-This information is taken from:
-  http://trac.gateworks.com/wiki/ventana/bootloader#NANDFLASH
+The u-boot.img, which is the non SPL u-boot binary appended to a u-boot image
+header must be programmed in the NAND flash boot device at an offset hard
+coded in the SPL. For the Ventana boards, this has been chosen to be 14MB.
+The image can be programmed from either u-boot or Linux:
 
-More details about the i.MX6 BOOT ROM can be found in the IMX6 reference manual.
-
-2. Build
---------
+u-boot:
+Ventana > setenv mtdparts mtdparts=nand:14m(spl),2m(uboot),1m(env),-(rootfs)
+Ventana > tftp ${loadaddr} u-boot.img && nand erase.part uboot && \
+          nand write ${loadaddr} uboot ${filesize}
 
-There are several Gateworks Ventana boards that share a simliar design but
-vary based on CPU, Memory configuration, and subloaded devices.  Although
-the subloaded devices are handled dynamically in the bootloader using
-factory configured EEPROM data to modify the device-tree, the CPU choice
-(IMX6Q vs IMX6DL) and memory configurations are currently compile-time
-options.
+Linux:
+nandwrite /dev/mtd1 u-boot.img
 
-The following Gateworks Ventana configurations exist:
- gwventanaq1gspi: MX6Q,1GB,SPI FLASH
- gwventanaq     : MX6Q,512MB,NAND FLASH
- gwventanaq1g   : MX6Q,1GB,NAND FLASH
- gwventanadl    : MX6DL,512MB,NAND FLASH
- gwventanadl1g  : MX6DL,1GB,NAND FLASH
+The above assumes the default Ventana partitioning scheme which is configured
+via the mtdparts env var:
+ - spl: 14MB
+ - uboot: 2M
+ - env: 1M
+ - rootfs: the rest
 
-To build U-Boot for the MX6Q,1GB,NAND FLASH for example:
+This information is taken from:
+  http://trac.gateworks.com/wiki/ventana/bootloader#NANDFLASH
 
- make gwventanaq1g_config
- make
+More details about the i.MX6 BOOT ROM can be found in the IMX6 reference manual.
 
diff --git a/board/gateworks/gw_ventana/gw_ventana.c b/board/gateworks/gw_ventana/gw_ventana.c
index 584762f..ee2b203 100644
--- a/board/gateworks/gw_ventana/gw_ventana.c
+++ b/board/gateworks/gw_ventana/gw_ventana.c
@@ -927,8 +927,7 @@  int board_early_init_f(void)
 
 int dram_init(void)
 {
-	gd->ram_size = get_ram_size((void *)PHYS_SDRAM,
-				    CONFIG_DDR_MB*1024*1024);
+	gd->ram_size = imx_ddr_size();
 	return 0;
 }
 
@@ -1071,9 +1070,11 @@  int misc_init_r(void)
 		 * env scripts will try loading each from most specific to
 		 * least.
 		 */
-		if (is_cpu_type(MXC_CPU_MX6Q))
+		if (is_cpu_type(MXC_CPU_MX6Q) ||
+		    is_cpu_type(MXC_CPU_MX6D))
 			cputype = "imx6q";
-		else if (is_cpu_type(MXC_CPU_MX6DL))
+		else if (is_cpu_type(MXC_CPU_MX6DL) ||
+			 is_cpu_type(MXC_CPU_MX6SOLO))
 			cputype = "imx6dl";
 		memset(str, 0, sizeof(str));
 		for (i = 0; i < (sizeof(str)-1) && info->model[i]; i++)
diff --git a/board/gateworks/gw_ventana/gw_ventana.cfg b/board/gateworks/gw_ventana/gw_ventana.cfg
index 27f0974..9ab95f5 100644
--- a/board/gateworks/gw_ventana/gw_ventana.cfg
+++ b/board/gateworks/gw_ventana/gw_ventana.cfg
@@ -24,21 +24,6 @@  BOOT_FROM      nand
 
 #define __ASSEMBLY__
 #include <config.h>
-#include "asm/arch/mx6-ddr.h"
 #include "asm/arch/iomux.h"
 #include "asm/arch/crm_regs.h"
-
-/* Memory configuration (size is overridden via eeprom config) */
-#include "../../boundary/nitrogen6x/ddr-setup.cfg"
-#if defined(CONFIG_MX6Q) && CONFIG_DDR_MB == 1024
-  #include "../../boundary/nitrogen6x/1066mhz_4x128mx16.cfg"
-#elif defined(CONFIG_MX6DL) && CONFIG_DDR_MB == 1024
-  #include "../../boundary/nitrogen6x/800mhz_4x128mx16.cfg"
-#elif defined(CONFIG_MX6DL) && CONFIG_DDR_MB == 512
-  #include "../../boundary/nitrogen6x/800mhz_2x128mx16.cfg"
-#elif defined(CONFIG_MX6Q) && CONFIG_DDR_MB == 512
-  #include "../../boundary/nitrogen6x/800mhz_2x128mx16.cfg"
-#else
-  #error "Unsupported CPU/Memory configuration"
-#endif
 #include "clocks.cfg"
diff --git a/board/gateworks/gw_ventana/gw_ventana_spl.c b/board/gateworks/gw_ventana/gw_ventana_spl.c
new file mode 100644
index 0000000..d6c99f8
--- /dev/null
+++ b/board/gateworks/gw_ventana/gw_ventana_spl.c
@@ -0,0 +1,407 @@ 
+/*
+ * Copyright (C) 2014 Gateworks Corporation
+ * Author: Tim Harvey <tharvey@gateworks.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-ddr.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <spl.h>
+
+#include "ventana_eeprom.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define RTT_NOM_120OHM /* use 120ohm Rtt_nom vs 60ohm (lower power) */
+#define I2C_GSC			0
+#define GSC_EEPROM_ADDR		0x51
+#define GSC_EEPROM_DDR_SIZE	0x2B	/* enum (512,1024,2048) MB */
+#define GSC_EEPROM_DDR_WIDTH	0x2D	/* enum (32,64) bit */
+#define I2C_PAD_CTRL  (PAD_CTL_PUS_100K_UP |                    \
+	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS |   \
+	PAD_CTL_ODE | PAD_CTL_SRE_FAST)
+#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
+#define CONFIG_SYS_I2C_SPEED	100000
+
+/* I2C1: GSC */
+static struct i2c_pads_info mx6q_i2c_pad_info0 = {
+	.scl = {
+		.i2c_mode = MX6Q_PAD_EIM_D21__I2C1_SCL | PC,
+		.gpio_mode = MX6Q_PAD_EIM_D21__GPIO3_IO21 | PC,
+		.gp = IMX_GPIO_NR(3, 21)
+	},
+	.sda = {
+		.i2c_mode = MX6Q_PAD_EIM_D28__I2C1_SDA | PC,
+		.gpio_mode = MX6Q_PAD_EIM_D28__GPIO3_IO28 | PC,
+		.gp = IMX_GPIO_NR(3, 28)
+	}
+};
+static struct i2c_pads_info mx6dl_i2c_pad_info0 = {
+	.scl = {
+		.i2c_mode = MX6DL_PAD_EIM_D21__I2C1_SCL | PC,
+		.gpio_mode = MX6DL_PAD_EIM_D21__GPIO3_IO21 | PC,
+		.gp = IMX_GPIO_NR(3, 21)
+	},
+	.sda = {
+		.i2c_mode = MX6DL_PAD_EIM_D28__I2C1_SDA | PC,
+		.gpio_mode = MX6DL_PAD_EIM_D28__GPIO3_IO28 | PC,
+		.gp = IMX_GPIO_NR(3, 28)
+	}
+};
+
+static void i2c_setup_iomux(void)
+{
+	if (is_cpu_type(MXC_CPU_MX6Q))
+		setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6q_i2c_pad_info0);
+	else
+		setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6dl_i2c_pad_info0);
+}
+
+/* configure MX6Q/DUAL mmdc DDR io registers */
+struct mx6dq_iomux_ddr_regs mx6dq_ddr_ioregs = {
+	/* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */
+	.dram_sdclk_0 = 0x00020030,
+	.dram_sdclk_1 = 0x00020030,
+	.dram_cas = 0x00020030,
+	.dram_ras = 0x00020030,
+	.dram_reset = 0x00020030,
+	/* SDCKE[0:1]: 100k pull-up */
+	.dram_sdcke0 = 0x00003000,
+	.dram_sdcke1 = 0x00003000,
+	/* SDBA2: pull-up disabled */
+	.dram_sdba2 = 0x00000000,
+	/* SDODT[0:1]: 100k pull-up, 40 ohm */
+	.dram_sdodt0 = 0x00003030,
+	.dram_sdodt1 = 0x00003030,
+	/* SDQS[0:7]: Differential input, 40 ohm */
+	.dram_sdqs0 = 0x00000030,
+	.dram_sdqs1 = 0x00000030,
+	.dram_sdqs2 = 0x00000030,
+	.dram_sdqs3 = 0x00000030,
+	.dram_sdqs4 = 0x00000030,
+	.dram_sdqs5 = 0x00000030,
+	.dram_sdqs6 = 0x00000030,
+	.dram_sdqs7 = 0x00000030,
+
+	/* DQM[0:7]: Differential input, 40 ohm */
+	.dram_dqm0 = 0x00020030,
+	.dram_dqm1 = 0x00020030,
+	.dram_dqm2 = 0x00020030,
+	.dram_dqm3 = 0x00020030,
+	.dram_dqm4 = 0x00020030,
+	.dram_dqm5 = 0x00020030,
+	.dram_dqm6 = 0x00020030,
+	.dram_dqm7 = 0x00020030,
+};
+
+/* configure MX6Q/DUAL mmdc GRP io registers */
+struct mx6dq_iomux_grp_regs mx6dq_grp_ioregs = {
+	/* DDR3 */
+	.grp_ddr_type = 0x000c0000,
+	.grp_ddrmode_ctl = 0x00020000,
+	/* disable DDR pullups */
+	.grp_ddrpke = 0x00000000,
+	/* ADDR[00:16], SDBA[0:1]: 40 ohm */
+	.grp_addds = 0x00000030,
+	/* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */
+	.grp_ctlds = 0x00000030,
+	/* DATA[00:63]: Differential input, 40 ohm */
+	.grp_ddrmode = 0x00020000,
+	.grp_b0ds = 0x00000030,
+	.grp_b1ds = 0x00000030,
+	.grp_b2ds = 0x00000030,
+	.grp_b3ds = 0x00000030,
+	.grp_b4ds = 0x00000030,
+	.grp_b5ds = 0x00000030,
+	.grp_b6ds = 0x00000030,
+	.grp_b7ds = 0x00000030,
+};
+
+/* configure MX6SOLO/DUALLITE mmdc DDR io registers */
+struct mx6sdl_iomux_ddr_regs mx6sdl_ddr_ioregs = {
+	/* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */
+	.dram_sdclk_0 = 0x00020030,
+	.dram_sdclk_1 = 0x00020030,
+	.dram_cas = 0x00020030,
+	.dram_ras = 0x00020030,
+	.dram_reset = 0x00020030,
+	/* SDCKE[0:1]: 100k pull-up */
+	.dram_sdcke0 = 0x00003000,
+	.dram_sdcke1 = 0x00003000,
+	/* SDBA2: pull-up disabled */
+	.dram_sdba2 = 0x00000000,
+	/* SDODT[0:1]: 100k pull-up, 40 ohm */
+	.dram_sdodt0 = 0x00003030,
+	.dram_sdodt1 = 0x00003030,
+	/* SDQS[0:7]: Differential input, 40 ohm */
+	.dram_sdqs0 = 0x00000030,
+	.dram_sdqs1 = 0x00000030,
+	.dram_sdqs2 = 0x00000030,
+	.dram_sdqs3 = 0x00000030,
+	.dram_sdqs4 = 0x00000030,
+	.dram_sdqs5 = 0x00000030,
+	.dram_sdqs6 = 0x00000030,
+	.dram_sdqs7 = 0x00000030,
+
+	/* DQM[0:7]: Differential input, 40 ohm */
+	.dram_dqm0 = 0x00020030,
+	.dram_dqm1 = 0x00020030,
+	.dram_dqm2 = 0x00020030,
+	.dram_dqm3 = 0x00020030,
+	.dram_dqm4 = 0x00020030,
+	.dram_dqm5 = 0x00020030,
+	.dram_dqm6 = 0x00020030,
+	.dram_dqm7 = 0x00020030,
+};
+
+/* configure MX6SOLO/DUALLITE mmdc GRP io registers */
+struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = {
+	/* DDR3 */
+	.grp_ddr_type = 0x000c0000,
+	/* SDQS[0:7]: Differential input, 40 ohm */
+	.grp_ddrmode_ctl = 0x00020000,
+	/* disable DDR pullups */
+	.grp_ddrpke = 0x00000000,
+	/* ADDR[00:16], SDBA[0:1]: 40 ohm */
+	.grp_addds = 0x00000030,
+	/* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */
+	.grp_ctlds = 0x00000030,
+	/* DATA[00:63]: Differential input, 40 ohm */
+	.grp_ddrmode = 0x00020000,
+	.grp_b0ds = 0x00000030,
+	.grp_b1ds = 0x00000030,
+	.grp_b2ds = 0x00000030,
+	.grp_b3ds = 0x00000030,
+	.grp_b4ds = 0x00000030,
+	.grp_b5ds = 0x00000030,
+	.grp_b6ds = 0x00000030,
+	.grp_b7ds = 0x00000030,
+};
+
+/* MT41K128M16JT-125 */
+static struct mx6_ddr3_cfg mt41k128m16jt_125 = {
+	.mem_speed = 1600,
+	.density = 2,
+	.width = 16,
+	.banks = 8,
+	.rowaddr = 14,
+	.coladdr = 10,
+	.pagesz = 2,
+	.trcd = 1375,
+	.trcmin = 4875,
+	.trasmin = 3500,
+};
+
+/* GW54xx specific calibration */
+static struct mx6_mmdc_calibration gw54xxq_mmdc_calib = {
+	/* write leveling calibration determine */
+	.p0_mpwldectrl0 = 0x00190018,
+	.p0_mpwldectrl1 = 0x0021001D,
+	.p1_mpwldectrl0 = 0x00160027,
+	.p1_mpwldectrl1 = 0x0012001E,
+	/* Read DQS Gating calibration */
+	.p0_mpdgctrl0 = 0x43370346,
+	.p0_mpdgctrl1 = 0x032A0321,
+	.p1_mpdgctrl0 = 0x433A034D,
+	.p1_mpdgctrl1 = 0x032F0235,
+	/* Read Calibration: DQS delay relative to DQ read access */
+	.p0_mprddlctl = 0x3C313539,
+	.p1_mprddlctl = 0x37333140,
+	/* Write Calibration: DQ/DM delay relative to DQS write access */
+	.p0_mpwrdlctl = 0x37393C38,
+	.p1_mpwrdlctl = 0x42334538,
+};
+
+/* GW53xx specific calibration */
+static struct mx6_mmdc_calibration gw53xxq_mmdc_calib = {
+	/* write leveling calibration determine */
+	.p0_mpwldectrl0 = 0x00160013,
+	.p0_mpwldectrl1 = 0x00090024,
+	.p1_mpwldectrl0 = 0x001F0018,
+	.p1_mpwldectrl1 = 0x000C001C,
+	/* Read DQS Gating calibration */
+	.p0_mpdgctrl0 = 0x433A034C,
+	.p0_mpdgctrl1 = 0x0336032F,
+	.p1_mpdgctrl0 = 0x4343034A,
+	.p1_mpdgctrl1 = 0x03370222,
+	/* Read Calibration: DQS delay relative to DQ read access */
+	.p0_mprddlctl = 0x3F343638,
+	.p1_mprddlctl = 0x38373442,
+	/* Write Calibration: DQ/DM delay relative to DQS write access */
+	.p0_mpwrdlctl = 0x343A3E39,
+	.p1_mpwrdlctl = 0x44344239,
+};
+static struct mx6_mmdc_calibration gw53xxdl_mmdc_calib = {
+	/* write leveling calibration determine */
+	.p0_mpwldectrl0 = 0x003C003C,
+	.p0_mpwldectrl1 = 0x00330038,
+	.p1_mpwldectrl0 = 0x001F002A,
+	.p1_mpwldectrl1 = 0x0022003F,
+	/* Read DQS Gating calibration */
+	.p0_mpdgctrl0 = 0x42410244,
+	.p0_mpdgctrl1 = 0x022D022D,
+	.p1_mpdgctrl0 = 0x4234023A,
+	.p1_mpdgctrl1 = 0x021C0228,
+	/* Read Calibration: DQS delay relative to DQ read access */
+	.p0_mprddlctl = 0x484A4C4B,
+	.p1_mprddlctl = 0x4B4D4E4B,
+	/* Write Calibration: DQ/DM delay relative to DQS write access */
+	.p0_mpwrdlctl = 0x33342B32,
+	.p1_mpwrdlctl = 0x3933332B,
+};
+
+/* GW52xx specific calibration */
+static struct mx6_mmdc_calibration gw52xxdl_mmdc_calib = {
+	/* write leveling calibration determine */
+	.p0_mpwldectrl0 = 0x0040003F,
+	.p0_mpwldectrl1 = 0x00370037,
+	/* Read DQS Gating calibration */
+	.p0_mpdgctrl0 = 0x42420244,
+	.p0_mpdgctrl1 = 0x022F022F,
+	/* Read Calibration: DQS delay relative to DQ read access */
+	.p0_mprddlctl = 0x49464B4A,
+	/* Write Calibration: DQ/DM delay relative to DQS write access */
+	.p0_mpwrdlctl = 0x32362C32,
+};
+
+/* GW51xx specific calibration */
+static struct mx6_mmdc_calibration gw51xxq_mmdc_calib = {
+	/* write leveling calibration determine */
+	.p0_mpwldectrl0 = 0x00150016,
+	.p0_mpwldectrl1 = 0x001F0017,
+	/* Read DQS Gating calibration */
+	.p0_mpdgctrl0 = 0x433D034D,
+	.p0_mpdgctrl1 = 0x033D032F,
+	/* Read Calibration: DQS delay relative to DQ read access */
+	.p0_mprddlctl = 0x3F313639,
+	/* Write Calibration: DQ/DM delay relative to DQS write access */
+	.p0_mpwrdlctl = 0x33393F36,
+};
+
+static struct mx6_mmdc_calibration gw51xxdl_mmdc_calib = {
+	/* write leveling calibration determine */
+	.p0_mpwldectrl0 = 0x003D003F,
+	.p0_mpwldectrl1 = 0x002F0038,
+	/* Read DQS Gating calibration */
+	.p0_mpdgctrl0 = 0x423A023A,
+	.p0_mpdgctrl1 = 0x022A0228,
+	/* Read Calibration: DQS delay relative to DQ read access */
+	.p0_mprddlctl = 0x48494C4C,
+	/* Write Calibration: DQ/DM delay relative to DQS write access */
+	.p0_mpwrdlctl = 0x34352D31,
+};
+
+static void spl_dram_init(int width, int size, int board_model)
+{
+	struct mx6_ddr3_cfg *mem = &mt41k128m16jt_125;
+	struct mx6_mmdc_calibration *calib;
+	struct mx6_ddr_sysinfo sysinfo = {
+		/* width of data bus:0=16,1=32,2=64 */
+		.dsize = width/32,
+		/* config for full 4GB range so that get_mem_size() works */
+		.cs_density = 32, /* 32Gb per CS */
+		/* single chip select */
+		.ncs = 1,
+		.cs1_mirror = 0,
+		.rtt_wr = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Wr = RZQ/4 */
+#ifdef RTT_NOM_120OHM
+		.rtt_nom = 2 /*DDR3_RTT_120_OHM*/,	/* RTT_Nom = RZQ/2 */
+#else
+		.rtt_nom = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Nom = RZQ/4 */
+#endif
+		.walat = 1,	/* Write additional latency */
+		.ralat = 5,	/* Read additional latency */
+		.mif3_mode = 3,	/* Command prediction working mode */
+		.bi_on = 1,	/* Bank interleaving enabled */
+		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
+		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+	};
+
+	/*
+	 * MMDC Calibration requires the following data:
+	 *   mx6_mmdc_calibration - board-specific calibration (routing delays)
+	 *   mx6_ddr_sysinfo - board-specific memory architecture (width/cs/etc)
+	 *   mx6_ddr_cfg - chip specific timing/layout details
+	 */
+	switch (board_model) {
+	default:
+	case GW51xx:
+		if (is_cpu_type(MXC_CPU_MX6Q))
+			calib = &gw51xxq_mmdc_calib;
+		else
+			calib = &gw51xxdl_mmdc_calib;
+		break;
+	case GW52xx:
+		calib = &gw52xxdl_mmdc_calib;
+		break;
+	case GW53xx:
+		if (is_cpu_type(MXC_CPU_MX6Q))
+			calib = &gw53xxq_mmdc_calib;
+		else
+			calib = &gw53xxdl_mmdc_calib;
+		break;
+	case GW54xx:
+		calib = &gw54xxq_mmdc_calib;
+		break;
+	}
+
+	if (is_cpu_type(MXC_CPU_MX6Q))
+		mx6dq_dram_iocfg(width, &mx6dq_ddr_ioregs,
+				 &mx6dq_grp_ioregs);
+	else
+		mx6sdl_dram_iocfg(width, &mx6sdl_ddr_ioregs,
+				  &mx6sdl_grp_ioregs);
+	mx6_dram_cfg(&sysinfo, calib, mem);
+}
+
+/*
+ * called from C runtime startup code (arch/arm/lib/crt0.S:_main)
+ * - we have a stack and a place to store GD, both in SRAM
+ * - no variable global data is available
+ */
+void board_init_f(ulong dummy)
+{
+	struct ventana_board_info ventana_info;
+	int board_model;
+
+	/* iomux and setup of i2c */
+	i2c_setup_iomux();
+	timer_init();
+	board_model = read_eeprom(I2C_GSC, &ventana_info);
+
+	/* provide some some default: 32bit 128MB */
+	if (GW_UNKNOWN == board_model) {
+		ventana_info.sdram_width = 2;
+		ventana_info.sdram_size = 3;
+	}
+	spl_dram_init(8 << ventana_info.sdram_width,
+		      16 << ventana_info.sdram_size,
+		      board_model);
+
+	arch_cpu_init();
+
+	/* Clear the BSS. */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	/* Set global data pointer. */
+	gd = &gdata;
+
+	board_early_init_f();
+
+	preloader_console_init();
+
+	board_init_r(NULL, 0);
+}
+
+void reset_cpu(ulong addr)
+{
+}
diff --git a/boards.cfg b/boards.cfg
index c83aff3..9119e24 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -322,11 +322,7 @@  Active  arm         armv7          mx6         freescale       mx6qsabreauto
 Active  arm         armv7          mx6         freescale       mx6sabresd          mx6dlsabresd                         mx6sabresd:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6dl.cfg,MX6DL                                                             Fabio Estevam <fabio.estevam@freescale.com>
 Active  arm         armv7          mx6         freescale       mx6sabresd          mx6qsabresd                          mx6sabresd:IMX_CONFIG=board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg,MX6Q                                                           Fabio Estevam <fabio.estevam@freescale.com>
 Active  arm         armv7          mx6         freescale       mx6slevk            mx6slevk                             mx6slevk:IMX_CONFIG=board/freescale/mx6slevk/imximage.cfg,MX6SL                                                                   Fabio Estevam <fabio.estevam@freescale.com>
-Active  arm         armv7          mx6         gateworks       gw_ventana          gwventanadl                          gw_ventana:IMX_CONFIG=board/gateworks/gw_ventana/gw_ventana.cfg,MX6DL,DDR_MB=512                                                  Tim Harvey <tharvey@gateworks.com>
-Active  arm         armv7          mx6         gateworks       gw_ventana          gwventanadl1g                        gw_ventana:IMX_CONFIG=board/gateworks/gw_ventana/gw_ventana.cfg,MX6DL,DDR_MB=1024                                                 Tim Harvey <tharvey@gateworks.com>
-Active  arm         armv7          mx6         gateworks       gw_ventana          gwventanaq                           gw_ventana:IMX_CONFIG=board/gateworks/gw_ventana/gw_ventana.cfg,MX6Q,DDR_MB=512                                                   Tim Harvey <tharvey@gateworks.com>
-Active  arm         armv7          mx6         gateworks       gw_ventana          gwventanaq1g                         gw_ventana:IMX_CONFIG=board/gateworks/gw_ventana/gw_ventana.cfg,MX6Q,DDR_MB=1024                                                  Tim Harvey <tharvey@gateworks.com>
-Active  arm         armv7          mx6         gateworks       gw_ventana          gwventanaq1gspi                      gw_ventana:IMX_CONFIG=board/gateworks/gw_ventana/gw_ventana.cfg,MX6Q,DDR_MB=1024,SPI_FLASH                                        Tim Harvey <tharvey@gateworks.com>
+Active  arm         armv7          mx6         gateworks       gw_ventana          gwventana                            gw_ventana:IMX_CONFIG=board/gateworks/gw_ventana/gw_ventana.cfg,MX6QDL,SPL                                                  Tim Harvey <tharvey@gateworks.com>
 Active  arm         armv7          mx6         solidrun        hummingboard        hummingboard_solo                    hummingboard:IMX_CONFIG=board/solidrun/hummingboard/solo.cfg,MX6S,DDR_MB=512                                                      Jon Nettleton <jon.nettleton@gmail.com>
 Active  arm         armv7          omap3       -               overo               omap3_overo                          -                                                                                                                                 Steve Sakoman <sakoman@gmail.com>
 Active  arm         armv7          omap3       -               pandora             omap3_pandora                        -                                                                                                                                 Grazvydas Ignotas <notasas@gmail.com>
diff --git a/include/configs/gw_ventana.h b/include/configs/gw_ventana.h
index 3398390..cd53737 100644
--- a/include/configs/gw_ventana.h
+++ b/include/configs/gw_ventana.h
@@ -7,6 +7,17 @@ 
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
+/* SPL */
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SPL_FAT_SUPPORT
+/*
+#define CONFIG_SPL_SATA_SUPPORT
+*/
+/* Location in NAND to read U-Boot from */
+#define CONFIG_SYS_NAND_U_BOOT_OFFS     (14 * 1024 * 1024)
+
+#include "imx6_spl.h"                  /* common IMX6 SPL configuration */
 #include "mx6_common.h"
 #define CONFIG_MX6
 #define CONFIG_DISPLAY_CPUINFO         /* display cpu info */