xref: /openbmc/linux/drivers/of/address.c (revision 9144f784f852f9a125cabe9927b986d909bfa439)
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>
11d657d286SThomas Weißschuh #include <linux/overflow.h>
12c5076cfeSTomasz Nowicki #include <linux/pci.h>
13dbbdee94SGrant Likely #include <linux/pci_regs.h>
1441f8bba7SLiviu Dudau #include <linux/sizes.h>
1541f8bba7SLiviu Dudau #include <linux/slab.h>
16dbbdee94SGrant Likely #include <linux/string.h>
17e0d07278SJim Quinlan #include <linux/dma-direct.h> /* for bus_dma_region */
186b884a8dSGrant Likely 
19b68ac8dcSRobin Murphy #include "of_private.h"
20b68ac8dcSRobin Murphy 
21dbbdee94SGrant Likely /* Max address size we deal with */
22dbbdee94SGrant Likely #define OF_MAX_ADDR_CELLS	4
235d61b165SStephen Warren #define OF_CHECK_ADDR_COUNT(na)	((na) > 0 && (na) <= OF_MAX_ADDR_CELLS)
245d61b165SStephen Warren #define OF_CHECK_COUNTS(na, ns)	(OF_CHECK_ADDR_COUNT(na) && (ns) > 0)
25dbbdee94SGrant Likely 
26dbbdee94SGrant Likely /* Debug utility */
27dbbdee94SGrant Likely #ifdef DEBUG
of_dump_addr(const char * s,const __be32 * addr,int na)280131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na)
29dbbdee94SGrant Likely {
30606ad42aSRob Herring 	pr_debug("%s", s);
31dbbdee94SGrant Likely 	while (na--)
32606ad42aSRob Herring 		pr_cont(" %08x", be32_to_cpu(*(addr++)));
33606ad42aSRob Herring 	pr_cont("\n");
34dbbdee94SGrant Likely }
35dbbdee94SGrant Likely #else
of_dump_addr(const char * s,const __be32 * addr,int na)360131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na) { }
37dbbdee94SGrant Likely #endif
38dbbdee94SGrant Likely 
39dbbdee94SGrant Likely /* Callbacks for bus specific translators */
40dbbdee94SGrant Likely struct of_bus {
41dbbdee94SGrant Likely 	const char	*name;
42dbbdee94SGrant Likely 	const char	*addresses;
43dbbdee94SGrant Likely 	int		(*match)(struct device_node *parent);
44dbbdee94SGrant Likely 	void		(*count_cells)(struct device_node *child,
45dbbdee94SGrant Likely 				       int *addrc, int *sizec);
4647b1e689SKim Phillips 	u64		(*map)(__be32 *addr, const __be32 *range,
47dbbdee94SGrant Likely 				int na, int ns, int pna);
4847b1e689SKim Phillips 	int		(*translate)(__be32 *addr, u64 offset, int na);
49443f803bSRob Herring 	int		flag_cells;
500131d897SSebastian Andrzej Siewior 	unsigned int	(*get_flags)(const __be32 *addr);
51dbbdee94SGrant Likely };
52dbbdee94SGrant Likely 
53dbbdee94SGrant Likely /*
54dbbdee94SGrant Likely  * Default translator (generic bus)
55dbbdee94SGrant Likely  */
56dbbdee94SGrant Likely 
of_bus_default_count_cells(struct device_node * dev,int * addrc,int * sizec)57dbbdee94SGrant Likely static void of_bus_default_count_cells(struct device_node *dev,
58dbbdee94SGrant Likely 				       int *addrc, int *sizec)
59dbbdee94SGrant Likely {
60dbbdee94SGrant Likely 	if (addrc)
61dbbdee94SGrant Likely 		*addrc = of_n_addr_cells(dev);
62dbbdee94SGrant Likely 	if (sizec)
63dbbdee94SGrant Likely 		*sizec = of_n_size_cells(dev);
64dbbdee94SGrant Likely }
65dbbdee94SGrant Likely 
of_bus_default_map(__be32 * addr,const __be32 * range,int na,int ns,int pna)6647b1e689SKim Phillips static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
67dbbdee94SGrant Likely 		int na, int ns, int pna)
68dbbdee94SGrant Likely {
69dbbdee94SGrant Likely 	u64 cp, s, da;
70dbbdee94SGrant Likely 
71dbbdee94SGrant Likely 	cp = of_read_number(range, na);
72dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
73dbbdee94SGrant Likely 	da = of_read_number(addr, na);
74dbbdee94SGrant Likely 
750e407a9aSGeert Uytterhoeven 	pr_debug("default map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);
76dbbdee94SGrant Likely 
77dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
78dbbdee94SGrant Likely 		return OF_BAD_ADDR;
79dbbdee94SGrant Likely 	return da - cp;
80dbbdee94SGrant Likely }
81dbbdee94SGrant Likely 
of_bus_default_translate(__be32 * addr,u64 offset,int na)8247b1e689SKim Phillips static int of_bus_default_translate(__be32 *addr, u64 offset, int na)
83dbbdee94SGrant Likely {
84dbbdee94SGrant Likely 	u64 a = of_read_number(addr, na);
85dbbdee94SGrant Likely 	memset(addr, 0, na * 4);
86dbbdee94SGrant Likely 	a += offset;
87dbbdee94SGrant Likely 	if (na > 1)
88154063a9SGrant Likely 		addr[na - 2] = cpu_to_be32(a >> 32);
89154063a9SGrant Likely 	addr[na - 1] = cpu_to_be32(a & 0xffffffffu);
90dbbdee94SGrant Likely 
91dbbdee94SGrant Likely 	return 0;
92dbbdee94SGrant Likely }
93dbbdee94SGrant Likely 
of_bus_default_flags_get_flags(const __be32 * addr)943d5089c4SRob Herring static unsigned int of_bus_default_flags_get_flags(const __be32 *addr)
953d5089c4SRob Herring {
963d5089c4SRob Herring 	return of_read_number(addr, 1);
973d5089c4SRob Herring }
983d5089c4SRob Herring 
of_bus_default_get_flags(const __be32 * addr)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 
of_bus_default_flags_map(__be32 * addr,const __be32 * range,int na,int ns,int pna)10476e2b215SHerve Codina static u64 of_bus_default_flags_map(__be32 *addr, const __be32 *range, int na,
10576e2b215SHerve Codina 				    int ns, int pna)
10676e2b215SHerve Codina {
10776e2b215SHerve Codina 	u64 cp, s, da;
10876e2b215SHerve Codina 
10976e2b215SHerve Codina 	/* Check that flags match */
11076e2b215SHerve Codina 	if (*addr != *range)
11176e2b215SHerve Codina 		return OF_BAD_ADDR;
11276e2b215SHerve Codina 
11376e2b215SHerve Codina 	/* Read address values, skipping high cell */
11476e2b215SHerve Codina 	cp = of_read_number(range + 1, na - 1);
11576e2b215SHerve Codina 	s  = of_read_number(range + na + pna, ns);
11676e2b215SHerve Codina 	da = of_read_number(addr + 1, na - 1);
11776e2b215SHerve Codina 
11876e2b215SHerve Codina 	pr_debug("default flags map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);
11976e2b215SHerve Codina 
12076e2b215SHerve Codina 	if (da < cp || da >= (cp + s))
12176e2b215SHerve Codina 		return OF_BAD_ADDR;
12276e2b215SHerve Codina 	return da - cp;
12376e2b215SHerve Codina }
12476e2b215SHerve Codina 
of_bus_default_flags_translate(__be32 * addr,u64 offset,int na)12576e2b215SHerve Codina static int of_bus_default_flags_translate(__be32 *addr, u64 offset, int na)
12676e2b215SHerve Codina {
12776e2b215SHerve Codina 	/* Keep "flags" part (high cell) in translated address */
12876e2b215SHerve Codina 	return of_bus_default_translate(addr + 1, offset, na - 1);
12976e2b215SHerve Codina }
1303d5089c4SRob Herring 
1310fc0ead3SJiaxun Yang #ifdef CONFIG_PCI
of_bus_pci_get_flags(const __be32 * addr)13267ccd2b9SRob Herring static unsigned int of_bus_pci_get_flags(const __be32 *addr)
13367ccd2b9SRob Herring {
13467ccd2b9SRob Herring 	unsigned int flags = 0;
13567ccd2b9SRob Herring 	u32 w = be32_to_cpup(addr);
13667ccd2b9SRob Herring 
13767ccd2b9SRob Herring 	if (!IS_ENABLED(CONFIG_PCI))
13867ccd2b9SRob Herring 		return 0;
13967ccd2b9SRob Herring 
14067ccd2b9SRob Herring 	switch((w >> 24) & 0x03) {
14167ccd2b9SRob Herring 	case 0x01:
14267ccd2b9SRob Herring 		flags |= IORESOURCE_IO;
14367ccd2b9SRob Herring 		break;
14467ccd2b9SRob Herring 	case 0x02: /* 32 bits */
14567ccd2b9SRob Herring 		flags |= IORESOURCE_MEM;
14667ccd2b9SRob Herring 		break;
1479d57e61bSLeonardo Bras 
1489d57e61bSLeonardo Bras 	case 0x03: /* 64 bits */
1499d57e61bSLeonardo Bras 		flags |= IORESOURCE_MEM | IORESOURCE_MEM_64;
1509d57e61bSLeonardo Bras 		break;
15167ccd2b9SRob Herring 	}
15267ccd2b9SRob Herring 	if (w & 0x40000000)
15367ccd2b9SRob Herring 		flags |= IORESOURCE_PREFETCH;
15467ccd2b9SRob Herring 	return flags;
15567ccd2b9SRob Herring }
15667ccd2b9SRob Herring 
157dbbdee94SGrant Likely /*
158dbbdee94SGrant Likely  * PCI bus specific translator
159dbbdee94SGrant Likely  */
160dbbdee94SGrant Likely 
of_node_is_pcie(struct device_node * np)161d1ac0002SMarc Zyngier static bool of_node_is_pcie(struct device_node *np)
162d1ac0002SMarc Zyngier {
163d1ac0002SMarc Zyngier 	bool is_pcie = of_node_name_eq(np, "pcie");
164d1ac0002SMarc Zyngier 
165d1ac0002SMarc Zyngier 	if (is_pcie)
166d1ac0002SMarc Zyngier 		pr_warn_once("%pOF: Missing device_type\n", np);
167d1ac0002SMarc Zyngier 
168d1ac0002SMarc Zyngier 	return is_pcie;
169d1ac0002SMarc Zyngier }
170d1ac0002SMarc Zyngier 
of_bus_pci_match(struct device_node * np)171dbbdee94SGrant Likely static int of_bus_pci_match(struct device_node *np)
172dbbdee94SGrant Likely {
1736dd18e46SBenjamin Herrenschmidt 	/*
17414e2abb7SKleber Sacilotto de Souza  	 * "pciex" is PCI Express
1756dd18e46SBenjamin Herrenschmidt 	 * "vci" is for the /chaos bridge on 1st-gen PCI powermacs
1766dd18e46SBenjamin Herrenschmidt 	 * "ht" is hypertransport
177d1ac0002SMarc Zyngier 	 *
178d1ac0002SMarc Zyngier 	 * If none of the device_type match, and that the node name is
179d1ac0002SMarc Zyngier 	 * "pcie", accept the device as PCI (with a warning).
1806dd18e46SBenjamin Herrenschmidt 	 */
181e8b1dee2SRob Herring 	return of_node_is_type(np, "pci") || of_node_is_type(np, "pciex") ||
182d1ac0002SMarc Zyngier 		of_node_is_type(np, "vci") || of_node_is_type(np, "ht") ||
183d1ac0002SMarc Zyngier 		of_node_is_pcie(np);
184dbbdee94SGrant Likely }
185dbbdee94SGrant Likely 
of_bus_pci_count_cells(struct device_node * np,int * addrc,int * sizec)186dbbdee94SGrant Likely static void of_bus_pci_count_cells(struct device_node *np,
187dbbdee94SGrant Likely 				   int *addrc, int *sizec)
188dbbdee94SGrant Likely {
189dbbdee94SGrant Likely 	if (addrc)
190dbbdee94SGrant Likely 		*addrc = 3;
191dbbdee94SGrant Likely 	if (sizec)
192dbbdee94SGrant Likely 		*sizec = 2;
193dbbdee94SGrant Likely }
194dbbdee94SGrant Likely 
of_bus_pci_map(__be32 * addr,const __be32 * range,int na,int ns,int pna)19547b1e689SKim Phillips static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns,
1960131d897SSebastian Andrzej Siewior 		int pna)
197dbbdee94SGrant Likely {
198dbbdee94SGrant Likely 	u64 cp, s, da;
199dbbdee94SGrant Likely 	unsigned int af, rf;
200dbbdee94SGrant Likely 
201dbbdee94SGrant Likely 	af = of_bus_pci_get_flags(addr);
202dbbdee94SGrant Likely 	rf = of_bus_pci_get_flags(range);
203dbbdee94SGrant Likely 
204dbbdee94SGrant Likely 	/* Check address type match */
205dbbdee94SGrant Likely 	if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO))
206dbbdee94SGrant Likely 		return OF_BAD_ADDR;
207dbbdee94SGrant Likely 
208dbbdee94SGrant Likely 	/* Read address values, skipping high cell */
209dbbdee94SGrant Likely 	cp = of_read_number(range + 1, na - 1);
210dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
211dbbdee94SGrant Likely 	da = of_read_number(addr + 1, na - 1);
212dbbdee94SGrant Likely 
2130e407a9aSGeert Uytterhoeven 	pr_debug("PCI map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);
214dbbdee94SGrant Likely 
215dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
216dbbdee94SGrant Likely 		return OF_BAD_ADDR;
217dbbdee94SGrant Likely 	return da - cp;
218dbbdee94SGrant Likely }
219dbbdee94SGrant Likely 
220c3c0dc75SRob Herring #endif /* CONFIG_PCI */
221dbbdee94SGrant Likely 
2220b0b0893SLiviu Dudau /*
2230b0b0893SLiviu Dudau  * of_pci_range_to_resource - Create a resource from an of_pci_range
2240b0b0893SLiviu Dudau  * @range:	the PCI range that describes the resource
2250b0b0893SLiviu Dudau  * @np:		device node where the range belongs to
2260b0b0893SLiviu Dudau  * @res:	pointer to a valid resource that will be updated to
2270b0b0893SLiviu Dudau  *              reflect the values contained in the range.
2280b0b0893SLiviu Dudau  *
22965b6b046SGeert Uytterhoeven  * Returns -EINVAL if the range cannot be converted to resource.
2300b0b0893SLiviu Dudau  *
2310b0b0893SLiviu Dudau  * Note that if the range is an IO range, the resource will be converted
2320b0b0893SLiviu Dudau  * using pci_address_to_pio() which can fail if it is called too early or
2330b0b0893SLiviu Dudau  * if the range cannot be matched to any host bridge IO space (our case here).
2340b0b0893SLiviu Dudau  * To guard against that we try to register the IO range first.
2350b0b0893SLiviu Dudau  * If that fails we know that pci_address_to_pio() will do too.
2360b0b0893SLiviu Dudau  */
of_pci_range_to_resource(struct of_pci_range * range,struct device_node * np,struct resource * res)2370b0b0893SLiviu Dudau int of_pci_range_to_resource(struct of_pci_range *range,
23883bbde1cSLiviu Dudau 			     struct device_node *np, struct resource *res)
23983bbde1cSLiviu Dudau {
2400b0b0893SLiviu Dudau 	int err;
24183bbde1cSLiviu Dudau 	res->flags = range->flags;
24283bbde1cSLiviu Dudau 	res->parent = res->child = res->sibling = NULL;
24383bbde1cSLiviu Dudau 	res->name = np->full_name;
2440b0b0893SLiviu Dudau 
2450b0b0893SLiviu Dudau 	if (res->flags & IORESOURCE_IO) {
2460b0b0893SLiviu Dudau 		unsigned long port;
247fcfaab30SGabriele Paoloni 		err = pci_register_io_range(&np->fwnode, range->cpu_addr,
248fcfaab30SGabriele Paoloni 				range->size);
2490b0b0893SLiviu Dudau 		if (err)
2500b0b0893SLiviu Dudau 			goto invalid_range;
2510b0b0893SLiviu Dudau 		port = pci_address_to_pio(range->cpu_addr);
2520b0b0893SLiviu Dudau 		if (port == (unsigned long)-1) {
2530b0b0893SLiviu Dudau 			err = -EINVAL;
2540b0b0893SLiviu Dudau 			goto invalid_range;
2550b0b0893SLiviu Dudau 		}
2560b0b0893SLiviu Dudau 		res->start = port;
2570b0b0893SLiviu Dudau 	} else {
2584af97106SPavel Fedin 		if ((sizeof(resource_size_t) < 8) &&
2594af97106SPavel Fedin 		    upper_32_bits(range->cpu_addr)) {
2604af97106SPavel Fedin 			err = -EINVAL;
2614af97106SPavel Fedin 			goto invalid_range;
2624af97106SPavel Fedin 		}
2634af97106SPavel Fedin 
2640b0b0893SLiviu Dudau 		res->start = range->cpu_addr;
2650b0b0893SLiviu Dudau 	}
2660b0b0893SLiviu Dudau 	res->end = res->start + range->size - 1;
2670b0b0893SLiviu Dudau 	return 0;
2680b0b0893SLiviu Dudau 
2690b0b0893SLiviu Dudau invalid_range:
2700b0b0893SLiviu Dudau 	res->start = (resource_size_t)OF_BAD_ADDR;
2710b0b0893SLiviu Dudau 	res->end = (resource_size_t)OF_BAD_ADDR;
2720b0b0893SLiviu Dudau 	return err;
27383bbde1cSLiviu Dudau }
274bf6681eaSManikanta Maddireddy EXPORT_SYMBOL(of_pci_range_to_resource);
275dbbdee94SGrant Likely 
276dbbdee94SGrant Likely /*
277c75a7949SRob Herring  * of_range_to_resource - Create a resource from a ranges entry
278c75a7949SRob Herring  * @np:		device node where the range belongs to
279c75a7949SRob Herring  * @index:	the 'ranges' index to convert to a resource
280c75a7949SRob Herring  * @res:	pointer to a valid resource that will be updated to
281c75a7949SRob Herring  *              reflect the values contained in the range.
282c75a7949SRob Herring  *
283c75a7949SRob Herring  * Returns ENOENT if the entry is not found or EINVAL if the range cannot be
284c75a7949SRob Herring  * converted to resource.
285c75a7949SRob Herring  */
of_range_to_resource(struct device_node * np,int index,struct resource * res)286c75a7949SRob Herring int of_range_to_resource(struct device_node *np, int index, struct resource *res)
287c75a7949SRob Herring {
288c75a7949SRob Herring 	int ret, i = 0;
289c75a7949SRob Herring 	struct of_range_parser parser;
290c75a7949SRob Herring 	struct of_range range;
291c75a7949SRob Herring 
292c75a7949SRob Herring 	ret = of_range_parser_init(&parser, np);
293c75a7949SRob Herring 	if (ret)
294c75a7949SRob Herring 		return ret;
295c75a7949SRob Herring 
296c75a7949SRob Herring 	for_each_of_range(&parser, &range)
297c75a7949SRob Herring 		if (i++ == index)
298c75a7949SRob Herring 			return of_pci_range_to_resource(&range, np, res);
299c75a7949SRob Herring 
300c75a7949SRob Herring 	return -ENOENT;
301c75a7949SRob Herring }
302c75a7949SRob Herring EXPORT_SYMBOL(of_range_to_resource);
303c75a7949SRob Herring 
304c75a7949SRob Herring /*
305dbbdee94SGrant Likely  * ISA bus specific translator
306dbbdee94SGrant Likely  */
307dbbdee94SGrant Likely 
of_bus_isa_match(struct device_node * np)308dbbdee94SGrant Likely static int of_bus_isa_match(struct device_node *np)
309dbbdee94SGrant Likely {
310b3e46d1aSRob Herring 	return of_node_name_eq(np, "isa");
311dbbdee94SGrant Likely }
312dbbdee94SGrant Likely 
of_bus_isa_count_cells(struct device_node * child,int * addrc,int * sizec)313dbbdee94SGrant Likely static void of_bus_isa_count_cells(struct device_node *child,
314dbbdee94SGrant Likely 				   int *addrc, int *sizec)
315dbbdee94SGrant Likely {
316dbbdee94SGrant Likely 	if (addrc)
317dbbdee94SGrant Likely 		*addrc = 2;
318dbbdee94SGrant Likely 	if (sizec)
319dbbdee94SGrant Likely 		*sizec = 1;
320dbbdee94SGrant Likely }
321dbbdee94SGrant Likely 
of_bus_isa_map(__be32 * addr,const __be32 * range,int na,int ns,int pna)32247b1e689SKim Phillips static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns,
3230131d897SSebastian Andrzej Siewior 		int pna)
324dbbdee94SGrant Likely {
325dbbdee94SGrant Likely 	u64 cp, s, da;
326dbbdee94SGrant Likely 
327dbbdee94SGrant Likely 	/* Check address type match */
3280131d897SSebastian Andrzej Siewior 	if ((addr[0] ^ range[0]) & cpu_to_be32(1))
329dbbdee94SGrant Likely 		return OF_BAD_ADDR;
330dbbdee94SGrant Likely 
331dbbdee94SGrant Likely 	/* Read address values, skipping high cell */
332dbbdee94SGrant Likely 	cp = of_read_number(range + 1, na - 1);
333dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
334dbbdee94SGrant Likely 	da = of_read_number(addr + 1, na - 1);
335dbbdee94SGrant Likely 
3360e407a9aSGeert Uytterhoeven 	pr_debug("ISA map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);
337dbbdee94SGrant Likely 
338dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
339dbbdee94SGrant Likely 		return OF_BAD_ADDR;
340dbbdee94SGrant Likely 	return da - cp;
341dbbdee94SGrant Likely }
342dbbdee94SGrant Likely 
of_bus_isa_get_flags(const __be32 * addr)3430131d897SSebastian Andrzej Siewior static unsigned int of_bus_isa_get_flags(const __be32 *addr)
344dbbdee94SGrant Likely {
345dbbdee94SGrant Likely 	unsigned int flags = 0;
3460131d897SSebastian Andrzej Siewior 	u32 w = be32_to_cpup(addr);
347dbbdee94SGrant Likely 
348dbbdee94SGrant Likely 	if (w & 1)
349dbbdee94SGrant Likely 		flags |= IORESOURCE_IO;
350dbbdee94SGrant Likely 	else
351dbbdee94SGrant Likely 		flags |= IORESOURCE_MEM;
352dbbdee94SGrant Likely 	return flags;
353dbbdee94SGrant Likely }
354dbbdee94SGrant Likely 
of_bus_default_flags_match(struct device_node * np)3553d5089c4SRob Herring static int of_bus_default_flags_match(struct device_node *np)
3563d5089c4SRob Herring {
3573d5089c4SRob Herring 	return of_bus_n_addr_cells(np) == 3;
3583d5089c4SRob Herring }
3593d5089c4SRob Herring 
360dbbdee94SGrant Likely /*
361dbbdee94SGrant Likely  * Array of bus specific translators
362dbbdee94SGrant Likely  */
363dbbdee94SGrant Likely 
364dbbdee94SGrant Likely static struct of_bus of_busses[] = {
3654670d610SRob Herring #ifdef CONFIG_PCI
366dbbdee94SGrant Likely 	/* PCI */
367dbbdee94SGrant Likely 	{
368dbbdee94SGrant Likely 		.name = "pci",
369dbbdee94SGrant Likely 		.addresses = "assigned-addresses",
370dbbdee94SGrant Likely 		.match = of_bus_pci_match,
371dbbdee94SGrant Likely 		.count_cells = of_bus_pci_count_cells,
372dbbdee94SGrant Likely 		.map = of_bus_pci_map,
3737a40a884SHerve Codina 		.translate = of_bus_default_flags_translate,
374443f803bSRob Herring 		.flag_cells = 1,
375dbbdee94SGrant Likely 		.get_flags = of_bus_pci_get_flags,
376dbbdee94SGrant Likely 	},
3774670d610SRob Herring #endif /* CONFIG_PCI */
378dbbdee94SGrant Likely 	/* ISA */
379dbbdee94SGrant Likely 	{
380dbbdee94SGrant Likely 		.name = "isa",
381dbbdee94SGrant Likely 		.addresses = "reg",
382dbbdee94SGrant Likely 		.match = of_bus_isa_match,
383dbbdee94SGrant Likely 		.count_cells = of_bus_isa_count_cells,
384dbbdee94SGrant Likely 		.map = of_bus_isa_map,
3857a40a884SHerve Codina 		.translate = of_bus_default_flags_translate,
386443f803bSRob Herring 		.flag_cells = 1,
387dbbdee94SGrant Likely 		.get_flags = of_bus_isa_get_flags,
388dbbdee94SGrant Likely 	},
3893d5089c4SRob Herring 	/* Default with flags cell */
3903d5089c4SRob Herring 	{
3913d5089c4SRob Herring 		.name = "default-flags",
3923d5089c4SRob Herring 		.addresses = "reg",
3933d5089c4SRob Herring 		.match = of_bus_default_flags_match,
3943d5089c4SRob Herring 		.count_cells = of_bus_default_count_cells,
39576e2b215SHerve Codina 		.map = of_bus_default_flags_map,
39676e2b215SHerve Codina 		.translate = of_bus_default_flags_translate,
397443f803bSRob Herring 		.flag_cells = 1,
3983d5089c4SRob Herring 		.get_flags = of_bus_default_flags_get_flags,
3993d5089c4SRob Herring 	},
400dbbdee94SGrant Likely 	/* Default */
401dbbdee94SGrant Likely 	{
402dbbdee94SGrant Likely 		.name = "default",
403dbbdee94SGrant Likely 		.addresses = "reg",
404dbbdee94SGrant Likely 		.match = NULL,
405dbbdee94SGrant Likely 		.count_cells = of_bus_default_count_cells,
406dbbdee94SGrant Likely 		.map = of_bus_default_map,
407dbbdee94SGrant Likely 		.translate = of_bus_default_translate,
408dbbdee94SGrant Likely 		.get_flags = of_bus_default_get_flags,
409dbbdee94SGrant Likely 	},
410dbbdee94SGrant Likely };
411dbbdee94SGrant Likely 
of_match_bus(struct device_node * np)412dbbdee94SGrant Likely static struct of_bus *of_match_bus(struct device_node *np)
413dbbdee94SGrant Likely {
414dbbdee94SGrant Likely 	int i;
415dbbdee94SGrant Likely 
416dbbdee94SGrant Likely 	for (i = 0; i < ARRAY_SIZE(of_busses); i++)
417dbbdee94SGrant Likely 		if (!of_busses[i].match || of_busses[i].match(np))
418dbbdee94SGrant Likely 			return &of_busses[i];
419dbbdee94SGrant Likely 	BUG();
420dbbdee94SGrant Likely 	return NULL;
421dbbdee94SGrant Likely }
422dbbdee94SGrant Likely 
of_empty_ranges_quirk(struct device_node * np)42341d94893SBenjamin Herrenschmidt static int of_empty_ranges_quirk(struct device_node *np)
424746c9e9fSBenjamin Herrenschmidt {
425746c9e9fSBenjamin Herrenschmidt 	if (IS_ENABLED(CONFIG_PPC)) {
42641d94893SBenjamin Herrenschmidt 		/* To save cycles, we cache the result for global "Mac" setting */
427746c9e9fSBenjamin Herrenschmidt 		static int quirk_state = -1;
428746c9e9fSBenjamin Herrenschmidt 
42941d94893SBenjamin Herrenschmidt 		/* PA-SEMI sdc DT bug */
43041d94893SBenjamin Herrenschmidt 		if (of_device_is_compatible(np, "1682m-sdc"))
43141d94893SBenjamin Herrenschmidt 			return true;
43241d94893SBenjamin Herrenschmidt 
43341d94893SBenjamin Herrenschmidt 		/* Make quirk cached */
434746c9e9fSBenjamin Herrenschmidt 		if (quirk_state < 0)
435746c9e9fSBenjamin Herrenschmidt 			quirk_state =
436746c9e9fSBenjamin Herrenschmidt 				of_machine_is_compatible("Power Macintosh") ||
437746c9e9fSBenjamin Herrenschmidt 				of_machine_is_compatible("MacRISC");
438746c9e9fSBenjamin Herrenschmidt 		return quirk_state;
439746c9e9fSBenjamin Herrenschmidt 	}
440746c9e9fSBenjamin Herrenschmidt 	return false;
441746c9e9fSBenjamin Herrenschmidt }
442746c9e9fSBenjamin Herrenschmidt 
of_translate_one(struct device_node * parent,struct of_bus * bus,struct of_bus * pbus,__be32 * addr,int na,int ns,int pna,const char * rprop)443dbbdee94SGrant Likely static int of_translate_one(struct device_node *parent, struct of_bus *bus,
44447b1e689SKim Phillips 			    struct of_bus *pbus, __be32 *addr,
445dbbdee94SGrant Likely 			    int na, int ns, int pna, const char *rprop)
446dbbdee94SGrant Likely {
4470131d897SSebastian Andrzej Siewior 	const __be32 *ranges;
448dbbdee94SGrant Likely 	unsigned int rlen;
449dbbdee94SGrant Likely 	int rone;
450dbbdee94SGrant Likely 	u64 offset = OF_BAD_ADDR;
451dbbdee94SGrant Likely 
452ba85edbeSMasahiro Yamada 	/*
453ba85edbeSMasahiro Yamada 	 * Normally, an absence of a "ranges" property means we are
454dbbdee94SGrant Likely 	 * crossing a non-translatable boundary, and thus the addresses
455ba85edbeSMasahiro Yamada 	 * below the current cannot be converted to CPU physical ones.
456dbbdee94SGrant Likely 	 * Unfortunately, while this is very clear in the spec, it's not
457dbbdee94SGrant Likely 	 * what Apple understood, and they do have things like /uni-n or
458dbbdee94SGrant Likely 	 * /ht nodes with no "ranges" property and a lot of perfectly
459dbbdee94SGrant Likely 	 * useable mapped devices below them. Thus we treat the absence of
460dbbdee94SGrant Likely 	 * "ranges" as equivalent to an empty "ranges" property which means
461dbbdee94SGrant Likely 	 * a 1:1 translation at that level. It's up to the caller not to try
462dbbdee94SGrant Likely 	 * to translate addresses that aren't supposed to be translated in
463dbbdee94SGrant Likely 	 * the first place. --BenH.
4643930f294SGrant Likely 	 *
4653930f294SGrant Likely 	 * As far as we know, this damage only exists on Apple machines, so
4663930f294SGrant Likely 	 * This code is only enabled on powerpc. --gcl
46781db12eeSRob Herring 	 *
46881db12eeSRob Herring 	 * This quirk also applies for 'dma-ranges' which frequently exist in
46981db12eeSRob Herring 	 * child nodes without 'dma-ranges' in the parent nodes. --RobH
470dbbdee94SGrant Likely 	 */
471dbbdee94SGrant Likely 	ranges = of_get_property(parent, rprop, &rlen);
47281db12eeSRob Herring 	if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
47381db12eeSRob Herring 	    strcmp(rprop, "dma-ranges")) {
474606ad42aSRob Herring 		pr_debug("no ranges; cannot translate\n");
4753930f294SGrant Likely 		return 1;
4763930f294SGrant Likely 	}
477dbbdee94SGrant Likely 	if (ranges == NULL || rlen == 0) {
478dbbdee94SGrant Likely 		offset = of_read_number(addr, na);
479*b222816fSAndrea della Porta 		/* set address to zero, pass flags through */
480*b222816fSAndrea della Porta 		memset(addr + pbus->flag_cells, 0, (pna - pbus->flag_cells) * 4);
481606ad42aSRob Herring 		pr_debug("empty ranges; 1:1 translation\n");
482dbbdee94SGrant Likely 		goto finish;
483dbbdee94SGrant Likely 	}
484dbbdee94SGrant Likely 
485606ad42aSRob Herring 	pr_debug("walking ranges...\n");
486dbbdee94SGrant Likely 
487dbbdee94SGrant Likely 	/* Now walk through the ranges */
488dbbdee94SGrant Likely 	rlen /= 4;
489dbbdee94SGrant Likely 	rone = na + pna + ns;
490dbbdee94SGrant Likely 	for (; rlen >= rone; rlen -= rone, ranges += rone) {
491dbbdee94SGrant Likely 		offset = bus->map(addr, ranges, na, ns, pna);
492dbbdee94SGrant Likely 		if (offset != OF_BAD_ADDR)
493dbbdee94SGrant Likely 			break;
494dbbdee94SGrant Likely 	}
495dbbdee94SGrant Likely 	if (offset == OF_BAD_ADDR) {
496606ad42aSRob Herring 		pr_debug("not found !\n");
497dbbdee94SGrant Likely 		return 1;
498dbbdee94SGrant Likely 	}
499dbbdee94SGrant Likely 	memcpy(addr, ranges + na, 4 * pna);
500dbbdee94SGrant Likely 
501dbbdee94SGrant Likely  finish:
502606ad42aSRob Herring 	of_dump_addr("parent translation for:", addr, pna);
5030e407a9aSGeert Uytterhoeven 	pr_debug("with offset: %llx\n", offset);
504dbbdee94SGrant Likely 
505dbbdee94SGrant Likely 	/* Translate it into parent bus space */
506dbbdee94SGrant Likely 	return pbus->translate(addr, offset, pna);
507dbbdee94SGrant Likely }
508dbbdee94SGrant Likely 
509dbbdee94SGrant Likely /*
510dbbdee94SGrant Likely  * Translate an address from the device-tree into a CPU physical address,
511dbbdee94SGrant Likely  * this walks up the tree and applies the various bus mappings on the
512dbbdee94SGrant Likely  * way.
513dbbdee94SGrant Likely  *
514dbbdee94SGrant Likely  * Note: We consider that crossing any level with #size-cells == 0 to mean
515dbbdee94SGrant Likely  * that translation is impossible (that is we are not dealing with a value
516dbbdee94SGrant Likely  * that can be mapped to a cpu physical address). This is not really specified
517dbbdee94SGrant Likely  * that way, but this is traditionally the way IBM at least do things
51865af618dSZhichang Yuan  *
51965af618dSZhichang Yuan  * Whenever the translation fails, the *host pointer will be set to the
52065af618dSZhichang Yuan  * device that had registered logical PIO mapping, and the return code is
52165af618dSZhichang Yuan  * relative to that node.
522dbbdee94SGrant Likely  */
__of_translate_address(struct device_node * dev,struct device_node * (* get_parent)(const struct device_node *),const __be32 * in_addr,const char * rprop,struct device_node ** host)52347b1e689SKim Phillips static u64 __of_translate_address(struct device_node *dev,
52495835a8dSMaxime Ripard 				  struct device_node *(*get_parent)(const struct device_node *),
52565af618dSZhichang Yuan 				  const __be32 *in_addr, const char *rprop,
52665af618dSZhichang Yuan 				  struct device_node **host)
527dbbdee94SGrant Likely {
528dbbdee94SGrant Likely 	struct device_node *parent = NULL;
529dbbdee94SGrant Likely 	struct of_bus *bus, *pbus;
53047b1e689SKim Phillips 	__be32 addr[OF_MAX_ADDR_CELLS];
531dbbdee94SGrant Likely 	int na, ns, pna, pns;
532dbbdee94SGrant Likely 	u64 result = OF_BAD_ADDR;
533dbbdee94SGrant Likely 
5340d638a07SRob Herring 	pr_debug("** translation for device %pOF **\n", dev);
535dbbdee94SGrant Likely 
536dbbdee94SGrant Likely 	/* Increase refcount at current level */
537dbbdee94SGrant Likely 	of_node_get(dev);
538dbbdee94SGrant Likely 
53965af618dSZhichang Yuan 	*host = NULL;
540dbbdee94SGrant Likely 	/* Get parent & match bus type */
54195835a8dSMaxime Ripard 	parent = get_parent(dev);
542dbbdee94SGrant Likely 	if (parent == NULL)
543dbbdee94SGrant Likely 		goto bail;
544dbbdee94SGrant Likely 	bus = of_match_bus(parent);
545dbbdee94SGrant Likely 
54659f5ca48SAndrew Murray 	/* Count address cells & copy address locally */
547dbbdee94SGrant Likely 	bus->count_cells(dev, &na, &ns);
548dbbdee94SGrant Likely 	if (!OF_CHECK_COUNTS(na, ns)) {
5490d638a07SRob Herring 		pr_debug("Bad cell count for %pOF\n", dev);
550dbbdee94SGrant Likely 		goto bail;
551dbbdee94SGrant Likely 	}
552dbbdee94SGrant Likely 	memcpy(addr, in_addr, na * 4);
553dbbdee94SGrant Likely 
5540d638a07SRob Herring 	pr_debug("bus is %s (na=%d, ns=%d) on %pOF\n",
5550d638a07SRob Herring 	    bus->name, na, ns, parent);
556606ad42aSRob Herring 	of_dump_addr("translating address:", addr, na);
557dbbdee94SGrant Likely 
558dbbdee94SGrant Likely 	/* Translate */
559dbbdee94SGrant Likely 	for (;;) {
56065af618dSZhichang Yuan 		struct logic_pio_hwaddr *iorange;
56165af618dSZhichang Yuan 
562dbbdee94SGrant Likely 		/* Switch to parent bus */
563dbbdee94SGrant Likely 		of_node_put(dev);
564dbbdee94SGrant Likely 		dev = parent;
56595835a8dSMaxime Ripard 		parent = get_parent(dev);
566dbbdee94SGrant Likely 
567dbbdee94SGrant Likely 		/* If root, we have finished */
568dbbdee94SGrant Likely 		if (parent == NULL) {
569606ad42aSRob Herring 			pr_debug("reached root node\n");
570dbbdee94SGrant Likely 			result = of_read_number(addr, na);
571dbbdee94SGrant Likely 			break;
572dbbdee94SGrant Likely 		}
573dbbdee94SGrant Likely 
57465af618dSZhichang Yuan 		/*
57565af618dSZhichang Yuan 		 * For indirectIO device which has no ranges property, get
57665af618dSZhichang Yuan 		 * the address from reg directly.
57765af618dSZhichang Yuan 		 */
57865af618dSZhichang Yuan 		iorange = find_io_range_by_fwnode(&dev->fwnode);
57965af618dSZhichang Yuan 		if (iorange && (iorange->flags != LOGIC_PIO_CPU_MMIO)) {
58065af618dSZhichang Yuan 			result = of_read_number(addr + 1, na - 1);
58165af618dSZhichang Yuan 			pr_debug("indirectIO matched(%pOF) 0x%llx\n",
58265af618dSZhichang Yuan 				 dev, result);
58365af618dSZhichang Yuan 			*host = of_node_get(dev);
58465af618dSZhichang Yuan 			break;
58565af618dSZhichang Yuan 		}
58665af618dSZhichang Yuan 
587dbbdee94SGrant Likely 		/* Get new parent bus and counts */
588dbbdee94SGrant Likely 		pbus = of_match_bus(parent);
589dbbdee94SGrant Likely 		pbus->count_cells(dev, &pna, &pns);
590dbbdee94SGrant Likely 		if (!OF_CHECK_COUNTS(pna, pns)) {
5910d638a07SRob Herring 			pr_err("Bad cell count for %pOF\n", dev);
592dbbdee94SGrant Likely 			break;
593dbbdee94SGrant Likely 		}
594dbbdee94SGrant Likely 
5950d638a07SRob Herring 		pr_debug("parent bus is %s (na=%d, ns=%d) on %pOF\n",
5960d638a07SRob Herring 		    pbus->name, pna, pns, parent);
597dbbdee94SGrant Likely 
598dbbdee94SGrant Likely 		/* Apply bus translation */
599dbbdee94SGrant Likely 		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
600dbbdee94SGrant Likely 			break;
601dbbdee94SGrant Likely 
602dbbdee94SGrant Likely 		/* Complete the move up one level */
603dbbdee94SGrant Likely 		na = pna;
604dbbdee94SGrant Likely 		ns = pns;
605dbbdee94SGrant Likely 		bus = pbus;
606dbbdee94SGrant Likely 
607606ad42aSRob Herring 		of_dump_addr("one level translation:", addr, na);
608dbbdee94SGrant Likely 	}
609dbbdee94SGrant Likely  bail:
610dbbdee94SGrant Likely 	of_node_put(parent);
611dbbdee94SGrant Likely 	of_node_put(dev);
612dbbdee94SGrant Likely 
613dbbdee94SGrant Likely 	return result;
614dbbdee94SGrant Likely }
615dbbdee94SGrant Likely 
of_translate_address(struct device_node * dev,const __be32 * in_addr)6160131d897SSebastian Andrzej Siewior u64 of_translate_address(struct device_node *dev, const __be32 *in_addr)
617dbbdee94SGrant Likely {
61865af618dSZhichang Yuan 	struct device_node *host;
61965af618dSZhichang Yuan 	u64 ret;
62065af618dSZhichang Yuan 
62195835a8dSMaxime Ripard 	ret = __of_translate_address(dev, of_get_parent,
62295835a8dSMaxime Ripard 				     in_addr, "ranges", &host);
62365af618dSZhichang Yuan 	if (host) {
62465af618dSZhichang Yuan 		of_node_put(host);
62565af618dSZhichang Yuan 		return OF_BAD_ADDR;
62665af618dSZhichang Yuan 	}
62765af618dSZhichang Yuan 
62865af618dSZhichang Yuan 	return ret;
629dbbdee94SGrant Likely }
630dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_address);
631dbbdee94SGrant Likely 
632f1ad5338SRobin Murphy #ifdef CONFIG_HAS_DMA
__of_get_dma_parent(const struct device_node * np)633f1ad5338SRobin Murphy struct device_node *__of_get_dma_parent(const struct device_node *np)
634f83a6e5dSMaxime Ripard {
635f83a6e5dSMaxime Ripard 	struct of_phandle_args args;
636f83a6e5dSMaxime Ripard 	int ret, index;
637f83a6e5dSMaxime Ripard 
638f83a6e5dSMaxime Ripard 	index = of_property_match_string(np, "interconnect-names", "dma-mem");
639f83a6e5dSMaxime Ripard 	if (index < 0)
640f83a6e5dSMaxime Ripard 		return of_get_parent(np);
641f83a6e5dSMaxime Ripard 
642f83a6e5dSMaxime Ripard 	ret = of_parse_phandle_with_args(np, "interconnects",
643f83a6e5dSMaxime Ripard 					 "#interconnect-cells",
644f83a6e5dSMaxime Ripard 					 index, &args);
645f83a6e5dSMaxime Ripard 	if (ret < 0)
646f83a6e5dSMaxime Ripard 		return of_get_parent(np);
647f83a6e5dSMaxime Ripard 
6487094f3b6SZijun Hu 	return args.np;
649f83a6e5dSMaxime Ripard }
650f1ad5338SRobin Murphy #endif
651f83a6e5dSMaxime Ripard 
of_get_next_dma_parent(struct device_node * np)652862ab557SRobin Murphy static struct device_node *of_get_next_dma_parent(struct device_node *np)
653862ab557SRobin Murphy {
654862ab557SRobin Murphy 	struct device_node *parent;
655862ab557SRobin Murphy 
656862ab557SRobin Murphy 	parent = __of_get_dma_parent(np);
657862ab557SRobin Murphy 	of_node_put(np);
658862ab557SRobin Murphy 
659862ab557SRobin Murphy 	return parent;
660862ab557SRobin Murphy }
661862ab557SRobin Murphy 
of_translate_dma_address(struct device_node * dev,const __be32 * in_addr)6620131d897SSebastian Andrzej Siewior u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
663dbbdee94SGrant Likely {
66465af618dSZhichang Yuan 	struct device_node *host;
66565af618dSZhichang Yuan 	u64 ret;
66665af618dSZhichang Yuan 
667f83a6e5dSMaxime Ripard 	ret = __of_translate_address(dev, __of_get_dma_parent,
66895835a8dSMaxime Ripard 				     in_addr, "dma-ranges", &host);
66965af618dSZhichang Yuan 
67065af618dSZhichang Yuan 	if (host) {
67165af618dSZhichang Yuan 		of_node_put(host);
67265af618dSZhichang Yuan 		return OF_BAD_ADDR;
67365af618dSZhichang Yuan 	}
67465af618dSZhichang Yuan 
67565af618dSZhichang Yuan 	return ret;
676dbbdee94SGrant Likely }
677dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_dma_address);
678dbbdee94SGrant Likely 
679e251c213SThierry Reding /**
680e251c213SThierry Reding  * of_translate_dma_region - Translate device tree address and size tuple
681e251c213SThierry Reding  * @dev: device tree node for which to translate
682e251c213SThierry Reding  * @prop: pointer into array of cells
683e251c213SThierry Reding  * @start: return value for the start of the DMA range
684e251c213SThierry Reding  * @length: return value for the length of the DMA range
685e251c213SThierry Reding  *
686e251c213SThierry Reding  * Returns a pointer to the cell immediately following the translated DMA region.
687e251c213SThierry Reding  */
of_translate_dma_region(struct device_node * dev,const __be32 * prop,phys_addr_t * start,size_t * length)688e251c213SThierry Reding const __be32 *of_translate_dma_region(struct device_node *dev, const __be32 *prop,
689e251c213SThierry Reding 				      phys_addr_t *start, size_t *length)
690e251c213SThierry Reding {
691e251c213SThierry Reding 	struct device_node *parent;
692e251c213SThierry Reding 	u64 address, size;
693e251c213SThierry Reding 	int na, ns;
694e251c213SThierry Reding 
695e251c213SThierry Reding 	parent = __of_get_dma_parent(dev);
696e251c213SThierry Reding 	if (!parent)
697e251c213SThierry Reding 		return NULL;
698e251c213SThierry Reding 
699e251c213SThierry Reding 	na = of_bus_n_addr_cells(parent);
700e251c213SThierry Reding 	ns = of_bus_n_size_cells(parent);
701e251c213SThierry Reding 
702e251c213SThierry Reding 	of_node_put(parent);
703e251c213SThierry Reding 
704e251c213SThierry Reding 	address = of_translate_dma_address(dev, prop);
705e251c213SThierry Reding 	if (address == OF_BAD_ADDR)
706e251c213SThierry Reding 		return NULL;
707e251c213SThierry Reding 
708e251c213SThierry Reding 	size = of_read_number(prop + na, ns);
709e251c213SThierry Reding 
710e251c213SThierry Reding 	if (start)
711e251c213SThierry Reding 		*start = address;
712e251c213SThierry Reding 
713e251c213SThierry Reding 	if (length)
714e251c213SThierry Reding 		*length = size;
715e251c213SThierry Reding 
716e251c213SThierry Reding 	return prop + na + ns;
717e251c213SThierry Reding }
718e251c213SThierry Reding EXPORT_SYMBOL(of_translate_dma_region);
719e251c213SThierry Reding 
__of_get_address(struct device_node * dev,int index,int bar_no,u64 * size,unsigned int * flags)720050a2c62SRob Herring const __be32 *__of_get_address(struct device_node *dev, int index, int bar_no,
721050a2c62SRob Herring 			       u64 *size, unsigned int *flags)
722dbbdee94SGrant Likely {
7230131d897SSebastian Andrzej Siewior 	const __be32 *prop;
724dbbdee94SGrant Likely 	unsigned int psize;
725dbbdee94SGrant Likely 	struct device_node *parent;
726dbbdee94SGrant Likely 	struct of_bus *bus;
727dbbdee94SGrant Likely 	int onesize, i, na, ns;
728dbbdee94SGrant Likely 
729dbbdee94SGrant Likely 	/* Get parent & match bus type */
730dbbdee94SGrant Likely 	parent = of_get_parent(dev);
731dbbdee94SGrant Likely 	if (parent == NULL)
732dbbdee94SGrant Likely 		return NULL;
733dbbdee94SGrant Likely 	bus = of_match_bus(parent);
734050a2c62SRob Herring 	if (strcmp(bus->name, "pci") && (bar_no >= 0)) {
735050a2c62SRob Herring 		of_node_put(parent);
736050a2c62SRob Herring 		return NULL;
737050a2c62SRob Herring 	}
738dbbdee94SGrant Likely 	bus->count_cells(dev, &na, &ns);
739dbbdee94SGrant Likely 	of_node_put(parent);
7405d61b165SStephen Warren 	if (!OF_CHECK_ADDR_COUNT(na))
741dbbdee94SGrant Likely 		return NULL;
742dbbdee94SGrant Likely 
743dbbdee94SGrant Likely 	/* Get "reg" or "assigned-addresses" property */
744dbbdee94SGrant Likely 	prop = of_get_property(dev, bus->addresses, &psize);
745dbbdee94SGrant Likely 	if (prop == NULL)
746dbbdee94SGrant Likely 		return NULL;
747dbbdee94SGrant Likely 	psize /= 4;
748dbbdee94SGrant Likely 
749dbbdee94SGrant Likely 	onesize = na + ns;
750050a2c62SRob Herring 	for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) {
751050a2c62SRob Herring 		u32 val = be32_to_cpu(prop[0]);
752050a2c62SRob Herring 		/* PCI bus matches on BAR number instead of index */
753050a2c62SRob Herring 		if (((bar_no >= 0) && ((val & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0))) ||
754050a2c62SRob Herring 		    ((index >= 0) && (i == index))) {
755dbbdee94SGrant Likely 			if (size)
756dbbdee94SGrant Likely 				*size = of_read_number(prop + na, ns);
757dbbdee94SGrant Likely 			if (flags)
758dbbdee94SGrant Likely 				*flags = bus->get_flags(prop);
759dbbdee94SGrant Likely 			return prop;
760dbbdee94SGrant Likely 		}
761050a2c62SRob Herring 	}
762dbbdee94SGrant Likely 	return NULL;
763dbbdee94SGrant Likely }
764050a2c62SRob Herring EXPORT_SYMBOL(__of_get_address);
765dbbdee94SGrant Likely 
766ff61bacdSRob Herring /**
767ff61bacdSRob Herring  * of_property_read_reg - Retrieve the specified "reg" entry index without translating
768ff61bacdSRob Herring  * @np: device tree node for which to retrieve "reg" from
769ff61bacdSRob Herring  * @idx: "reg" entry index to read
770ff61bacdSRob Herring  * @addr: return value for the untranslated address
771ff61bacdSRob Herring  * @size: return value for the entry size
772ff61bacdSRob Herring  *
773ff61bacdSRob Herring  * Returns -EINVAL if "reg" is not found. Returns 0 on success with addr and
774ff61bacdSRob Herring  * size values filled in.
775ff61bacdSRob Herring  */
of_property_read_reg(struct device_node * np,int idx,u64 * addr,u64 * size)776ff61bacdSRob Herring int of_property_read_reg(struct device_node *np, int idx, u64 *addr, u64 *size)
777ff61bacdSRob Herring {
778ff61bacdSRob Herring 	const __be32 *prop = of_get_address(np, idx, size, NULL);
779ff61bacdSRob Herring 
780ff61bacdSRob Herring 	if (!prop)
781ff61bacdSRob Herring 		return -EINVAL;
782ff61bacdSRob Herring 
783ff61bacdSRob Herring 	*addr = of_read_number(prop, of_n_addr_cells(np));
784ff61bacdSRob Herring 
785ff61bacdSRob Herring 	return 0;
786ff61bacdSRob Herring }
787ff61bacdSRob Herring EXPORT_SYMBOL(of_property_read_reg);
788ff61bacdSRob Herring 
parser_init(struct of_pci_range_parser * parser,struct device_node * node,const char * name)78967ccd2b9SRob Herring static int parser_init(struct of_pci_range_parser *parser,
79067ccd2b9SRob Herring 			struct device_node *node, const char *name)
79167ccd2b9SRob Herring {
79267ccd2b9SRob Herring 	int rlen;
79367ccd2b9SRob Herring 
79467ccd2b9SRob Herring 	parser->node = node;
79567ccd2b9SRob Herring 	parser->pna = of_n_addr_cells(node);
796bc5e522eSRob Herring 	parser->na = of_bus_n_addr_cells(node);
797bc5e522eSRob Herring 	parser->ns = of_bus_n_size_cells(node);
79867ccd2b9SRob Herring 	parser->dma = !strcmp(name, "dma-ranges");
7992f96593eSJiaxun Yang 	parser->bus = of_match_bus(node);
80067ccd2b9SRob Herring 
80167ccd2b9SRob Herring 	parser->range = of_get_property(node, name, &rlen);
80267ccd2b9SRob Herring 	if (parser->range == NULL)
80367ccd2b9SRob Herring 		return -ENOENT;
80467ccd2b9SRob Herring 
80567ccd2b9SRob Herring 	parser->end = parser->range + rlen / sizeof(__be32);
80667ccd2b9SRob Herring 
80767ccd2b9SRob Herring 	return 0;
80867ccd2b9SRob Herring }
80967ccd2b9SRob Herring 
of_pci_range_parser_init(struct of_pci_range_parser * parser,struct device_node * node)81067ccd2b9SRob Herring int of_pci_range_parser_init(struct of_pci_range_parser *parser,
81167ccd2b9SRob Herring 				struct device_node *node)
81267ccd2b9SRob Herring {
81367ccd2b9SRob Herring 	return parser_init(parser, node, "ranges");
81467ccd2b9SRob Herring }
81567ccd2b9SRob Herring EXPORT_SYMBOL_GPL(of_pci_range_parser_init);
81667ccd2b9SRob Herring 
of_pci_dma_range_parser_init(struct of_pci_range_parser * parser,struct device_node * node)81767ccd2b9SRob Herring int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser,
81867ccd2b9SRob Herring 				struct device_node *node)
81967ccd2b9SRob Herring {
82067ccd2b9SRob Herring 	return parser_init(parser, node, "dma-ranges");
82167ccd2b9SRob Herring }
82267ccd2b9SRob Herring EXPORT_SYMBOL_GPL(of_pci_dma_range_parser_init);
823bc5e522eSRob Herring #define of_dma_range_parser_init of_pci_dma_range_parser_init
82467ccd2b9SRob Herring 
of_pci_range_parser_one(struct of_pci_range_parser * parser,struct of_pci_range * range)82567ccd2b9SRob Herring struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
82667ccd2b9SRob Herring 						struct of_pci_range *range)
82767ccd2b9SRob Herring {
828bc5e522eSRob Herring 	int na = parser->na;
829bc5e522eSRob Herring 	int ns = parser->ns;
830bc5e522eSRob Herring 	int np = parser->pna + na + ns;
831443f803bSRob Herring 	int busflag_na = parser->bus->flag_cells;
83267ccd2b9SRob Herring 
83367ccd2b9SRob Herring 	if (!range)
83467ccd2b9SRob Herring 		return NULL;
83567ccd2b9SRob Herring 
836bc5e522eSRob Herring 	if (!parser->range || parser->range + np > parser->end)
83767ccd2b9SRob Herring 		return NULL;
83867ccd2b9SRob Herring 
8392f96593eSJiaxun Yang 	range->flags = parser->bus->get_flags(parser->range);
840bc5e522eSRob Herring 
8412f96593eSJiaxun Yang 	range->bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na);
842bc5e522eSRob Herring 
84367ccd2b9SRob Herring 	if (parser->dma)
84467ccd2b9SRob Herring 		range->cpu_addr = of_translate_dma_address(parser->node,
84567ccd2b9SRob Herring 				parser->range + na);
84667ccd2b9SRob Herring 	else
84767ccd2b9SRob Herring 		range->cpu_addr = of_translate_address(parser->node,
84867ccd2b9SRob Herring 				parser->range + na);
84967ccd2b9SRob Herring 	range->size = of_read_number(parser->range + parser->pna + na, ns);
85067ccd2b9SRob Herring 
851bc5e522eSRob Herring 	parser->range += np;
85267ccd2b9SRob Herring 
85367ccd2b9SRob Herring 	/* Now consume following elements while they are contiguous */
854bc5e522eSRob Herring 	while (parser->range + np <= parser->end) {
855bc5e522eSRob Herring 		u32 flags = 0;
8562f96593eSJiaxun Yang 		u64 bus_addr, cpu_addr, size;
85767ccd2b9SRob Herring 
8582f96593eSJiaxun Yang 		flags = parser->bus->get_flags(parser->range);
8592f96593eSJiaxun Yang 		bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na);
86067ccd2b9SRob Herring 		if (parser->dma)
86167ccd2b9SRob Herring 			cpu_addr = of_translate_dma_address(parser->node,
86267ccd2b9SRob Herring 					parser->range + na);
86367ccd2b9SRob Herring 		else
86467ccd2b9SRob Herring 			cpu_addr = of_translate_address(parser->node,
86567ccd2b9SRob Herring 					parser->range + na);
86667ccd2b9SRob Herring 		size = of_read_number(parser->range + parser->pna + na, ns);
86767ccd2b9SRob Herring 
86867ccd2b9SRob Herring 		if (flags != range->flags)
86967ccd2b9SRob Herring 			break;
8702f96593eSJiaxun Yang 		if (bus_addr != range->bus_addr + range->size ||
87167ccd2b9SRob Herring 		    cpu_addr != range->cpu_addr + range->size)
87267ccd2b9SRob Herring 			break;
87367ccd2b9SRob Herring 
87467ccd2b9SRob Herring 		range->size += size;
875bc5e522eSRob Herring 		parser->range += np;
87667ccd2b9SRob Herring 	}
87767ccd2b9SRob Herring 
87867ccd2b9SRob Herring 	return range;
87967ccd2b9SRob Herring }
88067ccd2b9SRob Herring EXPORT_SYMBOL_GPL(of_pci_range_parser_one);
88167ccd2b9SRob Herring 
of_translate_ioport(struct device_node * dev,const __be32 * in_addr,u64 size)88265af618dSZhichang Yuan static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr,
88365af618dSZhichang Yuan 			u64 size)
88465af618dSZhichang Yuan {
88565af618dSZhichang Yuan 	u64 taddr;
88665af618dSZhichang Yuan 	unsigned long port;
88765af618dSZhichang Yuan 	struct device_node *host;
88865af618dSZhichang Yuan 
88995835a8dSMaxime Ripard 	taddr = __of_translate_address(dev, of_get_parent,
89095835a8dSMaxime Ripard 				       in_addr, "ranges", &host);
89165af618dSZhichang Yuan 	if (host) {
89265af618dSZhichang Yuan 		/* host-specific port access */
89365af618dSZhichang Yuan 		port = logic_pio_trans_hwaddr(&host->fwnode, taddr, size);
89465af618dSZhichang Yuan 		of_node_put(host);
89565af618dSZhichang Yuan 	} else {
89665af618dSZhichang Yuan 		/* memory-mapped I/O range */
89765af618dSZhichang Yuan 		port = pci_address_to_pio(taddr);
89865af618dSZhichang Yuan 	}
89965af618dSZhichang Yuan 
90065af618dSZhichang Yuan 	if (port == (unsigned long)-1)
90165af618dSZhichang Yuan 		return OF_BAD_ADDR;
90265af618dSZhichang Yuan 
90365af618dSZhichang Yuan 	return port;
90465af618dSZhichang Yuan }
90565af618dSZhichang Yuan 
906e0d07278SJim Quinlan #ifdef CONFIG_HAS_DMA
90718308c94SGrygorii Strashko /**
908e0d07278SJim Quinlan  * of_dma_get_range - Get DMA range info and put it into a map array
90918308c94SGrygorii Strashko  * @np:		device node to get DMA range info
910e0d07278SJim Quinlan  * @map:	dma range structure to return
91118308c94SGrygorii Strashko  *
91218308c94SGrygorii Strashko  * Look in bottom up direction for the first "dma-ranges" property
913e0d07278SJim Quinlan  * and parse it.  Put the information into a DMA offset map array.
914e0d07278SJim Quinlan  *
91518308c94SGrygorii Strashko  * dma-ranges format:
91618308c94SGrygorii Strashko  *	DMA addr (dma_addr)	: naddr cells
91718308c94SGrygorii Strashko  *	CPU addr (phys_addr_t)	: pna cells
91818308c94SGrygorii Strashko  *	size			: nsize cells
91918308c94SGrygorii Strashko  *
920e0d07278SJim Quinlan  * It returns -ENODEV if "dma-ranges" property was not found for this
921e0d07278SJim Quinlan  * device in the DT.
92218308c94SGrygorii Strashko  */
of_dma_get_range(struct device_node * np,const struct bus_dma_region ** map)923e0d07278SJim Quinlan int of_dma_get_range(struct device_node *np, const struct bus_dma_region **map)
92418308c94SGrygorii Strashko {
92518308c94SGrygorii Strashko 	struct device_node *node = of_node_get(np);
92618308c94SGrygorii Strashko 	const __be32 *ranges = NULL;
927951d4885SRobin Murphy 	bool found_dma_ranges = false;
9287a8b64d1SRob Herring 	struct of_range_parser parser;
9297a8b64d1SRob Herring 	struct of_range range;
930e0d07278SJim Quinlan 	struct bus_dma_region *r;
931e0d07278SJim Quinlan 	int len, num_ranges = 0;
932e0d07278SJim Quinlan 	int ret = 0;
93318308c94SGrygorii Strashko 
934951d4885SRobin Murphy 	while (node) {
93518308c94SGrygorii Strashko 		ranges = of_get_property(node, "dma-ranges", &len);
93618308c94SGrygorii Strashko 
93718308c94SGrygorii Strashko 		/* Ignore empty ranges, they imply no translation required */
93818308c94SGrygorii Strashko 		if (ranges && len > 0)
93918308c94SGrygorii Strashko 			break;
94018308c94SGrygorii Strashko 
941951d4885SRobin Murphy 		/* Once we find 'dma-ranges', then a missing one is an error */
942951d4885SRobin Murphy 		if (found_dma_ranges && !ranges) {
943951d4885SRobin Murphy 			ret = -ENODEV;
944951d4885SRobin Murphy 			goto out;
945951d4885SRobin Murphy 		}
946951d4885SRobin Murphy 		found_dma_ranges = true;
947951d4885SRobin Murphy 
948951d4885SRobin Murphy 		node = of_get_next_dma_parent(node);
94918308c94SGrygorii Strashko 	}
95018308c94SGrygorii Strashko 
951951d4885SRobin Murphy 	if (!node || !ranges) {
9520d638a07SRob Herring 		pr_debug("no dma-ranges found for node(%pOF)\n", np);
95318308c94SGrygorii Strashko 		ret = -ENODEV;
95418308c94SGrygorii Strashko 		goto out;
95518308c94SGrygorii Strashko 	}
95618308c94SGrygorii Strashko 
9577a8b64d1SRob Herring 	of_dma_range_parser_init(&parser, node);
958f6933c01SMark Brown 	for_each_of_range(&parser, &range) {
959f6933c01SMark Brown 		if (range.cpu_addr == OF_BAD_ADDR) {
960f6933c01SMark Brown 			pr_err("translation of DMA address(%llx) to CPU address failed node(%pOF)\n",
961f6933c01SMark Brown 			       range.bus_addr, node);
962f6933c01SMark Brown 			continue;
963f6933c01SMark Brown 		}
964e0d07278SJim Quinlan 		num_ranges++;
965f6933c01SMark Brown 	}
966f6933c01SMark Brown 
967f6933c01SMark Brown 	if (!num_ranges) {
968f6933c01SMark Brown 		ret = -EINVAL;
969f6933c01SMark Brown 		goto out;
970f6933c01SMark Brown 	}
97118308c94SGrygorii Strashko 
972e0d07278SJim Quinlan 	r = kcalloc(num_ranges + 1, sizeof(*r), GFP_KERNEL);
973e0d07278SJim Quinlan 	if (!r) {
974e0d07278SJim Quinlan 		ret = -ENOMEM;
975e0d07278SJim Quinlan 		goto out;
976e0d07278SJim Quinlan 	}
977e0d07278SJim Quinlan 
978e0d07278SJim Quinlan 	/*
979f6933c01SMark Brown 	 * Record all info in the generic DMA ranges array for struct device,
980f6933c01SMark Brown 	 * returning an error if we don't find any parsable ranges.
981e0d07278SJim Quinlan 	 */
982e0d07278SJim Quinlan 	*map = r;
983e0d07278SJim Quinlan 	of_dma_range_parser_init(&parser, node);
9847a8b64d1SRob Herring 	for_each_of_range(&parser, &range) {
98518308c94SGrygorii Strashko 		pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n",
9867a8b64d1SRob Herring 			 range.bus_addr, range.cpu_addr, range.size);
987f6933c01SMark Brown 		if (range.cpu_addr == OF_BAD_ADDR)
988f49c7fafSColin Ian King 			continue;
989e0d07278SJim Quinlan 		r->cpu_start = range.cpu_addr;
990e0d07278SJim Quinlan 		r->dma_start = range.bus_addr;
991e0d07278SJim Quinlan 		r->size = range.size;
992e0d07278SJim Quinlan 		r->offset = range.cpu_addr - range.bus_addr;
993e0d07278SJim Quinlan 		r++;
9949d55bebdSRob Herring 	}
99518308c94SGrygorii Strashko out:
99618308c94SGrygorii Strashko 	of_node_put(node);
99718308c94SGrygorii Strashko 	return ret;
99818308c94SGrygorii Strashko }
999e0d07278SJim Quinlan #endif /* CONFIG_HAS_DMA */
100092ea637eSSantosh Shilimkar 
100192ea637eSSantosh Shilimkar /**
1002964db79dSNicolas Saenz Julienne  * of_dma_get_max_cpu_address - Gets highest CPU address suitable for DMA
1003964db79dSNicolas Saenz Julienne  * @np: The node to start searching from or NULL to start from the root
1004964db79dSNicolas Saenz Julienne  *
1005964db79dSNicolas Saenz Julienne  * Gets the highest CPU physical address that is addressable by all DMA masters
1006964db79dSNicolas Saenz Julienne  * in the sub-tree pointed by np, or the whole tree if NULL is passed. If no
1007964db79dSNicolas Saenz Julienne  * DMA constrained device is found, it returns PHYS_ADDR_MAX.
1008964db79dSNicolas Saenz Julienne  */
of_dma_get_max_cpu_address(struct device_node * np)1009964db79dSNicolas Saenz Julienne phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np)
1010964db79dSNicolas Saenz Julienne {
1011964db79dSNicolas Saenz Julienne 	phys_addr_t max_cpu_addr = PHYS_ADDR_MAX;
1012964db79dSNicolas Saenz Julienne 	struct of_range_parser parser;
1013964db79dSNicolas Saenz Julienne 	phys_addr_t subtree_max_addr;
1014964db79dSNicolas Saenz Julienne 	struct device_node *child;
1015964db79dSNicolas Saenz Julienne 	struct of_range range;
1016964db79dSNicolas Saenz Julienne 	const __be32 *ranges;
1017964db79dSNicolas Saenz Julienne 	u64 cpu_end = 0;
1018964db79dSNicolas Saenz Julienne 	int len;
1019964db79dSNicolas Saenz Julienne 
1020964db79dSNicolas Saenz Julienne 	if (!np)
1021964db79dSNicolas Saenz Julienne 		np = of_root;
1022964db79dSNicolas Saenz Julienne 
1023964db79dSNicolas Saenz Julienne 	ranges = of_get_property(np, "dma-ranges", &len);
1024964db79dSNicolas Saenz Julienne 	if (ranges && len) {
1025964db79dSNicolas Saenz Julienne 		of_dma_range_parser_init(&parser, np);
1026964db79dSNicolas Saenz Julienne 		for_each_of_range(&parser, &range)
1027964db79dSNicolas Saenz Julienne 			if (range.cpu_addr + range.size > cpu_end)
1028964db79dSNicolas Saenz Julienne 				cpu_end = range.cpu_addr + range.size - 1;
1029964db79dSNicolas Saenz Julienne 
1030964db79dSNicolas Saenz Julienne 		if (max_cpu_addr > cpu_end)
1031964db79dSNicolas Saenz Julienne 			max_cpu_addr = cpu_end;
1032964db79dSNicolas Saenz Julienne 	}
1033964db79dSNicolas Saenz Julienne 
1034964db79dSNicolas Saenz Julienne 	for_each_available_child_of_node(np, child) {
1035964db79dSNicolas Saenz Julienne 		subtree_max_addr = of_dma_get_max_cpu_address(child);
1036964db79dSNicolas Saenz Julienne 		if (max_cpu_addr > subtree_max_addr)
1037964db79dSNicolas Saenz Julienne 			max_cpu_addr = subtree_max_addr;
1038964db79dSNicolas Saenz Julienne 	}
1039964db79dSNicolas Saenz Julienne 
1040964db79dSNicolas Saenz Julienne 	return max_cpu_addr;
1041964db79dSNicolas Saenz Julienne }
1042964db79dSNicolas Saenz Julienne 
1043964db79dSNicolas Saenz Julienne /**
104492ea637eSSantosh Shilimkar  * of_dma_is_coherent - Check if device is coherent
104592ea637eSSantosh Shilimkar  * @np:	device node
104692ea637eSSantosh Shilimkar  *
104792ea637eSSantosh Shilimkar  * It returns true if "dma-coherent" property was found
1048dabf6b36SMichael Ellerman  * for this device in the DT, or if DMA is coherent by
104912b82775SHeiko Stuebner  * default for OF devices on the current platform and no
105012b82775SHeiko Stuebner  * "dma-noncoherent" property was found for this device.
105192ea637eSSantosh Shilimkar  */
of_dma_is_coherent(struct device_node * np)105292ea637eSSantosh Shilimkar bool of_dma_is_coherent(struct device_node *np)
105392ea637eSSantosh Shilimkar {
1054a5bea04fSEvan Nimmo 	struct device_node *node;
1055c00a60d6SJiaxun Yang 	bool is_coherent = dma_default_coherent;
1056dabf6b36SMichael Ellerman 
1057a5bea04fSEvan Nimmo 	node = of_node_get(np);
1058a5bea04fSEvan Nimmo 
105992ea637eSSantosh Shilimkar 	while (node) {
106092ea637eSSantosh Shilimkar 		if (of_property_read_bool(node, "dma-coherent")) {
106112b82775SHeiko Stuebner 			is_coherent = true;
106212b82775SHeiko Stuebner 			break;
106312b82775SHeiko Stuebner 		}
106412b82775SHeiko Stuebner 		if (of_property_read_bool(node, "dma-noncoherent")) {
106512b82775SHeiko Stuebner 			is_coherent = false;
106612b82775SHeiko Stuebner 			break;
106792ea637eSSantosh Shilimkar 		}
1068c60bf3ebSRobin Murphy 		node = of_get_next_dma_parent(node);
106992ea637eSSantosh Shilimkar 	}
107092ea637eSSantosh Shilimkar 	of_node_put(node);
107112b82775SHeiko Stuebner 	return is_coherent;
107292ea637eSSantosh Shilimkar }
107392ea637eSSantosh Shilimkar EXPORT_SYMBOL_GPL(of_dma_is_coherent);
107489897f73SHector Martin 
107589897f73SHector Martin /**
107689897f73SHector Martin  * of_mmio_is_nonposted - Check if device uses non-posted MMIO
107789897f73SHector Martin  * @np:	device node
107889897f73SHector Martin  *
107989897f73SHector Martin  * Returns true if the "nonposted-mmio" property was found for
108089897f73SHector Martin  * the device's bus.
108189897f73SHector Martin  *
108289897f73SHector Martin  * This is currently only enabled on builds that support Apple ARM devices, as
108389897f73SHector Martin  * an optimization.
108489897f73SHector Martin  */
of_mmio_is_nonposted(struct device_node * np)108589897f73SHector Martin static bool of_mmio_is_nonposted(struct device_node *np)
108689897f73SHector Martin {
108789897f73SHector Martin 	struct device_node *parent;
108889897f73SHector Martin 	bool nonposted;
108989897f73SHector Martin 
109089897f73SHector Martin 	if (!IS_ENABLED(CONFIG_ARCH_APPLE))
109189897f73SHector Martin 		return false;
109289897f73SHector Martin 
109389897f73SHector Martin 	parent = of_get_parent(np);
109489897f73SHector Martin 	if (!parent)
109589897f73SHector Martin 		return false;
109689897f73SHector Martin 
109789897f73SHector Martin 	nonposted = of_property_read_bool(parent, "nonposted-mmio");
109889897f73SHector Martin 
109989897f73SHector Martin 	of_node_put(parent);
110089897f73SHector Martin 	return nonposted;
110189897f73SHector Martin }
11025eac0bdcSGeert Uytterhoeven 
__of_address_to_resource(struct device_node * dev,int index,int bar_no,struct resource * r)11035eac0bdcSGeert Uytterhoeven static int __of_address_to_resource(struct device_node *dev, int index, int bar_no,
11045eac0bdcSGeert Uytterhoeven 		struct resource *r)
11055eac0bdcSGeert Uytterhoeven {
11065eac0bdcSGeert Uytterhoeven 	u64 taddr;
11075eac0bdcSGeert Uytterhoeven 	const __be32	*addrp;
11085eac0bdcSGeert Uytterhoeven 	u64		size;
11095eac0bdcSGeert Uytterhoeven 	unsigned int	flags;
11105eac0bdcSGeert Uytterhoeven 	const char	*name = NULL;
11115eac0bdcSGeert Uytterhoeven 
11125eac0bdcSGeert Uytterhoeven 	addrp = __of_get_address(dev, index, bar_no, &size, &flags);
11135eac0bdcSGeert Uytterhoeven 	if (addrp == NULL)
11145eac0bdcSGeert Uytterhoeven 		return -EINVAL;
11155eac0bdcSGeert Uytterhoeven 
11165eac0bdcSGeert Uytterhoeven 	/* Get optional "reg-names" property to add a name to a resource */
11175eac0bdcSGeert Uytterhoeven 	if (index >= 0)
11185eac0bdcSGeert Uytterhoeven 		of_property_read_string_index(dev, "reg-names",	index, &name);
11195eac0bdcSGeert Uytterhoeven 
11205eac0bdcSGeert Uytterhoeven 	if (flags & IORESOURCE_MEM)
11215eac0bdcSGeert Uytterhoeven 		taddr = of_translate_address(dev, addrp);
11225eac0bdcSGeert Uytterhoeven 	else if (flags & IORESOURCE_IO)
11235eac0bdcSGeert Uytterhoeven 		taddr = of_translate_ioport(dev, addrp, size);
11245eac0bdcSGeert Uytterhoeven 	else
11255eac0bdcSGeert Uytterhoeven 		return -EINVAL;
11265eac0bdcSGeert Uytterhoeven 
11275eac0bdcSGeert Uytterhoeven 	if (taddr == OF_BAD_ADDR)
11285eac0bdcSGeert Uytterhoeven 		return -EINVAL;
11295eac0bdcSGeert Uytterhoeven 	memset(r, 0, sizeof(struct resource));
11305eac0bdcSGeert Uytterhoeven 
11315eac0bdcSGeert Uytterhoeven 	if (of_mmio_is_nonposted(dev))
11325eac0bdcSGeert Uytterhoeven 		flags |= IORESOURCE_MEM_NONPOSTED;
11335eac0bdcSGeert Uytterhoeven 
1134d657d286SThomas Weißschuh 	if (overflows_type(taddr, r->start))
1135d657d286SThomas Weißschuh 		return -EOVERFLOW;
11365eac0bdcSGeert Uytterhoeven 	r->start = taddr;
1137d657d286SThomas Weißschuh 	if (overflows_type(taddr + size - 1, r->end))
1138d657d286SThomas Weißschuh 		return -EOVERFLOW;
11395eac0bdcSGeert Uytterhoeven 	r->end = taddr + size - 1;
11405eac0bdcSGeert Uytterhoeven 	r->flags = flags;
11415eac0bdcSGeert Uytterhoeven 	r->name = name ? name : dev->full_name;
11425eac0bdcSGeert Uytterhoeven 
11435eac0bdcSGeert Uytterhoeven 	return 0;
11445eac0bdcSGeert Uytterhoeven }
11455eac0bdcSGeert Uytterhoeven 
11465eac0bdcSGeert Uytterhoeven /**
11475eac0bdcSGeert Uytterhoeven  * of_address_to_resource - Translate device tree address and return as resource
11485eac0bdcSGeert Uytterhoeven  * @dev:	Caller's Device Node
11495eac0bdcSGeert Uytterhoeven  * @index:	Index into the array
11505eac0bdcSGeert Uytterhoeven  * @r:		Pointer to resource array
11515eac0bdcSGeert Uytterhoeven  *
11525eac0bdcSGeert Uytterhoeven  * Returns -EINVAL if the range cannot be converted to resource.
11535eac0bdcSGeert Uytterhoeven  *
11545eac0bdcSGeert Uytterhoeven  * Note that if your address is a PIO address, the conversion will fail if
11555eac0bdcSGeert Uytterhoeven  * the physical address can't be internally converted to an IO token with
11565eac0bdcSGeert Uytterhoeven  * pci_address_to_pio(), that is because it's either called too early or it
11575eac0bdcSGeert Uytterhoeven  * can't be matched to any host bridge IO space
11585eac0bdcSGeert Uytterhoeven  */
of_address_to_resource(struct device_node * dev,int index,struct resource * r)11595eac0bdcSGeert Uytterhoeven int of_address_to_resource(struct device_node *dev, int index,
11605eac0bdcSGeert Uytterhoeven 			   struct resource *r)
11615eac0bdcSGeert Uytterhoeven {
11625eac0bdcSGeert Uytterhoeven 	return __of_address_to_resource(dev, index, -1, r);
11635eac0bdcSGeert Uytterhoeven }
11645eac0bdcSGeert Uytterhoeven EXPORT_SYMBOL_GPL(of_address_to_resource);
11655eac0bdcSGeert Uytterhoeven 
of_pci_address_to_resource(struct device_node * dev,int bar,struct resource * r)11665eac0bdcSGeert Uytterhoeven int of_pci_address_to_resource(struct device_node *dev, int bar,
11675eac0bdcSGeert Uytterhoeven 			       struct resource *r)
11685eac0bdcSGeert Uytterhoeven {
11695eac0bdcSGeert Uytterhoeven 
11705eac0bdcSGeert Uytterhoeven 	if (!IS_ENABLED(CONFIG_PCI))
11715eac0bdcSGeert Uytterhoeven 		return -ENOSYS;
11725eac0bdcSGeert Uytterhoeven 
11735eac0bdcSGeert Uytterhoeven 	return __of_address_to_resource(dev, -1, bar, r);
11745eac0bdcSGeert Uytterhoeven }
11755eac0bdcSGeert Uytterhoeven EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
11765eac0bdcSGeert Uytterhoeven 
11775eac0bdcSGeert Uytterhoeven /**
11785eac0bdcSGeert Uytterhoeven  * of_iomap - Maps the memory mapped IO for a given device_node
11795eac0bdcSGeert Uytterhoeven  * @np:		the device whose io range will be mapped
11805eac0bdcSGeert Uytterhoeven  * @index:	index of the io range
11815eac0bdcSGeert Uytterhoeven  *
11825eac0bdcSGeert Uytterhoeven  * Returns a pointer to the mapped memory
11835eac0bdcSGeert Uytterhoeven  */
of_iomap(struct device_node * np,int index)11845eac0bdcSGeert Uytterhoeven void __iomem *of_iomap(struct device_node *np, int index)
11855eac0bdcSGeert Uytterhoeven {
11865eac0bdcSGeert Uytterhoeven 	struct resource res;
11875eac0bdcSGeert Uytterhoeven 
11885eac0bdcSGeert Uytterhoeven 	if (of_address_to_resource(np, index, &res))
11895eac0bdcSGeert Uytterhoeven 		return NULL;
11905eac0bdcSGeert Uytterhoeven 
11915eac0bdcSGeert Uytterhoeven 	if (res.flags & IORESOURCE_MEM_NONPOSTED)
11925eac0bdcSGeert Uytterhoeven 		return ioremap_np(res.start, resource_size(&res));
11935eac0bdcSGeert Uytterhoeven 	else
11945eac0bdcSGeert Uytterhoeven 		return ioremap(res.start, resource_size(&res));
11955eac0bdcSGeert Uytterhoeven }
11965eac0bdcSGeert Uytterhoeven EXPORT_SYMBOL(of_iomap);
11975eac0bdcSGeert Uytterhoeven 
11985eac0bdcSGeert Uytterhoeven /*
11995eac0bdcSGeert Uytterhoeven  * of_io_request_and_map - Requests a resource and maps the memory mapped IO
12005eac0bdcSGeert Uytterhoeven  *			   for a given device_node
12015eac0bdcSGeert Uytterhoeven  * @device:	the device whose io range will be mapped
12025eac0bdcSGeert Uytterhoeven  * @index:	index of the io range
12035eac0bdcSGeert Uytterhoeven  * @name:	name "override" for the memory region request or NULL
12045eac0bdcSGeert Uytterhoeven  *
12055eac0bdcSGeert Uytterhoeven  * Returns a pointer to the requested and mapped memory or an ERR_PTR() encoded
12065eac0bdcSGeert Uytterhoeven  * error code on failure. Usage example:
12075eac0bdcSGeert Uytterhoeven  *
12085eac0bdcSGeert Uytterhoeven  *	base = of_io_request_and_map(node, 0, "foo");
12095eac0bdcSGeert Uytterhoeven  *	if (IS_ERR(base))
12105eac0bdcSGeert Uytterhoeven  *		return PTR_ERR(base);
12115eac0bdcSGeert Uytterhoeven  */
of_io_request_and_map(struct device_node * np,int index,const char * name)12125eac0bdcSGeert Uytterhoeven void __iomem *of_io_request_and_map(struct device_node *np, int index,
12135eac0bdcSGeert Uytterhoeven 				    const char *name)
12145eac0bdcSGeert Uytterhoeven {
12155eac0bdcSGeert Uytterhoeven 	struct resource res;
12165eac0bdcSGeert Uytterhoeven 	void __iomem *mem;
12175eac0bdcSGeert Uytterhoeven 
12185eac0bdcSGeert Uytterhoeven 	if (of_address_to_resource(np, index, &res))
12195eac0bdcSGeert Uytterhoeven 		return IOMEM_ERR_PTR(-EINVAL);
12205eac0bdcSGeert Uytterhoeven 
12215eac0bdcSGeert Uytterhoeven 	if (!name)
12225eac0bdcSGeert Uytterhoeven 		name = res.name;
12235eac0bdcSGeert Uytterhoeven 	if (!request_mem_region(res.start, resource_size(&res), name))
12245eac0bdcSGeert Uytterhoeven 		return IOMEM_ERR_PTR(-EBUSY);
12255eac0bdcSGeert Uytterhoeven 
12265eac0bdcSGeert Uytterhoeven 	if (res.flags & IORESOURCE_MEM_NONPOSTED)
12275eac0bdcSGeert Uytterhoeven 		mem = ioremap_np(res.start, resource_size(&res));
12285eac0bdcSGeert Uytterhoeven 	else
12295eac0bdcSGeert Uytterhoeven 		mem = ioremap(res.start, resource_size(&res));
12305eac0bdcSGeert Uytterhoeven 
12315eac0bdcSGeert Uytterhoeven 	if (!mem) {
12325eac0bdcSGeert Uytterhoeven 		release_mem_region(res.start, resource_size(&res));
12335eac0bdcSGeert Uytterhoeven 		return IOMEM_ERR_PTR(-ENOMEM);
12345eac0bdcSGeert Uytterhoeven 	}
12355eac0bdcSGeert Uytterhoeven 
12365eac0bdcSGeert Uytterhoeven 	return mem;
12375eac0bdcSGeert Uytterhoeven }
12385eac0bdcSGeert Uytterhoeven EXPORT_SYMBOL(of_io_request_and_map);
1239