barebox has extensive support for manipulating the device tree it passes
to Linux, which can be useful during bringup.

Let's collect some of this functionality into a safemode command in an
attempt to gather that knowledge at one place.

Signed-off-by: Ahmad Fatoum <[email protected]>
---
 commands/Kconfig       |   7 +++
 commands/Makefile      |   1 +
 commands/safemode.c    | 109 +++++++++++++++++++++++++++++++++++++++++
 drivers/mci/mci-core.c |   6 +--
 include/mci.h          |   5 ++
 5 files changed, 123 insertions(+), 5 deletions(-)
 create mode 100644 commands/safemode.c

diff --git a/commands/Kconfig b/commands/Kconfig
index 6bfc1499afdb..af3b65f35547 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -226,6 +226,13 @@ config CMD_MEMINFO
          system bytes     =     282616
          in use bytes     =     274752
 
+config CMD_SAFEMODE
+       tristate
+       prompt "safemode"
+       select CMD_OF_PROPERTY
+       help
+         Apply safe-mode defaults for next kernel boot.
+
 config CMD_CHECKLEAK
        tristate
        prompt "checkleak"
diff --git a/commands/Makefile b/commands/Makefile
index e7d65163ad80..657fb426ba3e 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_CMD_MW)          += mw.o
 obj-$(CONFIG_CMD_MEMCMP)       += memcmp.o
 obj-$(CONFIG_CMD_MEMCPY)       += memcpy.o
 obj-$(CONFIG_CMD_MEMSET)       += memset.o
+obj-$(CONFIG_CMD_SAFEMODE)     += safemode.o
 obj-$(CONFIG_CMD_EDIT)         += edit.o
 obj-$(CONFIG_CMD_ETHLOG)       += ethlog.o
 obj-$(CONFIG_CMD_EXEC)         += exec.o
diff --git a/commands/safemode.c b/commands/safemode.c
new file mode 100644
index 000000000000..9016869bc56e
--- /dev/null
+++ b/commands/safemode.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <command.h>
+#include <getopt.h>
+#include <mci.h>
+#include <xfuncs.h>
+#include <stdio.h>
+#include <environment.h>
+
+#define        SAFEMODE_MMC            BIT(0)
+#define        SAFEMODE_CONSOLE        BIT(1)
+#define        SAFEMODE_BOOT           BIT(2)
+
+#define run_command_fmt(args...) ({    \
+       char *__buf = xasprintf(args);  \
+       if (verbose)                    \
+               printf("%s\n", __buf);  \
+       int __ret = run_command(__buf); \
+       free(__buf);                    \
+       __ret;                          \
+})
+
+static void safemode_mmc(int verbose)
+{
+       struct mci *mci;
+
+       for_each_mci(mci) {
+               const char *dev = dev_name(&mci->dev);
+
+               run_command_fmt("%s.broken_cd=1", dev);
+               run_command_fmt("of_property -fs %s max-frequency 
'<52000000>'", dev);
+               run_command_fmt("of_property -fs %s pinctrl-names default", 
dev);
+       }
+}
+
+static void safemode_console(int verbose)
+{
+       run_command_fmt("global.bootm.earlycon=1");
+}
+
+static void safemode_boot(int verbose)
+{
+       if (IS_ENABLED(CONFIG_WATCHDOG))
+               run_command_fmt("global.boot.watchdog_timeout=0");
+
+       if (IS_ENABLED(CONFIG_BOOTCHOOSER) &&
+           getenv_nonempty("global.bootchooser.targets"))
+               run_command_fmt("bootchooser -a default -p defaut");
+
+       if (IS_ENABLED(CONFIG_EFI_HANDOVER_PROTOCOL))
+               run_command_fmt("global.linux.efi.handover=1");
+}
+
+static int do_safemode(int argc, char *argv[])
+{
+       unsigned safemode = 0;
+       int opt, verbose = 0;
+
+       while((opt = getopt(argc, argv, "mcbv")) > 0) {
+               switch(opt) {
+               case 'm':
+                       safemode |= SAFEMODE_MMC;
+                       break;
+               case 'c':
+                       safemode |= SAFEMODE_CONSOLE;
+                       break;
+               case 'b':
+                       safemode |= SAFEMODE_BOOT;
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+               default:
+                       return COMMAND_ERROR_USAGE;
+               }
+       }
+
+       if (argc != optind)
+               return COMMAND_ERROR_USAGE;
+
+       if (!safemode)
+               safemode = ~0;
+
+       if (safemode & SAFEMODE_MMC)
+               safemode_mmc(verbose);
+       if (safemode & SAFEMODE_CONSOLE)
+               safemode_console(verbose);
+       if (safemode & SAFEMODE_BOOT)
+               safemode_boot(verbose);
+
+       return 0;
+}
+
+BAREBOX_CMD_HELP_START(safemode)
+BAREBOX_CMD_HELP_TEXT("Apply safe-mode defaults for next kernel boot.")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-m",  "safe mmc settings")
+BAREBOX_CMD_HELP_OPT ("-c",  "safe console settings")
+BAREBOX_CMD_HELP_OPT ("-b",  "safe boot defaults")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(safemode)
+       .cmd            = do_safemode,
+       BAREBOX_CMD_DESC("enable safe mode")
+       BAREBOX_CMD_OPTS("[-mcb]")
+       BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
+       BAREBOX_CMD_HELP(cmd_safemode_help)
+BAREBOX_CMD_END
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index 57825bc849a1..ef676deb7c7f 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -40,11 +40,7 @@ static inline u32 unstuff_bits(const u32 *resp, int start, 
int size)
        return __res & __mask;
 }
 
-static DEFINE_DEV_CLASS(mmc_class, "mmc");
-
-#define for_each_mci(mci) \
-       class_for_each_container_of_device(&mmc_class, mci, dev)
-
+DEFINE_DEV_CLASS(mmc_class, "mmc");
 
 /**
  * @file
diff --git a/include/mci.h b/include/mci.h
index 3db33f914236..3f2b63598568 100644
--- a/include/mci.h
+++ b/include/mci.h
@@ -798,4 +798,9 @@ static inline bool mmc_card_hs200(struct mci *mci)
        return mci->host->ios.timing == MMC_TIMING_MMC_HS200;
 }
 
+extern struct class mmc_class;
+
+#define for_each_mci(mci) \
+       class_for_each_container_of_device(&mmc_class, mci, dev)
+
 #endif /* _MCI_H_ */
-- 
2.47.3


Reply via email to