Messages in this thread Patch in this message | | | Date | Thu, 08 Sep 2016 20:35:46 +0000 | Subject | [PATCH] of: Overlay manager | From | dimitrysh@google ... |
| |
From e14eb45fa5a93c1bff8a6dfe7b6756e4ad72c579 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt <dimitrysh@google.com> Date: Wed, 24 Aug 2016 13:25:52 -0700 Subject: [PATCH] of: Overlay manager
Overlay manager processes DT entries on demand. It is chosen by CONFIG_OF_OVERLAY_MGR option. These entries can be chosen from kernel command line: overlay_mgr.overlay_dt_entry=hardware_cfg_0 DT contains main overlay_mng entry with all possible HW config setups. And then kernel command line option will allow to choose between them.
Kernel DT entry: overlay_mgr { compatible = "linux,overlay_manager"; hardware_cfg_0 { overlay@0 { fragment@0 { __overlay__ { }; }; }; overlay@1 { fragment@0 { __overlay__ { }; }; }; }; };
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com> Tested-by: John Stultz <john.stultz@linaro.org> Acked-by: John Stultz <john.stultz@linaro.org> --- .../devicetree/bindings/of/overlay_mgr.txt | 32 ++++++++ drivers/of/Kconfig | 10 +++ drivers/of/Makefile | 1 + drivers/of/overlay_mgr.c | 90 ++++++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 Documentation/devicetree/bindings/of/overlay_mgr.txt create mode 100644 drivers/of/overlay_mgr.c
diff --git a/Documentation/devicetree/bindings/of/overlay_mgr.txt b/Documentation/devicetree/bindings/of/overlay_mgr.txt new file mode 100644 index 0000000..5f3ce4c --- /dev/null +++ b/Documentation/devicetree/bindings/of/overlay_mgr.txt @@ -0,0 +1,32 @@ +overlay_mgr + +Required properties: +- compatible: "linux,overlay_manager"; + +Optional properties: +- starts from the word "hardware": hardware_cfg_0 + +These properties can be chosen from kernel command line: +overlay_mgr.overlay_dt_entry=hardware_cfg_0 +DT contains main overlay_mng entry with all possible +HW config setups. And then kernel command line option +will allow to choose between them. + +Example: + overlay_mgr { + compatible = "linux,overlay_manager"; + hardware_cfg_0 { + overlay@0 { + fragment@0 { + __overlay__ { + }; + }; + }; + overlay@1 { + fragment@0 { + __overlay__ { + }; + }; + }; + }; + }; diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index e2a4841..e3eb06d 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -112,4 +112,14 @@ config OF_OVERLAY While this option is selected automatically when needed, you can enable it manually to improve device tree unit test coverage.
+config OF_OVERLAY_MGR + bool "Enable Overlay manager" + default n + depends on OF_OVERLAY + help + Enables Overlay manager - it accepts DT entry from command line + overlay_mgr.overlay_dt_entry=<name> and applies all overlays in + it to current DT. It is also possible to apply predefined DT + entry on the fly by writing it to 'current_overlay' sysfs entry. + endif # OF diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 156c072..3bddd19 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -14,5 +14,6 @@ obj-$(CONFIG_OF_MTD) += of_mtd.o obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o obj-$(CONFIG_OF_RESOLVE) += resolver.o obj-$(CONFIG_OF_OVERLAY) += overlay.o +obj-$(CONFIG_OF_OVERLAY_MGR) += overlay_mgr.o
obj-$(CONFIG_OF_UNITTEST) += unittest-data/ diff --git a/drivers/of/overlay_mgr.c b/drivers/of/overlay_mgr.c new file mode 100644 index 0000000..1fdeb0a --- /dev/null +++ b/drivers/of/overlay_mgr.c @@ -0,0 +1,90 @@ +/* + * Overlay manager that allows to apply list of overlays from DT entry + * + * Copyright (C) 2016 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/of.h> +#include <linux/platform_device.h> + +static char *of_overlay_dt_entry; +module_param_named(overlay_dt_entry, of_overlay_dt_entry, charp, 0644); + +static int of_overlay_mgr_apply_overlay(struct device_node *onp) +{ + int ret; + + ret = of_overlay_create(onp); + if (ret < 0) { + pr_err("overlay_mgr: fail to create overlay: %d\n", ret); + of_node_put(onp); + return ret; + } + pr_info("overlay_mgr: %s overlay applied\n", onp->name); + return 0; +} + +static int of_overlay_mgr_apply_dt(struct device *dev, char *dt_entry) +{ + struct device_node *enp = dev->of_node; + struct device_node *next; + struct device_node *prev = NULL; + + if (!enp) { + pr_err("overlay_mgr: no dt entry\n"); + return -ENODEV; + } + + enp = of_get_child_by_name(enp, dt_entry); + if (!enp) { + pr_err("overlay_mgr: dt entry %s not found\n", dt_entry); + return -ENODEV; + } + pr_info("overlay_mgr: apply %s dt entry\n", enp->name); + while ((next = of_get_next_available_child(enp, prev)) != NULL) { + if (strncmp(next->name, "overlay", 7) == 0) + of_overlay_mgr_apply_overlay(next); + prev = next; + } + return 0; +} + +static int of_overlay_mgr_probe(struct platform_device *pdev) +{ + if (!of_overlay_dt_entry) + return 0; + of_overlay_mgr_apply_dt(&pdev->dev, of_overlay_dt_entry); + return 0; +} + +static const struct of_device_id of_overlay_mgr_match[] = { + { .compatible = "linux,overlay_manager", }, + {} +}; + +static struct platform_driver of_overlay_mgr_driver = { + .probe = of_overlay_mgr_probe, + .driver = { + .name = "overlay_manager", + .of_match_table = of_match_ptr(of_overlay_mgr_match), + }, +}; + +static int __init of_overlay_mgr_init(void) +{ + return platform_driver_register(&of_overlay_mgr_driver); +} + +postcore_initcall(of_overlay_mgr_init); -- 2.8.0.rc3.226.g39d4020
| |