Merge tag 'sched-core-2021-02-17' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / of / address.c
index 1c3257a..73ddf25 100644 (file)
@@ -1024,6 +1024,48 @@ out:
 }
 #endif /* CONFIG_HAS_DMA */
 
+/**
+ * of_dma_get_max_cpu_address - Gets highest CPU address suitable for DMA
+ * @np: The node to start searching from or NULL to start from the root
+ *
+ * Gets the highest CPU physical address that is addressable by all DMA masters
+ * in the sub-tree pointed by np, or the whole tree if NULL is passed. If no
+ * DMA constrained device is found, it returns PHYS_ADDR_MAX.
+ */
+phys_addr_t __init of_dma_get_max_cpu_address(struct device_node *np)
+{
+       phys_addr_t max_cpu_addr = PHYS_ADDR_MAX;
+       struct of_range_parser parser;
+       phys_addr_t subtree_max_addr;
+       struct device_node *child;
+       struct of_range range;
+       const __be32 *ranges;
+       u64 cpu_end = 0;
+       int len;
+
+       if (!np)
+               np = of_root;
+
+       ranges = of_get_property(np, "dma-ranges", &len);
+       if (ranges && len) {
+               of_dma_range_parser_init(&parser, np);
+               for_each_of_range(&parser, &range)
+                       if (range.cpu_addr + range.size > cpu_end)
+                               cpu_end = range.cpu_addr + range.size - 1;
+
+               if (max_cpu_addr > cpu_end)
+                       max_cpu_addr = cpu_end;
+       }
+
+       for_each_available_child_of_node(np, child) {
+               subtree_max_addr = of_dma_get_max_cpu_address(child);
+               if (max_cpu_addr > subtree_max_addr)
+                       max_cpu_addr = subtree_max_addr;
+       }
+
+       return max_cpu_addr;
+}
+
 /**
  * of_dma_is_coherent - Check if device is coherent
  * @np:        device node