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