xref: /openbmc/linux/drivers/of/address.c (revision f49c7faf)
1af6074fcSRob Herring // SPDX-License-Identifier: GPL-2.0
2606ad42aSRob Herring #define pr_fmt(fmt)	"OF: " fmt
3606ad42aSRob Herring 
45019f0b1SArnd Bergmann #include <linux/device.h>
5fcfaab30SGabriele Paoloni #include <linux/fwnode.h>
66b884a8dSGrant Likely #include <linux/io.h>
76b884a8dSGrant Likely #include <linux/ioport.h>
865af618dSZhichang Yuan #include <linux/logic_pio.h>
9dbbdee94SGrant Likely #include <linux/module.h>
106b884a8dSGrant Likely #include <linux/of_address.h>
11c5076cfeSTomasz Nowicki #include <linux/pci.h>
12dbbdee94SGrant Likely #include <linux/pci_regs.h>
1341f8bba7SLiviu Dudau #include <linux/sizes.h>
1441f8bba7SLiviu Dudau #include <linux/slab.h>
15dbbdee94SGrant Likely #include <linux/string.h>
166b884a8dSGrant Likely 
17b68ac8dcSRobin Murphy #include "of_private.h"
18b68ac8dcSRobin Murphy 
19dbbdee94SGrant Likely /* Max address size we deal with */
20dbbdee94SGrant Likely #define OF_MAX_ADDR_CELLS	4
215d61b165SStephen Warren #define OF_CHECK_ADDR_COUNT(na)	((na) > 0 && (na) <= OF_MAX_ADDR_CELLS)
225d61b165SStephen Warren #define OF_CHECK_COUNTS(na, ns)	(OF_CHECK_ADDR_COUNT(na) && (ns) > 0)
23dbbdee94SGrant Likely 
24dbbdee94SGrant Likely static struct of_bus *of_match_bus(struct device_node *np);
250131d897SSebastian Andrzej Siewior static int __of_address_to_resource(struct device_node *dev,
260131d897SSebastian Andrzej Siewior 		const __be32 *addrp, u64 size, unsigned int flags,
2735f3da32SBenoit Cousson 		const char *name, struct resource *r);
28dbbdee94SGrant Likely 
29dbbdee94SGrant Likely /* Debug utility */
30dbbdee94SGrant Likely #ifdef DEBUG
310131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na)
32dbbdee94SGrant Likely {
33606ad42aSRob Herring 	pr_debug("%s", s);
34dbbdee94SGrant Likely 	while (na--)
35606ad42aSRob Herring 		pr_cont(" %08x", be32_to_cpu(*(addr++)));
36606ad42aSRob Herring 	pr_cont("\n");
37dbbdee94SGrant Likely }
38dbbdee94SGrant Likely #else
390131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na) { }
40dbbdee94SGrant Likely #endif
41dbbdee94SGrant Likely 
42dbbdee94SGrant Likely /* Callbacks for bus specific translators */
43dbbdee94SGrant Likely struct of_bus {
44dbbdee94SGrant Likely 	const char	*name;
45dbbdee94SGrant Likely 	const char	*addresses;
46dbbdee94SGrant Likely 	int		(*match)(struct device_node *parent);
47dbbdee94SGrant Likely 	void		(*count_cells)(struct device_node *child,
48dbbdee94SGrant Likely 				       int *addrc, int *sizec);
4947b1e689SKim Phillips 	u64		(*map)(__be32 *addr, const __be32 *range,
50dbbdee94SGrant Likely 				int na, int ns, int pna);
5147b1e689SKim Phillips 	int		(*translate)(__be32 *addr, u64 offset, int na);
522f96593eSJiaxun Yang 	bool	has_flags;
530131d897SSebastian Andrzej Siewior 	unsigned int	(*get_flags)(const __be32 *addr);
54dbbdee94SGrant Likely };
55dbbdee94SGrant Likely 
56dbbdee94SGrant Likely /*
57dbbdee94SGrant Likely  * Default translator (generic bus)
58dbbdee94SGrant Likely  */
59dbbdee94SGrant Likely 
60dbbdee94SGrant Likely static void of_bus_default_count_cells(struct device_node *dev,
61dbbdee94SGrant Likely 				       int *addrc, int *sizec)
62dbbdee94SGrant Likely {
63dbbdee94SGrant Likely 	if (addrc)
64dbbdee94SGrant Likely 		*addrc = of_n_addr_cells(dev);
65dbbdee94SGrant Likely 	if (sizec)
66dbbdee94SGrant Likely 		*sizec = of_n_size_cells(dev);
67dbbdee94SGrant Likely }
68dbbdee94SGrant Likely 
6947b1e689SKim Phillips static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
70dbbdee94SGrant Likely 		int na, int ns, int pna)
71dbbdee94SGrant Likely {
72dbbdee94SGrant Likely 	u64 cp, s, da;
73dbbdee94SGrant Likely 
74dbbdee94SGrant Likely 	cp = of_read_number(range, na);
75dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
76dbbdee94SGrant Likely 	da = of_read_number(addr, na);
77dbbdee94SGrant Likely 
78606ad42aSRob Herring 	pr_debug("default map, cp=%llx, s=%llx, da=%llx\n",
79dbbdee94SGrant Likely 		 (unsigned long long)cp, (unsigned long long)s,
80dbbdee94SGrant Likely 		 (unsigned long long)da);
81dbbdee94SGrant Likely 
82dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
83dbbdee94SGrant Likely 		return OF_BAD_ADDR;
84dbbdee94SGrant Likely 	return da - cp;
85dbbdee94SGrant Likely }
86dbbdee94SGrant Likely 
8747b1e689SKim Phillips static int of_bus_default_translate(__be32 *addr, u64 offset, int na)
88dbbdee94SGrant Likely {
89dbbdee94SGrant Likely 	u64 a = of_read_number(addr, na);
90dbbdee94SGrant Likely 	memset(addr, 0, na * 4);
91dbbdee94SGrant Likely 	a += offset;
92dbbdee94SGrant Likely 	if (na > 1)
93154063a9SGrant Likely 		addr[na - 2] = cpu_to_be32(a >> 32);
94154063a9SGrant Likely 	addr[na - 1] = cpu_to_be32(a & 0xffffffffu);
95dbbdee94SGrant Likely 
96dbbdee94SGrant Likely 	return 0;
97dbbdee94SGrant Likely }
98dbbdee94SGrant Likely 
990131d897SSebastian Andrzej Siewior static unsigned int of_bus_default_get_flags(const __be32 *addr)
100dbbdee94SGrant Likely {
101dbbdee94SGrant Likely 	return IORESOURCE_MEM;
102dbbdee94SGrant Likely }
103dbbdee94SGrant Likely 
1040fc0ead3SJiaxun Yang #ifdef CONFIG_PCI
10567ccd2b9SRob Herring static unsigned int of_bus_pci_get_flags(const __be32 *addr)
10667ccd2b9SRob Herring {
10767ccd2b9SRob Herring 	unsigned int flags = 0;
10867ccd2b9SRob Herring 	u32 w = be32_to_cpup(addr);
10967ccd2b9SRob Herring 
11067ccd2b9SRob Herring 	if (!IS_ENABLED(CONFIG_PCI))
11167ccd2b9SRob Herring 		return 0;
11267ccd2b9SRob Herring 
11367ccd2b9SRob Herring 	switch((w >> 24) & 0x03) {
11467ccd2b9SRob Herring 	case 0x01:
11567ccd2b9SRob Herring 		flags |= IORESOURCE_IO;
11667ccd2b9SRob Herring 		break;
11767ccd2b9SRob Herring 	case 0x02: /* 32 bits */
11867ccd2b9SRob Herring 	case 0x03: /* 64 bits */
11967ccd2b9SRob Herring 		flags |= IORESOURCE_MEM;
12067ccd2b9SRob Herring 		break;
12167ccd2b9SRob Herring 	}
12267ccd2b9SRob Herring 	if (w & 0x40000000)
12367ccd2b9SRob Herring 		flags |= IORESOURCE_PREFETCH;
12467ccd2b9SRob Herring 	return flags;
12567ccd2b9SRob Herring }
12667ccd2b9SRob Herring 
127dbbdee94SGrant Likely /*
128dbbdee94SGrant Likely  * PCI bus specific translator
129dbbdee94SGrant Likely  */
130dbbdee94SGrant Likely 
131dbbdee94SGrant Likely static int of_bus_pci_match(struct device_node *np)
132dbbdee94SGrant Likely {
1336dd18e46SBenjamin Herrenschmidt 	/*
13414e2abb7SKleber Sacilotto de Souza  	 * "pciex" is PCI Express
1356dd18e46SBenjamin Herrenschmidt 	 * "vci" is for the /chaos bridge on 1st-gen PCI powermacs
1366dd18e46SBenjamin Herrenschmidt 	 * "ht" is hypertransport
1376dd18e46SBenjamin Herrenschmidt 	 */
138e8b1dee2SRob Herring 	return of_node_is_type(np, "pci") || of_node_is_type(np, "pciex") ||
139e8b1dee2SRob Herring 		of_node_is_type(np, "vci") || of_node_is_type(np, "ht");
140dbbdee94SGrant Likely }
141dbbdee94SGrant Likely 
142dbbdee94SGrant Likely static void of_bus_pci_count_cells(struct device_node *np,
143dbbdee94SGrant Likely 				   int *addrc, int *sizec)
144dbbdee94SGrant Likely {
145dbbdee94SGrant Likely 	if (addrc)
146dbbdee94SGrant Likely 		*addrc = 3;
147dbbdee94SGrant Likely 	if (sizec)
148dbbdee94SGrant Likely 		*sizec = 2;
149dbbdee94SGrant Likely }
150dbbdee94SGrant Likely 
15147b1e689SKim Phillips static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns,
1520131d897SSebastian Andrzej Siewior 		int pna)
153dbbdee94SGrant Likely {
154dbbdee94SGrant Likely 	u64 cp, s, da;
155dbbdee94SGrant Likely 	unsigned int af, rf;
156dbbdee94SGrant Likely 
157dbbdee94SGrant Likely 	af = of_bus_pci_get_flags(addr);
158dbbdee94SGrant Likely 	rf = of_bus_pci_get_flags(range);
159dbbdee94SGrant Likely 
160dbbdee94SGrant Likely 	/* Check address type match */
161dbbdee94SGrant Likely 	if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO))
162dbbdee94SGrant Likely 		return OF_BAD_ADDR;
163dbbdee94SGrant Likely 
164dbbdee94SGrant Likely 	/* Read address values, skipping high cell */
165dbbdee94SGrant Likely 	cp = of_read_number(range + 1, na - 1);
166dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
167dbbdee94SGrant Likely 	da = of_read_number(addr + 1, na - 1);
168dbbdee94SGrant Likely 
169606ad42aSRob Herring 	pr_debug("PCI map, cp=%llx, s=%llx, da=%llx\n",
170dbbdee94SGrant Likely 		 (unsigned long long)cp, (unsigned long long)s,
171dbbdee94SGrant Likely 		 (unsigned long long)da);
172dbbdee94SGrant Likely 
173dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
174dbbdee94SGrant Likely 		return OF_BAD_ADDR;
175dbbdee94SGrant Likely 	return da - cp;
176dbbdee94SGrant Likely }
177dbbdee94SGrant Likely 
17847b1e689SKim Phillips static int of_bus_pci_translate(__be32 *addr, u64 offset, int na)
179dbbdee94SGrant Likely {
180dbbdee94SGrant Likely 	return of_bus_default_translate(addr + 1, offset, na - 1);
181dbbdee94SGrant Likely }
182dbbdee94SGrant Likely 
1830131d897SSebastian Andrzej Siewior const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
184dbbdee94SGrant Likely 			unsigned int *flags)
185dbbdee94SGrant Likely {
186a9fadeefSJeremy Kerr 	const __be32 *prop;
187dbbdee94SGrant Likely 	unsigned int psize;
188dbbdee94SGrant Likely 	struct device_node *parent;
189dbbdee94SGrant Likely 	struct of_bus *bus;
190dbbdee94SGrant Likely 	int onesize, i, na, ns;
191dbbdee94SGrant Likely 
192dbbdee94SGrant Likely 	/* Get parent & match bus type */
193dbbdee94SGrant Likely 	parent = of_get_parent(dev);
194dbbdee94SGrant Likely 	if (parent == NULL)
195dbbdee94SGrant Likely 		return NULL;
196dbbdee94SGrant Likely 	bus = of_match_bus(parent);
197dbbdee94SGrant Likely 	if (strcmp(bus->name, "pci")) {
198dbbdee94SGrant Likely 		of_node_put(parent);
199dbbdee94SGrant Likely 		return NULL;
200dbbdee94SGrant Likely 	}
201dbbdee94SGrant Likely 	bus->count_cells(dev, &na, &ns);
202dbbdee94SGrant Likely 	of_node_put(parent);
2035d61b165SStephen Warren 	if (!OF_CHECK_ADDR_COUNT(na))
204dbbdee94SGrant Likely 		return NULL;
205dbbdee94SGrant Likely 
206dbbdee94SGrant Likely 	/* Get "reg" or "assigned-addresses" property */
207dbbdee94SGrant Likely 	prop = of_get_property(dev, bus->addresses, &psize);
208dbbdee94SGrant Likely 	if (prop == NULL)
209dbbdee94SGrant Likely 		return NULL;
210dbbdee94SGrant Likely 	psize /= 4;
211dbbdee94SGrant Likely 
212dbbdee94SGrant Likely 	onesize = na + ns;
213154063a9SGrant Likely 	for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) {
214154063a9SGrant Likely 		u32 val = be32_to_cpu(prop[0]);
215154063a9SGrant Likely 		if ((val & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
216dbbdee94SGrant Likely 			if (size)
217dbbdee94SGrant Likely 				*size = of_read_number(prop + na, ns);
218dbbdee94SGrant Likely 			if (flags)
219dbbdee94SGrant Likely 				*flags = bus->get_flags(prop);
220dbbdee94SGrant Likely 			return prop;
221dbbdee94SGrant Likely 		}
222154063a9SGrant Likely 	}
223dbbdee94SGrant Likely 	return NULL;
224dbbdee94SGrant Likely }
225dbbdee94SGrant Likely EXPORT_SYMBOL(of_get_pci_address);
226dbbdee94SGrant Likely 
227dbbdee94SGrant Likely int of_pci_address_to_resource(struct device_node *dev, int bar,
228dbbdee94SGrant Likely 			       struct resource *r)
229dbbdee94SGrant Likely {
2300131d897SSebastian Andrzej Siewior 	const __be32	*addrp;
231dbbdee94SGrant Likely 	u64		size;
232dbbdee94SGrant Likely 	unsigned int	flags;
233dbbdee94SGrant Likely 
234dbbdee94SGrant Likely 	addrp = of_get_pci_address(dev, bar, &size, &flags);
235dbbdee94SGrant Likely 	if (addrp == NULL)
236dbbdee94SGrant Likely 		return -EINVAL;
23735f3da32SBenoit Cousson 	return __of_address_to_resource(dev, addrp, size, flags, NULL, r);
238dbbdee94SGrant Likely }
239dbbdee94SGrant Likely EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
24029b635c0SAndrew Murray 
2410b0b0893SLiviu Dudau /*
2420b0b0893SLiviu Dudau  * of_pci_range_to_resource - Create a resource from an of_pci_range
2430b0b0893SLiviu Dudau  * @range:	the PCI range that describes the resource
2440b0b0893SLiviu Dudau  * @np:		device node where the range belongs to
2450b0b0893SLiviu Dudau  * @res:	pointer to a valid resource that will be updated to
2460b0b0893SLiviu Dudau  *              reflect the values contained in the range.
2470b0b0893SLiviu Dudau  *
2480b0b0893SLiviu Dudau  * Returns EINVAL if the range cannot be converted to resource.
2490b0b0893SLiviu Dudau  *
2500b0b0893SLiviu Dudau  * Note that if the range is an IO range, the resource will be converted
2510b0b0893SLiviu Dudau  * using pci_address_to_pio() which can fail if it is called too early or
2520b0b0893SLiviu Dudau  * if the range cannot be matched to any host bridge IO space (our case here).
2530b0b0893SLiviu Dudau  * To guard against that we try to register the IO range first.
2540b0b0893SLiviu Dudau  * If that fails we know that pci_address_to_pio() will do too.
2550b0b0893SLiviu Dudau  */
2560b0b0893SLiviu Dudau int of_pci_range_to_resource(struct of_pci_range *range,
25783bbde1cSLiviu Dudau 			     struct device_node *np, struct resource *res)
25883bbde1cSLiviu Dudau {
2590b0b0893SLiviu Dudau 	int err;
26083bbde1cSLiviu Dudau 	res->flags = range->flags;
26183bbde1cSLiviu Dudau 	res->parent = res->child = res->sibling = NULL;
26283bbde1cSLiviu Dudau 	res->name = np->full_name;
2630b0b0893SLiviu Dudau 
2640b0b0893SLiviu Dudau 	if (res->flags & IORESOURCE_IO) {
2650b0b0893SLiviu Dudau 		unsigned long port;
266fcfaab30SGabriele Paoloni 		err = pci_register_io_range(&np->fwnode, range->cpu_addr,
267fcfaab30SGabriele Paoloni 				range->size);
2680b0b0893SLiviu Dudau 		if (err)
2690b0b0893SLiviu Dudau 			goto invalid_range;
2700b0b0893SLiviu Dudau 		port = pci_address_to_pio(range->cpu_addr);
2710b0b0893SLiviu Dudau 		if (port == (unsigned long)-1) {
2720b0b0893SLiviu Dudau 			err = -EINVAL;
2730b0b0893SLiviu Dudau 			goto invalid_range;
2740b0b0893SLiviu Dudau 		}
2750b0b0893SLiviu Dudau 		res->start = port;
2760b0b0893SLiviu Dudau 	} else {
2774af97106SPavel Fedin 		if ((sizeof(resource_size_t) < 8) &&
2784af97106SPavel Fedin 		    upper_32_bits(range->cpu_addr)) {
2794af97106SPavel Fedin 			err = -EINVAL;
2804af97106SPavel Fedin 			goto invalid_range;
2814af97106SPavel Fedin 		}
2824af97106SPavel Fedin 
2830b0b0893SLiviu Dudau 		res->start = range->cpu_addr;
2840b0b0893SLiviu Dudau 	}
2850b0b0893SLiviu Dudau 	res->end = res->start + range->size - 1;
2860b0b0893SLiviu Dudau 	return 0;
2870b0b0893SLiviu Dudau 
2880b0b0893SLiviu Dudau invalid_range:
2890b0b0893SLiviu Dudau 	res->start = (resource_size_t)OF_BAD_ADDR;
2900b0b0893SLiviu Dudau 	res->end = (resource_size_t)OF_BAD_ADDR;
2910b0b0893SLiviu Dudau 	return err;
29283bbde1cSLiviu Dudau }
293bf6681eaSManikanta Maddireddy EXPORT_SYMBOL(of_pci_range_to_resource);
294dbbdee94SGrant Likely #endif /* CONFIG_PCI */
295dbbdee94SGrant Likely 
296dbbdee94SGrant Likely /*
297dbbdee94SGrant Likely  * ISA bus specific translator
298dbbdee94SGrant Likely  */
299dbbdee94SGrant Likely 
300dbbdee94SGrant Likely static int of_bus_isa_match(struct device_node *np)
301dbbdee94SGrant Likely {
302b3e46d1aSRob Herring 	return of_node_name_eq(np, "isa");
303dbbdee94SGrant Likely }
304dbbdee94SGrant Likely 
305dbbdee94SGrant Likely static void of_bus_isa_count_cells(struct device_node *child,
306dbbdee94SGrant Likely 				   int *addrc, int *sizec)
307dbbdee94SGrant Likely {
308dbbdee94SGrant Likely 	if (addrc)
309dbbdee94SGrant Likely 		*addrc = 2;
310dbbdee94SGrant Likely 	if (sizec)
311dbbdee94SGrant Likely 		*sizec = 1;
312dbbdee94SGrant Likely }
313dbbdee94SGrant Likely 
31447b1e689SKim Phillips static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns,
3150131d897SSebastian Andrzej Siewior 		int pna)
316dbbdee94SGrant Likely {
317dbbdee94SGrant Likely 	u64 cp, s, da;
318dbbdee94SGrant Likely 
319dbbdee94SGrant Likely 	/* Check address type match */
3200131d897SSebastian Andrzej Siewior 	if ((addr[0] ^ range[0]) & cpu_to_be32(1))
321dbbdee94SGrant Likely 		return OF_BAD_ADDR;
322dbbdee94SGrant Likely 
323dbbdee94SGrant Likely 	/* Read address values, skipping high cell */
324dbbdee94SGrant Likely 	cp = of_read_number(range + 1, na - 1);
325dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
326dbbdee94SGrant Likely 	da = of_read_number(addr + 1, na - 1);
327dbbdee94SGrant Likely 
328606ad42aSRob Herring 	pr_debug("ISA map, cp=%llx, s=%llx, da=%llx\n",
329dbbdee94SGrant Likely 		 (unsigned long long)cp, (unsigned long long)s,
330dbbdee94SGrant Likely 		 (unsigned long long)da);
331dbbdee94SGrant Likely 
332dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
333dbbdee94SGrant Likely 		return OF_BAD_ADDR;
334dbbdee94SGrant Likely 	return da - cp;
335dbbdee94SGrant Likely }
336dbbdee94SGrant Likely 
33747b1e689SKim Phillips static int of_bus_isa_translate(__be32 *addr, u64 offset, int na)
338dbbdee94SGrant Likely {
339dbbdee94SGrant Likely 	return of_bus_default_translate(addr + 1, offset, na - 1);
340dbbdee94SGrant Likely }
341dbbdee94SGrant Likely 
3420131d897SSebastian Andrzej Siewior static unsigned int of_bus_isa_get_flags(const __be32 *addr)
343dbbdee94SGrant Likely {
344dbbdee94SGrant Likely 	unsigned int flags = 0;
3450131d897SSebastian Andrzej Siewior 	u32 w = be32_to_cpup(addr);
346dbbdee94SGrant Likely 
347dbbdee94SGrant Likely 	if (w & 1)
348dbbdee94SGrant Likely 		flags |= IORESOURCE_IO;
349dbbdee94SGrant Likely 	else
350dbbdee94SGrant Likely 		flags |= IORESOURCE_MEM;
351dbbdee94SGrant Likely 	return flags;
352dbbdee94SGrant Likely }
353dbbdee94SGrant Likely 
354dbbdee94SGrant Likely /*
355dbbdee94SGrant Likely  * Array of bus specific translators
356dbbdee94SGrant Likely  */
357dbbdee94SGrant Likely 
358dbbdee94SGrant Likely static struct of_bus of_busses[] = {
3594670d610SRob Herring #ifdef CONFIG_PCI
360dbbdee94SGrant Likely 	/* PCI */
361dbbdee94SGrant Likely 	{
362dbbdee94SGrant Likely 		.name = "pci",
363dbbdee94SGrant Likely 		.addresses = "assigned-addresses",
364dbbdee94SGrant Likely 		.match = of_bus_pci_match,
365dbbdee94SGrant Likely 		.count_cells = of_bus_pci_count_cells,
366dbbdee94SGrant Likely 		.map = of_bus_pci_map,
367dbbdee94SGrant Likely 		.translate = of_bus_pci_translate,
3682f96593eSJiaxun Yang 		.has_flags = true,
369dbbdee94SGrant Likely 		.get_flags = of_bus_pci_get_flags,
370dbbdee94SGrant Likely 	},
3714670d610SRob Herring #endif /* CONFIG_PCI */
372dbbdee94SGrant Likely 	/* ISA */
373dbbdee94SGrant Likely 	{
374dbbdee94SGrant Likely 		.name = "isa",
375dbbdee94SGrant Likely 		.addresses = "reg",
376dbbdee94SGrant Likely 		.match = of_bus_isa_match,
377dbbdee94SGrant Likely 		.count_cells = of_bus_isa_count_cells,
378dbbdee94SGrant Likely 		.map = of_bus_isa_map,
379dbbdee94SGrant Likely 		.translate = of_bus_isa_translate,
3802f96593eSJiaxun Yang 		.has_flags = true,
381dbbdee94SGrant Likely 		.get_flags = of_bus_isa_get_flags,
382dbbdee94SGrant Likely 	},
383dbbdee94SGrant Likely 	/* Default */
384dbbdee94SGrant Likely 	{
385dbbdee94SGrant Likely 		.name = "default",
386dbbdee94SGrant Likely 		.addresses = "reg",
387dbbdee94SGrant Likely 		.match = NULL,
388dbbdee94SGrant Likely 		.count_cells = of_bus_default_count_cells,
389dbbdee94SGrant Likely 		.map = of_bus_default_map,
390dbbdee94SGrant Likely 		.translate = of_bus_default_translate,
391dbbdee94SGrant Likely 		.get_flags = of_bus_default_get_flags,
392dbbdee94SGrant Likely 	},
393dbbdee94SGrant Likely };
394dbbdee94SGrant Likely 
395dbbdee94SGrant Likely static struct of_bus *of_match_bus(struct device_node *np)
396dbbdee94SGrant Likely {
397dbbdee94SGrant Likely 	int i;
398dbbdee94SGrant Likely 
399dbbdee94SGrant Likely 	for (i = 0; i < ARRAY_SIZE(of_busses); i++)
400dbbdee94SGrant Likely 		if (!of_busses[i].match || of_busses[i].match(np))
401dbbdee94SGrant Likely 			return &of_busses[i];
402dbbdee94SGrant Likely 	BUG();
403dbbdee94SGrant Likely 	return NULL;
404dbbdee94SGrant Likely }
405dbbdee94SGrant Likely 
40641d94893SBenjamin Herrenschmidt static int of_empty_ranges_quirk(struct device_node *np)
407746c9e9fSBenjamin Herrenschmidt {
408746c9e9fSBenjamin Herrenschmidt 	if (IS_ENABLED(CONFIG_PPC)) {
40941d94893SBenjamin Herrenschmidt 		/* To save cycles, we cache the result for global "Mac" setting */
410746c9e9fSBenjamin Herrenschmidt 		static int quirk_state = -1;
411746c9e9fSBenjamin Herrenschmidt 
41241d94893SBenjamin Herrenschmidt 		/* PA-SEMI sdc DT bug */
41341d94893SBenjamin Herrenschmidt 		if (of_device_is_compatible(np, "1682m-sdc"))
41441d94893SBenjamin Herrenschmidt 			return true;
41541d94893SBenjamin Herrenschmidt 
41641d94893SBenjamin Herrenschmidt 		/* Make quirk cached */
417746c9e9fSBenjamin Herrenschmidt 		if (quirk_state < 0)
418746c9e9fSBenjamin Herrenschmidt 			quirk_state =
419746c9e9fSBenjamin Herrenschmidt 				of_machine_is_compatible("Power Macintosh") ||
420746c9e9fSBenjamin Herrenschmidt 				of_machine_is_compatible("MacRISC");
421746c9e9fSBenjamin Herrenschmidt 		return quirk_state;
422746c9e9fSBenjamin Herrenschmidt 	}
423746c9e9fSBenjamin Herrenschmidt 	return false;
424746c9e9fSBenjamin Herrenschmidt }
425746c9e9fSBenjamin Herrenschmidt 
426dbbdee94SGrant Likely static int of_translate_one(struct device_node *parent, struct of_bus *bus,
42747b1e689SKim Phillips 			    struct of_bus *pbus, __be32 *addr,
428dbbdee94SGrant Likely 			    int na, int ns, int pna, const char *rprop)
429dbbdee94SGrant Likely {
4300131d897SSebastian Andrzej Siewior 	const __be32 *ranges;
431dbbdee94SGrant Likely 	unsigned int rlen;
432dbbdee94SGrant Likely 	int rone;
433dbbdee94SGrant Likely 	u64 offset = OF_BAD_ADDR;
434dbbdee94SGrant Likely 
435ba85edbeSMasahiro Yamada 	/*
436ba85edbeSMasahiro Yamada 	 * Normally, an absence of a "ranges" property means we are
437dbbdee94SGrant Likely 	 * crossing a non-translatable boundary, and thus the addresses
438ba85edbeSMasahiro Yamada 	 * below the current cannot be converted to CPU physical ones.
439dbbdee94SGrant Likely 	 * Unfortunately, while this is very clear in the spec, it's not
440dbbdee94SGrant Likely 	 * what Apple understood, and they do have things like /uni-n or
441dbbdee94SGrant Likely 	 * /ht nodes with no "ranges" property and a lot of perfectly
442dbbdee94SGrant Likely 	 * useable mapped devices below them. Thus we treat the absence of
443dbbdee94SGrant Likely 	 * "ranges" as equivalent to an empty "ranges" property which means
444dbbdee94SGrant Likely 	 * a 1:1 translation at that level. It's up to the caller not to try
445dbbdee94SGrant Likely 	 * to translate addresses that aren't supposed to be translated in
446dbbdee94SGrant Likely 	 * the first place. --BenH.
4473930f294SGrant Likely 	 *
4483930f294SGrant Likely 	 * As far as we know, this damage only exists on Apple machines, so
4493930f294SGrant Likely 	 * This code is only enabled on powerpc. --gcl
45081db12eeSRob Herring 	 *
45181db12eeSRob Herring 	 * This quirk also applies for 'dma-ranges' which frequently exist in
45281db12eeSRob Herring 	 * child nodes without 'dma-ranges' in the parent nodes. --RobH
453dbbdee94SGrant Likely 	 */
454dbbdee94SGrant Likely 	ranges = of_get_property(parent, rprop, &rlen);
45581db12eeSRob Herring 	if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
45681db12eeSRob Herring 	    strcmp(rprop, "dma-ranges")) {
457606ad42aSRob Herring 		pr_debug("no ranges; cannot translate\n");
4583930f294SGrant Likely 		return 1;
4593930f294SGrant Likely 	}
460dbbdee94SGrant Likely 	if (ranges == NULL || rlen == 0) {
461dbbdee94SGrant Likely 		offset = of_read_number(addr, na);
462dbbdee94SGrant Likely 		memset(addr, 0, pna * 4);
463606ad42aSRob Herring 		pr_debug("empty ranges; 1:1 translation\n");
464dbbdee94SGrant Likely 		goto finish;
465dbbdee94SGrant Likely 	}
466dbbdee94SGrant Likely 
467606ad42aSRob Herring 	pr_debug("walking ranges...\n");
468dbbdee94SGrant Likely 
469dbbdee94SGrant Likely 	/* Now walk through the ranges */
470dbbdee94SGrant Likely 	rlen /= 4;
471dbbdee94SGrant Likely 	rone = na + pna + ns;
472dbbdee94SGrant Likely 	for (; rlen >= rone; rlen -= rone, ranges += rone) {
473dbbdee94SGrant Likely 		offset = bus->map(addr, ranges, na, ns, pna);
474dbbdee94SGrant Likely 		if (offset != OF_BAD_ADDR)
475dbbdee94SGrant Likely 			break;
476dbbdee94SGrant Likely 	}
477dbbdee94SGrant Likely 	if (offset == OF_BAD_ADDR) {
478606ad42aSRob Herring 		pr_debug("not found !\n");
479dbbdee94SGrant Likely 		return 1;
480dbbdee94SGrant Likely 	}
481dbbdee94SGrant Likely 	memcpy(addr, ranges + na, 4 * pna);
482dbbdee94SGrant Likely 
483dbbdee94SGrant Likely  finish:
484606ad42aSRob Herring 	of_dump_addr("parent translation for:", addr, pna);
485606ad42aSRob Herring 	pr_debug("with offset: %llx\n", (unsigned long long)offset);
486dbbdee94SGrant Likely 
487dbbdee94SGrant Likely 	/* Translate it into parent bus space */
488dbbdee94SGrant Likely 	return pbus->translate(addr, offset, pna);
489dbbdee94SGrant Likely }
490dbbdee94SGrant Likely 
491dbbdee94SGrant Likely /*
492dbbdee94SGrant Likely  * Translate an address from the device-tree into a CPU physical address,
493dbbdee94SGrant Likely  * this walks up the tree and applies the various bus mappings on the
494dbbdee94SGrant Likely  * way.
495dbbdee94SGrant Likely  *
496dbbdee94SGrant Likely  * Note: We consider that crossing any level with #size-cells == 0 to mean
497dbbdee94SGrant Likely  * that translation is impossible (that is we are not dealing with a value
498dbbdee94SGrant Likely  * that can be mapped to a cpu physical address). This is not really specified
499dbbdee94SGrant Likely  * that way, but this is traditionally the way IBM at least do things
50065af618dSZhichang Yuan  *
50165af618dSZhichang Yuan  * Whenever the translation fails, the *host pointer will be set to the
50265af618dSZhichang Yuan  * device that had registered logical PIO mapping, and the return code is
50365af618dSZhichang Yuan  * relative to that node.
504dbbdee94SGrant Likely  */
50547b1e689SKim Phillips static u64 __of_translate_address(struct device_node *dev,
50695835a8dSMaxime Ripard 				  struct device_node *(*get_parent)(const struct device_node *),
50765af618dSZhichang Yuan 				  const __be32 *in_addr, const char *rprop,
50865af618dSZhichang Yuan 				  struct device_node **host)
509dbbdee94SGrant Likely {
510dbbdee94SGrant Likely 	struct device_node *parent = NULL;
511dbbdee94SGrant Likely 	struct of_bus *bus, *pbus;
51247b1e689SKim Phillips 	__be32 addr[OF_MAX_ADDR_CELLS];
513dbbdee94SGrant Likely 	int na, ns, pna, pns;
514dbbdee94SGrant Likely 	u64 result = OF_BAD_ADDR;
515dbbdee94SGrant Likely 
5160d638a07SRob Herring 	pr_debug("** translation for device %pOF **\n", dev);
517dbbdee94SGrant Likely 
518dbbdee94SGrant Likely 	/* Increase refcount at current level */
519dbbdee94SGrant Likely 	of_node_get(dev);
520dbbdee94SGrant Likely 
52165af618dSZhichang Yuan 	*host = NULL;
522dbbdee94SGrant Likely 	/* Get parent & match bus type */
52395835a8dSMaxime Ripard 	parent = get_parent(dev);
524dbbdee94SGrant Likely 	if (parent == NULL)
525dbbdee94SGrant Likely 		goto bail;
526dbbdee94SGrant Likely 	bus = of_match_bus(parent);
527dbbdee94SGrant Likely 
52859f5ca48SAndrew Murray 	/* Count address cells & copy address locally */
529dbbdee94SGrant Likely 	bus->count_cells(dev, &na, &ns);
530dbbdee94SGrant Likely 	if (!OF_CHECK_COUNTS(na, ns)) {
5310d638a07SRob Herring 		pr_debug("Bad cell count for %pOF\n", dev);
532dbbdee94SGrant Likely 		goto bail;
533dbbdee94SGrant Likely 	}
534dbbdee94SGrant Likely 	memcpy(addr, in_addr, na * 4);
535dbbdee94SGrant Likely 
5360d638a07SRob Herring 	pr_debug("bus is %s (na=%d, ns=%d) on %pOF\n",
5370d638a07SRob Herring 	    bus->name, na, ns, parent);
538606ad42aSRob Herring 	of_dump_addr("translating address:", addr, na);
539dbbdee94SGrant Likely 
540dbbdee94SGrant Likely 	/* Translate */
541dbbdee94SGrant Likely 	for (;;) {
54265af618dSZhichang Yuan 		struct logic_pio_hwaddr *iorange;
54365af618dSZhichang Yuan 
544dbbdee94SGrant Likely 		/* Switch to parent bus */
545dbbdee94SGrant Likely 		of_node_put(dev);
546dbbdee94SGrant Likely 		dev = parent;
54795835a8dSMaxime Ripard 		parent = get_parent(dev);
548dbbdee94SGrant Likely 
549dbbdee94SGrant Likely 		/* If root, we have finished */
550dbbdee94SGrant Likely 		if (parent == NULL) {
551606ad42aSRob Herring 			pr_debug("reached root node\n");
552dbbdee94SGrant Likely 			result = of_read_number(addr, na);
553dbbdee94SGrant Likely 			break;
554dbbdee94SGrant Likely 		}
555dbbdee94SGrant Likely 
55665af618dSZhichang Yuan 		/*
55765af618dSZhichang Yuan 		 * For indirectIO device which has no ranges property, get
55865af618dSZhichang Yuan 		 * the address from reg directly.
55965af618dSZhichang Yuan 		 */
56065af618dSZhichang Yuan 		iorange = find_io_range_by_fwnode(&dev->fwnode);
56165af618dSZhichang Yuan 		if (iorange && (iorange->flags != LOGIC_PIO_CPU_MMIO)) {
56265af618dSZhichang Yuan 			result = of_read_number(addr + 1, na - 1);
56365af618dSZhichang Yuan 			pr_debug("indirectIO matched(%pOF) 0x%llx\n",
56465af618dSZhichang Yuan 				 dev, result);
56565af618dSZhichang Yuan 			*host = of_node_get(dev);
56665af618dSZhichang Yuan 			break;
56765af618dSZhichang Yuan 		}
56865af618dSZhichang Yuan 
569dbbdee94SGrant Likely 		/* Get new parent bus and counts */
570dbbdee94SGrant Likely 		pbus = of_match_bus(parent);
571dbbdee94SGrant Likely 		pbus->count_cells(dev, &pna, &pns);
572dbbdee94SGrant Likely 		if (!OF_CHECK_COUNTS(pna, pns)) {
5730d638a07SRob Herring 			pr_err("Bad cell count for %pOF\n", dev);
574dbbdee94SGrant Likely 			break;
575dbbdee94SGrant Likely 		}
576dbbdee94SGrant Likely 
5770d638a07SRob Herring 		pr_debug("parent bus is %s (na=%d, ns=%d) on %pOF\n",
5780d638a07SRob Herring 		    pbus->name, pna, pns, parent);
579dbbdee94SGrant Likely 
580dbbdee94SGrant Likely 		/* Apply bus translation */
581dbbdee94SGrant Likely 		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
582dbbdee94SGrant Likely 			break;
583dbbdee94SGrant Likely 
584dbbdee94SGrant Likely 		/* Complete the move up one level */
585dbbdee94SGrant Likely 		na = pna;
586dbbdee94SGrant Likely 		ns = pns;
587dbbdee94SGrant Likely 		bus = pbus;
588dbbdee94SGrant Likely 
589606ad42aSRob Herring 		of_dump_addr("one level translation:", addr, na);
590dbbdee94SGrant Likely 	}
591dbbdee94SGrant Likely  bail:
592dbbdee94SGrant Likely 	of_node_put(parent);
593dbbdee94SGrant Likely 	of_node_put(dev);
594dbbdee94SGrant Likely 
595dbbdee94SGrant Likely 	return result;
596dbbdee94SGrant Likely }
597dbbdee94SGrant Likely 
5980131d897SSebastian Andrzej Siewior u64 of_translate_address(struct device_node *dev, const __be32 *in_addr)
599dbbdee94SGrant Likely {
60065af618dSZhichang Yuan 	struct device_node *host;
60165af618dSZhichang Yuan 	u64 ret;
60265af618dSZhichang Yuan 
60395835a8dSMaxime Ripard 	ret = __of_translate_address(dev, of_get_parent,
60495835a8dSMaxime Ripard 				     in_addr, "ranges", &host);
60565af618dSZhichang Yuan 	if (host) {
60665af618dSZhichang Yuan 		of_node_put(host);
60765af618dSZhichang Yuan 		return OF_BAD_ADDR;
60865af618dSZhichang Yuan 	}
60965af618dSZhichang Yuan 
61065af618dSZhichang Yuan 	return ret;
611dbbdee94SGrant Likely }
612dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_address);
613dbbdee94SGrant Likely 
614f83a6e5dSMaxime Ripard static struct device_node *__of_get_dma_parent(const struct device_node *np)
615f83a6e5dSMaxime Ripard {
616f83a6e5dSMaxime Ripard 	struct of_phandle_args args;
617f83a6e5dSMaxime Ripard 	int ret, index;
618f83a6e5dSMaxime Ripard 
619f83a6e5dSMaxime Ripard 	index = of_property_match_string(np, "interconnect-names", "dma-mem");
620f83a6e5dSMaxime Ripard 	if (index < 0)
621f83a6e5dSMaxime Ripard 		return of_get_parent(np);
622f83a6e5dSMaxime Ripard 
623f83a6e5dSMaxime Ripard 	ret = of_parse_phandle_with_args(np, "interconnects",
624f83a6e5dSMaxime Ripard 					 "#interconnect-cells",
625f83a6e5dSMaxime Ripard 					 index, &args);
626f83a6e5dSMaxime Ripard 	if (ret < 0)
627f83a6e5dSMaxime Ripard 		return of_get_parent(np);
628f83a6e5dSMaxime Ripard 
629f83a6e5dSMaxime Ripard 	return of_node_get(args.np);
630f83a6e5dSMaxime Ripard }
631f83a6e5dSMaxime Ripard 
632862ab557SRobin Murphy static struct device_node *of_get_next_dma_parent(struct device_node *np)
633862ab557SRobin Murphy {
634862ab557SRobin Murphy 	struct device_node *parent;
635862ab557SRobin Murphy 
636862ab557SRobin Murphy 	parent = __of_get_dma_parent(np);
637862ab557SRobin Murphy 	of_node_put(np);
638862ab557SRobin Murphy 
639862ab557SRobin Murphy 	return parent;
640862ab557SRobin Murphy }
641862ab557SRobin Murphy 
6420131d897SSebastian Andrzej Siewior u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
643dbbdee94SGrant Likely {
64465af618dSZhichang Yuan 	struct device_node *host;
64565af618dSZhichang Yuan 	u64 ret;
64665af618dSZhichang Yuan 
647f83a6e5dSMaxime Ripard 	ret = __of_translate_address(dev, __of_get_dma_parent,
64895835a8dSMaxime Ripard 				     in_addr, "dma-ranges", &host);
64965af618dSZhichang Yuan 
65065af618dSZhichang Yuan 	if (host) {
65165af618dSZhichang Yuan 		of_node_put(host);
65265af618dSZhichang Yuan 		return OF_BAD_ADDR;
65365af618dSZhichang Yuan 	}
65465af618dSZhichang Yuan 
65565af618dSZhichang Yuan 	return ret;
656dbbdee94SGrant Likely }
657dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_dma_address);
658dbbdee94SGrant Likely 
6590131d897SSebastian Andrzej Siewior const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
660dbbdee94SGrant Likely 		    unsigned int *flags)
661dbbdee94SGrant Likely {
6620131d897SSebastian Andrzej Siewior 	const __be32 *prop;
663dbbdee94SGrant Likely 	unsigned int psize;
664dbbdee94SGrant Likely 	struct device_node *parent;
665dbbdee94SGrant Likely 	struct of_bus *bus;
666dbbdee94SGrant Likely 	int onesize, i, na, ns;
667dbbdee94SGrant Likely 
668dbbdee94SGrant Likely 	/* Get parent & match bus type */
669dbbdee94SGrant Likely 	parent = of_get_parent(dev);
670dbbdee94SGrant Likely 	if (parent == NULL)
671dbbdee94SGrant Likely 		return NULL;
672dbbdee94SGrant Likely 	bus = of_match_bus(parent);
673dbbdee94SGrant Likely 	bus->count_cells(dev, &na, &ns);
674dbbdee94SGrant Likely 	of_node_put(parent);
6755d61b165SStephen Warren 	if (!OF_CHECK_ADDR_COUNT(na))
676dbbdee94SGrant Likely 		return NULL;
677dbbdee94SGrant Likely 
678dbbdee94SGrant Likely 	/* Get "reg" or "assigned-addresses" property */
679dbbdee94SGrant Likely 	prop = of_get_property(dev, bus->addresses, &psize);
680dbbdee94SGrant Likely 	if (prop == NULL)
681dbbdee94SGrant Likely 		return NULL;
682dbbdee94SGrant Likely 	psize /= 4;
683dbbdee94SGrant Likely 
684dbbdee94SGrant Likely 	onesize = na + ns;
685dbbdee94SGrant Likely 	for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
686dbbdee94SGrant Likely 		if (i == index) {
687dbbdee94SGrant Likely 			if (size)
688dbbdee94SGrant Likely 				*size = of_read_number(prop + na, ns);
689dbbdee94SGrant Likely 			if (flags)
690dbbdee94SGrant Likely 				*flags = bus->get_flags(prop);
691dbbdee94SGrant Likely 			return prop;
692dbbdee94SGrant Likely 		}
693dbbdee94SGrant Likely 	return NULL;
694dbbdee94SGrant Likely }
695dbbdee94SGrant Likely EXPORT_SYMBOL(of_get_address);
696dbbdee94SGrant Likely 
69767ccd2b9SRob Herring static int parser_init(struct of_pci_range_parser *parser,
69867ccd2b9SRob Herring 			struct device_node *node, const char *name)
69967ccd2b9SRob Herring {
70067ccd2b9SRob Herring 	int rlen;
70167ccd2b9SRob Herring 
70267ccd2b9SRob Herring 	parser->node = node;
70367ccd2b9SRob Herring 	parser->pna = of_n_addr_cells(node);
704bc5e522eSRob Herring 	parser->na = of_bus_n_addr_cells(node);
705bc5e522eSRob Herring 	parser->ns = of_bus_n_size_cells(node);
70667ccd2b9SRob Herring 	parser->dma = !strcmp(name, "dma-ranges");
7072f96593eSJiaxun Yang 	parser->bus = of_match_bus(node);
70867ccd2b9SRob Herring 
70967ccd2b9SRob Herring 	parser->range = of_get_property(node, name, &rlen);
71067ccd2b9SRob Herring 	if (parser->range == NULL)
71167ccd2b9SRob Herring 		return -ENOENT;
71267ccd2b9SRob Herring 
71367ccd2b9SRob Herring 	parser->end = parser->range + rlen / sizeof(__be32);
71467ccd2b9SRob Herring 
71567ccd2b9SRob Herring 	return 0;
71667ccd2b9SRob Herring }
71767ccd2b9SRob Herring 
71867ccd2b9SRob Herring int of_pci_range_parser_init(struct of_pci_range_parser *parser,
71967ccd2b9SRob Herring 				struct device_node *node)
72067ccd2b9SRob Herring {
72167ccd2b9SRob Herring 	return parser_init(parser, node, "ranges");
72267ccd2b9SRob Herring }
72367ccd2b9SRob Herring EXPORT_SYMBOL_GPL(of_pci_range_parser_init);
72467ccd2b9SRob Herring 
72567ccd2b9SRob Herring int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser,
72667ccd2b9SRob Herring 				struct device_node *node)
72767ccd2b9SRob Herring {
72867ccd2b9SRob Herring 	return parser_init(parser, node, "dma-ranges");
72967ccd2b9SRob Herring }
73067ccd2b9SRob Herring EXPORT_SYMBOL_GPL(of_pci_dma_range_parser_init);
731bc5e522eSRob Herring #define of_dma_range_parser_init of_pci_dma_range_parser_init
73267ccd2b9SRob Herring 
73367ccd2b9SRob Herring struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
73467ccd2b9SRob Herring 						struct of_pci_range *range)
73567ccd2b9SRob Herring {
736bc5e522eSRob Herring 	int na = parser->na;
737bc5e522eSRob Herring 	int ns = parser->ns;
738bc5e522eSRob Herring 	int np = parser->pna + na + ns;
7392f96593eSJiaxun Yang 	int busflag_na = 0;
74067ccd2b9SRob Herring 
74167ccd2b9SRob Herring 	if (!range)
74267ccd2b9SRob Herring 		return NULL;
74367ccd2b9SRob Herring 
744bc5e522eSRob Herring 	if (!parser->range || parser->range + np > parser->end)
74567ccd2b9SRob Herring 		return NULL;
74667ccd2b9SRob Herring 
7472f96593eSJiaxun Yang 	range->flags = parser->bus->get_flags(parser->range);
748bc5e522eSRob Herring 
7492f96593eSJiaxun Yang 	/* A extra cell for resource flags */
7502f96593eSJiaxun Yang 	if (parser->bus->has_flags)
7512f96593eSJiaxun Yang 		busflag_na = 1;
7522f96593eSJiaxun Yang 
7532f96593eSJiaxun Yang 	range->bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na);
754bc5e522eSRob Herring 
75567ccd2b9SRob Herring 	if (parser->dma)
75667ccd2b9SRob Herring 		range->cpu_addr = of_translate_dma_address(parser->node,
75767ccd2b9SRob Herring 				parser->range + na);
75867ccd2b9SRob Herring 	else
75967ccd2b9SRob Herring 		range->cpu_addr = of_translate_address(parser->node,
76067ccd2b9SRob Herring 				parser->range + na);
76167ccd2b9SRob Herring 	range->size = of_read_number(parser->range + parser->pna + na, ns);
76267ccd2b9SRob Herring 
763bc5e522eSRob Herring 	parser->range += np;
76467ccd2b9SRob Herring 
76567ccd2b9SRob Herring 	/* Now consume following elements while they are contiguous */
766bc5e522eSRob Herring 	while (parser->range + np <= parser->end) {
767bc5e522eSRob Herring 		u32 flags = 0;
7682f96593eSJiaxun Yang 		u64 bus_addr, cpu_addr, size;
76967ccd2b9SRob Herring 
7702f96593eSJiaxun Yang 		flags = parser->bus->get_flags(parser->range);
7712f96593eSJiaxun Yang 		bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na);
77267ccd2b9SRob Herring 		if (parser->dma)
77367ccd2b9SRob Herring 			cpu_addr = of_translate_dma_address(parser->node,
77467ccd2b9SRob Herring 					parser->range + na);
77567ccd2b9SRob Herring 		else
77667ccd2b9SRob Herring 			cpu_addr = of_translate_address(parser->node,
77767ccd2b9SRob Herring 					parser->range + na);
77867ccd2b9SRob Herring 		size = of_read_number(parser->range + parser->pna + na, ns);
77967ccd2b9SRob Herring 
78067ccd2b9SRob Herring 		if (flags != range->flags)
78167ccd2b9SRob Herring 			break;
7822f96593eSJiaxun Yang 		if (bus_addr != range->bus_addr + range->size ||
78367ccd2b9SRob Herring 		    cpu_addr != range->cpu_addr + range->size)
78467ccd2b9SRob Herring 			break;
78567ccd2b9SRob Herring 
78667ccd2b9SRob Herring 		range->size += size;
787bc5e522eSRob Herring 		parser->range += np;
78867ccd2b9SRob Herring 	}
78967ccd2b9SRob Herring 
79067ccd2b9SRob Herring 	return range;
79167ccd2b9SRob Herring }
79267ccd2b9SRob Herring EXPORT_SYMBOL_GPL(of_pci_range_parser_one);
79367ccd2b9SRob Herring 
79465af618dSZhichang Yuan static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr,
79565af618dSZhichang Yuan 			u64 size)
79665af618dSZhichang Yuan {
79765af618dSZhichang Yuan 	u64 taddr;
79865af618dSZhichang Yuan 	unsigned long port;
79965af618dSZhichang Yuan 	struct device_node *host;
80065af618dSZhichang Yuan 
80195835a8dSMaxime Ripard 	taddr = __of_translate_address(dev, of_get_parent,
80295835a8dSMaxime Ripard 				       in_addr, "ranges", &host);
80365af618dSZhichang Yuan 	if (host) {
80465af618dSZhichang Yuan 		/* host-specific port access */
80565af618dSZhichang Yuan 		port = logic_pio_trans_hwaddr(&host->fwnode, taddr, size);
80665af618dSZhichang Yuan 		of_node_put(host);
80765af618dSZhichang Yuan 	} else {
80865af618dSZhichang Yuan 		/* memory-mapped I/O range */
80965af618dSZhichang Yuan 		port = pci_address_to_pio(taddr);
81065af618dSZhichang Yuan 	}
81165af618dSZhichang Yuan 
81265af618dSZhichang Yuan 	if (port == (unsigned long)-1)
81365af618dSZhichang Yuan 		return OF_BAD_ADDR;
81465af618dSZhichang Yuan 
81565af618dSZhichang Yuan 	return port;
81665af618dSZhichang Yuan }
81765af618dSZhichang Yuan 
8180131d897SSebastian Andrzej Siewior static int __of_address_to_resource(struct device_node *dev,
8190131d897SSebastian Andrzej Siewior 		const __be32 *addrp, u64 size, unsigned int flags,
82035f3da32SBenoit Cousson 		const char *name, struct resource *r)
8211f5bef30SGrant Likely {
8221f5bef30SGrant Likely 	u64 taddr;
8231f5bef30SGrant Likely 
82465af618dSZhichang Yuan 	if (flags & IORESOURCE_MEM)
8251f5bef30SGrant Likely 		taddr = of_translate_address(dev, addrp);
82665af618dSZhichang Yuan 	else if (flags & IORESOURCE_IO)
82765af618dSZhichang Yuan 		taddr = of_translate_ioport(dev, addrp, size);
82865af618dSZhichang Yuan 	else
82965af618dSZhichang Yuan 		return -EINVAL;
83065af618dSZhichang Yuan 
8311f5bef30SGrant Likely 	if (taddr == OF_BAD_ADDR)
8321f5bef30SGrant Likely 		return -EINVAL;
8331f5bef30SGrant Likely 	memset(r, 0, sizeof(struct resource));
83465af618dSZhichang Yuan 
8351f5bef30SGrant Likely 	r->start = taddr;
8361f5bef30SGrant Likely 	r->end = taddr + size - 1;
8371f5bef30SGrant Likely 	r->flags = flags;
83835f3da32SBenoit Cousson 	r->name = name ? name : dev->full_name;
83935f3da32SBenoit Cousson 
8401f5bef30SGrant Likely 	return 0;
8411f5bef30SGrant Likely }
8421f5bef30SGrant Likely 
8431f5bef30SGrant Likely /**
8441f5bef30SGrant Likely  * of_address_to_resource - Translate device tree address and return as resource
8451f5bef30SGrant Likely  *
8461f5bef30SGrant Likely  * Note that if your address is a PIO address, the conversion will fail if
8471f5bef30SGrant Likely  * the physical address can't be internally converted to an IO token with
8487602f422SFrank Rowand  * pci_address_to_pio(), that is because it's either called too early or it
8491f5bef30SGrant Likely  * can't be matched to any host bridge IO space
8501f5bef30SGrant Likely  */
8511f5bef30SGrant Likely int of_address_to_resource(struct device_node *dev, int index,
8521f5bef30SGrant Likely 			   struct resource *r)
8531f5bef30SGrant Likely {
8540131d897SSebastian Andrzej Siewior 	const __be32	*addrp;
8551f5bef30SGrant Likely 	u64		size;
8561f5bef30SGrant Likely 	unsigned int	flags;
85735f3da32SBenoit Cousson 	const char	*name = NULL;
8581f5bef30SGrant Likely 
8591f5bef30SGrant Likely 	addrp = of_get_address(dev, index, &size, &flags);
8601f5bef30SGrant Likely 	if (addrp == NULL)
8611f5bef30SGrant Likely 		return -EINVAL;
86235f3da32SBenoit Cousson 
86335f3da32SBenoit Cousson 	/* Get optional "reg-names" property to add a name to a resource */
86435f3da32SBenoit Cousson 	of_property_read_string_index(dev, "reg-names",	index, &name);
86535f3da32SBenoit Cousson 
86635f3da32SBenoit Cousson 	return __of_address_to_resource(dev, addrp, size, flags, name, r);
8671f5bef30SGrant Likely }
8681f5bef30SGrant Likely EXPORT_SYMBOL_GPL(of_address_to_resource);
8691f5bef30SGrant Likely 
8706b884a8dSGrant Likely /**
8716b884a8dSGrant Likely  * of_iomap - Maps the memory mapped IO for a given device_node
8721094d5dbSWenchao Hao  * @np:		the device whose io range will be mapped
8736b884a8dSGrant Likely  * @index:	index of the io range
8746b884a8dSGrant Likely  *
8756b884a8dSGrant Likely  * Returns a pointer to the mapped memory
8766b884a8dSGrant Likely  */
8776b884a8dSGrant Likely void __iomem *of_iomap(struct device_node *np, int index)
8786b884a8dSGrant Likely {
8796b884a8dSGrant Likely 	struct resource res;
8806b884a8dSGrant Likely 
8816b884a8dSGrant Likely 	if (of_address_to_resource(np, index, &res))
8826b884a8dSGrant Likely 		return NULL;
8836b884a8dSGrant Likely 
88428c1b6d6SFelipe Balbi 	return ioremap(res.start, resource_size(&res));
8856b884a8dSGrant Likely }
8866b884a8dSGrant Likely EXPORT_SYMBOL(of_iomap);
88718308c94SGrygorii Strashko 
888efd342fbSMatthias Brugger /*
889efd342fbSMatthias Brugger  * of_io_request_and_map - Requests a resource and maps the memory mapped IO
890efd342fbSMatthias Brugger  *			   for a given device_node
891efd342fbSMatthias Brugger  * @device:	the device whose io range will be mapped
892efd342fbSMatthias Brugger  * @index:	index of the io range
893b01dcdd8SBenjamin Herrenschmidt  * @name:	name "override" for the memory region request or NULL
894efd342fbSMatthias Brugger  *
895efd342fbSMatthias Brugger  * Returns a pointer to the requested and mapped memory or an ERR_PTR() encoded
896efd342fbSMatthias Brugger  * error code on failure. Usage example:
897efd342fbSMatthias Brugger  *
898efd342fbSMatthias Brugger  *	base = of_io_request_and_map(node, 0, "foo");
899efd342fbSMatthias Brugger  *	if (IS_ERR(base))
900efd342fbSMatthias Brugger  *		return PTR_ERR(base);
901efd342fbSMatthias Brugger  */
902efd342fbSMatthias Brugger void __iomem *of_io_request_and_map(struct device_node *np, int index,
903b75b276bSMatthias Brugger 				    const char *name)
904efd342fbSMatthias Brugger {
905efd342fbSMatthias Brugger 	struct resource res;
906efd342fbSMatthias Brugger 	void __iomem *mem;
907efd342fbSMatthias Brugger 
908efd342fbSMatthias Brugger 	if (of_address_to_resource(np, index, &res))
909efd342fbSMatthias Brugger 		return IOMEM_ERR_PTR(-EINVAL);
910efd342fbSMatthias Brugger 
911b01dcdd8SBenjamin Herrenschmidt 	if (!name)
912b01dcdd8SBenjamin Herrenschmidt 		name = res.name;
913efd342fbSMatthias Brugger 	if (!request_mem_region(res.start, resource_size(&res), name))
914efd342fbSMatthias Brugger 		return IOMEM_ERR_PTR(-EBUSY);
915efd342fbSMatthias Brugger 
916efd342fbSMatthias Brugger 	mem = ioremap(res.start, resource_size(&res));
917efd342fbSMatthias Brugger 	if (!mem) {
918efd342fbSMatthias Brugger 		release_mem_region(res.start, resource_size(&res));
919efd342fbSMatthias Brugger 		return IOMEM_ERR_PTR(-ENOMEM);
920efd342fbSMatthias Brugger 	}
921efd342fbSMatthias Brugger 
922efd342fbSMatthias Brugger 	return mem;
923efd342fbSMatthias Brugger }
924efd342fbSMatthias Brugger EXPORT_SYMBOL(of_io_request_and_map);
925efd342fbSMatthias Brugger 
92618308c94SGrygorii Strashko /**
92718308c94SGrygorii Strashko  * of_dma_get_range - Get DMA range info
92818308c94SGrygorii Strashko  * @np:		device node to get DMA range info
92918308c94SGrygorii Strashko  * @dma_addr:	pointer to store initial DMA address of DMA range
93018308c94SGrygorii Strashko  * @paddr:	pointer to store initial CPU address of DMA range
93118308c94SGrygorii Strashko  * @size:	pointer to store size of DMA range
93218308c94SGrygorii Strashko  *
93318308c94SGrygorii Strashko  * Look in bottom up direction for the first "dma-ranges" property
93418308c94SGrygorii Strashko  * and parse it.
93518308c94SGrygorii Strashko  *  dma-ranges format:
93618308c94SGrygorii Strashko  *	DMA addr (dma_addr)	: naddr cells
93718308c94SGrygorii Strashko  *	CPU addr (phys_addr_t)	: pna cells
93818308c94SGrygorii Strashko  *	size			: nsize cells
93918308c94SGrygorii Strashko  *
94018308c94SGrygorii Strashko  * It returns -ENODEV if "dma-ranges" property was not found
94118308c94SGrygorii Strashko  * for this device in DT.
94218308c94SGrygorii Strashko  */
94318308c94SGrygorii Strashko int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *size)
94418308c94SGrygorii Strashko {
94518308c94SGrygorii Strashko 	struct device_node *node = of_node_get(np);
94618308c94SGrygorii Strashko 	const __be32 *ranges = NULL;
9477a8b64d1SRob Herring 	int len;
94818308c94SGrygorii Strashko 	int ret = 0;
949951d4885SRobin Murphy 	bool found_dma_ranges = false;
9507a8b64d1SRob Herring 	struct of_range_parser parser;
9517a8b64d1SRob Herring 	struct of_range range;
9529d55bebdSRob Herring 	u64 dma_start = U64_MAX, dma_end = 0, dma_offset = 0;
95318308c94SGrygorii Strashko 
954951d4885SRobin Murphy 	while (node) {
95518308c94SGrygorii Strashko 		ranges = of_get_property(node, "dma-ranges", &len);
95618308c94SGrygorii Strashko 
95718308c94SGrygorii Strashko 		/* Ignore empty ranges, they imply no translation required */
95818308c94SGrygorii Strashko 		if (ranges && len > 0)
95918308c94SGrygorii Strashko 			break;
96018308c94SGrygorii Strashko 
961951d4885SRobin Murphy 		/* Once we find 'dma-ranges', then a missing one is an error */
962951d4885SRobin Murphy 		if (found_dma_ranges && !ranges) {
963951d4885SRobin Murphy 			ret = -ENODEV;
964951d4885SRobin Murphy 			goto out;
965951d4885SRobin Murphy 		}
966951d4885SRobin Murphy 		found_dma_ranges = true;
967951d4885SRobin Murphy 
968951d4885SRobin Murphy 		node = of_get_next_dma_parent(node);
96918308c94SGrygorii Strashko 	}
97018308c94SGrygorii Strashko 
971951d4885SRobin Murphy 	if (!node || !ranges) {
9720d638a07SRob Herring 		pr_debug("no dma-ranges found for node(%pOF)\n", np);
97318308c94SGrygorii Strashko 		ret = -ENODEV;
97418308c94SGrygorii Strashko 		goto out;
97518308c94SGrygorii Strashko 	}
97618308c94SGrygorii Strashko 
9777a8b64d1SRob Herring 	of_dma_range_parser_init(&parser, node);
97818308c94SGrygorii Strashko 
9797a8b64d1SRob Herring 	for_each_of_range(&parser, &range) {
98018308c94SGrygorii Strashko 		pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n",
9817a8b64d1SRob Herring 			 range.bus_addr, range.cpu_addr, range.size);
9827a8b64d1SRob Herring 
9839d55bebdSRob Herring 		if (dma_offset && range.cpu_addr - range.bus_addr != dma_offset) {
9849d55bebdSRob Herring 			pr_warn("Can't handle multiple dma-ranges with different offsets on node(%pOF)\n", node);
9859d55bebdSRob Herring 			/* Don't error out as we'd break some existing DTs */
9869d55bebdSRob Herring 			continue;
9879d55bebdSRob Herring 		}
988f49c7fafSColin Ian King 		if (range.cpu_addr == OF_BAD_ADDR) {
989f49c7fafSColin Ian King 			pr_err("translation of DMA address(%llx) to CPU address failed node(%pOF)\n",
990f49c7fafSColin Ian King 			       range.bus_addr, node);
991f49c7fafSColin Ian King 			continue;
992f49c7fafSColin Ian King 		}
9939d55bebdSRob Herring 		dma_offset = range.cpu_addr - range.bus_addr;
9947a8b64d1SRob Herring 
9959d55bebdSRob Herring 		/* Take lower and upper limits */
9969d55bebdSRob Herring 		if (range.bus_addr < dma_start)
9979d55bebdSRob Herring 			dma_start = range.bus_addr;
9989d55bebdSRob Herring 		if (range.bus_addr + range.size > dma_end)
9999d55bebdSRob Herring 			dma_end = range.bus_addr + range.size;
10009d55bebdSRob Herring 	}
10019d55bebdSRob Herring 
10029d55bebdSRob Herring 	if (dma_start >= dma_end) {
10039d55bebdSRob Herring 		ret = -EINVAL;
10049d55bebdSRob Herring 		pr_debug("Invalid DMA ranges configuration on node(%pOF)\n",
10059d55bebdSRob Herring 			 node);
10067a8b64d1SRob Herring 		goto out;
10077a8b64d1SRob Herring 	}
10087a8b64d1SRob Herring 
10099d55bebdSRob Herring 	*dma_addr = dma_start;
10109d55bebdSRob Herring 	*size = dma_end - dma_start;
10119d55bebdSRob Herring 	*paddr = dma_start + dma_offset;
10129d55bebdSRob Herring 
10139d55bebdSRob Herring 	pr_debug("final: dma_addr(%llx) cpu_addr(%llx) size(%llx)\n",
10149d55bebdSRob Herring 		 *dma_addr, *paddr, *size);
101518308c94SGrygorii Strashko 
101618308c94SGrygorii Strashko out:
101718308c94SGrygorii Strashko 	of_node_put(node);
101818308c94SGrygorii Strashko 
101918308c94SGrygorii Strashko 	return ret;
102018308c94SGrygorii Strashko }
102192ea637eSSantosh Shilimkar 
102292ea637eSSantosh Shilimkar /**
102392ea637eSSantosh Shilimkar  * of_dma_is_coherent - Check if device is coherent
102492ea637eSSantosh Shilimkar  * @np:	device node
102592ea637eSSantosh Shilimkar  *
102692ea637eSSantosh Shilimkar  * It returns true if "dma-coherent" property was found
1027dabf6b36SMichael Ellerman  * for this device in the DT, or if DMA is coherent by
1028dabf6b36SMichael Ellerman  * default for OF devices on the current platform.
102992ea637eSSantosh Shilimkar  */
103092ea637eSSantosh Shilimkar bool of_dma_is_coherent(struct device_node *np)
103192ea637eSSantosh Shilimkar {
103292ea637eSSantosh Shilimkar 	struct device_node *node = of_node_get(np);
103392ea637eSSantosh Shilimkar 
1034dabf6b36SMichael Ellerman 	if (IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT))
1035dabf6b36SMichael Ellerman 		return true;
1036dabf6b36SMichael Ellerman 
103792ea637eSSantosh Shilimkar 	while (node) {
103892ea637eSSantosh Shilimkar 		if (of_property_read_bool(node, "dma-coherent")) {
103992ea637eSSantosh Shilimkar 			of_node_put(node);
104092ea637eSSantosh Shilimkar 			return true;
104192ea637eSSantosh Shilimkar 		}
1042c60bf3ebSRobin Murphy 		node = of_get_next_dma_parent(node);
104392ea637eSSantosh Shilimkar 	}
104492ea637eSSantosh Shilimkar 	of_node_put(node);
104592ea637eSSantosh Shilimkar 	return false;
104692ea637eSSantosh Shilimkar }
104792ea637eSSantosh Shilimkar EXPORT_SYMBOL_GPL(of_dma_is_coherent);
1048