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