@@ -113,6 +113,7 @@
#define F_MMU_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f)
#define MTK_PROTECT_PA_ALIGN 256
+#define MTK_IOMMU_BANK_SZ 0x1000
#define PERICFG_IOMMU_1 0x714
@@ -1112,7 +1113,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
struct component_match *match = NULL;
struct regmap *infracfg;
void *protect;
- int ret, banks_num;
+ int ret, banks_num, i = 0;
u32 val;
char *p;
struct mtk_iommu_bank_data *bank;
@@ -1153,27 +1154,36 @@ static int mtk_iommu_probe(struct platform_device *pdev)
data->enable_4GB = !!(val & F_DDR_4GB_SUPPORT_EN);
}
+ banks_num = data->plat_data->banks_num;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (resource_size(res) < banks_num * MTK_IOMMU_BANK_SZ) {
+ dev_err(dev, "banknr %d. res %pR is not enough.\n", banks_num, res);
+ return -EINVAL;
+ }
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
ioaddr = res->start;
- banks_num = data->plat_data->banks_num;
data->bank = devm_kmalloc(dev, banks_num * sizeof(*data->bank), GFP_KERNEL);
if (!data->bank)
return -ENOMEM;
- bank = &data->bank[0];
- bank->id = 0;
- bank->base = base;
- bank->m4u_dom = NULL;
- bank->irq = platform_get_irq(pdev, 0);
- if (bank->irq < 0)
- return bank->irq;
- bank->parent_dev = dev;
- bank->parent_data = data;
- spin_lock_init(&bank->tlb_lock);
+ do {
+ if (!data->plat_data->banks_enable[i])
+ continue;
+ bank = &data->bank[i];
+ bank->id = i;
+ bank->base = base + i * MTK_IOMMU_BANK_SZ;
+ bank->m4u_dom = NULL;
+
+ bank->irq = platform_get_irq(pdev, i);
+ if (bank->irq < 0)
+ return bank->irq;
+ bank->parent_dev = dev;
+ bank->parent_data = data;
+ spin_lock_init(&bank->tlb_lock);
+ } while (++i < banks_num);
if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_BCLK)) {
data->bclk = devm_clk_get(dev, "bclk");
@@ -1261,7 +1271,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
static int mtk_iommu_remove(struct platform_device *pdev)
{
struct mtk_iommu_data *data = platform_get_drvdata(pdev);
- struct mtk_iommu_bank_data *bank = &data->bank[0];
+ struct mtk_iommu_bank_data *bank;
+ int i;
iommu_device_sysfs_remove(&data->iommu);
iommu_device_unregister(&data->iommu);
@@ -1278,7 +1289,12 @@ static int mtk_iommu_remove(struct platform_device *pdev)
#endif
}
pm_runtime_disable(&pdev->dev);
- devm_free_irq(&pdev->dev, bank->irq, bank);
+ for (i = 0; i < data->plat_data->banks_num; i++) {
+ bank = &data->bank[i];
+ if (!bank->m4u_dom)
+ continue;
+ devm_free_irq(&pdev->dev, bank->irq, bank);
+ }
return 0;
}