X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=arch%2Fx86%2Fcpu%2Fivybridge%2Fsdram.c;h=99bc48021e6900fdb439fc2b1e8e04de99dfa93e;hb=60c7facfc965af6ff8ea14ee26c9d49cd2d0ec22;hp=9a6da37d09d30282d10498a0e67463edcb7ecee3;hpb=b939689c7b87773c44275a578ffc8674a867e39d;p=oweals%2Fu-boot.git diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index 9a6da37d09..99bc48021e 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2011 The Chromium OS Authors. * (C) Copyright 2010,2011 @@ -6,25 +7,31 @@ * Portions from Coreboot mainboard/google/link/romstage.c * Copyright (C) 2007-2010 coresystems GmbH * Copyright (C) 2011 Google Inc. - * - * SPDX-License-Identifier: GPL-2.0 */ #include #include #include +#include +#include #include #include #include #include #include +#include +#include +#include #include #include #include +#include +#include +#include #include #include +#include #include -#include #include #include #include @@ -36,91 +43,14 @@ DECLARE_GLOBAL_DATA_PTR; #define CMOS_OFFSET_MRC_SEED_S3 156 #define CMOS_OFFSET_MRC_SEED_CHK 160 -/* - * This function looks for the highest region of memory lower than 4GB which - * has enough space for U-Boot where U-Boot is aligned on a page boundary. - * It overrides the default implementation found elsewhere which simply - * picks the end of ram, wherever that may be. The location of the stack, - * the relocation address, and how far U-Boot is moved by relocation are - * set in the global data structure. - */ ulong board_get_usable_ram_top(ulong total_size) { - struct memory_info *info = &gd->arch.meminfo; - uintptr_t dest_addr = 0; - struct memory_area *largest = NULL; - int i; - - /* Find largest area of memory below 4GB */ - - for (i = 0; i < info->num_areas; i++) { - struct memory_area *area = &info->area[i]; - - if (area->start >= 1ULL << 32) - continue; - if (!largest || area->size > largest->size) - largest = area; - } - - /* If no suitable area was found, return an error. */ - assert(largest); - if (!largest || largest->size < (2 << 20)) - panic("No available memory found for relocation"); - - dest_addr = largest->start + largest->size; - - return (ulong)dest_addr; -} - -void dram_init_banksize(void) -{ - struct memory_info *info = &gd->arch.meminfo; - int num_banks; - int i; - - for (i = 0, num_banks = 0; i < info->num_areas; i++) { - struct memory_area *area = &info->area[i]; - - if (area->start >= 1ULL << 32) - continue; - gd->bd->bi_dram[num_banks].start = area->start; - gd->bd->bi_dram[num_banks].size = area->size; - num_banks++; - } + return mrc_common_board_get_usable_ram_top(total_size); } -static int get_mrc_entry(struct udevice **devp, struct fmap_entry *entry) +int dram_init_banksize(void) { - const void *blob = gd->fdt_blob; - int node, spi_node, mrc_node; - int upto; - int ret; - - /* Find the flash chip within the SPI controller node */ - upto = 0; - spi_node = fdtdec_next_alias(blob, "spi", COMPAT_INTEL_ICH_SPI, &upto); - if (spi_node < 0) - return -ENOENT; - node = fdt_first_subnode(blob, spi_node); - if (node < 0) - return -ECHILD; - - /* Find the place where we put the MRC cache */ - mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache"); - if (mrc_node < 0) - return -EPERM; - - if (fdtdec_read_fmap_entry(blob, mrc_node, "rm-mrc-cache", entry)) - return -EINVAL; - - if (devp) { - debug("getting sf\n"); - ret = uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node, - devp); - debug("ret = %d\n", ret); - if (ret) - return ret; - } + mrc_common_dram_init_banksize(); return 0; } @@ -128,6 +58,14 @@ static int get_mrc_entry(struct udevice **devp, struct fmap_entry *entry) static int read_seed_from_cmos(struct pei_data *pei_data) { u16 c1, c2, checksum, seed_checksum; + struct udevice *dev; + int ret = 0; + + ret = uclass_get_device(UCLASS_RTC, 0, &dev); + if (ret) { + debug("Cannot find RTC: err=%d\n", ret); + return -ENODEV; + } /* * Read scrambler seeds from CMOS RAM. We don't want to store them in @@ -135,11 +73,18 @@ static int read_seed_from_cmos(struct pei_data *pei_data) * the flash too much. So we store these in CMOS and the large MRC * data in SPI flash. */ - pei_data->scrambler_seed = rtc_read32(CMOS_OFFSET_MRC_SEED); + ret = rtc_read32(dev, CMOS_OFFSET_MRC_SEED, &pei_data->scrambler_seed); + if (!ret) { + ret = rtc_read32(dev, CMOS_OFFSET_MRC_SEED_S3, + &pei_data->scrambler_seed_s3); + } + if (ret) { + debug("Failed to read from RTC %s\n", dev->name); + return ret; + } + debug("Read scrambler seed 0x%08x from CMOS 0x%02x\n", pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED); - - pei_data->scrambler_seed_s3 = rtc_read32(CMOS_OFFSET_MRC_SEED_S3); debug("Read S3 scrambler seed 0x%08x from CMOS 0x%02x\n", pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3); @@ -150,8 +95,8 @@ static int read_seed_from_cmos(struct pei_data *pei_data) sizeof(u32)); checksum = add_ip_checksums(sizeof(u32), c1, c2); - seed_checksum = rtc_read8(CMOS_OFFSET_MRC_SEED_CHK); - seed_checksum |= rtc_read8(CMOS_OFFSET_MRC_SEED_CHK + 1) << 8; + seed_checksum = rtc_read8(dev, CMOS_OFFSET_MRC_SEED_CHK); + seed_checksum |= rtc_read8(dev, CMOS_OFFSET_MRC_SEED_CHK + 1) << 8; if (checksum != seed_checksum) { debug("%s: invalid seed checksum\n", __func__); @@ -166,27 +111,21 @@ static int read_seed_from_cmos(struct pei_data *pei_data) static int prepare_mrc_cache(struct pei_data *pei_data) { struct mrc_data_container *mrc_cache; - struct fmap_entry entry; + struct mrc_region entry; int ret; ret = read_seed_from_cmos(pei_data); if (ret) return ret; - ret = get_mrc_entry(NULL, &entry); + ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry); if (ret) return ret; mrc_cache = mrccache_find_current(&entry); if (!mrc_cache) return -ENOENT; - /* - * TODO(sjg@chromium.org): Skip this for now as it causes boot - * problems - */ - if (0) { - pei_data->mrc_input = mrc_cache->data; - pei_data->mrc_input_len = mrc_cache->data_size; - } + pei_data->mrc_input = mrc_cache->data; + pei_data->mrc_input_len = mrc_cache->data_size; debug("%s: at %p, size %x checksum %04x\n", __func__, pei_data->mrc_input, pei_data->mrc_input_len, mrc_cache->checksum); @@ -194,42 +133,24 @@ static int prepare_mrc_cache(struct pei_data *pei_data) return 0; } -static int build_mrc_data(struct mrc_data_container **datap) -{ - struct mrc_data_container *data; - int orig_len; - int output_len; - - orig_len = gd->arch.mrc_output_len; - output_len = ALIGN(orig_len, 16); - data = malloc(output_len + sizeof(*data)); - if (!data) - return -ENOMEM; - data->signature = MRC_DATA_SIGNATURE; - data->data_size = output_len; - data->reserved = 0; - memcpy(data->data, gd->arch.mrc_output, orig_len); - - /* Zero the unused space in aligned buffer. */ - if (output_len > orig_len) - memset(data->data + orig_len, 0, output_len - orig_len); - - data->checksum = compute_ip_checksum(data->data, output_len); - *datap = data; - - return 0; -} - static int write_seeds_to_cmos(struct pei_data *pei_data) { u16 c1, c2, checksum; + struct udevice *dev; + int ret = 0; + + ret = uclass_get_device(UCLASS_RTC, 0, &dev); + if (ret) { + debug("Cannot find RTC: err=%d\n", ret); + return -ENODEV; + } /* Save the MRC seed values to CMOS */ - rtc_write32(CMOS_OFFSET_MRC_SEED, pei_data->scrambler_seed); + rtc_write32(dev, CMOS_OFFSET_MRC_SEED, pei_data->scrambler_seed); debug("Save scrambler seed 0x%08x to CMOS 0x%02x\n", pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED); - rtc_write32(CMOS_OFFSET_MRC_SEED_S3, pei_data->scrambler_seed_s3); + rtc_write32(dev, CMOS_OFFSET_MRC_SEED_S3, pei_data->scrambler_seed_s3); debug("Save s3 scrambler seed 0x%08x to CMOS 0x%02x\n", pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3); @@ -240,337 +161,62 @@ static int write_seeds_to_cmos(struct pei_data *pei_data) sizeof(u32)); checksum = add_ip_checksums(sizeof(u32), c1, c2); - rtc_write8(CMOS_OFFSET_MRC_SEED_CHK, checksum & 0xff); - rtc_write8(CMOS_OFFSET_MRC_SEED_CHK + 1, (checksum >> 8) & 0xff); + rtc_write8(dev, CMOS_OFFSET_MRC_SEED_CHK, checksum & 0xff); + rtc_write8(dev, CMOS_OFFSET_MRC_SEED_CHK + 1, (checksum >> 8) & 0xff); return 0; } -static int sdram_save_mrc_data(void) -{ - struct mrc_data_container *data; - struct fmap_entry entry; - struct udevice *sf; - int ret; - - if (!gd->arch.mrc_output_len) - return 0; - debug("Saving %d bytes of MRC output data to SPI flash\n", - gd->arch.mrc_output_len); - - ret = get_mrc_entry(&sf, &entry); - if (ret) - goto err_entry; - ret = build_mrc_data(&data); - if (ret) - goto err_data; - ret = mrccache_update(sf, &entry, data); - if (!ret) - debug("Saved MRC data with checksum %04x\n", data->checksum); - - free(data); -err_data: -err_entry: - if (ret) - debug("%s: Failed: %d\n", __func__, ret); - return ret; -} - /* Use this hook to save our SDRAM parameters */ int misc_init_r(void) { int ret; - ret = sdram_save_mrc_data(); + ret = mrccache_save(); if (ret) printf("Unable to save MRC data: %d\n", ret); return 0; } -static const char *const ecc_decoder[] = { - "inactive", - "active on IO", - "disabled on IO", - "active" -}; - -/* - * Dump in the log memory controller configuration as read from the memory - * controller registers. - */ -static void report_memory_config(void) -{ - u32 addr_decoder_common, addr_decode_ch[2]; - int i; - - addr_decoder_common = readl(MCHBAR_REG(0x5000)); - addr_decode_ch[0] = readl(MCHBAR_REG(0x5004)); - addr_decode_ch[1] = readl(MCHBAR_REG(0x5008)); - - debug("memcfg DDR3 clock %d MHz\n", - (readl(MCHBAR_REG(0x5e04)) * 13333 * 2 + 50) / 100); - debug("memcfg channel assignment: A: %d, B % d, C % d\n", - addr_decoder_common & 3, - (addr_decoder_common >> 2) & 3, - (addr_decoder_common >> 4) & 3); - - for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) { - u32 ch_conf = addr_decode_ch[i]; - debug("memcfg channel[%d] config (%8.8x):\n", i, ch_conf); - debug(" ECC %s\n", ecc_decoder[(ch_conf >> 24) & 3]); - debug(" enhanced interleave mode %s\n", - ((ch_conf >> 22) & 1) ? "on" : "off"); - debug(" rank interleave %s\n", - ((ch_conf >> 21) & 1) ? "on" : "off"); - debug(" DIMMA %d MB width x%d %s rank%s\n", - ((ch_conf >> 0) & 0xff) * 256, - ((ch_conf >> 19) & 1) ? 16 : 8, - ((ch_conf >> 17) & 1) ? "dual" : "single", - ((ch_conf >> 16) & 1) ? "" : ", selected"); - debug(" DIMMB %d MB width x%d %s rank%s\n", - ((ch_conf >> 8) & 0xff) * 256, - ((ch_conf >> 20) & 1) ? 16 : 8, - ((ch_conf >> 18) & 1) ? "dual" : "single", - ((ch_conf >> 16) & 1) ? ", selected" : ""); - } -} - -static void post_system_agent_init(struct pei_data *pei_data) -{ - /* If PCIe init is skipped, set the PEG clock gating */ - if (!pei_data->pcie_init) - setbits_le32(MCHBAR_REG(0x7010), 1); -} - -static asmlinkage void console_tx_byte(unsigned char byte) -{ -#ifdef DEBUG - putc(byte); -#endif -} - -static int recovery_mode_enabled(void) -{ - return false; -} - -/** - * Find the PEI executable in the ROM and execute it. - * - * @param pei_data: configuration data for UEFI PEI reference code - */ -int sdram_initialise(struct pei_data *pei_data) +static void post_system_agent_init(struct udevice *dev, struct udevice *me_dev, + struct pei_data *pei_data) { - unsigned version; - const char *data; uint16_t done; - int ret; - - report_platform_info(); - - /* Wait for ME to be ready */ - ret = intel_early_me_init(); - if (ret) - return ret; - ret = intel_early_me_uma_size(); - if (ret < 0) - return ret; - - debug("Starting UEFI PEI System Agent\n"); - - /* - * Do not pass MRC data in for recovery mode boot, - * Always pass it in for S3 resume. - */ - if (!recovery_mode_enabled() || - pei_data->boot_mode == PEI_BOOT_RESUME) { - ret = prepare_mrc_cache(pei_data); - if (ret) - debug("prepare_mrc_cache failed: %d\n", ret); - } - - /* If MRC data is not found we cannot continue S3 resume. */ - if (pei_data->boot_mode == PEI_BOOT_RESUME && !pei_data->mrc_input) { - debug("Giving up in sdram_initialize: No MRC data\n"); - outb(0x6, PORT_RESET); - cpu_hlt(); - } - - /* Pass console handler in pei_data */ - pei_data->tx_byte = console_tx_byte; - - debug("PEI data at %p, size %x:\n", pei_data, sizeof(*pei_data)); - - data = (char *)CONFIG_X86_MRC_ADDR; - if (data) { - int rv; - int (*func)(struct pei_data *); - - debug("Calling MRC at %p\n", data); - post_code(POST_PRE_MRC); - func = (int (*)(struct pei_data *))data; - rv = func(pei_data); - post_code(POST_MRC); - if (rv) { - switch (rv) { - case -1: - printf("PEI version mismatch.\n"); - break; - case -2: - printf("Invalid memory frequency.\n"); - break; - default: - printf("MRC returned %x.\n", rv); - } - printf("Nonzero MRC return value.\n"); - return -EFAULT; - } - } else { - printf("UEFI PEI System Agent not found.\n"); - return -ENOSYS; - } - -#if CONFIG_USBDEBUG - /* mrc.bin reconfigures USB, so reinit it to have debug */ - early_usbdebug_init(); -#endif - - version = readl(MCHBAR_REG(0x5034)); - debug("System Agent Version %d.%d.%d Build %d\n", - version >> 24 , (version >> 16) & 0xff, - (version >> 8) & 0xff, version & 0xff); - debug("MCR output data length %#x at %p\n", pei_data->mrc_output_len, - pei_data->mrc_output); /* * Send ME init done for SandyBridge here. This is done inside the * SystemAgent binary on IvyBridge */ - done = x86_pci_read_config32(PCH_DEV, PCI_DEVICE_ID); + dm_pci_read_config16(dev, PCI_DEVICE_ID, &done); done &= BASE_REV_MASK; if (BASE_REV_SNB == done) - intel_early_me_init_done(ME_INIT_STATUS_SUCCESS); + intel_early_me_init_done(dev, me_dev, ME_INIT_STATUS_SUCCESS); else - intel_early_me_status(); - - post_system_agent_init(pei_data); - report_memory_config(); - - /* S3 resume: don't save scrambler seed or MRC data */ - if (pei_data->boot_mode != PEI_BOOT_RESUME) { - /* - * This will be copied to SDRAM in reserve_arch(), then written - * to SPI flash in sdram_save_mrc_data() - */ - gd->arch.mrc_output = (char *)pei_data->mrc_output; - gd->arch.mrc_output_len = pei_data->mrc_output_len; - ret = write_seeds_to_cmos(pei_data); - if (ret) - debug("Failed to write seeds to CMOS: %d\n", ret); - } + intel_me_status(me_dev); - return 0; + /* If PCIe init is skipped, set the PEG clock gating */ + if (!pei_data->pcie_init) + setbits_le32(MCHBAR_REG(0x7010), 1); } -int reserve_arch(void) +static int recovery_mode_enabled(void) { - u16 checksum; - - checksum = compute_ip_checksum(gd->arch.mrc_output, - gd->arch.mrc_output_len); - debug("Saving %d bytes for MRC output data, checksum %04x\n", - gd->arch.mrc_output_len, checksum); - gd->start_addr_sp -= gd->arch.mrc_output_len; - memcpy((void *)gd->start_addr_sp, gd->arch.mrc_output, - gd->arch.mrc_output_len); - gd->arch.mrc_output = (char *)gd->start_addr_sp; - gd->start_addr_sp &= ~0xf; - - return 0; + return false; } -static int copy_spd(struct pei_data *peid) +static int copy_spd(struct udevice *dev, struct pei_data *peid) { - const int gpio_vector[] = {41, 42, 43, 10, -1}; - int spd_index; - const void *blob = gd->fdt_blob; - int node, spd_node; - int ret, i; - - for (i = 0; ; i++) { - if (gpio_vector[i] == -1) - break; - ret = gpio_requestf(gpio_vector[i], "spd_id%d", i); - if (ret) { - debug("%s: Could not request gpio %d\n", __func__, - gpio_vector[i]); - return ret; - } - } - spd_index = gpio_get_values_as_int(gpio_vector); - debug("spd index %d\n", spd_index); - node = fdtdec_next_compatible(blob, 0, COMPAT_MEMORY_SPD); - if (node < 0) { - printf("SPD data not found.\n"); - return -ENOENT; - } + const void *data; + int ret; - for (spd_node = fdt_first_subnode(blob, node); - spd_node > 0; - spd_node = fdt_next_subnode(blob, spd_node)) { - const char *data; - int len; - - if (fdtdec_get_int(blob, spd_node, "reg", -1) != spd_index) - continue; - data = fdt_getprop(blob, spd_node, "data", &len); - if (len < sizeof(peid->spd_data[0])) { - printf("Missing SPD data\n"); - return -EINVAL; - } - - debug("Using SDRAM SPD data for '%s'\n", - fdt_get_name(blob, spd_node, NULL)); - memcpy(peid->spd_data[0], data, sizeof(peid->spd_data[0])); - break; + ret = mrc_locate_spd(dev, sizeof(peid->spd_data[0]), &data); + if (ret) { + debug("%s: Could not locate SPD (ret=%d)\n", __func__, ret); + return ret; } - if (spd_node < 0) { - printf("No SPD data found for index %d\n", spd_index); - return -ENOENT; - } - - return 0; -} - -/** - * add_memory_area() - Add a new usable memory area to our list - * - * Note: @start and @end must not span the first 4GB boundary - * - * @info: Place to store memory info - * @start: Start of this memory area - * @end: End of this memory area + 1 - */ -static int add_memory_area(struct memory_info *info, - uint64_t start, uint64_t end) -{ - struct memory_area *ptr; - - if (info->num_areas == CONFIG_NR_DRAM_BANKS) - return -ENOSPC; - - ptr = &info->area[info->num_areas]; - ptr->start = start; - ptr->size = end - start; - info->total_memory += ptr->size; - if (ptr->start < (1ULL << 32)) - info->total_32bit_memory += ptr->size; - debug("%d: memory %llx size %llx, total now %llx / %llx\n", - info->num_areas, ptr->start, ptr->size, - info->total_32bit_memory, info->total_memory); - info->num_areas++; + memcpy(peid->spd_data[0], data, sizeof(peid->spd_data[0])); return 0; } @@ -580,16 +226,18 @@ static int add_memory_area(struct memory_info *info, * * This is a bit complicated since on x86 there are system memory holes all * over the place. We create a list of available memory blocks + * + * @dev: Northbridge device */ -static int sdram_find(pci_dev_t dev) +static int sdram_find(struct udevice *dev) { struct memory_info *info = &gd->arch.meminfo; uint32_t tseg_base, uma_size, tolud; uint64_t tom, me_base, touud; uint64_t uma_memory_base = 0; - uint64_t uma_memory_size; unsigned long long tomk; uint16_t ggc; + u32 val; /* Total Memory 2GB example: * @@ -618,24 +266,27 @@ static int sdram_find(pci_dev_t dev) */ /* Top of Upper Usable DRAM, including remap */ - touud = x86_pci_read_config32(dev, TOUUD+4); - touud <<= 32; - touud |= x86_pci_read_config32(dev, TOUUD); + dm_pci_read_config32(dev, TOUUD + 4, &val); + touud = (uint64_t)val << 32; + dm_pci_read_config32(dev, TOUUD, &val); + touud |= val; /* Top of Lower Usable DRAM */ - tolud = x86_pci_read_config32(dev, TOLUD); + dm_pci_read_config32(dev, TOLUD, &tolud); /* Top of Memory - does not account for any UMA */ - tom = x86_pci_read_config32(dev, 0xa4); - tom <<= 32; - tom |= x86_pci_read_config32(dev, 0xa0); + dm_pci_read_config32(dev, 0xa4, &val); + tom = (uint64_t)val << 32; + dm_pci_read_config32(dev, 0xa0, &val); + tom |= val; debug("TOUUD %llx TOLUD %08x TOM %llx\n", touud, tolud, tom); /* ME UMA needs excluding if total memory <4GB */ - me_base = x86_pci_read_config32(dev, 0x74); - me_base <<= 32; - me_base |= x86_pci_read_config32(dev, 0x70); + dm_pci_read_config32(dev, 0x74, &val); + me_base = (uint64_t)val << 32; + dm_pci_read_config32(dev, 0x70, &val); + me_base |= val; debug("MEBASE %llx\n", me_base); @@ -648,12 +299,11 @@ static int sdram_find(pci_dev_t dev) tolud += uma_size << 10; /* UMA starts at old TOLUD */ uma_memory_base = tomk * 1024ULL; - uma_memory_size = uma_size * 1024ULL; debug("ME UMA base %llx size %uM\n", me_base, uma_size >> 10); } /* Graphics memory comes next */ - ggc = x86_pci_read_config16(dev, GGC); + dm_pci_read_config16(dev, GGC, &ggc); if (!(ggc & 2)) { debug("IGD decoded, subtracting "); @@ -662,31 +312,28 @@ static int sdram_find(pci_dev_t dev) debug("%uM UMA", uma_size >> 10); tomk -= uma_size; uma_memory_base = tomk * 1024ULL; - uma_memory_size += uma_size * 1024ULL; /* GTT Graphics Stolen Memory Size (GGMS) */ uma_size = ((ggc >> 8) & 0x3) * 1024ULL; tomk -= uma_size; uma_memory_base = tomk * 1024ULL; - uma_memory_size += uma_size * 1024ULL; debug(" and %uM GTT\n", uma_size >> 10); } /* Calculate TSEG size from its base which must be below GTT */ - tseg_base = x86_pci_read_config32(dev, 0xb8); + dm_pci_read_config32(dev, 0xb8, &tseg_base); uma_size = (uma_memory_base - tseg_base) >> 10; tomk -= uma_size; uma_memory_base = tomk * 1024ULL; - uma_memory_size += uma_size * 1024ULL; debug("TSEG base 0x%08x size %uM\n", tseg_base, uma_size >> 10); debug("Available memory below 4GB: %lluM\n", tomk >> 10); /* Report the memory regions */ - add_memory_area(info, 1 << 20, 2 << 28); - add_memory_area(info, (2 << 28) + (2 << 20), 4 << 28); - add_memory_area(info, (4 << 28) + (2 << 20), tseg_base); - add_memory_area(info, 1ULL << 32, touud); + mrc_add_memory_area(info, 1 << 20, 2 << 28); + mrc_add_memory_area(info, (2 << 28) + (2 << 20), 4 << 28); + mrc_add_memory_area(info, (4 << 28) + (2 << 20), tseg_base); + mrc_add_memory_area(info, 1ULL << 32, touud); /* Add MTRRs for memory */ mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30); @@ -755,9 +402,9 @@ static void rcba_config(void) int dram_init(void) { - struct pei_data pei_data __aligned(8) = { + struct pei_data _pei_data __aligned(8) = { .pei_version = PEI_VERSION, - .mchbar = DEFAULT_MCHBAR, + .mchbar = MCH_BASE_ADDRESS, .dmibar = DEFAULT_DMIBAR, .epbar = DEFAULT_EPBAR, .pciexbar = CONFIG_PCIE_ECAM_BASE, @@ -808,30 +455,108 @@ int dram_init(void) { 0, 4, 0x0000 }, /* P13= Empty */ }, }; - pci_dev_t dev = PCI_BDF(0, 0, 0); + struct pei_data *pei_data = &_pei_data; + struct udevice *dev, *me_dev; int ret; - debug("Boot mode %d\n", gd->arch.pei_boot_mode); - debug("mcr_input %p\n", pei_data.mrc_input); - pei_data.boot_mode = gd->arch.pei_boot_mode; - ret = copy_spd(&pei_data); - if (!ret) - ret = sdram_initialise(&pei_data); - if (ret) + /* We need the pinctrl set up early */ + ret = syscon_get_by_driver_data(X86_SYSCON_PINCONF, &dev); + if (ret) { + debug("%s: Could not get pinconf (ret=%d)\n", __func__, ret); return ret; + } - rcba_config(); - quick_ram_check(); + ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev); + if (ret) { + debug("%s: Could not get northbridge (ret=%d)\n", __func__, + ret); + return ret; + } + ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev); + if (ret) { + debug("%s: Could not get ME (ret=%d)\n", __func__, ret); + return ret; + } + ret = copy_spd(dev, pei_data); + if (ret) { + debug("%s: Could not get SPD (ret=%d)\n", __func__, ret); + return ret; + } + pei_data->boot_mode = gd->arch.pei_boot_mode; + debug("Boot mode %d\n", gd->arch.pei_boot_mode); + debug("mrc_input %p\n", pei_data->mrc_input); - writew(0xCAFE, MCHBAR_REG(SSKPD)); + /* + * Do not pass MRC data in for recovery mode boot, + * Always pass it in for S3 resume. + */ + if (!recovery_mode_enabled() || + pei_data->boot_mode == PEI_BOOT_RESUME) { + ret = prepare_mrc_cache(pei_data); + if (ret) + debug("prepare_mrc_cache failed: %d\n", ret); + } + + /* If MRC data is not found we cannot continue S3 resume. */ + if (pei_data->boot_mode == PEI_BOOT_RESUME && !pei_data->mrc_input) { + debug("Giving up in sdram_initialize: No MRC data\n"); + sysreset_walk_halt(SYSRESET_COLD); + } + + /* Pass console handler in pei_data */ + pei_data->tx_byte = sdram_console_tx_byte; + + /* Wait for ME to be ready */ + ret = intel_early_me_init(me_dev); + if (ret) { + debug("%s: Could not init ME (ret=%d)\n", __func__, ret); + return ret; + } + ret = intel_early_me_uma_size(me_dev); + if (ret < 0) { + debug("%s: Could not get UMA size (ret=%d)\n", __func__, ret); + return ret; + } - post_code(POST_DRAM); + ret = mrc_common_init(dev, pei_data, false); + if (ret) { + debug("%s: mrc_common_init() failed (ret=%d)\n", __func__, ret); + return ret; + } ret = sdram_find(dev); + if (ret) { + debug("%s: sdram_find() failed (ret=%d)\n", __func__, ret); + return ret; + } + gd->ram_size = gd->arch.meminfo.total_32bit_memory; + + debug("MRC output data length %#x at %p\n", pei_data->mrc_output_len, + pei_data->mrc_output); + + post_system_agent_init(dev, me_dev, pei_data); + report_memory_config(); + + /* S3 resume: don't save scrambler seed or MRC data */ + if (pei_data->boot_mode != PEI_BOOT_RESUME) { + struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL]; + + /* + * This will be copied to SDRAM in reserve_arch(), then written + * to SPI flash in mrccache_save() + */ + mrc->buf = (char *)pei_data->mrc_output; + mrc->len = pei_data->mrc_output_len; + ret = write_seeds_to_cmos(pei_data); + if (ret) + debug("Failed to write seeds to CMOS: %d\n", ret); + } + + writew(0xCAFE, MCHBAR_REG(SSKPD)); if (ret) return ret; - gd->ram_size = gd->arch.meminfo.total_32bit_memory; + rcba_config(); return 0; }