2021-08-13 08:33:59

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v2 00/29] MT8195 IOMMU SUPPORT

This patchset add mt8195 iommu support.

mt8195 have 3 IOMMU HWs. 2 IOMMU HW is for multimedia, and 1 IOMMU HW is
for infra-master, like PCIe/USB.

About the 2 MM IOMMU HW, something like this:

IOMMU(VDO) IOMMU(VPP)
| |
SMI_COMMON(VDO) SMI_COMMON(VPP)
--------------- ----------------
| | ... | | ...
larb0 larb2 ... larb1 larb3 ...

these two MM IOMMU HW share a pgtable.

About the INFRA IOMMU, it don't have larbs, the master connects the iommu
directly. It use a independent pgtable.

Also, mt8195 IOMMU bank supports.Normally the IOMMU register size only
is 0x1000. In this IOMMU HW, the register size is 5 * 0x1000. each 0x1000
is a bank. the banks' register look like this:
----------------------------------------
|bank0 | bank1 | bank2 | bank3 | bank4|
----------------------------------------
|global |
|control| null
|regs |
-----------------------------------------
|bank |bank |bank |bank |bank |
|regs |regs |regs |regs |regs |
| | | | | |
-----------------------------------------
All the banks share some global control registers, and each bank have its
special bank registers, like pgtable base register, tlb operation registers,
the fault status registers.

In mt8195, we enable this bank feature for infra iommu, We put PCIe in bank0
and USB in bank4. they have independent pgtable.

patch[1..19]: support mt8195 iommu.
patch[20..29]: support bank feature.

TODO: there is another APU_IOMMU in mt8195, this should depend on APU patches.
thus, we need add that feature after that.

Change note:
v2: 1) Base on v5.14-rc1.
2) Fix build fail for arm32.
3) Fix dt-binding issue from Rob.
4) Fix the bank issue when tlb flush. v1 always use bank->base.
5) Adjust devlink with smi-common since the node may be smi-sub-common.
6) other changes: like reword some commit message(removing many
"This patch..."); seperate serveral patches.

v1: https://lore.kernel.org/linux-mediatek/[email protected]/
Base on v5.13-rc1.

Yong Wu (29):
dt-bindings: mediatek: mt8195: Add binding for MM IOMMU
dt-bindings: mediatek: mt8195: Add binding for infra IOMMU
iommu/mediatek: Fix 2 HW sharing pgtable issue
iommu/mediatek: Adapt sharing and non-sharing pgtable case
iommu/mediatek: Add 12G~16G support for multi domains
iommu/mediatek: Add a flag DCM_DISABLE
iommu/mediatek: Add a flag NON_STD_AXI
iommu/mediatek: Remove for_each_m4u in tlb_sync_all
iommu/mediatek: Add tlb_lock in tlb_flush_all
iommu/mediatek: Remove the granule in the tlb flush
iommu/mediatek: Always pm_runtime_get while tlb flush
iommu/mediatek: Always enable output PA over 32bits in isr
iommu/mediatek: Add SUB_COMMON_3BITS flag
iommu/mediatek: Add IOMMU_TYPE flag
iommu/mediatek: Contain MM IOMMU flow with the MM TYPE
iommu/mediatek: Adjust device link when it is sub-common
iommu/mediatek: Add infra iommu support
iommu/mediatek: Add PCIe support
iommu/mediatek: Add mt8195 support
iommu/mediatek: Only adjust code about register base
iommu/mediatek: Just move code position in hw_init
iommu/mediatek: Add mtk_iommu_bank_data structure
iommu/mediatek: Initialise bank HW for each a bank
iommu/mediatek: Add bank_nr and bank_enable
iommu/mediatek: Change the domid to iova_region_id
iommu/mediatek: Get the proper bankid for multi banks
iommu/mediatek: Initialise/Remove for multi bank dev
iommu/mediatek: Backup/restore regsiters for multi banks
iommu/mediatek: mt8195: Enable multi banks for infra iommu

.../bindings/iommu/mediatek,iommu.yaml | 20 +-
drivers/iommu/mtk_iommu.c | 792 ++++++++++++------
drivers/iommu/mtk_iommu.h | 55 +-
.../dt-bindings/memory/mt8195-memory-port.h | 408 +++++++++
include/dt-bindings/memory/mtk-memory-port.h | 2 +
5 files changed, 1010 insertions(+), 267 deletions(-)
create mode 100644 include/dt-bindings/memory/mt8195-memory-port.h

