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