| // 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, | |
| }; |