Naming a fixed SCSI device number cannot express "use the currently
activated boot LU". Offer the boot W-LU as an alternative source, so
that flipping bBootLunEn between boot LU A and boot LU B moves U-Boot
along with it and the SPL needs no reconfiguration.

Signed-off-by: Alexey Charkov <[email protected]>
---
 common/spl/Kconfig   | 30 +++++++++++++++++++++++++++++-
 common/spl/spl_ufs.c | 18 ++++++++++++++----
 2 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index d1e3c365ac9a..093bf55e6017 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1634,9 +1634,37 @@ config SPL_UFS_SUPPORT
          use of UFS devices such as hard drives and flash drivers for
          loading U-Boot.
 
+choice
+       prompt "Source of the U-Boot image on UFS"
+       depends on SPL_UFS_SUPPORT
+       default SPL_UFS_RAW_U_BOOT_USE_DEVNUM
+       help
+         Pick how the SPL decides which UFS logical unit holds U-Boot. Either
+         name a logical unit outright, or let the device point at one of its
+         boot logical units through the boot well known logical unit.
+
+config SPL_UFS_RAW_U_BOOT_USE_DEVNUM
+       bool "A fixed SCSI device number"
+       help
+         Load U-Boot from the logical unit that shows up at a known SCSI device
+         number once the SPL has scanned the bus.
+
+config SPL_UFS_RAW_U_BOOT_USE_BOOT_WLUN
+       bool "The UFS boot well known logical unit"
+       help
+         Load U-Boot through the boot W-LU, which the device maps onto 
whichever
+         logical unit bBootLunEn currently selects (boot LU A or boot LU B). 
This
+         follows an A/B switch made by the device itself, so the SPL does not 
have
+         to know which of the two is active.
+
+         Booting has to be enabled on the device (bBootLunEn is not 0), 
otherwise
+         the boot W-LU does not answer and the SPL will not find it.
+
+endchoice
+
 config SPL_UFS_RAW_U_BOOT_DEVNUM
        int "SCSI device number of the UFS device to load U-Boot from"
-       depends on SPL_UFS_SUPPORT
+       depends on SPL_UFS_RAW_U_BOOT_USE_DEVNUM
        default 0
        help
          UFS devices are usually configured with multiple LUNs, which present
diff --git a/common/spl/spl_ufs.c b/common/spl/spl_ufs.c
index cef1843f40f3..393736c7dc7c 100644
--- a/common/spl/spl_ufs.c
+++ b/common/spl/spl_ufs.c
@@ -8,6 +8,7 @@
 #include <scsi.h>
 #include <errno.h>
 #include <image.h>
+#include <ufs.h>
 #include <linux/compiler.h>
 #include <log.h>
 
@@ -24,16 +25,25 @@ static int spl_ufs_load_image(struct spl_image_info 
*spl_image,
                              struct spl_boot_device *bootdev)
 {
        unsigned long sector = CONFIG_SPL_UFS_RAW_U_BOOT_SECTOR;
-       int devnum = CONFIG_SPL_UFS_RAW_U_BOOT_DEVNUM;
+       int devnum = config_opt_enabled(CONFIG_SPL_UFS_RAW_U_BOOT_USE_DEVNUM,
+                                       CONFIG_SPL_UFS_RAW_U_BOOT_DEVNUM, -1);
        struct spl_load_info load;
        struct blk_desc *bd;
        int err;
 
        /* try to recognize storage devices immediately */
        scsi_scan(false);
-       bd = blk_get_devnum_by_uclass_id(UCLASS_SCSI, devnum);
-       if (!bd)
-               return -ENODEV;
+       if (CONFIG_IS_ENABLED(UFS_RAW_U_BOOT_USE_BOOT_WLUN)) {
+               /* A UFS controller only ever has a single target */
+               if (scsi_get_blk_by_lun(0, UFS_UPIU_BOOT_WLUN, &bd)) {
+                       puts("spl_ufs_load_image: UFS boot LU not found\n");
+                       return -ENODEV;
+               }
+       } else {
+               bd = blk_get_devnum_by_uclass_id(UCLASS_SCSI, devnum);
+               if (!bd)
+                       return -ENODEV;
+       }
 
        spl_load_init(&load, spl_ufs_load_read, bd, bd->blksz);
        err = spl_load(spl_image, bootdev, &load, 0, sector << bd->log2blksz);

-- 
2.54.0

Reply via email to