x86: mrccache: Allow use before driver model is active
authorSimon Glass <sjg@chromium.org>
Wed, 27 May 2020 12:58:49 +0000 (06:58 -0600)
committerBin Meng <bmeng.cn@gmail.com>
Tue, 2 Jun 2020 01:16:13 +0000 (09:16 +0800)
The change to avoid searching the device tree does not work on boards
wich don't have driver model set up this early, for example minnowmax.
Put back the old code (converted to livetree) as a fallback for these
devices. Also update the documentation.

This is tested on minnowmax, link, samus and coral.

Fixes: 87f1084a630 (x86: Adjust mrccache_get_region() to use livetree)
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Tested-by: Bin Meng <bmeng.cn@gmail.com> (on Intel minnowmax)
arch/x86/include/asm/mrccache.h
arch/x86/lib/mrccache.c

index d6b75290739d25c16334eb71934d147c2d8d5fe1..b60d1171f771ac7841ed6ecef251ab8afc5d523f 100644 (file)
@@ -66,19 +66,12 @@ int mrccache_reserve(void);
  * mrccache_get_region() - get MRC region on the SPI flash
  *
  * This gets MRC region whose offset and size are described in the device tree
- * as a subnode to the SPI flash. If a non-NULL device pointer is supplied,
- * this also probes the SPI flash device and returns its device pointer for
- * the caller to use later.
- *
- * Be careful when calling this routine with a non-NULL device pointer:
- * - driver model initialization must be complete
- * - calling in the pre-relocation phase may bring some side effects during
- *   the SPI flash device probe (eg: for SPI controllers on a PCI bus, it
- *   triggers PCI bus enumeration during which insufficient memory issue
- *   might be exposed and it causes subsequent SPI flash probe fails).
+ * as a subnode to the SPI flash. This tries to find the SPI flash device
+ * (without probing it), falling back to looking for the devicetree node if
+ * driver model is not inited or the SPI flash is not found.
  *
  * @type:      Type of MRC data to use
- * @devp:      Returns pointer to the SPI flash device
+ * @devp:      Returns pointer to the SPI flash device, if found
  * @entry:     Position and size of MRC cache in SPI flash
  * @return 0 if success, -ENOENT if SPI flash node does not exist in the
  * device tree, -EPERM if MRC region subnode does not exist in the device
index 21c71e036edc90864ed44322437e27d0923c3d8c..f181e8100cb77383120ef583d40537b747fcef89 100644 (file)
@@ -233,6 +233,7 @@ int mrccache_get_region(enum mrc_type_t type, struct udevice **devp,
        ulong map_base;
        uint map_size;
        uint offset;
+       ofnode node;
        u32 reg[2];
        int ret;
 
@@ -242,23 +243,36 @@ int mrccache_get_region(enum mrc_type_t type, struct udevice **devp,
         * memory map cannot be read.
         */
        ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev);
-       if (!ret && !dev)
+       if (ret || !dev) {
+               /*
+                * Fall back to searching the device tree since driver model
+                * may not be ready yet (e.g. with FSPv1)
+                */
+               node = ofnode_by_compatible(ofnode_null(), "jedec,spi-nor");
+               if (!ofnode_valid(node))
+                       return log_msg_ret("Cannot find SPI flash\n", -ENOENT);
                ret = -ENODEV;
-       if (ret)
-               return log_msg_ret("Cannot find SPI flash\n", ret);
-       ret = dm_spi_get_mmap(dev, &map_base, &map_size, &offset);
-       if (!ret) {
-               entry->base = map_base;
        } else {
-               ret = dev_read_u32_array(dev, "memory-map", reg, 2);
+               ret = dm_spi_get_mmap(dev, &map_base, &map_size, &offset);
+               if (!ret)
+                       entry->base = map_base;
+               node = dev_ofnode(dev);
+       }
+
+       /*
+        * At this point we have entry->base if ret == 0. If not, then we have
+        * the node and can look for memory-map
+        */
+       if (ret) {
+               ret = ofnode_read_u32_array(node, "memory-map", reg, 2);
                if (ret)
                        return log_msg_ret("Cannot find memory map\n", ret);
                entry->base = reg[0];
        }
 
        /* Find the place where we put the MRC cache */
-       mrc_node = dev_read_subnode(dev, type == MRC_TYPE_NORMAL ?
-                                   "rw-mrc-cache" : "rw-var-mrc-cache");
+       mrc_node = ofnode_find_subnode(node, type == MRC_TYPE_NORMAL ?
+                                      "rw-mrc-cache" : "rw-var-mrc-cache");
        if (!ofnode_valid(mrc_node))
                return log_msg_ret("Cannot find node", -EPERM);
 
@@ -271,7 +285,8 @@ int mrccache_get_region(enum mrc_type_t type, struct udevice **devp,
        if (devp)
                *devp = dev;
        debug("MRC cache type %d in '%s', offset %x, len %x, base %x\n",
-             type, dev->name, entry->offset, entry->length, entry->base);
+             type, dev ? dev->name : ofnode_get_name(node), entry->offset,
+             entry->length, entry->base);
 
        return 0;
 }