[U-Boot] [PATCH] mx6: Add board mx6memcal for use in validating DDR

From: Eric Nelson eric@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 eric@nelint.com Signed-off-by: Fabio Estevam fabio.estevam@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 eric@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 lg@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 eric@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 eric@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

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 eric@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 eric@nelint.com Signed-off-by: Fabio Estevam fabio.estevam@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 eric@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 lg@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 eric@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 eric@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
participants (2)
-
Fabio Estevam
-
Stefano Babic