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