[PATCH 01/10] driver: add feature controller framework
Ahmad Fatoum
a.fatoum at pengutronix.de
Wed Aug 17 22:19:46 PDT 2022
Many SoCs feature hardware that controls or reports access restrictions
to specific devices, e.g. a TrustZone firewall controller can limit
which devices are accessible to the non-secure world and a fusebank
can report that some peripherals are gated and unusable.
A feature controller is an abstraction that covers both cases.
Nodes that are dependent on a feature (e.g. exception level or
SoC type) get a barebox,feature-gates property that references
a feature controller with a feature index. The feature controller
registers a callback with the framework that checks whether
a device is accessible.
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
drivers/base/Kconfig | 3 +
drivers/base/Makefile | 1 +
drivers/base/featctrl.c | 120 ++++++++++++++++++++++++++++++++++++++++
include/featctrl.h | 29 ++++++++++
4 files changed, 153 insertions(+)
create mode 100644 drivers/base/featctrl.c
create mode 100644 include/featctrl.h
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 5bc70aa1e525..eebb60ce9193 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -2,3 +2,6 @@
config PM_GENERIC_DOMAINS
bool
+
+config FEATURE_CONTROLLER
+ bool "Feature controller support" if COMPILE_TEST
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 59645c6f5359..e8e354cdaabc 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -6,3 +6,4 @@ obj-y += resource.o
obj-y += regmap/
obj-$(CONFIG_PM_GENERIC_DOMAINS) += power.o
+obj-$(CONFIG_FEATURE_CONTROLLER) += featctrl.o
diff --git a/drivers/base/featctrl.c b/drivers/base/featctrl.c
new file mode 100644
index 000000000000..a5d06323c221
--- /dev/null
+++ b/drivers/base/featctrl.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2022 Ahmad Fatoum, Pengutronix
+
+#define pr_fmt(fmt) "featctrl: " fmt
+
+#include <common.h>
+#include <driver.h>
+#include <errno.h>
+#include <of.h>
+
+#include <featctrl.h>
+
+/* List of registered feature controllers */
+static LIST_HEAD(of_feature_controllers);
+
+/**
+ * feature_controller_register() - Register a feature controller
+ * @feat: Pointer to feature controller
+ */
+int feature_controller_register(struct feature_controller *feat)
+{
+ struct device_node *np = dev_of_node(feat->dev);
+
+ if (!np)
+ return -EINVAL;
+
+ list_add(&feat->list, &of_feature_controllers);
+ dev_dbg(feat->dev, "Registering feature controller\n");
+ return 0;
+}
+EXPORT_SYMBOL_GPL(feature_controller_register);
+
+/**
+ * featctrl_get_from_provider() - Look-up feature gate
+ * @spec: OF phandle args to use for look-up
+ * @gateid: ID of feature controller gate populated on successful lookup
+ *
+ * Looks for a feature controller under the node specified by @spec.
+ *
+ * Returns a valid pointer to struct feature_controller on success or ERR_PTR()
+ * on failure.
+ */
+static struct feature_controller *featctrl_get_from_provider(struct of_phandle_args *spec,
+ unsigned *gateid)
+{
+ struct feature_controller *featctrl;
+ int ret;
+
+ if (!spec)
+ return ERR_PTR(-EINVAL);
+
+ ret = of_device_ensure_probed(spec->np);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ /* Check if we have such a controller in our array */
+ list_for_each_entry(featctrl, &of_feature_controllers, list) {
+ if (dev_of_node(featctrl->dev) == spec->np) {
+ *gateid = spec->args[0];
+ return featctrl;
+ }
+ }
+
+ return ERR_PTR(-ENOENT);
+}
+
+/**
+ * of_feature_controller_check - Check whether a feature controller gates the device
+ * @np: Device node to check
+ *
+ * Parse device's OF node to find a feature controller specifier. If such is
+ * found, checks it to determine whether device is gated.
+ *
+ * Returns FEATCTRL_GATED if a specified feature controller gates the device
+ * and FEATCTRL_OKAY if none do. On error a negative error code is returned.
+ */
+int of_feature_controller_check(struct device_node *np)
+{
+ struct of_phandle_args featctrl_args;
+ struct feature_controller *featctrl;
+ int ret, err = 0, i, ngates;
+
+ ngates = of_count_phandle_with_args(np, "barebox,feature-gates",
+ "#feature-cells");
+ if (ngates <= 0)
+ return FEATCTRL_OKAY;
+
+ for (i = 0; i < ngates; i++) {
+ unsigned gateid = 0;
+
+ ret = of_parse_phandle_with_args(np, "barebox,feature-gates",
+ "#feature-cells", i, &featctrl_args);
+ if (ret < 0)
+ return ret;
+
+ featctrl = featctrl_get_from_provider(&featctrl_args, &gateid);
+ if (IS_ERR(featctrl)) {
+ ret = PTR_ERR(featctrl);
+ pr_debug("%s() failed to find feature controller: %pe\n",
+ __func__, ERR_PTR(ret));
+ /*
+ * Assume that missing featctrls are unresolved
+ * dependency are report them as deferred
+ */
+ return (ret == -ENOENT) ? -EPROBE_DEFER : ret;
+ }
+
+ ret = featctrl->check(featctrl, gateid);
+
+ dev_dbg(featctrl->dev, "checking %s: %d\n", np->full_name, ret);
+
+ if (ret == FEATCTRL_OKAY)
+ return FEATCTRL_OKAY;
+ if (ret != FEATCTRL_GATED)
+ err = ret;
+ }
+
+ return err ?: FEATCTRL_GATED;
+}
+EXPORT_SYMBOL_GPL(of_feature_controller_check);
diff --git a/include/featctrl.h b/include/featctrl.h
new file mode 100644
index 000000000000..fb9e4156bdc2
--- /dev/null
+++ b/include/featctrl.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __FEATCTRL_H_
+#define __FEATCTRL_H_
+
+#include <linux/list.h>
+
+struct feature_controller;
+struct device_node;
+
+struct feature_controller {
+ struct device_d *dev;
+ int (*check)(struct feature_controller *, int idx);
+ struct list_head list;
+};
+
+enum { FEATCTRL_GATED = 0, FEATCTRL_OKAY = 1 };
+
+int feature_controller_register(struct feature_controller *);
+
+#ifdef CONFIG_FEATURE_CONTROLLER
+int of_feature_controller_check(struct device_node *np);
+#else
+static inline int of_feature_controller_check(struct device_node *np)
+{
+ return FEATCTRL_OKAY;
+}
+#endif
+
+#endif /* PINCTRL_H */
--
2.30.2
More information about the barebox
mailing list