aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/include
diff options
context:
space:
mode:
authorYe Li2022-07-26 16:41:07 +0800
committerStefano Babic2022-07-26 11:29:01 +0200
commit99c7cc58e12d59a7562c637b7c1510cfdf33e4f9 (patch)
tree6f37204d0e08437af51e400e862d87fc53ccc1ae /arch/arm/include
parente631185a20ab730603d7bb04378e98a83d337735 (diff)
ddr: imx: Add i.MX9 DDR controller driver
Since i.MX9 uses same DDR PHY with i.MX8M, split the DDRPHY to a common directory under imx, then use dedicated ddr controller driver for each iMX9 and iMX8M. The DDRPHY registers are space compressed, so it needs conversion to access the DDRPHY address. Introduce a common PHY address remap function for both iMX8M and iMX9 for all PHY registers accessing. Signed-off-by: Ye Li <ye.li@nxp.com> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Diffstat (limited to 'arch/arm/include')
-rw-r--r--arch/arm/include/asm/arch-imx8m/ddr.h6
-rw-r--r--arch/arm/include/asm/arch-imx9/ddr.h126
2 files changed, 130 insertions, 2 deletions
diff --git a/arch/arm/include/asm/arch-imx8m/ddr.h b/arch/arm/include/asm/arch-imx8m/ddr.h
index 2ce8a8f2d41..2f76e7d69b9 100644
--- a/arch/arm/include/asm/arch-imx8m/ddr.h
+++ b/arch/arm/include/asm/arch-imx8m/ddr.h
@@ -725,6 +725,8 @@ void update_umctl2_rank_space_setting(unsigned int pstat_num);
void get_trained_CDD(unsigned int fsp);
unsigned int lpddr4_mr_read(unsigned int mr_rank, unsigned int mr_addr);
+ulong ddrphy_addr_remap(uint32_t paddr_apb_from_ctlr);
+
static inline void reg32_write(unsigned long addr, u32 val)
{
writel(val, addr);
@@ -741,9 +743,9 @@ static inline void reg32setbit(unsigned long addr, u32 bit)
}
#define dwc_ddrphy_apb_wr(addr, data) \
- reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * (addr), data)
+ reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + ddrphy_addr_remap(addr), data)
#define dwc_ddrphy_apb_rd(addr) \
- reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * (addr))
+ reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + ddrphy_addr_remap(addr))
extern struct dram_cfg_param ddrphy_trained_csr[];
extern uint32_t ddrphy_trained_csr_num;
diff --git a/arch/arm/include/asm/arch-imx9/ddr.h b/arch/arm/include/asm/arch-imx9/ddr.h
new file mode 100644
index 00000000000..62e6f7dda53
--- /dev/null
+++ b/arch/arm/include/asm/arch-imx9/ddr.h
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2022 NXP
+ */
+
+#ifndef __ASM_ARCH_IMX8M_DDR_H
+#define __ASM_ARCH_IMX8M_DDR_H
+
+#include <asm/io.h>
+#include <asm/types.h>
+
+#define DDR_CTL_BASE 0x4E300000
+#define DDR_PHY_BASE 0x4E100000
+#define DDRMIX_BLK_CTRL_BASE 0x4E010000
+
+#define REG_DDRDSR_2 (DDR_CTL_BASE + 0xB24)
+#define REG_DDR_SDRAM_CFG (DDR_CTL_BASE + 0x110)
+#define REG_DDR_DEBUG_19 (DDR_CTL_BASE + 0xF48)
+
+#define SRC_BASE_ADDR (0x44460000)
+#define SRC_DPHY_BASE_ADDR (SRC_BASE_ADDR + 0x1400)
+#define REG_SRC_DPHY_SW_CTRL (SRC_DPHY_BASE_ADDR + 0x20)
+#define REG_SRC_DPHY_SINGLE_RESET_SW_CTRL (SRC_DPHY_BASE_ADDR + 0x24)
+
+#define IP2APB_DDRPHY_IPS_BASE_ADDR(X) (DDR_PHY_BASE + ((X) * 0x2000000))
+#define DDRPHY_MEM(X) (DDR_PHY_BASE + ((X) * 0x2000000) + 0x50000)
+
+/* PHY State */
+enum pstate {
+ PS0,
+ PS1,
+ PS2,
+ PS3,
+};
+
+enum msg_response {
+ TRAIN_SUCCESS = 0x7,
+ TRAIN_STREAM_START = 0x8,
+ TRAIN_FAIL = 0xff,
+};
+
+/* 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);
+int 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);
+void board_dram_ecc_scrub(void);
+void ddrc_inline_ecc_scrub(unsigned int start_address,
+ unsigned int range_address);
+void ddrc_inline_ecc_scrub_end(unsigned int start_address,
+ unsigned int range_address);
+
+/* 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);
+
+void get_trained_CDD(unsigned int fsp);
+
+ulong ddrphy_addr_remap(u32 paddr_apb_from_ctlr);
+
+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) + ddrphy_addr_remap(addr), data)
+#define dwc_ddrphy_apb_rd(addr) \
+ reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + ddrphy_addr_remap(addr))
+
+extern struct dram_cfg_param ddrphy_trained_csr[];
+extern u32 ddrphy_trained_csr_num;
+
+#endif