Loading drivers/iommu/arm-smmu-impl.c +38 −4 Original line number Diff line number Diff line Loading @@ -48,25 +48,60 @@ const struct arm_smmu_impl calxeda_impl = { }; struct cavium_smmu { struct arm_smmu_device smmu; u32 id_base; }; static int cavium_cfg_probe(struct arm_smmu_device *smmu) { static atomic_t context_count = ATOMIC_INIT(0); struct cavium_smmu *cs = container_of(smmu, struct cavium_smmu, smmu); /* * Cavium CN88xx erratum #27704. * Ensure ASID and VMID allocation is unique across all SMMUs in * the system. */ smmu->cavium_id_base = atomic_fetch_add(smmu->num_context_banks, &context_count); cs->id_base = atomic_fetch_add(smmu->num_context_banks, &context_count); dev_notice(smmu->dev, "\tenabling workaround for Cavium erratum 27704\n"); return 0; } int cavium_init_context(struct arm_smmu_domain *smmu_domain) { struct cavium_smmu *cs = container_of(smmu_domain->smmu, struct cavium_smmu, smmu); if (smmu_domain->stage == ARM_SMMU_DOMAIN_S2) smmu_domain->cfg.vmid += cs->id_base; else smmu_domain->cfg.asid += cs->id_base; return 0; } const struct arm_smmu_impl cavium_impl = { .cfg_probe = cavium_cfg_probe, .init_context = cavium_init_context, }; struct arm_smmu_device *cavium_smmu_impl_init(struct arm_smmu_device *smmu) { struct cavium_smmu *cs; cs = devm_kzalloc(smmu->dev, sizeof(*cs), GFP_KERNEL); if (!cs) return ERR_PTR(-ENOMEM); cs->smmu = *smmu; cs->smmu.impl = &cavium_impl; devm_kfree(smmu->dev, smmu); return &cs->smmu; } #define ARM_MMU500_ACTLR_CPRE (1 << 1) Loading Loading @@ -126,8 +161,7 @@ struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu) smmu->impl = &arm_mmu500_impl; break; case CAVIUM_SMMUV2: smmu->impl = &cavium_impl; break; return cavium_smmu_impl_init(smmu); default: break; } Loading drivers/iommu/arm-smmu.c +15 −59 Original line number Diff line number Diff line Loading @@ -30,7 +30,6 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/io-64-nonatomic-hi-lo.h> #include <linux/io-pgtable.h> #include <linux/iopoll.h> #include <linux/module.h> #include <linux/interconnect.h> Loading Loading @@ -144,25 +143,6 @@ struct arm_smmu_master_cfg { #define for_each_cfg_sme(fw, i, idx) \ for (i = 0; idx = fwspec_smendx(fw, i), i < fw->num_ids; ++i) enum arm_smmu_context_fmt { ARM_SMMU_CTX_FMT_NONE, ARM_SMMU_CTX_FMT_AARCH64, ARM_SMMU_CTX_FMT_AARCH32_L, ARM_SMMU_CTX_FMT_AARCH32_S, }; struct arm_smmu_cfg { u8 cbndx; u8 irptndx; union { u16 asid; u16 vmid; }; u32 procid; enum arm_smmu_cbar_type cbar; enum arm_smmu_context_fmt fmt; }; #define INVALID_IRPTNDX 0xff #define INVALID_CBNDX 0xff #define INVALID_ASID 0xffff /* Loading @@ -175,42 +155,12 @@ struct arm_smmu_cfg { #define ARM_SMMU_CB_VMID(smmu, cfg) ((u16)(smmu)->cavium_id_base + \ (cfg)->cbndx + 1) enum arm_smmu_domain_stage { ARM_SMMU_DOMAIN_S1 = 0, ARM_SMMU_DOMAIN_S2, ARM_SMMU_DOMAIN_NESTED, ARM_SMMU_DOMAIN_BYPASS, }; struct arm_smmu_pte_info { void *virt_addr; size_t size; struct list_head entry; }; struct arm_smmu_domain { struct arm_smmu_device *smmu; struct device *dev; struct io_pgtable_ops *pgtbl_ops; const struct iommu_gather_ops *tlb_ops; struct arm_smmu_cfg cfg; enum arm_smmu_domain_stage stage; bool non_strict; struct mutex init_mutex; /* Protects smmu pointer */ spinlock_t cb_lock; /* Serialises ATS1* ops */ spinlock_t sync_lock; /* Serialises TLB syncs */ struct msm_io_pgtable_info pgtbl_info; u64 attributes; u32 secure_vmid; struct list_head pte_info_list; struct list_head unassign_list; struct mutex assign_lock; struct list_head secure_pool_list; /* nonsecure pool protected by pgtbl_lock */ struct list_head nonsecure_pool; struct msm_iommu_domain domain; }; static bool using_legacy_binding, using_generic_binding; struct arm_smmu_option_prop { Loading Loading @@ -1600,12 +1550,12 @@ static void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx, */ if (of_dma_is_coherent(smmu_domain->dev->of_node)) { reg |= SCTLR_RACFG_RA << SCTLR_RACFG_SHIFT; reg |= SCTLR_WACFG_WA << SCTLR_WACFG_SHIFT; reg |= SCTLR_MTCFG; reg |= SCTLR_MEM_ATTR_OISH_WB_CACHE << SCTLR_MEM_ATTR_SHIFT; reg |= FIELD_PREP(SCTLR_WACFG, SCTLR_WACFG_WA) | FIELD_PREP(SCTLR_RACFG, SCTLR_RACFG_RA) | SCTLR_MTCFG | FIELD_PREP(SCTLR_MEM_ATTR, SCTLR_MEM_ATTR_OISH_WB_CACHE); } else reg |= SCTLR_SHCFG_NSH << SCTLR_SHCFG_SHIFT; reg |= FIELD_PREP(SCTLR_SHCFG, SCTLR_SHCFG_NSH); if (attributes & (1ULL << DOMAIN_ATTR_CB_STALL_DISABLE)) { reg &= ~SCTLR_CFCFG; Loading Loading @@ -1958,6 +1908,13 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, cfg->cbndx = ret; smmu_domain->smmu = smmu; if (smmu->impl && smmu->impl->init_context) { ret = smmu->impl->init_context(smmu_domain); if (ret) goto out_clear_smmu; } pgtbl_info->pgtbl_cfg = (struct io_pgtable_cfg) { .quirks = quirks, .pgsize_bitmap = smmu->pgsize_bitmap, Loading @@ -1968,7 +1925,6 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, .iommu_dev = smmu->dev, }; smmu_domain->smmu = smmu; smmu_domain->dev = dev; smmu_domain->pgtbl_ops = alloc_io_pgtable_ops(fmt, &pgtbl_info->pgtbl_cfg, Loading Loading @@ -2152,7 +2108,7 @@ static void arm_smmu_write_s2cr(struct arm_smmu_device *smmu, int idx) u32 reg = FIELD_PREP(S2CR_TYPE, s2cr->type) | FIELD_PREP(S2CR_CBNDX, s2cr->cbndx) | FIELD_PREP(S2CR_PRIVCFG, s2cr->privcfg) | S2CR_SHCFG_NSH << S2CR_SHCFG_SHIFT; FIELD_PREP(S2CR_SHCFG, S2CR_SHCFG_NSH); if (smmu->features & ARM_SMMU_FEAT_EXIDS && smmu->smrs && smmu->smrs[idx].valid) Loading Loading @@ -3919,8 +3875,8 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu) reg |= sCR0_EXIDENABLE; /* Force bypass transaction to be Non-Shareable & not io-coherent */ reg &= ~(sCR0_SHCFG_MASK << sCR0_SHCFG_SHIFT); reg |= sCR0_SHCFG_NSH << sCR0_SHCFG_SHIFT; reg &= ~sCR0_SHCFG; reg |= FIELD_PREP(sCR0_SHCFG, sCR0_SHCFG_NSH); if (smmu->impl && smmu->impl->reset) smmu->impl->reset(smmu); Loading drivers/iommu/arm-smmu.h +68 −22 Original line number Diff line number Diff line Loading @@ -15,16 +15,16 @@ #include <linux/clk.h> #include <linux/device.h> #include <linux/iommu.h> #include <linux/io-pgtable.h> #include <linux/mutex.h> #include <linux/spinlock.h> #include <linux/types.h> /* Configuration registers */ #define ARM_SMMU_GR0_sCR0 0x0 #define sCR0_SHCFG_SHIFT 22 #define sCR0_SHCFG_MASK 0x3 #define sCR0_SHCFG_NSH 3 #define sCR0_VMID16EN BIT(31) #define sCR0_SHCFG GENMASK(23, 22) #define sCR0_SHCFG_NSH 0x3 #define sCR0_BSU GENMASK(15, 14) #define sCR0_FB BIT(13) #define sCR0_PTM BIT(12) Loading Loading @@ -95,15 +95,14 @@ /* Stream mapping registers */ #define ARM_SMMU_GR0_SMR(n) (0x800 + ((n) << 2)) #define SMR_MASK_MASK 0x7FFF #define SID_MASK 0x7FFF #define SMR_MASK_MASK GENMASK(14, 0) #define SID_MASK GENMASK(14, 0) #define SMR_VALID BIT(31) #define SMR_MASK GENMASK(31, 16) #define SMR_ID GENMASK(15, 0) #define ARM_SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2)) #define S2CR_SHCFG_SHIFT 8 #define S2CR_SHCFG_MASK 0x3 #define S2CR_SHCFG GENMASK(9, 8) #define S2CR_SHCFG_NSH 0x3 #define S2CR_PRIVCFG GENMASK(25, 24) Loading Loading @@ -146,7 +145,17 @@ enum arm_smmu_cbar_type { #define CBA2R_VA64 BIT(0) #define ARM_SMMU_CB_SCTLR 0x0 #define SCTLR_WACFG GENMASK(27, 26) #define SCTLR_WACFG_WA 0x2 #define SCTLR_RACFG GENMASK(25, 24) #define SCTLR_RACFG_RA 0x2 #define SCTLR_SHCFG GENMASK(23, 22) #define SCTLR_SHCFG_NSH 0x3 #define SCTLR_MTCFG BIT(20) #define SCTLR_MEM_ATTR GENMASK(19, 16) #define SCTLR_MEM_ATTR_OISH_WB_CACHE 0xf #define SCTLR_S1_ASIDPNE BIT(12) #define SCTLR_HUPCF BIT(8) #define SCTLR_CFCFG BIT(7) #define SCTLR_CFIE BIT(6) #define SCTLR_CFRE BIT(5) Loading Loading @@ -209,24 +218,12 @@ enum arm_smmu_cbar_type { #define ARM_SMMU_CB_S2_TLBIIPAS2L 0x638 #define ARM_SMMU_CB_TLBSYNC 0x7f0 #define ARM_SMMU_CB_TLBSTATUS 0x7f4 #define TLBSTATUS_SACTIVE (1 << 0) #define TLBSTATUS_SACTIVE BIT(0) #define ARM_SMMU_CB_ATS1PR 0x800 #define ARM_SMMU_STATS_SYNC_INV_TBU_ACK 0x25dc #define ARM_SMMU_TBU_PWR_STATUS 0x2204 #define ARM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR 0x2670 #define SCTLR_MEM_ATTR_SHIFT 16 #define SCTLR_SHCFG_SHIFT 22 #define SCTLR_RACFG_SHIFT 24 #define SCTLR_WACFG_SHIFT 26 #define SCTLR_SHCFG_MASK 0x3 #define SCTLR_SHCFG_NSH 0x3 #define SCTLR_RACFG_RA 0x2 #define SCTLR_WACFG_WA 0x2 #define SCTLR_MEM_ATTR_OISH_WB_CACHE 0xf #define SCTLR_MTCFG (1 << 20) #define SCTLR_HUPCF (1 << 8) #define ARM_SMMU_CB_ATSR 0x8f0 #define ATSR_ACTIVE BIT(0) Loading Loading @@ -341,8 +338,6 @@ struct arm_smmu_device { struct list_head list; u32 cavium_id_base; /* Specific to Cavium */ spinlock_t global_sync_lock; /* IOMMU core code handle */ Loading @@ -364,6 +359,56 @@ struct arm_smmu_device { void *archdata; }; enum arm_smmu_context_fmt { ARM_SMMU_CTX_FMT_NONE, ARM_SMMU_CTX_FMT_AARCH64, ARM_SMMU_CTX_FMT_AARCH32_L, ARM_SMMU_CTX_FMT_AARCH32_S, }; struct arm_smmu_cfg { u8 cbndx; u8 irptndx; union { u16 asid; u16 vmid; }; u32 procid; enum arm_smmu_cbar_type cbar; enum arm_smmu_context_fmt fmt; }; #define INVALID_IRPTNDX 0xff enum arm_smmu_domain_stage { ARM_SMMU_DOMAIN_S1 = 0, ARM_SMMU_DOMAIN_S2, ARM_SMMU_DOMAIN_NESTED, ARM_SMMU_DOMAIN_BYPASS, }; struct arm_smmu_domain { struct arm_smmu_device *smmu; struct device *dev; struct io_pgtable_ops *pgtbl_ops; const struct iommu_gather_ops *tlb_ops; struct arm_smmu_cfg cfg; enum arm_smmu_domain_stage stage; bool non_strict; struct mutex init_mutex; /* Protects smmu pointer */ spinlock_t cb_lock; /* Serialises ATS1* ops */ spinlock_t sync_lock; /* Serialises TLB syncs */ struct msm_io_pgtable_info pgtbl_info; u64 attributes; u32 secure_vmid; struct list_head pte_info_list; struct list_head unassign_list; struct mutex assign_lock; struct list_head secure_pool_list; /* nonsecure pool protected by pgtbl_lock */ struct list_head nonsecure_pool; struct msm_iommu_domain domain; }; /* Implementation details, yay! */ struct arm_smmu_impl { Loading @@ -375,6 +420,7 @@ struct arm_smmu_impl { u64 val); int (*cfg_probe)(struct arm_smmu_device *smmu); int (*reset)(struct arm_smmu_device *smmu); int (*init_context)(struct arm_smmu_domain *smmu_domain); }; static inline void __iomem *arm_smmu_page(struct arm_smmu_device *smmu, int n) Loading Loading
drivers/iommu/arm-smmu-impl.c +38 −4 Original line number Diff line number Diff line Loading @@ -48,25 +48,60 @@ const struct arm_smmu_impl calxeda_impl = { }; struct cavium_smmu { struct arm_smmu_device smmu; u32 id_base; }; static int cavium_cfg_probe(struct arm_smmu_device *smmu) { static atomic_t context_count = ATOMIC_INIT(0); struct cavium_smmu *cs = container_of(smmu, struct cavium_smmu, smmu); /* * Cavium CN88xx erratum #27704. * Ensure ASID and VMID allocation is unique across all SMMUs in * the system. */ smmu->cavium_id_base = atomic_fetch_add(smmu->num_context_banks, &context_count); cs->id_base = atomic_fetch_add(smmu->num_context_banks, &context_count); dev_notice(smmu->dev, "\tenabling workaround for Cavium erratum 27704\n"); return 0; } int cavium_init_context(struct arm_smmu_domain *smmu_domain) { struct cavium_smmu *cs = container_of(smmu_domain->smmu, struct cavium_smmu, smmu); if (smmu_domain->stage == ARM_SMMU_DOMAIN_S2) smmu_domain->cfg.vmid += cs->id_base; else smmu_domain->cfg.asid += cs->id_base; return 0; } const struct arm_smmu_impl cavium_impl = { .cfg_probe = cavium_cfg_probe, .init_context = cavium_init_context, }; struct arm_smmu_device *cavium_smmu_impl_init(struct arm_smmu_device *smmu) { struct cavium_smmu *cs; cs = devm_kzalloc(smmu->dev, sizeof(*cs), GFP_KERNEL); if (!cs) return ERR_PTR(-ENOMEM); cs->smmu = *smmu; cs->smmu.impl = &cavium_impl; devm_kfree(smmu->dev, smmu); return &cs->smmu; } #define ARM_MMU500_ACTLR_CPRE (1 << 1) Loading Loading @@ -126,8 +161,7 @@ struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu) smmu->impl = &arm_mmu500_impl; break; case CAVIUM_SMMUV2: smmu->impl = &cavium_impl; break; return cavium_smmu_impl_init(smmu); default: break; } Loading
drivers/iommu/arm-smmu.c +15 −59 Original line number Diff line number Diff line Loading @@ -30,7 +30,6 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/io-64-nonatomic-hi-lo.h> #include <linux/io-pgtable.h> #include <linux/iopoll.h> #include <linux/module.h> #include <linux/interconnect.h> Loading Loading @@ -144,25 +143,6 @@ struct arm_smmu_master_cfg { #define for_each_cfg_sme(fw, i, idx) \ for (i = 0; idx = fwspec_smendx(fw, i), i < fw->num_ids; ++i) enum arm_smmu_context_fmt { ARM_SMMU_CTX_FMT_NONE, ARM_SMMU_CTX_FMT_AARCH64, ARM_SMMU_CTX_FMT_AARCH32_L, ARM_SMMU_CTX_FMT_AARCH32_S, }; struct arm_smmu_cfg { u8 cbndx; u8 irptndx; union { u16 asid; u16 vmid; }; u32 procid; enum arm_smmu_cbar_type cbar; enum arm_smmu_context_fmt fmt; }; #define INVALID_IRPTNDX 0xff #define INVALID_CBNDX 0xff #define INVALID_ASID 0xffff /* Loading @@ -175,42 +155,12 @@ struct arm_smmu_cfg { #define ARM_SMMU_CB_VMID(smmu, cfg) ((u16)(smmu)->cavium_id_base + \ (cfg)->cbndx + 1) enum arm_smmu_domain_stage { ARM_SMMU_DOMAIN_S1 = 0, ARM_SMMU_DOMAIN_S2, ARM_SMMU_DOMAIN_NESTED, ARM_SMMU_DOMAIN_BYPASS, }; struct arm_smmu_pte_info { void *virt_addr; size_t size; struct list_head entry; }; struct arm_smmu_domain { struct arm_smmu_device *smmu; struct device *dev; struct io_pgtable_ops *pgtbl_ops; const struct iommu_gather_ops *tlb_ops; struct arm_smmu_cfg cfg; enum arm_smmu_domain_stage stage; bool non_strict; struct mutex init_mutex; /* Protects smmu pointer */ spinlock_t cb_lock; /* Serialises ATS1* ops */ spinlock_t sync_lock; /* Serialises TLB syncs */ struct msm_io_pgtable_info pgtbl_info; u64 attributes; u32 secure_vmid; struct list_head pte_info_list; struct list_head unassign_list; struct mutex assign_lock; struct list_head secure_pool_list; /* nonsecure pool protected by pgtbl_lock */ struct list_head nonsecure_pool; struct msm_iommu_domain domain; }; static bool using_legacy_binding, using_generic_binding; struct arm_smmu_option_prop { Loading Loading @@ -1600,12 +1550,12 @@ static void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx, */ if (of_dma_is_coherent(smmu_domain->dev->of_node)) { reg |= SCTLR_RACFG_RA << SCTLR_RACFG_SHIFT; reg |= SCTLR_WACFG_WA << SCTLR_WACFG_SHIFT; reg |= SCTLR_MTCFG; reg |= SCTLR_MEM_ATTR_OISH_WB_CACHE << SCTLR_MEM_ATTR_SHIFT; reg |= FIELD_PREP(SCTLR_WACFG, SCTLR_WACFG_WA) | FIELD_PREP(SCTLR_RACFG, SCTLR_RACFG_RA) | SCTLR_MTCFG | FIELD_PREP(SCTLR_MEM_ATTR, SCTLR_MEM_ATTR_OISH_WB_CACHE); } else reg |= SCTLR_SHCFG_NSH << SCTLR_SHCFG_SHIFT; reg |= FIELD_PREP(SCTLR_SHCFG, SCTLR_SHCFG_NSH); if (attributes & (1ULL << DOMAIN_ATTR_CB_STALL_DISABLE)) { reg &= ~SCTLR_CFCFG; Loading Loading @@ -1958,6 +1908,13 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, cfg->cbndx = ret; smmu_domain->smmu = smmu; if (smmu->impl && smmu->impl->init_context) { ret = smmu->impl->init_context(smmu_domain); if (ret) goto out_clear_smmu; } pgtbl_info->pgtbl_cfg = (struct io_pgtable_cfg) { .quirks = quirks, .pgsize_bitmap = smmu->pgsize_bitmap, Loading @@ -1968,7 +1925,6 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, .iommu_dev = smmu->dev, }; smmu_domain->smmu = smmu; smmu_domain->dev = dev; smmu_domain->pgtbl_ops = alloc_io_pgtable_ops(fmt, &pgtbl_info->pgtbl_cfg, Loading Loading @@ -2152,7 +2108,7 @@ static void arm_smmu_write_s2cr(struct arm_smmu_device *smmu, int idx) u32 reg = FIELD_PREP(S2CR_TYPE, s2cr->type) | FIELD_PREP(S2CR_CBNDX, s2cr->cbndx) | FIELD_PREP(S2CR_PRIVCFG, s2cr->privcfg) | S2CR_SHCFG_NSH << S2CR_SHCFG_SHIFT; FIELD_PREP(S2CR_SHCFG, S2CR_SHCFG_NSH); if (smmu->features & ARM_SMMU_FEAT_EXIDS && smmu->smrs && smmu->smrs[idx].valid) Loading Loading @@ -3919,8 +3875,8 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu) reg |= sCR0_EXIDENABLE; /* Force bypass transaction to be Non-Shareable & not io-coherent */ reg &= ~(sCR0_SHCFG_MASK << sCR0_SHCFG_SHIFT); reg |= sCR0_SHCFG_NSH << sCR0_SHCFG_SHIFT; reg &= ~sCR0_SHCFG; reg |= FIELD_PREP(sCR0_SHCFG, sCR0_SHCFG_NSH); if (smmu->impl && smmu->impl->reset) smmu->impl->reset(smmu); Loading
drivers/iommu/arm-smmu.h +68 −22 Original line number Diff line number Diff line Loading @@ -15,16 +15,16 @@ #include <linux/clk.h> #include <linux/device.h> #include <linux/iommu.h> #include <linux/io-pgtable.h> #include <linux/mutex.h> #include <linux/spinlock.h> #include <linux/types.h> /* Configuration registers */ #define ARM_SMMU_GR0_sCR0 0x0 #define sCR0_SHCFG_SHIFT 22 #define sCR0_SHCFG_MASK 0x3 #define sCR0_SHCFG_NSH 3 #define sCR0_VMID16EN BIT(31) #define sCR0_SHCFG GENMASK(23, 22) #define sCR0_SHCFG_NSH 0x3 #define sCR0_BSU GENMASK(15, 14) #define sCR0_FB BIT(13) #define sCR0_PTM BIT(12) Loading Loading @@ -95,15 +95,14 @@ /* Stream mapping registers */ #define ARM_SMMU_GR0_SMR(n) (0x800 + ((n) << 2)) #define SMR_MASK_MASK 0x7FFF #define SID_MASK 0x7FFF #define SMR_MASK_MASK GENMASK(14, 0) #define SID_MASK GENMASK(14, 0) #define SMR_VALID BIT(31) #define SMR_MASK GENMASK(31, 16) #define SMR_ID GENMASK(15, 0) #define ARM_SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2)) #define S2CR_SHCFG_SHIFT 8 #define S2CR_SHCFG_MASK 0x3 #define S2CR_SHCFG GENMASK(9, 8) #define S2CR_SHCFG_NSH 0x3 #define S2CR_PRIVCFG GENMASK(25, 24) Loading Loading @@ -146,7 +145,17 @@ enum arm_smmu_cbar_type { #define CBA2R_VA64 BIT(0) #define ARM_SMMU_CB_SCTLR 0x0 #define SCTLR_WACFG GENMASK(27, 26) #define SCTLR_WACFG_WA 0x2 #define SCTLR_RACFG GENMASK(25, 24) #define SCTLR_RACFG_RA 0x2 #define SCTLR_SHCFG GENMASK(23, 22) #define SCTLR_SHCFG_NSH 0x3 #define SCTLR_MTCFG BIT(20) #define SCTLR_MEM_ATTR GENMASK(19, 16) #define SCTLR_MEM_ATTR_OISH_WB_CACHE 0xf #define SCTLR_S1_ASIDPNE BIT(12) #define SCTLR_HUPCF BIT(8) #define SCTLR_CFCFG BIT(7) #define SCTLR_CFIE BIT(6) #define SCTLR_CFRE BIT(5) Loading Loading @@ -209,24 +218,12 @@ enum arm_smmu_cbar_type { #define ARM_SMMU_CB_S2_TLBIIPAS2L 0x638 #define ARM_SMMU_CB_TLBSYNC 0x7f0 #define ARM_SMMU_CB_TLBSTATUS 0x7f4 #define TLBSTATUS_SACTIVE (1 << 0) #define TLBSTATUS_SACTIVE BIT(0) #define ARM_SMMU_CB_ATS1PR 0x800 #define ARM_SMMU_STATS_SYNC_INV_TBU_ACK 0x25dc #define ARM_SMMU_TBU_PWR_STATUS 0x2204 #define ARM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR 0x2670 #define SCTLR_MEM_ATTR_SHIFT 16 #define SCTLR_SHCFG_SHIFT 22 #define SCTLR_RACFG_SHIFT 24 #define SCTLR_WACFG_SHIFT 26 #define SCTLR_SHCFG_MASK 0x3 #define SCTLR_SHCFG_NSH 0x3 #define SCTLR_RACFG_RA 0x2 #define SCTLR_WACFG_WA 0x2 #define SCTLR_MEM_ATTR_OISH_WB_CACHE 0xf #define SCTLR_MTCFG (1 << 20) #define SCTLR_HUPCF (1 << 8) #define ARM_SMMU_CB_ATSR 0x8f0 #define ATSR_ACTIVE BIT(0) Loading Loading @@ -341,8 +338,6 @@ struct arm_smmu_device { struct list_head list; u32 cavium_id_base; /* Specific to Cavium */ spinlock_t global_sync_lock; /* IOMMU core code handle */ Loading @@ -364,6 +359,56 @@ struct arm_smmu_device { void *archdata; }; enum arm_smmu_context_fmt { ARM_SMMU_CTX_FMT_NONE, ARM_SMMU_CTX_FMT_AARCH64, ARM_SMMU_CTX_FMT_AARCH32_L, ARM_SMMU_CTX_FMT_AARCH32_S, }; struct arm_smmu_cfg { u8 cbndx; u8 irptndx; union { u16 asid; u16 vmid; }; u32 procid; enum arm_smmu_cbar_type cbar; enum arm_smmu_context_fmt fmt; }; #define INVALID_IRPTNDX 0xff enum arm_smmu_domain_stage { ARM_SMMU_DOMAIN_S1 = 0, ARM_SMMU_DOMAIN_S2, ARM_SMMU_DOMAIN_NESTED, ARM_SMMU_DOMAIN_BYPASS, }; struct arm_smmu_domain { struct arm_smmu_device *smmu; struct device *dev; struct io_pgtable_ops *pgtbl_ops; const struct iommu_gather_ops *tlb_ops; struct arm_smmu_cfg cfg; enum arm_smmu_domain_stage stage; bool non_strict; struct mutex init_mutex; /* Protects smmu pointer */ spinlock_t cb_lock; /* Serialises ATS1* ops */ spinlock_t sync_lock; /* Serialises TLB syncs */ struct msm_io_pgtable_info pgtbl_info; u64 attributes; u32 secure_vmid; struct list_head pte_info_list; struct list_head unassign_list; struct mutex assign_lock; struct list_head secure_pool_list; /* nonsecure pool protected by pgtbl_lock */ struct list_head nonsecure_pool; struct msm_iommu_domain domain; }; /* Implementation details, yay! */ struct arm_smmu_impl { Loading @@ -375,6 +420,7 @@ struct arm_smmu_impl { u64 val); int (*cfg_probe)(struct arm_smmu_device *smmu); int (*reset)(struct arm_smmu_device *smmu); int (*init_context)(struct arm_smmu_domain *smmu_domain); }; static inline void __iomem *arm_smmu_page(struct arm_smmu_device *smmu, int n) Loading