mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-29 08:01:08 +00:00
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 <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
83f288f236
commit
515e8174f5
8 changed files with 105 additions and 47 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/* 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);
|
||||
for (i = 0; i < MRC_TYPE_COUNT; i++) {
|
||||
struct mrc_output *mrc = &gd->arch.mrc[i];
|
||||
|
||||
gd->start_addr_sp &= ~0xf;
|
||||
if (!mrc->len)
|
||||
continue;
|
||||
|
||||
/* 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;
|
||||
int i;
|
||||
|
||||
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;
|
||||
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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue