diff mbox

[2/6] iommu/tegra: smmu: Pass swgroup info from DT

Message ID 1358237848-968-2-git-send-email-hdoyu@nvidia.com
State Not Applicable, archived
Headers show

Commit Message

Hiroshi Doyu Jan. 15, 2013, 8:17 a.m. UTC
Pass available H/W client component(software client group) info from
DT in bitmap. This info is specific to a certain generation of Tegra
SoC. With this, Tegra SMMU driver could be identical among Tegra
generations. This also removes the old way of passing this bit from
each device pdata, which could configure(enable/disable) each device
IOMMU'able, but it belongs to a kind of "policy", which can be done by
kernel/system later. Now DT passes just pure H/W info.

Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
---
 .../bindings/iommu/nvidia,tegra30-smmu.txt         |   41 ++++++++
 drivers/iommu/tegra-smmu.c                         |   99 +++-----------------
 2 files changed, 55 insertions(+), 85 deletions(-)

Comments

Stephen Warren Jan. 16, 2013, 9:07 p.m. UTC | #1
On 01/15/2013 01:17 AM, Hiroshi Doyu wrote:
> Pass available H/W client component(software client group) info from
> DT in bitmap. This info is specific to a certain generation of Tegra
> SoC. With this, Tegra SMMU driver could be identical among Tegra
> generations. This also removes the old way of passing this bit from
> each device pdata, which could configure(enable/disable) each device
> IOMMU'able, but it belongs to a kind of "policy", which can be done by
> kernel/system later. Now DT passes just pure H/W info.

> diff --git a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt
> index 89fb543..de449d0 100644
> --- a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt
> +++ b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt
> @@ -8,6 +8,46 @@ Required properties:
>  - nvidia,#asids : # of ASIDs
>  - dma-window : IOVA start address and length.
>  - nvidia,ahb : phandle to the ahb bus connected to SMMU.
> +- nvidia,swgroups: Available H/W client component(software client
> +  group) in bitmap in SoC. Those IDs are calculated as below:
> +
> +	  <ID> = (<OFFSET> - MC_SMMU_AFI_ASID_0) / 4;

OK, so I understand the addition to the DT defines which clients exist,
and hence which ASID-selection registers exist. This addition makes
sense to me.

> diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c

>  /*
>   * Per client for address space
> @@ -263,7 +192,6 @@ struct smmu_client {
>  	struct device		*dev;
>  	struct list_head	list;
>  	struct smmu_as		*as;
> -	u32			swgrp;
>  };

What I don't quite understand is that change, but perhaps that's because
I'm not sure what that field meant before, and/or where the
client<->ASID mapping comes from.

Before this patch, did each client use that removed "u32 swgrp" to tell
the SMMU driver which ASID-selection register was used to configure it,
and then the SMMU took the union of all clients to know which
ASID-selection registers existed? If so, then perhaps this change makes
more sense than I thought... But, how does the SMMU driver know which of
the bits in the new nvidia,swgroups property is related to each struct
smmu_client?

Or, did the removed "u32 swgrp" indicate which of the SMMU's ASIDs
should be assigned to the client?

I guess what I'm missing is: How does the SMMU know which ASID to assign
to each client, either before or after this change? Or, does the driver
just assign every client to ASID 0 right now, and there's no provision
for separate ASIDs?
--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt
index 89fb543..de449d0 100644
--- a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt
@@ -8,6 +8,46 @@  Required properties:
 - nvidia,#asids : # of ASIDs
 - dma-window : IOVA start address and length.
 - nvidia,ahb : phandle to the ahb bus connected to SMMU.
+- nvidia,swgroups: Available H/W client component(software client
+  group) in bitmap in SoC. Those IDs are calculated as below:
+
+	  <ID> = (<OFFSET> - MC_SMMU_AFI_ASID_0) / 4;
+
+  This <ID>/<OFFSET> can grow if SWGROUP is added in the future
+  SoC. Please refer to Tegra SoC TRM to find which SWGROUPs are
+  implemented in SoC.
+
+------------------------
+ID	Offset	SWGROUP
+=======================
+0	238	AFI
+1	23c	AVP
+2	240	DC
+3	244	DCB
+------------------------
+4	248	EPP
+5	24c	G2
+6	250	HC
+7	254	HDA
+------------------------
+8	258	ISP
+9	25c	-
+10	260	-
+11	264	MPE
+------------------------
+12	268	NV
+13	26c	NV2
+14	270	PPC
+15	274	-
+------------------------
+16	278	SAT
+17	27c	VDE
+18	280	VI
+19	284	-
+------------------------
+20	288	-
+21	29c	-
+......
 
 Example:
 	smmu {
@@ -17,5 +57,6 @@  Example:
 		       0x7000f228 0x05c>;
 		nvidia,#asids = <4>;		/* # of ASIDs */
 		dma-window = <0 0x40000000>;	/* IOVA start & length */
