138d21b41SSimon Glass /*
238d21b41SSimon Glass * Taken from Linux v4.9 drivers/of/address.c
338d21b41SSimon Glass *
438d21b41SSimon Glass * Modified for U-Boot
538d21b41SSimon Glass * Copyright (c) 2017 Google, Inc
638d21b41SSimon Glass *
738d21b41SSimon Glass * SPDX-License-Identifier: GPL-2.0+
838d21b41SSimon Glass */
938d21b41SSimon Glass
1038d21b41SSimon Glass #include <common.h>
11*0e00a84cSMasahiro Yamada #include <linux/libfdt.h>
1238d21b41SSimon Glass #include <dm/of_access.h>
1338d21b41SSimon Glass #include <dm/of_addr.h>
1438d21b41SSimon Glass #include <linux/err.h>
1538d21b41SSimon Glass #include <linux/ioport.h>
1638d21b41SSimon Glass
1738d21b41SSimon Glass /* Max address size we deal with */
1838d21b41SSimon Glass #define OF_MAX_ADDR_CELLS 4
1938d21b41SSimon Glass #define OF_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS)
2038d21b41SSimon Glass #define OF_CHECK_COUNTS(na, ns) (OF_CHECK_ADDR_COUNT(na) && (ns) > 0)
2138d21b41SSimon Glass
2238d21b41SSimon Glass static struct of_bus *of_match_bus(struct device_node *np);
2338d21b41SSimon Glass
2438d21b41SSimon Glass /* Debug utility */
2538d21b41SSimon Glass #ifdef DEBUG
of_dump_addr(const char * s,const __be32 * addr,int na)2638d21b41SSimon Glass static void of_dump_addr(const char *s, const __be32 *addr, int na)
2738d21b41SSimon Glass {
2838d21b41SSimon Glass debug("%s", s);
2938d21b41SSimon Glass while (na--)
3038d21b41SSimon Glass pr_cont(" %08x", be32_to_cpu(*(addr++)));
3138d21b41SSimon Glass pr_cont("\n");
3238d21b41SSimon Glass }
3338d21b41SSimon Glass #else
of_dump_addr(const char * s,const __be32 * addr,int na)3438d21b41SSimon Glass static void of_dump_addr(const char *s, const __be32 *addr, int na) { }
3538d21b41SSimon Glass #endif
3638d21b41SSimon Glass
3738d21b41SSimon Glass /* Callbacks for bus specific translators */
3838d21b41SSimon Glass struct of_bus {
3938d21b41SSimon Glass const char *name;
4038d21b41SSimon Glass const char *addresses;
4138d21b41SSimon Glass int (*match)(struct device_node *parent);
4238d21b41SSimon Glass void (*count_cells)(const struct device_node *child, int *addrc,
4338d21b41SSimon Glass int *sizec);
4438d21b41SSimon Glass u64 (*map)(__be32 *addr, const __be32 *range, int na, int ns, int pna);
4538d21b41SSimon Glass int (*translate)(__be32 *addr, u64 offset, int na);
4638d21b41SSimon Glass unsigned int (*get_flags)(const __be32 *addr);
4738d21b41SSimon Glass };
4838d21b41SSimon Glass
of_bus_default_count_cells(const struct device_node * np,int * addrc,int * sizec)4938d21b41SSimon Glass static void of_bus_default_count_cells(const struct device_node *np,
5038d21b41SSimon Glass int *addrc, int *sizec)
5138d21b41SSimon Glass {
5238d21b41SSimon Glass if (addrc)
5338d21b41SSimon Glass *addrc = of_n_addr_cells(np);
5438d21b41SSimon Glass if (sizec)
5538d21b41SSimon Glass *sizec = of_n_size_cells(np);
5638d21b41SSimon Glass }
5738d21b41SSimon Glass
of_bus_default_map(__be32 * addr,const __be32 * range,int na,int ns,int pna)5838d21b41SSimon Glass static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
5938d21b41SSimon Glass int na, int ns, int pna)
6038d21b41SSimon Glass {
6138d21b41SSimon Glass u64 cp, s, da;
6238d21b41SSimon Glass
6338d21b41SSimon Glass cp = of_read_number(range, na);
6438d21b41SSimon Glass s = of_read_number(range + na + pna, ns);
6538d21b41SSimon Glass da = of_read_number(addr, na);
6638d21b41SSimon Glass
6738d21b41SSimon Glass debug("default map, cp=%llx, s=%llx, da=%llx\n",
6838d21b41SSimon Glass (unsigned long long)cp, (unsigned long long)s,
6938d21b41SSimon Glass (unsigned long long)da);
7038d21b41SSimon Glass
7138d21b41SSimon Glass if (da < cp || da >= (cp + s))
7238d21b41SSimon Glass return OF_BAD_ADDR;
7338d21b41SSimon Glass return da - cp;
7438d21b41SSimon Glass }
7538d21b41SSimon Glass
of_bus_default_translate(__be32 * addr,u64 offset,int na)7638d21b41SSimon Glass static int of_bus_default_translate(__be32 *addr, u64 offset, int na)
7738d21b41SSimon Glass {
7838d21b41SSimon Glass u64 a = of_read_number(addr, na);
7938d21b41SSimon Glass memset(addr, 0, na * 4);
8038d21b41SSimon Glass a += offset;
8138d21b41SSimon Glass if (na > 1)
8238d21b41SSimon Glass addr[na - 2] = cpu_to_be32(a >> 32);
8338d21b41SSimon Glass addr[na - 1] = cpu_to_be32(a & 0xffffffffu);
8438d21b41SSimon Glass
8538d21b41SSimon Glass return 0;
8638d21b41SSimon Glass }
8738d21b41SSimon Glass
of_bus_default_get_flags(const __be32 * addr)8838d21b41SSimon Glass static unsigned int of_bus_default_get_flags(const __be32 *addr)
8938d21b41SSimon Glass {
9038d21b41SSimon Glass return IORESOURCE_MEM;
9138d21b41SSimon Glass }
9238d21b41SSimon Glass
9338d21b41SSimon Glass /*
9438d21b41SSimon Glass * Array of bus-specific translators
9538d21b41SSimon Glass */
9638d21b41SSimon Glass static struct of_bus of_busses[] = {
9738d21b41SSimon Glass /* Default */
9838d21b41SSimon Glass {
9938d21b41SSimon Glass .name = "default",
10038d21b41SSimon Glass .addresses = "reg",
10138d21b41SSimon Glass .match = NULL,
10238d21b41SSimon Glass .count_cells = of_bus_default_count_cells,
10338d21b41SSimon Glass .map = of_bus_default_map,
10438d21b41SSimon Glass .translate = of_bus_default_translate,
10538d21b41SSimon Glass .get_flags = of_bus_default_get_flags,
10638d21b41SSimon Glass },
10738d21b41SSimon Glass };
10838d21b41SSimon Glass
of_match_bus(struct device_node * np)10938d21b41SSimon Glass static struct of_bus *of_match_bus(struct device_node *np)
11038d21b41SSimon Glass {
11138d21b41SSimon Glass int i;
11238d21b41SSimon Glass
11338d21b41SSimon Glass for (i = 0; i < ARRAY_SIZE(of_busses); i++)
11438d21b41SSimon Glass if (!of_busses[i].match || of_busses[i].match(np))
11538d21b41SSimon Glass return &of_busses[i];
11638d21b41SSimon Glass BUG();
11738d21b41SSimon Glass return NULL;
11838d21b41SSimon Glass }
11938d21b41SSimon Glass
dev_count_cells(const struct device_node * np,int * nap,int * nsp)12038d21b41SSimon Glass static void dev_count_cells(const struct device_node *np, int *nap, int *nsp)
12138d21b41SSimon Glass {
12238d21b41SSimon Glass of_bus_default_count_cells(np, nap, nsp);
12338d21b41SSimon Glass }
12438d21b41SSimon Glass
of_get_address(const struct device_node * dev,int index,u64 * size,unsigned int * flags)12538d21b41SSimon Glass const __be32 *of_get_address(const struct device_node *dev, int index,
12638d21b41SSimon Glass u64 *size, unsigned int *flags)
12738d21b41SSimon Glass {
12838d21b41SSimon Glass const __be32 *prop;
12938d21b41SSimon Glass int psize;
13038d21b41SSimon Glass struct device_node *parent;
13138d21b41SSimon Glass struct of_bus *bus;
13238d21b41SSimon Glass int onesize, i, na, ns;
13338d21b41SSimon Glass
13438d21b41SSimon Glass /* Get parent & match bus type */
13538d21b41SSimon Glass parent = of_get_parent(dev);
13638d21b41SSimon Glass if (parent == NULL)
13738d21b41SSimon Glass return NULL;
13838d21b41SSimon Glass dev_count_cells(dev, &na, &ns);
13938d21b41SSimon Glass bus = of_match_bus(parent);
14038d21b41SSimon Glass bus->count_cells(dev, &na, &ns);
14138d21b41SSimon Glass of_node_put(parent);
14238d21b41SSimon Glass if (!OF_CHECK_ADDR_COUNT(na))
14338d21b41SSimon Glass return NULL;
14438d21b41SSimon Glass
14538d21b41SSimon Glass /* Get "reg" or "assigned-addresses" property */
14638d21b41SSimon Glass prop = of_get_property(dev, "reg", &psize);
14738d21b41SSimon Glass if (prop == NULL)
14838d21b41SSimon Glass return NULL;
14938d21b41SSimon Glass psize /= 4;
15038d21b41SSimon Glass
15138d21b41SSimon Glass onesize = na + ns;
15238d21b41SSimon Glass for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
15338d21b41SSimon Glass if (i == index) {
15438d21b41SSimon Glass if (size)
15538d21b41SSimon Glass *size = of_read_number(prop + na, ns);
15638d21b41SSimon Glass if (flags)
15738d21b41SSimon Glass *flags = bus->get_flags(prop);
15838d21b41SSimon Glass return prop;
15938d21b41SSimon Glass }
16038d21b41SSimon Glass return NULL;
16138d21b41SSimon Glass }
16238d21b41SSimon Glass EXPORT_SYMBOL(of_get_address);
16338d21b41SSimon Glass
of_empty_ranges_quirk(const struct device_node * np)16438d21b41SSimon Glass static int of_empty_ranges_quirk(const struct device_node *np)
16538d21b41SSimon Glass {
16638d21b41SSimon Glass return false;
16738d21b41SSimon Glass }
16838d21b41SSimon Glass
of_translate_one(const struct device_node * parent,struct of_bus * bus,struct of_bus * pbus,__be32 * addr,int na,int ns,int pna,const char * rprop)16938d21b41SSimon Glass static int of_translate_one(const struct device_node *parent,
17038d21b41SSimon Glass struct of_bus *bus, struct of_bus *pbus,
17138d21b41SSimon Glass __be32 *addr, int na, int ns, int pna,
17238d21b41SSimon Glass const char *rprop)
17338d21b41SSimon Glass {
17438d21b41SSimon Glass const __be32 *ranges;
17538d21b41SSimon Glass int rlen;
17638d21b41SSimon Glass int rone;
17738d21b41SSimon Glass u64 offset = OF_BAD_ADDR;
17838d21b41SSimon Glass
17938d21b41SSimon Glass /*
18038d21b41SSimon Glass * Normally, an absence of a "ranges" property means we are
18138d21b41SSimon Glass * crossing a non-translatable boundary, and thus the addresses
18238d21b41SSimon Glass * below the current cannot be converted to CPU physical ones.
18338d21b41SSimon Glass * Unfortunately, while this is very clear in the spec, it's not
18438d21b41SSimon Glass * what Apple understood, and they do have things like /uni-n or
18538d21b41SSimon Glass * /ht nodes with no "ranges" property and a lot of perfectly
18638d21b41SSimon Glass * useable mapped devices below them. Thus we treat the absence of
18738d21b41SSimon Glass * "ranges" as equivalent to an empty "ranges" property which means
18838d21b41SSimon Glass * a 1:1 translation at that level. It's up to the caller not to try
18938d21b41SSimon Glass * to translate addresses that aren't supposed to be translated in
19038d21b41SSimon Glass * the first place. --BenH.
19138d21b41SSimon Glass *
19238d21b41SSimon Glass * As far as we know, this damage only exists on Apple machines, so
19338d21b41SSimon Glass * This code is only enabled on powerpc. --gcl
19438d21b41SSimon Glass */
19538d21b41SSimon Glass ranges = of_get_property(parent, rprop, &rlen);
19638d21b41SSimon Glass if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
19738d21b41SSimon Glass debug("no ranges; cannot translate\n");
19838d21b41SSimon Glass return 1;
19938d21b41SSimon Glass }
20038d21b41SSimon Glass if (ranges == NULL || rlen == 0) {
20138d21b41SSimon Glass offset = of_read_number(addr, na);
20238d21b41SSimon Glass memset(addr, 0, pna * 4);
20338d21b41SSimon Glass debug("empty ranges; 1:1 translation\n");
20438d21b41SSimon Glass goto finish;
20538d21b41SSimon Glass }
20638d21b41SSimon Glass
20738d21b41SSimon Glass debug("walking ranges...\n");
20838d21b41SSimon Glass
20938d21b41SSimon Glass /* Now walk through the ranges */
21038d21b41SSimon Glass rlen /= 4;
21138d21b41SSimon Glass rone = na + pna + ns;
21238d21b41SSimon Glass for (; rlen >= rone; rlen -= rone, ranges += rone) {
21338d21b41SSimon Glass offset = bus->map(addr, ranges, na, ns, pna);
21438d21b41SSimon Glass if (offset != OF_BAD_ADDR)
21538d21b41SSimon Glass break;
21638d21b41SSimon Glass }
21738d21b41SSimon Glass if (offset == OF_BAD_ADDR) {
21838d21b41SSimon Glass debug("not found !\n");
21938d21b41SSimon Glass return 1;
22038d21b41SSimon Glass }
22138d21b41SSimon Glass memcpy(addr, ranges + na, 4 * pna);
22238d21b41SSimon Glass
22338d21b41SSimon Glass finish:
22438d21b41SSimon Glass of_dump_addr("parent translation for:", addr, pna);
22538d21b41SSimon Glass debug("with offset: %llx\n", (unsigned long long)offset);
22638d21b41SSimon Glass
22738d21b41SSimon Glass /* Translate it into parent bus space */
22838d21b41SSimon Glass return pbus->translate(addr, offset, pna);
22938d21b41SSimon Glass }
23038d21b41SSimon Glass
23138d21b41SSimon Glass /*
23238d21b41SSimon Glass * Translate an address from the device-tree into a CPU physical address,
23338d21b41SSimon Glass * this walks up the tree and applies the various bus mappings on the
23438d21b41SSimon Glass * way.
23538d21b41SSimon Glass *
23638d21b41SSimon Glass * Note: We consider that crossing any level with #size-cells == 0 to mean
23738d21b41SSimon Glass * that translation is impossible (that is we are not dealing with a value
23838d21b41SSimon Glass * that can be mapped to a cpu physical address). This is not really specified
23938d21b41SSimon Glass * that way, but this is traditionally the way IBM at least do things
24038d21b41SSimon Glass */
__of_translate_address(const struct device_node * dev,const __be32 * in_addr,const char * rprop)24138d21b41SSimon Glass static u64 __of_translate_address(const struct device_node *dev,
24238d21b41SSimon Glass const __be32 *in_addr, const char *rprop)
24338d21b41SSimon Glass {
24438d21b41SSimon Glass struct device_node *parent = NULL;
24538d21b41SSimon Glass struct of_bus *bus, *pbus;
24638d21b41SSimon Glass __be32 addr[OF_MAX_ADDR_CELLS];
24738d21b41SSimon Glass int na, ns, pna, pns;
24838d21b41SSimon Glass u64 result = OF_BAD_ADDR;
24938d21b41SSimon Glass
25038d21b41SSimon Glass debug("** translation for device %s **\n", of_node_full_name(dev));
25138d21b41SSimon Glass
25238d21b41SSimon Glass /* Increase refcount at current level */
25338d21b41SSimon Glass (void)of_node_get(dev);
25438d21b41SSimon Glass
25538d21b41SSimon Glass /* Get parent & match bus type */
25638d21b41SSimon Glass parent = of_get_parent(dev);
25738d21b41SSimon Glass if (parent == NULL)
25838d21b41SSimon Glass goto bail;
25938d21b41SSimon Glass bus = of_match_bus(parent);
26038d21b41SSimon Glass
26138d21b41SSimon Glass /* Count address cells & copy address locally */
26238d21b41SSimon Glass bus->count_cells(dev, &na, &ns);
26338d21b41SSimon Glass if (!OF_CHECK_COUNTS(na, ns)) {
26438d21b41SSimon Glass debug("Bad cell count for %s\n", of_node_full_name(dev));
26538d21b41SSimon Glass goto bail;
26638d21b41SSimon Glass }
26738d21b41SSimon Glass memcpy(addr, in_addr, na * 4);
26838d21b41SSimon Glass
26938d21b41SSimon Glass debug("bus is %s (na=%d, ns=%d) on %s\n", bus->name, na, ns,
27038d21b41SSimon Glass of_node_full_name(parent));
27138d21b41SSimon Glass of_dump_addr("translating address:", addr, na);
27238d21b41SSimon Glass
27338d21b41SSimon Glass /* Translate */
27438d21b41SSimon Glass for (;;) {
27538d21b41SSimon Glass /* Switch to parent bus */
27638d21b41SSimon Glass of_node_put(dev);
27738d21b41SSimon Glass dev = parent;
27838d21b41SSimon Glass parent = of_get_parent(dev);
27938d21b41SSimon Glass
28038d21b41SSimon Glass /* If root, we have finished */
28138d21b41SSimon Glass if (parent == NULL) {
28238d21b41SSimon Glass debug("reached root node\n");
28338d21b41SSimon Glass result = of_read_number(addr, na);
28438d21b41SSimon Glass break;
28538d21b41SSimon Glass }
28638d21b41SSimon Glass
28738d21b41SSimon Glass /* Get new parent bus and counts */
28838d21b41SSimon Glass pbus = of_match_bus(parent);
28938d21b41SSimon Glass pbus->count_cells(dev, &pna, &pns);
29038d21b41SSimon Glass if (!OF_CHECK_COUNTS(pna, pns)) {
29138d21b41SSimon Glass debug("Bad cell count for %s\n",
29238d21b41SSimon Glass of_node_full_name(dev));
29338d21b41SSimon Glass break;
29438d21b41SSimon Glass }
29538d21b41SSimon Glass
29638d21b41SSimon Glass debug("parent bus is %s (na=%d, ns=%d) on %s\n", pbus->name,
29738d21b41SSimon Glass pna, pns, of_node_full_name(parent));
29838d21b41SSimon Glass
29938d21b41SSimon Glass /* Apply bus translation */
30038d21b41SSimon Glass if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
30138d21b41SSimon Glass break;
30238d21b41SSimon Glass
30338d21b41SSimon Glass /* Complete the move up one level */
30438d21b41SSimon Glass na = pna;
30538d21b41SSimon Glass ns = pns;
30638d21b41SSimon Glass bus = pbus;
30738d21b41SSimon Glass
30838d21b41SSimon Glass of_dump_addr("one level translation:", addr, na);
30938d21b41SSimon Glass }
31038d21b41SSimon Glass bail:
31138d21b41SSimon Glass of_node_put(parent);
31238d21b41SSimon Glass of_node_put(dev);
31338d21b41SSimon Glass
31438d21b41SSimon Glass return result;
31538d21b41SSimon Glass }
31638d21b41SSimon Glass
of_translate_address(const struct device_node * dev,const __be32 * in_addr)31738d21b41SSimon Glass u64 of_translate_address(const struct device_node *dev, const __be32 *in_addr)
31838d21b41SSimon Glass {
31938d21b41SSimon Glass return __of_translate_address(dev, in_addr, "ranges");
32038d21b41SSimon Glass }
32138d21b41SSimon Glass
32238d21b41SSimon Glass
__of_address_to_resource(const struct device_node * dev,const __be32 * addrp,u64 size,unsigned int flags,const char * name,struct resource * r)32338d21b41SSimon Glass static int __of_address_to_resource(const struct device_node *dev,
32438d21b41SSimon Glass const __be32 *addrp, u64 size, unsigned int flags,
32538d21b41SSimon Glass const char *name, struct resource *r)
32638d21b41SSimon Glass {
32738d21b41SSimon Glass u64 taddr;
32838d21b41SSimon Glass
32938d21b41SSimon Glass if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
33038d21b41SSimon Glass return -EINVAL;
33138d21b41SSimon Glass taddr = of_translate_address(dev, addrp);
33238d21b41SSimon Glass if (taddr == OF_BAD_ADDR)
33338d21b41SSimon Glass return -EINVAL;
33438d21b41SSimon Glass memset(r, 0, sizeof(struct resource));
33538d21b41SSimon Glass r->start = taddr;
33638d21b41SSimon Glass r->end = taddr + size - 1;
33738d21b41SSimon Glass r->flags = flags;
33838d21b41SSimon Glass r->name = name ? name : dev->full_name;
33938d21b41SSimon Glass
34038d21b41SSimon Glass return 0;
34138d21b41SSimon Glass }
34238d21b41SSimon Glass
of_address_to_resource(const struct device_node * dev,int index,struct resource * r)34338d21b41SSimon Glass int of_address_to_resource(const struct device_node *dev, int index,
34438d21b41SSimon Glass struct resource *r)
34538d21b41SSimon Glass {
34638d21b41SSimon Glass const __be32 *addrp;
34738d21b41SSimon Glass u64 size;
34838d21b41SSimon Glass unsigned int flags;
34938d21b41SSimon Glass const char *name = NULL;
35038d21b41SSimon Glass
35138d21b41SSimon Glass addrp = of_get_address(dev, index, &size, &flags);
35238d21b41SSimon Glass if (addrp == NULL)
35338d21b41SSimon Glass return -EINVAL;
35438d21b41SSimon Glass
35538d21b41SSimon Glass /* Get optional "reg-names" property to add a name to a resource */
35638d21b41SSimon Glass of_property_read_string_index(dev, "reg-names", index, &name);
35738d21b41SSimon Glass
35838d21b41SSimon Glass return __of_address_to_resource(dev, addrp, size, flags, name, r);
35938d21b41SSimon Glass }
360