summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorKory Maincent (TI.com) <[email protected]>2025-10-30 17:45:01 +0100
committerTom Rini <[email protected]>2025-11-03 10:02:39 -0600
commit78a06090f4860d52dfd1577619f53a7ec75122c9 (patch)
treeb0c3de30b114003baf8ffe4c1583d81fdd9a9a6b /boot
parentb7edeac950dae10759527a1ed0d1c306710ec9de (diff)
boot: Add UCLASS support for extension boards
Introduce UCLASS-based extension board support to enable more standardized and automatic loading of extension board device tree overlays in preparation for integration with bootstd and pxe_utils. Several #if CONFIG_IS_ENABLED are used in cmd/extension_board.c to ease the development but don't worry they are removed later in the series. Signed-off-by: Kory Maincent (TI.com) <[email protected]> Reviewed-by: Simon Glass <[email protected]>
Diffstat (limited to 'boot')
-rw-r--r--boot/Kconfig4
-rw-r--r--boot/Makefile1
-rw-r--r--boot/extension-uclass.c151
3 files changed, 156 insertions, 0 deletions
diff --git a/boot/Kconfig b/boot/Kconfig
index a75f6b641ed..08d666d4b93 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -1910,6 +1910,10 @@ config SUPPORT_EXTENSION_SCAN
select OF_LIBFDT_OVERLAY
bool
+config SUPPORT_DM_EXTENSION_SCAN
+ select OF_LIBFDT_OVERLAY
+ bool
+
config USE_BOOTARGS
bool "Enable boot arguments"
help
diff --git a/boot/Makefile b/boot/Makefile
index f60d13130b1..aa26070fbb8 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o
obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o
obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o
obj-$(CONFIG_SUPPORT_EXTENSION_SCAN) += extension.o
+obj-$(CONFIG_SUPPORT_DM_EXTENSION_SCAN) += extension-uclass.o
obj-$(CONFIG_PXE_UTILS) += pxe_utils.o
diff --git a/boot/extension-uclass.c b/boot/extension-uclass.c
new file mode 100644
index 00000000000..914971215af
--- /dev/null
+++ b/boot/extension-uclass.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2025 Köry Maincent <[email protected]>
+ */
+
+#include <alist.h>
+#include <command.h>
+#include <env.h>
+#include <extension_board.h>
+#include <fdt_support.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/uclass.h>
+
+struct alist *dm_extension_get_list(void)
+{
+ struct udevice *dev;
+
+ if (uclass_first_device_err(UCLASS_EXTENSION, &dev))
+ return NULL;
+
+ return dev_get_priv(dev);
+}
+
+int dm_extension_probe(struct udevice *dev)
+{
+ struct alist *extension_list = dev_get_priv(dev);
+
+ alist_init_struct(extension_list, struct extension);
+ return 0;
+}
+
+int dm_extension_remove(struct udevice *dev)
+{
+ struct alist *extension_list = dev_get_priv(dev);
+
+ alist_uninit(extension_list);
+ return 0;
+}
+
+int dm_extension_scan(void)
+{
+ struct alist *extension_list = dm_extension_get_list();
+ const struct extension_ops *ops;
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_EXTENSION, &dev);
+ if (ret)
+ return ret;
+
+ if (!extension_list)
+ return -ENODEV;
+
+ ops = extension_get_ops(dev);
+ alist_empty(extension_list);
+ return ops->scan(dev, extension_list);
+}
+
+static int _extension_apply(const struct extension *extension)
+{
+ ulong extrasize, overlay_addr;
+ struct fdt_header *blob;
+ char *overlay_cmd;
+ int ret;
+
+ if (!working_fdt) {
+ printf("No FDT memory address configured. Please configure\n"
+ "the FDT address via \"fdt addr <address>\" command.\n");
+ return -EINVAL;
+ }
+
+ overlay_cmd = env_get("extension_overlay_cmd");
+ if (!overlay_cmd) {
+ printf("Environment extension_overlay_cmd is missing\n");
+ return -EINVAL;
+ }
+
+ overlay_addr = env_get_hex("extension_overlay_addr", 0);
+ if (!overlay_addr) {
+ printf("Environment extension_overlay_addr is missing\n");
+ return -EINVAL;
+ }
+
+ env_set("extension_overlay_name", extension->overlay);
+ ret = run_command(overlay_cmd, 0);
+ if (ret)
+ return ret;
+
+ extrasize = env_get_hex("filesize", 0);
+ if (!extrasize)
+ return -EINVAL;
+
+ fdt_shrink_to_minimum(working_fdt, extrasize);
+
+ blob = map_sysmem(overlay_addr, 0);
+ if (!fdt_valid(&blob)) {
+ printf("Invalid overlay devicetree %s\n", extension->overlay);
+ return -EINVAL;
+ }
+
+ /* Apply method prints messages on error */
+ ret = fdt_overlay_apply_verbose(working_fdt, blob);
+ if (ret)
+ printf("Failed to apply overlay %s\n", extension->overlay);
+
+ return ret;
+}
+
+int dm_extension_apply(int extension_num)
+{
+ struct alist *extension_list = dm_extension_get_list();
+ const struct extension *extension;
+
+ if (!extension_list)
+ return -ENOENT;
+
+ extension = alist_get(extension_list, extension_num,
+ struct extension);
+ if (!extension) {
+ printf("Wrong extension number\n");
+ return -EINVAL;
+ }
+
+ return _extension_apply(extension);
+}
+
+int dm_extension_apply_all(void)
+{
+ struct alist *extension_list = dm_extension_get_list();
+ const struct extension *extension;
+ int ret;
+
+ if (!extension_list)
+ return -ENOENT;
+
+ alist_for_each(extension, extension_list) {
+ ret = _extension_apply(extension);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+UCLASS_DRIVER(extension) = {
+ .name = "extension",
+ .id = UCLASS_EXTENSION,
+};