+		nvidia,swgroups = <0x775ff>;
 		nvidia,ahb = <&ahb>;
 	};
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 224c0a0..e83797b 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -39,46 +39,6 @@ 
 #include <asm/page.h>
 #include <asm/cacheflush.h>
 
-enum smmu_swgrp {
-	SWGRP_AFI,
-	SWGRP_AVPC,
-	SWGRP_DC,
-	SWGRP_DCB,
-	SWGRP_EPP,
-	SWGRP_G2,
-	SWGRP_HC,
-	SWGRP_HDA,
-	SWGRP_ISP,
-	SWGRP_MPE,
-	SWGRP_NV,
-	SWGRP_NV2,
-	SWGRP_PPCS,
-	SWGRP_SATA,
-	SWGRP_VDE,
-	SWGRP_VI,
-
-	SWGRP_COUNT,
-
-	SWGRP_END = ~0,
-};
-
-#define SWG_AFI		(1 << SWGRP_AFI)
-#define SWG_AVPC	(1 << SWGRP_AVPC)
-#define SWG_DC		(1 << SWGRP_DC)
-#define SWG_DCB		(1 << SWGRP_DCB)
-#define SWG_EPP		(1 << SWGRP_EPP)
-#define SWG_G2		(1 << SWGRP_G2)
-#define SWG_HC		(1 << SWGRP_HC)
-#define SWG_HDA		(1 << SWGRP_HDA)
-#define SWG_ISP		(1 << SWGRP_ISP)
-#define SWG_MPE		(1 << SWGRP_MPE)
-#define SWG_NV		(1 << SWGRP_NV)
-#define SWG_NV2		(1 << SWGRP_NV2)
-#define SWG_PPCS	(1 << SWGRP_PPCS)
-#define SWG_SATA	(1 << SWGRP_SATA)
-#define SWG_VDE		(1 << SWGRP_VDE)
-#define SWG_VI		(1 << SWGRP_VI)
-
 /* bitmap of the page sizes currently supported */
 #define SMMU_IOMMU_PGSIZES	(SZ_4K)
 
