x86: Add mrccache support for a 'variable' cache
[oweals/u-boot.git] / arch / x86 / lib / mrccache.c
index 6e561fe5286dc196f2b21221c6ebc54261276cee..10949d249e529b5e8c2d715a4c4ea5c1713e2ea5 100644 (file)
@@ -168,44 +168,51 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
                                 cur);
        if (ret) {
                debug("Failed to write to SPI flash\n");
-               return ret;
+               return log_msg_ret("Cannot update mrccache", ret);
        }
 
        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];
+
+               if (!mrc->len)
+                       continue;
 
-       /* 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);
+               /* 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;
+               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;
@@ -234,7 +241,8 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
        }
 
        /* Find the place where we put the MRC cache */
-       mrc_node = dev_read_subnode(dev, "rw-mrc-cache");
+       mrc_node = dev_read_subnode(dev, type == MRC_TYPE_NORMAL ?
+                                   "rw-mrc-cache" : "rw-var-mrc-cache");
        if (!ofnode_valid(mrc_node))
                return log_msg_ret("Cannot find node", -EPERM);
 
@@ -246,56 +254,72 @@ 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 %d 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)
-               goto err_entry;
+               return log_msg_ret("Cannot get region", ret);
        ret = device_probe(sf);
        if (ret)
-               goto err_entry;
-       cache = gd->arch.mrc_cache;
+               return log_msg_ret("Cannot probe device", ret);
+       cache = mrc->cache;
+
        ret = mrccache_update(sf, &entry, cache);
-       if (!ret) {
+       if (!ret)
                debug("Saved MRC data with checksum %04x\n", cache->checksum);
-       } else if (ret == -EEXIST) {
+       else if (ret == -EEXIST)
                debug("MRC data is the same as last time, skipping save\n");
-               ret = 0;
+
+       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;
        }
 
-err_entry:
-       if (ret)
-               debug("%s: Failed: %d\n", __func__, 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();
 }