1 /* 2 * Copyright 2020-2023, 2025-2026 NXP 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 #include <assert.h> 7 8 #include <ddr_init.h> 9 10 static uint32_t load_phy_image(uint32_t start_addr, size_t size, 11 const uint16_t image[]); 12 13 /* Load DDR configuration from given address and populate ddrss struct */ 14 static struct ddrss_config load_ddr_config(uintptr_t load_from) 15 { 16 struct ddrss_config config; 17 struct ddr_fw_layout ddr_layout; 18 uintptr_t current_addr = load_from; 19 20 ddr_layout = *(struct ddr_fw_layout *)load_from; 21 current_addr += sizeof(struct ddr_fw_layout); 22 23 config.memory_type = ddr_layout.memory_type; 24 config.frequency = ddr_layout.frequency; 25 config.ddrc_size = ddr_layout.ddrc_size; 26 config.dq_swap_size = ddr_layout.dq_swap_size; 27 config.phy_size = ddr_layout.phy_size; 28 config.pie_size = ddr_layout.pie_size; 29 config.imem_1d_size = ddr_layout.imem_1d_size; 30 config.dmem_1d_size = ddr_layout.dmem_1d_size; 31 config.imem_2d_size = ddr_layout.imem_2d_size; 32 config.dmem_2d_size = ddr_layout.dmem_2d_size; 33 config.phy_csr_size = ddr_layout.phy_csr_size; 34 config.ddrc_csr_size = ddr_layout.ddrc_csr_size; 35 36 config.ddrc = (struct regconf *)(current_addr + ddr_layout.ddrc_offset); 37 config.dq_swap = (struct dqconf *)(current_addr + ddr_layout.dq_swap_offset); 38 config.phy = (struct regconf_16 *)(current_addr + ddr_layout.phy_offset); 39 config.pie = (struct regconf_16 *)(current_addr + ddr_layout.pie_offset); 40 config.imem_1d = (uint16_t *)(current_addr + ddr_layout.imem_1d_offset); 41 config.dmem_1d = (uint16_t *)(current_addr + ddr_layout.dmem_1d_offset); 42 config.imem_2d = (uint16_t *)(current_addr + ddr_layout.imem_2d_offset); 43 config.dmem_2d = (uint16_t *)(current_addr + ddr_layout.dmem_2d_offset); 44 config.phy_csr = (uint32_t *)(current_addr + ddr_layout.phy_csr_offset); 45 config.ddrc_csr = (uint32_t *)(current_addr + ddr_layout.ddrc_csr_offset); 46 47 return config; 48 } 49 50 /* Initialize ddr controller with given settings. */ 51 static uint32_t ddrc_init_cfg(const struct ddrss_config *config) 52 { 53 return load_register_cfg(config->ddrc_size, config->ddrc); 54 } 55 56 /* Main method needed to initialize ddr subsystem. */ 57 uint32_t ddr_init(uintptr_t load_from) 58 { 59 struct ddrss_config ddr_config; 60 int err; 61 62 assert(load_from != 0UL); 63 64 err = plat_ddr_mmap_setup(); 65 if (err != 0) { 66 return MAPPING_FAILED; 67 } 68 69 ddr_config = load_ddr_config(load_from + sizeof(struct ddr_fw_header)); 70 return ddr_init_cfg(&ddr_config); 71 } 72 73 /* Execute 2D training stage if images are available */ 74 static uint32_t execute_2d_training(const struct ddrss_config *config) 75 { 76 uint32_t ret = NO_ERR; 77 78 /* Load 2d imem image */ 79 mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS); 80 ret = load_phy_image(IMEM_START_ADDR, config->imem_2d_size, 81 config->imem_2d); 82 if (ret != NO_ERR) { 83 return ret; 84 } 85 mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS); 86 87 /* Load 2d dmem image */ 88 mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS); 89 ret = load_phy_image(DMEM_START_ADDR, config->dmem_2d_size, 90 config->dmem_2d); 91 if (ret != NO_ERR) { 92 return ret; 93 } 94 95 mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS); 96 mmio_write_32(APBONLY_MICRORESET, APBONLY_RESET_STALL_MASK); 97 mmio_write_32(APBONLY_MICRORESET, APBONLY_STALL_TO_MICRO_MASK); 98 mmio_write_32(APBONLY_MICRORESET, APBONLY_MICRORESET_CLR_MASK); 99 100 ret = wait_firmware_execution(); 101 if (ret != NO_ERR) { 102 return ret; 103 } 104 105 /* Read 2D training results */ 106 if (config->memory_type == (uint8_t)LPDDR4) { 107 mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS); 108 read_vref_dq(); 109 compute_tphy_wrdata_delay(); 110 mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS); 111 } 112 113 return ret; 114 } 115 116 /* Execute phy training with given settings. 2D training stage is optional. */ 117 static uint32_t execute_training(const struct ddrss_config *config) 118 { 119 uint32_t ret = NO_ERR; 120 121 /* Apply DQ swapping settings */ 122 ret = load_dq_cfg(config->dq_swap_size, config->dq_swap); 123 if (ret != NO_ERR) { 124 return ret; 125 } 126 127 /* Initialize phy module */ 128 ret = load_register_cfg_16(config->phy_size, config->phy); 129 if (ret != NO_ERR) { 130 return ret; 131 } 132 133 /* Configure PLL optimal settings */ 134 set_optimal_pll(config->frequency); 135 136 /* Load 1D imem image */ 137 mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS); 138 ret = load_phy_image(IMEM_START_ADDR, config->imem_1d_size, 139 config->imem_1d); 140 if (ret != NO_ERR) { 141 return ret; 142 } 143 mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS); 144 145 /* Load 1D dmem image */ 146 mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS); 147 ret = load_phy_image(DMEM_START_ADDR, config->dmem_1d_size, 148 config->dmem_1d); 149 if (ret != NO_ERR) { 150 return ret; 151 } 152 153 mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS); 154 mmio_write_32(APBONLY_MICRORESET, APBONLY_RESET_STALL_MASK); 155 mmio_write_32(APBONLY_MICRORESET, APBONLY_STALL_TO_MICRO_MASK); 156 mmio_write_32(APBONLY_MICRORESET, APBONLY_MICRORESET_CLR_MASK); 157 158 ret = wait_firmware_execution(); 159 mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS); 160 if (ret != NO_ERR) { 161 return ret; 162 } 163 164 /* Read critical delay differences and training results */ 165 mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS); 166 read_cdds(); 167 if (config->memory_type == (uint8_t)LPDDR4) { 168 read_vref_ca(); 169 } 170 if (config->memory_type == (uint8_t)DDR3L) { 171 compute_tphy_wrdata_delay(); 172 } 173 mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS); 174 175 /* 176 * Check if 2d training images have been initialized before executing 177 * the second training stage. 178 */ 179 if ((config->imem_2d_size > 0U) && (config->dmem_2d_size > 0U)) { 180 ret = execute_2d_training(config); 181 if (ret != NO_ERR) { 182 return ret; 183 } 184 } 185 186 mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS); 187 /* Load pie image after training has executed */ 188 ret = load_register_cfg_16(config->pie_size, config->pie); 189 mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS); 190 return ret; 191 } 192 193 /* Initialize ddr based on input configuration */ 194 uint32_t ddr_init_cfg(const struct ddrss_config *config) 195 { 196 uint32_t ret = NO_ERR; 197 198 /* Init DDR controller based on selected parameter values */ 199 ret = ddrc_init_cfg(config); 200 if (ret != NO_ERR) { 201 return ret; 202 } 203 204 /* Setup AXI ports parity */ 205 ret = set_axi_parity(); 206 if (ret != NO_ERR) { 207 return ret; 208 } 209 210 /* Init PHY module */ 211 ret = execute_training(config); 212 if (ret != NO_ERR) { 213 return ret; 214 } 215 216 /* Execute post training setup */ 217 ret = post_train_setup((uint8_t)(ADJUST_DDRC_MASK)); 218 219 return ret; 220 } 221 222 /* Load register array into memory. */ 223 uint32_t load_register_cfg_16(size_t size, const struct regconf_16 cfg[]) 224 { 225 size_t i; 226 227 for (i = 0; i < size; i++) { 228 mmio_write_16((uintptr_t)cfg[i].addr, cfg[i].data); 229 } 230 231 return NO_ERR; 232 } 233 234 /* Load register array into memory. */ 235 uint32_t load_register_cfg(size_t size, const struct regconf cfg[]) 236 { 237 size_t i; 238 239 for (i = 0; i < size; i++) { 240 mmio_write_32((uintptr_t)cfg[i].addr, cfg[i].data); 241 } 242 243 return NO_ERR; 244 } 245 246 /* Load dq config array into memory. */ 247 uint32_t load_dq_cfg(size_t size, const struct dqconf cfg[]) 248 { 249 size_t i; 250 251 for (i = 0; i < size; i++) { 252 mmio_write_32((uintptr_t)cfg[i].addr, cfg[i].data); 253 } 254 255 return NO_ERR; 256 } 257 258 /* Load image into memory at consecutive addresses */ 259 static uint32_t load_phy_image(uint32_t start_addr, size_t size, 260 const uint16_t image[]) 261 { 262 uint32_t current_addr = start_addr; 263 size_t i; 264 265 for (i = 0; i < size; i++) { 266 mmio_write_32((uintptr_t)current_addr, image[i]); 267 current_addr += (uint32_t)sizeof(uint32_t); 268 } 269 return NO_ERR; 270 } 271 272 /* Ensure optimal phy pll settings for selected frequency. */ 273 void set_optimal_pll(uint16_t frequency) 274 { 275 /* Configure phy pll registers */ 276 mmio_write_32(MASTER_PLLCTRL1, PLLCTRL1_VALUE); 277 mmio_write_32(MASTER_PLLTESTMODE, PLLTESTMODE_VALUE); 278 mmio_write_32(MASTER_PLLCTRL4, PLLCTRL4_VALUE); 279 mmio_write_32(MASTER_PLLCTRL2, pllctrl2_value(frequency)); 280 281 mmio_setbits_32(MASTER_CALMISC2, (CALMISC2 << CALMISC2_OFFSET)); 282 283 mmio_clrsetbits_32(MASTER_CALOFFSET, 284 CALDRV_MASK, ((CALDRV << CALDRV_OFFSET) | (CALDRV << CALDRV2_OFFSET))); 285 } 286