1 /* 2 * Copyright (C) 2021-2025, STMicroelectronics - All Rights Reserved 3 * 4 * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause 5 */ 6 7 #include <errno.h> 8 9 #include <arch_helpers.h> 10 #include <common/debug.h> 11 #include <common/fdt_wrappers.h> 12 #include <drivers/clk.h> 13 #include <drivers/st/stm32mp2_ddr.h> 14 #include <drivers/st/stm32mp2_ddr_helpers.h> 15 #include <drivers/st/stm32mp2_ram.h> 16 #include <drivers/st/stm32mp_ddr.h> 17 #include <drivers/st/stm32mp_ddr_test.h> 18 #include <drivers/st/stm32mp_ram.h> 19 20 #include <lib/mmio.h> 21 #include <libfdt.h> 22 23 #include <platform_def.h> 24 25 static struct stm32mp_ddr_priv ddr_priv_data; 26 static bool ddr_self_refresh; 27 28 static int ddr_dt_get_ui_param(void *fdt, int node, struct stm32mp_ddr_config *config) 29 { 30 int ret; 31 uint32_t size; 32 33 size = sizeof(struct user_input_basic) / sizeof(int); 34 ret = fdt_read_uint32_array(fdt, node, "st,phy-basic", size, (uint32_t *)&config->uib); 35 36 VERBOSE("%s: %s[0x%x] = %d\n", __func__, "st,phy-basic", size, ret); 37 if (ret != 0) { 38 ERROR("%s: can't read %s, error=%d\n", __func__, "st,phy-basic", ret); 39 return -EINVAL; 40 } 41 42 size = sizeof(struct user_input_advanced) / sizeof(int); 43 ret = fdt_read_uint32_array(fdt, node, "st,phy-advanced", size, (uint32_t *)&config->uia); 44 45 VERBOSE("%s: %s[0x%x] = %d\n", __func__, "st,phy-advanced", size, ret); 46 if (ret != 0) { 47 ERROR("%s: can't read %s, error=%d\n", __func__, "st,phy-advanced", ret); 48 return -EINVAL; 49 } 50 51 size = sizeof(struct user_input_mode_register) / sizeof(int); 52 ret = fdt_read_uint32_array(fdt, node, "st,phy-mr", size, (uint32_t *)&config->uim); 53 54 VERBOSE("%s: %s[0x%x] = %d\n", __func__, "st,phy-mr", size, ret); 55 if (ret != 0) { 56 ERROR("%s: can't read %s, error=%d\n", __func__, "st,phy-mr", ret); 57 return -EINVAL; 58 } 59 60 size = sizeof(struct user_input_swizzle) / sizeof(int); 61 ret = fdt_read_uint32_array(fdt, node, "st,phy-swizzle", size, (uint32_t *)&config->uis); 62 63 VERBOSE("%s: %s[0x%x] = %d\n", __func__, "st,phy-swizzle", size, ret); 64 if (ret != 0) { 65 ERROR("%s: can't read %s, error=%d\n", __func__, "st,phy-swizzle", ret); 66 return -EINVAL; 67 } 68 69 return 0; 70 } 71 72 static int stm32mp2_ddr_setup(void) 73 { 74 struct stm32mp_ddr_priv *priv = &ddr_priv_data; 75 int ret; 76 struct stm32mp_ddr_config config; 77 int node; 78 uintptr_t uret; 79 void *fdt; 80 81 const struct stm32mp_ddr_param param[] = { 82 CTL_PARAM(reg), 83 CTL_PARAM(timing), 84 CTL_PARAM(map), 85 CTL_PARAM(perf) 86 }; 87 88 if (fdt_get_address(&fdt) == 0) { 89 return -ENOENT; 90 } 91 92 node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); 93 if (node < 0) { 94 ERROR("%s: can't read DDR node in DT\n", __func__); 95 return -EINVAL; 96 } 97 98 ret = stm32mp_ddr_dt_get_info(fdt, node, &config.info); 99 if (ret < 0) { 100 return ret; 101 } 102 103 ret = stm32mp_ddr_dt_get_param(fdt, node, param, ARRAY_SIZE(param), (uintptr_t)&config); 104 if (ret < 0) { 105 return ret; 106 } 107 108 ret = ddr_dt_get_ui_param(fdt, node, &config); 109 if (ret < 0) { 110 return ret; 111 } 112 113 config.self_refresh = false; 114 115 if (stm32mp_is_wakeup_from_standby()) { 116 config.self_refresh = true; 117 } 118 119 /* Map dynamically RETRAM area to save or restore PHY retention registers */ 120 if (stm32mp_map_retram() != 0) { 121 panic(); 122 } 123 124 stm32mp2_ddr_init(priv, &config); 125 126 /* Unmap RETRAM, no more used until next DDR initialization call */ 127 if (stm32mp_unmap_retram() != 0) { 128 panic(); 129 } 130 131 priv->info.size = config.info.size; 132 133 VERBOSE("%s : ram size(%lx, %lx)\n", __func__, priv->info.base, priv->info.size); 134 135 if (stm32mp_map_ddr_non_cacheable() != 0) { 136 panic(); 137 } 138 139 if (config.self_refresh) { 140 uret = stm32mp_ddr_test_rw_access(); 141 if (uret != 0UL) { 142 ERROR("DDR rw test: can't access memory @ 0x%lx\n", uret); 143 panic(); 144 } 145 } else { 146 size_t retsize; 147 148 uret = stm32mp_ddr_test_data_bus(); 149 if (uret != 0UL) { 150 ERROR("DDR data bus test: can't access memory @ 0x%lx\n", uret); 151 panic(); 152 } 153 154 uret = stm32mp_ddr_test_addr_bus(config.info.size); 155 if (uret != 0UL) { 156 ERROR("DDR addr bus test: can't access memory @ 0x%lx\n", uret); 157 panic(); 158 } 159 160 retsize = stm32mp_ddr_check_size(); 161 if (retsize < config.info.size) { 162 ERROR("DDR size: 0x%zx does not match DT config: 0x%zx\n", 163 retsize, config.info.size); 164 panic(); 165 } 166 167 INFO("Memory size = 0x%zx (%zu MB)\n", retsize, retsize / (1024U * 1024U)); 168 } 169 170 /* 171 * Initialization sequence has configured DDR registers with settings. 172 * The Self Refresh (SR) mode corresponding to these settings has now 173 * to be set. 174 */ 175 ddr_set_sr_mode(ddr_read_sr_mode()); 176 177 if (stm32mp_unmap_ddr() != 0) { 178 panic(); 179 } 180 181 /* Save DDR self_refresh state */ 182 ddr_self_refresh = config.self_refresh; 183 184 return 0; 185 } 186 187 bool stm32mp2_ddr_is_restored(void) 188 { 189 return ddr_self_refresh; 190 } 191 192 int stm32mp2_ddr_probe(void) 193 { 194 struct stm32mp_ddr_priv *priv = &ddr_priv_data; 195 196 VERBOSE("STM32MP DDR probe\n"); 197 198 priv->ctl = (struct stm32mp_ddrctl *)stm32mp_ddrctrl_base(); 199 priv->phy = (struct stm32mp_ddrphy *)stm32mp_ddrphyc_base(); 200 priv->pwr = stm32mp_pwr_base(); 201 priv->rcc = stm32mp_rcc_base(); 202 203 priv->info.base = STM32MP_DDR_BASE; 204 priv->info.size = 0; 205 206 return stm32mp2_ddr_setup(); 207 } 208