All the devices which used iommu are connected to SMI_larb port,
so when different devices driver execute initialization, iommu
can check larb_id and port_id to distinguish them and then make
them match to iommu_group accordingly. We also add dom_cnt variable
to describe the number of mtk_iommu_domain.

Larb_id and port_id define can refer to "mtxxxx-larb-port.h(ex:
mt6779-larb-port.h)" file

Signed-off-by: Chao Hao <chao....@mediatek.com>
---
 drivers/iommu/mtk_iommu.c | 50 ++++++++++++++++++++++++++++++++-------
 drivers/iommu/mtk_iommu.h |  1 +
 2 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index bf781f4d7364..f2137033ec59 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -120,6 +120,7 @@ struct mtk_iommu_domain {
 struct mtk_iommu_pgtable {
        struct io_pgtable_cfg   cfg;
        struct io_pgtable_ops   *iop;
+       struct device           *init_dev;
        struct list_head        m4u_dom_v2;
 };
 
@@ -171,22 +172,35 @@ static struct mtk_iommu_data *mtk_iommu_get_m4u_data(void)
        return NULL;
 }
 
-static u32 get_domain_id(void)
+static u32 get_domain_id(struct mtk_iommu_data *data, u32 portid)
 {
-       /* only support one mtk_iommu_domain currently */
-       return 0;
+       u32 dom_id = 0;
+       int i;
+
+       /* only support one mtk_iommu_domain currently(dom_cnt = 1) */
+       for (i = 0; i < data->plat_data->dom_cnt; i++)
+               return i;
+
+       return dom_id;
 }
 
-static u32 mtk_iommu_get_domain_id(void)
+static u32 mtk_iommu_get_domain_id(struct device *dev)
 {
-       return get_domain_id();
+       struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+       struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
+       u32 portid = fwspec->ids[0];
+
+       return get_domain_id(data, portid);
 }
 
 static struct mtk_iommu_domain *get_mtk_domain(struct device *dev)
 {
        struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
        struct mtk_iommu_domain *dom;
-       u32 domain_id = mtk_iommu_get_domain_id();
+       u32 domain_id = mtk_iommu_get_domain_id(dev);
+
+       if (domain_id >= data->plat_data->dom_cnt)
+               return NULL;
 
        list_for_each_entry(dom, &data->pgtable->m4u_dom_v2, list) {
                if (dom->id == domain_id)
@@ -425,11 +439,18 @@ static struct iommu_domain 
*mtk_iommu_domain_alloc(unsigned type)
        struct mtk_iommu_pgtable *pgtable = mtk_iommu_get_pgtable();
        struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
        struct mtk_iommu_domain *dom;
+       struct device *dev;
 
        if (type != IOMMU_DOMAIN_DMA)
                return NULL;
 
-       if (!pgtable) {
+       if (pgtable) {
+               dev = pgtable->init_dev;
+               if (!data->m4u_group) {
+                       pr_err("%s, find m4u_group failed\n", __func__);
+                       return NULL;
+               }
+       } else {
                pr_err("%s, pgtable is not ready\n", __func__);
                return NULL;
        }
@@ -441,8 +462,11 @@ static struct iommu_domain 
*mtk_iommu_domain_alloc(unsigned type)
        if (iommu_get_dma_cookie(&dom->domain))
                goto  free_dom;
 
+       dom->id = mtk_iommu_get_domain_id(dev);
+       if (dom->id >= data->plat_data->dom_cnt)
+               goto  put_dma_cookie;
+
        dom->group = data->m4u_group;
-       dom->id = mtk_iommu_get_domain_id();
        /* Update our support page sizes bitmap */
        dom->domain.pgsize_bitmap = pgtable->cfg.pgsize_bitmap;
 
@@ -453,6 +477,8 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned 
type)
 
        return &dom->domain;
 
+put_dma_cookie:
+       iommu_put_dma_cookie(&dom->domain);
 free_dom:
        kfree(dom);
        return NULL;
@@ -613,6 +639,10 @@ static struct iommu_group *mtk_iommu_device_group(struct 
device *dev)
        } else {
                iommu_group_ref_get(data->m4u_group);
        }
+
+       /* save the latest init device */
+       pgtable->init_dev = dev;
+
        return data->m4u_group;
 }
 
@@ -922,12 +952,14 @@ static const struct mtk_iommu_plat_data mt2712_data = {
        .has_4gb_mode = true,
        .has_bclk     = true,
        .has_vld_pa_rng   = true,
+       .dom_cnt = 1,
        .larbid_remap[0] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
        .inv_sel_reg = REG_MMU_INV_SEL,
 };
 
 static const struct mtk_iommu_plat_data mt6779_data = {
        .m4u_plat = M4U_MT6779,
+       .dom_cnt = 1,
        .larbid_remap[0] = {0, 1, 2, 3, 5, 7, 10, 9},
        /* vp6a, vp6b, mdla/core2, mdla/edmc*/
        .larbid_remap[1] = {2, 0, 3, 1},
@@ -943,6 +975,7 @@ static const struct mtk_iommu_plat_data mt8173_data = {
        .has_4gb_mode = true,
        .has_bclk     = true,
        .reset_axi    = true,
+       .dom_cnt = 1,
        .larbid_remap[0] = {0, 1, 2, 3, 4, 5}, /* Linear mapping. */
        .inv_sel_reg = REG_MMU_INV_SEL,
 };
@@ -950,6 +983,7 @@ static const struct mtk_iommu_plat_data mt8173_data = {
 static const struct mtk_iommu_plat_data mt8183_data = {
        .m4u_plat     = M4U_MT8183,
        .reset_axi    = true,
+       .dom_cnt = 1,
        .larbid_remap[0] = {0, 4, 5, 6, 7, 2, 3, 1},
        .inv_sel_reg = REG_MMU_INV_SEL,
 };
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index a3c598f99ed5..3a1c79222d09 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -47,6 +47,7 @@ struct mtk_iommu_plat_data {
        bool                reset_axi;
        bool                has_wr_len;
        bool                has_misc_ctrl[2];
+       u32                                     dom_cnt;
        u32                 m4u1_mask;
        u32                 inv_sel_reg;
        unsigned char       larbid_remap[2][MTK_LARB_NR_MAX];
-- 
2.18.0
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to