Commit 60454847 authored by Ye Li's avatar Ye Li

MLK-18639-3 imx8mm_val: Add board codes for iMX8MM DDR4 validation board

Add SPL/u-boot board codes and DDR4 settings for iMX8MM DDR4 validation board.
DDR overnight stress test is passed.

Supported modules:
    SD/eMMC, I2C, ENET, Flexspi, UART and USB.

Build config:
    imx8mm_ddr4_val_defconfig
Signed-off-by: default avatarYe Li <ye.li@nxp.com>
parent abe2268c
......@@ -36,6 +36,11 @@ config TARGET_IMX8MQ_DDR4_ARM2
select IMX8MQ
select SUPPORT_SPL
config TARGET_IMX8MM_DDR4_VAL
bool "imx8mm validation board"
select IMX8MM
select SUPPORT_SPL
config TARGET_IMX8MM_EVK
bool "imx8mm evk"
select IMX8MM
......@@ -50,5 +55,6 @@ source "board/freescale/imx8mq_phanbell/Kconfig"
source "board/freescale/imx8mq_evk/Kconfig"
source "board/freescale/imx8mq_arm2/Kconfig"
source "board/freescale/imx8mm_evk/Kconfig"
source "board/freescale/imx8mm_val/Kconfig"
endif
if TARGET_IMX8MM_DDR4_VAL
config SYS_BOARD
default "imx8mm_val"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "imx8mm_val"
source "board/freescale/common/Kconfig"
endif
#
# Copyright 2018 NXP
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += imx8mm_val.o
ifdef CONFIG_SPL_BUILD
obj-y += spl.o
obj-y += ddr/
endif
#
# Copyright 2018 NXP
#
# SPDX-License-Identifier: GPL-2.0+
#
ifdef CONFIG_SPL_BUILD
obj-y += helper.o
obj-y += wait_ddrphy_training_complete.o
obj-$(CONFIG_TARGET_IMX8MM_DDR4_VAL) += ddr4/
endif
/*
* Copyright 2018 NXP
*
* SPDX-License-Identifier: GPL-2.0+
* Common file for ddr code
*/
#ifndef __M845S_DDR_H_
#define __M845S_DDR_H_
#ifdef DDR_DEBUG
#define ddr_dbg(fmt, ...) printf("DDR: debug:" fmt "\n", ##__VA_ARGS__)
#else
#define ddr_dbg(fmt, ...)
#endif
/*******************************************************************
Desc: user data type
*******************************************************************/
enum fw_type {
FW_1D_IMAGE,
FW_2D_IMAGE,
};
/*******************************************************************
Desc: prototype
*******************************************************************/
void ddr_init(void);
void ddr_load_train_code(enum fw_type type);
void wait_ddrphy_training_complete(void);
void dwc_ddrphy_phyinit_userCustom_E_setDfiClk(unsigned int pstate);
void dwc_ddrphy_phyinit_userCustom_J_enterMissionMode(void);
void dwc_ddrphy_phyinit_userCustom_customPostTrain(void);
void dwc_ddrphy_phyinit_userCustom_B_startClockResetPhy(void);
void dwc_ddrphy_phyinit_userCustom_A_bringupPower(void);
void dwc_ddrphy_phyinit_userCustom_overrideUserInput(void);
void dwc_ddrphy_phyinit_userCustom_H_readMsgBlock(unsigned int run_2D);
void dwc_ddrphy_phyinit_userCustom_G_waitFwDone(void);
/*******************************************************************
Desc: definition
*******************************************************************/
static inline void reg32_write(unsigned long addr, u32 val)
{
writel(val, addr);
}
static inline uint32_t reg32_read(unsigned long addr)
{
return readl(addr);
}
static inline void reg32setbit(unsigned long addr, u32 bit)
{
setbits_le32(addr, (1 << bit));
}
#endif
#
# Copyright 2018 NXP
#
# SPDX-License-Identifier: GPL-2.0+
#
ifdef CONFIG_SPL_BUILD
obj-y += ddr4_phyinit_task.o
obj-y += ddr4_phyinit_2400_400_100_2r_fw09.o
obj-y += ddr4_swffc_fw09.o
obj-y += save_1d2d_trained_csr_ddr4_p012.o
obj-y += restore_1d2d_trained_csr_ddr4_p012.o
endif
/*
* Copyright 2018 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef ANAMIX_COMMON_TMP_H
#define ANAMIX_COMMON_TMP_H
/*ANAMIX Address Definition*/
#define ANAMIX_PLL_BASE_ADDR 0x30360000
#define ANAMIX_OSC_BASE_ADDR 0x30270000
#define ANAMIX_TSN_BASE_ADDR 0x30260000
/* PLL TOP REG */
#define AUDIO_PLL1_GNRL_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x00)
#define AUDIO_PLL1_FDIV_CTL0_ADDR (ANAMIX_PLL_BASE_ADDR + 0x04)
#define AUDIO_PLL1_FDIV_CTL1_ADDR (ANAMIX_PLL_BASE_ADDR + 0x08)
#define AUDIO_PLL1_SSCG_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x0c)
#define AUDIO_PLL1_MINT_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x10)
#define AUDIO_PLL2_GNRL_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x14)
#define AUDIO_PLL2_FDIV_CTL0_ADDR (ANAMIX_PLL_BASE_ADDR + 0x18)
#define AUDIO_PLL2_FDIV_CTL1_ADDR (ANAMIX_PLL_BASE_ADDR + 0x1c)
#define AUDIO_PLL2_SSCG_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x20)
#define AUDIO_PLL2_MINT_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x24)
#define VIDEO_PLL1_GNRL_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x28)
#define VIDEO_PLL1_FDIV_CTL0_ADDR (ANAMIX_PLL_BASE_ADDR + 0x2c)
#define VIDEO_PLL1_FDIV_CTL1_ADDR (ANAMIX_PLL_BASE_ADDR + 0x30)
#define VIDEO_PLL1_SSCG_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x34)
#define VIDEO_PLL1_MINT_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x38)
#define VIDEO_PLL2_GNRL_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x3c)
#define VIDEO_PLL2_FDIV_CTL0_ADDR (ANAMIX_PLL_BASE_ADDR + 0x40)
#define VIDEO_PLL2_FDIV_CTL1_ADDR (ANAMIX_PLL_BASE_ADDR + 0x44)
#define VIDEO_PLL2_SSCG_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x48)
#define VIDEO_PLL2_MINT_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x4c)
#define DRAM_PLL_GNRL_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x50)
#define DRAM_PLL_FDIV_CTL0_ADDR (ANAMIX_PLL_BASE_ADDR + 0x54)
#define DRAM_PLL_FDIV_CTL1_ADDR (ANAMIX_PLL_BASE_ADDR + 0x58)
#define DRAM_PLL_SSCG_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x5c)
#define DRAM_PLL_MINT_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x60)
#define GPU_PLL_GNRL_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x64)
#define GPU_PLL_DIV_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x68)
#define GPU_PLL_LOCKD_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x6c)
#define GPU_PLL_MINT_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x70)
#define VPU_PLL_GNRL_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x74)
#define VPU_PLL_DIV_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x78)
#define VPU_PLL_LOCKD_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x7c)
#define VPU_PLL_MINT_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x80)
#define ARM_PLL_GNRL_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x84)
#define ARM_PLL_DIV_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x88)
#define ARM_PLL_LOCKD_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x8c)
#define ARM_PLL_MINT_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x90)
#define SYS_PLL1_GNRL_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x94)
#define SYS_PLL1_DIV_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x98)
#define SYS_PLL1_LOCKD_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x9c)
#define SYS_PLL1_MINT_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x100)
#define SYS_PLL2_GNRL_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x104)
#define SYS_PLL2_DIV_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x108)
#define SYS_PLL2_LOCKD_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x10c)
#define SYS_PLL2_MINT_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x110)
#define SYS_PLL3_GNRL_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x114)
#define SYS_PLL3_DIV_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x118)
#define SYS_PLL3_LOCKD_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x11c)
#define SYS_PLL3_MINT_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x120)
#define ANAMIX_MISC_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x124)
#define ANAMIX_CLK_MINT_CTL_ADDR (ANAMIX_PLL_BASE_ADDR + 0x128)
/* TMP SNSR REG */
#define TER_ADDR (ANAMIX_TSN_BASE_ADDR + 0x00)
#define TSR_ADDR (ANAMIX_TSN_BASE_ADDR + 0x04)
#define TIER_ADDR (ANAMIX_TSN_BASE_ADDR + 0x08)
#define TIDR_ADDR (ANAMIX_TSN_BASE_ADDR + 0x0c)
#define TMHTITR_ADDR (ANAMIX_TSN_BASE_ADDR + 0x10)
#define TMHTATR_ADDR (ANAMIX_TSN_BASE_ADDR + 0x14)
#define TMHTACTR_ADDR (ANAMIX_TSN_BASE_ADDR + 0x18)
#define TSCR_ADDR (ANAMIX_TSN_BASE_ADDR + 0x1c)
#define TRITSR_ADDR (ANAMIX_TSN_BASE_ADDR + 0x20)
#define TRATSR_ADDR (ANAMIX_TSN_BASE_ADDR + 0x24)
#define TASR_ADDR (ANAMIX_TSN_BASE_ADDR + 0x28)
#define TTMC_ADDR (ANAMIX_TSN_BASE_ADDR + 0x2c)
/* OSC */
#define SYS_OSCNML_CTL0_ADDR (ANAMIX_OSC_BASE_ADDR + 0x00)
#define SYS_OSCNML_CTL1_ADDR (ANAMIX_OSC_BASE_ADDR + 0x04)
#define HDMI_OSCNML_CTL0_ADDR (ANAMIX_OSC_BASE_ADDR + 0x8000)
#define HDMI_OSCNML_CTL1_ADDR (ANAMIX_OSC_BASE_ADDR + 0x8004)
#endif
/*
* Copyright 2018 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __DDR4_CONFIG_H__
#define __DDR4_CONFIG_H__
#include "../ddr.h"
#define RUN_ON_SILICON
#define DDR4_SW_FFC
#define ENABLE_RETENTION
#define DRAM_VREF 0x1f
#define SAVE_DDRPHY_TRAIN_ADDR 0x184000
/* choose p2 state data rate, define just one of below macro */
#define PLLBYPASS_400MBPS
/* //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */
/* for DDR4 */
/* Note:DQ SI RON=40ohm, RTT=48ohm */
/* CA SI RON=40ohm, RTT=65ohm */
/* //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */
/* for DDR RTT NOM/PARK */
#define DDR4_ODT_DIS 0
#define DDR4_ODT_60 1
#define DDR4_ODT_120 2
#define DDR4_ODT_40 3
#define DDR4_ODT_240 4
#define DDR4_ODT_48 5
#define DDR4_ODT_80 6
#define DDR4_ODT_34 7
/* for DDR RON */
#define DDR4_RON_34 0
#define DDR4_RON_48 1
#define DDR4_RON_40 2
#define DDR4_RON_RES 3
/* for DDR RTT write */
#define DDR4_RTT_WR_DIS 0
#define DDR4_RTT_WR_120 1
#define DDR4_RTT_WR_240 2
#define DDR4_RTT_WR_HZ 3
#define DDR4_RTT_WR_80 4
/* for DDR4 PHY data RON */
#define DDR4_PHY_DATA_RON_34 0xeba
#define DDR4_PHY_DATA_RON_40 0xe38
#define DDR4_PHY_DATA_RON_48 ((0x1a << 6) | 0x1a)
#define DDR4_PHY_DATA_RON_60 ((0x18 << 6) | 0x18)
#define DDR4_PHY_DATA_RON_80 ((0x0a << 6) | 0x0a)
#define DDR4_PHY_DATA_RON_120 ((0x08 << 6) | 0x08)
#define DDR4_PHY_DATA_RON_240 ((0x02<<6)|0x02)
/* for DDR4 PHY data RTT */
#define DDR4_PHY_DATA_RTT_34 0x3a
#define DDR4_PHY_DATA_RTT_40 0x38
#define DDR4_PHY_DATA_RTT_48 0x1a
#define DDR4_PHY_DATA_RTT_60 0x18
#define DDR4_PHY_DATA_RTT_80 0x0a
#define DDR4_PHY_DATA_RTT_120 0x08
#define DDR4_PHY_DATA_RTT_240 0x02
/* for DDR4 PHY address RON */
#define DDR4_PHY_ADDR_RON_30 ((0x07 << 5) | 0x07)
#define DDR4_PHY_ADDR_RON_40 0x63
#define DDR4_PHY_ADDR_RON_60 ((0x01 << 5) | 0x01)
#define DDR4_PHY_ADDR_RON_120 ((0x00 << 5) | 0x00)
#define DDR4_PHY_ADDR_RON DDR4_PHY_ADDR_RON_40
/* read DDR4 */
#ifdef DDR_ONE_RANK
#define DDR4_RON DDR4_RON_34
#define DDR4_PHY_DATA_RTT DDR4_PHY_DATA_RTT_48
#define DDR4_PHYREF_VALUE 91
#else
#define DDR4_RON DDR4_RON_40
#define DDR4_PHY_DATA_RTT DDR4_PHY_DATA_RTT_48
#define DDR4_PHYREF_VALUE 93
#endif
/* write DDR4 */
#ifdef DDR_ONE_RANK
/* one lank */
#define DDR4_PHY_DATA_RON DDR4_PHY_DATA_RON_34
#define DDR4_RTT_NOM DDR4_ODT_60
#define DDR4_RTT_WR DDR4_RTT_WR_DIS
#define DDR4_RTT_PARK DDR4_ODT_DIS
#define DDR4_MR6_VALUE 0x0d
#else
/* two lank */
#define DDR4_PHY_DATA_RON DDR4_PHY_DATA_RON_40
#define DDR4_RTT_NOM DDR4_ODT_60
#define DDR4_RTT_WR DDR4_RTT_WR_DIS
#define DDR4_RTT_PARK DDR4_ODT_DIS
#define DDR4_MR6_VALUE 0x10
#endif
/* voltage:delay */
#define DDR4_2D_WEIGHT (31 << 8 | 127)
#define ANAMIX_PLL_BASE_ADDR 0x30360000
#define HW_DRAM_PLL_CFG0_ADDR (ANAMIX_PLL_BASE_ADDR + 0x60)
#define HW_DRAM_PLL_CFG1_ADDR (ANAMIX_PLL_BASE_ADDR + 0x64)
#define HW_DRAM_PLL_CFG2_ADDR (ANAMIX_PLL_BASE_ADDR + 0x68)
#define GPC_PU_PWRHSK 0x303A01FC
#define GPC_TOP_CONFIG_OFFSET 0x0000
#define AIPS1_ARB_BASE_ADDR 0x30000000
#define AIPS_TZ1_BASE_ADDR AIPS1_ARB_BASE_ADDR
#define AIPS1_OFF_BASE_ADDR (AIPS_TZ1_BASE_ADDR + 0x200000)
#define CCM_IPS_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x180000)
#define CCM_SRC_CTRL_OFFSET (CCM_IPS_BASE_ADDR + 0x800)
#define CCM_SRC_CTRL(n) (CCM_SRC_CTRL_OFFSET + 0x10 * n)
#define dwc_ddrphy_apb_wr(addr, data) reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * (addr), data)
#define dwc_ddrphy_apb_rd(addr) (reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * (addr)))
#define reg32clrbit(addr, bitpos) reg32_write((addr), (reg32_read((addr)) & (0xFFFFFFFF ^ (1 << (bitpos)))))
#define DDR_CSD1_BASE_ADDR 0x40000000
#define DDR_CSD2_BASE_ADDR 0x80000000
void restore_1d2d_trained_csr_ddr4_p012(unsigned int addr);
void save_1d2d_trained_csr_ddr4_p012(unsigned int addr);
void ddr4_mr_write(unsigned int mr, unsigned int data, unsigned int read, unsigned int rank);
void ddr4_phyinit_train_sw_ffc(unsigned int Train2D);
#endif
/*
* Copyright 2018 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/arch/ddr_memory_map.h>
#include <asm/arch/clock.h>
#include "ddr4_define.h"
extern unsigned int mr_value[3][7];
void dwc_ddrphy_phyinit_userCustom_E_setDfiClk (unsigned int pstate) {
if (pstate == 1) {
ddr_dbg("C: pstate1 ...\n");
#ifdef PLLBYPASS_250MBPS
dram_enable_bypass(DRAM_BYPASSCLK_250M);
#endif
#ifdef PLLBYPASS_400MBPS
dram_enable_bypass(DRAM_BYPASSCLK_400M);
#endif
} else if (pstate == 2) {
ddr_dbg("C: pstate2 ...\n");
dram_enable_bypass(DRAM_BYPASSCLK_100M);
} else {
ddr_dbg("C: pstate0 ...\n");
dram_pll_init(DRAM_PLL_OUT_600M);
dram_disable_bypass();
}
}
void dwc_ddrphy_phyinit_userCustom_G_waitFwDone(void)
{
wait_ddrphy_training_complete();
}
void dwc_ddrphy_phyinit_userCustom_overrideUserInput (void) {}
void dwc_ddrphy_phyinit_userCustom_A_bringupPower (void) {}
void dwc_ddrphy_phyinit_userCustom_B_startClockResetPhy (void) {}
void dwc_ddrphy_phyinit_userCustom_H_readMsgBlock(unsigned int Train2D) {}
void dwc_ddrphy_phyinit_userCustom_customPostTrain(void) {}
void dwc_ddrphy_phyinit_userCustom_J_enterMissionMode(void) {}
void ddr4_mr_write(unsigned int mr, unsigned int data, unsigned int read, unsigned int rank)
{
unsigned int tmp, mr_mirror, data_mirror;
/* 1. Poll MRSTAT.mr_wr_busy until it is 0. This checks that there is no outstanding MR transaction. No */
/* writes should be performed to MRCTRL0 and MRCTRL1 if MRSTAT.mr_wr_busy = 1. */
do {
tmp = reg32_read(DDRC_MRSTAT(0));
} while (tmp & 0x1);
/* 2. Write the MRCTRL0.mr_type, MRCTRL0.mr_addr, MRCTRL0.mr_rank and (for MRWs) */
/* MRCTRL1.mr_data to define the MR transaction. */
/* (A3, A4), (A5, A6), (A7, A8), (BA0, BA1), (A11, A13), */
tmp = reg32_read(DDRC_DIMMCTL(0));
if ((tmp & 0x2) && (rank == 0x2)) {
mr_mirror = (mr & 0x4) | ((mr & 0x1) << 1) | ((mr & 0x2) >> 1);/* BA0, BA1 swap */
data_mirror = (data & 0x1607) | ((data & 0x8) << 1) | ((data & 0x10) >> 1) | ((data & 0x20) << 1) |
((data & 0x40) >> 1) | ((data & 0x80) << 1) | ((data & 0x100) >> 1) | ((data & 0x800) << 2) | ((data & 0x2000) >> 2) ;
} else {
mr_mirror = mr;
data_mirror = data;
}
reg32_write(DDRC_MRCTRL0(0), read | (mr_mirror << 12) | (rank << 4));
reg32_write(DDRC_MRCTRL1(0), data_mirror);
/* 3. In a separate APB transaction, write the MRCTRL0.mr_wr to 1. This bit is self-clearing, and triggers */
/* the MR transaction. The uMCTL2 then asserts the MRSTAT.mr_wr_busy while it performs the MR */
/* transaction to SDRAM, and no further accesses can be initiated until it is deasserted. */
reg32setbit(DDRC_MRCTRL0(0), 31);
do {
tmp = reg32_read(DDRC_MRSTAT(0));
} while (tmp);
}
This diff is collapsed.
/*
* Copyright 2018 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <spl.h>
#include <asm/io.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/arch/ddr_memory_map.h>
#include <asm/sections.h>
#include "ddr.h"
DECLARE_GLOBAL_DATA_PTR;
#define IMEM_LEN 32768
#define DMEM_LEN 16384
#define IMEM_2D_OFFSET 49152
#define IMEM_OFFSET_ADDR 0x00050000
#define DMEM_OFFSET_ADDR 0x00054000
#define DDR_TRAIN_CODE_BASE_ADDR IP2APB_DDRPHY_IPS_BASE_ADDR(0)
/* We need PHY iMEM PHY is 32KB padded */
void ddr_load_train_code(enum fw_type type)
{
u32 tmp32, i;
u32 error = 0;
unsigned long pr_to32, pr_from32;
unsigned long fw_offset = type ? IMEM_2D_OFFSET : 0;
unsigned long imem_start = (unsigned long)&_end + fw_offset;
unsigned long dmem_start = imem_start + IMEM_LEN;
pr_from32 = imem_start;
pr_to32 = DDR_TRAIN_CODE_BASE_ADDR + 4 * IMEM_OFFSET_ADDR;
for (i = 0x0; i < IMEM_LEN; ) {
tmp32 = readl(pr_from32);
writew(tmp32 & 0x0000ffff, pr_to32);
pr_to32 += 4;
writew((tmp32 >> 16) & 0x0000ffff, pr_to32);
pr_to32 += 4;
pr_from32 += 4;
i += 4;
}
pr_from32 = dmem_start;
pr_to32 = DDR_TRAIN_CODE_BASE_ADDR + 4 * DMEM_OFFSET_ADDR;
for (i = 0x0; i < DMEM_LEN;) {
tmp32 = readl(pr_from32);
writew(tmp32 & 0x0000ffff, pr_to32);
pr_to32 += 4;
writew((tmp32 >> 16) & 0x0000ffff, pr_to32);
pr_to32 += 4;
pr_from32 += 4;
i += 4;
}
printf("check ddr4_pmu_train_imem code\n");
pr_from32 = imem_start;
pr_to32 = DDR_TRAIN_CODE_BASE_ADDR + 4 * IMEM_OFFSET_ADDR;
for (i = 0x0; i < IMEM_LEN;) {
tmp32 = (readw(pr_to32) & 0x0000ffff);
pr_to32 += 4;
tmp32 += ((readw(pr_to32) & 0x0000ffff) << 16);
if (tmp32 != readl(pr_from32)) {
printf("%lx %lx\n", pr_from32, pr_to32);
error++;
}
pr_from32 += 4;
pr_to32 += 4;
i += 4;
}
if (error)
printf("check ddr4_pmu_train_imem code fail=%d\n", error);
else
printf("check ddr4_pmu_train_imem code pass\n");
printf("check ddr4_pmu_train_dmem code\n");
pr_from32 = dmem_start;
pr_to32 = DDR_TRAIN_CODE_BASE_ADDR + 4 * DMEM_OFFSET_ADDR;
for (i = 0x0; i < DMEM_LEN;) {
tmp32 = (readw(pr_to32) & 0x0000ffff);
pr_to32 += 4;
tmp32 += ((readw(pr_to32) & 0x0000ffff) << 16);
if (tmp32 != readl(pr_from32)) {
printf("%lx %lx\n", pr_from32, pr_to32);
error++;
}
pr_from32 += 4;
pr_to32 += 4;
i += 4;
}
if (error)
printf("check ddr4_pmu_train_dmem code fail=%d", error);
else
printf("check ddr4_pmu_train_dmem code pass\n");
}
/*
* Copyright 2017 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/arch/ddr_memory_map.h>
#include <asm/arch/clock.h>
#include "ddr.h"
static inline void poll_pmu_message_ready(void)
{
unsigned int reg;
do {
reg = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0004);
} while (reg & 0x1);
}
static inline void ack_pmu_message_recieve(void)
{
unsigned int reg;
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0031, 0x0);
do {
reg = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0004);
} while (!(reg & 0x1));
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0031, 0x1);
}
static inline unsigned int get_mail(void)
{
unsigned int reg;
poll_pmu_message_ready();
reg = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0032);
ack_pmu_message_recieve();
return reg;
}
static inline unsigned int get_stream_message(void)
{
unsigned int reg, reg2;
poll_pmu_message_ready();
reg = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0032);
reg2 = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0034);
reg2 = (reg2 << 16) | reg;
ack_pmu_message_recieve();
return reg2;
}
static inline void decode_major_message(unsigned int mail)
{
ddr_dbg("[PMU Major message = 0x%08x]\n", mail);
}
static inline void decode_streaming_message(void)
{
unsigned int string_index, arg __maybe_unused;
int i = 0;
string_index = get_stream_message();
ddr_dbg(" PMU String index = 0x%08x\n", string_index);
while (i < (string_index & 0xffff)) {
arg = get_stream_message();
ddr_dbg(" arg[%d] = 0x%08x\n", i, arg);
i++;
}
ddr_dbg("\n");
}
void wait_ddrphy_training_complete(void)
{
unsigned int mail;
while (1) {
mail = get_mail();
decode_major_message(mail);
if (mail == 0x08) {
decode_streaming_message();
} else if (mail == 0x07) {
printf("Training PASS\n");
break;
} else if (mail == 0xff) {
printf("Training FAILED\n");
break;
}
}
}
This diff is collapsed.
/*
* Copyright 2018 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <spl.h>
#include <asm/io.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/imx-common/iomux-v3.h>
#include <asm/arch/imx8mm_pins.h>
#include <asm/arch/sys_proto.h>
#include <power/pmic.h>
#include <power/bd71837.h>
#include <asm/arch/clock.h>
#include <asm/imx-common/gpio.h>
#include <asm/imx-common/mxc_i2c.h>
#include <fsl_esdhc.h>
#include <mmc.h>
#include "ddr/ddr.h"
DECLARE_GLOBAL_DATA_PTR;
void spl_dram_init(void)
{
/* ddr train */
ddr_init();
}
#define I2C_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE)
#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
struct i2c_pads_info i2c_pad_info1 = {
.scl = {
.i2c_mode = IMX8MM_PAD_I2C1_SCL_I2C1_SCL | PC,
.gpio_mode = IMX8MM_PAD_I2C1_SCL_GPIO5_IO14 | PC,
.gp = IMX_GPIO_NR(5, 14),
},
.sda = {
.i2c_mode = IMX8MM_PAD_I2C1_SDA_I2C1_SDA | PC,
.gpio_mode = IMX8MM_PAD_I2C1_SDA_GPIO5_IO15 | PC,
.gp = IMX_GPIO_NR(5, 15),
},
};
#define USDHC2_CD_GPIO IMX_GPIO_NR(2, 18)
#define USDHC2_PWR_GPIO IMX_GPIO_NR(2, 19)
#define USDHC_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE | PAD_CTL_PE | \
PAD_CTL_FSEL2)
#define USDHC_GPIO_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_DSE1)
static iomux_v3_cfg_t const usdhc3_pads[] = {
IMX8MM_PAD_NAND_WE_B_USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_NAND_WP_B_USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_NAND_DATA04_USDHC3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_NAND_DATA05_USDHC3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_NAND_DATA06_USDHC3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_NAND_DATA07_USDHC3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_NAND_RE_B_USDHC3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_NAND_CE2_B_USDHC3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_NAND_CE3_B_USDHC3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_NAND_CLE_USDHC3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
};
static iomux_v3_cfg_t const usdhc2_pads[] = {
IMX8MM_PAD_SD2_CLK_USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_SD2_CMD_USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_SD2_DATA0_USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_SD2_DATA1_USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_SD2_DATA2_USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_SD2_DATA3_USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MM_PAD_SD2_RESET_B_GPIO2_IO19 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL),</