feat(st-ddr): add STM32MP2 driver
Add driver to support DDR on STM32MP2 platform. It drives the DDR PHY
and its firmware, as well as the DDR controller.
Signed-off-by: Nicolas Le Bayon <nicolas.le.bayon@st.com>
Signed-off-by: Maxime Méré <maxime.mere@foss.st.com>
Change-Id: I93de2db1b9378d5654e76b3bf6f3407d80bc4ca5
diff --git a/include/drivers/st/stm32mp2_ddr.h b/include/drivers/st/stm32mp2_ddr.h
new file mode 100644
index 0000000..6b0462c
--- /dev/null
+++ b/include/drivers/st/stm32mp2_ddr.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2021-2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+ */
+
+#ifndef STM32MP2_DDR_H
+#define STM32MP2_DDR_H
+
+#include <stdbool.h>
+
+#include <ddrphy_phyinit_struct.h>
+
+#include <drivers/st/stm32mp_ddr.h>
+
+struct stm32mp2_ddrctrl_reg {
+ uint32_t mstr;
+ uint32_t mrctrl0;
+ uint32_t mrctrl1;
+ uint32_t mrctrl2;
+ uint32_t derateen;
+ uint32_t derateint;
+ uint32_t deratectl;
+ uint32_t pwrctl;
+ uint32_t pwrtmg;
+ uint32_t hwlpctl;
+ uint32_t rfshctl0;
+ uint32_t rfshctl1;
+ uint32_t rfshctl3;
+ uint32_t crcparctl0;
+ uint32_t crcparctl1;
+ uint32_t init0;
+ uint32_t init1;
+ uint32_t init2;
+ uint32_t init3;
+ uint32_t init4;
+ uint32_t init5;
+ uint32_t init6;
+ uint32_t init7;
+ uint32_t dimmctl;
+ uint32_t rankctl;
+ uint32_t rankctl1;
+ uint32_t zqctl0;
+ uint32_t zqctl1;
+ uint32_t zqctl2;
+ uint32_t dfitmg0;
+ uint32_t dfitmg1;
+ uint32_t dfilpcfg0;
+ uint32_t dfilpcfg1;
+ uint32_t dfiupd0;
+ uint32_t dfiupd1;
+ uint32_t dfiupd2;
+ uint32_t dfimisc;
+ uint32_t dfitmg2;
+ uint32_t dfitmg3;
+ uint32_t dbictl;
+ uint32_t dfiphymstr;
+ uint32_t dbg0;
+ uint32_t dbg1;
+ uint32_t dbgcmd;
+ uint32_t swctl;
+ uint32_t swctlstatic;
+ uint32_t poisoncfg;
+ uint32_t pccfg;
+};
+
+struct stm32mp2_ddrctrl_timing {
+ uint32_t rfshtmg;
+ uint32_t rfshtmg1;
+ uint32_t dramtmg0;
+ uint32_t dramtmg1;
+ uint32_t dramtmg2;
+ uint32_t dramtmg3;
+ uint32_t dramtmg4;
+ uint32_t dramtmg5;
+ uint32_t dramtmg6;
+ uint32_t dramtmg7;
+ uint32_t dramtmg8;
+ uint32_t dramtmg9;
+ uint32_t dramtmg10;
+ uint32_t dramtmg11;
+ uint32_t dramtmg12;
+ uint32_t dramtmg13;
+ uint32_t dramtmg14;
+ uint32_t dramtmg15;
+ uint32_t odtcfg;
+ uint32_t odtmap;
+};
+
+struct stm32mp2_ddrctrl_map {
+ uint32_t addrmap0;
+ uint32_t addrmap1;
+ uint32_t addrmap2;
+ uint32_t addrmap3;
+ uint32_t addrmap4;
+ uint32_t addrmap5;
+ uint32_t addrmap6;
+ uint32_t addrmap7;
+ uint32_t addrmap8;
+ uint32_t addrmap9;
+ uint32_t addrmap10;
+ uint32_t addrmap11;
+};
+
+struct stm32mp2_ddrctrl_perf {
+ uint32_t sched;
+ uint32_t sched1;
+ uint32_t perfhpr1;
+ uint32_t perflpr1;
+ uint32_t perfwr1;
+ uint32_t sched3;
+ uint32_t sched4;
+ uint32_t pcfgr_0;
+ uint32_t pcfgw_0;
+ uint32_t pctrl_0;
+ uint32_t pcfgqos0_0;
+ uint32_t pcfgqos1_0;
+ uint32_t pcfgwqos0_0;
+ uint32_t pcfgwqos1_0;
+#if STM32MP_DDR_DUAL_AXI_PORT
+ uint32_t pcfgr_1;
+ uint32_t pcfgw_1;
+ uint32_t pctrl_1;
+ uint32_t pcfgqos0_1;
+ uint32_t pcfgqos1_1;
+ uint32_t pcfgwqos0_1;
+ uint32_t pcfgwqos1_1;
+#endif /* STM32MP_DDR_DUAL_AXI_PORT */
+};
+
+struct stm32mp_ddr_config {
+ struct stm32mp_ddr_info info;
+ struct stm32mp2_ddrctrl_reg c_reg;
+ struct stm32mp2_ddrctrl_timing c_timing;
+ struct stm32mp2_ddrctrl_map c_map;
+ struct stm32mp2_ddrctrl_perf c_perf;
+ bool self_refresh;
+ uint32_t zdata;
+ struct user_input_basic uib;
+ struct user_input_advanced uia;
+ struct user_input_mode_register uim;
+ struct user_input_swizzle uis;
+};
+
+void stm32mp2_ddr_init(struct stm32mp_ddr_priv *priv, struct stm32mp_ddr_config *config);
+
+#endif /* STM32MP2_DDR_H */
diff --git a/include/drivers/st/stm32mp2_ddr_helpers.h b/include/drivers/st/stm32mp2_ddr_helpers.h
index 069fb83..9329fff 100644
--- a/include/drivers/st/stm32mp2_ddr_helpers.h
+++ b/include/drivers/st/stm32mp2_ddr_helpers.h
@@ -7,6 +7,29 @@
#ifndef STM32MP2_DDR_HELPERS_H
#define STM32MP2_DDR_HELPERS_H
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <drivers/st/stm32mp2_ddr_regs.h>
+
+enum stm32mp2_ddr_sr_mode {
+ DDR_SR_MODE_INVALID = 0,
+ DDR_SSR_MODE,
+ DDR_HSR_MODE,
+ DDR_ASR_MODE,
+};
+
+void ddr_activate_controller(struct stm32mp_ddrctl *ctl, bool sr_entry);
+void ddr_wait_lp3_mode(bool state);
+int ddr_sr_exit_loop(void);
+uint32_t ddr_get_io_calibration_val(void);
+int ddr_sr_entry(bool standby);
+int ddr_sr_exit(void);
+enum stm32mp2_ddr_sr_mode ddr_read_sr_mode(void);
+void ddr_set_sr_mode(enum stm32mp2_ddr_sr_mode mode);
+void ddr_save_sr_mode(void);
+void ddr_restore_sr_mode(void);
void ddr_sub_system_clk_init(void);
+void ddr_sub_system_clk_off(void);
#endif /* STM32MP2_DDR_HELPERS_H */
diff --git a/include/drivers/st/stm32mp2_ddr_regs.h b/include/drivers/st/stm32mp2_ddr_regs.h
new file mode 100644
index 0000000..9370f1c
--- /dev/null
+++ b/include/drivers/st/stm32mp2_ddr_regs.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021-2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+ */
+
+#ifndef STM32MP2_DDR_REGS_H
+#define STM32MP2_DDR_REGS_H
+
+#include <drivers/st/stm32mp_ddrctrl_regs.h>
+#include <lib/utils_def.h>
+
+/* DDR Physical Interface Control (DDRPHYC) registers*/
+struct stm32mp_ddrphy {
+ uint32_t dummy;
+} __packed;
+
+/* DDRPHY registers offsets */
+#define DDRPHY_INITENG0_P0_SEQ0BDISABLEFLAG6 U(0x240004)
+#define DDRPHY_INITENG0_P0_PHYINLPX U(0x2400A0)
+#define DDRPHY_DRTUB0_UCCLKHCLKENABLES U(0x300200)
+#define DDRPHY_APBONLY0_MICROCONTMUXSEL U(0x340000)
+
+/* DDRPHY registers fields */
+#define DDRPHY_INITENG0_P0_PHYINLPX_PHYINLP3 BIT(0)
+#define DDRPHY_DRTUB0_UCCLKHCLKENABLES_UCCLKEN BIT(0)
+#define DDRPHY_DRTUB0_UCCLKHCLKENABLES_HCLKEN BIT(1)
+#define DDRPHY_APBONLY0_MICROCONTMUXSEL_MICROCONTMUXSEL BIT(0)
+
+/* DDRDBG registers offsets */
+#define DDRDBG_LP_DISABLE U(0x0)
+#define DDRDBG_BYPASS_PCLKEN U(0x4)
+
+/* DDRDBG registers fields */
+#define DDRDBG_LP_DISABLE_LPI_XPI_DISABLE BIT(0)
+#define DDRDBG_LP_DISABLE_LPI_DDRC_DISABLE BIT(8)
+
+#endif /* STM32MP2_DDR_REGS_H */
diff --git a/include/drivers/st/stm32mp2_ram.h b/include/drivers/st/stm32mp2_ram.h
new file mode 100644
index 0000000..b6fa928
--- /dev/null
+++ b/include/drivers/st/stm32mp2_ram.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP2_RAM_H
+#define STM32MP2_RAM_H
+
+bool stm32mp2_ddr_is_restored(void);
+int stm32mp2_ddr_probe(void);
+
+#endif /* STM32MP2_RAM_H */
diff --git a/include/drivers/st/stm32mp_ddr.h b/include/drivers/st/stm32mp_ddr.h
index a02ba72..57b0668 100644
--- a/include/drivers/st/stm32mp_ddr.h
+++ b/include/drivers/st/stm32mp_ddr.h
@@ -28,6 +28,9 @@
struct stm32mp_ddr_reg_desc {
uint16_t offset; /* Offset for base address */
uint8_t par_offset; /* Offset for parameter array */
+#if !STM32MP13 && !STM32MP15
+ bool qd; /* quasi-dynamic register if true */
+#endif
};
struct stm32mp_ddr_reg_info {
diff --git a/include/drivers/st/stm32mp_ddrctrl_regs.h b/include/drivers/st/stm32mp_ddrctrl_regs.h
index be8f86d..f9f46aa 100644
--- a/include/drivers/st/stm32mp_ddrctrl_regs.h
+++ b/include/drivers/st/stm32mp_ddrctrl_regs.h
@@ -51,7 +51,8 @@
uint32_t init7; /* 0xec SDRAM Initialization 7 */
uint32_t dimmctl; /* 0xf0 DIMM Control */
uint32_t rankctl; /* 0xf4 Rank Control */
- uint8_t reserved0f4[0x100 - 0xf8];
+ uint32_t rankctl1; /* 0xf8 Rank Control 1 */
+ uint8_t reserved0fc[0x100 - 0xfc];
uint32_t dramtmg0; /* 0x100 SDRAM Timing 0 */
uint32_t dramtmg1; /* 0x104 SDRAM Timing 1 */
uint32_t dramtmg2; /* 0x108 SDRAM Timing 2 */
@@ -112,7 +113,9 @@
uint32_t perflpr1; /* 0x264 Low Priority Read CAM 1 */
uint32_t reserved268;
uint32_t perfwr1; /* 0x26c Write CAM 1 */
- uint8_t reserved27c[0x300 - 0x270];
+ uint32_t sched3; /* 0x270 Scheduler Control 3 */
+ uint32_t sched4; /* 0x274 Scheduler Control 4 */
+ uint8_t reserved278[0x300 - 0x278];
uint32_t dbg0; /* 0x300 Debug 0 */
uint32_t dbg1; /* 0x304 Debug 1 */
uint32_t dbgcam; /* 0x308 CAM Debug */
@@ -121,7 +124,8 @@
uint8_t reserved314[0x320 - 0x314];
uint32_t swctl; /* 0x320 Software Programming Control Enable */
uint32_t swstat; /* 0x324 Software Programming Control Status */
- uint8_t reserved328[0x36c - 0x328];
+ uint32_t swctlstatic; /* 0x328 Statics Write Enable */
+ uint8_t reserved32c[0x36c - 0x32c];
uint32_t poisoncfg; /* 0x36c AXI Poison Configuration Register */
uint32_t poisonstat; /* 0x370 AXI Poison Status Register */
uint8_t reserved374[0x3f0 - 0x374];
@@ -153,7 +157,7 @@
uint32_t pcfgqos1_1; /* 0x548 Read QoS Configuration 1 */
uint32_t pcfgwqos0_1; /* 0x54c Write QoS Configuration 0 */
uint32_t pcfgwqos1_1; /* 0x550 Write QoS Configuration 1 */
-#endif
+#endif /* STM32MP_DDR_DUAL_AXI_PORT */
uint8_t reserved554[0xff0 - 0x554];
uint32_t umctl2_ver_number; /* 0xff0 UMCTL2 Version Number */
@@ -170,6 +174,7 @@
#define DDRCTRL_RFSHCTL3 0x060
#define DDRCTRL_RFSHTMG 0x064
#define DDRCTRL_INIT0 0x0D0
+#define DDRCTRL_DFILPCFG0 0x198
#define DDRCTRL_DFIMISC 0x1B0
#define DDRCTRL_DBG1 0x304
#define DDRCTRL_DBGCAM 0x308
@@ -181,7 +186,7 @@
#define DDRCTRL_PCTRL_0 0x490
#if STM32MP_DDR_DUAL_AXI_PORT
#define DDRCTRL_PCTRL_1 0x540
-#endif
+#endif /* STM32MP_DDR_DUAL_AXI_PORT */
/* DDR Controller Register fields */
#define DDRCTRL_MSTR_DDR3 BIT(0)
@@ -201,6 +206,8 @@
#define DDRCTRL_STAT_SELFREF_TYPE_MASK GENMASK(5, 4)
#define DDRCTRL_STAT_SELFREF_TYPE_ASR (BIT(4) | BIT(5))
#define DDRCTRL_STAT_SELFREF_TYPE_SR BIT(5)
+#define DDRCTRL_STAT_SELFREF_STATE_MASK GENMASK(9, 8)
+#define DDRCTRL_STAT_SELFREF_STATE_SRPD BIT(9)
#define DDRCTRL_MRCTRL0_MR_TYPE_WRITE U(0)
/* Only one rank supported */
@@ -217,6 +224,7 @@
#define DDRCTRL_PWRCTL_POWERDOWN_EN BIT(1)
#define DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE BIT(3)
#define DDRCTRL_PWRCTL_SELFREF_SW BIT(5)
+#define DDRCTRL_PWRCTL_STAY_IN_SELFREF BIT(6)
#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK GENMASK(23, 16)
#define DDRCTRL_PWRTMG_SELFREF_TO_X32_0 BIT(16)
@@ -225,6 +233,9 @@
#define DDRCTRL_RFSHCTL3_REFRESH_UPDATE_LEVEL BIT(1)
#define DDRCTRL_HWLPCTL_HW_LP_EN BIT(0)
+#define DDRCTRL_HWLPCTL_HW_LP_EXIT_IDLE_EN BIT(1)
+#define DDRCTRL_HWLPCTL_HW_LP_IDLE_X32_MASK GENMASK(27, 16)
+#define DDRCTRL_HWLPCTL_HW_LP_IDLE_X32_SHIFT 16
#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_MASK GENMASK(27, 16)
#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_SHIFT 16
@@ -232,11 +243,16 @@
#define DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK GENMASK(31, 30)
#define DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL BIT(30)
+#define DDRCTRL_DFILPCFG0_DFI_LP_EN_SR BIT(8)
+
#define DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN BIT(0)
#define DDRCTRL_DFIMISC_DFI_INIT_START BIT(5)
+#define DDRCTRL_DFIMISC_DFI_FREQUENCY GENMASK(12, 8)
#define DDRCTRL_DFISTAT_DFI_INIT_COMPLETE BIT(0)
+#define DDRCTRL_DFISTAT_DFI_LP_ACK BIT(1)
+#define DDRCTRL_DBG1_DIS_DQ BIT(0)
#define DDRCTRL_DBG1_DIS_HIF BIT(1)
#define DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY BIT(29)