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@xxxxxxxxxxxxxx> --- arch/arm/boards/nxp-imx8mq-evk/ddr.h | 9 +- arch/arm/boards/nxp-imx8mq-evk/lowlevel.c | 2 +- arch/arm/boards/phytec-som-imx8mq/ddr.h | 7 +- .../boards/phytec-som-imx8mq/ddrphy_train.c | 1 - arch/arm/boards/phytec-som-imx8mq/lowlevel.c | 2 +- arch/arm/boards/zii-imx8mq-dev/ddr.h | 9 +- arch/arm/boards/zii-imx8mq-dev/lowlevel.c | 2 +- arch/arm/mach-imx/Kconfig | 1 + arch/arm/mach-imx/Makefile | 2 +- arch/arm/mach-imx/imx8-ddrc.c | 91 --- arch/arm/mach-imx/include/mach/imx8-ddrc.h | 66 -- drivers/ddr/Kconfig | 1 + drivers/ddr/Makefile | 1 + drivers/ddr/imx8m/Kconfig | 7 + drivers/ddr/imx8m/Makefile | 7 + drivers/ddr/imx8m/ddr_init.c | 211 +++++ drivers/ddr/imx8m/ddrphy_csr.c | 732 ++++++++++++++++++ drivers/ddr/imx8m/ddrphy_train.c | 112 +++ drivers/ddr/imx8m/ddrphy_utils.c | 306 ++++++++ drivers/ddr/imx8m/helper.c | 86 ++ include/soc/imx8m/ddr.h | 407 ++++++++++ include/soc/imx8m/lpddr4_define.h | 97 +++ 22 files changed, 1975 insertions(+), 184 deletions(-) delete mode 100644 arch/arm/mach-imx/imx8-ddrc.c delete mode 100644 arch/arm/mach-imx/include/mach/imx8-ddrc.h create mode 100644 drivers/ddr/imx8m/Kconfig create mode 100644 drivers/ddr/imx8m/Makefile create mode 100644 drivers/ddr/imx8m/ddr_init.c create mode 100644 drivers/ddr/imx8m/ddrphy_csr.c create mode 100644 drivers/ddr/imx8m/ddrphy_train.c create mode 100644 drivers/ddr/imx8m/ddrphy_utils.c create mode 100644 drivers/ddr/imx8m/helper.c create mode 100644 include/soc/imx8m/ddr.h create mode 100644 include/soc/imx8m/lpddr4_define.h diff --git a/arch/arm/boards/nxp-imx8mq-evk/ddr.h b/arch/arm/boards/nxp-imx8mq-evk/ddr.h index 65115dba1e..fd09ad6bf1 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 bf3d43b9a3..39358afad1 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 18ae6e9022..e125feaaf0 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 56af647821..cc00527649 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 f460901a2c..f5b9b6c008 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 1293ad3f34..a395211e62 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 2646f5fc3e..6400833809 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 d717d83865..7b79d80748 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 862dc78ff2..105785ba1b 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 8bb2672102..0000000000 --- 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 d49e29f263..0000000000 --- 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 4ea71598af..d92c272b58 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 faf2f9e1d6..7e33182cbc 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 0000000000..e8bce8c49d --- /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 0000000000..2be313900f --- /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 0000000000..374601b786 --- /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 0000000000..98ac5db3c0 --- /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 0000000000..c2238cc66b --- /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 0000000000..651bb4b698 --- /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 0000000000..9e32ef9376 --- /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 0000000000..5b2747ed1f --- /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 0000000000..caf5bafb6d --- /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__ */ -- 2.25.0 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox