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@xxxxxxxxxx> --- .../bindings/iommu/nvidia,tegra30-smmu.txt | 41 ++++++++ drivers/iommu/tegra-smmu.c | 99 +++----------------- 2 files changed, 55 insertions(+), 85 deletions(-) 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; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html