1e06e8b27082852bdab417af884241a4ed2037c73Rob Herring/* 2e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * FDT Address translation based on u-boot fdt_support.c which in turn was 3e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * based on the kernel unflattened DT address translation code. 4e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * 5e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * (C) Copyright 2007 6e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com 7e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * 8e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * Copyright 2010-2011 Freescale Semiconductor, Inc. 9e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * 10e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * This program is free software; you can redistribute it and/or modify 11e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * it under the terms of the GNU General Public License as published by 12e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * the Free Software Foundation; either version 2, or (at your option) 13e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * any later version. 14e06e8b27082852bdab417af884241a4ed2037c73Rob Herring */ 15e06e8b27082852bdab417af884241a4ed2037c73Rob Herring#include <linux/kernel.h> 16e06e8b27082852bdab417af884241a4ed2037c73Rob Herring#include <linux/libfdt.h> 17e06e8b27082852bdab417af884241a4ed2037c73Rob Herring#include <linux/of.h> 18e06e8b27082852bdab417af884241a4ed2037c73Rob Herring#include <linux/of_fdt.h> 19e06e8b27082852bdab417af884241a4ed2037c73Rob Herring#include <linux/sizes.h> 20e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 21e06e8b27082852bdab417af884241a4ed2037c73Rob Herring/* Max address size we deal with */ 22e06e8b27082852bdab417af884241a4ed2037c73Rob Herring#define OF_MAX_ADDR_CELLS 4 23e06e8b27082852bdab417af884241a4ed2037c73Rob Herring#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ 24e06e8b27082852bdab417af884241a4ed2037c73Rob Herring (ns) > 0) 25e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 26e06e8b27082852bdab417af884241a4ed2037c73Rob Herring/* Debug utility */ 27e06e8b27082852bdab417af884241a4ed2037c73Rob Herring#ifdef DEBUG 28e06e8b27082852bdab417af884241a4ed2037c73Rob Herringstatic void __init of_dump_addr(const char *s, const __be32 *addr, int na) 29e06e8b27082852bdab417af884241a4ed2037c73Rob Herring{ 30e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_debug("%s", s); 31e06e8b27082852bdab417af884241a4ed2037c73Rob Herring while(na--) 32e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_cont(" %08x", *(addr++)); 33e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_debug("\n"); 34e06e8b27082852bdab417af884241a4ed2037c73Rob Herring} 35e06e8b27082852bdab417af884241a4ed2037c73Rob Herring#else 36e06e8b27082852bdab417af884241a4ed2037c73Rob Herringstatic void __init of_dump_addr(const char *s, const __be32 *addr, int na) { } 37e06e8b27082852bdab417af884241a4ed2037c73Rob Herring#endif 38e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 39e06e8b27082852bdab417af884241a4ed2037c73Rob Herring/* Callbacks for bus specific translators */ 40e06e8b27082852bdab417af884241a4ed2037c73Rob Herringstruct of_bus { 41e06e8b27082852bdab417af884241a4ed2037c73Rob Herring void (*count_cells)(const void *blob, int parentoffset, 42e06e8b27082852bdab417af884241a4ed2037c73Rob Herring int *addrc, int *sizec); 43e06e8b27082852bdab417af884241a4ed2037c73Rob Herring u64 (*map)(__be32 *addr, const __be32 *range, 44e06e8b27082852bdab417af884241a4ed2037c73Rob Herring int na, int ns, int pna); 45e06e8b27082852bdab417af884241a4ed2037c73Rob Herring int (*translate)(__be32 *addr, u64 offset, int na); 46e06e8b27082852bdab417af884241a4ed2037c73Rob Herring}; 47e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 48e06e8b27082852bdab417af884241a4ed2037c73Rob Herring/* Default translator (generic bus) */ 49e06e8b27082852bdab417af884241a4ed2037c73Rob Herringstatic void __init fdt_bus_default_count_cells(const void *blob, int parentoffset, 50e06e8b27082852bdab417af884241a4ed2037c73Rob Herring int *addrc, int *sizec) 51e06e8b27082852bdab417af884241a4ed2037c73Rob Herring{ 52e06e8b27082852bdab417af884241a4ed2037c73Rob Herring const __be32 *prop; 53e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 54e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (addrc) { 55e06e8b27082852bdab417af884241a4ed2037c73Rob Herring prop = fdt_getprop(blob, parentoffset, "#address-cells", NULL); 56e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (prop) 57e06e8b27082852bdab417af884241a4ed2037c73Rob Herring *addrc = be32_to_cpup(prop); 58e06e8b27082852bdab417af884241a4ed2037c73Rob Herring else 59e06e8b27082852bdab417af884241a4ed2037c73Rob Herring *addrc = dt_root_addr_cells; 60e06e8b27082852bdab417af884241a4ed2037c73Rob Herring } 61e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 62e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (sizec) { 63e06e8b27082852bdab417af884241a4ed2037c73Rob Herring prop = fdt_getprop(blob, parentoffset, "#size-cells", NULL); 64e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (prop) 65e06e8b27082852bdab417af884241a4ed2037c73Rob Herring *sizec = be32_to_cpup(prop); 66e06e8b27082852bdab417af884241a4ed2037c73Rob Herring else 67e06e8b27082852bdab417af884241a4ed2037c73Rob Herring *sizec = dt_root_size_cells; 68e06e8b27082852bdab417af884241a4ed2037c73Rob Herring } 69e06e8b27082852bdab417af884241a4ed2037c73Rob Herring} 70e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 71e06e8b27082852bdab417af884241a4ed2037c73Rob Herringstatic u64 __init fdt_bus_default_map(__be32 *addr, const __be32 *range, 72e06e8b27082852bdab417af884241a4ed2037c73Rob Herring int na, int ns, int pna) 73e06e8b27082852bdab417af884241a4ed2037c73Rob Herring{ 74e06e8b27082852bdab417af884241a4ed2037c73Rob Herring u64 cp, s, da; 75e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 76e06e8b27082852bdab417af884241a4ed2037c73Rob Herring cp = of_read_number(range, na); 77e06e8b27082852bdab417af884241a4ed2037c73Rob Herring s = of_read_number(range + na + pna, ns); 78e06e8b27082852bdab417af884241a4ed2037c73Rob Herring da = of_read_number(addr, na); 79e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 80e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_debug("FDT: default map, cp=%llx, s=%llx, da=%llx\n", 81e06e8b27082852bdab417af884241a4ed2037c73Rob Herring cp, s, da); 82e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 83e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (da < cp || da >= (cp + s)) 84e06e8b27082852bdab417af884241a4ed2037c73Rob Herring return OF_BAD_ADDR; 85e06e8b27082852bdab417af884241a4ed2037c73Rob Herring return da - cp; 86e06e8b27082852bdab417af884241a4ed2037c73Rob Herring} 87e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 88e06e8b27082852bdab417af884241a4ed2037c73Rob Herringstatic int __init fdt_bus_default_translate(__be32 *addr, u64 offset, int na) 89e06e8b27082852bdab417af884241a4ed2037c73Rob Herring{ 90e06e8b27082852bdab417af884241a4ed2037c73Rob Herring u64 a = of_read_number(addr, na); 91e06e8b27082852bdab417af884241a4ed2037c73Rob Herring memset(addr, 0, na * 4); 92e06e8b27082852bdab417af884241a4ed2037c73Rob Herring a += offset; 93e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (na > 1) 94e06e8b27082852bdab417af884241a4ed2037c73Rob Herring addr[na - 2] = cpu_to_fdt32(a >> 32); 95e06e8b27082852bdab417af884241a4ed2037c73Rob Herring addr[na - 1] = cpu_to_fdt32(a & 0xffffffffu); 96e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 97e06e8b27082852bdab417af884241a4ed2037c73Rob Herring return 0; 98e06e8b27082852bdab417af884241a4ed2037c73Rob Herring} 99e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 100e06e8b27082852bdab417af884241a4ed2037c73Rob Herring/* Array of bus specific translators */ 101e06e8b27082852bdab417af884241a4ed2037c73Rob Herringstatic const struct of_bus of_busses[] __initconst = { 102e06e8b27082852bdab417af884241a4ed2037c73Rob Herring /* Default */ 103e06e8b27082852bdab417af884241a4ed2037c73Rob Herring { 104e06e8b27082852bdab417af884241a4ed2037c73Rob Herring .count_cells = fdt_bus_default_count_cells, 105e06e8b27082852bdab417af884241a4ed2037c73Rob Herring .map = fdt_bus_default_map, 106e06e8b27082852bdab417af884241a4ed2037c73Rob Herring .translate = fdt_bus_default_translate, 107e06e8b27082852bdab417af884241a4ed2037c73Rob Herring }, 108e06e8b27082852bdab417af884241a4ed2037c73Rob Herring}; 109e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 110e06e8b27082852bdab417af884241a4ed2037c73Rob Herringstatic int __init fdt_translate_one(const void *blob, int parent, 111e06e8b27082852bdab417af884241a4ed2037c73Rob Herring const struct of_bus *bus, 112e06e8b27082852bdab417af884241a4ed2037c73Rob Herring const struct of_bus *pbus, __be32 *addr, 113e06e8b27082852bdab417af884241a4ed2037c73Rob Herring int na, int ns, int pna, const char *rprop) 114e06e8b27082852bdab417af884241a4ed2037c73Rob Herring{ 115e06e8b27082852bdab417af884241a4ed2037c73Rob Herring const __be32 *ranges; 116e06e8b27082852bdab417af884241a4ed2037c73Rob Herring int rlen; 117e06e8b27082852bdab417af884241a4ed2037c73Rob Herring int rone; 118e06e8b27082852bdab417af884241a4ed2037c73Rob Herring u64 offset = OF_BAD_ADDR; 119e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 120e06e8b27082852bdab417af884241a4ed2037c73Rob Herring ranges = fdt_getprop(blob, parent, rprop, &rlen); 121e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (!ranges) 122e06e8b27082852bdab417af884241a4ed2037c73Rob Herring return 1; 123e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (rlen == 0) { 124e06e8b27082852bdab417af884241a4ed2037c73Rob Herring offset = of_read_number(addr, na); 125e06e8b27082852bdab417af884241a4ed2037c73Rob Herring memset(addr, 0, pna * 4); 126e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_debug("FDT: empty ranges, 1:1 translation\n"); 127e06e8b27082852bdab417af884241a4ed2037c73Rob Herring goto finish; 128e06e8b27082852bdab417af884241a4ed2037c73Rob Herring } 129e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 130e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_debug("FDT: walking ranges...\n"); 131e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 132e06e8b27082852bdab417af884241a4ed2037c73Rob Herring /* Now walk through the ranges */ 133e06e8b27082852bdab417af884241a4ed2037c73Rob Herring rlen /= 4; 134e06e8b27082852bdab417af884241a4ed2037c73Rob Herring rone = na + pna + ns; 135e06e8b27082852bdab417af884241a4ed2037c73Rob Herring for (; rlen >= rone; rlen -= rone, ranges += rone) { 136e06e8b27082852bdab417af884241a4ed2037c73Rob Herring offset = bus->map(addr, ranges, na, ns, pna); 137e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (offset != OF_BAD_ADDR) 138e06e8b27082852bdab417af884241a4ed2037c73Rob Herring break; 139e06e8b27082852bdab417af884241a4ed2037c73Rob Herring } 140e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (offset == OF_BAD_ADDR) { 141e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_debug("FDT: not found !\n"); 142e06e8b27082852bdab417af884241a4ed2037c73Rob Herring return 1; 143e06e8b27082852bdab417af884241a4ed2037c73Rob Herring } 144e06e8b27082852bdab417af884241a4ed2037c73Rob Herring memcpy(addr, ranges + na, 4 * pna); 145e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 146e06e8b27082852bdab417af884241a4ed2037c73Rob Herring finish: 147e06e8b27082852bdab417af884241a4ed2037c73Rob Herring of_dump_addr("FDT: parent translation for:", addr, pna); 148e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_debug("FDT: with offset: %llx\n", offset); 149e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 150e06e8b27082852bdab417af884241a4ed2037c73Rob Herring /* Translate it into parent bus space */ 151e06e8b27082852bdab417af884241a4ed2037c73Rob Herring return pbus->translate(addr, offset, pna); 152e06e8b27082852bdab417af884241a4ed2037c73Rob Herring} 153e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 154e06e8b27082852bdab417af884241a4ed2037c73Rob Herring/* 155e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * Translate an address from the device-tree into a CPU physical address, 156e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * this walks up the tree and applies the various bus mappings on the 157e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * way. 158e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * 159e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * Note: We consider that crossing any level with #size-cells == 0 to mean 160e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * that translation is impossible (that is we are not dealing with a value 161e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * that can be mapped to a cpu physical address). This is not really specified 162e06e8b27082852bdab417af884241a4ed2037c73Rob Herring * that way, but this is traditionally the way IBM at least do things 163e06e8b27082852bdab417af884241a4ed2037c73Rob Herring */ 164e06e8b27082852bdab417af884241a4ed2037c73Rob Herringu64 __init fdt_translate_address(const void *blob, int node_offset) 165e06e8b27082852bdab417af884241a4ed2037c73Rob Herring{ 166e06e8b27082852bdab417af884241a4ed2037c73Rob Herring int parent, len; 167e06e8b27082852bdab417af884241a4ed2037c73Rob Herring const struct of_bus *bus, *pbus; 168e06e8b27082852bdab417af884241a4ed2037c73Rob Herring const __be32 *reg; 169e06e8b27082852bdab417af884241a4ed2037c73Rob Herring __be32 addr[OF_MAX_ADDR_CELLS]; 170e06e8b27082852bdab417af884241a4ed2037c73Rob Herring int na, ns, pna, pns; 171e06e8b27082852bdab417af884241a4ed2037c73Rob Herring u64 result = OF_BAD_ADDR; 172e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 173e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_debug("FDT: ** translation for device %s **\n", 174e06e8b27082852bdab417af884241a4ed2037c73Rob Herring fdt_get_name(blob, node_offset, NULL)); 175e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 176e06e8b27082852bdab417af884241a4ed2037c73Rob Herring reg = fdt_getprop(blob, node_offset, "reg", &len); 177e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (!reg) { 178e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_err("FDT: warning: device tree node '%s' has no address.\n", 179e06e8b27082852bdab417af884241a4ed2037c73Rob Herring fdt_get_name(blob, node_offset, NULL)); 180e06e8b27082852bdab417af884241a4ed2037c73Rob Herring goto bail; 181e06e8b27082852bdab417af884241a4ed2037c73Rob Herring } 182e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 183e06e8b27082852bdab417af884241a4ed2037c73Rob Herring /* Get parent & match bus type */ 184e06e8b27082852bdab417af884241a4ed2037c73Rob Herring parent = fdt_parent_offset(blob, node_offset); 185e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (parent < 0) 186e06e8b27082852bdab417af884241a4ed2037c73Rob Herring goto bail; 187e06e8b27082852bdab417af884241a4ed2037c73Rob Herring bus = &of_busses[0]; 188e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 189e06e8b27082852bdab417af884241a4ed2037c73Rob Herring /* Cound address cells & copy address locally */ 190e06e8b27082852bdab417af884241a4ed2037c73Rob Herring bus->count_cells(blob, parent, &na, &ns); 191e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (!OF_CHECK_COUNTS(na, ns)) { 192e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_err("FDT: Bad cell count for %s\n", 193e06e8b27082852bdab417af884241a4ed2037c73Rob Herring fdt_get_name(blob, node_offset, NULL)); 194e06e8b27082852bdab417af884241a4ed2037c73Rob Herring goto bail; 195e06e8b27082852bdab417af884241a4ed2037c73Rob Herring } 196e06e8b27082852bdab417af884241a4ed2037c73Rob Herring memcpy(addr, reg, na * 4); 197e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 198e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_debug("FDT: bus (na=%d, ns=%d) on %s\n", 199e06e8b27082852bdab417af884241a4ed2037c73Rob Herring na, ns, fdt_get_name(blob, parent, NULL)); 200e06e8b27082852bdab417af884241a4ed2037c73Rob Herring of_dump_addr("OF: translating address:", addr, na); 201e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 202e06e8b27082852bdab417af884241a4ed2037c73Rob Herring /* Translate */ 203e06e8b27082852bdab417af884241a4ed2037c73Rob Herring for (;;) { 204e06e8b27082852bdab417af884241a4ed2037c73Rob Herring /* Switch to parent bus */ 205e06e8b27082852bdab417af884241a4ed2037c73Rob Herring node_offset = parent; 206e06e8b27082852bdab417af884241a4ed2037c73Rob Herring parent = fdt_parent_offset(blob, node_offset); 207e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 208e06e8b27082852bdab417af884241a4ed2037c73Rob Herring /* If root, we have finished */ 209e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (parent < 0) { 210e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_debug("FDT: reached root node\n"); 211e06e8b27082852bdab417af884241a4ed2037c73Rob Herring result = of_read_number(addr, na); 212e06e8b27082852bdab417af884241a4ed2037c73Rob Herring break; 213e06e8b27082852bdab417af884241a4ed2037c73Rob Herring } 214e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 215e06e8b27082852bdab417af884241a4ed2037c73Rob Herring /* Get new parent bus and counts */ 216e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pbus = &of_busses[0]; 217e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pbus->count_cells(blob, parent, &pna, &pns); 218e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (!OF_CHECK_COUNTS(pna, pns)) { 219e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_err("FDT: Bad cell count for %s\n", 220e06e8b27082852bdab417af884241a4ed2037c73Rob Herring fdt_get_name(blob, node_offset, NULL)); 221e06e8b27082852bdab417af884241a4ed2037c73Rob Herring break; 222e06e8b27082852bdab417af884241a4ed2037c73Rob Herring } 223e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 224e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pr_debug("FDT: parent bus (na=%d, ns=%d) on %s\n", 225e06e8b27082852bdab417af884241a4ed2037c73Rob Herring pna, pns, fdt_get_name(blob, parent, NULL)); 226e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 227e06e8b27082852bdab417af884241a4ed2037c73Rob Herring /* Apply bus translation */ 228e06e8b27082852bdab417af884241a4ed2037c73Rob Herring if (fdt_translate_one(blob, node_offset, bus, pbus, 229e06e8b27082852bdab417af884241a4ed2037c73Rob Herring addr, na, ns, pna, "ranges")) 230e06e8b27082852bdab417af884241a4ed2037c73Rob Herring break; 231e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 232e06e8b27082852bdab417af884241a4ed2037c73Rob Herring /* Complete the move up one level */ 233e06e8b27082852bdab417af884241a4ed2037c73Rob Herring na = pna; 234e06e8b27082852bdab417af884241a4ed2037c73Rob Herring ns = pns; 235e06e8b27082852bdab417af884241a4ed2037c73Rob Herring bus = pbus; 236e06e8b27082852bdab417af884241a4ed2037c73Rob Herring 237e06e8b27082852bdab417af884241a4ed2037c73Rob Herring of_dump_addr("FDT: one level translation:", addr, na); 238e06e8b27082852bdab417af884241a4ed2037c73Rob Herring } 239e06e8b27082852bdab417af884241a4ed2037c73Rob Herring bail: 240e06e8b27082852bdab417af884241a4ed2037c73Rob Herring return result; 241e06e8b27082852bdab417af884241a4ed2037c73Rob Herring} 242