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