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