Skip to content

Commit

Permalink
Merge tag 'arm-smmu-updates' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/will/linux into arm/smmu

Arm SMMU updates for 6.3

- Device-tree binding updates:
  * Cater for three power domains on SM6375
  * Document existing compatible strings for Qualcomm SoCs
  * Tighten up clocks description for platform-specific compatible strings

- Enable Qualcomm workarounds for some additional platforms that need them
  • Loading branch information
joergroedel committed Jan 25, 2023
2 parents b7bfaa7 + 8a24401 commit 9e61321
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 26 deletions.
66 changes: 57 additions & 9 deletions Documentation/devicetree/bindings/iommu/arm,smmu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,17 @@ properties:
- enum:
- qcom,qcm2290-smmu-500
- qcom,qdu1000-smmu-500
- qcom,sa8775p-smmu-500
- qcom,sc7180-smmu-500
- qcom,sc7280-smmu-500
- qcom,sc8180x-smmu-500
- qcom,sc8280xp-smmu-500
- qcom,sdm670-smmu-500
- qcom,sdm845-smmu-500
- qcom,sdx55-smmu-500
- qcom,sdx65-smmu-500
- qcom,sm6115-smmu-500
- qcom,sm6125-smmu-500
- qcom,sm6350-smmu-500
- qcom,sm6375-smmu-500
- qcom,sm8150-smmu-500
Expand All @@ -52,14 +56,6 @@ properties:
- const: qcom,smmu-500
- const: arm,mmu-500

- description: Qcom SoCs implementing "arm,mmu-500" (non-qcom implementation)
deprecated: true
items:
- enum:
- qcom,sdx55-smmu-500
- qcom,sdx65-smmu-500
- const: arm,mmu-500

- description: Qcom SoCs implementing "arm,mmu-500" (legacy binding)
deprecated: true
items:
Expand All @@ -84,6 +80,7 @@ properties:
items:
- enum:
- qcom,sc7280-smmu-500
- qcom,sm8150-smmu-500
- qcom,sm8250-smmu-500
- const: qcom,adreno-smmu
- const: arm,mmu-500
Expand Down Expand Up @@ -201,7 +198,8 @@ properties:
maxItems: 7

power-domains:
maxItems: 1
minItems: 1
maxItems: 3

nvidia,memory-controller:
description: |
Expand Down Expand Up @@ -366,6 +364,56 @@ allOf:
- description: interface clock required to access smmu's registers
through the TCU's programming interface.

# Disallow clocks for all other platforms with specific compatibles
- if:
properties:
compatible:
contains:
enum:
- cavium,smmu-v2
- marvell,ap806-smmu-500
- nvidia,smmu-500
- qcom,qcm2290-smmu-500
- qcom,qdu1000-smmu-500
- qcom,sa8775p-smmu-500
- qcom,sc7180-smmu-500
- qcom,sc8180x-smmu-500
- qcom,sc8280xp-smmu-500
- qcom,sdm670-smmu-500
- qcom,sdm845-smmu-500
- qcom,sdx55-smmu-500
- qcom,sdx65-smmu-500
- qcom,sm6115-smmu-500
- qcom,sm6125-smmu-500
- qcom,sm6350-smmu-500
- qcom,sm6375-smmu-500
- qcom,sm8350-smmu-500
- qcom,sm8450-smmu-500
then:
properties:
clock-names: false
clocks: false

- if:
properties:
compatible:
contains:
const: qcom,sm6375-smmu-500
then:
properties:
power-domains:
items:
- description: SNoC MMU TBU RT GDSC
- description: SNoC MMU TBU NRT GDSC
- description: SNoC TURING MMU TBU0 GDSC

required:
- power-domains
else:
properties:
power-domains:
maxItems: 1

examples:
- |+
/* SMMU with stream matching or stream indexing */
Expand Down
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/iommu/qcom,iommu.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ to non-secure vs secure interrupt line.
- compatible : Should be one of:

"qcom,msm8916-iommu"
"qcom,msm8953-iommu"

Followed by "qcom,msm-iommu-v1".

Expand Down
4 changes: 3 additions & 1 deletion drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -3858,7 +3858,9 @@ static int arm_smmu_device_remove(struct platform_device *pdev)

static void arm_smmu_device_shutdown(struct platform_device *pdev)
{
arm_smmu_device_remove(pdev);
struct arm_smmu_device *smmu = platform_get_drvdata(pdev);

arm_smmu_device_disable(smmu);
}

static const struct of_device_id arm_smmu_of_match[] = {
Expand Down
2 changes: 2 additions & 0 deletions drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
{ .compatible = "qcom,sc7280-mdss" },
{ .compatible = "qcom,sc7280-mss-pil" },
{ .compatible = "qcom,sc8180x-mdss" },
{ .compatible = "qcom,sc8280xp-mdss" },
{ .compatible = "qcom,sm8150-mdss" },
{ .compatible = "qcom,sm8250-mdss" },
{ .compatible = "qcom,sdm845-mdss" },
{ .compatible = "qcom,sdm845-mss-pil" },
Expand Down
32 changes: 22 additions & 10 deletions drivers/iommu/arm/arm-smmu/arm-smmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1316,8 +1316,14 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)

