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