From e73e454d11dab13a87b6068a24509a1f118ac812 Mon Sep 17 00:00:00 2001 From: Jacky Bai Date: Tue, 7 Jan 2020 16:44:46 +0800 Subject: plat: imx8mq: Add the dram retention support for imx8mq Add the dram retention support for i.MX8MQ. As there is no enough ocram space available before entering TF-A, so the timing info need to be copied from dram into ocram. Signed-off-by: Jacky Bai --- plat/imx/imx8m/ddr/clock.c | 2 +- plat/imx/imx8m/ddr/dram.c | 32 ++++++++++++++++++++++++++++ plat/imx/imx8m/ddr/dram_retention.c | 2 -- plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c | 5 +++++ plat/imx/imx8m/imx8mq/imx8mq_psci.c | 3 +++ plat/imx/imx8m/imx8mq/include/platform_def.h | 11 ++++++++++ plat/imx/imx8m/imx8mq/platform.mk | 7 ++++++ 7 files changed, 59 insertions(+), 3 deletions(-) diff --git a/plat/imx/imx8m/ddr/clock.c b/plat/imx/imx8m/ddr/clock.c index c462bb45..b724d2f6 100644 --- a/plat/imx/imx8m/ddr/clock.c +++ b/plat/imx/imx8m/ddr/clock.c @@ -73,7 +73,7 @@ void dram_pll_init(unsigned int drate) /* unbypass the PLL */ mmio_clrbits_32(HW_DRAM_PLL_CFG0, 0x30); - while(!(mmio_read_32(HW_DRAM_PLL_CFG0) & (1 << 31))) + while(!(mmio_read_32(HW_DRAM_PLL_CFG0) & BIT(31))) ; } #else diff --git a/plat/imx/imx8m/ddr/dram.c b/plat/imx/imx8m/ddr/dram.c index 917464eb..d3ecf769 100644 --- a/plat/imx/imx8m/ddr/dram.c +++ b/plat/imx/imx8m/ddr/dram.c @@ -15,11 +15,19 @@ #define IMX_SIP_DDR_DVFS_GET_FREQ_COUNT 0x10 #define IMX_SIP_DDR_DVFS_GET_FREQ_INFO 0x11 +#define TIMING_CFG_PTR(ptr, old_base, new_base) \ + ((struct dram_cfg_param *)(((uint64_t)(ptr) & ~(uint64_t)(old_base)) + (uint64_t)(new_base))) + struct dram_info dram_info; /* lock used for DDR DVFS */ spinlock_t dfs_lock; +#if defined(PLAT_imx8mq) +/* ocram used to dram timing */ +static uint8_t dram_timing_saved[13 * 1024] __aligned(8); +#endif + static volatile uint32_t wfe_done; static volatile bool wait_ddrc_hwffc_done = true; static unsigned int dev_fsp = 0x1; @@ -30,6 +38,24 @@ static uint32_t fsp_init_reg[3][4] = { { DDRC_FREQ2_INIT3(0), DDRC_FREQ2_INIT4(0), DDRC_FREQ2_INIT6(0), DDRC_FREQ2_INIT7(0) }, }; + +#if defined (PLAT_imx8mq) +/* copy the dram timing info from DRAM to OCRAM */ +void imx8mq_dram_timing_copy(struct dram_timing_info *from) +{ + struct dram_timing_info *info = (struct dram_timing_info *)dram_timing_saved; + + /* copy the whole 13KB content used for dram timing info */ + memcpy(dram_timing_saved, from, sizeof(dram_timing_saved)); + + /* correct the header after copied into ocram */ + info->ddrc_cfg = TIMING_CFG_PTR(info->ddrc_cfg, from, dram_timing_saved); + info->ddrphy_cfg = TIMING_CFG_PTR(info->ddrphy_cfg, from, dram_timing_saved); + info->ddrphy_trained_csr = TIMING_CFG_PTR(info->ddrphy_trained_csr, from, dram_timing_saved); + info->ddrphy_pie = TIMING_CFG_PTR(info->ddrphy_pie, from, dram_timing_saved); +} +#endif + static void get_mr_values(uint32_t (*mr_value)[8]) { uint32_t init_val; @@ -134,6 +160,12 @@ void dram_info_init(unsigned long dram_timing_base) dram_info.boot_fsp = current_fsp; dram_info.current_fsp = current_fsp; +#if defined(PLAT_imx8mq) + imx8mq_dram_timing_copy((struct dram_timing_info *)dram_timing_base); + + dram_timing_base = (unsigned long) dram_timing_saved; +#endif + get_mr_values(dram_info.mr_table); dram_info.timing_info = (struct dram_timing_info *)dram_timing_base; diff --git a/plat/imx/imx8m/ddr/dram_retention.c b/plat/imx/imx8m/ddr/dram_retention.c index b919fecc..2eb1438a 100644 --- a/plat/imx/imx8m/ddr/dram_retention.c +++ b/plat/imx/imx8m/ddr/dram_retention.c @@ -21,8 +21,6 @@ #define CCM_SRC_CTRL(n) (CCM_SRC_CTRL_OFFSET + 0x10 * (n)) #define CCM_CCGR(n) (CCM_CCGR_OFFSET + 0x10 * (n)) -#define DRAM_PLL_CTRL (IMX_ANAMIX_BASE + 0x50) - void dram_enter_retention(void) { /* Wait DBGCAM to be empty */ diff --git a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c index 27c55454..ec1a9cc0 100644 --- a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c +++ b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,8 @@ static const mmap_region_t imx_mmap[] = { MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_MEMORY | MT_RW), /* ROM map */ MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW), /* AIPS map */ MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW), /* GIC map */ + MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW), /* DDRMIX map */ + MAP_REGION_FLAT(IMX_DRAM_BASE, IMX_DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS), {0}, }; @@ -195,6 +198,8 @@ void bl31_platform_setup(void) /* gpc init */ imx_gpc_init(); + + dram_info_init(SAVED_DRAM_TIMING_BASE); } entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type) diff --git a/plat/imx/imx8m/imx8mq/imx8mq_psci.c b/plat/imx/imx8m/imx8mq/imx8mq_psci.c index 04e191ff..78a6ea70 100644 --- a/plat/imx/imx8m/imx8mq/imx8mq_psci.c +++ b/plat/imx/imx8m/imx8mq/imx8mq_psci.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -63,6 +64,7 @@ void imx_domain_suspend(const psci_power_state_t *target_state) if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) { imx_set_sys_lpm(core_id, true); + dram_enter_retention(); } } @@ -73,6 +75,7 @@ void imx_domain_suspend_finish(const psci_power_state_t *target_state) /* check the system level status */ if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) { + dram_exit_retention(); imx_set_sys_lpm(core_id, false); imx_clear_rbc_count(); } diff --git a/plat/imx/imx8m/imx8mq/include/platform_def.h b/plat/imx/imx8m/imx8mq/include/platform_def.h index 9aa759fd..c7d972ad 100644 --- a/plat/imx/imx8m/imx8mq/include/platform_def.h +++ b/plat/imx/imx8m/imx8mq/include/platform_def.h @@ -4,6 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include + #define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" #define PLATFORM_LINKER_ARCH aarch64 @@ -74,6 +76,9 @@ #define IMX_DDRC_BASE U(0x3d400000) #define IMX_DDRPHY_BASE U(0x3c000000) #define IMX_DDR_IPS_BASE U(0x3d000000) +#define IMX_DDR_IPS_SIZE U(0x1800000) +#define IMX_DRAM_BASE U(0x40000000) +#define IMX_DRAM_SIZE U(0xc0000000) #define IMX_ROM_BASE U(0x00000000) #define IMX_ROM_SIZE U(0x20000) @@ -109,6 +114,12 @@ #define SNVS_LPCR_DP_EN BIT(5) #define SNVS_LPCR_TOP BIT(6) +#define SAVED_DRAM_TIMING_BASE 0x40000000 + +#define HW_DRAM_PLL_CFG0 (IMX_ANAMIX_BASE + 0x60) +#define HW_DRAM_PLL_CFG1 (IMX_ANAMIX_BASE + 0x64) +#define HW_DRAM_PLL_CFG2 (IMX_ANAMIX_BASE + 0x68) +#define DRAM_PLL_CTRL HW_DRAM_PLL_CFG0 #define IOMUXC_GPR10 U(0x28) #define GPR_TZASC_EN BIT(0) diff --git a/plat/imx/imx8m/imx8mq/platform.mk b/plat/imx/imx8m/imx8mq/platform.mk index c63559a2..4dd659e3 100644 --- a/plat/imx/imx8m/imx8mq/platform.mk +++ b/plat/imx/imx8m/imx8mq/platform.mk @@ -8,6 +8,12 @@ PLAT_INCLUDES := -Iplat/imx/common/include \ -Iplat/imx/imx8m/include \ -Iplat/imx/imx8m/imx8mq/include +IMX_DRAM_SOURCES := plat/imx/imx8m/ddr/dram.c \ + plat/imx/imx8m/ddr/clock.c \ + plat/imx/imx8m/ddr/dram_retention.c \ + plat/imx/imx8m/ddr/ddr4_dvfs.c \ + plat/imx/imx8m/ddr/lpddr4_dvfs.c + IMX_GIC_SOURCES := drivers/arm/gic/v3/gicv3_helpers.c \ drivers/arm/gic/v3/arm_gicv3_common.c \ drivers/arm/gic/v3/gic500.c \ @@ -35,6 +41,7 @@ BL31_SOURCES += plat/imx/common/imx8_helpers.S \ drivers/arm/tzc/tzc380.c \ drivers/delay_timer/delay_timer.c \ drivers/delay_timer/generic_delay_timer.c \ + ${IMX_DRAM_SOURCES} \ ${IMX_GIC_SOURCES} XLAT_TABLE_IN_OCRAM_S := 1 -- cgit v1.2.3