MLK-19541 imx8mm_evk: Add imx8mm DDR4 EVK CPU board support
Add DDR4 init codes, u-boot dtb and defconfig to support DDR4 EVK. The DDR4 EVK removed eMMC and Flexspi, but use NAND instead. Current codes support to boot from SD and enable NAND access in regular u-boot. Signed-off-by: Ye Li <ye.li@nxp.com> Acked-by: Peng Fan <peng.fan@nxp.com>
This commit is contained in:
parent
02b8787d0d
commit
6a8f5581f2
|
|
@ -462,6 +462,7 @@ dtb-$(CONFIG_ARCH_IMX8M) += fsl-imx8mq-evk.dtb \
|
|||
fsl-imx8mq-ddr3l-arm2.dtb \
|
||||
fsl-imx8mq-ddr4-arm2.dtb \
|
||||
fsl-imx8mq-phanbell.dtb \
|
||||
fsl-imx8mm-ddr4-evk.dtb \
|
||||
fsl-imx8mm-ddr4-val.dtb \
|
||||
fsl-imx8mm-evk.dtb
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2018 NXP
|
||||
*/
|
||||
|
||||
#include "fsl-imx8mm-evk.dts"
|
||||
|
||||
/ {
|
||||
model = "FSL i.MX8MM DDR4 EVK board";
|
||||
};
|
||||
|
||||
&usdhc3 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&flexspi0{
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
@ -48,6 +48,11 @@ config TARGET_IMX8MM_EVK
|
|||
select SUPPORT_SPL
|
||||
select IMX8M_LPDDR4
|
||||
|
||||
config TARGET_IMX8MM_DDR4_EVK
|
||||
bool "imx8mm validation board"
|
||||
select IMX8MM
|
||||
select SUPPORT_SPL
|
||||
|
||||
endchoice
|
||||
|
||||
config SYS_SOC
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
if TARGET_IMX8MM_EVK
|
||||
if TARGET_IMX8MM_EVK || TARGET_IMX8MM_DDR4_EVK
|
||||
|
||||
config SYS_BOARD
|
||||
default "imx8mm_evk"
|
||||
|
|
|
|||
|
|
@ -8,5 +8,9 @@ obj-y += imx8mm_evk.o
|
|||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
obj-y += spl.o
|
||||
ifdef CONFIG_IMX8M_LPDDR4
|
||||
obj-y += lpddr4_timing.o
|
||||
else
|
||||
obj-y += ddr/
|
||||
endif
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# 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_EVK) += ddr4/
|
||||
endif
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# 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
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright 2018 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __DDR4_CONFIG_H__
|
||||
#define __DDR4_CONFIG_H__
|
||||
|
||||
#include "../ddr.h"
|
||||
|
||||
#define DDR_ONE_RANK
|
||||
#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
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright 2018 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/ddr.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);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,599 @@
|
|||
/*
|
||||
* Copyright 2018 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/ddr.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include "anamix_common.h"
|
||||
#include "ddr4_define.h"
|
||||
|
||||
unsigned int mr_value[3][7] = {
|
||||
{0xa34, 0x105, 0x1028, 0x240, 0x200, 0x200, 0x814}, /* pstate0 MR */
|
||||
{0x204, 0x104, 0x1000, 0x040, 0x200, 0x200, 0x014}, /* pstate1 MR */
|
||||
{0x204, 0x104, 0x1000, 0x040, 0x200, 0x200, 0x014} }; /* pstate2 MR */
|
||||
|
||||
static unsigned int cur_pstate;
|
||||
unsigned int after_retention = 0;
|
||||
|
||||
void ddr4_dll_change(unsigned int pstate);
|
||||
void ddr4_dll_no_change(unsigned int pstate);
|
||||
|
||||
void umctl2_cfg(void)
|
||||
{
|
||||
#ifdef DDR_ONE_RANK
|
||||
reg32_write(DDRC_MSTR(0), 0x81040010);
|
||||
#else
|
||||
reg32_write(DDRC_MSTR(0), 0x83040010);
|
||||
#endif
|
||||
|
||||
reg32_write(DDRC_PWRCTL(0), 0x000000aa);
|
||||
reg32_write(DDRC_PWRTMG(0), 0x00221306);
|
||||
|
||||
reg32_write(DDRC_RFSHCTL0(0), 0x00c0a070);
|
||||
reg32_write(DDRC_RFSHCTL1(0), 0x00010008);
|
||||
reg32_write(DDRC_RFSHCTL3(0), 0x00000010);
|
||||
reg32_write(DDRC_RFSHTMG(0), 0x004980f4);
|
||||
reg32_write(DDRC_CRCPARCTL0(0), 0x00000000);
|
||||
reg32_write(DDRC_CRCPARCTL1(0), 0x00001010);
|
||||
reg32_write(DDRC_INIT0(0), 0xc0030002);
|
||||
reg32_write(DDRC_INIT1(0), 0x00020009);
|
||||
reg32_write(DDRC_INIT2(0), 0x0000350f);
|
||||
reg32_write(DDRC_INIT3(0), (mr_value[0][0]<<16) | (mr_value[0][1]));
|
||||
reg32_write(DDRC_INIT4(0), (mr_value[0][2]<<16) | (mr_value[0][3]));
|
||||
reg32_write(DDRC_INIT5(0), 0x001103cb);
|
||||
reg32_write(DDRC_INIT6(0), (mr_value[0][4]<<16) | (mr_value[0][5]));
|
||||
reg32_write(DDRC_INIT7(0), mr_value[0][6]);
|
||||
reg32_write(DDRC_DIMMCTL(0), 0x00000032);
|
||||
reg32_write(DDRC_RANKCTL(0), 0x00000fc7);
|
||||
reg32_write(DDRC_DRAMTMG0(0), 0x14132813);
|
||||
reg32_write(DDRC_DRAMTMG1(0), 0x0004051b);
|
||||
reg32_write(DDRC_DRAMTMG2(0), 0x0808030f);
|
||||
reg32_write(DDRC_DRAMTMG3(0), 0x0000400c);
|
||||
reg32_write(DDRC_DRAMTMG4(0), 0x08030409);
|
||||
reg32_write(DDRC_DRAMTMG5(0), 0x0e090504);
|
||||
reg32_write(DDRC_DRAMTMG6(0), 0x05030000);
|
||||
reg32_write(DDRC_DRAMTMG7(0), 0x0000090e);
|
||||
reg32_write(DDRC_DRAMTMG8(0), 0x0606700c);
|
||||
reg32_write(DDRC_DRAMTMG9(0), 0x0002040c);
|
||||
reg32_write(DDRC_DRAMTMG10(0), 0x000f0c07);
|
||||
reg32_write(DDRC_DRAMTMG11(0), 0x1809011d);
|
||||
reg32_write(DDRC_DRAMTMG12(0), 0x0000000d);
|
||||
reg32_write(DDRC_DRAMTMG13(0), 0x2b000000);
|
||||
reg32_write(DDRC_DRAMTMG14(0), 0x000000a4);
|
||||
reg32_write(DDRC_DRAMTMG15(0), 0x00000000);
|
||||
reg32_write(DDRC_DRAMTMG17(0), 0x00250078);
|
||||
reg32_write(DDRC_ZQCTL0(0), 0x51000040);
|
||||
reg32_write(DDRC_ZQCTL1(0), 0x00000070);
|
||||
reg32_write(DDRC_ZQCTL2(0), 0x00000000);
|
||||
reg32_write(DDRC_DFITMG0(0), 0x038b820b);
|
||||
reg32_write(DDRC_DFITMG1(0), 0x02020103);
|
||||
reg32_write(DDRC_DFILPCFG0(0), 0x07f04011); /* [8]dfi_lp_en_sr = 0 */
|
||||
reg32_write(DDRC_DFILPCFG1(0), 0x000000b0);
|
||||
reg32_write(DDRC_DFIUPD0(0), 0xe0400018);
|
||||
reg32_write(DDRC_DFIUPD1(0), 0x0048005a);
|
||||
reg32_write(DDRC_DFIUPD2(0), 0x80000000);
|
||||
reg32_write(DDRC_DFIMISC(0), 0x00000001);
|
||||
reg32_write(DDRC_DFITMG2(0), 0x00000b0b);
|
||||
reg32_write(DDRC_DFITMG3(0), 0x00000001);
|
||||
reg32_write(DDRC_DBICTL(0), 0x00000000);
|
||||
reg32_write(DDRC_DFIPHYMSTR(0), 0x00000000);
|
||||
|
||||
#ifdef DDR_ONE_RANK
|
||||
reg32_write(DDRC_ADDRMAP0(0), 0x0000001F);
|
||||
#else
|
||||
reg32_write(DDRC_ADDRMAP0(0), 0x00000017); /* [4:0]cs0: 6+23 */
|
||||
#endif
|
||||
reg32_write(DDRC_ADDRMAP1(0), 0x003F0909); /* [5:0] bank b0: 2+9; [13:8] b1: P3+9 ; [21:16] b2: 4+, unused */
|
||||
reg32_write(DDRC_ADDRMAP2(0), 0x01010100); /* [3:0] col-b2: 2; [11:8] col-b3: 3+1; [19:16] col-b4: 4+1 ; [27:24] col-b5: 5+1 */
|
||||
reg32_write(DDRC_ADDRMAP3(0), 0x01010101); /* [3:0] col-b6: 6+1; [11:8] col-b7: 7+1; [19:16] col-b8: 8+1 ; [27:24] col-b9: 9+1 */
|
||||
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; [27:24] row-b15: 21+7 */
|
||||
reg32_write(DDRC_ADDRMAP7(0), 0x00000f0f); /* col-b10, col-b11 not used */
|
||||
reg32_write(DDRC_ADDRMAP8(0), 0x00003F01); /* [5:0] bg-b0: 2+1; [13:8]bg-b1:3+, unused */
|
||||
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);
|
||||
|
||||
/* FREQ0: BL8, CL=16, CWL=16, WR_PREAMBLE = 1,RD_PREAMBLE = 1, CRC_MODE = 1, so wr_odt_hold=5+1+1=7 */
|
||||
/* wr_odt_delay=DFITMG1.dfi_t_cmd_lat=0 */
|
||||
reg32_write(DDRC_ODTCFG(0), 0x07000600);
|
||||
#ifdef DDR_ONE_RANK
|
||||
reg32_write(DDRC_ODTMAP(0), 0x0001);
|
||||
#else
|
||||
reg32_write(DDRC_ODTMAP(0), 0x0201);/* disable ODT0x00001120); */
|
||||
#endif
|
||||
reg32_write(DDRC_SCHED(0), 0x317d1a07);
|
||||
reg32_write(DDRC_SCHED1(0), 0x0000000f);
|
||||
reg32_write(DDRC_PERFHPR1(0), 0x2a001b76);
|
||||
reg32_write(DDRC_PERFLPR1(0), 0x7300b473);
|
||||
reg32_write(DDRC_PERFWR1(0), 0x30000e06);
|
||||
reg32_write(DDRC_DBG0(0), 0x00000014);
|
||||
reg32_write(DDRC_DBG1(0), 0x00000000);
|
||||
reg32_write(DDRC_DBGCMD(0), 0x00000000);
|
||||
reg32_write(DDRC_SWCTL(0), 0x00000001);
|
||||
reg32_write(DDRC_POISONCFG(0), 0x00000010);
|
||||
reg32_write(DDRC_PCCFG(0), 0x00000100);/* bl_exp_mode=1 */
|
||||
reg32_write(DDRC_PCFGR_0(0), 0x00013193);
|
||||
reg32_write(DDRC_PCFGW_0(0), 0x00006096);
|
||||
reg32_write(DDRC_PCTRL_0(0), 0x00000001);
|
||||
reg32_write(DDRC_PCFGQOS0_0(0), 0x02000c00);
|
||||
reg32_write(DDRC_PCFGQOS1_0(0), 0x003c00db);
|
||||
reg32_write(DDRC_PCFGWQOS0_0(0), 0x00100009);
|
||||
reg32_write(DDRC_PCFGWQOS1_0(0), 0x00000002);
|
||||
|
||||
}
|
||||
|
||||
void umctl2_freq1_cfg(void)
|
||||
{
|
||||
reg32_write(DDRC_FREQ1_RFSHCTL0(0), 0x0021a0c0);
|
||||
#ifdef PLLBYPASS_250MBPS
|
||||
reg32_write(DDRC_FREQ1_RFSHTMG(0), 0x000f0011);/* tREFI=7.8us */
|
||||
#endif
|
||||
#ifdef PLLBYPASS_400MBPS
|
||||
reg32_write(DDRC_FREQ1_RFSHTMG(0), 0x0018001a);/* tREFI=7.8us */
|
||||
#endif
|
||||
|
||||
reg32_write(DDRC_FREQ1_INIT3(0), (mr_value[1][0]<<16) | (mr_value[1][1]));
|
||||
reg32_write(DDRC_FREQ1_INIT4(0), (mr_value[1][2]<<16) | (mr_value[1][3]));
|
||||
reg32_write(DDRC_FREQ1_INIT6(0), (mr_value[1][4]<<16) | (mr_value[1][5]));
|
||||
reg32_write(DDRC_FREQ1_INIT7(0), mr_value[1][6]);
|
||||
#ifdef PLLBYPASS_250MBPS
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG0(0), 0x0c0e0403);/* t_ras_max=9*7.8us, t_ras_min=35ns */
|
||||
#endif
|
||||
#ifdef PLLBYPASS_400MBPS
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG0(0), 0x0c0e0604);/* t_ras_max=9*7.8us, t_ras_min=35ns */
|
||||
#endif
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG1(0), 0x00030314);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG2(0), 0x0505040a);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG3(0), 0x0000400c);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG4(0), 0x06040307); /* tRP=6 --> 7 */
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG5(0), 0x090d0202);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG6(0), 0x0a070008);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG7(0), 0x00000d09);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG8(0), 0x08084b09);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG9(0), 0x00020308);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG10(0), 0x000f0d06);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG11(0), 0x12060111);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG12(0), 0x00000008);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG13(0), 0x21000000);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG14(0), 0x00000000);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG15(0), 0x00000000);
|
||||
reg32_write(DDRC_FREQ1_DRAMTMG17(0), 0x00c6007d);
|
||||
reg32_write(DDRC_FREQ1_ZQCTL0(0), 0x51000040);
|
||||
reg32_write(DDRC_FREQ1_DFITMG0(0), 0x03858204);
|
||||
reg32_write(DDRC_FREQ1_DFITMG1(0), 0x00020103);
|
||||
reg32_write(DDRC_FREQ1_DFITMG2(0), 0x00000504);
|
||||
reg32_write(DDRC_FREQ1_DFITMG3(0), 0x00000001);
|
||||
/* FREQ1: BL8, CL=10, CWL=9, WR_PREAMBLE = 1,RD_PREAMBLE = 1, CRC_MODE = 1 */
|
||||
/* wr_odt_delay=DFITMG1.dfi_t_cmd_lat=0 */
|
||||
reg32_write(DDRC_FREQ1_ODTCFG(0), 0x07000601);
|
||||
}
|
||||
|
||||
void umctl2_freq2_cfg(void)
|
||||
{
|
||||
reg32_write(DDRC_FREQ2_RFSHCTL0(0), 0x0021a0c0);
|
||||
reg32_write(DDRC_FREQ2_RFSHTMG(0), 0x0006000e);/* tREFI=7.8us */
|
||||
reg32_write(DDRC_FREQ2_INIT3(0), (mr_value[2][0]<<16) | (mr_value[2][1]));
|
||||
reg32_write(DDRC_FREQ2_INIT4(0), (mr_value[2][2]<<16) | (mr_value[2][3]));
|
||||
reg32_write(DDRC_FREQ2_INIT6(0), (mr_value[2][4]<<16) | (mr_value[2][5]));
|
||||
reg32_write(DDRC_FREQ2_INIT7(0), mr_value[2][6]);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG0(0), 0x0c0e0101);/* t_ras_max=9*7.8us, t_ras_min=35ns */
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG1(0), 0x00030314);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG2(0), 0x0505040a);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG3(0), 0x0000400c);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG4(0), 0x06040307); /* tRP=6 --> 7 */
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG5(0), 0x090d0202);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG6(0), 0x0a070008);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG7(0), 0x00000d09);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG8(0), 0x08084b09);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG9(0), 0x00020308);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG10(0), 0x000f0d06);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG11(0), 0x12060111);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG12(0), 0x00000008);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG13(0), 0x21000000);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG14(0), 0x00000000);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG15(0), 0x00000000);
|
||||
reg32_write(DDRC_FREQ2_DRAMTMG17(0), 0x00c6007d);
|
||||
reg32_write(DDRC_FREQ2_ZQCTL0(0), 0x51000040);
|
||||
reg32_write(DDRC_FREQ2_DFITMG0(0), 0x03858204);
|
||||
reg32_write(DDRC_FREQ2_DFITMG1(0), 0x00020103);
|
||||
reg32_write(DDRC_FREQ2_DFITMG2(0), 0x00000504);
|
||||
reg32_write(DDRC_FREQ2_DFITMG3(0), 0x00000001);
|
||||
/* FREQ1: BL8, CL=10, CWL=9, WR_PREAMBLE = 1,RD_PREAMBLE = 1, CRC_MODE = 1 */
|
||||
/* wr_odt_delay=DFITMG1.dfi_t_cmd_lat=0 */
|
||||
reg32_write(DDRC_FREQ2_ODTCFG(0), 0x07000601);
|
||||
}
|
||||
|
||||
|
||||
void ddr4_pub_train(void)
|
||||
{
|
||||
volatile unsigned int tmp_t;
|
||||
after_retention = 0;
|
||||
|
||||
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00003F); /* assert [0]ddr1_preset_n, [1]ddr1_core_reset_n, [2]ddr1_phy_reset, [3]ddr1_phy_pwrokin_n, [4]src_system_rst_b! */
|
||||
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F); /* deassert [4]src_system_rst_b! */
|
||||
|
||||
/* change the clock source of dram_apb_clk_root */
|
||||
clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(4) | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4)); /* to source 4 --800MHz/4 */
|
||||
|
||||
/* DDR_PLL_CONFIG_600MHz(); */
|
||||
dram_pll_init(DRAM_PLL_OUT_600M);
|
||||
ddr_dbg("C: dram pll init finished\n");
|
||||
|
||||
reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */
|
||||
reg32setbit(0x303A00F8, 5);/* PU_PGC_SW_PUP_REQ */
|
||||
|
||||
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006); /* release [0]ddr1_preset_n, [3]ddr1_phy_pwrokin_n */
|
||||
|
||||
reg32_write(DDRC_DBG1(0), 0x00000001);
|
||||
reg32_write(DDRC_PWRCTL(0), 0x00000001);
|
||||
|
||||
while (0 != (0x7 & reg32_read(DDRC_STAT(0))))
|
||||
;
|
||||
|
||||
ddr_dbg("C: cfg umctl2 regs ...\n");
|
||||
umctl2_cfg();
|
||||
#ifdef DDR4_SW_FFC
|
||||
umctl2_freq1_cfg();
|
||||
umctl2_freq2_cfg();
|
||||
#endif
|
||||
|
||||
reg32_write(DDRC_RFSHCTL3(0), 0x00000011);
|
||||
/* RESET: <ctn> DEASSERTED */
|
||||
/* RESET: <a Port 0 DEASSERTED(0) */
|
||||
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004);
|
||||
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000);
|
||||
|
||||
reg32_write(DDRC_DBG1(0), 0x00000000);
|
||||
reg32_write(DDRC_PWRCTL(0), 0x00000aa);
|
||||
reg32_write(DDRC_SWCTL(0), 0x00000000);
|
||||
|
||||
reg32_write(DDRC_DFIMISC(0), 0x00000000);
|
||||
|
||||
ddr_dbg("C: phy training ...\n");
|
||||
ddr4_phyinit_train_sw_ffc(1);/* for dvfs flow, 2D training is a must item */
|
||||
|
||||
do {
|
||||
tmp_t = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0x00020097);
|
||||
ddr_dbg("C: Waiting CalBusy value = 0\n");
|
||||
} while (tmp_t != 0);
|
||||
|
||||
reg32_write(DDRC_DFIMISC(0), 0x00000020);
|
||||
|
||||
/* wait DFISTAT.dfi_init_complete to 1 */
|
||||
while (0 == (0x1 & reg32_read(DDRC_DFISTAT(0))))
|
||||
;
|
||||
|
||||
/* 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), 0x0000088);
|
||||
|
||||
/* 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 */
|
||||
while (0 == (0x1 & reg32_read(DDRC_SWSTAT(0))))
|
||||
;
|
||||
|
||||
/* wait STAT to normal state */
|
||||
while (0x1 != (0x7 & reg32_read(DDRC_STAT(0))))
|
||||
;
|
||||
|
||||
reg32_write(DDRC_PWRCTL(0), 0x0000088);
|
||||
reg32_write(DDRC_PCTRL_0(0), 0x00000001);
|
||||
reg32_write(DDRC_RFSHCTL3(0), 0x00000010); /* dis_auto-refresh is set to 0 */
|
||||
}
|
||||
|
||||
void ddr4_switch_freq(unsigned int pstate)
|
||||
{
|
||||
if ((pstate != 0 && cur_pstate == 0) || (pstate == 0 && cur_pstate != 0)) {
|
||||
ddr4_dll_change(pstate);
|
||||
} else {
|
||||
ddr4_dll_no_change(pstate);
|
||||
ddr_dbg("dll no change\n");
|
||||
}
|
||||
cur_pstate = pstate;
|
||||
}
|
||||
|
||||
void dram_all_mr_cfg(unsigned int pstate)
|
||||
{
|
||||
unsigned int i;
|
||||
/* 15. Perform MRS commands as required to re-program timing registers in the SDRAM for the new */
|
||||
/* frequency (in particular, CL, CWL and WR may need to be changed). */
|
||||
for (i = 0; i < 7; i++)
|
||||
ddr4_mr_write(i, mr_value[pstate][i], 0, 0x1);
|
||||
|
||||
#ifndef DDR_ONE_RANK
|
||||
for (i = 0; i < 7; i++)
|
||||
ddr4_mr_write(i, mr_value[pstate][i], 0, 0x2);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sw_pstate(unsigned int pstate)
|
||||
{
|
||||
volatile unsigned int tmp;
|
||||
unsigned int i;
|
||||
/* the the following software programming sequence to switch from DLL-on to DLL-off, or reverse: */
|
||||
reg32_write(DDRC_SWCTL(0), 0x0000);
|
||||
/* 12. Change the clock frequency to the desired value. */
|
||||
/* 13. Update any registers which may be required to change for the new frequency. This includes quasidynamic and dynamic registers. This includes both uMCTL2 registers and PHY registers. */
|
||||
reg32_write(DDRC_DFIMISC(0), 0x00000000);
|
||||
reg32_write(DDRC_MSTR2(0), pstate);/* UMCTL2_REGS_FREQ1 */
|
||||
reg32setbit(DDRC_MSTR(0), 29);
|
||||
|
||||
/* dvfs.18. Toggle RFSHCTL3.refresh_update_level to allow the new refresh-related register values to */
|
||||
/* propagate to the refresh logic. */
|
||||
tmp = reg32_read(DDRC_RFSHCTL3(0));
|
||||
if ((tmp & 0x2) == 0x2)
|
||||
reg32_write(DDRC_RFSHCTL3(0), tmp & 0xFFFFFFFD);
|
||||
else
|
||||
reg32_write(DDRC_RFSHCTL3(0), tmp | 0x2);
|
||||
|
||||
/* dvfs.19. If required, trigger the initialization in the PHY. If using the gen2 multiPHY, PLL initialization */
|
||||
/* should be triggered at this point. See the PHY databook for details about the frequency change */
|
||||
/* procedure. */
|
||||
reg32_write(DDRC_DFIMISC(0), 0x00000000 | (pstate<<8));/* pstate1 */
|
||||
reg32_write(DDRC_DFIMISC(0), 0x00000020 | (pstate<<8));
|
||||
|
||||
/* wait DFISTAT.dfi_init_complete to 0 */
|
||||
do {
|
||||
tmp = 0x1 & reg32_read(DDRC_DFISTAT(0));
|
||||
} while (tmp);
|
||||
|
||||
dwc_ddrphy_phyinit_userCustom_E_setDfiClk(pstate);
|
||||
|
||||
reg32_write(DDRC_DFIMISC(0), 0x00000000 | (pstate<<8));
|
||||
/* wait DFISTAT.dfi_init_complete to 1 */
|
||||
do {
|
||||
tmp = 0x1 & reg32_read(DDRC_DFISTAT(0));
|
||||
} while (!tmp);
|
||||
|
||||
/* When changing frequencies the controller may violate the JEDEC requirement that no */
|
||||
/* more than 16 refreshes should be issued within 2*tREFI. These extra refreshes are not */
|
||||
/* expected to cause a problem in the SDRAM. This issue can be avoided by waiting for at */
|
||||
/* least 2*tREFI before exiting self-refresh in step 19. */
|
||||
for (i = 20; i > 0; i--)
|
||||
;
|
||||
ddr_dbg("C: waiting for 2*tREFI (2*7.8us)\n");
|
||||
|
||||
/* 14. Exit the self-refresh state by setting PWRCTL.selfref_sw = 0. */
|
||||
reg32clrbit(DDRC_PWRCTL(0), 5);
|
||||
do {
|
||||
tmp = 0x3f & (reg32_read((DDRC_STAT(0))));
|
||||
ddr_dbg("C: waiting for exit Self Refresh\n");
|
||||
} while (tmp == 0x23);
|
||||
}
|
||||
|
||||
void ddr4_dll_change(unsigned int pstate)
|
||||
{
|
||||
volatile unsigned int tmp;
|
||||
enum DLL_STATE { NO_CHANGE = 0, ON2OFF = 1, OFF2ON = 2} dll_sw; /* 0-no change, 1-on2off, 2-off2on.; */
|
||||
|
||||
if (pstate != 0 && cur_pstate == 0) {
|
||||
dll_sw = ON2OFF;
|
||||
ddr_dbg("dll ON2OFF\n");
|
||||
} else if (pstate == 0 && cur_pstate != 0) {
|
||||
dll_sw = OFF2ON;
|
||||
ddr_dbg("dll OFF2ON\n");
|
||||
} else {
|
||||
dll_sw = NO_CHANGE;
|
||||
}
|
||||
|
||||
/* the the following software programming sequence to switch from DLL-on to DLL-off, or reverse: */
|
||||
reg32_write(DDRC_SWCTL(0), 0x0000);
|
||||
|
||||
/* 1. Set the DBG1.dis_hif = 1. This prevents further reads/writes being received on the HIF. */
|
||||
reg32setbit(DDRC_DBG1(0), 1);
|
||||
/* 2. Set ZQCTL0.dis_auto_zq=1, to disable automatic generation of ZQCS/MPC(ZQ calibration) */
|
||||
/* commands */
|
||||
if (pstate == 1)
|
||||
reg32setbit(DDRC_FREQ1_ZQCTL0(0), 31);
|
||||
else if (pstate == 2)
|
||||
reg32setbit(DDRC_FREQ2_ZQCTL0(0), 31);
|
||||
else
|
||||
reg32setbit(DDRC_ZQCTL0(0), 31);
|
||||
|
||||
/* 3. Set RFSHCTL3.dis_auto_refresh=1, to disable automatic refreshes */
|
||||
reg32setbit(DDRC_RFSHCTL3(0), 0);
|
||||
/* 4. Ensure all commands have been flushed from the uMCTL2 by polling */
|
||||
/* DBGCAM.wr_data_pipeline_empty, DBGCAM.rd_data_pipeline_empty1, */
|
||||
/* DBGCAM.dbg_wr_q_depth, DBGCAM.dbg_lpr_q_depth, DBGCAM.dbg_rd_q_empty, */
|
||||
/* DBGCAM.dbg_wr_q_empty. */
|
||||
do {
|
||||
tmp = 0x06000000 & reg32_read(DDRC_DBGCAM(0));
|
||||
} while (tmp != 0x06000000);
|
||||
reg32_write(DDRC_PCTRL_0(0), 0x00000000);
|
||||
/* 5. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers) to disable RTT_NOM: */
|
||||
/* a. DDR3: Write 0 to MR1[9], MR1[6] and MR1[2] */
|
||||
/* b. DDR4: Write 0 to MR1[10:8] */
|
||||
if (mr_value[pstate][1] & 0x700) {
|
||||
ddr4_mr_write(1, mr_value[pstate][1] & 0xF8FF, 0, 0x1);
|
||||
#ifndef DDR_ONE_RANK
|
||||
ddr4_mr_write(1, mr_value[pstate][1] & 0xF8FF, 0, 0x2);
|
||||
#endif
|
||||
}
|
||||
/* 6. For DDR4 only: Perform an MRS command (using MRCTRL0 and MRCTRL1 registers) to write 0 to */
|
||||
/* MR5[8:6] to disable RTT_PARK */
|
||||
if (mr_value[pstate][5] & 0x1C0) {
|
||||
ddr4_mr_write(5, mr_value[pstate][5] & 0xFE3F, 0, 0x1);
|
||||
#ifndef DDR_ONE_RANK
|
||||
ddr4_mr_write(5, mr_value[pstate][5] & 0xFE3F, 0, 0x2);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dll_sw == ON2OFF) {
|
||||
/* 7. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers) to write 0 to MR2[11:9], to */
|
||||
/* disable RTT_WR (and therefore disable dynamic ODT). This applies for both DDR3 and DDR4. */
|
||||
if (mr_value[pstate][2] & 0xE00) {
|
||||
ddr4_mr_write(2, mr_value[pstate][2] & 0xF1FF, 0, 0x1);
|
||||
#ifndef DDR_ONE_RANK
|
||||
ddr4_mr_write(2, mr_value[pstate][2] & 0xF1FF, 0, 0x2);
|
||||
#endif
|
||||
}
|
||||
/* 8. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers) to disable the DLL. The */
|
||||
/* timing of this MRS is automatically handled by the uMCTL2. */
|
||||
/* a. DDR3: Write 1 to MR1[0] */
|
||||
/* b. DDR4: Write 0 to MR1[0] */
|
||||
ddr4_mr_write(1, mr_value[pstate][1] & 0xFFFE, 0, 0x1);
|
||||
#ifndef DDR_ONE_RANK
|
||||
ddr4_mr_write(1, mr_value[pstate][1] & 0xFFFE, 0, 0x2);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 9. Put the SDRAM into self-refresh mode by setting PWRCTL.selfref_sw = 1, and polling */
|
||||
/* STAT.operating_mode to ensure the DDRC has entered self-refresh. */
|
||||
reg32setbit(DDRC_PWRCTL(0), 5);
|
||||
/* 10. Wait until STAT.operating_mode[1:0]==11 indicating that the DWC_ddr_umctl2 core is in selfrefresh mode. Ensure transition to self-refresh was due to software by checking that */
|
||||
/* STAT.selfref_type[1:0]=2`b10. */
|
||||
do {
|
||||
tmp = 0x3f & (reg32_read((DDRC_STAT(0))));
|
||||
ddr_dbg("C: wait DRAM in Self Refresh\n");
|
||||
} while (tmp != 0x23);
|
||||
|
||||
/* 11. Set the MSTR.dll_off_mode = 1 or 0. */
|
||||
if (dll_sw == ON2OFF)
|
||||
reg32setbit(DDRC_MSTR(0), 15);
|
||||
|
||||
if (dll_sw == OFF2ON)
|
||||
reg32clrbit(DDRC_MSTR(0), 15);
|
||||
|
||||
sw_pstate(pstate);
|
||||
|
||||
/* DRAM dll enable */
|
||||
if (dll_sw == OFF2ON) {
|
||||
ddr4_mr_write(1, mr_value[pstate][1] | 0x1, 0, 0x1);
|
||||
#ifndef DDR_ONE_RANK
|
||||
ddr4_mr_write(1, mr_value[pstate][1] | 0x1, 0, 0x2);
|
||||
#endif
|
||||
/* DRAM dll reset, self-clear */
|
||||
ddr4_mr_write(0, mr_value[pstate][0] | 0x100, 0, 0x1);
|
||||
#ifndef DDR_ONE_RANK
|
||||
ddr4_mr_write(0, mr_value[pstate][0] | 0x100, 0, 0x2);
|
||||
#endif
|
||||
}
|
||||
|
||||
dram_all_mr_cfg(pstate);
|
||||
|
||||
/* 16. Re-enable automatic generation of ZQCS/MPC(ZQ calibration) commands, by setting */
|
||||
/* ZQCTL0.dis_auto_zq=0 if they were previously disabled */
|
||||
if (pstate == 1)
|
||||
reg32clrbit(DDRC_FREQ1_ZQCTL0(0), 31);
|
||||
else if (pstate == 2)
|
||||
reg32clrbit(DDRC_FREQ2_ZQCTL0(0), 31);
|
||||
else
|
||||
reg32clrbit(DDRC_ZQCTL0(0), 31);
|
||||
|
||||
/* 17. Re-enable automatic refreshes (RFSHCTL3.dis_auto_refresh = 0) if they have been previously */
|
||||
/* disabled. */
|
||||
reg32clrbit(DDRC_RFSHCTL3(0), 0);
|
||||
/* 18. Restore ZQCTL0.dis_srx_zqcl */
|
||||
/* 19. Write DBG1.dis_hif = 0 to re-enable reads and writes. */
|
||||
reg32clrbit(DDRC_DBG1(0), 1);
|
||||
|
||||
reg32_write(DDRC_PCTRL_0(0), 0x00000001);
|
||||
/* 27. Write 1 to SBRCTL.scrub_en. Enable SBR if desired, only required if SBR instantiated. */
|
||||
|
||||
/* set SWCTL.sw_done to enable quasi-dynamic register programming outside reset. */
|
||||
reg32_write(DDRC_SWCTL(0), 0x0001);
|
||||
|
||||
/* wait SWSTAT.sw_done_ack to 1 */
|
||||
do {
|
||||
tmp = 0x1 & reg32_read(DDRC_SWSTAT(0));
|
||||
} while (!tmp);
|
||||
}
|
||||
|
||||
void ddr4_dll_no_change(unsigned int pstate)
|
||||
{
|
||||
volatile unsigned int tmp;
|
||||
/* ------------------------------------------------------------------------------------- */
|
||||
/* change to pstate1 */
|
||||
/* ------------------------------------------------------------------------------------- */
|
||||
/* 1. Program one of UMCTL2_REGS_FREQ1/2/3, whichever you prefer, timing register-set with the */
|
||||
/* timing settings required for the alternative clock frequency. */
|
||||
/* set SWCTL.sw_done to disable quasi-dynamic register programming outside reset. */
|
||||
reg32_write(DDRC_SWCTL(0), 0x0000);
|
||||
|
||||
/* set SWCTL.sw_done to enable quasi-dynamic register programming outside reset. */
|
||||
/* wait SWSTAT.sw_done_ack to 1 */
|
||||
|
||||
/* 2. Write 0 to PCTRL_n.port_en. This blocks AXI port(s) from taking any transaction (blocks traffic on */
|
||||
/* AXI ports). */
|
||||
reg32_write(DDRC_PCTRL_0(0), 0x00000000);
|
||||
/* 3. Poll PSTAT.rd_port_busy_n=0 and PSTAT.wr_port_busy_n=0. Wait until all AXI ports are idle (the */
|
||||
/* uMCTL2 core has to be idle). */
|
||||
do {
|
||||
tmp = reg32_read(DDRC_PSTAT(0));
|
||||
} while (tmp & 0x10001);
|
||||
|
||||
/* 4. Write 0 to SBRCTL.scrub_en. Disable SBR, required only if SBR instantiated. */
|
||||
/* 5. Poll SBRSTAT.scrub_busy=0. Indicates that there are no outstanding SBR read commands (required */
|
||||
/* only if SBR instantiated). */
|
||||
/* 6. Set DERATEEN.derate_enable = 0, if DERATEEN.derate_eanble = 1 and the read latency (RL) value */
|
||||
/* needs to change after the frequency change (LPDDR2/3/4 only). */
|
||||
/* 7. Set DBG1.dis_hif=1 so that no new commands will be accepted by the uMCTL2. */
|
||||
reg32setbit(DDRC_DBG1(0), 1);
|
||||
/* 8. Poll DBGCAM.dbg_wr_q_empty and DBGCAM.dbg_rd_q_empty to ensure that write and read data */
|
||||
/* buffers are empty. */
|
||||
do {
|
||||
tmp = 0x06000000 & reg32_read(DDRC_DBGCAM(0));
|
||||
} while (tmp != 0x06000000);
|
||||
/* 9. For DDR4, update MR6 with the new tDLLK value via the Mode Register Write signals */
|
||||
/* (MRCTRL0.mr_x/MRCTRL1.mr_x). */
|
||||
/* 10. Set DFILPCFG0.dfi_lp_en_sr = 0, if DFILPCFG0.dfi_lp_en_sr = 1, and wait until DFISTAT.dfi_lp_ack */
|
||||
/* = 0. */
|
||||
/* 11. If DFI PHY Master interface is active in uMCTL2 (DFIPHYMSTR.phymstr_en == 1'b1) then disable it */
|
||||
/* by programming DFIPHYMSTR.phymstr_en = 1'b0. */
|
||||
/* 12. Wait until STAT.operating_mode[1:0]!=11 indicating that the DWC_ddr_umctl2 controller is not in */
|
||||
/* self-refresh mode. */
|
||||
tmp = 0x3 & (reg32_read((DDRC_STAT(0))));
|
||||
if (tmp == 0x3) {
|
||||
ddr_dbg("C: Error DRAM should not in Self Refresh\n");
|
||||
ddr_dbg("vt_error\n");
|
||||
}
|
||||
/* 13. Assert PWRCTL.selfref_sw for the DWC_ddr_umctl2 core to enter the self-refresh mode. */
|
||||
reg32setbit(DDRC_PWRCTL(0), 5);
|
||||
/* 14. Wait until STAT.operating_mode[1:0]==11 indicating that the DWC_ddr_umctl2 core is in selfrefresh mode. Ensure transition to self-refresh was due to software by checking that STAT.selfref_type[1:0]=2'b10. */
|
||||
do {
|
||||
tmp = 0x3f & (reg32_read((DDRC_STAT(0))));
|
||||
ddr_dbg("C: DRAM in Self Refresh\n");
|
||||
} while (tmp != 0x23);
|
||||
|
||||
sw_pstate(pstate);
|
||||
dram_all_mr_cfg(pstate);
|
||||
|
||||
|
||||
/* 23. Enable HIF commands by setting DBG1.dis_hif=0. */
|
||||
reg32clrbit(DDRC_DBG1(0), 1);
|
||||
/* 24. Reset DERATEEN.derate_enable = 1 if DERATEEN.derate_enable has been set to 0 in step 6. */
|
||||
/* 25. If DFI PHY Master interface was active in uMCTL2 (DFIPHYMSTR.phymstr_en == 1'b1) before the */
|
||||
/* step 11 then enable it back by programming DFIPHYMSTR.phymstr_en = 1'b1. */
|
||||
/* 26. Write 1 to PCTRL_n.port_en. AXI port(s) are no longer blocked from taking transactions (Re-enable */
|
||||
/* traffic on AXI ports). */
|
||||
reg32_write(DDRC_PCTRL_0(0), 0x00000001);
|
||||
/* 27. Write 1 to SBRCTL.scrub_en. Enable SBR if desired, only required if SBR instantiated. */
|
||||
|
||||
|
||||
|
||||
/* set SWCTL.sw_done to enable quasi-dynamic register programming outside reset. */
|
||||
reg32_write(DDRC_SWCTL(0), 0x0001);
|
||||
|
||||
/* wait SWSTAT.sw_done_ack to 1 */
|
||||
do {
|
||||
tmp = 0x1 & reg32_read(DDRC_SWSTAT(0));
|
||||
} while (!tmp);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ddr_init(void)
|
||||
{
|
||||
/* initialize DDR4-2400 (umctl2@800MHz) */
|
||||
ddr4_pub_train();
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* 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.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");
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/ddr.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -123,7 +123,6 @@ static iomux_v3_cfg_t const gpmi_pads[] = {
|
|||
static void setup_gpmi_nand(void)
|
||||
{
|
||||
imx_iomux_v3_setup_multiple_pads(gpmi_pads, ARRAY_SIZE(gpmi_pads));
|
||||
mxs_dma_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -137,6 +136,10 @@ int board_early_init_f(void)
|
|||
|
||||
imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads));
|
||||
|
||||
#ifdef CONFIG_NAND_MXS
|
||||
setup_gpmi_nand(); /* SPL will call the board_early_init_f */
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -405,9 +408,6 @@ int board_init(void)
|
|||
board_qspi_init();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NAND_MXS
|
||||
setup_gpmi_nand(); /* SPL will call the board_early_init_f */
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,14 +19,22 @@
|
|||
#include <asm/mach-imx/mxc_i2c.h>
|
||||
#include <fsl_esdhc.h>
|
||||
#include <mmc.h>
|
||||
#ifdef CONFIG_IMX8M_LPDDR4
|
||||
#include <asm/arch/imx8m_ddr.h>
|
||||
#else
|
||||
#include "ddr/ddr.h"
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
void spl_dram_init(void)
|
||||
{
|
||||
#ifdef CONFIG_IMX8M_LPDDR4
|
||||
/* ddr train */
|
||||
ddr_init(&lpddr4_timing);
|
||||
#else
|
||||
ddr_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
#define I2C_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE)
|
||||
|
|
@ -181,6 +189,11 @@ int power_init_board(void)
|
|||
/* increase VDD_DRAM to 0.9v for 3Ghz DDR */
|
||||
pmic_reg_write(p, BD71837_BUCK5_VOLT, 0x2);
|
||||
|
||||
#ifndef CONFIG_IMX8M_LPDDR4
|
||||
/* increase NVCC_DRAM_1V2 to 1.2v for DDR4 */
|
||||
pmic_reg_write(p, BD71837_BUCK8_VOLT, 0x28);
|
||||
#endif
|
||||
|
||||
/* lock the PMIC regs */
|
||||
pmic_reg_write(p, BD71837_REGLOCK, 0x11);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_IMX8M=y
|
||||
CONFIG_SYS_TEXT_BASE=0x40200000
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x2000
|
||||
CONFIG_USB_TCPC=y
|
||||
CONFIG_TARGET_IMX8MM_DDR4_EVK=y
|
||||
CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/spl_sd.cfg,SPL_TEXT_BASE=0x7E1000"
|
||||
CONFIG_FIT=y
|
||||
CONFIG_SPL_LOAD_FIT=y
|
||||
CONFIG_ARCH_MISC_INIT=y
|
||||
CONFIG_SPL=y
|
||||
CONFIG_SPL_BOARD_INIT=y
|
||||
CONFIG_SPL_MMC_SUPPORT=y
|
||||
CONFIG_HUSH_PARSER=y
|
||||
CONFIG_OF_LIBFDT=y
|
||||
CONFIG_FS_FAT=y
|
||||
CONFIG_CMD_EXT2=y
|
||||
CONFIG_CMD_EXT4=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_CMD_FAT=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="fsl-imx8mm-ddr4-evk"
|
||||
CONFIG_DEFAULT_FDT_FILE="fsl-imx8mm-ddr4-evk.dtb"
|
||||
CONFIG_ENV_IS_IN_MMC=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_CACHE=y
|
||||
CONFIG_CMD_REGULATOR=y
|
||||
CONFIG_CMD_MEMTEST=y
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_FASTBOOT=y
|
||||
CONFIG_USB_FUNCTION_FASTBOOT=y
|
||||
CONFIG_CMD_FASTBOOT=y
|
||||
CONFIG_ANDROID_BOOT_IMAGE=y
|
||||
CONFIG_FSL_FASTBOOT=y
|
||||
CONFIG_FASTBOOT_BUF_ADDR=0x42800000
|
||||
CONFIG_FASTBOOT_BUF_SIZE=0x40000000
|
||||
CONFIG_FASTBOOT_FLASH=y
|
||||
CONFIG_FASTBOOT_FLASH_MMC_DEV=0
|
||||
|
||||
CONFIG_DM_GPIO=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_SYS_I2C_MXC=y
|
||||
CONFIG_DM_MMC=y
|
||||
# CONFIG_DM_PMIC=y
|
||||
CONFIG_EFI_PARTITION=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_PINCTRL_IMX8M=y
|
||||
CONFIG_DM_REGULATOR=y
|
||||
CONFIG_DM_REGULATOR_FIXED=y
|
||||
CONFIG_DM_REGULATOR_GPIO=y
|
||||
CONFIG_NXP_TMU=y
|
||||
CONFIG_DM_THERMAL=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_DM_USB=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
|
||||
CONFIG_SPL_USB_HOST_SUPPORT=y
|
||||
CONFIG_SPL_USB_GADGET_SUPPORT=y
|
||||
CONFIG_SPL_USB_SDP_SUPPORT=y
|
||||
CONFIG_SDP_LOADADDR=0x40400000
|
||||
CONFIG_USB_GADGET_MANUFACTURER="FSL"
|
||||
CONFIG_USB_GADGET_VENDOR_NUM=0x0525
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
|
||||
|
||||
CONFIG_VIDEO=y
|
||||
CONFIG_IMX_SEC_MIPI_DSI=y
|
||||
|
||||
CONFIG_CMD_NAND=y
|
||||
CONFIG_CMD_UBI=y
|
||||
|
|
@ -19,6 +19,7 @@ CONFIG_CMD_EXT4=y
|
|||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_CMD_FAT=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="fsl-imx8mm-evk"
|
||||
CONFIG_DEFAULT_FDT_FILE="fsl-imx8mm-evk.dtb"
|
||||
CONFIG_ENV_IS_IN_MMC=y
|
||||
CONFIG_CMD_SF=y
|
||||
CONFIG_CMD_I2C=y
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@
|
|||
"fdt_addr=0x43000000\0" \
|
||||
"fdt_high=0xffffffffffffffff\0" \
|
||||
"boot_fdt=try\0" \
|
||||
"fdt_file=fsl-imx8mm-evk.dtb\0" \
|
||||
"fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \
|
||||
"initrd_addr=0x43800000\0" \
|
||||
"initrd_high=0xffffffffffffffff\0" \
|
||||
"mmcdev="__stringify(CONFIG_SYS_MMC_ENV_DEV)"\0" \
|
||||
|
|
@ -244,7 +244,11 @@
|
|||
#define CONFIG_FSL_ESDHC
|
||||
#define CONFIG_FSL_USDHC
|
||||
|
||||
#ifdef CONFIG_TARGET_IMX8MM_DDR4_EVK
|
||||
#define CONFIG_SYS_FSL_USDHC_NUM 1
|
||||
#else
|
||||
#define CONFIG_SYS_FSL_USDHC_NUM 2
|
||||
#endif
|
||||
#define CONFIG_SYS_FSL_ESDHC_ADDR 0
|
||||
|
||||
#define CONFIG_SUPPORT_EMMC_BOOT /* eMMC specific */
|
||||
|
|
@ -279,7 +283,8 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NAND_MXS
|
||||
#ifdef CONFIG_CMD_NAND
|
||||
#define CONFIG_NAND_MXS
|
||||
#define CONFIG_CMD_NAND_TRIMFFS
|
||||
|
||||
/* NAND stuff */
|
||||
|
|
@ -292,7 +297,13 @@
|
|||
#define CONFIG_APBH_DMA
|
||||
#define CONFIG_APBH_DMA_BURST
|
||||
#define CONFIG_APBH_DMA_BURST8
|
||||
|
||||
#ifdef CONFIG_CMD_UBI
|
||||
#define CONFIG_MTD_PARTITIONS
|
||||
#define CONFIG_MTD_DEVICE
|
||||
#endif
|
||||
#endif /* CONFIG_CMD_NAND */
|
||||
|
||||
|
||||
#define CONFIG_MXC_GPIO
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue