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