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 /* the bus #address-cells and #size-cells properties */ 71 u32 nr_address_cells, nr_size_cells; 72 }; 73 74 /* dt_bus_match_any matches any fdt node, i.e. it always returns true */ 75 extern int dt_bus_match_any(const struct dt_device *dev, int fdtnode); 76 77 /* the processor bus (pbus) address type and register tuple */ 78 typedef u64 dt_pbus_addr_t; 79 struct dt_pbus_reg { 80 dt_pbus_addr_t addr; 81 dt_pbus_addr_t size; 82 }; 83 84 static inline dt_pbus_addr_t dt_pbus_read_cells(u32 nr_cells, u32 *cells) 85 { 86 switch (nr_cells) { 87 case 1: return cells[0]; 88 case 2: return ((u64)cells[0] << 32) | cells[1]; 89 } 90 return (~0ULL); 91 } 92 93 /* 94 * dt_pbus_translate translates device node regs for the 95 * processor bus using the root node's #address-cells and 96 * #size-cells and dt_pbus_read_cells() 97 * returns 98 * - zero on success 99 * - a negative FDT_ERR_* value on failure 100 */ 101 extern int dt_pbus_translate(const struct dt_device *dev, int regidx, 102 void *reg); 103 104 /* 105 * dt_pbus_translate_node is the same as dt_pbus_translate but 106 * operates on an fdt node instead of a dt_device 107 */ 108 extern int dt_pbus_translate_node(int fdtnode, int regidx, 109 struct dt_pbus_reg *reg); 110 111 /* 112 * dt_pbus_get_base is an alias for 113 * dt_pbus_translate(dev, 0, base) 114 * returns 115 * - zero on success 116 * - a negative FDT_ERR_* value on failure 117 */ 118 static inline int dt_pbus_get_base(const struct dt_device *dev, 119 struct dt_pbus_reg *base) 120 { 121 return dt_pbus_translate(dev, 0, base); 122 } 123 124 /* 125 * dt_bus_init_defaults initializes @bus with 126 * match <- dt_bus_match_any 127 * translate <- dt_pbus_translate 128 * nr_address_cells <- #address-cells of the root node 129 * nr_size_cells <- #size-cells of the root node 130 */ 131 extern void dt_bus_init_defaults(struct dt_bus *bus); 132 133 /* 134 * dt_device_init initializes a dt_device with the given parameters 135 */ 136 extern void dt_device_init(struct dt_device *dev, const struct dt_bus *bus, 137 void *info); 138 139 static inline void dt_device_bind_node(struct dt_device *dev, int fdtnode) 140 { 141 dev->fdtnode = fdtnode; 142 } 143 144 /* 145 * dt_device_find_compatible finds a @compatible node 146 * returns 147 * - node (>= 0) on success 148 * - a negative FDT_ERR_* value on failure 149 */ 150 extern int dt_device_find_compatible(const struct dt_device *dev, 151 const char *compatible); 152 153 /* 154 * dt_pbus_get_base_compatible simply bundles many functions into one. 155 * It finds the first @compatible fdt node, then translates the 0th reg 156 * tuple (the base) using the processor bus translation, and finally it 157 * stores that result in @base. 158 * returns 159 * - zero on success 160 * - a negative FDT_ERR_* value on failure 161 */ 162 extern int dt_pbus_get_base_compatible(const char *compatible, 163 struct dt_pbus_reg *base); 164 165 /********************************************************************** 166 * Low-level accessors for required node types and properties 167 **********************************************************************/ 168 169 /* 170 * dt_get_nr_cells sets @nr_address_cells and @nr_size_cells to the 171 * #address-cells and #size-cells properties of @fdtnode 172 * returns 173 * - zero on success 174 * - a negative FDT_ERR_* value on failure 175 */ 176 extern int dt_get_nr_cells(int fdtnode, u32 *nr_address_cells, 177 u32 *nr_size_cells); 178 179 /* dt_reg is a structure for "raw" reg tuples */ 180 #define MAX_ADDRESS_CELLS 4 181 #define MAX_SIZE_CELLS 4 182 struct dt_reg { 183 u32 nr_address_cells, nr_size_cells; 184 u32 address_cells[MAX_ADDRESS_CELLS]; 185 u32 size_cells[MAX_SIZE_CELLS]; 186 }; 187 188 /* 189 * dt_reg_init initialize a dt_reg struct to zero and sets 190 * nr_address_cells and nr_size_cells to @nr_address_cells and 191 * @nr_size_cells respectively. 192 */ 193 extern void dt_reg_init(struct dt_reg *reg, u32 nr_address_cells, 194 u32 nr_size_cells); 195 196 /* 197 * dt_get_reg gets the @regidx'th reg tuple of @fdtnode's reg property 198 * and stores it in @reg. @reg must be initialized. 199 * returns 200 * - zero on success 201 * - a negative FDT_ERR_* value on failure 202 */ 203 extern int dt_get_reg(int fdtnode, int regidx, struct dt_reg *reg); 204 205 /********************************************************************** 206 * High-level accessors for required node types and properties 207 **********************************************************************/ 208 209 /* 210 * dt_get_bootargs gets a pointer to /chosen/bootargs 211 * returns 212 * - zero on success 213 * - a negative FDT_ERR_* value on failure 214 */ 215 extern int dt_get_bootargs(const char **bootargs); 216 217 /* 218 * dt_get_memory_params gets the memory parameters from the /memory node(s) 219 * storing each memory region ("address size" tuple) in consecutive entries 220 * of @regs, up to @nr_regs 221 * returns 222 * - number of memory regions found on success 223 * - a negative FDT_ERR_* value on failure 224 */ 225 extern int dt_get_memory_params(struct dt_pbus_reg *regs, int nr_regs); 226 227 /* 228 * dt_for_each_cpu_node runs @func on each cpu node in the /cpus node 229 * passing it its fdt node, its reg property value, and @info 230 * - zero on success 231 * - a negative FDT_ERR_* value on failure 232 */ 233 extern int dt_for_each_cpu_node(void (*func)(int fdtnode, u32 regval, 234 void *info), void *info); 235 236 #endif /* _DEVICETREE_H_ */ 237