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 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 * @consumer_node: Node of the consumer requesting this device
93 * @args_count: Count of cells for the device
94 * @args: Device consumer specifiers
95 */
96 struct dt_pargs {
97 const void *fdt;
98 int phandle_node;
99 int consumer_node;
100 int args_count;
101 uint32_t args[];
102 };
103
104 /*
105 * get_of_device_func - Callback function for returning a driver private
106 * instance based on a FDT phandle with possible arguments and the
107 * registered dt_driver private data reference.
108 *
109 * @parg: phandle argument(s) referencing the device in the FDT.
110 * @data: driver private data registered in struct dt_driver.
111 * @device_ref: output device reference upon success, e.g. a struct clk
112 * pointer for a clock driver.
113 *
114 * Return code:
115 * TEE_SUCCESS in case of success
116 * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized
117 * Any TEE_Result compliant code in case of error.
118 */
119 typedef TEE_Result (*get_of_device_func)(struct dt_pargs *parg, void *data,
120 void *device_ref);
121
122 /**
123 * dt_driver_register_provider - Register a driver provider
124 *
125 * @fdt: Device tree to work on
126 * @nodeoffset: Node offset in the FDT
127 * @get_of_device: Function to match the devicetree with a device instance
128 * @data: Data which will be passed to the @get_of_device callback
129 * @type: Driver type
130 *
131 * @get_of_device returns a void *. Driver provider is expected to
132 * include a shim helper to cast to device reference into provider driver
133 * target structure reference (e.g (struct clk *) for clock devices).
134 */
135 TEE_Result dt_driver_register_provider(const void *fdt, int nodeoffset,
136 get_of_device_func get_of_device,
137 void *data, enum dt_driver_type type);
138
139 /*
140 * dt_driver_device_from_node_idx_prop - Return a device instance based on a
141 * property name and FDT information
142 *
143 * @prop_name: DT property name, e.g. "clocks" for clock resources
144 * @fdt: FDT base address
145 * @nodeoffset: node offset in the FDT
146 * @prop_idx: index of the phandle data in the property
147 * @type: Driver type
148 * @device_ref: output device opaque reference upon support, for example
149 * a struct clk pointer for a clock driver.
150
151 * Return code:
152 * TEE_SUCCESS in case of success,
153 * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized
154 * TEE_ERROR_ITEM_NOT_FOUND if @prop_name does not match a property's name
155 * or @prop_idx does not match any index in @prop_name phandle list
156 * Any TEE_Result compliant code in case of error.
157 */
158 TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name,
159 const void *fdt, int nodeoffset,
160 unsigned int prop_idx,
161 enum dt_driver_type type,
162 void *device_ref);
163
164 /*
165 * dt_driver_device_from_parent - Return a device instance based on the parent.
166 * This is mainly used for the devices that are children of a controller
167 * such as I2C, SPI and so on.
168 *
169 * @fdt: FDT base address
170 * @nodeoffset: node offset in the FDT
171 * @type: Driver type
172 * @device_ref: output device opaque reference upon success, for example
173 * a struct i2c_dev pointer for a I2C bus driver
174 *
175 * Return code:
176 * TEE_SUCCESS in case of success,
177 * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized
178 * Any TEE_Result compliant code in case of error.
179 */
180 TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset,
181 enum dt_driver_type type,
182 void *device_ref);
183
184 /*
185 * dt_driver_device_from_node_idx_prop_phandle() - Same as
186 * dt_driver_device_from_node_idx_prop() but phandle is not the first
187 * cells in property @prop_name but is passed as an argument.
188 *
189 * This function is used for DT bindings as "interrupts" property where the
190 * property carries the interrupt information but not the interrupt controller
191 * phandle which is found in a specific property (here "interrupt-parent").
192 */
193 TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name,
194 const void *fdt,
195 int nodeoffs,
196 unsigned int prop_index,
197 enum dt_driver_type type,
198 uint32_t phandle,
199 void *device_ref);
200
201 /*
202 * dt_driver_get_crypto() - Request crypto support for driver initialization
203 *
204 * Return TEE_SUCCESS if cryptography services are initialized, otherwise return
205 * TEE_ERROR_DEFER_DRIVER_INIT.
206 */
207 TEE_Result dt_driver_get_crypto(void);
208
209 #ifdef CFG_DT
210 /* Inform DT driver probe sequence that core crypto support is initialized */
211 void dt_driver_crypt_init_complete(void);
212 #else
dt_driver_crypt_init_complete(void)213 static inline void dt_driver_crypt_init_complete(void) {}
214 #endif
215
216 /*
217 * Return driver provider reference from its node offset value in the FDT
218 */
219 struct dt_driver_provider *
220 dt_driver_get_provider_by_node(int nodeoffset, enum dt_driver_type type);
221
222 /*
223 * Return driver provider reference from its phandle value in the FDT
224 */
225 struct dt_driver_provider *
226 dt_driver_get_provider_by_phandle(uint32_t phandle, enum dt_driver_type type);
227
228 /*
229 * Return number cells used for phandle arguments by a driver provider
230 */
231 unsigned int dt_driver_provider_cells(struct dt_driver_provider *prv);
232
233 /*
234 * Return provider private data registered by dt_driver_register_provider()
235 */
236 void *dt_driver_provider_priv_data(struct dt_driver_provider *prv);
237
238 /*
239 * dt_driver_probe_device_by_node - Probe matching driver to create a device
240 * from a FDT node
241 *
242 * @fdt: FDT base address
243 * @nodeoffset: Node byte offset from FDT base
244 * @type: Target driver to match or DT_DRIVER_ANY
245 *
246 * Read the dt_driver database. Compatible list is looked up in the order
247 * of the FDT "compatible" property list. @type can be used to probe only
248 * specific drivers.
249 *
250 */
251 TEE_Result dt_driver_probe_device_by_node(const void *fdt, int nodeoffset,
252 enum dt_driver_type type);
253
254 /*
255 * Get cells count of a device node given its dt_driver type
256 *
257 * @fdt: FDT base address
258 * @nodeoffset: Node offset on the FDT for the device
259 * @type: One of the supported DT_DRIVER_* value.
260 *
261 * Return a positive cell count value (>= 0) or a negative FDT_ error code
262 */
263 int fdt_get_dt_driver_cells(const void *fdt, int nodeoffset,
264 enum dt_driver_type type);
265
266 /*
267 * Called by bus like nodes to propose a node for dt_driver probing
268 *
269 * @fdt: FDT base address
270 * @nodeoffset: Node offset on the FDT for the device
271 */
272 TEE_Result dt_driver_maybe_add_probe_node(const void *fdt, int nodeoffset);
273
274 #ifdef CFG_DT_DRIVER_EMBEDDED_TEST
275 /*
276 * Return TEE_ERROR_NOT_IMPLEMENTED if test are not implemented
277 * otherwise return TEE_ERROR_GENERIC if some test has failed
278 * otherwise return TEE_SUCCESS (tests succeed or skipped)
279 */
280 TEE_Result dt_driver_test_status(void);
281 #else
dt_driver_test_status(void)282 static inline TEE_Result dt_driver_test_status(void)
283 {
284 return TEE_ERROR_NOT_IMPLEMENTED;
285 }
286 #endif
287 #endif /* __KERNEL_DT_DRIVER_H */
288