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 * dt_getprop_as_number() - get a DT property a unsigned number 78 * @fdt: DT base address 79 * @nodeoffset: node offset 80 * @name: property string name 81 * @num: output number read 82 * Return 0 on success and a negative FDT error value on error 83 * 84 * The size of the property determines if it is read as an unsigned 32-bit 85 * or 64-bit integer. 86 */ 87 int dt_getprop_as_number(const void *fdt, int nodeoffset, const char *name, 88 uint64_t *num); 89 90 #ifdef CFG_DT 91 /* 92 * Find a driver that is suitable for the given DT node, that is, with 93 * a matching "compatible" property. 94 * 95 * @fdt: pointer to the device tree 96 * @offs: node offset 97 */ 98 const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs); 99 100 /* 101 * Map a device into secure or non-secure memory and return the base VA and 102 * the mapping size. The mapping is done with type MEM_AREA_IO_SEC or 103 * MEM_AREA_IO_NSEC, depending on the device status. 104 * If the mapping already exists, the function simply returns the @vbase and 105 * @size information. 106 * 107 * @offs is the offset of the node that describes the device in @fdt. 108 * @base receives the base virtual address corresponding to the base physical 109 * address of the "reg" property 110 * @size receives the size of the mapping 111 * @mapping what kind of mapping is done for memory. 112 * 113 * Returns 0 on success or -1 in case of error. 114 */ 115 int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size, 116 enum dt_map_dev_directive mapping); 117 118 /* 119 * Check whether the node at @offs contains the property with propname or not. 120 * 121 * @offs is the offset of the node that describes the device in @fdt. 122 * @propname is the property that need to check 123 * 124 * Returns true on success or false if no propname. 125 */ 126 bool dt_have_prop(const void *fdt, int offs, const char *propname); 127 128 /* 129 * Modify or add "status" property to "disabled" 130 * 131 * @fdt reference to the Device Tree 132 * @node is the node offset to modify 133 * 134 * Returns 0 on success or -1 on failure 135 */ 136 int dt_disable_status(void *fdt, int node); 137 138 /* 139 * Force secure-status = "okay" and status="disabled" for the target node. 140 * 141 * @fdt reference to the Device Tree 142 * @node is the node offset to modify 143 * 144 * Returns 0 on success or -1 on failure 145 */ 146 int dt_enable_secure_status(void *fdt, int node); 147 148 /* 149 * FDT manipulation functions, not provided by <libfdt.h> 150 */ 151 152 /* 153 * Return the base address for the "reg" property of the specified node or 154 * (paddr_t)-1 in case of error 155 */ 156 paddr_t fdt_reg_base_address(const void *fdt, int offs); 157 158 /* 159 * Return the reg size for the reg property of the specified node or -1 in case 160 * of error 161 */ 162 size_t fdt_reg_size(const void *fdt, int offs); 163 164 /* 165 * Read the status and secure-status properties into a bitfield. 166 * Return -1 on failure, DT_STATUS_DISABLED if the node is disabled, 167 * otherwise return a combination of DT_STATUS_OK_NSEC and DT_STATUS_OK_SEC. 168 */ 169 int fdt_get_status(const void *fdt, int offs); 170 171 /* 172 * fdt_fill_device_info - Get generic device info from a node 173 * 174 * This function fills the generic information from a given node. 175 * Currently supports a single base register, a single clock, 176 * a single reset ID line and a single interrupt ID. 177 * Default DT_INFO_* macros are used when the relate property is not found. 178 */ 179 void fdt_fill_device_info(const void *fdt, struct dt_node_info *info, 180 int node); 181 /* 182 * Read cells from a given property of the given node. Any number of 32-bit 183 * cells of the property can be read. Returns 0 on success, or a negative 184 * FDT error value otherwise. 185 */ 186 int fdt_read_uint32_array(const void *fdt, int node, const char *prop_name, 187 uint32_t *array, size_t count); 188 189 /* 190 * Read one cell from a given multi-value property of the given node. 191 * Returns 0 on success, or a negative FDT error value otherwise. 192 */ 193 int fdt_read_uint32_index(const void *fdt, int node, const char *prop_name, 194 int index, uint32_t *value); 195 196 /* 197 * Read one cell from a given property of the given node. 198 * Returns 0 on success, or a negative FDT error value otherwise. 199 */ 200 int fdt_read_uint32(const void *fdt, int node, const char *prop_name, 201 uint32_t *value); 202 203 /* 204 * Read one cell from a property of a cell or default to a given value 205 * Returns the 32bit cell value or @dflt_value on failure. 206 */ 207 uint32_t fdt_read_uint32_default(const void *fdt, int node, 208 const char *prop_name, uint32_t dflt_value); 209 210 /* 211 * This function fills reg node info (base & size) with an index. 212 * 213 * Returns 0 on success and a negative FDT error code on failure. 214 */ 215 int fdt_get_reg_props_by_index(const void *fdt, int node, int index, 216 paddr_t *base, size_t *size); 217 218 /* 219 * This function fills reg node info (base & size) with an index found by 220 * checking the reg-names node. 221 * 222 * Returns 0 on success and a negative FDT error code on failure. 223 */ 224 int fdt_get_reg_props_by_name(const void *fdt, int node, const char *name, 225 paddr_t *base, size_t *size); 226 227 #else /* !CFG_DT */ 228 229 static inline const struct dt_driver *dt_find_compatible_driver( 230 const void *fdt __unused, 231 int offs __unused) 232 { 233 return NULL; 234 } 235 236 static inline int dt_map_dev(const void *fdt __unused, int offs __unused, 237 vaddr_t *vbase __unused, size_t *size __unused, 238 enum dt_map_dev_directive mapping __unused) 239 { 240 return -1; 241 } 242 243 static inline paddr_t fdt_reg_base_address(const void *fdt __unused, 244 int offs __unused) 245 { 246 return (paddr_t)-1; 247 } 248 249 static inline size_t fdt_reg_size(const void *fdt __unused, 250 int offs __unused) 251 { 252 return (size_t)-1; 253 } 254 255 static inline int fdt_get_status(const void *fdt __unused, int offs __unused) 256 { 257 return -1; 258 } 259 260 __noreturn 261 static inline void fdt_fill_device_info(const void *fdt __unused, 262 struct dt_node_info *info __unused, 263 int node __unused) 264 { 265 panic(); 266 } 267 268 static inline int fdt_read_uint32_array(const void *fdt __unused, 269 int node __unused, 270 const char *prop_name __unused, 271 uint32_t *array __unused, 272 size_t count __unused) 273 { 274 return -1; 275 } 276 277 static inline int fdt_read_uint32(const void *fdt __unused, 278 int node __unused, 279 const char *prop_name __unused, 280 uint32_t *value __unused) 281 { 282 return -1; 283 } 284 285 static inline uint32_t fdt_read_uint32_default(const void *fdt __unused, 286 int node __unused, 287 const char *prop_name __unused, 288 uint32_t dflt_value __unused) 289 { 290 return dflt_value; 291 } 292 293 static inline int fdt_read_uint32_index(const void *fdt __unused, 294 int node __unused, 295 const char *prop_name __unused, 296 int index __unused, 297 uint32_t *value __unused) 298 { 299 return -1; 300 } 301 302 static inline int fdt_get_reg_props_by_index(const void *fdt __unused, 303 int node __unused, 304 int index __unused, 305 paddr_t *base __unused, 306 size_t *size __unused) 307 { 308 return -1; 309 } 310 311 static inline int fdt_get_reg_props_by_name(const void *fdt __unused, 312 int node __unused, 313 const char *name __unused, 314 paddr_t *base __unused, 315 size_t *size __unused) 316 { 317 return -1; 318 } 319 320 #endif /* !CFG_DT */ 321 #endif /* KERNEL_DT_H */ 322