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