diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index 2df61831092f..4a2e4bacd914 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -16,6 +16,7 @@ conditions. "arm,mmu-400" "arm,mmu-401" "arm,mmu-500" + "qcom,smmu-v2" depending on the particular implementation and/or the version of the architecture implemented. diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 0cd8fbbda22a..389befcc58c6 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -229,6 +229,7 @@ #define ARM_SMMU_CB(smmu, n) ((n) * (1 << (smmu)->pgshift)) #define ARM_SMMU_CB_SCTLR 0x0 +#define ARM_SMMU_CB_ACTLR 0x4 #define ARM_SMMU_CB_RESUME 0x8 #define ARM_SMMU_CB_TTBCR2 0x10 #define ARM_SMMU_CB_TTBR0_LO 0x20 @@ -331,6 +332,17 @@ #define FSR_AFF (1 << 2) #define FSR_TF (1 << 1) +/* Definitions for implementation-defined registers */ +#define ACTLR_QCOM_OSH_SHIFT 28 +#define ACTLR_QCOM_OSH 1 + +#define ACTLR_QCOM_ISH_SHIFT 29 +#define ACTLR_QCOM_ISH 1 + +#define ACTLR_QCOM_NSH_SHIFT 30 +#define ACTLR_QCOM_NSH 1 + + #define FSR_IGN (FSR_AFF | FSR_ASF | \ FSR_TLBMCF | FSR_TLBLKF) #define FSR_FAULT (FSR_MULTI | FSR_SS | FSR_UUT | \ @@ -366,9 +378,16 @@ struct arm_smmu_master { struct arm_smmu_master_cfg cfg; }; +enum smmu_model_id { + SMMU_MODEL_DEFAULT, + SMMU_MODEL_QCOM_V2, +}; + struct arm_smmu_device { struct device *dev; + enum smmu_model_id model; + void __iomem *base; unsigned long size; unsigned long pgshift; @@ -1018,6 +1037,13 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR); + if (smmu->model == SMMU_MODEL_QCOM_V2) { + reg = ACTLR_QCOM_ISH << ACTLR_QCOM_ISH_SHIFT | + ACTLR_QCOM_OSH << ACTLR_QCOM_OSH_SHIFT | + ACTLR_QCOM_NSH << ACTLR_QCOM_NSH_SHIFT; + writel_relaxed(reg, cb_base + ARM_SMMU_CB_ACTLR); + } + /* MAIR0 (stage-1 only) */ if (stage1) { reg = (MAIR_ATTR_NC << MAIR_ATTR_SHIFT(MAIR_ATTR_IDX_NC)) | @@ -2246,6 +2272,7 @@ static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,mmu-400", .data = (void *)ARM_SMMU_V1 }, { .compatible = "arm,mmu-401", .data = (void *)ARM_SMMU_V1 }, { .compatible = "arm,mmu-500", .data = (void *)ARM_SMMU_V2 }, + { .compatible = "qcom,smmu-v2", .data = (void *)ARM_SMMU_V2 }, { }, }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); @@ -2338,6 +2365,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) parse_driver_options(smmu); + if (of_device_is_compatible(dev->of_node, "qcom,smmu-v2")) + smmu->model = SMMU_MODEL_QCOM_V2; + if (smmu->version > ARM_SMMU_V1 && smmu->num_context_banks != smmu->num_context_irqs) { dev_err(dev,