.. | .. |
---|
13 | 13 | #include <linux/sizes.h> |
---|
14 | 14 | #include <linux/slab.h> |
---|
15 | 15 | #include <linux/string.h> |
---|
| 16 | +#include <linux/dma-direct.h> /* for bus_dma_region */ |
---|
| 17 | + |
---|
| 18 | +#include "of_private.h" |
---|
16 | 19 | |
---|
17 | 20 | /* Max address size we deal with */ |
---|
18 | 21 | #define OF_MAX_ADDR_CELLS 4 |
---|
.. | .. |
---|
47 | 50 | u64 (*map)(__be32 *addr, const __be32 *range, |
---|
48 | 51 | int na, int ns, int pna); |
---|
49 | 52 | int (*translate)(__be32 *addr, u64 offset, int na); |
---|
| 53 | + bool has_flags; |
---|
50 | 54 | unsigned int (*get_flags)(const __be32 *addr); |
---|
51 | 55 | }; |
---|
52 | 56 | |
---|
.. | .. |
---|
99 | 103 | } |
---|
100 | 104 | |
---|
101 | 105 | #ifdef CONFIG_PCI |
---|
102 | | -/* |
---|
103 | | - * PCI bus specific translator |
---|
104 | | - */ |
---|
105 | | - |
---|
106 | | -static int of_bus_pci_match(struct device_node *np) |
---|
107 | | -{ |
---|
108 | | - /* |
---|
109 | | - * "pciex" is PCI Express |
---|
110 | | - * "vci" is for the /chaos bridge on 1st-gen PCI powermacs |
---|
111 | | - * "ht" is hypertransport |
---|
112 | | - */ |
---|
113 | | - return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex") || |
---|
114 | | - !strcmp(np->type, "vci") || !strcmp(np->type, "ht"); |
---|
115 | | -} |
---|
116 | | - |
---|
117 | | -static void of_bus_pci_count_cells(struct device_node *np, |
---|
118 | | - int *addrc, int *sizec) |
---|
119 | | -{ |
---|
120 | | - if (addrc) |
---|
121 | | - *addrc = 3; |
---|
122 | | - if (sizec) |
---|
123 | | - *sizec = 2; |
---|
124 | | -} |
---|
125 | | - |
---|
126 | 106 | static unsigned int of_bus_pci_get_flags(const __be32 *addr) |
---|
127 | 107 | { |
---|
128 | 108 | unsigned int flags = 0; |
---|
129 | 109 | u32 w = be32_to_cpup(addr); |
---|
| 110 | + |
---|
| 111 | + if (!IS_ENABLED(CONFIG_PCI)) |
---|
| 112 | + return 0; |
---|
130 | 113 | |
---|
131 | 114 | switch((w >> 24) & 0x03) { |
---|
132 | 115 | case 0x01: |
---|
.. | .. |
---|
140 | 123 | if (w & 0x40000000) |
---|
141 | 124 | flags |= IORESOURCE_PREFETCH; |
---|
142 | 125 | return flags; |
---|
| 126 | +} |
---|
| 127 | + |
---|
| 128 | +/* |
---|
| 129 | + * PCI bus specific translator |
---|
| 130 | + */ |
---|
| 131 | + |
---|
| 132 | +static bool of_node_is_pcie(struct device_node *np) |
---|
| 133 | +{ |
---|
| 134 | + bool is_pcie = of_node_name_eq(np, "pcie"); |
---|
| 135 | + |
---|
| 136 | + if (is_pcie) |
---|
| 137 | + pr_warn_once("%pOF: Missing device_type\n", np); |
---|
| 138 | + |
---|
| 139 | + return is_pcie; |
---|
| 140 | +} |
---|
| 141 | + |
---|
| 142 | +static int of_bus_pci_match(struct device_node *np) |
---|
| 143 | +{ |
---|
| 144 | + /* |
---|
| 145 | + * "pciex" is PCI Express |
---|
| 146 | + * "vci" is for the /chaos bridge on 1st-gen PCI powermacs |
---|
| 147 | + * "ht" is hypertransport |
---|
| 148 | + * |
---|
| 149 | + * If none of the device_type match, and that the node name is |
---|
| 150 | + * "pcie", accept the device as PCI (with a warning). |
---|
| 151 | + */ |
---|
| 152 | + return of_node_is_type(np, "pci") || of_node_is_type(np, "pciex") || |
---|
| 153 | + of_node_is_type(np, "vci") || of_node_is_type(np, "ht") || |
---|
| 154 | + of_node_is_pcie(np); |
---|
| 155 | +} |
---|
| 156 | + |
---|
| 157 | +static void of_bus_pci_count_cells(struct device_node *np, |
---|
| 158 | + int *addrc, int *sizec) |
---|
| 159 | +{ |
---|
| 160 | + if (addrc) |
---|
| 161 | + *addrc = 3; |
---|
| 162 | + if (sizec) |
---|
| 163 | + *sizec = 2; |
---|
143 | 164 | } |
---|
144 | 165 | |
---|
145 | 166 | static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, |
---|
.. | .. |
---|
232 | 253 | } |
---|
233 | 254 | EXPORT_SYMBOL_GPL(of_pci_address_to_resource); |
---|
234 | 255 | |
---|
235 | | -static int parser_init(struct of_pci_range_parser *parser, |
---|
236 | | - struct device_node *node, const char *name) |
---|
237 | | -{ |
---|
238 | | - const int na = 3, ns = 2; |
---|
239 | | - int rlen; |
---|
240 | | - |
---|
241 | | - parser->node = node; |
---|
242 | | - parser->pna = of_n_addr_cells(node); |
---|
243 | | - parser->np = parser->pna + na + ns; |
---|
244 | | - |
---|
245 | | - parser->range = of_get_property(node, name, &rlen); |
---|
246 | | - if (parser->range == NULL) |
---|
247 | | - return -ENOENT; |
---|
248 | | - |
---|
249 | | - parser->end = parser->range + rlen / sizeof(__be32); |
---|
250 | | - |
---|
251 | | - return 0; |
---|
252 | | -} |
---|
253 | | - |
---|
254 | | -int of_pci_range_parser_init(struct of_pci_range_parser *parser, |
---|
255 | | - struct device_node *node) |
---|
256 | | -{ |
---|
257 | | - return parser_init(parser, node, "ranges"); |
---|
258 | | -} |
---|
259 | | -EXPORT_SYMBOL_GPL(of_pci_range_parser_init); |
---|
260 | | - |
---|
261 | | -int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser, |
---|
262 | | - struct device_node *node) |
---|
263 | | -{ |
---|
264 | | - return parser_init(parser, node, "dma-ranges"); |
---|
265 | | -} |
---|
266 | | -EXPORT_SYMBOL_GPL(of_pci_dma_range_parser_init); |
---|
267 | | - |
---|
268 | | -struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, |
---|
269 | | - struct of_pci_range *range) |
---|
270 | | -{ |
---|
271 | | - const int na = 3, ns = 2; |
---|
272 | | - |
---|
273 | | - if (!range) |
---|
274 | | - return NULL; |
---|
275 | | - |
---|
276 | | - if (!parser->range || parser->range + parser->np > parser->end) |
---|
277 | | - return NULL; |
---|
278 | | - |
---|
279 | | - range->pci_space = be32_to_cpup(parser->range); |
---|
280 | | - range->flags = of_bus_pci_get_flags(parser->range); |
---|
281 | | - range->pci_addr = of_read_number(parser->range + 1, ns); |
---|
282 | | - range->cpu_addr = of_translate_address(parser->node, |
---|
283 | | - parser->range + na); |
---|
284 | | - range->size = of_read_number(parser->range + parser->pna + na, ns); |
---|
285 | | - |
---|
286 | | - parser->range += parser->np; |
---|
287 | | - |
---|
288 | | - /* Now consume following elements while they are contiguous */ |
---|
289 | | - while (parser->range + parser->np <= parser->end) { |
---|
290 | | - u32 flags; |
---|
291 | | - u64 pci_addr, cpu_addr, size; |
---|
292 | | - |
---|
293 | | - flags = of_bus_pci_get_flags(parser->range); |
---|
294 | | - pci_addr = of_read_number(parser->range + 1, ns); |
---|
295 | | - cpu_addr = of_translate_address(parser->node, |
---|
296 | | - parser->range + na); |
---|
297 | | - size = of_read_number(parser->range + parser->pna + na, ns); |
---|
298 | | - |
---|
299 | | - if (flags != range->flags) |
---|
300 | | - break; |
---|
301 | | - if (pci_addr != range->pci_addr + range->size || |
---|
302 | | - cpu_addr != range->cpu_addr + range->size) |
---|
303 | | - break; |
---|
304 | | - |
---|
305 | | - range->size += size; |
---|
306 | | - parser->range += parser->np; |
---|
307 | | - } |
---|
308 | | - |
---|
309 | | - return range; |
---|
310 | | -} |
---|
311 | | -EXPORT_SYMBOL_GPL(of_pci_range_parser_one); |
---|
312 | | - |
---|
313 | 256 | /* |
---|
314 | 257 | * of_pci_range_to_resource - Create a resource from an of_pci_range |
---|
315 | 258 | * @range: the PCI range that describes the resource |
---|
.. | .. |
---|
371 | 314 | |
---|
372 | 315 | static int of_bus_isa_match(struct device_node *np) |
---|
373 | 316 | { |
---|
374 | | - return !strcmp(np->name, "isa"); |
---|
| 317 | + return of_node_name_eq(np, "isa"); |
---|
375 | 318 | } |
---|
376 | 319 | |
---|
377 | 320 | static void of_bus_isa_count_cells(struct device_node *child, |
---|
.. | .. |
---|
437 | 380 | .count_cells = of_bus_pci_count_cells, |
---|
438 | 381 | .map = of_bus_pci_map, |
---|
439 | 382 | .translate = of_bus_pci_translate, |
---|
| 383 | + .has_flags = true, |
---|
440 | 384 | .get_flags = of_bus_pci_get_flags, |
---|
441 | 385 | }, |
---|
442 | 386 | #endif /* CONFIG_PCI */ |
---|
.. | .. |
---|
448 | 392 | .count_cells = of_bus_isa_count_cells, |
---|
449 | 393 | .map = of_bus_isa_map, |
---|
450 | 394 | .translate = of_bus_isa_translate, |
---|
| 395 | + .has_flags = true, |
---|
451 | 396 | .get_flags = of_bus_isa_get_flags, |
---|
452 | 397 | }, |
---|
453 | 398 | /* Default */ |
---|
.. | .. |
---|
517 | 462 | * |
---|
518 | 463 | * As far as we know, this damage only exists on Apple machines, so |
---|
519 | 464 | * This code is only enabled on powerpc. --gcl |
---|
| 465 | + * |
---|
| 466 | + * This quirk also applies for 'dma-ranges' which frequently exist in |
---|
| 467 | + * child nodes without 'dma-ranges' in the parent nodes. --RobH |
---|
520 | 468 | */ |
---|
521 | 469 | ranges = of_get_property(parent, rprop, &rlen); |
---|
522 | | - if (ranges == NULL && !of_empty_ranges_quirk(parent)) { |
---|
| 470 | + if (ranges == NULL && !of_empty_ranges_quirk(parent) && |
---|
| 471 | + strcmp(rprop, "dma-ranges")) { |
---|
523 | 472 | pr_debug("no ranges; cannot translate\n"); |
---|
524 | 473 | return 1; |
---|
525 | 474 | } |
---|
.. | .. |
---|
569 | 518 | * relative to that node. |
---|
570 | 519 | */ |
---|
571 | 520 | static u64 __of_translate_address(struct device_node *dev, |
---|
| 521 | + struct device_node *(*get_parent)(const struct device_node *), |
---|
572 | 522 | const __be32 *in_addr, const char *rprop, |
---|
573 | 523 | struct device_node **host) |
---|
574 | 524 | { |
---|
.. | .. |
---|
585 | 535 | |
---|
586 | 536 | *host = NULL; |
---|
587 | 537 | /* Get parent & match bus type */ |
---|
588 | | - parent = of_get_parent(dev); |
---|
| 538 | + parent = get_parent(dev); |
---|
589 | 539 | if (parent == NULL) |
---|
590 | 540 | goto bail; |
---|
591 | 541 | bus = of_match_bus(parent); |
---|
.. | .. |
---|
609 | 559 | /* Switch to parent bus */ |
---|
610 | 560 | of_node_put(dev); |
---|
611 | 561 | dev = parent; |
---|
612 | | - parent = of_get_parent(dev); |
---|
| 562 | + parent = get_parent(dev); |
---|
613 | 563 | |
---|
614 | 564 | /* If root, we have finished */ |
---|
615 | 565 | if (parent == NULL) { |
---|
.. | .. |
---|
665 | 615 | struct device_node *host; |
---|
666 | 616 | u64 ret; |
---|
667 | 617 | |
---|
668 | | - ret = __of_translate_address(dev, in_addr, "ranges", &host); |
---|
| 618 | + ret = __of_translate_address(dev, of_get_parent, |
---|
| 619 | + in_addr, "ranges", &host); |
---|
669 | 620 | if (host) { |
---|
670 | 621 | of_node_put(host); |
---|
671 | 622 | return OF_BAD_ADDR; |
---|
.. | .. |
---|
675 | 626 | } |
---|
676 | 627 | EXPORT_SYMBOL(of_translate_address); |
---|
677 | 628 | |
---|
| 629 | +static struct device_node *__of_get_dma_parent(const struct device_node *np) |
---|
| 630 | +{ |
---|
| 631 | + struct of_phandle_args args; |
---|
| 632 | + int ret, index; |
---|
| 633 | + |
---|
| 634 | + index = of_property_match_string(np, "interconnect-names", "dma-mem"); |
---|
| 635 | + if (index < 0) |
---|
| 636 | + return of_get_parent(np); |
---|
| 637 | + |
---|
| 638 | + ret = of_parse_phandle_with_args(np, "interconnects", |
---|
| 639 | + "#interconnect-cells", |
---|
| 640 | + index, &args); |
---|
| 641 | + if (ret < 0) |
---|
| 642 | + return of_get_parent(np); |
---|
| 643 | + |
---|
| 644 | + return of_node_get(args.np); |
---|
| 645 | +} |
---|
| 646 | + |
---|
| 647 | +static struct device_node *of_get_next_dma_parent(struct device_node *np) |
---|
| 648 | +{ |
---|
| 649 | + struct device_node *parent; |
---|
| 650 | + |
---|
| 651 | + parent = __of_get_dma_parent(np); |
---|
| 652 | + of_node_put(np); |
---|
| 653 | + |
---|
| 654 | + return parent; |
---|
| 655 | +} |
---|
| 656 | + |
---|
678 | 657 | u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) |
---|
679 | 658 | { |
---|
680 | 659 | struct device_node *host; |
---|
681 | 660 | u64 ret; |
---|
682 | 661 | |
---|
683 | | - ret = __of_translate_address(dev, in_addr, "dma-ranges", &host); |
---|
| 662 | + ret = __of_translate_address(dev, __of_get_dma_parent, |
---|
| 663 | + in_addr, "dma-ranges", &host); |
---|
684 | 664 | |
---|
685 | 665 | if (host) { |
---|
686 | 666 | of_node_put(host); |
---|
.. | .. |
---|
729 | 709 | } |
---|
730 | 710 | EXPORT_SYMBOL(of_get_address); |
---|
731 | 711 | |
---|
| 712 | +static int parser_init(struct of_pci_range_parser *parser, |
---|
| 713 | + struct device_node *node, const char *name) |
---|
| 714 | +{ |
---|
| 715 | + int rlen; |
---|
| 716 | + |
---|
| 717 | + parser->node = node; |
---|
| 718 | + parser->pna = of_n_addr_cells(node); |
---|
| 719 | + parser->na = of_bus_n_addr_cells(node); |
---|
| 720 | + parser->ns = of_bus_n_size_cells(node); |
---|
| 721 | + parser->dma = !strcmp(name, "dma-ranges"); |
---|
| 722 | + parser->bus = of_match_bus(node); |
---|
| 723 | + |
---|
| 724 | + parser->range = of_get_property(node, name, &rlen); |
---|
| 725 | + if (parser->range == NULL) |
---|
| 726 | + return -ENOENT; |
---|
| 727 | + |
---|
| 728 | + parser->end = parser->range + rlen / sizeof(__be32); |
---|
| 729 | + |
---|
| 730 | + return 0; |
---|
| 731 | +} |
---|
| 732 | + |
---|
| 733 | +int of_pci_range_parser_init(struct of_pci_range_parser *parser, |
---|
| 734 | + struct device_node *node) |
---|
| 735 | +{ |
---|
| 736 | + return parser_init(parser, node, "ranges"); |
---|
| 737 | +} |
---|
| 738 | +EXPORT_SYMBOL_GPL(of_pci_range_parser_init); |
---|
| 739 | + |
---|
| 740 | +int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser, |
---|
| 741 | + struct device_node *node) |
---|
| 742 | +{ |
---|
| 743 | + return parser_init(parser, node, "dma-ranges"); |
---|
| 744 | +} |
---|
| 745 | +EXPORT_SYMBOL_GPL(of_pci_dma_range_parser_init); |
---|
| 746 | +#define of_dma_range_parser_init of_pci_dma_range_parser_init |
---|
| 747 | + |
---|
| 748 | +struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, |
---|
| 749 | + struct of_pci_range *range) |
---|
| 750 | +{ |
---|
| 751 | + int na = parser->na; |
---|
| 752 | + int ns = parser->ns; |
---|
| 753 | + int np = parser->pna + na + ns; |
---|
| 754 | + int busflag_na = 0; |
---|
| 755 | + |
---|
| 756 | + if (!range) |
---|
| 757 | + return NULL; |
---|
| 758 | + |
---|
| 759 | + if (!parser->range || parser->range + np > parser->end) |
---|
| 760 | + return NULL; |
---|
| 761 | + |
---|
| 762 | + range->flags = parser->bus->get_flags(parser->range); |
---|
| 763 | + |
---|
| 764 | + /* A extra cell for resource flags */ |
---|
| 765 | + if (parser->bus->has_flags) |
---|
| 766 | + busflag_na = 1; |
---|
| 767 | + |
---|
| 768 | + range->bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na); |
---|
| 769 | + |
---|
| 770 | + if (parser->dma) |
---|
| 771 | + range->cpu_addr = of_translate_dma_address(parser->node, |
---|
| 772 | + parser->range + na); |
---|
| 773 | + else |
---|
| 774 | + range->cpu_addr = of_translate_address(parser->node, |
---|
| 775 | + parser->range + na); |
---|
| 776 | + range->size = of_read_number(parser->range + parser->pna + na, ns); |
---|
| 777 | + |
---|
| 778 | + parser->range += np; |
---|
| 779 | + |
---|
| 780 | + /* Now consume following elements while they are contiguous */ |
---|
| 781 | + while (parser->range + np <= parser->end) { |
---|
| 782 | + u32 flags = 0; |
---|
| 783 | + u64 bus_addr, cpu_addr, size; |
---|
| 784 | + |
---|
| 785 | + flags = parser->bus->get_flags(parser->range); |
---|
| 786 | + bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na); |
---|
| 787 | + if (parser->dma) |
---|
| 788 | + cpu_addr = of_translate_dma_address(parser->node, |
---|
| 789 | + parser->range + na); |
---|
| 790 | + else |
---|
| 791 | + cpu_addr = of_translate_address(parser->node, |
---|
| 792 | + parser->range + na); |
---|
| 793 | + size = of_read_number(parser->range + parser->pna + na, ns); |
---|
| 794 | + |
---|
| 795 | + if (flags != range->flags) |
---|
| 796 | + break; |
---|
| 797 | + if (bus_addr != range->bus_addr + range->size || |
---|
| 798 | + cpu_addr != range->cpu_addr + range->size) |
---|
| 799 | + break; |
---|
| 800 | + |
---|
| 801 | + range->size += size; |
---|
| 802 | + parser->range += np; |
---|
| 803 | + } |
---|
| 804 | + |
---|
| 805 | + return range; |
---|
| 806 | +} |
---|
| 807 | +EXPORT_SYMBOL_GPL(of_pci_range_parser_one); |
---|
| 808 | + |
---|
732 | 809 | static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr, |
---|
733 | 810 | u64 size) |
---|
734 | 811 | { |
---|
.. | .. |
---|
736 | 813 | unsigned long port; |
---|
737 | 814 | struct device_node *host; |
---|
738 | 815 | |
---|
739 | | - taddr = __of_translate_address(dev, in_addr, "ranges", &host); |
---|
| 816 | + taddr = __of_translate_address(dev, of_get_parent, |
---|
| 817 | + in_addr, "ranges", &host); |
---|
740 | 818 | if (host) { |
---|
741 | 819 | /* host-specific port access */ |
---|
742 | 820 | port = logic_pio_trans_hwaddr(&host->fwnode, taddr, size); |
---|
.. | .. |
---|
804 | 882 | } |
---|
805 | 883 | EXPORT_SYMBOL_GPL(of_address_to_resource); |
---|
806 | 884 | |
---|
807 | | -struct device_node *of_find_matching_node_by_address(struct device_node *from, |
---|
808 | | - const struct of_device_id *matches, |
---|
809 | | - u64 base_address) |
---|
810 | | -{ |
---|
811 | | - struct device_node *dn = of_find_matching_node(from, matches); |
---|
812 | | - struct resource res; |
---|
813 | | - |
---|
814 | | - while (dn) { |
---|
815 | | - if (!of_address_to_resource(dn, 0, &res) && |
---|
816 | | - res.start == base_address) |
---|
817 | | - return dn; |
---|
818 | | - |
---|
819 | | - dn = of_find_matching_node(dn, matches); |
---|
820 | | - } |
---|
821 | | - |
---|
822 | | - return NULL; |
---|
823 | | -} |
---|
824 | | - |
---|
825 | | - |
---|
826 | 885 | /** |
---|
827 | 886 | * of_iomap - Maps the memory mapped IO for a given device_node |
---|
828 | | - * @device: the device whose io range will be mapped |
---|
| 887 | + * @np: the device whose io range will be mapped |
---|
829 | 888 | * @index: index of the io range |
---|
830 | 889 | * |
---|
831 | 890 | * Returns a pointer to the mapped memory |
---|
.. | .. |
---|
879 | 938 | } |
---|
880 | 939 | EXPORT_SYMBOL(of_io_request_and_map); |
---|
881 | 940 | |
---|
| 941 | +#ifdef CONFIG_HAS_DMA |
---|
882 | 942 | /** |
---|
883 | | - * of_dma_get_range - Get DMA range info |
---|
| 943 | + * of_dma_get_range - Get DMA range info and put it into a map array |
---|
884 | 944 | * @np: device node to get DMA range info |
---|
885 | | - * @dma_addr: pointer to store initial DMA address of DMA range |
---|
886 | | - * @paddr: pointer to store initial CPU address of DMA range |
---|
887 | | - * @size: pointer to store size of DMA range |
---|
| 945 | + * @map: dma range structure to return |
---|
888 | 946 | * |
---|
889 | 947 | * Look in bottom up direction for the first "dma-ranges" property |
---|
890 | | - * and parse it. |
---|
891 | | - * dma-ranges format: |
---|
| 948 | + * and parse it. Put the information into a DMA offset map array. |
---|
| 949 | + * |
---|
| 950 | + * dma-ranges format: |
---|
892 | 951 | * DMA addr (dma_addr) : naddr cells |
---|
893 | 952 | * CPU addr (phys_addr_t) : pna cells |
---|
894 | 953 | * size : nsize cells |
---|
895 | 954 | * |
---|
896 | | - * It returns -ENODEV if "dma-ranges" property was not found |
---|
897 | | - * for this device in DT. |
---|
| 955 | + * It returns -ENODEV if "dma-ranges" property was not found for this |
---|
| 956 | + * device in the DT. |
---|
898 | 957 | */ |
---|
899 | | -int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *size) |
---|
| 958 | +int of_dma_get_range(struct device_node *np, const struct bus_dma_region **map) |
---|
900 | 959 | { |
---|
901 | 960 | struct device_node *node = of_node_get(np); |
---|
902 | 961 | const __be32 *ranges = NULL; |
---|
903 | | - int len, naddr, nsize, pna; |
---|
| 962 | + bool found_dma_ranges = false; |
---|
| 963 | + struct of_range_parser parser; |
---|
| 964 | + struct of_range range; |
---|
| 965 | + struct bus_dma_region *r; |
---|
| 966 | + int len, num_ranges = 0; |
---|
904 | 967 | int ret = 0; |
---|
905 | | - u64 dmaaddr; |
---|
906 | 968 | |
---|
907 | | - if (!node) |
---|
908 | | - return -EINVAL; |
---|
909 | | - |
---|
910 | | - while (1) { |
---|
911 | | - naddr = of_n_addr_cells(node); |
---|
912 | | - nsize = of_n_size_cells(node); |
---|
913 | | - node = of_get_next_parent(node); |
---|
914 | | - if (!node) |
---|
915 | | - break; |
---|
916 | | - |
---|
| 969 | + while (node) { |
---|
917 | 970 | ranges = of_get_property(node, "dma-ranges", &len); |
---|
918 | 971 | |
---|
919 | 972 | /* Ignore empty ranges, they imply no translation required */ |
---|
920 | 973 | if (ranges && len > 0) |
---|
921 | 974 | break; |
---|
922 | 975 | |
---|
923 | | - /* |
---|
924 | | - * At least empty ranges has to be defined for parent node if |
---|
925 | | - * DMA is supported |
---|
926 | | - */ |
---|
927 | | - if (!ranges) |
---|
928 | | - break; |
---|
| 976 | + /* Once we find 'dma-ranges', then a missing one is an error */ |
---|
| 977 | + if (found_dma_ranges && !ranges) { |
---|
| 978 | + ret = -ENODEV; |
---|
| 979 | + goto out; |
---|
| 980 | + } |
---|
| 981 | + found_dma_ranges = true; |
---|
| 982 | + |
---|
| 983 | + node = of_get_next_dma_parent(node); |
---|
929 | 984 | } |
---|
930 | 985 | |
---|
931 | | - if (!ranges) { |
---|
| 986 | + if (!node || !ranges) { |
---|
932 | 987 | pr_debug("no dma-ranges found for node(%pOF)\n", np); |
---|
933 | 988 | ret = -ENODEV; |
---|
934 | 989 | goto out; |
---|
935 | 990 | } |
---|
936 | 991 | |
---|
937 | | - len /= sizeof(u32); |
---|
| 992 | + of_dma_range_parser_init(&parser, node); |
---|
| 993 | + for_each_of_range(&parser, &range) |
---|
| 994 | + num_ranges++; |
---|
938 | 995 | |
---|
939 | | - pna = of_n_addr_cells(node); |
---|
940 | | - |
---|
941 | | - /* dma-ranges format: |
---|
942 | | - * DMA addr : naddr cells |
---|
943 | | - * CPU addr : pna cells |
---|
944 | | - * size : nsize cells |
---|
945 | | - */ |
---|
946 | | - dmaaddr = of_read_number(ranges, naddr); |
---|
947 | | - *paddr = of_translate_dma_address(np, ranges); |
---|
948 | | - if (*paddr == OF_BAD_ADDR) { |
---|
949 | | - pr_err("translation of DMA address(%pad) to CPU address failed node(%pOF)\n", |
---|
950 | | - dma_addr, np); |
---|
951 | | - ret = -EINVAL; |
---|
| 996 | + r = kcalloc(num_ranges + 1, sizeof(*r), GFP_KERNEL); |
---|
| 997 | + if (!r) { |
---|
| 998 | + ret = -ENOMEM; |
---|
952 | 999 | goto out; |
---|
953 | 1000 | } |
---|
954 | | - *dma_addr = dmaaddr; |
---|
955 | 1001 | |
---|
956 | | - *size = of_read_number(ranges + naddr + pna, nsize); |
---|
957 | | - |
---|
958 | | - pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", |
---|
959 | | - *dma_addr, *paddr, *size); |
---|
960 | | - |
---|
| 1002 | + /* |
---|
| 1003 | + * Record all info in the generic DMA ranges array for struct device. |
---|
| 1004 | + */ |
---|
| 1005 | + *map = r; |
---|
| 1006 | + of_dma_range_parser_init(&parser, node); |
---|
| 1007 | + for_each_of_range(&parser, &range) { |
---|
| 1008 | + pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", |
---|
| 1009 | + range.bus_addr, range.cpu_addr, range.size); |
---|
| 1010 | + if (range.cpu_addr == OF_BAD_ADDR) { |
---|
| 1011 | + pr_err("translation of DMA address(%llx) to CPU address failed node(%pOF)\n", |
---|
| 1012 | + range.bus_addr, node); |
---|
| 1013 | + continue; |
---|
| 1014 | + } |
---|
| 1015 | + r->cpu_start = range.cpu_addr; |
---|
| 1016 | + r->dma_start = range.bus_addr; |
---|
| 1017 | + r->size = range.size; |
---|
| 1018 | + r->offset = range.cpu_addr - range.bus_addr; |
---|
| 1019 | + r++; |
---|
| 1020 | + } |
---|
961 | 1021 | out: |
---|
962 | 1022 | of_node_put(node); |
---|
963 | | - |
---|
964 | 1023 | return ret; |
---|
965 | 1024 | } |
---|
966 | | -EXPORT_SYMBOL_GPL(of_dma_get_range); |
---|
| 1025 | +#endif /* CONFIG_HAS_DMA */ |
---|
| 1026 | + |
---|
| 1027 | +/** |
---|
| 1028 | + * of_dma_get_max_cpu_address - Gets highest CPU address suitable for DMA |
---|
| 1029 | + * @np: The node to start searching from or NULL to start from the root |
---|
| 1030 | + * |
---|
| 1031 | + * Gets the highest CPU physical address that is addressable by all DMA masters |
---|
| 1032 | + * in the sub-tree pointed by np, or the whole tree if NULL is passed. If no |
---|
| 1033 | + * DMA constrained device is found, it returns PHYS_ADDR_MAX. |
---|
| 1034 | + */ |
---|
| 1035 | +phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np) |
---|
| 1036 | +{ |
---|
| 1037 | + phys_addr_t max_cpu_addr = PHYS_ADDR_MAX; |
---|
| 1038 | + struct of_range_parser parser; |
---|
| 1039 | + phys_addr_t subtree_max_addr; |
---|
| 1040 | + struct device_node *child; |
---|
| 1041 | + struct of_range range; |
---|
| 1042 | + const __be32 *ranges; |
---|
| 1043 | + u64 cpu_end = 0; |
---|
| 1044 | + int len; |
---|
| 1045 | + |
---|
| 1046 | + if (!np) |
---|
| 1047 | + np = of_root; |
---|
| 1048 | + |
---|
| 1049 | + ranges = of_get_property(np, "dma-ranges", &len); |
---|
| 1050 | + if (ranges && len) { |
---|
| 1051 | + of_dma_range_parser_init(&parser, np); |
---|
| 1052 | + for_each_of_range(&parser, &range) |
---|
| 1053 | + if (range.cpu_addr + range.size > cpu_end) |
---|
| 1054 | + cpu_end = range.cpu_addr + range.size - 1; |
---|
| 1055 | + |
---|
| 1056 | + if (max_cpu_addr > cpu_end) |
---|
| 1057 | + max_cpu_addr = cpu_end; |
---|
| 1058 | + } |
---|
| 1059 | + |
---|
| 1060 | + for_each_available_child_of_node(np, child) { |
---|
| 1061 | + subtree_max_addr = of_dma_get_max_cpu_address(child); |
---|
| 1062 | + if (max_cpu_addr > subtree_max_addr) |
---|
| 1063 | + max_cpu_addr = subtree_max_addr; |
---|
| 1064 | + } |
---|
| 1065 | + |
---|
| 1066 | + return max_cpu_addr; |
---|
| 1067 | +} |
---|
967 | 1068 | |
---|
968 | 1069 | /** |
---|
969 | 1070 | * of_dma_is_coherent - Check if device is coherent |
---|
.. | .. |
---|
987 | 1088 | of_node_put(node); |
---|
988 | 1089 | return true; |
---|
989 | 1090 | } |
---|
990 | | - node = of_get_next_parent(node); |
---|
| 1091 | + node = of_get_next_dma_parent(node); |
---|
991 | 1092 | } |
---|
992 | 1093 | of_node_put(node); |
---|
993 | 1094 | return false; |
---|