switch (cap) {
case IOMMU_CAP_CACHE_COHERENCY:
/* Assume that a coherent TCU implies coherent TBUs */
return cfg->smmu->features & ARM_SMMU_FEAT_COHERENT_WALK;
/*
* It's overwhelmingly the case in practice that when the pagetable
* walk interface is connected to a coherent interconnect, all the
* translation interfaces are too. Furthermore if the device is
* natively coherent, then its translation interface must also be.
*/
return cfg->smmu->features & ARM_SMMU_FEAT_COHERENT_WALK ||
device_get_dma_attr(dev) == DEV_DMA_COHERENT;
case IOMMU_CAP_NOEXEC:
return true;
default:
Expand Down Expand Up @@ -2185,19 +2191,16 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
return 0;
}

static int arm_smmu_device_remove(struct platform_device *pdev)
static void arm_smmu_device_shutdown(struct platform_device *pdev)
{
struct arm_smmu_device *smmu = platform_get_drvdata(pdev);

if (!smmu)
return -ENODEV;
return;

if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS))
dev_notice(&pdev->dev, "disabling translation\n");

iommu_device_unregister(&smmu->iommu);
iommu_device_sysfs_remove(&smmu->iommu);

arm_smmu_rpm_get(smmu);
/* Turn the thing off */
arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sCR0, ARM_SMMU_sCR0_CLIENTPD);
Expand All @@ -2209,12 +2212,21 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
clk_bulk_disable(smmu->num_clks, smmu->clks);

clk_bulk_unprepare(smmu->num_clks, smmu->clks);
return 0;
}

static void arm_smmu_device_shutdown(struct platform_device *pdev)
static int arm_smmu_device_remove(struct platform_device *pdev)
{
arm_smmu_device_remove(pdev);
struct arm_smmu_device *smmu = platform_get_drvdata(pdev);

if (!smmu)
return -ENODEV;

iommu_device_unregister(&smmu->iommu);
iommu_device_sysfs_remove(&smmu->iommu);

arm_smmu_device_shutdown(pdev);

return 0;
}

static int __maybe_unused arm_smmu_runtime_resume(struct device *dev)
Expand Down
8 changes: 5 additions & 3 deletions drivers/iommu/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -3185,14 +3185,16 @@ EXPORT_SYMBOL_GPL(iommu_group_claim_dma_owner);
*/
int iommu_device_claim_dma_owner(struct device *dev, void *owner)
{
struct iommu_group *group = iommu_group_get(dev);
struct iommu_group *group;
int ret = 0;

if (!group)
return -ENODEV;
if (WARN_ON(!owner))
return -EINVAL;

group = iommu_group_get(dev);
if (!group)
return -ENODEV;

mutex_lock(&group->mutex);
if (group->owner_cnt) {
if (group->owner != owner) {
Expand Down
4 changes: 2 additions & 2 deletions drivers/iommu/iova.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ static int __alloc_and_insert_iova_range(struct iova_domain *iovad,

curr = __get_cached_rbnode(iovad, limit_pfn);
curr_iova = to_iova(curr);
retry_pfn = curr_iova->pfn_hi + 1;
retry_pfn = curr_iova->pfn_hi;

retry:
do {
Expand All @@ -211,7 +211,7 @@ static int __alloc_and_insert_iova_range(struct iova_domain *iovad,
if (high_pfn < size || new_pfn < low_pfn) {
if (low_pfn == iovad->start_pfn && retry_pfn < limit_pfn) {
high_pfn = limit_pfn;
low_pfn = retry_pfn;
low_pfn = retry_pfn + 1;
curr = iova_find_limit(iovad, limit_pfn);
curr_iova = to_iova(curr);
goto retry;
Expand Down
4 changes: 3 additions & 1 deletion drivers/iommu/mtk_iommu_v1.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ static int mtk_iommu_v1_probe(struct platform_device *pdev)
ret = iommu_device_sysfs_add(&data->iommu, &pdev->dev, NULL,
dev_name(&pdev->dev));
if (ret)
return ret;
goto out_clk_unprepare;

ret = iommu_device_register(&data->iommu, &mtk_iommu_v1_ops, dev);
if (ret)
Expand All @@ -698,6 +698,8 @@ static int mtk_iommu_v1_probe(struct platform_device *pdev)
iommu_device_unregister(&data->iommu);
out_sysfs_remove:
iommu_device_sysfs_remove(&data->iommu);
out_clk_unprepare:
clk_disable_unprepare(data->bclk);
return ret;
}

Expand Down

0 comments on commit 9e61321

Please sign in to comment.