1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3 * Copyright (c) 2021, Bootlin
4 */
5
6 #ifndef __DRIVERS_CLK_DT_H
7 #define __DRIVERS_CLK_DT_H
8
9 #include <kernel/dt.h>
10 #include <kernel/dt_driver.h>
11 #include <scattered_array.h>
12 #include <stdint.h>
13 #include <sys/queue.h>
14
15 /**
16 * CLK_DT_DECLARE - Declare a clock driver
17 * @__name: Clock driver name
18 * @__compat: Compatible string
19 * @__probe: Clock probe function
20 */
21 #define CLK_DT_DECLARE(__name, __compat, __probe) \
22 static const struct dt_device_match __name ## _match_table[] = { \
23 { .compatible = __compat }, \
24 { } \
25 }; \
26 DEFINE_DT_DRIVER(__name ## _dt_driver) = { \
27 .name = # __name, \
28 .type = DT_DRIVER_CLK, \
29 .match_table = __name ## _match_table, \
30 .probe = __probe, \
31 }
32
33 /**
34 * clk_dt_get_by_index - Get a clock at a specific index in "clocks" property
35 *
36 * @fdt: Device tree to work on
37 * @nodeoffset: Node offset of the subnode containing a clock property
38 * @clk_idx: Clock index to get
39 * @clk: Output clock reference upon success
40 *
41 * Return TEE_SUCCESS in case of success
42 * Return TEE_ERROR_DEFER_DRIVER_INIT if clock is not initialized
43 * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not provide a clock reference
44 * Return any other TEE_Result compliant code in case of error
45 */
46 TEE_Result clk_dt_get_by_index(const void *fdt, int nodeoffset,
47 unsigned int clk_idx, struct clk **clk);
48
49 /**
50 * clk_dt_get_by_name - Get a clock matching a name in "clock-names" property
51 *
52 * @fdt: Device tree to work on
53 * @nodeoffset: Node offset of the subnode containing a clock property
54 * @name: Clock name to get
55 * @clk: Output clock reference upon success
56 *
57 * Return TEE_SUCCESS in case of success
58 * Return TEE_ERROR_DEFER_DRIVER_INIT if clock is not initialized
59 * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not provide a clock reference
60 * Return any other TEE_Result compliant code in case of error
61 */
62 TEE_Result clk_dt_get_by_name(const void *fdt, int nodeoffset,
63 const char *name, struct clk **clk);
64
65 /**
66 * clk_dt_get_func - Typedef of function to get clock from devicetree properties
67 *
68 * @args: Pointer to devicetree description of the clock to parse
69 * @data: Pointer to data given at clk_dt_register_clk_provider() call
70 * @res: Output result code of the operation:
71 * TEE_SUCCESS in case of success
72 * TEE_ERROR_DEFER_DRIVER_INIT if clock is not initialized
73 * Any TEE_Result compliant code in case of error.
74 *
75 * Returns a clk struct pointer pointing to a clock matching the devicetree
76 * description or NULL if invalid description in which case @res provides the
77 * error code.
78 */
79 typedef struct clk *(*clk_dt_get_func)(struct dt_driver_phandle_args *args,
80 void *data, TEE_Result *res);
81
82 /**
83 * clk_dt_register_clk_provider - Register a clock provider
84 *
85 * @fdt: Device tree to work on
86 * @nodeoffset: Node offset of the clock
87 * @get_dt_clk: Callback to match the devicetree clock with a clock struct
88 * @data: Data which will be passed to the get_dt_clk callback
89 * Returns TEE_Result value
90 */
91 static inline
92 TEE_Result clk_dt_register_clk_provider(const void *fdt, int nodeoffset,
93 clk_dt_get_func get_dt_clk, void *data)
94 {
95 return dt_driver_register_provider(fdt, nodeoffset,
96 (get_of_device_func)get_dt_clk,
97 data, DT_DRIVER_CLK);
98 }
99
100 /**
101 * clk_dt_get_simple_clk: simple clock matching function for single clock
102 * providers
103 */
104 static inline
clk_dt_get_simple_clk(struct dt_driver_phandle_args * args __unused,void * data,TEE_Result * res)105 struct clk *clk_dt_get_simple_clk(struct dt_driver_phandle_args *args __unused,
106 void *data, TEE_Result *res)
107 {
108 *res = TEE_SUCCESS;
109
110 return data;
111 }
112
113 #endif /* __DRIVERS_CLK_DT_H */
114