Message ID | 1396504871-1454-12-git-send-email-tharvey@gateworks.com |
---|---|
State | Changes Requested |
Delegated to: | Stefano Babic |
Headers | show |
On Wed, Apr 2, 2014 at 11:01 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 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> > --- <snip> > 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..492c814 > --- /dev/null > +++ b/board/gateworks/gw_ventana/gw_ventana_spl.c > @@ -0,0 +1,394 @@ > +/* > + * 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_regs.h> this header is non-existent and the include should be removed. I left this in by accident. Tim
Hi Tim, On 03/04/2014 08:01, Tim Harvey 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 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> > --- > board/gateworks/gw_ventana/Makefile | 2 +- > board/gateworks/gw_ventana/README | 91 +++--- > board/gateworks/gw_ventana/gw_ventana.c | 5 +- > board/gateworks/gw_ventana/gw_ventana.cfg | 15 - > board/gateworks/gw_ventana/gw_ventana_spl.c | 394 ++++++++++++++++++++++++++ > board/gateworks/gw_ventana/gw_ventana_spl.cfg | 29 ++ > boards.cfg | 6 +- > include/config/uboot.release | 1 + > include/configs/gw_ventana.h | 13 +- > 9 files changed, 500 insertions(+), 56 deletions(-) > create mode 100644 board/gateworks/gw_ventana/gw_ventana_spl.c > create mode 100644 board/gateworks/gw_ventana/gw_ventana_spl.cfg > create mode 100644 include/config/uboot.release > > diff --git a/board/gateworks/gw_ventana/Makefile b/board/gateworks/gw_ventana/Makefile > index e8dab89..8b239ae 100644 > --- a/board/gateworks/gw_ventana/Makefile > +++ b/board/gateworks/gw_ventana/Makefile > @@ -6,5 +6,5 @@ > # SPDX-License-Identifier: GPL-2.0+ > # > > -obj-y := gw_ventana.o gsc.o > +obj-y := gw_ventana.o gsc.o gw_ventana_spl.o I think that gw_ventana_spl.o is always built. Should we use instead : obj-$(CONFIG_SPL_BUILD) += gw_ventana_spl.o > > diff --git a/board/gateworks/gw_ventana/README b/board/gateworks/gw_ventana/README > index 9e697d6..c45d4b8 100644 > --- a/board/gateworks/gw_ventana/README > +++ b/board/gateworks/gw_ventana/README > @@ -3,53 +3,80 @@ 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 Line too long ? > +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 ebf7e7d..7508141 100644 > --- a/board/gateworks/gw_ventana/gw_ventana.c > +++ b/board/gateworks/gw_ventana/gw_ventana.c > @@ -1019,8 +1019,9 @@ int board_early_init_f(void) > > int dram_init(void) > { > - gd->ram_size = get_ram_size((void *)PHYS_SDRAM, > - CONFIG_DDR_MB*1024*1024); > + struct mx6_spl_data *data = (struct mx6_spl_data *) > + ((CONFIG_SPL_TEXT_BASE - sizeof(struct mx6_spl_data)) & ~0xf); Ok, you have *data on the stack, you initialize to a magic number and then you do nothing with it. > + gd->ram_size = data->mem_dram_size; We have already talked about it. A runtime detection is absolutely preferable, as suggested by Igor. > > return 0; > } > 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" Right - this is what I have expected for the .cfg file adding SPL. > 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..492c814 > --- /dev/null > +++ b/board/gateworks/gw_ventana/gw_ventana_spl.c > @@ -0,0 +1,394 @@ > +/* > + * 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_regs.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> > +#ifdef CONFIG_SPL > +#include <spl.h> > +#endif > + > +DECLARE_GLOBAL_DATA_PTR; > + > +#if defined(CONFIG_SPL_BUILD) I will drop it from here and conditionally compile this file if SPL_BUILD is set. > + > +#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); > +} > + > +static u16 > +read_eeprom(void) > +{ > + u8 data[3]; > + > + /* > + * On a board with a missing/depleted backup battery for GSC, the > + * board may be ready to probe the GSC before its firmware is > + * running. We will wait here indefinately for the GSC/EEPROM. > + */ > + while (1) { > + if (0 == i2c_set_bus_num(I2C_GSC) && > + 0 == i2c_probe(GSC_EEPROM_ADDR)) > + break; > + /* TODO: mdelay hangs at this point > + mdelay(1); > + */ > + } > + > + i2c_read(GSC_EEPROM_ADDR, GSC_EEPROM_DDR_SIZE, 1, data, 3); > + > + return (data[0] << 8) | data[2]; > +} This is a simplified version of the same function in gw_ventana.c. By submitting the original patch, you convinced me that due to hardware issues the read can fails the first time and you add gsc_i2c_read(). Why do we have no problem with i2c in SPL ? It should be even worse. > + > +/* configure mx6 mmdc io registers */ > +struct mx6_mmdc_ioregs mmdc_ioregs = { > + /* DDR3 */ > + .mmdc_grp_ddr_type = 0x000c0000, > + /* disable DDR pullups */ > + .mmdc_grp_ddrpke = 0x00000000, > + /* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */ > + .mmdc_dram_sdclk_0 = 0x00020030, > + .mmdc_dram_sdclk_1 = 0x00020030, > + .mmdc_dram_cas = 0x00020030, > + .mmdc_dram_ras = 0x00020030, > + .mmdc_dram_reset = 0x00020030, > + /* ADDR[00:16], SDBA[0:1]: 40 ohm */ > + .mmdc_grp_addds = 0x00000030, > + /* SDCKE[0:1]: 100k pull-up */ > + .mmdc_dram_sdcke0 = 0x00003000, > + .mmdc_dram_sdcke1 = 0x00003000, > + /* SDBA2: pull-up disabled */ > + .mmdc_dram_sdba2 = 0x00000000, > + /* SDODT[0:1]: 100k pull-up, 40 ohm */ > + .mmdc_dram_sdodt0 = 0x00003030, > + .mmdc_dram_sdodt1 = 0x00003030, > + /* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */ > + .mmdc_grp_ctlds = 0x00000030, > + /* SDQS[0:7]: Differential input, 40 ohm */ > + .mmdc_ddrmode_ctl = 0x00020000, > + .mmdc_dram_sdqs0 = 0x00000030, > + .mmdc_dram_sdqs1 = 0x00000030, > + .mmdc_dram_sdqs2 = 0x00000030, > + .mmdc_dram_sdqs3 = 0x00000030, > + .mmdc_dram_sdqs4 = 0x00000030, > + .mmdc_dram_sdqs5 = 0x00000030, > + .mmdc_dram_sdqs6 = 0x00000030, > + .mmdc_dram_sdqs7 = 0x00000030, > + > + /* DATA[00:63]: Differential input, 40 ohm */ > + .mmdc_grp_ddrmode = 0x00020000, > + .mmdc_grp_b0ds = 0x00000030, > + .mmdc_grp_b1ds = 0x00000030, > + .mmdc_grp_b2ds = 0x00000030, > + .mmdc_grp_b3ds = 0x00000030, > + .mmdc_grp_b4ds = 0x00000030, > + .mmdc_grp_b5ds = 0x00000030, > + .mmdc_grp_b6ds = 0x00000030, > + .mmdc_grp_b7ds = 0x00000030, > + > + /* DQM[0:7]: Differential input, 40 ohm */ > + .mmdc_dram_dqm0 = 0x00020030, > + .mmdc_dram_dqm1 = 0x00020030, > + .mmdc_dram_dqm2 = 0x00020030, > + .mmdc_dram_dqm3 = 0x00020030, > + .mmdc_dram_dqm4 = 0x00020030, > + .mmdc_dram_dqm5 = 0x00020030, > + .mmdc_dram_dqm6 = 0x00020030, > + .mmdc_dram_dqm7 = 0x00020030, > +}; I will suggest you move these structure in a separate file. It is then easier for a board developer to understand what is very board specific. > + > +/* 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 gw54xx_mmdc_calibration = { > + /* write leveling calibration determine */ > + .mmdc_p0_mpwldectrl0 = 0x00210021, > + .mmdc_p0_mpwldectrl1 = 0x00284024, > + .mmdc_p1_mpwldectrl0 = 0x0018002b, > + .mmdc_p1_mpwldectrl1 = 0x000c801f, > + /* Read DQS Gating calibration */ > + .mmdc_p0_mpdgctrl0 = 0x43430354, > + .mmdc_p0_mpdgctrl1 = 0x034e0344, > + .mmdc_p1_mpdgctrl0 = 0x43500359, > + .mmdc_p1_mpdgctrl1 = 0x034b031c, > + /* Read Calibration: DQS delay relative to DQ read access */ > + .mmdc_p0_mprddlctl = 0x3e363abe, > + .mmdc_p1_mprddlctl = 0x35b23040, > + /* Write Calibration: DQ/DM delay relative to DQS write access */ > + .mmdc_p0_mpwrdlctl = 0x3839403c, > + .mmdc_p1_mpwrdlctl = 0x45b6483c, > +}; > + > +/* GW53xx specific calibration */ > +static struct mx6_mmdc_calibration gw53xx_mmdc_calibration = { > + /* write leveling calibration determine */ > + .mmdc_p0_mpwldectrl0 = 0x007c007e, > + .mmdc_p0_mpwldectrl1 = 0x003b007c, > + .mmdc_p1_mpwldectrl0 = 0x001f002b, > + .mmdc_p1_mpwldectrl1 = 0x003f003f, > + /* Read DQS Gating calibration */ > + .mmdc_p0_mpdgctrl0 = 0x42550254, > + .mmdc_p0_mpdgctrl1 = 0x023d023d, > + .mmdc_p1_mpdgctrl0 = 0x423c027e, > + .mmdc_p1_mpdgctrl1 = 0x021c0238, > + /* Read Calibration: DQS delay relative to DQ read access */ > + .mmdc_p0_mprddlctl = 0x484a4e4b, > + .mmdc_p1_mprddlctl = 0x4b4d4e4b, > + /* Write Calibration: DQ/DM delay relative to DQS write access */ > + .mmdc_p0_mpwrdlctl = 0x37342f32, > + .mmdc_p1_mpwrdlctl = 0x3f33372b, > +}; > + > +/* GW52xx specific calibration */ > +static struct mx6_mmdc_calibration gw52xx_mmdc_calibration = { > + /* write leveling calibration determine */ > + .mmdc_p0_mpwldectrl0 = 0x0040003C, > + .mmdc_p0_mpwldectrl1 = 0x0032003E, > + /* Read DQS Gating calibration */ > + .mmdc_p0_mpdgctrl0 = 0x42350231, > + .mmdc_p0_mpdgctrl1 = 0x021A0218, > + /* Read Calibration: DQS delay relative to DQ read access */ > + .mmdc_p0_mprddlctl = 0x4B4B4E49, > + /* Write Calibration: DQ/DM delay relative to DQS write access */ > + .mmdc_p0_mpwrdlctl = 0x3F3F3035, > +}; > + > +/* GW51xx specific calibration */ > +static struct mx6_mmdc_calibration gw51xx_mmdc_calibration = { > + /* write leveling calibration determine */ > + .mmdc_p0_mpwldectrl0 = 0x0040003C, > + .mmdc_p0_mpwldectrl1 = 0x0032003E, > + /* Read DQS Gating calibration */ > + .mmdc_p0_mpdgctrl0 = 0x42350231, > + .mmdc_p0_mpdgctrl1 = 0x021A0218, > + /* Read Calibration: DQS delay relative to DQ read access */ > + .mmdc_p0_mprddlctl = 0x4B4B4E49, > + /* Write Calibration: DQ/DM delay relative to DQS write access */ > + .mmdc_p0_mpwrdlctl = 0x3F3F3035, > +}; > + > +static void spl_dram_init(int ddr_cfg) > +{ > + struct mx6_spl_data *data = (struct mx6_spl_data *) > + ((CONFIG_SPL_TEXT_BASE - sizeof(struct mx6_spl_data)) & ~0xf); > + u32 cpurev, imxtype; > + int width, size; > + struct mx6_ddr3_cfg *mem = &mt41k128m16jt_125; > + struct mx6_mmdc_calibration *calib; > + struct mx6_ddr_sysinfo sysinfo = { > + .dsize = (8 << (ddr_cfg & 0xff))/32, > + .cs_density = (16 << (ddr_cfg>>8))/128, > + /* 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) */ > + }; > + u8 model[16]; > + > + i2c_read(GSC_EEPROM_ADDR, 0x30, 1, model, 16); > + debug("model:%s\n", model); > + > + /* > + * 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 (model[3]) { > + case '1': > + calib = &gw51xx_mmdc_calibration; > + break; > + case '2': > + calib = &gw52xx_mmdc_calibration; > + break; > + case '3': > + calib = &gw53xx_mmdc_calibration; > + break; > + default: > + case '4': > + calib = &gw54xx_mmdc_calibration; > + break; > + } > + > + cpurev = get_cpu_rev(); > + imxtype = (cpurev & 0xFF000) >> 12; > + size = (16 << (ddr_cfg >> 8)); > + width = (8 << (ddr_cfg & 0xff)); > + data->mem_dram_size = size * 1024 * 1024; > + > + get_imx_type(imxtype); > + > + switch (imxtype) { > + case MXC_CPU_MX6Q: > + mx6_dram_iocfg(width, &mx6dq_ctrl, &mmdc_ioregs); > + mx6_dram_cfg(&sysinfo, &mx6_ddrcfg, calib, mem); > + break; > + case MXC_CPU_MX6DL: > + default: > + mx6_dram_iocfg(width, &mx6sdl_ctrl, &mmdc_ioregs); > + mx6_dram_cfg(&sysinfo, &mx6_ddrcfg, calib, mem); > + break; > + } > +} > + > +/* > + * 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) > +{ > + int ddrcfg; > + > + /* iomux and setup of i2c */ > + i2c_setup_iomux(); > + > + /* TODO: possible to get console support at this point for debugging? */ > + timer_init(); > + ddrcfg = read_eeprom(); > + spl_dram_init(ddrcfg); > + > + 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(); > + > + if (is_cpu_type(MXC_CPU_MX6Q)) > + puts("CPU: IMX6Q\n"); > + else if (is_cpu_type(MXC_CPU_MX6DL)) > + puts("CPU: IMX6DL\n"); > + else > + puts("CPU: unsupported\n"); > + printf("SDRAM: %dMB %dbit\n", (16 << (ddrcfg>>8)), > + (8 << (ddrcfg & 0xff))); Really do we need this in SPL ? Is not enough in U-Boot ? > + > + board_init_r(NULL, 0); > +} Mmhhh...apart the access to the eeprom to get the ram size, this function should be common. > + > +/* called from board_init_r() to decide what spl_*_load_image() to call */ > +u32 spl_boot_device(void) > +{ > + puts("Boot Device: "); > + switch (get_boot_device()) { > + case MX6_MMC_BOOT: > + printf("uSD\n"); > + return BOOT_DEVICE_MMC1; > + case MX6_NAND_BOOT: > + printf("NAND\n"); > + return BOOT_DEVICE_NAND; > + case MX6_SATA_BOOT: > + printf("SATA\n"); > + return BOOT_DEVICE_SATA; > + default: > + printf("UNKNOWN\n"); > + return BOOT_DEVICE_NONE; > + } > +} This function (without unneeded printf) should be made common. Feel free to add a spl.c file inside ./arch/arm/imx-common > + > +#if defined(CONFIG_SPL_MMC_SUPPORT) > +/* called from spl_mmc to see type of boot mode for storage (RAW or FAT) */ > +u32 spl_boot_mode(void) > +{ > + switch (get_boot_device()) { > + /* for MMC return either RAW or FAT mode */ > + case BOOT_DEVICE_MMC1: > +#ifdef CONFIG_SPL_FAT_SUPPORT > + return MMCSD_MODE_FAT; > +#else > + return MMCSD_MODE_RAW; > +#endif > + break; > + default: > + puts("spl: ERROR: unsupported device\n"); > + hang(); > + } > +} > +#endif > + > +void reset_cpu(ulong addr) > +{ > +} > +#endif Ditto > + > diff --git a/board/gateworks/gw_ventana/gw_ventana_spl.cfg b/board/gateworks/gw_ventana/gw_ventana_spl.cfg > new file mode 100644 > index 0000000..9ab95f5 > --- /dev/null > +++ b/board/gateworks/gw_ventana/gw_ventana_spl.cfg > @@ -0,0 +1,29 @@ > +/* > + * Copyright (C) 2013 Gateworks Corporation > + * > + * SPDX-License-Identifier: GPL-2.0+ > + * > + * Refer doc/README.imximage for more details about how-to configure > + * and create imximage boot image > + * > + * The syntax is taken as close as possible with the kwbimage > + */ > + > +/* image version */ > +IMAGE_VERSION 2 > + > +/* > + * Boot Device : one of > + * spi, sd, nand, sata > + */ > +#ifdef CONFIG_SPI_FLASH > +BOOT_FROM spi > +#else > +BOOT_FROM nand > +#endif > + > +#define __ASSEMBLY__ > +#include <config.h> > +#include "asm/arch/iomux.h" > +#include "asm/arch/crm_regs.h" > +#include "clocks.cfg" Mmhhh...which is the reason to have gw_ventana.cfg and gw_ventana_spl.cfg ? You need the .cfg file to generate the IVT header only for SPL. It is not required for U-Boot, because the boot ROM has already processed the first i.MX header. > diff --git a/boards.cfg b/boards.cfg > index a7be5a3..aa48f89 100644 > --- a/boards.cfg > +++ b/boards.cfg > @@ -320,11 +320,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> Nice, only one entry for all of your boards. > 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/config/uboot.release b/include/config/uboot.release > new file mode 100644 > index 0000000..0e37110 > --- /dev/null > +++ b/include/config/uboot.release > @@ -0,0 +1 @@ > +2014.04-rc1-00227-g1879963-dirty > diff --git a/include/configs/gw_ventana.h b/include/configs/gw_ventana.h > index 3398390..f6dc52a 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_SATA_SUPPORT > +#define CONFIG_SPL_FAT_SUPPORT > +*/ > +/* Location in NAND to read U-Boot from */ > +#define CONFIG_SYS_NAND_U_BOOT_OFFS (14 * 1024 * 1024) This is ok - it is your decision where to put it. May I ask why do you need 14 MB at the beginning ? It seems you lose a lot of place. NAND is cheap nowadays, but... > + > +#include "imx6_spl.h" /* common IMX6 SPL configuration */ > #include "mx6_common.h" > #define CONFIG_MX6 > #define CONFIG_DISPLAY_CPUINFO /* display cpu info */ > @@ -242,7 +253,7 @@ > "mtdparts=nor:512k(uboot),64k(env),2m(kernel),-(rootfs)" > #else > #define MTDIDS_DEFAULT "nand0=nand" > -#define MTDPARTS_DEFAULT "mtdparts=nand:16m(uboot),1m(env),-(rootfs)" > +#define MTDPARTS_DEFAULT "mtdparts=nand:14m(spl),2m(uboot),1m(env),-(rootfs)" Best regards, Stefano Babic
On Wed, Apr 23, 2014 at 11:03 AM, Stefano Babic <sbabic@denx.de> wrote: > Hi Tim, Hi Stefano, > > On 03/04/2014 08:01, Tim Harvey 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 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> >> --- >> board/gateworks/gw_ventana/Makefile | 2 +- >> board/gateworks/gw_ventana/README | 91 +++--- >> board/gateworks/gw_ventana/gw_ventana.c | 5 +- >> board/gateworks/gw_ventana/gw_ventana.cfg | 15 - >> board/gateworks/gw_ventana/gw_ventana_spl.c | 394 ++++++++++++++++++++++++++ >> board/gateworks/gw_ventana/gw_ventana_spl.cfg | 29 ++ >> boards.cfg | 6 +- >> include/config/uboot.release | 1 + >> include/configs/gw_ventana.h | 13 +- >> 9 files changed, 500 insertions(+), 56 deletions(-) >> create mode 100644 board/gateworks/gw_ventana/gw_ventana_spl.c >> create mode 100644 board/gateworks/gw_ventana/gw_ventana_spl.cfg >> create mode 100644 include/config/uboot.release >> >> diff --git a/board/gateworks/gw_ventana/Makefile b/board/gateworks/gw_ventana/Makefile >> index e8dab89..8b239ae 100644 >> --- a/board/gateworks/gw_ventana/Makefile >> +++ b/board/gateworks/gw_ventana/Makefile >> @@ -6,5 +6,5 @@ >> # SPDX-License-Identifier: GPL-2.0+ >> # >> >> -obj-y := gw_ventana.o gsc.o >> +obj-y := gw_ventana.o gsc.o gw_ventana_spl.o > > I think that gw_ventana_spl.o is always built. Should we use instead : > > obj-$(CONFIG_SPL_BUILD) += gw_ventana_spl.o > yes, you are right. I will change this >> >> diff --git a/board/gateworks/gw_ventana/README b/board/gateworks/gw_ventana/README >> index 9e697d6..c45d4b8 100644 >> --- a/board/gateworks/gw_ventana/README >> +++ b/board/gateworks/gw_ventana/README >> @@ -3,53 +3,80 @@ 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 > > Line too long ? will fix > <snip> >> --- a/board/gateworks/gw_ventana/gw_ventana.c >> +++ b/board/gateworks/gw_ventana/gw_ventana.c >> @@ -1019,8 +1019,9 @@ int board_early_init_f(void) >> >> int dram_init(void) >> { >> - gd->ram_size = get_ram_size((void *)PHYS_SDRAM, >> - CONFIG_DDR_MB*1024*1024); >> + struct mx6_spl_data *data = (struct mx6_spl_data *) >> + ((CONFIG_SPL_TEXT_BASE - sizeof(struct mx6_spl_data)) & ~0xf); > > Ok, you have *data on the stack, you initialize to a magic number and > then you do nothing with it. > >> + gd->ram_size = data->mem_dram_size; > > We have already talked about it. A runtime detection is absolutely > preferable, as suggested by Igor. Yes, as discussed in the other thread I will be changing this to runtime detection and dropping the shared struct between SPL and u-boot.img. > >> >> return 0; >> } <snip> >> 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..492c814 >> --- /dev/null >> +++ b/board/gateworks/gw_ventana/gw_ventana_spl.c >> @@ -0,0 +1,394 @@ >> +/* >> + * 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_regs.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> >> +#ifdef CONFIG_SPL >> +#include <spl.h> >> +#endif >> + >> +DECLARE_GLOBAL_DATA_PTR; >> + >> +#if defined(CONFIG_SPL_BUILD) > > I will drop it from here and conditionally compile this file if > SPL_BUILD is set. Agreed - will do this > <snip> >> +static u16 >> +read_eeprom(void) >> +{ >> + u8 data[3]; >> + >> + /* >> + * On a board with a missing/depleted backup battery for GSC, the >> + * board may be ready to probe the GSC before its firmware is >> + * running. We will wait here indefinately for the GSC/EEPROM. >> + */ >> + while (1) { >> + if (0 == i2c_set_bus_num(I2C_GSC) && >> + 0 == i2c_probe(GSC_EEPROM_ADDR)) >> + break; >> + /* TODO: mdelay hangs at this point >> + mdelay(1); >> + */ >> + } >> + >> + i2c_read(GSC_EEPROM_ADDR, GSC_EEPROM_DDR_SIZE, 1, data, 3); >> + >> + return (data[0] << 8) | data[2]; >> +} > > This is a simplified version of the same function in gw_ventana.c. By > submitting the original patch, you convinced me that due to hardware > issues the read can fails the first time and you add gsc_i2c_read(). Why > do we have no problem with i2c in SPL ? It should be even worse. > You are absolutely right - I will split out the read_eeprom from gw_ventana.c and re-use it here as well. >> + >> +/* configure mx6 mmdc io registers */ >> +struct mx6_mmdc_ioregs mmdc_ioregs = { >> + /* DDR3 */ >> + .mmdc_grp_ddr_type = 0x000c0000, >> + /* disable DDR pullups */ >> + .mmdc_grp_ddrpke = 0x00000000, >> + /* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */ >> + .mmdc_dram_sdclk_0 = 0x00020030, >> + .mmdc_dram_sdclk_1 = 0x00020030, >> + .mmdc_dram_cas = 0x00020030, >> + .mmdc_dram_ras = 0x00020030, >> + .mmdc_dram_reset = 0x00020030, >> + /* ADDR[00:16], SDBA[0:1]: 40 ohm */ >> + .mmdc_grp_addds = 0x00000030, >> + /* SDCKE[0:1]: 100k pull-up */ >> + .mmdc_dram_sdcke0 = 0x00003000, >> + .mmdc_dram_sdcke1 = 0x00003000, >> + /* SDBA2: pull-up disabled */ >> + .mmdc_dram_sdba2 = 0x00000000, >> + /* SDODT[0:1]: 100k pull-up, 40 ohm */ >> + .mmdc_dram_sdodt0 = 0x00003030, >> + .mmdc_dram_sdodt1 = 0x00003030, >> + /* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */ >> + .mmdc_grp_ctlds = 0x00000030, >> + /* SDQS[0:7]: Differential input, 40 ohm */ >> + .mmdc_ddrmode_ctl = 0x00020000, >> + .mmdc_dram_sdqs0 = 0x00000030, >> + .mmdc_dram_sdqs1 = 0x00000030, >> + .mmdc_dram_sdqs2 = 0x00000030, >> + .mmdc_dram_sdqs3 = 0x00000030, >> + .mmdc_dram_sdqs4 = 0x00000030, >> + .mmdc_dram_sdqs5 = 0x00000030, >> + .mmdc_dram_sdqs6 = 0x00000030, >> + .mmdc_dram_sdqs7 = 0x00000030, >> + >> + /* DATA[00:63]: Differential input, 40 ohm */ >> + .mmdc_grp_ddrmode = 0x00020000, >> + .mmdc_grp_b0ds = 0x00000030, >> + .mmdc_grp_b1ds = 0x00000030, >> + .mmdc_grp_b2ds = 0x00000030, >> + .mmdc_grp_b3ds = 0x00000030, >> + .mmdc_grp_b4ds = 0x00000030, >> + .mmdc_grp_b5ds = 0x00000030, >> + .mmdc_grp_b6ds = 0x00000030, >> + .mmdc_grp_b7ds = 0x00000030, >> + >> + /* DQM[0:7]: Differential input, 40 ohm */ >> + .mmdc_dram_dqm0 = 0x00020030, >> + .mmdc_dram_dqm1 = 0x00020030, >> + .mmdc_dram_dqm2 = 0x00020030, >> + .mmdc_dram_dqm3 = 0x00020030, >> + .mmdc_dram_dqm4 = 0x00020030, >> + .mmdc_dram_dqm5 = 0x00020030, >> + .mmdc_dram_dqm6 = 0x00020030, >> + .mmdc_dram_dqm7 = 0x00020030, >> +}; > > I will suggest you move these structure in a separate file. It is then > easier for a board developer to understand what is very board specific. hmmm... they are all very board specific but ok. > <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) >> +{ >> + int ddrcfg; >> + >> + /* iomux and setup of i2c */ >> + i2c_setup_iomux(); >> + >> + /* TODO: possible to get console support at this point for debugging? */ >> + timer_init(); >> + ddrcfg = read_eeprom(); >> + spl_dram_init(ddrcfg); >> + >> + 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(); >> + >> + if (is_cpu_type(MXC_CPU_MX6Q)) >> + puts("CPU: IMX6Q\n"); >> + else if (is_cpu_type(MXC_CPU_MX6DL)) >> + puts("CPU: IMX6DL\n"); >> + else >> + puts("CPU: unsupported\n"); >> + printf("SDRAM: %dMB %dbit\n", (16 << (ddrcfg>>8)), >> + (8 << (ddrcfg & 0xff))); > > Really do we need this in SPL ? Is not enough in U-Boot ? not needed - I used it mainly for debugging and will remove it. > >> + >> + board_init_r(NULL, 0); >> +} > > Mmhhh...apart the access to the eeprom to get the ram size, this > function should be common. maybe, but I think we should wait to see what other boards come up with SPL support to see what actually ends up being common. An SPL that supports SPI or some of the other boot devices may need to do some additional things. > > >> + >> +/* called from board_init_r() to decide what spl_*_load_image() to call */ >> +u32 spl_boot_device(void) >> +{ >> + puts("Boot Device: "); >> + switch (get_boot_device()) { >> + case MX6_MMC_BOOT: >> + printf("uSD\n"); >> + return BOOT_DEVICE_MMC1; >> + case MX6_NAND_BOOT: >> + printf("NAND\n"); >> + return BOOT_DEVICE_NAND; >> + case MX6_SATA_BOOT: >> + printf("SATA\n"); >> + return BOOT_DEVICE_SATA; >> + default: >> + printf("UNKNOWN\n"); >> + return BOOT_DEVICE_NONE; >> + } >> +} > > This function (without unneeded printf) should be made common. Feel free > to add a spl.c file inside ./arch/arm/imx-common I'm removing this function and instead using what was 'get_boot_device()' from my other patch for it, which I've moved into arch/arm/imx-common/misc.c. I'm not sure I see the need to display the boot device so I'm removing that as well. > >> + >> +#if defined(CONFIG_SPL_MMC_SUPPORT) >> +/* called from spl_mmc to see type of boot mode for storage (RAW or FAT) */ >> +u32 spl_boot_mode(void) >> +{ >> + switch (get_boot_device()) { >> + /* for MMC return either RAW or FAT mode */ >> + case BOOT_DEVICE_MMC1: >> +#ifdef CONFIG_SPL_FAT_SUPPORT >> + return MMCSD_MODE_FAT; >> +#else >> + return MMCSD_MODE_RAW; >> +#endif >> + break; >> + default: >> + puts("spl: ERROR: unsupported device\n"); >> + hang(); >> + } >> +} >> +#endif >> + >> +void reset_cpu(ulong addr) >> +{ >> +} >> +#endif > > Ditto yes, I'll make this common as well. > > >> + >> diff --git a/board/gateworks/gw_ventana/gw_ventana_spl.cfg b/board/gateworks/gw_ventana/gw_ventana_spl.cfg >> new file mode 100644 >> index 0000000..9ab95f5 >> --- /dev/null >> +++ b/board/gateworks/gw_ventana/gw_ventana_spl.cfg >> @@ -0,0 +1,29 @@ >> +/* >> + * Copyright (C) 2013 Gateworks Corporation >> + * >> + * SPDX-License-Identifier: GPL-2.0+ >> + * >> + * Refer doc/README.imximage for more details about how-to configure >> + * and create imximage boot image >> + * >> + * The syntax is taken as close as possible with the kwbimage >> + */ >> + >> +/* image version */ >> +IMAGE_VERSION 2 >> + >> +/* >> + * Boot Device : one of >> + * spi, sd, nand, sata >> + */ >> +#ifdef CONFIG_SPI_FLASH >> +BOOT_FROM spi >> +#else >> +BOOT_FROM nand >> +#endif >> + >> +#define __ASSEMBLY__ >> +#include <config.h> >> +#include "asm/arch/iomux.h" >> +#include "asm/arch/crm_regs.h" >> +#include "clocks.cfg" > > Mmhhh...which is the reason to have gw_ventana.cfg and gw_ventana_spl.cfg ? > > You need the .cfg file to generate the IVT header only for SPL. It is > not required for U-Boot, because the boot ROM has already processed the > first i.MX header. > oops - gw_ventana_spl.cfg is not used so I'll remove it > >> diff --git a/boards.cfg b/boards.cfg >> index a7be5a3..aa48f89 100644 >> --- a/boards.cfg >> +++ b/boards.cfg >> @@ -320,11 +320,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> > > Nice, only one entry for all of your boards. yes... considering we currently have 4 baseboards (a fifth on the way), supporting both IMX6DL or IMX6Q on each, and have 2 memory densities (a third on the way) SPL is a must for my sanity to eliminate what would be something like 5*2*3 various build-time configurations. The dynamic ddr configuration functionality I'm proposing helps out tremendously as well because the DDR3 calibration and testing I've done tells me that each board design (varied layout between SoC and DDR3) needs its own calibration values due to propagation delays and IMX6Q/D vs IMX6DL/SOLO need different calibration values on each board as well. This can all be handled with minimal tables and easily configured at runtime via baseboard detection, cpu detection, and memory density information. > <snip> >> diff --git a/include/configs/gw_ventana.h b/include/configs/gw_ventana.h >> index 3398390..f6dc52a 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_SATA_SUPPORT >> +#define CONFIG_SPL_FAT_SUPPORT >> +*/ >> +/* Location in NAND to read U-Boot from */ >> +#define CONFIG_SYS_NAND_U_BOOT_OFFS (14 * 1024 * 1024) > > This is ok - it is your decision where to put it. > > May I ask why do you need 14 MB at the beginning ? It seems you lose a > lot of place. NAND is cheap nowadays, but... it was perhaps a poor decision I made early on when I was following too much of the reference design without understanding all the details. They used a 16MB area in NAND for the bootstreams so that is what I used as well. I worked through the calculation once and the 16MB wasn't all that crazy considering at the time I was wanting enough room to support a 1MB u-boot. When you add the blocks and redundant blocks for FCB/DBBT (default is to have 2 copies of these), then double the bootloader size (because IMX BOOT ROM supports 2 firmware images for redundancy), and factor in 20% headroom to allow for bad blocks, the 16MB wasn't all that crazy. Now that I'm talking about using 14MB for a <64KB SPL image, its overkill for sure. I don't want to impose a partition layout change on our existing users that I want to update to the SPL bootloader (with all the improved DDR3 calibration values) so I figure we'll put u-boot.img in the last 2MB of the 16MB partition for the 'bootloader' and leave the first 14MB for SPL to be flashed according to the IMX6 BOOT ROM. > >> + >> +#include "imx6_spl.h" /* common IMX6 SPL configuration */ >> #include "mx6_common.h" >> #define CONFIG_MX6 >> #define CONFIG_DISPLAY_CPUINFO /* display cpu info */ >> @@ -242,7 +253,7 @@ >> "mtdparts=nor:512k(uboot),64k(env),2m(kernel),-(rootfs)" >> #else >> #define MTDIDS_DEFAULT "nand0=nand" >> -#define MTDPARTS_DEFAULT "mtdparts=nand:16m(uboot),1m(env),-(rootfs)" >> +#define MTDPARTS_DEFAULT "mtdparts=nand:14m(spl),2m(uboot),1m(env),-(rootfs)" and I'll be reverting that last change as well and leaving the original 16M partition for the 'bootloader' meaning the 14MB area flashed by kobs-ng according to the IMX6 BOOT ROM requirements for NAND boot as well as the 2MB area I'm reserving for u-boot.img. If I were to split the partitions like the above change, it will cause some grief for existing users that are using the 3.0.35 (non device-tree) vendor kernel that has the mtd partitions hard coded in the board support. Instead, I decided to patch the kobs-ng application used to flash the SPL so that it can be passed a max size to use within /dev/mtd0 and users that need to upgrade to the SPL bootloader will need to use that patched kobs-ng to flash the SPL to the first 14MB, then use std mtd utils to flash u-boot.img in the area between 14M and 16M. Don't forget, at some point soon I hope to add some functionality to u-boot to flash the SPL portion to nand (the way kobs-ng does) so that you don't need to boot to linux and use kobs-ng or use our JTAG tool. Thanks for the reviews. I have a few more things to catch up on, but hope to post a v2 by the end of the week or early next week. Regards, Tim
Hi Tim, On 24/04/2014 10:06, Tim Harvey wrote: >>> + >>> +/* configure mx6 mmdc io registers */ >>> +struct mx6_mmdc_ioregs mmdc_ioregs = { >>> + /* DDR3 */ >>> + .mmdc_grp_ddr_type = 0x000c0000, >>> + /* disable DDR pullups */ >>> + .mmdc_grp_ddrpke = 0x00000000, >>> + /* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */ >>> + .mmdc_dram_sdclk_0 = 0x00020030, >>> + .mmdc_dram_sdclk_1 = 0x00020030, >>> + .mmdc_dram_cas = 0x00020030, >>> + .mmdc_dram_ras = 0x00020030, >>> + .mmdc_dram_reset = 0x00020030, >>> + /* ADDR[00:16], SDBA[0:1]: 40 ohm */ >>> + .mmdc_grp_addds = 0x00000030, >>> + /* SDCKE[0:1]: 100k pull-up */ >>> + .mmdc_dram_sdcke0 = 0x00003000, >>> + .mmdc_dram_sdcke1 = 0x00003000, >>> + /* SDBA2: pull-up disabled */ >>> + .mmdc_dram_sdba2 = 0x00000000, >>> + /* SDODT[0:1]: 100k pull-up, 40 ohm */ >>> + .mmdc_dram_sdodt0 = 0x00003030, >>> + .mmdc_dram_sdodt1 = 0x00003030, >>> + /* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */ >>> + .mmdc_grp_ctlds = 0x00000030, >>> + /* SDQS[0:7]: Differential input, 40 ohm */ >>> + .mmdc_ddrmode_ctl = 0x00020000, >>> + .mmdc_dram_sdqs0 = 0x00000030, >>> + .mmdc_dram_sdqs1 = 0x00000030, >>> + .mmdc_dram_sdqs2 = 0x00000030, >>> + .mmdc_dram_sdqs3 = 0x00000030, >>> + .mmdc_dram_sdqs4 = 0x00000030, >>> + .mmdc_dram_sdqs5 = 0x00000030, >>> + .mmdc_dram_sdqs6 = 0x00000030, >>> + .mmdc_dram_sdqs7 = 0x00000030, >>> + >>> + /* DATA[00:63]: Differential input, 40 ohm */ >>> + .mmdc_grp_ddrmode = 0x00020000, >>> + .mmdc_grp_b0ds = 0x00000030, >>> + .mmdc_grp_b1ds = 0x00000030, >>> + .mmdc_grp_b2ds = 0x00000030, >>> + .mmdc_grp_b3ds = 0x00000030, >>> + .mmdc_grp_b4ds = 0x00000030, >>> + .mmdc_grp_b5ds = 0x00000030, >>> + .mmdc_grp_b6ds = 0x00000030, >>> + .mmdc_grp_b7ds = 0x00000030, >>> + >>> + /* DQM[0:7]: Differential input, 40 ohm */ >>> + .mmdc_dram_dqm0 = 0x00020030, >>> + .mmdc_dram_dqm1 = 0x00020030, >>> + .mmdc_dram_dqm2 = 0x00020030, >>> + .mmdc_dram_dqm3 = 0x00020030, >>> + .mmdc_dram_dqm4 = 0x00020030, >>> + .mmdc_dram_dqm5 = 0x00020030, >>> + .mmdc_dram_dqm6 = 0x00020030, >>> + .mmdc_dram_dqm7 = 0x00020030, >>> +}; >> >> I will suggest you move these structure in a separate file. It is then >> easier for a board developer to understand what is very board specific. > > hmmm... they are all very board specific but ok. Well, I am noy saying to move it outside board/gateworks/gw_ventana. My proposal is more as to signalize how to add SPL support for a new board. Anyway, I agree it is a personal taste. > > not needed - I used it mainly for debugging and will remove it. > >> >>> + >>> + board_init_r(NULL, 0); >>> +} >> >> Mmhhh...apart the access to the eeprom to get the ram size, this >> function should be common. > > maybe, but I think we should wait to see what other boards come up > with SPL support to see what actually ends up being common. An SPL > that supports SPI or some of the other boot devices may need to do > some additional things. Agree, this makes sense. We can do it later. > > yes... considering we currently have 4 baseboards (a fifth on the > way), supporting both IMX6DL or IMX6Q on each, and have 2 memory > densities (a third on the way) SPL is a must for my sanity to > eliminate what would be something like 5*2*3 various build-time > configurations. > > The dynamic ddr configuration functionality I'm proposing helps out > tremendously as well because the DDR3 calibration and testing I've > done tells me that each board design (varied layout between SoC and > DDR3) needs its own calibration values due to propagation delays and > IMX6Q/D vs IMX6DL/SOLO need different calibration values on each board > as well. This can all be handled with minimal tables and easily > configured at runtime via baseboard detection, cpu detection, and > memory density information. Very nice. >>> +#define CONFIG_SYS_NAND_U_BOOT_OFFS (14 * 1024 * 1024) >> >> This is ok - it is your decision where to put it. >> >> May I ask why do you need 14 MB at the beginning ? It seems you lose a >> lot of place. NAND is cheap nowadays, but... > > it was perhaps a poor decision I made early on when I was following > too much of the reference design without understanding all the > details. They used a 16MB area in NAND for the bootstreams so that is > what I used as well. I worked through the calculation once and the > 16MB wasn't all that crazy considering at the time I was wanting > enough room to support a 1MB u-boot. When you add the blocks and > redundant blocks for FCB/DBBT (default is to have 2 copies of these), > then double the bootloader size (because IMX BOOT ROM supports 2 > firmware images for redundancy), and factor in 20% headroom to allow > for bad blocks, the 16MB wasn't all that crazy. Now that I'm talking > about using 14MB for a <64KB SPL image, its overkill for sure. > > I don't want to impose a partition layout change on our existing users > that I want to update to the SPL bootloader (with all the improved > DDR3 calibration values) so I figure we'll put u-boot.img in the last > 2MB of the 16MB partition for the 'bootloader' and leave the first > 14MB for SPL to be flashed according to the IMX6 BOOT ROM. ok, thanks for explanation > >> >>> + >>> +#include "imx6_spl.h" /* common IMX6 SPL configuration */ >>> #include "mx6_common.h" >>> #define CONFIG_MX6 >>> #define CONFIG_DISPLAY_CPUINFO /* display cpu info */ >>> @@ -242,7 +253,7 @@ >>> "mtdparts=nor:512k(uboot),64k(env),2m(kernel),-(rootfs)" >>> #else >>> #define MTDIDS_DEFAULT "nand0=nand" >>> -#define MTDPARTS_DEFAULT "mtdparts=nand:16m(uboot),1m(env),-(rootfs)" >>> +#define MTDPARTS_DEFAULT "mtdparts=nand:14m(spl),2m(uboot),1m(env),-(rootfs)" > > and I'll be reverting that last change as well and leaving the > original 16M partition for the 'bootloader' meaning the 14MB area > flashed by kobs-ng according to the IMX6 BOOT ROM requirements for > NAND boot as well as the 2MB area I'm reserving for u-boot.img. > > If I were to split the partitions like the above change, it will cause > some grief for existing users that are using the 3.0.35 (non > device-tree) vendor kernel that has the mtd partitions hard coded in > the board support. Instead, I decided to patch the kobs-ng application > used to flash the SPL so that it can be passed a max size to use > within /dev/mtd0 and users that need to upgrade to the SPL bootloader > will need to use that patched kobs-ng to flash the SPL to the first > 14MB, then use std mtd utils to flash u-boot.img in the area between > 14M and 16M. > > Don't forget, at some point soon I hope to add some functionality to > u-boot to flash the SPL portion to nand (the way kobs-ng does) so that > you don't need to boot to linux and use kobs-ng or use our JTAG tool. This will be a great improvement ! Thanks for working on this issue. Best regards, Stefano
Hi Tim! BTW: Thanks for all your work on this. Great work and really appreciated. Just a quick note: On 24.04.2014 10:06, Tim Harvey wrote: <big snip> > If I were to split the partitions like the above change, it will cause > some grief for existing users that are using the 3.0.35 (non > device-tree) vendor kernel that has the mtd partitions hard coded in > the board support. Instead, I decided to patch the kobs-ng application > used to flash the SPL so that it can be passed a max size to use > within /dev/mtd0 and users that need to upgrade to the SPL bootloader > will need to use that patched kobs-ng to flash the SPL to the first > 14MB, then use std mtd utils to flash u-boot.img in the area between > 14M and 16M. > > Don't forget, at some point soon I hope to add some functionality to > u-boot to flash the SPL portion to nand (the way kobs-ng does) so that > you don't need to boot to linux and use kobs-ng or use our JTAG tool. For such a functionality it might make sense to take a look at what has been recently added to barebox: http://comments.gmane.org/gmane.comp.boot-loaders.barebox/12612 http://comments.gmane.org/gmane.comp.boot-loaders.barebox/12856 Thanks, Stefan
diff --git a/board/gateworks/gw_ventana/Makefile b/board/gateworks/gw_ventana/Makefile index e8dab89..8b239ae 100644 --- a/board/gateworks/gw_ventana/Makefile +++ b/board/gateworks/gw_ventana/Makefile @@ -6,5 +6,5 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y := gw_ventana.o gsc.o +obj-y := gw_ventana.o gsc.o gw_ventana_spl.o diff --git a/board/gateworks/gw_ventana/README b/board/gateworks/gw_ventana/README index 9e697d6..c45d4b8 100644 --- a/board/gateworks/gw_ventana/README +++ b/board/gateworks/gw_ventana/README @@ -3,53 +3,80 @@ 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 ebf7e7d..7508141 100644 --- a/board/gateworks/gw_ventana/gw_ventana.c +++ b/board/gateworks/gw_ventana/gw_ventana.c @@ -1019,8 +1019,9 @@ int board_early_init_f(void) int dram_init(void) { - gd->ram_size = get_ram_size((void *)PHYS_SDRAM, - CONFIG_DDR_MB*1024*1024); + struct mx6_spl_data *data = (struct mx6_spl_data *) + ((CONFIG_SPL_TEXT_BASE - sizeof(struct mx6_spl_data)) & ~0xf); + gd->ram_size = data->mem_dram_size; return 0; } 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..492c814 --- /dev/null +++ b/board/gateworks/gw_ventana/gw_ventana_spl.c @@ -0,0 +1,394 @@ +/* + * 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_regs.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> +#ifdef CONFIG_SPL +#include <spl.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_SPL_BUILD) + +#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); +} + +static u16 +read_eeprom(void) +{ + u8 data[3]; + + /* + * On a board with a missing/depleted backup battery for GSC, the + * board may be ready to probe the GSC before its firmware is + * running. We will wait here indefinately for the GSC/EEPROM. + */ + while (1) { + if (0 == i2c_set_bus_num(I2C_GSC) && + 0 == i2c_probe(GSC_EEPROM_ADDR)) + break; + /* TODO: mdelay hangs at this point + mdelay(1); + */ + } + + i2c_read(GSC_EEPROM_ADDR, GSC_EEPROM_DDR_SIZE, 1, data, 3); + + return (data[0] << 8) | data[2]; +} + +/* configure mx6 mmdc io registers */ +struct mx6_mmdc_ioregs mmdc_ioregs = { + /* DDR3 */ + .mmdc_grp_ddr_type = 0x000c0000, + /* disable DDR pullups */ + .mmdc_grp_ddrpke = 0x00000000, + /* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */ + .mmdc_dram_sdclk_0 = 0x00020030, + .mmdc_dram_sdclk_1 = 0x00020030, + .mmdc_dram_cas = 0x00020030, + .mmdc_dram_ras = 0x00020030, + .mmdc_dram_reset = 0x00020030, + /* ADDR[00:16], SDBA[0:1]: 40 ohm */ + .mmdc_grp_addds = 0x00000030, + /* SDCKE[0:1]: 100k pull-up */ + .mmdc_dram_sdcke0 = 0x00003000, + .mmdc_dram_sdcke1 = 0x00003000, + /* SDBA2: pull-up disabled */ + .mmdc_dram_sdba2 = 0x00000000, + /* SDODT[0:1]: 100k pull-up, 40 ohm */ + .mmdc_dram_sdodt0 = 0x00003030, + .mmdc_dram_sdodt1 = 0x00003030, + /* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */ + .mmdc_grp_ctlds = 0x00000030, + /* SDQS[0:7]: Differential input, 40 ohm */ + .mmdc_ddrmode_ctl = 0x00020000, + .mmdc_dram_sdqs0 = 0x00000030, + .mmdc_dram_sdqs1 = 0x00000030, + .mmdc_dram_sdqs2 = 0x00000030, + .mmdc_dram_sdqs3 = 0x00000030, + .mmdc_dram_sdqs4 = 0x00000030, + .mmdc_dram_sdqs5 = 0x00000030, + .mmdc_dram_sdqs6 = 0x00000030, + .mmdc_dram_sdqs7 = 0x00000030, + + /* DATA[00:63]: Differential input, 40 ohm */ + .mmdc_grp_ddrmode = 0x00020000, + .mmdc_grp_b0ds = 0x00000030, + .mmdc_grp_b1ds = 0x00000030, + .mmdc_grp_b2ds = 0x00000030, + .mmdc_grp_b3ds = 0x00000030, + .mmdc_grp_b4ds = 0x00000030, + .mmdc_grp_b5ds = 0x00000030, + .mmdc_grp_b6ds = 0x00000030, + .mmdc_grp_b7ds = 0x00000030, + + /* DQM[0:7]: Differential input, 40 ohm */ + .mmdc_dram_dqm0 = 0x00020030, + .mmdc_dram_dqm1 = 0x00020030, + .mmdc_dram_dqm2 = 0x00020030, + .mmdc_dram_dqm3 = 0x00020030, + .mmdc_dram_dqm4 = 0x00020030, + .mmdc_dram_dqm5 = 0x00020030, + .mmdc_dram_dqm6 = 0x00020030, + .mmdc_dram_dqm7 = 0x00020030, +}; + +/* 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 gw54xx_mmdc_calibration = { + /* write leveling calibration determine */ + .mmdc_p0_mpwldectrl0 = 0x00210021, + .mmdc_p0_mpwldectrl1 = 0x00284024, + .mmdc_p1_mpwldectrl0 = 0x0018002b, + .mmdc_p1_mpwldectrl1 = 0x000c801f, + /* Read DQS Gating calibration */ + .mmdc_p0_mpdgctrl0 = 0x43430354, + .mmdc_p0_mpdgctrl1 = 0x034e0344, + .mmdc_p1_mpdgctrl0 = 0x43500359, + .mmdc_p1_mpdgctrl1 = 0x034b031c, + /* Read Calibration: DQS delay relative to DQ read access */ + .mmdc_p0_mprddlctl = 0x3e363abe, + .mmdc_p1_mprddlctl = 0x35b23040, + /* Write Calibration: DQ/DM delay relative to DQS write access */ + .mmdc_p0_mpwrdlctl = 0x3839403c, + .mmdc_p1_mpwrdlctl = 0x45b6483c, +}; + +/* GW53xx specific calibration */ +static struct mx6_mmdc_calibration gw53xx_mmdc_calibration = { + /* write leveling calibration determine */ + .mmdc_p0_mpwldectrl0 = 0x007c007e, + .mmdc_p0_mpwldectrl1 = 0x003b007c, + .mmdc_p1_mpwldectrl0 = 0x001f002b, + .mmdc_p1_mpwldectrl1 = 0x003f003f, + /* Read DQS Gating calibration */ + .mmdc_p0_mpdgctrl0 = 0x42550254, + .mmdc_p0_mpdgctrl1 = 0x023d023d, + .mmdc_p1_mpdgctrl0 = 0x423c027e, + .mmdc_p1_mpdgctrl1 = 0x021c0238, + /* Read Calibration: DQS delay relative to DQ read access */ + .mmdc_p0_mprddlctl = 0x484a4e4b, + .mmdc_p1_mprddlctl = 0x4b4d4e4b, + /* Write Calibration: DQ/DM delay relative to DQS write access */ + .mmdc_p0_mpwrdlctl = 0x37342f32, + .mmdc_p1_mpwrdlctl = 0x3f33372b, +}; + +/* GW52xx specific calibration */ +static struct mx6_mmdc_calibration gw52xx_mmdc_calibration = { + /* write leveling calibration determine */ + .mmdc_p0_mpwldectrl0 = 0x0040003C, + .mmdc_p0_mpwldectrl1 = 0x0032003E, + /* Read DQS Gating calibration */ + .mmdc_p0_mpdgctrl0 = 0x42350231, + .mmdc_p0_mpdgctrl1 = 0x021A0218, + /* Read Calibration: DQS delay relative to DQ read access */ + .mmdc_p0_mprddlctl = 0x4B4B4E49, + /* Write Calibration: DQ/DM delay relative to DQS write access */ + .mmdc_p0_mpwrdlctl = 0x3F3F3035, +}; + +/* GW51xx specific calibration */ +static struct mx6_mmdc_calibration gw51xx_mmdc_calibration = { + /* write leveling calibration determine */ + .mmdc_p0_mpwldectrl0 = 0x0040003C, + .mmdc_p0_mpwldectrl1 = 0x0032003E, + /* Read DQS Gating calibration */ + .mmdc_p0_mpdgctrl0 = 0x42350231, + .mmdc_p0_mpdgctrl1 = 0x021A0218, + /* Read Calibration: DQS delay relative to DQ read access */ + .mmdc_p0_mprddlctl = 0x4B4B4E49, + /* Write Calibration: DQ/DM delay relative to DQS write access */ + .mmdc_p0_mpwrdlctl = 0x3F3F3035, +}; + +static void spl_dram_init(int ddr_cfg) +{ + struct mx6_spl_data *data = (struct mx6_spl_data *) + ((CONFIG_SPL_TEXT_BASE - sizeof(struct mx6_spl_data)) & ~0xf); + u32 cpurev, imxtype; + int width, size; + struct mx6_ddr3_cfg *mem = &mt41k128m16jt_125; + struct mx6_mmdc_calibration *calib; + struct mx6_ddr_sysinfo sysinfo = { + .dsize = (8 << (ddr_cfg & 0xff))/32, + .cs_density = (16 << (ddr_cfg>>8))/128, + /* 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) */ + }; + u8 model[16]; + + i2c_read(GSC_EEPROM_ADDR, 0x30, 1, model, 16); + debug("model:%s\n", model); + + /* + * 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 (model[3]) { + case '1': + calib = &gw51xx_mmdc_calibration; + break; + case '2': + calib = &gw52xx_mmdc_calibration; + break; + case '3': + calib = &gw53xx_mmdc_calibration; + break; + default: + case '4': + calib = &gw54xx_mmdc_calibration; + break; + } + + cpurev = get_cpu_rev(); + imxtype = (cpurev & 0xFF000) >> 12; + size = (16 << (ddr_cfg >> 8)); + width = (8 << (ddr_cfg & 0xff)); + data->mem_dram_size = size * 1024 * 1024; + + get_imx_type(imxtype); + + switch (imxtype) { + case MXC_CPU_MX6Q: + mx6_dram_iocfg(width, &mx6dq_ctrl, &mmdc_ioregs); + mx6_dram_cfg(&sysinfo, &mx6_ddrcfg, calib, mem); + break; + case MXC_CPU_MX6DL: + default: + mx6_dram_iocfg(width, &mx6sdl_ctrl, &mmdc_ioregs); + mx6_dram_cfg(&sysinfo, &mx6_ddrcfg, calib, mem); + break; + } +} + +/* + * 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) +{ + int ddrcfg; + + /* iomux and setup of i2c */ + i2c_setup_iomux(); + + /* TODO: possible to get console support at this point for debugging? */ + timer_init(); + ddrcfg = read_eeprom(); + spl_dram_init(ddrcfg); + + 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(); + + if (is_cpu_type(MXC_CPU_MX6Q)) + puts("CPU: IMX6Q\n"); + else if (is_cpu_type(MXC_CPU_MX6DL)) + puts("CPU: IMX6DL\n"); + else + puts("CPU: unsupported\n"); + printf("SDRAM: %dMB %dbit\n", (16 << (ddrcfg>>8)), + (8 << (ddrcfg & 0xff))); + + board_init_r(NULL, 0); +} + +/* called from board_init_r() to decide what spl_*_load_image() to call */ +u32 spl_boot_device(void) +{ + puts("Boot Device: "); + switch (get_boot_device()) { + case MX6_MMC_BOOT: + printf("uSD\n"); + return BOOT_DEVICE_MMC1; + case MX6_NAND_BOOT: + printf("NAND\n"); + return BOOT_DEVICE_NAND; + case MX6_SATA_BOOT: + printf("SATA\n"); + return BOOT_DEVICE_SATA; + default: + printf("UNKNOWN\n"); + return BOOT_DEVICE_NONE; + } +} + +#if defined(CONFIG_SPL_MMC_SUPPORT) +/* called from spl_mmc to see type of boot mode for storage (RAW or FAT) */ +u32 spl_boot_mode(void) +{ + switch (get_boot_device()) { + /* for MMC return either RAW or FAT mode */ + case BOOT_DEVICE_MMC1: +#ifdef CONFIG_SPL_FAT_SUPPORT + return MMCSD_MODE_FAT; +#else + return MMCSD_MODE_RAW; +#endif + break; + default: + puts("spl: ERROR: unsupported device\n"); + hang(); + } +} +#endif + +void reset_cpu(ulong addr) +{ +} +#endif + diff --git a/board/gateworks/gw_ventana/gw_ventana_spl.cfg b/board/gateworks/gw_ventana/gw_ventana_spl.cfg new file mode 100644 index 0000000..9ab95f5 --- /dev/null +++ b/board/gateworks/gw_ventana/gw_ventana_spl.cfg @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2013 Gateworks Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Refer doc/README.imximage for more details about how-to configure + * and create imximage boot image + * + * The syntax is taken as close as possible with the kwbimage + */ + +/* image version */ +IMAGE_VERSION 2 + +/* + * Boot Device : one of + * spi, sd, nand, sata + */ +#ifdef CONFIG_SPI_FLASH +BOOT_FROM spi +#else +BOOT_FROM nand +#endif + +#define __ASSEMBLY__ +#include <config.h> +#include "asm/arch/iomux.h" +#include "asm/arch/crm_regs.h" +#include "clocks.cfg" diff --git a/boards.cfg b/boards.cfg index a7be5a3..aa48f89 100644 --- a/boards.cfg +++ b/boards.cfg @@ -320,11 +320,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/config/uboot.release b/include/config/uboot.release new file mode 100644 index 0000000..0e37110 --- /dev/null +++ b/include/config/uboot.release @@ -0,0 +1 @@ +2014.04-rc1-00227-g1879963-dirty diff --git a/include/configs/gw_ventana.h b/include/configs/gw_ventana.h index 3398390..f6dc52a 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_SATA_SUPPORT +#define CONFIG_SPL_FAT_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 */ @@ -242,7 +253,7 @@ "mtdparts=nor:512k(uboot),64k(env),2m(kernel),-(rootfs)" #else #define MTDIDS_DEFAULT "nand0=nand" -#define MTDPARTS_DEFAULT "mtdparts=nand:16m(uboot),1m(env),-(rootfs)" +#define MTDPARTS_DEFAULT "mtdparts=nand:14m(spl),2m(uboot),1m(env),-(rootfs)" #endif /* Persistent Environment Config */
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 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> --- board/gateworks/gw_ventana/Makefile | 2 +- board/gateworks/gw_ventana/README | 91 +++--- board/gateworks/gw_ventana/gw_ventana.c | 5 +- board/gateworks/gw_ventana/gw_ventana.cfg | 15 - board/gateworks/gw_ventana/gw_ventana_spl.c | 394 ++++++++++++++++++++++++++ board/gateworks/gw_ventana/gw_ventana_spl.cfg | 29 ++ boards.cfg | 6 +- include/config/uboot.release | 1 + include/configs/gw_ventana.h | 13 +- 9 files changed, 500 insertions(+), 56 deletions(-) create mode 100644 board/gateworks/gw_ventana/gw_ventana_spl.c create mode 100644 board/gateworks/gw_ventana/gw_ventana_spl.cfg create mode 100644 include/config/uboot.release