xref: /openbmc/linux/drivers/of/address.c (revision 76e2b215)
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>
16e0d07278SJim Quinlan #include <linux/dma-direct.h> /* for bus_dma_region */
176b884a8dSGrant Likely 
18b68ac8dcSRobin Murphy #include "of_private.h"
19b68ac8dcSRobin Murphy 
20dbbdee94SGrant Likely /* Max address size we deal with */
21dbbdee94SGrant Likely #define OF_MAX_ADDR_CELLS	4
225d61b165SStephen Warren #define OF_CHECK_ADDR_COUNT(na)	((na) > 0 && (na) <= OF_MAX_ADDR_CELLS)
235d61b165SStephen Warren #define OF_CHECK_COUNTS(na, ns)	(OF_CHECK_ADDR_COUNT(na) && (ns) > 0)
24dbbdee94SGrant Likely 
25dbbdee94SGrant Likely /* Debug utility */
26dbbdee94SGrant Likely #ifdef DEBUG
of_dump_addr(const char * s,const __be32 * addr,int na)270131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na)
28dbbdee94SGrant Likely {
29606ad42aSRob Herring 	pr_debug("%s", s);
30dbbdee94SGrant Likely 	while (na--)
31606ad42aSRob Herring 		pr_cont(" %08x", be32_to_cpu(*(addr++)));
32606ad42aSRob Herring 	pr_cont("\n");
33dbbdee94SGrant Likely }
34dbbdee94SGrant Likely #else
of_dump_addr(const char * s,const __be32 * addr,int na)350131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na) { }
36dbbdee94SGrant Likely #endif
37dbbdee94SGrant Likely 
38dbbdee94SGrant Likely /* Callbacks for bus specific translators */
39dbbdee94SGrant Likely struct of_bus {
40dbbdee94SGrant Likely 	const char	*name;
41dbbdee94SGrant Likely 	const char	*addresses;
42dbbdee94SGrant Likely 	int		(*match)(struct device_node *parent);
43dbbdee94SGrant Likely 	void		(*count_cells)(struct device_node *child,
44dbbdee94SGrant Likely 				       int *addrc, int *sizec);
4547b1e689SKim Phillips 	u64		(*map)(__be32 *addr, const __be32 *range,
46dbbdee94SGrant Likely 				int na, int ns, int pna);
4747b1e689SKim Phillips 	int		(*translate)(__be32 *addr, u64 offset, int na);
482f96593eSJiaxun Yang 	bool	has_flags;
490131d897SSebastian Andrzej Siewior 	unsigned int	(*get_flags)(const __be32 *addr);
50dbbdee94SGrant Likely };
51dbbdee94SGrant Likely 
52dbbdee94SGrant Likely /*
53dbbdee94SGrant Likely  * Default translator (generic bus)
54dbbdee94SGrant Likely  */
55dbbdee94SGrant Likely 
of_bus_default_count_cells(struct device_node * dev,int * addrc,int * sizec)56dbbdee94SGrant Likely static void of_bus_default_count_cells(struct device_node *dev,
57dbbdee94SGrant Likely 				       int *addrc, int *sizec)
58dbbdee94SGrant Likely {
59dbbdee94SGrant Likely 	if (addrc)
60dbbdee94SGrant Likely 		*addrc = of_n_addr_cells(dev);
61dbbdee94SGrant Likely 	if (sizec)
62dbbdee94SGrant Likely 		*sizec = of_n_size_cells(dev);
63dbbdee94SGrant Likely }
64dbbdee94SGrant Likely 
of_bus_default_map(__be32 * addr,const __be32 * range,int na,int ns,int pna)6547b1e689SKim Phillips static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
66dbbdee94SGrant Likely 		int na, int ns, int pna)
67dbbdee94SGrant Likely {
68dbbdee94SGrant Likely 	u64 cp, s, da;
69dbbdee94SGrant Likely 
70dbbdee94SGrant Likely 	cp = of_read_number(range, na);
71dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
72dbbdee94SGrant Likely 	da = of_read_number(addr, na);
73dbbdee94SGrant Likely 
740e407a9aSGeert Uytterhoeven 	pr_debug("default map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);
75dbbdee94SGrant Likely 
76dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
77dbbdee94SGrant Likely 		return OF_BAD_ADDR;
78dbbdee94SGrant Likely 	return da - cp;
79dbbdee94SGrant Likely }
80dbbdee94SGrant Likely 
of_bus_default_translate(__be32 * addr,u64 offset,int na)8147b1e689SKim Phillips static int of_bus_default_translate(__be32 *addr, u64 offset, int na)
82dbbdee94SGrant Likely {
83dbbdee94SGrant Likely 	u64 a = of_read_number(addr, na);
84dbbdee94SGrant Likely 	memset(addr, 0, na * 4);
85dbbdee94SGrant Likely 	a += offset;
86dbbdee94SGrant Likely 	if (na > 1)
87154063a9SGrant Likely 		addr[na - 2] = cpu_to_be32(a >> 32);
88154063a9SGrant Likely 	addr[na - 1] = cpu_to_be32(a & 0xffffffffu);
89dbbdee94SGrant Likely 
90dbbdee94SGrant Likely 	return 0;
91dbbdee94SGrant Likely }
92dbbdee94SGrant Likely 
of_bus_default_flags_get_flags(const __be32 * addr)933d5089c4SRob Herring static unsigned int of_bus_default_flags_get_flags(const __be32 *addr)
943d5089c4SRob Herring {
953d5089c4SRob Herring 	return of_read_number(addr, 1);
963d5089c4SRob Herring }
973d5089c4SRob Herring 
of_bus_default_get_flags(const __be32 * addr)980131d897SSebastian Andrzej Siewior static unsigned int of_bus_default_get_flags(const __be32 *addr)
99dbbdee94SGrant Likely {
100dbbdee94SGrant Likely 	return IORESOURCE_MEM;
101dbbdee94SGrant Likely }
102dbbdee94SGrant Likely 
of_bus_default_flags_map(__be32 * addr,const __be32 * range,int na,int ns,int pna)103*76e2b215SHerve Codina static u64 of_bus_default_flags_map(__be32 *addr, const __be32 *range, int na,
104*76e2b215SHerve Codina 				    int ns, int pna)
105*76e2b215SHerve Codina {
106*76e2b215SHerve Codina 	u64 cp, s, da;
107*76e2b215SHerve Codina 
108*76e2b215SHerve Codina 	/* Check that flags match */
109*76e2b215SHerve Codina 	if (*addr != *range)
110*76e2b215SHerve Codina 		return OF_BAD_ADDR;
111*76e2b215SHerve Codina 
112*76e2b215SHerve Codina 	/* Read address values, skipping high cell */
113*76e2b215SHerve Codina 	cp = of_read_number(range + 1, na - 1);
114*76e2b215SHerve Codina 	s  = of_read_number(range + na + pna, ns);
115*76e2b215SHerve Codina 	da = of_read_number(addr + 1, na - 1);
116*76e2b215SHerve Codina 
117*76e2b215SHerve Codina 	pr_debug("default flags map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);
118*76e2b215SHerve Codina 
119*76e2b215SHerve Codina 	if (da < cp || da >= (cp + s))
120*76e2b215SHerve Codina 		return OF_BAD_ADDR;
121*76e2b215SHerve Codina 	return da - cp;
122*76e2b215SHerve Codina }
123*76e2b215SHerve Codina 
of_bus_default_flags_translate(__be32 * addr,u64 offset,int na)124*76e2b215SHerve Codina static int of_bus_default_flags_translate(__be32 *addr, u64 offset, int na)
125*76e2b215SHerve Codina {
126*76e2b215SHerve Codina 	/* Keep "flags" part (high cell) in translated address */
127*76e2b215SHerve Codina 	return of_bus_default_translate(addr + 1, offset, na - 1);
128*76e2b215SHerve Codina }
1293d5089c4SRob Herring 
1300fc0ead3SJiaxun Yang #ifdef CONFIG_PCI
of_bus_pci_get_flags(const __be32 * addr)13167ccd2b9SRob Herring static unsigned int of_bus_pci_get_flags(const __be32 *addr)
13267ccd2b9SRob Herring {
13367ccd2b9SRob Herring 	unsigned int flags = 0;
13467ccd2b9SRob Herring 	u32 w = be32_to_cpup(addr);
13567ccd2b9SRob Herring 
13667ccd2b9SRob Herring 	if (!IS_ENABLED(CONFIG_PCI))
13767ccd2b9SRob Herring 		return 0;
13867ccd2b9SRob Herring 
13967ccd2b9SRob Herring 	switch((w >> 24) & 0x03) {
14067ccd2b9SRob Herring 	case 0x01:
14167ccd2b9SRob Herring 		flags |= IORESOURCE_IO;
14267ccd2b9SRob Herring 		break;
14367ccd2b9SRob Herring 	case 0x02: /* 32 bits */
14467ccd2b9SRob Herring 		flags |= IORESOURCE_MEM;
14567ccd2b9SRob Herring 		break;
1469d57e61bSLeonardo Bras 
1479d57e61bSLeonardo Bras 	case 0x03: /* 64 bits */
1489d57e61bSLeonardo Bras 		flags |= IORESOURCE_MEM | IORESOURCE_MEM_64;
1499d57e61bSLeonardo Bras 		break;
15067ccd2b9SRob Herring 	}
15167ccd2b9SRob Herring 	if (w & 0x40000000)
15267ccd2b9SRob Herring 		flags |= IORESOURCE_PREFETCH;
15367ccd2b9SRob Herring 	return flags;
15467ccd2b9SRob Herring }
15567ccd2b9SRob Herring 
156dbbdee94SGrant Likely /*
157dbbdee94SGrant Likely  * PCI bus specific translator
158dbbdee94SGrant Likely  */
159dbbdee94SGrant Likely 
of_node_is_pcie(struct device_node * np)160d1ac0002SMarc Zyngier static bool of_node_is_pcie(struct device_node *np)
161d1ac0002SMarc Zyngier {
162d1ac0002SMarc Zyngier 	bool is_pcie = of_node_name_eq(np, "pcie");
163d1ac0002SMarc Zyngier 
164d1ac0002SMarc Zyngier 	if (is_pcie)
165d1ac0002SMarc Zyngier 		pr_warn_once("%pOF: Missing device_type\n", np);
166d1ac0002SMarc Zyngier 
167d1ac0002SMarc Zyngier 	return is_pcie;
168d1ac0002SMarc Zyngier }
169d1ac0002SMarc Zyngier 
of_bus_pci_match(struct device_node * np)170dbbdee94SGrant Likely static int of_bus_pci_match(struct device_node *np)
171dbbdee94SGrant Likely {
1726dd18e46SBenjamin Herrenschmidt 	/*
17314e2abb7SKleber Sacilotto de Souza  	 * "pciex" is PCI Express
1746dd18e46SBenjamin Herrenschmidt 	 * "vci" is for the /chaos bridge on 1st-gen PCI powermacs
1756dd18e46SBenjamin Herrenschmidt 	 * "ht" is hypertransport
176d1ac0002SMarc Zyngier 	 *
177d1ac0002SMarc Zyngier 	 * If none of the device_type match, and that the node name is
178d1ac0002SMarc Zyngier 	 * "pcie", accept the device as PCI (with a warning).
1796dd18e46SBenjamin Herrenschmidt 	 */
180e8b1dee2SRob Herring 	return of_node_is_type(np, "pci") || of_node_is_type(np, "pciex") ||
181d1ac0002SMarc Zyngier 		of_node_is_type(np, "vci") || of_node_is_type(np, "ht") ||
182d1ac0002SMarc Zyngier 		of_node_is_pcie(np);
183dbbdee94SGrant Likely }
184dbbdee94SGrant Likely 
of_bus_pci_count_cells(struct device_node * np,int * addrc,int * sizec)185dbbdee94SGrant Likely static void of_bus_pci_count_cells(struct device_node *np,
186dbbdee94SGrant Likely 				   int *addrc, int *sizec)
187dbbdee94SGrant Likely {
188dbbdee94SGrant Likely 	if (addrc)
189dbbdee94SGrant Likely 		*addrc = 3;
190dbbdee94SGrant Likely 	if (sizec)
191dbbdee94SGrant Likely 		*sizec = 2;
192dbbdee94SGrant Likely }
193dbbdee94SGrant Likely 
of_bus_pci_map(__be32 * addr,const __be32 * range,int na,int ns,int pna)19447b1e689SKim Phillips static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns,
1950131d897SSebastian Andrzej Siewior 		int pna)
196dbbdee94SGrant Likely {
197dbbdee94SGrant Likely 	u64 cp, s, da;
198dbbdee94SGrant Likely 	unsigned int af, rf;
199dbbdee94SGrant Likely 
200dbbdee94SGrant Likely 	af = of_bus_pci_get_flags(addr);
201dbbdee94SGrant Likely 	rf = of_bus_pci_get_flags(range);
202dbbdee94SGrant Likely 
203dbbdee94SGrant Likely 	/* Check address type match */
204dbbdee94SGrant Likely 	if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO))
205dbbdee94SGrant Likely 		return OF_BAD_ADDR;
206dbbdee94SGrant Likely 
207dbbdee94SGrant Likely 	/* Read address values, skipping high cell */
208dbbdee94SGrant Likely 	cp = of_read_number(range + 1, na - 1);
209dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
210dbbdee94SGrant Likely 	da = of_read_number(addr + 1, na - 1);
211dbbdee94SGrant Likely 
2120e407a9aSGeert Uytterhoeven 	pr_debug("PCI map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);
213dbbdee94SGrant Likely 
214dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
215dbbdee94SGrant Likely 		return OF_BAD_ADDR;
216dbbdee94SGrant Likely 	return da - cp;
217dbbdee94SGrant Likely }
218dbbdee94SGrant Likely 
of_bus_pci_translate(__be32 * addr,u64 offset,int na)21947b1e689SKim Phillips static int of_bus_pci_translate(__be32 *addr, u64 offset, int na)
220dbbdee94SGrant Likely {
221dbbdee94SGrant Likely 	return of_bus_default_translate(addr + 1, offset, na - 1);
222dbbdee94SGrant Likely }
223c3c0dc75SRob Herring #endif /* CONFIG_PCI */
224dbbdee94SGrant Likely 
2250b0b0893SLiviu Dudau /*
2260b0b0893SLiviu Dudau  * of_pci_range_to_resource - Create a resource from an of_pci_range
2270b0b0893SLiviu Dudau  * @range:	the PCI range that describes the resource
2280b0b0893SLiviu Dudau  * @np:		device node where the range belongs to
2290b0b0893SLiviu Dudau  * @res:	pointer to a valid resource that will be updated to
2300b0b0893SLiviu Dudau  *              reflect the values contained in the range.
2310b0b0893SLiviu Dudau  *
23265b6b046SGeert Uytterhoeven  * Returns -EINVAL if the range cannot be converted to resource.
2330b0b0893SLiviu Dudau  *
2340b0b0893SLiviu Dudau  * Note that if the range is an IO range, the resource will be converted
2350b0b0893SLiviu Dudau  * using pci_address_to_pio() which can fail if it is called too early or
2360b0b0893SLiviu Dudau  * if the range cannot be matched to any host bridge IO space (our case here).
2370b0b0893SLiviu Dudau  * To guard against that we try to register the IO range first.
2380b0b0893SLiviu Dudau  * If that fails we know that pci_address_to_pio() will do too.
2390b0b0893SLiviu Dudau  */
of_pci_range_to_resource(struct of_pci_range * range,struct device_node * np,struct resource * res)2400b0b0893SLiviu Dudau int of_pci_range_to_resource(struct of_pci_range *range,
24183bbde1cSLiviu Dudau 			     struct device_node *np, struct resource *res)
24283bbde1cSLiviu Dudau {
2430b0b0893SLiviu Dudau 	int err;
24483bbde1cSLiviu Dudau 	res->flags = range->flags;
24583bbde1cSLiviu Dudau 	res->parent = res->child = res->sibling = NULL;
24683bbde1cSLiviu Dudau 	res->name = np->full_name;
2470b0b0893SLiviu Dudau 
2480b0b0893SLiviu Dudau 	if (res->flags & IORESOURCE_IO) {
2490b0b0893SLiviu Dudau 		unsigned long port;
250fcfaab30SGabriele Paoloni 		err = pci_register_io_range(&np->fwnode, range->cpu_addr,
251fcfaab30SGabriele Paoloni 				range->size);
2520b0b0893SLiviu Dudau 		if (err)
2530b0b0893SLiviu Dudau 			goto invalid_range;
2540b0b0893SLiviu Dudau 		port = pci_address_to_pio(range->cpu_addr);
2550b0b0893SLiviu Dudau 		if (port == (unsigned long)-1) {
2560b0b0893SLiviu Dudau 			err = -EINVAL;
2570b0b0893SLiviu Dudau 			goto invalid_range;
2580b0b0893SLiviu Dudau 		}
2590b0b0893SLiviu Dudau 		res->start = port;
2600b0b0893SLiviu Dudau 	} else {
2614af97106SPavel Fedin 		if ((sizeof(resource_size_t) < 8) &&
2624af97106SPavel Fedin 		    upper_32_bits(range->cpu_addr)) {
2634af97106SPavel Fedin 			err = -EINVAL;
2644af97106SPavel Fedin 			goto invalid_range;
2654af97106SPavel Fedin 		}
2664af97106SPavel Fedin 
2670b0b0893SLiviu Dudau 		res->start = range->cpu_addr;
2680b0b0893SLiviu Dudau 	}
2690b0b0893SLiviu Dudau 	res->end = res->start + range->size - 1;
2700b0b0893SLiviu Dudau 	return 0;
2710b0b0893SLiviu Dudau 
2720b0b0893SLiviu Dudau invalid_range:
2730b0b0893SLiviu Dudau 	res->start = (resource_size_t)OF_BAD_ADDR;
2740b0b0893SLiviu Dudau 	res->end = (resource_size_t)OF_BAD_ADDR;
2750b0b0893SLiviu Dudau 	return err;
27683bbde1cSLiviu Dudau }
277bf6681eaSManikanta Maddireddy EXPORT_SYMBOL(of_pci_range_to_resource);
278dbbdee94SGrant Likely 
279dbbdee94SGrant Likely /*
280c75a7949SRob Herring  * of_range_to_resource - Create a resource from a ranges entry
281c75a7949SRob Herring  * @np:		device node where the range belongs to
282c75a7949SRob Herring  * @index:	the 'ranges' index to convert to a resource
283c75a7949SRob Herring  * @res:	pointer to a valid resource that will be updated to
284c75a7949SRob Herring  *              reflect the values contained in the range.
285c75a7949SRob Herring  *
286c75a7949SRob Herring  * Returns ENOENT if the entry is not found or EINVAL if the range cannot be
287c75a7949SRob Herring  * converted to resource.
288c75a7949SRob Herring  */
of_range_to_resource(struct device_node * np,int index,struct resource * res)289c75a7949SRob Herring int of_range_to_resource(struct device_node *np, int index, struct resource *res)
290c75a7949SRob Herring {
291c75a7949SRob Herring 	int ret, i = 0;
292c75a7949SRob Herring 	struct of_range_parser parser;
293c75a7949SRob Herring 	struct of_range range;
294c75a7949SRob Herring 
295c75a7949SRob Herring 	ret = of_range_parser_init(&parser, np);
296c75a7949SRob Herring 	if (ret)
297c75a7949SRob Herring 		return ret;
298c75a7949SRob Herring 
299c75a7949SRob Herring 	for_each_of_range(&parser, &range)
300c75a7949SRob Herring 		if (i++ == index)
301c75a7949SRob Herring 			return of_pci_range_to_resource(&range, np, res);
302c75a7949SRob Herring 
303c75a7949SRob Herring 	return -ENOENT;
304c75a7949SRob Herring }
305c75a7949SRob Herring EXPORT_SYMBOL(of_range_to_resource);
306c75a7949SRob Herring 
307c75a7949SRob Herring /*
308dbbdee94SGrant Likely  * ISA bus specific translator
309dbbdee94SGrant Likely  */
310dbbdee94SGrant Likely 
of_bus_isa_match(struct device_node * np)311dbbdee94SGrant Likely static int of_bus_isa_match(struct device_node *np)
312dbbdee94SGrant Likely {
313b3e46d1aSRob Herring 	return of_node_name_eq(np, "isa");
314dbbdee94SGrant Likely }
315dbbdee94SGrant Likely 
of_bus_isa_count_cells(struct device_node * child,int * addrc,int * sizec)316dbbdee94SGrant Likely static void of_bus_isa_count_cells(struct device_node *child,
317dbbdee94SGrant Likely 				   int *addrc, int *sizec)
318dbbdee94SGrant Likely {
319dbbdee94SGrant Likely 	if (addrc)
320dbbdee94SGrant Likely 		*addrc = 2;
321dbbdee94SGrant Likely 	if (sizec)
322dbbdee94SGrant Likely 		*sizec = 1;
323dbbdee94SGrant Likely }
324dbbdee94SGrant Likely 
of_bus_isa_map(__be32 * addr,const __be32 * range,int na,int ns,int pna)32547b1e689SKim Phillips static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns,
3260131d897SSebastian Andrzej Siewior 		int pna)
327dbbdee94SGrant Likely {
328dbbdee94SGrant Likely 	u64 cp, s, da;
329dbbdee94SGrant Likely 
330dbbdee94SGrant Likely 	/* Check address type match */
3310131d897SSebastian Andrzej Siewior 	if ((addr[0] ^ range[0]) & cpu_to_be32(1))
332dbbdee94SGrant Likely 		return OF_BAD_ADDR;
333dbbdee94SGrant Likely 
334dbbdee94SGrant Likely 	/* Read address values, skipping high cell */
335dbbdee94SGrant Likely 	cp = of_read_number(range + 1, na - 1);
336dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
337dbbdee94SGrant Likely 	da = of_read_number(addr + 1, na - 1);
338dbbdee94SGrant Likely 
3390e407a9aSGeert Uytterhoeven 	pr_debug("ISA map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);
340dbbdee94SGrant Likely 
341dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
342dbbdee94SGrant Likely 		return OF_BAD_ADDR;
343dbbdee94SGrant Likely 	return da - cp;
344dbbdee94SGrant Likely }
345dbbdee94SGrant Likely 
of_bus_isa_translate(__be32 * addr,u64 offset,int na)34647b1e689SKim Phillips static int of_bus_isa_translate(__be32 *addr, u64 offset, int na)
347dbbdee94SGrant Likely {
348dbbdee94SGrant Likely 	return of_bus_default_translate(addr + 1, offset, na - 1);
349dbbdee94SGrant Likely }
350dbbdee94SGrant Likely 
of_bus_isa_get_flags(const __be32 * addr)3510131d897SSebastian Andrzej Siewior static unsigned int of_bus_isa_get_flags(const __be32 *addr)
352dbbdee94SGrant Likely {
353dbbdee94SGrant Likely 	unsigned int flags = 0;
3540131d897SSebastian Andrzej Siewior 	u32 w = be32_to_cpup(addr);
355dbbdee94SGrant Likely 
356dbbdee94SGrant Likely 	if (w & 1)
357dbbdee94SGrant Likely 		flags |= IORESOURCE_IO;
358dbbdee94SGrant Likely 	else
359dbbdee94SGrant Likely 		flags |= IORESOURCE_MEM;
360dbbdee94SGrant Likely 	return flags;
361dbbdee94SGrant Likely }
362dbbdee94SGrant Likely 
of_bus_default_flags_match(struct device_node * np)3633d5089c4SRob Herring static int of_bus_default_flags_match(struct device_node *np)
3643d5089c4SRob Herring {
3653d5089c4SRob Herring 	return of_bus_n_addr_cells(np) == 3;
3663d5089c4SRob Herring }
3673d5089c4SRob Herring 
368dbbdee94SGrant Likely /*
369dbbdee94SGrant Likely  * Array of bus specific translators
370dbbdee94SGrant Likely  */
371dbbdee94SGrant Likely 
372dbbdee94SGrant Likely static struct of_bus of_busses[] = {
3734670d610SRob Herring #ifdef CONFIG_PCI
374dbbdee94SGrant Likely 	/* PCI */
375dbbdee94SGrant Likely 	{
376dbbdee94SGrant Likely 		.name = "pci",
377dbbdee94SGrant Likely 		.addresses = "assigned-addresses",
378dbbdee94SGrant Likely 		.match = of_bus_pci_match,
379dbbdee94SGrant Likely 		.count_cells = of_bus_pci_count_cells,
380dbbdee94SGrant Likely 		.map = of_bus_pci_map,
381dbbdee94SGrant Likely 		.translate = of_bus_pci_translate,
3822f96593eSJiaxun Yang 		.has_flags = true,
383dbbdee94SGrant Likely 		.get_flags = of_bus_pci_get_flags,
384dbbdee94SGrant Likely 	},
3854670d610SRob Herring #endif /* CONFIG_PCI */
386dbbdee94SGrant Likely 	/* ISA */
387dbbdee94SGrant Likely 	{
388dbbdee94SGrant Likely 		.name = "isa",
389dbbdee94SGrant Likely 		.addresses = "reg",
390dbbdee94SGrant Likely 		.match = of_bus_isa_match,
391dbbdee94SGrant Likely 		.count_cells = of_bus_isa_count_cells,
392dbbdee94SGrant Likely 		.map = of_bus_isa_map,
393dbbdee94SGrant Likely 		.translate = of_bus_isa_translate,
3942f96593eSJiaxun Yang 		.has_flags = true,
395dbbdee94SGrant Likely 		.get_flags = of_bus_isa_get_flags,
396dbbdee94SGrant Likely 	},
3973d5089c4SRob Herring 	/* Default with flags cell */
3983d5089c4SRob Herring 	{
3993d5089c4SRob Herring 		.name = "default-flags",
4003d5089c4SRob Herring 		.addresses = "reg",
4013d5089c4SRob Herring 		.match = of_bus_default_flags_match,
4023d5089c4SRob Herring 		.count_cells = of_bus_default_count_cells,
403*76e2b215SHerve Codina 		.map = of_bus_default_flags_map,
404*76e2b215SHerve Codina 		.translate = of_bus_default_flags_translate,
4053d5089c4SRob Herring 		.has_flags = true,
4063d5089c4SRob Herring 		.get_flags = of_bus_default_flags_get_flags,
4073d5089c4SRob Herring 	},
408dbbdee94SGrant Likely 	/* Default */
409dbbdee94SGrant Likely 	{
410dbbdee94SGrant Likely 		.name = "default",
411dbbdee94SGrant Likely 		.addresses = "reg",
412dbbdee94SGrant Likely 		.match = NULL,
413dbbdee94SGrant Likely 		.count_cells = of_bus_default_count_cells,
414dbbdee94SGrant Likely 		.map = of_bus_default_map,
415dbbdee94SGrant Likely 		.translate = of_bus_default_translate,
416dbbdee94SGrant Likely 		.get_flags = of_bus_default_get_flags,
417dbbdee94SGrant Likely 	},
418dbbdee94SGrant Likely };
419dbbdee94SGrant Likely 
of_match_bus(struct device_node * np)420dbbdee94SGrant Likely static struct of_bus *of_match_bus(struct device_node *np)
421dbbdee94SGrant Likely {
422dbbdee94SGrant Likely 	int i;
423dbbdee94SGrant Likely 
424dbbdee94SGrant Likely 	for (i = 0; i < ARRAY_SIZE(of_busses); i++)
425dbbdee94SGrant Likely 		if (!of_busses[i].match || of_busses[i].match(np))
426dbbdee94SGrant Likely 			return &of_busses[i];
427dbbdee94SGrant Likely 	BUG();
428dbbdee94SGrant Likely 	return NULL;
429dbbdee94SGrant Likely }
430dbbdee94SGrant Likely 
of_empty_ranges_quirk(struct device_node * np)43141d94893SBenjamin Herrenschmidt static int of_empty_ranges_quirk(struct device_node *np)
432746c9e9fSBenjamin Herrenschmidt {
433746c9e9fSBenjamin Herrenschmidt 	if (IS_ENABLED(CONFIG_PPC)) {
43441d94893SBenjamin Herrenschmidt 		/* To save cycles, we cache the result for global "Mac" setting */
435746c9e9fSBenjamin Herrenschmidt 		static int quirk_state = -1;
436746c9e9fSBenjamin Herrenschmidt 
43741d94893SBenjamin Herrenschmidt 		/* PA-SEMI sdc DT bug */
43841d94893SBenjamin Herrenschmidt 		if (of_device_is_compatible(np, "1682m-sdc"))
43941d94893SBenjamin Herrenschmidt 			return true;
44041d94893SBenjamin Herrenschmidt 
44141d94893SBenjamin Herrenschmidt 		/* Make quirk cached */
442746c9e9fSBenjamin Herrenschmidt 		if (quirk_state < 0)
443746c9e9fSBenjamin Herrenschmidt 			quirk_state =
444746c9e9fSBenjamin Herrenschmidt 				of_machine_is_compatible("Power Macintosh") ||
445746c9e9fSBenjamin Herrenschmidt 				of_machine_is_compatible("MacRISC");
446746c9e9fSBenjamin Herrenschmidt 		return quirk_state;
447746c9e9fSBenjamin Herrenschmidt 	}
448746c9e9fSBenjamin Herrenschmidt 	return false;
449746c9e9fSBenjamin Herrenschmidt }
450746c9e9fSBenjamin 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)451dbbdee94SGrant Likely static int of_translate_one(struct device_node *parent, struct of_bus *bus,
45247b1e689SKim Phillips 			    struct of_bus *pbus, __be32 *addr,
453dbbdee94SGrant Likely 			    int na, int ns, int pna, const char *rprop)
454dbbdee94SGrant Likely {
4550131d897SSebastian Andrzej Siewior 	const __be32 *ranges;
456dbbdee94SGrant Likely 	unsigned int rlen;
457dbbdee94SGrant Likely 	int rone;
458dbbdee94SGrant Likely 	u64 offset = OF_BAD_ADDR;
459dbbdee94SGrant Likely 
460ba85edbeSMasahiro Yamada 	/*
461ba85edbeSMasahiro Yamada 	 * Normally, an absence of a "ranges" property means we are
462dbbdee94SGrant Likely 	 * crossing a non-translatable boundary, and thus the addresses
463ba85edbeSMasahiro Yamada 	 * below the current cannot be converted to CPU physical ones.
464dbbdee94SGrant Likely 	 * Unfortunately, while this is very clear in the spec, it's not
465dbbdee94SGrant Likely 	 * what Apple understood, and they do have things like /uni-n or
466dbbdee94SGrant Likely 	 * /ht nodes with no "ranges" property and a lot of perfectly
467dbbdee94SGrant Likely 	 * useable mapped devices below them. Thus we treat the absence of
468dbbdee94SGrant Likely 	 * "ranges" as equivalent to an empty "ranges" property which means
469dbbdee94SGrant Likely 	 * a 1:1 translation at that level. It's up to the caller not to try
470dbbdee94SGrant Likely 	 * to translate addresses that aren't supposed to be translated in
471dbbdee94SGrant Likely 	 * the first place. --BenH.
4723930f294SGrant Likely 	 *
4733930f294SGrant Likely 	 * As far as we know, this damage only exists on Apple machines, so
4743930f294SGrant Likely 	 * This code is only enabled on powerpc. --gcl
47581db12eeSRob Herring 	 *
47681db12eeSRob Herring 	 * This quirk also applies for 'dma-ranges' which frequently exist in
47781db12eeSRob Herring 	 * child nodes without 'dma-ranges' in the parent nodes. --RobH
478dbbdee94SGrant Likely 	 */
479dbbdee94SGrant Likely 	ranges = of_get_property(parent, rprop, &rlen);
48081db12eeSRob Herring 	if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
48181db12eeSRob Herring 	    strcmp(rprop, "dma-ranges")) {
482606ad42aSRob Herring 		pr_debug("no ranges; cannot translate\n");
4833930f294SGrant Likely 		return 1;
4843930f294SGrant Likely 	}
485dbbdee94SGrant Likely 	if (ranges == NULL || rlen == 0) {
486dbbdee94SGrant Likely 		offset = of_read_number(addr, na);
487dbbdee94SGrant Likely 		memset(addr, 0, pna * 4);
488606ad42aSRob Herring 		pr_debug("empty ranges; 1:1 translation\n");
489dbbdee94SGrant Likely 		goto finish;
490dbbdee94SGrant Likely 	}
491dbbdee94SGrant Likely 
492606ad42aSRob Herring 	pr_debug("walking ranges...\n");
493dbbdee94SGrant Likely 
494dbbdee94SGrant Likely 	/* Now walk through the ranges */
495dbbdee94SGrant Likely 	rlen /= 4;
496dbbdee94SGrant Likely 	rone = na + pna + ns;
497dbbdee94SGrant Likely 	for (; rlen >= rone; rlen -= rone, ranges += rone) {
498dbbdee94SGrant Likely 		offset = bus->map(addr, ranges, na, ns, pna);
499dbbdee94SGrant Likely 		if (offset != OF_BAD_ADDR)
500dbbdee94SGrant Likely 			break;
501dbbdee94SGrant Likely 	}
502dbbdee94SGrant Likely 	if (offset == OF_BAD_ADDR) {
503606ad42aSRob Herring 		pr_debug("not found !\n");
504dbbdee94SGrant Likely 		return 1;
505dbbdee94SGrant Likely 	}
506dbbdee94SGrant Likely 	memcpy(addr, ranges + na, 4 * pna);
507dbbdee94SGrant Likely 
508dbbdee94SGrant Likely  finish:
509606ad42aSRob Herring 	of_dump_addr("parent translation for:", addr, pna);
5100e407a9aSGeert Uytterhoeven 	pr_debug("with offset: %llx\n", offset);
511dbbdee94SGrant Likely 
512dbbdee94SGrant Likely 	/* Translate it into parent bus space */
513dbbdee94SGrant Likely 	return pbus->translate(addr, offset, pna);
514dbbdee94SGrant Likely }
515dbbdee94SGrant Likely 
516dbbdee94SGrant Likely /*
517dbbdee94SGrant Likely  * Translate an address from the device-tree into a CPU physical address,
518dbbdee94SGrant Likely  * this walks up the tree and applies the various bus mappings on the
519dbbdee94SGrant Likely  * way.
520dbbdee94SGrant Likely  *
521dbbdee94SGrant Likely  * Note: We consider that crossing any level with #size-cells == 0 to mean
522dbbdee94SGrant Likely  * that translation is impossible (that is we are not dealing with a value
523dbbdee94SGrant Likely  * that can be mapped to a cpu physical address). This is not really specified
524dbbdee94SGrant Likely  * that way, but this is traditionally the way IBM at least do things
52565af618dSZhichang Yuan  *
52665af618dSZhichang Yuan  * Whenever the translation fails, the *host pointer will be set to the
52765af618dSZhichang Yuan  * device that had registered logical PIO mapping, and the return code is
52865af618dSZhichang Yuan  * relative to that node.
529dbbdee94SGrant 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)53047b1e689SKim Phillips static u64 __of_translate_address(struct device_node *dev,
53195835a8dSMaxime Ripard 				  struct device_node *(*get_parent)(const struct device_node *),
53265af618dSZhichang Yuan 				  const __be32 *in_addr, const char *rprop,
53365af618dSZhichang Yuan 				  struct device_node **host)
534dbbdee94SGrant Likely {
535dbbdee94SGrant Likely 	struct device_node *parent = NULL;
536dbbdee94SGrant Likely 	struct of_bus *bus, *pbus;
53747b1e689SKim Phillips 	__be32 addr[OF_MAX_ADDR_CELLS];
538dbbdee94SGrant Likely 	int na, ns, pna, pns;
539dbbdee94SGrant Likely 	u64 result = OF_BAD_ADDR;
540dbbdee94SGrant Likely 
5410d638a07SRob Herring 	pr_debug("** translation for device %pOF **\n", dev);
542dbbdee94SGrant Likely 
543dbbdee94SGrant Likely 	/* Increase refcount at current level */
544dbbdee94SGrant Likely 	of_node_get(dev);
545dbbdee94SGrant Likely 
54665af618dSZhichang Yuan 	*host = NULL;
547dbbdee94SGrant Likely 	/* Get parent & match bus type */
54895835a8dSMaxime Ripard 	parent = get_parent(dev);
549dbbdee94SGrant Likely 	if (parent == NULL)
550dbbdee94SGrant Likely 		goto bail;
551dbbdee94SGrant Likely 	bus = of_match_bus(parent);
552dbbdee94SGrant Likely 
55359f5ca48SAndrew Murray 	/* Count address cells & copy address locally */
554dbbdee94SGrant Likely 	bus->count_cells(dev, &na, &ns);
555dbbdee94SGrant Likely 	if (!OF_CHECK_COUNTS(na, ns)) {
5560d638a07SRob Herring 		pr_debug("Bad cell count for %pOF\n", dev);
557dbbdee94SGrant Likely 		goto bail;
558dbbdee94SGrant Likely 	}
559dbbdee94SGrant Likely 	memcpy(addr, in_addr, na * 4);
560dbbdee94SGrant Likely 
5610d638a07SRob Herring 	pr_debug("bus is %s (na=%d, ns=%d) on %pOF\n",
5620d638a07SRob Herring 	    bus->name, na, ns, parent);
563606ad42aSRob Herring 	of_dump_addr("translating address:", addr, na);
564dbbdee94SGrant Likely 
565dbbdee94SGrant Likely 	/* Translate */
566dbbdee94SGrant Likely 	for (;;) {
56765af618dSZhichang Yuan 		struct logic_pio_hwaddr *iorange;
56865af618dSZhichang Yuan 
569dbbdee94SGrant Likely 		/* Switch to parent bus */
570dbbdee94SGrant Likely 		of_node_put(dev);
571dbbdee94SGrant Likely 		dev = parent;
57295835a8dSMaxime Ripard 		parent = get_parent(dev);
573dbbdee94SGrant Likely 
574dbbdee94SGrant Likely 		/* If root, we have finished */
575dbbdee94SGrant Likely 		if (parent == NULL) {
576606ad42aSRob Herring 			pr_debug("reached root node\n");
577dbbdee94SGrant Likely 			result = of_read_number(addr, na);
578dbbdee94SGrant Likely 			break;
579dbbdee94SGrant Likely 		}
580dbbdee94SGrant Likely 
58165af618dSZhichang Yuan 		/*
58265af618dSZhichang Yuan 		 * For indirectIO device which has no ranges property, get
58365af618dSZhichang Yuan 		 * the address from reg directly.
58465af618dSZhichang Yuan 		 */
58565af618dSZhichang Yuan 		iorange = find_io_range_by_fwnode(&dev->fwnode);
58665af618dSZhichang Yuan 		if (iorange && (iorange->flags != LOGIC_PIO_CPU_MMIO)) {
58765af618dSZhichang Yuan 			result = of_read_number(addr + 1, na - 1);
58865af618dSZhichang Yuan 			pr_debug("indirectIO matched(%pOF) 0x%llx\n",
58965af618dSZhichang Yuan 				 dev, result);
59065af618dSZhichang Yuan 			*host = of_node_get(dev);
59165af618dSZhichang Yuan 			break;
59265af618dSZhichang Yuan 		}
59365af618dSZhichang Yuan 
594dbbdee94SGrant Likely 		/* Get new parent bus and counts */
595dbbdee94SGrant Likely 		pbus = of_match_bus(parent);
596dbbdee94SGrant Likely 		pbus->count_cells(dev, &pna, &pns);
597dbbdee94SGrant Likely 		if (!OF_CHECK_COUNTS(pna, pns)) {
5980d638a07SRob Herring 			pr_err("Bad cell count for %pOF\n", dev);
599dbbdee94SGrant Likely 			break;
600dbbdee94SGrant Likely 		}
601dbbdee94SGrant Likely 
6020d638a07SRob Herring 		pr_debug("parent bus is %s (na=%d, ns=%d) on %pOF\n",
6030d638a07SRob Herring 		    pbus->name, pna, pns, parent);
604dbbdee94SGrant Likely 
605dbbdee94SGrant Likely 		/* Apply bus translation */
606dbbdee94SGrant Likely 		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
607dbbdee94SGrant Likely 			break;
608dbbdee94SGrant Likely 
609dbbdee94SGrant Likely 		/* Complete the move up one level */
610dbbdee94SGrant Likely 		na = pna;
611dbbdee94SGrant Likely 		ns = pns;
612dbbdee94SGrant Likely 		bus = pbus;
613dbbdee94SGrant Likely 
614606ad42aSRob Herring 		of_dump_addr("one level translation:", addr, na);
615dbbdee94SGrant Likely 	}
616dbbdee94SGrant Likely  bail:
617dbbdee94SGrant Likely 	of_node_put(parent);
618dbbdee94SGrant Likely 	of_node_put(dev);
619dbbdee94SGrant Likely 
620dbbdee94SGrant Likely 	return result;
621dbbdee94SGrant Likely }
622dbbdee94SGrant Likely 
of_translate_address(struct device_node * dev,const __be32 * in_addr)6230131d897SSebastian Andrzej Siewior u64 of_translate_address(struct device_node *dev, const __be32 *in_addr)
624dbbdee94SGrant Likely {
62565af618dSZhichang Yuan 	struct device_node *host;
62665af618dSZhichang Yuan 	u64 ret;
62765af618dSZhichang Yuan 
62895835a8dSMaxime Ripard 	ret = __of_translate_address(dev, of_get_parent,
62995835a8dSMaxime Ripard 				     in_addr, "ranges", &host);
63065af618dSZhichang Yuan 	if (host) {
63165af618dSZhichang Yuan 		of_node_put(host);
63265af618dSZhichang Yuan 		return OF_BAD_ADDR;
63365af618dSZhichang Yuan 	}
63465af618dSZhichang Yuan 
63565af618dSZhichang Yuan 	return ret;
636dbbdee94SGrant Likely }
637dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_address);
638dbbdee94SGrant Likely 
639f1ad5338SRobin Murphy #ifdef CONFIG_HAS_DMA
__of_get_dma_parent(const struct device_node * np)640f1ad5338SRobin Murphy struct device_node *__of_get_dma_parent(const struct device_node *np)
641f83a6e5dSMaxime Ripard {
642f83a6e5dSMaxime Ripard 	struct of_phandle_args args;
643f83a6e5dSMaxime Ripard 	int ret, index;
644f83a6e5dSMaxime Ripard 
645f83a6e5dSMaxime Ripard 	index = of_property_match_string(np, "interconnect-names", "dma-mem");
646f83a6e5dSMaxime Ripard 	if (index < 0)
647f83a6e5dSMaxime Ripard 		return of_get_parent(np);
648f83a6e5dSMaxime Ripard 
649f83a6e5dSMaxime Ripard 	ret = of_parse_phandle_with_args(np, "interconnects",
650f83a6e5dSMaxime Ripard 					 "#interconnect-cells",
651f83a6e5dSMaxime Ripard 					 index, &args);
652f83a6e5dSMaxime Ripard 	if (ret < 0)
653f83a6e5dSMaxime Ripard 		return of_get_parent(np);
654f83a6e5dSMaxime Ripard 
655f83a6e5dSMaxime Ripard 	return of_node_get(args.np);
656f83a6e5dSMaxime Ripard }
657f1ad5338SRobin Murphy #endif
658f83a6e5dSMaxime Ripard 
of_get_next_dma_parent(struct device_node * np)659862ab557SRobin Murphy static struct device_node *of_get_next_dma_parent(struct device_node *np)
660862ab557SRobin Murphy {
661862ab557SRobin Murphy 	struct device_node *parent;
662862ab557SRobin Murphy 
663862ab557SRobin Murphy 	parent = __of_get_dma_parent(np);
664862ab557SRobin Murphy 	of_node_put(np);
665862ab557SRobin Murphy 
666862ab557SRobin Murphy 	return parent;
667862ab557SRobin Murphy }
668862ab557SRobin Murphy 
of_translate_dma_address(struct device_node * dev,const __be32 * in_addr)6690131d897SSebastian Andrzej Siewior u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
670dbbdee94SGrant Likely {
67165af618dSZhichang Yuan 	struct device_node *host;
67265af618dSZhichang Yuan 	u64 ret;
67365af618dSZhichang Yuan 
674f83a6e5dSMaxime Ripard 	ret = __of_translate_address(dev, __of_get_dma_parent,
67595835a8dSMaxime Ripard 				     in_addr, "dma-ranges", &host);
67665af618dSZhichang Yuan 
67765af618dSZhichang Yuan 	if (host) {
67865af618dSZhichang Yuan 		of_node_put(host);
67965af618dSZhichang Yuan 		return OF_BAD_ADDR;
68065af618dSZhichang Yuan 	}
68165af618dSZhichang Yuan 
68265af618dSZhichang Yuan 	return ret;
683dbbdee94SGrant Likely }
684dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_dma_address);
685dbbdee94SGrant Likely 
686e251c213SThierry Reding /**
687e251c213SThierry Reding  * of_translate_dma_region - Translate device tree address and size tuple
688e251c213SThierry Reding  * @dev: device tree node for which to translate
689e251c213SThierry Reding  * @prop: pointer into array of cells
690e251c213SThierry Reding  * @start: return value for the start of the DMA range
691e251c213SThierry Reding  * @length: return value for the length of the DMA range
692e251c213SThierry Reding  *
693e251c213SThierry Reding  * Returns a pointer to the cell immediately following the translated DMA region.
694e251c213SThierry Reding  */
of_translate_dma_region(struct device_node * dev,const __be32 * prop,phys_addr_t * start,size_t * length)695e251c213SThierry Reding const __be32 *of_translate_dma_region(struct device_node *dev, const __be32 *prop,
696e251c213SThierry Reding 				      phys_addr_t *start, size_t *length)
697e251c213SThierry Reding {
698e251c213SThierry Reding 	struct device_node *parent;
699e251c213SThierry Reding 	u64 address, size;
700e251c213SThierry Reding 	int na, ns;
701e251c213SThierry Reding 
702e251c213SThierry Reding 	parent = __of_get_dma_parent(dev);
703e251c213SThierry Reding 	if (!parent)
704e251c213SThierry Reding 		return NULL;
705e251c213SThierry Reding 
706e251c213SThierry Reding 	na = of_bus_n_addr_cells(parent);
707e251c213SThierry Reding 	ns = of_bus_n_size_cells(parent);
708e251c213SThierry Reding 
709e251c213SThierry Reding 	of_node_put(parent);
710e251c213SThierry Reding 
711e251c213SThierry Reding 	address = of_translate_dma_address(dev, prop);
712e251c213SThierry Reding 	if (address == OF_BAD_ADDR)
713e251c213SThierry Reding 		return NULL;
714e251c213SThierry Reding 
715e251c213SThierry Reding 	size = of_read_number(prop + na, ns);
716e251c213SThierry Reding 
717e251c213SThierry Reding 	if (start)
718e251c213SThierry Reding 		*start = address;
719e251c213SThierry Reding 
720e251c213SThierry Reding 	if (length)
721e251c213SThierry Reding 		*length = size;
722e251c213SThierry Reding 
723e251c213SThierry Reding 	return prop + na + ns;
724e251c213SThierry Reding }
725e251c213SThierry Reding EXPORT_SYMBOL(of_translate_dma_region);
726e251c213SThierry Reding 
__of_get_address(struct device_node * dev,int index,int bar_no,u64 * size,unsigned int * flags)727050a2c62SRob Herring const __be32 *__of_get_address(struct device_node *dev, int index, int bar_no,
728050a2c62SRob Herring 			       u64 *size, unsigned int *flags)
729dbbdee94SGrant Likely {
7300131d897SSebastian Andrzej Siewior 	const __be32 *prop;
731dbbdee94SGrant Likely 	unsigned int psize;
732dbbdee94SGrant Likely 	struct device_node *parent;
733dbbdee94SGrant Likely 	struct of_bus *bus;
734dbbdee94SGrant Likely 	int onesize, i, na, ns;
735dbbdee94SGrant Likely 
736dbbdee94SGrant Likely 	/* Get parent & match bus type */
737dbbdee94SGrant Likely 	parent = of_get_parent(dev);
738dbbdee94SGrant Likely 	if (parent == NULL)
739dbbdee94SGrant Likely 		return NULL;
740dbbdee94SGrant Likely 	bus = of_match_bus(parent);
741050a2c62SRob Herring 	if (strcmp(bus->name, "pci") && (bar_no >= 0)) {
742050a2c62SRob Herring 		of_node_put(parent);
743050a2c62SRob Herring 		return NULL;
744050a2c62SRob Herring 	}
745dbbdee94SGrant Likely 	bus->count_cells(dev, &na, &ns);
746dbbdee94SGrant Likely 	of_node_put(parent);
7475d61b165SStephen Warren 	if (!OF_CHECK_ADDR_COUNT(na))
748dbbdee94SGrant Likely 		return NULL;
749dbbdee94SGrant Likely 
750dbbdee94SGrant Likely 	/* Get "reg" or "assigned-addresses" property */
751dbbdee94SGrant Likely 	prop = of_get_property(dev, bus->addresses, &psize);
752dbbdee94SGrant Likely 	if (prop == NULL)
753dbbdee94SGrant Likely 		return NULL;
754dbbdee94SGrant Likely 	psize /= 4;
755dbbdee94SGrant Likely 
756dbbdee94SGrant Likely 	onesize = na + ns;
757050a2c62SRob Herring 	for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) {
758050a2c62SRob Herring 		u32 val = be32_to_cpu(prop[0]);
759050a2c62SRob Herring 		/* PCI bus matches on BAR number instead of index */
760050a2c62SRob Herring 		if (((bar_no >= 0) && ((val & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0))) ||
761050a2c62SRob Herring 		    ((index >= 0) && (i == index))) {
762dbbdee94SGrant Likely 			if (size)
763dbbdee94SGrant Likely 				*size = of_read_number(prop + na, ns);
764dbbdee94SGrant Likely 			if (flags)
765dbbdee94SGrant Likely 				*flags = bus->get_flags(prop);
766dbbdee94SGrant Likely 			return prop;
767dbbdee94SGrant Likely 		}
768050a2c62SRob Herring 	}
769dbbdee94SGrant Likely 	return NULL;
770dbbdee94SGrant Likely }
771050a2c62SRob Herring EXPORT_SYMBOL(__of_get_address);
772dbbdee94SGrant Likely 
773ff61bacdSRob Herring /**
774ff61bacdSRob Herring  * of_property_read_reg - Retrieve the specified "reg" entry index without translating
775ff61bacdSRob Herring  * @np: device tree node for which to retrieve "reg" from
776ff61bacdSRob Herring  * @idx: "reg" entry index to read
777ff61bacdSRob Herring  * @addr: return value for the untranslated address
778ff61bacdSRob Herring  * @size: return value for the entry size
779ff61bacdSRob Herring  *
780ff61bacdSRob Herring  * Returns -EINVAL if "reg" is not found. Returns 0 on success with addr and
781ff61bacdSRob Herring  * size values filled in.
782ff61bacdSRob Herring  */
of_property_read_reg(struct device_node * np,int idx,u64 * addr,u64 * size)783ff61bacdSRob Herring int of_property_read_reg(struct device_node *np, int idx, u64 *addr, u64 *size)
784ff61bacdSRob Herring {
785ff61bacdSRob Herring 	const __be32 *prop = of_get_address(np, idx, size, NULL);
786ff61bacdSRob Herring 
787ff61bacdSRob Herring 	if (!prop)
788ff61bacdSRob Herring 		return -EINVAL;
789ff61bacdSRob Herring 
790ff61bacdSRob Herring 	*addr = of_read_number(prop, of_n_addr_cells(np));
791ff61bacdSRob Herring 
792ff61bacdSRob Herring 	return 0;
793ff61bacdSRob Herring }
794ff61bacdSRob Herring EXPORT_SYMBOL(of_property_read_reg);
795ff61bacdSRob Herring 
parser_init(struct of_pci_range_parser * parser,struct device_node * node,const char * name)79667ccd2b9SRob Herring static int parser_init(struct of_pci_range_parser *parser,
79767ccd2b9SRob Herring 			struct device_node *node, const char *name)
79867ccd2b9SRob Herring {
79967ccd2b9SRob Herring 	int rlen;
80067ccd2b9SRob Herring 
80167ccd2b9SRob Herring 	parser->node = node;
80267ccd2b9SRob Herring 	parser->pna = of_n_addr_cells(node);
803bc5e522eSRob Herring 	parser->na = of_bus_n_addr_cells(node);
804bc5e522eSRob Herring 	parser->ns = of_bus_n_size_cells(node);
80567ccd2b9SRob Herring 	parser->dma = !strcmp(name, "dma-ranges");
8062f96593eSJiaxun Yang 	parser->bus = of_match_bus(node);
80767ccd2b9SRob Herring 
80867ccd2b9SRob Herring 	parser->range = of_get_property(node, name, &rlen);
80967ccd2b9SRob Herring 	if (parser->range == NULL)
81067ccd2b9SRob Herring 		return -ENOENT;
81167ccd2b9SRob Herring 
81267ccd2b9SRob Herring 	parser->end = parser->range + rlen / sizeof(__be32);
81367ccd2b9SRob Herring 
81467ccd2b9SRob Herring 	return 0;
81567ccd2b9SRob Herring }
81667ccd2b9SRob Herring 
of_pci_range_parser_init(struct of_pci_range_parser * parser,struct device_node * node)81767ccd2b9SRob Herring int of_pci_range_parser_init(struct of_pci_range_parser *parser,
81867ccd2b9SRob Herring 				struct device_node *node)
81967ccd2b9SRob Herring {
82067ccd2b9SRob Herring 	return parser_init(parser, node, "ranges");
82167ccd2b9SRob Herring }
82267ccd2b9SRob Herring EXPORT_SYMBOL_GPL(of_pci_range_parser_init);
82367ccd2b9SRob Herring 
of_pci_dma_range_parser_init(struct of_pci_range_parser * parser,struct device_node * node)82467ccd2b9SRob Herring int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser,
82567ccd2b9SRob Herring 				struct device_node *node)
82667ccd2b9SRob Herring {
82767ccd2b9SRob Herring 	return parser_init(parser, node, "dma-ranges");
82867ccd2b9SRob Herring }
82967ccd2b9SRob Herring EXPORT_SYMBOL_GPL(of_pci_dma_range_parser_init);
830bc5e522eSRob Herring #define of_dma_range_parser_init of_pci_dma_range_parser_init
83167ccd2b9SRob Herring 
of_pci_range_parser_one(struct of_pci_range_parser * parser,struct of_pci_range * range)83267ccd2b9SRob Herring struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
83367ccd2b9SRob Herring 						struct of_pci_range *range)
83467ccd2b9SRob Herring {
835bc5e522eSRob Herring 	int na = parser->na;
836bc5e522eSRob Herring 	int ns = parser->ns;
837bc5e522eSRob Herring 	int np = parser->pna + na + ns;
8382f96593eSJiaxun Yang 	int busflag_na = 0;
83967ccd2b9SRob Herring 
84067ccd2b9SRob Herring 	if (!range)
84167ccd2b9SRob Herring 		return NULL;
84267ccd2b9SRob Herring 
843bc5e522eSRob Herring 	if (!parser->range || parser->range + np > parser->end)
84467ccd2b9SRob Herring 		return NULL;
84567ccd2b9SRob Herring 
8462f96593eSJiaxun Yang 	range->flags = parser->bus->get_flags(parser->range);
847bc5e522eSRob Herring 
8482f96593eSJiaxun Yang 	/* A extra cell for resource flags */
8492f96593eSJiaxun Yang 	if (parser->bus->has_flags)
8502f96593eSJiaxun Yang 		busflag_na = 1;
8512f96593eSJiaxun Yang 
8522f96593eSJiaxun Yang 	range->bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na);
853bc5e522eSRob Herring 
85467ccd2b9SRob Herring 	if (parser->dma)
85567ccd2b9SRob Herring 		range->cpu_addr = of_translate_dma_address(parser->node,
85667ccd2b9SRob Herring 				parser->range + na);
85767ccd2b9SRob Herring 	else
85867ccd2b9SRob Herring 		range->cpu_addr = of_translate_address(parser->node,
85967ccd2b9SRob Herring 				parser->range + na);
86067ccd2b9SRob Herring 	range->size = of_read_number(parser->range + parser->pna + na, ns);
86167ccd2b9SRob Herring 
862bc5e522eSRob Herring 	parser->range += np;
86367ccd2b9SRob Herring 
86467ccd2b9SRob Herring 	/* Now consume following elements while they are contiguous */
865bc5e522eSRob Herring 	while (parser->range + np <= parser->end) {
866bc5e522eSRob Herring 		u32 flags = 0;
8672f96593eSJiaxun Yang 		u64 bus_addr, cpu_addr, size;
86867ccd2b9SRob Herring 
8692f96593eSJiaxun Yang 		flags = parser->bus->get_flags(parser->range);
8702f96593eSJiaxun Yang 		bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na);
87167ccd2b9SRob Herring 		if (parser->dma)
87267ccd2b9SRob Herring 			cpu_addr = of_translate_dma_address(parser->node,
87367ccd2b9SRob Herring 					parser->range + na);
87467ccd2b9SRob Herring 		else
87567ccd2b9SRob Herring 			cpu_addr = of_translate_address(parser->node,
87667ccd2b9SRob Herring 					parser->range + na);
87767ccd2b9SRob Herring 		size = of_read_number(parser->range + parser->pna + na, ns);
87867ccd2b9SRob Herring 
87967ccd2b9SRob Herring 		if (flags != range->flags)
88067ccd2b9SRob Herring 			break;
8812f96593eSJiaxun Yang 		if (bus_addr != range->bus_addr + range->size ||
88267ccd2b9SRob Herring 		    cpu_addr != range->cpu_addr + range->size)
88367ccd2b9SRob Herring 			break;
88467ccd2b9SRob Herring 
88567ccd2b9SRob Herring 		range->size += size;
886bc5e522eSRob Herring 		parser->range += np;
88767ccd2b9SRob Herring 	}
88867ccd2b9SRob Herring 
88967ccd2b9SRob Herring 	return range;
89067ccd2b9SRob Herring }
89167ccd2b9SRob Herring EXPORT_SYMBOL_GPL(of_pci_range_parser_one);
89267ccd2b9SRob Herring 
of_translate_ioport(struct device_node * dev,const __be32 * in_addr,u64 size)89365af618dSZhichang Yuan static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr,
89465af618dSZhichang Yuan 			u64 size)
89565af618dSZhichang Yuan {
89665af618dSZhichang Yuan 	u64 taddr;
89765af618dSZhichang Yuan 	unsigned long port;
89865af618dSZhichang Yuan 	struct device_node *host;
89965af618dSZhichang Yuan 
90095835a8dSMaxime Ripard 	taddr = __of_translate_address(dev, of_get_parent,
90195835a8dSMaxime Ripard 				       in_addr, "ranges", &host);
90265af618dSZhichang Yuan 	if (host) {
90365af618dSZhichang Yuan 		/* host-specific port access */
90465af618dSZhichang Yuan 		port = logic_pio_trans_hwaddr(&host->fwnode, taddr, size);
90565af618dSZhichang Yuan 		of_node_put(host);
90665af618dSZhichang Yuan 	} else {
90765af618dSZhichang Yuan 		/* memory-mapped I/O range */
90865af618dSZhichang Yuan 		port = pci_address_to_pio(taddr);
90965af618dSZhichang Yuan 	}
91065af618dSZhichang Yuan 
91165af618dSZhichang Yuan 	if (port == (unsigned long)-1)
91265af618dSZhichang Yuan 		return OF_BAD_ADDR;
91365af618dSZhichang Yuan 
91465af618dSZhichang Yuan 	return port;
91565af618dSZhichang Yuan }
91665af618dSZhichang Yuan 
917e0d07278SJim Quinlan #ifdef CONFIG_HAS_DMA
91818308c94SGrygorii Strashko /**
919e0d07278SJim Quinlan  * of_dma_get_range - Get DMA range info and put it into a map array
92018308c94SGrygorii Strashko  * @np:		device node to get DMA range info
921e0d07278SJim Quinlan  * @map:	dma range structure to return
92218308c94SGrygorii Strashko  *
92318308c94SGrygorii Strashko  * Look in bottom up direction for the first "dma-ranges" property
924e0d07278SJim Quinlan  * and parse it.  Put the information into a DMA offset map array.
925e0d07278SJim Quinlan  *
92618308c94SGrygorii Strashko  * dma-ranges format:
92718308c94SGrygorii Strashko  *	DMA addr (dma_addr)	: naddr cells
92818308c94SGrygorii Strashko  *	CPU addr (phys_addr_t)	: pna cells
92918308c94SGrygorii Strashko  *	size			: nsize cells
93018308c94SGrygorii Strashko  *
931e0d07278SJim Quinlan  * It returns -ENODEV if "dma-ranges" property was not found for this
932e0d07278SJim Quinlan  * device in the DT.
93318308c94SGrygorii Strashko  */
of_dma_get_range(struct device_node * np,const struct bus_dma_region ** map)934e0d07278SJim Quinlan int of_dma_get_range(struct device_node *np, const struct bus_dma_region **map)
93518308c94SGrygorii Strashko {
93618308c94SGrygorii Strashko 	struct device_node *node = of_node_get(np);
93718308c94SGrygorii Strashko 	const __be32 *ranges = NULL;
938951d4885SRobin Murphy 	bool found_dma_ranges = false;
9397a8b64d1SRob Herring 	struct of_range_parser parser;
9407a8b64d1SRob Herring 	struct of_range range;
941e0d07278SJim Quinlan 	struct bus_dma_region *r;
942e0d07278SJim Quinlan 	int len, num_ranges = 0;
943e0d07278SJim Quinlan 	int ret = 0;
94418308c94SGrygorii Strashko 
945951d4885SRobin Murphy 	while (node) {
94618308c94SGrygorii Strashko 		ranges = of_get_property(node, "dma-ranges", &len);
94718308c94SGrygorii Strashko 
94818308c94SGrygorii Strashko 		/* Ignore empty ranges, they imply no translation required */
94918308c94SGrygorii Strashko 		if (ranges && len > 0)
95018308c94SGrygorii Strashko 			break;
95118308c94SGrygorii Strashko 
952951d4885SRobin Murphy 		/* Once we find 'dma-ranges', then a missing one is an error */
953951d4885SRobin Murphy 		if (found_dma_ranges && !ranges) {
954951d4885SRobin Murphy 			ret = -ENODEV;
955951d4885SRobin Murphy 			goto out;
956951d4885SRobin Murphy 		}
957951d4885SRobin Murphy 		found_dma_ranges = true;
958951d4885SRobin Murphy 
959951d4885SRobin Murphy 		node = of_get_next_dma_parent(node);
96018308c94SGrygorii Strashko 	}
96118308c94SGrygorii Strashko 
962951d4885SRobin Murphy 	if (!node || !ranges) {
9630d638a07SRob Herring 		pr_debug("no dma-ranges found for node(%pOF)\n", np);
96418308c94SGrygorii Strashko 		ret = -ENODEV;
96518308c94SGrygorii Strashko 		goto out;
96618308c94SGrygorii Strashko 	}
96718308c94SGrygorii Strashko 
9687a8b64d1SRob Herring 	of_dma_range_parser_init(&parser, node);
969f6933c01SMark Brown 	for_each_of_range(&parser, &range) {
970f6933c01SMark Brown 		if (range.cpu_addr == OF_BAD_ADDR) {
971f6933c01SMark Brown 			pr_err("translation of DMA address(%llx) to CPU address failed node(%pOF)\n",
972f6933c01SMark Brown 			       range.bus_addr, node);
973f6933c01SMark Brown 			continue;
974f6933c01SMark Brown 		}
975e0d07278SJim Quinlan 		num_ranges++;
976f6933c01SMark Brown 	}
977f6933c01SMark Brown 
978f6933c01SMark Brown 	if (!num_ranges) {
979f6933c01SMark Brown 		ret = -EINVAL;
980f6933c01SMark Brown 		goto out;
981f6933c01SMark Brown 	}
98218308c94SGrygorii Strashko 
983e0d07278SJim Quinlan 	r = kcalloc(num_ranges + 1, sizeof(*r), GFP_KERNEL);
984e0d07278SJim Quinlan 	if (!r) {
985e0d07278SJim Quinlan 		ret = -ENOMEM;
986e0d07278SJim Quinlan 		goto out;
987e0d07278SJim Quinlan 	}
988e0d07278SJim Quinlan 
989e0d07278SJim Quinlan 	/*
990f6933c01SMark Brown 	 * Record all info in the generic DMA ranges array for struct device,
991f6933c01SMark Brown 	 * returning an error if we don't find any parsable ranges.
992e0d07278SJim Quinlan 	 */
993e0d07278SJim Quinlan 	*map = r;
994e0d07278SJim Quinlan 	of_dma_range_parser_init(&parser, node);
9957a8b64d1SRob Herring 	for_each_of_range(&parser, &range) {
99618308c94SGrygorii Strashko 		pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n",
9977a8b64d1SRob Herring 			 range.bus_addr, range.cpu_addr, range.size);
998f6933c01SMark Brown 		if (range.cpu_addr == OF_BAD_ADDR)
999f49c7fafSColin Ian King 			continue;
1000e0d07278SJim Quinlan 		r->cpu_start = range.cpu_addr;
1001e0d07278SJim Quinlan 		r->dma_start = range.bus_addr;
1002e0d07278SJim Quinlan 		r->size = range.size;
1003e0d07278SJim Quinlan 		r->offset = range.cpu_addr - range.bus_addr;
1004e0d07278SJim Quinlan 		r++;
10059d55bebdSRob Herring 	}
100618308c94SGrygorii Strashko out:
100718308c94SGrygorii Strashko 	of_node_put(node);
100818308c94SGrygorii Strashko 	return ret;
100918308c94SGrygorii Strashko }
1010e0d07278SJim Quinlan #endif /* CONFIG_HAS_DMA */
101192ea637eSSantosh Shilimkar 
101292ea637eSSantosh Shilimkar /**
1013964db79dSNicolas Saenz Julienne  * of_dma_get_max_cpu_address - Gets highest CPU address suitable for DMA
1014964db79dSNicolas Saenz Julienne  * @np: The node to start searching from or NULL to start from the root
1015964db79dSNicolas Saenz Julienne  *
1016964db79dSNicolas Saenz Julienne  * Gets the highest CPU physical address that is addressable by all DMA masters
1017964db79dSNicolas Saenz Julienne  * in the sub-tree pointed by np, or the whole tree if NULL is passed. If no
1018964db79dSNicolas Saenz Julienne  * DMA constrained device is found, it returns PHYS_ADDR_MAX.
1019964db79dSNicolas Saenz Julienne  */
of_dma_get_max_cpu_address(struct device_node * np)1020964db79dSNicolas Saenz Julienne phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np)
1021964db79dSNicolas Saenz Julienne {
1022964db79dSNicolas Saenz Julienne 	phys_addr_t max_cpu_addr = PHYS_ADDR_MAX;
1023964db79dSNicolas Saenz Julienne 	struct of_range_parser parser;
1024964db79dSNicolas Saenz Julienne 	phys_addr_t subtree_max_addr;
1025964db79dSNicolas Saenz Julienne 	struct device_node *child;
1026964db79dSNicolas Saenz Julienne 	struct of_range range;
1027964db79dSNicolas Saenz Julienne 	const __be32 *ranges;
1028964db79dSNicolas Saenz Julienne 	u64 cpu_end = 0;
1029964db79dSNicolas Saenz Julienne 	int len;
1030964db79dSNicolas Saenz Julienne 
1031964db79dSNicolas Saenz Julienne 	if (!np)
1032964db79dSNicolas Saenz Julienne 		np = of_root;
1033964db79dSNicolas Saenz Julienne 
1034964db79dSNicolas Saenz Julienne 	ranges = of_get_property(np, "dma-ranges", &len);
1035964db79dSNicolas Saenz Julienne 	if (ranges && len) {
1036964db79dSNicolas Saenz Julienne 		of_dma_range_parser_init(&parser, np);
1037964db79dSNicolas Saenz Julienne 		for_each_of_range(&parser, &range)
1038964db79dSNicolas Saenz Julienne 			if (range.cpu_addr + range.size > cpu_end)
1039964db79dSNicolas Saenz Julienne 				cpu_end = range.cpu_addr + range.size - 1;
1040964db79dSNicolas Saenz Julienne 
1041964db79dSNicolas Saenz Julienne 		if (max_cpu_addr > cpu_end)
1042964db79dSNicolas Saenz Julienne 			max_cpu_addr = cpu_end;
1043964db79dSNicolas Saenz Julienne 	}
1044964db79dSNicolas Saenz Julienne 
1045964db79dSNicolas Saenz Julienne 	for_each_available_child_of_node(np, child) {
1046964db79dSNicolas Saenz Julienne 		subtree_max_addr = of_dma_get_max_cpu_address(child);
1047964db79dSNicolas Saenz Julienne 		if (max_cpu_addr > subtree_max_addr)
1048964db79dSNicolas Saenz Julienne 			max_cpu_addr = subtree_max_addr;
1049964db79dSNicolas Saenz Julienne 	}
1050964db79dSNicolas Saenz Julienne 
1051964db79dSNicolas Saenz Julienne 	return max_cpu_addr;
1052964db79dSNicolas Saenz Julienne }
1053964db79dSNicolas Saenz Julienne 
1054964db79dSNicolas Saenz Julienne /**
105592ea637eSSantosh Shilimkar  * of_dma_is_coherent - Check if device is coherent
105692ea637eSSantosh Shilimkar  * @np:	device node
105792ea637eSSantosh Shilimkar  *
105892ea637eSSantosh Shilimkar  * It returns true if "dma-coherent" property was found
1059dabf6b36SMichael Ellerman  * for this device in the DT, or if DMA is coherent by
106012b82775SHeiko Stuebner  * default for OF devices on the current platform and no
106112b82775SHeiko Stuebner  * "dma-noncoherent" property was found for this device.
106292ea637eSSantosh Shilimkar  */
of_dma_is_coherent(struct device_node * np)106392ea637eSSantosh Shilimkar bool of_dma_is_coherent(struct device_node *np)
106492ea637eSSantosh Shilimkar {
1065a5bea04fSEvan Nimmo 	struct device_node *node;
1066c00a60d6SJiaxun Yang 	bool is_coherent = dma_default_coherent;
1067dabf6b36SMichael Ellerman 
1068a5bea04fSEvan Nimmo 	node = of_node_get(np);
1069a5bea04fSEvan Nimmo 
107092ea637eSSantosh Shilimkar 	while (node) {
107192ea637eSSantosh Shilimkar 		if (of_property_read_bool(node, "dma-coherent")) {
107212b82775SHeiko Stuebner 			is_coherent = true;
107312b82775SHeiko Stuebner 			break;
107412b82775SHeiko Stuebner 		}
107512b82775SHeiko Stuebner 		if (of_property_read_bool(node, "dma-noncoherent")) {
107612b82775SHeiko Stuebner 			is_coherent = false;
107712b82775SHeiko Stuebner 			break;
107892ea637eSSantosh Shilimkar 		}
1079c60bf3ebSRobin Murphy 		node = of_get_next_dma_parent(node);
108092ea637eSSantosh Shilimkar 	}
108192ea637eSSantosh Shilimkar 	of_node_put(node);
108212b82775SHeiko Stuebner 	return is_coherent;
108392ea637eSSantosh Shilimkar }
108492ea637eSSantosh Shilimkar EXPORT_SYMBOL_GPL(of_dma_is_coherent);
108589897f73SHector Martin 
108689897f73SHector Martin /**
108789897f73SHector Martin  * of_mmio_is_nonposted - Check if device uses non-posted MMIO
108889897f73SHector Martin  * @np:	device node
108989897f73SHector Martin  *
109089897f73SHector Martin  * Returns true if the "nonposted-mmio" property was found for
109189897f73SHector Martin  * the device's bus.
109289897f73SHector Martin  *
109389897f73SHector Martin  * This is currently only enabled on builds that support Apple ARM devices, as
109489897f73SHector Martin  * an optimization.
109589897f73SHector Martin  */
of_mmio_is_nonposted(struct device_node * np)109689897f73SHector Martin static bool of_mmio_is_nonposted(struct device_node *np)
109789897f73SHector Martin {
109889897f73SHector Martin 	struct device_node *parent;
109989897f73SHector Martin 	bool nonposted;
110089897f73SHector Martin 
110189897f73SHector Martin 	if (!IS_ENABLED(CONFIG_ARCH_APPLE))
110289897f73SHector Martin 		return false;
110389897f73SHector Martin 
110489897f73SHector Martin 	parent = of_get_parent(np);
110589897f73SHector Martin 	if (!parent)
110689897f73SHector Martin 		return false;
110789897f73SHector Martin 
110889897f73SHector Martin 	nonposted = of_property_read_bool(parent, "nonposted-mmio");
110989897f73SHector Martin 
111089897f73SHector Martin 	of_node_put(parent);
111189897f73SHector Martin 	return nonposted;
111289897f73SHector Martin }
11135eac0bdcSGeert Uytterhoeven 
__of_address_to_resource(struct device_node * dev,int index,int bar_no,struct resource * r)11145eac0bdcSGeert Uytterhoeven static int __of_address_to_resource(struct device_node *dev, int index, int bar_no,
11155eac0bdcSGeert Uytterhoeven 		struct resource *r)
11165eac0bdcSGeert Uytterhoeven {
11175eac0bdcSGeert Uytterhoeven 	u64 taddr;
11185eac0bdcSGeert Uytterhoeven 	const __be32	*addrp;
11195eac0bdcSGeert Uytterhoeven 	u64		size;
11205eac0bdcSGeert Uytterhoeven 	unsigned int	flags;
11215eac0bdcSGeert Uytterhoeven 	const char	*name = NULL;
11225eac0bdcSGeert Uytterhoeven 
11235eac0bdcSGeert Uytterhoeven 	addrp = __of_get_address(dev, index, bar_no, &size, &flags);
11245eac0bdcSGeert Uytterhoeven 	if (addrp == NULL)
11255eac0bdcSGeert Uytterhoeven 		return -EINVAL;
11265eac0bdcSGeert Uytterhoeven 
11275eac0bdcSGeert Uytterhoeven 	/* Get optional "reg-names" property to add a name to a resource */
11285eac0bdcSGeert Uytterhoeven 	if (index >= 0)
11295eac0bdcSGeert Uytterhoeven 		of_property_read_string_index(dev, "reg-names",	index, &name);
11305eac0bdcSGeert Uytterhoeven 
11315eac0bdcSGeert Uytterhoeven 	if (flags & IORESOURCE_MEM)
11325eac0bdcSGeert Uytterhoeven 		taddr = of_translate_address(dev, addrp);
11335eac0bdcSGeert Uytterhoeven 	else if (flags & IORESOURCE_IO)
11345eac0bdcSGeert Uytterhoeven 		taddr = of_translate_ioport(dev, addrp, size);
11355eac0bdcSGeert Uytterhoeven 	else
11365eac0bdcSGeert Uytterhoeven 		return -EINVAL;
11375eac0bdcSGeert Uytterhoeven 
11385eac0bdcSGeert Uytterhoeven 	if (taddr == OF_BAD_ADDR)
11395eac0bdcSGeert Uytterhoeven 		return -EINVAL;
11405eac0bdcSGeert Uytterhoeven 	memset(r, 0, sizeof(struct resource));
11415eac0bdcSGeert Uytterhoeven 
11425eac0bdcSGeert Uytterhoeven 	if (of_mmio_is_nonposted(dev))
11435eac0bdcSGeert Uytterhoeven 		flags |= IORESOURCE_MEM_NONPOSTED;
11445eac0bdcSGeert Uytterhoeven 
11455eac0bdcSGeert Uytterhoeven 	r->start = taddr;
11465eac0bdcSGeert Uytterhoeven 	r->end = taddr + size - 1;
11475eac0bdcSGeert Uytterhoeven 	r->flags = flags;
11485eac0bdcSGeert Uytterhoeven 	r->name = name ? name : dev->full_name;
11495eac0bdcSGeert Uytterhoeven 
11505eac0bdcSGeert Uytterhoeven 	return 0;
11515eac0bdcSGeert Uytterhoeven }
11525eac0bdcSGeert Uytterhoeven 
11535eac0bdcSGeert Uytterhoeven /**
11545eac0bdcSGeert Uytterhoeven  * of_address_to_resource - Translate device tree address and return as resource
11555eac0bdcSGeert Uytterhoeven  * @dev:	Caller's Device Node
11565eac0bdcSGeert Uytterhoeven  * @index:	Index into the array
11575eac0bdcSGeert Uytterhoeven  * @r:		Pointer to resource array
11585eac0bdcSGeert Uytterhoeven  *
11595eac0bdcSGeert Uytterhoeven  * Returns -EINVAL if the range cannot be converted to resource.
11605eac0bdcSGeert Uytterhoeven  *
11615eac0bdcSGeert Uytterhoeven  * Note that if your address is a PIO address, the conversion will fail if
11625eac0bdcSGeert Uytterhoeven  * the physical address can't be internally converted to an IO token with
11635eac0bdcSGeert Uytterhoeven  * pci_address_to_pio(), that is because it's either called too early or it
11645eac0bdcSGeert Uytterhoeven  * can't be matched to any host bridge IO space
11655eac0bdcSGeert Uytterhoeven  */
of_address_to_resource(struct device_node * dev,int index,struct resource * r)11665eac0bdcSGeert Uytterhoeven int of_address_to_resource(struct device_node *dev, int index,
11675eac0bdcSGeert Uytterhoeven 			   struct resource *r)
11685eac0bdcSGeert Uytterhoeven {
11695eac0bdcSGeert Uytterhoeven 	return __of_address_to_resource(dev, index, -1, r);
11705eac0bdcSGeert Uytterhoeven }
11715eac0bdcSGeert Uytterhoeven EXPORT_SYMBOL_GPL(of_address_to_resource);
11725eac0bdcSGeert Uytterhoeven 
of_pci_address_to_resource(struct device_node * dev,int bar,struct resource * r)11735eac0bdcSGeert Uytterhoeven int of_pci_address_to_resource(struct device_node *dev, int bar,
11745eac0bdcSGeert Uytterhoeven 			       struct resource *r)
11755eac0bdcSGeert Uytterhoeven {
11765eac0bdcSGeert Uytterhoeven 
11775eac0bdcSGeert Uytterhoeven 	if (!IS_ENABLED(CONFIG_PCI))
11785eac0bdcSGeert Uytterhoeven 		return -ENOSYS;
11795eac0bdcSGeert Uytterhoeven 
11805eac0bdcSGeert Uytterhoeven 	return __of_address_to_resource(dev, -1, bar, r);
11815eac0bdcSGeert Uytterhoeven }
11825eac0bdcSGeert Uytterhoeven EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
11835eac0bdcSGeert Uytterhoeven 
11845eac0bdcSGeert Uytterhoeven /**
11855eac0bdcSGeert Uytterhoeven  * of_iomap - Maps the memory mapped IO for a given device_node
11865eac0bdcSGeert Uytterhoeven  * @np:		the device whose io range will be mapped
11875eac0bdcSGeert Uytterhoeven  * @index:	index of the io range
11885eac0bdcSGeert Uytterhoeven  *
11895eac0bdcSGeert Uytterhoeven  * Returns a pointer to the mapped memory
11905eac0bdcSGeert Uytterhoeven  */
of_iomap(struct device_node * np,int index)11915eac0bdcSGeert Uytterhoeven void __iomem *of_iomap(struct device_node *np, int index)
11925eac0bdcSGeert Uytterhoeven {
11935eac0bdcSGeert Uytterhoeven 	struct resource res;
11945eac0bdcSGeert Uytterhoeven 
11955eac0bdcSGeert Uytterhoeven 	if (of_address_to_resource(np, index, &res))
11965eac0bdcSGeert Uytterhoeven 		return NULL;
11975eac0bdcSGeert Uytterhoeven 
11985eac0bdcSGeert Uytterhoeven 	if (res.flags & IORESOURCE_MEM_NONPOSTED)
11995eac0bdcSGeert Uytterhoeven 		return ioremap_np(res.start, resource_size(&res));
12005eac0bdcSGeert Uytterhoeven 	else
12015eac0bdcSGeert Uytterhoeven 		return ioremap(res.start, resource_size(&res));
12025eac0bdcSGeert Uytterhoeven }
12035eac0bdcSGeert Uytterhoeven EXPORT_SYMBOL(of_iomap);
12045eac0bdcSGeert Uytterhoeven 
12055eac0bdcSGeert Uytterhoeven /*
12065eac0bdcSGeert Uytterhoeven  * of_io_request_and_map - Requests a resource and maps the memory mapped IO
12075eac0bdcSGeert Uytterhoeven  *			   for a given device_node
12085eac0bdcSGeert Uytterhoeven  * @device:	the device whose io range will be mapped
12095eac0bdcSGeert Uytterhoeven  * @index:	index of the io range
12105eac0bdcSGeert Uytterhoeven  * @name:	name "override" for the memory region request or NULL
12115eac0bdcSGeert Uytterhoeven  *
12125eac0bdcSGeert Uytterhoeven  * Returns a pointer to the requested and mapped memory or an ERR_PTR() encoded
12135eac0bdcSGeert Uytterhoeven  * error code on failure. Usage example:
12145eac0bdcSGeert Uytterhoeven  *
12155eac0bdcSGeert Uytterhoeven  *	base = of_io_request_and_map(node, 0, "foo");
12165eac0bdcSGeert Uytterhoeven  *	if (IS_ERR(base))
12175eac0bdcSGeert Uytterhoeven  *		return PTR_ERR(base);
12185eac0bdcSGeert Uytterhoeven  */
of_io_request_and_map(struct device_node * np,int index,const char * name)12195eac0bdcSGeert Uytterhoeven void __iomem *of_io_request_and_map(struct device_node *np, int index,
12205eac0bdcSGeert Uytterhoeven 				    const char *name)
12215eac0bdcSGeert Uytterhoeven {
12225eac0bdcSGeert Uytterhoeven 	struct resource res;
12235eac0bdcSGeert Uytterhoeven 	void __iomem *mem;
12245eac0bdcSGeert Uytterhoeven 
12255eac0bdcSGeert Uytterhoeven 	if (of_address_to_resource(np, index, &res))
12265eac0bdcSGeert Uytterhoeven 		return IOMEM_ERR_PTR(-EINVAL);
12275eac0bdcSGeert Uytterhoeven 
12285eac0bdcSGeert Uytterhoeven 	if (!name)
12295eac0bdcSGeert Uytterhoeven 		name = res.name;
12305eac0bdcSGeert Uytterhoeven 	if (!request_mem_region(res.start, resource_size(&res), name))
12315eac0bdcSGeert Uytterhoeven 		return IOMEM_ERR_PTR(-EBUSY);
12325eac0bdcSGeert Uytterhoeven 
12335eac0bdcSGeert Uytterhoeven 	if (res.flags & IORESOURCE_MEM_NONPOSTED)
12345eac0bdcSGeert Uytterhoeven 		mem = ioremap_np(res.start, resource_size(&res));
12355eac0bdcSGeert Uytterhoeven 	else
12365eac0bdcSGeert Uytterhoeven 		mem = ioremap(res.start, resource_size(&res));
12375eac0bdcSGeert Uytterhoeven 
12385eac0bdcSGeert Uytterhoeven 	if (!mem) {
12395eac0bdcSGeert Uytterhoeven 		release_mem_region(res.start, resource_size(&res));
12405eac0bdcSGeert Uytterhoeven 		return IOMEM_ERR_PTR(-ENOMEM);
12415eac0bdcSGeert Uytterhoeven 	}
12425eac0bdcSGeert Uytterhoeven 
12435eac0bdcSGeert Uytterhoeven 	return mem;
12445eac0bdcSGeert Uytterhoeven }
12455eac0bdcSGeert Uytterhoeven EXPORT_SYMBOL(of_io_request_and_map);
1246