1 /* 2 * Copyright (C) 2018-2021, 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 <libfdt.h> 10 11 #include <platform_def.h> 12 13 #include <arch_helpers.h> 14 #include <common/debug.h> 15 #include <common/fdt_wrappers.h> 16 #include <drivers/clk.h> 17 #include <drivers/st/stm32mp1_ddr.h> 18 #include <drivers/st/stm32mp1_ddr_helpers.h> 19 #include <drivers/st/stm32mp1_ram.h> 20 #include <lib/mmio.h> 21 22 #define DDR_PATTERN 0xAAAAAAAAU 23 #define DDR_ANTIPATTERN 0x55555555U 24 25 static struct ddr_info ddr_priv_data; 26 27 int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) 28 { 29 unsigned long ddrphy_clk, ddr_clk, mem_speed_hz; 30 31 ddr_enable_clock(); 32 33 ddrphy_clk = clk_get_rate(DDRPHYC); 34 35 VERBOSE("DDR: mem_speed (%d kHz), RCC %ld kHz\n", 36 mem_speed, ddrphy_clk / 1000U); 37 38 mem_speed_hz = mem_speed * 1000U; 39 40 /* Max 10% frequency delta */ 41 if (ddrphy_clk > mem_speed_hz) { 42 ddr_clk = ddrphy_clk - mem_speed_hz; 43 } else { 44 ddr_clk = mem_speed_hz - ddrphy_clk; 45 } 46 if (ddr_clk > (mem_speed_hz / 10)) { 47 ERROR("DDR expected freq %d kHz, current is %ld kHz\n", 48 mem_speed, ddrphy_clk / 1000U); 49 return -1; 50 } 51 return 0; 52 } 53 54 /******************************************************************************* 55 * This function tests the DDR data bus wiring. 56 * This is inspired from the Data Bus Test algorithm written by Michael Barr 57 * in "Programming Embedded Systems in C and C++" book. 58 * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ 59 * File: memtest.c - This source code belongs to Public Domain. 60 * Returns 0 if success, and address value else. 61 ******************************************************************************/ 62 static uint32_t ddr_test_data_bus(void) 63 { 64 uint32_t pattern; 65 66 for (pattern = 1U; pattern != 0U; pattern <<= 1) { 67 mmio_write_32(STM32MP_DDR_BASE, pattern); 68 69 if (mmio_read_32(STM32MP_DDR_BASE) != pattern) { 70 return (uint32_t)STM32MP_DDR_BASE; 71 } 72 } 73 74 return 0; 75 } 76 77 /******************************************************************************* 78 * This function tests the DDR address bus wiring. 79 * This is inspired from the Data Bus Test algorithm written by Michael Barr 80 * in "Programming Embedded Systems in C and C++" book. 81 * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ 82 * File: memtest.c - This source code belongs to Public Domain. 83 * Returns 0 if success, and address value else. 84 ******************************************************************************/ 85 static uint32_t ddr_test_addr_bus(void) 86 { 87 uint64_t addressmask = (ddr_priv_data.info.size - 1U); 88 uint64_t offset; 89 uint64_t testoffset = 0; 90 91 /* Write the default pattern at each of the power-of-two offsets. */ 92 for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; 93 offset <<= 1) { 94 mmio_write_32(STM32MP_DDR_BASE + (uint32_t)offset, 95 DDR_PATTERN); 96 } 97 98 /* Check for address bits stuck high. */ 99 mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, 100 DDR_ANTIPATTERN); 101 102 for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; 103 offset <<= 1) { 104 if (mmio_read_32(STM32MP_DDR_BASE + (uint32_t)offset) != 105 DDR_PATTERN) { 106 return (uint32_t)(STM32MP_DDR_BASE + offset); 107 } 108 } 109 110 mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN); 111 112 /* Check for address bits stuck low or shorted. */ 113 for (testoffset = sizeof(uint32_t); (testoffset & addressmask) != 0U; 114 testoffset <<= 1) { 115 mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, 116 DDR_ANTIPATTERN); 117 118 if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { 119 return STM32MP_DDR_BASE; 120 } 121 122 for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; 123 offset <<= 1) { 124 if ((mmio_read_32(STM32MP_DDR_BASE + 125 (uint32_t)offset) != DDR_PATTERN) && 126 (offset != testoffset)) { 127 return (uint32_t)(STM32MP_DDR_BASE + offset); 128 } 129 } 130 131 mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, 132 DDR_PATTERN); 133 } 134 135 return 0; 136 } 137 138 /******************************************************************************* 139 * This function checks the DDR size. It has to be run with Data Cache off. 140 * This test is run before data have been put in DDR, and is only done for 141 * cold boot. The DDR data can then be overwritten, and it is not useful to 142 * restore its content. 143 * Returns DDR computed size. 144 ******************************************************************************/ 145 static uint32_t ddr_check_size(void) 146 { 147 uint32_t offset = sizeof(uint32_t); 148 149 mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); 150 151 while (offset < STM32MP_DDR_MAX_SIZE) { 152 mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN); 153 dsb(); 154 155 if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { 156 break; 157 } 158 159 offset <<= 1; 160 } 161 162 INFO("Memory size = 0x%x (%d MB)\n", offset, offset / (1024U * 1024U)); 163 164 return offset; 165 } 166 167 static int stm32mp1_ddr_setup(void) 168 { 169 struct ddr_info *priv = &ddr_priv_data; 170 int ret; 171 struct stm32mp1_ddr_config config; 172 int node, len; 173 uint32_t uret, idx; 174 void *fdt; 175 176 #define PARAM(x, y) \ 177 { \ 178 .name = x, \ 179 .offset = offsetof(struct stm32mp1_ddr_config, y), \ 180 .size = sizeof(config.y) / sizeof(uint32_t) \ 181 } 182 183 #define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x) 184 #define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x) 185 186 const struct { 187 const char *name; /* Name in DT */ 188 const uint32_t offset; /* Offset in config struct */ 189 const uint32_t size; /* Size of parameters */ 190 } param[] = { 191 CTL_PARAM(reg), 192 CTL_PARAM(timing), 193 CTL_PARAM(map), 194 CTL_PARAM(perf), 195 PHY_PARAM(reg), 196 PHY_PARAM(timing), 197 PHY_PARAM(cal) 198 }; 199 200 if (fdt_get_address(&fdt) == 0) { 201 return -ENOENT; 202 } 203 204 node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); 205 if (node < 0) { 206 ERROR("%s: Cannot read DDR node in DT\n", __func__); 207 return -EINVAL; 208 } 209 210 ret = fdt_read_uint32(fdt, node, "st,mem-speed", &config.info.speed); 211 if (ret < 0) { 212 VERBOSE("%s: no st,mem-speed\n", __func__); 213 return -EINVAL; 214 } 215 ret = fdt_read_uint32(fdt, node, "st,mem-size", &config.info.size); 216 if (ret < 0) { 217 VERBOSE("%s: no st,mem-size\n", __func__); 218 return -EINVAL; 219 } 220 config.info.name = fdt_getprop(fdt, node, "st,mem-name", &len); 221 if (config.info.name == NULL) { 222 VERBOSE("%s: no st,mem-name\n", __func__); 223 return -EINVAL; 224 } 225 INFO("RAM: %s\n", config.info.name); 226 227 for (idx = 0; idx < ARRAY_SIZE(param); idx++) { 228 ret = fdt_read_uint32_array(fdt, node, param[idx].name, 229 param[idx].size, 230 (void *)((uintptr_t)&config + 231 param[idx].offset)); 232 233 VERBOSE("%s: %s[0x%x] = %d\n", __func__, 234 param[idx].name, param[idx].size, ret); 235 if (ret != 0) { 236 ERROR("%s: Cannot read %s\n", 237 __func__, param[idx].name); 238 return -EINVAL; 239 } 240 } 241 242 /* Disable axidcg clock gating during init */ 243 mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); 244 245 stm32mp1_ddr_init(priv, &config); 246 247 /* Enable axidcg clock gating */ 248 mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); 249 250 priv->info.size = config.info.size; 251 252 VERBOSE("%s : ram size(%x, %x)\n", __func__, 253 (uint32_t)priv->info.base, (uint32_t)priv->info.size); 254 255 if (stm32mp_map_ddr_non_cacheable() != 0) { 256 panic(); 257 } 258 259 uret = ddr_test_data_bus(); 260 if (uret != 0U) { 261 ERROR("DDR data bus test: can't access memory @ 0x%x\n", 262 uret); 263 panic(); 264 } 265 266 uret = ddr_test_addr_bus(); 267 if (uret != 0U) { 268 ERROR("DDR addr bus test: can't access memory @ 0x%x\n", 269 uret); 270 panic(); 271 } 272 273 uret = ddr_check_size(); 274 if (uret < config.info.size) { 275 ERROR("DDR size: 0x%x does not match DT config: 0x%x\n", 276 uret, config.info.size); 277 panic(); 278 } 279 280 if (stm32mp_unmap_ddr() != 0) { 281 panic(); 282 } 283 284 return 0; 285 } 286 287 int stm32mp1_ddr_probe(void) 288 { 289 struct ddr_info *priv = &ddr_priv_data; 290 291 VERBOSE("STM32MP DDR probe\n"); 292 293 priv->ctl = (struct stm32mp1_ddrctl *)stm32mp_ddrctrl_base(); 294 priv->phy = (struct stm32mp1_ddrphy *)stm32mp_ddrphyc_base(); 295 priv->pwr = stm32mp_pwr_base(); 296 priv->rcc = stm32mp_rcc_base(); 297 298 priv->info.base = STM32MP_DDR_BASE; 299 priv->info.size = 0; 300 301 return stm32mp1_ddr_setup(); 302 } 303