diff options
| author | Will Deacon <will.deacon@arm.com> | 2014-08-27 11:20:32 -0400 |
|---|---|---|
| committer | Will Deacon <will.deacon@arm.com> | 2014-12-01 11:50:38 -0500 |
| commit | 7eba1d51485197fa77c43c42eae3ce04b4b1c1c0 (patch) | |
| tree | ace7a25c7d2aaf0e6250d60db0ee08faf55bf201 | |
| parent | d0f60a44f5120a8e1c48995285c7d8d1e4915b35 (diff) | |
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>
| -rw-r--r-- | drivers/iommu/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/iommu/of_iommu.c | 33 | ||||
| -rw-r--r-- | include/linux/of_iommu.h | 6 |
3 files changed, 40 insertions, 1 deletions
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dd5112265cc9..6d13f962f156 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig | |||
| @@ -15,7 +15,7 @@ if IOMMU_SUPPORT | |||
| 15 | 15 | ||
| 16 | config OF_IOMMU | 16 | config OF_IOMMU |
| 17 | def_bool y | 17 | def_bool y |
| 18 | depends on OF | 18 | depends on OF && IOMMU_API |
| 19 | 19 | ||
| 20 | config FSL_PAMU | 20 | config FSL_PAMU |
| 21 | bool "Freescale IOMMU support" | 21 | bool "Freescale IOMMU support" |
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 @@ | |||
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #include <linux/export.h> | 20 | #include <linux/export.h> |
| 21 | #include <linux/iommu.h> | ||
| 21 | #include <linux/limits.h> | 22 | #include <linux/limits.h> |
| 22 | #include <linux/of.h> | 23 | #include <linux/of.h> |
| 23 | #include <linux/of_iommu.h> | 24 | #include <linux/of_iommu.h> |
| @@ -93,6 +94,38 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index, | |||
| 93 | } | 94 | } |
| 94 | EXPORT_SYMBOL_GPL(of_get_dma_window); | 95 | EXPORT_SYMBOL_GPL(of_get_dma_window); |
| 95 | 96 | ||
| 97 | struct iommu_ops *of_iommu_configure(struct device *dev) | ||
| 98 | { | ||
| 99 | struct of_phandle_args iommu_spec; | ||
| 100 | struct device_node *np; | ||
| 101 | struct iommu_ops *ops = NULL; | ||
| 102 | int idx = 0; | ||
| 103 | |||
| 104 | /* | ||
| 105 | * We don't currently walk up the tree looking for a parent IOMMU. | ||
| 106 | * See the `Notes:' section of | ||
| 107 | * Documentation/devicetree/bindings/iommu/iommu.txt | ||
| 108 | */ | ||
| 109 | while (!of_parse_phandle_with_args(dev->of_node, "iommus", | ||
| 110 | "#iommu-cells", idx, | ||
| 111 | &iommu_spec)) { | ||
| 112 | np = iommu_spec.np; | ||
| 113 | ops = of_iommu_get_ops(np); | ||
| 114 | |||
| 115 | if (!ops || !ops->of_xlate || ops->of_xlate(dev, &iommu_spec)) | ||
| 116 | goto err_put_node; | ||
| 117 | |||
| 118 | of_node_put(np); | ||
| 119 | idx++; | ||
| 120 | } | ||
| 121 | |||
| 122 | return ops; | ||
| 123 | |||
| 124 | err_put_node: | ||
| 125 | of_node_put(np); | ||
| 126 | return NULL; | ||
| 127 | } | ||
| 128 | |||
| 96 | void __init of_iommu_init(void) | 129 | void __init of_iommu_init(void) |
| 97 | { | 130 | { |
| 98 | struct device_node *np; | 131 | struct device_node *np; |
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index 5762cdc8effe..d03abbb11c34 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #ifndef __OF_IOMMU_H | 1 | #ifndef __OF_IOMMU_H |
| 2 | #define __OF_IOMMU_H | 2 | #define __OF_IOMMU_H |
| 3 | 3 | ||
| 4 | #include <linux/device.h> | ||
| 4 | #include <linux/iommu.h> | 5 | #include <linux/iommu.h> |
| 5 | #include <linux/of.h> | 6 | #include <linux/of.h> |
| 6 | 7 | ||
| @@ -11,6 +12,7 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix, | |||
| 11 | size_t *size); | 12 | size_t *size); |
| 12 | 13 | ||
| 13 | extern void of_iommu_init(void); | 14 | extern void of_iommu_init(void); |
| 15 | extern struct iommu_ops *of_iommu_configure(struct device *dev); | ||
| 14 | 16 | ||
| 15 | #else | 17 | #else |
| 16 | 18 | ||
| @@ -22,6 +24,10 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix, | |||
| 22 | } | 24 | } |
| 23 | 25 | ||
| 24 | static inline void of_iommu_init(void) { } | 26 | static inline void of_iommu_init(void) { } |
| 27 | static inline struct iommu_ops *of_iommu_configure(struct device *dev) | ||
| 28 | { | ||
| 29 | return NULL; | ||
| 30 | } | ||
| 25 | 31 | ||
| 26 | #endif /* CONFIG_OF_IOMMU */ | 32 | #endif /* CONFIG_OF_IOMMU */ |
| 27 | 33 | ||
