xref: /optee_os/core/include/kernel/dt_driver.h (revision 17a66904a791447da1356331f01e7c1ca25329be)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2021, Linaro Limited
4  * Copyright (c) 2021, Bootlin
5  * Copyright (c) 2021, STMicroelectronics
6  */
7 
8 #ifndef __KERNEL_DT_DRIVER_H
9 #define __KERNEL_DT_DRIVER_H
10 
11 #include <kernel/dt.h>
12 #include <stdint.h>
13 #include <sys/queue.h>
14 #include <tee_api_types.h>
15 
16 /*
17  * Type indentifiers for registered device drivers consumer can query
18  *
19  * DT_DRIVER_NOTYPE Generic type for when no generic FDT parsing is supported
20  * DT_DRIVER_UART   UART driver currently designed for console means
21  * DT_DRIVER_CLK    Clock controller using generic clock DT bindings
22  * DT_DRIVER_RSTCTRL Reset controller using generic reset DT bindings
23  * DT_DRIVER_I2C    I2C bus controller using generic I2C bus DT bindings
24  * DT_DRIVER_GPIO   GPIO controller using generic GPIO DT bindings
25  * DT_DRIVER_PINCTRL Pin controller using generic reset DT bindings
26  * DT_DRIVER_INTERRUPT Interrupt controller using generic DT bindings
27  * DT_DRIVER_REGULATOR Voltage regulator controller using generic DT bindings
28  */
29 enum dt_driver_type {
30 	DT_DRIVER_NOTYPE,
31 	DT_DRIVER_UART,
32 	DT_DRIVER_CLK,
33 	DT_DRIVER_RSTCTRL,
34 	DT_DRIVER_I2C,
35 	DT_DRIVER_GPIO,
36 	DT_DRIVER_PINCTRL,
37 	DT_DRIVER_INTERRUPT,
38 	DT_DRIVER_REGULATOR,
39 };
40 
41 /*
42  * dt_driver_probe_func - Callback probe function for a driver.
43  *
44  * @fdt: FDT base address
45  * @nodeoffset: Offset of the node in the FDT
46  * @compat_data: Data registered for the compatible that probed the device
47  *
48  * Return TEE_SUCCESS on successful probe,
49  *	TEE_ERROR_DEFER_DRIVER_INIT if probe must be deferred
50  *	TEE_ERROR_ITEM_NOT_FOUND when no driver matched node's compatible string
51  *	Any other TEE_ERROR_* compliant code.
52  */
53 typedef TEE_Result (*dt_driver_probe_func)(const void *fdt, int nodeoffset,
54 					   const void *compat_data);
55 
56 /*
57  * Driver instance registered to be probed on compatible node found in the DT.
58  *
59  * @name: Driver name
60  * @type: Drive type
61  * @match_table: Compatible matching identifiers, null terminated
62  * @driver: Driver private reference or NULL
63  * @probe: Probe callback (see dt_driver_probe_func) or NULL
64  */
65 struct dt_driver {
66 	const char *name;
67 	enum dt_driver_type type;
68 	const struct dt_device_match *match_table; /* null-terminated */
69 	const void *driver;
70 	TEE_Result (*probe)(const void *fdt, int node, const void *compat_data);
71 };
72 
73 #define DEFINE_DT_DRIVER(name) \
74 		SCATTERED_ARRAY_DEFINE_PG_ITEM(dt_drivers, struct dt_driver)
75 
76 #define for_each_dt_driver(drv) \
77 	for (drv = SCATTERED_ARRAY_BEGIN(dt_drivers, struct dt_driver); \
78 	     drv < SCATTERED_ARRAY_END(dt_drivers, struct dt_driver); \
79 	     drv++)
80 
81 /* Opaque reference to DT driver device provider instance */
82 struct dt_driver_provider;
83 
84 /**
85  * struct dt_pargs - Devicetree phandle arguments
86  * @fdt: Device-tree to work on
87  * @phandle_node: Node pointed by the specifier phandle
88  * @args_count: Count of cells for the device
89  * @args: Device consumer specifiers
90  */
91 struct dt_pargs {
92 	const void *fdt;
93 	int phandle_node;
94 	int args_count;
95 	uint32_t args[];
96 };
97 
98 /*
99  * get_of_device_func - Callback function for returning a driver private
100  *	instance based on a FDT phandle with possible arguments and the
101  *	registered dt_driver private data reference.
102  *
103  * @parg: phandle argument(s) referencing the device in the FDT.
104  * @data: driver private data registered in struct dt_driver.
105  * @out_device: output device reference upon success, e.g. a struct clk
106  *	pointer for a clock driver.
107  *
108  * Return code:
109  * TEE_SUCCESS in case of success
110  * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized
111  * Any TEE_Result compliant code in case of error.
112  */
113 typedef TEE_Result (*get_of_device_func)(struct dt_pargs *parg, void *data,
114 					 void **out_device);
115 
116 /**
117  * dt_driver_register_provider - Register a driver provider
118  *
119  * @fdt: Device tree to work on
120  * @nodeoffset: Node offset in the FDT
121  * @get_of_device: Function to match the devicetree with a device instance
122  * @data: Data which will be passed to the @get_of_device callback
123  * @type: Driver type
124  *
125  * @get_of_device returns a void *. Driver provider is expected to
126  * include a shim helper to cast to device reference into provider driver
127  * target structure reference (e.g (struct clk *) for clock devices).
128  */
129 TEE_Result dt_driver_register_provider(const void *fdt, int nodeoffset,
130 				       get_of_device_func get_of_device,
131 				       void *data, enum dt_driver_type type);
132 
133 /*
134  * dt_driver_device_from_node_idx_prop - Return a device instance based on a
135  *	property name and FDT information
136  *
137  * @prop_name: DT property name, e.g. "clocks" for clock resources
138  * @fdt: FDT base address
139  * @nodeoffset: node offset in the FDT
140  * @prop_idx: index of the phandle data in the property
141  * @type: Driver type
142  * @out_device: output device opaque reference upon support, for example
143  *	a struct clk pointer for a clock driver.
144 
145  * Return code:
146  * TEE_SUCCESS in case of success,
147  * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized
148  * TEE_ERROR_ITEM_NOT_FOUND if @prop_name does not match a property's name
149  *	or @prop_idx does not match any index in @prop_name phandle list
150  * Any TEE_Result compliant code in case of error.
151  */
152 TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name,
153 					       const void *fdt, int nodeoffset,
154 					       unsigned int prop_idx,
155 					       enum dt_driver_type type,
156 					       void **out_device);
157 
158 /*
159  * dt_driver_device_from_parent - Return a device instance based on the parent.
160  *	This is mainly used for the devices that are children of a controller
161  *	such as I2C, SPI and so on.
162  *
163  * @fdt: FDT base address
164  * @nodeoffset: node offset in the FDT
165  * @type: Driver type
166  * @out_device: output device opaque reference upon success, for example
167  *	a struct i2c_dev pointer for a I2C bus driver
168  *
169  * Return code:
170  * TEE_SUCCESS in case of success,
171  * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized
172  * Any TEE_Result compliant code in case of error.
173  */
174 TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset,
175 					enum dt_driver_type type,
176 					void **out_device);
177 
178 /*
179  * dt_driver_device_from_node_idx_prop_phandle() - Same as
180  *	dt_driver_device_from_node_idx_prop() but phandle is not the first
181  *	cells in property @prop_name but is passed as an argument.
182  *
183  * This function is used for DT bindings as "interrupts" property where the
184  * property carries the interrupt information but not the interrupt controller
185  * phandle which is found in a specific property (here "interrupt-parent").
186  */
187 TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name,
188 						       const void *fdt,
189 						       int nodeoffs,
190 						       unsigned int prop_index,
191 						       enum dt_driver_type type,
192 						       uint32_t phandle,
193 						       void **out_device);
194 
195 /*
196  * dt_driver_get_crypto() - Request crypto support for driver initialization
197  *
198  * Return TEE_SUCCESS if cryptography services are initialized, otherwise return
199  * TEE_ERROR_DEFER_DRIVER_INIT.
200  */
201 TEE_Result dt_driver_get_crypto(void);
202 
203 #ifdef CFG_DT
204 /* Inform DT driver probe sequence that core crypto support is initialized */
205 void dt_driver_crypt_init_complete(void);
206 #else
207 static inline void dt_driver_crypt_init_complete(void) {}
208 #endif
209 
210 /*
211  * Return driver provider reference from its node offset value in the FDT
212  */
213 struct dt_driver_provider *
214 dt_driver_get_provider_by_node(int nodeoffset, enum dt_driver_type type);
215 
216 /*
217  * Return driver provider reference from its phandle value in the FDT
218  */
219 struct dt_driver_provider *
220 dt_driver_get_provider_by_phandle(uint32_t phandle, enum dt_driver_type type);
221 
222 /*
223  * Return number cells used for phandle arguments by a driver provider
224  */
225 unsigned int dt_driver_provider_cells(struct dt_driver_provider *prv);
226 
227 /*
228  * Return provider private data registered by dt_driver_register_provider()
229  */
230 void *dt_driver_provider_priv_data(struct dt_driver_provider *prv);
231 
232 /*
233  * dt_driver_probe_device_by_node - Probe matching driver to create a device
234  *	from a FDT node
235  *
236  * @fdt: FDT base address
237  * @nodeoffset: Node byte offset from FDT base
238  * @type: Target driver to match or DT_DRIVER_ANY
239  *
240  * Read the dt_driver database. Compatible list is looked up in the order
241  * of the FDT "compatible" property list. @type can be used to probe only
242  * specific drivers.
243  *
244  */
245 TEE_Result dt_driver_probe_device_by_node(const void *fdt, int nodeoffset,
246 					  enum dt_driver_type type);
247 
248 /*
249  * Get cells count of a device node given its dt_driver type
250  *
251  * @fdt: FDT base address
252  * @nodeoffset: Node offset on the FDT for the device
253  * @type: One of the supported DT_DRIVER_* value.
254  *
255  * Return a positive cell count value (>= 0) or a negative FDT_ error code
256  */
257 int fdt_get_dt_driver_cells(const void *fdt, int nodeoffset,
258 			    enum dt_driver_type type);
259 
260 /*
261  * Called by bus like nodes to propose a node for dt_driver probing
262  *
263  * @fdt: FDT base address
264  * @nodeoffset: Node offset on the FDT for the device
265  */
266 TEE_Result dt_driver_maybe_add_probe_node(const void *fdt, int nodeoffset);
267 
268 #ifdef CFG_DT_DRIVER_EMBEDDED_TEST
269 /*
270  * Return TEE_ERROR_NOT_IMPLEMENTED if test are not implemented
271  * otherwise return TEE_ERROR_GENERIC if some test has failed
272  * otherwise return TEE_SUCCESS (tests succeed or skipped)
273  */
274 TEE_Result dt_driver_test_status(void);
275 #else
276 static inline TEE_Result dt_driver_test_status(void)
277 {
278 	return TEE_ERROR_NOT_IMPLEMENTED;
279 }
280 #endif
281 #endif /* __KERNEL_DT_DRIVER_H */
282