All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5
@ 2017-10-16 12:29 Magnus Damm
  2017-10-16 12:29   ` Magnus Damm
                   ` (9 more replies)
  0 siblings, 10 replies; 13+ messages in thread
From: Magnus Damm @ 2017-10-16 12:29 UTC (permalink / raw)
  To: joro
  Cc: laurent.pinchart+renesas, geert+renesas, linux-kernel,
	linux-renesas-soc, iommu, horms+renesas, Magnus Damm,
	robin.murphy, m.szyprowski

iommu/ipmmu-vmsa: r8a7795 support V5

[PATCH v5 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias
[PATCH v5 02/09] iommu/ipmmu-vmsa: Add optional root device feature
[PATCH v5 03/09] iommu/ipmmu-vmsa: Enable multi context support
[PATCH v5 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()
[PATCH v5 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master
[PATCH v5 06/09] iommu/ipmmu-vmsa: Write IMCTR twice
[PATCH v5 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional
[PATCH v5 08/09] iommu/ipmmu-vmsa: Allow two bit SL0
[PATCH v5 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

This is V5 of r8a7795 IPMMU driver where the series has been rebased
and reworked to fit on next-20171013 that includes:
[PATCH v2 00/05] iommu/ipmmu-vmsa: 32-bit ARM update V2
[PATCH] iommu/ipmmu-vmsa: Use iommu_device_sysfs_add()/remove()

The major feature change is in patch 2/9 that now gets by without
using a local list of registered IPMMU devices and instead relies
on driver_for_each_device(). Thanks to Robin Murphy for his support.

The DT binding for r8a7795 has been accepted for upstream merge
and this series implements support following such format:

d4e42e7 iommu/ipmmu-vmsa: Add r8a7795 DT binding

The r8a7795 IPMMU is almost register compatible with earlier devices
like r8a7790-r8a7794, however some bitfields have been shifted
slightly. On a grander scale topology has been added and interrupts
have been reworked. So now there are several "cache" IPMMU units
without interrupt that somehow communicate with IPMMU-MM that
is the only instance that supports interrupts. The code refers to
IPMMU-MM as a "root" device and the other ones as "leaf" nodes.

Changes since V4:
 - Rebased on top of [PATCH v2 00/05] iommu/ipmmu-vmsa: 32-bit ARM update V2
 - Reworked root device handling to make use of driver_for_each_device()
 - Added deferred probing to make sure root device always is present

Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---

 Developed on top of next-20171013
 Also applies to renesas-drivers-2017-10-03-v4.14-rc3
 Tested on top of renesas-drivers on r8a7796-m3ulcb using /dev/ttySC1
  - [PATCH v4 0/3] iommu/ipmmu-vmsa: r8a7796 support V4
  - local /dev/ttySC1 enablement for testing purpose
  - local DTS changes to hook up SYS-DMAC and IPMMU DS0, DS1 and MM
  - local whitelist code to enable "e7310000.dma-controller"
 
 drivers/iommu/ipmmu-vmsa.c |  310 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 244 insertions(+), 66 deletions(-)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias
  2017-10-16 12:29 [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Magnus Damm
@ 2017-10-16 12:29   ` Magnus Damm
  2017-10-16 12:29 ` [PATCH v5 02/09] iommu/ipmmu-vmsa: Add optional root device feature Magnus Damm
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Magnus Damm @ 2017-10-16 12:29 UTC (permalink / raw)
  To: joro
  Cc: laurent.pinchart+renesas, geert+renesas, linux-kernel,
	linux-renesas-soc, iommu, horms+renesas, Magnus Damm,
	robin.murphy, m.szyprowski

From: Magnus Damm <damm+renesas@opensource.se>

Introduce struct ipmmu_features to track various hardware
and software implementation changes inside the driver for
different kinds of IPMMU hardware. Add use_ns_alias_offset
as a first example of a feature to control if the secure
register bank offset should be used or not.

Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---

 Changes since V4:
 - None

 Changes since V3:
 - Use of_device_get_match_data(), thanks Robin!

 Changes since V2:
 - None

 Changes since V1:
 - Moved patch to front of the series


 drivers/iommu/ipmmu-vmsa.c |   31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2017-10-12 15:16:43.510607110 +0900
@@ -19,6 +19,7 @@
 #include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/sizes.h>
@@ -33,11 +34,15 @@
 
 #define IPMMU_CTX_MAX 1
 
+struct ipmmu_features {
+	bool use_ns_alias_offset;
+};
+
 struct ipmmu_vmsa_device {
 	struct device *dev;
 	void __iomem *base;
 	struct iommu_device iommu;
-
+	const struct ipmmu_features *features;
 	unsigned int num_utlbs;
 	spinlock_t lock;			/* Protects ctx and domains[] */
 	DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
@@ -910,6 +915,21 @@ static void ipmmu_device_reset(struct ip
 		ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
+static const struct ipmmu_features ipmmu_features_default = {
+	.use_ns_alias_offset = true,
+};
+
+static const struct of_device_id ipmmu_of_ids[] = {
+	{
+		.compatible = "renesas,ipmmu-vmsa",
+		.data = &ipmmu_features_default,
+	}, {
+		/* Terminator */
+	},
+};
+
+MODULE_DEVICE_TABLE(of, ipmmu_of_ids);
+
 static int ipmmu_probe(struct platform_device *pdev)
 {
 	struct ipmmu_vmsa_device *mmu;
@@ -927,6 +947,7 @@ static int ipmmu_probe(struct platform_d
 	mmu->num_utlbs = 32;
 	spin_lock_init(&mmu->lock);
 	bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
+	mmu->features = of_device_get_match_data(&pdev->dev);
 
 	/* Map I/O memory and request IRQ. */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -946,7 +967,8 @@ static int ipmmu_probe(struct platform_d
 	 * Offset the registers base unconditionally to point to the non-secure
 	 * alias space for now.
 	 */
-	mmu->base += IM_NS_ALIAS_OFFSET;
+	if (mmu->features->use_ns_alias_offset)
+		mmu->base += IM_NS_ALIAS_OFFSET;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
@@ -1002,11 +1024,6 @@ static int ipmmu_remove(struct platform_
 	return 0;
 }
 
-static const struct of_device_id ipmmu_of_ids[] = {
-	{ .compatible = "renesas,ipmmu-vmsa", },
-	{ }
-};
-
 static struct platform_driver ipmmu_driver = {
 	.driver = {
 		.name = "ipmmu-vmsa",

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias
@ 2017-10-16 12:29   ` Magnus Damm
  0 siblings, 0 replies; 13+ messages in thread
From: Magnus Damm @ 2017-10-16 12:29 UTC (permalink / raw)
  To: joro-zLv9SwRftAIdnm+yROfE0A
  Cc: laurent.pinchart+renesas-ryLnwIuWjnjg/C1BVhZhaw,
	geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ, Magnus Damm,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	horms+renesas-/R6kz+dDXgpPR4JQBCEnsQ

From: Magnus Damm <damm+renesas-yzvPICuk2ACczHhG9Qg4qA@public.gmane.org>

Introduce struct ipmmu_features to track various hardware
and software implementation changes inside the driver for
different kinds of IPMMU hardware. Add use_ns_alias_offset
as a first example of a feature to control if the secure
register bank offset should be used or not.

Signed-off-by: Magnus Damm <damm+renesas-yzvPICuk2ACczHhG9Qg4qA@public.gmane.org>
---

 Changes since V4:
 - None

 Changes since V3:
 - Use of_device_get_match_data(), thanks Robin!

 Changes since V2:
 - None

 Changes since V1:
 - Moved patch to front of the series


 drivers/iommu/ipmmu-vmsa.c |   31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2017-10-12 15:16:43.510607110 +0900
@@ -19,6 +19,7 @@
 #include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/sizes.h>
@@ -33,11 +34,15 @@
 
 #define IPMMU_CTX_MAX 1
 
+struct ipmmu_features {
+	bool use_ns_alias_offset;
+};
+
 struct ipmmu_vmsa_device {
 	struct device *dev;
 	void __iomem *base;
 	struct iommu_device iommu;
-
+	const struct ipmmu_features *features;
 	unsigned int num_utlbs;
 	spinlock_t lock;			/* Protects ctx and domains[] */
 	DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
@@ -910,6 +915,21 @@ static void ipmmu_device_reset(struct ip
 		ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
+static const struct ipmmu_features ipmmu_features_default = {
+	.use_ns_alias_offset = true,
+};
+
+static const struct of_device_id ipmmu_of_ids[] = {
+	{
+		.compatible = "renesas,ipmmu-vmsa",
+		.data = &ipmmu_features_default,
+	}, {
+		/* Terminator */
+	},
+};
+
+MODULE_DEVICE_TABLE(of, ipmmu_of_ids);
+
 static int ipmmu_probe(struct platform_device *pdev)
 {
 	struct ipmmu_vmsa_device *mmu;
@@ -927,6 +947,7 @@ static int ipmmu_probe(struct platform_d
 	mmu->num_utlbs = 32;
 	spin_lock_init(&mmu->lock);
 	bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
+	mmu->features = of_device_get_match_data(&pdev->dev);
 
 	/* Map I/O memory and request IRQ. */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -946,7 +967,8 @@ static int ipmmu_probe(struct platform_d
 	 * Offset the registers base unconditionally to point to the non-secure
 	 * alias space for now.
 	 */
-	mmu->base += IM_NS_ALIAS_OFFSET;
+	if (mmu->features->use_ns_alias_offset)
+		mmu->base += IM_NS_ALIAS_OFFSET;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
@@ -1002,11 +1024,6 @@ static int ipmmu_remove(struct platform_
 	return 0;
 }
 
-static const struct of_device_id ipmmu_of_ids[] = {
-	{ .compatible = "renesas,ipmmu-vmsa", },
-	{ }
-};
-
 static struct platform_driver ipmmu_driver = {
 	.driver = {
 		.name = "ipmmu-vmsa",

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 02/09] iommu/ipmmu-vmsa: Add optional root device feature
  2017-10-16 12:29 [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Magnus Damm
  2017-10-16 12:29   ` Magnus Damm
@ 2017-10-16 12:29 ` Magnus Damm
  2017-10-16 12:29 ` [PATCH v5 03/09] iommu/ipmmu-vmsa: Enable multi context support Magnus Damm
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Magnus Damm @ 2017-10-16 12:29 UTC (permalink / raw)
  To: joro
  Cc: laurent.pinchart+renesas, geert+renesas, linux-kernel,
	linux-renesas-soc, iommu, horms+renesas, Magnus Damm,
	robin.murphy, m.szyprowski

From: Magnus Damm <damm+renesas@opensource.se>

Add root device handling to the IPMMU driver by allowing certain
DT compat strings to enable has_cache_leaf_nodes that in turn will
support both root devices with interrupts and leaf devices that
face the actual IPMMU consumer devices.

Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---

 Changes since V4: (Many thanks to Robin for feedback)
 - Put the root pointer under struct ipmmu_vmsa_device
 - Drop is_leaf flag
 - Use driver_for_each_device instead of local list of devices
 - Return -EPROBE_DEFER to hook up root device first

 Changes since V3:
 - Reworked root finding code to make it easier to follow, thanks Geert!
 
 Changes since V2:
 - Fixed a bug in ipmmu_find_root() when only leaf devices are present
 - Broke out __ipmmu_find_root() to allow ->xlate() check for root devices

 Changes since V1:
 - Moved patch to earlier in the series
 - Updated code to work with recent changes in:
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3

 drivers/iommu/ipmmu-vmsa.c |   90 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 73 insertions(+), 17 deletions(-)

--- 0009/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2017-10-16 19:43:27.020607110 +0900
@@ -36,12 +36,14 @@
 
 struct ipmmu_features {
 	bool use_ns_alias_offset;
+	bool has_cache_leaf_nodes;
 };
 
 struct ipmmu_vmsa_device {
 	struct device *dev;
 	void __iomem *base;
 	struct iommu_device iommu;
+	struct ipmmu_vmsa_device *root;
 	const struct ipmmu_features *features;
 	unsigned int num_utlbs;
 	spinlock_t lock;			/* Protects ctx and domains[] */
@@ -199,6 +201,36 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMUASID_ASID0_SHIFT		0
 
 /* -----------------------------------------------------------------------------
+ * Root device handling
+ */
+
+static struct platform_driver ipmmu_driver;
+
+static bool ipmmu_is_root(struct ipmmu_vmsa_device *mmu)
+{
+	return mmu->root == mmu;
+}
+
+static int __ipmmu_check_device(struct device *dev, void *data)
+{
+	struct ipmmu_vmsa_device *mmu = dev_get_drvdata(dev);
+	struct ipmmu_vmsa_device **rootp = data;
+
+	if (ipmmu_is_root(mmu))
+		*rootp = mmu;
+
+	return 0;
+}
+
+static struct ipmmu_vmsa_device *ipmmu_find_root(void)
+{
+	struct ipmmu_vmsa_device *root = NULL;
+
+	return driver_for_each_device(&ipmmu_driver.driver, NULL, &root,
+				      __ipmmu_check_device) == 0 ? root : NULL;
+}
+
+/* -----------------------------------------------------------------------------
  * Read/Write Access
  */
 
@@ -215,13 +247,15 @@ static void ipmmu_write(struct ipmmu_vms
 
 static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
 {
-	return ipmmu_read(domain->mmu, domain->context_id * IM_CTX_SIZE + reg);
+	return ipmmu_read(domain->mmu->root,
+			  domain->context_id * IM_CTX_SIZE + reg);
 }
 
 static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
 			    u32 data)
 {
-	ipmmu_write(domain->mmu, domain->context_id * IM_CTX_SIZE + reg, data);
+	ipmmu_write(domain->mmu->root,
+		    domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
 /* -----------------------------------------------------------------------------
@@ -369,12 +403,12 @@ static int ipmmu_domain_init_context(str
 	 * TODO: Add support for coherent walk through CCI with DVM and remove
 	 * cache handling. For now, delegate it to the io-pgtable code.
 	 */
-	domain->cfg.iommu_dev = domain->mmu->dev;
+	domain->cfg.iommu_dev = domain->mmu->root->dev;
 
 	/*
 	 * Find an unused context.
 	 */
-	ret = ipmmu_domain_allocate_context(domain->mmu, domain);
+	ret = ipmmu_domain_allocate_context(domain->mmu->root, domain);
 	if (ret == IPMMU_CTX_MAX)
 		return -EBUSY;
 
@@ -383,7 +417,8 @@ static int ipmmu_domain_init_context(str
 	domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &domain->cfg,
 					   domain);
 	if (!domain->iop) {
-		ipmmu_domain_free_context(domain->mmu, domain->context_id);
+		ipmmu_domain_free_context(domain->mmu->root,
+					  domain->context_id);
 		return -EINVAL;
 	}
 
@@ -437,7 +472,7 @@ static void ipmmu_domain_destroy_context
 	 */
 	ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
 	ipmmu_tlb_sync(domain);
-	ipmmu_domain_free_context(domain->mmu, domain->context_id);
+	ipmmu_domain_free_context(domain->mmu->root, domain->context_id);
 }
 
 /* -----------------------------------------------------------------------------
@@ -917,6 +952,7 @@ static void ipmmu_device_reset(struct ip
 
 static const struct ipmmu_features ipmmu_features_default = {
 	.use_ns_alias_offset = true,
+	.has_cache_leaf_nodes = false,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
@@ -971,19 +1007,39 @@ static int ipmmu_probe(struct platform_d
 		mmu->base += IM_NS_ALIAS_OFFSET;
 
 	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "no IRQ found\n");
-		return irq;
-	}
 
-	ret = devm_request_irq(&pdev->dev, irq, ipmmu_irq, 0,
-			       dev_name(&pdev->dev), mmu);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to request IRQ %d\n", irq);
-		return ret;
-	}
+	/*
+	 * Determine if this IPMMU instance is a root device by checking for
+	 * the lack of has_cache_leaf_nodes flag or renesas,ipmmu-main property.
+	 */
+	if (!mmu->features->has_cache_leaf_nodes ||
+	    !of_find_property(pdev->dev.of_node, "renesas,ipmmu-main", NULL))
+		mmu->root = mmu;
+	else
+		mmu->root = ipmmu_find_root();
+
+	/*
+	 * Wait until the root device has been registered for sure.
+	 */
+	if (!mmu->root)
+		return -EPROBE_DEFER;
+
+	/* Root devices have mandatory IRQs */
+	if (ipmmu_is_root(mmu)) {
+		if (irq < 0) {
+			dev_err(&pdev->dev, "no IRQ found\n");
+			return irq;
+		}
 
-	ipmmu_device_reset(mmu);
+		ret = devm_request_irq(&pdev->dev, irq, ipmmu_irq, 0,
+				       dev_name(&pdev->dev), mmu);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "failed to request IRQ %d\n", irq);
+			return ret;
+		}
+
+		ipmmu_device_reset(mmu);
+	}
 
 	ret = iommu_device_sysfs_add(&mmu->iommu, &pdev->dev, NULL,
 				     dev_name(&pdev->dev));

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 03/09] iommu/ipmmu-vmsa: Enable multi context support
  2017-10-16 12:29 [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Magnus Damm
  2017-10-16 12:29   ` Magnus Damm
  2017-10-16 12:29 ` [PATCH v5 02/09] iommu/ipmmu-vmsa: Add optional root device feature Magnus Damm
@ 2017-10-16 12:29 ` Magnus Damm
  2017-10-16 12:29   ` Magnus Damm
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Magnus Damm @ 2017-10-16 12:29 UTC (permalink / raw)
  To: joro
  Cc: laurent.pinchart+renesas, geert+renesas, linux-kernel,
	linux-renesas-soc, iommu, horms+renesas, Magnus Damm,
	robin.murphy, m.szyprowski

From: Magnus Damm <damm+renesas@opensource.se>

Add support for up to 8 contexts. Each context is mapped to one
domain. One domain is assigned one or more slave devices. Contexts
are allocated dynamically and slave devices are grouped together
based on which IPMMU device they are connected to. This makes slave
devices tied to the same IPMMU device share the same IOVA space.

Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---

 Changes since V4:
 - None

 Changes since V3:
 - Use number_of_contexts unsigned int, drop WARN_ON() - Thanks Robin!

 Changes since V2:
 - Updated patch description to reflect code included in:
   [PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7

 Changes since V1:
 - Support up to 8 contexts instead of 4
 - Use feature flag and runtime handling
 - Default to single context

 drivers/iommu/ipmmu-vmsa.c |   30 ++++++++++++++++++++++--------
 1 file changed, 22 insertions(+), 8 deletions(-)

--- 0011/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2017-10-16 19:46:09.900607110 +0900
@@ -32,11 +32,12 @@
 
 #include "io-pgtable.h"
 
-#define IPMMU_CTX_MAX 1
+#define IPMMU_CTX_MAX 8
 
 struct ipmmu_features {
 	bool use_ns_alias_offset;
 	bool has_cache_leaf_nodes;
+	unsigned int number_of_contexts;
 };
 
 struct ipmmu_vmsa_device {
@@ -46,6 +47,7 @@ struct ipmmu_vmsa_device {
 	struct ipmmu_vmsa_device *root;
 	const struct ipmmu_features *features;
 	unsigned int num_utlbs;
+	unsigned int num_ctx;
 	spinlock_t lock;			/* Protects ctx and domains[] */
 	DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
 	struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
@@ -352,11 +354,12 @@ static int ipmmu_domain_allocate_context
 
 	spin_lock_irqsave(&mmu->lock, flags);
 
-	ret = find_first_zero_bit(mmu->ctx, IPMMU_CTX_MAX);
-	if (ret != IPMMU_CTX_MAX) {
+	ret = find_first_zero_bit(mmu->ctx, mmu->num_ctx);
+	if (ret != mmu->num_ctx) {
 		mmu->domains[ret] = domain;
 		set_bit(ret, mmu->ctx);
-	}
+	} else
+		ret = -EBUSY;
 
 	spin_unlock_irqrestore(&mmu->lock, flags);
 
@@ -409,8 +412,8 @@ static int ipmmu_domain_init_context(str
 	 * Find an unused context.
 	 */
 	ret = ipmmu_domain_allocate_context(domain->mmu->root, domain);
-	if (ret == IPMMU_CTX_MAX)
-		return -EBUSY;
+	if (ret < 0)
+		return ret;
 
 	domain->context_id = ret;
 
@@ -539,7 +542,7 @@ static irqreturn_t ipmmu_irq(int irq, vo
 	/*
 	 * Check interrupts for all active contexts.
 	 */
-	for (i = 0; i < IPMMU_CTX_MAX; i++) {
+	for (i = 0; i < mmu->num_ctx; i++) {
 		if (!mmu->domains[i])
 			continue;
 		if (ipmmu_domain_irq(mmu->domains[i]) == IRQ_HANDLED)
@@ -603,6 +606,13 @@ static int ipmmu_attach_device(struct io
 		/* The domain hasn't been used yet, initialize it. */
 		domain->mmu = mmu;
 		ret = ipmmu_domain_init_context(domain);
+		if (ret < 0) {
+			dev_err(dev, "Unable to initialize IPMMU context\n");
+			domain->mmu = NULL;
+		} else {
+			dev_info(dev, "Using IPMMU context %u\n",
+				 domain->context_id);
+		}
 	} else if (domain->mmu != mmu) {
 		/*
 		 * Something is wrong, we can't attach two devices using
@@ -946,13 +956,14 @@ static void ipmmu_device_reset(struct ip
 	unsigned int i;
 
 	/* Disable all contexts. */
-	for (i = 0; i < 4; ++i)
+	for (i = 0; i < mmu->num_ctx; ++i)
 		ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
 static const struct ipmmu_features ipmmu_features_default = {
 	.use_ns_alias_offset = true,
 	.has_cache_leaf_nodes = false,
+	.number_of_contexts = 1, /* software only tested with one context */
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
@@ -1006,6 +1017,9 @@ static int ipmmu_probe(struct platform_d
 	if (mmu->features->use_ns_alias_offset)
 		mmu->base += IM_NS_ALIAS_OFFSET;
 
+	mmu->num_ctx = min_t(unsigned int, IPMMU_CTX_MAX,
+			     mmu->features->number_of_contexts);
+
 	irq = platform_get_irq(pdev, 0);
 
 	/*

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()
  2017-10-16 12:29 [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Magnus Damm
@ 2017-10-16 12:29   ` Magnus Damm
  2017-10-16 12:29 ` [PATCH v5 02/09] iommu/ipmmu-vmsa: Add optional root device feature Magnus Damm
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Magnus Damm @ 2017-10-16 12:29 UTC (permalink / raw)
  To: joro
  Cc: laurent.pinchart+renesas, geert+renesas, linux-kernel,
	linux-renesas-soc, iommu, horms+renesas, Magnus Damm,
	robin.murphy, m.szyprowski

From: Magnus Damm <damm+renesas@opensource.se>

Hook up IOMMU_OF_DECLARE() support in case CONFIG_IOMMU_DMA
is enabled. The only current supported case for 32-bit ARM
is disabled, however for 64-bit ARM usage of OF is required.

Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---

 Changes since V4:
 - Use ipmmu_is_root() instead of now removed is_leaf flag

 Changes since V3:
 - Reworked to fit on top of
   [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update

 Changes since V2:
 - Reworked registration code to make use of recently introduced:
     iommu_device_register()
     iommu_device_set_ops()
     iommu_device_set_fwnode()

 Changes since V1:
 - Reworked slightly to fit updated patch order and
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3


 drivers/iommu/ipmmu-vmsa.c |   50 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 41 insertions(+), 9 deletions(-)

--- 0014/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2017-10-16 19:59:42.700607110 +0900
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_iommu.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/sizes.h>
@@ -1055,17 +1056,30 @@ static int ipmmu_probe(struct platform_d
 		ipmmu_device_reset(mmu);
 	}
 
-	ret = iommu_device_sysfs_add(&mmu->iommu, &pdev->dev, NULL,
-				     dev_name(&pdev->dev));
-	if (ret)
-		return ret;
+	/*
+	 * Register the IPMMU to the IOMMU subsystem in the following cases:
+	 * - R-Car Gen2 IPMMU (all devices registered)
+	 * - R-Car Gen3 IPMMU (leaf devices only - skip root IPMMU-MM device)
+	 */
+	if (!mmu->features->has_cache_leaf_nodes || !ipmmu_is_root(mmu)) {
+		ret = iommu_device_sysfs_add(&mmu->iommu, &pdev->dev, NULL,
+					     dev_name(&pdev->dev));
+		if (ret)
+			return ret;
 
-	iommu_device_set_ops(&mmu->iommu, &ipmmu_ops);
-	iommu_device_set_fwnode(&mmu->iommu, &pdev->dev.of_node->fwnode);
+		iommu_device_set_ops(&mmu->iommu, &ipmmu_ops);
+		iommu_device_set_fwnode(&mmu->iommu,
+					&pdev->dev.of_node->fwnode);
 
-	ret = iommu_device_register(&mmu->iommu);
-	if (ret)
-		return ret;
+		ret = iommu_device_register(&mmu->iommu);
+		if (ret)
+			return ret;
+
+#if defined(CONFIG_IOMMU_DMA)
+		if (!iommu_present(&platform_bus_type))
+			bus_set_iommu(&platform_bus_type, &ipmmu_ops);
+#endif
+	}
 
 	/*
 	 * We can't create the ARM mapping here as it requires the bus to have
@@ -1105,15 +1119,22 @@ static struct platform_driver ipmmu_driv
 
 static int __init ipmmu_init(void)
 {
+	static bool setup_done;
 	int ret;
 
+	if (setup_done)
+		return 0;
+
 	ret = platform_driver_register(&ipmmu_driver);
 	if (ret < 0)
 		return ret;
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 	if (!iommu_present(&platform_bus_type))
 		bus_set_iommu(&platform_bus_type, &ipmmu_ops);
+#endif
 
+	setup_done = true;
 	return 0;
 }
 
@@ -1125,6 +1146,17 @@ static void __exit ipmmu_exit(void)
 subsys_initcall(ipmmu_init);
 module_exit(ipmmu_exit);
 
+#ifdef CONFIG_IOMMU_DMA
+static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np)
+{
+	ipmmu_init();
+	return 0;
+}
+
+IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
+		 ipmmu_vmsa_iommu_of_setup);
+#endif
+
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
 MODULE_LICENSE("GPL v2");

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()
@ 2017-10-16 12:29   ` Magnus Damm
  0 siblings, 0 replies; 13+ messages in thread
From: Magnus Damm @ 2017-10-16 12:29 UTC (permalink / raw)
  To: joro-zLv9SwRftAIdnm+yROfE0A
  Cc: laurent.pinchart+renesas-ryLnwIuWjnjg/C1BVhZhaw,
	geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ, Magnus Damm,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	horms+renesas-/R6kz+dDXgpPR4JQBCEnsQ

From: Magnus Damm <damm+renesas-yzvPICuk2ACczHhG9Qg4qA@public.gmane.org>

Hook up IOMMU_OF_DECLARE() support in case CONFIG_IOMMU_DMA
is enabled. The only current supported case for 32-bit ARM
is disabled, however for 64-bit ARM usage of OF is required.

Signed-off-by: Magnus Damm <damm+renesas-yzvPICuk2ACczHhG9Qg4qA@public.gmane.org>
---

 Changes since V4:
 - Use ipmmu_is_root() instead of now removed is_leaf flag

 Changes since V3:
 - Reworked to fit on top of
   [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update

 Changes since V2:
 - Reworked registration code to make use of recently introduced:
     iommu_device_register()
     iommu_device_set_ops()
     iommu_device_set_fwnode()

 Changes since V1:
 - Reworked slightly to fit updated patch order and
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3


 drivers/iommu/ipmmu-vmsa.c |   50 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 41 insertions(+), 9 deletions(-)

--- 0014/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2017-10-16 19:59:42.700607110 +0900
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_iommu.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/sizes.h>
@@ -1055,17 +1056,30 @@ static int ipmmu_probe(struct platform_d
 		ipmmu_device_reset(mmu);
 	}
 
-	ret = iommu_device_sysfs_add(&mmu->iommu, &pdev->dev, NULL,
-				     dev_name(&pdev->dev));
-	if (ret)
-		return ret;
+	/*
+	 * Register the IPMMU to the IOMMU subsystem in the following cases:
+	 * - R-Car Gen2 IPMMU (all devices registered)
+	 * - R-Car Gen3 IPMMU (leaf devices only - skip root IPMMU-MM device)
+	 */
+	if (!mmu->features->has_cache_leaf_nodes || !ipmmu_is_root(mmu)) {
+		ret = iommu_device_sysfs_add(&mmu->iommu, &pdev->dev, NULL,
+					     dev_name(&pdev->dev));
+		if (ret)
+			return ret;
 
-	iommu_device_set_ops(&mmu->iommu, &ipmmu_ops);
-	iommu_device_set_fwnode(&mmu->iommu, &pdev->dev.of_node->fwnode);
+		iommu_device_set_ops(&mmu->iommu, &ipmmu_ops);
+		iommu_device_set_fwnode(&mmu->iommu,
+					&pdev->dev.of_node->fwnode);
 
-	ret = iommu_device_register(&mmu->iommu);
-	if (ret)
-		return ret;
+		ret = iommu_device_register(&mmu->iommu);
+		if (ret)
+			return ret;
+
+#if defined(CONFIG_IOMMU_DMA)
+		if (!iommu_present(&platform_bus_type))
+			bus_set_iommu(&platform_bus_type, &ipmmu_ops);
+#endif
+	}
 
 	/*
 	 * We can't create the ARM mapping here as it requires the bus to have
@@ -1105,15 +1119,22 @@ static struct platform_driver ipmmu_driv
 
 static int __init ipmmu_init(void)
 {
+	static bool setup_done;
 	int ret;
 
+	if (setup_done)
+		return 0;
+
 	ret = platform_driver_register(&ipmmu_driver);
 	if (ret < 0)
 		return ret;
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 	if (!iommu_present(&platform_bus_type))
 		bus_set_iommu(&platform_bus_type, &ipmmu_ops);
+#endif
 
+	setup_done = true;
 	return 0;
 }
 
@@ -1125,6 +1146,17 @@ static void __exit ipmmu_exit(void)
 subsys_initcall(ipmmu_init);
 module_exit(ipmmu_exit);
 
+#ifdef CONFIG_IOMMU_DMA
+static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np)
+{
+	ipmmu_init();
+	return 0;
+}
+
+IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
+		 ipmmu_vmsa_iommu_of_setup);
+#endif
+
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>");
 MODULE_LICENSE("GPL v2");

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master
  2017-10-16 12:29 [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Magnus Damm
                   ` (3 preceding siblings ...)
  2017-10-16 12:29   ` Magnus Damm
@ 2017-10-16 12:30 ` Magnus Damm
  2017-10-16 12:30 ` [PATCH v5 06/09] iommu/ipmmu-vmsa: Write IMCTR twice Magnus Damm
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Magnus Damm @ 2017-10-16 12:30 UTC (permalink / raw)
  To: joro
  Cc: laurent.pinchart+renesas, geert+renesas, linux-kernel,
	linux-renesas-soc, iommu, horms+renesas, Magnus Damm,
	robin.murphy, m.szyprowski

From: Magnus Damm <damm+renesas@opensource.se>

The r8a7795 IPMMU supports 40-bit bus mastering. Both
the coherent DMA mask and the streaming DMA mask are
set to unlock the 40-bit address space for coherent
allocations and streaming operations.

Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---

 Changes since V4:
 - None

 Changes since V3:
 - None

 Changes since V2:
 - Updated the code and commit message to use 40 bits instead of 64 bits

 Changes since V1:
 - Updated the commit message

 drivers/iommu/ipmmu-vmsa.c |    1 +
 1 file changed, 1 insertion(+)

--- 0012/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2017-10-16 20:37:31.480607110 +0900
@@ -996,6 +996,7 @@ static int ipmmu_probe(struct platform_d
 	spin_lock_init(&mmu->lock);
 	bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
 	mmu->features = of_device_get_match_data(&pdev->dev);
+	dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
 
 	/* Map I/O memory and request IRQ. */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 06/09] iommu/ipmmu-vmsa: Write IMCTR twice
  2017-10-16 12:29 [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Magnus Damm
                   ` (4 preceding siblings ...)
  2017-10-16 12:30 ` [PATCH v5 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master Magnus Damm
@ 2017-10-16 12:30 ` Magnus Damm
  2017-10-16 12:30 ` [PATCH v5 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional Magnus Damm
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Magnus Damm @ 2017-10-16 12:30 UTC (permalink / raw)
  To: joro
  Cc: laurent.pinchart+renesas, geert+renesas, linux-kernel,
	linux-renesas-soc, iommu, horms+renesas, Magnus Damm,
	robin.murphy, m.szyprowski

From: Magnus Damm <damm+renesas@opensource.se>

Write IMCTR both in the root device and the leaf node.

To allow access of IMCTR introduce the following function:
 - ipmmu_ctx_write_all()

While at it also rename context functions:
 - ipmmu_ctx_read() -> ipmmu_ctx_read_root()
 - ipmmu_ctx_write() -> ipmmu_ctx_write_root()

Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---

 Changes since V4:
 - Updated to make use of new root pointer location

 Changes since V3:
 - Changed function names to improve code readability - Thanks Robin!

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   56 +++++++++++++++++++++++++++-----------------
 1 file changed, 35 insertions(+), 21 deletions(-)

--- 0015/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2017-10-16 19:50:19.240607110 +0900
@@ -248,19 +248,31 @@ static void ipmmu_write(struct ipmmu_vms
 	iowrite32(data, mmu->base + offset);
 }
 
-static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
+static u32 ipmmu_ctx_read_root(struct ipmmu_vmsa_domain *domain,
+			       unsigned int reg)
 {
 	return ipmmu_read(domain->mmu->root,
 			  domain->context_id * IM_CTX_SIZE + reg);
 }
 
-static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
-			    u32 data)
+static void ipmmu_ctx_write_root(struct ipmmu_vmsa_domain *domain,
+				 unsigned int reg, u32 data)
 {
 	ipmmu_write(domain->mmu->root,
 		    domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
+static void ipmmu_ctx_write_all(struct ipmmu_vmsa_domain *domain,
+				unsigned int reg, u32 data)
+{
+	if (domain->mmu != domain->mmu->root)
+		ipmmu_write(domain->mmu,
+			    domain->context_id * IM_CTX_SIZE + reg, data);
+
+	ipmmu_write(domain->mmu->root,
+		    domain->context_id * IM_CTX_SIZE + reg, data);
+}
+
 /* -----------------------------------------------------------------------------
  * TLB and microTLB Management
  */
@@ -270,7 +282,7 @@ static void ipmmu_tlb_sync(struct ipmmu_
 {
 	unsigned int count = 0;
 
-	while (ipmmu_ctx_read(domain, IMCTR) & IMCTR_FLUSH) {
+	while (ipmmu_ctx_read_root(domain, IMCTR) & IMCTR_FLUSH) {
 		cpu_relax();
 		if (++count == TLB_LOOP_TIMEOUT) {
 			dev_err_ratelimited(domain->mmu->dev,
@@ -285,9 +297,9 @@ static void ipmmu_tlb_invalidate(struct
 {
 	u32 reg;
 
-	reg = ipmmu_ctx_read(domain, IMCTR);
+	reg = ipmmu_ctx_read_root(domain, IMCTR);
 	reg |= IMCTR_FLUSH;
-	ipmmu_ctx_write(domain, IMCTR, reg);
+	ipmmu_ctx_write_all(domain, IMCTR, reg);
 
 	ipmmu_tlb_sync(domain);
 }
@@ -428,31 +440,32 @@ static int ipmmu_domain_init_context(str
 
 	/* TTBR0 */
 	ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0];
-	ipmmu_ctx_write(domain, IMTTLBR0, ttbr);
-	ipmmu_ctx_write(domain, IMTTUBR0, ttbr >> 32);
+	ipmmu_ctx_write_root(domain, IMTTLBR0, ttbr);
+	ipmmu_ctx_write_root(domain, IMTTUBR0, ttbr >> 32);
 
 	/*
 	 * TTBCR
 	 * We use long descriptors with inner-shareable WBWA tables and allocate
 	 * the whole 32-bit VA space to TTBR0.
 	 */
-	ipmmu_ctx_write(domain, IMTTBCR, IMTTBCR_EAE |
-			IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
-			IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
+	ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE |
+			     IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
+			     IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
 
 	/* MAIR0 */
-	ipmmu_ctx_write(domain, IMMAIR0, domain->cfg.arm_lpae_s1_cfg.mair[0]);
+	ipmmu_ctx_write_root(domain, IMMAIR0,
+			     domain->cfg.arm_lpae_s1_cfg.mair[0]);
 
 	/* IMBUSCR */
-	ipmmu_ctx_write(domain, IMBUSCR,
-			ipmmu_ctx_read(domain, IMBUSCR) &
-			~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
+	ipmmu_ctx_write_root(domain, IMBUSCR,
+			     ipmmu_ctx_read_root(domain, IMBUSCR) &
+			     ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
 
 	/*
 	 * IMSTR
 	 * Clear all interrupt flags.
 	 */
-	ipmmu_ctx_write(domain, IMSTR, ipmmu_ctx_read(domain, IMSTR));
+	ipmmu_ctx_write_root(domain, IMSTR, ipmmu_ctx_read_root(domain, IMSTR));
 
 	/*
 	 * IMCTR
@@ -461,7 +474,8 @@ static int ipmmu_domain_init_context(str
 	 * software management as we have no use for it. Flush the TLB as
 	 * required when modifying the context registers.
 	 */
-	ipmmu_ctx_write(domain, IMCTR, IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
+	ipmmu_ctx_write_all(domain, IMCTR,
+			    IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
 
 	return 0;
 }
@@ -474,7 +488,7 @@ static void ipmmu_domain_destroy_context
 	 *
 	 * TODO: Is TLB flush really needed ?
 	 */
-	ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
+	ipmmu_ctx_write_all(domain, IMCTR, IMCTR_FLUSH);
 	ipmmu_tlb_sync(domain);
 	ipmmu_domain_free_context(domain->mmu->root, domain->context_id);
 }
@@ -490,11 +504,11 @@ static irqreturn_t ipmmu_domain_irq(stru
 	u32 status;
 	u32 iova;
 
-	status = ipmmu_ctx_read(domain, IMSTR);
+	status = ipmmu_ctx_read_root(domain, IMSTR);
 	if (!(status & err_mask))
 		return IRQ_NONE;
 
-	iova = ipmmu_ctx_read(domain, IMEAR);
+	iova = ipmmu_ctx_read_root(domain, IMEAR);
 
 	/*
 	 * Clear the error status flags. Unlike traditional interrupt flag
@@ -502,7 +516,7 @@ static irqreturn_t ipmmu_domain_irq(stru
 	 * seems to require 0. The error address register must be read before,
 	 * otherwise its value will be 0.
 	 */
-	ipmmu_ctx_write(domain, IMSTR, 0);
+	ipmmu_ctx_write_root(domain, IMSTR, 0);
 
 	/* Log fatal errors. */
 	if (status & IMSTR_MHIT)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional
  2017-10-16 12:29 [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Magnus Damm
                   ` (5 preceding siblings ...)
  2017-10-16 12:30 ` [PATCH v5 06/09] iommu/ipmmu-vmsa: Write IMCTR twice Magnus Damm
@ 2017-10-16 12:30 ` Magnus Damm
  2017-10-16 12:30 ` [PATCH v5 08/09] iommu/ipmmu-vmsa: Allow two bit SL0 Magnus Damm
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Magnus Damm @ 2017-10-16 12:30 UTC (permalink / raw)
  To: joro
  Cc: laurent.pinchart+renesas, geert+renesas, linux-kernel,
	linux-renesas-soc, iommu, horms+renesas, Magnus Damm,
	robin.murphy, m.szyprowski

From: Magnus Damm <damm+renesas@opensource.se>

Introduce a feature to allow opt-out of setting up
IMBUSCR. The default case is unchanged.

Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---

 Changes since V4:
 - Use leaf node mmu instead of root

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - Updated the commit message
 - Reworked patch to coexist with the multi context feature


 drivers/iommu/ipmmu-vmsa.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

--- 0018/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2017-10-16 20:20:30.860607110 +0900
@@ -39,6 +39,7 @@ struct ipmmu_features {
 	bool use_ns_alias_offset;
 	bool has_cache_leaf_nodes;
 	unsigned int number_of_contexts;
+	bool setup_imbuscr;
 };
 
 struct ipmmu_vmsa_device {
@@ -457,9 +458,10 @@ static int ipmmu_domain_init_context(str
 			     domain->cfg.arm_lpae_s1_cfg.mair[0]);
 
 	/* IMBUSCR */
-	ipmmu_ctx_write_root(domain, IMBUSCR,
-			     ipmmu_ctx_read_root(domain, IMBUSCR) &
-			     ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
+	if (domain->mmu->features->setup_imbuscr)
+		ipmmu_ctx_write_root(domain, IMBUSCR,
+				     ipmmu_ctx_read_root(domain, IMBUSCR) &
+				     ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
 
 	/*
 	 * IMSTR
@@ -979,6 +981,7 @@ static const struct ipmmu_features ipmmu
 	.use_ns_alias_offset = true,
 	.has_cache_leaf_nodes = false,
 	.number_of_contexts = 1, /* software only tested with one context */
+	.setup_imbuscr = true,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 08/09] iommu/ipmmu-vmsa: Allow two bit SL0
  2017-10-16 12:29 [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Magnus Damm
                   ` (6 preceding siblings ...)
  2017-10-16 12:30 ` [PATCH v5 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional Magnus Damm
@ 2017-10-16 12:30 ` Magnus Damm
  2017-10-16 12:30 ` [PATCH v5 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code Magnus Damm
  2017-11-06 20:08 ` [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Alex Williamson
  9 siblings, 0 replies; 13+ messages in thread
From: Magnus Damm @ 2017-10-16 12:30 UTC (permalink / raw)
  To: joro
  Cc: laurent.pinchart+renesas, geert+renesas, linux-kernel,
	linux-renesas-soc, iommu, horms+renesas, Magnus Damm,
	robin.murphy, m.szyprowski

From: Magnus Damm <damm+renesas@opensource.se>

Introduce support for two bit SL0 bitfield in IMTTBCR
by using a separate feature flag.

Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---

 Changes since V4:
 - Use leaf node mmu instead of root

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

--- 0019/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2017-10-16 20:24:22.990607110 +0900
@@ -40,6 +40,7 @@ struct ipmmu_features {
 	bool has_cache_leaf_nodes;
 	unsigned int number_of_contexts;
 	bool setup_imbuscr;
+	bool twobit_imttbcr_sl0;
 };
 
 struct ipmmu_vmsa_device {
@@ -144,6 +145,10 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMTTBCR_TSZ0_MASK		(7 << 0)
 #define IMTTBCR_TSZ0_SHIFT		O
 
+#define IMTTBCR_SL0_TWOBIT_LVL_3	(0 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_2	(1 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_1	(2 << 6)
+
 #define IMBUSCR				0x000c
 #define IMBUSCR_DVM			(1 << 2)
 #define IMBUSCR_BUSSEL_SYS		(0 << 0)
@@ -396,6 +401,7 @@ static void ipmmu_domain_free_context(st
 static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
 {
 	u64 ttbr;
+	u32 tmp;
 	int ret;
 
 	/*
@@ -449,9 +455,14 @@ static int ipmmu_domain_init_context(str
 	 * We use long descriptors with inner-shareable WBWA tables and allocate
 	 * the whole 32-bit VA space to TTBR0.
 	 */
+	if (domain->mmu->features->twobit_imttbcr_sl0)
+		tmp = IMTTBCR_SL0_TWOBIT_LVL_1;
+	else
+		tmp = IMTTBCR_SL0_LVL_1;
+
 	ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE |
 			     IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
-			     IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
+			     IMTTBCR_IRGN0_WB_WA | tmp);
 
 	/* MAIR0 */
 	ipmmu_ctx_write_root(domain, IMMAIR0,
@@ -982,6 +993,7 @@ static const struct ipmmu_features ipmmu
 	.has_cache_leaf_nodes = false,
 	.number_of_contexts = 1, /* software only tested with one context */
 	.setup_imbuscr = true,
+	.twobit_imttbcr_sl0 = false,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code
  2017-10-16 12:29 [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Magnus Damm
                   ` (7 preceding siblings ...)
  2017-10-16 12:30 ` [PATCH v5 08/09] iommu/ipmmu-vmsa: Allow two bit SL0 Magnus Damm
@ 2017-10-16 12:30 ` Magnus Damm
  2017-11-06 20:08 ` [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Alex Williamson
  9 siblings, 0 replies; 13+ messages in thread
From: Magnus Damm @ 2017-10-16 12:30 UTC (permalink / raw)
  To: joro
  Cc: laurent.pinchart+renesas, geert+renesas, linux-kernel,
	linux-renesas-soc, iommu, horms+renesas, Magnus Damm,
	robin.murphy, m.szyprowski

From: Magnus Damm <damm+renesas@opensource.se>

Tie in r8a7795 features and update the IOMMU_OF_DECLARE
compat string to include the updated compat string.

Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---

 Changes since V4:
 - Got rid of root device availability check in ->xlate()
   -> deferred probing is used to make sure the root is always present

 Changes since V3:
 - Rebased code on top of
   [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update
   This includes support for iommu_fwspec_add_ids()
 - Use dev_err() instead of dev_info() - Thanks Geert!
 - Moved single-invokation check into of_xlate() - Thanks Geert!
 - Dropped TODO list
 
 Changes since V2:
 - Check for lack of root device in ->xlate()
   This fixed a bug when IPMMU-MM is disabled in DT the system hangs on boot
 - Added code to ipmmu_init_platform_device() to handle multiple ->xlate() calls
 - Include empty white list by default
 - Updated TODO list

 Changes since V1:
 - Enable multi context feature
 - Update TODO list

 drivers/iommu/ipmmu-vmsa.c |   29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

--- 0019/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2017-10-16 19:53:14.710607110 +0900
@@ -25,6 +25,7 @@
 #include <linux/platform_device.h>
 #include <linux/sizes.h>
 #include <linux/slab.h>
+#include <linux/sys_soc.h>
 
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 #include <asm/dma-iommu.h>
@@ -735,9 +736,24 @@ static int ipmmu_init_platform_device(st
 	return 0;
 }
 
+static bool ipmmu_slave_whitelist(struct device *dev)
+{
+	/* By default, do not allow use of IPMMU */
+	return false;
+}
+
+static const struct soc_device_attribute soc_r8a7795[] = {
+	{ .soc_id = "r8a7795", },
+	{ /* sentinel */ }
+};
+
 static int ipmmu_of_xlate(struct device *dev,
 			  struct of_phandle_args *spec)
 {
+	/* For R-Car Gen3 use a white list to opt-in slave devices */
+	if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
+		return -ENODEV;
+
 	iommu_fwspec_add_ids(dev, spec->args, 1);
 
 	/* Initialize once - xlate() will call multiple times */
@@ -996,11 +1012,22 @@ static const struct ipmmu_features ipmmu
 	.twobit_imttbcr_sl0 = false,
 };
 
+static const struct ipmmu_features ipmmu_features_r8a7795 = {
+	.use_ns_alias_offset = false,
+	.has_cache_leaf_nodes = true,
+	.number_of_contexts = 8,
+	.setup_imbuscr = false,
+	.twobit_imttbcr_sl0 = true,
+};
+
 static const struct of_device_id ipmmu_of_ids[] = {
 	{
 		.compatible = "renesas,ipmmu-vmsa",
 		.data = &ipmmu_features_default,
 	}, {
+		.compatible = "renesas,ipmmu-r8a7795",
+		.data = &ipmmu_features_r8a7795,
+	}, {
 		/* Terminator */
 	},
 };
@@ -1185,6 +1212,8 @@ static int __init ipmmu_vmsa_iommu_of_se
 
 IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
 		 ipmmu_vmsa_iommu_of_setup);
+IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
+		 ipmmu_vmsa_iommu_of_setup);
 #endif
 
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5
  2017-10-16 12:29 [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Magnus Damm
                   ` (8 preceding siblings ...)
  2017-10-16 12:30 ` [PATCH v5 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code Magnus Damm
@ 2017-11-06 20:08 ` Alex Williamson
  9 siblings, 0 replies; 13+ messages in thread
From: Alex Williamson @ 2017-11-06 20:08 UTC (permalink / raw)
  To: Magnus Damm
  Cc: joro, laurent.pinchart+renesas, geert+renesas, linux-kernel,
	linux-renesas-soc, iommu, horms+renesas

On Mon, 16 Oct 2017 21:29:14 +0900
Magnus Damm <magnus.damm@gmail.com> wrote:

> iommu/ipmmu-vmsa: r8a7795 support V5
> 
> [PATCH v5 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias
> [PATCH v5 02/09] iommu/ipmmu-vmsa: Add optional root device feature
> [PATCH v5 03/09] iommu/ipmmu-vmsa: Enable multi context support
> [PATCH v5 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()
> [PATCH v5 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master
> [PATCH v5 06/09] iommu/ipmmu-vmsa: Write IMCTR twice
> [PATCH v5 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional
> [PATCH v5 08/09] iommu/ipmmu-vmsa: Allow two bit SL0
> [PATCH v5 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code
> 
> This is V5 of r8a7795 IPMMU driver where the series has been rebased
> and reworked to fit on next-20171013 that includes:
> [PATCH v2 00/05] iommu/ipmmu-vmsa: 32-bit ARM update V2
> [PATCH] iommu/ipmmu-vmsa: Use iommu_device_sysfs_add()/remove()
> 
> The major feature change is in patch 2/9 that now gets by without
> using a local list of registered IPMMU devices and instead relies
> on driver_for_each_device(). Thanks to Robin Murphy for his support.
> 
> The DT binding for r8a7795 has been accepted for upstream merge
> and this series implements support following such format:
> 
> d4e42e7 iommu/ipmmu-vmsa: Add r8a7795 DT binding
> 
> The r8a7795 IPMMU is almost register compatible with earlier devices
> like r8a7790-r8a7794, however some bitfields have been shifted
> slightly. On a grander scale topology has been added and interrupts
> have been reworked. So now there are several "cache" IPMMU units
> without interrupt that somehow communicate with IPMMU-MM that
> is the only instance that supports interrupts. The code refers to
> IPMMU-MM as a "root" device and the other ones as "leaf" nodes.
> 
> Changes since V4:
>  - Rebased on top of [PATCH v2 00/05] iommu/ipmmu-vmsa: 32-bit ARM update V2
>  - Reworked root device handling to make use of driver_for_each_device()
>  - Added deferred probing to make sure root device always is present
> 
> Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
> ---
> 
>  Developed on top of next-20171013
>  Also applies to renesas-drivers-2017-10-03-v4.14-rc3
>  Tested on top of renesas-drivers on r8a7796-m3ulcb using /dev/ttySC1
>   - [PATCH v4 0/3] iommu/ipmmu-vmsa: r8a7796 support V4
>   - local /dev/ttySC1 enablement for testing purpose
>   - local DTS changes to hook up SYS-DMAC and IPMMU DS0, DS1 and MM
>   - local whitelist code to enable "e7310000.dma-controller"
>  
>  drivers/iommu/ipmmu-vmsa.c |  310 ++++++++++++++++++++++++++++++++++----------
>  1 file changed, 244 insertions(+), 66 deletions(-)

Applied to iommu/ipmmu-vmsa for v4.15.  Thanks,

Alex

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2017-11-06 20:08 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-16 12:29 [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Magnus Damm
2017-10-16 12:29 ` [PATCH v5 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias Magnus Damm
2017-10-16 12:29   ` Magnus Damm
2017-10-16 12:29 ` [PATCH v5 02/09] iommu/ipmmu-vmsa: Add optional root device feature Magnus Damm
2017-10-16 12:29 ` [PATCH v5 03/09] iommu/ipmmu-vmsa: Enable multi context support Magnus Damm
2017-10-16 12:29 ` [PATCH v5 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE() Magnus Damm
2017-10-16 12:29   ` Magnus Damm
2017-10-16 12:30 ` [PATCH v5 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master Magnus Damm
2017-10-16 12:30 ` [PATCH v5 06/09] iommu/ipmmu-vmsa: Write IMCTR twice Magnus Damm
2017-10-16 12:30 ` [PATCH v5 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional Magnus Damm
2017-10-16 12:30 ` [PATCH v5 08/09] iommu/ipmmu-vmsa: Allow two bit SL0 Magnus Damm
2017-10-16 12:30 ` [PATCH v5 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code Magnus Damm
2017-11-06 20:08 ` [PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5 Alex Williamson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.