diff options
author | Will Deacon <will.deacon@arm.com> | 2014-08-27 16:20:32 +0100 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2014-12-01 16:50:38 +0000 |
commit | 7eba1d51485197fa77c43c42eae3ce04b4b1c1c0 (patch) | |
tree | ace7a25c7d2aaf0e6250d60db0ee08faf55bf201 /drivers/iommu/of_iommu.c | |
parent | d0f60a44f5120a8e1c48995285c7d8d1e4915b35 (diff) | |
download | lwn-7eba1d51485197fa77c43c42eae3ce04b4b1c1c0.tar.gz lwn-7eba1d51485197fa77c43c42eae3ce04b4b1c1c0.zip |
iommu: provide helper function to configure an IOMMU for an of master
The generic IOMMU device-tree bindings can be used to add arbitrary OF
masters to an IOMMU with a compliant binding.
This patch introduces of_iommu_configure, which does exactly that.
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Joerg Roedel <jroedel@suse.de>
Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/iommu/of_iommu.c')
-rw-r--r-- | drivers/iommu/of_iommu.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 89b903406968..73236d3cc955 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -18,6 +18,7 @@ */ #include <linux/export.h> +#include <linux/iommu.h> #include <linux/limits.h> #include <linux/of.h> #include <linux/of_iommu.h> @@ -93,6 +94,38 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index, } EXPORT_SYMBOL_GPL(of_get_dma_window); +struct iommu_ops *of_iommu_configure(struct device *dev) +{ + struct of_phandle_args iommu_spec; + struct device_node *np; + struct iommu_ops *ops = NULL; + int idx = 0; + + /* + * We don't currently walk up the tree looking for a parent IOMMU. + * See the `Notes:' section of + * Documentation/devicetree/bindings/iommu/iommu.txt + */ + while (!of_parse_phandle_with_args(dev->of_node, "iommus", + "#iommu-cells", idx, + &iommu_spec)) { + np = iommu_spec.np; + ops = of_iommu_get_ops(np); + + if (!ops || !ops->of_xlate || ops->of_xlate(dev, &iommu_spec)) + goto err_put_node; + + of_node_put(np); + idx++; + } + + return ops; + +err_put_node: + of_node_put(np); + return NULL; +} + void __init of_iommu_init(void) { struct device_node *np; |