summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2020-02-14 11:53:38 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2020-02-19 08:30:32 +0100
commit0266042714b2e0a17e397fe5d8a29a4487785df4 (patch)
tree3ec6d49a15181e40d14ef2349afdbd84438acd2d
parent5973ed7e2196aac7df53f81033cd46b51acba09c (diff)
downloadbarebox-0266042714b2e0a17e397fe5d8a29a4487785df4.tar.gz
ARM: i.MX8M: Add DDR controller support
This adds the DDR driver for the i.MX8MQ/i.MX8MM. It's taken from U-Boot v2020.04-rc1 with slight modifications for barebox The i.MX8MQ boards in the tree currently use the output of an earlier version of the NXP i.MX8M DDR Tool which doesn't use a controller driver but instead does most stuff in board code. It seems this can coexist with the new driver, only a few helper functions that previously lived in arch/arm/mach-imx/imx8-ddrc.c are now provided by the new driver. Tested on an i.MX8MM EVK Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--arch/arm/boards/nxp-imx8mq-evk/ddr.h9
-rw-r--r--arch/arm/boards/nxp-imx8mq-evk/lowlevel.c2
-rw-r--r--arch/arm/boards/phytec-som-imx8mq/ddr.h7
-rw-r--r--arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c1
-rw-r--r--arch/arm/boards/phytec-som-imx8mq/lowlevel.c2
-rw-r--r--arch/arm/boards/zii-imx8mq-dev/ddr.h9
-rw-r--r--arch/arm/boards/zii-imx8mq-dev/lowlevel.c2
-rw-r--r--arch/arm/mach-imx/Kconfig1
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/imx8-ddrc.c91
-rw-r--r--arch/arm/mach-imx/include/mach/imx8-ddrc.h66
-rw-r--r--drivers/ddr/Kconfig1
-rw-r--r--drivers/ddr/Makefile1
-rw-r--r--drivers/ddr/imx8m/Kconfig7
-rw-r--r--drivers/ddr/imx8m/Makefile7
-rw-r--r--drivers/ddr/imx8m/ddr_init.c211
-rw-r--r--drivers/ddr/imx8m/ddrphy_csr.c732
-rw-r--r--drivers/ddr/imx8m/ddrphy_train.c112
-rw-r--r--drivers/ddr/imx8m/ddrphy_utils.c306
-rw-r--r--drivers/ddr/imx8m/helper.c86
-rw-r--r--include/soc/imx8m/ddr.h407
-rw-r--r--include/soc/imx8m/lpddr4_define.h97
22 files changed, 1975 insertions, 184 deletions
diff --git a/arch/arm/boards/nxp-imx8mq-evk/ddr.h b/arch/arm/boards/nxp-imx8mq-evk/ddr.h
index 65115db..fd09ad6 100644
--- a/arch/arm/boards/nxp-imx8mq-evk/ddr.h
+++ b/arch/arm/boards/nxp-imx8mq-evk/ddr.h
@@ -8,7 +8,7 @@
*/
#include <common.h>
#include <io.h>
-#include <mach/imx8-ddrc.h>
+#include <soc/imx8m/ddr.h>
/*
* Code generated by i.MX8 M DDR Tool doesn't have any prefixes in the
@@ -20,10 +20,3 @@
void nxp_imx8mq_evk_ddr_init(void);
void nxp_imx8mq_evk_ddr_cfg_phy(void);
-
-#define FW_1D_IMAGE lpddr4_pmu_train_1d_imem_bin, \
- lpddr4_pmu_train_1d_dmem_bin
-#define FW_2D_IMAGE lpddr4_pmu_train_2d_imem_bin, \
- lpddr4_pmu_train_2d_dmem_bin
-
-
diff --git a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c
index bf3d43b..39358af 100644
--- a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c
+++ b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c
@@ -8,7 +8,7 @@
#include <asm/barebox-arm.h>
#include <mach/imx8m-ccm-regs.h>
#include <mach/iomux-mx8mq.h>
-#include <mach/imx8-ddrc.h>
+#include <soc/imx8m/ddr.h>
#include <mach/xload.h>
#include <io.h>
#include <debug_ll.h>
diff --git a/arch/arm/boards/phytec-som-imx8mq/ddr.h b/arch/arm/boards/phytec-som-imx8mq/ddr.h
index 18ae6e9..e125fea 100644
--- a/arch/arm/boards/phytec-som-imx8mq/ddr.h
+++ b/arch/arm/boards/phytec-som-imx8mq/ddr.h
@@ -7,7 +7,7 @@
*/
#include <common.h>
#include <io.h>
-#include <mach/imx8-ddrc.h>
+#include <soc/imx8m/ddr.h>
/*
* Code generated by i.MX8 M DDR Tool doesn't have any prefixes in the
@@ -19,8 +19,3 @@
void phytec_imx8mq_phycore_ddr_init(void);
void phytec_imx8mq_phycore_ddr_cfg_phy(void);
-
-#define FW_1D_IMAGE lpddr4_pmu_train_1d_imem_bin, \
- lpddr4_pmu_train_1d_dmem_bin
-#define FW_2D_IMAGE lpddr4_pmu_train_2d_imem_bin, \
- lpddr4_pmu_train_2d_dmem_bin
diff --git a/arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c b/arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c
index 56af647..cc00527 100644
--- a/arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c
+++ b/arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c
@@ -9,7 +9,6 @@
#include "ddr.h"
-extern void wait_ddrphy_training_complete(void);
void ddr_cfg_phy(void) {
unsigned int tmp, tmp_t;
diff --git a/arch/arm/boards/phytec-som-imx8mq/lowlevel.c b/arch/arm/boards/phytec-som-imx8mq/lowlevel.c
index f460901..f5b9b6c 100644
--- a/arch/arm/boards/phytec-som-imx8mq/lowlevel.c
+++ b/arch/arm/boards/phytec-som-imx8mq/lowlevel.c
@@ -11,7 +11,7 @@
#include <asm/barebox-arm.h>
#include <mach/imx8m-ccm-regs.h>
#include <mach/iomux-mx8mq.h>
-#include <mach/imx8-ddrc.h>
+#include <soc/imx8m/ddr.h>
#include <mach/xload.h>
#include <io.h>
#include <debug_ll.h>
diff --git a/arch/arm/boards/zii-imx8mq-dev/ddr.h b/arch/arm/boards/zii-imx8mq-dev/ddr.h
index 1293ad3..a395211 100644
--- a/arch/arm/boards/zii-imx8mq-dev/ddr.h
+++ b/arch/arm/boards/zii-imx8mq-dev/ddr.h
@@ -8,7 +8,7 @@
*/
#include <common.h>
#include <io.h>
-#include <mach/imx8-ddrc.h>
+#include <soc/imx8m/ddr.h>
/*
* Code generated by i.MX8 M DDR Tool doesn't have any prefixes in the
@@ -20,10 +20,3 @@
void zii_imx8mq_rdu3_ddr_init(void);
void zii_imx8mq_rdu3_ddr_cfg_phy(void);
-
-#define FW_1D_IMAGE lpddr4_pmu_train_1d_imem_bin, \
- lpddr4_pmu_train_1d_dmem_bin
-#define FW_2D_IMAGE lpddr4_pmu_train_2d_imem_bin, \
- lpddr4_pmu_train_2d_dmem_bin
-
-
diff --git a/arch/arm/boards/zii-imx8mq-dev/lowlevel.c b/arch/arm/boards/zii-imx8mq-dev/lowlevel.c
index 2646f5f..6400833 100644
--- a/arch/arm/boards/zii-imx8mq-dev/lowlevel.c
+++ b/arch/arm/boards/zii-imx8mq-dev/lowlevel.c
@@ -12,7 +12,7 @@
#include <asm/barebox-arm.h>
#include <mach/imx8m-ccm-regs.h>
#include <mach/iomux-mx8mq.h>
-#include <mach/imx8-ddrc.h>
+#include <soc/imx8m/ddr.h>
#include <mach/xload.h>
#include <io.h>
#include <debug_ll.h>
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index d717d83..7b79d80 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -183,6 +183,7 @@ config ARCH_IMX8M
select COMMON_CLK_OF_PROVIDER
select ARCH_HAS_FEC_IMX
select HW_HAS_PCI
+ select IMX8M_DRAM
select PBL_VERIFY_PIGGY if HABV4
config ARCH_IMX8MQ
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 862dc78..105785b 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -16,7 +16,7 @@ lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o
obj-$(CONFIG_ARCH_IMX7) += imx7.o
obj-$(CONFIG_ARCH_VF610) += vf610.o
obj-$(CONFIG_ARCH_IMX8M) += imx8m.o
-lwl-$(CONFIG_ARCH_IMX8MQ) += imx8-ddrc.o atf.o
+lwl-$(CONFIG_ARCH_IMX8MQ) += atf.o
obj-$(CONFIG_IMX_IIM) += iim.o
obj-$(CONFIG_NAND_IMX) += nand.o
lwl-$(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND) += external-nand-boot.o
diff --git a/arch/arm/mach-imx/imx8-ddrc.c b/arch/arm/mach-imx/imx8-ddrc.c
deleted file mode 100644
index 8bb2672..0000000
--- a/arch/arm/mach-imx/imx8-ddrc.c
+++ /dev/null
@@ -1,91 +0,0 @@
-#include <common.h>
-#include <linux/iopoll.h>
-#include <mach/imx8-ddrc.h>
-#include <debug_ll.h>
-
-void ddrc_phy_load_firmware(void __iomem *phy,
- enum ddrc_phy_firmware_offset offset,
- const u16 *blob, size_t size)
-{
- while (size) {
- writew(*blob++, phy + DDRC_PHY_REG(offset));
- offset++;
- size -= sizeof(*blob);
- }
-}
-
-enum pmc_constants {
- PMC_MESSAGE_ID,
- PMC_MESSAGE_STREAM,
-
- PMC_TRAIN_SUCCESS = 0x07,
- PMC_TRAIN_STREAM_START = 0x08,
- PMC_TRAIN_FAIL = 0xff,
-};
-
-static u32 ddrc_phy_get_message(void __iomem *phy, int type)
-{
- u32 r, message;
-
- /*
- * When BIT0 set to 0, the PMU has a message for the user
- * Wait for it indefinitely.
- */
- readl_poll_timeout(phy + DDRC_PHY_REG(0xd0004),
- r, !(r & BIT(0)), 0);
-
- switch (type) {
- case PMC_MESSAGE_ID:
- /*
- * Get the major message ID
- */
- message = readl(phy + DDRC_PHY_REG(0xd0032));
- break;
- case PMC_MESSAGE_STREAM:
- message = readl(phy + DDRC_PHY_REG(0xd0034));
- message <<= 16;
- message |= readl(phy + DDRC_PHY_REG(0xd0032));
- break;
- }
-
- /*
- * By setting this register to 0, the user acknowledges the
- * receipt of the message.
- */
- writel(0x00000000, phy + DDRC_PHY_REG(0xd0031));
- /*
- * When BIT0 set to 0, the PMU has a message for the user
- */
- readl_poll_timeout(phy + DDRC_PHY_REG(0xd0004),
- r, r & BIT(0), 0);
-
- writel(0x00000001, phy + DDRC_PHY_REG(0xd0031));
-
- return message;
-}
-
-static void ddrc_phy_fetch_streaming_message(void __iomem *phy)
-{
- const u16 index = ddrc_phy_get_message(phy, PMC_MESSAGE_STREAM);
- u16 i;
-
- for (i = 0; i < index; i++)
- ddrc_phy_get_message(phy, PMC_MESSAGE_STREAM);
-}
-
-void ddrc_phy_wait_training_complete(void __iomem *phy)
-{
- for (;;) {
- const u32 m = ddrc_phy_get_message(phy, PMC_MESSAGE_ID);
-
- switch (m) {
- case PMC_TRAIN_STREAM_START:
- ddrc_phy_fetch_streaming_message(phy);
- break;
- case PMC_TRAIN_SUCCESS:
- return;
- case PMC_TRAIN_FAIL:
- hang();
- }
- }
-}
diff --git a/arch/arm/mach-imx/include/mach/imx8-ddrc.h b/arch/arm/mach-imx/include/mach/imx8-ddrc.h
deleted file mode 100644
index d49e29f..0000000
--- a/arch/arm/mach-imx/include/mach/imx8-ddrc.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef __IMX8_DDRC_H__
-#define __IMX8_DDRC_H__
-
-#include <mach/imx8mq-regs.h>
-#include <io.h>
-#include <firmware.h>
-#include <linux/compiler.h>
-
-enum ddrc_phy_firmware_offset {
- DDRC_PHY_IMEM = 0x00050000U,
- DDRC_PHY_DMEM = 0x00054000U,
-};
-
-void ddrc_phy_load_firmware(void __iomem *,
- enum ddrc_phy_firmware_offset,
- const u16 *, size_t);
-
-#define DDRC_PHY_REG(x) ((x) * 4)
-
-void ddrc_phy_wait_training_complete(void __iomem *phy);
-
-
-/*
- * i.MX8M DDR Tool compatibility layer
- */
-
-#define reg32_write(a, v) writel(v, a)
-#define reg32_read(a) readl(a)
-
-static inline void wait_ddrphy_training_complete(void)
-{
- ddrc_phy_wait_training_complete(IOMEM(MX8MQ_DDRC_PHY_BASE_ADDR));
-}
-
-#define __ddr_load_train_code(imem, dmem) \
- do { \
- const u16 *__mem; \
- size_t __size; \
- \
- get_builtin_firmware(imem, &__mem, &__size); \
- ddrc_phy_load_firmware(IOMEM(MX8MQ_DDRC_PHY_BASE_ADDR), \
- DDRC_PHY_IMEM, __mem, __size); \
- \
- get_builtin_firmware(dmem, &__mem, &__size); \
- ddrc_phy_load_firmware(IOMEM(MX8MQ_DDRC_PHY_BASE_ADDR), \
- DDRC_PHY_DMEM, __mem, __size); \
- } while (0)
-
-#define ddr_load_train_code(imem_dmem) __ddr_load_train_code(imem_dmem)
-
-#define DDRC_IPS_BASE_ADDR(X) (0x3d400000 + (X * 0x2000000))
-
-#define DDRC_STAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x04)
-#define DDRC_MRSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x18)
-#define DDRC_PWRCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x30)
-#define DDRC_RFSHCTL3(X) (DDRC_IPS_BASE_ADDR(X) + 0x60)
-#define DDRC_CRCPARSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0xcc)
-#define DDRC_DFIMISC(X) (DDRC_IPS_BASE_ADDR(X) + 0x1b0)
-#define DDRC_DFISTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x1bc)
-#define DDRC_SWCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x320)
-#define DDRC_SWSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x324)
-#define DDRC_PCTRL_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x490)
-
-#define IP2APB_DDRPHY_IPS_BASE_ADDR(X) (0x3c000000 + (X * 0x2000000))
-
-#endif \ No newline at end of file
diff --git a/drivers/ddr/Kconfig b/drivers/ddr/Kconfig
index 4ea7159..d92c272 100644
--- a/drivers/ddr/Kconfig
+++ b/drivers/ddr/Kconfig
@@ -1 +1,2 @@
source "drivers/ddr/fsl/Kconfig"
+source "drivers/ddr/imx8m/Kconfig"
diff --git a/drivers/ddr/Makefile b/drivers/ddr/Makefile
index faf2f9e..7e33182 100644
--- a/drivers/ddr/Makefile
+++ b/drivers/ddr/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_DDR_FSL) += fsl/
+obj-$(CONFIG_IMX8M_DRAM) += imx8m/
diff --git a/drivers/ddr/imx8m/Kconfig b/drivers/ddr/imx8m/Kconfig
new file mode 100644
index 0000000..e8bce8c
--- /dev/null
+++ b/drivers/ddr/imx8m/Kconfig
@@ -0,0 +1,7 @@
+menu "i.MX8M DDR controllers"
+ depends on ARCH_IMX8MQ || ARCH_IMX8MM
+
+config IMX8M_DRAM
+ bool "imx8m dram controller support"
+
+endmenu
diff --git a/drivers/ddr/imx8m/Makefile b/drivers/ddr/imx8m/Makefile
new file mode 100644
index 0000000..2be3139
--- /dev/null
+++ b/drivers/ddr/imx8m/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright 2018 NXP
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+pbl-$(CONFIG_IMX8M_DRAM) += helper.o ddrphy_utils.o ddrphy_train.o ddrphy_csr.o ddr_init.o
diff --git a/drivers/ddr/imx8m/ddr_init.c b/drivers/ddr/imx8m/ddr_init.c
new file mode 100644
index 0000000..374601b
--- /dev/null
+++ b/drivers/ddr/imx8m/ddr_init.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018-2019 NXP
+ */
+#define DEBUG
+#include <common.h>
+#include <errno.h>
+#include <io.h>
+#include <soc/imx8m/ddr.h>
+#include <mach/generic.h>
+#include <mach/imx8m-regs.h>
+#include <mach/imx8m-ccm-regs.h>
+
+#define SRC_DDRC_RCR_ADDR MX8MQ_SRC_DDRC_RCR_ADDR
+
+static void ddr_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num)
+{
+ int i = 0;
+
+ for (i = 0; i < num; i++) {
+ reg32_write((unsigned long)ddrc_cfg->reg, ddrc_cfg->val);
+ ddrc_cfg++;
+ }
+}
+
+static int imx8m_ddr_init(unsigned long src_ddrc_rcr,
+ struct dram_timing_info *dram_timing)
+{
+ unsigned int tmp, initial_drate, target_freq;
+ int ret;
+
+ debug("DDRINFO: start DRAM init\n");
+
+ debug("DDRINFO: cfg clk\n");
+
+ /* disable iso */
+ reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */
+ reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */
+
+ initial_drate = dram_timing->fsp_msg[0].drate;
+ /* default to the frequency point 0 clock */
+ ddrphy_init_set_dfi_clk(initial_drate);
+
+ /* D-aasert the presetn */
+ reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
+
+ /* Step2: Program the dwc_ddr_umctl2 registers */
+ debug("DDRINFO: ddrc config start\n");
+ ddr_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num);
+ debug("DDRINFO: ddrc config done\n");
+
+ /* Step3: De-assert reset signal(core_ddrc_rstn & aresetn_n) */
+ reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004);
+ reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000);
+
+ /*
+ * Step4: Disable auto-refreshes, self-refresh, powerdown, and
+ * assertion of dfi_dram_clk_disable by setting RFSHCTL3.dis_auto_refresh = 1,
+ * PWRCTL.powerdown_en = 0, and PWRCTL.selfref_en = 0,
+ * PWRCTL.en_dfi_dram_clk_disable = 0
+ */
+ reg32_write(DDRC_DBG1(0), 0x00000000);
+ reg32_write(DDRC_RFSHCTL3(0), 0x0000001);
+ reg32_write(DDRC_PWRCTL(0), 0xa0);
+
+ /* if ddr type is LPDDR4, do it */
+ tmp = reg32_read(DDRC_MSTR(0));
+ if (tmp & (0x1 << 5))
+ reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */
+
+ /* determine the initial boot frequency */
+ target_freq = reg32_read(DDRC_MSTR2(0)) & 0x3;
+ target_freq = (tmp & (0x1 << 29)) ? target_freq : 0x0;
+
+ /* Step5: Set SWCT.sw_done to 0 */
+ reg32_write(DDRC_SWCTL(0), 0x00000000);
+
+ /* Set the default boot frequency point */
+ clrsetbits_le32(DDRC_DFIMISC(0), (0x1f << 8), target_freq << 8);
+ /* Step6: Set DFIMISC.dfi_init_complete_en to 0 */
+ clrbits_le32(DDRC_DFIMISC(0), 0x1);
+
+ /* Step7: Set SWCTL.sw_done to 1; need to polling SWSTAT.sw_done_ack */
+ reg32_write(DDRC_SWCTL(0), 0x00000001);
+ do {
+ tmp = reg32_read(DDRC_SWSTAT(0));
+ } while ((tmp & 0x1) == 0x0);
+
+ /*
+ * Step8 ~ Step13: Start PHY initialization and training by
+ * accessing relevant PUB registers
+ */
+ debug("DDRINFO:ddrphy config start\n");
+
+ ret = ddr_cfg_phy(dram_timing);
+ if (ret)
+ return ret;
+
+ debug("DDRINFO: ddrphy config done\n");
+
+ /*
+ * step14 CalBusy.0 =1, indicates the calibrator is actively
+ * calibrating. Wait Calibrating done.
+ */
+ do {
+ tmp = reg32_read(DDRPHY_CalBusy(0));
+ } while ((tmp & 0x1));
+
+ debug("DDRINFO:ddrphy calibration done\n");
+
+ /* Step15: Set SWCTL.sw_done to 0 */
+ reg32_write(DDRC_SWCTL(0), 0x00000000);
+
+ /* Step16: Set DFIMISC.dfi_init_start to 1 */
+ setbits_le32(DDRC_DFIMISC(0), (0x1 << 5));
+
+ /* Step17: Set SWCTL.sw_done to 1; need to polling SWSTAT.sw_done_ack */
+ reg32_write(DDRC_SWCTL(0), 0x00000001);
+ do {
+ tmp = reg32_read(DDRC_SWSTAT(0));
+ } while ((tmp & 0x1) == 0x0);
+
+ /* Step18: Polling DFISTAT.dfi_init_complete = 1 */
+ do {
+ tmp = reg32_read(DDRC_DFISTAT(0));
+ } while ((tmp & 0x1) == 0x0);
+
+ /* Step19: Set SWCTL.sw_done to 0 */
+ reg32_write(DDRC_SWCTL(0), 0x00000000);
+
+ /* Step20: Set DFIMISC.dfi_init_start to 0 */
+ clrbits_le32(DDRC_DFIMISC(0), (0x1 << 5));
+
+ /* Step21: optional */
+
+ /* Step22: Set DFIMISC.dfi_init_complete_en to 1 */
+ setbits_le32(DDRC_DFIMISC(0), 0x1);
+
+ /* Step23: Set PWRCTL.selfref_sw to 0 */
+ clrbits_le32(DDRC_PWRCTL(0), (0x1 << 5));
+
+ /* Step24: Set SWCTL.sw_done to 1; need polling SWSTAT.sw_done_ack */
+ reg32_write(DDRC_SWCTL(0), 0x00000001);
+ do {
+ tmp = reg32_read(DDRC_SWSTAT(0));
+ } while ((tmp & 0x1) == 0x0);
+
+ /* Step25: Wait for dwc_ddr_umctl2 to move to normal operating mode by monitoring
+ * STAT.operating_mode signal */
+ do {
+ tmp = reg32_read(DDRC_STAT(0));
+ } while ((tmp & 0x3) != 0x1);
+
+ /* Step26: Set back register in Step4 to the original values if desired */
+ reg32_write(DDRC_RFSHCTL3(0), 0x0000000);
+ /* enable selfref_en by default */
+ setbits_le32(DDRC_PWRCTL(0), 0x1 << 3);
+
+ /* enable port 0 */
+ reg32_write(DDRC_PCTRL_0(0), 0x00000001);
+ debug("DDRINFO: ddrmix config done\n");
+
+ return 0;
+}
+
+/*
+ * We store the timing parameters here. the TF-A will pick these up.
+ * Note that the timing used we leave the driver with is a PLL bypass 25MHz
+ * mode. So if your board runs horribly slow you'll likely have to provide a
+ * TF-A binary.
+ */
+#define IMX8M_SAVED_DRAM_TIMING_BASE 0x180000
+
+int imx8mm_ddr_init(struct dram_timing_info *dram_timing)
+{
+ unsigned long src_ddrc_rcr = MX8M_SRC_DDRC_RCR_ADDR;
+ int ret;
+
+ /* Step1: Follow the power up procedure */
+ reg32_write(src_ddrc_rcr, 0x8f00001f);
+ reg32_write(src_ddrc_rcr, 0x8f00000f);
+
+ ret = imx8m_ddr_init(src_ddrc_rcr, dram_timing);
+ if (ret)
+ return ret;
+
+ /* save the dram timing config into memory */
+ dram_config_save(dram_timing, IMX8M_SAVED_DRAM_TIMING_BASE);
+
+ return 0;
+}
+
+int imx8mq_ddr_init(struct dram_timing_info *dram_timing)
+{
+ unsigned long src_ddrc_rcr = MX8MQ_SRC_DDRC_RCR_ADDR;
+ int ret;
+
+ /* Step1: Follow the power up procedure */
+ reg32_write(src_ddrc_rcr + 0x04, 0x8f00000f);
+ reg32_write(src_ddrc_rcr, 0x8f00000f);
+ reg32_write(src_ddrc_rcr + 0x04, 0x8f000000);
+
+ ret = imx8m_ddr_init(src_ddrc_rcr, dram_timing);
+ if (ret)
+ return ret;
+
+ /* save the dram timing config into memory */
+ dram_config_save(dram_timing, IMX8M_SAVED_DRAM_TIMING_BASE);
+
+ return 0;
+}
diff --git a/drivers/ddr/imx8m/ddrphy_csr.c b/drivers/ddr/imx8m/ddrphy_csr.c
new file mode 100644
index 0000000..98ac5db
--- /dev/null
+++ b/drivers/ddr/imx8m/ddrphy_csr.c
@@ -0,0 +1,732 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <linux/kernel.h>
+#include <soc/imx8m/ddr.h>
+
+/* ddr phy trained csr */
+struct dram_cfg_param ddrphy_trained_csr[] = {
+ { 0x200b2, 0x0 },
+ { 0x1200b2, 0x0 },
+ { 0x2200b2, 0x0 },
+ { 0x200cb, 0x0 },
+ { 0x10043, 0x0 },
+ { 0x110043, 0x0 },
+ { 0x210043, 0x0 },
+ { 0x10143, 0x0 },
+ { 0x110143, 0x0 },
+ { 0x210143, 0x0 },
+ { 0x11043, 0x0 },
+ { 0x111043, 0x0 },
+ { 0x211043, 0x0 },
+ { 0x11143, 0x0 },
+ { 0x111143, 0x0 },
+ { 0x211143, 0x0 },
+ { 0x12043, 0x0 },
+ { 0x112043, 0x0 },
+ { 0x212043, 0x0 },
+ { 0x12143, 0x0 },
+ { 0x112143, 0x0 },
+ { 0x212143, 0x0 },
+ { 0x13043, 0x0 },
+ { 0x113043, 0x0 },
+ { 0x213043, 0x0 },
+ { 0x13143, 0x0 },
+ { 0x113143, 0x0 },
+ { 0x213143, 0x0 },
+ { 0x80, 0x0 },
+ { 0x100080, 0x0 },
+ { 0x200080, 0x0 },
+ { 0x1080, 0x0 },
+ { 0x101080, 0x0 },
+ { 0x201080, 0x0 },
+ { 0x2080, 0x0 },
+ { 0x102080, 0x0 },
+ { 0x202080, 0x0 },
+ { 0x3080, 0x0 },
+ { 0x103080, 0x0 },
+ { 0x203080, 0x0 },
+ { 0x4080, 0x0 },
+ { 0x104080, 0x0 },
+ { 0x204080, 0x0 },
+ { 0x5080, 0x0 },
+ { 0x105080, 0x0 },
+ { 0x205080, 0x0 },
+ { 0x6080, 0x0 },
+ { 0x106080, 0x0 },
+ { 0x206080, 0x0 },
+ { 0x7080, 0x0 },
+ { 0x107080, 0x0 },
+ { 0x207080, 0x0 },
+ { 0x8080, 0x0 },
+ { 0x108080, 0x0 },
+ { 0x208080, 0x0 },
+ { 0x9080, 0x0 },
+ { 0x109080, 0x0 },
+ { 0x209080, 0x0 },
+ { 0x10080, 0x0 },
+ { 0x110080, 0x0 },
+ { 0x210080, 0x0 },
+ { 0x10180, 0x0 },
+ { 0x110180, 0x0 },
+ { 0x210180, 0x0 },
+ { 0x11080, 0x0 },
+ { 0x111080, 0x0 },
+ { 0x211080, 0x0 },
+ { 0x11180, 0x0 },
+ { 0x111180, 0x0 },
+ { 0x211180, 0x0 },
+ { 0x12080, 0x0 },
+ { 0x112080, 0x0 },
+ { 0x212080, 0x0 },
+ { 0x12180, 0x0 },
+ { 0x112180, 0x0 },
+ { 0x212180, 0x0 },
+ { 0x13080, 0x0 },
+ { 0x113080, 0x0 },
+ { 0x213080, 0x0 },
+ { 0x13180, 0x0 },
+ { 0x113180, 0x0 },
+ { 0x213180, 0x0 },
+ { 0x10081, 0x0 },
+ { 0x110081, 0x0 },
+ { 0x210081, 0x0 },
+ { 0x10181, 0x0 },
+ { 0x110181, 0x0 },
+ { 0x210181, 0x0 },
+ { 0x11081, 0x0 },
+ { 0x111081, 0x0 },
+ { 0x211081, 0x0 },
+ { 0x11181, 0x0 },
+ { 0x111181, 0x0 },
+ { 0x211181, 0x0 },
+ { 0x12081, 0x0 },
+ { 0x112081, 0x0 },
+ { 0x212081, 0x0 },
+ { 0x12181, 0x0 },
+ { 0x112181, 0x0 },
+ { 0x212181, 0x0 },
+ { 0x13081, 0x0 },
+ { 0x113081, 0x0 },
+ { 0x213081, 0x0 },
+ { 0x13181, 0x0 },
+ { 0x113181, 0x0 },
+ { 0x213181, 0x0 },
+ { 0x100d0, 0x0 },
+ { 0x1100d0, 0x0 },
+ { 0x2100d0, 0x0 },
+ { 0x101d0, 0x0 },
+ { 0x1101d0, 0x0 },
+ { 0x2101d0, 0x0 },
+ { 0x110d0, 0x0 },
+ { 0x1110d0, 0x0 },
+ { 0x2110d0, 0x0 },
+ { 0x111d0, 0x0 },
+ { 0x1111d0, 0x0 },
+ { 0x2111d0, 0x0 },
+ { 0x120d0, 0x0 },
+ { 0x1120d0, 0x0 },
+ { 0x2120d0, 0x0 },
+ { 0x121d0, 0x0 },
+ { 0x1121d0, 0x0 },
+ { 0x2121d0, 0x0 },
+ { 0x130d0, 0x0 },
+ { 0x1130d0, 0x0 },
+ { 0x2130d0, 0x0 },
+ { 0x131d0, 0x0 },
+ { 0x1131d0, 0x0 },
+ { 0x2131d0, 0x0 },
+ { 0x100d1, 0x0 },
+ { 0x1100d1, 0x0 },
+ { 0x2100d1, 0x0 },
+ { 0x101d1, 0x0 },
+ { 0x1101d1, 0x0 },
+ { 0x2101d1, 0x0 },
+ { 0x110d1, 0x0 },
+ { 0x1110d1, 0x0 },
+ { 0x2110d1, 0x0 },
+ { 0x111d1, 0x0 },
+ { 0x1111d1, 0x0 },
+ { 0x2111d1, 0x0 },
+ { 0x120d1, 0x0 },
+ { 0x1120d1, 0x0 },
+ { 0x2120d1, 0x0 },
+ { 0x121d1, 0x0 },
+ { 0x1121d1, 0x0 },
+ { 0x2121d1, 0x0 },
+ { 0x130d1, 0x0 },
+ { 0x1130d1, 0x0 },
+ { 0x2130d1, 0x0 },
+ { 0x131d1, 0x0 },
+ { 0x1131d1, 0x0 },
+ { 0x2131d1, 0x0 },
+ { 0x10068, 0x0 },
+ { 0x10168, 0x0 },
+ { 0x10268, 0x0 },
+ { 0x10368, 0x0 },
+ { 0x10468, 0x0 },
+ { 0x10568, 0x0 },
+ { 0x10668, 0x0 },
+ { 0x10768, 0x0 },
+ { 0x10868, 0x0 },
+ { 0x11068, 0x0 },
+ { 0x11168, 0x0 },
+ { 0x11268, 0x0 },
+ { 0x11368, 0x0 },
+ { 0x11468, 0x0 },
+ { 0x11568, 0x0 },
+ { 0x11668, 0x0 },
+ { 0x11768, 0x0 },
+ { 0x11868, 0x0 },
+ { 0x12068, 0x0 },
+ { 0x12168, 0x0 },
+ { 0x12268, 0x0 },
+ { 0x12368, 0x0 },
+ { 0x12468, 0x0 },
+ { 0x12568, 0x0 },
+ { 0x12668, 0x0 },
+ { 0x12768, 0x0 },
+ { 0x12868, 0x0 },
+ { 0x13068, 0x0 },
+ { 0x13168, 0x0 },
+ { 0x13268, 0x0 },
+ { 0x13368, 0x0 },
+ { 0x13468, 0x0 },
+ { 0x13568, 0x0 },
+ { 0x13668, 0x0 },
+ { 0x13768, 0x0 },
+ { 0x13868, 0x0 },
+ { 0x10069, 0x0 },
+ { 0x10169, 0x0 },
+ { 0x10269, 0x0 },
+ { 0x10369, 0x0 },
+ { 0x10469, 0x0 },
+ { 0x10569, 0x0 },
+ { 0x10669, 0x0 },
+ { 0x10769, 0x0 },
+ { 0x10869, 0x0 },
+ { 0x11069, 0x0 },
+ { 0x11169, 0x0 },
+ { 0x11269, 0x0 },
+ { 0x11369, 0x0 },
+ { 0x11469, 0x0 },
+ { 0x11569, 0x0 },
+ { 0x11669, 0x0 },
+ { 0x11769, 0x0 },
+ { 0x11869, 0x0 },
+ { 0x12069, 0x0 },
+ { 0x12169, 0x0 },
+ { 0x12269, 0x0 },
+ { 0x12369, 0x0 },
+ { 0x12469, 0x0 },
+ { 0x12569, 0x0 },
+ { 0x12669, 0x0 },
+ { 0x12769, 0x0 },
+ { 0x12869, 0x0 },
+ { 0x13069, 0x0 },
+ { 0x13169, 0x0 },
+ { 0x13269, 0x0 },
+ { 0x13369, 0x0 },
+ { 0x13469, 0x0 },
+ { 0x13569, 0x0 },
+ { 0x13669, 0x0 },
+ { 0x13769, 0x0 },
+ { 0x13869, 0x0 },
+ { 0x1008c, 0x0 },
+ { 0x11008c, 0x0 },
+ { 0x21008c, 0x0 },
+ { 0x1018c, 0x0 },
+ { 0x11018c, 0x0 },
+ { 0x21018c, 0x0 },
+ { 0x1108c, 0x0 },
+ { 0x11108c, 0x0 },
+ { 0x21108c, 0x0 },
+ { 0x1118c, 0x0 },
+ { 0x11118c, 0x0 },
+ { 0x21118c, 0x0 },
+ { 0x1208c, 0x0 },
+ { 0x11208c, 0x0 },
+ { 0x21208c, 0x0 },
+ { 0x1218c, 0x0 },
+ { 0x11218c, 0x0 },
+ { 0x21218c, 0x0 },
+ { 0x1308c, 0x0 },
+ { 0x11308c, 0x0 },
+ { 0x21308c, 0x0 },
+ { 0x1318c, 0x0 },
+ { 0x11318c, 0x0 },
+ { 0x21318c, 0x0 },
+ { 0x1008d, 0x0 },
+ { 0x11008d, 0x0 },
+ { 0x21008d, 0x0 },
+ { 0x1018d, 0x0 },
+ { 0x11018d, 0x0 },
+ { 0x21018d, 0x0 },
+ { 0x1108d, 0x0 },
+ { 0x11108d, 0x0 },
+ { 0x21108d, 0x0 },
+ { 0x1118d, 0x0 },
+ { 0x11118d, 0x0 },
+ { 0x21118d, 0x0 },
+ { 0x1208d, 0x0 },
+ { 0x11208d, 0x0 },
+ { 0x21208d, 0x0 },
+ { 0x1218d, 0x0 },
+ { 0x11218d, 0x0 },
+ { 0x21218d, 0x0 },
+ { 0x1308d, 0x0 },
+ { 0x11308d, 0x0 },
+ { 0x21308d, 0x0 },
+ { 0x1318d, 0x0 },
+ { 0x11318d, 0x0 },
+ { 0x21318d, 0x0 },
+ { 0x100c0, 0x0 },
+ { 0x1100c0, 0x0 },
+ { 0x2100c0, 0x0 },
+ { 0x101c0, 0x0 },
+ { 0x1101c0, 0x0 },
+ { 0x2101c0, 0x0 },
+ { 0x102c0, 0x0 },
+ { 0x1102c0, 0x0 },
+ { 0x2102c0, 0x0 },
+ { 0x103c0, 0x0 },
+ { 0x1103c0, 0x0 },
+ { 0x2103c0, 0x0 },
+ { 0x104c0, 0x0 },
+ { 0x1104c0, 0x0 },
+ { 0x2104c0, 0x0 },
+ { 0x105c0, 0x0 },
+ { 0x1105c0, 0x0 },
+ { 0x2105c0, 0x0 },
+ { 0x106c0, 0x0 },
+ { 0x1106c0, 0x0 },
+ { 0x2106c0, 0x0 },
+ { 0x107c0, 0x0 },
+ { 0x1107c0, 0x0 },
+ { 0x2107c0, 0x0 },
+ { 0x108c0, 0x0 },
+ { 0x1108c0, 0x0 },
+ { 0x2108c0, 0x0 },
+ { 0x110c0, 0x0 },
+ { 0x1110c0, 0x0 },
+ { 0x2110c0, 0x0 },
+ { 0x111c0, 0x0 },
+ { 0x1111c0, 0x0 },
+ { 0x2111c0, 0x0 },
+ { 0x112c0, 0x0 },
+ { 0x1112c0, 0x0 },
+ { 0x2112c0, 0x0 },
+ { 0x113c0, 0x0 },
+ { 0x1113c0, 0x0 },
+ { 0x2113c0, 0x0 },
+ { 0x114c0, 0x0 },
+ { 0x1114c0, 0x0 },
+ { 0x2114c0, 0x0 },
+ { 0x115c0, 0x0 },
+ { 0x1115c0, 0x0 },
+ { 0x2115c0, 0x0 },
+ { 0x116c0, 0x0 },
+ { 0x1116c0, 0x0 },
+ { 0x2116c0, 0x0 },
+ { 0x117c0, 0x0 },
+ { 0x1117c0, 0x0 },
+ { 0x2117c0, 0x0 },
+ { 0x118c0, 0x0 },
+ { 0x1118c0, 0x0 },
+ { 0x2118c0, 0x0 },
+ { 0x120c0, 0x0 },
+ { 0x1120c0, 0x0 },
+ { 0x2120c0, 0x0 },
+ { 0x121c0, 0x0 },
+ { 0x1121c0, 0x0 },
+ { 0x2121c0, 0x0 },
+ { 0x122c0, 0x0 },
+ { 0x1122c0, 0x0 },
+ { 0x2122c0, 0x0 },
+ { 0x123c0, 0x0 },
+ { 0x1123c0, 0x0 },
+ { 0x2123c0, 0x0 },
+ { 0x124c0, 0x0 },
+ { 0x1124c0, 0x0 },
+ { 0x2124c0, 0x0 },
+ { 0x125c0, 0x0 },
+ { 0x1125c0, 0x0 },
+ { 0x2125c0, 0x0 },
+ { 0x126c0, 0x0 },
+ { 0x1126c0, 0x0 },
+ { 0x2126c0, 0x0 },
+ { 0x127c0, 0x0 },
+ { 0x1127c0, 0x0 },
+ { 0x2127c0, 0x0 },
+ { 0x128c0, 0x0 },
+ { 0x1128c0, 0x0 },
+ { 0x2128c0, 0x0 },
+ { 0x130c0, 0x0 },
+ { 0x1130c0, 0x0 },
+ { 0x2130c0, 0x0 },
+ { 0x131c0, 0x0 },
+ { 0x1131c0, 0x0 },
+ { 0x2131c0, 0x0 },
+ { 0x132c0, 0x0 },
+ { 0x1132c0, 0x0 },
+ { 0x2132c0, 0x0 },
+ { 0x133c0, 0x0 },
+ { 0x1133c0, 0x0 },
+ { 0x2133c0, 0x0 },
+ { 0x134c0, 0x0 },
+ { 0x1134c0, 0x0 },
+ { 0x2134c0, 0x0 },
+ { 0x135c0, 0x0 },
+ { 0x1135c0, 0x0 },
+ { 0x2135c0, 0x0 },
+ { 0x136c0, 0x0 },
+ { 0x1136c0, 0x0 },
+ { 0x2136c0, 0x0 },
+ { 0x137c0, 0x0 },
+ { 0x1137c0, 0x0 },
+ { 0x2137c0, 0x0 },
+ { 0x138c0, 0x0 },
+ { 0x1138c0, 0x0 },
+ { 0x2138c0, 0x0 },
+ { 0x100c1, 0x0 },
+ { 0x1100c1, 0x0 },
+ { 0x2100c1, 0x0 },
+ { 0x101c1, 0x0 },
+ { 0x1101c1, 0x0 },
+ { 0x2101c1, 0x0 },
+ { 0x102c1, 0x0 },
+ { 0x1102c1, 0x0 },
+ { 0x2102c1, 0x0 },
+ { 0x103c1, 0x0 },
+ { 0x1103c1, 0x0 },
+ { 0x2103c1, 0x0 },
+ { 0x104c1, 0x0 },
+ { 0x1104c1, 0x0 },
+ { 0x2104c1, 0x0 },
+ { 0x105c1, 0x0 },
+ { 0x1105c1, 0x0 },
+ { 0x2105c1, 0x0 },
+ { 0x106c1, 0x0 },
+ { 0x1106c1, 0x0 },
+ { 0x2106c1, 0x0 },
+ { 0x107c1, 0x0 },
+ { 0x1107c1, 0x0 },
+ { 0x2107c1, 0x0 },
+ { 0x108c1, 0x0 },
+ { 0x1108c1, 0x0 },
+ { 0x2108c1, 0x0 },
+ { 0x110c1, 0x0 },
+ { 0x1110c1, 0x0 },
+ { 0x2110c1, 0x0 },
+ { 0x111c1, 0x0 },
+ { 0x1111c1, 0x0 },
+ { 0x2111c1, 0x0 },
+ { 0x112c1, 0x0 },
+ { 0x1112c1, 0x0 },
+ { 0x2112c1, 0x0 },
+ { 0x113c1, 0x0 },
+ { 0x1113c1, 0x0 },
+ { 0x2113c1, 0x0 },
+ { 0x114c1, 0x0 },
+ { 0x1114c1, 0x0 },
+ { 0x2114c1, 0x0 },
+ { 0x115c1, 0x0 },
+ { 0x1115c1, 0x0 },
+ { 0x2115c1, 0x0 },
+ { 0x116c1, 0x0 },
+ { 0x1116c1, 0x0 },
+ { 0x2116c1, 0x0 },
+ { 0x117c1, 0x0 },
+ { 0x1117c1, 0x0 },
+ { 0x2117c1, 0x0 },
+ { 0x118c1, 0x0 },
+ { 0x1118c1, 0x0 },
+ { 0x2118c1, 0x0 },
+ { 0x120c1, 0x0 },
+ { 0x1120c1, 0x0 },
+ { 0x2120c1, 0x0 },
+ { 0x121c1, 0x0 },
+ { 0x1121c1, 0x0 },
+ { 0x2121c1, 0x0 },
+ { 0x122c1, 0x0 },
+ { 0x1122c1, 0x0 },
+ { 0x2122c1, 0x0 },
+ { 0x123c1, 0x0 },
+ { 0x1123c1, 0x0 },
+ { 0x2123c1, 0x0 },
+ { 0x124c1, 0x0 },
+ { 0x1124c1, 0x0 },
+ { 0x2124c1, 0x0 },
+ { 0x125c1, 0x0 },
+ { 0x1125c1, 0x0 },
+ { 0x2125c1, 0x0 },
+ { 0x126c1, 0x0 },
+ { 0x1126c1, 0x0 },
+ { 0x2126c1, 0x0 },
+ { 0x127c1, 0x0 },
+ { 0x1127c1, 0x0 },
+ { 0x2127c1, 0x0 },
+ { 0x128c1, 0x0 },
+ { 0x1128c1, 0x0 },
+ { 0x2128c1, 0x0 },
+ { 0x130c1, 0x0 },
+ { 0x1130c1, 0x0 },
+ { 0x2130c1, 0x0 },
+ { 0x131c1, 0x0 },
+ { 0x1131c1, 0x0 },
+ { 0x2131c1, 0x0 },
+ { 0x132c1, 0x0 },
+ { 0x1132c1, 0x0 },
+ { 0x2132c1, 0x0 },
+ { 0x133c1, 0x0 },
+ { 0x1133c1, 0x0 },
+ { 0x2133c1, 0x0 },
+ { 0x134c1, 0x0 },
+ { 0x1134c1, 0x0 },
+ { 0x2134c1, 0x0 },
+ { 0x135c1, 0x0 },
+ { 0x1135c1, 0x0 },
+ { 0x2135c1, 0x0 },
+ { 0x136c1, 0x0 },
+ { 0x1136c1, 0x0 },
+ { 0x2136c1, 0x0 },
+ { 0x137c1, 0x0 },
+ { 0x1137c1, 0x0 },
+ { 0x2137c1, 0x0 },
+ { 0x138c1, 0x0 },
+ { 0x1138c1, 0x0 },
+ { 0x2138c1, 0x0 },
+ { 0x10020, 0x0 },
+ { 0x110020, 0x0 },
+ { 0x210020, 0x0 },
+ { 0x11020, 0x0 },
+ { 0x111020, 0x0 },
+ { 0x211020, 0x0 },
+ { 0x12020, 0x0 },
+ { 0x112020, 0x0 },
+ { 0x212020, 0x0 },
+ { 0x13020, 0x0 },
+ { 0x113020, 0x0 },
+ { 0x213020, 0x0 },
+ { 0x20072, 0x0 },
+ { 0x20073, 0x0 },
+ { 0x20074, 0x0 },
+ { 0x100aa, 0x0 },
+ { 0x110aa, 0x0 },
+ { 0x120aa, 0x0 },
+ { 0x130aa, 0x0 },
+ { 0x20010, 0x0 },
+ { 0x120010, 0x0 },
+ { 0x220010, 0x0 },
+ { 0x20011, 0x0 },
+ { 0x120011, 0x0 },
+ { 0x220011, 0x0 },
+ { 0x100ae, 0x0 },
+ { 0x1100ae, 0x0 },
+ { 0x2100ae, 0x0 },
+ { 0x100af, 0x0 },
+ { 0x1100af, 0x0 },
+ { 0x2100af, 0x0 },
+ { 0x110ae, 0x0 },
+ { 0x1110ae, 0x0 },
+ { 0x2110ae, 0x0 },
+ { 0x110af, 0x0 },
+ { 0x1110af, 0x0 },
+ { 0x2110af, 0x0 },
+ { 0x120ae, 0x0 },
+ { 0x1120ae, 0x0 },
+ { 0x2120ae, 0x0 },
+ { 0x120af, 0x0 },
+ { 0x1120af, 0x0 },
+ { 0x2120af, 0x0 },
+ { 0x130ae, 0x0 },
+ { 0x1130ae, 0x0 },
+ { 0x2130ae, 0x0 },
+ { 0x130af, 0x0 },
+ { 0x1130af, 0x0 },
+ { 0x2130af, 0x0 },
+ { 0x20020, 0x0 },
+ { 0x120020, 0x0 },
+ { 0x220020, 0x0 },
+ { 0x100a0, 0x0 },
+ { 0x100a1, 0x0 },
+ { 0x100a2, 0x0 },
+ { 0x100a3, 0x0 },
+ { 0x100a4, 0x0 },
+ { 0x100a5, 0x0 },
+ { 0x100a6, 0x0 },
+ { 0x100a7, 0x0 },
+ { 0x110a0, 0x0 },
+ { 0x110a1, 0x0 },
+ { 0x110a2, 0x0 },
+ { 0x110a3, 0x0 },
+ { 0x110a4, 0x0 },
+ { 0x110a5, 0x0 },
+ { 0x110a6, 0x0 },
+ { 0x110a7, 0x0 },
+ { 0x120a0, 0x0 },
+ { 0x120a1, 0x0 },
+ { 0x120a2, 0x0 },
+ { 0x120a3, 0x0 },
+ { 0x120a4, 0x0 },
+ { 0x120a5, 0x0 },
+ { 0x120a6, 0x0 },
+ { 0x120a7, 0x0 },
+ { 0x130a0, 0x0 },
+ { 0x130a1, 0x0 },
+ { 0x130a2, 0x0 },
+ { 0x130a3, 0x0 },
+ { 0x130a4, 0x0 },
+ { 0x130a5, 0x0 },
+ { 0x130a6, 0x0 },
+ { 0x130a7, 0x0 },
+ { 0x2007c, 0x0 },
+ { 0x12007c, 0x0 },
+ { 0x22007c, 0x0 },
+ { 0x2007d, 0x0 },
+ { 0x12007d, 0x0 },
+ { 0x22007d, 0x0 },
+ { 0x400fd, 0x0 },
+ { 0x400c0, 0x0 },
+ { 0x90201, 0x0 },
+ { 0x190201, 0x0 },
+ { 0x290201, 0x0 },
+ { 0x90202, 0x0 },
+ { 0x190202, 0x0 },
+ { 0x290202, 0x0 },
+ { 0x90203, 0x0 },
+ { 0x190203, 0x0 },
+ { 0x290203, 0x0 },
+ { 0x90204, 0x0 },
+ { 0x190204, 0x0 },
+ { 0x290204, 0x0 },
+ { 0x90205, 0x0 },
+ { 0x190205, 0x0 },
+ { 0x290205, 0x0 },
+ { 0x90206, 0x0 },
+ { 0x190206, 0x0 },
+ { 0x290206, 0x0 },
+ { 0x90207, 0x0 },
+ { 0x190207, 0x0 },
+ { 0x290207, 0x0 },
+ { 0x90208, 0x0 },
+ { 0x190208, 0x0 },
+ { 0x290208, 0x0 },
+ { 0x10062, 0x0 },
+ { 0x10162, 0x0 },
+ { 0x10262, 0x0 },
+ { 0x10362, 0x0 },
+ { 0x10462, 0x0 },
+ { 0x10562, 0x0 },
+ { 0x10662, 0x0 },
+ { 0x10762, 0x0 },
+ { 0x10862, 0x0 },
+ { 0x11062, 0x0 },
+ { 0x11162, 0x0 },
+ { 0x11262, 0x0 },
+ { 0x11362, 0x0 },
+ { 0x11462, 0x0 },
+ { 0x11562, 0x0 },
+ { 0x11662, 0x0 },
+ { 0x11762, 0x0 },
+ { 0x11862, 0x0 },
+ { 0x12062, 0x0 },
+ { 0x12162, 0x0 },
+ { 0x12262, 0x0 },
+ { 0x12362, 0x0 },
+ { 0x12462, 0x0 },
+ { 0x12562, 0x0 },
+ { 0x12662, 0x0 },
+ { 0x12762, 0x0 },
+ { 0x12862, 0x0 },
+ { 0x13062, 0x0 },
+ { 0x13162, 0x0 },
+ { 0x13262, 0x0 },
+ { 0x13362, 0x0 },
+ { 0x13462, 0x0 },
+ { 0x13562, 0x0 },
+ { 0x13662, 0x0 },
+ { 0x13762, 0x0 },
+ { 0x13862, 0x0 },
+ { 0x20077, 0x0 },
+ { 0x10001, 0x0 },
+ { 0x11001, 0x0 },
+ { 0x12001, 0x0 },
+ { 0x13001, 0x0 },
+ { 0x10040, 0x0 },
+ { 0x10140, 0x0 },
+ { 0x10240, 0x0 },
+ { 0x10340, 0x0 },
+ { 0x10440, 0x0 },
+ { 0x10540, 0x0 },
+ { 0x10640, 0x0 },
+ { 0x10740, 0x0 },
+ { 0x10840, 0x0 },
+ { 0x10030, 0x0 },
+ { 0x10130, 0x0 },
+ { 0x10230, 0x0 },
+ { 0x10330, 0x0 },
+ { 0x10430, 0x0 },
+ { 0x10530, 0x0 },
+ { 0x10630, 0x0 },
+ { 0x10730, 0x0 },
+ { 0x10830, 0x0 },
+ { 0x11040, 0x0 },
+ { 0x11140, 0x0 },
+ { 0x11240, 0x0 },
+ { 0x11340, 0x0 },
+ { 0x11440, 0x0 },
+ { 0x11540, 0x0 },
+ { 0x11640, 0x0 },
+ { 0x11740, 0x0 },
+ { 0x11840, 0x0 },
+ { 0x11030, 0x0 },
+ { 0x11130, 0x0 },
+ { 0x11230, 0x0 },
+ { 0x11330, 0x0 },
+ { 0x11430, 0x0 },
+ { 0x11530, 0x0 },
+ { 0x11630, 0x0 },
+ { 0x11730, 0x0 },
+ { 0x11830, 0x0 },
+ { 0x12040, 0x0 },
+ { 0x12140, 0x0 },
+ { 0x12240, 0x0 },
+ { 0x12340, 0x0 },
+ { 0x12440, 0x0 },
+ { 0x12540, 0x0 },
+ { 0x12640, 0x0 },
+ { 0x12740, 0x0 },
+ { 0x12840, 0x0 },
+ { 0x12030, 0x0 },
+ { 0x12130, 0x0 },
+ { 0x12230, 0x0 },
+ { 0x12330, 0x0 },
+ { 0x12430, 0x0 },
+ { 0x12530, 0x0 },
+ { 0x12630, 0x0 },
+ { 0x12730, 0x0 },
+ { 0x12830, 0x0 },
+ { 0x13040, 0x0 },
+ { 0x13140, 0x0 },
+ { 0x13240, 0x0 },
+ { 0x13340, 0x0 },
+ { 0x13440, 0x0 },
+ { 0x13540, 0x0 },
+ { 0x13640, 0x0 },
+ { 0x13740, 0x0 },
+ { 0x13840, 0x0 },
+ { 0x13030, 0x0 },
+ { 0x13130, 0x0 },
+ { 0x13230, 0x0 },
+ { 0x13330, 0x0 },
+ { 0x13430, 0x0 },
+ { 0x13530, 0x0 },
+ { 0x13630, 0x0 },
+ { 0x13730, 0x0 },
+ { 0x13830, 0x0 },
+};
+
+uint32_t ddrphy_trained_csr_num = ARRAY_SIZE(ddrphy_trained_csr);
diff --git a/drivers/ddr/imx8m/ddrphy_train.c b/drivers/ddr/imx8m/ddrphy_train.c
new file mode 100644
index 0000000..c2238cc
--- /dev/null
+++ b/drivers/ddr/imx8m/ddrphy_train.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+#define DEBUG
+#include <common.h>
+#include <linux/kernel.h>
+#include <soc/imx8m/ddr.h>
+#include <firmware.h>
+#include <mach/imx8m-regs.h>
+
+void ddr_load_train_code(enum fw_type type)
+{
+ const u16 *imem, *dmem;
+ size_t isize, dsize;
+
+ if (type == FW_1D_IMAGE) {
+ get_builtin_firmware(lpddr4_pmu_train_1d_imem_bin, &imem, &isize);
+ get_builtin_firmware(lpddr4_pmu_train_1d_dmem_bin, &dmem, &dsize);
+ } else {
+ get_builtin_firmware(lpddr4_pmu_train_2d_imem_bin, &imem, &isize);
+ get_builtin_firmware(lpddr4_pmu_train_2d_dmem_bin, &dmem, &dsize);
+ }
+
+ ddrc_phy_load_firmware(IOMEM(MX8M_DDRC_PHY_BASE_ADDR),
+ DDRC_PHY_IMEM, imem, isize);
+
+ ddrc_phy_load_firmware(IOMEM(MX8M_DDRC_PHY_BASE_ADDR),
+ DDRC_PHY_DMEM, dmem, dsize);
+}
+
+int ddr_cfg_phy(struct dram_timing_info *dram_timing)
+{
+ struct dram_cfg_param *dram_cfg;
+ struct dram_fsp_msg *fsp_msg;
+ unsigned int num;
+ int i = 0;
+ int j = 0;
+ int ret;
+
+ /* initialize PHY configuration */
+ dram_cfg = dram_timing->ddrphy_cfg;
+ num = dram_timing->ddrphy_cfg_num;
+ for (i = 0; i < num; i++) {
+ /* config phy reg */
+ dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val);
+ dram_cfg++;
+ }
+
+ /* load the frequency setpoint message block config */
+ fsp_msg = dram_timing->fsp_msg;
+ for (i = 0; i < dram_timing->fsp_msg_num; i++) {
+ debug("DRAM PHY training for %dMTS\n", fsp_msg->drate);
+ /* set dram PHY input clocks to desired frequency */
+ ddrphy_init_set_dfi_clk(fsp_msg->drate);
+
+ /* load the dram training firmware image */
+ dwc_ddrphy_apb_wr(0xd0000, 0x0);
+ ddr_load_train_code(fsp_msg->fw_type);
+
+ /* load the frequency set point message block parameter */
+ dram_cfg = fsp_msg->fsp_cfg;
+ num = fsp_msg->fsp_cfg_num;
+ for (j = 0; j < num; j++) {
+ dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val);
+ dram_cfg++;
+ }
+
+ /*
+ * -------------------- excute the firmware --------------------
+ * Running the firmware is a simply process to taking the
+ * PMU out of reset and stall, then the firwmare will be run
+ * 1. reset the PMU;
+ * 2. begin the excution;
+ * 3. wait for the training done;
+ * 4. read the message block result.
+ * -------------------------------------------------------------
+ */
+ dwc_ddrphy_apb_wr(0xd0000, 0x1);
+ dwc_ddrphy_apb_wr(0xd0099, 0x9);
+ dwc_ddrphy_apb_wr(0xd0099, 0x1);
+ dwc_ddrphy_apb_wr(0xd0099, 0x0);
+
+ /* Wait for the training firmware to complete */
+ ret = wait_ddrphy_training_complete();
+ if (ret)
+ return ret;
+
+ /* Halt the microcontroller. */
+ dwc_ddrphy_apb_wr(0xd0099, 0x1);
+
+ /* Read the Message Block results */
+ dwc_ddrphy_apb_wr(0xd0000, 0x0);
+ ddrphy_init_read_msg_block(fsp_msg->fw_type);
+ dwc_ddrphy_apb_wr(0xd0000, 0x1);
+
+ fsp_msg++;
+ }
+
+ /* Load PHY Init Engine Image */
+ dram_cfg = dram_timing->ddrphy_pie;
+ num = dram_timing->ddrphy_pie_num;
+ for (i = 0; i < num; i++) {
+ dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val);
+ dram_cfg++;
+ }
+
+ /* save the ddr PHY trained CSR in memory for low power use */
+ ddrphy_trained_csr_save(ddrphy_trained_csr, ddrphy_trained_csr_num);
+
+ return 0;
+}
diff --git a/drivers/ddr/imx8m/ddrphy_utils.c b/drivers/ddr/imx8m/ddrphy_utils.c
new file mode 100644
index 0000000..651bb4b
--- /dev/null
+++ b/drivers/ddr/imx8m/ddrphy_utils.c
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+* Copyright 2018 NXP
+*/
+
+#include <common.h>
+#include <errno.h>
+#include <io.h>
+#include <linux/iopoll.h>
+#include <soc/imx8m/ddr.h>
+#include <mach/imx8m-regs.h>
+#include <mach/imx8m-ccm-regs.h>
+
+void ddrc_phy_load_firmware(void __iomem *phy,
+ enum ddrc_phy_firmware_offset offset,
+ const u16 *blob, size_t size)
+{
+ while (size) {
+ writew(*blob++, phy + DDRC_PHY_REG(offset));
+ offset++;
+ size -= sizeof(*blob);
+ }
+}
+
+enum pmc_constants {
+ PMC_MESSAGE_ID,
+ PMC_MESSAGE_STREAM,
+
+ PMC_TRAIN_SUCCESS = 0x07,
+ PMC_TRAIN_STREAM_START = 0x08,
+ PMC_TRAIN_FAIL = 0xff,
+};
+
+static u32 ddrc_phy_get_message(void __iomem *phy, int type)
+{
+ u32 r, message;
+
+ /*
+ * When BIT0 set to 0, the PMU has a message for the user
+ * Wait for it indefinitely.
+ */
+ readl_poll_timeout(phy + DDRC_PHY_REG(0xd0004),
+ r, !(r & BIT(0)), 0);
+
+ switch (type) {
+ case PMC_MESSAGE_ID:
+ /*
+ * Get the major message ID
+ */
+ message = readl(phy + DDRC_PHY_REG(0xd0032));
+ break;
+ case PMC_MESSAGE_STREAM:
+ message = readl(phy + DDRC_PHY_REG(0xd0034));
+ message <<= 16;
+ message |= readl(phy + DDRC_PHY_REG(0xd0032));
+ break;
+ }
+
+ /*
+ * By setting this register to 0, the user acknowledges the
+ * receipt of the message.
+ */
+ writel(0x00000000, phy + DDRC_PHY_REG(0xd0031));
+ /*
+ * When BIT0 set to 0, the PMU has a message for the user
+ */
+ readl_poll_timeout(phy + DDRC_PHY_REG(0xd0004),
+ r, r & BIT(0), 0);
+
+ writel(0x00000001, phy + DDRC_PHY_REG(0xd0031));
+
+ return message;
+}
+
+static void ddrc_phy_fetch_streaming_message(void __iomem *phy)
+{
+ const u16 index = ddrc_phy_get_message(phy, PMC_MESSAGE_STREAM);
+ u16 i;
+
+ for (i = 0; i < index; i++)
+ ddrc_phy_get_message(phy, PMC_MESSAGE_STREAM);
+}
+
+int wait_ddrphy_training_complete(void)
+{
+ void __iomem *phy = IOMEM(MX8M_DDRC_PHY_BASE_ADDR);
+
+ for (;;) {
+ const u32 m = ddrc_phy_get_message(phy, PMC_MESSAGE_ID);
+
+ switch (m) {
+ case PMC_TRAIN_STREAM_START:
+ ddrc_phy_fetch_streaming_message(phy);
+ break;
+ case PMC_TRAIN_SUCCESS:
+ return 0;
+ case PMC_TRAIN_FAIL:
+ hang();
+ }
+ }
+}
+
+struct dram_bypass_clk_setting {
+ ulong clk;
+ int alt_root_sel;
+ int alt_pre_div;
+ int apb_root_sel;
+ int apb_pre_div;
+};
+
+#define MHZ(x) (1000000UL * (x))
+
+static struct dram_bypass_clk_setting imx8mq_dram_bypass_tbl[] = {
+ {
+ .clk = MHZ(100),
+ .alt_root_sel = 2,
+ .alt_pre_div = 1 - 1,
+ .apb_root_sel = 2,
+ .apb_pre_div = 2 - 1,
+ } , {
+ .clk = MHZ(250),
+ .alt_root_sel = 3,
+ .alt_pre_div = 2 - 1,
+ .apb_root_sel = 2,
+ .apb_pre_div = 2 - 1,
+ }, {
+ .clk = MHZ(400),
+ .alt_root_sel = 1,
+ .alt_pre_div = 2 - 1,
+ .apb_root_sel = 3,
+ .apb_pre_div = 2 - 1,
+ },
+};
+
+static void dram_enable_bypass(ulong clk_val)
+{
+ int i;
+ struct dram_bypass_clk_setting *config;
+
+ for (i = 0; i < ARRAY_SIZE(imx8mq_dram_bypass_tbl); i++) {
+ if (clk_val == imx8mq_dram_bypass_tbl[i].clk)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(imx8mq_dram_bypass_tbl)) {
+ printf("No matched freq table %lu\n", clk_val);
+ return;
+ }
+
+ config = &imx8mq_dram_bypass_tbl[i];
+
+ imx8m_clock_set_target_val(IMX8M_DRAM_ALT_CLK_ROOT,
+ IMX8M_CCM_TARGET_ROOTn_ENABLE |
+ IMX8M_CCM_TARGET_ROOTn_MUX(config->alt_root_sel) |
+ IMX8M_CCM_TARGET_ROOTn_PRE_DIV(config->alt_pre_div));
+ imx8m_clock_set_target_val(IMX8M_DRAM_APB_CLK_ROOT,
+ IMX8M_CCM_TARGET_ROOTn_ENABLE |
+ IMX8M_CCM_TARGET_ROOTn_MUX(config->apb_root_sel) |
+ IMX8M_CCM_TARGET_ROOTn_PRE_DIV(config->apb_pre_div));
+ imx8m_clock_set_target_val(IMX8M_DRAM_SEL_CFG, IMX8M_CCM_TARGET_ROOTn_ENABLE |
+ IMX8M_CCM_TARGET_ROOTn_MUX(1));
+}
+
+static void dram_disable_bypass(void)
+{
+ imx8m_clock_set_target_val(IMX8M_DRAM_SEL_CFG,
+ IMX8M_CCM_TARGET_ROOTn_ENABLE |
+ IMX8M_CCM_TARGET_ROOTn_MUX(0));
+ imx8m_clock_set_target_val(IMX8M_DRAM_APB_CLK_ROOT,
+ IMX8M_CCM_TARGET_ROOTn_ENABLE |
+ IMX8M_CCM_TARGET_ROOTn_MUX(4) |
+ IMX8M_CCM_TARGET_ROOTn_PRE_DIV(5 - 1));
+}
+
+struct imx_int_pll_rate_table {
+ u32 rate;
+ u32 r1;
+ u32 r2;
+};
+
+#define MDIV(x) ((x) << 12)
+#define PDIV(x) ((x) << 4)
+#define SDIV(x) ((x) << 0)
+
+#define LOCK_STATUS BIT(31)
+#define LOCK_SEL_MASK BIT(29)
+#define CLKE_MASK BIT(11)
+#define RST_MASK BIT(9)
+#define BYPASS_MASK BIT(4)
+
+static struct imx_int_pll_rate_table imx8mm_fracpll_tbl[] = {
+ { .rate = 1000000000U, .r1 = MDIV(250) | PDIV(3) | SDIV(1), .r2 = 0 },
+ { .rate = 800000000U, .r1 = MDIV(300) | PDIV(9) | SDIV(0), .r2 = 0 },
+ { .rate = 750000000U, .r1 = MDIV(250) | PDIV(8) | SDIV(0), .r2 = 0 },
+ { .rate = 650000000U, .r1 = MDIV(325) | PDIV(3) | SDIV(2), .r2 = 0 },
+ { .rate = 600000000U, .r1 = MDIV(300) | PDIV(3) | SDIV(2), .r2 = 0 },
+ { .rate = 594000000U, .r1 = MDIV( 99) | PDIV(1) | SDIV(2), .r2 = 0 },
+ { .rate = 400000000U, .r1 = MDIV(300) | PDIV(9) | SDIV(1), .r2 = 0 },
+ { .rate = 266666667U, .r1 = MDIV(400) | PDIV(9) | SDIV(2), .r2 = 0 },
+ { .rate = 167000000U, .r1 = MDIV(334) | PDIV(3) | SDIV(4), .r2 = 0 },
+ { .rate = 100000000U, .r1 = MDIV(300) | PDIV(9) | SDIV(3), .r2 = 0 },
+};
+
+static struct imx_int_pll_rate_table *fracpll(u32 freq)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(imx8mm_fracpll_tbl); i++)
+ if (freq == imx8mm_fracpll_tbl[i].rate)
+ return &imx8mm_fracpll_tbl[i];
+
+ return NULL;
+}
+
+static int dram_pll_init(u32 freq)
+{
+ volatile int i;
+ u32 tmp;
+ void *pll_base;
+ struct imx_int_pll_rate_table *rate;
+
+ rate = fracpll(freq);
+ if (!rate) {
+ printf("No matched freq table %u\n", freq);
+ return -EINVAL;
+ }
+
+ setbits_le32(MX8M_GPC_BASE_ADDR + 0xec, 1 << 7);
+ setbits_le32(MX8M_GPC_BASE_ADDR + 0xf8, 1 << 5);
+ writel(0x8F000000UL, MX8M_SRC_BASE_ADDR + 0x1004);
+
+ pll_base = IOMEM(MX8M_ANATOP_BASE_ADDR) + 0x50;
+
+ /* Bypass clock and set lock to pll output lock */
+ tmp = readl(pll_base);
+ tmp |= BYPASS_MASK;
+ writel(tmp, pll_base);
+
+ /* Enable RST */
+ tmp &= ~RST_MASK;
+ writel(tmp, pll_base);
+
+ writel(rate->r1, pll_base + 4);
+ writel(rate->r2, pll_base + 8);
+
+ for (i = 0; i < 1000; i++);
+
+ /* Disable RST */
+ tmp |= RST_MASK;
+ writel(tmp, pll_base);
+
+ /* Wait Lock*/
+ while (!(readl(pll_base) & LOCK_STATUS));
+
+ /* Bypass */
+ tmp &= ~BYPASS_MASK;
+ writel(tmp, pll_base);
+
+ return 0;
+}
+
+void ddrphy_init_set_dfi_clk(unsigned int drate)
+{
+ switch (drate) {
+ case 4000:
+ dram_pll_init(MHZ(1000));
+ dram_disable_bypass();
+ break;
+ case 3200:
+ dram_pll_init(MHZ(800));
+ dram_disable_bypass();
+ break;
+ case 3000:
+ dram_pll_init(MHZ(750));
+ dram_disable_bypass();
+ break;
+ case 2400:
+ dram_pll_init(MHZ(600));
+ dram_disable_bypass();
+ break;
+ case 1600:
+ dram_pll_init(MHZ(400));
+ dram_disable_bypass();
+ break;
+ case 1066:
+ dram_pll_init(MHZ(266));
+ dram_disable_bypass();
+ break;
+ case 667:
+ dram_pll_init(MHZ(167));
+ dram_disable_bypass();
+ break;
+ case 400:
+ dram_enable_bypass(MHZ(400));
+ break;
+ case 100:
+ dram_enable_bypass(MHZ(100));
+ break;
+ default:
+ return;
+ }
+}
+
+void ddrphy_init_read_msg_block(enum fw_type type)
+{
+}
diff --git a/drivers/ddr/imx8m/helper.c b/drivers/ddr/imx8m/helper.c
new file mode 100644
index 0000000..9e32ef9
--- /dev/null
+++ b/drivers/ddr/imx8m/helper.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <common.h>
+#include <io.h>
+#include <errno.h>
+#include <soc/imx8m/ddr.h>
+
+#define IMEM_LEN 32768 /* byte */
+#define DMEM_LEN 16384 /* byte */
+#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)
+
+void ddrphy_trained_csr_save(struct dram_cfg_param *ddrphy_csr,
+ unsigned int num)
+{
+ int i = 0;
+
+ /* enable the ddrphy apb */
+ dwc_ddrphy_apb_wr(0xd0000, 0x0);
+ dwc_ddrphy_apb_wr(0xc0080, 0x3);
+ for (i = 0; i < num; i++) {
+ ddrphy_csr->val = dwc_ddrphy_apb_rd(ddrphy_csr->reg);
+ ddrphy_csr++;
+ }
+ /* disable the ddrphy apb */
+ dwc_ddrphy_apb_wr(0xc0080, 0x2);
+ dwc_ddrphy_apb_wr(0xd0000, 0x1);
+}
+
+void dram_config_save(struct dram_timing_info *timing_info,
+ unsigned long saved_timing_base)
+{
+ int i = 0;
+ struct dram_timing_info *saved_timing = (void *)saved_timing_base;
+ struct dram_cfg_param *cfg;
+
+ saved_timing->ddrc_cfg_num = timing_info->ddrc_cfg_num;
+ saved_timing->ddrphy_cfg_num = timing_info->ddrphy_cfg_num;
+ saved_timing->ddrphy_trained_csr_num = ddrphy_trained_csr_num;
+ saved_timing->ddrphy_pie_num = timing_info->ddrphy_pie_num;
+
+ /* save the fsp table */
+ for (i = 0; i < 4; i++)
+ saved_timing->fsp_table[i] = timing_info->fsp_table[i];
+
+ cfg = (struct dram_cfg_param *)(saved_timing_base +
+ sizeof(*timing_info));
+
+ /* save ddrc config */
+ saved_timing->ddrc_cfg = cfg;
+ for (i = 0; i < timing_info->ddrc_cfg_num; i++) {
+ cfg->reg = timing_info->ddrc_cfg[i].reg;
+ cfg->val = timing_info->ddrc_cfg[i].val;
+ cfg++;
+ }
+
+ /* save ddrphy config */
+ saved_timing->ddrphy_cfg = cfg;
+ for (i = 0; i < timing_info->ddrphy_cfg_num; i++) {
+ cfg->reg = timing_info->ddrphy_cfg[i].reg;
+ cfg->val = timing_info->ddrphy_cfg[i].val;
+ cfg++;
+ }
+
+ /* save the ddrphy csr */
+ saved_timing->ddrphy_trained_csr = cfg;
+ for (i = 0; i < ddrphy_trained_csr_num; i++) {
+ cfg->reg = ddrphy_trained_csr[i].reg;
+ cfg->val = ddrphy_trained_csr[i].val;
+ cfg++;
+ }
+
+ /* save the ddrphy pie */
+ saved_timing->ddrphy_pie = cfg;
+ for (i = 0; i < timing_info->ddrphy_pie_num; i++) {
+ cfg->reg = timing_info->ddrphy_pie[i].reg;
+ cfg->val = timing_info->ddrphy_pie[i].val;
+ cfg++;
+ }
+}
diff --git a/include/soc/imx8m/ddr.h b/include/soc/imx8m/ddr.h
new file mode 100644
index 0000000..5b2747e
--- /dev/null
+++ b/include/soc/imx8m/ddr.h
@@ -0,0 +1,407 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2017 NXP
+ */
+
+#ifndef __ASM_ARCH_IMX8M_DDR_H
+#define __ASM_ARCH_IMX8M_DDR_H
+
+#include <io.h>
+#include <asm/types.h>
+#include <soc/imx8m/ddr.h>
+
+#define DDRC_DDR_SS_GPR0 0x3d000000
+#define DDRC_IPS_BASE_ADDR_0 0x3f400000
+#define IP2APB_DDRPHY_IPS_BASE_ADDR(X) (0x3c000000 + (X * 0x2000000))
+#define DDRPHY_MEM(X) (0x3c000000 + (X * 0x2000000) + 0x50000)
+
+#define DDRC_MSTR(X) (DDRC_IPS_BASE_ADDR(X) + 0x00)
+#define DDRC_STAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x04)
+#define DDRC_MSTR1(X) (DDRC_IPS_BASE_ADDR(X) + 0x08)
+#define DDRC_MRCTRL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x10)
+#define DDRC_MRCTRL1(X) (DDRC_IPS_BASE_ADDR(X) + 0x14)
+#define DDRC_MRSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x18)
+#define DDRC_MRCTRL2(X) (DDRC_IPS_BASE_ADDR(X) + 0x1c)
+#define DDRC_DERATEEN(X) (DDRC_IPS_BASE_ADDR(X) + 0x20)
+#define DDRC_DERATEINT(X) (DDRC_IPS_BASE_ADDR(X) + 0x24)
+#define DDRC_MSTR2(X) (DDRC_IPS_BASE_ADDR(X) + 0x28)
+#define DDRC_PWRCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x30)
+#define DDRC_PWRTMG(X) (DDRC_IPS_BASE_ADDR(X) + 0x34)
+#define DDRC_HWLPCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x38)
+#define DDRC_HWFFCCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x3c)
+#define DDRC_HWFFCSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x40)
+#define DDRC_RFSHCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x50)
+#define DDRC_RFSHCTL1(X) (DDRC_IPS_BASE_ADDR(X) + 0x54)
+#define DDRC_RFSHCTL2(X) (DDRC_IPS_BASE_ADDR(X) + 0x58)
+#define DDRC_RFSHCTL3(X) (DDRC_IPS_BASE_ADDR(X) + 0x60)
+#define DDRC_RFSHTMG(X) (DDRC_IPS_BASE_ADDR(X) + 0x64)
+#define DDRC_ECCCFG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x70)
+#define DDRC_ECCCFG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x74)
+#define DDRC_ECCSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x78)
+#define DDRC_ECCCLR(X) (DDRC_IPS_BASE_ADDR(X) + 0x7c)
+#define DDRC_ECCERRCNT(X) (DDRC_IPS_BASE_ADDR(X) + 0x80)
+#define DDRC_ECCCADDR0(X) (DDRC_IPS_BASE_ADDR(X) + 0x84)
+#define DDRC_ECCCADDR1(X) (DDRC_IPS_BASE_ADDR(X) + 0x88)
+#define DDRC_ECCCSYN0(X) (DDRC_IPS_BASE_ADDR(X) + 0x8c)
+#define DDRC_ECCCSYN1(X) (DDRC_IPS_BASE_ADDR(X) + 0x90)
+#define DDRC_ECCCSYN2(X) (DDRC_IPS_BASE_ADDR(X) + 0x94)
+#define DDRC_ECCBITMASK0(X) (DDRC_IPS_BASE_ADDR(X) + 0x98)
+#define DDRC_ECCBITMASK1(X) (DDRC_IPS_BASE_ADDR(X) + 0x9c)
+#define DDRC_ECCBITMASK2(X) (DDRC_IPS_BASE_ADDR(X) + 0xa0)
+#define DDRC_ECCUADDR0(X) (DDRC_IPS_BASE_ADDR(X) + 0xa4)
+#define DDRC_ECCUADDR1(X) (DDRC_IPS_BASE_ADDR(X) + 0xa8)
+#define DDRC_ECCUSYN0(X) (DDRC_IPS_BASE_ADDR(X) + 0xac)
+#define DDRC_ECCUSYN1(X) (DDRC_IPS_BASE_ADDR(X) + 0xb0)
+#define DDRC_ECCUSYN2(X) (DDRC_IPS_BASE_ADDR(X) + 0xb4)
+#define DDRC_ECCPOISONADDR0(X) (DDRC_IPS_BASE_ADDR(X) + 0xb8)
+#define DDRC_ECCPOISONADDR1(X) (DDRC_IPS_BASE_ADDR(X) + 0xbc)
+#define DDRC_CRCPARCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0xc0)
+#define DDRC_CRCPARCTL1(X) (DDRC_IPS_BASE_ADDR(X) + 0xc4)
+#define DDRC_CRCPARCTL2(X) (DDRC_IPS_BASE_ADDR(X) + 0xc8)
+#define DDRC_CRCPARSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0xcc)
+#define DDRC_INIT0(X) (DDRC_IPS_BASE_ADDR(X) + 0xd0)
+#define DDRC_INIT1(X) (DDRC_IPS_BASE_ADDR(X) + 0xd4)
+#define DDRC_INIT2(X) (DDRC_IPS_BASE_ADDR(X) + 0xd8)
+#define DDRC_INIT3(X) (DDRC_IPS_BASE_ADDR(X) + 0xdc)
+#define DDRC_INIT4(X) (DDRC_IPS_BASE_ADDR(X) + 0xe0)
+#define DDRC_INIT5(X) (DDRC_IPS_BASE_ADDR(X) + 0xe4)
+#define DDRC_INIT6(X) (DDRC_IPS_BASE_ADDR(X) + 0xe8)
+#define DDRC_INIT7(X) (DDRC_IPS_BASE_ADDR(X) + 0xec)
+#define DDRC_DIMMCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0xf0)
+#define DDRC_RANKCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0xf4)
+#define DDRC_DRAMTMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x100)
+#define DDRC_DRAMTMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x104)
+#define DDRC_DRAMTMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x108)
+#define DDRC_DRAMTMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x10c)
+#define DDRC_DRAMTMG4(X) (DDRC_IPS_BASE_ADDR(X) + 0x110)
+#define DDRC_DRAMTMG5(X) (DDRC_IPS_BASE_ADDR(X) + 0x114)
+#define DDRC_DRAMTMG6(X) (DDRC_IPS_BASE_ADDR(X) + 0x118)
+#define DDRC_DRAMTMG7(X) (DDRC_IPS_BASE_ADDR(X) + 0x11c)
+#define DDRC_DRAMTMG8(X) (DDRC_IPS_BASE_ADDR(X) + 0x120)
+#define DDRC_DRAMTMG9(X) (DDRC_IPS_BASE_ADDR(X) + 0x124)
+#define DDRC_DRAMTMG10(X) (DDRC_IPS_BASE_ADDR(X) + 0x128)
+#define DDRC_DRAMTMG11(X) (DDRC_IPS_BASE_ADDR(X) + 0x12c)
+#define DDRC_DRAMTMG12(X) (DDRC_IPS_BASE_ADDR(X) + 0x130)
+#define DDRC_DRAMTMG13(X) (DDRC_IPS_BASE_ADDR(X) + 0x134)
+#define DDRC_DRAMTMG14(X) (DDRC_IPS_BASE_ADDR(X) + 0x138)
+#define DDRC_DRAMTMG15(X) (DDRC_IPS_BASE_ADDR(X) + 0x13C)
+#define DDRC_DRAMTMG16(X) (DDRC_IPS_BASE_ADDR(X) + 0x140)
+#define DDRC_DRAMTMG17(X) (DDRC_IPS_BASE_ADDR(X) + 0x144)
+#define DDRC_ZQCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x180)
+#define DDRC_ZQCTL1(X) (DDRC_IPS_BASE_ADDR(X) + 0x184)
+#define DDRC_ZQCTL2(X) (DDRC_IPS_BASE_ADDR(X) + 0x188)
+#define DDRC_ZQSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x18c)
+#define DDRC_DFITMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x190)
+#define DDRC_DFITMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x194)
+#define DDRC_DFILPCFG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x198)
+#define DDRC_DFILPCFG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x19c)
+#define DDRC_DFIUPD0(X) (DDRC_IPS_BASE_ADDR(X) + 0x1a0)
+#define DDRC_DFIUPD1(X) (DDRC_IPS_BASE_ADDR(X) + 0x1a4)
+#define DDRC_DFIUPD2(X) (DDRC_IPS_BASE_ADDR(X) + 0x1a8)
+#define DDRC_DFIMISC(X) (DDRC_IPS_BASE_ADDR(X) + 0x1b0)
+#define DDRC_DFITMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x1b4)
+#define DDRC_DFITMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x1b8)
+#define DDRC_DFISTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x1bc)
+#define DDRC_DBICTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x1c0)
+#define DDRC_DFIPHYMSTR(X) (DDRC_IPS_BASE_ADDR(X) + 0x1c4)
+#define DDRC_TRAINCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x1d0)
+#define DDRC_TRAINCTL1(X) (DDRC_IPS_BASE_ADDR(X) + 0x1d4)
+#define DDRC_TRAINCTL2(X) (DDRC_IPS_BASE_ADDR(X) + 0x1d8)
+#define DDRC_TRAINSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x1dc)
+#define DDRC_ADDRMAP0(X) (DDRC_IPS_BASE_ADDR(X) + 0x200)
+#define DDRC_ADDRMAP1(X) (DDRC_IPS_BASE_ADDR(X) + 0x204)
+#define DDRC_ADDRMAP2(X) (DDRC_IPS_BASE_ADDR(X) + 0x208)
+#define DDRC_ADDRMAP3(X) (DDRC_IPS_BASE_ADDR(X) + 0x20c)
+#define DDRC_ADDRMAP4(X) (DDRC_IPS_BASE_ADDR(X) + 0x210)
+#define DDRC_ADDRMAP5(X) (DDRC_IPS_BASE_ADDR(X) + 0x214)
+#define DDRC_ADDRMAP6(X) (DDRC_IPS_BASE_ADDR(X) + 0x218)
+#define DDRC_ADDRMAP7(X) (DDRC_IPS_BASE_ADDR(X) + 0x21c)
+#define DDRC_ADDRMAP8(X) (DDRC_IPS_BASE_ADDR(X) + 0x220)
+#define DDRC_ADDRMAP9(X) (DDRC_IPS_BASE_ADDR(X) + 0x224)
+#define DDRC_ADDRMAP10(X) (DDRC_IPS_BASE_ADDR(X) + 0x228)
+#define DDRC_ADDRMAP11(X) (DDRC_IPS_BASE_ADDR(X) + 0x22c)
+#define DDRC_ODTCFG(X) (DDRC_IPS_BASE_ADDR(X) + 0x240)
+#define DDRC_ODTMAP(X) (DDRC_IPS_BASE_ADDR(X) + 0x244)
+#define DDRC_SCHED(X) (DDRC_IPS_BASE_ADDR(X) + 0x250)
+#define DDRC_SCHED1(X) (DDRC_IPS_BASE_ADDR(X) + 0x254)
+#define DDRC_PERFHPR1(X) (DDRC_IPS_BASE_ADDR(X) + 0x25c)
+#define DDRC_PERFLPR1(X) (DDRC_IPS_BASE_ADDR(X) + 0x264)
+#define DDRC_PERFWR1(X) (DDRC_IPS_BASE_ADDR(X) + 0x26c)
+#define DDRC_PERFVPR1(X) (DDRC_IPS_BASE_ADDR(X) + 0x274)
+#define DDRC_PERFVPW1(X) (DDRC_IPS_BASE_ADDR(X) + 0x278)
+#define DDRC_DQMAP0(X) (DDRC_IPS_BASE_ADDR(X) + 0x280)
+#define DDRC_DQMAP1(X) (DDRC_IPS_BASE_ADDR(X) + 0x284)
+#define DDRC_DQMAP2(X) (DDRC_IPS_BASE_ADDR(X) + 0x288)
+#define DDRC_DQMAP3(X) (DDRC_IPS_BASE_ADDR(X) + 0x28c)
+#define DDRC_DQMAP4(X) (DDRC_IPS_BASE_ADDR(X) + 0x290)
+#define DDRC_DQMAP5(X) (DDRC_IPS_BASE_ADDR(X) + 0x294)
+#define DDRC_DBG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x300)
+#define DDRC_DBG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x304)
+#define DDRC_DBGCAM(X) (DDRC_IPS_BASE_ADDR(X) + 0x308)
+#define DDRC_DBGCMD(X) (DDRC_IPS_BASE_ADDR(X) + 0x30c)
+#define DDRC_DBGSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x310)
+#define DDRC_SWCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x320)
+#define DDRC_SWSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x324)
+#define DDRC_OCPARCFG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x330)
+#define DDRC_OCPARCFG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x334)
+#define DDRC_OCPARCFG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x338)
+#define DDRC_OCPARCFG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x33c)
+#define DDRC_OCPARSTAT0(X) (DDRC_IPS_BASE_ADDR(X) + 0x340)
+#define DDRC_OCPARSTAT1(X) (DDRC_IPS_BASE_ADDR(X) + 0x344)
+#define DDRC_OCPARWLOG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x348)
+#define DDRC_OCPARWLOG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x34c)
+#define DDRC_OCPARWLOG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x350)
+#define DDRC_OCPARAWLOG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x354)
+#define DDRC_OCPARAWLOG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x358)
+#define DDRC_OCPARRLOG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x35c)
+#define DDRC_OCPARRLOG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x360)
+#define DDRC_OCPARARLOG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x364)
+#define DDRC_OCPARARLOG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x368)
+#define DDRC_POISONCFG(X) (DDRC_IPS_BASE_ADDR(X) + 0x36C)
+#define DDRC_POISONSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x370)
+
+#define DDRC_PSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x3fc)
+#define DDRC_PCCFG(X) (DDRC_IPS_BASE_ADDR(X) + 0x400)
+#define DDRC_PCFGR_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x404)
+#define DDRC_PCFGR_1(X) (DDRC_IPS_BASE_ADDR(X) + 1 * 0xb0 + 0x404)
+#define DDRC_PCFGR_2(X) (DDRC_IPS_BASE_ADDR(X) + 2 * 0xb0 + 0x404)
+#define DDRC_PCFGR_3(X) (DDRC_IPS_BASE_ADDR(X) + 3 * 0xb0 + 0x404)
+#define DDRC_PCFGW_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x408)
+#define DDRC_PCFGW_1(X) (DDRC_IPS_BASE_ADDR(X) + 1 * 0xb0 + 0x408)
+#define DDRC_PCFGW_2(X) (DDRC_IPS_BASE_ADDR(X) + 2 * 0xb0 + 0x408)
+#define DDRC_PCFGW_3(X) (DDRC_IPS_BASE_ADDR(X) + 3 * 0xb0 + 0x408)
+#define DDRC_PCFGC_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x40c)
+#define DDRC_PCFGIDMASKCH(X) (DDRC_IPS_BASE_ADDR(X) + 0x410)
+#define DDRC_PCFGIDVALUECH(X) (DDRC_IPS_BASE_ADDR(X) + 0x414)
+#define DDRC_PCTRL_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x490)
+#define DDRC_PCTRL_1(X) (DDRC_IPS_BASE_ADDR(X) + 0x490 + 1 * 0xb0)
+#define DDRC_PCTRL_2(X) (DDRC_IPS_BASE_ADDR(X) + 0x490 + 2 * 0xb0)
+#define DDRC_PCTRL_3(X) (DDRC_IPS_BASE_ADDR(X) + 0x490 + 3 * 0xb0)
+#define DDRC_PCFGQOS0_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x494)
+#define DDRC_PCFGQOS1_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x498)
+#define DDRC_PCFGWQOS0_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x49c)
+#define DDRC_PCFGWQOS1_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x4a0)
+#define DDRC_SARBASE0(X) (DDRC_IPS_BASE_ADDR(X) + 0xf04)
+#define DDRC_SARSIZE0(X) (DDRC_IPS_BASE_ADDR(X) + 0xf08)
+#define DDRC_SBRCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0xf24)
+#define DDRC_SBRSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0xf28)
+#define DDRC_SBRWDATA0(X) (DDRC_IPS_BASE_ADDR(X) + 0xf2c)
+#define DDRC_SBRWDATA1(X) (DDRC_IPS_BASE_ADDR(X) + 0xf30)
+#define DDRC_PDCH(X) (DDRC_IPS_BASE_ADDR(X) + 0xf34)
+
+#define DDRC_FREQ1_DERATEEN(X) (DDRC_IPS_BASE_ADDR(X) + 0x2020)
+#define DDRC_FREQ1_DERATEINT(X) (DDRC_IPS_BASE_ADDR(X) + 0x2024)
+#define DDRC_FREQ1_RFSHCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x2050)
+#define DDRC_FREQ1_RFSHTMG(X) (DDRC_IPS_BASE_ADDR(X) + 0x2064)
+#define DDRC_FREQ1_INIT3(X) (DDRC_IPS_BASE_ADDR(X) + 0x20dc)
+#define DDRC_FREQ1_INIT4(X) (DDRC_IPS_BASE_ADDR(X) + 0x20e0)
+#define DDRC_FREQ1_INIT6(X) (DDRC_IPS_BASE_ADDR(X) + 0x20e8)
+#define DDRC_FREQ1_INIT7(X) (DDRC_IPS_BASE_ADDR(X) + 0x20ec)
+#define DDRC_FREQ1_DRAMTMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x2100)
+#define DDRC_FREQ1_DRAMTMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x2104)
+#define DDRC_FREQ1_DRAMTMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x2108)
+#define DDRC_FREQ1_DRAMTMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x210c)
+#define DDRC_FREQ1_DRAMTMG4(X) (DDRC_IPS_BASE_ADDR(X) + 0x2110)
+#define DDRC_FREQ1_DRAMTMG5(X) (DDRC_IPS_BASE_ADDR(X) + 0x2114)
+#define DDRC_FREQ1_DRAMTMG6(X) (DDRC_IPS_BASE_ADDR(X) + 0x2118)
+#define DDRC_FREQ1_DRAMTMG7(X) (DDRC_IPS_BASE_ADDR(X) + 0x211c)
+#define DDRC_FREQ1_DRAMTMG8(X) (DDRC_IPS_BASE_ADDR(X) + 0x2120)
+#define DDRC_FREQ1_DRAMTMG9(X) (DDRC_IPS_BASE_ADDR(X) + 0x2124)
+#define DDRC_FREQ1_DRAMTMG10(X) (DDRC_IPS_BASE_ADDR(X) + 0x2128)
+#define DDRC_FREQ1_DRAMTMG11(X) (DDRC_IPS_BASE_ADDR(X) + 0x212c)
+#define DDRC_FREQ1_DRAMTMG12(X) (DDRC_IPS_BASE_ADDR(X) + 0x2130)
+#define DDRC_FREQ1_DRAMTMG13(X) (DDRC_IPS_BASE_ADDR(X) + 0x2134)
+#define DDRC_FREQ1_DRAMTMG14(X) (DDRC_IPS_BASE_ADDR(X) + 0x2138)
+#define DDRC_FREQ1_DRAMTMG15(X) (DDRC_IPS_BASE_ADDR(X) + 0x213C)
+#define DDRC_FREQ1_DRAMTMG16(X) (DDRC_IPS_BASE_ADDR(X) + 0x2140)
+#define DDRC_FREQ1_DRAMTMG17(X) (DDRC_IPS_BASE_ADDR(X) + 0x2144)
+#define DDRC_FREQ1_ZQCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x2180)
+#define DDRC_FREQ1_DFITMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x2190)
+#define DDRC_FREQ1_DFITMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x2194)
+#define DDRC_FREQ1_DFITMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x21b4)
+#define DDRC_FREQ1_DFITMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x21b8)
+#define DDRC_FREQ1_ODTCFG(X) (DDRC_IPS_BASE_ADDR(X) + 0x2240)
+
+#define DDRC_FREQ2_DERATEEN(X) (DDRC_IPS_BASE_ADDR(X) + 0x3020)
+#define DDRC_FREQ2_DERATEINT(X) (DDRC_IPS_BASE_ADDR(X) + 0x3024)
+#define DDRC_FREQ2_RFSHCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x3050)
+#define DDRC_FREQ2_RFSHTMG(X) (DDRC_IPS_BASE_ADDR(X) + 0x3064)
+#define DDRC_FREQ2_INIT3(X) (DDRC_IPS_BASE_ADDR(X) + 0x30dc)
+#define DDRC_FREQ2_INIT4(X) (DDRC_IPS_BASE_ADDR(X) + 0x30e0)
+#define DDRC_FREQ2_INIT6(X) (DDRC_IPS_BASE_ADDR(X) + 0x30e8)
+#define DDRC_FREQ2_INIT7(X) (DDRC_IPS_BASE_ADDR(X) + 0x30ec)
+#define DDRC_FREQ2_DRAMTMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x3100)
+#define DDRC_FREQ2_DRAMTMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x3104)
+#define DDRC_FREQ2_DRAMTMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x3108)
+#define DDRC_FREQ2_DRAMTMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x310c)
+#define DDRC_FREQ2_DRAMTMG4(X) (DDRC_IPS_BASE_ADDR(X) + 0x3110)
+#define DDRC_FREQ2_DRAMTMG5(X) (DDRC_IPS_BASE_ADDR(X) + 0x3114)
+#define DDRC_FREQ2_DRAMTMG6(X) (DDRC_IPS_BASE_ADDR(X) + 0x3118)
+#define DDRC_FREQ2_DRAMTMG7(X) (DDRC_IPS_BASE_ADDR(X) + 0x311c)
+#define DDRC_FREQ2_DRAMTMG8(X) (DDRC_IPS_BASE_ADDR(X) + 0x3120)
+#define DDRC_FREQ2_DRAMTMG9(X) (DDRC_IPS_BASE_ADDR(X) + 0x3124)
+#define DDRC_FREQ2_DRAMTMG10(X) (DDRC_IPS_BASE_ADDR(X) + 0x3128)
+#define DDRC_FREQ2_DRAMTMG11(X) (DDRC_IPS_BASE_ADDR(X) + 0x312c)
+#define DDRC_FREQ2_DRAMTMG12(X) (DDRC_IPS_BASE_ADDR(X) + 0x3130)
+#define DDRC_FREQ2_DRAMTMG13(X) (DDRC_IPS_BASE_ADDR(X) + 0x3134)
+#define DDRC_FREQ2_DRAMTMG14(X) (DDRC_IPS_BASE_ADDR(X) + 0x3138)
+#define DDRC_FREQ2_DRAMTMG15(X) (DDRC_IPS_BASE_ADDR(X) + 0x313C)
+#define DDRC_FREQ2_DRAMTMG16(X) (DDRC_IPS_BASE_ADDR(X) + 0x3140)
+#define DDRC_FREQ2_DRAMTMG17(X) (DDRC_IPS_BASE_ADDR(X) + 0x3144)
+#define DDRC_FREQ2_ZQCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x3180)
+#define DDRC_FREQ2_DFITMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x3190)
+#define DDRC_FREQ2_DFITMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x3194)
+#define DDRC_FREQ2_DFITMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x31b4)
+#define DDRC_FREQ2_DFITMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x31b8)
+#define DDRC_FREQ2_ODTCFG(X) (DDRC_IPS_BASE_ADDR(X) + 0x3240)
+
+#define DDRC_FREQ3_DERATEEN(X) (DDRC_IPS_BASE_ADDR(X) + 0x4020)
+#define DDRC_FREQ3_DERATEINT(X) (DDRC_IPS_BASE_ADDR(X) + 0x4024)
+#define DDRC_FREQ3_RFSHCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x4050)
+#define DDRC_FREQ3_RFSHTMG(X) (DDRC_IPS_BASE_ADDR(X) + 0x4064)
+#define DDRC_FREQ3_INIT3(X) (DDRC_IPS_BASE_ADDR(X) + 0x40dc)
+#define DDRC_FREQ3_INIT4(X) (DDRC_IPS_BASE_ADDR(X) + 0x40e0)
+#define DDRC_FREQ3_INIT6(X) (DDRC_IPS_BASE_ADDR(X) + 0x40e8)
+#define DDRC_FREQ3_INIT7(X) (DDRC_IPS_BASE_ADDR(X) + 0x40ec)
+#define DDRC_FREQ3_DRAMTMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x4100)
+#define DDRC_FREQ3_DRAMTMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x4104)
+#define DDRC_FREQ3_DRAMTMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x4108)
+#define DDRC_FREQ3_DRAMTMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x410c)
+#define DDRC_FREQ3_DRAMTMG4(X) (DDRC_IPS_BASE_ADDR(X) + 0x4110)
+#define DDRC_FREQ3_DRAMTMG5(X) (DDRC_IPS_BASE_ADDR(X) + 0x4114)
+#define DDRC_FREQ3_DRAMTMG6(X) (DDRC_IPS_BASE_ADDR(X) + 0x4118)
+#define DDRC_FREQ3_DRAMTMG7(X) (DDRC_IPS_BASE_ADDR(X) + 0x411c)
+#define DDRC_FREQ3_DRAMTMG8(X) (DDRC_IPS_BASE_ADDR(X) + 0x4120)
+#define DDRC_FREQ3_DRAMTMG9(X) (DDRC_IPS_BASE_ADDR(X) + 0x4124)
+#define DDRC_FREQ3_DRAMTMG10(X) (DDRC_IPS_BASE_ADDR(X) + 0x4128)
+#define DDRC_FREQ3_DRAMTMG11(X) (DDRC_IPS_BASE_ADDR(X) + 0x412c)
+#define DDRC_FREQ3_DRAMTMG12(X) (DDRC_IPS_BASE_ADDR(X) + 0x4130)
+#define DDRC_FREQ3_DRAMTMG13(X) (DDRC_IPS_BASE_ADDR(X) + 0x4134)
+#define DDRC_FREQ3_DRAMTMG14(X) (DDRC_IPS_BASE_ADDR(X) + 0x4138)
+#define DDRC_FREQ3_DRAMTMG15(X) (DDRC_IPS_BASE_ADDR(X) + 0x413C)
+#define DDRC_FREQ3_DRAMTMG16(X) (DDRC_IPS_BASE_ADDR(X) + 0x4140)
+
+#define DDRC_FREQ3_ZQCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x4180)
+#define DDRC_FREQ3_DFITMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x4190)
+#define DDRC_FREQ3_DFITMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x4194)
+#define DDRC_FREQ3_DFITMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x41b4)
+#define DDRC_FREQ3_DFITMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x41b8)
+#define DDRC_FREQ3_ODTCFG(X) (DDRC_IPS_BASE_ADDR(X) + 0x4240)
+#define DDRC_DFITMG0_SHADOW(X) (DDRC_IPS_BASE_ADDR(X) + 0x2190)
+#define DDRC_DFITMG1_SHADOW(X) (DDRC_IPS_BASE_ADDR(X) + 0x2194)
+#define DDRC_DFITMG2_SHADOW(X) (DDRC_IPS_BASE_ADDR(X) + 0x21b4)
+#define DDRC_DFITMG3_SHADOW(X) (DDRC_IPS_BASE_ADDR(X) + 0x21b8)
+#define DDRC_ODTCFG_SHADOW(X) (DDRC_IPS_BASE_ADDR(X) + 0x2240)
+
+#define DDRPHY_CalBusy(X) (IP2APB_DDRPHY_IPS_BASE_ADDR(X) + 4 * 0x020097)
+
+#define DRC_PERF_MON_BASE_ADDR(X) (0x3d800000 + ((X) * 0x2000000))
+#define DRC_PERF_MON_CNT0_CTL(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x0)
+#define DRC_PERF_MON_CNT1_CTL(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x4)
+#define DRC_PERF_MON_CNT2_CTL(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x8)
+#define DRC_PERF_MON_CNT3_CTL(X) (DRC_PERF_MON_BASE_ADDR(X) + 0xC)
+#define DRC_PERF_MON_CNT0_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x20)
+#define DRC_PERF_MON_CNT1_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x24)
+#define DRC_PERF_MON_CNT2_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x28)
+#define DRC_PERF_MON_CNT3_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x2C)
+#define DRC_PERF_MON_MRR0_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x40)
+#define DRC_PERF_MON_MRR1_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x44)
+#define DRC_PERF_MON_MRR2_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x48)
+#define DRC_PERF_MON_MRR3_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x4C)
+#define DRC_PERF_MON_MRR4_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x50)
+#define DRC_PERF_MON_MRR5_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x54)
+#define DRC_PERF_MON_MRR6_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x58)
+#define DRC_PERF_MON_MRR7_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x5C)
+#define DRC_PERF_MON_MRR8_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x60)
+#define DRC_PERF_MON_MRR9_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x64)
+#define DRC_PERF_MON_MRR10_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x68)
+#define DRC_PERF_MON_MRR11_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x6C)
+#define DRC_PERF_MON_MRR12_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x70)
+#define DRC_PERF_MON_MRR13_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x74)
+#define DRC_PERF_MON_MRR14_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x78)
+#define DRC_PERF_MON_MRR15_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x7C)
+
+#define DDRC_IPS_BASE_ADDR(X) (0x3d400000 + (X * 0x2000000))
+
+/* user data type */
+enum fw_type {
+ FW_1D_IMAGE,
+ FW_2D_IMAGE,
+};
+
+struct dram_cfg_param {
+ unsigned int reg;
+ unsigned int val;
+};
+
+struct dram_fsp_msg {
+ unsigned int drate;
+ enum fw_type fw_type;
+ struct dram_cfg_param *fsp_cfg;
+ unsigned int fsp_cfg_num;
+};
+
+struct dram_timing_info {
+ /* umctl2 config */
+ struct dram_cfg_param *ddrc_cfg;
+ unsigned int ddrc_cfg_num;
+ /* ddrphy config */
+ struct dram_cfg_param *ddrphy_cfg;
+ unsigned int ddrphy_cfg_num;
+ /* ddr fsp train info */
+ struct dram_fsp_msg *fsp_msg;
+ unsigned int fsp_msg_num;
+ /* ddr phy trained CSR */
+ struct dram_cfg_param *ddrphy_trained_csr;
+ unsigned int ddrphy_trained_csr_num;
+ /* ddr phy PIE */
+ struct dram_cfg_param *ddrphy_pie;
+ unsigned int ddrphy_pie_num;
+ /* initialized drate table */
+ unsigned int fsp_table[4];
+};
+
+extern struct dram_timing_info dram_timing;
+
+int imx8mm_ddr_init(struct dram_timing_info *timing_info);
+int imx8mq_ddr_init(struct dram_timing_info *timing_info);
+int ddr_cfg_phy(struct dram_timing_info *timing_info);
+void load_lpddr4_phy_pie(void);
+void ddrphy_trained_csr_save(struct dram_cfg_param *param, unsigned int num);
+void dram_config_save(struct dram_timing_info *info, unsigned long base);
+
+/* utils function for ddr phy training */
+int wait_ddrphy_training_complete(void);
+void ddrphy_init_set_dfi_clk(unsigned int drate);
+void ddrphy_init_read_msg_block(enum fw_type type);
+
+#define reg32_write(a, v) writel(v, a)
+#define reg32_read(a) readl(a)
+
+static inline void reg32setbit(unsigned long addr, u32 bit)
+{
+ setbits_le32(addr, (1 << bit));
+}
+
+#define dwc_ddrphy_apb_wr(addr, data) \
+ reg32_write(IOMEM(IP2APB_DDRPHY_IPS_BASE_ADDR(0)) + 4 * (addr), data)
+#define dwc_ddrphy_apb_rd(addr) \
+ reg32_read(IOMEM(IP2APB_DDRPHY_IPS_BASE_ADDR(0)) + 4 * (addr))
+
+extern struct dram_cfg_param ddrphy_trained_csr[];
+extern uint32_t ddrphy_trained_csr_num;
+
+enum ddrc_phy_firmware_offset {
+ DDRC_PHY_IMEM = 0x00050000U,
+ DDRC_PHY_DMEM = 0x00054000U,
+};
+
+void ddr_load_train_code(enum fw_type type);
+
+void ddrc_phy_load_firmware(void __iomem *,
+ enum ddrc_phy_firmware_offset,
+ const u16 *, size_t);
+
+#define DDRC_PHY_REG(x) ((x) * 4)
+
+#endif
diff --git a/include/soc/imx8m/lpddr4_define.h b/include/soc/imx8m/lpddr4_define.h
new file mode 100644
index 0000000..caf5baf
--- /dev/null
+++ b/include/soc/imx8m/lpddr4_define.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 NXP
+ */
+
+#ifndef __LPDDR4_DEFINE_H_
+#define __LPDDR4_DEFINE_H_
+
+#define LPDDR4_DVFS_DBI
+#define DDR_ONE_RANK
+/* #define LPDDR4_DBI_ON */
+#define DFI_BUG_WR
+#define M845S_4GBx2
+#define PRETRAIN
+
+/* DRAM MR setting */
+#ifdef LPDDR4_DBI_ON
+#define LPDDR4_MR3 0xf1
+#define LPDDR4_PHY_DMIPinPresent 0x1
+#else
+#define LPDDR4_MR3 0x31
+#define LPDDR4_PHY_DMIPinPresent 0x0
+#endif
+
+#ifdef DDR_ONE_RANK
+#define LPDDR4_CS 0x1
+#else
+#define LPDDR4_CS 0x3
+#endif
+
+/* PHY training feature */
+#define LPDDR4_HDT_CTL_2D 0xC8
+#define LPDDR4_HDT_CTL_3200_1D 0xC8
+#define LPDDR4_HDT_CTL_400_1D 0xC8
+#define LPDDR4_HDT_CTL_100_1D 0xC8
+
+/* 400/100 training seq */
+#define LPDDR4_TRAIN_SEQ_P2 0x121f
+#define LPDDR4_TRAIN_SEQ_P1 0x121f
+#define LPDDR4_TRAIN_SEQ_P0 0x121f
+#define LPDDR4_TRAIN_SEQ_100 0x121f
+#define LPDDR4_TRAIN_SEQ_400 0x121f
+
+/* 2D share & weight */
+#define LPDDR4_2D_WEIGHT 0x1f7f
+#define LPDDR4_2D_SHARE 1
+#define LPDDR4_CATRAIN_3200_1d 0
+#define LPDDR4_CATRAIN_400 0
+#define LPDDR4_CATRAIN_100 0
+#define LPDDR4_CATRAIN_3200_2d 0
+
+/* MRS parameter */
+/* for LPDDR4 Rtt */
+#define LPDDR4_RTT40 6
+#define LPDDR4_RTT48 5
+#define LPDDR4_RTT60 4
+#define LPDDR4_RTT80 3
+#define LPDDR4_RTT120 2
+#define LPDDR4_RTT240 1
+#define LPDDR4_RTT_DIS 0
+
+/* for LPDDR4 Ron */
+#define LPDDR4_RON34 7
+#define LPDDR4_RON40 6
+#define LPDDR4_RON48 5
+#define LPDDR4_RON60 4
+#define LPDDR4_RON80 3
+
+#define LPDDR4_PHY_ADDR_RON60 0x1
+#define LPDDR4_PHY_ADDR_RON40 0x3
+#define LPDDR4_PHY_ADDR_RON30 0x7
+#define LPDDR4_PHY_ADDR_RON24 0xf
+#define LPDDR4_PHY_ADDR_RON20 0x1f
+
+/* for read channel */
+#define LPDDR4_RON LPDDR4_RON40
+#define LPDDR4_PHY_RTT 30
+#define LPDDR4_PHY_VREF_VALUE 17
+
+/* for write channel */
+#define LPDDR4_PHY_RON 30
+#define LPDDR4_PHY_ADDR_RON LPDDR4_PHY_ADDR_RON40
+#define LPDDR4_RTT_DQ LPDDR4_RTT40
+#define LPDDR4_RTT_CA LPDDR4_RTT40
+#define LPDDR4_RTT_CA_BANK0 LPDDR4_RTT40
+#define LPDDR4_RTT_CA_BANK1 LPDDR4_RTT40
+#define LPDDR4_VREF_VALUE_CA ((1 << 6) | (0xd))
+#define LPDDR4_VREF_VALUE_DQ_RANK0 ((1 << 6) | (0xd))
+#define LPDDR4_VREF_VALUE_DQ_RANK1 ((1 << 6) | (0xd))
+#define LPDDR4_MR22_RANK0 ((0 << 5) | (1 << 4) | (0 << 3) | \
+ (LPDDR4_RTT40))
+#define LPDDR4_MR22_RANK1 ((1 << 5) | (1 << 4) | (1 << 3) | \
+ (LPDDR4_RTT40))
+
+#define LPDDR4_MR3_PU_CAL 1
+
+#endif /* __LPDDR4_DEFINE_H__ */