1 /* 2 * Copyright (C) 2018-2022, 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 <arch_helpers.h> 10 #include <common/debug.h> 11 #include <common/fdt_wrappers.h> 12 #include <drivers/clk.h> 13 #include <drivers/st/stm32mp1_ddr.h> 14 #include <drivers/st/stm32mp1_ddr_helpers.h> 15 #include <drivers/st/stm32mp1_ram.h> 16 #include <drivers/st/stm32mp_ddr.h> 17 #include <drivers/st/stm32mp_ram.h> 18 #include <lib/mmio.h> 19 #include <libfdt.h> 20 21 #include <platform_def.h> 22 23 #define DDR_PATTERN 0xAAAAAAAAU 24 #define DDR_ANTIPATTERN 0x55555555U 25 26 static struct stm32mp_ddr_priv ddr_priv_data; 27 28 int stm32mp1_ddr_clk_enable(struct stm32mp_ddr_priv *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 = clk_get_rate(DDRPHYC); 35 36 VERBOSE("DDR: mem_speed (%u kHz), RCC %lu 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 %u kHz, current is %lu 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(STM32MP_DDR_BASE, pattern); 69 70 if (mmio_read_32(STM32MP_DDR_BASE) != pattern) { 71 return (uint32_t)STM32MP_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(STM32MP_DDR_BASE + (uint32_t)offset, 96 DDR_PATTERN); 97 } 98 99 /* Check for address bits stuck high. */ 100 mmio_write_32(STM32MP_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(STM32MP_DDR_BASE + (uint32_t)offset) != 106 DDR_PATTERN) { 107 return (uint32_t)(STM32MP_DDR_BASE + offset); 108 } 109 } 110 111 mmio_write_32(STM32MP_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(STM32MP_DDR_BASE + (uint32_t)testoffset, 117 DDR_ANTIPATTERN); 118 119 if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { 120 return STM32MP_DDR_BASE; 121 } 122 123 for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; 124 offset <<= 1) { 125 if ((mmio_read_32(STM32MP_DDR_BASE + 126 (uint32_t)offset) != DDR_PATTERN) && 127 (offset != testoffset)) { 128 return (uint32_t)(STM32MP_DDR_BASE + offset); 129 } 130 } 131 132 mmio_write_32(STM32MP_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(STM32MP_DDR_BASE, DDR_PATTERN); 151 152 while (offset < STM32MP_DDR_MAX_SIZE) { 153 mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN); 154 dsb(); 155 156 if (mmio_read_32(STM32MP_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 stm32mp_ddr_priv *priv = &ddr_priv_data; 171 int ret; 172 struct stm32mp_ddr_config config; 173 int node; 174 uint32_t uret; 175 void *fdt; 176 177 const struct stm32mp_ddr_param param[] = { 178 CTL_PARAM(reg), 179 CTL_PARAM(timing), 180 CTL_PARAM(map), 181 CTL_PARAM(perf), 182 PHY_PARAM(reg), 183 PHY_PARAM(timing), 184 }; 185 186 if (fdt_get_address(&fdt) == 0) { 187 return -ENOENT; 188 } 189 190 node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); 191 if (node < 0) { 192 ERROR("%s: Cannot read DDR node in DT\n", __func__); 193 return -EINVAL; 194 } 195 196 ret = stm32mp_ddr_dt_get_info(fdt, node, &config.info); 197 if (ret < 0) { 198 return ret; 199 } 200 201 ret = stm32mp_ddr_dt_get_param(fdt, node, param, ARRAY_SIZE(param), (uintptr_t)&config); 202 if (ret < 0) { 203 return ret; 204 } 205 206 /* Disable axidcg clock gating during init */ 207 mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); 208 209 stm32mp1_ddr_init(priv, &config); 210 211 /* Enable axidcg clock gating */ 212 mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); 213 214 priv->info.size = config.info.size; 215 216 VERBOSE("%s : ram size(%x, %x)\n", __func__, 217 (uint32_t)priv->info.base, (uint32_t)priv->info.size); 218 219 if (stm32mp_map_ddr_non_cacheable() != 0) { 220 panic(); 221 } 222 223 uret = ddr_test_data_bus(); 224 if (uret != 0U) { 225 ERROR("DDR data bus test: can't access memory @ 0x%x\n", 226 uret); 227 panic(); 228 } 229 230 uret = ddr_test_addr_bus(); 231 if (uret != 0U) { 232 ERROR("DDR addr bus test: can't access memory @ 0x%x\n", 233 uret); 234 panic(); 235 } 236 237 uret = ddr_check_size(); 238 if (uret < config.info.size) { 239 ERROR("DDR size: 0x%x does not match DT config: 0x%x\n", 240 uret, config.info.size); 241 panic(); 242 } 243 244 if (stm32mp_unmap_ddr() != 0) { 245 panic(); 246 } 247 248 return 0; 249 } 250 251 int stm32mp1_ddr_probe(void) 252 { 253 struct stm32mp_ddr_priv *priv = &ddr_priv_data; 254 255 VERBOSE("STM32MP DDR probe\n"); 256 257 priv->ctl = (struct stm32mp_ddrctl *)stm32mp_ddrctrl_base(); 258 priv->phy = (struct stm32mp_ddrphy *)stm32mp_ddrphyc_base(); 259 priv->pwr = stm32mp_pwr_base(); 260 priv->rcc = stm32mp_rcc_base(); 261 262 priv->info.base = STM32MP_DDR_BASE; 263 priv->info.size = 0; 264 265 return stm32mp1_ddr_setup(); 266 } 267