devicetree.h 7.4 KB

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