Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ if IOMMU_SUPPORT

config OF_IOMMU
       def_bool y
       depends on OF
       depends on OF && IOMMU_API

config FSL_PAMU
	bool "Freescale IOMMU support"
+33 −0
Original line number Diff line number Diff line
@@ -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;
+6 −0
Original line number Diff line number Diff line
#ifndef __OF_IOMMU_H
#define __OF_IOMMU_H

#include <linux/device.h>
#include <linux/iommu.h>
#include <linux/of.h>

@@ -11,6 +12,7 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
			     size_t *size);

extern void of_iommu_init(void);
extern struct iommu_ops *of_iommu_configure(struct device *dev);

#else

@@ -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 struct iommu_ops *of_iommu_configure(struct device *dev)
{
	return NULL;
}

#endif	/* CONFIG_OF_IOMMU */