2 * FDT Address translation based on u-boot fdt_support.c which in turn was
3 * based on the kernel unflattened DT address translation code.
6 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
8 * Copyright 2010-2011 Freescale Semiconductor, Inc.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
16 #define pr_fmt(fmt) "OF: fdt: " fmt
18 #include <linux/kernel.h>
19 #include <linux/libfdt.h>
21 #include <linux/of_fdt.h>
22 #include <linux/sizes.h>
24 /* Max address size we deal with */
25 #define OF_MAX_ADDR_CELLS 4
26 #define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
31 static void __init
of_dump_addr(const char *s
, const __be32
*addr
, int na
)
35 pr_cont(" %08x", *(addr
++));
39 static void __init
of_dump_addr(const char *s
, const __be32
*addr
, int na
) { }
42 /* Callbacks for bus specific translators */
44 void (*count_cells
)(const void *blob
, int parentoffset
,
45 int *addrc
, int *sizec
);
46 u64 (*map
)(__be32
*addr
, const __be32
*range
,
47 int na
, int ns
, int pna
);
48 int (*translate
)(__be32
*addr
, u64 offset
, int na
);
51 /* Default translator (generic bus) */
52 static void __init
fdt_bus_default_count_cells(const void *blob
, int parentoffset
,
53 int *addrc
, int *sizec
)
58 prop
= fdt_getprop(blob
, parentoffset
, "#address-cells", NULL
);
60 *addrc
= be32_to_cpup(prop
);
62 *addrc
= dt_root_addr_cells
;
66 prop
= fdt_getprop(blob
, parentoffset
, "#size-cells", NULL
);
68 *sizec
= be32_to_cpup(prop
);
70 *sizec
= dt_root_size_cells
;
74 static u64 __init
fdt_bus_default_map(__be32
*addr
, const __be32
*range
,
75 int na
, int ns
, int pna
)
79 cp
= of_read_number(range
, na
);
80 s
= of_read_number(range
+ na
+ pna
, ns
);
81 da
= of_read_number(addr
, na
);
83 pr_debug("default map, cp=%llx, s=%llx, da=%llx\n",
86 if (da
< cp
|| da
>= (cp
+ s
))
91 static int __init
fdt_bus_default_translate(__be32
*addr
, u64 offset
, int na
)
93 u64 a
= of_read_number(addr
, na
);
94 memset(addr
, 0, na
* 4);
97 addr
[na
- 2] = cpu_to_fdt32(a
>> 32);
98 addr
[na
- 1] = cpu_to_fdt32(a
& 0xffffffffu
);
103 /* Array of bus specific translators */
104 static const struct of_bus of_busses
[] __initconst
= {
107 .count_cells
= fdt_bus_default_count_cells
,
108 .map
= fdt_bus_default_map
,
109 .translate
= fdt_bus_default_translate
,
113 static int __init
fdt_translate_one(const void *blob
, int parent
,
114 const struct of_bus
*bus
,
115 const struct of_bus
*pbus
, __be32
*addr
,
116 int na
, int ns
, int pna
, const char *rprop
)
118 const __be32
*ranges
;
121 u64 offset
= OF_BAD_ADDR
;
123 ranges
= fdt_getprop(blob
, parent
, rprop
, &rlen
);
127 offset
= of_read_number(addr
, na
);
128 memset(addr
, 0, pna
* 4);
129 pr_debug("empty ranges, 1:1 translation\n");
133 pr_debug("walking ranges...\n");
135 /* Now walk through the ranges */
137 rone
= na
+ pna
+ ns
;
138 for (; rlen
>= rone
; rlen
-= rone
, ranges
+= rone
) {
139 offset
= bus
->map(addr
, ranges
, na
, ns
, pna
);
140 if (offset
!= OF_BAD_ADDR
)
143 if (offset
== OF_BAD_ADDR
) {
144 pr_debug("not found !\n");
147 memcpy(addr
, ranges
+ na
, 4 * pna
);
150 of_dump_addr("parent translation for:", addr
, pna
);
151 pr_debug("with offset: %llx\n", offset
);
153 /* Translate it into parent bus space */
154 return pbus
->translate(addr
, offset
, pna
);
158 * Translate an address from the device-tree into a CPU physical address,
159 * this walks up the tree and applies the various bus mappings on the
162 * Note: We consider that crossing any level with #size-cells == 0 to mean
163 * that translation is impossible (that is we are not dealing with a value
164 * that can be mapped to a cpu physical address). This is not really specified
165 * that way, but this is traditionally the way IBM at least do things
167 static u64 __init
fdt_translate_address(const void *blob
, int node_offset
)
170 const struct of_bus
*bus
, *pbus
;
172 __be32 addr
[OF_MAX_ADDR_CELLS
];
173 int na
, ns
, pna
, pns
;
174 u64 result
= OF_BAD_ADDR
;
176 pr_debug("** translation for device %s **\n",
177 fdt_get_name(blob
, node_offset
, NULL
));
179 reg
= fdt_getprop(blob
, node_offset
, "reg", &len
);
181 pr_err("warning: device tree node '%s' has no address.\n",
182 fdt_get_name(blob
, node_offset
, NULL
));
186 /* Get parent & match bus type */
187 parent
= fdt_parent_offset(blob
, node_offset
);
192 /* Cound address cells & copy address locally */
193 bus
->count_cells(blob
, parent
, &na
, &ns
);
194 if (!OF_CHECK_COUNTS(na
, ns
)) {
195 pr_err("Bad cell count for %s\n",
196 fdt_get_name(blob
, node_offset
, NULL
));
199 memcpy(addr
, reg
, na
* 4);
201 pr_debug("bus (na=%d, ns=%d) on %s\n",
202 na
, ns
, fdt_get_name(blob
, parent
, NULL
));
203 of_dump_addr("translating address:", addr
, na
);
207 /* Switch to parent bus */
208 node_offset
= parent
;
209 parent
= fdt_parent_offset(blob
, node_offset
);
211 /* If root, we have finished */
213 pr_debug("reached root node\n");
214 result
= of_read_number(addr
, na
);
218 /* Get new parent bus and counts */
219 pbus
= &of_busses
[0];
220 pbus
->count_cells(blob
, parent
, &pna
, &pns
);
221 if (!OF_CHECK_COUNTS(pna
, pns
)) {
222 pr_err("Bad cell count for %s\n",
223 fdt_get_name(blob
, node_offset
, NULL
));
227 pr_debug("parent bus (na=%d, ns=%d) on %s\n",
228 pna
, pns
, fdt_get_name(blob
, parent
, NULL
));
230 /* Apply bus translation */
231 if (fdt_translate_one(blob
, node_offset
, bus
, pbus
,
232 addr
, na
, ns
, pna
, "ranges"))
235 /* Complete the move up one level */
240 of_dump_addr("one level translation:", addr
, na
);
247 * of_flat_dt_translate_address - translate DT addr into CPU phys addr
248 * @node: node in the flat blob
250 u64 __init
of_flat_dt_translate_address(unsigned long node
)
252 return fdt_translate_address(initial_boot_params
, node
);