common: Move some board functions out of common.h
[oweals/u-boot.git] / arch / arm / mach-rockchip / spl-boot-order.c
index 4f78c72720948e9adc77ae1c3437d096d5c5dca9..fa8e096426b68cafb0a95977ffcb2c00130e0ae8 100644 (file)
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
- *
- * SPDX-License-Identifier:     GPL-2.0+
  */
 
 #include <common.h>
@@ -9,7 +8,26 @@
 #include <mmc.h>
 #include <spl.h>
 
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_LIBFDT)
+/**
+ * spl_node_to_boot_device() - maps from a DT-node to a SPL boot device
+ * @node:      of_offset of the node
+ *
+ * The SPL framework uses BOOT_DEVICE_... constants to identify its boot
+ * sources.  These may take on a device-specific meaning, depending on
+ * what nodes are enabled in a DTS (e.g. BOOT_DEVICE_MMC1 may refer to
+ * different controllers/block-devices, depending on which SD/MMC controllers
+ * are enabled in any given DTS).  This function maps from a DT-node back
+ * onto a BOOT_DEVICE_... constant, considering the currently active devices.
+ *
+ * Returns
+ *   -ENOENT, if no device matching the node could be found
+ *   -ENOSYS, if the device matching the node can not be mapped onto a
+ *            SPL boot device (e.g. the third MMC device)
+ *   -1, for unspecified failures
+ *   a positive integer (from the BOOT_DEVICE_... family) on succes.
+ */
+
 static int spl_node_to_boot_device(int node)
 {
        struct udevice *parent;
@@ -43,6 +61,9 @@ static int spl_node_to_boot_device(int node)
                default:
                        return -ENOSYS;
                }
+       } else if (!uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node,
+               &parent)) {
+               return BOOT_DEVICE_SPI;
        }
 
        /*
@@ -57,6 +78,24 @@ static int spl_node_to_boot_device(int node)
        return -1;
 }
 
+/**
+ * board_spl_was_booted_from() - retrieves the of-path the SPL was loaded from
+ *
+ * To support a 'same-as-spl' specification in the search-order for the next
+ * stage, we need a SoC- or board-specific way to handshake with what 'came
+ * before us' (either a BROM or TPL stage) and map the info retrieved onto
+ * a OF path.
+ *
+ * Returns
+ *   NULL, on failure or if the device could not be identified
+ *   a of_path (a string), on success
+ */
+__weak const char *board_spl_was_booted_from(void)
+{
+       debug("%s: no support for 'same-as-spl' for this board\n", __func__);
+       return NULL;
+}
+
 void board_boot_order(u32 *spl_boot_list)
 {
        const void *blob = gd->fdt_blob;
@@ -78,15 +117,24 @@ void board_boot_order(u32 *spl_boot_list)
             (conf = fdt_stringlist_get(blob, chosen_node,
                                        "u-boot,spl-boot-order", elem, NULL));
             elem++) {
+               const char *alias;
+
+               /* Handle the case of 'same device the SPL was loaded from' */
+               if (strncmp(conf, "same-as-spl", 11) == 0) {
+                       conf = board_spl_was_booted_from();
+                       if (!conf)
+                               continue;
+               }
+
                /* First check if the list element is an alias */
-               const char *alias = fdt_get_alias(blob, conf);
+               alias = fdt_get_alias(blob, conf);
                if (alias)
                        conf = alias;
 
                /* Try to resolve the config item (or alias) as a path */
                node = fdt_path_offset(blob, conf);
                if (node < 0) {
-                       debug("%s: could not find %s in FDT", __func__, conf);
+                       debug("%s: could not find %s in FDT\n", __func__, conf);
                        continue;
                }