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