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