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