|
@@ -1675,7 +1675,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
|
|
unsigned long size;
|
|
unsigned long size;
|
|
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
|
|
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
|
|
u32 id;
|
|
u32 id;
|
|
- bool cttw_dt, cttw_reg;
|
|
|
|
|
|
+ bool cttw_reg, cttw_fw = smmu->features & ARM_SMMU_FEAT_COHERENT_WALK;
|
|
int i;
|
|
int i;
|
|
|
|
|
|
dev_notice(smmu->dev, "probing hardware configuration...\n");
|
|
dev_notice(smmu->dev, "probing hardware configuration...\n");
|
|
@@ -1720,20 +1720,17 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
|
|
|
|
|
|
/*
|
|
/*
|
|
* In order for DMA API calls to work properly, we must defer to what
|
|
* 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.
|
|
|
|
|
|
+ * the FW says about coherency, regardless of what the hardware claims.
|
|
* Fortunately, this also opens up a workaround for systems where the
|
|
* Fortunately, this also opens up a workaround for systems where the
|
|
* ID register value has ended up configured incorrectly.
|
|
* ID register value has ended up configured incorrectly.
|
|
*/
|
|
*/
|
|
- cttw_dt = of_dma_is_coherent(smmu->dev->of_node);
|
|
|
|
cttw_reg = !!(id & ID0_CTTW);
|
|
cttw_reg = !!(id & ID0_CTTW);
|
|
- if (cttw_dt)
|
|
|
|
- smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
|
|
|
|
- if (cttw_dt || cttw_reg)
|
|
|
|
|
|
+ if (cttw_fw || cttw_reg)
|
|
dev_notice(smmu->dev, "\t%scoherent table walk\n",
|
|
dev_notice(smmu->dev, "\t%scoherent table walk\n",
|
|
- cttw_dt ? "" : "non-");
|
|
|
|
- if (cttw_dt != cttw_reg)
|
|
|
|
|
|
+ cttw_fw ? "" : "non-");
|
|
|
|
+ if (cttw_fw != cttw_reg)
|
|
dev_notice(smmu->dev,
|
|
dev_notice(smmu->dev,
|
|
- "\t(IDR0.CTTW overridden by dma-coherent property)\n");
|
|
|
|
|
|
+ "\t(IDR0.CTTW overridden by FW configuration)\n");
|
|
|
|
|
|
/* Max. number of entries we have for stream matching/indexing */
|
|
/* Max. number of entries we have for stream matching/indexing */
|
|
size = 1 << ((id >> ID0_NUMSIDB_SHIFT) & ID0_NUMSIDB_MASK);
|
|
size = 1 << ((id >> ID0_NUMSIDB_SHIFT) & ID0_NUMSIDB_MASK);
|
|
@@ -1914,15 +1911,25 @@ static const struct of_device_id arm_smmu_of_match[] = {
|
|
};
|
|
};
|
|
MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
|
|
MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
|
|
|
|
|
|
-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)
|
|
{
|
|
{
|
|
const struct arm_smmu_match_data *data;
|
|
const struct arm_smmu_match_data *data;
|
|
- struct resource *res;
|
|
|
|
- struct arm_smmu_device *smmu;
|
|
|
|
struct device *dev = &pdev->dev;
|
|
struct device *dev = &pdev->dev;
|
|
- int num_irqs, i, err;
|
|
|
|
bool legacy_binding;
|
|
bool legacy_binding;
|
|
|
|
|
|
|
|
+ if (of_property_read_u32(dev->of_node, "#global-interrupts",
|
|
|
|
+ &smmu->num_global_irqs)) {
|
|
|
|
+ dev_err(dev, "missing #global-interrupts property\n");
|
|
|
|
+ return -ENODEV;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ data = of_device_get_match_data(dev);
|
|
|
|
+ smmu->version = data->version;
|
|
|
|
+ smmu->model = data->model;
|
|
|
|
+
|
|
|
|
+ parse_driver_options(smmu);
|
|
|
|
+
|
|
legacy_binding = of_find_property(dev->of_node, "mmu-masters", NULL);
|
|
legacy_binding = of_find_property(dev->of_node, "mmu-masters", NULL);
|
|
if (legacy_binding && !using_generic_binding) {
|
|
if (legacy_binding && !using_generic_binding) {
|
|
if (!using_legacy_binding)
|
|
if (!using_legacy_binding)
|
|
@@ -1935,6 +1942,19 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (of_dma_is_coherent(dev->of_node))
|
|
|
|
+ smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int arm_smmu_device_probe(struct platform_device *pdev)
|
|
|
|
+{
|
|
|
|
+ struct resource *res;
|
|
|
|
+ struct arm_smmu_device *smmu;
|
|
|
|
+ struct device *dev = &pdev->dev;
|
|
|
|
+ int num_irqs, i, err;
|
|
|
|
+
|
|
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
|
|
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
|
|
if (!smmu) {
|
|
if (!smmu) {
|
|
dev_err(dev, "failed to allocate arm_smmu_device\n");
|
|
dev_err(dev, "failed to allocate arm_smmu_device\n");
|
|
@@ -1942,9 +1962,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
|
|
}
|
|
}
|
|
smmu->dev = dev;
|
|
smmu->dev = dev;
|
|
|
|
|
|
- data = of_device_get_match_data(dev);
|
|
|
|
- smmu->version = data->version;
|
|
|
|
- smmu->model = data->model;
|
|
|
|
|
|
+ err = arm_smmu_device_dt_probe(pdev, smmu);
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
smmu->base = devm_ioremap_resource(dev, res);
|
|
smmu->base = devm_ioremap_resource(dev, res);
|
|
@@ -1952,12 +1972,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
|
|
return PTR_ERR(smmu->base);
|
|
return PTR_ERR(smmu->base);
|
|
smmu->size = resource_size(res);
|
|
smmu->size = resource_size(res);
|
|
|
|
|
|
- if (of_property_read_u32(dev->of_node, "#global-interrupts",
|
|
|
|
- &smmu->num_global_irqs)) {
|
|
|
|
- dev_err(dev, "missing #global-interrupts property\n");
|
|
|
|
- return -ENODEV;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
num_irqs = 0;
|
|
num_irqs = 0;
|
|
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, num_irqs))) {
|
|
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, num_irqs))) {
|
|
num_irqs++;
|
|
num_irqs++;
|
|
@@ -1992,8 +2006,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
- parse_driver_options(smmu);
|
|
|
|
-
|
|
|
|
if (smmu->version == ARM_SMMU_V2 &&
|
|
if (smmu->version == ARM_SMMU_V2 &&
|
|
smmu->num_context_banks != smmu->num_context_irqs) {
|
|
smmu->num_context_banks != smmu->num_context_irqs) {
|
|
dev_err(dev,
|
|
dev_err(dev,
|
|
@@ -2055,7 +2067,7 @@ static struct platform_driver arm_smmu_driver = {
|
|
.name = "arm-smmu",
|
|
.name = "arm-smmu",
|
|
.of_match_table = of_match_ptr(arm_smmu_of_match),
|
|
.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,
|
|
.remove = arm_smmu_device_remove,
|
|
};
|
|
};
|
|
|
|
|