xref: /optee_os/core/include/drivers/clk_dt.h (revision f8c1dacbeef9d2a7d4f7af7bf905de198e3587bb)
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 <drivers/clk.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  * @clk: Output clock reference upon success
71  */
72 typedef TEE_Result (*clk_dt_get_func)(struct dt_pargs *args, void *data,
73 				      struct clk **out_clk);
74 
75 /**
76  * clk_dt_register_clk_provider() - Register a clock provider
77  *
78  * @fdt: Device tree to work on
79  * @nodeoffset: Node offset of the clock
80  * @func: Callback to match the devicetree clock with a clock struct
81  * @data: Data which will be passed to the get_dt_clk callback
82  * Returns TEE_Result value
83  */
clk_dt_register_clk_provider(const void * fdt,int nodeoffset,clk_dt_get_func func,void * data)84 static inline TEE_Result clk_dt_register_clk_provider(const void *fdt,
85 						      int nodeoffset,
86 						      clk_dt_get_func func,
87 						      void *data)
88 {
89 	return dt_driver_register_provider(fdt, nodeoffset,
90 					   (get_of_device_func)func, data,
91 					   DT_DRIVER_CLK);
92 }
93 
94 /**
95  * clk_dt_get_simple_clk() - Simple clock matching function for single clock
96  * providers
97  *
98  * @args: Unused argument as there is no description to parse
99  * @data: Pointer to data given at clk_dt_register_clk_provider() call
100  * @out_clk: Output clock reference filled with @data
101  */
clk_dt_get_simple_clk(struct dt_pargs * args __unused,void * data,struct clk ** out_clk)102 static inline TEE_Result clk_dt_get_simple_clk(struct dt_pargs *args __unused,
103 					       void *data, struct clk **out_clk)
104 {
105 	*out_clk = data;
106 
107 	return TEE_SUCCESS;
108 }
109 
110 #endif /* __DRIVERS_CLK_DT_H */
111