1 // SPDX-License-Identifier: GPL-2.0+
3 * FDT Address translation based on u-boot fdt_support.c which in turn was
4 * based on the kernel unflattened DT address translation code.
7 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
9 * Copyright 2010-2011 Freescale Semiconductor, Inc.
12 #define pr_fmt(fmt) "OF: fdt: " fmt
14 #include <linux/kernel.h>
15 #include <linux/libfdt.h>
17 #include <linux/of_fdt.h>
18 #include <linux/sizes.h>
20 /* Max address size we deal with */
21 #define OF_MAX_ADDR_CELLS 4
22 #define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
27 static void __init
of_dump_addr(const char *s
, const __be32
*addr
, int na
)
31 pr_cont(" %08x", *(addr
++));
35 static void __init
of_dump_addr(const char *s
, const __be32
*addr
, int na
) { }
38 /* Callbacks for bus specific translators */
40 void (*count_cells
)(const void *blob
, int parentoffset
,
41 int *addrc
, int *sizec
);
42 u64 (*map
)(__be32
*addr
, const __be32
*range
,
43 int na
, int ns
, int pna
);
44 int (*translate
)(__be32
*addr
, u64 offset
, int na
);
47 /* Default translator (generic bus) */
48 static void __init
fdt_bus_default_count_cells(const void *blob
, int parentoffset
,
49 int *addrc
, int *sizec
)
54 prop
= fdt_getprop(blob
, parentoffset
, "#address-cells", NULL
);
56 *addrc
= be32_to_cpup(prop
);
58 *addrc
= dt_root_addr_cells
;
62 prop
= fdt_getprop(blob
, parentoffset
, "#size-cells", NULL
);
64 *sizec
= be32_to_cpup(prop
);
66 *sizec
= dt_root_size_cells
;
70 static u64 __init
fdt_bus_default_map(__be32
*addr
, const __be32
*range
,
71 int na
, int ns
, int pna
)
75 cp
= of_read_number(range
, na
);
76 s
= of_read_number(range
+ na
+ pna
, ns
);
77 da
= of_read_number(addr
, na
);
79 pr_debug("default map, cp=%llx, s=%llx, da=%llx\n",
82 if (da
< cp
|| da
>= (cp
+ s
))
87 static int __init
fdt_bus_default_translate(__be32
*addr
, u64 offset
, int na
)
89 u64 a
= of_read_number(addr
, na
);
90 memset(addr
, 0, na
* 4);
93 addr
[na
- 2] = cpu_to_fdt32(a
>> 32);
94 addr
[na
- 1] = cpu_to_fdt32(a
& 0xffffffffu
);
99 /* Array of bus specific translators */
100 static const struct of_bus of_busses
[] __initconst
= {
103 .count_cells
= fdt_bus_default_count_cells
,
104 .map
= fdt_bus_default_map
,
105 .translate
= fdt_bus_default_translate
,
109 static int __init
fdt_translate_one(const void *blob
, int parent
,
110 const struct of_bus
*bus
,
111 const struct of_bus
*pbus
, __be32
*addr
,
112 int na
, int ns
, int pna
, const char *rprop
)
114 const __be32
*ranges
;
117 u64 offset
= OF_BAD_ADDR
;
119 ranges
= fdt_getprop(blob
, parent
, rprop
, &rlen
);
123 offset
= of_read_number(addr
, na
);
124 memset(addr
, 0, pna
* 4);
125 pr_debug("empty ranges, 1:1 translation\n");
129 pr_debug("walking ranges...\n");
131 /* Now walk through the ranges */
133 rone
= na
+ pna
+ ns
;
134 for (; rlen
>= rone
; rlen
-= rone
, ranges
+= rone
) {
135 offset
= bus
->map(addr
, ranges
, na
, ns
, pna
);
136 if (offset
!= OF_BAD_ADDR
)
139 if (offset
== OF_BAD_ADDR
) {
140 pr_debug("not found !\n");
143 memcpy(addr
, ranges
+ na
, 4 * pna
);
146 of_dump_addr("parent translation for:", addr
, pna
);
147 pr_debug("with offset: %llx\n", offset
);
149 /* Translate it into parent bus space */
150 return pbus
->translate(addr
, offset
, pna
);
154 * Translate an address from the device-tree into a CPU physical address,
155 * this walks up the tree and applies the various bus mappings on the
158 * Note: We consider that crossing any level with #size-cells == 0 to mean
159 * that translation is impossible (that is we are not dealing with a value
160 * that can be mapped to a cpu physical address). This is not really specified
161 * that way, but this is traditionally the way IBM at least do things
163 static u64 __init
fdt_translate_address(const void *blob
, int node_offset
)
166 const struct of_bus
*bus
, *pbus
;
168 __be32 addr
[OF_MAX_ADDR_CELLS
];
169 int na
, ns
, pna
, pns
;
170 u64 result
= OF_BAD_ADDR
;
172 pr_debug("** translation for device %s **\n",
173 fdt_get_name(blob
, node_offset
, NULL
));
175 reg
= fdt_getprop(blob
, node_offset
, "reg", &len
);
177 pr_err("warning: device tree node '%s' has no address.\n",
178 fdt_get_name(blob
, node_offset
, NULL
));
182 /* Get parent & match bus type */
183 parent
= fdt_parent_offset(blob
, node_offset
);
188 /* Cound address cells & copy address locally */
189 bus
->count_cells(blob
, parent
, &na
, &ns
);
190 if (!OF_CHECK_COUNTS(na
, ns
)) {
191 pr_err("Bad cell count for %s\n",
192 fdt_get_name(blob
, node_offset
, NULL
));
195 memcpy(addr
, reg
, na
* 4);
197 pr_debug("bus (na=%d, ns=%d) on %s\n",
198 na
, ns
, fdt_get_name(blob
, parent
, NULL
));
199 of_dump_addr("translating address:", addr
, na
);
203 /* Switch to parent bus */
204 node_offset
= parent
;
205 parent
= fdt_parent_offset(blob
, node_offset
);
207 /* If root, we have finished */
209 pr_debug("reached root node\n");
210 result
= of_read_number(addr
, na
);
214 /* Get new parent bus and counts */
215 pbus
= &of_busses
[0];
216 pbus
->count_cells(blob
, parent
, &pna
, &pns
);
217 if (!OF_CHECK_COUNTS(pna
, pns
)) {
218 pr_err("Bad cell count for %s\n",
219 fdt_get_name(blob
, node_offset
, NULL
));
223 pr_debug("parent bus (na=%d, ns=%d) on %s\n",
224 pna
, pns
, fdt_get_name(blob
, parent
, NULL
));
226 /* Apply bus translation */
227 if (fdt_translate_one(blob
, node_offset
, bus
, pbus
,
228 addr
, na
, ns
, pna
, "ranges"))
231 /* Complete the move up one level */
236 of_dump_addr("one level translation:", addr
, na
);
243 * of_flat_dt_translate_address - translate DT addr into CPU phys addr
244 * @node: node in the flat blob
246 u64 __init
of_flat_dt_translate_address(unsigned long node
)
248 return fdt_translate_address(initial_boot_params
, node
);