aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEtienne Carriere <etienne.carriere@linaro.org>2021-09-10 18:37:05 +0200
committerJérôme Forissier <jerome@forissier.org>2021-11-12 10:15:58 +0100
commit8c0c44c9d2f768a95beacd4605776cfe29c9bff6 (patch)
treed696c972ff06d1cf68f2499cd39b451ade0b6a8c
parentc282ebd61200b0cb0830399c1c33514dbd129dfd (diff)
core: dt_driver: factorize DT phandle util resources
Move struct clk_dt_phandle_args and struct clk_dt_provider from clk_dt.h to dt_driver.h and rename them to struct dt_driver_phandle_args and struct dt_driver_provider. Introduce type get_of_device_func for callback functions used to retrieve a device instance reference from a DT phandle possible with arguments. Acked-by: Jerome Forissier <jerome@forissier.org> Acked-by: Clément Léger <clement.leger@bootlin.com> Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
-rw-r--r--core/drivers/clk/clk_dt.c65
-rw-r--r--core/include/drivers/clk_dt.h17
-rw-r--r--core/include/kernel/dt_driver.h63
-rw-r--r--core/kernel/dt_driver.c11
-rw-r--r--core/kernel/sub.mk1
5 files changed, 106 insertions, 51 deletions
diff --git a/core/drivers/clk/clk_dt.c b/core/drivers/clk/clk_dt.c
index 3549b61e..1941531d 100644
--- a/core/drivers/clk/clk_dt.c
+++ b/core/drivers/clk/clk_dt.c
@@ -8,22 +8,11 @@
#include <drivers/clk_dt.h>
#include <initcall.h>
#include <kernel/boot.h>
+#include <kernel/dt_driver.h>
#include <kernel/panic.h>
#include <libfdt.h>
#include <stddef.h>
-struct clk_dt_provider {
- int nodeoffset;
- unsigned int clock_cells;
- uint32_t phandle;
- clk_dt_get_func get_dt_clk;
- void *data;
- SLIST_ENTRY(clk_dt_provider) link;
-};
-
-static SLIST_HEAD(, clk_dt_provider) clk_dt_provider_list =
- SLIST_HEAD_INITIALIZER(clk_dt_provider_list);
-
static int fdt_clock_cells(const void *fdt, int nodeoffset)
{
const fdt32_t *c = NULL;
@@ -42,36 +31,36 @@ static int fdt_clock_cells(const void *fdt, int nodeoffset)
TEE_Result clk_dt_register_clk_provider(const void *fdt, int nodeoffset,
clk_dt_get_func get_dt_clk, void *data)
{
- struct clk_dt_provider *prv = NULL;
+ struct dt_driver_provider *prv = NULL;
int clock_cells = 0;
prv = calloc(1, sizeof(*prv));
if (!prv)
return TEE_ERROR_OUT_OF_MEMORY;
- prv->get_dt_clk = get_dt_clk;
- prv->data = data;
+ prv->get_of_device = (get_of_device_func)get_dt_clk;
+ prv->priv_data = data;
prv->nodeoffset = nodeoffset;
clock_cells = fdt_clock_cells(fdt, nodeoffset);
if (clock_cells < 0) {
free(prv);
return TEE_ERROR_GENERIC;
}
- prv->clock_cells = clock_cells;
+ prv->provider_cells = clock_cells;
prv->phandle = fdt_get_phandle(fdt, nodeoffset);
- SLIST_INSERT_HEAD(&clk_dt_provider_list, prv, link);
+ SLIST_INSERT_HEAD(&dt_driver_provider_list, prv, link);
return TEE_SUCCESS;
}
static TEE_Result clk_dt_release_provider(void)
{
- struct clk_dt_provider *prv = NULL;
+ struct dt_driver_provider *prv = NULL;
- while (!SLIST_EMPTY(&clk_dt_provider_list)) {
- prv = SLIST_FIRST(&clk_dt_provider_list);
- SLIST_REMOVE_HEAD(&clk_dt_provider_list, link);
+ while (!SLIST_EMPTY(&dt_driver_provider_list)) {
+ prv = SLIST_FIRST(&dt_driver_provider_list);
+ SLIST_REMOVE_HEAD(&dt_driver_provider_list, link);
free(prv);
}
@@ -80,46 +69,48 @@ static TEE_Result clk_dt_release_provider(void)
driver_init_late(clk_dt_release_provider);
-static struct clk_dt_provider *clk_get_provider_by_node(int nodeoffset)
+static struct dt_driver_provider *clk_get_provider_by_node(int nodeoffset)
{
- struct clk_dt_provider *prv = NULL;
+ struct dt_driver_provider *prv = NULL;
- SLIST_FOREACH(prv, &clk_dt_provider_list, link)
+ SLIST_FOREACH(prv, &dt_driver_provider_list, link)
if (prv->nodeoffset == nodeoffset)
return prv;
return NULL;
}
-static struct clk_dt_provider *clk_get_provider_by_phandle(uint32_t phandle)
+static struct dt_driver_provider *clk_get_provider_by_phandle(uint32_t phandle)
{
- struct clk_dt_provider *prv = NULL;
+ struct dt_driver_provider *prv = NULL;
- SLIST_FOREACH(prv, &clk_dt_provider_list, link)
+ SLIST_FOREACH(prv, &dt_driver_provider_list, link)
if (prv->phandle == phandle)
return prv;
return NULL;
}
-static struct clk *clk_dt_get_from_provider(struct clk_dt_provider *prv,
+static struct clk *clk_dt_get_from_provider(struct dt_driver_provider *prv,
unsigned int clock_cells,
const uint32_t *prop)
{
unsigned int arg = 0;
struct clk *clk = NULL;
- struct clk_dt_phandle_args pargs = { };
+ struct dt_driver_phandle_args *pargs = NULL;
- pargs.args_count = clock_cells;
- pargs.args = calloc(pargs.args_count, sizeof(uint32_t));
- if (!pargs.args)
+ pargs = calloc(1, clock_cells * sizeof(uint32_t *) +
+ sizeof(*pargs));
+ if (!pargs)
return NULL;
+ pargs->args_count = clock_cells;
for (arg = 0; arg < clock_cells; arg++)
- pargs.args[arg] = fdt32_to_cpu(prop[arg + 1]);
+ pargs->args[arg] = fdt32_to_cpu(prop[arg + 1]);
+
+ clk = prv->get_of_device(pargs, prv->priv_data);
- clk = prv->get_dt_clk(&pargs, prv->data);
- free(pargs.args);
+ free(pargs);
return clk;
}
@@ -146,7 +137,7 @@ static struct clk *clk_dt_get_by_idx_prop(const char *prop_name,
int clock_cells = 0;
uint32_t phandle = 0;
const uint32_t *prop = NULL;
- struct clk_dt_provider *prv = NULL;
+ struct dt_driver_provider *prv = NULL;
prop = fdt_getprop(fdt, nodeoffset, prop_name, &len);
if (!prop)
@@ -160,7 +151,7 @@ static struct clk *clk_dt_get_by_idx_prop(const char *prop_name,
if (!prv)
return NULL;
- clock_cells = prv->clock_cells;
+ clock_cells = prv->provider_cells;
if (clk_idx) {
clk_idx--;
idx += sizeof(phandle) + clock_cells * sizeof(uint32_t);
diff --git a/core/include/drivers/clk_dt.h b/core/include/drivers/clk_dt.h
index 60396990..34ef51be 100644
--- a/core/include/drivers/clk_dt.h
+++ b/core/include/drivers/clk_dt.h
@@ -7,22 +7,11 @@
#define __DRIVERS_CLK_DT_H
#include <kernel/dt.h>
+#include <kernel/dt_driver.h>
#include <stdint.h>
#include <sys/queue.h>
/**
- * struct clk_dt_phandle_args - Devicetree clock args
- * @nodeoffset: Clock consumer node offset
- * @args_count: Count of items in @args
- * @args: Clocks consumer specifiers
- */
-struct clk_dt_phandle_args {
- int nodeoffset;
- int args_count;
- uint32_t *args;
-};
-
-/**
* struct clk_driver - Clock driver setup struct
* probe: probe function for the clock driver
*/
@@ -85,7 +74,7 @@ struct clk *clk_dt_get_by_name(const void *fdt, int nodeoffset,
* Returns a clk struct pointer pointing to a clock matching the devicetree
* description or NULL if invalid description.
*/
-typedef struct clk *(*clk_dt_get_func)(struct clk_dt_phandle_args *args,
+typedef struct clk *(*clk_dt_get_func)(struct dt_driver_phandle_args *args,
void *data);
/**
@@ -105,7 +94,7 @@ TEE_Result clk_dt_register_clk_provider(const void *fdt, int nodeoffset,
* providers
*/
static inline
-struct clk *clk_dt_get_simple_clk(struct clk_dt_phandle_args *args __unused,
+struct clk *clk_dt_get_simple_clk(struct dt_driver_phandle_args *args __unused,
void *data)
{
return data;
diff --git a/core/include/kernel/dt_driver.h b/core/include/kernel/dt_driver.h
new file mode 100644
index 00000000..e011ce99
--- /dev/null
+++ b/core/include/kernel/dt_driver.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2021, Linaro Limited
+ * Copyright (c) 2021, Bootlin
+ */
+
+#ifndef __DT_DRIVER_H
+#define __DT_DRIVER_H
+
+#include <kernel/dt.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+/**
+ * struct dt_driver_phandle_args - Devicetree phandle arguments
+ * @args_count: Count of cells for the device
+ * @args: Device consumer specifiers
+ */
+struct dt_driver_phandle_args {
+ int args_count;
+ uint32_t args[];
+};
+
+/*
+ * get_of_device_func - Callback function for returning a driver private
+ * instance based on a FDT phandle with possible arguments and the
+ * registered dt_driver private data reference.
+ *
+ * @parg: phandle argument(s) referencing the device in the FDT.
+ * @data: driver private data registered in struct dt_driver.
+ *
+ * Return a device opaque reference, e.g. a struct clk pointer for a clock
+ * driver, or NULL if not found.
+ */
+typedef void *(*get_of_device_func)(struct dt_driver_phandle_args *parg,
+ void *data);
+
+/*
+ * struct dt_driver_provider - DT related info on probed device
+ *
+ * Saves information on the probed device so that device
+ * drivers can get resources from DT phandle and related arguments.
+ *
+ * @nodeoffset: Node offset of device referenced in the FDT
+ * @type: One of DT_DRIVER_* or DT_DRIVER_NOTYPE.
+ * @provider_cells: Cells count in the FDT used by the driver's references
+ * @get_of_device: Function to get driver's device ref from phandle data
+ * @priv_data: Driver private data passed as @get_of_device argument
+ * @link: Reference in DT driver providers list
+ */
+struct dt_driver_provider {
+ int nodeoffset;
+ enum dt_driver_type type;
+ unsigned int provider_cells;
+ uint32_t phandle;
+ get_of_device_func get_of_device;
+ void *priv_data;
+ SLIST_ENTRY(dt_driver_provider) link;
+};
+
+SLIST_HEAD(dt_driver_prov_list, dt_driver_provider);
+extern struct dt_driver_prov_list dt_driver_provider_list;
+#endif /* __DT_DRIVER_H */
diff --git a/core/kernel/dt_driver.c b/core/kernel/dt_driver.c
new file mode 100644
index 00000000..4b08ee45
--- /dev/null
+++ b/core/kernel/dt_driver.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2021, Linaro Limited
+ * Copyright (c) 2021, Bootlin
+ */
+
+#include <kernel/dt_driver.h>
+#include <sys/queue.h>
+
+struct dt_driver_prov_list dt_driver_provider_list =
+ SLIST_HEAD_INITIALIZER(dt_driver_provider_list);
diff --git a/core/kernel/sub.mk b/core/kernel/sub.mk
index a5dfae22..853883dc 100644
--- a/core/kernel/sub.mk
+++ b/core/kernel/sub.mk
@@ -3,6 +3,7 @@ cflags-remove-asan.c-y += $(cflags_kasan)
srcs-y += assert.c
srcs-y += console.c
srcs-$(CFG_DT) += dt.c
+srcs-$(CFG_DT) += dt_driver.c
srcs-y += pm.c
srcs-y += handle.c
srcs-y += interrupt.c