xref: /openbmc/linux/drivers/of/address.c (revision 28c1b6d6)
16b884a8dSGrant Likely 
26b884a8dSGrant Likely #include <linux/io.h>
36b884a8dSGrant Likely #include <linux/ioport.h>
4dbbdee94SGrant Likely #include <linux/module.h>
56b884a8dSGrant Likely #include <linux/of_address.h>
6dbbdee94SGrant Likely #include <linux/pci_regs.h>
7dbbdee94SGrant Likely #include <linux/string.h>
86b884a8dSGrant Likely 
9dbbdee94SGrant Likely /* Max address size we deal with */
10dbbdee94SGrant Likely #define OF_MAX_ADDR_CELLS	4
11dbbdee94SGrant Likely #define OF_CHECK_COUNTS(na, ns)	((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
12dbbdee94SGrant Likely 			(ns) > 0)
13dbbdee94SGrant Likely 
14dbbdee94SGrant Likely static struct of_bus *of_match_bus(struct device_node *np);
150131d897SSebastian Andrzej Siewior static int __of_address_to_resource(struct device_node *dev,
160131d897SSebastian Andrzej Siewior 		const __be32 *addrp, u64 size, unsigned int flags,
17dbbdee94SGrant Likely 				    struct resource *r);
18dbbdee94SGrant Likely 
19dbbdee94SGrant Likely /* Debug utility */
20dbbdee94SGrant Likely #ifdef DEBUG
210131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na)
22dbbdee94SGrant Likely {
23dbbdee94SGrant Likely 	printk(KERN_DEBUG "%s", s);
24dbbdee94SGrant Likely 	while (na--)
25154063a9SGrant Likely 		printk(" %08x", be32_to_cpu(*(addr++)));
26dbbdee94SGrant Likely 	printk("\n");
27dbbdee94SGrant Likely }
28dbbdee94SGrant Likely #else
290131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na) { }
30dbbdee94SGrant Likely #endif
31dbbdee94SGrant Likely 
32dbbdee94SGrant Likely /* Callbacks for bus specific translators */
33dbbdee94SGrant Likely struct of_bus {
34dbbdee94SGrant Likely 	const char	*name;
35dbbdee94SGrant Likely 	const char	*addresses;
36dbbdee94SGrant Likely 	int		(*match)(struct device_node *parent);
37dbbdee94SGrant Likely 	void		(*count_cells)(struct device_node *child,
38dbbdee94SGrant Likely 				       int *addrc, int *sizec);
390131d897SSebastian Andrzej Siewior 	u64		(*map)(u32 *addr, const __be32 *range,
40dbbdee94SGrant Likely 				int na, int ns, int pna);
41dbbdee94SGrant Likely 	int		(*translate)(u32 *addr, u64 offset, int na);
420131d897SSebastian Andrzej Siewior 	unsigned int	(*get_flags)(const __be32 *addr);
43dbbdee94SGrant Likely };
44dbbdee94SGrant Likely 
45dbbdee94SGrant Likely /*
46dbbdee94SGrant Likely  * Default translator (generic bus)
47dbbdee94SGrant Likely  */
48dbbdee94SGrant Likely 
49dbbdee94SGrant Likely static void of_bus_default_count_cells(struct device_node *dev,
50dbbdee94SGrant Likely 				       int *addrc, int *sizec)
51dbbdee94SGrant Likely {
52dbbdee94SGrant Likely 	if (addrc)
53dbbdee94SGrant Likely 		*addrc = of_n_addr_cells(dev);
54dbbdee94SGrant Likely 	if (sizec)
55dbbdee94SGrant Likely 		*sizec = of_n_size_cells(dev);
56dbbdee94SGrant Likely }
57dbbdee94SGrant Likely 
580131d897SSebastian Andrzej Siewior static u64 of_bus_default_map(u32 *addr, const __be32 *range,
59dbbdee94SGrant Likely 		int na, int ns, int pna)
60dbbdee94SGrant Likely {
61dbbdee94SGrant Likely 	u64 cp, s, da;
62dbbdee94SGrant Likely 
63dbbdee94SGrant Likely 	cp = of_read_number(range, na);
64dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
65dbbdee94SGrant Likely 	da = of_read_number(addr, na);
66dbbdee94SGrant Likely 
67dbbdee94SGrant Likely 	pr_debug("OF: default map, cp=%llx, s=%llx, da=%llx\n",
68dbbdee94SGrant Likely 		 (unsigned long long)cp, (unsigned long long)s,
69dbbdee94SGrant Likely 		 (unsigned long long)da);
70dbbdee94SGrant Likely 
71dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
72dbbdee94SGrant Likely 		return OF_BAD_ADDR;
73dbbdee94SGrant Likely 	return da - cp;
74dbbdee94SGrant Likely }
75dbbdee94SGrant Likely 
76dbbdee94SGrant Likely static int of_bus_default_translate(u32 *addr, u64 offset, int na)
77dbbdee94SGrant Likely {
78dbbdee94SGrant Likely 	u64 a = of_read_number(addr, na);
79dbbdee94SGrant Likely 	memset(addr, 0, na * 4);
80dbbdee94SGrant Likely 	a += offset;
81dbbdee94SGrant Likely 	if (na > 1)
82154063a9SGrant Likely 		addr[na - 2] = cpu_to_be32(a >> 32);
83154063a9SGrant Likely 	addr[na - 1] = cpu_to_be32(a & 0xffffffffu);
84dbbdee94SGrant Likely 
85dbbdee94SGrant Likely 	return 0;
86dbbdee94SGrant Likely }
87dbbdee94SGrant Likely 
880131d897SSebastian Andrzej Siewior static unsigned int of_bus_default_get_flags(const __be32 *addr)
89dbbdee94SGrant Likely {
90dbbdee94SGrant Likely 	return IORESOURCE_MEM;
91dbbdee94SGrant Likely }
92dbbdee94SGrant Likely 
93dbbdee94SGrant Likely #ifdef CONFIG_PCI
94dbbdee94SGrant Likely /*
95dbbdee94SGrant Likely  * PCI bus specific translator
96dbbdee94SGrant Likely  */
97dbbdee94SGrant Likely 
98dbbdee94SGrant Likely static int of_bus_pci_match(struct device_node *np)
99dbbdee94SGrant Likely {
100dbbdee94SGrant Likely 	/* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */
101dbbdee94SGrant Likely 	return !strcmp(np->type, "pci") || !strcmp(np->type, "vci");
102dbbdee94SGrant Likely }
103dbbdee94SGrant Likely 
104dbbdee94SGrant Likely static void of_bus_pci_count_cells(struct device_node *np,
105dbbdee94SGrant Likely 				   int *addrc, int *sizec)
106dbbdee94SGrant Likely {
107dbbdee94SGrant Likely 	if (addrc)
108dbbdee94SGrant Likely 		*addrc = 3;
109dbbdee94SGrant Likely 	if (sizec)
110dbbdee94SGrant Likely 		*sizec = 2;
111dbbdee94SGrant Likely }
112dbbdee94SGrant Likely 
1130131d897SSebastian Andrzej Siewior static unsigned int of_bus_pci_get_flags(const __be32 *addr)
114dbbdee94SGrant Likely {
115dbbdee94SGrant Likely 	unsigned int flags = 0;
1160131d897SSebastian Andrzej Siewior 	u32 w = be32_to_cpup(addr);
117dbbdee94SGrant Likely 
118dbbdee94SGrant Likely 	switch((w >> 24) & 0x03) {
119dbbdee94SGrant Likely 	case 0x01:
120dbbdee94SGrant Likely 		flags |= IORESOURCE_IO;
121dbbdee94SGrant Likely 		break;
122dbbdee94SGrant Likely 	case 0x02: /* 32 bits */
123dbbdee94SGrant Likely 	case 0x03: /* 64 bits */
124dbbdee94SGrant Likely 		flags |= IORESOURCE_MEM;
125dbbdee94SGrant Likely 		break;
126dbbdee94SGrant Likely 	}
127dbbdee94SGrant Likely 	if (w & 0x40000000)
128dbbdee94SGrant Likely 		flags |= IORESOURCE_PREFETCH;
129dbbdee94SGrant Likely 	return flags;
130dbbdee94SGrant Likely }
131dbbdee94SGrant Likely 
1320131d897SSebastian Andrzej Siewior static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns,
1330131d897SSebastian Andrzej Siewior 		int pna)
134dbbdee94SGrant Likely {
135dbbdee94SGrant Likely 	u64 cp, s, da;
136dbbdee94SGrant Likely 	unsigned int af, rf;
137dbbdee94SGrant Likely 
138dbbdee94SGrant Likely 	af = of_bus_pci_get_flags(addr);
139dbbdee94SGrant Likely 	rf = of_bus_pci_get_flags(range);
140dbbdee94SGrant Likely 
141dbbdee94SGrant Likely 	/* Check address type match */
142dbbdee94SGrant Likely 	if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO))
143dbbdee94SGrant Likely 		return OF_BAD_ADDR;
144dbbdee94SGrant Likely 
145dbbdee94SGrant Likely 	/* Read address values, skipping high cell */
146dbbdee94SGrant Likely 	cp = of_read_number(range + 1, na - 1);
147dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
148dbbdee94SGrant Likely 	da = of_read_number(addr + 1, na - 1);
149dbbdee94SGrant Likely 
150dbbdee94SGrant Likely 	pr_debug("OF: PCI map, cp=%llx, s=%llx, da=%llx\n",
151dbbdee94SGrant Likely 		 (unsigned long long)cp, (unsigned long long)s,
152dbbdee94SGrant Likely 		 (unsigned long long)da);
153dbbdee94SGrant Likely 
154dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
155dbbdee94SGrant Likely 		return OF_BAD_ADDR;
156dbbdee94SGrant Likely 	return da - cp;
157dbbdee94SGrant Likely }
158dbbdee94SGrant Likely 
159dbbdee94SGrant Likely static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
160dbbdee94SGrant Likely {
161dbbdee94SGrant Likely 	return of_bus_default_translate(addr + 1, offset, na - 1);
162dbbdee94SGrant Likely }
163dbbdee94SGrant Likely 
1640131d897SSebastian Andrzej Siewior const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
165dbbdee94SGrant Likely 			unsigned int *flags)
166dbbdee94SGrant Likely {
167a9fadeefSJeremy Kerr 	const __be32 *prop;
168dbbdee94SGrant Likely 	unsigned int psize;
169dbbdee94SGrant Likely 	struct device_node *parent;
170dbbdee94SGrant Likely 	struct of_bus *bus;
171dbbdee94SGrant Likely 	int onesize, i, na, ns;
172dbbdee94SGrant Likely 
173dbbdee94SGrant Likely 	/* Get parent & match bus type */
174dbbdee94SGrant Likely 	parent = of_get_parent(dev);
175dbbdee94SGrant Likely 	if (parent == NULL)
176dbbdee94SGrant Likely 		return NULL;
177dbbdee94SGrant Likely 	bus = of_match_bus(parent);
178dbbdee94SGrant Likely 	if (strcmp(bus->name, "pci")) {
179dbbdee94SGrant Likely 		of_node_put(parent);
180dbbdee94SGrant Likely 		return NULL;
181dbbdee94SGrant Likely 	}
182dbbdee94SGrant Likely 	bus->count_cells(dev, &na, &ns);
183dbbdee94SGrant Likely 	of_node_put(parent);
184dbbdee94SGrant Likely 	if (!OF_CHECK_COUNTS(na, ns))
185dbbdee94SGrant Likely 		return NULL;
186dbbdee94SGrant Likely 
187dbbdee94SGrant Likely 	/* Get "reg" or "assigned-addresses" property */
188dbbdee94SGrant Likely 	prop = of_get_property(dev, bus->addresses, &psize);
189dbbdee94SGrant Likely 	if (prop == NULL)
190dbbdee94SGrant Likely 		return NULL;
191dbbdee94SGrant Likely 	psize /= 4;
192dbbdee94SGrant Likely 
193dbbdee94SGrant Likely 	onesize = na + ns;
194154063a9SGrant Likely 	for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) {
195154063a9SGrant Likely 		u32 val = be32_to_cpu(prop[0]);
196154063a9SGrant Likely 		if ((val & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
197dbbdee94SGrant Likely 			if (size)
198dbbdee94SGrant Likely 				*size = of_read_number(prop + na, ns);
199dbbdee94SGrant Likely 			if (flags)
200dbbdee94SGrant Likely 				*flags = bus->get_flags(prop);
201dbbdee94SGrant Likely 			return prop;
202dbbdee94SGrant Likely 		}
203154063a9SGrant Likely 	}
204dbbdee94SGrant Likely 	return NULL;
205dbbdee94SGrant Likely }
206dbbdee94SGrant Likely EXPORT_SYMBOL(of_get_pci_address);
207dbbdee94SGrant Likely 
208dbbdee94SGrant Likely int of_pci_address_to_resource(struct device_node *dev, int bar,
209dbbdee94SGrant Likely 			       struct resource *r)
210dbbdee94SGrant Likely {
2110131d897SSebastian Andrzej Siewior 	const __be32	*addrp;
212dbbdee94SGrant Likely 	u64		size;
213dbbdee94SGrant Likely 	unsigned int	flags;
214dbbdee94SGrant Likely 
215dbbdee94SGrant Likely 	addrp = of_get_pci_address(dev, bar, &size, &flags);
216dbbdee94SGrant Likely 	if (addrp == NULL)
217dbbdee94SGrant Likely 		return -EINVAL;
218dbbdee94SGrant Likely 	return __of_address_to_resource(dev, addrp, size, flags, r);
219dbbdee94SGrant Likely }
220dbbdee94SGrant Likely EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
221dbbdee94SGrant Likely #endif /* CONFIG_PCI */
222dbbdee94SGrant Likely 
223dbbdee94SGrant Likely /*
224dbbdee94SGrant Likely  * ISA bus specific translator
225dbbdee94SGrant Likely  */
226dbbdee94SGrant Likely 
227dbbdee94SGrant Likely static int of_bus_isa_match(struct device_node *np)
228dbbdee94SGrant Likely {
229dbbdee94SGrant Likely 	return !strcmp(np->name, "isa");
230dbbdee94SGrant Likely }
231dbbdee94SGrant Likely 
232dbbdee94SGrant Likely static void of_bus_isa_count_cells(struct device_node *child,
233dbbdee94SGrant Likely 				   int *addrc, int *sizec)
234dbbdee94SGrant Likely {
235dbbdee94SGrant Likely 	if (addrc)
236dbbdee94SGrant Likely 		*addrc = 2;
237dbbdee94SGrant Likely 	if (sizec)
238dbbdee94SGrant Likely 		*sizec = 1;
239dbbdee94SGrant Likely }
240dbbdee94SGrant Likely 
2410131d897SSebastian Andrzej Siewior static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns,
2420131d897SSebastian Andrzej Siewior 		int pna)
243dbbdee94SGrant Likely {
244dbbdee94SGrant Likely 	u64 cp, s, da;
245dbbdee94SGrant Likely 
246dbbdee94SGrant Likely 	/* Check address type match */
2470131d897SSebastian Andrzej Siewior 	if ((addr[0] ^ range[0]) & cpu_to_be32(1))
248dbbdee94SGrant Likely 		return OF_BAD_ADDR;
249dbbdee94SGrant Likely 
250dbbdee94SGrant Likely 	/* Read address values, skipping high cell */
251dbbdee94SGrant Likely 	cp = of_read_number(range + 1, na - 1);
252dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
253dbbdee94SGrant Likely 	da = of_read_number(addr + 1, na - 1);
254dbbdee94SGrant Likely 
255dbbdee94SGrant Likely 	pr_debug("OF: ISA map, cp=%llx, s=%llx, da=%llx\n",
256dbbdee94SGrant Likely 		 (unsigned long long)cp, (unsigned long long)s,
257dbbdee94SGrant Likely 		 (unsigned long long)da);
258dbbdee94SGrant Likely 
259dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
260dbbdee94SGrant Likely 		return OF_BAD_ADDR;
261dbbdee94SGrant Likely 	return da - cp;
262dbbdee94SGrant Likely }
263dbbdee94SGrant Likely 
264dbbdee94SGrant Likely static int of_bus_isa_translate(u32 *addr, u64 offset, int na)
265dbbdee94SGrant Likely {
266dbbdee94SGrant Likely 	return of_bus_default_translate(addr + 1, offset, na - 1);
267dbbdee94SGrant Likely }
268dbbdee94SGrant Likely 
2690131d897SSebastian Andrzej Siewior static unsigned int of_bus_isa_get_flags(const __be32 *addr)
270dbbdee94SGrant Likely {
271dbbdee94SGrant Likely 	unsigned int flags = 0;
2720131d897SSebastian Andrzej Siewior 	u32 w = be32_to_cpup(addr);
273dbbdee94SGrant Likely 
274dbbdee94SGrant Likely 	if (w & 1)
275dbbdee94SGrant Likely 		flags |= IORESOURCE_IO;
276dbbdee94SGrant Likely 	else
277dbbdee94SGrant Likely 		flags |= IORESOURCE_MEM;
278dbbdee94SGrant Likely 	return flags;
279dbbdee94SGrant Likely }
280dbbdee94SGrant Likely 
281dbbdee94SGrant Likely /*
282dbbdee94SGrant Likely  * Array of bus specific translators
283dbbdee94SGrant Likely  */
284dbbdee94SGrant Likely 
285dbbdee94SGrant Likely static struct of_bus of_busses[] = {
286dbbdee94SGrant Likely #ifdef CONFIG_PCI
287dbbdee94SGrant Likely 	/* PCI */
288dbbdee94SGrant Likely 	{
289dbbdee94SGrant Likely 		.name = "pci",
290dbbdee94SGrant Likely 		.addresses = "assigned-addresses",
291dbbdee94SGrant Likely 		.match = of_bus_pci_match,
292dbbdee94SGrant Likely 		.count_cells = of_bus_pci_count_cells,
293dbbdee94SGrant Likely 		.map = of_bus_pci_map,
294dbbdee94SGrant Likely 		.translate = of_bus_pci_translate,
295dbbdee94SGrant Likely 		.get_flags = of_bus_pci_get_flags,
296dbbdee94SGrant Likely 	},
297dbbdee94SGrant Likely #endif /* CONFIG_PCI */
298dbbdee94SGrant Likely 	/* ISA */
299dbbdee94SGrant Likely 	{
300dbbdee94SGrant Likely 		.name = "isa",
301dbbdee94SGrant Likely 		.addresses = "reg",
302dbbdee94SGrant Likely 		.match = of_bus_isa_match,
303dbbdee94SGrant Likely 		.count_cells = of_bus_isa_count_cells,
304dbbdee94SGrant Likely 		.map = of_bus_isa_map,
305dbbdee94SGrant Likely 		.translate = of_bus_isa_translate,
306dbbdee94SGrant Likely 		.get_flags = of_bus_isa_get_flags,
307dbbdee94SGrant Likely 	},
308dbbdee94SGrant Likely 	/* Default */
309dbbdee94SGrant Likely 	{
310dbbdee94SGrant Likely 		.name = "default",
311dbbdee94SGrant Likely 		.addresses = "reg",
312dbbdee94SGrant Likely 		.match = NULL,
313dbbdee94SGrant Likely 		.count_cells = of_bus_default_count_cells,
314dbbdee94SGrant Likely 		.map = of_bus_default_map,
315dbbdee94SGrant Likely 		.translate = of_bus_default_translate,
316dbbdee94SGrant Likely 		.get_flags = of_bus_default_get_flags,
317dbbdee94SGrant Likely 	},
318dbbdee94SGrant Likely };
319dbbdee94SGrant Likely 
320dbbdee94SGrant Likely static struct of_bus *of_match_bus(struct device_node *np)
321dbbdee94SGrant Likely {
322dbbdee94SGrant Likely 	int i;
323dbbdee94SGrant Likely 
324dbbdee94SGrant Likely 	for (i = 0; i < ARRAY_SIZE(of_busses); i++)
325dbbdee94SGrant Likely 		if (!of_busses[i].match || of_busses[i].match(np))
326dbbdee94SGrant Likely 			return &of_busses[i];
327dbbdee94SGrant Likely 	BUG();
328dbbdee94SGrant Likely 	return NULL;
329dbbdee94SGrant Likely }
330dbbdee94SGrant Likely 
331dbbdee94SGrant Likely static int of_translate_one(struct device_node *parent, struct of_bus *bus,
332dbbdee94SGrant Likely 			    struct of_bus *pbus, u32 *addr,
333dbbdee94SGrant Likely 			    int na, int ns, int pna, const char *rprop)
334dbbdee94SGrant Likely {
3350131d897SSebastian Andrzej Siewior 	const __be32 *ranges;
336dbbdee94SGrant Likely 	unsigned int rlen;
337dbbdee94SGrant Likely 	int rone;
338dbbdee94SGrant Likely 	u64 offset = OF_BAD_ADDR;
339dbbdee94SGrant Likely 
340dbbdee94SGrant Likely 	/* Normally, an absence of a "ranges" property means we are
341dbbdee94SGrant Likely 	 * crossing a non-translatable boundary, and thus the addresses
342dbbdee94SGrant Likely 	 * below the current not cannot be converted to CPU physical ones.
343dbbdee94SGrant Likely 	 * Unfortunately, while this is very clear in the spec, it's not
344dbbdee94SGrant Likely 	 * what Apple understood, and they do have things like /uni-n or
345dbbdee94SGrant Likely 	 * /ht nodes with no "ranges" property and a lot of perfectly
346dbbdee94SGrant Likely 	 * useable mapped devices below them. Thus we treat the absence of
347dbbdee94SGrant Likely 	 * "ranges" as equivalent to an empty "ranges" property which means
348dbbdee94SGrant Likely 	 * a 1:1 translation at that level. It's up to the caller not to try
349dbbdee94SGrant Likely 	 * to translate addresses that aren't supposed to be translated in
350dbbdee94SGrant Likely 	 * the first place. --BenH.
3513930f294SGrant Likely 	 *
3523930f294SGrant Likely 	 * As far as we know, this damage only exists on Apple machines, so
3533930f294SGrant Likely 	 * This code is only enabled on powerpc. --gcl
354dbbdee94SGrant Likely 	 */
355dbbdee94SGrant Likely 	ranges = of_get_property(parent, rprop, &rlen);
3563930f294SGrant Likely #if !defined(CONFIG_PPC)
3573930f294SGrant Likely 	if (ranges == NULL) {
3583930f294SGrant Likely 		pr_err("OF: no ranges; cannot translate\n");
3593930f294SGrant Likely 		return 1;
3603930f294SGrant Likely 	}
3613930f294SGrant Likely #endif /* !defined(CONFIG_PPC) */
362dbbdee94SGrant Likely 	if (ranges == NULL || rlen == 0) {
363dbbdee94SGrant Likely 		offset = of_read_number(addr, na);
364dbbdee94SGrant Likely 		memset(addr, 0, pna * 4);
3653930f294SGrant Likely 		pr_debug("OF: empty ranges; 1:1 translation\n");
366dbbdee94SGrant Likely 		goto finish;
367dbbdee94SGrant Likely 	}
368dbbdee94SGrant Likely 
369dbbdee94SGrant Likely 	pr_debug("OF: walking ranges...\n");
370dbbdee94SGrant Likely 
371dbbdee94SGrant Likely 	/* Now walk through the ranges */
372dbbdee94SGrant Likely 	rlen /= 4;
373dbbdee94SGrant Likely 	rone = na + pna + ns;
374dbbdee94SGrant Likely 	for (; rlen >= rone; rlen -= rone, ranges += rone) {
375dbbdee94SGrant Likely 		offset = bus->map(addr, ranges, na, ns, pna);
376dbbdee94SGrant Likely 		if (offset != OF_BAD_ADDR)
377dbbdee94SGrant Likely 			break;
378dbbdee94SGrant Likely 	}
379dbbdee94SGrant Likely 	if (offset == OF_BAD_ADDR) {
380dbbdee94SGrant Likely 		pr_debug("OF: not found !\n");
381dbbdee94SGrant Likely 		return 1;
382dbbdee94SGrant Likely 	}
383dbbdee94SGrant Likely 	memcpy(addr, ranges + na, 4 * pna);
384dbbdee94SGrant Likely 
385dbbdee94SGrant Likely  finish:
386dbbdee94SGrant Likely 	of_dump_addr("OF: parent translation for:", addr, pna);
387dbbdee94SGrant Likely 	pr_debug("OF: with offset: %llx\n", (unsigned long long)offset);
388dbbdee94SGrant Likely 
389dbbdee94SGrant Likely 	/* Translate it into parent bus space */
390dbbdee94SGrant Likely 	return pbus->translate(addr, offset, pna);
391dbbdee94SGrant Likely }
392dbbdee94SGrant Likely 
393dbbdee94SGrant Likely /*
394dbbdee94SGrant Likely  * Translate an address from the device-tree into a CPU physical address,
395dbbdee94SGrant Likely  * this walks up the tree and applies the various bus mappings on the
396dbbdee94SGrant Likely  * way.
397dbbdee94SGrant Likely  *
398dbbdee94SGrant Likely  * Note: We consider that crossing any level with #size-cells == 0 to mean
399dbbdee94SGrant Likely  * that translation is impossible (that is we are not dealing with a value
400dbbdee94SGrant Likely  * that can be mapped to a cpu physical address). This is not really specified
401dbbdee94SGrant Likely  * that way, but this is traditionally the way IBM at least do things
402dbbdee94SGrant Likely  */
4030131d897SSebastian Andrzej Siewior u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr,
404dbbdee94SGrant Likely 			   const char *rprop)
405dbbdee94SGrant Likely {
406dbbdee94SGrant Likely 	struct device_node *parent = NULL;
407dbbdee94SGrant Likely 	struct of_bus *bus, *pbus;
408dbbdee94SGrant Likely 	u32 addr[OF_MAX_ADDR_CELLS];
409dbbdee94SGrant Likely 	int na, ns, pna, pns;
410dbbdee94SGrant Likely 	u64 result = OF_BAD_ADDR;
411dbbdee94SGrant Likely 
412dbbdee94SGrant Likely 	pr_debug("OF: ** translation for device %s **\n", dev->full_name);
413dbbdee94SGrant Likely 
414dbbdee94SGrant Likely 	/* Increase refcount at current level */
415dbbdee94SGrant Likely 	of_node_get(dev);
416dbbdee94SGrant Likely 
417dbbdee94SGrant Likely 	/* Get parent & match bus type */
418dbbdee94SGrant Likely 	parent = of_get_parent(dev);
419dbbdee94SGrant Likely 	if (parent == NULL)
420dbbdee94SGrant Likely 		goto bail;
421dbbdee94SGrant Likely 	bus = of_match_bus(parent);
422dbbdee94SGrant Likely 
423dbbdee94SGrant Likely 	/* Cound address cells & copy address locally */
424dbbdee94SGrant Likely 	bus->count_cells(dev, &na, &ns);
425dbbdee94SGrant Likely 	if (!OF_CHECK_COUNTS(na, ns)) {
426dbbdee94SGrant Likely 		printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
427dbbdee94SGrant Likely 		       dev->full_name);
428dbbdee94SGrant Likely 		goto bail;
429dbbdee94SGrant Likely 	}
430dbbdee94SGrant Likely 	memcpy(addr, in_addr, na * 4);
431dbbdee94SGrant Likely 
432dbbdee94SGrant Likely 	pr_debug("OF: bus is %s (na=%d, ns=%d) on %s\n",
433dbbdee94SGrant Likely 	    bus->name, na, ns, parent->full_name);
434dbbdee94SGrant Likely 	of_dump_addr("OF: translating address:", addr, na);
435dbbdee94SGrant Likely 
436dbbdee94SGrant Likely 	/* Translate */
437dbbdee94SGrant Likely 	for (;;) {
438dbbdee94SGrant Likely 		/* Switch to parent bus */
439dbbdee94SGrant Likely 		of_node_put(dev);
440dbbdee94SGrant Likely 		dev = parent;
441dbbdee94SGrant Likely 		parent = of_get_parent(dev);
442dbbdee94SGrant Likely 
443dbbdee94SGrant Likely 		/* If root, we have finished */
444dbbdee94SGrant Likely 		if (parent == NULL) {
445dbbdee94SGrant Likely 			pr_debug("OF: reached root node\n");
446dbbdee94SGrant Likely 			result = of_read_number(addr, na);
447dbbdee94SGrant Likely 			break;
448dbbdee94SGrant Likely 		}
449dbbdee94SGrant Likely 
450dbbdee94SGrant Likely 		/* Get new parent bus and counts */
451dbbdee94SGrant Likely 		pbus = of_match_bus(parent);
452dbbdee94SGrant Likely 		pbus->count_cells(dev, &pna, &pns);
453dbbdee94SGrant Likely 		if (!OF_CHECK_COUNTS(pna, pns)) {
454dbbdee94SGrant Likely 			printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
455dbbdee94SGrant Likely 			       dev->full_name);
456dbbdee94SGrant Likely 			break;
457dbbdee94SGrant Likely 		}
458dbbdee94SGrant Likely 
459dbbdee94SGrant Likely 		pr_debug("OF: parent bus is %s (na=%d, ns=%d) on %s\n",
460dbbdee94SGrant Likely 		    pbus->name, pna, pns, parent->full_name);
461dbbdee94SGrant Likely 
462dbbdee94SGrant Likely 		/* Apply bus translation */
463dbbdee94SGrant Likely 		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
464dbbdee94SGrant Likely 			break;
465dbbdee94SGrant Likely 
466dbbdee94SGrant Likely 		/* Complete the move up one level */
467dbbdee94SGrant Likely 		na = pna;
468dbbdee94SGrant Likely 		ns = pns;
469dbbdee94SGrant Likely 		bus = pbus;
470dbbdee94SGrant Likely 
471dbbdee94SGrant Likely 		of_dump_addr("OF: one level translation:", addr, na);
472dbbdee94SGrant Likely 	}
473dbbdee94SGrant Likely  bail:
474dbbdee94SGrant Likely 	of_node_put(parent);
475dbbdee94SGrant Likely 	of_node_put(dev);
476dbbdee94SGrant Likely 
477dbbdee94SGrant Likely 	return result;
478dbbdee94SGrant Likely }
479dbbdee94SGrant Likely 
4800131d897SSebastian Andrzej Siewior u64 of_translate_address(struct device_node *dev, const __be32 *in_addr)
481dbbdee94SGrant Likely {
482dbbdee94SGrant Likely 	return __of_translate_address(dev, in_addr, "ranges");
483dbbdee94SGrant Likely }
484dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_address);
485dbbdee94SGrant Likely 
4860131d897SSebastian Andrzej Siewior u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
487dbbdee94SGrant Likely {
488dbbdee94SGrant Likely 	return __of_translate_address(dev, in_addr, "dma-ranges");
489dbbdee94SGrant Likely }
490dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_dma_address);
491dbbdee94SGrant Likely 
4920131d897SSebastian Andrzej Siewior const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
493dbbdee94SGrant Likely 		    unsigned int *flags)
494dbbdee94SGrant Likely {
4950131d897SSebastian Andrzej Siewior 	const __be32 *prop;
496dbbdee94SGrant Likely 	unsigned int psize;
497dbbdee94SGrant Likely 	struct device_node *parent;
498dbbdee94SGrant Likely 	struct of_bus *bus;
499dbbdee94SGrant Likely 	int onesize, i, na, ns;
500dbbdee94SGrant Likely 
501dbbdee94SGrant Likely 	/* Get parent & match bus type */
502dbbdee94SGrant Likely 	parent = of_get_parent(dev);
503dbbdee94SGrant Likely 	if (parent == NULL)
504dbbdee94SGrant Likely 		return NULL;
505dbbdee94SGrant Likely 	bus = of_match_bus(parent);
506dbbdee94SGrant Likely 	bus->count_cells(dev, &na, &ns);
507dbbdee94SGrant Likely 	of_node_put(parent);
508dbbdee94SGrant Likely 	if (!OF_CHECK_COUNTS(na, ns))
509dbbdee94SGrant Likely 		return NULL;
510dbbdee94SGrant Likely 
511dbbdee94SGrant Likely 	/* Get "reg" or "assigned-addresses" property */
512dbbdee94SGrant Likely 	prop = of_get_property(dev, bus->addresses, &psize);
513dbbdee94SGrant Likely 	if (prop == NULL)
514dbbdee94SGrant Likely 		return NULL;
515dbbdee94SGrant Likely 	psize /= 4;
516dbbdee94SGrant Likely 
517dbbdee94SGrant Likely 	onesize = na + ns;
518dbbdee94SGrant Likely 	for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
519dbbdee94SGrant Likely 		if (i == index) {
520dbbdee94SGrant Likely 			if (size)
521dbbdee94SGrant Likely 				*size = of_read_number(prop + na, ns);
522dbbdee94SGrant Likely 			if (flags)
523dbbdee94SGrant Likely 				*flags = bus->get_flags(prop);
524dbbdee94SGrant Likely 			return prop;
525dbbdee94SGrant Likely 		}
526dbbdee94SGrant Likely 	return NULL;
527dbbdee94SGrant Likely }
528dbbdee94SGrant Likely EXPORT_SYMBOL(of_get_address);
529dbbdee94SGrant Likely 
5300131d897SSebastian Andrzej Siewior static int __of_address_to_resource(struct device_node *dev,
5310131d897SSebastian Andrzej Siewior 		const __be32 *addrp, u64 size, unsigned int flags,
5321f5bef30SGrant Likely 				    struct resource *r)
5331f5bef30SGrant Likely {
5341f5bef30SGrant Likely 	u64 taddr;
5351f5bef30SGrant Likely 
5361f5bef30SGrant Likely 	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
5371f5bef30SGrant Likely 		return -EINVAL;
5381f5bef30SGrant Likely 	taddr = of_translate_address(dev, addrp);
5391f5bef30SGrant Likely 	if (taddr == OF_BAD_ADDR)
5401f5bef30SGrant Likely 		return -EINVAL;
5411f5bef30SGrant Likely 	memset(r, 0, sizeof(struct resource));
5421f5bef30SGrant Likely 	if (flags & IORESOURCE_IO) {
5431f5bef30SGrant Likely 		unsigned long port;
5441f5bef30SGrant Likely 		port = pci_address_to_pio(taddr);
5451f5bef30SGrant Likely 		if (port == (unsigned long)-1)
5461f5bef30SGrant Likely 			return -EINVAL;
5471f5bef30SGrant Likely 		r->start = port;
5481f5bef30SGrant Likely 		r->end = port + size - 1;
5491f5bef30SGrant Likely 	} else {
5501f5bef30SGrant Likely 		r->start = taddr;
5511f5bef30SGrant Likely 		r->end = taddr + size - 1;
5521f5bef30SGrant Likely 	}
5531f5bef30SGrant Likely 	r->flags = flags;
554d3571c3aSGrant Likely 	r->name = dev->full_name;
5551f5bef30SGrant Likely 	return 0;
5561f5bef30SGrant Likely }
5571f5bef30SGrant Likely 
5581f5bef30SGrant Likely /**
5591f5bef30SGrant Likely  * of_address_to_resource - Translate device tree address and return as resource
5601f5bef30SGrant Likely  *
5611f5bef30SGrant Likely  * Note that if your address is a PIO address, the conversion will fail if
5621f5bef30SGrant Likely  * the physical address can't be internally converted to an IO token with
5631f5bef30SGrant Likely  * pci_address_to_pio(), that is because it's either called to early or it
5641f5bef30SGrant Likely  * can't be matched to any host bridge IO space
5651f5bef30SGrant Likely  */
5661f5bef30SGrant Likely int of_address_to_resource(struct device_node *dev, int index,
5671f5bef30SGrant Likely 			   struct resource *r)
5681f5bef30SGrant Likely {
5690131d897SSebastian Andrzej Siewior 	const __be32	*addrp;
5701f5bef30SGrant Likely 	u64		size;
5711f5bef30SGrant Likely 	unsigned int	flags;
5721f5bef30SGrant Likely 
5731f5bef30SGrant Likely 	addrp = of_get_address(dev, index, &size, &flags);
5741f5bef30SGrant Likely 	if (addrp == NULL)
5751f5bef30SGrant Likely 		return -EINVAL;
5761f5bef30SGrant Likely 	return __of_address_to_resource(dev, addrp, size, flags, r);
5771f5bef30SGrant Likely }
5781f5bef30SGrant Likely EXPORT_SYMBOL_GPL(of_address_to_resource);
5791f5bef30SGrant Likely 
58090e33f62SGrant Likely struct device_node *of_find_matching_node_by_address(struct device_node *from,
58190e33f62SGrant Likely 					const struct of_device_id *matches,
58290e33f62SGrant Likely 					u64 base_address)
58390e33f62SGrant Likely {
58490e33f62SGrant Likely 	struct device_node *dn = of_find_matching_node(from, matches);
58590e33f62SGrant Likely 	struct resource res;
58690e33f62SGrant Likely 
58790e33f62SGrant Likely 	while (dn) {
58890e33f62SGrant Likely 		if (of_address_to_resource(dn, 0, &res))
58990e33f62SGrant Likely 			continue;
59090e33f62SGrant Likely 		if (res.start == base_address)
59190e33f62SGrant Likely 			return dn;
59290e33f62SGrant Likely 		dn = of_find_matching_node(dn, matches);
59390e33f62SGrant Likely 	}
59490e33f62SGrant Likely 
59590e33f62SGrant Likely 	return NULL;
59690e33f62SGrant Likely }
59790e33f62SGrant Likely 
5981f5bef30SGrant Likely 
5996b884a8dSGrant Likely /**
6006b884a8dSGrant Likely  * of_iomap - Maps the memory mapped IO for a given device_node
6016b884a8dSGrant Likely  * @device:	the device whose io range will be mapped
6026b884a8dSGrant Likely  * @index:	index of the io range
6036b884a8dSGrant Likely  *
6046b884a8dSGrant Likely  * Returns a pointer to the mapped memory
6056b884a8dSGrant Likely  */
6066b884a8dSGrant Likely void __iomem *of_iomap(struct device_node *np, int index)
6076b884a8dSGrant Likely {
6086b884a8dSGrant Likely 	struct resource res;
6096b884a8dSGrant Likely 
6106b884a8dSGrant Likely 	if (of_address_to_resource(np, index, &res))
6116b884a8dSGrant Likely 		return NULL;
6126b884a8dSGrant Likely 
61328c1b6d6SFelipe Balbi 	return ioremap(res.start, resource_size(&res));
6146b884a8dSGrant Likely }
6156b884a8dSGrant Likely EXPORT_SYMBOL(of_iomap);
616