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