mx6: ddr: updates for dynamic DDR calibration
Subsystems (2)
cover mx6: ddr: updates for dynamic DDR calibration
This set of patches updates the interface to the DDR calibration in preparation for the addition of a pseudo-board for calibration on i.MX6.
The first patch fixes an ommission in the use of the DG_CMP_CYC flag in register MPDGCTRL0.
The second patch cleans up the handling of bus widths by passing the system configuration information to the calibration routines.
The third routine adds support for returning the calibration data written to the MMDC registers.
Eric Nelson (3):
mx6: ddr: allow 32 cycles for DQS gating calibration
mx6: ddr: pass mx6_ddr_sysinfo to calibration routines
mx6: ddr: add mmdc_read_calibration routine to return dynamic data
arch/arm/cpu/armv7/mx6/ddr.c | 128 +++++++++++++++++++++----------- arch/arm/include/asm/arch-mx6/mx6-ddr.h | 6 +- board/kosagi/novena/novena_spl.c | 4 +- 3 files changed, 92 insertions(+), 46 deletions(-)
Signature · 1 line
2.7.4
PATCH 1/3 mx6: ddr: allow 32 cycles for DQS gating calibration
The DDR calibration code is only setting flag DG_CMP_CYC (DQS gating sample cycle) for the first PHY.
Set the 32-cycle flag for both PHYs and clear when done so the MPDGCTRL0 output value isn't polluted with calibration artifacts.
--- arch/arm/cpu/armv7/mx6/ddr.c | 7 +++++++ 1 file changed, 7 insertions(+)
arch/arm/cpu/armv7/mx6/ddr.c +7 -0
@@ -347,6 +347,8 @@ int mmdc_do_dqs_calibration(void)* 16 before comparing read data. */ setbits_le32 (&mmdc0->mpdgctrl0,1 <<30 ); +if (sysinfo->dsize ==2 ) +setbits_le32 (&mmdc1->mpdgctrl0,1 <<30 );/* Set bit 28 to start automatic read DQS gating calibration */ setbits_le32 (&mmdc0->mpdgctrl0,5 <<28 );
@@ -365,6 +367,11 @@ int mmdc_do_dqs_calibration(void)if ((bus_size ==0x2 ) && (readl (&mmdc1->mpdgctrl0) &0x00001000 )) errors |=2 ; +/* now disable mpdgctrl0[DG_CMP_CYC] */ +clrbits_le32 (&mmdc0->mpdgctrl0,1 <<30 ); +if (sysinfo->dsize ==2 ) +clrbits_le32 (&mmdc1->mpdgctrl0,1 <<30 ); +/* * DQS gating absolute offset should be modified from * reflecting (HW_DG_LOWx + HW_DG_UPx)/2 to
Signature · 1 line
2.7.4
PATCH 1/3 mx6: ddr: allow 32 cycles for DQS gating calibration
Quoted 7 lines · Eric Nelson
The DDR calibration code is only setting flag
DG_CMP_CYC(DQS gating sample cycle) for the first PHY.Set the 32-cycle flag for both PHYs and clear when done so the MPDGCTRL0 output value isn't polluted with calibration artifacts.
Signed-off-by Eric Nelson <[email protected]>
Quoted 30 lines
--- arch/arm/cpu/armv7/mx6/ddr.c | 7 +++++++ 1 file changed, 7 insertions(+)arch/arm/cpu/armv7/mx6/ddr.c +7
-0@@ -347,6 +347,8 @@ int mmdc_do_dqs_calibration(void)* 16 before comparing read data. */ setbits_le32 (&mmdc0->mpdgctrl0,1 <<30 ); +if (sysinfo->dsize ==2 ) +setbits_le32 (&mmdc1->mpdgctrl0,1 <<30 );/* Set bit 28 to start automatic read DQS gating calibration */ setbits_le32 (&mmdc0->mpdgctrl0,5 <<28 );@@ -365,6 +367,11 @@ int mmdc_do_dqs_calibration(void)if ((bus_size ==0x2 ) && (readl (&mmdc1->mpdgctrl0) &0x00001000 )) errors |=2 ; +/* now disable mpdgctrl0[DG_CMP_CYC] */ +clrbits_le32 (&mmdc0->mpdgctrl0,1 <<30 ); +if (sysinfo->dsize ==2 ) +clrbits_le32 (&mmdc1->mpdgctrl0,1 <<30 ); +/* * DQS gating absolute offset should be modified from * reflecting (HW_DG_LOWx + HW_DG_UPx)/2 to
Signature · 2 lines
Best regards, Marek Vasut
PATCH 2/3 mx6: ddr: pass mx6_ddr_sysinfo to calibration routines
In reply to Eric NelsonThe DDR calibration routines have scattered support for bus widths other than 64-bits:
-- The mmdc_do_write_level_calibration() routine assumes the presence of PHY1, and
-- The mmdc_do_dqs_calibration() routine tries to determine whether one or two DDR PHYs are active by reading MDCTL.
Since a caller of these routines must have a valid struct mx6_ddr_sysinfo for use in calling mx6_dram_cfg(), and the bus width is available in the "dsize" field, use this structure to inform the calibration routines which PHYs are active.
This allows the use of the DDR calibration routines on CPU variants like i.MX6SL that only have a single MMDC port.
--- arch/arm/cpu/armv7/mx6/ddr.c | 98 +++++++++++++++++++-------------- arch/arm/include/asm/arch-mx6/mx6-ddr.h | 4 +- board/kosagi/novena/novena_spl.c | 4 +- 3 files changed, 60 insertions(+), 46 deletions(-)
arch/arm/cpu/armv7/mx6/ddr.c +56 -42
@@ -86,14 +86,15 @@ static void modify_dg_result(u32 *reg_st0, u32 *reg_st1, u32 *reg_ctrl)writel (val_ctrl, reg_ctrl); } -int mmdc_do_write_level_calibration (void ) +int mmdc_do_write_level_calibration (struct mx6_ddr_sysinfo const *sysinfo) {struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR ;struct mmdc_p_regs *mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR ;u32 esdmisc_val, zq_val;u32 errors =0 ; -u32 ldectrl[4 ]; +u32 ldectrl[4 ] = {0 };u32 ddr_mr1 =0x4 ; +u32 rwalat_max;/* * Stash old values in case calibration fails,
@@ -101,8 +102,10 @@ int mmdc_do_write_level_calibration(void)*/ ldectrl[0 ] =readl (&mmdc0->mpwldectrl0); ldectrl[1 ] =readl (&mmdc0->mpwldectrl1); - ldectrl[2 ] =readl (&mmdc1->mpwldectrl0); - ldectrl[3 ] =readl (&mmdc1->mpwldectrl1); +if (sysinfo->dsize ==2 ) { + ldectrl[2 ] =readl (&mmdc1->mpwldectrl0); + ldectrl[3 ] =readl (&mmdc1->mpwldectrl1); + }/* disable DDR logic power down timer */ clrbits_le32 (&mmdc0->mdpdc,0xff00 );
@@ -122,10 +125,10 @@ int mmdc_do_write_level_calibration(void)writel (zq_val & ~0x3 , &mmdc0->mpzqhwctrl);/* 3. increase walat and ralat to maximum */ -setbits_le32 (&mmdc0->mdmisc, - (1 <<6 ) | (1 <<7 ) | (1 <<8 ) | (1 <<16 ) | (1 <<17 )); -setbits_le32 (&mmdc1->mdmisc, - (1 <<6 ) | (1 <<7 ) | (1 <<8 ) | (1 <<16 ) | (1 <<17 )); + rwalat_max = (1 <<6 ) | (1 <<7 ) | (1 <<8 ) | (1 <<16 ) | (1 <<17 ); +setbits_le32 (&mmdc0->mdmisc, rwalat_max); +if (sysinfo->dsize ==2 ) +setbits_le32 (&mmdc1->mdmisc, rwalat_max);/* * 4 & 5. Configure the external DDR device to enter write-leveling * mode through Load Mode Register command.
@@ -152,21 +155,25 @@ int mmdc_do_write_level_calibration(void)*/ if (readl (&mmdc0->mpwlgcr) &0x00000F00 ) errors |=1 ; -if (readl (&mmdc1->mpwlgcr) &0x00000F00 ) - errors |=2 ; +if (sysinfo->dsize ==2 ) +if (readl (&mmdc1->mpwlgcr) &0x00000F00 ) + errors |=2 ;debug ("Ending write leveling calibration. Error mask: 0x%x\n" , errors);/* check to see if cal failed */ if ((readl (&mmdc0->mpwldectrl0) ==0x001F001F ) && (readl (&mmdc0->mpwldectrl1) ==0x001F001F ) && - (readl (&mmdc1->mpwldectrl0) ==0x001F001F ) && - (readl (&mmdc1->mpwldectrl1) ==0x001F001F )) { + ((sysinfo->dsize <2 ) || + ((readl (&mmdc1->mpwldectrl0) ==0x001F001F ) && + (readl (&mmdc1->mpwldectrl1) ==0x001F001F )))) {debug ("Cal seems to have soft-failed due to memory not supporting write leveling on all channels. Restoring original write leveling values.\n" );writel (ldectrl[0 ], &mmdc0->mpwldectrl0);writel (ldectrl[1 ], &mmdc0->mpwldectrl1); -writel (ldectrl[2 ], &mmdc1->mpwldectrl0); -writel (ldectrl[3 ], &mmdc1->mpwldectrl1); +if (sysinfo->dsize ==2 ) { +writel (ldectrl[2 ], &mmdc1->mpwldectrl0); +writel (ldectrl[3 ], &mmdc1->mpwldectrl1); + } errors |=4 ; }
@@ -189,16 +196,20 @@ int mmdc_do_write_level_calibration(void) readl(&mmdc0->mpwldectrl0));debug ("\tMMDC_MPWLDECTRL1 after write level cal: 0x%08X\n" ,readl (&mmdc0->mpwldectrl1)); -debug ("\tMMDC_MPWLDECTRL0 after write level cal: 0x%08X\n" , -readl (&mmdc1->mpwldectrl0)); -debug ("\tMMDC_MPWLDECTRL1 after write level cal: 0x%08X\n" , -readl (&mmdc1->mpwldectrl1)); +if (sysinfo->dsize ==2 ) { +debug ("\tMMDC_MPWLDECTRL0 after write level cal: 0x%08X\n" , +readl (&mmdc1->mpwldectrl0)); +debug ("\tMMDC_MPWLDECTRL1 after write level cal: 0x%08X\n" , +readl (&mmdc1->mpwldectrl1)); + }/* We must force a readback of these values, to get them to stick */ readl (&mmdc0->mpwldectrl0);readl (&mmdc0->mpwldectrl1); -readl (&mmdc1->mpwldectrl0); -readl (&mmdc1->mpwldectrl1); +if (sysinfo->dsize ==2 ) { +readl (&mmdc1->mpwldectrl0); +readl (&mmdc1->mpwldectrl1); + }/* enable DDR logic power down timer: */ setbits_le32 (&mmdc0->mdpdc,0x00005500 );
@@ -212,7 +223,7 @@ int mmdc_do_write_level_calibration(void)return errors; } -int mmdc_do_dqs_calibration (void ) +int mmdc_do_dqs_calibration (struct mx6_ddr_sysinfo const *sysinfo) {struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR ;struct mmdc_p_regs *mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR ;
@@ -223,7 +234,6 @@ int mmdc_do_dqs_calibration(void)bool cs0_enable_initial;bool cs1_enable_initial;u32 esdmisc_val; -u32 bus_size;u32 temp_ref;u32 pddword =0x00ffff00 ;/* best so far, place into MPPDCMPR1 */ u32 errors =0 ;
@@ -292,10 +302,6 @@ int mmdc_do_dqs_calibration(void) cs0_enable =readl (&mmdc0->mdctl) &0x80000000 ; cs1_enable =readl (&mmdc0->mdctl) &0x40000000 ; -/* Check to see what the data bus size is */ - bus_size = (readl (&mmdc0->mdctl) &0x30000 ) >>16 ; -debug ("Data bus size: %d (%d bits)\n" , bus_size,1 << (bus_size +4 )); -precharge_all (cs0_enable, cs1_enable);/* Write the pre-defined value into MPPDCMPR1 */
@@ -314,11 +320,11 @@ int mmdc_do_dqs_calibration(void)* Both PHYs for x64 configuration, if x32, do only PHY0. */ writel (initdelay, &mmdc0->mprddlctl); -if (bus_size ==0x2 ) +if (sysinfo->dsize ==0x2 )writel (initdelay, &mmdc1->mprddlctl);/* Force a measurment, for previous delay setup to take effect. */ -force_delay_measurement (bus_size); +force_delay_measurement (sysinfo->dsize);/* * ***************************
@@ -364,7 +370,7 @@ int mmdc_do_dqs_calibration(void)if (readl (&mmdc0->mpdgctrl0) &0x00001000 ) errors |=1 ; -if ((bus_size ==0x2 ) && (readl (&mmdc1->mpdgctrl0) &0x00001000 )) +if ((sysinfo->dsize ==0x2 ) && (readl (&mmdc1->mpdgctrl0) &0x00001000 )) errors |=2 ;/* now disable mpdgctrl0[DG_CMP_CYC] */
@@ -381,7 +387,7 @@ int mmdc_do_dqs_calibration(void) &mmdc0->mpdgctrl0);modify_dg_result (&mmdc0->mpdghwst2, &mmdc0->mpdghwst3, &mmdc0->mpdgctrl1); -if (bus_size ==0x2 ) { +if (sysinfo->dsize ==0x2 ) {modify_dg_result (&mmdc1->mpdghwst0, &mmdc1->mpdghwst1, &mmdc1->mpdgctrl0); modify_dg_result(&mmdc1->mpdghwst2, &mmdc1->mpdghwst3,
@@ -424,7 +430,8 @@ int mmdc_do_dqs_calibration(void)if (readl (&mmdc0->mprddlhwctl) &0x0000000f ) errors |=4 ; -if ((bus_size ==0x2 ) && (readl (&mmdc1->mprddlhwctl) &0x0000000f )) +if ((sysinfo->dsize ==0x2 ) && + (readl (&mmdc1->mprddlhwctl) &0x0000000f )) errors |=8 ;debug ("Ending Read Delay calibration. Error mask: 0x%x\n" , errors);
@@ -450,14 +457,14 @@ int mmdc_do_dqs_calibration(void)* Both PHYs for x64 configuration, if x32, do only PHY0. */ writel (initdelay, &mmdc0->mpwrdlctl); -if (bus_size ==0x2 ) +if (sysinfo->dsize ==0x2 )writel (initdelay, &mmdc1->mpwrdlctl);/* * XXX This isn't in the manual. Force a measurement, * for previous delay setup to effect. */ -force_delay_measurement (bus_size); +force_delay_measurement (sysinfo->dsize);/* * 9. 10. Start the automatic write calibration process
@@ -477,7 +484,8 @@ int mmdc_do_dqs_calibration(void)if (readl (&mmdc0->mpwrdlhwctl) &0x0000000f ) errors |=16 ; -if ((bus_size ==0x2 ) && (readl (&mmdc1->mpwrdlhwctl) &0x0000000f )) +if ((sysinfo->dsize ==0x2 ) && + (readl (&mmdc1->mpwrdlhwctl) &0x0000000f )) errors |=32 ;debug ("Ending Write Delay calibration. Error mask: 0x%x\n" , errors);
@@ -529,14 +537,18 @@ int mmdc_do_dqs_calibration(void)debug ("Read DQS gating calibration:\n" );debug ("\tMPDGCTRL0 PHY0 = 0x%08X\n" ,readl (&mmdc0->mpdgctrl0));debug ("\tMPDGCTRL1 PHY0 = 0x%08X\n" ,readl (&mmdc0->mpdgctrl1)); -debug ("\tMPDGCTRL0 PHY1 = 0x%08X\n" ,readl (&mmdc1->mpdgctrl0)); -debug ("\tMPDGCTRL1 PHY1 = 0x%08X\n" ,readl (&mmdc1->mpdgctrl1)); +if (sysinfo->dsize ==2 ) { +debug ("\tMPDGCTRL0 PHY1 = 0x%08X\n" ,readl (&mmdc1->mpdgctrl0)); +debug ("\tMPDGCTRL1 PHY1 = 0x%08X\n" ,readl (&mmdc1->mpdgctrl1)); + }debug ("Read calibration:\n" );debug ("\tMPRDDLCTL PHY0 = 0x%08X\n" ,readl (&mmdc0->mprddlctl)); -debug ("\tMPRDDLCTL PHY1 = 0x%08X\n" ,readl (&mmdc1->mprddlctl)); +if (sysinfo->dsize ==2 ) +debug ("\tMPRDDLCTL PHY1 = 0x%08X\n" ,readl (&mmdc1->mprddlctl));debug ("Write calibration:\n" );debug ("\tMPWRDLCTL PHY0 = 0x%08X\n" ,readl (&mmdc0->mpwrdlctl)); -debug ("\tMPWRDLCTL PHY1 = 0x%08X\n" ,readl (&mmdc1->mpwrdlctl)); +if (sysinfo->dsize ==2 ) +debug ("\tMPWRDLCTL PHY1 = 0x%08X\n" ,readl (&mmdc1->mpwrdlctl));/* * Registers below are for debugging purposes. These print out
@@ -548,10 +560,12 @@ int mmdc_do_dqs_calibration(void)debug ("\tMPDGHWST1 PHY0 = 0x%08x\n" ,readl (&mmdc0->mpdghwst1));debug ("\tMPDGHWST2 PHY0 = 0x%08x\n" ,readl (&mmdc0->mpdghwst2));debug ("\tMPDGHWST3 PHY0 = 0x%08x\n" ,readl (&mmdc0->mpdghwst3)); -debug ("\tMPDGHWST0 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst0)); -debug ("\tMPDGHWST1 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst1)); -debug ("\tMPDGHWST2 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst2)); -debug ("\tMPDGHWST3 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst3)); +if (sysinfo->dsize ==2 ) { +debug ("\tMPDGHWST0 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst0)); +debug ("\tMPDGHWST1 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst1)); +debug ("\tMPDGHWST2 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst2)); +debug ("\tMPDGHWST3 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst3)); + }debug ("Final do_dqs_calibration error mask: 0x%x\n" , errors);
arch/arm/include/asm/arch-mx6/mx6-ddr.h +2 -2
@@ -459,8 +459,8 @@ void mx6sl_dram_iocfg(unsigned width, const struct mx6sl_iomux_grp_regs *);#if defined(CONFIG_MX6QDL ) || defined(CONFIG_MX6Q ) || defined(CONFIG_MX6D ) -int mmdc_do_write_level_calibration (void ); -int mmdc_do_dqs_calibration (void ); +int mmdc_do_write_level_calibration (struct mx6_ddr_sysinfo const *sysinfo); +int mmdc_do_dqs_calibration (struct mx6_ddr_sysinfo const *sysinfo);#endif /* configure mx6 mmdc registers */
board/kosagi/novena/novena_spl.c +2 -2
@@ -605,8 +605,8 @@ void board_init_f(ulong dummy)/* Perform DDR DRAM calibration */ udelay (100 ); -mmdc_do_write_level_calibration (); -mmdc_do_dqs_calibration (); +mmdc_do_write_level_calibration (&novena_ddr_info); +mmdc_do_dqs_calibration (&novena_ddr_info);/* Clear the BSS. */ memset (__bss_start,0 , __bss_end - __bss_start);
Signature · 1 line
2.7.4
PATCH 2/3 mx6: ddr: pass mx6_ddr_sysinfo to calibration routines
Quoted 13 lines · Eric Nelson
The DDR calibration routines have scattered support for bus widths other than 64-bits:
-- The
mmdc_do_write_level_calibration()routine assumes the presence of PHY1, and
-- Themmdc_do_dqs_calibration()routine tries to determine whether one or two DDR PHYs are active by reading MDCTL.Since a caller of these routines must have a valid struct
mx6_ddr_sysinfofor use in callingmx6_dram_cfg(), and the bus width is available in the "dsize" field, use this structure to inform the calibration routines which PHYs are active.
Quoted 4 lines
This allows the use of the DDR calibration routines on CPU variants like i.MX6SL that only have a single MMDC port.
Signed-off-by Eric Nelson <[email protected]>
Signature · 2 lines
Best regards, Marek Vasut
PATCH 3/3 mx6: ddr: add routine to return DDR calibration data
In reply to Eric NelsonAdd routine mmdc_read_calibration() to return the output of DDR calibration. This can be used for debugging or to aid in construction of static memory configuration.
--- arch/arm/cpu/armv7/mx6/ddr.c | 23 +++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/mx6-ddr.h | 2 ++ 2 files changed, 25 insertions(+)
arch/arm/cpu/armv7/mx6/ddr.c +23 -0
@@ -1501,6 +1501,29 @@ void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,mdelay (1 ); } +void mmdc_read_calibration (struct mx6_ddr_sysinfo const *sysinfo, +struct mx6_mmdc_calibration *calib) +{ +struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR ; +struct mmdc_p_regs *mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR ; + + calib->p0_mpwldectrl0 =readl (&mmdc0->mpwldectrl0); + calib->p0_mpwldectrl1 =readl (&mmdc0->mpwldectrl1); + calib->p0_mpdgctrl0 =readl (&mmdc0->mpdgctrl0); + calib->p0_mpdgctrl1 =readl (&mmdc0->mpdgctrl1); + calib->p0_mprddlctl =readl (&mmdc0->mprddlctl); + calib->p0_mpwrdlctl =readl (&mmdc0->mpwrdlctl); + +if (sysinfo->dsize ==2 ) { + calib->p1_mpwldectrl0 =readl (&mmdc1->mpwldectrl0); + calib->p1_mpwldectrl1 =readl (&mmdc1->mpwldectrl1); + calib->p1_mpdgctrl0 =readl (&mmdc1->mpdgctrl0); + calib->p1_mpdgctrl1 =readl (&mmdc1->mpdgctrl1); + calib->p1_mprddlctl =readl (&mmdc1->mprddlctl); + calib->p1_mpwrdlctl =readl (&mmdc1->mpwrdlctl); + } +} +void mx6_dram_cfg (const struct mx6_ddr_sysinfo *sysinfo,const struct mx6_mmdc_calibration *calib,const void *ddr_cfg)
arch/arm/include/asm/arch-mx6/mx6-ddr.h +2 -0
@@ -461,6 +461,8 @@ void mx6sl_dram_iocfg(unsigned width,#if defined(CONFIG_MX6QDL ) || defined(CONFIG_MX6Q ) || defined(CONFIG_MX6D )int mmdc_do_write_level_calibration (struct mx6_ddr_sysinfo const *sysinfo);int mmdc_do_dqs_calibration (struct mx6_ddr_sysinfo const *sysinfo); +void mmdc_read_calibration (struct mx6_ddr_sysinfo const *sysinfo, +struct mx6_mmdc_calibration *calib);#endif /* configure mx6 mmdc registers */
Signature · 1 line
2.7.4
PATCH 3/3 mx6: ddr: add routine to return DDR calibration data
Quoted 5 lines · Eric Nelson
Add routine
mmdc_read_calibration()to return the output of DDR calibration. This can be used for debugging or to aid in construction of static memory configuration.Signed-off-by Eric Nelson <[email protected]>
Do you plan to use it or will this be mostly dead code ?
Quoted 53 lines
--- arch/arm/cpu/armv7/mx6/ddr.c | 23 +++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/mx6-ddr.h | 2 ++ 2 files changed, 25 insertions(+)arch/arm/cpu/armv7/mx6/ddr.c +23
-0@@ -1501,6 +1501,29 @@ void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,mdelay (1 ); } +void mmdc_read_calibration (struct mx6_ddr_sysinfo const *sysinfo, +struct mx6_mmdc_calibration *calib) +{ +struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR ; +struct mmdc_p_regs *mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR ; + + calib->p0_mpwldectrl0 =readl (&mmdc0->mpwldectrl0); + calib->p0_mpwldectrl1 =readl (&mmdc0->mpwldectrl1); + calib->p0_mpdgctrl0 =readl (&mmdc0->mpdgctrl0); + calib->p0_mpdgctrl1 =readl (&mmdc0->mpdgctrl1); + calib->p0_mprddlctl =readl (&mmdc0->mprddlctl); + calib->p0_mpwrdlctl =readl (&mmdc0->mpwrdlctl); + +if (sysinfo->dsize ==2 ) { + calib->p1_mpwldectrl0 =readl (&mmdc1->mpwldectrl0); + calib->p1_mpwldectrl1 =readl (&mmdc1->mpwldectrl1); + calib->p1_mpdgctrl0 =readl (&mmdc1->mpdgctrl0); + calib->p1_mpdgctrl1 =readl (&mmdc1->mpdgctrl1); + calib->p1_mprddlctl =readl (&mmdc1->mprddlctl); + calib->p1_mpwrdlctl =readl (&mmdc1->mpwrdlctl); + } +} +void mx6_dram_cfg (const struct mx6_ddr_sysinfo *sysinfo,const struct mx6_mmdc_calibration *calib,const void *ddr_cfg)arch/arm/include/asm/arch-mx6/mx6-ddr.h +2
-0@@ -461,6 +461,8 @@ void mx6sl_dram_iocfg(unsigned width,#if defined(CONFIG_MX6QDL ) || defined(CONFIG_MX6Q ) || defined(CONFIG_MX6D )int mmdc_do_write_level_calibration (struct mx6_ddr_sysinfo const *sysinfo);int mmdc_do_dqs_calibration (struct mx6_ddr_sysinfo const *sysinfo); +void mmdc_read_calibration (struct mx6_ddr_sysinfo const *sysinfo, +struct mx6_mmdc_calibration *calib);#endif /* configure mx6 mmdc registers */
Signature · 2 lines
Best regards, Marek Vasut
PATCH 3/3 mx6: ddr: add routine to return DDR calibration data
Hi Marek,
Quoted 9 lines · Marek Vasut
Quoted 5 lines · Eric Nelson
Add routine
mmdc_read_calibration()to return the output of DDR calibration. This can be used for debugging or to aid in construction of static memory configuration.Signed-off-by Eric Nelson <[email protected]>Do you plan to use it or will this be mostly dead code ?
I plan to use it.
I'm cleaning things up before (re)sending a patch adding the virtual "mx6memcal" board and wanted to push the supporting changes in a separate set.
I have one more independent patch (4/3?) to send before the new board.
PATCH 3/3 mx6: ddr: add routine to return DDR calibration data
Quoted 1 line · Eric Nelson
Hi Marek,
Hi!
Quoted 8 lines · Marek Vasut
Quoted 7 lines · Eric Nelson
Quoted 5 lines
Add routine
mmdc_read_calibration()to return the output of DDR calibration. This can be used for debugging or to aid in construction of static memory configuration.Signed-off-by Eric Nelson <[email protected]>
Quoted 8 lines
Quoted 2 lines
Do you plan to use it or will this be mostly dead code ?
I plan to use it.
I'm cleaning things up before (re)sending a patch adding the virtual "mx6memcal" board and wanted to push the supporting changes in a separate set.
Oh cool, all right.
Quoted 3 lines
I have one more independent patch (4/3?) to send before the new board.
Signature · 2 lines
Best regards, Marek Vasut
PATCH 1/1 ARM: mx6: ddr: use Kconfig for inclusion of DDR calibration routines
In reply to Eric NelsonThe DDR calibration routines are gated by conditionals for the i.MX6DQ SOCs, but with the use of the sysinfo parameter, these are usable on at least i.MX6SDL and i.MX6SL variants with DDR3.
Also, since only the Novena board currently uses the dynamic DDR calibration routines, these routines waste space on other boards using SPL.
Add a KConfig entry to allow boards to selectively include the DDR calibration routines.
--- arch/arm/cpu/armv7/mx6/Kconfig | 5 +++++ arch/arm/cpu/armv7/mx6/ddr.c | 3 +-- arch/arm/include/asm/arch-mx6/mx6-ddr.h | 2 +- configs/novena_defconfig | 1 + 4 files changed, 8 insertions(+), 3 deletions(-)
arch/arm/cpu/armv7/mx6/Kconfig +5 -0
@@ -35,6 +35,11 @@ config MX6ULL bool select MX6UL +config MX6_DDRCAL + bool "Include dynamic DDR calibration routines" + depends on SPL + default n + choice prompt "MX6 board select" optional
arch/arm/cpu/armv7/mx6/ddr.c +1 -2
@@ -14,8 +14,7 @@#include <asm/types.h> #include <wait_bit.h> -#if defined(CONFIG_MX6QDL ) || defined(CONFIG_MX6Q ) || defined(CONFIG_MX6D ) - +#if defined(CONFIG_MX6_DDRCAL )static void reset_read_data_fifos (void ) {struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR ;
arch/arm/include/asm/arch-mx6/mx6-ddr.h +1 -1
@@ -458,7 +458,7 @@ void mx6sl_dram_iocfg(unsigned width, const struct mx6sl_iomux_ddr_regs *, const struct mx6sl_iomux_grp_regs *); -#if defined(CONFIG_MX6QDL ) || defined(CONFIG_MX6Q ) || defined(CONFIG_MX6D ) +#if defined(CONFIG_MX6_DDRCAL )int mmdc_do_write_level_calibration (struct mx6_ddr_sysinfo const *sysinfo);int mmdc_do_dqs_calibration (struct mx6_ddr_sysinfo const *sysinfo); void mmdc_read_calibration(struct mx6_ddr_sysinfo const *sysinfo,
configs/novena_defconfig +1 -0
@@ -3,6 +3,7 @@ CONFIG_ARCH_MX6=y CONFIG_SPL_GPIO_SUPPORT=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_MX6_DDRCAL=y CONFIG_TARGET_KOSAGI_NOVENA=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_FAT_SUPPORT=y
Signature · 1 line
2.7.4
PATCH 1/1 ARM: mx6: ddr: use Kconfig for inclusion of DDR calibration routines
Quoted 24 lines · Eric Nelson
The DDR calibration routines are gated by conditionals for the i.MX6DQ SOCs, but with the use of the sysinfo parameter, these are usable on at least i.MX6SDL and i.MX6SL variants with DDR3.
Also, since only the Novena board currently uses the dynamic DDR calibration routines, these routines waste space on other boards using SPL.
Add a KConfig entry to allow boards to selectively include the DDR calibration routines.
Signed-off-by Eric Nelson <[email protected]>--- arch/arm/cpu/armv7/mx6/Kconfig | 5 +++++ arch/arm/cpu/armv7/mx6/ddr.c | 3 +-- arch/arm/include/asm/arch-mx6/mx6-ddr.h | 2 +- configs/novena_defconfig | 1 + 4 files changed, 8 insertions(+), 3 deletions(-)arch/arm/cpu/armv7/mx6/Kconfig +0
-0
arch/arm/cpu/armv7/mx6/Kconfig config MX6ULL · line 41
Quoted 7 lines
arch/arm/cpu/armv7/mx6/Kconfig +4
-0@@ -35,6 +35,11 @@ config MX6ULL bool select MX6UL +config MX6_DDRCAL + bool "Include dynamic DDR calibration routines" + depends on SPL + default n
Help text would really be helpful ;)
Quoted 43 lines
arch/arm/cpu/armv7/mx6/Kconfig +0
-0choice prompt "MX6 board select" optionalarch/arm/cpu/armv7/mx6/ddr.c +1
-2@@ -14,8 +14,7 @@#include <asm/types.h> #include <wait_bit.h> -#if defined(CONFIG_MX6QDL ) || defined(CONFIG_MX6Q ) || defined(CONFIG_MX6D ) - +#if defined(CONFIG_MX6_DDRCAL )static void reset_read_data_fifos (void ) {struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR ;arch/arm/include/asm/arch-mx6/mx6-ddr.h +1
-1@@ -458,7 +458,7 @@ void mx6sl_dram_iocfg(unsigned width, const struct mx6sl_iomux_ddr_regs *, const struct mx6sl_iomux_grp_regs *); -#if defined(CONFIG_MX6QDL ) || defined(CONFIG_MX6Q ) || defined(CONFIG_MX6D ) +#if defined(CONFIG_MX6_DDRCAL )int mmdc_do_write_level_calibration (struct mx6_ddr_sysinfo const *sysinfo);int mmdc_do_dqs_calibration (struct mx6_ddr_sysinfo const *sysinfo); void mmdc_read_calibration(struct mx6_ddr_sysinfo const *sysinfo,configs/novena_defconfig +1
-0@@ -3,6 +3,7 @@ CONFIG_ARCH_MX6=y CONFIG_SPL_GPIO_SUPPORT=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_MX6_DDRCAL=y CONFIG_TARGET_KOSAGI_NOVENA=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_FAT_SUPPORT=y
Signature · 2 lines
Best regards, Marek Vasut
PATCH 1/1 ARM: mx6: ddr: use Kconfig for inclusion of DDR calibration routines
Thanks Marek,
Quoted 28 lines · Marek Vasut
Quoted 27 lines · Eric Nelson
The DDR calibration routines are gated by conditionals for the i.MX6DQ SOCs, but with the use of the sysinfo parameter, these are usable on at least i.MX6SDL and i.MX6SL variants with DDR3.
Also, since only the Novena board currently uses the dynamic DDR calibration routines, these routines waste space on other boards using SPL.
Add a KConfig entry to allow boards to selectively include the DDR calibration routines.
Signed-off-by Eric Nelson <[email protected]>--- arch/arm/cpu/armv7/mx6/Kconfig | 5 +++++ arch/arm/cpu/armv7/mx6/ddr.c | 3 +-- arch/arm/include/asm/arch-mx6/mx6-ddr.h | 2 +- configs/novena_defconfig | 1 + 4 files changed, 8 insertions(+), 3 deletions(-)arch/arm/cpu/armv7/mx6/Kconfig +0
-0@@ -35,6 +35,11 @@ config MX6ULL bool select MX6UL
Quoted 7 lines
arch/arm/cpu/armv7/mx6/Kconfig config MX6ULL · line 41
Quoted 4 lines
arch/arm/cpu/armv7/mx6/Kconfig +4
-0+config MX6_DDRCAL + bool "Include dynamic DDR calibration routines" + depends on SPL + default nHelp text would really be helpful ;)
Cool.
I'll fix this and re-send the series as V2 (with the fourth patch).
v2 cover mx6: ddr: updates for dynamic DDR calibration
This set of patches updates the interface to the DDR calibration in preparation for the addition of a pseudo-board for calibration on i.MX6.
The first patch fixes an ommission in the use of the DG_CMP_CYC flag in register MPDGCTRL0.
The second patch cleans up the handling of bus widths by passing the system configuration information to the calibration routines.
The third patch adds support for returning the calibration data written to the MMDC registers.
The fourth patch adds a Kconfig selection to inclut the DDR calibration routines.
Eric Nelson (4):
mx6: ddr: allow 32 cycles for DQS gating calibration
mx6: ddr: pass mx6_ddr_sysinfo to calibration routines
mx6: ddr: add routine to return DDR calibration data
ARM: mx6: ddr: use Kconfig for inclusion of DDR calibration routines
arch/arm/cpu/armv7/mx6/Kconfig | 5 ++ arch/arm/cpu/armv7/mx6/ddr.c | 131 +++++++++++++++++++++----------- arch/arm/include/asm/arch-mx6/mx6-ddr.h | 8 +- board/kosagi/novena/novena_spl.c | 4 +- configs/novena_defconfig | 1 + 5 files changed, 100 insertions(+), 49 deletions(-)
Signature · 2 lines
V2 adds patch 4 2.7.4
PATCH v2 1/4 mx6: ddr: allow 32 cycles for DQS gating calibration
The DDR calibration code is only setting flag DG_CMP_CYC (DQS gating sample cycle) for the first PHY.
Set the 32-cycle flag for both PHYs and clear when done so the MPDGCTRL0 output value isn't polluted with calibration artifacts.
---
No change in V2.
arch/arm/cpu/armv7/mx6/ddr.c | 7 +++++++ 1 file changed, 7 insertions(+)
arch/arm/cpu/armv7/mx6/ddr.c +7 -0
@@ -347,6 +347,8 @@ int mmdc_do_dqs_calibration(void)* 16 before comparing read data. */ setbits_le32 (&mmdc0->mpdgctrl0,1 <<30 ); +if (sysinfo->dsize ==2 ) +setbits_le32 (&mmdc1->mpdgctrl0,1 <<30 );/* Set bit 28 to start automatic read DQS gating calibration */ setbits_le32 (&mmdc0->mpdgctrl0,5 <<28 );
@@ -365,6 +367,11 @@ int mmdc_do_dqs_calibration(void)if ((bus_size ==0x2 ) && (readl (&mmdc1->mpdgctrl0) &0x00001000 )) errors |=2 ; +/* now disable mpdgctrl0[DG_CMP_CYC] */ +clrbits_le32 (&mmdc0->mpdgctrl0,1 <<30 ); +if (sysinfo->dsize ==2 ) +clrbits_le32 (&mmdc1->mpdgctrl0,1 <<30 ); +/* * DQS gating absolute offset should be modified from * reflecting (HW_DG_LOWx + HW_DG_UPx)/2 to
Signature · 1 line
2.7.4
PATCH v2 2/4 mx6: ddr: pass mx6_ddr_sysinfo to calibration routines
In reply to Eric NelsonThe DDR calibration routines have scattered support for bus widths other than 64-bits:
-- The mmdc_do_write_level_calibration() routine assumes the presence of PHY1, and
-- The mmdc_do_dqs_calibration() routine tries to determine whether one or two DDR PHYs are active by reading MDCTL.
Since a caller of these routines must have a valid struct mx6_ddr_sysinfo for use in calling mx6_dram_cfg(), and the bus width is available in the "dsize" field, use this structure to inform the calibration routines which PHYs are active.
This allows the use of the DDR calibration routines on CPU variants like i.MX6SL that only have a single MMDC port.
---
No change in V2
arch/arm/cpu/armv7/mx6/ddr.c | 98 +++++++++++++++++++-------------- arch/arm/include/asm/arch-mx6/mx6-ddr.h | 4 +- board/kosagi/novena/novena_spl.c | 4 +- 3 files changed, 60 insertions(+), 46 deletions(-)
arch/arm/cpu/armv7/mx6/ddr.c +56 -42
@@ -86,14 +86,15 @@ static void modify_dg_result(u32 *reg_st0, u32 *reg_st1, u32 *reg_ctrl)writel (val_ctrl, reg_ctrl); } -int mmdc_do_write_level_calibration (void ) +int mmdc_do_write_level_calibration (struct mx6_ddr_sysinfo const *sysinfo) {struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR ;struct mmdc_p_regs *mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR ;u32 esdmisc_val, zq_val;u32 errors =0 ; -u32 ldectrl[4 ]; +u32 ldectrl[4 ] = {0 };u32 ddr_mr1 =0x4 ; +u32 rwalat_max;/* * Stash old values in case calibration fails,
@@ -101,8 +102,10 @@ int mmdc_do_write_level_calibration(void)*/ ldectrl[0 ] =readl (&mmdc0->mpwldectrl0); ldectrl[1 ] =readl (&mmdc0->mpwldectrl1); - ldectrl[2 ] =readl (&mmdc1->mpwldectrl0); - ldectrl[3 ] =readl (&mmdc1->mpwldectrl1); +if (sysinfo->dsize ==2 ) { + ldectrl[2 ] =readl (&mmdc1->mpwldectrl0); + ldectrl[3 ] =readl (&mmdc1->mpwldectrl1); + }/* disable DDR logic power down timer */ clrbits_le32 (&mmdc0->mdpdc,0xff00 );
@@ -122,10 +125,10 @@ int mmdc_do_write_level_calibration(void)writel (zq_val & ~0x3 , &mmdc0->mpzqhwctrl);/* 3. increase walat and ralat to maximum */ -setbits_le32 (&mmdc0->mdmisc, - (1 <<6 ) | (1 <<7 ) | (1 <<8 ) | (1 <<16 ) | (1 <<17 )); -setbits_le32 (&mmdc1->mdmisc, - (1 <<6 ) | (1 <<7 ) | (1 <<8 ) | (1 <<16 ) | (1 <<17 )); + rwalat_max = (1 <<6 ) | (1 <<7 ) | (1 <<8 ) | (1 <<16 ) | (1 <<17 ); +setbits_le32 (&mmdc0->mdmisc, rwalat_max); +if (sysinfo->dsize ==2 ) +setbits_le32 (&mmdc1->mdmisc, rwalat_max);/* * 4 & 5. Configure the external DDR device to enter write-leveling * mode through Load Mode Register command.
@@ -152,21 +155,25 @@ int mmdc_do_write_level_calibration(void)*/ if (readl (&mmdc0->mpwlgcr) &0x00000F00 ) errors |=1 ; -if (readl (&mmdc1->mpwlgcr) &0x00000F00 ) - errors |=2 ; +if (sysinfo->dsize ==2 ) +if (readl (&mmdc1->mpwlgcr) &0x00000F00 ) + errors |=2 ;debug ("Ending write leveling calibration. Error mask: 0x%x\n" , errors);/* check to see if cal failed */ if ((readl (&mmdc0->mpwldectrl0) ==0x001F001F ) && (readl (&mmdc0->mpwldectrl1) ==0x001F001F ) && - (readl (&mmdc1->mpwldectrl0) ==0x001F001F ) && - (readl (&mmdc1->mpwldectrl1) ==0x001F001F )) { + ((sysinfo->dsize <2 ) || + ((readl (&mmdc1->mpwldectrl0) ==0x001F001F ) && + (readl (&mmdc1->mpwldectrl1) ==0x001F001F )))) {debug ("Cal seems to have soft-failed due to memory not supporting write leveling on all channels. Restoring original write leveling values.\n" );writel (ldectrl[0 ], &mmdc0->mpwldectrl0);writel (ldectrl[1 ], &mmdc0->mpwldectrl1); -writel (ldectrl[2 ], &mmdc1->mpwldectrl0); -writel (ldectrl[3 ], &mmdc1->mpwldectrl1); +if (sysinfo->dsize ==2 ) { +writel (ldectrl[2 ], &mmdc1->mpwldectrl0); +writel (ldectrl[3 ], &mmdc1->mpwldectrl1); + } errors |=4 ; }
@@ -189,16 +196,20 @@ int mmdc_do_write_level_calibration(void) readl(&mmdc0->mpwldectrl0));debug ("\tMMDC_MPWLDECTRL1 after write level cal: 0x%08X\n" ,readl (&mmdc0->mpwldectrl1)); -debug ("\tMMDC_MPWLDECTRL0 after write level cal: 0x%08X\n" , -readl (&mmdc1->mpwldectrl0)); -debug ("\tMMDC_MPWLDECTRL1 after write level cal: 0x%08X\n" , -readl (&mmdc1->mpwldectrl1)); +if (sysinfo->dsize ==2 ) { +debug ("\tMMDC_MPWLDECTRL0 after write level cal: 0x%08X\n" , +readl (&mmdc1->mpwldectrl0)); +debug ("\tMMDC_MPWLDECTRL1 after write level cal: 0x%08X\n" , +readl (&mmdc1->mpwldectrl1)); + }/* We must force a readback of these values, to get them to stick */ readl (&mmdc0->mpwldectrl0);readl (&mmdc0->mpwldectrl1); -readl (&mmdc1->mpwldectrl0); -readl (&mmdc1->mpwldectrl1); +if (sysinfo->dsize ==2 ) { +readl (&mmdc1->mpwldectrl0); +readl (&mmdc1->mpwldectrl1); + }/* enable DDR logic power down timer: */ setbits_le32 (&mmdc0->mdpdc,0x00005500 );
@@ -212,7 +223,7 @@ int mmdc_do_write_level_calibration(void)return errors; } -int mmdc_do_dqs_calibration (void ) +int mmdc_do_dqs_calibration (struct mx6_ddr_sysinfo const *sysinfo) {struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR ;struct mmdc_p_regs *mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR ;
@@ -223,7 +234,6 @@ int mmdc_do_dqs_calibration(void)bool cs0_enable_initial;bool cs1_enable_initial;u32 esdmisc_val; -u32 bus_size;u32 temp_ref;u32 pddword =0x00ffff00 ;/* best so far, place into MPPDCMPR1 */ u32 errors =0 ;
@@ -292,10 +302,6 @@ int mmdc_do_dqs_calibration(void) cs0_enable =readl (&mmdc0->mdctl) &0x80000000 ; cs1_enable =readl (&mmdc0->mdctl) &0x40000000 ; -/* Check to see what the data bus size is */ - bus_size = (readl (&mmdc0->mdctl) &0x30000 ) >>16 ; -debug ("Data bus size: %d (%d bits)\n" , bus_size,1 << (bus_size +4 )); -precharge_all (cs0_enable, cs1_enable);/* Write the pre-defined value into MPPDCMPR1 */
@@ -314,11 +320,11 @@ int mmdc_do_dqs_calibration(void)* Both PHYs for x64 configuration, if x32, do only PHY0. */ writel (initdelay, &mmdc0->mprddlctl); -if (bus_size ==0x2 ) +if (sysinfo->dsize ==0x2 )writel (initdelay, &mmdc1->mprddlctl);/* Force a measurment, for previous delay setup to take effect. */ -force_delay_measurement (bus_size); +force_delay_measurement (sysinfo->dsize);/* * ***************************
@@ -364,7 +370,7 @@ int mmdc_do_dqs_calibration(void)if (readl (&mmdc0->mpdgctrl0) &0x00001000 ) errors |=1 ; -if ((bus_size ==0x2 ) && (readl (&mmdc1->mpdgctrl0) &0x00001000 )) +if ((sysinfo->dsize ==0x2 ) && (readl (&mmdc1->mpdgctrl0) &0x00001000 )) errors |=2 ;/* now disable mpdgctrl0[DG_CMP_CYC] */
@@ -381,7 +387,7 @@ int mmdc_do_dqs_calibration(void) &mmdc0->mpdgctrl0);modify_dg_result (&mmdc0->mpdghwst2, &mmdc0->mpdghwst3, &mmdc0->mpdgctrl1); -if (bus_size ==0x2 ) { +if (sysinfo->dsize ==0x2 ) {modify_dg_result (&mmdc1->mpdghwst0, &mmdc1->mpdghwst1, &mmdc1->mpdgctrl0); modify_dg_result(&mmdc1->mpdghwst2, &mmdc1->mpdghwst3,
@@ -424,7 +430,8 @@ int mmdc_do_dqs_calibration(void)if (readl (&mmdc0->mprddlhwctl) &0x0000000f ) errors |=4 ; -if ((bus_size ==0x2 ) && (readl (&mmdc1->mprddlhwctl) &0x0000000f )) +if ((sysinfo->dsize ==0x2 ) && + (readl (&mmdc1->mprddlhwctl) &0x0000000f )) errors |=8 ;debug ("Ending Read Delay calibration. Error mask: 0x%x\n" , errors);
@@ -450,14 +457,14 @@ int mmdc_do_dqs_calibration(void)* Both PHYs for x64 configuration, if x32, do only PHY0. */ writel (initdelay, &mmdc0->mpwrdlctl); -if (bus_size ==0x2 ) +if (sysinfo->dsize ==0x2 )writel (initdelay, &mmdc1->mpwrdlctl);/* * XXX This isn't in the manual. Force a measurement, * for previous delay setup to effect. */ -force_delay_measurement (bus_size); +force_delay_measurement (sysinfo->dsize);/* * 9. 10. Start the automatic write calibration process
@@ -477,7 +484,8 @@ int mmdc_do_dqs_calibration(void)if (readl (&mmdc0->mpwrdlhwctl) &0x0000000f ) errors |=16 ; -if ((bus_size ==0x2 ) && (readl (&mmdc1->mpwrdlhwctl) &0x0000000f )) +if ((sysinfo->dsize ==0x2 ) && + (readl (&mmdc1->mpwrdlhwctl) &0x0000000f )) errors |=32 ;debug ("Ending Write Delay calibration. Error mask: 0x%x\n" , errors);
@@ -529,14 +537,18 @@ int mmdc_do_dqs_calibration(void)debug ("Read DQS gating calibration:\n" );debug ("\tMPDGCTRL0 PHY0 = 0x%08X\n" ,readl (&mmdc0->mpdgctrl0));debug ("\tMPDGCTRL1 PHY0 = 0x%08X\n" ,readl (&mmdc0->mpdgctrl1)); -debug ("\tMPDGCTRL0 PHY1 = 0x%08X\n" ,readl (&mmdc1->mpdgctrl0)); -debug ("\tMPDGCTRL1 PHY1 = 0x%08X\n" ,readl (&mmdc1->mpdgctrl1)); +if (sysinfo->dsize ==2 ) { +debug ("\tMPDGCTRL0 PHY1 = 0x%08X\n" ,readl (&mmdc1->mpdgctrl0)); +debug ("\tMPDGCTRL1 PHY1 = 0x%08X\n" ,readl (&mmdc1->mpdgctrl1)); + }debug ("Read calibration:\n" );debug ("\tMPRDDLCTL PHY0 = 0x%08X\n" ,readl (&mmdc0->mprddlctl)); -debug ("\tMPRDDLCTL PHY1 = 0x%08X\n" ,readl (&mmdc1->mprddlctl)); +if (sysinfo->dsize ==2 ) +debug ("\tMPRDDLCTL PHY1 = 0x%08X\n" ,readl (&mmdc1->mprddlctl));debug ("Write calibration:\n" );debug ("\tMPWRDLCTL PHY0 = 0x%08X\n" ,readl (&mmdc0->mpwrdlctl)); -debug ("\tMPWRDLCTL PHY1 = 0x%08X\n" ,readl (&mmdc1->mpwrdlctl)); +if (sysinfo->dsize ==2 ) +debug ("\tMPWRDLCTL PHY1 = 0x%08X\n" ,readl (&mmdc1->mpwrdlctl));/* * Registers below are for debugging purposes. These print out
@@ -548,10 +560,12 @@ int mmdc_do_dqs_calibration(void)debug ("\tMPDGHWST1 PHY0 = 0x%08x\n" ,readl (&mmdc0->mpdghwst1));debug ("\tMPDGHWST2 PHY0 = 0x%08x\n" ,readl (&mmdc0->mpdghwst2));debug ("\tMPDGHWST3 PHY0 = 0x%08x\n" ,readl (&mmdc0->mpdghwst3)); -debug ("\tMPDGHWST0 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst0)); -debug ("\tMPDGHWST1 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst1)); -debug ("\tMPDGHWST2 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst2)); -debug ("\tMPDGHWST3 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst3)); +if (sysinfo->dsize ==2 ) { +debug ("\tMPDGHWST0 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst0)); +debug ("\tMPDGHWST1 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst1)); +debug ("\tMPDGHWST2 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst2)); +debug ("\tMPDGHWST3 PHY1 = 0x%08x\n" ,readl (&mmdc1->mpdghwst3)); + }debug ("Final do_dqs_calibration error mask: 0x%x\n" , errors);
arch/arm/include/asm/arch-mx6/mx6-ddr.h +2 -2
@@ -459,8 +459,8 @@ void mx6sl_dram_iocfg(unsigned width, const struct mx6sl_iomux_grp_regs *);#if defined(CONFIG_MX6QDL ) || defined(CONFIG_MX6Q ) || defined(CONFIG_MX6D ) -int mmdc_do_write_level_calibration (void ); -int mmdc_do_dqs_calibration (void ); +int mmdc_do_write_level_calibration (struct mx6_ddr_sysinfo const *sysinfo); +int mmdc_do_dqs_calibration (struct mx6_ddr_sysinfo const *sysinfo);#endif /* configure mx6 mmdc registers */
board/kosagi/novena/novena_spl.c +2 -2
@@ -605,8 +605,8 @@ void board_init_f(ulong dummy)/* Perform DDR DRAM calibration */ udelay (100 ); -mmdc_do_write_level_calibration (); -mmdc_do_dqs_calibration (); +mmdc_do_write_level_calibration (&novena_ddr_info); +mmdc_do_dqs_calibration (&novena_ddr_info);/* Clear the BSS. */ memset (__bss_start,0 , __bss_end - __bss_start);
Signature · 1 line
2.7.4
PATCH v2 3/4 mx6: ddr: add routine to return DDR calibration data
In reply to Eric NelsonAdd routine mmdc_read_calibration() to return the output of DDR calibration. This can be used for debugging or to aid in construction of static memory configuration.
This routine will be used in a subsequent patch set adding a virtual "mx6memcal" board, but could also be useful when gathering statistics during an initial production run.
---
Commit message expanded in V2
arch/arm/cpu/armv7/mx6/ddr.c | 23 +++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/mx6-ddr.h | 2 ++ 2 files changed, 25 insertions(+)
arch/arm/cpu/armv7/mx6/ddr.c +23 -0
@@ -1501,6 +1501,29 @@ void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,mdelay (1 ); } +void mmdc_read_calibration (struct mx6_ddr_sysinfo const *sysinfo, +struct mx6_mmdc_calibration *calib) +{ +struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR ; +struct mmdc_p_regs *mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR ; + + calib->p0_mpwldectrl0 =readl (&mmdc0->mpwldectrl0); + calib->p0_mpwldectrl1 =readl (&mmdc0->mpwldectrl1); + calib->p0_mpdgctrl0 =readl (&mmdc0->mpdgctrl0); + calib->p0_mpdgctrl1 =readl (&mmdc0->mpdgctrl1); + calib->p0_mprddlctl =readl (&mmdc0->mprddlctl); + calib->p0_mpwrdlctl =readl (&mmdc0->mpwrdlctl); + +if (sysinfo->dsize ==2 ) { + calib->p1_mpwldectrl0 =readl (&mmdc1->mpwldectrl0); + calib->p1_mpwldectrl1 =readl (&mmdc1->mpwldectrl1); + calib->p1_mpdgctrl0 =readl (&mmdc1->mpdgctrl0); + calib->p1_mpdgctrl1 =readl (&mmdc1->mpdgctrl1); + calib->p1_mprddlctl =readl (&mmdc1->mprddlctl); + calib->p1_mpwrdlctl =readl (&mmdc1->mpwrdlctl); + } +} +void mx6_dram_cfg (const struct mx6_ddr_sysinfo *sysinfo,const struct mx6_mmdc_calibration *calib,const void *ddr_cfg)
arch/arm/include/asm/arch-mx6/mx6-ddr.h +2 -0
@@ -461,6 +461,8 @@ void mx6sl_dram_iocfg(unsigned width,#if defined(CONFIG_MX6QDL ) || defined(CONFIG_MX6Q ) || defined(CONFIG_MX6D )int mmdc_do_write_level_calibration (struct mx6_ddr_sysinfo const *sysinfo);int mmdc_do_dqs_calibration (struct mx6_ddr_sysinfo const *sysinfo); +void mmdc_read_calibration (struct mx6_ddr_sysinfo const *sysinfo, +struct mx6_mmdc_calibration *calib);#endif /* configure mx6 mmdc registers */
Signature · 1 line
2.7.4
PATCH v2 4/4 ARM: mx6: ddr: use Kconfig for inclusion of DDR calibration routines
In reply to Eric NelsonThe DDR calibration routines are gated by conditionals for the i.MX6DQ SOCs, but with the use of the sysinfo parameter, these are usable on at least i.MX6SDL and i.MX6SL variants with DDR3.
Also, since only the Novena board currently uses the dynamic DDR calibration routines, these routines waste space on other boards using SPL.
Add a KConfig entry to allow boards to selectively include the DDR calibration routines.
--- arch/arm/cpu/armv7/mx6/Kconfig | 8 ++++++++ arch/arm/cpu/armv7/mx6/ddr.c | 3 +-- arch/arm/include/asm/arch-mx6/mx6-ddr.h | 2 +- configs/novena_defconfig | 1 + 4 files changed, 11 insertions(+), 3 deletions(-)
arch/arm/cpu/armv7/mx6/Kconfig +8 -0
@@ -35,6 +35,14 @@ config MX6ULL bool select MX6UL +config MX6_DDRCAL + bool "Include dynamic DDR calibration routines" + depends on SPL + default n + help + Say "Y" if your board uses dynamic (per-boot) DDR calibration. + If unsure, say N. + choice prompt "MX6 board select" optional
arch/arm/cpu/armv7/mx6/ddr.c +1 -2
@@ -14,8 +14,7 @@#include <asm/types.h> #include <wait_bit.h> -#if defined(CONFIG_MX6QDL ) || defined(CONFIG_MX6Q ) || defined(CONFIG_MX6D ) - +#if defined(CONFIG_MX6_DDRCAL )static void reset_read_data_fifos (void ) {struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR ;
arch/arm/include/asm/arch-mx6/mx6-ddr.h +1 -1
@@ -458,7 +458,7 @@ void mx6sl_dram_iocfg(unsigned width, const struct mx6sl_iomux_ddr_regs *, const struct mx6sl_iomux_grp_regs *); -#if defined(CONFIG_MX6QDL ) || defined(CONFIG_MX6Q ) || defined(CONFIG_MX6D ) +#if defined(CONFIG_MX6_DDRCAL )int mmdc_do_write_level_calibration (struct mx6_ddr_sysinfo const *sysinfo);int mmdc_do_dqs_calibration (struct mx6_ddr_sysinfo const *sysinfo); void mmdc_read_calibration(struct mx6_ddr_sysinfo const *sysinfo,
configs/novena_defconfig +1 -0
@@ -3,6 +3,7 @@ CONFIG_ARCH_MX6=y CONFIG_SPL_GPIO_SUPPORT=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_MX6_DDRCAL=y CONFIG_TARGET_KOSAGI_NOVENA=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_FAT_SUPPORT=y
Signature · 1 line
2.7.4
v2 cover mx6: ddr: updates for dynamic DDR calibration
In reply to Eric NelsonQuoted 3 lines · Eric Nelson
This set of patches updates the interface to the DDR calibration in preparation for the addition of a pseudo-board for calibration on i.MX6.
What's the current state in regard of applying this patchset?
Does it also work on i.MX6SX like the sabresd board?
Thanks
-- Christoph
v2 cover mx6: ddr: updates for dynamic DDR calibration
In reply to Eric NelsonQuoted 22 lines · Eric Nelson
This set of patches updates the interface to the DDR calibration in preparation for the addition of a pseudo-board for calibration on i.MX6.
The first patch fixes an ommission in the use of the
DG_CMP_CYCflag in register MPDGCTRL0.The second patch cleans up the handling of bus widths by passing the system configuration information to the calibration routines.
The third patch adds support for returning the calibration data written to the MMDC registers.
The fourth patch adds a
Kconfigselection to inclut the DDR calibration routines.Eric Nelson (4):
mx6: ddr: allow 32 cycles for DQS gating calibration
mx6: ddr: passmx6_ddr_sysinfoto calibration routines
mx6: ddr: add routine to return DDR calibration data
ARM: mx6: ddr: useKconfigfor inclusion of DDR calibration routines
Quoted 7 lines
arch/arm/cpu/armv7/mx6/Kconfig | 5 ++ arch/arm/cpu/armv7/mx6/ddr.c | 131 +++++++++++++++++++++----------- arch/arm/include/asm/arch-mx6/mx6-ddr.h | 8 +- board/kosagi/novena/novena_spl.c | 4 +- configs/novena_defconfig | 1 + 5 files changed, 100 insertions(+), 49 deletions(-)
Applied to u-boot-imx, thanks !
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de =====================================================================
cover ARM: imx: mx6: Add virtual mx6memcal board
In reply to Eric NelsonThis patch series adds a DDR calibration tool in the form of a virtual i.MX6 board named "mx6memcal".
I was hoping to send this without the RFC, but found something that needs some investigation in the process of cleanup (see ccgr_init in patch 1) and would like to get it out so that others can experiment and so I can get some additional feedback.
The board is added in patch 1.
The second patch is kept separate because I don't yet know why this is needed. If the initial calibration is left as all zero, the calibration of the Nitrogen6_Max board will fail. Other boards don't appear to have this problem.
The rest of the patches add configurations for use in testing.
Most of the boards are supported in main-line U-Boot, though I did add the Nitrogen6_max board as a test of a 4GiB DDR arrangement.
The 'tr1x' board is a custom design that uses i.MX6SL and DDR3 that I've been testing against and it works fine.
The mx6slevk and warp boards aren't currently supported because LPDDR2 isn't fully supported.
I did have them working in a local tree that pre-dated Marek's addition of the calibration code into main-line:
https://github.com/ericnelsonaz/u-boot/tree/memcal-pass1
Finally, as noted in the commit message, I saw some quirkiness with a Wandboard Quad. For some reason, the dynamic calibration failed on this platform when I selected 64-bit bus width and I haven't taken time to investigate.
Eric Nelson (9):
mx6: Add board mx6memcal for use in validating DDR
mx6memcal: zero values for MPWRDLCTL cause read DQS calibration errors
mx6memcal: add configuration for SABRE Lite
mx6memcal: add configuration for Nitrogen6_max board
mx6memcal: add configuration for tr1x board (i.MX6SL with DDR3)
mx6memcal: add configuration for Wandboard Solo (512MiB of x32 DDR3)
mx6memcal: add configuration for Wandboard Quad
mx6memcal: add configuration for mx6slevk
mx6memcal: add configuration for warp board (i.MX6SL)
arch/arm/cpu/armv7/mx6/Kconfig | 9 + board/freescale/mx6memcal/Kconfig | 235 +++++++++++++++ board/freescale/mx6memcal/MAINTAINERS | 7 + board/freescale/mx6memcal/Makefile | 13 + board/freescale/mx6memcal/README | 49 +++ board/freescale/mx6memcal/mx6memcal.c | 32 ++ board/freescale/mx6memcal/spl.c | 462 +++++++++++++++++++++++++++++ configs/mx6memcal_defconfig | 32 ++ configs/mx6memcal_mx6slevk_defconfig | 37 +++ configs/mx6memcal_nitrogen6_max_defconfig | 33 +++ configs/mx6memcal_sabrelite_defconfig | 34 +++ configs/mx6memcal_tr1x_defconfig | 36 +++ configs/mx6memcal_wandboard_quad_defconfig | 34 +++ configs/mx6memcal_wandboard_solo_defconfig | 35 +++ configs/mx6memcal_warpboard_defconfig | 39 +++ include/configs/mx6memcal.h | 62 ++++ scripts/config_whitelist.txt | 5 + 17 files changed, 1154 insertions(+) create mode 100644 board/freescale/mx6memcal/Kconfig create mode 100644 board/freescale/mx6memcal/MAINTAINERS create mode 100644 board/freescale/mx6memcal/Makefile create mode 100644 board/freescale/mx6memcal/README create mode 100644 board/freescale/mx6memcal/mx6memcal.c create mode 100644 board/freescale/mx6memcal/spl.c create mode 100644 configs/mx6memcal_defconfig create mode 100644 configs/mx6memcal_mx6slevk_defconfig create mode 100644 configs/mx6memcal_nitrogen6_max_defconfig create mode 100644 configs/mx6memcal_sabrelite_defconfig create mode 100644 configs/mx6memcal_tr1x_defconfig create mode 100644 configs/mx6memcal_wandboard_quad_defconfig create mode 100644 configs/mx6memcal_wandboard_solo_defconfig create mode 100644 configs/mx6memcal_warpboard_defconfig create mode 100644 include/configs/mx6memcal.h
Signature · 1 line
2.7.4
RFC PATCH 1/9 mx6: Add board mx6memcal for use in validating DDR
This is a virtual "board" that uses configuration files and Kconfig to define the memory layout used by a real board during the board bring-up process.
It generates an SPL image that can be loaded using imx_usb or SB_LOADER.exe.
When run, it will generate a set of calibration constants for use in either or both a DCD configuration file for boards that use u-boot.imx or struct mx6_mmdc_calibration for boards that boot via SPL.
In essence, it is a configurable, open-source variant of the Freescale ddr-stress tool.
https://community.nxp.com/docs/DOC-105652
File mx6memcal_defconfig configures the board for use with mx6sabresd or mx6qsabreauto.
--- arch/arm/cpu/armv7/mx6/Kconfig | 9 + board/freescale/mx6memcal/Kconfig | 235 +++++++++++++++++ board/freescale/mx6memcal/MAINTAINERS | 7 + board/freescale/mx6memcal/Makefile | 13 + board/freescale/mx6memcal/README | 49 ++++ board/freescale/mx6memcal/mx6memcal.c | 32 +++ board/freescale/mx6memcal/spl.c | 458 ++++++++++++++++++++++++++++++++++ configs/mx6memcal_defconfig | 32 +++ include/configs/mx6memcal.h | 62 +++++ scripts/config_whitelist.txt | 5 + 10 files changed, 902 insertions(+) create mode 100644 board/freescale/mx6memcal/Kconfig create mode 100644 board/freescale/mx6memcal/MAINTAINERS create mode 100644 board/freescale/mx6memcal/Makefile create mode 100644 board/freescale/mx6memcal/README create mode 100644 board/freescale/mx6memcal/mx6memcal.c create mode 100644 board/freescale/mx6memcal/spl.c create mode 100644 configs/mx6memcal_defconfig create mode 100644 include/configs/mx6memcal.h
arch/arm/cpu/armv7/mx6/Kconfig +9 -0
@@ -100,6 +100,14 @@ config TARGET_MX6CUBOXI bool "Solid-run mx6 boards" select SUPPORT_SPL +config TARGET_MX6MEMCAL + bool "mx6memcal" + select SUPPORT_SPL + help + The mx6memcal board is a virtual board that can be used to validate + and characterize the memory layout of a new design during the initial + development and pre-production stages. + config TARGET_MX6QARM2 bool "mx6qarm2"
@@ -245,6 +253,7 @@ source "board/el/el6x/Kconfig" source "board/embest/mx6boards/Kconfig" source "board/engicam/icorem6/Kconfig" source "board/freescale/mx6qarm2/Kconfig" +source "board/freescale/mx6memcal/Kconfig" source "board/freescale/mx6qsabreauto/Kconfig" source "board/freescale/mx6sabresd/Kconfig" source "board/freescale/mx6slevk/Kconfig"
board/freescale/mx6memcal/Kconfig new file +235 -0
235 lines not on this page · raw message
board/freescale/mx6memcal/MAINTAINERS new file +7 -0
@@ -0,0 +1,7 @@ +MX6MEMCAL BOARD +M: Eric Nelson <[email protected]> +S: Maintained +F: board/freescale/mx6memcal/ +F: include/configs/mx6memcal.h +F: configs/mx6memcal_defconfig +
board/freescale/mx6memcal/Makefile new file +13 -0
@@ -0,0 +1,13 @@ +# +# Copyright (C) 2007, Guennadi Liakhovetski <[email protected]> +# +# (C) Copyright 2011 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +ifdef CONFIG_SPL_BUILD +obj-y := spl.o +else +obj-y := mx6memcal.o +endif
board/freescale/mx6memcal/README new file +49 -0
49 lines not on this page · raw message
board/freescale/mx6memcal/mx6memcal.c new file +32 -0
@@ -0,0 +1,32 @@ +/* +* mx6memcal board support - provides a minimal, UART-only +* U-Boot that's capable of running a memory test. +* +* Copyright (C) 2016 Nelson Integration, LLC +* Author: Eric Nelson <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <asm/arch/sys_proto.h> + +DECLARE_GLOBAL_DATA_PTR ; + +int board_init (void ) +{ +return 0 ; +} + +int checkboard (void ) +{ +puts ("Board: mx6memcal\n" ); +return 0 ; +} + +int dram_init (void ) +{ + gd->ram_size =imx_ddr_size (); +return 0 ; +} +
board/freescale/mx6memcal/spl.c new file +458 -0
458 lines not on this page · raw message
configs/mx6memcal_defconfig new file +32 -0
@@ -0,0 +1,32 @@ +CONFIG_ARM=y +CONFIG_ARCH_MX6=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_MX6_DDRCAL=y +CONFIG_TARGET_MX6MEMCAL=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_WATCHDOG_SUPPORT=y +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,SPL,MX6QDL" +CONFIG_SPL=y +CONFIG_HUSH_PARSER=y +# CONFIG_CMD_BOOTD is not set +# CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_SAVEENV is not set +# CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MEMINFO=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_CACHE=y +CONFIG_REGEX=y
include/configs/mx6memcal.h new file +62 -0
62 lines not on this page · raw message
scripts/config_whitelist.txt +5 -0
@@ -781,6 +781,7 @@ CONFIG_DCACHE_OFF CONFIG_DCACHE_WB CONFIG_DCFG_ADDR CONFIG_DCLK_DIV +CONFIG_DDR3 CONFIG_DDR_ CONFIG_DDR_2HCLK CONFIG_DDR_2T_TIMING
@@ -1947,6 +1948,7 @@ CONFIG_LPC32XX_SSP CONFIG_LPC32XX_SSP_TIMEOUT CONFIG_LPC_BASE CONFIG_LPC_IO_BASE +CONFIG_LPDDR2 CONFIG_LPUART CONFIG_LPUART_32B_REG CONFIG_LQ035Q1_LCD_MODE
@@ -8048,6 +8050,9 @@ CONFIG_TWR_P1025 CONFIG_TX_DESCR_NUM CONFIG_TZSW_RESERVED_DRAM_SIZE CONFIG_T_SH7706LSR +CONFIG_UART1_CSI0_DAT10_11 +CONFIG_UART1_UART1 +CONFIG_UART2_EIM_D26_27 CONFIG_UART_BASE CONFIG_UART_BR_PRELIM CONFIG_UART_CONSOLE
Signature · 1 line
2.7.4
Fabio Estevam
reviewerRFC PATCH 1/9 mx6: Add board mx6memcal for use in validating DDR
Hi Eric,
Quoted 12 lines · Eric Nelson
This is a virtual "board" that uses configuration files and
Kconfigto define the memory layout used by a real board during the board bring-up process.It generates an SPL image that can be loaded using
imx_usbor SB_LOADER.exe.When run, it will generate a set of calibration constants for use in either or both a DCD configuration file for boards that use u-boot.imx or struct
mx6_mmdc_calibrationfor boards that boot via SPL.
Quoted 7 lines
In essence, it is a configurable, open-source variant of the Freescale ddr-stress tool.
https://community.nxp.com/docs/DOC-105652File
mx6memcal_defconfigconfigures the board for use with mx6sabresd or mx6qsabreauto.
Do you still have plans on refreshing this series?
It does seem very useful.
Thanks
RFC PATCH 1/9 mx6: Add board mx6memcal for use in validating DDR
Hi Fabio,
Quoted 18 lines · Fabio Estevam
Hi Eric,
Quoted 15 lines · Eric Nelson
This is a virtual "board" that uses configuration files and
Kconfigto define the memory layout used by a real board during the board bring-up process.It generates an SPL image that can be loaded using
imx_usbor SB_LOADER.exe.When run, it will generate a set of calibration constants for use in either or both a DCD configuration file for boards that use u-boot.imx or struct
mx6_mmdc_calibrationfor boards that boot via SPL.In essence, it is a configurable, open-source variant of the Freescale ddr-stress tool.
Quoted 7 lines
Quoted 4 lines
https://community.nxp.com/docs/DOC-105652File
mx6memcal_defconfigconfigures the board for use with mx6sabresd or mx6qsabreauto.Do you still have plans on refreshing this series?
Plans is a strong word, but I certainly hope to find some time to continue this effort.
I haven't been doing too many new board bring-ups lately though, so it moved away from my front burner.
I set this aside because I wasn't able to get the "return to RBL" code working and figured I'd try to reverse-engineer the API.
Any hints you have in that area would be helpful, and will solve that other long-standing issue of how to live with SPL on i.MX.
Quoted 2 lines
It does seem very useful.
It is, and even the RFC patch allows very quick testing of large numbers of boards to gather calibration data.
Regards,
Eric
Fabio Estevam
reviewerRFC PATCH 1/9 mx6: Add board mx6memcal for use in validating DDR
Hi Eric,
Quoted 5 lines · Eric Nelson
I set this aside because I wasn't able to get the "return to RBL" code working and figured I'd try to reverse-engineer the API.
Any hints you have in that area would be helpful, and will solve that other long-standing issue of how to live with SPL on i.MX.
Sorry, but what does "return to RBL" mean?
Regards,
Fabio Estevam
RFC PATCH 1/9 mx6: Add board mx6memcal for use in validating DDR
Hi Fabio,
Quoted 4 lines · Fabio Estevam
Hi Eric,
On Fri, Jul 14, 2017 at 2:58 PM, Eric Nelson <[email protected]> wrote:
Quoted 9 lines
Quoted 5 lines
I set this aside because I wasn't able to get the "return to RBL" code working and figured I'd try to reverse-engineer the API.
Any hints you have in that area would be helpful, and will solve that other long-standing issue of how to live with SPL on i.MX.
Sorry, but what does "return to RBL" mean?
I was trying to get the SPL to act as a plugin in this patch set, so we could send
a full U-Boot with a memory test as a payload, but got stuck on the details.
https://lists.denx.de/pipermail/u-boot/2016-June/258784.html
Looking back at the patch set, the plugin support wasn't explicitly included.
I sent some notes in November:
https://lists.denx.de/pipermail/u-boot/2016-November/271647.html
And there was some follow-up in January:
https://lists.denx.de/pipermail/u-boot/2017-January/278518.html
RFC PATCH 2/9 mx6memcal: zero values for MPWRDLCTL cause read DQS calibration errors
In reply to Eric Nelson--- board/freescale/mx6memcal/spl.c | 4 ++++ 1 file changed, 4 insertions(+)
board/freescale/mx6memcal/spl.c +4 -0
@@ -400,6 +400,10 @@ void board_init_f(ulong dummy)memset ((void *)gd,0 ,sizeof (struct global_data )); +/* write leveling calibration defaults */ + calibration.p0_mpwrdlctl =0x40404040 ; + calibration.p1_mpwrdlctl =0x40404040 ; +/* setup AIPS and disable watchdog */ arch_cpu_init ();
Signature · 1 line
2.7.4
RFC PATCH 3/9 mx6memcal: add configuration for SABRE Lite
In reply to Eric Nelson--- configs/mx6memcal_sabrelite_defconfig | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 configs/mx6memcal_sabrelite_defconfig
configs/mx6memcal_sabrelite_defconfig new file +34 -0
@@ -0,0 +1,34 @@ +CONFIG_ARM=y +CONFIG_ARCH_MX6=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_MX6_DDRCAL=y +CONFIG_TARGET_MX6MEMCAL=y +CONFIG_MT41K128M16JT=y +CONFIG_SERIAL_CONSOLE_UART2=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_WATCHDOG_SUPPORT=y +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,SPL,MX6QDL" +CONFIG_SPL=y +CONFIG_HUSH_PARSER=y +# CONFIG_CMD_BOOTD is not set +# CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_SAVEENV is not set +# CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MEMINFO=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_CACHE=y +CONFIG_REGEX=y
Signature · 1 line
2.7.4
RFC PATCH 4/9 mx6memcal: add configuration for Nitrogen6_max board
In reply to Eric Nelson--- configs/mx6memcal_nitrogen6_max_defconfig | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 configs/mx6memcal_nitrogen6_max_defconfig
configs/mx6memcal_nitrogen6_max_defconfig new file +33 -0
@@ -0,0 +1,33 @@ +CONFIG_ARM=y +CONFIG_ARCH_MX6=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_MX6_DDRCAL=y +CONFIG_TARGET_MX6MEMCAL=y +CONFIG_SERIAL_CONSOLE_UART2=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_WATCHDOG_SUPPORT=y +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,SPL,MX6QDL" +CONFIG_SPL=y +CONFIG_HUSH_PARSER=y +# CONFIG_CMD_BOOTD is not set +# CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_SAVEENV is not set +# CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MEMINFO=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_CACHE=y +CONFIG_REGEX=y
Signature · 1 line
2.7.4
RFC PATCH 5/9 mx6memcal: add configuration for tr1x board (i.MX6SL with DDR3)
In reply to Eric Nelson--- configs/mx6memcal_tr1x_defconfig | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 configs/mx6memcal_tr1x_defconfig
configs/mx6memcal_tr1x_defconfig new file +36 -0
@@ -0,0 +1,36 @@ +CONFIG_ARM=y +CONFIG_ARCH_MX6=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_MX6_DDRCAL=y +CONFIG_TARGET_MX6MEMCAL=y +CONFIG_DDRWIDTH=32 +CONFIG_DDRCS=1 +CONFIG_MT41K128M16JT=y +CONFIG_UART1_UART1=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_WATCHDOG_SUPPORT=y +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,SPL,MX6SL" +CONFIG_SPL=y +CONFIG_HUSH_PARSER=y +# CONFIG_CMD_BOOTD is not set +# CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_SAVEENV is not set +# CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MEMINFO=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_CACHE=y +CONFIG_REGEX=y
Signature · 1 line
2.7.4
RFC PATCH 6/9 mx6memcal: add configuration for Wandboard Solo (512MiB of x32 DDR3)
In reply to Eric Nelson--- configs/mx6memcal_wandboard_solo_defconfig | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 configs/mx6memcal_wandboard_solo_defconfig
configs/mx6memcal_wandboard_solo_defconfig new file +35 -0
@@ -0,0 +1,35 @@ +CONFIG_ARM=y +CONFIG_ARCH_MX6=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_MX6_DDRCAL=y +CONFIG_TARGET_MX6MEMCAL=y +CONFIG_DDRWIDTH=32 +CONFIG_DDRCS=1 +CONFIG_H5TQ2G63DFR=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_WATCHDOG_SUPPORT=y +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,SPL,MX6QDL" +CONFIG_SPL=y +CONFIG_HUSH_PARSER=y +# CONFIG_CMD_BOOTD is not set +# CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_SAVEENV is not set +# CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MEMINFO=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_CACHE=y +CONFIG_REGEX=y
Signature · 1 line
2.7.4
RFC PATCH 7/9 mx6memcal: add configuration for Wandboard Quad
In reply to Eric NelsonNote that for some reason, this is failing for me unless I select a DDR bus width of 32 bits.
--- configs/mx6memcal_wandboard_quad_defconfig | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 configs/mx6memcal_wandboard_quad_defconfig
configs/mx6memcal_wandboard_quad_defconfig new file +34 -0
@@ -0,0 +1,34 @@ +CONFIG_ARM=y +CONFIG_ARCH_MX6=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_MX6_DDRCAL=y +CONFIG_TARGET_MX6MEMCAL=y +CONFIG_DDRCS=1 +CONFIG_H5TQ4G63AFR=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_WATCHDOG_SUPPORT=y +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,SPL,MX6QDL" +CONFIG_SPL=y +CONFIG_HUSH_PARSER=y +# CONFIG_CMD_BOOTD is not set +# CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_SAVEENV is not set +# CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MEMINFO=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_CACHE=y +CONFIG_REGEX=y
Signature · 1 line
2.7.4
RFC PATCH 8/9 mx6memcal: add configuration for mx6slevk
In reply to Eric Nelson--- configs/mx6memcal_mx6slevk_defconfig | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 configs/mx6memcal_mx6slevk_defconfig
configs/mx6memcal_mx6slevk_defconfig new file +37 -0
@@ -0,0 +1,37 @@ +CONFIG_ARM=y +CONFIG_ARCH_MX6=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_MX6_DDRCAL=y +CONFIG_TARGET_MX6MEMCAL=y +CONFIG_DDRWIDTH=32 +CONFIG_DDRCS=1 +CONFIG_LPDDR2=y +CONFIG_RALAT=2 +CONFIG_UART1_UART1=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_WATCHDOG_SUPPORT=y +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,SPL,MX6SL" +CONFIG_SPL=y +CONFIG_HUSH_PARSER=y +# CONFIG_CMD_BOOTD is not set +# CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_SAVEENV is not set +# CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MEMINFO=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_CACHE=y +CONFIG_REGEX=y
Signature · 1 line
2.7.4
RFC PATCH 9/9 mx6memcal: add configuration for warp board (i.MX6SL)
In reply to Eric Nelson--- configs/mx6memcal_warpboard_defconfig | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 configs/mx6memcal_warpboard_defconfig
configs/mx6memcal_warpboard_defconfig new file +39 -0
@@ -0,0 +1,39 @@ +CONFIG_ARM=y +CONFIG_ARCH_MX6=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_MX6_DDRCAL=y +CONFIG_TARGET_MX6MEMCAL=y +CONFIG_DDRWIDTH=32 +CONFIG_DDRCS=1 +CONFIG_LPDDR2=y +CONFIG_MT29PZZZ4D4BKESK=y +CONFIG_DRAM_DRIVE_STRENGTH=4 +CONFIG_RALAT=2 +CONFIG_UART1_UART1=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_WATCHDOG_SUPPORT=y +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,SPL,MX6SL" +CONFIG_SPL=y +CONFIG_HUSH_PARSER=y +# CONFIG_CMD_BOOTD is not set +# CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_SAVEENV is not set +# CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MEMINFO=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_CACHE=y +CONFIG_REGEX=y
Signature · 1 line
2.7.4
cover ARM: imx: mx6: Add plugin support for SPL
In reply to Eric NelsonI forgot to mention in the cover letter for the previous patch set that because the mx6memcal board has no implementation of storage (it only supports a serial console and DDR), I haven't tested the resulting U-Boot, which has very little besides "mtest" included.
I'm hoping to use this code base (mx6memcal) as a straw man for loading both SPL (as a plugin) and U-Boot through the serial download path as we've previously discussed in at least [1], [2] and [3].
Now that Peng's patch to imximage has been applied, we can start to look at the implementation details, and I hope this patch set can help move us toward an implementation.
The gist of what's needed to allow SPL to be loaded as a plugin and avoid the need for removable storage or a full (non-SPL) U-Boot is shown in patch 2.
That is, we need something akin to setjmp/longjmp to:
1. to save the early state of the machine before SPL configures the DDR controller, and
2. a routine that we can call to return to the boot ROM
To address #1, there's a clear precedent in the support for a save_boot_params() routine and patch 2 adds one that simply saves the working register set. Examining the registers used by the ROM code shows that r0-r9 plus sp and lr are sufficient.
Experimentally, I've found that the boot ROM stack is initialized to 0x91ffb4 and that the stack pointer is at 0x91febc (248 bytes) on all of the machines I've tested against (MX6Q, MX6DL, MX6S and MX6SL), so we can save the stack just by moving the SPL stack (patch #1).
We'll also need to determine where the decision to return to the boot ROM occurs (i.e. when we call routine #2).
The obvious place for use during development is right after DDR initialization if loaded through the serial downloader, but it might also be useful to invoke the serial loader as a last resort instead of the current call to hang().
Patch 3 adds a config file which will allow a build of u-boot.imx with SPL as a plugin followed by u-boot.bin as the primary payload. It highlights the issue of only having a single IMX_CONFIG variable so it breaks the build of a stand-alone SPL. Rather, it doesn't break the build, but produces SPL that is effectively the same as u-boot.imx.
This leaves only the question of what the return_to_rom code should look like, and I'm a bit stumped. The ROM API isn't documented in any document I have.
In Troy's original patch ([4]), he calls a routine that he names HAB_RVT_LOAD_DATA. On i.MX Community ([5]), I found a reference to a plugin_download() routine and I'm not sure where that came from. The Community post suggests that it's used in EBOOT.
I tried a simplistic copy of the tail end of plugin start from [6] that calls pu_irom_hwcnfg_setup() and then returns to ROM without success. I'm not certain that this was the right approach and am hoping for some guidance.
References:
[1] - http://lists.denx.de/pipermail/u-boot/2015-June/thread.html#215606
[2] - http://lists.denx.de/pipermail/u-boot/2016-September/thread.html#266303
[3] - http://lists.denx.de/pipermail/u-boot/2015-May/thread.html#215573
[4] - http://patchwork.ozlabs.org/patch/186054/
[5] - http://community.nxp.com/thread/303794
[6] - http://git.denx.de/?p=u-boot.git;a=blob;f=arch/arm/include/asm/arch-mx6/mx6_plugin.S
Eric Nelson (3):
ARM: mx6: preserve Boot ROM stack in SPL
ARM: mx6: ddr: add plugin-utils placeholder
ARM: imx: mx6memcal: allow build of combined SPL+U-Boot
arch/arm/cpu/armv7/mx6/Makefile | 2 +- arch/arm/cpu/armv7/mx6/ddr.c | 4 ++++ arch/arm/cpu/armv7/mx6/plugin-utils.S | 24 ++++++++++++++++++++++++ arch/arm/imx-common/spl-plus-u-boot.cfg | 4 ++++ arch/arm/include/asm/arch-mx6/mx6-ddr.h | 19 +++++++++++++++++++ configs/mx6memcal_defconfig | 2 +- include/configs/imx6_spl.h | 2 +- 7 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 arch/arm/cpu/armv7/mx6/plugin-utils.S create mode 100644 arch/arm/imx-common/spl-plus-u-boot.cfg
Signature · 1 line
2.7.4
RFC PATCH 1/3 ARM: mx6: preserve Boot ROM stack in SPL
The i.MX6 Boot ROM starts its' stack at 0x091ffb4 and appears to be a little less than 256 bytes deep when starting U-Boot.
This was determined experimentally on i.MX6DL and i.MX6SL.
Allow this stack to be preserved to simplify returning to ROM when SPL is loaded as a plugin.
--- include/configs/imx6_spl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/configs/imx6_spl.h +1 -1
@@ -28,7 +28,7 @@#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv7/omap-common/u-boot-spl.lds"#define CONFIG_SPL_TEXT_BASE 0x00908000#define CONFIG_SPL_MAX_SIZE 0x10000 -#define CONFIG_SPL_STACK 0x0091FFB8 +#define CONFIG_SPL_STACK 0x0091FEB8/* NAND support */ #if defined(CONFIG_SPL_NAND_SUPPORT )
Signature · 1 line
2.7.4
RFC PATCH 2/3 ARM: mx6: ddr: add plugin-utils placeholder
In reply to Eric NelsonAdd entry points for saving the state of the machine at entry from the Boot ROM and for restoring the state before a return.
Note that this needs some fixup before it's useful, so I'm forwarding it as an RFC to solicit advice.
This placeholder is little more than a setjmp/longjmp that saves the SP, LR and registers 0-9. Disassembling the ROM for i.MX6DL and i.MX6SL shows that these are the only registers used by the ROM on those SOCs.
--- arch/arm/cpu/armv7/mx6/Makefile | 2 +- arch/arm/cpu/armv7/mx6/ddr.c | 4 ++++ arch/arm/cpu/armv7/mx6/plugin-utils.S | 24 ++++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/mx6-ddr.h | 19 +++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv7/mx6/plugin-utils.S
arch/arm/cpu/armv7/mx6/Makefile +1 -1
@@ -8,5 +8,5 @@ # obj-y := soc.o clock.o -obj-$(CONFIG_SPL_BUILD) += ddr.o +obj-$(CONFIG_SPL_BUILD) += ddr.o plugin-utils.o obj-$(CONFIG_MP) += mp.o
arch/arm/cpu/armv7/mx6/ddr.c +4 -0
@@ -1536,3 +1536,7 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,hang (); } } + +#ifdef CONFIG_SPL_BUILD +struct plugin_state plugin_state __attribute__((section(".data"))); +#endif
arch/arm/cpu/armv7/mx6/plugin-utils.S new file +24 -0
@@ -0,0 +1,24 @@ +/* + * Utility functions for executing as an i.MX plugin + * + * Copyright (c) 2016 Nelson Integration, LLC + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <asm/system.h> +#include <linux/linkage.h> + +ENTRY(save_boot_params) + ldr r10, =plugin_state + stmia r10, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, fp, sp, lr} + b save_boot_params_ret +ENDPROC(save_boot_params) + +ENTRY(return_to_rom) + ldr r10, =plugin_state + ldmia r10, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, fp, sp, lr} + bx lr +ENDPROC(return_to_rom)
arch/arm/include/asm/arch-mx6/mx6-ddr.h +19 -0
@@ -528,4 +528,23 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *,#define MX6_MMDC_P1_MPZQLP2CTL 0x021b485C#define MX6_MMDC_P1_MPMUR0 0x021b48b8 +#ifdef CONFIG_SPL_BUILD +struct plugin_state { +uint32_t r0; +uint32_t r1; +uint32_t r2; +uint32_t r3; +uint32_t r4; +uint32_t r5; +uint32_t r6; +uint32_t r7; +uint32_t r8; +uint32_t r9; +uint32_t fp; +uint32_t sp; +uint32_t lr; +}; +void return_to_rom (void ); +#endif +#endif /*__ASM_ARCH_MX6_DDR_H__ */
Signature · 1 line
2.7.4
RFC PATCH 3/3 ARM: imx: mx6memcal: allow build of combined SPL+U-Boot
In reply to Eric NelsonAdd an imximage config file to construct u-boot.imx with SPL as a plugin and use it as a straw-man for the mx6memcal virtual board.
Note that this breaks the build of SPL because only one value can be listed for IMX_CONFIG.
As it stands, all imx SPL builds use an almost empty .cfg file from arch/arm/configs/spl_sd.cfg.
This could be hard-coded for use in building SPL if we just remove the comments from the file (copyright).
--- arch/arm/imx-common/spl-plus-u-boot.cfg | 4 ++++ configs/mx6memcal_defconfig | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 arch/arm/imx-common/spl-plus-u-boot.cfg
arch/arm/imx-common/spl-plus-u-boot.cfg new file +4 -0
@@ -0,0 +1,4 @@ +IMAGE_VERSION 2 +BOOT_FROM sd +PLUGIN spl/u-boot-spl.bin 0x00907000 +
configs/mx6memcal_defconfig +1 -1
@@ -6,7 +6,7 @@ CONFIG_MX6_DDRCAL=y CONFIG_TARGET_MX6MEMCAL=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_WATCHDOG_SUPPORT=y -CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,SPL,MX6QDL" +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl-plus-u-boot.cfg,SPL,MX6QDL" CONFIG_SPL=y CONFIG_HUSH_PARSER=y # CONFIG_CMD_BOOTD is not set
Signature · 1 line
2.7.4
cover ARM: imx: mx6: Add plugin support for SPL
In reply to Eric NelsonQuoted 87 lines · Eric Nelson
I forgot to mention in the cover letter for the previous patch set that because the mx6memcal board has no implementation of storage (it only supports a serial console and DDR), I haven't tested the resulting U-Boot, which has very little besides "mtest" included.
I'm hoping to use this code base (mx6memcal) as a straw man for loading both SPL (as a plugin) and U-Boot through the serial download path as we've previously discussed in at least [1], [2] and [3].
Now that Peng's patch to imximage has been applied, we can start to look at the implementation details, and I hope this patch set can help move us toward an implementation.
The gist of what's needed to allow SPL to be loaded as a plugin and avoid the need for removable storage or a full (non-SPL) U-Boot is shown in patch 2.
That is, we need something akin to setjmp/longjmp to:
1. to save the early state of the machine before SPL configures the DDR controller, and
2. a routine that we can call to return to the boot ROMTo address #1, there's a clear precedent in the support for a
save_boot_params()routine and patch 2 adds one that simply saves the working register set. Examining the registers used by the ROM code shows that r0-r9 plus sp and lr are sufficient.Experimentally, I've found that the boot ROM stack is initialized to
0x91ffb4and that the stack pointer is at0x91febc(248 bytes) on all of the machines I've tested against (MX6Q, MX6DL, MX6S and MX6SL), so we can save the stack just by moving the SPL stack (patch #1).We'll also need to determine where the decision to return to the boot ROM occurs (i.e. when we call routine #2).
The obvious place for use during development is right after DDR initialization if loaded through the serial downloader, but it might also be useful to invoke the serial loader as a last resort instead of the current call to
hang().Patch 3 adds a config file which will allow a build of u-boot.imx with SPL as a plugin followed by u-boot.bin as the primary payload. It highlights the issue of only having a single
IMX_CONFIGvariable so it breaks the build of a stand-alone SPL. Rather, it doesn't break the build, but produces SPL that is effectively the same as u-boot.imx.This leaves only the question of what the
return_to_romcode should look like, and I'm a bit stumped. The ROM API isn't documented in any document I have.In Troy's original patch ([4]), he calls a routine that he names
HAB_RVT_LOAD_DATA. On i.MX Community ([5]), I found a reference to aplugin_download()routine and I'm not sure where that came from. The Community post suggests that it's used in EBOOT.I tried a simplistic copy of the tail end of plugin start from [6] that calls
pu_irom_hwcnfg_setup()and then returns to ROM without success. I'm not certain that this was the right approach and am hoping for some guidance.References:
[1] - http://lists.denx.de/pipermail/u-boot/2015-June/thread.html#215606
[2] - http://lists.denx.de/pipermail/u-boot/2016-September/thread.html#266303
[3] - http://lists.denx.de/pipermail/u-boot/2015-May/thread.html#215573
[4] - http://patchwork.ozlabs.org/patch/186054/
[5] - http://community.nxp.com/thread/303794
[6] - http://git.denx.de/?p=u-boot.git;a=blob;f=arch/arm/include/asm/arch-mx6/mx6_plugin.SEric Nelson (3):
ARM: mx6: preserve Boot ROM stack in SPL
ARM: mx6: ddr: add plugin-utils placeholder
ARM: imx: mx6memcal: allow build of combined SPL+U-Bootarch/arm/cpu/armv7/mx6/Makefile | 2 +- arch/arm/cpu/armv7/mx6/ddr.c | 4 ++++ arch/arm/cpu/armv7/mx6/plugin-utils.S | 24 ++++++++++++++++++++++++ arch/arm/imx-common/spl-plus-u-boot.cfg | 4 ++++ arch/arm/include/asm/arch-mx6/mx6-ddr.h | 19 +++++++++++++++++++ configs/mx6memcal_defconfig | 2 +- include/configs/imx6_spl.h | 2 +- 7 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 arch/arm/cpu/armv7/mx6/plugin-utils.S create mode 100644 arch/arm/imx-common/spl-plus-u-boot.cfg
Quoted 3 lines
--
2.7.4
Hi Eric,
I'm interested loading U-Boot from the OTG serial downloader and this looks like a good approach. Thanks for continuing to plug away at this!
If I understand correctly the approach here is to use the plugin support such that the boot ROM will execute the SPL as a plugin which then returns and jumps to U-boot?
I've applied your mx6memcal series to master and support for one of the Gateworks boards I'm working with and can boot that SPL (23KB) fine (so I've got the UART and configured correctly at least). When I adapt that to use pl-plus-u-boot.cfg on top of this patch series the resulting SPL (85KB) image doens't appear to boot (nothing over the serial console) but I'm thinking I'm doing something wrong as imx_usb_loader seems like its not loading it fully or loading it too quickly. Do I need patches to imx_usb_loader or am I doing something obvious wrong here?
Incidentally, did anyone ever proof out the other discussed method where an SPL is built with zmodem and allows loading u-boot.img over that?
Regards,
Tim
cover ARM: imx: mx6: Add plugin support for SPL
Hi Tim,
Quoted 92 lines · Tim Harvey
Quoted 87 lines · Eric Nelson
I forgot to mention in the cover letter for the previous patch set that because the mx6memcal board has no implementation of storage (it only supports a serial console and DDR), I haven't tested the resulting U-Boot, which has very little besides "mtest" included.
I'm hoping to use this code base (mx6memcal) as a straw man for loading both SPL (as a plugin) and U-Boot through the serial download path as we've previously discussed in at least [1], [2] and [3].
Now that Peng's patch to imximage has been applied, we can start to look at the implementation details, and I hope this patch set can help move us toward an implementation.
The gist of what's needed to allow SPL to be loaded as a plugin and avoid the need for removable storage or a full (non-SPL) U-Boot is shown in patch 2.
That is, we need something akin to setjmp/longjmp to:
1. to save the early state of the machine before SPL configures the DDR controller, and
2. a routine that we can call to return to the boot ROMTo address #1, there's a clear precedent in the support for a
save_boot_params()routine and patch 2 adds one that simply saves the working register set. Examining the registers used by the ROM code shows that r0-r9 plus sp and lr are sufficient.Experimentally, I've found that the boot ROM stack is initialized to
0x91ffb4and that the stack pointer is at0x91febc(248 bytes) on all of the machines I've tested against (MX6Q, MX6DL, MX6S and MX6SL), so we can save the stack just by moving the SPL stack (patch #1).We'll also need to determine where the decision to return to the boot ROM occurs (i.e. when we call routine #2).
The obvious place for use during development is right after DDR initialization if loaded through the serial downloader, but it might also be useful to invoke the serial loader as a last resort instead of the current call to
hang().Patch 3 adds a config file which will allow a build of u-boot.imx with SPL as a plugin followed by u-boot.bin as the primary payload. It highlights the issue of only having a single
IMX_CONFIGvariable so it breaks the build of a stand-alone SPL. Rather, it doesn't break the build, but produces SPL that is effectively the same as u-boot.imx.This leaves only the question of what the
return_to_romcode should look like, and I'm a bit stumped. The ROM API isn't documented in any document I have.In Troy's original patch ([4]), he calls a routine that he names
HAB_RVT_LOAD_DATA. On i.MX Community ([5]), I found a reference to aplugin_download()routine and I'm not sure where that came from. The Community post suggests that it's used in EBOOT.I tried a simplistic copy of the tail end of plugin start from [6] that calls
pu_irom_hwcnfg_setup()and then returns to ROM without success. I'm not certain that this was the right approach and am hoping for some guidance.References:
[1] - http://lists.denx.de/pipermail/u-boot/2015-June/thread.html#215606
[2] - http://lists.denx.de/pipermail/u-boot/2016-September/thread.html#266303
[3] - http://lists.denx.de/pipermail/u-boot/2015-May/thread.html#215573
[4] - http://patchwork.ozlabs.org/patch/186054/
[5] - http://community.nxp.com/thread/303794
[6] - http://git.denx.de/?p=u-boot.git;a=blob;f=arch/arm/include/asm/arch-mx6/mx6_plugin.SEric Nelson (3):
ARM: mx6: preserve Boot ROM stack in SPL
ARM: mx6: ddr: add plugin-utils placeholder
ARM: imx: mx6memcal: allow build of combined SPL+U-Bootarch/arm/cpu/armv7/mx6/Makefile | 2 +- arch/arm/cpu/armv7/mx6/ddr.c | 4 ++++ arch/arm/cpu/armv7/mx6/plugin-utils.S | 24 ++++++++++++++++++++++++ arch/arm/imx-common/spl-plus-u-boot.cfg | 4 ++++ arch/arm/include/asm/arch-mx6/mx6-ddr.h | 19 +++++++++++++++++++ configs/mx6memcal_defconfig | 2 +- include/configs/imx6_spl.h | 2 +- 7 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 arch/arm/cpu/armv7/mx6/plugin-utils.S create mode 100644 arch/arm/imx-common/spl-plus-u-boot.cfgQuoted 3 lines
--
2.7.4
Quoted 6 lines
Hi Eric,
I'm interested loading U-Boot from the OTG serial downloader and this looks like a good approach. Thanks for continuing to plug away at this!
NP. It seems like the easy route if we can figure out the details of the ROM API calls.
I was hoping to get some feedback from Peng or Troy, but it seems that they're also overloaded.
Quoted 4 lines
If I understand correctly the approach here is to use the plugin support such that the boot ROM will execute the SPL as a plugin which then returns and jumps to U-boot?
That's the idea. Both SB_LOADER and imx_usb support this, so the key is figuring out how to return to the Boot ROM.
Quoted 10 lines
I've applied your mx6memcal series to master and support for one of the Gateworks boards I'm working with and can boot that SPL (23KB) fine (so I've got the UART and configured correctly at least). When I adapt that to use spl-plus-u-boot.cfg on top of this patch series the resulting SPL (85KB) image doens't appear to boot (nothing over the serial console) but I'm thinking I'm doing something wrong as
imx_usb_loaderseems like its not loading it fully or loading it too quickly. Do I need patches toimx_usb_loaderor am I doing something obvious wrong here?
I need to re-visit this. My recollection is that the SPL portion should load and run, but the return-to-ROM portion will fail.
My next thought is to use JTAG to trace things through the return to BOOT ROM and use an image from the Freescale fork as a working example.
Quoted 4 lines
Incidentally, did anyone ever proof out the other discussed method where an SPL is built with zmodem and allows loading u-boot.img over that?
Yeah.
Stefano had that working, though I had some issues getting microcom working. I had to stop and restart microcom and initiate the upload.
Regards,
Eric
cover ARM: imx: mx6: Add plugin support for SPL
Quoted 127 lines · Eric Nelson
Hi Tim,
Quoted 92 lines · Tim Harvey
Quoted 87 lines · Eric Nelson
I forgot to mention in the cover letter for the previous patch set that because the mx6memcal board has no implementation of storage (it only supports a serial console and DDR), I haven't tested the resulting U-Boot, which has very little besides "mtest" included.
I'm hoping to use this code base (mx6memcal) as a straw man for loading both SPL (as a plugin) and U-Boot through the serial download path as we've previously discussed in at least [1], [2] and [3].
Now that Peng's patch to imximage has been applied, we can start to look at the implementation details, and I hope this patch set can help move us toward an implementation.
The gist of what's needed to allow SPL to be loaded as a plugin and avoid the need for removable storage or a full (non-SPL) U-Boot is shown in patch 2.
That is, we need something akin to setjmp/longjmp to:
1. to save the early state of the machine before SPL configures the DDR controller, and
2. a routine that we can call to return to the boot ROMTo address #1, there's a clear precedent in the support for a
save_boot_params()routine and patch 2 adds one that simply saves the working register set. Examining the registers used by the ROM code shows that r0-r9 plus sp and lr are sufficient.Experimentally, I've found that the boot ROM stack is initialized to
0x91ffb4and that the stack pointer is at0x91febc(248 bytes) on all of the machines I've tested against (MX6Q, MX6DL, MX6S and MX6SL), so we can save the stack just by moving the SPL stack (patch #1).We'll also need to determine where the decision to return to the boot ROM occurs (i.e. when we call routine #2).
The obvious place for use during development is right after DDR initialization if loaded through the serial downloader, but it might also be useful to invoke the serial loader as a last resort instead of the current call to
hang().Patch 3 adds a config file which will allow a build of u-boot.imx with SPL as a plugin followed by u-boot.bin as the primary payload. It highlights the issue of only having a single
IMX_CONFIGvariable so it breaks the build of a stand-alone SPL. Rather, it doesn't break the build, but produces SPL that is effectively the same as u-boot.imx.This leaves only the question of what the
return_to_romcode should look like, and I'm a bit stumped. The ROM API isn't documented in any document I have.In Troy's original patch ([4]), he calls a routine that he names
HAB_RVT_LOAD_DATA. On i.MX Community ([5]), I found a reference to aplugin_download()routine and I'm not sure where that came from. The Community post suggests that it's used in EBOOT.I tried a simplistic copy of the tail end of plugin start from [6] that calls
pu_irom_hwcnfg_setup()and then returns to ROM without success. I'm not certain that this was the right approach and am hoping for some guidance.References:
[1] - http://lists.denx.de/pipermail/u-boot/2015-June/thread.html#215606
[2] - http://lists.denx.de/pipermail/u-boot/2016-September/thread.html#266303
[3] - http://lists.denx.de/pipermail/u-boot/2015-May/thread.html#215573
[4] - http://patchwork.ozlabs.org/patch/186054/
[5] - http://community.nxp.com/thread/303794
[6] - http://git.denx.de/?p=u-boot.git;a=blob;f=arch/arm/include/asm/arch-mx6/mx6_plugin.SEric Nelson (3):
ARM: mx6: preserve Boot ROM stack in SPL
ARM: mx6: ddr: add plugin-utils placeholder
ARM: imx: mx6memcal: allow build of combined SPL+U-Bootarch/arm/cpu/armv7/mx6/Makefile | 2 +- arch/arm/cpu/armv7/mx6/ddr.c | 4 ++++ arch/arm/cpu/armv7/mx6/plugin-utils.S | 24 ++++++++++++++++++++++++ arch/arm/imx-common/spl-plus-u-boot.cfg | 4 ++++ arch/arm/include/asm/arch-mx6/mx6-ddr.h | 19 +++++++++++++++++++ configs/mx6memcal_defconfig | 2 +- include/configs/imx6_spl.h | 2 +- 7 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 arch/arm/cpu/armv7/mx6/plugin-utils.S create mode 100644 arch/arm/imx-common/spl-plus-u-boot.cfgQuoted 3 lines
--
2.7.4Quoted 6 lines
Hi Eric,
I'm interested loading U-Boot from the OTG serial downloader and this looks like a good approach. Thanks for continuing to plug away at this!
NP. It seems like the easy route if we can figure out the details of the ROM API calls.
I was hoping to get some feedback from Peng or Troy, but it seems that they're also overloaded.
Quoted 4 lines
If I understand correctly the approach here is to use the plugin support such that the boot ROM will execute the SPL as a plugin which then returns and jumps to U-boot?
That's the idea. Both
SB_LOADERandimx_usbsupport this, so the key is figuring out how to return to the Boot ROM.Quoted 10 lines
I've applied your mx6memcal series to master and support for one of the Gateworks boards I'm working with and can boot that SPL (23KB) fine (so I've got the UART and configured correctly at least). When I adapt that to use spl-plus-u-boot.cfg on top of this patch series the resulting SPL (85KB) image doens't appear to boot (nothing over the serial console) but I'm thinking I'm doing something wrong as
imx_usb_loaderseems like its not loading it fully or loading it too quickly. Do I need patches toimx_usb_loaderor am I doing something obvious wrong here?
Quoted 2 lines
I need to re-visit this. My recollection is that the SPL portion should load and run, but the return-to-ROM portion will fail.
ok - I thought you had it fully working, but it does sound like you at least got further than I'm getting (you saw the SPL boot at least) so let me know what you find when you re-visit it.
Quoted 9 lines
My next thought is to use JTAG to trace things through the return to BOOT ROM and use an image from the Freescale fork as a working example.
Quoted 4 lines
Incidentally, did anyone ever proof out the other discussed method where an SPL is built with zmodem and allows loading u-boot.img over that?
Quoted 5 lines
Yeah.
Stefano had that working, though I had some issues getting microcom working. I had to stop and restart microcom and initiate the upload.
Stefano,
Did you document the 'IMX6 SPL to U-Boot over serial' setup anywhere, or can you talk me through what you did?
Thanks,
Tim
Fabio Estevam
reviewercover ARM: imx: mx6: Add plugin support for SPL
Hi Tim,
Quoted 2 lines · Tim Harvey
Did you document the 'IMX6 SPL to U-Boot over serial' setup anywhere, or can you talk me through what you did?
It is available at doc/README.imx6 (2. Using imx_usb_loader for first install with SPL).
cover ARM: imx: mx6: Add plugin support for SPL
Quoted 9 lines · Fabio Estevam
Hi Tim,
Quoted 2 lines · Tim Harvey
Did you document the 'IMX6 SPL to U-Boot over serial' setup anywhere, or can you talk me through what you did?
It is available at doc/README.imx6 (2. Using
imx_usb_loaderfor first install with SPL).
Fabio,
Thanks for pointing me in the right direction. I did manage to get IMX6 SPL Ymodem working although I had to hack the return value of spl_boot_device(). In my current situation with a board that has no BOOT MODE pin strapping, and no fuses blown imx_usb_loader spl_boot_device() returns BOOT_DEVICE_NOR which is wrong.
The SRC_SBMR register reflects the BOOT MODE pins of the chip (strapping) but the reference manual defines SRC_GPR9 and SRC_GPR10[28] as reserved and I don't recall the reasoning for using these for the boot mode. Can you provide some documentation that we can put in the code? I'm thinking there is something else missing from this function that should be able to determine that the serial downloader was used in my case and return BOOT_DEVICE_UART appropriately.
Regards,
Tim
Fabio Estevam
reviewercover ARM: imx: mx6: Add plugin support for SPL
Hi Tim,
Quoted 8 lines · Tim Harvey
The
SRC_SBMRregister reflects the BOOT MODE pins of the chip (strapping) but the reference manual definesSRC_GPR9and SRC_GPR10[28] as reserved and I don't recall the reasoning for using these for the boot mode. Can you provide some documentation that we can put in the code? I'm thinking there is something else missing from this function that should be able to determine that the serial downloader was used in my case and returnBOOT_DEVICE_UARTappropriately.
I could also not found any documentation about SRC_GPR9 and SRC_GPR10[28].
I also find it confusing that we use such undocumented registers in U-Boot for determining the boot mode.
cover ARM: imx: mx6: Add plugin support for SPL
Quoted 11 lines · Fabio Estevam
Quoted 8 lines · Tim Harvey
The
SRC_SBMRregister reflects the BOOT MODE pins of the chip (strapping) but the reference manual definesSRC_GPR9and SRC_GPR10[28] as reserved and I don't recall the reasoning for using these for the boot mode. Can you provide some documentation that we can put in the code? I'm thinking there is something else missing from this function that should be able to determine that the serial downloader was used in my case and returnBOOT_DEVICE_UARTappropriately.I could also not found any documentation about
SRC_GPR9and SRC_GPR10[28].
I think the BootROM is the ultimate resource here. Did you look internally for its source?
Signature · 3 lines
Otavio Salvador O.S. Systems http://www.ossystems.com.br http://code.ossystems.com.br Mobile: +55 (53) 9981-7854 Mobile: +1 (347) 903-9750