Add logic to determine the current boot device by reading the
SoC's configuration registers, rather than using a hardcoded
default.

Signed-off-by: Eric Chung <[email protected]>
Reviewed-by: Yao Zi <[email protected]>
---
v11:
- Fix read_boot_mode() on returning both boot mode and boot device.
v9:
- Enhance detection on booting from SD card.
v5:
- Add blank lines around the switch statement.
v2:
- Use FIELD_GET() to parse boot strap mode.
- Remove comments on hacking. Since the sequence between eMMC
  and SD device is exchanged in the upstream DTS. So it isn't
  a hacking any more.
---
 board/spacemit/k1/spl.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 1 deletion(-)

diff --git a/board/spacemit/k1/spl.c b/board/spacemit/k1/spl.c
index d749e21a2d57..374922573c98 100644
--- a/board/spacemit/k1/spl.c
+++ b/board/spacemit/k1/spl.c
@@ -13,6 +13,7 @@
 #include <dm/device.h>
 #include <dm/uclass.h>
 #include <i2c.h>
+#include <linux/bitfield.h>
 #include <linux/ctype.h>
 #include <linux/delay.h>
 #include <log.h>
@@ -22,6 +23,20 @@
 #include <tlv_eeprom.h>
 #include "tlv_codes.h"
 
+/* boot mode configs */
+#define BOOT_DEV_FLAG_REG      0xd4282d10
+#define BOOT_PIN_SEL_REG       0xd4282c20
+
+#define BOOT_STRAP_MODE_OFFSET 9
+#define BOOT_STRAP_MODE_MASK   3
+#define BOOT_STRAP_MODE_EMMC   0
+#define BOOT_STRAP_MODE_SPI    1
+#define BOOT_STRAP_MODE_NAND   2
+#define BOOT_STRAP_MODE_SD     3
+
+#define STORAGE_API_P_ADDR     0xc0838498
+#define SDCARD_API_ENTRY       0xffe0a548
+
 #define MUX_MODE4              4
 #define EDGE_NONE              BIT(6)
 #define PULL_UP                        (6 << 13)       /* bit[15:13] 110 */
@@ -46,6 +61,17 @@ typedef void (*puts_func_t)(const char *s);
 typedef int (*ddr_init_func_t)(u64 ddr_base, u32 cs_num, u32 data_rate,
                               puts_func_t puts);
 
+enum board_boot_mode {
+       BOOT_MODE_NONE = 0,
+       BOOT_MODE_USB = 0x55a,
+       BOOT_MODE_EMMC,
+       BOOT_MODE_NAND,
+       BOOT_MODE_SPI,
+       BOOT_MODE_SD,
+       BOOT_MODE_SHELL = 0x55f,
+       BOOT_MODE_BOOTSTRAP,
+};
+
 struct ddr_cfg {
        u32     data_rate;
        u32     cs_num;
@@ -58,6 +84,47 @@ binman_sym_declare(ulong, ddr_fw, size);
 
 char product_name[I2C_BUF_SIZE] = "k1";
 
+static u32 read_boot_mode(void)
+{
+       void __iomem *boot_dev = (void __iomem *)BOOT_DEV_FLAG_REG;
+       void __iomem *boot_strap = (void __iomem *)BOOT_PIN_SEL_REG;
+       void __iomem *storage_api = (void __iomem *)STORAGE_API_P_ADDR;
+       u32 mode, sel;
+
+       mode = readl(storage_api);
+       if (mode == SDCARD_API_ENTRY)
+               return BOOT_MODE_SD;
+
+       mode = readl(boot_dev);
+       if (mode == BOOT_MODE_NONE || mode > BOOT_MODE_SD) {
+               sel = FIELD_GET(BOOT_STRAP_MODE_MASK << BOOT_STRAP_MODE_OFFSET,
+                               readl(boot_strap));
+               switch (sel) {
+               case BOOT_STRAP_MODE_EMMC:
+                       mode = BOOT_MODE_EMMC;
+                       break;
+               case BOOT_STRAP_MODE_NAND:
+                       mode = BOOT_MODE_NAND;
+                       break;
+               case BOOT_STRAP_MODE_SPI:
+                       mode = BOOT_MODE_SPI;
+                       break;
+               case BOOT_STRAP_MODE_SD:
+               default:
+                       mode = BOOT_MODE_SD;
+                       break;
+               }
+       }
+       return mode;
+}
+
+static void write_boot_mode(u32 mode)
+{
+       void __iomem *boot_dev = (void __iomem *)BOOT_DEV_FLAG_REG;
+
+       writel(mode, boot_dev);
+}
+
 static void i2c_early_init(void)
 {
        struct udevice *bus;
@@ -327,8 +394,12 @@ void nor_early_init(void)
 
 void board_init_f(ulong dummy)
 {
+       u32 mode;
        int ret;
 
+       mode = read_boot_mode();
+       write_boot_mode(mode);
+
        ret = spl_early_init();
        if (ret)
                panic("spl_early_init() failed:%d\n", ret);
@@ -354,7 +425,32 @@ void board_init_f(ulong dummy)
 
 u32 spl_boot_device(void)
 {
-       return BOOT_DEVICE_SPI;
+       u32 mode;
+       int ret;
+
+       mode = read_boot_mode();
+       switch (mode) {
+       case BOOT_MODE_EMMC:
+               ret = BOOT_DEVICE_MMC1;
+               break;
+       case BOOT_MODE_NAND:
+               ret = BOOT_DEVICE_NAND;
+               break;
+       case BOOT_MODE_SPI:
+               ret = BOOT_DEVICE_SPI;
+               break;
+       case BOOT_MODE_USB:
+               ret = BOOT_DEVICE_USB;
+               break;
+       case BOOT_MODE_SD:
+               ret = BOOT_DEVICE_MMC2;
+               break;
+       default:
+               ret = BOOT_DEVICE_MMC1;
+               break;
+       }
+
+       return ret;
 }
 
 void spl_board_init(void)

-- 
2.51.0

Reply via email to