This code was based on:
    "arch/microblaze/kernel/prom_parse.c"
    "arch/powerpc/kernel/prom_parse.c"

Can be promoted as a global function for general use.

Signed-off-by: Hiroshi DOYU <[email protected]>
---
Based on the discussion:
http://marc.info/?l=linux-tegra&m=133732046606458&w=2
---
 drivers/iommu/tegra-smmu.c |   50 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 192fc4a..7fc444b 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -874,6 +874,56 @@ static struct iommu_ops smmu_iommu_ops = {
        .pgsize_bitmap  = SMMU_IOMMU_PGSIZES,
 };
 
+static int of_get_dma_window(struct device_node *dn,
+                       const char *propname, int index,
+                       unsigned long *busno,
+                       dma_addr_t *addr, size_t *size)
+{
+       const __be32 *dma_window, *end;
+       int bytes, cur_index = 0;
+
+       if (!dn || !addr || !size)
+               return -EINVAL;
+
+       if (!propname)
+               propname = "dma-window";
+
+       dma_window = of_get_property(dn, propname, &bytes);
+       if (!dma_window)
+               return -ENODEV;
+       end = dma_window + bytes / sizeof(*dma_window);
+
+       while (dma_window < end) {
+               u32 cells;
+               const void *prop;
+
+               /* busno is always one cell */
+               if (busno)
+                       *busno = be32_to_cpup(dma_window++);
+
+               prop = of_get_property(dn, "#dma-address-cells", NULL);
+               if (!prop)
+                       prop = of_get_property(dn, "#address-cells", NULL);
+
+               cells = prop ? be32_to_cpup(prop) : of_n_addr_cells(dn);
+               if (!cells)
+                       return -EINVAL;
+               *addr = of_read_number(dma_window, cells);
+               dma_window += cells;
+
+               prop = of_get_property(dn, "#dma-size-cells", NULL);
+               cells = prop ? be32_to_cpup(prop) : of_n_size_cells(dn);
+               if (!cells)
+                       return -EINVAL;
+               *size = of_read_number(dma_window, cells);
+               dma_window += cells;
+
+               if (cur_index++ == index)
+                       break;
+       }
+       return 0;
+}
+
 static int tegra_smmu_suspend(struct device *dev)
 {
        struct smmu_device *smmu = dev_get_drvdata(dev);
-- 
1.7.5.4

_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to