1af6074fcSRob Herring // SPDX-License-Identifier: GPL-2.0 2606ad42aSRob Herring #define pr_fmt(fmt) "OF: " fmt 3606ad42aSRob Herring 45019f0b1SArnd Bergmann #include <linux/device.h> 5fcfaab30SGabriele Paoloni #include <linux/fwnode.h> 66b884a8dSGrant Likely #include <linux/io.h> 76b884a8dSGrant Likely #include <linux/ioport.h> 865af618dSZhichang Yuan #include <linux/logic_pio.h> 9dbbdee94SGrant Likely #include <linux/module.h> 106b884a8dSGrant Likely #include <linux/of_address.h> 11c5076cfeSTomasz Nowicki #include <linux/pci.h> 12dbbdee94SGrant Likely #include <linux/pci_regs.h> 1341f8bba7SLiviu Dudau #include <linux/sizes.h> 1441f8bba7SLiviu Dudau #include <linux/slab.h> 15dbbdee94SGrant Likely #include <linux/string.h> 166b884a8dSGrant Likely 17b68ac8dcSRobin Murphy #include "of_private.h" 18b68ac8dcSRobin Murphy 19dbbdee94SGrant Likely /* Max address size we deal with */ 20dbbdee94SGrant Likely #define OF_MAX_ADDR_CELLS 4 215d61b165SStephen Warren #define OF_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS) 225d61b165SStephen Warren #define OF_CHECK_COUNTS(na, ns) (OF_CHECK_ADDR_COUNT(na) && (ns) > 0) 23dbbdee94SGrant Likely 24dbbdee94SGrant Likely static struct of_bus *of_match_bus(struct device_node *np); 250131d897SSebastian Andrzej Siewior static int __of_address_to_resource(struct device_node *dev, 260131d897SSebastian Andrzej Siewior const __be32 *addrp, u64 size, unsigned int flags, 2735f3da32SBenoit Cousson const char *name, struct resource *r); 28dbbdee94SGrant Likely 29dbbdee94SGrant Likely /* Debug utility */ 30dbbdee94SGrant Likely #ifdef DEBUG 310131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na) 32dbbdee94SGrant Likely { 33606ad42aSRob Herring pr_debug("%s", s); 34dbbdee94SGrant Likely while (na--) 35606ad42aSRob Herring pr_cont(" %08x", be32_to_cpu(*(addr++))); 36606ad42aSRob Herring pr_cont("\n"); 37dbbdee94SGrant Likely } 38dbbdee94SGrant Likely #else 390131d897SSebastian Andrzej Siewior static void of_dump_addr(const char *s, const __be32 *addr, int na) { } 40dbbdee94SGrant Likely #endif 41dbbdee94SGrant Likely 42dbbdee94SGrant Likely /* Callbacks for bus specific translators */ 43dbbdee94SGrant Likely struct of_bus { 44dbbdee94SGrant Likely const char *name; 45dbbdee94SGrant Likely const char *addresses; 46dbbdee94SGrant Likely int (*match)(struct device_node *parent); 47dbbdee94SGrant Likely void (*count_cells)(struct device_node *child, 48dbbdee94SGrant Likely int *addrc, int *sizec); 4947b1e689SKim Phillips u64 (*map)(__be32 *addr, const __be32 *range, 50dbbdee94SGrant Likely int na, int ns, int pna); 5147b1e689SKim Phillips int (*translate)(__be32 *addr, u64 offset, int na); 522f96593eSJiaxun Yang bool has_flags; 530131d897SSebastian Andrzej Siewior unsigned int (*get_flags)(const __be32 *addr); 54dbbdee94SGrant Likely }; 55dbbdee94SGrant Likely 56dbbdee94SGrant Likely /* 57dbbdee94SGrant Likely * Default translator (generic bus) 58dbbdee94SGrant Likely */ 59dbbdee94SGrant Likely 60dbbdee94SGrant Likely static void of_bus_default_count_cells(struct device_node *dev, 61dbbdee94SGrant Likely int *addrc, int *sizec) 62dbbdee94SGrant Likely { 63dbbdee94SGrant Likely if (addrc) 64dbbdee94SGrant Likely *addrc = of_n_addr_cells(dev); 65dbbdee94SGrant Likely if (sizec) 66dbbdee94SGrant Likely *sizec = of_n_size_cells(dev); 67dbbdee94SGrant Likely } 68dbbdee94SGrant Likely 6947b1e689SKim Phillips static u64 of_bus_default_map(__be32 *addr, const __be32 *range, 70dbbdee94SGrant Likely int na, int ns, int pna) 71dbbdee94SGrant Likely { 72dbbdee94SGrant Likely u64 cp, s, da; 73dbbdee94SGrant Likely 74dbbdee94SGrant Likely cp = of_read_number(range, na); 75dbbdee94SGrant Likely s = of_read_number(range + na + pna, ns); 76dbbdee94SGrant Likely da = of_read_number(addr, na); 77dbbdee94SGrant Likely 78606ad42aSRob Herring pr_debug("default map, cp=%llx, s=%llx, da=%llx\n", 79dbbdee94SGrant Likely (unsigned long long)cp, (unsigned long long)s, 80dbbdee94SGrant Likely (unsigned long long)da); 81dbbdee94SGrant Likely 82dbbdee94SGrant Likely if (da < cp || da >= (cp + s)) 83dbbdee94SGrant Likely return OF_BAD_ADDR; 84dbbdee94SGrant Likely return da - cp; 85dbbdee94SGrant Likely } 86dbbdee94SGrant Likely 8747b1e689SKim Phillips static int of_bus_default_translate(__be32 *addr, u64 offset, int na) 88dbbdee94SGrant Likely { 89dbbdee94SGrant Likely u64 a = of_read_number(addr, na); 90dbbdee94SGrant Likely memset(addr, 0, na * 4); 91dbbdee94SGrant Likely a += offset; 92dbbdee94SGrant Likely if (na > 1) 93154063a9SGrant Likely addr[na - 2] = cpu_to_be32(a >> 32); 94154063a9SGrant Likely addr[na - 1] = cpu_to_be32(a & 0xffffffffu); 95dbbdee94SGrant Likely 96dbbdee94SGrant Likely return 0; 97dbbdee94SGrant Likely } 98dbbdee94SGrant Likely 990131d897SSebastian Andrzej Siewior static unsigned int of_bus_default_get_flags(const __be32 *addr) 100dbbdee94SGrant Likely { 101dbbdee94SGrant Likely return IORESOURCE_MEM; 102dbbdee94SGrant Likely } 103dbbdee94SGrant Likely 1040fc0ead3SJiaxun Yang #ifdef CONFIG_PCI 10567ccd2b9SRob Herring static unsigned int of_bus_pci_get_flags(const __be32 *addr) 10667ccd2b9SRob Herring { 10767ccd2b9SRob Herring unsigned int flags = 0; 10867ccd2b9SRob Herring u32 w = be32_to_cpup(addr); 10967ccd2b9SRob Herring 11067ccd2b9SRob Herring if (!IS_ENABLED(CONFIG_PCI)) 11167ccd2b9SRob Herring return 0; 11267ccd2b9SRob Herring 11367ccd2b9SRob Herring switch((w >> 24) & 0x03) { 11467ccd2b9SRob Herring case 0x01: 11567ccd2b9SRob Herring flags |= IORESOURCE_IO; 11667ccd2b9SRob Herring break; 11767ccd2b9SRob Herring case 0x02: /* 32 bits */ 11867ccd2b9SRob Herring case 0x03: /* 64 bits */ 11967ccd2b9SRob Herring flags |= IORESOURCE_MEM; 12067ccd2b9SRob Herring break; 12167ccd2b9SRob Herring } 12267ccd2b9SRob Herring if (w & 0x40000000) 12367ccd2b9SRob Herring flags |= IORESOURCE_PREFETCH; 12467ccd2b9SRob Herring return flags; 12567ccd2b9SRob Herring } 12667ccd2b9SRob Herring 127dbbdee94SGrant Likely /* 128dbbdee94SGrant Likely * PCI bus specific translator 129dbbdee94SGrant Likely */ 130dbbdee94SGrant Likely 131dbbdee94SGrant Likely static int of_bus_pci_match(struct device_node *np) 132dbbdee94SGrant Likely { 1336dd18e46SBenjamin Herrenschmidt /* 13414e2abb7SKleber Sacilotto de Souza * "pciex" is PCI Express 1356dd18e46SBenjamin Herrenschmidt * "vci" is for the /chaos bridge on 1st-gen PCI powermacs 1366dd18e46SBenjamin Herrenschmidt * "ht" is hypertransport 1376dd18e46SBenjamin Herrenschmidt */ 138e8b1dee2SRob Herring return of_node_is_type(np, "pci") || of_node_is_type(np, "pciex") || 139e8b1dee2SRob Herring of_node_is_type(np, "vci") || of_node_is_type(np, "ht"); 140dbbdee94SGrant Likely } 141dbbdee94SGrant Likely 142dbbdee94SGrant Likely static void of_bus_pci_count_cells(struct device_node *np, 143dbbdee94SGrant Likely int *addrc, int *sizec) 144dbbdee94SGrant Likely { 145dbbdee94SGrant Likely if (addrc) 146dbbdee94SGrant Likely *addrc = 3; 147dbbdee94SGrant Likely if (sizec) 148dbbdee94SGrant Likely *sizec = 2; 149dbbdee94SGrant Likely } 150dbbdee94SGrant Likely 15147b1e689SKim Phillips static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, 1520131d897SSebastian Andrzej Siewior int pna) 153dbbdee94SGrant Likely { 154dbbdee94SGrant Likely u64 cp, s, da; 155dbbdee94SGrant Likely unsigned int af, rf; 156dbbdee94SGrant Likely 157dbbdee94SGrant Likely af = of_bus_pci_get_flags(addr); 158dbbdee94SGrant Likely rf = of_bus_pci_get_flags(range); 159dbbdee94SGrant Likely 160dbbdee94SGrant Likely /* Check address type match */ 161dbbdee94SGrant Likely if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO)) 162dbbdee94SGrant Likely return OF_BAD_ADDR; 163dbbdee94SGrant Likely 164dbbdee94SGrant Likely /* Read address values, skipping high cell */ 165dbbdee94SGrant Likely cp = of_read_number(range + 1, na - 1); 166dbbdee94SGrant Likely s = of_read_number(range + na + pna, ns); 167dbbdee94SGrant Likely da = of_read_number(addr + 1, na - 1); 168dbbdee94SGrant Likely 169606ad42aSRob Herring pr_debug("PCI map, cp=%llx, s=%llx, da=%llx\n", 170dbbdee94SGrant Likely (unsigned long long)cp, (unsigned long long)s, 171dbbdee94SGrant Likely (unsigned long long)da); 172dbbdee94SGrant Likely 173dbbdee94SGrant Likely if (da < cp || da >= (cp + s)) 174dbbdee94SGrant Likely return OF_BAD_ADDR; 175dbbdee94SGrant Likely return da - cp; 176dbbdee94SGrant Likely } 177dbbdee94SGrant Likely 17847b1e689SKim Phillips static int of_bus_pci_translate(__be32 *addr, u64 offset, int na) 179dbbdee94SGrant Likely { 180dbbdee94SGrant Likely return of_bus_default_translate(addr + 1, offset, na - 1); 181dbbdee94SGrant Likely } 182dbbdee94SGrant Likely 1830131d897SSebastian Andrzej Siewior const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, 184dbbdee94SGrant Likely unsigned int *flags) 185dbbdee94SGrant Likely { 186a9fadeefSJeremy Kerr const __be32 *prop; 187dbbdee94SGrant Likely unsigned int psize; 188dbbdee94SGrant Likely struct device_node *parent; 189dbbdee94SGrant Likely struct of_bus *bus; 190dbbdee94SGrant Likely int onesize, i, na, ns; 191dbbdee94SGrant Likely 192dbbdee94SGrant Likely /* Get parent & match bus type */ 193dbbdee94SGrant Likely parent = of_get_parent(dev); 194dbbdee94SGrant Likely if (parent == NULL) 195dbbdee94SGrant Likely return NULL; 196dbbdee94SGrant Likely bus = of_match_bus(parent); 197dbbdee94SGrant Likely if (strcmp(bus->name, "pci")) { 198dbbdee94SGrant Likely of_node_put(parent); 199dbbdee94SGrant Likely return NULL; 200dbbdee94SGrant Likely } 201dbbdee94SGrant Likely bus->count_cells(dev, &na, &ns); 202dbbdee94SGrant Likely of_node_put(parent); 2035d61b165SStephen Warren if (!OF_CHECK_ADDR_COUNT(na)) 204dbbdee94SGrant Likely return NULL; 205dbbdee94SGrant Likely 206dbbdee94SGrant Likely /* Get "reg" or "assigned-addresses" property */ 207dbbdee94SGrant Likely prop = of_get_property(dev, bus->addresses, &psize); 208dbbdee94SGrant Likely if (prop == NULL) 209dbbdee94SGrant Likely return NULL; 210dbbdee94SGrant Likely psize /= 4; 211dbbdee94SGrant Likely 212dbbdee94SGrant Likely onesize = na + ns; 213154063a9SGrant Likely for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) { 214154063a9SGrant Likely u32 val = be32_to_cpu(prop[0]); 215154063a9SGrant Likely if ((val & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) { 216dbbdee94SGrant Likely if (size) 217dbbdee94SGrant Likely *size = of_read_number(prop + na, ns); 218dbbdee94SGrant Likely if (flags) 219dbbdee94SGrant Likely *flags = bus->get_flags(prop); 220dbbdee94SGrant Likely return prop; 221dbbdee94SGrant Likely } 222154063a9SGrant Likely } 223dbbdee94SGrant Likely return NULL; 224dbbdee94SGrant Likely } 225dbbdee94SGrant Likely EXPORT_SYMBOL(of_get_pci_address); 226dbbdee94SGrant Likely 227dbbdee94SGrant Likely int of_pci_address_to_resource(struct device_node *dev, int bar, 228dbbdee94SGrant Likely struct resource *r) 229dbbdee94SGrant Likely { 2300131d897SSebastian Andrzej Siewior const __be32 *addrp; 231dbbdee94SGrant Likely u64 size; 232dbbdee94SGrant Likely unsigned int flags; 233dbbdee94SGrant Likely 234dbbdee94SGrant Likely addrp = of_get_pci_address(dev, bar, &size, &flags); 235dbbdee94SGrant Likely if (addrp == NULL) 236dbbdee94SGrant Likely return -EINVAL; 23735f3da32SBenoit Cousson return __of_address_to_resource(dev, addrp, size, flags, NULL, r); 238dbbdee94SGrant Likely } 239dbbdee94SGrant Likely EXPORT_SYMBOL_GPL(of_pci_address_to_resource); 24029b635c0SAndrew Murray 2410b0b0893SLiviu Dudau /* 2420b0b0893SLiviu Dudau * of_pci_range_to_resource - Create a resource from an of_pci_range 2430b0b0893SLiviu Dudau * @range: the PCI range that describes the resource 2440b0b0893SLiviu Dudau * @np: device node where the range belongs to 2450b0b0893SLiviu Dudau * @res: pointer to a valid resource that will be updated to 2460b0b0893SLiviu Dudau * reflect the values contained in the range. 2470b0b0893SLiviu Dudau * 2480b0b0893SLiviu Dudau * Returns EINVAL if the range cannot be converted to resource. 2490b0b0893SLiviu Dudau * 2500b0b0893SLiviu Dudau * Note that if the range is an IO range, the resource will be converted 2510b0b0893SLiviu Dudau * using pci_address_to_pio() which can fail if it is called too early or 2520b0b0893SLiviu Dudau * if the range cannot be matched to any host bridge IO space (our case here). 2530b0b0893SLiviu Dudau * To guard against that we try to register the IO range first. 2540b0b0893SLiviu Dudau * If that fails we know that pci_address_to_pio() will do too. 2550b0b0893SLiviu Dudau */ 2560b0b0893SLiviu Dudau int of_pci_range_to_resource(struct of_pci_range *range, 25783bbde1cSLiviu Dudau struct device_node *np, struct resource *res) 25883bbde1cSLiviu Dudau { 2590b0b0893SLiviu Dudau int err; 26083bbde1cSLiviu Dudau res->flags = range->flags; 26183bbde1cSLiviu Dudau res->parent = res->child = res->sibling = NULL; 26283bbde1cSLiviu Dudau res->name = np->full_name; 2630b0b0893SLiviu Dudau 2640b0b0893SLiviu Dudau if (res->flags & IORESOURCE_IO) { 2650b0b0893SLiviu Dudau unsigned long port; 266fcfaab30SGabriele Paoloni err = pci_register_io_range(&np->fwnode, range->cpu_addr, 267fcfaab30SGabriele Paoloni range->size); 2680b0b0893SLiviu Dudau if (err) 2690b0b0893SLiviu Dudau goto invalid_range; 2700b0b0893SLiviu Dudau port = pci_address_to_pio(range->cpu_addr); 2710b0b0893SLiviu Dudau if (port == (unsigned long)-1) { 2720b0b0893SLiviu Dudau err = -EINVAL; 2730b0b0893SLiviu Dudau goto invalid_range; 2740b0b0893SLiviu Dudau } 2750b0b0893SLiviu Dudau res->start = port; 2760b0b0893SLiviu Dudau } else { 2774af97106SPavel Fedin if ((sizeof(resource_size_t) < 8) && 2784af97106SPavel Fedin upper_32_bits(range->cpu_addr)) { 2794af97106SPavel Fedin err = -EINVAL; 2804af97106SPavel Fedin goto invalid_range; 2814af97106SPavel Fedin } 2824af97106SPavel Fedin 2830b0b0893SLiviu Dudau res->start = range->cpu_addr; 2840b0b0893SLiviu Dudau } 2850b0b0893SLiviu Dudau res->end = res->start + range->size - 1; 2860b0b0893SLiviu Dudau return 0; 2870b0b0893SLiviu Dudau 2880b0b0893SLiviu Dudau invalid_range: 2890b0b0893SLiviu Dudau res->start = (resource_size_t)OF_BAD_ADDR; 2900b0b0893SLiviu Dudau res->end = (resource_size_t)OF_BAD_ADDR; 2910b0b0893SLiviu Dudau return err; 29283bbde1cSLiviu Dudau } 293bf6681eaSManikanta Maddireddy EXPORT_SYMBOL(of_pci_range_to_resource); 294dbbdee94SGrant Likely #endif /* CONFIG_PCI */ 295dbbdee94SGrant Likely 296dbbdee94SGrant Likely /* 297dbbdee94SGrant Likely * ISA bus specific translator 298dbbdee94SGrant Likely */ 299dbbdee94SGrant Likely 300dbbdee94SGrant Likely static int of_bus_isa_match(struct device_node *np) 301dbbdee94SGrant Likely { 302b3e46d1aSRob Herring return of_node_name_eq(np, "isa"); 303dbbdee94SGrant Likely } 304dbbdee94SGrant Likely 305dbbdee94SGrant Likely static void of_bus_isa_count_cells(struct device_node *child, 306dbbdee94SGrant Likely int *addrc, int *sizec) 307dbbdee94SGrant Likely { 308dbbdee94SGrant Likely if (addrc) 309dbbdee94SGrant Likely *addrc = 2; 310dbbdee94SGrant Likely if (sizec) 311dbbdee94SGrant Likely *sizec = 1; 312dbbdee94SGrant Likely } 313dbbdee94SGrant Likely 31447b1e689SKim Phillips static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns, 3150131d897SSebastian Andrzej Siewior int pna) 316dbbdee94SGrant Likely { 317dbbdee94SGrant Likely u64 cp, s, da; 318dbbdee94SGrant Likely 319dbbdee94SGrant Likely /* Check address type match */ 3200131d897SSebastian Andrzej Siewior if ((addr[0] ^ range[0]) & cpu_to_be32(1)) 321dbbdee94SGrant Likely return OF_BAD_ADDR; 322dbbdee94SGrant Likely 323dbbdee94SGrant Likely /* Read address values, skipping high cell */ 324dbbdee94SGrant Likely cp = of_read_number(range + 1, na - 1); 325dbbdee94SGrant Likely s = of_read_number(range + na + pna, ns); 326dbbdee94SGrant Likely da = of_read_number(addr + 1, na - 1); 327dbbdee94SGrant Likely 328606ad42aSRob Herring pr_debug("ISA map, cp=%llx, s=%llx, da=%llx\n", 329dbbdee94SGrant Likely (unsigned long long)cp, (unsigned long long)s, 330dbbdee94SGrant Likely (unsigned long long)da); 331dbbdee94SGrant Likely 332dbbdee94SGrant Likely if (da < cp || da >= (cp + s)) 333dbbdee94SGrant Likely return OF_BAD_ADDR; 334dbbdee94SGrant Likely return da - cp; 335dbbdee94SGrant Likely } 336dbbdee94SGrant Likely 33747b1e689SKim Phillips static int of_bus_isa_translate(__be32 *addr, u64 offset, int na) 338dbbdee94SGrant Likely { 339dbbdee94SGrant Likely return of_bus_default_translate(addr + 1, offset, na - 1); 340dbbdee94SGrant Likely } 341dbbdee94SGrant Likely 3420131d897SSebastian Andrzej Siewior static unsigned int of_bus_isa_get_flags(const __be32 *addr) 343dbbdee94SGrant Likely { 344dbbdee94SGrant Likely unsigned int flags = 0; 3450131d897SSebastian Andrzej Siewior u32 w = be32_to_cpup(addr); 346dbbdee94SGrant Likely 347dbbdee94SGrant Likely if (w & 1) 348dbbdee94SGrant Likely flags |= IORESOURCE_IO; 349dbbdee94SGrant Likely else 350dbbdee94SGrant Likely flags |= IORESOURCE_MEM; 351dbbdee94SGrant Likely return flags; 352dbbdee94SGrant Likely } 353dbbdee94SGrant Likely 354dbbdee94SGrant Likely /* 355dbbdee94SGrant Likely * Array of bus specific translators 356dbbdee94SGrant Likely */ 357dbbdee94SGrant Likely 358dbbdee94SGrant Likely static struct of_bus of_busses[] = { 3594670d610SRob Herring #ifdef CONFIG_PCI 360dbbdee94SGrant Likely /* PCI */ 361dbbdee94SGrant Likely { 362dbbdee94SGrant Likely .name = "pci", 363dbbdee94SGrant Likely .addresses = "assigned-addresses", 364dbbdee94SGrant Likely .match = of_bus_pci_match, 365dbbdee94SGrant Likely .count_cells = of_bus_pci_count_cells, 366dbbdee94SGrant Likely .map = of_bus_pci_map, 367dbbdee94SGrant Likely .translate = of_bus_pci_translate, 3682f96593eSJiaxun Yang .has_flags = true, 369dbbdee94SGrant Likely .get_flags = of_bus_pci_get_flags, 370dbbdee94SGrant Likely }, 3714670d610SRob Herring #endif /* CONFIG_PCI */ 372dbbdee94SGrant Likely /* ISA */ 373dbbdee94SGrant Likely { 374dbbdee94SGrant Likely .name = "isa", 375dbbdee94SGrant Likely .addresses = "reg", 376dbbdee94SGrant Likely .match = of_bus_isa_match, 377dbbdee94SGrant Likely .count_cells = of_bus_isa_count_cells, 378dbbdee94SGrant Likely .map = of_bus_isa_map, 379dbbdee94SGrant Likely .translate = of_bus_isa_translate, 3802f96593eSJiaxun Yang .has_flags = true, 381dbbdee94SGrant Likely .get_flags = of_bus_isa_get_flags, 382dbbdee94SGrant Likely }, 383dbbdee94SGrant Likely /* Default */ 384dbbdee94SGrant Likely { 385dbbdee94SGrant Likely .name = "default", 386dbbdee94SGrant Likely .addresses = "reg", 387dbbdee94SGrant Likely .match = NULL, 388dbbdee94SGrant Likely .count_cells = of_bus_default_count_cells, 389dbbdee94SGrant Likely .map = of_bus_default_map, 390dbbdee94SGrant Likely .translate = of_bus_default_translate, 391dbbdee94SGrant Likely .get_flags = of_bus_default_get_flags, 392dbbdee94SGrant Likely }, 393dbbdee94SGrant Likely }; 394dbbdee94SGrant Likely 395dbbdee94SGrant Likely static struct of_bus *of_match_bus(struct device_node *np) 396dbbdee94SGrant Likely { 397dbbdee94SGrant Likely int i; 398dbbdee94SGrant Likely 399dbbdee94SGrant Likely for (i = 0; i < ARRAY_SIZE(of_busses); i++) 400dbbdee94SGrant Likely if (!of_busses[i].match || of_busses[i].match(np)) 401dbbdee94SGrant Likely return &of_busses[i]; 402dbbdee94SGrant Likely BUG(); 403dbbdee94SGrant Likely return NULL; 404dbbdee94SGrant Likely } 405dbbdee94SGrant Likely 40641d94893SBenjamin Herrenschmidt static int of_empty_ranges_quirk(struct device_node *np) 407746c9e9fSBenjamin Herrenschmidt { 408746c9e9fSBenjamin Herrenschmidt if (IS_ENABLED(CONFIG_PPC)) { 40941d94893SBenjamin Herrenschmidt /* To save cycles, we cache the result for global "Mac" setting */ 410746c9e9fSBenjamin Herrenschmidt static int quirk_state = -1; 411746c9e9fSBenjamin Herrenschmidt 41241d94893SBenjamin Herrenschmidt /* PA-SEMI sdc DT bug */ 41341d94893SBenjamin Herrenschmidt if (of_device_is_compatible(np, "1682m-sdc")) 41441d94893SBenjamin Herrenschmidt return true; 41541d94893SBenjamin Herrenschmidt 41641d94893SBenjamin Herrenschmidt /* Make quirk cached */ 417746c9e9fSBenjamin Herrenschmidt if (quirk_state < 0) 418746c9e9fSBenjamin Herrenschmidt quirk_state = 419746c9e9fSBenjamin Herrenschmidt of_machine_is_compatible("Power Macintosh") || 420746c9e9fSBenjamin Herrenschmidt of_machine_is_compatible("MacRISC"); 421746c9e9fSBenjamin Herrenschmidt return quirk_state; 422746c9e9fSBenjamin Herrenschmidt } 423746c9e9fSBenjamin Herrenschmidt return false; 424746c9e9fSBenjamin Herrenschmidt } 425746c9e9fSBenjamin Herrenschmidt 426dbbdee94SGrant Likely static int of_translate_one(struct device_node *parent, struct of_bus *bus, 42747b1e689SKim Phillips struct of_bus *pbus, __be32 *addr, 428dbbdee94SGrant Likely int na, int ns, int pna, const char *rprop) 429dbbdee94SGrant Likely { 4300131d897SSebastian Andrzej Siewior const __be32 *ranges; 431dbbdee94SGrant Likely unsigned int rlen; 432dbbdee94SGrant Likely int rone; 433dbbdee94SGrant Likely u64 offset = OF_BAD_ADDR; 434dbbdee94SGrant Likely 435ba85edbeSMasahiro Yamada /* 436ba85edbeSMasahiro Yamada * Normally, an absence of a "ranges" property means we are 437dbbdee94SGrant Likely * crossing a non-translatable boundary, and thus the addresses 438ba85edbeSMasahiro Yamada * below the current cannot be converted to CPU physical ones. 439dbbdee94SGrant Likely * Unfortunately, while this is very clear in the spec, it's not 440dbbdee94SGrant Likely * what Apple understood, and they do have things like /uni-n or 441dbbdee94SGrant Likely * /ht nodes with no "ranges" property and a lot of perfectly 442dbbdee94SGrant Likely * useable mapped devices below them. Thus we treat the absence of 443dbbdee94SGrant Likely * "ranges" as equivalent to an empty "ranges" property which means 444dbbdee94SGrant Likely * a 1:1 translation at that level. It's up to the caller not to try 445dbbdee94SGrant Likely * to translate addresses that aren't supposed to be translated in 446dbbdee94SGrant Likely * the first place. --BenH. 4473930f294SGrant Likely * 4483930f294SGrant Likely * As far as we know, this damage only exists on Apple machines, so 4493930f294SGrant Likely * This code is only enabled on powerpc. --gcl 45081db12eeSRob Herring * 45181db12eeSRob Herring * This quirk also applies for 'dma-ranges' which frequently exist in 45281db12eeSRob Herring * child nodes without 'dma-ranges' in the parent nodes. --RobH 453dbbdee94SGrant Likely */ 454dbbdee94SGrant Likely ranges = of_get_property(parent, rprop, &rlen); 45581db12eeSRob Herring if (ranges == NULL && !of_empty_ranges_quirk(parent) && 45681db12eeSRob Herring strcmp(rprop, "dma-ranges")) { 457606ad42aSRob Herring pr_debug("no ranges; cannot translate\n"); 4583930f294SGrant Likely return 1; 4593930f294SGrant Likely } 460dbbdee94SGrant Likely if (ranges == NULL || rlen == 0) { 461dbbdee94SGrant Likely offset = of_read_number(addr, na); 462dbbdee94SGrant Likely memset(addr, 0, pna * 4); 463606ad42aSRob Herring pr_debug("empty ranges; 1:1 translation\n"); 464dbbdee94SGrant Likely goto finish; 465dbbdee94SGrant Likely } 466dbbdee94SGrant Likely 467606ad42aSRob Herring pr_debug("walking ranges...\n"); 468dbbdee94SGrant Likely 469dbbdee94SGrant Likely /* Now walk through the ranges */ 470dbbdee94SGrant Likely rlen /= 4; 471dbbdee94SGrant Likely rone = na + pna + ns; 472dbbdee94SGrant Likely for (; rlen >= rone; rlen -= rone, ranges += rone) { 473dbbdee94SGrant Likely offset = bus->map(addr, ranges, na, ns, pna); 474dbbdee94SGrant Likely if (offset != OF_BAD_ADDR) 475dbbdee94SGrant Likely break; 476dbbdee94SGrant Likely } 477dbbdee94SGrant Likely if (offset == OF_BAD_ADDR) { 478606ad42aSRob Herring pr_debug("not found !\n"); 479dbbdee94SGrant Likely return 1; 480dbbdee94SGrant Likely } 481dbbdee94SGrant Likely memcpy(addr, ranges + na, 4 * pna); 482dbbdee94SGrant Likely 483dbbdee94SGrant Likely finish: 484606ad42aSRob Herring of_dump_addr("parent translation for:", addr, pna); 485606ad42aSRob Herring pr_debug("with offset: %llx\n", (unsigned long long)offset); 486dbbdee94SGrant Likely 487dbbdee94SGrant Likely /* Translate it into parent bus space */ 488dbbdee94SGrant Likely return pbus->translate(addr, offset, pna); 489dbbdee94SGrant Likely } 490dbbdee94SGrant Likely 491dbbdee94SGrant Likely /* 492dbbdee94SGrant Likely * Translate an address from the device-tree into a CPU physical address, 493dbbdee94SGrant Likely * this walks up the tree and applies the various bus mappings on the 494dbbdee94SGrant Likely * way. 495dbbdee94SGrant Likely * 496dbbdee94SGrant Likely * Note: We consider that crossing any level with #size-cells == 0 to mean 497dbbdee94SGrant Likely * that translation is impossible (that is we are not dealing with a value 498dbbdee94SGrant Likely * that can be mapped to a cpu physical address). This is not really specified 499dbbdee94SGrant Likely * that way, but this is traditionally the way IBM at least do things 50065af618dSZhichang Yuan * 50165af618dSZhichang Yuan * Whenever the translation fails, the *host pointer will be set to the 50265af618dSZhichang Yuan * device that had registered logical PIO mapping, and the return code is 50365af618dSZhichang Yuan * relative to that node. 504dbbdee94SGrant Likely */ 50547b1e689SKim Phillips static u64 __of_translate_address(struct device_node *dev, 50695835a8dSMaxime Ripard struct device_node *(*get_parent)(const struct device_node *), 50765af618dSZhichang Yuan const __be32 *in_addr, const char *rprop, 50865af618dSZhichang Yuan struct device_node **host) 509dbbdee94SGrant Likely { 510dbbdee94SGrant Likely struct device_node *parent = NULL; 511dbbdee94SGrant Likely struct of_bus *bus, *pbus; 51247b1e689SKim Phillips __be32 addr[OF_MAX_ADDR_CELLS]; 513dbbdee94SGrant Likely int na, ns, pna, pns; 514dbbdee94SGrant Likely u64 result = OF_BAD_ADDR; 515dbbdee94SGrant Likely 5160d638a07SRob Herring pr_debug("** translation for device %pOF **\n", dev); 517dbbdee94SGrant Likely 518dbbdee94SGrant Likely /* Increase refcount at current level */ 519dbbdee94SGrant Likely of_node_get(dev); 520dbbdee94SGrant Likely 52165af618dSZhichang Yuan *host = NULL; 522dbbdee94SGrant Likely /* Get parent & match bus type */ 52395835a8dSMaxime Ripard parent = get_parent(dev); 524dbbdee94SGrant Likely if (parent == NULL) 525dbbdee94SGrant Likely goto bail; 526dbbdee94SGrant Likely bus = of_match_bus(parent); 527dbbdee94SGrant Likely 52859f5ca48SAndrew Murray /* Count address cells & copy address locally */ 529dbbdee94SGrant Likely bus->count_cells(dev, &na, &ns); 530dbbdee94SGrant Likely if (!OF_CHECK_COUNTS(na, ns)) { 5310d638a07SRob Herring pr_debug("Bad cell count for %pOF\n", dev); 532dbbdee94SGrant Likely goto bail; 533dbbdee94SGrant Likely } 534dbbdee94SGrant Likely memcpy(addr, in_addr, na * 4); 535dbbdee94SGrant Likely 5360d638a07SRob Herring pr_debug("bus is %s (na=%d, ns=%d) on %pOF\n", 5370d638a07SRob Herring bus->name, na, ns, parent); 538606ad42aSRob Herring of_dump_addr("translating address:", addr, na); 539dbbdee94SGrant Likely 540dbbdee94SGrant Likely /* Translate */ 541dbbdee94SGrant Likely for (;;) { 54265af618dSZhichang Yuan struct logic_pio_hwaddr *iorange; 54365af618dSZhichang Yuan 544dbbdee94SGrant Likely /* Switch to parent bus */ 545dbbdee94SGrant Likely of_node_put(dev); 546dbbdee94SGrant Likely dev = parent; 54795835a8dSMaxime Ripard parent = get_parent(dev); 548dbbdee94SGrant Likely 549dbbdee94SGrant Likely /* If root, we have finished */ 550dbbdee94SGrant Likely if (parent == NULL) { 551606ad42aSRob Herring pr_debug("reached root node\n"); 552dbbdee94SGrant Likely result = of_read_number(addr, na); 553dbbdee94SGrant Likely break; 554dbbdee94SGrant Likely } 555dbbdee94SGrant Likely 55665af618dSZhichang Yuan /* 55765af618dSZhichang Yuan * For indirectIO device which has no ranges property, get 55865af618dSZhichang Yuan * the address from reg directly. 55965af618dSZhichang Yuan */ 56065af618dSZhichang Yuan iorange = find_io_range_by_fwnode(&dev->fwnode); 56165af618dSZhichang Yuan if (iorange && (iorange->flags != LOGIC_PIO_CPU_MMIO)) { 56265af618dSZhichang Yuan result = of_read_number(addr + 1, na - 1); 56365af618dSZhichang Yuan pr_debug("indirectIO matched(%pOF) 0x%llx\n", 56465af618dSZhichang Yuan dev, result); 56565af618dSZhichang Yuan *host = of_node_get(dev); 56665af618dSZhichang Yuan break; 56765af618dSZhichang Yuan } 56865af618dSZhichang Yuan 569dbbdee94SGrant Likely /* Get new parent bus and counts */ 570dbbdee94SGrant Likely pbus = of_match_bus(parent); 571dbbdee94SGrant Likely pbus->count_cells(dev, &pna, &pns); 572dbbdee94SGrant Likely if (!OF_CHECK_COUNTS(pna, pns)) { 5730d638a07SRob Herring pr_err("Bad cell count for %pOF\n", dev); 574dbbdee94SGrant Likely break; 575dbbdee94SGrant Likely } 576dbbdee94SGrant Likely 5770d638a07SRob Herring pr_debug("parent bus is %s (na=%d, ns=%d) on %pOF\n", 5780d638a07SRob Herring pbus->name, pna, pns, parent); 579dbbdee94SGrant Likely 580dbbdee94SGrant Likely /* Apply bus translation */ 581dbbdee94SGrant Likely if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) 582dbbdee94SGrant Likely break; 583dbbdee94SGrant Likely 584dbbdee94SGrant Likely /* Complete the move up one level */ 585dbbdee94SGrant Likely na = pna; 586dbbdee94SGrant Likely ns = pns; 587dbbdee94SGrant Likely bus = pbus; 588dbbdee94SGrant Likely 589606ad42aSRob Herring of_dump_addr("one level translation:", addr, na); 590dbbdee94SGrant Likely } 591dbbdee94SGrant Likely bail: 592dbbdee94SGrant Likely of_node_put(parent); 593dbbdee94SGrant Likely of_node_put(dev); 594dbbdee94SGrant Likely 595dbbdee94SGrant Likely return result; 596dbbdee94SGrant Likely } 597dbbdee94SGrant Likely 5980131d897SSebastian Andrzej Siewior u64 of_translate_address(struct device_node *dev, const __be32 *in_addr) 599dbbdee94SGrant Likely { 60065af618dSZhichang Yuan struct device_node *host; 60165af618dSZhichang Yuan u64 ret; 60265af618dSZhichang Yuan 60395835a8dSMaxime Ripard ret = __of_translate_address(dev, of_get_parent, 60495835a8dSMaxime Ripard in_addr, "ranges", &host); 60565af618dSZhichang Yuan if (host) { 60665af618dSZhichang Yuan of_node_put(host); 60765af618dSZhichang Yuan return OF_BAD_ADDR; 60865af618dSZhichang Yuan } 60965af618dSZhichang Yuan 61065af618dSZhichang Yuan return ret; 611dbbdee94SGrant Likely } 612dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_address); 613dbbdee94SGrant Likely 614f83a6e5dSMaxime Ripard static struct device_node *__of_get_dma_parent(const struct device_node *np) 615f83a6e5dSMaxime Ripard { 616f83a6e5dSMaxime Ripard struct of_phandle_args args; 617f83a6e5dSMaxime Ripard int ret, index; 618f83a6e5dSMaxime Ripard 619f83a6e5dSMaxime Ripard index = of_property_match_string(np, "interconnect-names", "dma-mem"); 620f83a6e5dSMaxime Ripard if (index < 0) 621f83a6e5dSMaxime Ripard return of_get_parent(np); 622f83a6e5dSMaxime Ripard 623f83a6e5dSMaxime Ripard ret = of_parse_phandle_with_args(np, "interconnects", 624f83a6e5dSMaxime Ripard "#interconnect-cells", 625f83a6e5dSMaxime Ripard index, &args); 626f83a6e5dSMaxime Ripard if (ret < 0) 627f83a6e5dSMaxime Ripard return of_get_parent(np); 628f83a6e5dSMaxime Ripard 629f83a6e5dSMaxime Ripard return of_node_get(args.np); 630f83a6e5dSMaxime Ripard } 631f83a6e5dSMaxime Ripard 632862ab557SRobin Murphy static struct device_node *of_get_next_dma_parent(struct device_node *np) 633862ab557SRobin Murphy { 634862ab557SRobin Murphy struct device_node *parent; 635862ab557SRobin Murphy 636862ab557SRobin Murphy parent = __of_get_dma_parent(np); 637862ab557SRobin Murphy of_node_put(np); 638862ab557SRobin Murphy 639862ab557SRobin Murphy return parent; 640862ab557SRobin Murphy } 641862ab557SRobin Murphy 6420131d897SSebastian Andrzej Siewior u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) 643dbbdee94SGrant Likely { 64465af618dSZhichang Yuan struct device_node *host; 64565af618dSZhichang Yuan u64 ret; 64665af618dSZhichang Yuan 647f83a6e5dSMaxime Ripard ret = __of_translate_address(dev, __of_get_dma_parent, 64895835a8dSMaxime Ripard in_addr, "dma-ranges", &host); 64965af618dSZhichang Yuan 65065af618dSZhichang Yuan if (host) { 65165af618dSZhichang Yuan of_node_put(host); 65265af618dSZhichang Yuan return OF_BAD_ADDR; 65365af618dSZhichang Yuan } 65465af618dSZhichang Yuan 65565af618dSZhichang Yuan return ret; 656dbbdee94SGrant Likely } 657dbbdee94SGrant Likely EXPORT_SYMBOL(of_translate_dma_address); 658dbbdee94SGrant Likely 6590131d897SSebastian Andrzej Siewior const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, 660dbbdee94SGrant Likely unsigned int *flags) 661dbbdee94SGrant Likely { 6620131d897SSebastian Andrzej Siewior const __be32 *prop; 663dbbdee94SGrant Likely unsigned int psize; 664dbbdee94SGrant Likely struct device_node *parent; 665dbbdee94SGrant Likely struct of_bus *bus; 666dbbdee94SGrant Likely int onesize, i, na, ns; 667dbbdee94SGrant Likely 668dbbdee94SGrant Likely /* Get parent & match bus type */ 669dbbdee94SGrant Likely parent = of_get_parent(dev); 670dbbdee94SGrant Likely if (parent == NULL) 671dbbdee94SGrant Likely return NULL; 672dbbdee94SGrant Likely bus = of_match_bus(parent); 673dbbdee94SGrant Likely bus->count_cells(dev, &na, &ns); 674dbbdee94SGrant Likely of_node_put(parent); 6755d61b165SStephen Warren if (!OF_CHECK_ADDR_COUNT(na)) 676dbbdee94SGrant Likely return NULL; 677dbbdee94SGrant Likely 678dbbdee94SGrant Likely /* Get "reg" or "assigned-addresses" property */ 679dbbdee94SGrant Likely prop = of_get_property(dev, bus->addresses, &psize); 680dbbdee94SGrant Likely if (prop == NULL) 681dbbdee94SGrant Likely return NULL; 682dbbdee94SGrant Likely psize /= 4; 683dbbdee94SGrant Likely 684dbbdee94SGrant Likely onesize = na + ns; 685dbbdee94SGrant Likely for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) 686dbbdee94SGrant Likely if (i == index) { 687dbbdee94SGrant Likely if (size) 688dbbdee94SGrant Likely *size = of_read_number(prop + na, ns); 689dbbdee94SGrant Likely if (flags) 690dbbdee94SGrant Likely *flags = bus->get_flags(prop); 691dbbdee94SGrant Likely return prop; 692dbbdee94SGrant Likely } 693dbbdee94SGrant Likely return NULL; 694dbbdee94SGrant Likely } 695dbbdee94SGrant Likely EXPORT_SYMBOL(of_get_address); 696dbbdee94SGrant Likely 69767ccd2b9SRob Herring static int parser_init(struct of_pci_range_parser *parser, 69867ccd2b9SRob Herring struct device_node *node, const char *name) 69967ccd2b9SRob Herring { 70067ccd2b9SRob Herring int rlen; 70167ccd2b9SRob Herring 70267ccd2b9SRob Herring parser->node = node; 70367ccd2b9SRob Herring parser->pna = of_n_addr_cells(node); 704bc5e522eSRob Herring parser->na = of_bus_n_addr_cells(node); 705bc5e522eSRob Herring parser->ns = of_bus_n_size_cells(node); 70667ccd2b9SRob Herring parser->dma = !strcmp(name, "dma-ranges"); 7072f96593eSJiaxun Yang parser->bus = of_match_bus(node); 70867ccd2b9SRob Herring 70967ccd2b9SRob Herring parser->range = of_get_property(node, name, &rlen); 71067ccd2b9SRob Herring if (parser->range == NULL) 71167ccd2b9SRob Herring return -ENOENT; 71267ccd2b9SRob Herring 71367ccd2b9SRob Herring parser->end = parser->range + rlen / sizeof(__be32); 71467ccd2b9SRob Herring 71567ccd2b9SRob Herring return 0; 71667ccd2b9SRob Herring } 71767ccd2b9SRob Herring 71867ccd2b9SRob Herring int of_pci_range_parser_init(struct of_pci_range_parser *parser, 71967ccd2b9SRob Herring struct device_node *node) 72067ccd2b9SRob Herring { 72167ccd2b9SRob Herring return parser_init(parser, node, "ranges"); 72267ccd2b9SRob Herring } 72367ccd2b9SRob Herring EXPORT_SYMBOL_GPL(of_pci_range_parser_init); 72467ccd2b9SRob Herring 72567ccd2b9SRob Herring int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser, 72667ccd2b9SRob Herring struct device_node *node) 72767ccd2b9SRob Herring { 72867ccd2b9SRob Herring return parser_init(parser, node, "dma-ranges"); 72967ccd2b9SRob Herring } 73067ccd2b9SRob Herring EXPORT_SYMBOL_GPL(of_pci_dma_range_parser_init); 731bc5e522eSRob Herring #define of_dma_range_parser_init of_pci_dma_range_parser_init 73267ccd2b9SRob Herring 73367ccd2b9SRob Herring struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, 73467ccd2b9SRob Herring struct of_pci_range *range) 73567ccd2b9SRob Herring { 736bc5e522eSRob Herring int na = parser->na; 737bc5e522eSRob Herring int ns = parser->ns; 738bc5e522eSRob Herring int np = parser->pna + na + ns; 7392f96593eSJiaxun Yang int busflag_na = 0; 74067ccd2b9SRob Herring 74167ccd2b9SRob Herring if (!range) 74267ccd2b9SRob Herring return NULL; 74367ccd2b9SRob Herring 744bc5e522eSRob Herring if (!parser->range || parser->range + np > parser->end) 74567ccd2b9SRob Herring return NULL; 74667ccd2b9SRob Herring 7472f96593eSJiaxun Yang range->flags = parser->bus->get_flags(parser->range); 748bc5e522eSRob Herring 7492f96593eSJiaxun Yang /* A extra cell for resource flags */ 7502f96593eSJiaxun Yang if (parser->bus->has_flags) 7512f96593eSJiaxun Yang busflag_na = 1; 7522f96593eSJiaxun Yang 7532f96593eSJiaxun Yang range->bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na); 754bc5e522eSRob Herring 75567ccd2b9SRob Herring if (parser->dma) 75667ccd2b9SRob Herring range->cpu_addr = of_translate_dma_address(parser->node, 75767ccd2b9SRob Herring parser->range + na); 75867ccd2b9SRob Herring else 75967ccd2b9SRob Herring range->cpu_addr = of_translate_address(parser->node, 76067ccd2b9SRob Herring parser->range + na); 76167ccd2b9SRob Herring range->size = of_read_number(parser->range + parser->pna + na, ns); 76267ccd2b9SRob Herring 763bc5e522eSRob Herring parser->range += np; 76467ccd2b9SRob Herring 76567ccd2b9SRob Herring /* Now consume following elements while they are contiguous */ 766bc5e522eSRob Herring while (parser->range + np <= parser->end) { 767bc5e522eSRob Herring u32 flags = 0; 7682f96593eSJiaxun Yang u64 bus_addr, cpu_addr, size; 76967ccd2b9SRob Herring 7702f96593eSJiaxun Yang flags = parser->bus->get_flags(parser->range); 7712f96593eSJiaxun Yang bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na); 77267ccd2b9SRob Herring if (parser->dma) 77367ccd2b9SRob Herring cpu_addr = of_translate_dma_address(parser->node, 77467ccd2b9SRob Herring parser->range + na); 77567ccd2b9SRob Herring else 77667ccd2b9SRob Herring cpu_addr = of_translate_address(parser->node, 77767ccd2b9SRob Herring parser->range + na); 77867ccd2b9SRob Herring size = of_read_number(parser->range + parser->pna + na, ns); 77967ccd2b9SRob Herring 78067ccd2b9SRob Herring if (flags != range->flags) 78167ccd2b9SRob Herring break; 7822f96593eSJiaxun Yang if (bus_addr != range->bus_addr + range->size || 78367ccd2b9SRob Herring cpu_addr != range->cpu_addr + range->size) 78467ccd2b9SRob Herring break; 78567ccd2b9SRob Herring 78667ccd2b9SRob Herring range->size += size; 787bc5e522eSRob Herring parser->range += np; 78867ccd2b9SRob Herring } 78967ccd2b9SRob Herring 79067ccd2b9SRob Herring return range; 79167ccd2b9SRob Herring } 79267ccd2b9SRob Herring EXPORT_SYMBOL_GPL(of_pci_range_parser_one); 79367ccd2b9SRob Herring 79465af618dSZhichang Yuan static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr, 79565af618dSZhichang Yuan u64 size) 79665af618dSZhichang Yuan { 79765af618dSZhichang Yuan u64 taddr; 79865af618dSZhichang Yuan unsigned long port; 79965af618dSZhichang Yuan struct device_node *host; 80065af618dSZhichang Yuan 80195835a8dSMaxime Ripard taddr = __of_translate_address(dev, of_get_parent, 80295835a8dSMaxime Ripard in_addr, "ranges", &host); 80365af618dSZhichang Yuan if (host) { 80465af618dSZhichang Yuan /* host-specific port access */ 80565af618dSZhichang Yuan port = logic_pio_trans_hwaddr(&host->fwnode, taddr, size); 80665af618dSZhichang Yuan of_node_put(host); 80765af618dSZhichang Yuan } else { 80865af618dSZhichang Yuan /* memory-mapped I/O range */ 80965af618dSZhichang Yuan port = pci_address_to_pio(taddr); 81065af618dSZhichang Yuan } 81165af618dSZhichang Yuan 81265af618dSZhichang Yuan if (port == (unsigned long)-1) 81365af618dSZhichang Yuan return OF_BAD_ADDR; 81465af618dSZhichang Yuan 81565af618dSZhichang Yuan return port; 81665af618dSZhichang Yuan } 81765af618dSZhichang Yuan 8180131d897SSebastian Andrzej Siewior static int __of_address_to_resource(struct device_node *dev, 8190131d897SSebastian Andrzej Siewior const __be32 *addrp, u64 size, unsigned int flags, 82035f3da32SBenoit Cousson const char *name, struct resource *r) 8211f5bef30SGrant Likely { 8221f5bef30SGrant Likely u64 taddr; 8231f5bef30SGrant Likely 82465af618dSZhichang Yuan if (flags & IORESOURCE_MEM) 8251f5bef30SGrant Likely taddr = of_translate_address(dev, addrp); 82665af618dSZhichang Yuan else if (flags & IORESOURCE_IO) 82765af618dSZhichang Yuan taddr = of_translate_ioport(dev, addrp, size); 82865af618dSZhichang Yuan else 82965af618dSZhichang Yuan return -EINVAL; 83065af618dSZhichang Yuan 8311f5bef30SGrant Likely if (taddr == OF_BAD_ADDR) 8321f5bef30SGrant Likely return -EINVAL; 8331f5bef30SGrant Likely memset(r, 0, sizeof(struct resource)); 83465af618dSZhichang Yuan 8351f5bef30SGrant Likely r->start = taddr; 8361f5bef30SGrant Likely r->end = taddr + size - 1; 8371f5bef30SGrant Likely r->flags = flags; 83835f3da32SBenoit Cousson r->name = name ? name : dev->full_name; 83935f3da32SBenoit Cousson 8401f5bef30SGrant Likely return 0; 8411f5bef30SGrant Likely } 8421f5bef30SGrant Likely 8431f5bef30SGrant Likely /** 8441f5bef30SGrant Likely * of_address_to_resource - Translate device tree address and return as resource 8451f5bef30SGrant Likely * 8461f5bef30SGrant Likely * Note that if your address is a PIO address, the conversion will fail if 8471f5bef30SGrant Likely * the physical address can't be internally converted to an IO token with 8487602f422SFrank Rowand * pci_address_to_pio(), that is because it's either called too early or it 8491f5bef30SGrant Likely * can't be matched to any host bridge IO space 8501f5bef30SGrant Likely */ 8511f5bef30SGrant Likely int of_address_to_resource(struct device_node *dev, int index, 8521f5bef30SGrant Likely struct resource *r) 8531f5bef30SGrant Likely { 8540131d897SSebastian Andrzej Siewior const __be32 *addrp; 8551f5bef30SGrant Likely u64 size; 8561f5bef30SGrant Likely unsigned int flags; 85735f3da32SBenoit Cousson const char *name = NULL; 8581f5bef30SGrant Likely 8591f5bef30SGrant Likely addrp = of_get_address(dev, index, &size, &flags); 8601f5bef30SGrant Likely if (addrp == NULL) 8611f5bef30SGrant Likely return -EINVAL; 86235f3da32SBenoit Cousson 86335f3da32SBenoit Cousson /* Get optional "reg-names" property to add a name to a resource */ 86435f3da32SBenoit Cousson of_property_read_string_index(dev, "reg-names", index, &name); 86535f3da32SBenoit Cousson 86635f3da32SBenoit Cousson return __of_address_to_resource(dev, addrp, size, flags, name, r); 8671f5bef30SGrant Likely } 8681f5bef30SGrant Likely EXPORT_SYMBOL_GPL(of_address_to_resource); 8691f5bef30SGrant Likely 8706b884a8dSGrant Likely /** 8716b884a8dSGrant Likely * of_iomap - Maps the memory mapped IO for a given device_node 8721094d5dbSWenchao Hao * @np: the device whose io range will be mapped 8736b884a8dSGrant Likely * @index: index of the io range 8746b884a8dSGrant Likely * 8756b884a8dSGrant Likely * Returns a pointer to the mapped memory 8766b884a8dSGrant Likely */ 8776b884a8dSGrant Likely void __iomem *of_iomap(struct device_node *np, int index) 8786b884a8dSGrant Likely { 8796b884a8dSGrant Likely struct resource res; 8806b884a8dSGrant Likely 8816b884a8dSGrant Likely if (of_address_to_resource(np, index, &res)) 8826b884a8dSGrant Likely return NULL; 8836b884a8dSGrant Likely 88428c1b6d6SFelipe Balbi return ioremap(res.start, resource_size(&res)); 8856b884a8dSGrant Likely } 8866b884a8dSGrant Likely EXPORT_SYMBOL(of_iomap); 88718308c94SGrygorii Strashko 888efd342fbSMatthias Brugger /* 889efd342fbSMatthias Brugger * of_io_request_and_map - Requests a resource and maps the memory mapped IO 890efd342fbSMatthias Brugger * for a given device_node 891efd342fbSMatthias Brugger * @device: the device whose io range will be mapped 892efd342fbSMatthias Brugger * @index: index of the io range 893b01dcdd8SBenjamin Herrenschmidt * @name: name "override" for the memory region request or NULL 894efd342fbSMatthias Brugger * 895efd342fbSMatthias Brugger * Returns a pointer to the requested and mapped memory or an ERR_PTR() encoded 896efd342fbSMatthias Brugger * error code on failure. Usage example: 897efd342fbSMatthias Brugger * 898efd342fbSMatthias Brugger * base = of_io_request_and_map(node, 0, "foo"); 899efd342fbSMatthias Brugger * if (IS_ERR(base)) 900efd342fbSMatthias Brugger * return PTR_ERR(base); 901efd342fbSMatthias Brugger */ 902efd342fbSMatthias Brugger void __iomem *of_io_request_and_map(struct device_node *np, int index, 903b75b276bSMatthias Brugger const char *name) 904efd342fbSMatthias Brugger { 905efd342fbSMatthias Brugger struct resource res; 906efd342fbSMatthias Brugger void __iomem *mem; 907efd342fbSMatthias Brugger 908efd342fbSMatthias Brugger if (of_address_to_resource(np, index, &res)) 909efd342fbSMatthias Brugger return IOMEM_ERR_PTR(-EINVAL); 910efd342fbSMatthias Brugger 911b01dcdd8SBenjamin Herrenschmidt if (!name) 912b01dcdd8SBenjamin Herrenschmidt name = res.name; 913efd342fbSMatthias Brugger if (!request_mem_region(res.start, resource_size(&res), name)) 914efd342fbSMatthias Brugger return IOMEM_ERR_PTR(-EBUSY); 915efd342fbSMatthias Brugger 916efd342fbSMatthias Brugger mem = ioremap(res.start, resource_size(&res)); 917efd342fbSMatthias Brugger if (!mem) { 918efd342fbSMatthias Brugger release_mem_region(res.start, resource_size(&res)); 919efd342fbSMatthias Brugger return IOMEM_ERR_PTR(-ENOMEM); 920efd342fbSMatthias Brugger } 921efd342fbSMatthias Brugger 922efd342fbSMatthias Brugger return mem; 923efd342fbSMatthias Brugger } 924efd342fbSMatthias Brugger EXPORT_SYMBOL(of_io_request_and_map); 925efd342fbSMatthias Brugger 92618308c94SGrygorii Strashko /** 92718308c94SGrygorii Strashko * of_dma_get_range - Get DMA range info 92818308c94SGrygorii Strashko * @np: device node to get DMA range info 92918308c94SGrygorii Strashko * @dma_addr: pointer to store initial DMA address of DMA range 93018308c94SGrygorii Strashko * @paddr: pointer to store initial CPU address of DMA range 93118308c94SGrygorii Strashko * @size: pointer to store size of DMA range 93218308c94SGrygorii Strashko * 93318308c94SGrygorii Strashko * Look in bottom up direction for the first "dma-ranges" property 93418308c94SGrygorii Strashko * and parse it. 93518308c94SGrygorii Strashko * dma-ranges format: 93618308c94SGrygorii Strashko * DMA addr (dma_addr) : naddr cells 93718308c94SGrygorii Strashko * CPU addr (phys_addr_t) : pna cells 93818308c94SGrygorii Strashko * size : nsize cells 93918308c94SGrygorii Strashko * 94018308c94SGrygorii Strashko * It returns -ENODEV if "dma-ranges" property was not found 94118308c94SGrygorii Strashko * for this device in DT. 94218308c94SGrygorii Strashko */ 94318308c94SGrygorii Strashko int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *size) 94418308c94SGrygorii Strashko { 94518308c94SGrygorii Strashko struct device_node *node = of_node_get(np); 94618308c94SGrygorii Strashko const __be32 *ranges = NULL; 9477a8b64d1SRob Herring int len; 94818308c94SGrygorii Strashko int ret = 0; 949951d4885SRobin Murphy bool found_dma_ranges = false; 9507a8b64d1SRob Herring struct of_range_parser parser; 9517a8b64d1SRob Herring struct of_range range; 9529d55bebdSRob Herring u64 dma_start = U64_MAX, dma_end = 0, dma_offset = 0; 95318308c94SGrygorii Strashko 954951d4885SRobin Murphy while (node) { 95518308c94SGrygorii Strashko ranges = of_get_property(node, "dma-ranges", &len); 95618308c94SGrygorii Strashko 95718308c94SGrygorii Strashko /* Ignore empty ranges, they imply no translation required */ 95818308c94SGrygorii Strashko if (ranges && len > 0) 95918308c94SGrygorii Strashko break; 96018308c94SGrygorii Strashko 961951d4885SRobin Murphy /* Once we find 'dma-ranges', then a missing one is an error */ 962951d4885SRobin Murphy if (found_dma_ranges && !ranges) { 963951d4885SRobin Murphy ret = -ENODEV; 964951d4885SRobin Murphy goto out; 965951d4885SRobin Murphy } 966951d4885SRobin Murphy found_dma_ranges = true; 967951d4885SRobin Murphy 968951d4885SRobin Murphy node = of_get_next_dma_parent(node); 96918308c94SGrygorii Strashko } 97018308c94SGrygorii Strashko 971951d4885SRobin Murphy if (!node || !ranges) { 9720d638a07SRob Herring pr_debug("no dma-ranges found for node(%pOF)\n", np); 97318308c94SGrygorii Strashko ret = -ENODEV; 97418308c94SGrygorii Strashko goto out; 97518308c94SGrygorii Strashko } 97618308c94SGrygorii Strashko 9777a8b64d1SRob Herring of_dma_range_parser_init(&parser, node); 97818308c94SGrygorii Strashko 9797a8b64d1SRob Herring for_each_of_range(&parser, &range) { 98018308c94SGrygorii Strashko pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", 9817a8b64d1SRob Herring range.bus_addr, range.cpu_addr, range.size); 9827a8b64d1SRob Herring 9839d55bebdSRob Herring if (dma_offset && range.cpu_addr - range.bus_addr != dma_offset) { 9849d55bebdSRob Herring pr_warn("Can't handle multiple dma-ranges with different offsets on node(%pOF)\n", node); 9859d55bebdSRob Herring /* Don't error out as we'd break some existing DTs */ 9869d55bebdSRob Herring continue; 9879d55bebdSRob Herring } 988f49c7fafSColin Ian King if (range.cpu_addr == OF_BAD_ADDR) { 989f49c7fafSColin Ian King pr_err("translation of DMA address(%llx) to CPU address failed node(%pOF)\n", 990f49c7fafSColin Ian King range.bus_addr, node); 991f49c7fafSColin Ian King continue; 992f49c7fafSColin Ian King } 9939d55bebdSRob Herring dma_offset = range.cpu_addr - range.bus_addr; 9947a8b64d1SRob Herring 9959d55bebdSRob Herring /* Take lower and upper limits */ 9969d55bebdSRob Herring if (range.bus_addr < dma_start) 9979d55bebdSRob Herring dma_start = range.bus_addr; 9989d55bebdSRob Herring if (range.bus_addr + range.size > dma_end) 9999d55bebdSRob Herring dma_end = range.bus_addr + range.size; 10009d55bebdSRob Herring } 10019d55bebdSRob Herring 10029d55bebdSRob Herring if (dma_start >= dma_end) { 10039d55bebdSRob Herring ret = -EINVAL; 10049d55bebdSRob Herring pr_debug("Invalid DMA ranges configuration on node(%pOF)\n", 10059d55bebdSRob Herring node); 10067a8b64d1SRob Herring goto out; 10077a8b64d1SRob Herring } 10087a8b64d1SRob Herring 10099d55bebdSRob Herring *dma_addr = dma_start; 10109d55bebdSRob Herring *size = dma_end - dma_start; 10119d55bebdSRob Herring *paddr = dma_start + dma_offset; 10129d55bebdSRob Herring 10139d55bebdSRob Herring pr_debug("final: dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", 10149d55bebdSRob Herring *dma_addr, *paddr, *size); 101518308c94SGrygorii Strashko 101618308c94SGrygorii Strashko out: 101718308c94SGrygorii Strashko of_node_put(node); 101818308c94SGrygorii Strashko 101918308c94SGrygorii Strashko return ret; 102018308c94SGrygorii Strashko } 102192ea637eSSantosh Shilimkar 102292ea637eSSantosh Shilimkar /** 102392ea637eSSantosh Shilimkar * of_dma_is_coherent - Check if device is coherent 102492ea637eSSantosh Shilimkar * @np: device node 102592ea637eSSantosh Shilimkar * 102692ea637eSSantosh Shilimkar * It returns true if "dma-coherent" property was found 1027dabf6b36SMichael Ellerman * for this device in the DT, or if DMA is coherent by 1028dabf6b36SMichael Ellerman * default for OF devices on the current platform. 102992ea637eSSantosh Shilimkar */ 103092ea637eSSantosh Shilimkar bool of_dma_is_coherent(struct device_node *np) 103192ea637eSSantosh Shilimkar { 103292ea637eSSantosh Shilimkar struct device_node *node = of_node_get(np); 103392ea637eSSantosh Shilimkar 1034dabf6b36SMichael Ellerman if (IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT)) 1035dabf6b36SMichael Ellerman return true; 1036dabf6b36SMichael Ellerman 103792ea637eSSantosh Shilimkar while (node) { 103892ea637eSSantosh Shilimkar if (of_property_read_bool(node, "dma-coherent")) { 103992ea637eSSantosh Shilimkar of_node_put(node); 104092ea637eSSantosh Shilimkar return true; 104192ea637eSSantosh Shilimkar } 1042c60bf3ebSRobin Murphy node = of_get_next_dma_parent(node); 104392ea637eSSantosh Shilimkar } 104492ea637eSSantosh Shilimkar of_node_put(node); 104592ea637eSSantosh Shilimkar return false; 104692ea637eSSantosh Shilimkar } 104792ea637eSSantosh Shilimkar EXPORT_SYMBOL_GPL(of_dma_is_coherent); 1048