Commit 7eba1d51 authored by Will Deacon's avatar Will Deacon

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: default avatarArnd Bergmann <arnd@arndb.de>
Acked-by: default avatarJoerg Roedel <jroedel@suse.de>
Acked-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Tested-by: default avatarRobin Murphy <robin.murphy@arm.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent d0f60a44
...@@ -15,7 +15,7 @@ if IOMMU_SUPPORT ...@@ -15,7 +15,7 @@ if IOMMU_SUPPORT
config OF_IOMMU config OF_IOMMU
def_bool y def_bool y
depends on OF depends on OF && IOMMU_API
config FSL_PAMU config FSL_PAMU
bool "Freescale IOMMU support" bool "Freescale IOMMU support"
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
*/ */
#include <linux/export.h> #include <linux/export.h>
#include <linux/iommu.h>
#include <linux/limits.h> #include <linux/limits.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_iommu.h> #include <linux/of_iommu.h>
...@@ -93,6 +94,38 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index, ...@@ -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); 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) void __init of_iommu_init(void)
{ {
struct device_node *np; struct device_node *np;
......
#ifndef __OF_IOMMU_H #ifndef __OF_IOMMU_H
#define __OF_IOMMU_H #define __OF_IOMMU_H
#include <linux/device.h>
#include <linux/iommu.h> #include <linux/iommu.h>
#include <linux/of.h> #include <linux/of.h>
...@@ -11,6 +12,7 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix, ...@@ -11,6 +12,7 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
size_t *size); size_t *size);
extern void of_iommu_init(void); extern void of_iommu_init(void);
extern struct iommu_ops *of_iommu_configure(struct device *dev);
#else #else
...@@ -22,6 +24,10 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix, ...@@ -22,6 +24,10 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
} }
static inline void of_iommu_init(void) { } static inline void of_iommu_init(void) { }
static inline struct iommu_ops *of_iommu_configure(struct device *dev)
{
return NULL;
}
#endif /* CONFIG_OF_IOMMU */ #endif /* CONFIG_OF_IOMMU */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment