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 any other TEE_Result compliant code in case of error
44  */
45 TEE_Result clk_dt_get_by_index(const void *fdt, int nodeoffset,
46 			       unsigned int clk_idx, struct clk **clk);
47 
48 /**
49  * clk_dt_get_by_name - Get a clock matching a name in "clock-names" property
50  *
51  * @fdt: Device tree to work on
52  * @nodeoffset: Node offset of the subnode containing a clock property
53  * @name: Clock name to get
54  * @clk: Output clock reference upon success
55  *
56  * Return TEE_SUCCESS in case of success
57  * Return TEE_ERROR_DEFER_DRIVER_INIT if clock is not initialized
58  * Return any other TEE_Result compliant code in case of error
59  */
60 TEE_Result clk_dt_get_by_name(const void *fdt, int nodeoffset,
61 			      const char *name, struct clk **clk);
62 
63 /**
64  * clk_dt_get_func - Typedef of function to get clock from devicetree properties
65  *
66  * @args: Pointer to devicetree description of the clock to parse
67  * @data: Pointer to data given at clk_dt_register_clk_provider() call
68  * @res: Output result code of the operation:
69  *	TEE_SUCCESS in case of success
70  *	TEE_ERROR_DEFER_DRIVER_INIT if clock is not initialized
71  *	Any TEE_Result compliant code in case of error.
72  *
73  * Returns a clk struct pointer pointing to a clock matching the devicetree
74  * description or NULL if invalid description in which case @res provides the
75  * error code.
76  */
77 typedef struct clk *(*clk_dt_get_func)(struct dt_driver_phandle_args *args,
78 				       void *data, TEE_Result *res);
79 
80 /**
81  * clk_dt_register_clk_provider - Register a clock provider
82  *
83  * @fdt: Device tree to work on
84  * @nodeoffset: Node offset of the clock
85  * @get_dt_clk: Callback to match the devicetree clock with a clock struct
86  * @data: Data which will be passed to the get_dt_clk callback
87  * Returns TEE_Result value
88  */
89 static inline
90 TEE_Result clk_dt_register_clk_provider(const void *fdt, int nodeoffset,
91 					clk_dt_get_func get_dt_clk, void *data)
92 {
93 	return dt_driver_register_provider(fdt, nodeoffset,
94 					   (get_of_device_func)get_dt_clk,
95 					   data, DT_DRIVER_CLK);
96 }
97 
98 /**
99  * clk_dt_get_simple_clk: simple clock matching function for single clock
100  * providers
101  */
102 static inline
clk_dt_get_simple_clk(struct dt_driver_phandle_args * args __unused,void * data,TEE_Result * res)103 struct clk *clk_dt_get_simple_clk(struct dt_driver_phandle_args *args __unused,
104 				  void *data, TEE_Result *res)
105 {
106 	*res = TEE_SUCCESS;
107 
108 	return data;
109 }
110 
111 #endif /* __DRIVERS_CLK_DT_H */
112