1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * Copyright (c) 2016, Linaro Limited 4 */ 5 6 #ifndef KERNEL_DT_H 7 #define KERNEL_DT_H 8 9 #include <compiler.h> 10 #include <kernel/panic.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 #define DT_INFO_INVALID_REG ((paddr_t)-1) 24 #define DT_INFO_INVALID_CLOCK -1 25 #define DT_INFO_INVALID_RESET -1 26 /* 27 * @status: Bit mask for DT_STATUS_* 28 * @reg: Device register physical base address or DT_INFO_INVALID_REG 29 * @clock: Device identifier (positive value) or DT_INFO_INVALID_CLOCK 30 * @reset: Device reset identifier (positive value) or DT_INFO_INVALID_CLOCK 31 */ 32 struct dt_node_info { 33 unsigned int status; 34 paddr_t reg; 35 int clock; 36 int reset; 37 }; 38 39 #if defined(CFG_DT) 40 41 /* 42 * DT-aware drivers 43 */ 44 45 struct dt_device_match { 46 const char *compatible; 47 }; 48 49 struct dt_driver { 50 const char *name; 51 const struct dt_device_match *match_table; /* null-terminated */ 52 const void *driver; 53 }; 54 55 #define __dt_driver __section(".rodata.dtdrv" __SECTION_FLAGS_RODATA) 56 57 /* 58 * Find a driver that is suitable for the given DT node, that is, with 59 * a matching "compatible" property. 60 * 61 * @fdt: pointer to the device tree 62 * @offs: node offset 63 */ 64 const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs); 65 66 const struct dt_driver *__dt_driver_start(void); 67 68 const struct dt_driver *__dt_driver_end(void); 69 70 /* 71 * Map a device into secure or non-secure memory and return the base VA and 72 * the mapping size. The mapping is done with type MEM_AREA_IO_SEC or 73 * MEM_AREA_IO_NSEC, depending on the device status. 74 * If the mapping already exists, the function simply returns the @vbase and 75 * @size information. 76 * 77 * @offs is the offset of the node that describes the device in @fdt. 78 * @base receives the base virtual address corresponding to the base physical 79 * address of the "reg" property 80 * @size receives the size of the mapping 81 * 82 * Returns 0 on success or -1 in case of error. 83 */ 84 int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size); 85 86 /* 87 * Check whether the node at @offs contains the property with propname or not. 88 * 89 * @offs is the offset of the node that describes the device in @fdt. 90 * @propname is the property that need to check 91 * 92 * Returns true on success or false if no propname. 93 */ 94 bool dt_have_prop(const void *fdt, int offs, const char *propname); 95 96 /* 97 * FDT manipulation functions, not provided by <libfdt.h> 98 */ 99 100 /* 101 * Return the base address for the "reg" property of the specified node or 102 * (paddr_t)-1 in case of error 103 */ 104 paddr_t _fdt_reg_base_address(const void *fdt, int offs); 105 106 /* 107 * Return the reg size for the reg property of the specified node or -1 in case 108 * of error 109 */ 110 ssize_t _fdt_reg_size(const void *fdt, int offs); 111 112 /* 113 * Read the status and secure-status properties into a bitfield. 114 * @status is set to DT_STATUS_DISABLED or a combination of DT_STATUS_OK_NSEC 115 * and DT_STATUS_OK_SEC 116 * Returns positive or null status value on success or -1 in case of error. 117 */ 118 int _fdt_get_status(const void *fdt, int offs); 119 120 /* 121 * fdt_fill_device_info - Get generic device info from a node 122 * 123 * This function fills the generic information from a given node. 124 * Currently supports a single base register, a single clock, 125 * a single reset ID line and a single interrupt ID. 126 * Default DT_INFO_* macros are used when the relate property is not found. 127 */ 128 void _fdt_fill_device_info(void *fdt, struct dt_node_info *info, int node); 129 130 #else /* !CFG_DT */ 131 132 static inline const struct dt_driver *__dt_driver_start(void) 133 { 134 return NULL; 135 } 136 137 static inline const struct dt_driver *__dt_driver_end(void) 138 { 139 return NULL; 140 } 141 142 static inline const struct dt_driver *dt_find_compatible_driver( 143 const void *fdt __unused, 144 int offs __unused) 145 { 146 return NULL; 147 } 148 149 static inline int dt_map_dev(const void *fdt __unused, int offs __unused, 150 vaddr_t *vbase __unused, size_t *size __unused) 151 { 152 return -1; 153 } 154 155 static inline paddr_t _fdt_reg_base_address(const void *fdt __unused, 156 int offs __unused) 157 { 158 return (paddr_t)-1; 159 } 160 161 static inline ssize_t _fdt_reg_size(const void *fdt __unused, 162 int offs __unused) 163 { 164 return -1; 165 } 166 167 static inline int _fdt_get_status(const void *fdt __unused, int offs __unused) 168 { 169 return -1; 170 } 171 172 static inline void _fdt_fill_device_info(void *fdt __unused, 173 struct dt_node_info *info __unused, 174 int node __unused) 175 { 176 panic(); 177 } 178 #endif /* !CFG_DT */ 179 180 #define for_each_dt_driver(drv) \ 181 for (drv = __dt_driver_start(); drv < __dt_driver_end(); drv++) 182 183 #endif /* KERNEL_DT_H */ 184