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