@@ -148,21 +108,10 @@  enum {
 #define SMMU_TRANSLATION_ENABLE_2		0x230
 
 #define SMMU_AFI_ASID	0x238   /* PCIE */
+#define SMMU_SWGRP_ASID_BASE	SMMU_AFI_ASID
+
 #define SMMU_AVPC_ASID	0x23c   /* AVP */
-#define SMMU_DC_ASID	0x240   /* Display controller */
-#define SMMU_DCB_ASID	0x244   /* Display controller B */
-#define SMMU_EPP_ASID	0x248   /* Encoder pre-processor */
-#define SMMU_G2_ASID	0x24c   /* 2D engine */
-#define SMMU_HC_ASID	0x250   /* Host1x */
-#define SMMU_HDA_ASID	0x254   /* High-def audio */
-#define SMMU_ISP_ASID	0x258   /* Image signal processor */
-#define SMMU_MPE_ASID	0x264   /* MPEG encoder */
-#define SMMU_NV_ASID	0x268   /* (3D) */
-#define SMMU_NV2_ASID	0x26c   /* (3D) */
-#define SMMU_PPCS_ASID	0x270   /* AHB */
-#define SMMU_SATA_ASID	0x278   /* SATA */
-#define SMMU_VDE_ASID	0x27c   /* Video decoder */
-#define SMMU_VI_ASID	0x280   /* Video input */
+#define SWG_AVPC	((SMMU_AVPC_ASID - SMMU_SWGRP_ASID_BASE) / 4)
 
 #define SMMU_PDE_NEXT_SHIFT		28
 
@@ -234,27 +183,7 @@  enum {
 #define __smmu_client_enable_swgrp(c, m) __smmu_client_set_swgrp(c, m, 1)
 #define __smmu_client_disable_swgrp(c)	__smmu_client_set_swgrp(c, 0, 0)
 
-#define SWGRP_INIT(client) [SWGRP_##client] = SMMU_##client##_ASID
-
-static const u32 smmu_swgrp_asid_reg[] = {
-	SWGRP_INIT(AFI),
-	SWGRP_INIT(AVPC),
-	SWGRP_INIT(DC),
-	SWGRP_INIT(DCB),
-	SWGRP_INIT(EPP),
-	SWGRP_INIT(G2),
-	SWGRP_INIT(HC),
-	SWGRP_INIT(HDA),
-	SWGRP_INIT(ISP),
-	SWGRP_INIT(MPE),
-	SWGRP_INIT(NV),
-	SWGRP_INIT(NV2),
-	SWGRP_INIT(PPCS),
-	SWGRP_INIT(SATA),
-	SWGRP_INIT(VDE),
-	SWGRP_INIT(VI),
-};
-#define SWGRP_ASID_REG(x) (smmu_swgrp_asid_reg[x])
+#define SWGRP_ASID_REG(id) (4 * (id) + SMMU_SWGRP_ASID_BASE)
 
 /*
  * Per client for address space
@@ -263,7 +192,6 @@  struct smmu_client {
 	struct device		*dev;
 	struct list_head	list;
 	struct smmu_as		*as;
-	u32			swgrp;
 };
 
 /*
@@ -313,6 +241,7 @@  struct smmu_device {
 	struct smmu_debugfs_info *debugfs_info;
 
 	struct device_node *ahb;
+	u32 swgrp;
 
 	int		num_as;
 	struct smmu_as	as[0];		/* Run-time allocated array */
@@ -375,8 +304,6 @@  static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs)
  */
 #define FLUSH_SMMU_REGS(smmu)	smmu_read(smmu, SMMU_CONFIG)
 
-#define smmu_client_swgrp(c) (u32)((c)->dev->platform_data)
-
 static int __smmu_client_set_swgrp(struct smmu_client *c,
 				   unsigned long map, int on)
 {
@@ -388,10 +315,8 @@  static int __smmu_client_set_swgrp(struct smmu_client *c,
 	WARN_ON(!on && map);
 	if (on && !map)
 		return -EINVAL;
-	if (!on)
-		map = smmu_client_swgrp(c);
 
-	for_each_set_bit(i, &map, SWGRP_COUNT) {
+	for_each_set_bit(i, &map, BITS_PER_LONG) {
 		offs = SWGRP_ASID_REG(i);
 		val = smmu_read(smmu, offs);
 		if (on) {
@@ -405,11 +330,10 @@  static int __smmu_client_set_swgrp(struct smmu_client *c,
 		smmu_write(smmu, val, offs);
 	}
 	FLUSH_SMMU_REGS(smmu);
-	c->swgrp = map;
 	return 0;
 
 err_hw_busy:
-	for_each_set_bit(i, &map, SWGRP_COUNT) {
+	for_each_set_bit(i, &map, BITS_PER_LONG) {
 		offs = SWGRP_ASID_REG(i);
 		val = smmu_read(smmu, offs);
 		val &= ~mask;
@@ -466,7 +390,7 @@  static int smmu_setup_regs(struct smmu_device *smmu)
 		smmu_write(smmu, val, SMMU_PTB_DATA);
 
 		list_for_each_entry(c, &as->client, list)
-			__smmu_client_set_swgrp(c, c->swgrp, 1);
+			__smmu_client_set_swgrp(c, smmu->swgrp, 1);
 	}
 
 	smmu_write(smmu, smmu->translation_enable_0, SMMU_TRANSLATION_ENABLE_0);
@@ -794,7 +718,7 @@  static int smmu_iommu_attach_dev(struct iommu_domain *domain,
 		return -ENOMEM;
 	client->dev = dev;
 	client->as = as;
-	map = (unsigned long)dev->platform_data;
+	map = smmu->swgrp;
 	if (!map)
 		return -EINVAL;
 
@@ -1154,12 +1078,16 @@  static int tegra_smmu_probe(struct platform_device *pdev)
 	int i, asids, err = 0;
 	dma_addr_t uninitialized_var(base);
 	size_t bytes, uninitialized_var(size);
+	u32 swgrp;
 
 	if (smmu_handle)
 		return -EIO;
 
 	BUILD_BUG_ON(PAGE_SHIFT != SMMU_PAGE_SHIFT);
 
+	if (of_property_read_u32(dev->of_node, "nvidia,swgroups", &swgrp))
+		return -ENODEV;
+
 	if (of_property_read_u32(dev->of_node, "nvidia,#asids", &asids))
 		return -ENODEV;
 
@@ -1198,6 +1126,7 @@  static int tegra_smmu_probe(struct platform_device *pdev)
 
 	smmu->dev = dev;
 	smmu->num_as = asids;
+	smmu->swgrp = swgrp;
 	smmu->iovmm_base = base;
 	smmu->page_count = size;