From: Simon Glass Date: Sat, 7 Dec 2019 04:42:07 +0000 (-0700) Subject: x86: Update mrccache to support multiple caches X-Git-Tag: v2020.04-rc1~39^2~2^2~68 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=515e8174f5560d98c2f84999b2e5585c0f2ccd57;p=oweals%2Fu-boot.git x86: Update mrccache to support multiple caches With Apollo Lake we need to support a normal cache, which almost never changes and a much smaller 'variable' cache which changes every time. Update the code to add a cache type, use an array for the caches and use a for loop to iterate over the caches. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- diff --git a/arch/x86/cpu/broadwell/sdram.c b/arch/x86/cpu/broadwell/sdram.c index dfd8afc35f..15bfc5811c 100644 --- a/arch/x86/cpu/broadwell/sdram.c +++ b/arch/x86/cpu/broadwell/sdram.c @@ -83,7 +83,7 @@ static int prepare_mrc_cache(struct pei_data *pei_data) struct mrc_region entry; int ret; - ret = mrccache_get_region(NULL, &entry); + ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry); if (ret) return ret; mrc_cache = mrccache_find_current(&entry); @@ -169,12 +169,14 @@ int dram_init(void) 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() */ - gd->arch.mrc_output = (char *)pei_data->data_to_save; - gd->arch.mrc_output_len = pei_data->data_to_save_size; + mrc->buf = (char *)pei_data->data_to_save; + mrc->len = pei_data->data_to_save_size; } gd->arch.pei_meminfo = pei_data->meminfo; diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index 51ca4ad301..cf34f94a91 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -116,7 +116,7 @@ static int prepare_mrc_cache(struct pei_data *pei_data) ret = read_seed_from_cmos(pei_data); if (ret) return ret; - ret = mrccache_get_region(NULL, &entry); + ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry); if (ret) return ret; mrc_cache = mrccache_find_current(&entry); @@ -538,12 +538,14 @@ int dram_init(void) /* 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() */ - gd->arch.mrc_output = (char *)pei_data->mrc_output; - gd->arch.mrc_output_len = pei_data->mrc_output_len; + 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); diff --git a/arch/x86/cpu/quark/dram.c b/arch/x86/cpu/quark/dram.c index 995e119fb6..2bf90dcfc6 100644 --- a/arch/x86/cpu/quark/dram.c +++ b/arch/x86/cpu/quark/dram.c @@ -24,7 +24,7 @@ static __maybe_unused int prepare_mrc_cache(struct mrc_params *mrc_params) struct mrc_region entry; int ret; - ret = mrccache_get_region(NULL, &entry); + ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry); if (ret) return ret; @@ -154,9 +154,11 @@ int dram_init(void) #ifdef CONFIG_ENABLE_MRC_CACHE cache = malloc(sizeof(struct mrc_timings)); if (cache) { + struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL]; + memcpy(cache, &mrc_params.timings, sizeof(struct mrc_timings)); - gd->arch.mrc_output = cache; - gd->arch.mrc_output_len = sizeof(struct mrc_timings); + mrc->buf = cache; + mrc->len = sizeof(struct mrc_timings); } #endif diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 3212b006eb..190b604e0f 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -67,6 +67,21 @@ struct mtrr_request { uint64_t size; }; +/** + * struct mrc_output - holds the MRC data + * + * @buf: MRC training data to save for the next boot. This is set to point to + * the raw data after SDRAM init is complete. Then mrccache_setup() + * turns it into a proper cache record with a checksum + * @len: Length of @buf + * @cache: Resulting cache record + */ +struct mrc_output { + char *buf; + uint len; + struct mrc_data_container *cache; +}; + /* Architecture-specific global data */ struct arch_global_data { u64 gdt[X86_GDT_NUM_ENTRIES] __aligned(16); @@ -91,10 +106,8 @@ struct arch_global_data { struct mtrr_request mtrr_req[MAX_MTRR_REQUESTS]; int mtrr_req_count; int has_mtrr; - /* MRC training data to save for the next boot */ - char *mrc_output; - unsigned int mrc_output_len; - struct mrc_data_container *mrc_cache; + /* MRC training data */ + struct mrc_output mrc[MRC_TYPE_COUNT]; ulong table; /* Table pointer from previous loader */ int turbo_state; /* Current turbo state */ struct irq_routing_table *pirq_routing_table; diff --git a/arch/x86/include/asm/mrccache.h b/arch/x86/include/asm/mrccache.h index abf5818223..b81e2b2fb6 100644 --- a/arch/x86/include/asm/mrccache.h +++ b/arch/x86/include/asm/mrccache.h @@ -27,6 +27,13 @@ struct mrc_region { u32 length; }; +/* Types of MRC data */ +enum mrc_type_t { + MRC_TYPE_NORMAL, + + MRC_TYPE_COUNT, +}; + struct udevice; /** @@ -84,6 +91,7 @@ int mrccache_reserve(void); * triggers PCI bus enumeration during which insufficient memory issue * might be exposed and it causes subsequent SPI flash probe fails). * + * @type: Type of MRC data to use * @devp: Returns pointer to the SPI flash device * @entry: Position and size of MRC cache in SPI flash * @return 0 if success, -ENOENT if SPI flash node does not exist in the @@ -91,7 +99,8 @@ int mrccache_reserve(void); * tree, -EINVAL if MRC region properties format is incorrect, other error * if SPI flash probe failed. */ -int mrccache_get_region(struct udevice **devp, struct mrc_region *entry); +int mrccache_get_region(enum mrc_type_t type, struct udevice **devp, + struct mrc_region *entry); /** * mrccache_save() - save MRC data to the SPI flash diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c index a5efe35f59..4c5358e1d2 100644 --- a/arch/x86/lib/fsp/fsp_common.c +++ b/arch/x86/lib/fsp/fsp_common.c @@ -64,7 +64,7 @@ void *fsp_prepare_mrc_cache(void) struct mrc_region entry; int ret; - ret = mrccache_get_region(NULL, &entry); + ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry); if (ret) return NULL; diff --git a/arch/x86/lib/fsp1/fsp_dram.c b/arch/x86/lib/fsp1/fsp_dram.c index 6a3349b42a..5ef89744b9 100644 --- a/arch/x86/lib/fsp1/fsp_dram.c +++ b/arch/x86/lib/fsp1/fsp_dram.c @@ -15,9 +15,11 @@ int dram_init(void) if (ret) return ret; - if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) - gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list, - &gd->arch.mrc_output_len); + if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) { + struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL]; + + mrc->buf = fsp_get_nvs_data(gd->arch.hob_list, &mrc->len); + } return 0; } diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c index 712bacd5d2..1278737ce4 100644 --- a/arch/x86/lib/mrccache.c +++ b/arch/x86/lib/mrccache.c @@ -174,38 +174,45 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry, return 0; } -static void mrccache_setup(void *data) +static void mrccache_setup(struct mrc_output *mrc, void *data) { struct mrc_data_container *cache = data; u16 checksum; cache->signature = MRC_DATA_SIGNATURE; - cache->data_size = gd->arch.mrc_output_len; - checksum = compute_ip_checksum(gd->arch.mrc_output, cache->data_size); + cache->data_size = mrc->len; + checksum = compute_ip_checksum(mrc->buf, cache->data_size); debug("Saving %d bytes for MRC output data, checksum %04x\n", cache->data_size, checksum); cache->checksum = checksum; cache->reserved = 0; - memcpy(cache->data, gd->arch.mrc_output, cache->data_size); + memcpy(cache->data, mrc->buf, cache->data_size); - gd->arch.mrc_cache = cache; + mrc->cache = cache; } int mrccache_reserve(void) { - if (!gd->arch.mrc_output_len) - return 0; + int i; + + for (i = 0; i < MRC_TYPE_COUNT; i++) { + struct mrc_output *mrc = &gd->arch.mrc[i]; - /* adjust stack pointer to store pure cache data plus the header */ - gd->start_addr_sp -= (gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE); - mrccache_setup((void *)gd->start_addr_sp); + if (!mrc->len) + continue; - gd->start_addr_sp &= ~0xf; + /* adjust stack pointer to store pure cache data plus header */ + gd->start_addr_sp -= (mrc->len + MRC_DATA_HEADER_SIZE); + mrccache_setup(mrc, (void *)gd->start_addr_sp); + + gd->start_addr_sp &= ~0xf; + } return 0; } -int mrccache_get_region(struct udevice **devp, struct mrc_region *entry) +int mrccache_get_region(enum mrc_type_t type, struct udevice **devp, + struct mrc_region *entry) { struct udevice *dev; ofnode mrc_node; @@ -246,31 +253,33 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry) if (devp) *devp = dev; - debug("MRC cache in '%s', offset %x, len %x, base %x\n", - dev->name, entry->offset, entry->length, entry->base); + debug("MRC cache type %d in '%s', offset %x, len %x, base %x\n", + type, dev->name, entry->offset, entry->length, entry->base); return 0; } -int mrccache_save(void) +static int mrccache_save_type(enum mrc_type_t type) { struct mrc_data_container *cache; + struct mrc_output *mrc; struct mrc_region entry; struct udevice *sf; int ret; - if (!gd->arch.mrc_output_len) + mrc = &gd->arch.mrc[type]; + if (!mrc->len) return 0; - debug("Saving %#x bytes of MRC output data to SPI flash\n", - gd->arch.mrc_output_len); - - ret = mrccache_get_region(&sf, &entry); + log_debug("Saving %#x bytes of MRC output data type %d to SPI flash\n", + mrc->len, type); + ret = mrccache_get_region(type, &sf, &entry); if (ret) return log_msg_ret("Cannot get region", ret); ret = device_probe(sf); if (ret) return log_msg_ret("Cannot probe device", ret); - cache = gd->arch.mrc_cache; + cache = mrc->cache; + ret = mrccache_update(sf, &entry, cache); if (!ret) debug("Saved MRC data with checksum %04x\n", cache->checksum); @@ -280,17 +289,36 @@ int mrccache_save(void) return 0; } +int mrccache_save(void) +{ + int i; + + for (i = 0; i < MRC_TYPE_COUNT; i++) { + int ret; + + ret = mrccache_save_type(i); + if (ret) + return ret; + } + + return 0; +} + int mrccache_spl_save(void) { - void *data; - int size; - - size = gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE; - data = malloc(size); - if (!data) - return log_msg_ret("Allocate MRC cache block", -ENOMEM); - mrccache_setup(data); - gd->arch.mrc_output = data; + int i; + + for (i = 0; i < MRC_TYPE_COUNT; i++) { + struct mrc_output *mrc = &gd->arch.mrc[i]; + void *data; + int size; + + size = mrc->len + MRC_DATA_HEADER_SIZE; + data = malloc(size); + if (!data) + return log_msg_ret("Allocate MRC cache block", -ENOMEM); + mrccache_setup(mrc, data); + } return mrccache_save(); }