16b884a8dSGrant Likely 26b884a8dSGrant Likely #include <linux/io.h> 36b884a8dSGrant Likely #include <linux/ioport.h> 4dbbdee94SGrant Likely #include <linux/module.h> 56b884a8dSGrant Likely #include <linux/of_address.h> 6dbbdee94SGrant Likely #include <linux/pci_regs.h> 7dbbdee94SGrant Likely #include <linux/string.h> 86b884a8dSGrant Likely 9dbbdee94SGrant Likely /* Max address size we deal with */ 10dbbdee94SGrant Likely #define OF_MAX_ADDR_CELLS 4 11dbbdee94SGrant Likely #define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ 12dbbdee94SGrant Likely (ns) > 0) 13dbbdee94SGrant Likely 14dbbdee94SGrant Likely static struct of_bus *of_match_bus(struct device_node *np); 150131d897SSebastian Andrzej Siewior static int __of_address_to_resource(struct device_node *dev, 160131d897SSebastian Andrzej Siewior const __be32 *addrp, u64 size, unsigned int flags, 17dbbdee94SGrant Likely struct resource *r); 18dbbdee94SGrant Likely 19dbbdee94SGrant Likely /* Debug utility */ 20dbbdee94SGrant Likely #ifdef DEBUG 210131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na) 22dbbdee94SGrant Likely { 23dbbdee94SGrant Likely printk(KERN_DEBUG "%s", s); 24dbbdee94SGrant Likely while (na--) 25154063a9SGrant Likely printk(" %08x", be32_to_cpu(*(addr++))); 26dbbdee94SGrant Likely printk("\n"); 27dbbdee94SGrant Likely } 28dbbdee94SGrant Likely #else 290131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na) { } 30dbbdee94SGrant Likely #endif 31dbbdee94SGrant Likely 32dbbdee94SGrant Likely /* Callbacks for bus specific translators */ 33dbbdee94SGrant Likely struct of_bus { 34dbbdee94SGrant Likely const char *name; 35dbbdee94SGrant Likely const char *addresses; 36dbbdee94SGrant Likely int (*match)(struct device_node *parent); 37dbbdee94SGrant Likely void (*count_cells)(struct device_node *child, 38dbbdee94SGrant Likely int *addrc, int *sizec); 390131d897SSebastian Andrzej Siewior u64 (*map)(u32 *addr, const __be32 *range, 40dbbdee94SGrant Likely int na, int ns, int pna); 41dbbdee94SGrant Likely int (*translate)(u32 *addr, u64 offset, int na); 420131d897SSebastian Andrzej Siewior unsigned int (*get_flags)(const __be32 *addr); 43dbbdee94SGrant Likely }; 44dbbdee94SGrant Likely 45dbbdee94SGrant Likely /* 46dbbdee94SGrant Likely * Default translator (generic bus) 47dbbdee94SGrant Likely */ 48dbbdee94SGrant Likely 49dbbdee94SGrant Likely static void of_bus_default_count_cells(struct device_node *dev, 50dbbdee94SGrant Likely int *addrc, int *sizec) 51dbbdee94SGrant Likely { 52dbbdee94SGrant Likely if (addrc) 53dbbdee94SGrant Likely *addrc = of_n_addr_cells(dev); 54dbbdee94SGrant Likely if (sizec) 55dbbdee94SGrant Likely *sizec = of_n_size_cells(dev); 56dbbdee94SGrant Likely } 57dbbdee94SGrant Likely 580131d897SSebastian Andrzej Siewior static u64 of_bus_default_map(u32 *addr, const __be32 *range, 59dbbdee94SGrant Likely int na, int ns, int pna) 60dbbdee94SGrant Likely { 61dbbdee94SGrant Likely u64 cp, s, da; 62dbbdee94SGrant Likely 63dbbdee94SGrant Likely cp = of_read_number(range, na); 64dbbdee94SGrant Likely s = of_read_number(range + na + pna, ns); 65dbbdee94SGrant Likely da = of_read_number(addr, na); 66dbbdee94SGrant Likely 67dbbdee94SGrant Likely pr_debug("OF: default map, cp=%llx, s=%llx, da=%llx\n", 68dbbdee94SGrant Likely (unsigned long long)cp, (unsigned long long)s, 69dbbdee94SGrant Likely (unsigned long long)da); 70dbbdee94SGrant Likely 71dbbdee94SGrant Likely if (da < cp || da >= (cp + s)) 72dbbdee94SGrant Likely return OF_BAD_ADDR; 73dbbdee94SGrant Likely return da - cp; 74dbbdee94SGrant Likely } 75dbbdee94SGrant Likely 76dbbdee94SGrant Likely static int of_bus_default_translate(u32 *addr, u64 offset, int na) 77dbbdee94SGrant Likely { 78dbbdee94SGrant Likely u64 a = of_read_number(addr, na); 79dbbdee94SGrant Likely memset(addr, 0, na * 4); 80dbbdee94SGrant Likely a += offset; 81dbbdee94SGrant Likely if (na > 1) 82154063a9SGrant Likely addr[na - 2] = cpu_to_be32(a >> 32); 83154063a9SGrant Likely addr[na - 1] = cpu_to_be32(a & 0xffffffffu); 84dbbdee94SGrant Likely 85dbbdee94SGrant Likely return 0; 86dbbdee94SGrant Likely } 87dbbdee94SGrant Likely 880131d897SSebastian Andrzej Siewior static unsigned int of_bus_default_get_flags(const __be32 *addr) 89dbbdee94SGrant Likely { 90dbbdee94SGrant Likely return IORESOURCE_MEM; 91dbbdee94SGrant Likely } 92dbbdee94SGrant Likely 93dbbdee94SGrant Likely #ifdef CONFIG_PCI 94dbbdee94SGrant Likely /* 95dbbdee94SGrant Likely * PCI bus specific translator 96dbbdee94SGrant Likely */ 97dbbdee94SGrant Likely 98dbbdee94SGrant Likely static int of_bus_pci_match(struct device_node *np) 99dbbdee94SGrant Likely { 100dbbdee94SGrant Likely /* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */ 101dbbdee94SGrant Likely return !strcmp(np->type, "pci") || !strcmp(np->type, "vci"); 102dbbdee94SGrant Likely } 103dbbdee94SGrant Likely 104dbbdee94SGrant Likely static void of_bus_pci_count_cells(struct device_node *np, 105dbbdee94SGrant Likely int *addrc, int *sizec) 106dbbdee94SGrant Likely { 107dbbdee94SGrant Likely if (addrc) 108dbbdee94SGrant Likely *addrc = 3; 109dbbdee94SGrant Likely if (sizec) 110dbbdee94SGrant Likely *sizec = 2; 111dbbdee94SGrant Likely } 112dbbdee94SGrant Likely 1130131d897SSebastian Andrzej Siewior static unsigned int of_bus_pci_get_flags(const __be32 *addr) 114dbbdee94SGrant Likely { 115dbbdee94SGrant Likely unsigned int flags = 0; 1160131d897SSebastian Andrzej Siewior u32 w = be32_to_cpup(addr); 117dbbdee94SGrant Likely 118dbbdee94SGrant Likely switch((w >> 24) & 0x03) { 119dbbdee94SGrant Likely case 0x01: 120dbbdee94SGrant Likely flags |= IORESOURCE_IO; 121dbbdee94SGrant Likely break; 122dbbdee94SGrant Likely case 0x02: /* 32 bits */ 123dbbdee94SGrant Likely case 0x03: /* 64 bits */ 124dbbdee94SGrant Likely flags |= IORESOURCE_MEM; 125dbbdee94SGrant Likely break; 126dbbdee94SGrant Likely } 127dbbdee94SGrant Likely if (w & 0x40000000) 128dbbdee94SGrant Likely flags |= IORESOURCE_PREFETCH; 129dbbdee94SGrant Likely return flags; 130dbbdee94SGrant Likely } 131dbbdee94SGrant Likely 1320131d897SSebastian Andrzej Siewior static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns, 1330131d897SSebastian Andrzej Siewior int pna) 134dbbdee94SGrant Likely { 135dbbdee94SGrant Likely u64 cp, s, da; 136dbbdee94SGrant Likely unsigned int af, rf; 137dbbdee94SGrant Likely 138dbbdee94SGrant Likely af = of_bus_pci_get_flags(addr); 139dbbdee94SGrant Likely rf = of_bus_pci_get_flags(range); 140dbbdee94SGrant Likely 141dbbdee94SGrant Likely /* Check address type match */ 142dbbdee94SGrant Likely if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO)) 143dbbdee94SGrant Likely return OF_BAD_ADDR; 144dbbdee94SGrant Likely 145dbbdee94SGrant Likely /* Read address values, skipping high cell */ 146dbbdee94SGrant Likely cp = of_read_number(range + 1, na - 1); 147dbbdee94SGrant Likely s = of_read_number(range + na + pna, ns); 148dbbdee94SGrant Likely da = of_read_number(addr + 1, na - 1); 149dbbdee94SGrant Likely 150dbbdee94SGrant Likely pr_debug("OF: PCI map, cp=%llx, s=%llx, da=%llx\n", 151dbbdee94SGrant Likely (unsigned long long)cp, (unsigned long long)s, 152dbbdee94SGrant Likely (unsigned long long)da); 153dbbdee94SGrant Likely 154dbbdee94SGrant Likely if (da < cp || da >= (cp + s)) 155dbbdee94SGrant Likely return OF_BAD_ADDR; 156dbbdee94SGrant Likely return da - cp; 157dbbdee94SGrant Likely } 158dbbdee94SGrant Likely 159dbbdee94SGrant Likely static int of_bus_pci_translate(u32 *addr, u64 offset, int na) 160dbbdee94SGrant Likely { 161dbbdee94SGrant Likely return of_bus_default_translate(addr + 1, offset, na - 1); 162dbbdee94SGrant Likely } 163dbbdee94SGrant Likely 1640131d897SSebastian Andrzej Siewior const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, 165dbbdee94SGrant Likely unsigned int *flags) 166dbbdee94SGrant Likely { 167a9fadeefSJeremy Kerr const __be32 *prop; 168dbbdee94SGrant Likely unsigned int psize; 169dbbdee94SGrant Likely struct device_node *parent; 170dbbdee94SGrant Likely struct of_bus *bus; 171dbbdee94SGrant Likely int onesize, i, na, ns; 172dbbdee94SGrant Likely 173dbbdee94SGrant Likely /* Get parent & match bus type */ 174dbbdee94SGrant Likely parent = of_get_parent(dev); 175dbbdee94SGrant Likely if (parent == NULL) 176dbbdee94SGrant Likely return NULL; 177dbbdee94SGrant Likely bus = of_match_bus(parent); 178dbbdee94SGrant Likely if (strcmp(bus->name, "pci")) { 179dbbdee94SGrant Likely of_node_put(parent); 180dbbdee94SGrant Likely return NULL; 181dbbdee94SGrant Likely } 182dbbdee94SGrant Likely bus->count_cells(dev, &na, &ns); 183dbbdee94SGrant Likely of_node_put(parent); 184dbbdee94SGrant Likely if (!OF_CHECK_COUNTS(na, ns)) 185dbbdee94SGrant Likely return NULL; 186dbbdee94SGrant Likely 187dbbdee94SGrant Likely /* Get "reg" or "assigned-addresses" property */ 188dbbdee94SGrant Likely prop = of_get_property(dev, bus->addresses, &psize); 189dbbdee94SGrant Likely if (prop == NULL) 190dbbdee94SGrant Likely return NULL; 191dbbdee94SGrant Likely psize /= 4; 192dbbdee94SGrant Likely 193dbbdee94SGrant Likely onesize = na + ns; 194154063a9SGrant Likely for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) { 195154063a9SGrant Likely u32 val = be32_to_cpu(prop[0]); 196154063a9SGrant Likely if ((val & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) { 197dbbdee94SGrant Likely if (size) 198dbbdee94SGrant Likely *size = of_read_number(prop + na, ns); 199dbbdee94SGrant Likely if (flags) 200dbbdee94SGrant Likely *flags = bus->get_flags(prop); 201dbbdee94SGrant Likely return prop; 202dbbdee94SGrant Likely } 203154063a9SGrant Likely } 204dbbdee94SGrant Likely return NULL; 205dbbdee94SGrant Likely } 206dbbdee94SGrant Likely EXPORT_SYMBOL(of_get_pci_address); 207dbbdee94SGrant Likely 208dbbdee94SGrant Likely int of_pci_address_to_resource(struct device_node *dev, int bar, 209dbbdee94SGrant Likely struct resource *r) 210dbbdee94SGrant Likely { 2110131d897SSebastian Andrzej Siewior const __be32 *addrp; 212dbbdee94SGrant Likely u64 size; 213dbbdee94SGrant Likely unsigned int flags; 214dbbdee94SGrant Likely 215dbbdee94SGrant Likely addrp = of_get_pci_address(dev, bar, &size, &flags); 216dbbdee94SGrant Likely if (addrp == NULL) 217dbbdee94SGrant Likely return -EINVAL; 218dbbdee94SGrant Likely return __of_address_to_resource(dev, addrp, size, flags, r); 219dbbdee94SGrant Likely } 220dbbdee94SGrant Likely EXPORT_SYMBOL_GPL(of_pci_address_to_resource); 221dbbdee94SGrant Likely #endif /* CONFIG_PCI */ 222dbbdee94SGrant Likely 223dbbdee94SGrant Likely /* 224dbbdee94SGrant Likely * ISA bus specific translator 225dbbdee94SGrant Likely */ 226dbbdee94SGrant Likely 227dbbdee94SGrant Likely static int of_bus_isa_match(struct device_node *np) 228dbbdee94SGrant Likely { 229dbbdee94SGrant Likely return !strcmp(np->name, "isa"); 230dbbdee94SGrant Likely } 231dbbdee94SGrant Likely 232dbbdee94SGrant Likely static void of_bus_isa_count_cells(struct device_node *child, 233dbbdee94SGrant Likely int *addrc, int *sizec) 234dbbdee94SGrant Likely { 235dbbdee94SGrant Likely if (addrc) 236dbbdee94SGrant Likely *addrc = 2; 237dbbdee94SGrant Likely if (sizec) 238dbbdee94SGrant Likely *sizec = 1; 239dbbdee94SGrant Likely } 240dbbdee94SGrant Likely 2410131d897SSebastian Andrzej Siewior static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns, 2420131d897SSebastian Andrzej Siewior int pna) 243dbbdee94SGrant Likely { 244dbbdee94SGrant Likely u64 cp, s, da; 245dbbdee94SGrant Likely 246dbbdee94SGrant Likely /* Check address type match */ 2470131d897SSebastian Andrzej Siewior if ((addr[0] ^ range[0]) & cpu_to_be32(1)) 248dbbdee94SGrant Likely return OF_BAD_ADDR; 249dbbdee94SGrant Likely 250dbbdee94SGrant Likely /* Read address values, skipping high cell */ 251dbbdee94SGrant Likely cp = of_read_number(range + 1, na - 1); 252dbbdee94SGrant Likely s = of_read_number(range + na + pna, ns); 253dbbdee94SGrant Likely da = of_read_number(addr + 1, na - 1); 254dbbdee94SGrant Likely 255dbbdee94SGrant Likely pr_debug("OF: ISA map, cp=%llx, s=%llx, da=%llx\n", 256dbbdee94SGrant Likely (unsigned long long)cp, (unsigned long long)s, 257dbbdee94SGrant Likely (unsigned long long)da); 258dbbdee94SGrant Likely 259dbbdee94SGrant Likely if (da < cp || da >= (cp + s)) 260dbbdee94SGrant Likely return OF_BAD_ADDR; 261dbbdee94SGrant Likely return da - cp; 262dbbdee94SGrant Likely } 263dbbdee94SGrant Likely 264dbbdee94SGrant Likely static int of_bus_isa_translate(u32 *addr, u64 offset, int na) 265dbbdee94SGrant Likely { 266dbbdee94SGrant Likely return of_bus_default_translate(addr + 1, offset, na - 1); 267dbbdee94SGrant Likely } 268dbbdee94SGrant Likely 2690131d897SSebastian Andrzej Siewior static unsigned int of_bus_isa_get_flags(const __be32 *addr) 270dbbdee94SGrant Likely { 271dbbdee94SGrant Likely unsigned int flags = 0; 2720131d897SSebastian Andrzej Siewior u32 w = be32_to_cpup(addr); 273dbbdee94SGrant Likely 274dbbdee94SGrant Likely if (w & 1) 275dbbdee94SGrant Likely flags |= IORESOURCE_IO; 276dbbdee94SGrant Likely else 277dbbdee94SGrant Likely flags |= IORESOURCE_MEM; 278dbbdee94SGrant Likely return flags; 279dbbdee94SGrant Likely } 280dbbdee94SGrant Likely 281dbbdee94SGrant Likely /* 282dbbdee94SGrant Likely * Array of bus specific translators 283dbbdee94SGrant Likely */ 284dbbdee94SGrant Likely 285dbbdee94SGrant Likely static struct of_bus of_busses[] = { 286dbbdee94SGrant Likely #ifdef CONFIG_PCI 287dbbdee94SGrant Likely /* PCI */ 288dbbdee94SGrant Likely { 289dbbdee94SGrant Likely .name = "pci", 290dbbdee94SGrant Likely .addresses = "assigned-addresses", 291dbbdee94SGrant Likely .match = of_bus_pci_match, 292dbbdee94SGrant Likely .count_cells = of_bus_pci_count_cells, 293dbbdee94SGrant Likely .map = of_bus_pci_map, 294dbbdee94SGrant Likely .translate = of_bus_pci_translate, 295dbbdee94SGrant Likely .get_flags = of_bus_pci_get_flags, 296dbbdee94SGrant Likely }, 297dbbdee94SGrant Likely #endif /* CONFIG_PCI */ 298dbbdee94SGrant Likely /* ISA */ 299dbbdee94SGrant Likely { 300dbbdee94SGrant Likely .name = "isa", 301dbbdee94SGrant Likely .addresses = "reg", 302dbbdee94SGrant Likely .match = of_bus_isa_match, 303dbbdee94SGrant Likely .count_cells = of_bus_isa_count_cells, 304dbbdee94SGrant Likely .map = of_bus_isa_map, 305dbbdee94SGrant Likely .translate = of_bus_isa_translate, 306dbbdee94SGrant Likely .get_flags = of_bus_isa_get_flags, 307dbbdee94SGrant Likely }, 308dbbdee94SGrant Likely /* Default */ 309dbbdee94SGrant Likely { 310dbbdee94SGrant Likely .name = "default", 311dbbdee94SGrant Likely .addresses = "reg", 312dbbdee94SGrant Likely .match = NULL, 313dbbdee94SGrant Likely .count_cells = of_bus_default_count_cells, 314dbbdee94SGrant Likely .map = of_bus_default_map, 315dbbdee94SGrant Likely .translate = of_bus_default_translate, 316dbbdee94SGrant Likely .get_flags = of_bus_default_get_flags, 317dbbdee94SGrant Likely }, 318dbbdee94SGrant Likely }; 319dbbdee94SGrant Likely 320dbbdee94SGrant Likely static struct of_bus *of_match_bus(struct device_node *np) 321dbbdee94SGrant Likely { 322dbbdee94SGrant Likely int i; 323dbbdee94SGrant Likely 324dbbdee94SGrant Likely for (i = 0; i < ARRAY_SIZE(of_busses); i++) 325dbbdee94SGrant Likely if (!of_busses[i].match || of_busses[i].match(np)) 326dbbdee94SGrant Likely return &of_busses[i]; 327dbbdee94SGrant Likely BUG(); 328dbbdee94SGrant Likely return NULL; 329dbbdee94SGrant Likely } 330dbbdee94SGrant Likely 331dbbdee94SGrant Likely static int of_translate_one(struct device_node *parent, struct of_bus *bus, 332dbbdee94SGrant Likely struct of_bus *pbus, u32 *addr, 333dbbdee94SGrant Likely int na, int ns, int pna, const char *rprop) 334dbbdee94SGrant Likely { 3350131d897SSebastian Andrzej Siewior const __be32 *ranges; 336dbbdee94SGrant Likely unsigned int rlen; 337dbbdee94SGrant Likely int rone; 338dbbdee94SGrant Likely u64 offset = OF_BAD_ADDR; 339dbbdee94SGrant Likely 340dbbdee94SGrant Likely /* Normally, an absence of a "ranges" property means we are 341dbbdee94SGrant Likely * crossing a non-translatable boundary, and thus the addresses 342dbbdee94SGrant Likely * below the current not cannot be converted to CPU physical ones. 343dbbdee94SGrant Likely * Unfortunately, while this is very clear in the spec, it's not 344dbbdee94SGrant Likely * what Apple understood, and they do have things like /uni-n or 345dbbdee94SGrant Likely * /ht nodes with no "ranges" property and a lot of perfectly 346dbbdee94SGrant Likely * useable mapped devices below them. Thus we treat the absence of 347dbbdee94SGrant Likely * "ranges" as equivalent to an empty "ranges" property which means 348dbbdee94SGrant Likely * a 1:1 translation at that level. It's up to the caller not to try 349dbbdee94SGrant Likely * to translate addresses that aren't supposed to be translated in 350dbbdee94SGrant Likely * the first place. --BenH. 3513930f294SGrant Likely * 3523930f294SGrant Likely * As far as we know, this damage only exists on Apple machines, so 3533930f294SGrant Likely * This code is only enabled on powerpc. --gcl 354dbbdee94SGrant Likely */ 355dbbdee94SGrant Likely ranges = of_get_property(parent, rprop, &rlen); 3563930f294SGrant Likely #if !defined(CONFIG_PPC) 3573930f294SGrant Likely if (ranges == NULL) { 3583930f294SGrant Likely pr_err("OF: no ranges; cannot translate\n"); 3593930f294SGrant Likely return 1; 3603930f294SGrant Likely } 3613930f294SGrant Likely #endif /* !defined(CONFIG_PPC) */ 362dbbdee94SGrant Likely if (ranges == NULL || rlen == 0) { 363dbbdee94SGrant Likely offset = of_read_number(addr, na); 364dbbdee94SGrant Likely memset(addr, 0, pna * 4); 3653930f294SGrant Likely pr_debug("OF: empty ranges; 1:1 translation\n"); 366dbbdee94SGrant Likely goto finish; 367dbbdee94SGrant Likely } 368dbbdee94SGrant Likely 369dbbdee94SGrant Likely pr_debug("OF: walking ranges...\n"); 370dbbdee94SGrant Likely 371dbbdee94SGrant Likely /* Now walk through the ranges */ 372dbbdee94SGrant Likely rlen /= 4; 373dbbdee94SGrant Likely rone = na + pna + ns; 374dbbdee94SGrant Likely for (; rlen >= rone; rlen -= rone, ranges += rone) { 375dbbdee94SGrant Likely offset = bus->map(addr, ranges, na, ns, pna); 376dbbdee94SGrant Likely if (offset != OF_BAD_ADDR) 377dbbdee94SGrant Likely break; 378dbbdee94SGrant Likely } 379dbbdee94SGrant Likely if (offset == OF_BAD_ADDR) { 380dbbdee94SGrant Likely pr_debug("OF: not found !\n"); 381dbbdee94SGrant Likely return 1; 382dbbdee94SGrant Likely } 383dbbdee94SGrant Likely memcpy(addr, ranges + na, 4 * pna); 384dbbdee94SGrant Likely 385dbbdee94SGrant Likely finish: 386dbbdee94SGrant Likely of_dump_addr("OF: parent translation for:", addr, pna); 387dbbdee94SGrant Likely pr_debug("OF: with offset: %llx\n", (unsigned long long)offset); 388dbbdee94SGrant Likely 389dbbdee94SGrant Likely /* Translate it into parent bus space */ 390dbbdee94SGrant Likely return pbus->translate(addr, offset, pna); 391dbbdee94SGrant Likely } 392dbbdee94SGrant Likely 393dbbdee94SGrant Likely /* 394dbbdee94SGrant Likely * Translate an address from the device-tree into a CPU physical address, 395dbbdee94SGrant Likely * this walks up the tree and applies the various bus mappings on the 396dbbdee94SGrant Likely * way. 397dbbdee94SGrant Likely * 398dbbdee94SGrant Likely * Note: We consider that crossing any level with #size-cells == 0 to mean 399dbbdee94SGrant Likely * that translation is impossible (that is we are not dealing with a value 400dbbdee94SGrant Likely * that can be mapped to a cpu physical address). This is not really specified 401dbbdee94SGrant Likely * that way, but this is traditionally the way IBM at least do things 402dbbdee94SGrant Likely */ 4030131d897SSebastian Andrzej Siewior u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr, 404dbbdee94SGrant Likely const char *rprop) 405dbbdee94SGrant Likely { 406dbbdee94SGrant Likely struct device_node *parent = NULL; 407dbbdee94SGrant Likely struct of_bus *bus, *pbus; 408dbbdee94SGrant Likely u32 addr[OF_MAX_ADDR_CELLS]; 409dbbdee94SGrant Likely int na, ns, pna, pns; 410dbbdee94SGrant Likely u64 result = OF_BAD_ADDR; 411dbbdee94SGrant Likely 412dbbdee94SGrant Likely pr_debug("OF: ** translation for device %s **\n", dev->full_name); 413dbbdee94SGrant Likely 414dbbdee94SGrant Likely /* Increase refcount at current level */ 415dbbdee94SGrant Likely of_node_get(dev); 416dbbdee94SGrant Likely 417dbbdee94SGrant Likely /* Get parent & match bus type */ 418dbbdee94SGrant Likely parent = of_get_parent(dev); 419dbbdee94SGrant Likely if (parent == NULL) 420dbbdee94SGrant Likely goto bail; 421dbbdee94SGrant Likely bus = of_match_bus(parent); 422dbbdee94SGrant Likely 423dbbdee94SGrant Likely /* Cound address cells & copy address locally */ 424dbbdee94SGrant Likely bus->count_cells(dev, &na, &ns); 425dbbdee94SGrant Likely if (!OF_CHECK_COUNTS(na, ns)) { 426dbbdee94SGrant Likely printk(KERN_ERR "prom_parse: Bad cell count for %s\n", 427dbbdee94SGrant Likely dev->full_name); 428dbbdee94SGrant Likely goto bail; 429dbbdee94SGrant Likely } 430dbbdee94SGrant Likely memcpy(addr, in_addr, na * 4); 431dbbdee94SGrant Likely 432dbbdee94SGrant Likely pr_debug("OF: bus is %s (na=%d, ns=%d) on %s\n", 433dbbdee94SGrant Likely bus->name, na, ns, parent->full_name); 434dbbdee94SGrant Likely of_dump_addr("OF: translating address:", addr, na); 435dbbdee94SGrant Likely 436dbbdee94SGrant Likely /* Translate */ 437dbbdee94SGrant Likely for (;;) { 438dbbdee94SGrant Likely /* Switch to parent bus */ 439dbbdee94SGrant Likely of_node_put(dev); 440dbbdee94SGrant Likely dev = parent; 441dbbdee94SGrant Likely parent = of_get_parent(dev); 442dbbdee94SGrant Likely 443dbbdee94SGrant Likely /* If root, we have finished */ 444dbbdee94SGrant Likely if (parent == NULL) { 445dbbdee94SGrant Likely pr_debug("OF: reached root node\n"); 446dbbdee94SGrant Likely result = of_read_number(addr, na); 447dbbdee94SGrant Likely break; 448dbbdee94SGrant Likely } 449dbbdee94SGrant Likely 450dbbdee94SGrant Likely /* Get new parent bus and counts */ 451dbbdee94SGrant Likely pbus = of_match_bus(parent); 452dbbdee94SGrant Likely pbus->count_cells(dev, &pna, &pns); 453dbbdee94SGrant Likely if (!OF_CHECK_COUNTS(pna, pns)) { 454dbbdee94SGrant Likely printk(KERN_ERR "prom_parse: Bad cell count for %s\n", 455dbbdee94SGrant Likely dev->full_name); 456dbbdee94SGrant Likely break; 457dbbdee94SGrant Likely } 458dbbdee94SGrant Likely 459dbbdee94SGrant Likely pr_debug("OF: parent bus is %s (na=%d, ns=%d) on %s\n", 460dbbdee94SGrant Likely pbus->name, pna, pns, parent->full_name); 461dbbdee94SGrant Likely 462dbbdee94SGrant Likely /* Apply bus translation */ 463dbbdee94SGrant Likely if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) 464dbbdee94SGrant Likely break; 465dbbdee94SGrant Likely 466dbbdee94SGrant Likely /* Complete the move up one level */ 467dbbdee94SGrant Likely na = pna; 468dbbdee94SGrant Likely ns = pns; 469dbbdee94SGrant Likely bus = pbus; 470dbbdee94SGrant Likely 471dbbdee94SGrant Likely of_dump_addr("OF: one level translation:", addr, na); 472dbbdee94SGrant Likely } 473dbbdee94SGrant Likely bail: 474dbbdee94SGrant Likely of_node_put(parent); 475dbbdee94SGrant Likely of_node_put(dev); 476dbbdee94SGrant Likely 477dbbdee94SGrant Likely return result; 478dbbdee94SGrant Likely } 479dbbdee94SGrant Likely 4800131d897SSebastian Andrzej Siewior u64 of_translate_address(struct device_node *dev, const __be32 *in_addr) 481dbbdee94SGrant Likely { 482dbbdee94SGrant Likely return __of_translate_address(dev, in_addr, "ranges"); 483dbbdee94SGrant Likely } 484dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_address); 485dbbdee94SGrant Likely 4860131d897SSebastian Andrzej Siewior u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) 487dbbdee94SGrant Likely { 488dbbdee94SGrant Likely return __of_translate_address(dev, in_addr, "dma-ranges"); 489dbbdee94SGrant Likely } 490dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_dma_address); 491dbbdee94SGrant Likely 4920131d897SSebastian Andrzej Siewior const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, 493dbbdee94SGrant Likely unsigned int *flags) 494dbbdee94SGrant Likely { 4950131d897SSebastian Andrzej Siewior const __be32 *prop; 496dbbdee94SGrant Likely unsigned int psize; 497dbbdee94SGrant Likely struct device_node *parent; 498dbbdee94SGrant Likely struct of_bus *bus; 499dbbdee94SGrant Likely int onesize, i, na, ns; 500dbbdee94SGrant Likely 501dbbdee94SGrant Likely /* Get parent & match bus type */ 502dbbdee94SGrant Likely parent = of_get_parent(dev); 503dbbdee94SGrant Likely if (parent == NULL) 504dbbdee94SGrant Likely return NULL; 505dbbdee94SGrant Likely bus = of_match_bus(parent); 506dbbdee94SGrant Likely bus->count_cells(dev, &na, &ns); 507dbbdee94SGrant Likely of_node_put(parent); 508dbbdee94SGrant Likely if (!OF_CHECK_COUNTS(na, ns)) 509dbbdee94SGrant Likely return NULL; 510dbbdee94SGrant Likely 511dbbdee94SGrant Likely /* Get "reg" or "assigned-addresses" property */ 512dbbdee94SGrant Likely prop = of_get_property(dev, bus->addresses, &psize); 513dbbdee94SGrant Likely if (prop == NULL) 514dbbdee94SGrant Likely return NULL; 515dbbdee94SGrant Likely psize /= 4; 516dbbdee94SGrant Likely 517dbbdee94SGrant Likely onesize = na + ns; 518dbbdee94SGrant Likely for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) 519dbbdee94SGrant Likely if (i == index) { 520dbbdee94SGrant Likely if (size) 521dbbdee94SGrant Likely *size = of_read_number(prop + na, ns); 522dbbdee94SGrant Likely if (flags) 523dbbdee94SGrant Likely *flags = bus->get_flags(prop); 524dbbdee94SGrant Likely return prop; 525dbbdee94SGrant Likely } 526dbbdee94SGrant Likely return NULL; 527dbbdee94SGrant Likely } 528dbbdee94SGrant Likely EXPORT_SYMBOL(of_get_address); 529dbbdee94SGrant Likely 5300131d897SSebastian Andrzej Siewior static int __of_address_to_resource(struct device_node *dev, 5310131d897SSebastian Andrzej Siewior const __be32 *addrp, u64 size, unsigned int flags, 5321f5bef30SGrant Likely struct resource *r) 5331f5bef30SGrant Likely { 5341f5bef30SGrant Likely u64 taddr; 5351f5bef30SGrant Likely 5361f5bef30SGrant Likely if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0) 5371f5bef30SGrant Likely return -EINVAL; 5381f5bef30SGrant Likely taddr = of_translate_address(dev, addrp); 5391f5bef30SGrant Likely if (taddr == OF_BAD_ADDR) 5401f5bef30SGrant Likely return -EINVAL; 5411f5bef30SGrant Likely memset(r, 0, sizeof(struct resource)); 5421f5bef30SGrant Likely if (flags & IORESOURCE_IO) { 5431f5bef30SGrant Likely unsigned long port; 5441f5bef30SGrant Likely port = pci_address_to_pio(taddr); 5451f5bef30SGrant Likely if (port == (unsigned long)-1) 5461f5bef30SGrant Likely return -EINVAL; 5471f5bef30SGrant Likely r->start = port; 5481f5bef30SGrant Likely r->end = port + size - 1; 5491f5bef30SGrant Likely } else { 5501f5bef30SGrant Likely r->start = taddr; 5511f5bef30SGrant Likely r->end = taddr + size - 1; 5521f5bef30SGrant Likely } 5531f5bef30SGrant Likely r->flags = flags; 554d3571c3aSGrant Likely r->name = dev->full_name; 5551f5bef30SGrant Likely return 0; 5561f5bef30SGrant Likely } 5571f5bef30SGrant Likely 5581f5bef30SGrant Likely /** 5591f5bef30SGrant Likely * of_address_to_resource - Translate device tree address and return as resource 5601f5bef30SGrant Likely * 5611f5bef30SGrant Likely * Note that if your address is a PIO address, the conversion will fail if 5621f5bef30SGrant Likely * the physical address can't be internally converted to an IO token with 5631f5bef30SGrant Likely * pci_address_to_pio(), that is because it's either called to early or it 5641f5bef30SGrant Likely * can't be matched to any host bridge IO space 5651f5bef30SGrant Likely */ 5661f5bef30SGrant Likely int of_address_to_resource(struct device_node *dev, int index, 5671f5bef30SGrant Likely struct resource *r) 5681f5bef30SGrant Likely { 5690131d897SSebastian Andrzej Siewior const __be32 *addrp; 5701f5bef30SGrant Likely u64 size; 5711f5bef30SGrant Likely unsigned int flags; 5721f5bef30SGrant Likely 5731f5bef30SGrant Likely addrp = of_get_address(dev, index, &size, &flags); 5741f5bef30SGrant Likely if (addrp == NULL) 5751f5bef30SGrant Likely return -EINVAL; 5761f5bef30SGrant Likely return __of_address_to_resource(dev, addrp, size, flags, r); 5771f5bef30SGrant Likely } 5781f5bef30SGrant Likely EXPORT_SYMBOL_GPL(of_address_to_resource); 5791f5bef30SGrant Likely 58090e33f62SGrant Likely struct device_node *of_find_matching_node_by_address(struct device_node *from, 58190e33f62SGrant Likely const struct of_device_id *matches, 58290e33f62SGrant Likely u64 base_address) 58390e33f62SGrant Likely { 58490e33f62SGrant Likely struct device_node *dn = of_find_matching_node(from, matches); 58590e33f62SGrant Likely struct resource res; 58690e33f62SGrant Likely 58790e33f62SGrant Likely while (dn) { 58890e33f62SGrant Likely if (of_address_to_resource(dn, 0, &res)) 58990e33f62SGrant Likely continue; 59090e33f62SGrant Likely if (res.start == base_address) 59190e33f62SGrant Likely return dn; 59290e33f62SGrant Likely dn = of_find_matching_node(dn, matches); 59390e33f62SGrant Likely } 59490e33f62SGrant Likely 59590e33f62SGrant Likely return NULL; 59690e33f62SGrant Likely } 59790e33f62SGrant Likely 5981f5bef30SGrant Likely 5996b884a8dSGrant Likely /** 6006b884a8dSGrant Likely * of_iomap - Maps the memory mapped IO for a given device_node 6016b884a8dSGrant Likely * @device: the device whose io range will be mapped 6026b884a8dSGrant Likely * @index: index of the io range 6036b884a8dSGrant Likely * 6046b884a8dSGrant Likely * Returns a pointer to the mapped memory 6056b884a8dSGrant Likely */ 6066b884a8dSGrant Likely void __iomem *of_iomap(struct device_node *np, int index) 6076b884a8dSGrant Likely { 6086b884a8dSGrant Likely struct resource res; 6096b884a8dSGrant Likely 6106b884a8dSGrant Likely if (of_address_to_resource(np, index, &res)) 6116b884a8dSGrant Likely return NULL; 6126b884a8dSGrant Likely 61328c1b6d6SFelipe Balbi return ioremap(res.start, resource_size(&res)); 6146b884a8dSGrant Likely } 6156b884a8dSGrant Likely EXPORT_SYMBOL(of_iomap); 616