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