1 #ifndef _DEVICETREE_H_ 2 #define _DEVICETREE_H_ 3 /* 4 * devicetree builds on libfdt to implement abstractions and accessors 5 * for Linux required device tree content. The accessors provided are 6 * common across architectures. See section III of the kernel doc 7 * Documentation/devicetree/booting-without-of.txt 8 * 9 * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com> 10 * 11 * This work is licensed under the terms of the GNU LGPL, version 2. 12 */ 13 #include "libcflat.h" 14 #include "libfdt/libfdt.h" 15 16 /********************************************************************** 17 * devicetree init and libfdt helpers 18 **********************************************************************/ 19 20 /* dt_init initializes devicetree with a pointer to an fdt, @fdt_ptr */ 21 extern int dt_init(const void *fdt_ptr); 22 23 /* get the fdt pointer that devicetree is using */ 24 extern const void *dt_fdt(void); 25 26 /* check for an initialized, valid devicetree */ 27 extern bool dt_available(void); 28 29 /* traverse child nodes */ 30 #define dt_for_each_subnode(n, s) \ 31 for (s = fdt_first_subnode(dt_fdt(), n); \ 32 s != -FDT_ERR_NOTFOUND; \ 33 s = fdt_next_subnode(dt_fdt(), s)) 34 35 /********************************************************************** 36 * Abstractions for required node types and properties 37 **********************************************************************/ 38 39 struct dt_device { 40 int fdtnode; 41 const struct dt_bus *bus; 42 43 /* 44 * info is a pointer to device specific data, which may be 45 * used by the bus match() and translate() functions 46 */ 47 void *info; 48 }; 49 50 struct dt_bus { 51 /* 52 * match a device @dev to an fdt node @fdtnode 53 * returns 54 * - a positive value on match 55 * - zero on no match 56 * - a negative FDT_ERR_* value on failure 57 */ 58 int (*match)(const struct dt_device *dev, int fdtnode); 59 60 /* 61 * translate the @regidx'th "address size" tuple of 62 * @dev's fdt node's "reg" property, and store the result 63 * in @reg, a bus specific structure 64 * returns 65 * - zero on success 66 * - a negative FDT_ERR_* value on failure 67 */ 68 int (*translate)(const struct dt_device *dev, int regidx, void *reg); 69 }; 70 71 /* dt_bus_match_any matches any fdt node, i.e. it always returns true */ 72 extern int dt_bus_match_any(const struct dt_device *dev, int fdtnode); 73 74 /* the processor bus (pbus) address type and register tuple */ 75 typedef u64 dt_pbus_addr_t; 76 struct dt_pbus_reg { 77 dt_pbus_addr_t addr; 78 dt_pbus_addr_t size; 79 }; 80 81 static inline dt_pbus_addr_t dt_pbus_read_cells(u32 nr_cells, u32 *cells) 82 { 83 switch (nr_cells) { 84 case 1: return cells[0]; 85 case 2: return ((u64)cells[0] << 32) | cells[1]; 86 } 87 return (~0ULL); 88 } 89 90 /* 91 * dt_pbus_translate translates device node regs for the 92 * processor bus using the parent node's #address-cells 93 * and #size-cells and dt_pbus_read_cells() 94 * returns 95 * - zero on success 96 * - a negative FDT_ERR_* value on failure 97 */ 98 extern int dt_pbus_translate(const struct dt_device *dev, int regidx, 99 void *reg); 100 101 /* 102 * dt_pbus_translate_node is the same as dt_pbus_translate but 103 * operates on an fdt node instead of a dt_device 104 */ 105 extern int dt_pbus_translate_node(int fdtnode, int regidx, 106 struct dt_pbus_reg *reg); 107 108 /* 109 * dt_pbus_get_base is an alias for 110 * dt_pbus_translate(dev, 0, base) 111 * returns 112 * - zero on success 113 * - a negative FDT_ERR_* value on failure 114 */ 115 static inline int dt_pbus_get_base(const struct dt_device *dev, 116 struct dt_pbus_reg *base) 117 { 118 return dt_pbus_translate(dev, 0, base); 119 } 120 121 /* 122 * dt_bus_init_defaults initializes @bus with 123 * match <- dt_bus_match_any 124 * translate <- dt_pbus_translate 125 */ 126 extern void dt_bus_init_defaults(struct dt_bus *bus); 127 128 /* 129 * dt_device_init initializes a dt_device with the given parameters 130 */ 131 extern void dt_device_init(struct dt_device *dev, const struct dt_bus *bus, 132 void *info); 133 134 static inline void dt_device_bind_node(struct dt_device *dev, int fdtnode) 135 { 136 dev->fdtnode = fdtnode; 137 } 138 139 /* 140 * dt_device_find_compatible finds a @compatible node 141 * returns 142 * - node (>= 0) on success 143 * - a negative FDT_ERR_* value on failure 144 */ 145 extern int dt_device_find_compatible(const struct dt_device *dev, 146 const char *compatible); 147 148 /* 149 * dt_pbus_get_base_compatible simply bundles many functions into one. 150 * It finds the first @compatible fdt node, then translates the 0th reg 151 * tuple (the base) using the processor bus translation, and finally it 152 * stores that result in @base. 153 * returns 154 * - zero on success 155 * - a negative FDT_ERR_* value on failure 156 */ 157 extern int dt_pbus_get_base_compatible(const char *compatible, 158 struct dt_pbus_reg *base); 159 160 /********************************************************************** 161 * Low-level accessors for required node types and properties 162 **********************************************************************/ 163 164 /* 165 * dt_get_nr_cells sets @nr_address_cells and @nr_size_cells to the 166 * #address-cells and #size-cells properties of @fdtnode 167 * returns 168 * - zero on success 169 * - a negative FDT_ERR_* value on failure 170 */ 171 extern int dt_get_nr_cells(int fdtnode, u32 *nr_address_cells, 172 u32 *nr_size_cells); 173 174 /* dt_reg is a structure for "raw" reg tuples */ 175 #define MAX_ADDRESS_CELLS 4 176 #define MAX_SIZE_CELLS 4 177 struct dt_reg { 178 u32 nr_address_cells, nr_size_cells; 179 u32 address_cells[MAX_ADDRESS_CELLS]; 180 u32 size_cells[MAX_SIZE_CELLS]; 181 }; 182 183 /* 184 * dt_reg_init initialize a dt_reg struct to zero and sets 185 * nr_address_cells and nr_size_cells to @nr_address_cells and 186 * @nr_size_cells respectively. 187 */ 188 extern void dt_reg_init(struct dt_reg *reg, u32 nr_address_cells, 189 u32 nr_size_cells); 190 191 /* 192 * dt_get_reg gets the @regidx'th reg tuple of @fdtnode's reg property 193 * and stores it in @reg. @reg must be initialized. 194 * returns 195 * - zero on success 196 * - a negative FDT_ERR_* value on failure 197 */ 198 extern int dt_get_reg(int fdtnode, int regidx, struct dt_reg *reg); 199 200 /********************************************************************** 201 * High-level accessors for required node types and properties 202 **********************************************************************/ 203 204 /* 205 * dt_get_bootargs gets the string pointer from /chosen/bootargs 206 * returns 207 * - zero on success 208 * - a negative FDT_ERR_* value on failure, and @bootargs 209 * will be set to NULL 210 */ 211 extern int dt_get_bootargs(const char **bootargs); 212 213 /* 214 * dt_get_default_console_node gets the node of the path stored in 215 * /chosen/stdout-path (or the deprecated /chosen/linux,stdout-path) 216 * returns 217 * - the node (>= 0) on success 218 * - a negative FDT_ERR_* value on failure 219 */ 220 extern int dt_get_default_console_node(void); 221 222 /* 223 * dt_get_initrd gets the physical address of the initrd and its 224 * size from /chosen 225 * returns 226 * - zero on success 227 * - a negative FDT_ERR_* value on failure, and @initrd will be 228 * set to NULL and @size set to zero 229 */ 230 extern int dt_get_initrd(const char **initrd, u32 *size); 231 232 /* 233 * dt_get_memory_params gets the memory parameters from the /memory node(s) 234 * storing each memory region ("address size" tuple) in consecutive entries 235 * of @regs, up to @nr_regs 236 * returns 237 * - number of memory regions found on success 238 * - a negative FDT_ERR_* value on failure 239 */ 240 extern int dt_get_memory_params(struct dt_pbus_reg *regs, int nr_regs); 241 242 /* 243 * dt_for_each_cpu_node runs @func on each cpu node in the /cpus node 244 * passing it its fdt node, its reg property value, and @info 245 * - zero on success 246 * - a negative FDT_ERR_* value on failure 247 */ 248 extern int dt_for_each_cpu_node(void (*func)(int fdtnode, u64 regval, 249 void *info), void *info); 250 251 #endif /* _DEVICETREE_H_ */ 252