Skip to content

Commit e30c960

Browse files
AngeloGioacchino Del Regnowilldeacon
authored andcommitted
iommu/qcom: Add support for QSMMUv2 and QSMMU-500 secured contexts
On some SoCs like MSM8956, MSM8976 and others, secure contexts are also secured: these get programmed by the bootloader or TZ (as usual) but their "interesting" registers are locked out by the hypervisor, disallowing direct register writes from Linux and, in many cases, completely disallowing the reprogramming of TTBR, TCR, MAIR and other registers including, but not limited to, resetting contexts. This is referred downstream as a "v2" IOMMU but this is effectively a "v2 firmware configuration" instead. Luckily, the described behavior of version 2 is effective only on secure contexts and not on non-secure ones: add support for that, finally getting a completely working IOMMU on at least MSM8956/76. Signed-off-by: Marijn Suijten <[email protected]> [Marijn: Rebased over next-20221111] Signed-off-by: AngeloGioacchino Del Regno <[email protected]> Reviewed-by: Dmitry Baryshkov <[email protected]> Reviewed-by: Konrad Dybcio <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent ec56016 commit e30c960

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

drivers/iommu/arm/arm-smmu/qcom_iommu.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ struct qcom_iommu_ctx {
5959
struct device *dev;
6060
void __iomem *base;
6161
bool secure_init;
62+
bool secured_ctx;
6263
u8 asid; /* asid and ctx bank # are 1:1 */
6364
struct iommu_domain *domain;
6465
};
@@ -273,6 +274,12 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
273274
ctx->secure_init = true;
274275
}
275276

277+
/* Secured QSMMU-500/QSMMU-v2 contexts cannot be programmed */
278+
if (ctx->secured_ctx) {
279+
ctx->domain = domain;
280+
continue;
281+
}
282+
276283
/* Disable context bank before programming */
277284
iommu_writel(ctx, ARM_SMMU_CB_SCTLR, 0);
278285

@@ -667,10 +674,14 @@ static int qcom_iommu_ctx_probe(struct platform_device *pdev)
667674
if (irq < 0)
668675
return irq;
669676

677+
if (of_device_is_compatible(dev->of_node, "qcom,msm-iommu-v2-sec"))
678+
ctx->secured_ctx = true;
679+
670680
/* clear IRQs before registering fault handler, just in case the
671681
* boot-loader left us a surprise:
672682
*/
673-
iommu_writel(ctx, ARM_SMMU_CB_FSR, iommu_readl(ctx, ARM_SMMU_CB_FSR));
683+
if (!ctx->secured_ctx)
684+
iommu_writel(ctx, ARM_SMMU_CB_FSR, iommu_readl(ctx, ARM_SMMU_CB_FSR));
674685

675686
ret = devm_request_irq(dev, irq,
676687
qcom_iommu_fault,
@@ -710,6 +721,8 @@ static void qcom_iommu_ctx_remove(struct platform_device *pdev)
710721
static const struct of_device_id ctx_of_match[] = {
711722
{ .compatible = "qcom,msm-iommu-v1-ns" },
712723
{ .compatible = "qcom,msm-iommu-v1-sec" },
724+
{ .compatible = "qcom,msm-iommu-v2-ns" },
725+
{ .compatible = "qcom,msm-iommu-v2-sec" },
713726
{ /* sentinel */ }
714727
};
715728

@@ -727,7 +740,8 @@ static bool qcom_iommu_has_secure_context(struct qcom_iommu_dev *qcom_iommu)
727740
struct device_node *child;
728741

729742
for_each_child_of_node(qcom_iommu->dev->of_node, child) {
730-
if (of_device_is_compatible(child, "qcom,msm-iommu-v1-sec")) {
743+
if (of_device_is_compatible(child, "qcom,msm-iommu-v1-sec") ||
744+
of_device_is_compatible(child, "qcom,msm-iommu-v2-sec")) {
731745
of_node_put(child);
732746
return true;
733747
}
@@ -871,6 +885,7 @@ static const struct dev_pm_ops qcom_iommu_pm_ops = {
871885

872886
static const struct of_device_id qcom_iommu_of_match[] = {
873887
{ .compatible = "qcom,msm-iommu-v1" },
888+
{ .compatible = "qcom,msm-iommu-v2" },
874889
{ /* sentinel */ }
875890
};
876891

0 commit comments

Comments
 (0)