1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * Copyright (c) 2016-2021, Linaro Limited 4 */ 5 6 #ifndef __KERNEL_DT_H 7 #define __KERNEL_DT_H 8 9 #include <compiler.h> 10 #include <kernel/interrupt.h> 11 #include <kernel/panic.h> 12 #include <scattered_array.h> 13 #include <stdint.h> 14 #include <tee_api_types.h> 15 #include <types_ext.h> 16 #include <util.h> 17 18 /* 19 * Bitfield to reflect status and secure-status values ("okay", "disabled" 20 * or not present) 21 */ 22 #define DT_STATUS_DISABLED U(0) 23 #define DT_STATUS_OK_NSEC BIT(0) 24 #define DT_STATUS_OK_SEC BIT(1) 25 26 #define DT_INFO_INVALID_REG ((paddr_t)-1) 27 #define DT_INFO_INVALID_REG_SIZE ((size_t)-1) 28 #define DT_INFO_INVALID_CLOCK -1 29 #define DT_INFO_INVALID_RESET -1 30 #define DT_INFO_INVALID_INTERRUPT -1 31 32 /* 33 * @status: Bit mask for DT_STATUS_* 34 * @reg: Device register physical base address or DT_INFO_INVALID_REG 35 * @reg_size: Device register size or DT_INFO_INVALID_REG_SIZE 36 * @clock: Device identifier (positive value) or DT_INFO_INVALID_CLOCK 37 * @reset: Device reset identifier (positive value) or DT_INFO_INVALID_CLOCK 38 * @interrupt: Device interrupt identifier (positive value) or 39 * DT_INFO_INVALID_INTERRUPT 40 * @type: IRQ_TYPE_* value parsed from interrupts properties or IRQ_TYPE_NONE if 41 * not present 42 * @prio: interrupt priority parsed from interrupts properties or 0 if not 43 * present 44 */ 45 struct dt_node_info { 46 unsigned int status; 47 paddr_t reg; 48 size_t reg_size; 49 int clock; 50 int reset; 51 int interrupt; 52 uint32_t type; 53 uint32_t prio; 54 }; 55 56 /* 57 * DT-aware drivers 58 */ 59 60 struct dt_device_match { 61 const char *compatible; 62 const void *compat_data; 63 }; 64 65 /* 66 * DT_MAP_AUTO: Uses status properties from device tree to determine mapping. 67 * DT_MAP_SECURE: Force mapping for device to be secure. 68 * DT_MAP_NON_SECURE: Force mapping for device to be non-secure. 69 */ 70 enum dt_map_dev_directive { 71 DT_MAP_AUTO, 72 DT_MAP_SECURE, 73 DT_MAP_NON_SECURE 74 }; 75 76 /* 77 * struct dt_descriptor - Descriptor of the device tree 78 * @blob: Pointer to the device tree binary 79 * @frag_id: Used ID of fragments for device tree overlay 80 */ 81 struct dt_descriptor { 82 void *blob; 83 #ifdef _CFG_USE_DTB_OVERLAY 84 int frag_id; 85 #endif 86 }; 87 88 extern uint8_t embedded_secure_dtb[]; 89 90 /* 91 * dt_getprop_as_number() - get a DT property a unsigned number 92 * @fdt: DT base address 93 * @nodeoffset: node offset 94 * @name: property string name 95 * @num: output number read 96 * Return 0 on success and a negative FDT error value on error 97 * 98 * The size of the property determines if it is read as an unsigned 32-bit 99 * or 64-bit integer. 100 */ 101 int dt_getprop_as_number(const void *fdt, int nodeoffset, const char *name, 102 uint64_t *num); 103 104 #ifdef CFG_DT 105 /* 106 * Find a driver that is suitable for the given DT node, that is, with 107 * a matching "compatible" property. 108 * 109 * @fdt: pointer to the device tree 110 * @offs: node offset 111 */ 112 const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs); 113 114 /* 115 * Map a device into secure or non-secure memory and return the base VA and 116 * the mapping size. The mapping is done with type MEM_AREA_IO_SEC or 117 * MEM_AREA_IO_NSEC, depending on the device status. 118 * If the mapping already exists, the function simply returns the @vbase and 119 * @size information. 120 * 121 * @offs is the offset of the node that describes the device in @fdt. 122 * @base receives the base virtual address corresponding to the base physical 123 * address of the "reg" property 124 * @size receives the size of the mapping 125 * @mapping what kind of mapping is done for memory. 126 * 127 * Returns 0 on success or -1 in case of error. 128 */ 129 int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size, 130 enum dt_map_dev_directive mapping); 131 132 /* 133 * Check whether the node at @offs contains the property with propname or not. 134 * 135 * @offs is the offset of the node that describes the device in @fdt. 136 * @propname is the property that need to check 137 * 138 * Returns true on success or false if no propname. 139 */ 140 bool dt_have_prop(const void *fdt, int offs, const char *propname); 141 142 /* 143 * Modify or add "status" property to "disabled" 144 * 145 * @fdt reference to the Device Tree 146 * @node is the node offset to modify 147 * 148 * Returns 0 on success or -1 on failure 149 */ 150 int dt_disable_status(void *fdt, int node); 151 152 /* 153 * Force secure-status = "okay" and status="disabled" for the target node. 154 * 155 * @fdt reference to the Device Tree 156 * @node is the node offset to modify 157 * 158 * Returns 0 on success or -1 on failure 159 */ 160 int dt_enable_secure_status(void *fdt, int node); 161 162 /* 163 * FDT manipulation functions, not provided by <libfdt.h> 164 */ 165 166 /* 167 * Return the base address for the "reg" property of the specified node or 168 * (paddr_t)-1 in case of error 169 */ 170 paddr_t fdt_reg_base_address(const void *fdt, int offs); 171 172 /* 173 * Return the reg size for the reg property of the specified node or -1 in case 174 * of error 175 */ 176 size_t fdt_reg_size(const void *fdt, int offs); 177 178 /* 179 * Read the status and secure-status properties into a bitfield. 180 * Return -1 on failure, DT_STATUS_DISABLED if the node is disabled, 181 * otherwise return a combination of DT_STATUS_OK_NSEC and DT_STATUS_OK_SEC. 182 */ 183 int fdt_get_status(const void *fdt, int offs); 184 185 /* 186 * fdt_fill_device_info - Get generic device info from a node 187 * 188 * This function fills the generic information from a given node. 189 * Currently supports a single base register, a single clock, 190 * a single reset ID line and a single interrupt ID. 191 * Default DT_INFO_* macros are used when the relate property is not found. 192 */ 193 void fdt_fill_device_info(const void *fdt, struct dt_node_info *info, 194 int node); 195 /* 196 * Read cells from a given property of the given node. Any number of 32-bit 197 * cells of the property can be read. Returns 0 on success, or a negative 198 * FDT error value otherwise. 199 */ 200 int fdt_read_uint32_array(const void *fdt, int node, const char *prop_name, 201 uint32_t *array, size_t count); 202 203 /* 204 * Read one cell from a given multi-value property of the given node. 205 * Returns 0 on success, or a negative FDT error value otherwise. 206 */ 207 int fdt_read_uint32_index(const void *fdt, int node, const char *prop_name, 208 int index, uint32_t *value); 209 210 /* 211 * Read one cell from a given property of the given node. 212 * Returns 0 on success, or a negative FDT error value otherwise. 213 */ 214 int fdt_read_uint32(const void *fdt, int node, const char *prop_name, 215 uint32_t *value); 216 217 /* 218 * Read one cell from a property of a cell or default to a given value 219 * Returns the 32bit cell value or @dflt_value on failure. 220 */ 221 uint32_t fdt_read_uint32_default(const void *fdt, int node, 222 const char *prop_name, uint32_t dflt_value); 223 224 /* 225 * This function fills reg node info (base & size) with an index. 226 * 227 * Returns 0 on success and a negative FDT error code on failure. 228 */ 229 int fdt_get_reg_props_by_index(const void *fdt, int node, int index, 230 paddr_t *base, size_t *size); 231 232 /* 233 * This function fills reg node info (base & size) with an index found by 234 * checking the reg-names node. 235 * 236 * Returns 0 on success and a negative FDT error code on failure. 237 */ 238 int fdt_get_reg_props_by_name(const void *fdt, int node, const char *name, 239 paddr_t *base, size_t *size); 240 241 /* Returns embedded DTB if present, then external DTB if found, then NULL */ 242 void *get_dt(void); 243 244 /* 245 * get_secure_dt() - returns secure DTB for drivers 246 * 247 * Returns device tree that is considered secure for drivers to use. 248 * 249 * 1. Returns embedded DTB if available, 250 * 2. Secure external DTB if available, 251 * 3. If neither then NULL 252 */ 253 void *get_secure_dt(void); 254 255 /* Returns embedded DTB location if present, otherwise NULL */ 256 void *get_embedded_dt(void); 257 258 /* Returns true if passed DTB is same as Embedded DTB, otherwise false */ 259 static inline bool is_embedded_dt(void *fdt) 260 { 261 return fdt && fdt == get_embedded_dt(); 262 } 263 264 /* Returns DTB descriptor of the external DTB if present, otherwise NULL */ 265 struct dt_descriptor *get_external_dt_desc(void); 266 267 /* 268 * init_external_dt() - Initialize the external DTB located at given address. 269 * @phys_dt: Physical address where the external DTB located. 270 * @dt_sz: Maximum size of the external DTB. 271 * 272 * Initialize the external DTB. 273 * 274 * 1. Add MMU mapping of the external DTB, 275 * 2. Initialize device tree overlay 276 */ 277 void init_external_dt(unsigned long phys_dt, size_t dt_sz); 278 279 /* Returns external DTB if present, otherwise NULL */ 280 void *get_external_dt(void); 281 282 /* 283 * add_dt_path_subnode() - Add new child node into a parent node. 284 * @dt: Pointer to a device tree descriptor which has DTB. 285 * @path: Path to the parent node. 286 * @subnode: Name of the child node. 287 * 288 * Returns the offset of the child node in DTB on success or a negative libfdt 289 * error number. 290 */ 291 int add_dt_path_subnode(struct dt_descriptor *dt, const char *path, 292 const char *subnode); 293 294 /* 295 * add_res_mem_dt_node() - Create "reserved-memory" parent and child nodes. 296 * @dt: Pointer to a device tree descriptor which has DTB. 297 * @name: Name of the child node. 298 * @pa: Physical address of specific reserved memory region. 299 * @size: Size of specific reserved memory region. 300 * 301 * Returns 0 if succeeds, otherwise a negative libfdt error number. 302 */ 303 int add_res_mem_dt_node(struct dt_descriptor *dt, const char *name, 304 paddr_t pa, size_t size); 305 306 #else /* !CFG_DT */ 307 308 static inline const struct dt_driver *dt_find_compatible_driver( 309 const void *fdt __unused, 310 int offs __unused) 311 { 312 return NULL; 313 } 314 315 static inline int dt_map_dev(const void *fdt __unused, int offs __unused, 316 vaddr_t *vbase __unused, size_t *size __unused, 317 enum dt_map_dev_directive mapping __unused) 318 { 319 return -1; 320 } 321 322 static inline paddr_t fdt_reg_base_address(const void *fdt __unused, 323 int offs __unused) 324 { 325 return (paddr_t)-1; 326 } 327 328 static inline size_t fdt_reg_size(const void *fdt __unused, 329 int offs __unused) 330 { 331 return (size_t)-1; 332 } 333 334 static inline int fdt_get_status(const void *fdt __unused, int offs __unused) 335 { 336 return -1; 337 } 338 339 __noreturn 340 static inline void fdt_fill_device_info(const void *fdt __unused, 341 struct dt_node_info *info __unused, 342 int node __unused) 343 { 344 panic(); 345 } 346 347 static inline int fdt_read_uint32_array(const void *fdt __unused, 348 int node __unused, 349 const char *prop_name __unused, 350 uint32_t *array __unused, 351 size_t count __unused) 352 { 353 return -1; 354 } 355 356 static inline int fdt_read_uint32(const void *fdt __unused, 357 int node __unused, 358 const char *prop_name __unused, 359 uint32_t *value __unused) 360 { 361 return -1; 362 } 363 364 static inline uint32_t fdt_read_uint32_default(const void *fdt __unused, 365 int node __unused, 366 const char *prop_name __unused, 367 uint32_t dflt_value __unused) 368 { 369 return dflt_value; 370 } 371 372 static inline int fdt_read_uint32_index(const void *fdt __unused, 373 int node __unused, 374 const char *prop_name __unused, 375 int index __unused, 376 uint32_t *value __unused) 377 { 378 return -1; 379 } 380 381 static inline int fdt_get_reg_props_by_index(const void *fdt __unused, 382 int node __unused, 383 int index __unused, 384 paddr_t *base __unused, 385 size_t *size __unused) 386 { 387 return -1; 388 } 389 390 static inline int fdt_get_reg_props_by_name(const void *fdt __unused, 391 int node __unused, 392 const char *name __unused, 393 paddr_t *base __unused, 394 size_t *size __unused) 395 { 396 return -1; 397 } 398 399 static inline void *get_dt(void) 400 { 401 return NULL; 402 } 403 404 static inline void *get_secure_dt(void) 405 { 406 return NULL; 407 } 408 409 static inline void *get_embedded_dt(void) 410 { 411 return NULL; 412 } 413 414 static inline bool is_embedded_dt(void *fdt __unused) 415 { 416 return false; 417 } 418 419 static inline struct dt_descriptor *get_external_dt_desc(void) 420 { 421 return NULL; 422 } 423 424 static inline void init_external_dt(unsigned long phys_dt __unused, 425 size_t dt_sz __unused) 426 { 427 } 428 429 static inline void *get_external_dt(void) 430 { 431 return NULL; 432 } 433 434 static inline int add_dt_path_subnode(struct dt_descriptor *dt __unused, 435 const char *path __unused, 436 const char *subnode __unused) 437 { 438 return -1; 439 } 440 441 static inline int add_res_mem_dt_node(struct dt_descriptor *dt __unused, 442 const char *name __unused, 443 paddr_t pa __unused, 444 size_t size __unused) 445 { 446 return -1; 447 } 448 449 #endif /* !CFG_DT */ 450 #endif /* __KERNEL_DT_H */ 451