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