--
2.18.0



2021-08-13 08:34:40

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v2 07/29] iommu/mediatek: Add a flag NON_STD_AXI

Add a new flag NON_STD_AXI, All the previous SoC support this flag.
Prepare for adding infra and apu iommu which don't support this.

Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/mtk_iommu.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index bd50f3020bc1..175065b76509 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -123,6 +123,7 @@
#define IOVA_34_EN BIT(8)
#define SHARE_PGTABLE BIT(9) /* 2 HW share pgtable */
#define DCM_DISABLE BIT(10)
+#define NOT_STD_AXI_MODE BIT(11)

#define MTK_IOMMU_HAS_FLAG(pdata, _x) \
((((pdata)->flags) & (_x)) == (_x))
@@ -753,7 +754,8 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
regval = 0;
} else {
regval = readl_relaxed(data->base + REG_MMU_MISC_CTRL);
- regval &= ~F_MMU_STANDARD_AXI_MODE_MASK;
+ if (MTK_IOMMU_HAS_FLAG(data->plat_data, NOT_STD_AXI_MODE))
+ regval &= ~F_MMU_STANDARD_AXI_MODE_MASK;
if (MTK_IOMMU_HAS_FLAG(data->plat_data, OUT_ORDER_WR_EN))
regval &= ~F_MMU_IN_ORDER_WR_EN_MASK;
}
@@ -1016,7 +1018,8 @@ static const struct dev_pm_ops mtk_iommu_pm_ops = {

static const struct mtk_iommu_plat_data mt2712_data = {
.m4u_plat = M4U_MT2712,
- .flags = HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG | SHARE_PGTABLE,
+ .flags = HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG | SHARE_PGTABLE |
+ NOT_STD_AXI_MODE,
.hw_list = &m4ulist,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
.iova_region = single_domain,
@@ -1026,7 +1029,8 @@ static const struct mtk_iommu_plat_data mt2712_data = {

static const struct mtk_iommu_plat_data mt6779_data = {
.m4u_plat = M4U_MT6779,
- .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN,
+ .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN |
+ NOT_STD_AXI_MODE,
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1035,7 +1039,7 @@ static const struct mtk_iommu_plat_data mt6779_data = {

static const struct mtk_iommu_plat_data mt8167_data = {
.m4u_plat = M4U_MT8167,
- .flags = RESET_AXI | HAS_LEGACY_IVRP_PADDR,
+ .flags = RESET_AXI | HAS_LEGACY_IVRP_PADDR | NOT_STD_AXI_MODE,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1045,7 +1049,7 @@ static const struct mtk_iommu_plat_data mt8167_data = {
static const struct mtk_iommu_plat_data mt8173_data = {
.m4u_plat = M4U_MT8173,
.flags = HAS_4GB_MODE | HAS_BCLK | RESET_AXI |
- HAS_LEGACY_IVRP_PADDR,
+ HAS_LEGACY_IVRP_PADDR | NOT_STD_AXI_MODE,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1064,7 +1068,7 @@ static const struct mtk_iommu_plat_data mt8183_data = {
static const struct mtk_iommu_plat_data mt8192_data = {
.m4u_plat = M4U_MT8192,
.flags = HAS_BCLK | HAS_SUB_COMM | OUT_ORDER_WR_EN |
- WR_THROT_EN | IOVA_34_EN,
+ WR_THROT_EN | IOVA_34_EN | NOT_STD_AXI_MODE,
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
.iova_region = mt8192_multi_dom,
.iova_region_nr = ARRAY_SIZE(mt8192_multi_dom),
--
2.18.0

2021-08-13 09:24:34

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v2 13/29] iommu/mediatek: Add SUB_COMMON_3BITS flag

In prevous SoC, the sub common id occupy 2 bits. the mt8195's sub common
id has 3bits. Add a new flag for this. and rename the prevous flag to
_2BITS. For readable, I put these two flags together, then move the
other flags. no functional change.

Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/mtk_iommu.c | 26 ++++++++++++++++----------
drivers/iommu/mtk_iommu.h | 2 +-
2 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index a831e56a90eb..f75fbfd951e0 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -106,6 +106,8 @@
#define REG_MMU1_INT_ID 0x154
#define F_MMU_INT_ID_COMM_ID(a) (((a) >> 9) & 0x7)
#define F_MMU_INT_ID_SUB_COMM_ID(a) (((a) >> 7) & 0x3)
+#define F_MMU_INT_ID_COMM_ID_EXT(a) (((a) >> 10) & 0x7)
+#define F_MMU_INT_ID_SUB_COMM_ID_EXT(a) (((a) >> 7) & 0x7)
#define F_MMU_INT_ID_LARB_ID(a) (((a) >> 7) & 0x7)
#define F_MMU_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f)

@@ -117,13 +119,14 @@
#define HAS_VLD_PA_RNG BIT(2)
#define RESET_AXI BIT(3)
#define OUT_ORDER_WR_EN BIT(4)
-#define HAS_SUB_COMM BIT(5)
-#define WR_THROT_EN BIT(6)
-#define HAS_LEGACY_IVRP_PADDR BIT(7)
-#define IOVA_34_EN BIT(8)
-#define SHARE_PGTABLE BIT(9) /* 2 HW share pgtable */
-#define DCM_DISABLE BIT(10)
-#define NOT_STD_AXI_MODE BIT(11)
+#define HAS_SUB_COMM_2BITS BIT(5)
+#define HAS_SUB_COMM_3BITS BIT(6)
+#define WR_THROT_EN BIT(7)
+#define HAS_LEGACY_IVRP_PADDR BIT(8)
+#define IOVA_34_EN BIT(9)
+#define SHARE_PGTABLE BIT(10) /* 2 HW share pgtable */
+#define DCM_DISABLE BIT(11)
+#define NOT_STD_AXI_MODE BIT(12)

#define MTK_IOMMU_HAS_FLAG(pdata, _x) \
((((pdata)->flags) & (_x)) == (_x))
@@ -304,9 +307,12 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
fault_pa |= (u64)pa34_32 << 32;

fault_port = F_MMU_INT_ID_PORT_ID(regval);
- if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM)) {
+ if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_2BITS)) {
fault_larb = F_MMU_INT_ID_COMM_ID(regval);
sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval);
+ } else if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_3BITS)) {
+ fault_larb = F_MMU_INT_ID_COMM_ID_EXT(regval);
+ sub_comm = F_MMU_INT_ID_SUB_COMM_ID_EXT(regval);
} else {
fault_larb = F_MMU_INT_ID_LARB_ID(regval);
}
@@ -1035,7 +1041,7 @@ static const struct mtk_iommu_plat_data mt2712_data = {

static const struct mtk_iommu_plat_data mt6779_data = {
.m4u_plat = M4U_MT6779,
- .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN |
+ .flags = HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN |
NOT_STD_AXI_MODE,
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
.iova_region = single_domain,
@@ -1073,7 +1079,7 @@ static const struct mtk_iommu_plat_data mt8183_data = {

static const struct mtk_iommu_plat_data mt8192_data = {
.m4u_plat = M4U_MT8192,
- .flags = HAS_BCLK | HAS_SUB_COMM | OUT_ORDER_WR_EN |
+ .flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN |
WR_THROT_EN | IOVA_34_EN | NOT_STD_AXI_MODE,
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
.iova_region = mt8192_multi_dom,
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 027a42396557..5b32277fee99 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -20,7 +20,7 @@
#include <dt-bindings/memory/mtk-memory-port.h>

#define MTK_LARB_COM_MAX 8
-#define MTK_LARB_SUBCOM_MAX 4
+#define MTK_LARB_SUBCOM_MAX 8

#define MTK_IOMMU_GROUP_MAX 8

--
2.18.0

2021-08-13 09:24:52

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v2 16/29] iommu/mediatek: Adjust device link when it is sub-common

For MM IOMMU, We always add device link between smi-common and IOMMU HW.
In mt8195, we add smi-sub-common. Thus, if the node is sub-common, we still
need find again to get smi-common, then do device link.

Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/mtk_iommu.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index a4479916ad33..a72241724adb 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -845,6 +845,17 @@ static int mtk_iommu_mm_dts_parse(struct device *dev,
if (!smicomm_node)
return -EINVAL;

+ /* Find smi-common again if this is smi-sub-common */
+ if (of_property_read_bool(smicomm_node, "mediatek,smi_sub_common")) {
+ of_node_put(smicomm_node); /* put the sub common */
+
+ smicomm_node = of_parse_phandle(smicomm_node, "mediatek,smi", 0);
+ if (!smicomm_node) {
+ dev_err(dev, "sub-comm has no common.\n");
+ return -EINVAL;
+ }
+ }
+
plarbdev = of_find_device_by_node(smicomm_node);
of_node_put(smicomm_node);
data->smicomm_dev = &plarbdev->dev;
--
2.18.0

2021-08-24 07:36:42

by Hsin-Yi Wang

[permalink] [raw]
Subject: Re: [PATCH v2 16/29] iommu/mediatek: Adjust device link when it is sub-common

On Fri, Aug 13, 2021 at 3:03 PM Yong Wu <[email protected]> wrote:
>
> For MM IOMMU, We always add device link between smi-common and IOMMU HW.
> In mt8195, we add smi-sub-common. Thus, if the node is sub-common, we still
> need find again to get smi-common, then do device link.
>
> Signed-off-by: Yong Wu <[email protected]>
> ---
> drivers/iommu/mtk_iommu.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index a4479916ad33..a72241724adb 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -845,6 +845,17 @@ static int mtk_iommu_mm_dts_parse(struct device *dev,
> if (!smicomm_node)
> return -EINVAL;
>
> + /* Find smi-common again if this is smi-sub-common */
> + if (of_property_read_bool(smicomm_node, "mediatek,smi_sub_common")) {
> + of_node_put(smicomm_node); /* put the sub common */
> +
> + smicomm_node = of_parse_phandle(smicomm_node, "mediatek,smi", 0);

This only checks 1 level here, and does not check if the mediatek,smi
of a sub-common node is not another sub-common node.
So maybe add a check that the updated node here doesn't have
mediatek,smi_sub_common property.

> + if (!smicomm_node) {
> + dev_err(dev, "sub-comm has no common.\n");
> + return -EINVAL;
> + }
> + }
> +
> plarbdev = of_find_device_by_node(smicomm_node);
> of_node_put(smicomm_node);
> data->smicomm_dev = &plarbdev->dev;
> --
> 2.18.0
> _______________________________________________
> Linux-mediatek mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

2021-09-01 13:44:42

by Yong Wu (吴勇)

[permalink] [raw]
Subject: Re: [PATCH v2 16/29] iommu/mediatek: Adjust device link when it is sub-common

On Tue, 2021-08-24 at 15:35 +0800, Hsin-Yi Wang wrote:
> On Fri, Aug 13, 2021 at 3:03 PM Yong Wu <[email protected]> wrote:
> >
> > For MM IOMMU, We always add device link between smi-common and
> > IOMMU HW.
> > In mt8195, we add smi-sub-common. Thus, if the node is sub-common,
> > we still
> > need find again to get smi-common, then do device link.
> >
> > Signed-off-by: Yong Wu <[email protected]>
> > ---
> > drivers/iommu/mtk_iommu.c | 11 +++++++++++
> > 1 file changed, 11 insertions(+)
> >
> > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> > index a4479916ad33..a72241724adb 100644
> > --- a/drivers/iommu/mtk_iommu.c
> > +++ b/drivers/iommu/mtk_iommu.c
> > @@ -845,6 +845,17 @@ static int mtk_iommu_mm_dts_parse(struct
> > device *dev,
> > if (!smicomm_node)
> > return -EINVAL;
> >
> > + /* Find smi-common again if this is smi-sub-common */
> > + if (of_property_read_bool(smicomm_node,
> > "mediatek,smi_sub_common")) {
> > + of_node_put(smicomm_node); /* put the sub common */
> > +
> > + smicomm_node = of_parse_phandle(smicomm_node,
> > "mediatek,smi", 0);
>
> This only checks 1 level here, and does not check if the mediatek,smi
> of a sub-common node is not another sub-common node.
> So maybe add a check that the updated node here doesn't have
> mediatek,smi_sub_common property.

Yes. Currently there are only 2 levels. we could confirm if it is sub-
common from if it has "mediatek,smi", then "mediatek,smi_sub_common" is
unnecessary.

Will fix in the next version.

>
> > + if (!smicomm_node) {
> > + dev_err(dev, "sub-comm has no common.\n");
> > + return -EINVAL;
> > + }
> > + }
> > +
> > plarbdev = of_find_device_by_node(smicomm_node);
> > of_node_put(smicomm_node);
> > data->smicomm_dev = &plarbdev->dev;
> > --
> > 2.18.0
> > _______________________________________________
> > Linux-mediatek mailing list
> > [email protected]
> > http://lists.infradead.org/mailman/listinfo/linux-mediatek