diff options
Diffstat (limited to 'roms/u-boot/arch/x86/cpu/broadwell/sdram.c')
-rw-r--r-- | roms/u-boot/arch/x86/cpu/broadwell/sdram.c | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/roms/u-boot/arch/x86/cpu/broadwell/sdram.c b/roms/u-boot/arch/x86/cpu/broadwell/sdram.c new file mode 100644 index 000000000..c104a849a --- /dev/null +++ b/roms/u-boot/arch/x86/cpu/broadwell/sdram.c @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2016 Google, Inc + * + * From coreboot src/soc/intel/broadwell/romstage/raminit.c + */ + +#include <common.h> +#include <dm.h> +#include <init.h> +#include <log.h> +#include <pci.h> +#include <syscon.h> +#include <asm/cpu.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <asm/lpc_common.h> +#include <asm/mrccache.h> +#include <asm/mrc_common.h> +#include <asm/mtrr.h> +#include <asm/pci.h> +#include <asm/arch/iomap.h> +#include <asm/arch/me.h> +#include <asm/arch/pch.h> +#include <asm/arch/pei_data.h> +#include <asm/arch/pm.h> + +ulong board_get_usable_ram_top(ulong total_size) +{ + return mrc_common_board_get_usable_ram_top(total_size); +} + +int dram_init_banksize(void) +{ + mrc_common_dram_init_banksize(); + + return 0; +} + +static unsigned long get_top_of_ram(struct udevice *dev) +{ + /* + * Base of DPR is top of usable DRAM below 4GiB. The register has + * 1 MiB alignment and reports the TOP of the range, the base + * must be calculated from the size in MiB in bits 11:4. + */ + u32 dpr, tom; + + dm_pci_read_config32(dev, DPR, &dpr); + tom = dpr & ~((1 << 20) - 1); + + debug("dpt %08x tom %08x\n", dpr, tom); + /* Subtract DMA Protected Range size if enabled */ + if (dpr & DPR_EPM) + tom -= (dpr & DPR_SIZE_MASK) << 16; + + return (unsigned long)tom; +} + +/** + * sdram_find() - Find available memory + * + * 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(struct udevice *dev) +{ + struct memory_info *info = &gd->arch.meminfo; + ulong top_of_ram; + + top_of_ram = get_top_of_ram(dev); + mrc_add_memory_area(info, 0, top_of_ram); + + /* Add MTRRs for memory */ + mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30); + + return 0; +} + +static int prepare_mrc_cache(struct pei_data *pei_data) +{ + struct mrc_data_container *mrc_cache; + struct mrc_region entry; + int ret; + + ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry); + if (ret) + return ret; + mrc_cache = mrccache_find_current(&entry); + if (!mrc_cache) + return -ENOENT; + + pei_data->saved_data = mrc_cache->data; + pei_data->saved_data_size = mrc_cache->data_size; + debug("%s: at %p, size %x checksum %04x\n", __func__, + pei_data->saved_data, pei_data->saved_data_size, + mrc_cache->checksum); + + return 0; +} + +int dram_init(void) +{ + struct pei_data _pei_data __aligned(8); + struct pei_data *pei_data = &_pei_data; + struct udevice *dev, *me_dev, *pch_dev; + struct chipset_power_state ps; + const void *spd_data; + int ret, size; + + memset(pei_data, '\0', sizeof(struct pei_data)); + + /* Print ME state before MRC */ + ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev); + if (ret) { + debug("Cannot get ME (err=%d)\n", ret); + return ret; + } + intel_me_status(me_dev); + + /* Save ME HSIO version */ + ret = uclass_first_device_err(UCLASS_PCH, &pch_dev); + if (ret) { + debug("Cannot get PCH (err=%d)\n", ret); + return ret; + } + power_state_get(pch_dev, &ps); + + intel_me_hsio_version(me_dev, &ps.hsio_version, &ps.hsio_checksum); + + broadwell_fill_pei_data(pei_data); + mainboard_fill_pei_data(pei_data); + + ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev); + if (ret) { + debug("Cannot get Northbridge (err=%d)\n", ret); + return ret; + } + size = 256; + ret = mrc_locate_spd(dev, size, &spd_data); + if (ret) { + debug("Cannot locate SPD (err=%d)\n", ret); + return ret; + } + memcpy(pei_data->spd_data[0][0], spd_data, size); + memcpy(pei_data->spd_data[1][0], spd_data, size); + + ret = prepare_mrc_cache(pei_data); + if (ret) + debug("prepare_mrc_cache failed: %d\n", ret); + + debug("PEI version %#x\n", pei_data->pei_version); + ret = mrc_common_init(dev, pei_data, true); + if (ret) { + debug("mrc_common_init() failed(err=%d)\n", ret); + return ret; + } + debug("Memory init done\n"); + + ret = sdram_find(dev); + if (ret) { + debug("sdram_find() failed (err=%d)\n", ret); + return ret; + } + gd->ram_size = gd->arch.meminfo.total_32bit_memory; + debug("RAM size %llx\n", (unsigned long long)gd->ram_size); + + debug("MRC output data length %#x at %p\n", pei_data->data_to_save_size, + pei_data->data_to_save); + /* S3 resume: don't save scrambler seed or MRC data */ + if (pei_data->boot_mode != SLEEP_STATE_S3) { + 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->data_to_save; + mrc->len = pei_data->data_to_save_size; + } + gd->arch.pei_meminfo = pei_data->meminfo; + + return 0; +} + +/* Use this hook to save our SDRAM parameters */ +int misc_init_r(void) +{ + int ret; + + ret = mrccache_save(); + if (ret) + printf("Unable to save MRC data: %d\n", ret); + else + debug("Saved MRC cache data\n"); + + return 0; +} + +static const struct udevice_id broadwell_syscon_ids[] = { + { .compatible = "intel,me", .data = X86_SYSCON_ME }, + { } +}; + +U_BOOT_DRIVER(syscon_intel_me) = { + .name = "intel_me_syscon", + .id = UCLASS_SYSCON, + .of_match = broadwell_syscon_ids, +}; |