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