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