summaryrefslogtreecommitdiff
path: root/boot/extension-uclass.c
diff options
context:
space:
mode:
Diffstat (limited to 'boot/extension-uclass.c')
-rw-r--r--boot/extension-uclass.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/boot/extension-uclass.c b/boot/extension-uclass.c
new file mode 100644
index 00000000000..4b3dd1bc0cd
--- /dev/null
+++ b/boot/extension-uclass.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2025 Köry Maincent <kory.maincent@bootlin.com>
+ */
+
+#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 *extension_get_list(void)
+{
+ struct udevice *dev;
+
+ if (uclass_first_device_err(UCLASS_EXTENSION, &dev))
+ return NULL;
+
+ return dev_get_priv(dev);
+}
+
+int extension_probe(struct udevice *dev)
+{
+ struct alist *extension_list = dev_get_priv(dev);
+
+ alist_init_struct(extension_list, struct extension);
+ return 0;
+}
+
+int extension_remove(struct udevice *dev)
+{
+ struct alist *extension_list = dev_get_priv(dev);
+
+ alist_uninit(extension_list);
+ return 0;
+}
+
+int extension_scan(void)
+{
+ struct alist *extension_list = 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);
+}
+
+int extension_apply(struct fdt_header *working_fdt, ulong size)
+{
+ struct fdt_header *blob;
+ ulong overlay_addr;
+ int ret;
+
+ overlay_addr = env_get_hex("extension_overlay_addr", 0);
+ if (!overlay_addr) {
+ printf("Environment extension_overlay_addr is missing\n");
+ return -EINVAL;
+ }
+
+ fdt_shrink_to_minimum(working_fdt, size);
+
+ blob = map_sysmem(overlay_addr, 0);
+ if (!fdt_valid(&blob)) {
+ printf("Invalid overlay devicetree\n");
+ return -EINVAL;
+ }
+
+ /* Apply method prints messages on error */
+ ret = fdt_overlay_apply_verbose(working_fdt, blob);
+ if (ret)
+ printf("Failed to apply overlay\n");
+
+ return ret;
+}
+
+UCLASS_DRIVER(extension) = {
+ .name = "extension",
+ .id = UCLASS_EXTENSION,
+};