Hi Fabio, Eric, first of all, many thanks for this patch ! A full FOSS tool to replace the proprietary ddr-stress is what we are missing from the beginning of i.MX6.
Applied to u-boot-imx, thanks ! Best regards, Stefano On 11/12/2017 16:52, Fabio Estevam wrote: > From: Eric Nelson <e...@nelint.com> > > 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. > > Signed-off-by: Eric Nelson <e...@nelint.com> > Signed-off-by: Fabio Estevam <fabio.este...@nxp.com> > --- > This is an attempt to bring Eric's useful patch to life: > https://lists.denx.de/pipermail/u-boot/2016-November/271597.html > > Changes since RFC: > - Rebased against latest U-Boot > - Removed get_imx_type() as it does not build with SPL (to be added lates). > - Include patch 2/9 into this one: > https://lists.denx.de/pipermail/u-boot/2016-November/271596.html > ,otherwise mmdc_do_dqs_calibration() always fail on my tests with mx6qsabresd > - Fixed some Coding Style issues to make checkpatch happier > > arch/arm/mach-imx/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 | 456 > ++++++++++++++++++++++++++++++++++ > configs/mx6memcal_defconfig | 33 +++ > include/configs/mx6memcal.h | 59 +++++ > scripts/config_whitelist.txt | 1 + > 10 files changed, 894 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 > > diff --git a/arch/arm/mach-imx/mx6/Kconfig b/arch/arm/mach-imx/mx6/Kconfig > index bee7eab..89bf1ae 100644 > --- a/arch/arm/mach-imx/mx6/Kconfig > +++ b/arch/arm/mach-imx/mx6/Kconfig > @@ -202,6 +202,14 @@ config TARGET_MX6LOGICPD > select DM_REGULATOR > select OF_CONTROL > > +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" > > @@ -441,6 +449,7 @@ source "board/embest/mx6boards/Kconfig" > source "board/engicam/imx6q/Kconfig" > source "board/engicam/imx6ul/Kconfig" > source "board/freescale/mx6qarm2/Kconfig" > +source "board/freescale/mx6memcal/Kconfig" > source "board/freescale/mx6sabreauto/Kconfig" > source "board/freescale/mx6sabresd/Kconfig" > source "board/freescale/mx6slevk/Kconfig" > diff --git a/board/freescale/mx6memcal/Kconfig > b/board/freescale/mx6memcal/Kconfig > new file mode 100644 > index 0000000..443804d > --- /dev/null > +++ b/board/freescale/mx6memcal/Kconfig > @@ -0,0 +1,235 @@ > +if TARGET_MX6MEMCAL > + > +config SYS_BOARD > + default "mx6memcal" > + > +config SYS_VENDOR > + default "freescale" > + > +config SYS_CONFIG_NAME > + default "mx6memcal" > + > +menu "mx6memcal specifics" > +choice > + prompt "Serial console" > + help > + Either UART1 or UART2 will be used as the console for > + displaying the calibration values or errors. > + > +config SERIAL_CONSOLE_UART1 > + bool "UART1" > + help > + Select this if your board uses UART1 for its' console. > + > +config SERIAL_CONSOLE_UART2 > + bool "UART2" > + help > + Select this if your board uses UART2 for its' console. > + > +endchoice > + > +choice > + prompt "UART pads" > + help > + Select the RX and TX pads used for your serial console. > + The choices below reflect the most commonly used options > + for your UART. > + > + config UART2_EIM_D26_27 > + bool "UART2 on EIM_D26/27 (SabreLite, Nitrogen6x)" > + depends on SERIAL_CONSOLE_UART2 > + help > + Choose this configuration if you're using pads > + EIM_D26 and D27 for a console on UART2. > + This is typical for designs that are based on the > + NXP SABRELite. > + > + config UART1_CSI0_DAT10_11 > + bool "UART1 on CSI0_DAT10/11 (Wand)" > + depends on SERIAL_CONSOLE_UART1 > + help > + Choose this configuration if you're using pads > + CSI0_DAT10 and DAT11 for a console on UART1 as > + is done on the i.MX6 Wand board. > + > + config UART1_SD3_DAT6_7 > + bool "UART1 on SD3_DAT6/7 (SabreSD, SabreAuto)" > + depends on SERIAL_CONSOLE_UART1 > + help > + Choose this configuration if you're using pads > + SD3_DAT6 and DAT7 for a console on UART1 as is > + done on the NXP SABRESD or SABREAUTO designs. > + > + config UART1_UART1 > + bool "UART1 on UART1 (i.MX6SL EVK, WaRP)" > + depends on SERIAL_CONSOLE_UART1 > + help > + Choose this configuration if you're using pads > + UART1_TXD/RXD for a console on UART1 as is done > + on most i.MX6SL designs. > + > +endchoice > + > +config IMXIMAGE_OUTPUT > + bool "Include output for imximage .cfg files" > + default y > + help > + Say "Y" if you want output formatted for use in non-SPL > + (DCD-style) configuration files. > + > +config DDRWIDTH > + int "DDR bus width" > + default 64 > + help > + Select either 32 or 64 to reflect the DDR bus width. > + > +config DDRCS > + int "DDR chip selects" > + default 2 > + range 1 2 > + help > + Select the number of chip selects used in your board design > + > +choice > + prompt "Memory type" > + help > + Select the type of DDR (DDR3 or LPDDR2) used on your design > + > +config DDR3 > + bool "DDR3" > + help > + Select this if your board design uses DDR3. > + > +config LPDDR2 > + bool "LPDDR2" > + help > + Select this if your board design uses LPDDR2. > + > +endchoice > + > +choice > + prompt "Memory device" > + > +config MT41K512M16TNA > + bool "Micron MT41K512M16TNA 512Mx16 (1GiB/chip)" > + depends on DDR3 > + > +config MT41K128M16JT > + bool "Micron MT41K128M16JT 128Mx16 (256 MiB/chip)" > + depends on DDR3 > + > +config H5TQ4G63AFR > + bool "Hynix H5TQ4G63AFR 256Mx16 (512 MiB/chip)" > + depends on DDR3 > + > +config H5TQ2G63DFR > + bool "Hynix H5TQ2G63DFR 128Mx16 (256 MiB/chip)" > + depends on DDR3 > + > +config MT42L256M32D2LG > + bool "Micron MT42L256M32D2LG LPDDR2 256Mx32 (1GiB/chip)" > + depends on LPDDR2 > + > +config MT29PZZZ4D4BKESK > + bool "Micron MT29PZZZ4D4BKESK multi-chip 512MiB LPDDR2/4GiB eMMC" > + depends on LPDDR2 > + > +endchoice > + > +config DDR_ODT > + int "DDR On-die-termination" > + default 2 > + range 0 7 > + help > + Enter the on-die termination value as an index defined for > + IOMUX settings for PAD_DRAM_SDCLK0_P and others. > + 0 == Disabled > + 1 == 120 Ohm > + 2 == 60 Ohm > + 3 == 40 Ohm > + 4 == 30 Ohm > + 5 == 24 Ohm > + 6 == 20 Ohm > + 7 == 17 Ohm > + Value will be applied to all clock and data lines > + > + > +config DRAM_DRIVE_STRENGTH > + int "DRAM Drive strength" > + default 6 > + range 0 7 > + help > + Enter drive strength as an index defined for IOMUX settings > + for GRP_B1DS and others. > + 0 == Hi Z > + 6 == 40 Ohm (default) > + 7 == 34 Ohm > + Value will be applied to all clock and data lines > + > +config RTT_NOM > + int "RTT_NOM" > + default 1 > + range 1 2 > + help > + Enter the RTT_NOM selector > + 1 == RZQ/4 (60ohm) > + 2 == RZQ/2 (120ohm) > + > +config RTT_WR > + int "RTT_WR" > + default 1 > + range 0 2 > + help > + Enter the RTT_WR selector for MR2 > + 0 == Dynamic ODT disabled > + 1 == RZQ/4 (60ohm) > + 2 == RZQ/2 (120ohm) > + > +config RALAT > + int "Read additional latency" > + default 5 > + range 0 7 > + help > + Enter a latency in number of cycles. This will be added to > + CAS and internal delays for which the MMDC will retrieve the > + read data from the internal FIFO. > + This is used to compensate for board/chip delays. > + > +config WALAT > + int "Write additional latency" > + default 0 > + range 0 7 > + help > + Enter a latency in number of cycles. This will be added to > + CAS and internal delays for which the MMDC will retrieve the > + read data from the internal FIFO > + This is used to compensate for board/chip delays. > + > +config REFSEL > + int "Refresh period" > + range 0 3 > + default 1 > + help > + Select the DDR refresh period. > + See the description of bitfield REF_SEL in the reference manual > + for details. > + 0 == disabled > + 1 == 32 kHz > + 2 == 64 kHz > + 3 == fast counter > + > +config REFR > + int "Number of refreshes" > + range 0 7 > + default 7 > + help > + This selects the number of refreshes (-1) during each period. > + i.e.: > + 0 == 1 refresh (tRFC) > + 7 == 8 refreshes (tRFC*8) > + See the description of MDREF[REFR] in the reference manual for > + details. > + > +endmenu > +endif > + > diff --git a/board/freescale/mx6memcal/MAINTAINERS > b/board/freescale/mx6memcal/MAINTAINERS > new file mode 100644 > index 0000000..5da38f7 > --- /dev/null > +++ b/board/freescale/mx6memcal/MAINTAINERS > @@ -0,0 +1,7 @@ > +MX6MEMCAL BOARD > +M: Eric Nelson <e...@nelint.com> > +S: Maintained > +F: board/freescale/mx6memcal/ > +F: include/configs/mx6memcal.h > +F: configs/mx6memcal_defconfig > + > diff --git a/board/freescale/mx6memcal/Makefile > b/board/freescale/mx6memcal/Makefile > new file mode 100644 > index 0000000..2d7a6fa > --- /dev/null > +++ b/board/freescale/mx6memcal/Makefile > @@ -0,0 +1,13 @@ > +# > +# Copyright (C) 2007, Guennadi Liakhovetski <l...@denx.de> > +# > +# (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 > diff --git a/board/freescale/mx6memcal/README > b/board/freescale/mx6memcal/README > new file mode 100644 > index 0000000..9fe2fe2 > --- /dev/null > +++ b/board/freescale/mx6memcal/README > @@ -0,0 +1,49 @@ > +mx6memcal - a tool for calibrating DDR on i.MX6 boards. > + > +The mx6memcal board isn't a real board, but a tool for use in bring-up of > +new i.MX6 board designs. > + > +It provides a similar function to the tool from NXP([1]) with a number > +of advantages: > + > +1. It's open-source, so it's easier to change if needed. > + Typical reasons for needing to change include the use of alternate > + UARTs and PMIC initialization. > +2. It produces an image that's directly loadable with imx_usb [2] or > + SB_LOADER.exe [3]. > + The NXP tool requires either a cumbersome JTAG connection that > + makes running the DDR very slow or a working U-Boot image that > + suffers from a chicken-and-egg problem (i.e. where do you get the > + DDR parameters for U-Boot?). > +3. It doesn't prompt for parameters, so it's much faster to gather > + data from multiple boards. > +4. Parameters to the calibration process can be chosen through > + 'make menuconfig'. > + > +When booted, the mx6memcal board will run the DDR calibration > +routines and display the result in a form suitable for cut and > +paste into struct mx6_mmdc_calibration. It can also optionally > +produce output in a form usable in a DCD-style .cfg file. > + > +Selections in Kconfig allow most system design settings to be chosen: > + > +1. The UART number and pad configuration for the UART. Options > + include support for the most frequent reference designs on > + i.MX6DQ/SDL (SABRE Lite and SABRESD designs). > +2. The memory bus width (64 and 32-bit) > +3. The number of chip-selects in use > +4. The type of DDR (DDR3 or LPDDR2). Note that LPDDR2 support > + is incomplete as of this writing. > +5. The type of DDR chips in use. This selection allows re-use of common > + parts and four DDR3 and two LPDDR2 parts are currently defined > +6. The On-die termination value for the DRAM lines > +7. The DRAM drive strength > +8. The RTT_NOM and RTT_WR termination settings > +9. RALAT/WALAT latency values > + > +References: > +[1] - NXP DDR Stress Test Tool - https://community.nxp.com/docs/DOC-105652 > +[2] - Boundary Devices imx_usb_loader > + https://github.com/boundarydevices/imx_usb_loader > +[3] - Use of SB_Loader.exe > + https://boundarydevices.com/windows-users-and-unbricking > diff --git a/board/freescale/mx6memcal/mx6memcal.c > b/board/freescale/mx6memcal/mx6memcal.c > new file mode 100644 > index 0000000..afea0fb > --- /dev/null > +++ b/board/freescale/mx6memcal/mx6memcal.c > @@ -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 <e...@nelint.com> > + * > + * 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; > +} > + > diff --git a/board/freescale/mx6memcal/spl.c b/board/freescale/mx6memcal/spl.c > new file mode 100644 > index 0000000..9c19e9c > --- /dev/null > +++ b/board/freescale/mx6memcal/spl.c > @@ -0,0 +1,456 @@ > +/* > + * Copyright (C) 2016 Nelson Integration, LLC > + * Author: Eric Nelson <e...@nelint.com> > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <common.h> > +#include <asm/io.h> > +#include <asm/arch/iomux.h> > +#include <asm/arch/clock.h> > +#include <asm/arch/crm_regs.h> > +#include <asm/arch/mx6-ddr.h> > +#include <asm/arch/mx6-pins.h> > +#include <asm/arch/sys_proto.h> > +#include <spl.h> > + > +DECLARE_GLOBAL_DATA_PTR; > + > +#define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ > + PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ > + PAD_CTL_SRE_FAST | PAD_CTL_HYS) > + > +static iomux_v3_cfg_t const uart_pads[] = { > +#ifdef CONFIG_UART2_EIM_D26_27 > + IOMUX_PADS(PAD_EIM_D26__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), > + IOMUX_PADS(PAD_EIM_D27__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), > +#elif defined(CONFIG_UART1_CSI0_DAT10_11) > + IOMUX_PADS(PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), > + IOMUX_PADS(PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), > +#elif defined(CONFIG_UART1_SD3_DAT6_7) > + IOMUX_PADS(PAD_SD3_DAT6__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), > + IOMUX_PADS(PAD_SD3_DAT7__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), > +#elif defined(CONFIG_UART1_UART1) > + MX6_PAD_UART1_TXD__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL), > + MX6_PAD_UART1_RXD__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL), > +#else > +#error select UART console pads > +#endif > +}; > + > +#ifdef CONFIG_DDR3 > +#define GRP_DDRTYPE 0x000C0000 > +#else > +#define GRP_DDRTYPE 0x00080000 > +#endif > + > +/* all existing designs have this disabled */ > +#define DDR_PKE 0 > + > +/* use Kconfig for ODT and DRIVE_STRENGTH */ > +#define DDR_ODT \ > + (CONFIG_DDR_ODT << 8) > +#define DRAM_DRIVE_STRENGTH \ > + (CONFIG_DRAM_DRIVE_STRENGTH << 3) > + > +/* configure MX6Q/DUAL mmdc DDR io registers */ > +static struct mx6dq_iomux_ddr_regs const mx6dq_ddr_ioregs = { > + /* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */ > + .dram_sdclk_0 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_sdclk_1 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_cas = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_ras = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_reset = DDR_ODT + DRAM_DRIVE_STRENGTH, > + /* SDCKE[0:1]: 100k pull-up */ > + .dram_sdcke0 = 0x00003000, > + .dram_sdcke1 = 0x00003000, > + /* SDBA2: pull-up disabled */ > + .dram_sdba2 = 0x00000000, > + /* SDODT[0:1]: 100k pull-up, 40 ohm */ > + .dram_sdodt0 = 0x00003000 + DRAM_DRIVE_STRENGTH, > + .dram_sdodt1 = 0x00003000 + DRAM_DRIVE_STRENGTH, > + /* SDQS[0:7]: Differential input, 40 ohm */ > + .dram_sdqs0 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs1 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs2 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs3 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs4 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs5 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs6 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs7 = DRAM_DRIVE_STRENGTH, > + > + /* DQM[0:7]: Differential input, 40 ohm */ > + .dram_dqm0 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm1 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm2 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm3 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm4 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm5 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm6 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm7 = DDR_ODT + DRAM_DRIVE_STRENGTH, > +}; > + > +/* configure MX6Q/DUAL mmdc GRP io registers */ > +static struct mx6dq_iomux_grp_regs const mx6dq_grp_ioregs = { > + /* DDR3 */ > + .grp_ddr_type = GRP_DDRTYPE, > + .grp_ddrmode_ctl = DDR_ODT, > + /* disable DDR pullups */ > + .grp_ddrpke = DDR_PKE, > + /* ADDR[00:16], SDBA[0:1]: 40 ohm */ > + .grp_addds = DRAM_DRIVE_STRENGTH, > + /* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */ > + .grp_ctlds = DRAM_DRIVE_STRENGTH, > + /* DATA[00:63]: Differential input, 40 ohm */ > + .grp_ddrmode = DDR_ODT, > + .grp_b0ds = DRAM_DRIVE_STRENGTH, > + .grp_b1ds = DRAM_DRIVE_STRENGTH, > + .grp_b2ds = DRAM_DRIVE_STRENGTH, > + .grp_b3ds = DRAM_DRIVE_STRENGTH, > + .grp_b4ds = DRAM_DRIVE_STRENGTH, > + .grp_b5ds = DRAM_DRIVE_STRENGTH, > + .grp_b6ds = DRAM_DRIVE_STRENGTH, > + .grp_b7ds = DRAM_DRIVE_STRENGTH, > +}; > + > +static struct mx6sdl_iomux_ddr_regs const mx6sdl_ddr_ioregs = { > + /* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */ > + .dram_sdclk_0 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_sdclk_1 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_cas = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_ras = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_reset = DDR_ODT + DRAM_DRIVE_STRENGTH, > + /* SDCKE[0:1]: 100k pull-up */ > + .dram_sdcke0 = 0x00003000, > + .dram_sdcke1 = 0x00003000, > + /* SDBA2: pull-up disabled */ > + .dram_sdba2 = 0x00000000, > + /* SDODT[0:1]: 100k pull-up, 40 ohm */ > + .dram_sdodt0 = 0x00003000 + DRAM_DRIVE_STRENGTH, > + .dram_sdodt1 = 0x00003000 + DRAM_DRIVE_STRENGTH, > + /* SDQS[0:7]: Differential input, 40 ohm */ > + .dram_sdqs0 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs1 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs2 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs3 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs4 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs5 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs6 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs7 = DRAM_DRIVE_STRENGTH, > + > + /* DQM[0:7]: Differential input, 40 ohm */ > + .dram_dqm0 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm1 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm2 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm3 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm4 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm5 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm6 = DDR_ODT + DRAM_DRIVE_STRENGTH, > + .dram_dqm7 = DDR_ODT + DRAM_DRIVE_STRENGTH, > +}; > + > +/* configure MX6SOLO/DUALLITE mmdc GRP io registers */ > +static struct mx6sdl_iomux_grp_regs const mx6sdl_grp_ioregs = { > + /* DDR3 */ > + .grp_ddr_type = GRP_DDRTYPE, > + /* SDQS[0:7]: Differential input, 40 ohm */ > + .grp_ddrmode_ctl = DDR_ODT, > + /* disable DDR pullups */ > + .grp_ddrpke = DDR_PKE, > + /* ADDR[00:16], SDBA[0:1]: 40 ohm */ > + .grp_addds = DRAM_DRIVE_STRENGTH, > + /* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */ > + .grp_ctlds = DRAM_DRIVE_STRENGTH, > + /* DATA[00:63]: Differential input, 40 ohm */ > + .grp_ddrmode = DDR_ODT, > + .grp_b0ds = DRAM_DRIVE_STRENGTH, > + .grp_b1ds = DRAM_DRIVE_STRENGTH, > + .grp_b2ds = DRAM_DRIVE_STRENGTH, > + .grp_b3ds = DRAM_DRIVE_STRENGTH, > + .grp_b4ds = DRAM_DRIVE_STRENGTH, > + .grp_b5ds = DRAM_DRIVE_STRENGTH, > + .grp_b6ds = DRAM_DRIVE_STRENGTH, > + .grp_b7ds = DRAM_DRIVE_STRENGTH, > +}; > + > +const struct mx6sl_iomux_ddr_regs mx6sl_ddr_ioregs = { > + .dram_sdqs0 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs1 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs2 = DRAM_DRIVE_STRENGTH, > + .dram_sdqs3 = DRAM_DRIVE_STRENGTH, > + .dram_dqm0 = DRAM_DRIVE_STRENGTH, > + .dram_dqm1 = DRAM_DRIVE_STRENGTH, > + .dram_dqm2 = DRAM_DRIVE_STRENGTH, > + .dram_dqm3 = DRAM_DRIVE_STRENGTH, > + .dram_cas = DRAM_DRIVE_STRENGTH, > + .dram_ras = DRAM_DRIVE_STRENGTH, > + .dram_sdclk_0 = DRAM_DRIVE_STRENGTH, > + .dram_reset = DRAM_DRIVE_STRENGTH, > + .dram_sdba2 = 0x00020000, > + .dram_odt0 = 0x00030000 + DRAM_DRIVE_STRENGTH, > + .dram_odt1 = 0x00030000 + DRAM_DRIVE_STRENGTH, > +}; > + > +const struct mx6sl_iomux_grp_regs mx6sl_grp_ioregs = { > + .grp_b0ds = DRAM_DRIVE_STRENGTH, > + .grp_b1ds = DRAM_DRIVE_STRENGTH, > + .grp_b2ds = DRAM_DRIVE_STRENGTH, > + .grp_b3ds = DRAM_DRIVE_STRENGTH, > + .grp_addds = DRAM_DRIVE_STRENGTH, > + .grp_ctlds = DRAM_DRIVE_STRENGTH, > + .grp_ddrmode_ctl = DDR_ODT, > + .grp_ddrpke = DDR_PKE, > + .grp_ddrmode = DDR_ODT, > + .grp_ddr_type = GRP_DDRTYPE, > +}; > + > +static struct mx6_ddr_sysinfo const sysinfo = { > + /* width of data bus:0=16,1=32,2=64 */ > +#if CONFIG_DDRWIDTH == 32 > + .dsize = 1, > +#elif CONFIG_DDRWIDTH == 64 > + .dsize = 2, > +#else > +#error missing CONFIG_DDRWIDTH > +#endif > + /* config for full 4GB range so that get_mem_size() works */ > + .cs_density = 32, /* 32Gb per CS */ > + > + /* # of chip selects */ > + .ncs = CONFIG_DDRCS, > + .cs1_mirror = 0, > + .bi_on = 1, /* Bank interleaving enabled */ > + .rtt_nom = CONFIG_RTT_NOM, > + .rtt_wr = CONFIG_RTT_WR, > + .ralat = CONFIG_RALAT, /* Read additional latency */ > + .walat = CONFIG_WALAT, /* Write additional latency */ > + .mif3_mode = 3, /* Command prediction working mode */ > +#ifdef CONFIG_DDR3 > + .rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */ > + .sde_to_rst = 0x10, /* JEDEC value for LPDDR2 - 200us */ > + .pd_fast_exit = 0, /* immaterial for calibration */ > + .ddr_type = DDR_TYPE_DDR3, > +#else > + .rst_to_cke = 0x10, /* JEDEC value for LPDDR2: 200us */ > + .sde_to_rst = 0, /* LPDDR2 does not need this field */ > + .pd_fast_exit = 0, /* immaterial for calibration */ > + .ddr_type = DDR_TYPE_LPDDR2, > +#endif > + .refsel = CONFIG_REFSEL, > + .refr = CONFIG_REFR, > +}; > + > +#ifdef CONFIG_MT41K512M16TNA > +/* Micron MT41K512M16TNA-125 */ > +static struct mx6_ddr3_cfg const ddrtype = { > + .mem_speed = 1600, > + .density = 8, > + .width = 16, > + .banks = 8, > + .rowaddr = 15, > + .coladdr = 10, > + .pagesz = 1, > + .trcd = 1375, > + .trcmin = 5062, > + .trasmin = 3750, > +}; > +#elif defined(CONFIG_MT41K128M16JT) > +/* Micron MT41K128M16JT-125 */ > +static struct mx6_ddr3_cfg const ddrtype = { > + .mem_speed = 1600, > + .density = 2, > + .width = 16, > + .banks = 8, > + .rowaddr = 14, > + .coladdr = 10, > + .pagesz = 2, > + .trcd = 1375, > + .trcmin = 4875, > + .trasmin = 3500, > +}; > +#elif defined(CONFIG_H5TQ4G63AFR) > +/* Hynix H5TQ4G63AFR */ > +static struct mx6_ddr3_cfg const ddrtype = { > + .mem_speed = 1600, > + .density = 4, > + .width = 16, > + .banks = 8, > + .rowaddr = 15, > + .coladdr = 10, > + .pagesz = 2, > + .trcd = 1375, > + .trcmin = 4875, > + .trasmin = 3500, > +}; > +#elif defined CONFIG_H5TQ2G63DFR > +/* Hynix H5TQ2G63DFR */ > +static struct mx6_ddr3_cfg const ddrtype = { > + .mem_speed = 1333, > + .density = 2, > + .width = 16, > + .banks = 8, > + .rowaddr = 14, > + .coladdr = 10, > + .pagesz = 2, > + .trcd = 1350, > + .trcmin = 4950, > + .trasmin = 3600, > +}; > +#elif defined(CONFIG_MT42L256M32D2LG) > +/* Micron MT42L256M32D2LG */ > +static struct mx6_lpddr2_cfg ddrtype = { > + .mem_speed = 800, > + .density = 4, > + .width = 32, > + .banks = 8, > + .rowaddr = 14, > + .coladdr = 10, > + .trcd_lp = 2000, > + .trppb_lp = 2000, > + .trpab_lp = 2250, > + .trasmin = 4200, > +}; > +#elif defined(CONFIG_MT29PZZZ4D4BKESK) > +/* Micron MT29PZZZ4D4BKESK */ > +static struct mx6_lpddr2_cfg ddrtype = { > + .mem_speed = 800, > + .density = 4, > + .width = 32, > + .banks = 8, > + .rowaddr = 14, > + .coladdr = 10, > + .trcd_lp = 2000, > + .trppb_lp = 2000, > + .trpab_lp = 2250, > + .trasmin = 4200, > +}; > +#else > +#error please select DDR type using menuconfig > +#endif > + > +static void ccgr_init(void) > +{ > + struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; > + > + /* FIXME: these should probably be checked, especially > + * for i.MX6SL, UL, ULL > + */ > + writel(0x00C03F3F, &ccm->CCGR0); > + writel(0x0030FC03, &ccm->CCGR1); > + writel(0x0FFFC000, &ccm->CCGR2); > + writel(0x3FF00000, &ccm->CCGR3); > + writel(0x00FFF300, &ccm->CCGR4); > + writel(0x0F0000C3, &ccm->CCGR5); > + writel(0x000003FF, &ccm->CCGR6); > +} > + > +static void display_calibration(struct mx6_mmdc_calibration *calib) > +{ > + printf(".p0_mpdgctrl0\t= 0x%08X\n", calib->p0_mpdgctrl0); > + printf(".p0_mpdgctrl1\t= 0x%08X\n", calib->p0_mpdgctrl1); > + printf(".p0_mprddlctl\t= 0x%08X\n", calib->p0_mprddlctl); > + printf(".p0_mpwrdlctl\t= 0x%08X\n", calib->p0_mpwrdlctl); > + printf(".p0_mpwldectrl0\t= 0x%08X\n", calib->p0_mpwldectrl0); > + printf(".p0_mpwldectrl1\t= 0x%08X\n", calib->p0_mpwldectrl1); > + if (sysinfo.dsize == 2) { > + printf(".p1_mpdgctrl0\t= 0x%08X\n", calib->p1_mpdgctrl0); > + printf(".p1_mpdgctrl1\t= 0x%08X\n", calib->p1_mpdgctrl1); > + printf(".p1_mprddlctl\t= 0x%08X\n", calib->p1_mprddlctl); > + printf(".p1_mpwrdlctl\t= 0x%08X\n", calib->p1_mpwrdlctl); > + printf(".p1_mpwldectrl0\t= 0x%08X\n", calib->p1_mpwldectrl0); > + printf(".p1_mpwldectrl1\t= 0x%08X\n", calib->p1_mpwldectrl1); > + } > +#ifdef CONFIG_IMXIMAGE_OUTPUT > + printf("DATA 4 MX6_MMDC_P0_MPDGCTRL0\t= 0x%08X\n", calib->p0_mpdgctrl0); > + printf("DATA 4 MX6_MMDC_P0_MPDGCTRL1\t= 0x%08X\n", calib->p0_mpdgctrl1); > + printf("DATA 4 MX6_MMDC_P0_MPRDDLCTL\t= 0x%08X\n", calib->p0_mprddlctl); > + printf("DATA 4 MX6_MMDC_P0_MPWRDLCTL\t= 0x%08X\n", calib->p0_mpwrdlctl); > + printf("DATA 4 MX6_MMDC_P0_MPWLDECTRL0\t= 0x%08X\n", > + calib->p0_mpwldectrl0); > + printf("DATA 4 MX6_MMDC_P0_MPWLDECTRL1\t= 0x%08X\n", > + calib->p0_mpwldectrl1); > + if (sysinfo.dsize == 2) { > + printf("DATA 4 MX6_MMDC_P1_MPDGCTRL0\t= 0x%08X\n", > + calib->p1_mpdgctrl0); > + printf("DATA 4 MX6_MMDC_P1_MPDGCTRL1\t= 0x%08X\n", > + calib->p1_mpdgctrl1); > + printf("DATA 4 MX6_MMDC_P1_MPRDDLCTL\t= 0x%08X\n", > + calib->p1_mprddlctl); > + printf("DATA 4 MX6_MMDC_P1_MPWRDLCTL\t= 0x%08X\n", > + calib->p1_mpwrdlctl); > + printf("DATA 4 MX6_MMDC_P1_MPWLDECTRL0\t= 0x%08X\n", > + calib->p1_mpwldectrl0); > + printf("DATA 4 MX6_MMDC_P1_MPWLDECTRL1\t= 0x%08X\n", > + calib->p1_mpwldectrl1); > + } > +#endif > +} > + > +/* > + * called from C runtime startup code (arch/arm/lib/crt0.S:_main) > + * - we have a stack and a place to store GD, both in SRAM > + * - no variable global data is available > + */ > +void board_init_f(ulong dummy) > +{ > + int errs; > + struct mx6_mmdc_calibration calibration = {0}; > + > + 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(); > + > + ccgr_init(); > + > + SETUP_IOMUX_PADS(uart_pads); > + > + /* setup GP timer */ > + timer_init(); > + > + /* UART clocks enabled and gd valid - init serial console */ > + preloader_console_init(); > + > + if (sysinfo.dsize != 1) { > + if (is_cpu_type(MXC_CPU_MX6SX) || > + is_cpu_type(MXC_CPU_MX6UL) || > + is_cpu_type(MXC_CPU_MX6SL)) { > + printf("cpu type 0x%x doesn't support 64-bit bus\n", > + get_cpu_type()); > + reset_cpu(0); > + } > + } > +#ifdef CONFIG_MX6SL > + mx6sl_dram_iocfg(CONFIG_DDRWIDTH, &mx6sl_ddr_ioregs, > + &mx6sl_grp_ioregs); > +#else > + if (is_cpu_type(MXC_CPU_MX6Q)) { > + mx6dq_dram_iocfg(CONFIG_DDRWIDTH, &mx6dq_ddr_ioregs, > + &mx6dq_grp_ioregs); > + } else { > + mx6sdl_dram_iocfg(CONFIG_DDRWIDTH, &mx6sdl_ddr_ioregs, > + &mx6sdl_grp_ioregs); > + } > +#endif > + mx6_dram_cfg(&sysinfo, &calibration, &ddrtype); > + > + errs = mmdc_do_write_level_calibration(&sysinfo); > + if (errs) { > + printf("error %d from write level calibration\n", errs); > + } else { > + errs = mmdc_do_dqs_calibration(&sysinfo); > + if (errs) { > + printf("error %d from write level calibration\n", errs); > + } else { > + printf("completed successfully\n"); > + mmdc_read_calibration(&sysinfo, &calibration); > + display_calibration(&calibration); > + } > + } > + reset_cpu(0); > +} > diff --git a/configs/mx6memcal_defconfig b/configs/mx6memcal_defconfig > new file mode 100644 > index 0000000..9a3bb83 > --- /dev/null > +++ b/configs/mx6memcal_defconfig > @@ -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_SPL_SERIAL_SUPPORT=y > +CONFIG_SPL_WATCHDOG_SUPPORT=y > +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/spl_sd.cfg,SPL,MX6QDL" > +CONFIG_SPL=y > +CONFIG_HUSH_PARSER=y > +# CONFIG_MMC is not set > +# 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 > diff --git a/include/configs/mx6memcal.h b/include/configs/mx6memcal.h > new file mode 100644 > index 0000000..f5238a5 > --- /dev/null > +++ b/include/configs/mx6memcal.h > @@ -0,0 +1,59 @@ > +/* > + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. > + * > + * Configuration settings for the Boundary Devices Nitrogen6X > + * and Freescale i.MX6Q Sabre Lite boards. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifndef __CONFIG_H > +#define __CONFIG_H > + > +/* SPL */ > + > +#include "mx6_common.h" > +#include "imx6_spl.h" > + > +#undef CONFIG_FSL_ESDHC > +#undef CONFIG_MMC > +#undef CONFIG_SPL_MMC_SUPPORT > +#undef CONFIG_GENERIC_MMC > +#undef CONFIG_CMD_FUSE > + > +#define CONFIG_SYS_MEMTEST_START 0x10000000 > +#define CONFIG_SYS_MEMTEST_END 0x20000000 > +#define CONFIG_SYS_MALLOC_LEN (64 * 1024 * 1024) > + > +#define CONFIG_MXC_UART > +#ifdef CONFIG_SERIAL_CONSOLE_UART1 > +#if defined(CONFIG_MX6SL) > +#define CONFIG_MXC_UART_BASE UART1_IPS_BASE_ADDR > +#else > +#define CONFIG_MXC_UART_BASE UART1_BASE > +#endif > +#elif defined(CONFIG_SERIAL_CONSOLE_UART2) > +#define CONFIG_MXC_UART_BASE UART2_BASE > +#else > +#error please define serial console (CONFIG_SERIAL_CONSOLE_UARTx) > +#endif > +#define CONFIG_BAUDRATE 115200 > + > +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + 16) > + > +/* Physical Memory Map */ > +#define CONFIG_NR_DRAM_BANKS 1 > +#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR > + > +#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM > +#define CONFIG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR > +#define CONFIG_SYS_INIT_RAM_SIZE IRAM_SIZE > + > +#define CONFIG_SYS_INIT_SP_OFFSET \ > + (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE) > +#define CONFIG_SYS_INIT_SP_ADDR \ > + (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET) > + > +#define CONFIG_ENV_SIZE (8 * 1024) > + > +#endif /* __CONFIG_H */ > diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt > index d5ae1f4..3732f5e 100644 > --- a/scripts/config_whitelist.txt > +++ b/scripts/config_whitelist.txt > @@ -372,6 +372,7 @@ CONFIG_DB_784MP_GP > CONFIG_DCACHE > CONFIG_DCACHE_OFF > CONFIG_DCFG_ADDR > +CONFIG_DDR3 > CONFIG_DDR_ > CONFIG_DDR_2HCLK > CONFIG_DDR_2T_TIMING > -- ===================================================================== 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: sba...@denx.de ===================================================================== _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot