[U-Boot] [PATCH 14/15] drivers: ddr: introduce DDR driver for i.MX8M
Peng Fan
peng.fan at nxp.com
Fri Nov 9 09:17:02 UTC 2018
Introduce DDR driver for i.MX8M. The driver will be used by SPL to
initialze DDR PHY and DDR Controller.
Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
arch/arm/include/asm/arch-imx8m/ddr.h | 575 ++++++++++++++++++++++++++++++++++
drivers/Makefile | 1 +
drivers/ddr/Kconfig | 1 +
drivers/ddr/imx/Kconfig | 1 +
drivers/ddr/imx/imx8m/Kconfig | 22 ++
drivers/ddr/imx/imx8m/Makefile | 11 +
drivers/ddr/imx/imx8m/ddr4_init.c | 113 +++++++
drivers/ddr/imx/imx8m/ddrphy_train.c | 87 +++++
drivers/ddr/imx/imx8m/ddrphy_utils.c | 186 +++++++++++
drivers/ddr/imx/imx8m/helper.c | 171 ++++++++++
drivers/ddr/imx/imx8m/lpddr4_init.c | 188 +++++++++++
11 files changed, 1356 insertions(+)
create mode 100644 drivers/ddr/imx/Kconfig
create mode 100644 drivers/ddr/imx/imx8m/Kconfig
create mode 100644 drivers/ddr/imx/imx8m/Makefile
create mode 100644 drivers/ddr/imx/imx8m/ddr4_init.c
create mode 100644 drivers/ddr/imx/imx8m/ddrphy_train.c
create mode 100644 drivers/ddr/imx/imx8m/ddrphy_utils.c
create mode 100644 drivers/ddr/imx/imx8m/helper.c
create mode 100644 drivers/ddr/imx/imx8m/lpddr4_init.c
diff --git a/arch/arm/include/asm/arch-imx8m/ddr.h b/arch/arm/include/asm/arch-imx8m/ddr.h
index 1a5cbabdaf..c7da3017ba 100644
--- a/arch/arm/include/asm/arch-imx8m/ddr.h
+++ b/arch/arm/include/asm/arch-imx8m/ddr.h
@@ -6,6 +6,10 @@
#ifndef __ASM_ARCH_IMX8M_DDR_H
#define __ASM_ARCH_IMX8M_DDR_H
+#include <asm/io.h>
+#include <asm/types.h>
+#include <asm/arch/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))
@@ -352,4 +356,575 @@ enum msg_response {
TRAIN_FAIL = 0xff,
};
+#define DDRC_MSTR_0 0x3d400000
+#define DDRC_STAT_0 0x3d400004
+#define DDRC_MSTR1_0 0x3d400008
+#define DDRC_MRCTRL0_0 0x3d400010
+#define DDRC_MRCTRL1_0 0x3d400014
+#define DDRC_MRSTAT_0 0x3d400018
+#define DDRC_MRCTRL2_0 0x3d40001c
+#define DDRC_DERATEEN_0 0x3d400020
+#define DDRC_DERATEINT_0 0x3d400024
+#define DDRC_MSTR2_0 0x3d400028
+#define DDRC_PWRCTL_0 0x3d400030
+#define DDRC_PWRTMG_0 0x3d400034
+#define DDRC_HWLPCTL_0 0x3d400038
+#define DDRC_HWFFCCTL_0 0x3d40003c
+#define DDRC_HWFFCSTAT_0 0x3d400040
+#define DDRC_RFSHCTL0_0 0x3d400050
+#define DDRC_RFSHCTL1_0 0x3d400054
+#define DDRC_RFSHCTL2_0 0x3d400058
+#define DDRC_RFSHCTL3_0 0x3d400060
+#define DDRC_RFSHTMG_0 0x3d400064
+#define DDRC_ECCCFG0_0 0x3d400070
+#define DDRC_ECCCFG1_0 0x3d400074
+#define DDRC_ECCSTAT_0 0x3d400078
+#define DDRC_ECCCLR_0 0x3d40007c
+#define DDRC_ECCERRCNT_0 0x3d400080
+#define DDRC_ECCCADDR0_0 0x3d400084
+#define DDRC_ECCCADDR1_0 0x3d400088
+#define DDRC_ECCCSYN0_0 0x3d40008c
+#define DDRC_ECCCSYN1_0 0x3d400090
+#define DDRC_ECCCSYN2_0 0x3d400094
+#define DDRC_ECCBITMASK0_0 0x3d400098
+#define DDRC_ECCBITMASK1_0 0x3d40009c
+#define DDRC_ECCBITMASK2_0 0x3d4000a0
+#define DDRC_ECCUADDR0_0 0x3d4000a4
+#define DDRC_ECCUADDR1_0 0x3d4000a8
+#define DDRC_ECCUSYN0_0 0x3d4000ac
+#define DDRC_ECCUSYN1_0 0x3d4000b0
+#define DDRC_ECCUSYN2_0 0x3d4000b4
+#define DDRC_ECCPOISONADDR0_0 0x3d4000b8
+#define DDRC_ECCPOISONADDR1_0 0x3d4000bc
+#define DDRC_CRCPARCTL0_0 0x3d4000c0
+#define DDRC_CRCPARCTL1_0 0x3d4000c4
+#define DDRC_CRCPARCTL2_0 0x3d4000c8
+#define DDRC_CRCPARSTAT_0 0x3d4000cc
+#define DDRC_INIT0_0 0x3d4000d0
+#define DDRC_INIT1_0 0x3d4000d4
+#define DDRC_INIT2_0 0x3d4000d8
+#define DDRC_INIT3_0 0x3d4000dc
+#define DDRC_INIT4_0 0x3d4000e0
+#define DDRC_INIT5_0 0x3d4000e4
+#define DDRC_INIT6_0 0x3d4000e8
+#define DDRC_INIT7_0 0x3d4000ec
+#define DDRC_DIMMCTL_0 0x3d4000f0
+#define DDRC_RANKCTL_0 0x3d4000f4
+#define DDRC_DRAMTMG0_0 0x3d400100
+#define DDRC_DRAMTMG1_0 0x3d400104
+#define DDRC_DRAMTMG2_0 0x3d400108
+#define DDRC_DRAMTMG3_0 0x3d40010c
+#define DDRC_DRAMTMG4_0 0x3d400110
+#define DDRC_DRAMTMG5_0 0x3d400114
+#define DDRC_DRAMTMG6_0 0x3d400118
+#define DDRC_DRAMTMG7_0 0x3d40011c
+#define DDRC_DRAMTMG8_0 0x3d400120
+#define DDRC_DRAMTMG9_0 0x3d400124
+#define DDRC_DRAMTMG10_0 0x3d400128
+#define DDRC_DRAMTMG11_0 0x3d40012c
+#define DDRC_DRAMTMG12_0 0x3d400130
+#define DDRC_DRAMTMG13_0 0x3d400134
+#define DDRC_DRAMTMG14_0 0x3d400138
+#define DDRC_DRAMTMG15_0 0x3d40013C
+#define DDRC_DRAMTMG16_0 0x3d400140
+#define DDRC_DRAMTMG17_0 0x3d400144
+
+#define DDRC_ZQCTL0_0 0x3d400180
+#define DDRC_ZQCTL1_0 0x3d400184
+#define DDRC_ZQCTL2_0 0x3d400188
+#define DDRC_ZQSTAT_0 0x3d40018c
+#define DDRC_DFITMG0_0 0x3d400190
+#define DDRC_DFITMG1_0 0x3d400194
+#define DDRC_DFILPCFG0_0 0x3d400198
+#define DDRC_DFILPCFG1_0 0x3d40019c
+#define DDRC_DFIUPD0_0 0x3d4001a0
+#define DDRC_DFIUPD1_0 0x3d4001a4
+#define DDRC_DFIUPD2_0 0x3d4001a8
+
+#define DDRC_DFIMISC_0 0x3d4001b0
+#define DDRC_DFITMG2_0 0x3d4001b4
+#define DDRC_DFITMG3_0 0x3d4001b8
+#define DDRC_DFISTAT_0 0x3d4001bc
+
+#define DDRC_DBICTL_0 0x3d4001c0
+#define DDRC_DFIPHYMSTR_0 0x3d4001c4
+#define DDRC_TRAINCTL0_0 0x3d4001d0
+#define DDRC_TRAINCTL1_0 0x3d4001d4
+#define DDRC_TRAINCTL2_0 0x3d4001d8
+#define DDRC_TRAINSTAT_0 0x3d4001dc
+#define DDRC_ADDRMAP0_0 0x3d400200
+#define DDRC_ADDRMAP1_0 0x3d400204
+#define DDRC_ADDRMAP2_0 0x3d400208
+#define DDRC_ADDRMAP3_0 0x3d40020c
+#define DDRC_ADDRMAP4_0 0x3d400210
+#define DDRC_ADDRMAP5_0 0x3d400214
+#define DDRC_ADDRMAP6_0 0x3d400218
+#define DDRC_ADDRMAP7_0 0x3d40021c
+#define DDRC_ADDRMAP8_0 0x3d400220
+#define DDRC_ADDRMAP9_0 0x3d400224
+#define DDRC_ADDRMAP10_0 0x3d400228
+#define DDRC_ADDRMAP11_0 0x3d40022c
+
+#define DDRC_ODTCFG_0 0x3d400240
+#define DDRC_ODTMAP_0 0x3d400244
+#define DDRC_SCHED_0 0x3d400250
+#define DDRC_SCHED1_0 0x3d400254
+#define DDRC_PERFHPR1_0 0x3d40025c
+#define DDRC_PERFLPR1_0 0x3d400264
+#define DDRC_PERFWR1_0 0x3d40026c
+#define DDRC_PERFVPR1_0 0x3d400274
+
+#define DDRC_PERFVPW1_0 0x3d400278
+
+#define DDRC_DQMAP0_0 0x3d400280
+#define DDRC_DQMAP1_0 0x3d400284
+#define DDRC_DQMAP2_0 0x3d400288
+#define DDRC_DQMAP3_0 0x3d40028c
+#define DDRC_DQMAP4_0 0x3d400290
+#define DDRC_DQMAP5_0 0x3d400294
+#define DDRC_DBG0_0 0x3d400300
+#define DDRC_DBG1_0 0x3d400304
+#define DDRC_DBGCAM_0 0x3d400308
+#define DDRC_DBGCMD_0 0x3d40030c
+#define DDRC_DBGSTAT_0 0x3d400310
+
+#define DDRC_SWCTL_0 0x3d400320
+#define DDRC_SWSTAT_0 0x3d400324
+#define DDRC_OCPARCFG0_0 0x3d400330
+#define DDRC_OCPARCFG1_0 0x3d400334
+#define DDRC_OCPARCFG2_0 0x3d400338
+#define DDRC_OCPARCFG3_0 0x3d40033c
+#define DDRC_OCPARSTAT0_0 0x3d400340
+#define DDRC_OCPARSTAT1_0 0x3d400344
+#define DDRC_OCPARWLOG0_0 0x3d400348
+#define DDRC_OCPARWLOG1_0 0x3d40034c
+#define DDRC_OCPARWLOG2_0 0x3d400350
+#define DDRC_OCPARAWLOG0_0 0x3d400354
+#define DDRC_OCPARAWLOG1_0 0x3d400358
+#define DDRC_OCPARRLOG0_0 0x3d40035c
+#define DDRC_OCPARRLOG1_0 0x3d400360
+#define DDRC_OCPARARLOG0_0 0x3d400364
+#define DDRC_OCPARARLOG1_0 0x3d400368
+#define DDRC_POISONCFG_0 0x3d40036C
+#define DDRC_POISONSTAT_0 0x3d400370
+#define DDRC_ADVECCINDEX_0 0x3d400003
+#define DDRC_ADVECCSTAT_0 0x3d400003
+#define DDRC_ECCPOISONPAT0_0 0x3d400003
+#define DDRC_ECCPOISONPAT1_0 0x3d400003
+#define DDRC_ECCPOISONPAT2_0 0x3d400003
+#define DDRC_HIFCTL_0 0x3d400003
+
+#define DDRC_PSTAT_0 0x3d4003fc
+#define DDRC_PCCFG_0 0x3d400400
+#define DDRC_PCFGR_0_0 0x3d400404
+#define DDRC_PCFGR_1_0 0x3d4004b4
+#define DDRC_PCFGR_2_0 0x3d400564
+#define DDRC_PCFGR_3_0 0x3d400614
+#define DDRC_PCFGW_0_0 0x3d400408
+#define DDRC_PCFGW_1_0 0x3d400408
+#define DDRC_PCFGW_2_0 0x3d400568
+#define DDRC_PCFGW_3_0 0x3d400618
+#define DDRC_PCFGC_0_0 0x3d40040c
+#define DDRC_PCFGIDMASKCH_0 0x3d400410
+#define DDRC_PCFGIDVALUECH_0 0x3d400414
+#define DDRC_PCTRL_0_0 0x3d400490
+#define DDRC_PCTRL_1_0 0x3d400540
+#define DDRC_PCTRL_2_0 0x3d4005f0
+#define DDRC_PCTRL_3_0 0x3d4006a0
+#define DDRC_PCFGQOS0_0_0 0x3d400494
+#define DDRC_PCFGQOS1_0_0 0x3d400498
+#define DDRC_PCFGWQOS0_0_0 0x3d40049c
+#define DDRC_PCFGWQOS1_0_0 0x3d4004a0
+#define DDRC_SARBASE0_0 0x3d400f04
+#define DDRC_SARSIZE0_0 0x3d400f08
+#define DDRC_SBRCTL_0 0x3d400f24
+#define DDRC_SBRSTAT_0 0x3d400f28
+#define DDRC_SBRWDATA0_0 0x3d400f2c
+#define DDRC_SBRWDATA1_0 0x3d400f30
+#define DDRC_PDCH_0 0x3d400f34
+
+/**********************/
+#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_ADVECCINDEX(X) (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_ADVECCSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_ECCPOISONPAT0(X) (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_ECCPOISONPAT1(X) (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_ECCPOISONPAT2(X) (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_HIFCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x3)
+
+#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)
+
+/* 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;
+
+void ddr_load_train_firmware(enum fw_type type);
+void ddr_init(struct dram_timing_info *timing_info);
+void 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 */
+void wait_ddrphy_training_complete(void);
+void ddrphy_init_set_dfi_clk(unsigned int drate);
+void ddrphy_init_read_msg_block(enum fw_type type);
+
+static inline void reg32_write(unsigned long addr, u32 val)
+{
+ writel(val, addr);
+}
+
+static inline u32 reg32_read(unsigned long addr)
+{
+ return readl(addr);
+}
+
+static inline void reg32setbit(unsigned long addr, u32 bit)
+{
+ setbits_le32(addr, (1 << bit));
+}
+
+#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))
#endif
diff --git a/drivers/Makefile b/drivers/Makefile
index fb38b67541..f0c57f937e 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
obj-$(CONFIG_ARMADA_38X) += ddr/marvell/a38x/
obj-$(CONFIG_ARMADA_XP) += ddr/marvell/axp/
obj-$(CONFIG_ALTERA_SDRAM) += ddr/altera/
+obj-$(CONFIG_ARCH_IMX8M) += ddr/imx/imx8m/
obj-$(CONFIG_SPL_POWER_SUPPORT) += power/ power/pmic/
obj-$(CONFIG_SPL_POWER_SUPPORT) += power/regulator/
obj-$(CONFIG_SPL_POWER_DOMAIN) += power/domain/
diff --git a/drivers/ddr/Kconfig b/drivers/ddr/Kconfig
index b764add060..d4b393d25e 100644
--- a/drivers/ddr/Kconfig
+++ b/drivers/ddr/Kconfig
@@ -1 +1,2 @@
source "drivers/ddr/altera/Kconfig"
+source "drivers/ddr/imx/Kconfig"
diff --git a/drivers/ddr/imx/Kconfig b/drivers/ddr/imx/Kconfig
new file mode 100644
index 0000000000..7e06fb2f7d
--- /dev/null
+++ b/drivers/ddr/imx/Kconfig
@@ -0,0 +1 @@
+source "drivers/ddr/imx/imx8m/Kconfig"
diff --git a/drivers/ddr/imx/imx8m/Kconfig b/drivers/ddr/imx/imx8m/Kconfig
new file mode 100644
index 0000000000..71f466f5ec
--- /dev/null
+++ b/drivers/ddr/imx/imx8m/Kconfig
@@ -0,0 +1,22 @@
+config IMX8M_DRAM
+ bool "imx8m dram"
+
+config IMX8M_LPDDR4
+ bool "imx8m lpddr4"
+ select IMX8M_DRAM
+ help
+ Select the i.MX8M LPDDR4 driver support on i.MX8M SOC.
+
+config IMX8M_DDR4
+ bool "imx8m ddr4"
+ select IMX8M_DRAM
+ help
+ Select the i.MX8M DDR4 driver support on i.MX8M SOC.
+
+config SAVED_DRAM_TIMING_BASE
+ hex "Define the base address for saved dram timing"
+ help
+ after DRAM is trained, need to save the dram related timming
+ info into memory for low power use. OCRAM_S is used for this
+ purpose on i.MX8MM.
+ default 0x180000
diff --git a/drivers/ddr/imx/imx8m/Makefile b/drivers/ddr/imx/imx8m/Makefile
new file mode 100644
index 0000000000..079e143f6d
--- /dev/null
+++ b/drivers/ddr/imx/imx8m/Makefile
@@ -0,0 +1,11 @@
+#
+# Copyright 2018 NXP
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_IMX8M_DRAM) += helper.o ddrphy_utils.o ddrphy_train.o
+obj-$(CONFIG_IMX8M_LPDDR4) += lpddr4_init.o
+obj-$(CONFIG_IMX8M_DDR4) += ddr4_init.o
+endif
diff --git a/drivers/ddr/imx/imx8m/ddr4_init.c b/drivers/ddr/imx/imx8m/ddr4_init.c
new file mode 100644
index 0000000000..031cdc57e1
--- /dev/null
+++ b/drivers/ddr/imx/imx8m/ddr4_init.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/ddr.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx8m_ddr.h>
+#include <asm/arch/sys_proto.h>
+
+void ddr4_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num)
+{
+ int i = 0;
+
+ for (i = 0; i < num; i++) {
+ reg32_write(ddrc_cfg->reg, ddrc_cfg->val);
+ ddrc_cfg++;
+ }
+}
+
+void ddr_init(struct dram_timing_info *dram_timing)
+{
+ volatile unsigned int tmp_t;
+ /*
+ * 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, 0x8F00003F);
+ /* deassert [4]src_system_rst_b! */
+ reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
+
+ /*
+ * change the clock source of dram_apb_clk_root
+ * to source 4 --800MHz/4
+ */
+ clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON |
+ CLK_ROOT_SOURCE_SEL(4) |
+ CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4));
+
+ dram_pll_init(DRAM_PLL_OUT_600M);
+
+ reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */
+ reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */
+
+ /* release [0]ddr1_preset_n, [3]ddr1_phy_pwrokin_n */
+ reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
+
+ reg32_write(DDRC_DBG1(0), 0x00000001);
+ reg32_write(DDRC_PWRCTL(0), 0x00000001);
+
+ while (0 != (0x7 & reg32_read(DDRC_STAT(0))))
+ ;
+
+ /* config the uMCTL2's registers */
+ ddr4_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num);
+
+ reg32_write(DDRC_RFSHCTL3(0), 0x00000001);
+ /* 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);
+
+ /* config the DDR PHY's registers */
+ ddr_cfg_phy(dram_timing);
+
+ do {
+ tmp_t = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) +
+ 4 * 0x00020097);
+ } while (tmp_t != 0);
+
+ reg32_write(DDRC_DFIMISC(0), 0x00000020);
+
+ /* wait DFISTAT.dfi_init_complete to 1 */
+ 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);
+ /* dis_auto-refresh is set to 0 */
+ reg32_write(DDRC_RFSHCTL3(0), 0x00000000);
+
+ /* save the dram timing config into memory */
+ dram_config_save(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE);
+}
diff --git a/drivers/ddr/imx/imx8m/ddrphy_train.c b/drivers/ddr/imx/imx8m/ddrphy_train.c
new file mode 100644
index 0000000000..f48804e6cd
--- /dev/null
+++ b/drivers/ddr/imx/imx8m/ddrphy_train.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <common.h>
+#include <linux/kernel.h>
+#include <asm/arch/ddr.h>
+#include <asm/arch/lpddr4_define.h>
+
+void 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;
+
+ /* 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_firmware(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 */
+ wait_ddrphy_training_complete();
+
+ /* 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(dram_timing->ddrphy_trained_csr,
+ dram_timing->ddrphy_trained_csr_num);
+}
diff --git a/drivers/ddr/imx/imx8m/ddrphy_utils.c b/drivers/ddr/imx/imx8m/ddrphy_utils.c
new file mode 100644
index 0000000000..e65bf0c460
--- /dev/null
+++ b/drivers/ddr/imx/imx8m/ddrphy_utils.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+* Copyright 2018 NXP
+*/
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/ddr.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/ddr.h>
+#include <asm/arch/lpddr4_define.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_receive(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_receive();
+
+ 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_receive();
+
+ return reg2;
+}
+
+static inline void decode_major_message(unsigned int mail)
+{
+ debug("[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();
+ debug("PMU String index = 0x%08x\n", string_index);
+ while (i < (string_index & 0xffff)) {
+ arg = get_stream_message();
+ debug("arg[%d] = 0x%08x\n", i, arg);
+ i++;
+ }
+
+ debug("\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) {
+ debug("Training PASS\n");
+ break;
+ } else if (mail == 0xff) {
+ printf("Training FAILED\n");
+ break;
+ }
+ }
+}
+
+void ddrphy_init_set_dfi_clk(unsigned int drate)
+{
+ switch (drate) {
+ case 3200:
+ dram_pll_init(DRAM_PLL_OUT_800M);
+ dram_disable_bypass();
+ break;
+ case 3000:
+ dram_pll_init(DRAM_PLL_OUT_750M);
+ dram_disable_bypass();
+ break;
+ case 2400:
+ dram_pll_init(DRAM_PLL_OUT_600M);
+ dram_disable_bypass();
+ break;
+ case 1600:
+ dram_pll_init(DRAM_PLL_OUT_400M);
+ dram_disable_bypass();
+ break;
+ case 667:
+ dram_pll_init(DRAM_PLL_OUT_167M);
+ dram_disable_bypass();
+ break;
+ case 400:
+ dram_enable_bypass(DRAM_BYPASSCLK_400M);
+ break;
+ case 100:
+ dram_enable_bypass(DRAM_BYPASSCLK_100M);
+ break;
+ default:
+ return;
+ }
+}
+
+void ddrphy_init_read_msg_block(enum fw_type type)
+{
+}
+
+void lpddr4_mr_write(unsigned int mr_rank, unsigned int mr_addr,
+ unsigned int mr_data)
+{
+ unsigned int tmp;
+ /*
+ * 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.
+ */
+ reg32_write(DDRC_MRCTRL0(0), (mr_rank << 4));
+ reg32_write(DDRC_MRCTRL1(0), (mr_addr << 8) | mr_data);
+ reg32setbit(DDRC_MRCTRL0(0), 31);
+}
+
+unsigned int lpddr4_mr_read(unsigned int mr_rank, unsigned int mr_addr)
+{
+ unsigned int tmp;
+
+ reg32_write(DRC_PERF_MON_MRR0_DAT(0), 0x1);
+ do {
+ tmp = reg32_read(DDRC_MRSTAT(0));
+ } while (tmp & 0x1);
+
+ reg32_write(DDRC_MRCTRL0(0), (mr_rank << 4) | 0x1);
+ reg32_write(DDRC_MRCTRL1(0), (mr_addr << 8));
+ reg32setbit(DDRC_MRCTRL0(0), 31);
+ do {
+ tmp = reg32_read(DRC_PERF_MON_MRR0_DAT(0));
+ } while ((tmp & 0x8) == 0);
+ tmp = reg32_read(DRC_PERF_MON_MRR1_DAT(0));
+ tmp = tmp & 0xff;
+ reg32_write(DRC_PERF_MON_MRR0_DAT(0), 0x4);
+
+ return tmp;
+}
diff --git a/drivers/ddr/imx/imx8m/helper.c b/drivers/ddr/imx/imx8m/helper.c
new file mode 100644
index 0000000000..574fe84a04
--- /dev/null
+++ b/drivers/ddr/imx/imx8m/helper.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/ddr.h>
+#include <asm/arch/ddr.h>
+#include <asm/arch/lpddr4_define.h>
+#include <asm/sections.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#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)
+
+/* We need PHY iMEM PHY is 32KB padded */
+void ddr_load_train_firmware(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;
+ }
+
+ debug("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)) {
+ debug("%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
+ debug("check ddr4_pmu_train_imem code pass\n");
+
+ debug("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)) {
+ debug("%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
+ debug("check ddr4_pmu_train_dmem code pass\n");
+}
+
+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 = (struct dram_timing_info *)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 =
+ timing_info->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 < timing_info->ddrphy_trained_csr_num; i++) {
+ cfg->reg = timing_info->ddrphy_trained_csr[i].reg;
+ cfg->val = timing_info->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/drivers/ddr/imx/imx8m/lpddr4_init.c b/drivers/ddr/imx/imx8m/lpddr4_init.c
new file mode 100644
index 0000000000..d1cfcb95b5
--- /dev/null
+++ b/drivers/ddr/imx/imx8m/lpddr4_init.c
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+* Copyright 2018 NXP
+*
+*/
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/ddr.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/ddr.h>
+#include <asm/arch/lpddr4_define.h>
+#include <asm/arch/sys_proto.h>
+
+void lpddr4_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num)
+{
+ int i = 0;
+
+ for (i = 0; i < num; i++) {
+ reg32_write(ddrc_cfg->reg, ddrc_cfg->val);
+ ddrc_cfg++;
+ }
+}
+
+void ddr_init(struct dram_timing_info *dram_timing)
+{
+ unsigned int tmp;
+
+ debug("DDRINFO: start lpddr4 ddr init\n");
+ /* step 1: reset */
+ if (is_imx8mq()) {
+ reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F00000F);
+ reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
+ reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000);
+ } else {
+ reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00001F);
+ reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
+ }
+
+ mdelay(100);
+
+ debug("DDRINFO: reset done\n");
+ /*
+ * change the clock source of dram_apb_clk_root:
+ * source 4 800MHz /4 = 200MHz
+ */
+ clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON |
+ CLK_ROOT_SOURCE_SEL(4) |
+ CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4));
+
+ /* disable iso */
+ reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */
+ reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */
+
+ debug("DDRINFO: cfg clk\n");
+ dram_pll_init(DRAM_PLL_OUT_750M);
+
+ /*
+ * release [0]ddr1_preset_n, [1]ddr1_core_reset_n,
+ * [2]ddr1_phy_reset, [3]ddr1_phy_pwrokin_n
+ */
+ reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
+
+ /*step2 Configure uMCTL2's registers */
+ debug("DDRINFO: ddrc config start\n");
+ lpddr4_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num);
+ debug("DDRINFO: ddrc config done\n");
+
+ /*
+ * step3 de-assert all reset
+ * RESET: <core_ddrc_rstn> DEASSERTED
+ * RESET: <aresetn> for Port 0 DEASSERT(0)ED
+ */
+ reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004);
+ reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000);
+
+ reg32_write(DDRC_DBG1(0), 0x00000000);
+ /* step4 */
+ /* [0]dis_auto_refresh=1 */
+ reg32_write(DDRC_RFSHCTL3(0), 0x00000011);
+
+ /* [8]--1: lpddr4_sr allowed; [5]--1: software entry to SR */
+ reg32_write(DDRC_PWRCTL(0), 0x000000a8);
+
+ do {
+ tmp = reg32_read(DDRC_STAT(0));
+ } while ((tmp & 0x33f) != 0x223);
+
+ reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */
+
+ /* step5 */
+ reg32_write(DDRC_SWCTL(0), 0x00000000);
+
+ /* step6 */
+ tmp = reg32_read(DDRC_MSTR2(0));
+ if (tmp == 0x2)
+ reg32_write(DDRC_DFIMISC(0), 0x00000210);
+ else if (tmp == 0x1)
+ reg32_write(DDRC_DFIMISC(0), 0x00000110);
+ else
+ reg32_write(DDRC_DFIMISC(0), 0x00000010);
+
+ /* step7 [0]--1: disable quasi-dynamic programming */
+ reg32_write(DDRC_SWCTL(0), 0x00000001);
+
+ /* step8 Configure LPDDR4 PHY's registers */
+ debug("DDRINFO:ddrphy config start\n");
+ ddr_cfg_phy(dram_timing);
+ 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 [0]--0: to enable quasi-dynamic programming */
+ reg32_write(DDRC_SWCTL(0), 0x00000000);
+
+ /* step16 */
+ tmp = reg32_read(DDRC_MSTR2(0));
+ if (tmp == 0x2)
+ reg32_write(DDRC_DFIMISC(0), 0x00000230);
+ else if (tmp == 0x1)
+ reg32_write(DDRC_DFIMISC(0), 0x00000130);
+ else
+ reg32_write(DDRC_DFIMISC(0), 0x00000030);
+
+ /* step17 [0]--1: disable quasi-dynamic programming */
+ reg32_write(DDRC_SWCTL(0), 0x00000001);
+ /* step18 wait DFISTAT.dfi_init_complete to 1 */
+ do {
+ tmp = reg32_read(DDRC_DFISTAT(0));
+ } while ((tmp & 0x1) == 0x0);
+
+ /* step19 */
+ reg32_write(DDRC_SWCTL(0), 0x00000000);
+
+ /* step20~22 */
+ tmp = reg32_read(DDRC_MSTR2(0));
+ if (tmp == 0x2) {
+ reg32_write(DDRC_DFIMISC(0), 0x00000210);
+ /* set DFIMISC.dfi_init_complete_en again */
+ reg32_write(DDRC_DFIMISC(0), 0x00000211);
+ } else if (tmp == 0x1) {
+ reg32_write(DDRC_DFIMISC(0), 0x00000110);
+ /* set DFIMISC.dfi_init_complete_en again */
+ reg32_write(DDRC_DFIMISC(0), 0x00000111);
+ } else {
+ /* clear DFIMISC.dfi_init_complete_en */
+ reg32_write(DDRC_DFIMISC(0), 0x00000010);
+ /* set DFIMISC.dfi_init_complete_en again */
+ reg32_write(DDRC_DFIMISC(0), 0x00000011);
+ }
+
+ /* step23 [5]selfref_sw=0; */
+ reg32_write(DDRC_PWRCTL(0), 0x00000008);
+ /* step24 sw_done=1 */
+ reg32_write(DDRC_SWCTL(0), 0x00000001);
+
+ /* step25 wait SWSTAT.sw_done_ack to 1 */
+ do {
+ tmp = reg32_read(DDRC_SWSTAT(0));
+ } while ((tmp & 0x1) == 0x0);
+
+#ifdef DFI_BUG_WR
+ reg32_write(DDRC_DFIPHYMSTR(0), 0x00000001);
+#endif
+ /* wait STAT.operating_mode([1:0] for ddr3) to normal state */
+ do {
+ tmp = reg32_read(DDRC_STAT(0));
+ } while ((tmp & 0x3) != 0x1);
+
+ /* step26 */
+ reg32_write(DDRC_RFSHCTL3(0), 0x00000010);
+
+ /* enable port 0 */
+ reg32_write(DDRC_PCTRL_0(0), 0x00000001);
+ debug("DDRINFO: ddrmix config done\n");
+
+ /* save the dram timing config into memory */
+ dram_config_save(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE);
+}
--
2.14.1
More information about the U-Boot
mailing list