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