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 TEE_Result (*get_of_device_func)(struct dt_pargs *parg, void *data, 112 void **out_device); 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 * @out_device: output device opaque reference upon support, for example 141 * a struct clk pointer for a clock driver. 142 143 * Return code: 144 * TEE_SUCCESS in case of success, 145 * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized 146 * TEE_ERROR_ITEM_NOT_FOUND if @prop_name does not match a property's name 147 * or @prop_idx does not match any index in @prop_name phandle list 148 * Any TEE_Result compliant code in case of error. 149 */ 150 TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name, 151 const void *fdt, int nodeoffset, 152 unsigned int prop_idx, 153 enum dt_driver_type type, 154 void **out_device); 155 156 /* 157 * dt_driver_device_from_parent - Return a device instance based on the parent. 158 * This is mainly used for the devices that are children of a controller 159 * such as I2C, SPI and so on. 160 * 161 * @fdt: FDT base address 162 * @nodeoffset: node offset in the FDT 163 * @type: Driver type 164 * @dout_device: output device opaque reference upon success, for example 165 * a struct i2c_dev pointer for a I2C bus driver 166 * 167 * Return code: 168 * TEE_SUCCESS in case of success, 169 * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized 170 * Any TEE_Result compliant code in case of error. 171 */ 172 TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset, 173 enum dt_driver_type type, 174 void **out_device); 175 176 /* 177 * dt_driver_device_from_node_idx_prop_phandle() - Same as 178 * dt_driver_device_from_node_idx_prop() but phandle is not the first 179 * cells in property @prop_name but is passed as an argument. 180 * 181 * This function is used for DT bindings as "interrupts" property where the 182 * property carries the interrupt information but not the interrupt controller 183 * phandle which is found in a specific property (here "interrupt-parent"). 184 */ 185 TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name, 186 const void *fdt, 187 int nodeoffs, 188 unsigned int prop_index, 189 enum dt_driver_type type, 190 uint32_t phandle, 191 void **out_device); 192 193 /* 194 * dt_driver_get_crypto() - Request crypto support for driver initialization 195 * 196 * Return TEE_SUCCESS if cryptography services are initialized, otherwise return 197 * TEE_ERROR_DEFER_DRIVER_INIT. 198 */ 199 TEE_Result dt_driver_get_crypto(void); 200 201 #ifdef CFG_DT 202 /* Inform DT driver probe sequence that core crypto support is initialized */ 203 void dt_driver_crypt_init_complete(void); 204 #else 205 static inline void dt_driver_crypt_init_complete(void) {} 206 #endif 207 208 /* 209 * Return driver provider reference from its node offset value in the FDT 210 */ 211 struct dt_driver_provider * 212 dt_driver_get_provider_by_node(int nodeoffset, enum dt_driver_type type); 213 214 /* 215 * Return driver provider reference from its phandle value in the FDT 216 */ 217 struct dt_driver_provider * 218 dt_driver_get_provider_by_phandle(uint32_t phandle, enum dt_driver_type type); 219 220 /* 221 * Return number cells used for phandle arguments by a driver provider 222 */ 223 unsigned int dt_driver_provider_cells(struct dt_driver_provider *prv); 224 225 /* 226 * dt_driver_probe_device_by_node - Probe matching driver to create a device 227 * from a FDT node 228 * 229 * @fdt: FDT base address 230 * @nodeoffset: Node byte offset from FDT base 231 * @type: Target driver to match or DT_DRIVER_ANY 232 * 233 * Read the dt_driver database. Compatible list is looked up in the order 234 * of the FDT "compatible" property list. @type can be used to probe only 235 * specific drivers. 236 * 237 */ 238 TEE_Result dt_driver_probe_device_by_node(const void *fdt, int nodeoffset, 239 enum dt_driver_type type); 240 241 /* 242 * Get cells count of a device node given its dt_driver type 243 * 244 * @fdt: FDT base address 245 * @nodeoffset: Node offset on the FDT for the device 246 * @type: One of the supported DT_DRIVER_* value. 247 * 248 * Return a positive cell count value (>= 0) or a negative FDT_ error code 249 */ 250 int fdt_get_dt_driver_cells(const void *fdt, int nodeoffset, 251 enum dt_driver_type type); 252 253 /* 254 * Called by bus like nodes to propose a node for dt_driver probing 255 * 256 * @fdt: FDT base address 257 * @nodeoffset: Node offset on the FDT for the device 258 */ 259 TEE_Result dt_driver_maybe_add_probe_node(const void *fdt, int nodeoffset); 260 261 #ifdef CFG_DT_DRIVER_EMBEDDED_TEST 262 /* 263 * Return TEE_ERROR_NOT_IMPLEMENTED if test are not implemented 264 * otherwise return TEE_ERROR_GENERIC if some test has failed 265 * otherwise return TEE_SUCCESS (tests succeed or skipped) 266 */ 267 TEE_Result dt_driver_test_status(void); 268 #else 269 static inline TEE_Result dt_driver_test_status(void) 270 { 271 return TEE_ERROR_NOT_IMPLEMENTED; 272 } 273 #endif 274 275 #endif /* __DT_DRIVER_H */ 276