1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * Copyright (c) 2016, Linaro Limited 4 * All rights reserved. 5 */ 6 7 #ifndef KERNEL_DT_H 8 #define KERNEL_DT_H 9 10 #include <compiler.h> 11 #include <stdint.h> 12 #include <types_ext.h> 13 #include <util.h> 14 15 /* 16 * Bitfield to reflect status and secure-status values ("okay", "disabled" 17 * or not present) 18 */ 19 #define DT_STATUS_DISABLED 0 20 #define DT_STATUS_OK_NSEC BIT(0) 21 #define DT_STATUS_OK_SEC BIT(1) 22 23 #if defined(CFG_DT) 24 25 /* 26 * DT-aware drivers 27 */ 28 29 struct dt_device_match { 30 const char *compatible; 31 }; 32 33 struct dt_driver { 34 const char *name; 35 const struct dt_device_match *match_table; /* null-terminated */ 36 const void *driver; 37 }; 38 39 #define __dt_driver __section(".rodata.dtdrv") 40 41 /* 42 * Find a driver that is suitable for the given DT node, that is, with 43 * a matching "compatible" property. 44 * 45 * @fdt: pointer to the device tree 46 * @offs: node offset 47 */ 48 const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs); 49 50 const struct dt_driver *__dt_driver_start(void); 51 52 const struct dt_driver *__dt_driver_end(void); 53 54 /* 55 * Map a device into secure or non-secure memory and return the base VA and 56 * the mapping size. The mapping is done with type MEM_AREA_IO_SEC or 57 * MEM_AREA_IO_NSEC, depending on the device status. 58 * If the mapping already exists, the function simply returns the @vbase and 59 * @size information. 60 * 61 * @offs is the offset of the node that describes the device in @fdt. 62 * @base receives the base virtual address corresponding to the base physical 63 * address of the "reg" property 64 * @size receives the size of the mapping 65 * 66 * Returns 0 on success or -1 in case of error. 67 */ 68 int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size); 69 70 /* 71 * Check whether the node at @offs contains the property with propname or not. 72 * 73 * @offs is the offset of the node that describes the device in @fdt. 74 * @propname is the property that need to check 75 * 76 * Returns true on success or false if no propname. 77 */ 78 bool dt_have_prop(const void *fdt, int offs, const char *propname); 79 80 /* 81 * FDT manipulation functions, not provided by <libfdt.h> 82 */ 83 84 /* 85 * Return the base address for the "reg" property of the specified node or 86 * (paddr_t)-1 in case of error 87 */ 88 paddr_t _fdt_reg_base_address(const void *fdt, int offs); 89 90 /* 91 * Return the reg size for the reg property of the specified node or -1 in case 92 * of error 93 */ 94 ssize_t _fdt_reg_size(const void *fdt, int offs); 95 96 /* 97 * Read the status and secure-status properties into a bitfield. 98 * @status is set to DT_STATUS_DISABLED or a combination of DT_STATUS_OK_NSEC 99 * and DT_STATUS_OK_SEC 100 * Returns 0 on success or -1 in case of error. 101 */ 102 int _fdt_get_status(const void *fdt, int offs); 103 104 #else /* !CFG_DT */ 105 106 static inline const struct dt_driver *__dt_driver_start(void) 107 { 108 return NULL; 109 } 110 111 static inline const struct dt_driver *__dt_driver_end(void) 112 { 113 return NULL; 114 } 115 116 static inline const struct dt_driver *dt_find_compatible_driver( 117 const void *fdt __unused, 118 int offs __unused) 119 { 120 return NULL; 121 } 122 123 static inline int dt_map_dev(const void *fdt __unused, int offs __unused, 124 vaddr_t *vbase __unused, size_t *size __unused) 125 { 126 return -1; 127 } 128 129 static inline paddr_t _fdt_reg_base_address(const void *fdt __unused, 130 int offs __unused) 131 { 132 return (paddr_t)-1; 133 } 134 135 static inline ssize_t _fdt_reg_size(const void *fdt __unused, 136 int offs __unused) 137 { 138 return -1; 139 } 140 141 static inline int _fdt_get_status(const void *fdt __unused, int offs __unused) 142 { 143 return -1; 144 } 145 146 #endif /* !CFG_DT */ 147 148 #define for_each_dt_driver(drv) \ 149 for (drv = __dt_driver_start(); drv < __dt_driver_end(); drv++) 150 151 #endif /* KERNEL_DT_H */ 152