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