linux/drivers/iommu/arm-smmu-qcom.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
   4 */
   5
   6#include <linux/of_device.h>
   7#include <linux/qcom_scm.h>
   8
   9#include "arm-smmu.h"
  10
  11struct qcom_smmu {
  12        struct arm_smmu_device smmu;
  13};
  14
  15static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
  16        { .compatible = "qcom,adreno" },
  17        { .compatible = "qcom,mdp4" },
  18        { .compatible = "qcom,mdss" },
  19        { .compatible = "qcom,sc7180-mdss" },
  20        { .compatible = "qcom,sc7180-mss-pil" },
  21        { .compatible = "qcom,sdm845-mdss" },
  22        { .compatible = "qcom,sdm845-mss-pil" },
  23        { }
  24};
  25
  26static int qcom_smmu_def_domain_type(struct device *dev)
  27{
  28        const struct of_device_id *match =
  29                of_match_device(qcom_smmu_client_of_match, dev);
  30
  31        return match ? IOMMU_DOMAIN_IDENTITY : 0;
  32}
  33
  34static int qcom_sdm845_smmu500_reset(struct arm_smmu_device *smmu)
  35{
  36        int ret;
  37
  38        /*
  39         * To address performance degradation in non-real time clients,
  40         * such as USB and UFS, turn off wait-for-safe on sdm845 based boards,
  41         * such as MTP and db845, whose firmwares implement secure monitor
  42         * call handlers to turn on/off the wait-for-safe logic.
  43         */
  44        ret = qcom_scm_qsmmu500_wait_safe_toggle(0);
  45        if (ret)
  46                dev_warn(smmu->dev, "Failed to turn off SAFE logic\n");
  47
  48        return ret;
  49}
  50
  51static int qcom_smmu500_reset(struct arm_smmu_device *smmu)
  52{
  53        const struct device_node *np = smmu->dev->of_node;
  54
  55        arm_mmu500_reset(smmu);
  56
  57        if (of_device_is_compatible(np, "qcom,sdm845-smmu-500"))
  58                return qcom_sdm845_smmu500_reset(smmu);
  59
  60        return 0;
  61}
  62
  63static const struct arm_smmu_impl qcom_smmu_impl = {
  64        .def_domain_type = qcom_smmu_def_domain_type,
  65        .reset = qcom_smmu500_reset,
  66};
  67
  68struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu)
  69{
  70        struct qcom_smmu *qsmmu;
  71
  72        qsmmu = devm_kzalloc(smmu->dev, sizeof(*qsmmu), GFP_KERNEL);
  73        if (!qsmmu)
  74                return ERR_PTR(-ENOMEM);
  75
  76        qsmmu->smmu = *smmu;
  77
  78        qsmmu->smmu.impl = &qcom_smmu_impl;
  79        devm_kfree(smmu->dev, smmu);
  80
  81        return &qsmmu->smmu;
  82}
  83