x86: Update mrccache to support multiple caches
authorSimon Glass <sjg@chromium.org>
Sat, 7 Dec 2019 04:42:07 +0000 (21:42 -0700)
committerBin Meng <bmeng.cn@gmail.com>
Sun, 15 Dec 2019 03:44:14 +0000 (11:44 +0800)
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>
arch/x86/cpu/broadwell/sdram.c
arch/x86/cpu/ivybridge/sdram.c
arch/x86/cpu/quark/dram.c
arch/x86/include/asm/global_data.h
arch/x86/include/asm/mrccache.h
arch/x86/lib/fsp/fsp_common.c
arch/x86/lib/fsp1/fsp_dram.c
arch/x86/lib/mrccache.c

index dfd8afc35f5a35d6f89d5d4c7f6c93d40bbe84aa..15bfc5811cb4dc397ec129ff3745982c3ce7df7a 100644 (file)
@@ -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;
 
index 51ca4ad3017eebb0f198f98b4eef0d1535ea5fe0..cf34f94a91d5472db494b8c2907f34768bca1a90 100644 (file)
@@ -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);
index 995e119fb6f09e955b51512a67972464b51a2e7a..2bf90dcfc62e140a7d90a1ce838ff50ed68f74d9 100644 (file)
@@ -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
 
index 3212b006eb4d66fe2e32c771e512341b3c69036c..190b604e0f795f3b5e1c83dcc749b72d2e2630f3 100644 (file)
@@ -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;
index abf581822375d3ad8cd5ec157f28883fdf1bc0b7..b81e2b2fb6a527676614344c92554ce86e4aa8a3 100644 (file)
@@ -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
index a5efe35f593ef6b1ae7bfc6463ee44ec49517d8d..4c5358e1d251dfc309c307c00a42bfc5e2e6dfd0 100644 (file)
@@ -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;
 
index 6a3349b42af23f2aa896d17fab6ff89dcf8b9e08..5ef89744b944469d89e9527ca1cea9d3adbce200 100644 (file)
@@ -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;
 }
index 712bacd5d2811af4aa2223a7cdf450225127dd02..1278737ce453bdd0b78bd0fb41b8fd0211d2349d 100644 (file)
@@ -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();
 }