|
@@ -2381,10 +2381,10 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
|
|
|
+static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
|
|
|
{
|
|
|
u32 reg;
|
|
|
- bool coherent;
|
|
|
+ bool coherent = smmu->features & ARM_SMMU_FEAT_COHERENCY;
|
|
|
|
|
|
/* IDR0 */
|
|
|
reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
|
|
@@ -2436,13 +2436,9 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
|
|
|
smmu->features |= ARM_SMMU_FEAT_HYP;
|
|
|
|
|
|
/*
|
|
|
- * The dma-coherent property is used in preference to the ID
|
|
|
+ * The coherency feature as set by FW is used in preference to the ID
|
|
|
* register, but warn on mismatch.
|
|
|
*/
|
|
|
- coherent = of_dma_is_coherent(smmu->dev->of_node);
|
|
|
- if (coherent)
|
|
|
- smmu->features |= ARM_SMMU_FEAT_COHERENCY;
|
|
|
-
|
|
|
if (!!(reg & IDR0_COHACC) != coherent)
|
|
|
dev_warn(smmu->dev, "IDR0.COHACC overridden by dma-coherent property (%s)\n",
|
|
|
coherent ? "true" : "false");
|
|
@@ -2563,21 +2559,35 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int arm_smmu_device_dt_probe(struct platform_device *pdev)
|
|
|
+static int arm_smmu_device_dt_probe(struct platform_device *pdev,
|
|
|
+ struct arm_smmu_device *smmu)
|
|
|
{
|
|
|
- int irq, ret;
|
|
|
- struct resource *res;
|
|
|
- struct arm_smmu_device *smmu;
|
|
|
struct device *dev = &pdev->dev;
|
|
|
- bool bypass = true;
|
|
|
u32 cells;
|
|
|
+ int ret = -EINVAL;
|
|
|
|
|
|
if (of_property_read_u32(dev->of_node, "#iommu-cells", &cells))
|
|
|
dev_err(dev, "missing #iommu-cells property\n");
|
|
|
else if (cells != 1)
|
|
|
dev_err(dev, "invalid #iommu-cells value (%d)\n", cells);
|
|
|
else
|
|
|
- bypass = false;
|
|
|
+ ret = 0;
|
|
|
+
|
|
|
+ parse_driver_options(smmu);
|
|
|
+
|
|
|
+ if (of_dma_is_coherent(dev->of_node))
|
|
|
+ smmu->features |= ARM_SMMU_FEAT_COHERENCY;
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int arm_smmu_device_probe(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ int irq, ret;
|
|
|
+ struct resource *res;
|
|
|
+ struct arm_smmu_device *smmu;
|
|
|
+ struct device *dev = &pdev->dev;
|
|
|
+ bool bypass;
|
|
|
|
|
|
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
|
|
|
if (!smmu) {
|
|
@@ -2614,10 +2624,11 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
|
|
|
if (irq > 0)
|
|
|
smmu->gerr_irq = irq;
|
|
|
|
|
|
- parse_driver_options(smmu);
|
|
|
+ /* Set bypass mode according to firmware probing result */
|
|
|
+ bypass = !!arm_smmu_device_dt_probe(pdev, smmu);
|
|
|
|
|
|
/* Probe the h/w */
|
|
|
- ret = arm_smmu_device_probe(smmu);
|
|
|
+ ret = arm_smmu_device_hw_probe(smmu);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -2679,7 +2690,7 @@ static struct platform_driver arm_smmu_driver = {
|
|
|
.name = "arm-smmu-v3",
|
|
|
.of_match_table = of_match_ptr(arm_smmu_of_match),
|
|
|
},
|
|
|
- .probe = arm_smmu_device_dt_probe,
|
|
|
+ .probe = arm_smmu_device_probe,
|
|
|
.remove = arm_smmu_device_remove,
|
|
|
};
|
|
|
|