diff options
author | Etienne Carriere <etienne.carriere@linaro.org> | 2021-09-10 18:37:05 +0200 |
---|---|---|
committer | Jérôme Forissier <jerome@forissier.org> | 2021-11-12 10:15:58 +0100 |
commit | 8c0c44c9d2f768a95beacd4605776cfe29c9bff6 (patch) | |
tree | d696c972ff06d1cf68f2499cd39b451ade0b6a8c | |
parent | c282ebd61200b0cb0830399c1c33514dbd129dfd (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.c | 65 | ||||
-rw-r--r-- | core/include/drivers/clk_dt.h | 17 | ||||
-rw-r--r-- | core/include/kernel/dt_driver.h | 63 | ||||
-rw-r--r-- | core/kernel/dt_driver.c | 11 | ||||
-rw-r--r-- | core/kernel/sub.mk | 1 |
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 |