1*38d21b41SSimon Glass /* 2*38d21b41SSimon Glass * Taken from Linux v4.9 drivers/of/address.c 3*38d21b41SSimon Glass * 4*38d21b41SSimon Glass * Modified for U-Boot 5*38d21b41SSimon Glass * Copyright (c) 2017 Google, Inc 6*38d21b41SSimon Glass * 7*38d21b41SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 8*38d21b41SSimon Glass */ 9*38d21b41SSimon Glass 10*38d21b41SSimon Glass #include <common.h> 11*38d21b41SSimon Glass #include <libfdt.h> 12*38d21b41SSimon Glass #include <dm/of_access.h> 13*38d21b41SSimon Glass #include <dm/of_addr.h> 14*38d21b41SSimon Glass #include <linux/err.h> 15*38d21b41SSimon Glass #include <linux/ioport.h> 16*38d21b41SSimon Glass 17*38d21b41SSimon Glass /* Max address size we deal with */ 18*38d21b41SSimon Glass #define OF_MAX_ADDR_CELLS 4 19*38d21b41SSimon Glass #define OF_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS) 20*38d21b41SSimon Glass #define OF_CHECK_COUNTS(na, ns) (OF_CHECK_ADDR_COUNT(na) && (ns) > 0) 21*38d21b41SSimon Glass 22*38d21b41SSimon Glass static struct of_bus *of_match_bus(struct device_node *np); 23*38d21b41SSimon Glass 24*38d21b41SSimon Glass /* Debug utility */ 25*38d21b41SSimon Glass #ifdef DEBUG 26*38d21b41SSimon Glass static void of_dump_addr(const char *s, const __be32 *addr, int na) 27*38d21b41SSimon Glass { 28*38d21b41SSimon Glass debug("%s", s); 29*38d21b41SSimon Glass while (na--) 30*38d21b41SSimon Glass pr_cont(" %08x", be32_to_cpu(*(addr++))); 31*38d21b41SSimon Glass pr_cont("\n"); 32*38d21b41SSimon Glass } 33*38d21b41SSimon Glass #else 34*38d21b41SSimon Glass static void of_dump_addr(const char *s, const __be32 *addr, int na) { } 35*38d21b41SSimon Glass #endif 36*38d21b41SSimon Glass 37*38d21b41SSimon Glass /* Callbacks for bus specific translators */ 38*38d21b41SSimon Glass struct of_bus { 39*38d21b41SSimon Glass const char *name; 40*38d21b41SSimon Glass const char *addresses; 41*38d21b41SSimon Glass int (*match)(struct device_node *parent); 42*38d21b41SSimon Glass void (*count_cells)(const struct device_node *child, int *addrc, 43*38d21b41SSimon Glass int *sizec); 44*38d21b41SSimon Glass u64 (*map)(__be32 *addr, const __be32 *range, int na, int ns, int pna); 45*38d21b41SSimon Glass int (*translate)(__be32 *addr, u64 offset, int na); 46*38d21b41SSimon Glass unsigned int (*get_flags)(const __be32 *addr); 47*38d21b41SSimon Glass }; 48*38d21b41SSimon Glass 49*38d21b41SSimon Glass static void of_bus_default_count_cells(const struct device_node *np, 50*38d21b41SSimon Glass int *addrc, int *sizec) 51*38d21b41SSimon Glass { 52*38d21b41SSimon Glass if (addrc) 53*38d21b41SSimon Glass *addrc = of_n_addr_cells(np); 54*38d21b41SSimon Glass if (sizec) 55*38d21b41SSimon Glass *sizec = of_n_size_cells(np); 56*38d21b41SSimon Glass } 57*38d21b41SSimon Glass 58*38d21b41SSimon Glass static u64 of_bus_default_map(__be32 *addr, const __be32 *range, 59*38d21b41SSimon Glass int na, int ns, int pna) 60*38d21b41SSimon Glass { 61*38d21b41SSimon Glass u64 cp, s, da; 62*38d21b41SSimon Glass 63*38d21b41SSimon Glass cp = of_read_number(range, na); 64*38d21b41SSimon Glass s = of_read_number(range + na + pna, ns); 65*38d21b41SSimon Glass da = of_read_number(addr, na); 66*38d21b41SSimon Glass 67*38d21b41SSimon Glass debug("default map, cp=%llx, s=%llx, da=%llx\n", 68*38d21b41SSimon Glass (unsigned long long)cp, (unsigned long long)s, 69*38d21b41SSimon Glass (unsigned long long)da); 70*38d21b41SSimon Glass 71*38d21b41SSimon Glass if (da < cp || da >= (cp + s)) 72*38d21b41SSimon Glass return OF_BAD_ADDR; 73*38d21b41SSimon Glass return da - cp; 74*38d21b41SSimon Glass } 75*38d21b41SSimon Glass 76*38d21b41SSimon Glass static int of_bus_default_translate(__be32 *addr, u64 offset, int na) 77*38d21b41SSimon Glass { 78*38d21b41SSimon Glass u64 a = of_read_number(addr, na); 79*38d21b41SSimon Glass memset(addr, 0, na * 4); 80*38d21b41SSimon Glass a += offset; 81*38d21b41SSimon Glass if (na > 1) 82*38d21b41SSimon Glass addr[na - 2] = cpu_to_be32(a >> 32); 83*38d21b41SSimon Glass addr[na - 1] = cpu_to_be32(a & 0xffffffffu); 84*38d21b41SSimon Glass 85*38d21b41SSimon Glass return 0; 86*38d21b41SSimon Glass } 87*38d21b41SSimon Glass 88*38d21b41SSimon Glass static unsigned int of_bus_default_get_flags(const __be32 *addr) 89*38d21b41SSimon Glass { 90*38d21b41SSimon Glass return IORESOURCE_MEM; 91*38d21b41SSimon Glass } 92*38d21b41SSimon Glass 93*38d21b41SSimon Glass /* 94*38d21b41SSimon Glass * Array of bus-specific translators 95*38d21b41SSimon Glass */ 96*38d21b41SSimon Glass static struct of_bus of_busses[] = { 97*38d21b41SSimon Glass /* Default */ 98*38d21b41SSimon Glass { 99*38d21b41SSimon Glass .name = "default", 100*38d21b41SSimon Glass .addresses = "reg", 101*38d21b41SSimon Glass .match = NULL, 102*38d21b41SSimon Glass .count_cells = of_bus_default_count_cells, 103*38d21b41SSimon Glass .map = of_bus_default_map, 104*38d21b41SSimon Glass .translate = of_bus_default_translate, 105*38d21b41SSimon Glass .get_flags = of_bus_default_get_flags, 106*38d21b41SSimon Glass }, 107*38d21b41SSimon Glass }; 108*38d21b41SSimon Glass 109*38d21b41SSimon Glass static struct of_bus *of_match_bus(struct device_node *np) 110*38d21b41SSimon Glass { 111*38d21b41SSimon Glass int i; 112*38d21b41SSimon Glass 113*38d21b41SSimon Glass for (i = 0; i < ARRAY_SIZE(of_busses); i++) 114*38d21b41SSimon Glass if (!of_busses[i].match || of_busses[i].match(np)) 115*38d21b41SSimon Glass return &of_busses[i]; 116*38d21b41SSimon Glass BUG(); 117*38d21b41SSimon Glass return NULL; 118*38d21b41SSimon Glass } 119*38d21b41SSimon Glass 120*38d21b41SSimon Glass static void dev_count_cells(const struct device_node *np, int *nap, int *nsp) 121*38d21b41SSimon Glass { 122*38d21b41SSimon Glass of_bus_default_count_cells(np, nap, nsp); 123*38d21b41SSimon Glass } 124*38d21b41SSimon Glass 125*38d21b41SSimon Glass const __be32 *of_get_address(const struct device_node *dev, int index, 126*38d21b41SSimon Glass u64 *size, unsigned int *flags) 127*38d21b41SSimon Glass { 128*38d21b41SSimon Glass const __be32 *prop; 129*38d21b41SSimon Glass int psize; 130*38d21b41SSimon Glass struct device_node *parent; 131*38d21b41SSimon Glass struct of_bus *bus; 132*38d21b41SSimon Glass int onesize, i, na, ns; 133*38d21b41SSimon Glass 134*38d21b41SSimon Glass /* Get parent & match bus type */ 135*38d21b41SSimon Glass parent = of_get_parent(dev); 136*38d21b41SSimon Glass if (parent == NULL) 137*38d21b41SSimon Glass return NULL; 138*38d21b41SSimon Glass dev_count_cells(dev, &na, &ns); 139*38d21b41SSimon Glass bus = of_match_bus(parent); 140*38d21b41SSimon Glass bus->count_cells(dev, &na, &ns); 141*38d21b41SSimon Glass of_node_put(parent); 142*38d21b41SSimon Glass if (!OF_CHECK_ADDR_COUNT(na)) 143*38d21b41SSimon Glass return NULL; 144*38d21b41SSimon Glass 145*38d21b41SSimon Glass /* Get "reg" or "assigned-addresses" property */ 146*38d21b41SSimon Glass prop = of_get_property(dev, "reg", &psize); 147*38d21b41SSimon Glass if (prop == NULL) 148*38d21b41SSimon Glass return NULL; 149*38d21b41SSimon Glass psize /= 4; 150*38d21b41SSimon Glass 151*38d21b41SSimon Glass onesize = na + ns; 152*38d21b41SSimon Glass for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) 153*38d21b41SSimon Glass if (i == index) { 154*38d21b41SSimon Glass if (size) 155*38d21b41SSimon Glass *size = of_read_number(prop + na, ns); 156*38d21b41SSimon Glass if (flags) 157*38d21b41SSimon Glass *flags = bus->get_flags(prop); 158*38d21b41SSimon Glass return prop; 159*38d21b41SSimon Glass } 160*38d21b41SSimon Glass return NULL; 161*38d21b41SSimon Glass } 162*38d21b41SSimon Glass EXPORT_SYMBOL(of_get_address); 163*38d21b41SSimon Glass 164*38d21b41SSimon Glass static int of_empty_ranges_quirk(const struct device_node *np) 165*38d21b41SSimon Glass { 166*38d21b41SSimon Glass return false; 167*38d21b41SSimon Glass } 168*38d21b41SSimon Glass 169*38d21b41SSimon Glass static int of_translate_one(const struct device_node *parent, 170*38d21b41SSimon Glass struct of_bus *bus, struct of_bus *pbus, 171*38d21b41SSimon Glass __be32 *addr, int na, int ns, int pna, 172*38d21b41SSimon Glass const char *rprop) 173*38d21b41SSimon Glass { 174*38d21b41SSimon Glass const __be32 *ranges; 175*38d21b41SSimon Glass int rlen; 176*38d21b41SSimon Glass int rone; 177*38d21b41SSimon Glass u64 offset = OF_BAD_ADDR; 178*38d21b41SSimon Glass 179*38d21b41SSimon Glass /* 180*38d21b41SSimon Glass * Normally, an absence of a "ranges" property means we are 181*38d21b41SSimon Glass * crossing a non-translatable boundary, and thus the addresses 182*38d21b41SSimon Glass * below the current cannot be converted to CPU physical ones. 183*38d21b41SSimon Glass * Unfortunately, while this is very clear in the spec, it's not 184*38d21b41SSimon Glass * what Apple understood, and they do have things like /uni-n or 185*38d21b41SSimon Glass * /ht nodes with no "ranges" property and a lot of perfectly 186*38d21b41SSimon Glass * useable mapped devices below them. Thus we treat the absence of 187*38d21b41SSimon Glass * "ranges" as equivalent to an empty "ranges" property which means 188*38d21b41SSimon Glass * a 1:1 translation at that level. It's up to the caller not to try 189*38d21b41SSimon Glass * to translate addresses that aren't supposed to be translated in 190*38d21b41SSimon Glass * the first place. --BenH. 191*38d21b41SSimon Glass * 192*38d21b41SSimon Glass * As far as we know, this damage only exists on Apple machines, so 193*38d21b41SSimon Glass * This code is only enabled on powerpc. --gcl 194*38d21b41SSimon Glass */ 195*38d21b41SSimon Glass ranges = of_get_property(parent, rprop, &rlen); 196*38d21b41SSimon Glass if (ranges == NULL && !of_empty_ranges_quirk(parent)) { 197*38d21b41SSimon Glass debug("no ranges; cannot translate\n"); 198*38d21b41SSimon Glass return 1; 199*38d21b41SSimon Glass } 200*38d21b41SSimon Glass if (ranges == NULL || rlen == 0) { 201*38d21b41SSimon Glass offset = of_read_number(addr, na); 202*38d21b41SSimon Glass memset(addr, 0, pna * 4); 203*38d21b41SSimon Glass debug("empty ranges; 1:1 translation\n"); 204*38d21b41SSimon Glass goto finish; 205*38d21b41SSimon Glass } 206*38d21b41SSimon Glass 207*38d21b41SSimon Glass debug("walking ranges...\n"); 208*38d21b41SSimon Glass 209*38d21b41SSimon Glass /* Now walk through the ranges */ 210*38d21b41SSimon Glass rlen /= 4; 211*38d21b41SSimon Glass rone = na + pna + ns; 212*38d21b41SSimon Glass for (; rlen >= rone; rlen -= rone, ranges += rone) { 213*38d21b41SSimon Glass offset = bus->map(addr, ranges, na, ns, pna); 214*38d21b41SSimon Glass if (offset != OF_BAD_ADDR) 215*38d21b41SSimon Glass break; 216*38d21b41SSimon Glass } 217*38d21b41SSimon Glass if (offset == OF_BAD_ADDR) { 218*38d21b41SSimon Glass debug("not found !\n"); 219*38d21b41SSimon Glass return 1; 220*38d21b41SSimon Glass } 221*38d21b41SSimon Glass memcpy(addr, ranges + na, 4 * pna); 222*38d21b41SSimon Glass 223*38d21b41SSimon Glass finish: 224*38d21b41SSimon Glass of_dump_addr("parent translation for:", addr, pna); 225*38d21b41SSimon Glass debug("with offset: %llx\n", (unsigned long long)offset); 226*38d21b41SSimon Glass 227*38d21b41SSimon Glass /* Translate it into parent bus space */ 228*38d21b41SSimon Glass return pbus->translate(addr, offset, pna); 229*38d21b41SSimon Glass } 230*38d21b41SSimon Glass 231*38d21b41SSimon Glass /* 232*38d21b41SSimon Glass * Translate an address from the device-tree into a CPU physical address, 233*38d21b41SSimon Glass * this walks up the tree and applies the various bus mappings on the 234*38d21b41SSimon Glass * way. 235*38d21b41SSimon Glass * 236*38d21b41SSimon Glass * Note: We consider that crossing any level with #size-cells == 0 to mean 237*38d21b41SSimon Glass * that translation is impossible (that is we are not dealing with a value 238*38d21b41SSimon Glass * that can be mapped to a cpu physical address). This is not really specified 239*38d21b41SSimon Glass * that way, but this is traditionally the way IBM at least do things 240*38d21b41SSimon Glass */ 241*38d21b41SSimon Glass static u64 __of_translate_address(const struct device_node *dev, 242*38d21b41SSimon Glass const __be32 *in_addr, const char *rprop) 243*38d21b41SSimon Glass { 244*38d21b41SSimon Glass struct device_node *parent = NULL; 245*38d21b41SSimon Glass struct of_bus *bus, *pbus; 246*38d21b41SSimon Glass __be32 addr[OF_MAX_ADDR_CELLS]; 247*38d21b41SSimon Glass int na, ns, pna, pns; 248*38d21b41SSimon Glass u64 result = OF_BAD_ADDR; 249*38d21b41SSimon Glass 250*38d21b41SSimon Glass debug("** translation for device %s **\n", of_node_full_name(dev)); 251*38d21b41SSimon Glass 252*38d21b41SSimon Glass /* Increase refcount at current level */ 253*38d21b41SSimon Glass (void)of_node_get(dev); 254*38d21b41SSimon Glass 255*38d21b41SSimon Glass /* Get parent & match bus type */ 256*38d21b41SSimon Glass parent = of_get_parent(dev); 257*38d21b41SSimon Glass if (parent == NULL) 258*38d21b41SSimon Glass goto bail; 259*38d21b41SSimon Glass bus = of_match_bus(parent); 260*38d21b41SSimon Glass 261*38d21b41SSimon Glass /* Count address cells & copy address locally */ 262*38d21b41SSimon Glass bus->count_cells(dev, &na, &ns); 263*38d21b41SSimon Glass if (!OF_CHECK_COUNTS(na, ns)) { 264*38d21b41SSimon Glass debug("Bad cell count for %s\n", of_node_full_name(dev)); 265*38d21b41SSimon Glass goto bail; 266*38d21b41SSimon Glass } 267*38d21b41SSimon Glass memcpy(addr, in_addr, na * 4); 268*38d21b41SSimon Glass 269*38d21b41SSimon Glass debug("bus is %s (na=%d, ns=%d) on %s\n", bus->name, na, ns, 270*38d21b41SSimon Glass of_node_full_name(parent)); 271*38d21b41SSimon Glass of_dump_addr("translating address:", addr, na); 272*38d21b41SSimon Glass 273*38d21b41SSimon Glass /* Translate */ 274*38d21b41SSimon Glass for (;;) { 275*38d21b41SSimon Glass /* Switch to parent bus */ 276*38d21b41SSimon Glass of_node_put(dev); 277*38d21b41SSimon Glass dev = parent; 278*38d21b41SSimon Glass parent = of_get_parent(dev); 279*38d21b41SSimon Glass 280*38d21b41SSimon Glass /* If root, we have finished */ 281*38d21b41SSimon Glass if (parent == NULL) { 282*38d21b41SSimon Glass debug("reached root node\n"); 283*38d21b41SSimon Glass result = of_read_number(addr, na); 284*38d21b41SSimon Glass break; 285*38d21b41SSimon Glass } 286*38d21b41SSimon Glass 287*38d21b41SSimon Glass /* Get new parent bus and counts */ 288*38d21b41SSimon Glass pbus = of_match_bus(parent); 289*38d21b41SSimon Glass pbus->count_cells(dev, &pna, &pns); 290*38d21b41SSimon Glass if (!OF_CHECK_COUNTS(pna, pns)) { 291*38d21b41SSimon Glass debug("Bad cell count for %s\n", 292*38d21b41SSimon Glass of_node_full_name(dev)); 293*38d21b41SSimon Glass break; 294*38d21b41SSimon Glass } 295*38d21b41SSimon Glass 296*38d21b41SSimon Glass debug("parent bus is %s (na=%d, ns=%d) on %s\n", pbus->name, 297*38d21b41SSimon Glass pna, pns, of_node_full_name(parent)); 298*38d21b41SSimon Glass 299*38d21b41SSimon Glass /* Apply bus translation */ 300*38d21b41SSimon Glass if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) 301*38d21b41SSimon Glass break; 302*38d21b41SSimon Glass 303*38d21b41SSimon Glass /* Complete the move up one level */ 304*38d21b41SSimon Glass na = pna; 305*38d21b41SSimon Glass ns = pns; 306*38d21b41SSimon Glass bus = pbus; 307*38d21b41SSimon Glass 308*38d21b41SSimon Glass of_dump_addr("one level translation:", addr, na); 309*38d21b41SSimon Glass } 310*38d21b41SSimon Glass bail: 311*38d21b41SSimon Glass of_node_put(parent); 312*38d21b41SSimon Glass of_node_put(dev); 313*38d21b41SSimon Glass 314*38d21b41SSimon Glass return result; 315*38d21b41SSimon Glass } 316*38d21b41SSimon Glass 317*38d21b41SSimon Glass u64 of_translate_address(const struct device_node *dev, const __be32 *in_addr) 318*38d21b41SSimon Glass { 319*38d21b41SSimon Glass return __of_translate_address(dev, in_addr, "ranges"); 320*38d21b41SSimon Glass } 321*38d21b41SSimon Glass 322*38d21b41SSimon Glass 323*38d21b41SSimon Glass static int __of_address_to_resource(const struct device_node *dev, 324*38d21b41SSimon Glass const __be32 *addrp, u64 size, unsigned int flags, 325*38d21b41SSimon Glass const char *name, struct resource *r) 326*38d21b41SSimon Glass { 327*38d21b41SSimon Glass u64 taddr; 328*38d21b41SSimon Glass 329*38d21b41SSimon Glass if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0) 330*38d21b41SSimon Glass return -EINVAL; 331*38d21b41SSimon Glass taddr = of_translate_address(dev, addrp); 332*38d21b41SSimon Glass if (taddr == OF_BAD_ADDR) 333*38d21b41SSimon Glass return -EINVAL; 334*38d21b41SSimon Glass memset(r, 0, sizeof(struct resource)); 335*38d21b41SSimon Glass r->start = taddr; 336*38d21b41SSimon Glass r->end = taddr + size - 1; 337*38d21b41SSimon Glass r->flags = flags; 338*38d21b41SSimon Glass r->name = name ? name : dev->full_name; 339*38d21b41SSimon Glass 340*38d21b41SSimon Glass return 0; 341*38d21b41SSimon Glass } 342*38d21b41SSimon Glass 343*38d21b41SSimon Glass int of_address_to_resource(const struct device_node *dev, int index, 344*38d21b41SSimon Glass struct resource *r) 345*38d21b41SSimon Glass { 346*38d21b41SSimon Glass const __be32 *addrp; 347*38d21b41SSimon Glass u64 size; 348*38d21b41SSimon Glass unsigned int flags; 349*38d21b41SSimon Glass const char *name = NULL; 350*38d21b41SSimon Glass 351*38d21b41SSimon Glass addrp = of_get_address(dev, index, &size, &flags); 352*38d21b41SSimon Glass if (addrp == NULL) 353*38d21b41SSimon Glass return -EINVAL; 354*38d21b41SSimon Glass 355*38d21b41SSimon Glass /* Get optional "reg-names" property to add a name to a resource */ 356*38d21b41SSimon Glass of_property_read_string_index(dev, "reg-names", index, &name); 357*38d21b41SSimon Glass 358*38d21b41SSimon Glass return __of_address_to_resource(dev, addrp, size, flags, name, r); 359*38d21b41SSimon Glass } 360