[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