1 /* 2 * Copyright (C) 2018, 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, uint16_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 MHz), RCC %ld MHz\n", 37 mem_speed, ddrphy_clk / 1000U / 1000U); 38 39 mem_speed_hz = (uint32_t)mem_speed * 1000U * 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) { 48 ERROR("DDR expected freq %d MHz, current is %ld MHz\n", 49 mem_speed, ddrphy_clk / 1000U / 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 = 212 (uint16_t)fdt_read_uint32_default(node, "st,mem-speed", 213 STM32MP1_DDR_SPEED_DFLT); 214 config.info.size = fdt_read_uint32_default(node, "st,mem-size", 215 STM32MP1_DDR_SIZE_DFLT); 216 config.info.name = fdt_getprop(fdt, node, "st,mem-name", &len); 217 if (config.info.name == NULL) { 218 VERBOSE("%s: no st,mem-name\n", __func__); 219 return -EINVAL; 220 } 221 INFO("RAM: %s\n", config.info.name); 222 223 for (idx = 0; idx < ARRAY_SIZE(param); idx++) { 224 ret = fdt_read_uint32_array(node, param[idx].name, 225 (void *)((uint32_t)&config + 226 param[idx].offset), 227 param[idx].size); 228 229 VERBOSE("%s: %s[0x%x] = %d\n", __func__, 230 param[idx].name, param[idx].size, ret); 231 if (ret != 0) { 232 ERROR("%s: Cannot read %s\n", 233 __func__, param[idx].name); 234 return -EINVAL; 235 } 236 } 237 238 if (!stm32mp1_clk_is_enabled(RTCAPB)) { 239 tamp_clk_off = 1; 240 if (stm32mp1_clk_enable(RTCAPB) != 0) { 241 return -EINVAL; 242 } 243 } 244 245 if (tamp_clk_off != 0U) { 246 if (stm32mp1_clk_disable(RTCAPB) != 0) { 247 return -EINVAL; 248 } 249 } 250 251 /* Disable axidcg clock gating during init */ 252 mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); 253 254 stm32mp1_ddr_init(priv, &config); 255 256 /* Enable axidcg clock gating */ 257 mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); 258 259 priv->info.size = config.info.size; 260 261 VERBOSE("%s : ram size(%x, %x)\n", __func__, 262 (uint32_t)priv->info.base, (uint32_t)priv->info.size); 263 264 dcsw_op_all(DC_OP_CISW); 265 write_sctlr(read_sctlr() & ~SCTLR_C_BIT); 266 267 uret = ddr_test_data_bus(); 268 if (uret != 0U) { 269 ERROR("DDR data bus test: can't access memory @ 0x%x\n", 270 uret); 271 panic(); 272 } 273 274 uret = ddr_test_addr_bus(); 275 if (uret != 0U) { 276 ERROR("DDR addr bus test: can't access memory @ 0x%x\n", 277 uret); 278 panic(); 279 } 280 281 uret = ddr_check_size(); 282 if (uret < config.info.size) { 283 ERROR("DDR size: 0x%x does not match DT config: 0x%x\n", 284 uret, config.info.size); 285 panic(); 286 } 287 288 write_sctlr(read_sctlr() | SCTLR_C_BIT); 289 290 return 0; 291 } 292 293 int stm32mp1_ddr_probe(void) 294 { 295 struct ddr_info *priv = &ddr_priv_data; 296 297 VERBOSE("STM32MP DDR probe\n"); 298 299 priv->ctl = (struct stm32mp1_ddrctl *)DDRCTRL_BASE; 300 priv->phy = (struct stm32mp1_ddrphy *)DDRPHYC_BASE; 301 priv->pwr = PWR_BASE; 302 priv->rcc = RCC_BASE; 303 304 priv->info.base = STM32MP1_DDR_BASE; 305 priv->info.size = 0; 306 307 return stm32mp1_ddr_setup(); 308 } 309