|
@@ -37,6 +37,7 @@
|
|
|
#include <linux/iopoll.h>
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/of.h>
|
|
|
+#include <linux/of_address.h>
|
|
|
#include <linux/pci.h>
|
|
|
#include <linux/platform_device.h>
|
|
|
#include <linux/slab.h>
|
|
@@ -1532,6 +1533,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
|
|
|
unsigned long size;
|
|
|
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
|
|
|
u32 id;
|
|
|
+ bool cttw_dt, cttw_reg;
|
|
|
|
|
|
dev_notice(smmu->dev, "probing hardware configuration...\n");
|
|
|
dev_notice(smmu->dev, "SMMUv%d with:\n", smmu->version);
|
|
@@ -1571,10 +1573,22 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
|
|
|
dev_notice(smmu->dev, "\taddress translation ops\n");
|
|
|
}
|
|
|
|
|
|
- if (id & ID0_CTTW) {
|
|
|
+ /*
|
|
|
+ * In order for DMA API calls to work properly, we must defer to what
|
|
|
+ * the DT says about coherency, regardless of what the hardware claims.
|
|
|
+ * Fortunately, this also opens up a workaround for systems where the
|
|
|
+ * ID register value has ended up configured incorrectly.
|
|
|
+ */
|
|
|
+ cttw_dt = of_dma_is_coherent(smmu->dev->of_node);
|
|
|
+ cttw_reg = !!(id & ID0_CTTW);
|
|
|
+ if (cttw_dt)
|
|
|
smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
|
|
|
- dev_notice(smmu->dev, "\tcoherent table walk\n");
|
|
|
- }
|
|
|
+ if (cttw_dt || cttw_reg)
|
|
|
+ dev_notice(smmu->dev, "\t%scoherent table walk\n",
|
|
|
+ cttw_dt ? "" : "non-");
|
|
|
+ if (cttw_dt != cttw_reg)
|
|
|
+ dev_notice(smmu->dev,
|
|
|
+ "\t(IDR0.CTTW overridden by dma-coherent property)\n");
|
|
|
|
|
|
if (id & ID0_SMS) {
|
|
|
u32 smr, sid, mask;
|