Commit 31d29dd1 authored by Ye Li's avatar Ye Li

MLK-17109-4 imx8mq_arm2: Add i.MX8MQ DDR3L and DDR4 ARM2 boards support

Add board codes, configurations, DTS and DDR initialization codes for the
DDR3L and DDR4 ARM2 boards.

Supported modules
    - DDR3L ARM2: Two RANK DDR3L, QSPI B, eMMC/SD, RMII ENET, UART.
    - DDR4  ARM2: Two RANK DDR4, SD, NAND, RGMII ENET, UART.
      NAND read/write/erase is ok in u-boot, NAND SPL boot will be tested later
      when tool is ready.
Signed-off-by: default avatarYe Li <ye.li@nxp.com>
Acked-by: default avatarPeng Fan <peng.fan@nxp.com>
parent 6cb839ca
......@@ -12,11 +12,22 @@ config TARGET_IMX8MQ_EVK
select IMX8M
select SUPPORT_SPL
config TARGET_IMX8MQ_DDR3L_ARM2
bool "imx8mq_ddr3l_arm2"
select IMX8M
select SUPPORT_SPL
config TARGET_IMX8MQ_DDR4_ARM2
bool "imx8mq_ddr4_arm2"
select IMX8M
select SUPPORT_SPL
endchoice
config SYS_SOC
default "imx8m"
source "board/freescale/imx8mq_evk/Kconfig"
source "board/freescale/imx8mq_arm2/Kconfig"
endif
......@@ -625,6 +625,14 @@ int clock_init()
clock_set_target_val(QSPI_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(7));
clock_enable(CCGR_QSPI, 1);
/*
* set rawnand root
* sys pll1 400M
*/
clock_enable(CCGR_RAWNAND, 0);
clock_set_target_val(NAND_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(3) | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV4)); /* 100M */
clock_enable(CCGR_RAWNAND, 1);
if (!is_usb_boot()) {
clock_enable(CCGR_USB_CTRL1, 0);
clock_enable(CCGR_USB_CTRL2, 0);
......
......@@ -386,7 +386,9 @@ dtb-$(CONFIG_ARCH_MX7ULP) += imx7ulp-evk.dtb \
imx7ulp-10x10-arm2.dtb \
imx7ulp-14x14-arm2.dtb
dtb-$(CONFIG_ARCH_IMX8M) += fsl-imx8mq-evk.dtb
dtb-$(CONFIG_ARCH_IMX8M) += fsl-imx8mq-evk.dtb \
fsl-imx8mq-ddr3l-arm2.dtb \
fsl-imx8mq-ddr4-arm2.dtb
dtb-$(CONFIG_ARCH_IMX8) += fsl-imx8qm-lpddr4-arm2.dtb \
fsl-imx8qm-mek.dtb \
......
This diff is collapsed.
This diff is collapsed.
if TARGET_IMX8MQ_DDR3L_ARM2 || TARGET_IMX8MQ_DDR4_ARM2
config SYS_BOARD
default "imx8mq_arm2"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "imx8mq_arm2"
endif
#
# Copyright 2017 Freescale Semiconductor
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += imx8m_arm2.o
ifdef CONFIG_SPL_BUILD
obj-y += spl.o
obj-y += ddr/helper.o
ifdef CONFIG_TARGET_IMX8MQ_DDR3L_ARM2
obj-y += ddr/ddr3l/ddr_init.o ddr/ddr3l/ddrphy_train.o
else
obj-y += ddr/ddr4/ddr_init.o ddr/ddr4/ddrphy_train.o
endif
endif
/*
* Copyright 2017 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef SRC_DDRC_RCR_ADDR
#define SRC_DDRC_RCR_ADDR SRC_IPS_BASE_ADDR +0x1000
#endif
#ifndef DDR_CSD1_BASE_ADDR
#define DDR_CSD1_BASE_ADDR 0x40000000
#endif
enum fw_type {
FW_1D_IMAGE,
FW_2D_IMAGE,
};
void ddr_init(void);
void ddr_load_train_code(enum fw_type type);
void wait_ddrphy_training_complete(void);
void ddr3_phyinit_train_1600mts(void);
void ddr4_phyinit_train_2400mts(void);
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 void inline dwc_ddrphy_apb_wr(unsigned long addr, u32 val)
{
writel(val, addr);
}
*/
static inline void reg32setbit(unsigned long addr, u32 bit)
{
setbits_le32(addr, (1 << bit));
}
static inline void reg32clrbit(unsigned long addr, u32 bit)
{
clrbits_le32(addr, (1 << bit));
}
/*
* 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"
#ifdef CONFIG_ENABLE_DDR_TRAINING_DEBUG
#define ddr_printf(args...) printf(args)
#else
#define ddr_printf(args...)
#endif
#include "../wait_ddrphy_training_complete.c"
volatile unsigned int tmp;
void umctl2_cfg(void){
reg32_write(DDRC_DBG1(0), 0x00000001);
reg32_write(DDRC_PWRCTL(0), 0x00000001);
do{
tmp = 0x7 & (reg32_read(DDRC_STAT(0)));
} while (tmp);/* wait init state */
reg32_write(DDRC_MSTR(0), 0x83040001);/* two rank */
reg32_write(DDRC_MRCTRL0(0), 0x40004030);
reg32_write(DDRC_MRCTRL1(0), 0x0001c68e);
reg32_write(DDRC_MRCTRL2(0), 0x921b7e95);
reg32_write(DDRC_DERATEEN(0), 0x00000506);
reg32_write(DDRC_DERATEINT(0), 0x9a4fbdf1);
reg32_write(DDRC_MSTR2(0), 0x00000001);
reg32_write(DDRC_PWRCTL(0), 0x000000a8);
reg32_write(DDRC_PWRTMG(0), 0x00532203);
reg32_write(DDRC_HWLPCTL(0), 0x0b6d0000);
reg32_write(DDRC_HWFFCCTL(0), 0x00000030);
reg32_write(DDRC_RFSHCTL0(0), 0x00203020);
reg32_write(DDRC_RFSHCTL1(0), 0x0001000d);
reg32_write(DDRC_RFSHCTL3(0), 0x00000000);
reg32_write(DDRC_RFSHTMG(0), 0x0061008c);
reg32_write(DDRC_CRCPARCTL0(0), 0x00000000);
reg32_write(DDRC_CRCPARCTL1(0), 0x00000000);
reg32_write(DDRC_INIT0(0), 0xc0030002);
reg32_write(DDRC_INIT1(0), 0x0001000b);
reg32_write(DDRC_INIT2(0), 0x00006303);
reg32_write(DDRC_INIT3(0), 0x0d700044);/* MR1, MR0 */
reg32_write(DDRC_INIT4(0), 0x00180000);/* MR2 */
reg32_write(DDRC_INIT5(0), 0x00090071);
reg32_write(DDRC_INIT6(0), 0x00000000);
reg32_write(DDRC_INIT7(0), 0x00000000);
reg32_write(DDRC_DIMMCTL(0), 0x00000032);
reg32_write(DDRC_RANKCTL(0), 0x00000ee5);
reg32_write(DDRC_DRAMTMG0(0), 0x0c101a0e);
reg32_write(DDRC_DRAMTMG1(0), 0x000a0314);
reg32_write(DDRC_DRAMTMG2(0), 0x04060509);
reg32_write(DDRC_DRAMTMG3(0), 0x00002006);
reg32_write(DDRC_DRAMTMG4(0), 0x06020306);
reg32_write(DDRC_DRAMTMG5(0), 0x0b060202);
reg32_write(DDRC_DRAMTMG6(0), 0x060a0009);
reg32_write(DDRC_DRAMTMG7(0), 0x0000060b);
reg32_write(DDRC_DRAMTMG8(0), 0x01017c0a);
reg32_write(DDRC_DRAMTMG9(0), 0x4000000e);
reg32_write(DDRC_DRAMTMG10(0), 0x00070803);
reg32_write(DDRC_DRAMTMG11(0), 0x0101000b);
reg32_write(DDRC_DRAMTMG12(0), 0x00000000);
reg32_write(DDRC_DRAMTMG13(0), 0x5d000000);
reg32_write(DDRC_DRAMTMG14(0), 0x00000b39);
reg32_write(DDRC_DRAMTMG15(0), 0x80000000);
reg32_write(DDRC_DRAMTMG17(0), 0x00f1006a);
reg32_write(DDRC_ZQCTL0(0), 0x50800020);
reg32_write(DDRC_ZQCTL1(0), 0x00000070);
reg32_write(DDRC_ZQCTL2(0), 0x00000000);
reg32_write(DDRC_DFITMG0(0), 0x03868203);
reg32_write(DDRC_DFITMG1(0), 0x00020103);
reg32_write(DDRC_DFILPCFG0(0), 0x07713121);
reg32_write(DDRC_DFILPCFG1(0), 0x00000010);
reg32_write(DDRC_DFIUPD0(0), 0xe0400018);
reg32_write(DDRC_DFIUPD1(0), 0x0005003c);
reg32_write(DDRC_DFIUPD2(0), 0x00000000);
reg32_write(DDRC_DFIMISC(0), 0x00000011);
reg32_write(DDRC_DFITMG2(0), 0x00000603);
reg32_write(DDRC_DFITMG3(0), 0x00000001);
reg32_write(DDRC_DBICTL(0), 0x00000001);
reg32_write(DDRC_DFIPHYMSTR(0), 0x00000000);
reg32_write(DDRC_ADDRMAP0(0), 0x00000016); /* [4:0] cs-bit0: 6+22=28; [12:8] cs-bit1: 7+0 */
reg32_write(DDRC_ADDRMAP1(0), 0x00080808); /* [5:0] bank b0: 2+8; [13:8] b1: P3+8 ; [21:16] b2: 4+8 */
reg32_write(DDRC_ADDRMAP2(0), 0x00000000); /* [3:0] col-b2: 2; [11:8] col-b3: 3; [19:16] col-b4: 4 ; [27:24] col-b5: 5 */
reg32_write(DDRC_ADDRMAP3(0), 0x00000000); /* [3:0] col-b6: 6; [11:8] col-b7: 7; [19:16] col-b8: 8 ; [27:24] col-b9: 9 */
reg32_write(DDRC_ADDRMAP4(0), 0x00001f1f); /* col-b10, col-b11 not used */
reg32_write(DDRC_ADDRMAP5(0), 0x07070707); /* [3:0] row-b0: 6; [11:8] row-b1: 7; [19:16] row-b2_b10 ; [27:24] row-b11: 17 */
reg32_write(DDRC_ADDRMAP6(0), 0x0f070707); /* [3:0] row-b12:18; [11:8] row-b13: 19; [19:16] row-b14:20 */
reg32_write(DDRC_ADDRMAP7(0), 0x00000f0f);
reg32_write(DDRC_ADDRMAP8(0), 0x00000000); /* [5:0] bg-b0; [13:8]bg-b1 */
reg32_write(DDRC_ADDRMAP9(0), 0x0a020b06); /* it's valid only when ADDRMAP5.addrmap_row_b2_10 is set to value 15 */
reg32_write(DDRC_ADDRMAP10(0), 0x0a0a0a0a);/* it's valid only when ADDRMAP5.addrmap_row_b2_10 is set to value 15 */
reg32_write(DDRC_ADDRMAP11(0), 0x00000000);
reg32_write(DDRC_ODTCFG(0), 0x041d0f5c);
reg32_write(DDRC_ODTMAP(0), 0x00000201);
reg32_write(DDRC_SCHED(0), 0x7ab50b07);
reg32_write(DDRC_SCHED1(0), 0x00000022);
reg32_write(DDRC_PERFHPR1(0), 0x7b00665e);
reg32_write(DDRC_PERFLPR1(0), 0x2b00c4e1);
reg32_write(DDRC_PERFWR1(0), 0xb700c9fe);
reg32_write(DDRC_DBG0(0), 0x00000017);
reg32_write(DDRC_DBG1(0), 0x00000000);
reg32_write(DDRC_DBGCMD(0), 0x00000000);
reg32_write(DDRC_SWCTL(0), 0x00000001);
reg32_write(DDRC_POISONCFG(0), 0x00010000);
reg32_write(DDRC_PCCFG(0), 0x00000100);
reg32_write(DDRC_PCFGR_0(0), 0x00003051);
reg32_write(DDRC_PCFGW_0(0), 0x000061d2);
reg32_write(DDRC_PCTRL_0(0), 0x00000001);
reg32_write(DDRC_PCFGQOS0_0(0), 0x02100b04);
reg32_write(DDRC_PCFGQOS1_0(0), 0x003f0353);
reg32_write(DDRC_PCFGWQOS0_0(0), 0x00000002);
reg32_write(DDRC_PCFGWQOS1_0(0), 0x000005fd);
}
void ddr_init(void)
{
/* change the clock source of dram_apb_clk_root */
reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1),(0x7<<24)|(0x7<<16));
reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1),(0x4<<24)|(0x3<<16));
/* disable the clock gating */
reg32_write(0x303A00EC,0x0000ffff);
reg32setbit(0x303A00F8,5);
reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000);
dram_pll_init(SSCG_PLL_OUT_400M);
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
/* Configure uMCTL2's registers */
umctl2_cfg();
reg32setbit(DDRC_RFSHCTL3(0),0); /* dis_auto_refresh */
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000);
ddr_load_train_code(FW_1D_IMAGE);
reg32_write(DDRC_DBG1(0), 0x00000000); /* ('b00000000_00000000_00000000_00000000) ('d0) */
reg32setbit(DDRC_PWRCTL(0),5); /* selfref_sw=1, self-refresh */
reg32clrbit(DDRC_SWCTL(0), 0); /* sw_done=0, enable quasi-dynamic programming */
reg32_write(DDRC_DFIMISC(0), 0x00000000);
/* Configure DDR3L PHY's registers */
ddr3_phyinit_train_1600mts();
do {
tmp = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0x00020097);
} while (tmp != 0);
reg32setbit(DDRC_DFIMISC(0),5);/* dfi_init_start=1 */
do{
tmp = 0x1 & (reg32_read(DDRC_DFISTAT(0)));
} while (!tmp);/* wait DFISTAT.dfi_init_complete to 1 */
reg32clrbit(DDRC_DFIMISC(0),5);/* dfi_init_start=0 */
reg32setbit(DDRC_DFIMISC(0),0);/* dfi_init_complete_en=1 */
reg32clrbit(DDRC_PWRCTL(0),5);/* selfref_sw=0, exit self-refresh */
reg32setbit(DDRC_SWCTL(0), 0);/* sw_done=1, disable quasi-dynamic programming */
/* wait SWSTAT.sw_done_ack to 1 */
do{
tmp = 0x1 & (reg32_read(DDRC_SWSTAT(0)));
} while (!tmp);
/* wait STAT to normal state */
do{
tmp = 0x7 & (reg32_read(DDRC_STAT(0)));
} while (tmp != 0x1);
reg32_write(DDRC_PCTRL_0(0), 0x00000001); /* enable port 0 */
reg32clrbit(DDRC_RFSHCTL3(0), 0); /* auto-refresh enable */
}
This diff is collapsed.
/*
* 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"
#ifdef CONFIG_ENABLE_DDR_TRAINING_DEBUG
#define ddr_printf(args...) printf(args)
#else
#define ddr_printf(args...)
#endif
#include "../wait_ddrphy_training_complete.c"
volatile unsigned int tmp, tmp_t;
void umctl2_cfg(void){
reg32_write(DDRC_DBG1(0), 0x00000001);
reg32_write(DDRC_PWRCTL(0), 0x00000001);
tmp = reg32_read(DDRC_STAT(0));
while (tmp_t == 0x00000001){
tmp = reg32_read(DDRC_STAT(0));
tmp_t = tmp && 0x00000001;
}
reg32_write(DDRC_MSTR(0), 0x83040010); /* Two ranks */
reg32_write(DDRC_MRCTRL0(0), 0x40007030);
reg32_write(DDRC_MRCTRL1(0), 0x000170df);
reg32_write(DDRC_MRCTRL2(0), 0x97d37be3);
reg32_write(DDRC_DERATEEN(0), 0x00000302);
reg32_write(DDRC_DERATEINT(0), 0xbc808cc7);
reg32_write(DDRC_MSTR2(0), 0x00000001);
reg32_write(DDRC_PWRCTL(0), 0x000001ae);
reg32_write(DDRC_PWRTMG(0), 0x000d2800);
reg32_write(DDRC_HWLPCTL(0), 0x000c0000);
reg32_write(DDRC_HWFFCCTL(0), 0x00000010);
reg32_write(DDRC_RFSHCTL0(0), 0x007090b0);
reg32_write(DDRC_RFSHCTL1(0), 0x00420019);
reg32_write(DDRC_RFSHCTL3(0), 0x00000010);
reg32_write(DDRC_RFSHTMG(0), 0x0049009d);
reg32_write(DDRC_CRCPARCTL0(0), 0x00000000);
reg32_write(DDRC_CRCPARCTL1(0), 0x00001011);
reg32_write(DDRC_INIT0(0), 0xc0030002);
reg32_write(DDRC_INIT1(0), 0x00030006);
reg32_write(DDRC_INIT2(0), 0x00000305);
reg32_write(DDRC_INIT3(0), 0x0a300001);
reg32_write(DDRC_INIT4(0), 0x10180240);
reg32_write(DDRC_INIT5(0), 0x0011008a);
reg32_write(DDRC_INIT6(0), 0x0a000042);
reg32_write(DDRC_INIT7(0), 0x00000800);
reg32_write(DDRC_DIMMCTL(0), 0x00000032); /* [1] dimm_addr_mirr_en, it will effect the MRS if use umctl2 to initi dram. */
reg32_write(DDRC_RANKCTL(0), 0x00000530);
reg32_write(DDRC_DRAMTMG0(0), 0x14132813);
reg32_write(DDRC_DRAMTMG1(0), 0x0007051b);
reg32_write(DDRC_DRAMTMG2(0), 0x090a050f);
reg32_write(DDRC_DRAMTMG3(0), 0x0000f00f);
reg32_write(DDRC_DRAMTMG4(0), 0x08030409);
reg32_write(DDRC_DRAMTMG5(0), 0x0c0d0504);
reg32_write(DDRC_DRAMTMG6(0), 0x00000003);
reg32_write(DDRC_DRAMTMG7(0), 0x00000d0c);
reg32_write(DDRC_DRAMTMG8(0), 0x05051f09);
reg32_write(DDRC_DRAMTMG9(0), 0x0002040c);
reg32_write(DDRC_DRAMTMG10(0), 0x000e0d0b);
reg32_write(DDRC_DRAMTMG11(0), 0x1409011e);
reg32_write(DDRC_DRAMTMG12(0), 0x0000000d);
reg32_write(DDRC_DRAMTMG13(0), 0x09000000);
reg32_write(DDRC_DRAMTMG14(0), 0x00000371);
reg32_write(DDRC_DRAMTMG15(0), 0x80000000);
reg32_write(DDRC_DRAMTMG17(0), 0x0076006e);
reg32_write(DDRC_ZQCTL0(0), 0x51000040);
reg32_write(DDRC_ZQCTL1(0), 0x00000070);
reg32_write(DDRC_ZQCTL2(0), 0x00000000);
reg32_write(DDRC_DFITMG0(0), 0x038f820c);
reg32_write(DDRC_DFITMG1(0), 0x00020103);
reg32_write(DDRC_DFILPCFG0(0), 0x07e1b011);
reg32_write(DDRC_DFILPCFG1(0), 0x00000030);
reg32_write(DDRC_DFIUPD0(0), 0xe0400018);
reg32_write(DDRC_DFIUPD1(0), 0x004e00c3);
reg32_write(DDRC_DFIUPD2(0), 0x00000000);
reg32_write(DDRC_DFIMISC(0), 0x00000001);
reg32_write(DDRC_DFITMG2(0), 0x00000f0c);
reg32_write(DDRC_DFITMG3(0), 0x00000001);
reg32_write(DDRC_DBICTL(0), 0x00000000);
reg32_write(DDRC_DFIPHYMSTR(0), 0x00000000);
reg32_write(DDRC_ADDRMAP0(0), 0x00001F17); /* [4:0]cs0: 6+23 */
reg32_write(DDRC_ADDRMAP1(0), 0x003F0808); /* [5:0] bank b0: 2+8; [13:8] b1: P3+8 ; [21:16] b2: 4+, unused */
reg32_write(DDRC_ADDRMAP2(0), 0x00000000); /* [3:0] col-b2: 2; [11:8] col-b3: 3+0; [19:16] col-b4: 4+0 ; [27:24] col-b5: 5+0 */
reg32_write(DDRC_ADDRMAP3(0), 0x00000000); /* [3:0] col-b6: 6+0; [11:8] col-b7: 7+0; [19:16] col-b8: 8+0 ; [27:24] col-b9: 9+0 */
reg32_write(DDRC_ADDRMAP4(0), 0x00001f1f); /* col-b10, col-b11 not used */
reg32_write(DDRC_ADDRMAP5(0), 0x07070707); /* [3:0] row-b0: 6+7; [11:8] row-b1: 7+7; [19:16] row-b2_b10: 8~16+7; [27:24] row-b11: 17+7 */
reg32_write(DDRC_ADDRMAP6(0), 0x07070707); /* [3:0] row-b12:18+7; [11:8] row-b13: 19+7; [19:16] row-b14:20+7 */
reg32_write(DDRC_ADDRMAP7(0), 0x00000f0f); /* col-b10, col-b11 not used */
reg32_write(DDRC_ADDRMAP8(0), 0x00003F0A); /* [5:0] bg-b0: 2+10; [13:8]bg-b1:3+, unused */
reg32_write(DDRC_ADDRMAP9(0), 0x00000000); /* it's valid only when ADDRMAP5.addrmap_row_b2_10 is set to value 15 */
reg32_write(DDRC_ADDRMAP10(0), 0x00000000);/* it's valid only when ADDRMAP5.addrmap_row_b2_10 is set to value 15 */
reg32_write(DDRC_ADDRMAP11(0), 0x00000000);
reg32_write(DDRC_ODTCFG(0), 0x05170558);
reg32_write(DDRC_ODTMAP(0), 0x00002113);
reg32_write(DDRC_SCHED(0), 0x0d6f0705);
reg32_write(DDRC_SCHED1(0), 0x00000000);
reg32_write(DDRC_PERFHPR1(0), 0xe500558b);
reg32_write(DDRC_PERFLPR1(0), 0x75001fea);
reg32_write(DDRC_PERFWR1(0), 0x880026c7);
reg32_write(DDRC_DBG0(0), 0x00000011);
reg32_write(DDRC_DBG1(0), 0x00000000);
reg32_write(DDRC_DBGCMD(0), 0x00000000);
reg32_write(DDRC_SWCTL(0), 0x00000001);
reg32_write(DDRC_POISONCFG(0), 0x00100011);
reg32_write(DDRC_PCCFG(0), 0x00000100);
reg32_write(DDRC_PCFGR_0(0), 0x00015313);
reg32_write(DDRC_PCFGW_0(0), 0x000050dc);
reg32_write(DDRC_PCTRL_0(0), 0x00000001);
reg32_write(DDRC_PCFGQOS0_0(0), 0x01100200);
reg32_write(DDRC_PCFGQOS1_0(0), 0x01ba023a);
reg32_write(DDRC_PCFGWQOS0_0(0), 0x00110000);
reg32_write(DDRC_PCFGWQOS1_0(0), 0x0000001e);
}
void ddr_init(void)
{
/* change the clock source of dram_apb_clk_root */
reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1),(0x7<<24)|(0x7<<16));
reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1),(0x4<<24)|(0x3<<16));
/* disable the clock gating */
reg32_write(0x303A00EC,0x0000ffff);
reg32setbit(0x303A00F8,5);
reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000);
dram_pll_init(SSCG_PLL_OUT_600M);
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
/* Configure uMCTL2's registers */
umctl2_cfg();
tmp = reg32_read(DDRC_RFSHCTL3(0));
reg32_write(DDRC_RFSHCTL3(0), 0x00000011);
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000);
ddr_load_train_code(FW_1D_IMAGE);
reg32_write(DDRC_DBG1(0), 0x00000000);
tmp = reg32_read(DDRC_PWRCTL(0));
reg32_write(DDRC_PWRCTL(0), 0x000001ae);
tmp = reg32_read(DDRC_PWRCTL(0));
reg32_write(DDRC_PWRCTL(0), 0x000001ac);
reg32_write(DDRC_SWCTL(0), 0x00000000);
tmp = reg32_read(DDRC_CRCPARSTAT(0));
reg32_write(DDRC_DFIMISC(0), 0x00000000);
reg32_write(DDRC_DFIMISC(0), 0x00000000);
tmp = reg32_read(DDRC_DBICTL(0));
tmp = reg32_read(DDRC_MSTR(0));
tmp = reg32_read(DDRC_INIT3(0));
tmp = reg32_read(DDRC_INIT4(0));
tmp = reg32_read(DDRC_INIT6(0));
tmp = reg32_read(DDRC_INIT7(0));
tmp = reg32_read(DDRC_INIT0(0));
ddr4_phyinit_train_2400mts();
do {
tmp_t = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4*0x00020097);
} while (tmp_t != 0);
reg32_write(DDRC_DFIMISC(0), 0x00000020);
/* wait DFISTAT.dfi_init_complete to 1 */
tmp_t = 0;
while(tmp_t == 0){
tmp = reg32_read(DDRC_DFISTAT(0));
tmp_t = tmp & 0x01;
}
/* clear DFIMISC.dfi_init_complete_en */
reg32_write(DDRC_DFIMISC(0), 0x00000000);
/* set DFIMISC.dfi_init_complete_en again */
reg32_write(DDRC_DFIMISC(0), 0x00000001);
reg32_write(DDRC_PWRCTL(0), 0x0000018c);
/* set SWCTL.sw_done to enable quasi-dynamic register programming outside reset .*/
reg32_write(DDRC_SWCTL(0), 0x00000001);
/* wait SWSTAT.sw_done_ack to 1 */
tmp_t = 0;
while(tmp_t==0){
tmp = reg32_read(DDRC_SWSTAT(0));
tmp_t = tmp & 0x01;
}
/* wait STAT to normal state */
tmp_t = 0;
while(tmp_t==0){
tmp = reg32_read(DDRC_STAT(0));
tmp_t = tmp & 0x01;
}
tmp = reg32_read(DDRC_CRCPARSTAT(0));
reg32_write(DDRC_PWRCTL(0), 0x0000018c);
reg32_write(DDRC_DERATEEN(0), 0x00000302);
reg32_write(DDRC_PCTRL_0(0), 0x00000001);
reg32_write(DDRC_RFSHCTL3(0), 0x00000010); /* dis_auto-refresh is set to 0 */
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4*(0xd0000), 0);
tmp = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4*(0x54030));
tmp = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4*(0x54035));
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4*(0xd0000), 1);
}
This diff is collapsed.
/*
* Copyright 2017 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 ddr_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 ddr_imem code fail=%d\n",error);
}else{
printf("check ddr_imem code pass\n");
}
printf("check ddr_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 ddr_dmem code fail=%d",error);
}else{
printf("check ddr_dmem code pass\n");
}
}
/*
* Copyright 2017 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
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)