1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2016 Google, Inc 4 */ 5 6#define LOG_CATEGORY UCLASS_RAM 7 8#include <common.h> 9#include <dm.h> 10#include <init.h> 11#include <log.h> 12#include <spl.h> 13#include <syscon.h> 14#include <asm/cpu.h> 15#include <asm/global_data.h> 16#include <asm/gpio.h> 17#include <asm/intel_regs.h> 18#include <asm/mrc_common.h> 19#include <asm/pch_common.h> 20#include <asm/post.h> 21#include <asm/arch/me.h> 22#include <asm/report_platform.h> 23 24static const char *const ecc_decoder[] = { 25 "inactive", 26 "active on IO", 27 "disabled on IO", 28 "active" 29}; 30 31phys_size_t mrc_common_board_get_usable_ram_top(phys_size_t total_size) 32{ 33 struct memory_info *info = &gd->arch.meminfo; 34 uintptr_t dest_addr = 0; 35 struct memory_area *largest = NULL; 36 int i; 37 38 /* Find largest area of memory below 4GB */ 39 40 for (i = 0; i < info->num_areas; i++) { 41 struct memory_area *area = &info->area[i]; 42 43 if (area->start >= 1ULL << 32) 44 continue; 45 if (!largest || area->size > largest->size) 46 largest = area; 47 } 48 49 /* If no suitable area was found, return an error. */ 50 assert(largest); 51 if (!largest || largest->size < (2 << 20)) 52 panic("No available memory found for relocation"); 53 54 dest_addr = largest->start + largest->size; 55 56 return (phys_size_t)dest_addr; 57} 58 59void mrc_common_dram_init_banksize(void) 60{ 61 struct memory_info *info = &gd->arch.meminfo; 62 int num_banks; 63 int i; 64 65 for (i = 0, num_banks = 0; i < info->num_areas; i++) { 66 struct memory_area *area = &info->area[i]; 67 68 if (area->start >= 1ULL << 32) 69 continue; 70 gd->bd->bi_dram[num_banks].start = area->start; 71 gd->bd->bi_dram[num_banks].size = area->size; 72 num_banks++; 73 } 74} 75 76int mrc_add_memory_area(struct memory_info *info, uint64_t start, 77 uint64_t end) 78{ 79 struct memory_area *ptr; 80 81 if (info->num_areas == CONFIG_NR_DRAM_BANKS) 82 return -ENOSPC; 83 84 ptr = &info->area[info->num_areas]; 85 ptr->start = start; 86 ptr->size = end - start; 87 info->total_memory += ptr->size; 88 if (ptr->start < (1ULL << 32)) 89 info->total_32bit_memory += ptr->size; 90 debug("%d: memory %llx size %llx, total now %llx / %llx\n", 91 info->num_areas, ptr->start, ptr->size, 92 info->total_32bit_memory, info->total_memory); 93 info->num_areas++; 94 95 return 0; 96} 97 98/* 99 * Dump in the log memory controller configuration as read from the memory 100 * controller registers. 101 */ 102void report_memory_config(void) 103{ 104 u32 addr_decoder_common, addr_decode_ch[2]; 105 int i; 106 107 addr_decoder_common = readl(MCHBAR_REG(0x5000)); 108 addr_decode_ch[0] = readl(MCHBAR_REG(0x5004)); 109 addr_decode_ch[1] = readl(MCHBAR_REG(0x5008)); 110 111 debug("memcfg DDR3 clock %d MHz\n", 112 (readl(MCHBAR_REG(0x5e04)) * 13333 * 2 + 50) / 100); 113 debug("memcfg channel assignment: A: %d, B % d, C % d\n", 114 addr_decoder_common & 3, 115 (addr_decoder_common >> 2) & 3, 116 (addr_decoder_common >> 4) & 3); 117 118 for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) { 119 u32 ch_conf = addr_decode_ch[i]; 120 debug("memcfg channel[%d] config (%8.8x):\n", i, ch_conf); 121 debug(" ECC %s\n", ecc_decoder[(ch_conf >> 24) & 3]); 122 debug(" enhanced interleave mode %s\n", 123 ((ch_conf >> 22) & 1) ? "on" : "off"); 124 debug(" rank interleave %s\n", 125 ((ch_conf >> 21) & 1) ? "on" : "off"); 126 debug(" DIMMA %d MB width x%d %s rank%s\n", 127 ((ch_conf >> 0) & 0xff) * 256, 128 ((ch_conf >> 19) & 1) ? 16 : 8, 129 ((ch_conf >> 17) & 1) ? "dual" : "single", 130 ((ch_conf >> 16) & 1) ? "" : ", selected"); 131 debug(" DIMMB %d MB width x%d %s rank%s\n", 132 ((ch_conf >> 8) & 0xff) * 256, 133 ((ch_conf >> 20) & 1) ? 16 : 8, 134 ((ch_conf >> 18) & 1) ? "dual" : "single", 135 ((ch_conf >> 16) & 1) ? ", selected" : ""); 136 } 137} 138 139int mrc_locate_spd(struct udevice *dev, int size, const void **spd_datap) 140{ 141 const void *blob = gd->fdt_blob; 142 int spd_index; 143 struct gpio_desc desc[4]; 144 int spd_node; 145 int node; 146 int ret; 147 148 ret = gpio_request_list_by_name(dev, "board-id-gpios", desc, 149 ARRAY_SIZE(desc), GPIOD_IS_IN); 150 if (ret < 0) 151 return log_msg_ret("gpio", ret); 152 spd_index = dm_gpio_get_values_as_int(desc, ret); 153 log_debug("spd index %d\n", spd_index); 154 155 node = fdt_first_subnode(blob, dev_of_offset(dev)); 156 if (node < 0) 157 return -EINVAL; 158 for (spd_node = fdt_first_subnode(blob, node); 159 spd_node > 0; 160 spd_node = fdt_next_subnode(blob, spd_node)) { 161 int len; 162 163 if (fdtdec_get_int(blob, spd_node, "reg", -1) != spd_index) 164 continue; 165 *spd_datap = fdt_getprop(blob, spd_node, "data", &len); 166 if (len < size) { 167 printf("Missing SPD data\n"); 168 return -EINVAL; 169 } 170 171 debug("Using SDRAM SPD data for '%s'\n", 172 fdt_get_name(blob, spd_node, NULL)); 173 return 0; 174 } 175 176 printf("No SPD data found for index %d\n", spd_index); 177 return -ENOENT; 178} 179 180asmlinkage void sdram_console_tx_byte(unsigned char byte) 181{ 182#ifdef DEBUG 183 putc(byte); 184#endif 185} 186 187/** 188 * Find the PEI executable in the ROM and execute it. 189 * 190 * @me_dev: Management Engine device 191 * @pei_data: configuration data for UEFI PEI reference code 192 */ 193static int sdram_initialise(struct udevice *dev, struct udevice *me_dev, 194 void *pei_data, bool use_asm_linkage) 195{ 196 unsigned version; 197 const char *data; 198 199 report_platform_info(dev); 200 debug("Starting UEFI PEI System Agent\n"); 201 202 debug("PEI data at %p:\n", pei_data); 203 204 data = (char *)CFG_X86_MRC_ADDR; 205 if (data) { 206 int rv; 207 ulong start; 208 209 debug("Calling MRC at %p\n", data); 210 post_code(POST_PRE_MRC); 211 start = get_timer(0); 212 if (use_asm_linkage) { 213 asmlinkage int (*func)(void *); 214 215 func = (asmlinkage int (*)(void *))data; 216 rv = func(pei_data); 217 } else { 218 int (*func)(void *); 219 220 func = (int (*)(void *))data; 221 rv = func(pei_data); 222 } 223 post_code(POST_MRC); 224 if (rv) { 225 switch (rv) { 226 case -1: 227 printf("PEI version mismatch.\n"); 228 break; 229 case -2: 230 printf("Invalid memory frequency.\n"); 231 break; 232 default: 233 printf("MRC returned %x.\n", rv); 234 } 235 printf("Nonzero MRC return value.\n"); 236 return -EFAULT; 237 } 238 debug("MRC execution time %lu ms\n", get_timer(start)); 239 } else { 240 printf("UEFI PEI System Agent not found.\n"); 241 return -ENOSYS; 242 } 243 244 version = readl(MCHBAR_REG(MCHBAR_PEI_VERSION)); 245 debug("System Agent Version %d.%d.%d Build %d\n", 246 version >> 24 , (version >> 16) & 0xff, 247 (version >> 8) & 0xff, version & 0xff); 248 249 return 0; 250} 251 252int mrc_common_init(struct udevice *dev, void *pei_data, bool use_asm_linkage) 253{ 254 struct udevice *me_dev; 255 int ret, delay; 256 257 ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev); 258 if (ret) 259 return ret; 260 261 delay = dev_read_u32_default(dev, "fspm,training-delay", 0); 262 if (spl_phase() == PHASE_SPL) { 263 if (delay) 264 printf("SDRAM training (%d seconds)...", delay); 265 else 266 log_debug("SDRAM init..."); 267 } else { 268 if (delay) 269 printf("(%d seconds)...", delay); 270 } 271 272 ret = sdram_initialise(dev, me_dev, pei_data, use_asm_linkage); 273 if (delay) 274 printf("done\n"); 275 else 276 log_debug("done\n"); 277 if (ret) 278 return ret; 279 quick_ram_check(); 280 post_code(POST_DRAM); 281 report_memory_config(); 282 283 return 0; 284} 285