xref: /openbmc/linux/drivers/of/address.c (revision b3e46d1a)
1af6074fcSRob Herring // SPDX-License-Identifier: GPL-2.0
2606ad42aSRob Herring #define pr_fmt(fmt)	"OF: " fmt
3606ad42aSRob Herring 
45019f0b1SArnd Bergmann #include <linux/device.h>
5fcfaab30SGabriele Paoloni #include <linux/fwnode.h>
66b884a8dSGrant Likely #include <linux/io.h>
76b884a8dSGrant Likely #include <linux/ioport.h>
865af618dSZhichang Yuan #include <linux/logic_pio.h>
9dbbdee94SGrant Likely #include <linux/module.h>
106b884a8dSGrant Likely #include <linux/of_address.h>
11c5076cfeSTomasz Nowicki #include <linux/pci.h>
12dbbdee94SGrant Likely #include <linux/pci_regs.h>
1341f8bba7SLiviu Dudau #include <linux/sizes.h>
1441f8bba7SLiviu Dudau #include <linux/slab.h>
15dbbdee94SGrant Likely #include <linux/string.h>
166b884a8dSGrant Likely 
17dbbdee94SGrant Likely /* Max address size we deal with */
18dbbdee94SGrant Likely #define OF_MAX_ADDR_CELLS	4
195d61b165SStephen Warren #define OF_CHECK_ADDR_COUNT(na)	((na) > 0 && (na) <= OF_MAX_ADDR_CELLS)
205d61b165SStephen Warren #define OF_CHECK_COUNTS(na, ns)	(OF_CHECK_ADDR_COUNT(na) && (ns) > 0)
21dbbdee94SGrant Likely 
22dbbdee94SGrant Likely static struct of_bus *of_match_bus(struct device_node *np);
230131d897SSebastian Andrzej Siewior static int __of_address_to_resource(struct device_node *dev,
240131d897SSebastian Andrzej Siewior 		const __be32 *addrp, u64 size, unsigned int flags,
2535f3da32SBenoit Cousson 		const char *name, struct resource *r);
26dbbdee94SGrant Likely 
27dbbdee94SGrant Likely /* Debug utility */
28dbbdee94SGrant Likely #ifdef DEBUG
290131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na)
30dbbdee94SGrant Likely {
31606ad42aSRob Herring 	pr_debug("%s", s);
32dbbdee94SGrant Likely 	while (na--)
33606ad42aSRob Herring 		pr_cont(" %08x", be32_to_cpu(*(addr++)));
34606ad42aSRob Herring 	pr_cont("\n");
35dbbdee94SGrant Likely }
36dbbdee94SGrant Likely #else
370131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na) { }
38dbbdee94SGrant Likely #endif
39dbbdee94SGrant Likely 
40dbbdee94SGrant Likely /* Callbacks for bus specific translators */
41dbbdee94SGrant Likely struct of_bus {
42dbbdee94SGrant Likely 	const char	*name;
43dbbdee94SGrant Likely 	const char	*addresses;
44dbbdee94SGrant Likely 	int		(*match)(struct device_node *parent);
45dbbdee94SGrant Likely 	void		(*count_cells)(struct device_node *child,
46dbbdee94SGrant Likely 				       int *addrc, int *sizec);
4747b1e689SKim Phillips 	u64		(*map)(__be32 *addr, const __be32 *range,
48dbbdee94SGrant Likely 				int na, int ns, int pna);
4947b1e689SKim Phillips 	int		(*translate)(__be32 *addr, u64 offset, int na);
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 
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 
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 
75606ad42aSRob Herring 	pr_debug("default map, cp=%llx, s=%llx, da=%llx\n",
76dbbdee94SGrant Likely 		 (unsigned long long)cp, (unsigned long long)s,
77dbbdee94SGrant Likely 		 (unsigned long long)da);
78dbbdee94SGrant Likely 
79dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
80dbbdee94SGrant Likely 		return OF_BAD_ADDR;
81dbbdee94SGrant Likely 	return da - cp;
82dbbdee94SGrant Likely }
83dbbdee94SGrant Likely 
8447b1e689SKim Phillips static int of_bus_default_translate(__be32 *addr, u64 offset, int na)
85dbbdee94SGrant Likely {
86dbbdee94SGrant Likely 	u64 a = of_read_number(addr, na);
87dbbdee94SGrant Likely 	memset(addr, 0, na * 4);
88dbbdee94SGrant Likely 	a += offset;
89dbbdee94SGrant Likely 	if (na > 1)
90154063a9SGrant Likely 		addr[na - 2] = cpu_to_be32(a >> 32);
91154063a9SGrant Likely 	addr[na - 1] = cpu_to_be32(a & 0xffffffffu);
92dbbdee94SGrant Likely 
93dbbdee94SGrant Likely 	return 0;
94dbbdee94SGrant Likely }
95dbbdee94SGrant Likely 
960131d897SSebastian Andrzej Siewior static unsigned int of_bus_default_get_flags(const __be32 *addr)
97dbbdee94SGrant Likely {
98dbbdee94SGrant Likely 	return IORESOURCE_MEM;
99dbbdee94SGrant Likely }
100dbbdee94SGrant Likely 
1014670d610SRob Herring #ifdef CONFIG_PCI
102dbbdee94SGrant Likely /*
103dbbdee94SGrant Likely  * PCI bus specific translator
104dbbdee94SGrant Likely  */
105dbbdee94SGrant Likely 
106dbbdee94SGrant Likely static int of_bus_pci_match(struct device_node *np)
107dbbdee94SGrant Likely {
1086dd18e46SBenjamin Herrenschmidt 	/*
10914e2abb7SKleber Sacilotto de Souza  	 * "pciex" is PCI Express
1106dd18e46SBenjamin Herrenschmidt 	 * "vci" is for the /chaos bridge on 1st-gen PCI powermacs
1116dd18e46SBenjamin Herrenschmidt 	 * "ht" is hypertransport
1126dd18e46SBenjamin Herrenschmidt 	 */
113e8b1dee2SRob Herring 	return of_node_is_type(np, "pci") || of_node_is_type(np, "pciex") ||
114e8b1dee2SRob Herring 		of_node_is_type(np, "vci") || of_node_is_type(np, "ht");
115dbbdee94SGrant Likely }
116dbbdee94SGrant Likely 
117dbbdee94SGrant Likely static void of_bus_pci_count_cells(struct device_node *np,
118dbbdee94SGrant Likely 				   int *addrc, int *sizec)
119dbbdee94SGrant Likely {
120dbbdee94SGrant Likely 	if (addrc)
121dbbdee94SGrant Likely 		*addrc = 3;
122dbbdee94SGrant Likely 	if (sizec)
123dbbdee94SGrant Likely 		*sizec = 2;
124dbbdee94SGrant Likely }
125dbbdee94SGrant Likely 
1260131d897SSebastian Andrzej Siewior static unsigned int of_bus_pci_get_flags(const __be32 *addr)
127dbbdee94SGrant Likely {
128dbbdee94SGrant Likely 	unsigned int flags = 0;
1290131d897SSebastian Andrzej Siewior 	u32 w = be32_to_cpup(addr);
130dbbdee94SGrant Likely 
131dbbdee94SGrant Likely 	switch((w >> 24) & 0x03) {
132dbbdee94SGrant Likely 	case 0x01:
133dbbdee94SGrant Likely 		flags |= IORESOURCE_IO;
134dbbdee94SGrant Likely 		break;
135dbbdee94SGrant Likely 	case 0x02: /* 32 bits */
136dbbdee94SGrant Likely 	case 0x03: /* 64 bits */
137dbbdee94SGrant Likely 		flags |= IORESOURCE_MEM;
138dbbdee94SGrant Likely 		break;
139dbbdee94SGrant Likely 	}
140dbbdee94SGrant Likely 	if (w & 0x40000000)
141dbbdee94SGrant Likely 		flags |= IORESOURCE_PREFETCH;
142dbbdee94SGrant Likely 	return flags;
143dbbdee94SGrant Likely }
144dbbdee94SGrant Likely 
14547b1e689SKim Phillips static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns,
1460131d897SSebastian Andrzej Siewior 		int pna)
147dbbdee94SGrant Likely {
148dbbdee94SGrant Likely 	u64 cp, s, da;
149dbbdee94SGrant Likely 	unsigned int af, rf;
150dbbdee94SGrant Likely 
151dbbdee94SGrant Likely 	af = of_bus_pci_get_flags(addr);
152dbbdee94SGrant Likely 	rf = of_bus_pci_get_flags(range);
153dbbdee94SGrant Likely 
154dbbdee94SGrant Likely 	/* Check address type match */
155dbbdee94SGrant Likely 	if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO))
156dbbdee94SGrant Likely 		return OF_BAD_ADDR;
157dbbdee94SGrant Likely 
158dbbdee94SGrant Likely 	/* Read address values, skipping high cell */
159dbbdee94SGrant Likely 	cp = of_read_number(range + 1, na - 1);
160dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
161dbbdee94SGrant Likely 	da = of_read_number(addr + 1, na - 1);
162dbbdee94SGrant Likely 
163606ad42aSRob Herring 	pr_debug("PCI map, cp=%llx, s=%llx, da=%llx\n",
164dbbdee94SGrant Likely 		 (unsigned long long)cp, (unsigned long long)s,
165dbbdee94SGrant Likely 		 (unsigned long long)da);
166dbbdee94SGrant Likely 
167dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
168dbbdee94SGrant Likely 		return OF_BAD_ADDR;
169dbbdee94SGrant Likely 	return da - cp;
170dbbdee94SGrant Likely }
171dbbdee94SGrant Likely 
17247b1e689SKim Phillips static int of_bus_pci_translate(__be32 *addr, u64 offset, int na)
173dbbdee94SGrant Likely {
174dbbdee94SGrant Likely 	return of_bus_default_translate(addr + 1, offset, na - 1);
175dbbdee94SGrant Likely }
176dbbdee94SGrant Likely 
1770131d897SSebastian Andrzej Siewior const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
178dbbdee94SGrant Likely 			unsigned int *flags)
179dbbdee94SGrant Likely {
180a9fadeefSJeremy Kerr 	const __be32 *prop;
181dbbdee94SGrant Likely 	unsigned int psize;
182dbbdee94SGrant Likely 	struct device_node *parent;
183dbbdee94SGrant Likely 	struct of_bus *bus;
184dbbdee94SGrant Likely 	int onesize, i, na, ns;
185dbbdee94SGrant Likely 
186dbbdee94SGrant Likely 	/* Get parent & match bus type */
187dbbdee94SGrant Likely 	parent = of_get_parent(dev);
188dbbdee94SGrant Likely 	if (parent == NULL)
189dbbdee94SGrant Likely 		return NULL;
190dbbdee94SGrant Likely 	bus = of_match_bus(parent);
191dbbdee94SGrant Likely 	if (strcmp(bus->name, "pci")) {
192dbbdee94SGrant Likely 		of_node_put(parent);
193dbbdee94SGrant Likely 		return NULL;
194dbbdee94SGrant Likely 	}
195dbbdee94SGrant Likely 	bus->count_cells(dev, &na, &ns);
196dbbdee94SGrant Likely 	of_node_put(parent);
1975d61b165SStephen Warren 	if (!OF_CHECK_ADDR_COUNT(na))
198dbbdee94SGrant Likely 		return NULL;
199dbbdee94SGrant Likely 
200dbbdee94SGrant Likely 	/* Get "reg" or "assigned-addresses" property */
201dbbdee94SGrant Likely 	prop = of_get_property(dev, bus->addresses, &psize);
202dbbdee94SGrant Likely 	if (prop == NULL)
203dbbdee94SGrant Likely 		return NULL;
204dbbdee94SGrant Likely 	psize /= 4;
205dbbdee94SGrant Likely 
206dbbdee94SGrant Likely 	onesize = na + ns;
207154063a9SGrant Likely 	for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) {
208154063a9SGrant Likely 		u32 val = be32_to_cpu(prop[0]);
209154063a9SGrant Likely 		if ((val & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
210dbbdee94SGrant Likely 			if (size)
211dbbdee94SGrant Likely 				*size = of_read_number(prop + na, ns);
212dbbdee94SGrant Likely 			if (flags)
213dbbdee94SGrant Likely 				*flags = bus->get_flags(prop);
214dbbdee94SGrant Likely 			return prop;
215dbbdee94SGrant Likely 		}
216154063a9SGrant Likely 	}
217dbbdee94SGrant Likely 	return NULL;
218dbbdee94SGrant Likely }
219dbbdee94SGrant Likely EXPORT_SYMBOL(of_get_pci_address);
220dbbdee94SGrant Likely 
221dbbdee94SGrant Likely int of_pci_address_to_resource(struct device_node *dev, int bar,
222dbbdee94SGrant Likely 			       struct resource *r)
223dbbdee94SGrant Likely {
2240131d897SSebastian Andrzej Siewior 	const __be32	*addrp;
225dbbdee94SGrant Likely 	u64		size;
226dbbdee94SGrant Likely 	unsigned int	flags;
227dbbdee94SGrant Likely 
228dbbdee94SGrant Likely 	addrp = of_get_pci_address(dev, bar, &size, &flags);
229dbbdee94SGrant Likely 	if (addrp == NULL)
230dbbdee94SGrant Likely 		return -EINVAL;
23135f3da32SBenoit Cousson 	return __of_address_to_resource(dev, addrp, size, flags, NULL, r);
232dbbdee94SGrant Likely }
233dbbdee94SGrant Likely EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
23429b635c0SAndrew Murray 
235a060c210SMarc Gonzalez static int parser_init(struct of_pci_range_parser *parser,
236a060c210SMarc Gonzalez 			struct device_node *node, const char *name)
23729b635c0SAndrew Murray {
23829b635c0SAndrew Murray 	const int na = 3, ns = 2;
23929b635c0SAndrew Murray 	int rlen;
24029b635c0SAndrew Murray 
24129b635c0SAndrew Murray 	parser->node = node;
24229b635c0SAndrew Murray 	parser->pna = of_n_addr_cells(node);
24329b635c0SAndrew Murray 	parser->np = parser->pna + na + ns;
24429b635c0SAndrew Murray 
245a060c210SMarc Gonzalez 	parser->range = of_get_property(node, name, &rlen);
24629b635c0SAndrew Murray 	if (parser->range == NULL)
24729b635c0SAndrew Murray 		return -ENOENT;
24829b635c0SAndrew Murray 
24929b635c0SAndrew Murray 	parser->end = parser->range + rlen / sizeof(__be32);
25029b635c0SAndrew Murray 
25129b635c0SAndrew Murray 	return 0;
25229b635c0SAndrew Murray }
253a060c210SMarc Gonzalez 
254a060c210SMarc Gonzalez int of_pci_range_parser_init(struct of_pci_range_parser *parser,
255a060c210SMarc Gonzalez 				struct device_node *node)
256a060c210SMarc Gonzalez {
257a060c210SMarc Gonzalez 	return parser_init(parser, node, "ranges");
258a060c210SMarc Gonzalez }
25929b635c0SAndrew Murray EXPORT_SYMBOL_GPL(of_pci_range_parser_init);
26029b635c0SAndrew Murray 
261a060c210SMarc Gonzalez int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser,
262a060c210SMarc Gonzalez 				struct device_node *node)
263a060c210SMarc Gonzalez {
264a060c210SMarc Gonzalez 	return parser_init(parser, node, "dma-ranges");
265a060c210SMarc Gonzalez }
266a060c210SMarc Gonzalez EXPORT_SYMBOL_GPL(of_pci_dma_range_parser_init);
267a060c210SMarc Gonzalez 
26829b635c0SAndrew Murray struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
26929b635c0SAndrew Murray 						struct of_pci_range *range)
27029b635c0SAndrew Murray {
27129b635c0SAndrew Murray 	const int na = 3, ns = 2;
27229b635c0SAndrew Murray 
27329b635c0SAndrew Murray 	if (!range)
27429b635c0SAndrew Murray 		return NULL;
27529b635c0SAndrew Murray 
27629b635c0SAndrew Murray 	if (!parser->range || parser->range + parser->np > parser->end)
27729b635c0SAndrew Murray 		return NULL;
27829b635c0SAndrew Murray 
279eb310036SRob Herring 	range->pci_space = be32_to_cpup(parser->range);
28029b635c0SAndrew Murray 	range->flags = of_bus_pci_get_flags(parser->range);
28129b635c0SAndrew Murray 	range->pci_addr = of_read_number(parser->range + 1, ns);
28229b635c0SAndrew Murray 	range->cpu_addr = of_translate_address(parser->node,
28329b635c0SAndrew Murray 				parser->range + na);
28429b635c0SAndrew Murray 	range->size = of_read_number(parser->range + parser->pna + na, ns);
28529b635c0SAndrew Murray 
28629b635c0SAndrew Murray 	parser->range += parser->np;
28729b635c0SAndrew Murray 
28829b635c0SAndrew Murray 	/* Now consume following elements while they are contiguous */
28929b635c0SAndrew Murray 	while (parser->range + parser->np <= parser->end) {
290fda9f5d4SShawn Lin 		u32 flags;
29129b635c0SAndrew Murray 		u64 pci_addr, cpu_addr, size;
29229b635c0SAndrew Murray 
29329b635c0SAndrew Murray 		flags = of_bus_pci_get_flags(parser->range);
29429b635c0SAndrew Murray 		pci_addr = of_read_number(parser->range + 1, ns);
29529b635c0SAndrew Murray 		cpu_addr = of_translate_address(parser->node,
29629b635c0SAndrew Murray 				parser->range + na);
29729b635c0SAndrew Murray 		size = of_read_number(parser->range + parser->pna + na, ns);
29829b635c0SAndrew Murray 
29929b635c0SAndrew Murray 		if (flags != range->flags)
30029b635c0SAndrew Murray 			break;
30129b635c0SAndrew Murray 		if (pci_addr != range->pci_addr + range->size ||
30229b635c0SAndrew Murray 		    cpu_addr != range->cpu_addr + range->size)
30329b635c0SAndrew Murray 			break;
30429b635c0SAndrew Murray 
30529b635c0SAndrew Murray 		range->size += size;
30629b635c0SAndrew Murray 		parser->range += parser->np;
30729b635c0SAndrew Murray 	}
30829b635c0SAndrew Murray 
30929b635c0SAndrew Murray 	return range;
31029b635c0SAndrew Murray }
31129b635c0SAndrew Murray EXPORT_SYMBOL_GPL(of_pci_range_parser_one);
31229b635c0SAndrew Murray 
3130b0b0893SLiviu Dudau /*
3140b0b0893SLiviu Dudau  * of_pci_range_to_resource - Create a resource from an of_pci_range
3150b0b0893SLiviu Dudau  * @range:	the PCI range that describes the resource
3160b0b0893SLiviu Dudau  * @np:		device node where the range belongs to
3170b0b0893SLiviu Dudau  * @res:	pointer to a valid resource that will be updated to
3180b0b0893SLiviu Dudau  *              reflect the values contained in the range.
3190b0b0893SLiviu Dudau  *
3200b0b0893SLiviu Dudau  * Returns EINVAL if the range cannot be converted to resource.
3210b0b0893SLiviu Dudau  *
3220b0b0893SLiviu Dudau  * Note that if the range is an IO range, the resource will be converted
3230b0b0893SLiviu Dudau  * using pci_address_to_pio() which can fail if it is called too early or
3240b0b0893SLiviu Dudau  * if the range cannot be matched to any host bridge IO space (our case here).
3250b0b0893SLiviu Dudau  * To guard against that we try to register the IO range first.
3260b0b0893SLiviu Dudau  * If that fails we know that pci_address_to_pio() will do too.
3270b0b0893SLiviu Dudau  */
3280b0b0893SLiviu Dudau int of_pci_range_to_resource(struct of_pci_range *range,
32983bbde1cSLiviu Dudau 			     struct device_node *np, struct resource *res)
33083bbde1cSLiviu Dudau {
3310b0b0893SLiviu Dudau 	int err;
33283bbde1cSLiviu Dudau 	res->flags = range->flags;
33383bbde1cSLiviu Dudau 	res->parent = res->child = res->sibling = NULL;
33483bbde1cSLiviu Dudau 	res->name = np->full_name;
3350b0b0893SLiviu Dudau 
3360b0b0893SLiviu Dudau 	if (res->flags & IORESOURCE_IO) {
3370b0b0893SLiviu Dudau 		unsigned long port;
338fcfaab30SGabriele Paoloni 		err = pci_register_io_range(&np->fwnode, range->cpu_addr,
339fcfaab30SGabriele Paoloni 				range->size);
3400b0b0893SLiviu Dudau 		if (err)
3410b0b0893SLiviu Dudau 			goto invalid_range;
3420b0b0893SLiviu Dudau 		port = pci_address_to_pio(range->cpu_addr);
3430b0b0893SLiviu Dudau 		if (port == (unsigned long)-1) {
3440b0b0893SLiviu Dudau 			err = -EINVAL;
3450b0b0893SLiviu Dudau 			goto invalid_range;
3460b0b0893SLiviu Dudau 		}
3470b0b0893SLiviu Dudau 		res->start = port;
3480b0b0893SLiviu Dudau 	} else {
3494af97106SPavel Fedin 		if ((sizeof(resource_size_t) < 8) &&
3504af97106SPavel Fedin 		    upper_32_bits(range->cpu_addr)) {
3514af97106SPavel Fedin 			err = -EINVAL;
3524af97106SPavel Fedin 			goto invalid_range;
3534af97106SPavel Fedin 		}
3544af97106SPavel Fedin 
3550b0b0893SLiviu Dudau 		res->start = range->cpu_addr;
3560b0b0893SLiviu Dudau 	}
3570b0b0893SLiviu Dudau 	res->end = res->start + range->size - 1;
3580b0b0893SLiviu Dudau 	return 0;
3590b0b0893SLiviu Dudau 
3600b0b0893SLiviu Dudau invalid_range:
3610b0b0893SLiviu Dudau 	res->start = (resource_size_t)OF_BAD_ADDR;
3620b0b0893SLiviu Dudau 	res->end = (resource_size_t)OF_BAD_ADDR;
3630b0b0893SLiviu Dudau 	return err;
36483bbde1cSLiviu Dudau }
365bf6681eaSManikanta Maddireddy EXPORT_SYMBOL(of_pci_range_to_resource);
366dbbdee94SGrant Likely #endif /* CONFIG_PCI */
367dbbdee94SGrant Likely 
368dbbdee94SGrant Likely /*
369dbbdee94SGrant Likely  * ISA bus specific translator
370dbbdee94SGrant Likely  */
371dbbdee94SGrant Likely 
372dbbdee94SGrant Likely static int of_bus_isa_match(struct device_node *np)
373dbbdee94SGrant Likely {
374b3e46d1aSRob Herring 	return of_node_name_eq(np, "isa");
375dbbdee94SGrant Likely }
376dbbdee94SGrant Likely 
377dbbdee94SGrant Likely static void of_bus_isa_count_cells(struct device_node *child,
378dbbdee94SGrant Likely 				   int *addrc, int *sizec)
379dbbdee94SGrant Likely {
380dbbdee94SGrant Likely 	if (addrc)
381dbbdee94SGrant Likely 		*addrc = 2;
382dbbdee94SGrant Likely 	if (sizec)
383dbbdee94SGrant Likely 		*sizec = 1;
384dbbdee94SGrant Likely }
385dbbdee94SGrant Likely 
38647b1e689SKim Phillips static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns,
3870131d897SSebastian Andrzej Siewior 		int pna)
388dbbdee94SGrant Likely {
389dbbdee94SGrant Likely 	u64 cp, s, da;
390dbbdee94SGrant Likely 
391dbbdee94SGrant Likely 	/* Check address type match */
3920131d897SSebastian Andrzej Siewior 	if ((addr[0] ^ range[0]) & cpu_to_be32(1))
393dbbdee94SGrant Likely 		return OF_BAD_ADDR;
394dbbdee94SGrant Likely 
395dbbdee94SGrant Likely 	/* Read address values, skipping high cell */
396dbbdee94SGrant Likely 	cp = of_read_number(range + 1, na - 1);
397dbbdee94SGrant Likely 	s  = of_read_number(range + na + pna, ns);
398dbbdee94SGrant Likely 	da = of_read_number(addr + 1, na - 1);
399dbbdee94SGrant Likely 
400606ad42aSRob Herring 	pr_debug("ISA map, cp=%llx, s=%llx, da=%llx\n",
401dbbdee94SGrant Likely 		 (unsigned long long)cp, (unsigned long long)s,
402dbbdee94SGrant Likely 		 (unsigned long long)da);
403dbbdee94SGrant Likely 
404dbbdee94SGrant Likely 	if (da < cp || da >= (cp + s))
405dbbdee94SGrant Likely 		return OF_BAD_ADDR;
406dbbdee94SGrant Likely 	return da - cp;
407dbbdee94SGrant Likely }
408dbbdee94SGrant Likely 
40947b1e689SKim Phillips static int of_bus_isa_translate(__be32 *addr, u64 offset, int na)
410dbbdee94SGrant Likely {
411dbbdee94SGrant Likely 	return of_bus_default_translate(addr + 1, offset, na - 1);
412dbbdee94SGrant Likely }
413dbbdee94SGrant Likely 
4140131d897SSebastian Andrzej Siewior static unsigned int of_bus_isa_get_flags(const __be32 *addr)
415dbbdee94SGrant Likely {
416dbbdee94SGrant Likely 	unsigned int flags = 0;
4170131d897SSebastian Andrzej Siewior 	u32 w = be32_to_cpup(addr);
418dbbdee94SGrant Likely 
419dbbdee94SGrant Likely 	if (w & 1)
420dbbdee94SGrant Likely 		flags |= IORESOURCE_IO;
421dbbdee94SGrant Likely 	else
422dbbdee94SGrant Likely 		flags |= IORESOURCE_MEM;
423dbbdee94SGrant Likely 	return flags;
424dbbdee94SGrant Likely }
425dbbdee94SGrant Likely 
426dbbdee94SGrant Likely /*
427dbbdee94SGrant Likely  * Array of bus specific translators
428dbbdee94SGrant Likely  */
429dbbdee94SGrant Likely 
430dbbdee94SGrant Likely static struct of_bus of_busses[] = {
4314670d610SRob Herring #ifdef CONFIG_PCI
432dbbdee94SGrant Likely 	/* PCI */
433dbbdee94SGrant Likely 	{
434dbbdee94SGrant Likely 		.name = "pci",
435dbbdee94SGrant Likely 		.addresses = "assigned-addresses",
436dbbdee94SGrant Likely 		.match = of_bus_pci_match,
437dbbdee94SGrant Likely 		.count_cells = of_bus_pci_count_cells,
438dbbdee94SGrant Likely 		.map = of_bus_pci_map,
439dbbdee94SGrant Likely 		.translate = of_bus_pci_translate,
440dbbdee94SGrant Likely 		.get_flags = of_bus_pci_get_flags,
441dbbdee94SGrant Likely 	},
4424670d610SRob Herring #endif /* CONFIG_PCI */
443dbbdee94SGrant Likely 	/* ISA */
444dbbdee94SGrant Likely 	{
445dbbdee94SGrant Likely 		.name = "isa",
446dbbdee94SGrant Likely 		.addresses = "reg",
447dbbdee94SGrant Likely 		.match = of_bus_isa_match,
448dbbdee94SGrant Likely 		.count_cells = of_bus_isa_count_cells,
449dbbdee94SGrant Likely 		.map = of_bus_isa_map,
450dbbdee94SGrant Likely 		.translate = of_bus_isa_translate,
451dbbdee94SGrant Likely 		.get_flags = of_bus_isa_get_flags,
452dbbdee94SGrant Likely 	},
453dbbdee94SGrant Likely 	/* Default */
454dbbdee94SGrant Likely 	{
455dbbdee94SGrant Likely 		.name = "default",
456dbbdee94SGrant Likely 		.addresses = "reg",
457dbbdee94SGrant Likely 		.match = NULL,
458dbbdee94SGrant Likely 		.count_cells = of_bus_default_count_cells,
459dbbdee94SGrant Likely 		.map = of_bus_default_map,
460dbbdee94SGrant Likely 		.translate = of_bus_default_translate,
461dbbdee94SGrant Likely 		.get_flags = of_bus_default_get_flags,
462dbbdee94SGrant Likely 	},
463dbbdee94SGrant Likely };
464dbbdee94SGrant Likely 
465dbbdee94SGrant Likely static struct of_bus *of_match_bus(struct device_node *np)
466dbbdee94SGrant Likely {
467dbbdee94SGrant Likely 	int i;
468dbbdee94SGrant Likely 
469dbbdee94SGrant Likely 	for (i = 0; i < ARRAY_SIZE(of_busses); i++)
470dbbdee94SGrant Likely 		if (!of_busses[i].match || of_busses[i].match(np))
471dbbdee94SGrant Likely 			return &of_busses[i];
472dbbdee94SGrant Likely 	BUG();
473dbbdee94SGrant Likely 	return NULL;
474dbbdee94SGrant Likely }
475dbbdee94SGrant Likely 
47641d94893SBenjamin Herrenschmidt static int of_empty_ranges_quirk(struct device_node *np)
477746c9e9fSBenjamin Herrenschmidt {
478746c9e9fSBenjamin Herrenschmidt 	if (IS_ENABLED(CONFIG_PPC)) {
47941d94893SBenjamin Herrenschmidt 		/* To save cycles, we cache the result for global "Mac" setting */
480746c9e9fSBenjamin Herrenschmidt 		static int quirk_state = -1;
481746c9e9fSBenjamin Herrenschmidt 
48241d94893SBenjamin Herrenschmidt 		/* PA-SEMI sdc DT bug */
48341d94893SBenjamin Herrenschmidt 		if (of_device_is_compatible(np, "1682m-sdc"))
48441d94893SBenjamin Herrenschmidt 			return true;
48541d94893SBenjamin Herrenschmidt 
48641d94893SBenjamin Herrenschmidt 		/* Make quirk cached */
487746c9e9fSBenjamin Herrenschmidt 		if (quirk_state < 0)
488746c9e9fSBenjamin Herrenschmidt 			quirk_state =
489746c9e9fSBenjamin Herrenschmidt 				of_machine_is_compatible("Power Macintosh") ||
490746c9e9fSBenjamin Herrenschmidt 				of_machine_is_compatible("MacRISC");
491746c9e9fSBenjamin Herrenschmidt 		return quirk_state;
492746c9e9fSBenjamin Herrenschmidt 	}
493746c9e9fSBenjamin Herrenschmidt 	return false;
494746c9e9fSBenjamin Herrenschmidt }
495746c9e9fSBenjamin Herrenschmidt 
496dbbdee94SGrant Likely static int of_translate_one(struct device_node *parent, struct of_bus *bus,
49747b1e689SKim Phillips 			    struct of_bus *pbus, __be32 *addr,
498dbbdee94SGrant Likely 			    int na, int ns, int pna, const char *rprop)
499dbbdee94SGrant Likely {
5000131d897SSebastian Andrzej Siewior 	const __be32 *ranges;
501dbbdee94SGrant Likely 	unsigned int rlen;
502dbbdee94SGrant Likely 	int rone;
503dbbdee94SGrant Likely 	u64 offset = OF_BAD_ADDR;
504dbbdee94SGrant Likely 
505ba85edbeSMasahiro Yamada 	/*
506ba85edbeSMasahiro Yamada 	 * Normally, an absence of a "ranges" property means we are
507dbbdee94SGrant Likely 	 * crossing a non-translatable boundary, and thus the addresses
508ba85edbeSMasahiro Yamada 	 * below the current cannot be converted to CPU physical ones.
509dbbdee94SGrant Likely 	 * Unfortunately, while this is very clear in the spec, it's not
510dbbdee94SGrant Likely 	 * what Apple understood, and they do have things like /uni-n or
511dbbdee94SGrant Likely 	 * /ht nodes with no "ranges" property and a lot of perfectly
512dbbdee94SGrant Likely 	 * useable mapped devices below them. Thus we treat the absence of
513dbbdee94SGrant Likely 	 * "ranges" as equivalent to an empty "ranges" property which means
514dbbdee94SGrant Likely 	 * a 1:1 translation at that level. It's up to the caller not to try
515dbbdee94SGrant Likely 	 * to translate addresses that aren't supposed to be translated in
516dbbdee94SGrant Likely 	 * the first place. --BenH.
5173930f294SGrant Likely 	 *
5183930f294SGrant Likely 	 * As far as we know, this damage only exists on Apple machines, so
5193930f294SGrant Likely 	 * This code is only enabled on powerpc. --gcl
520dbbdee94SGrant Likely 	 */
521dbbdee94SGrant Likely 	ranges = of_get_property(parent, rprop, &rlen);
52241d94893SBenjamin Herrenschmidt 	if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
523606ad42aSRob Herring 		pr_debug("no ranges; cannot translate\n");
5243930f294SGrant Likely 		return 1;
5253930f294SGrant Likely 	}
526dbbdee94SGrant Likely 	if (ranges == NULL || rlen == 0) {
527dbbdee94SGrant Likely 		offset = of_read_number(addr, na);
528dbbdee94SGrant Likely 		memset(addr, 0, pna * 4);
529606ad42aSRob Herring 		pr_debug("empty ranges; 1:1 translation\n");
530dbbdee94SGrant Likely 		goto finish;
531dbbdee94SGrant Likely 	}
532dbbdee94SGrant Likely 
533606ad42aSRob Herring 	pr_debug("walking ranges...\n");
534dbbdee94SGrant Likely 
535dbbdee94SGrant Likely 	/* Now walk through the ranges */
536dbbdee94SGrant Likely 	rlen /= 4;
537dbbdee94SGrant Likely 	rone = na + pna + ns;
538dbbdee94SGrant Likely 	for (; rlen >= rone; rlen -= rone, ranges += rone) {
539dbbdee94SGrant Likely 		offset = bus->map(addr, ranges, na, ns, pna);
540dbbdee94SGrant Likely 		if (offset != OF_BAD_ADDR)
541dbbdee94SGrant Likely 			break;
542dbbdee94SGrant Likely 	}
543dbbdee94SGrant Likely 	if (offset == OF_BAD_ADDR) {
544606ad42aSRob Herring 		pr_debug("not found !\n");
545dbbdee94SGrant Likely 		return 1;
546dbbdee94SGrant Likely 	}
547dbbdee94SGrant Likely 	memcpy(addr, ranges + na, 4 * pna);
548dbbdee94SGrant Likely 
549dbbdee94SGrant Likely  finish:
550606ad42aSRob Herring 	of_dump_addr("parent translation for:", addr, pna);
551606ad42aSRob Herring 	pr_debug("with offset: %llx\n", (unsigned long long)offset);
552dbbdee94SGrant Likely 
553dbbdee94SGrant Likely 	/* Translate it into parent bus space */
554dbbdee94SGrant Likely 	return pbus->translate(addr, offset, pna);
555dbbdee94SGrant Likely }
556dbbdee94SGrant Likely 
557dbbdee94SGrant Likely /*
558dbbdee94SGrant Likely  * Translate an address from the device-tree into a CPU physical address,
559dbbdee94SGrant Likely  * this walks up the tree and applies the various bus mappings on the
560dbbdee94SGrant Likely  * way.
561dbbdee94SGrant Likely  *
562dbbdee94SGrant Likely  * Note: We consider that crossing any level with #size-cells == 0 to mean
563dbbdee94SGrant Likely  * that translation is impossible (that is we are not dealing with a value
564dbbdee94SGrant Likely  * that can be mapped to a cpu physical address). This is not really specified
565dbbdee94SGrant Likely  * that way, but this is traditionally the way IBM at least do things
56665af618dSZhichang Yuan  *
56765af618dSZhichang Yuan  * Whenever the translation fails, the *host pointer will be set to the
56865af618dSZhichang Yuan  * device that had registered logical PIO mapping, and the return code is
56965af618dSZhichang Yuan  * relative to that node.
570dbbdee94SGrant Likely  */
57147b1e689SKim Phillips static u64 __of_translate_address(struct device_node *dev,
57265af618dSZhichang Yuan 				  const __be32 *in_addr, const char *rprop,
57365af618dSZhichang Yuan 				  struct device_node **host)
574dbbdee94SGrant Likely {
575dbbdee94SGrant Likely 	struct device_node *parent = NULL;
576dbbdee94SGrant Likely 	struct of_bus *bus, *pbus;
57747b1e689SKim Phillips 	__be32 addr[OF_MAX_ADDR_CELLS];
578dbbdee94SGrant Likely 	int na, ns, pna, pns;
579dbbdee94SGrant Likely 	u64 result = OF_BAD_ADDR;
580dbbdee94SGrant Likely 
5810d638a07SRob Herring 	pr_debug("** translation for device %pOF **\n", dev);
582dbbdee94SGrant Likely 
583dbbdee94SGrant Likely 	/* Increase refcount at current level */
584dbbdee94SGrant Likely 	of_node_get(dev);
585dbbdee94SGrant Likely 
58665af618dSZhichang Yuan 	*host = NULL;
587dbbdee94SGrant Likely 	/* Get parent & match bus type */
588dbbdee94SGrant Likely 	parent = of_get_parent(dev);
589dbbdee94SGrant Likely 	if (parent == NULL)
590dbbdee94SGrant Likely 		goto bail;
591dbbdee94SGrant Likely 	bus = of_match_bus(parent);
592dbbdee94SGrant Likely 
59359f5ca48SAndrew Murray 	/* Count address cells & copy address locally */
594dbbdee94SGrant Likely 	bus->count_cells(dev, &na, &ns);
595dbbdee94SGrant Likely 	if (!OF_CHECK_COUNTS(na, ns)) {
5960d638a07SRob Herring 		pr_debug("Bad cell count for %pOF\n", dev);
597dbbdee94SGrant Likely 		goto bail;
598dbbdee94SGrant Likely 	}
599dbbdee94SGrant Likely 	memcpy(addr, in_addr, na * 4);
600dbbdee94SGrant Likely 
6010d638a07SRob Herring 	pr_debug("bus is %s (na=%d, ns=%d) on %pOF\n",
6020d638a07SRob Herring 	    bus->name, na, ns, parent);
603606ad42aSRob Herring 	of_dump_addr("translating address:", addr, na);
604dbbdee94SGrant Likely 
605dbbdee94SGrant Likely 	/* Translate */
606dbbdee94SGrant Likely 	for (;;) {
60765af618dSZhichang Yuan 		struct logic_pio_hwaddr *iorange;
60865af618dSZhichang Yuan 
609dbbdee94SGrant Likely 		/* Switch to parent bus */
610dbbdee94SGrant Likely 		of_node_put(dev);
611dbbdee94SGrant Likely 		dev = parent;
612dbbdee94SGrant Likely 		parent = of_get_parent(dev);
613dbbdee94SGrant Likely 
614dbbdee94SGrant Likely 		/* If root, we have finished */
615dbbdee94SGrant Likely 		if (parent == NULL) {
616606ad42aSRob Herring 			pr_debug("reached root node\n");
617dbbdee94SGrant Likely 			result = of_read_number(addr, na);
618dbbdee94SGrant Likely 			break;
619dbbdee94SGrant Likely 		}
620dbbdee94SGrant Likely 
62165af618dSZhichang Yuan 		/*
62265af618dSZhichang Yuan 		 * For indirectIO device which has no ranges property, get
62365af618dSZhichang Yuan 		 * the address from reg directly.
62465af618dSZhichang Yuan 		 */
62565af618dSZhichang Yuan 		iorange = find_io_range_by_fwnode(&dev->fwnode);
62665af618dSZhichang Yuan 		if (iorange && (iorange->flags != LOGIC_PIO_CPU_MMIO)) {
62765af618dSZhichang Yuan 			result = of_read_number(addr + 1, na - 1);
62865af618dSZhichang Yuan 			pr_debug("indirectIO matched(%pOF) 0x%llx\n",
62965af618dSZhichang Yuan 				 dev, result);
63065af618dSZhichang Yuan 			*host = of_node_get(dev);
63165af618dSZhichang Yuan 			break;
63265af618dSZhichang Yuan 		}
63365af618dSZhichang Yuan 
634dbbdee94SGrant Likely 		/* Get new parent bus and counts */
635dbbdee94SGrant Likely 		pbus = of_match_bus(parent);
636dbbdee94SGrant Likely 		pbus->count_cells(dev, &pna, &pns);
637dbbdee94SGrant Likely 		if (!OF_CHECK_COUNTS(pna, pns)) {
6380d638a07SRob Herring 			pr_err("Bad cell count for %pOF\n", dev);
639dbbdee94SGrant Likely 			break;
640dbbdee94SGrant Likely 		}
641dbbdee94SGrant Likely 
6420d638a07SRob Herring 		pr_debug("parent bus is %s (na=%d, ns=%d) on %pOF\n",
6430d638a07SRob Herring 		    pbus->name, pna, pns, parent);
644dbbdee94SGrant Likely 
645dbbdee94SGrant Likely 		/* Apply bus translation */
646dbbdee94SGrant Likely 		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
647dbbdee94SGrant Likely 			break;
648dbbdee94SGrant Likely 
649dbbdee94SGrant Likely 		/* Complete the move up one level */
650dbbdee94SGrant Likely 		na = pna;
651dbbdee94SGrant Likely 		ns = pns;
652dbbdee94SGrant Likely 		bus = pbus;
653dbbdee94SGrant Likely 
654606ad42aSRob Herring 		of_dump_addr("one level translation:", addr, na);
655dbbdee94SGrant Likely 	}
656dbbdee94SGrant Likely  bail:
657dbbdee94SGrant Likely 	of_node_put(parent);
658dbbdee94SGrant Likely 	of_node_put(dev);
659dbbdee94SGrant Likely 
660dbbdee94SGrant Likely 	return result;
661dbbdee94SGrant Likely }
662dbbdee94SGrant Likely 
6630131d897SSebastian Andrzej Siewior u64 of_translate_address(struct device_node *dev, const __be32 *in_addr)
664dbbdee94SGrant Likely {
66565af618dSZhichang Yuan 	struct device_node *host;
66665af618dSZhichang Yuan 	u64 ret;
66765af618dSZhichang Yuan 
66865af618dSZhichang Yuan 	ret = __of_translate_address(dev, in_addr, "ranges", &host);
66965af618dSZhichang Yuan 	if (host) {
67065af618dSZhichang Yuan 		of_node_put(host);
67165af618dSZhichang Yuan 		return OF_BAD_ADDR;
67265af618dSZhichang Yuan 	}
67365af618dSZhichang Yuan 
67465af618dSZhichang Yuan 	return ret;
675dbbdee94SGrant Likely }
676dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_address);
677dbbdee94SGrant Likely 
6780131d897SSebastian Andrzej Siewior u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
679dbbdee94SGrant Likely {
68065af618dSZhichang Yuan 	struct device_node *host;
68165af618dSZhichang Yuan 	u64 ret;
68265af618dSZhichang Yuan 
68365af618dSZhichang Yuan 	ret = __of_translate_address(dev, in_addr, "dma-ranges", &host);
68465af618dSZhichang Yuan 
68565af618dSZhichang Yuan 	if (host) {
68665af618dSZhichang Yuan 		of_node_put(host);
68765af618dSZhichang Yuan 		return OF_BAD_ADDR;
68865af618dSZhichang Yuan 	}
68965af618dSZhichang Yuan 
69065af618dSZhichang Yuan 	return ret;
691dbbdee94SGrant Likely }
692dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_dma_address);
693dbbdee94SGrant Likely 
6940131d897SSebastian Andrzej Siewior const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
695dbbdee94SGrant Likely 		    unsigned int *flags)
696dbbdee94SGrant Likely {
6970131d897SSebastian Andrzej Siewior 	const __be32 *prop;
698dbbdee94SGrant Likely 	unsigned int psize;
699dbbdee94SGrant Likely 	struct device_node *parent;
700dbbdee94SGrant Likely 	struct of_bus *bus;
701dbbdee94SGrant Likely 	int onesize, i, na, ns;
702dbbdee94SGrant Likely 
703dbbdee94SGrant Likely 	/* Get parent & match bus type */
704dbbdee94SGrant Likely 	parent = of_get_parent(dev);
705dbbdee94SGrant Likely 	if (parent == NULL)
706dbbdee94SGrant Likely 		return NULL;
707dbbdee94SGrant Likely 	bus = of_match_bus(parent);
708dbbdee94SGrant Likely 	bus->count_cells(dev, &na, &ns);
709dbbdee94SGrant Likely 	of_node_put(parent);
7105d61b165SStephen Warren 	if (!OF_CHECK_ADDR_COUNT(na))
711dbbdee94SGrant Likely 		return NULL;
712dbbdee94SGrant Likely 
713dbbdee94SGrant Likely 	/* Get "reg" or "assigned-addresses" property */
714dbbdee94SGrant Likely 	prop = of_get_property(dev, bus->addresses, &psize);
715dbbdee94SGrant Likely 	if (prop == NULL)
716dbbdee94SGrant Likely 		return NULL;
717dbbdee94SGrant Likely 	psize /= 4;
718dbbdee94SGrant Likely 
719dbbdee94SGrant Likely 	onesize = na + ns;
720dbbdee94SGrant Likely 	for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
721dbbdee94SGrant Likely 		if (i == index) {
722dbbdee94SGrant Likely 			if (size)
723dbbdee94SGrant Likely 				*size = of_read_number(prop + na, ns);
724dbbdee94SGrant Likely 			if (flags)
725dbbdee94SGrant Likely 				*flags = bus->get_flags(prop);
726dbbdee94SGrant Likely 			return prop;
727dbbdee94SGrant Likely 		}
728dbbdee94SGrant Likely 	return NULL;
729dbbdee94SGrant Likely }
730dbbdee94SGrant Likely EXPORT_SYMBOL(of_get_address);
731dbbdee94SGrant Likely 
73265af618dSZhichang Yuan static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr,
73365af618dSZhichang Yuan 			u64 size)
73465af618dSZhichang Yuan {
73565af618dSZhichang Yuan 	u64 taddr;
73665af618dSZhichang Yuan 	unsigned long port;
73765af618dSZhichang Yuan 	struct device_node *host;
73865af618dSZhichang Yuan 
73965af618dSZhichang Yuan 	taddr = __of_translate_address(dev, in_addr, "ranges", &host);
74065af618dSZhichang Yuan 	if (host) {
74165af618dSZhichang Yuan 		/* host-specific port access */
74265af618dSZhichang Yuan 		port = logic_pio_trans_hwaddr(&host->fwnode, taddr, size);
74365af618dSZhichang Yuan 		of_node_put(host);
74465af618dSZhichang Yuan 	} else {
74565af618dSZhichang Yuan 		/* memory-mapped I/O range */
74665af618dSZhichang Yuan 		port = pci_address_to_pio(taddr);
74765af618dSZhichang Yuan 	}
74865af618dSZhichang Yuan 
74965af618dSZhichang Yuan 	if (port == (unsigned long)-1)
75065af618dSZhichang Yuan 		return OF_BAD_ADDR;
75165af618dSZhichang Yuan 
75265af618dSZhichang Yuan 	return port;
75365af618dSZhichang Yuan }
75465af618dSZhichang Yuan 
7550131d897SSebastian Andrzej Siewior static int __of_address_to_resource(struct device_node *dev,
7560131d897SSebastian Andrzej Siewior 		const __be32 *addrp, u64 size, unsigned int flags,
75735f3da32SBenoit Cousson 		const char *name, struct resource *r)
7581f5bef30SGrant Likely {
7591f5bef30SGrant Likely 	u64 taddr;
7601f5bef30SGrant Likely 
76165af618dSZhichang Yuan 	if (flags & IORESOURCE_MEM)
7621f5bef30SGrant Likely 		taddr = of_translate_address(dev, addrp);
76365af618dSZhichang Yuan 	else if (flags & IORESOURCE_IO)
76465af618dSZhichang Yuan 		taddr = of_translate_ioport(dev, addrp, size);
76565af618dSZhichang Yuan 	else
76665af618dSZhichang Yuan 		return -EINVAL;
76765af618dSZhichang Yuan 
7681f5bef30SGrant Likely 	if (taddr == OF_BAD_ADDR)
7691f5bef30SGrant Likely 		return -EINVAL;
7701f5bef30SGrant Likely 	memset(r, 0, sizeof(struct resource));
77165af618dSZhichang Yuan 
7721f5bef30SGrant Likely 	r->start = taddr;
7731f5bef30SGrant Likely 	r->end = taddr + size - 1;
7741f5bef30SGrant Likely 	r->flags = flags;
77535f3da32SBenoit Cousson 	r->name = name ? name : dev->full_name;
77635f3da32SBenoit Cousson 
7771f5bef30SGrant Likely 	return 0;
7781f5bef30SGrant Likely }
7791f5bef30SGrant Likely 
7801f5bef30SGrant Likely /**
7811f5bef30SGrant Likely  * of_address_to_resource - Translate device tree address and return as resource
7821f5bef30SGrant Likely  *
7831f5bef30SGrant Likely  * Note that if your address is a PIO address, the conversion will fail if
7841f5bef30SGrant Likely  * the physical address can't be internally converted to an IO token with
7857602f422SFrank Rowand  * pci_address_to_pio(), that is because it's either called too early or it
7861f5bef30SGrant Likely  * can't be matched to any host bridge IO space
7871f5bef30SGrant Likely  */
7881f5bef30SGrant Likely int of_address_to_resource(struct device_node *dev, int index,
7891f5bef30SGrant Likely 			   struct resource *r)
7901f5bef30SGrant Likely {
7910131d897SSebastian Andrzej Siewior 	const __be32	*addrp;
7921f5bef30SGrant Likely 	u64		size;
7931f5bef30SGrant Likely 	unsigned int	flags;
79435f3da32SBenoit Cousson 	const char	*name = NULL;
7951f5bef30SGrant Likely 
7961f5bef30SGrant Likely 	addrp = of_get_address(dev, index, &size, &flags);
7971f5bef30SGrant Likely 	if (addrp == NULL)
7981f5bef30SGrant Likely 		return -EINVAL;
79935f3da32SBenoit Cousson 
80035f3da32SBenoit Cousson 	/* Get optional "reg-names" property to add a name to a resource */
80135f3da32SBenoit Cousson 	of_property_read_string_index(dev, "reg-names",	index, &name);
80235f3da32SBenoit Cousson 
80335f3da32SBenoit Cousson 	return __of_address_to_resource(dev, addrp, size, flags, name, r);
8041f5bef30SGrant Likely }
8051f5bef30SGrant Likely EXPORT_SYMBOL_GPL(of_address_to_resource);
8061f5bef30SGrant Likely 
80790e33f62SGrant Likely struct device_node *of_find_matching_node_by_address(struct device_node *from,
80890e33f62SGrant Likely 					const struct of_device_id *matches,
80990e33f62SGrant Likely 					u64 base_address)
81090e33f62SGrant Likely {
81190e33f62SGrant Likely 	struct device_node *dn = of_find_matching_node(from, matches);
81290e33f62SGrant Likely 	struct resource res;
81390e33f62SGrant Likely 
81490e33f62SGrant Likely 	while (dn) {
8153a496b00SDavid Daney 		if (!of_address_to_resource(dn, 0, &res) &&
8163a496b00SDavid Daney 		    res.start == base_address)
81790e33f62SGrant Likely 			return dn;
8183a496b00SDavid Daney 
81990e33f62SGrant Likely 		dn = of_find_matching_node(dn, matches);
82090e33f62SGrant Likely 	}
82190e33f62SGrant Likely 
82290e33f62SGrant Likely 	return NULL;
82390e33f62SGrant Likely }
82490e33f62SGrant Likely 
8251f5bef30SGrant Likely 
8266b884a8dSGrant Likely /**
8276b884a8dSGrant Likely  * of_iomap - Maps the memory mapped IO for a given device_node
8286b884a8dSGrant Likely  * @device:	the device whose io range will be mapped
8296b884a8dSGrant Likely  * @index:	index of the io range
8306b884a8dSGrant Likely  *
8316b884a8dSGrant Likely  * Returns a pointer to the mapped memory
8326b884a8dSGrant Likely  */
8336b884a8dSGrant Likely void __iomem *of_iomap(struct device_node *np, int index)
8346b884a8dSGrant Likely {
8356b884a8dSGrant Likely 	struct resource res;
8366b884a8dSGrant Likely 
8376b884a8dSGrant Likely 	if (of_address_to_resource(np, index, &res))
8386b884a8dSGrant Likely 		return NULL;
8396b884a8dSGrant Likely 
84028c1b6d6SFelipe Balbi 	return ioremap(res.start, resource_size(&res));
8416b884a8dSGrant Likely }
8426b884a8dSGrant Likely EXPORT_SYMBOL(of_iomap);
84318308c94SGrygorii Strashko 
844efd342fbSMatthias Brugger /*
845efd342fbSMatthias Brugger  * of_io_request_and_map - Requests a resource and maps the memory mapped IO
846efd342fbSMatthias Brugger  *			   for a given device_node
847efd342fbSMatthias Brugger  * @device:	the device whose io range will be mapped
848efd342fbSMatthias Brugger  * @index:	index of the io range
849b01dcdd8SBenjamin Herrenschmidt  * @name:	name "override" for the memory region request or NULL
850efd342fbSMatthias Brugger  *
851efd342fbSMatthias Brugger  * Returns a pointer to the requested and mapped memory or an ERR_PTR() encoded
852efd342fbSMatthias Brugger  * error code on failure. Usage example:
853efd342fbSMatthias Brugger  *
854efd342fbSMatthias Brugger  *	base = of_io_request_and_map(node, 0, "foo");
855efd342fbSMatthias Brugger  *	if (IS_ERR(base))
856efd342fbSMatthias Brugger  *		return PTR_ERR(base);
857efd342fbSMatthias Brugger  */
858efd342fbSMatthias Brugger void __iomem *of_io_request_and_map(struct device_node *np, int index,
859b75b276bSMatthias Brugger 				    const char *name)
860efd342fbSMatthias Brugger {
861efd342fbSMatthias Brugger 	struct resource res;
862efd342fbSMatthias Brugger 	void __iomem *mem;
863efd342fbSMatthias Brugger 
864efd342fbSMatthias Brugger 	if (of_address_to_resource(np, index, &res))
865efd342fbSMatthias Brugger 		return IOMEM_ERR_PTR(-EINVAL);
866efd342fbSMatthias Brugger 
867b01dcdd8SBenjamin Herrenschmidt 	if (!name)
868b01dcdd8SBenjamin Herrenschmidt 		name = res.name;
869efd342fbSMatthias Brugger 	if (!request_mem_region(res.start, resource_size(&res), name))
870efd342fbSMatthias Brugger 		return IOMEM_ERR_PTR(-EBUSY);
871efd342fbSMatthias Brugger 
872efd342fbSMatthias Brugger 	mem = ioremap(res.start, resource_size(&res));
873efd342fbSMatthias Brugger 	if (!mem) {
874efd342fbSMatthias Brugger 		release_mem_region(res.start, resource_size(&res));
875efd342fbSMatthias Brugger 		return IOMEM_ERR_PTR(-ENOMEM);
876efd342fbSMatthias Brugger 	}
877efd342fbSMatthias Brugger 
878efd342fbSMatthias Brugger 	return mem;
879efd342fbSMatthias Brugger }
880efd342fbSMatthias Brugger EXPORT_SYMBOL(of_io_request_and_map);
881efd342fbSMatthias Brugger 
88218308c94SGrygorii Strashko /**
88318308c94SGrygorii Strashko  * of_dma_get_range - Get DMA range info
88418308c94SGrygorii Strashko  * @np:		device node to get DMA range info
88518308c94SGrygorii Strashko  * @dma_addr:	pointer to store initial DMA address of DMA range
88618308c94SGrygorii Strashko  * @paddr:	pointer to store initial CPU address of DMA range
88718308c94SGrygorii Strashko  * @size:	pointer to store size of DMA range
88818308c94SGrygorii Strashko  *
88918308c94SGrygorii Strashko  * Look in bottom up direction for the first "dma-ranges" property
89018308c94SGrygorii Strashko  * and parse it.
89118308c94SGrygorii Strashko  *  dma-ranges format:
89218308c94SGrygorii Strashko  *	DMA addr (dma_addr)	: naddr cells
89318308c94SGrygorii Strashko  *	CPU addr (phys_addr_t)	: pna cells
89418308c94SGrygorii Strashko  *	size			: nsize cells
89518308c94SGrygorii Strashko  *
89618308c94SGrygorii Strashko  * It returns -ENODEV if "dma-ranges" property was not found
89718308c94SGrygorii Strashko  * for this device in DT.
89818308c94SGrygorii Strashko  */
89918308c94SGrygorii Strashko int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *size)
90018308c94SGrygorii Strashko {
90118308c94SGrygorii Strashko 	struct device_node *node = of_node_get(np);
90218308c94SGrygorii Strashko 	const __be32 *ranges = NULL;
90318308c94SGrygorii Strashko 	int len, naddr, nsize, pna;
90418308c94SGrygorii Strashko 	int ret = 0;
90518308c94SGrygorii Strashko 	u64 dmaaddr;
90618308c94SGrygorii Strashko 
90718308c94SGrygorii Strashko 	if (!node)
90818308c94SGrygorii Strashko 		return -EINVAL;
90918308c94SGrygorii Strashko 
91018308c94SGrygorii Strashko 	while (1) {
91118308c94SGrygorii Strashko 		naddr = of_n_addr_cells(node);
91218308c94SGrygorii Strashko 		nsize = of_n_size_cells(node);
91318308c94SGrygorii Strashko 		node = of_get_next_parent(node);
91418308c94SGrygorii Strashko 		if (!node)
91518308c94SGrygorii Strashko 			break;
91618308c94SGrygorii Strashko 
91718308c94SGrygorii Strashko 		ranges = of_get_property(node, "dma-ranges", &len);
91818308c94SGrygorii Strashko 
91918308c94SGrygorii Strashko 		/* Ignore empty ranges, they imply no translation required */
92018308c94SGrygorii Strashko 		if (ranges && len > 0)
92118308c94SGrygorii Strashko 			break;
92218308c94SGrygorii Strashko 
92318308c94SGrygorii Strashko 		/*
92418308c94SGrygorii Strashko 		 * At least empty ranges has to be defined for parent node if
92518308c94SGrygorii Strashko 		 * DMA is supported
92618308c94SGrygorii Strashko 		 */
92718308c94SGrygorii Strashko 		if (!ranges)
92818308c94SGrygorii Strashko 			break;
92918308c94SGrygorii Strashko 	}
93018308c94SGrygorii Strashko 
93118308c94SGrygorii Strashko 	if (!ranges) {
9320d638a07SRob Herring 		pr_debug("no dma-ranges found for node(%pOF)\n", np);
93318308c94SGrygorii Strashko 		ret = -ENODEV;
93418308c94SGrygorii Strashko 		goto out;
93518308c94SGrygorii Strashko 	}
93618308c94SGrygorii Strashko 
93718308c94SGrygorii Strashko 	len /= sizeof(u32);
93818308c94SGrygorii Strashko 
93918308c94SGrygorii Strashko 	pna = of_n_addr_cells(node);
94018308c94SGrygorii Strashko 
94118308c94SGrygorii Strashko 	/* dma-ranges format:
94218308c94SGrygorii Strashko 	 * DMA addr	: naddr cells
94318308c94SGrygorii Strashko 	 * CPU addr	: pna cells
94418308c94SGrygorii Strashko 	 * size		: nsize cells
94518308c94SGrygorii Strashko 	 */
94618308c94SGrygorii Strashko 	dmaaddr = of_read_number(ranges, naddr);
94718308c94SGrygorii Strashko 	*paddr = of_translate_dma_address(np, ranges);
94818308c94SGrygorii Strashko 	if (*paddr == OF_BAD_ADDR) {
9490d638a07SRob Herring 		pr_err("translation of DMA address(%pad) to CPU address failed node(%pOF)\n",
9500d638a07SRob Herring 		       dma_addr, np);
95118308c94SGrygorii Strashko 		ret = -EINVAL;
95218308c94SGrygorii Strashko 		goto out;
95318308c94SGrygorii Strashko 	}
95418308c94SGrygorii Strashko 	*dma_addr = dmaaddr;
95518308c94SGrygorii Strashko 
95618308c94SGrygorii Strashko 	*size = of_read_number(ranges + naddr + pna, nsize);
95718308c94SGrygorii Strashko 
95818308c94SGrygorii Strashko 	pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n",
95918308c94SGrygorii Strashko 		 *dma_addr, *paddr, *size);
96018308c94SGrygorii Strashko 
96118308c94SGrygorii Strashko out:
96218308c94SGrygorii Strashko 	of_node_put(node);
96318308c94SGrygorii Strashko 
96418308c94SGrygorii Strashko 	return ret;
96518308c94SGrygorii Strashko }
96618308c94SGrygorii Strashko EXPORT_SYMBOL_GPL(of_dma_get_range);
96792ea637eSSantosh Shilimkar 
96892ea637eSSantosh Shilimkar /**
96992ea637eSSantosh Shilimkar  * of_dma_is_coherent - Check if device is coherent
97092ea637eSSantosh Shilimkar  * @np:	device node
97192ea637eSSantosh Shilimkar  *
97292ea637eSSantosh Shilimkar  * It returns true if "dma-coherent" property was found
97392ea637eSSantosh Shilimkar  * for this device in DT.
97492ea637eSSantosh Shilimkar  */
97592ea637eSSantosh Shilimkar bool of_dma_is_coherent(struct device_node *np)
97692ea637eSSantosh Shilimkar {
97792ea637eSSantosh Shilimkar 	struct device_node *node = of_node_get(np);
97892ea637eSSantosh Shilimkar 
97992ea637eSSantosh Shilimkar 	while (node) {
98092ea637eSSantosh Shilimkar 		if (of_property_read_bool(node, "dma-coherent")) {
98192ea637eSSantosh Shilimkar 			of_node_put(node);
98292ea637eSSantosh Shilimkar 			return true;
98392ea637eSSantosh Shilimkar 		}
98492ea637eSSantosh Shilimkar 		node = of_get_next_parent(node);
98592ea637eSSantosh Shilimkar 	}
98692ea637eSSantosh Shilimkar 	of_node_put(node);
98792ea637eSSantosh Shilimkar 	return false;
98892ea637eSSantosh Shilimkar }
98992ea637eSSantosh Shilimkar EXPORT_SYMBOL_GPL(of_dma_is_coherent);
990