2021-06-30 02:37:06

by Yong Wu (吴勇)

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

This patchset add mt8195 iommu supports.

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 dependent 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 registser, 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..15]: support mt8195 iommu.
patch[16..24]: support bank feature.

base on v5.13-rc1.

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

---
Yong Wu (24):
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 mult domain
iommu/mediatek: Add a flag DCM_DISABLE
iommu/mediatek: Add flag NON_STD_AXI
iommu/mediatek: Remove for_each_m4u in tlb_sync_all
iommu/mediatek: Always pm_runtime_get while tlb flush
iommu/mediatek: Always enable output PA over 32bits
iommu/mediatek: Add SUB_COMMON_3BITS flag
iommu/mediatek: Add IOMMU_TYPE flag
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: Add multi bank support
iommu/mediatek: mt8195: Enable multi-bank for infra iommu

.../bindings/iommu/mediatek,iommu.yaml | 21 +-
drivers/iommu/mtk_iommu.c | 760 ++++++++++++------
drivers/iommu/mtk_iommu.h | 33 +-
.../dt-bindings/memory/mt8195-memory-port.h | 408 ++++++++++
include/dt-bindings/memory/mtk-memory-port.h | 2 +
5 files changed, 961 insertions(+), 263 deletions(-)
create mode 100644 include/dt-bindings/memory/mt8195-memory-port.h

--
2.18.0



2021-06-30 02:37:08

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 02/24] dt-bindings: mediatek: mt8195: Add binding for infra IOMMU

In mt8195, we have a new IOMMU that is for INFRA IOMMU. its masters
mainly are PCIe and USB. Different with MM IOMMU, all these masters
connect with IOMMU directly, there is no mediatek,larbs property for
infra IOMMU.

Another thing is about PCIe ports. currently the function
"of_iommu_configure_dev_id" only support the id number is 1, But our
PCIe have two ports, one is for reading and the other is for writing.
see more about the PCIe patch in this patchset. Thus, I only list
the reading id here and add the other id in our driver.

Signed-off-by: Yong Wu <[email protected]>
---
.../bindings/iommu/mediatek,iommu.yaml | 14 +++++++++++++-
.../dt-bindings/memory/mt8195-memory-port.h | 18 ++++++++++++++++++
include/dt-bindings/memory/mtk-memory-port.h | 2 ++
3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
index 9b04630158c8..6f3ff631c06b 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
@@ -79,6 +79,7 @@ properties:
- mediatek,mt8192-m4u # generation two
- mediatek,mt8195-iommu-vdo # generation two
- mediatek,mt8195-iommu-vpp # generation two
+ - mediatek,mt8195-iommu-infra # generation two

- description: mt7623 generation one
items:
@@ -129,7 +130,6 @@ required:
- compatible
- reg
- interrupts
- - mediatek,larbs
- '#iommu-cells'

allOf:
@@ -161,6 +161,18 @@ allOf:
required:
- power-domains

+ - if:
+ not:
+ properties:
+ compatible:
+ items:
+ enum:
+ - mediatek,mt8195-iommu-infra
+
+ then:
+ required:
+ - mediatek,larbs
+
additionalProperties: false

examples:
diff --git a/include/dt-bindings/memory/mt8195-memory-port.h b/include/dt-bindings/memory/mt8195-memory-port.h
index 783bcae8cdea..67afad848725 100644
--- a/include/dt-bindings/memory/mt8195-memory-port.h
+++ b/include/dt-bindings/memory/mt8195-memory-port.h
@@ -387,4 +387,22 @@
#define M4U_PORT_L28_CAM_DRZS4NO_R1 MTK_M4U_ID(28, 5)
#define M4U_PORT_L28_CAM_TNCSO_R1 MTK_M4U_ID(28, 6)

+/* infra iommu ports */
+/* PCIe1: read: BIT16; write BIT17. */
+#define M4U_PORT_INFRA_PCIE1 MTK_IFAIOMMU_PERI_ID(16)
+/* PCIe0: read: BIT18; write BIT19. */
+#define M4U_PORT_INFRA_PCIE0 MTK_IFAIOMMU_PERI_ID(18)
+#define M4U_PORT_INFRA_SSUSB_P3_R MTK_IFAIOMMU_PERI_ID(20)
+#define M4U_PORT_INFRA_SSUSB_P3_W MTK_IFAIOMMU_PERI_ID(21)
+#define M4U_PORT_INFRA_SSUSB_P2_R MTK_IFAIOMMU_PERI_ID(22)
+#define M4U_PORT_INFRA_SSUSB_P2_W MTK_IFAIOMMU_PERI_ID(23)
+#define M4U_PORT_INFRA_SSUSB_P1_1_R MTK_IFAIOMMU_PERI_ID(24)
+#define M4U_PORT_INFRA_SSUSB_P1_1_W MTK_IFAIOMMU_PERI_ID(25)
+#define M4U_PORT_INFRA_SSUSB_P1_0_R MTK_IFAIOMMU_PERI_ID(26)
+#define M4U_PORT_INFRA_SSUSB_P1_0_W MTK_IFAIOMMU_PERI_ID(27)
+#define M4U_PORT_INFRA_SSUSB2_R MTK_IFAIOMMU_PERI_ID(28)
+#define M4U_PORT_INFRA_SSUSB2_W MTK_IFAIOMMU_PERI_ID(29)
+#define M4U_PORT_INFRA_SSUSB_R MTK_IFAIOMMU_PERI_ID(30)
+#define M4U_PORT_INFRA_SSUSB_W MTK_IFAIOMMU_PERI_ID(31)
+
#endif
diff --git a/include/dt-bindings/memory/mtk-memory-port.h b/include/dt-bindings/memory/mtk-memory-port.h
index 7d64103209af..2f68a0511a25 100644
--- a/include/dt-bindings/memory/mtk-memory-port.h
+++ b/include/dt-bindings/memory/mtk-memory-port.h
@@ -12,4 +12,6 @@
#define MTK_M4U_TO_LARB(id) (((id) >> 5) & 0x1f)
#define MTK_M4U_TO_PORT(id) ((id) & 0x1f)

+#define MTK_IFAIOMMU_PERI_ID(port) MTK_M4U_ID(0, port)
+
#endif
--
2.18.0

2021-06-30 02:37:24

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 01/24] dt-bindings: mediatek: mt8195: Add binding for MM IOMMU

This patch adds descriptions for mt8195 IOMMU which also use ARM
Short-Descriptor translation table format.

In mt8195, there are two smi-common HW and IOMMU, one is for vdo(video
output), the other is for vpp(video processing pipe). They connects
with different smi-larbs, then some setting(larbid_remap) is different.
Differentiate them with the compatible string.

Something like this:

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

Another change is that we have a new IOMMU that is for infra master like
PCIe and USB. The infra master don't have the larb and ports, thus we
rename the port header file to mt8195-memory-port.h rather than
mt8195-larb-port.h.

Also, the IOMMU is not only for MM, thus, we don't call it "m4u" which
means "MultiMedia Memory Management UNIT". thus, use the "iommu" as the
compatiable string.

Signed-off-by: Yong Wu <[email protected]>
---
.../bindings/iommu/mediatek,iommu.yaml | 7 +
.../dt-bindings/memory/mt8195-memory-port.h | 390 ++++++++++++++++++
2 files changed, 397 insertions(+)
create mode 100644 include/dt-bindings/memory/mt8195-memory-port.h

diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
index 0f26fe14c8e2..9b04630158c8 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
@@ -77,6 +77,8 @@ properties:
- mediatek,mt8173-m4u # generation two
- mediatek,mt8183-m4u # generation two
- mediatek,mt8192-m4u # generation two
+ - mediatek,mt8195-iommu-vdo # generation two
+ - mediatek,mt8195-iommu-vpp # generation two

- description: mt7623 generation one
items:
@@ -118,6 +120,7 @@ properties:
dt-binding/memory/mt8173-larb-port.h for mt8173,
dt-binding/memory/mt8183-larb-port.h for mt8183,
dt-binding/memory/mt8192-larb-port.h for mt8192.
+ dt-binding/memory/mt8195-memory-port.h for mt8195.

power-domains:
maxItems: 1
@@ -139,6 +142,8 @@ allOf:
- mediatek,mt2712-m4u
- mediatek,mt8173-m4u
- mediatek,mt8192-m4u
+ - mediatek,mt8195-iommu-vdo
+ - mediatek,mt8195-iommu-vpp

then:
required:
@@ -149,6 +154,8 @@ allOf:
compatible:
enum:
- mediatek,mt8192-m4u
+ - mediatek,mt8195-iommu-vdo
+ - mediatek,mt8195-iommu-vpp

then:
required:
diff --git a/include/dt-bindings/memory/mt8195-memory-port.h b/include/dt-bindings/memory/mt8195-memory-port.h
new file mode 100644
index 000000000000..783bcae8cdea
--- /dev/null
+++ b/include/dt-bindings/memory/mt8195-memory-port.h
@@ -0,0 +1,390 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Yong Wu <[email protected]>
+ */
+#ifndef _DT_BINDINGS_MEMORY_MT8195_LARB_PORT_H_
+#define _DT_BINDINGS_MEMORY_MT8195_LARB_PORT_H_
+
+#include <dt-bindings/memory/mtk-memory-port.h>
+
+/*
+ * MM IOMMU supports 16GB dma address. We separate it to four ranges:
+ * 0 ~ 4G; 4G ~ 8G; 8G ~ 12G; 12G ~ 16G. we could adjust these master
+ * locate an banks. BUT:
+ * a) Make sure all the ports inside a larb are in one range.
+ * b) The iova of any master can NOT cross the 4G/8G/12G boundary.
+ *
+ * This is the suggested mapping in this SoC:
+ *
+ * modules dma-address-region larbs-ports
+ * disp 0 ~ 4G larb0/1/2/3
+ * vcodec 4G ~ 8G larb19/20/21/22/23/24
+ * cam/mdp 8G ~ 12G the other larbs.
+ * N/A 12G ~ 16G
+ * CCU0 0x24000_0000 ~ 0x243ff_ffff larb18: port 0/1
+ * CCU1 0x24400_0000 ~ 0x247ff_ffff larb18: port 2/3
+ *
+ * This SoC have two IOMMU HWs, this is the detailed connected information:
+ * iommu-vdo: larb0/2/5/7/9/10/11/13/17/19/21/24/25/28
+ * iommu-vpp: larb1/3/4/6/8/12/14/16/18/20/22/23/26/27
+ */
+
+/* mm iommu ports */
+/* larb0 */
+#define M4U_PORT_L0_DISP_RDMA0 MTK_M4U_ID(0, 0)
+#define M4U_PORT_L0_DISP_WDMA0 MTK_M4U_ID(0, 1)
+#define M4U_PORT_L0_DISP_OVL0_RDMA0 MTK_M4U_ID(0, 2)
+#define M4U_PORT_L0_DISP_OVL0_RDMA1 MTK_M4U_ID(0, 3)
+#define M4U_PORT_L0_DISP_OVL0_HDR MTK_M4U_ID(0, 4)
+#define M4U_PORT_L0_DISP_FAKE0 MTK_M4U_ID(0, 5)
+
+/* larb1 */
+#define M4U_PORT_L1_DISP_RDMA0 MTK_M4U_ID(1, 0)
+#define M4U_PORT_L1_DISP_WDMA0 MTK_M4U_ID(1, 1)
+#define M4U_PORT_L1_DISP_OVL0_RDMA0 MTK_M4U_ID(1, 2)
+#define M4U_PORT_L1_DISP_OVL0_RDMA1 MTK_M4U_ID(1, 3)
+#define M4U_PORT_L1_DISP_OVL0_HDR MTK_M4U_ID(1, 4)
+#define M4U_PORT_L1_DISP_FAKE0 MTK_M4U_ID(1, 5)
+
+/* larb2 */
+#define M4U_PORT_L2_MDP_RDMA0 MTK_M4U_ID(2, 0)
+#define M4U_PORT_L2_MDP_RDMA2 MTK_M4U_ID(2, 1)
+#define M4U_PORT_L2_MDP_RDMA4 MTK_M4U_ID(2, 2)
+#define M4U_PORT_L2_MDP_RDMA6 MTK_M4U_ID(2, 3)
+#define M4U_PORT_L2_DISP_FAKE1 MTK_M4U_ID(2, 4)
+
+/* larb3 */
+#define M4U_PORT_L3_MDP_RDMA1 MTK_M4U_ID(3, 0)
+#define M4U_PORT_L3_MDP_RDMA3 MTK_M4U_ID(3, 1)
+#define M4U_PORT_L3_MDP_RDMA5 MTK_M4U_ID(3, 2)
+#define M4U_PORT_L3_MDP_RDMA7 MTK_M4U_ID(3, 3)
+#define M4U_PORT_L3_HDR_DS MTK_M4U_ID(3, 4)
+#define M4U_PORT_L3_HDR_ADL MTK_M4U_ID(3, 5)
+#define M4U_PORT_L3_DISP_FAKE1 MTK_M4U_ID(3, 6)
+
+/* larb4 */
+#define M4U_PORT_L4_MDP_RDMA MTK_M4U_ID(4, 0)
+#define M4U_PORT_L4_MDP_FG MTK_M4U_ID(4, 1)
+#define M4U_PORT_L4_MDP_OVL MTK_M4U_ID(4, 2)
+#define M4U_PORT_L4_MDP_WROT MTK_M4U_ID(4, 3)
+#define M4U_PORT_L4_FAKE MTK_M4U_ID(4, 4)
+
+/* larb5 */
+#define M4U_PORT_L5_SVPP1_MDP_RDMA MTK_M4U_ID(5, 0)
+#define M4U_PORT_L5_SVPP1_MDP_FG MTK_M4U_ID(5, 1)
+#define M4U_PORT_L5_SVPP1_MDP_OVL MTK_M4U_ID(5, 2)
+#define M4U_PORT_L5_SVPP1_MDP_WROT MTK_M4U_ID(5, 3)
+#define M4U_PORT_L5_SVPP2_MDP_RDMA MTK_M4U_ID(5, 4)
+#define M4U_PORT_L5_SVPP2_MDP_FG MTK_M4U_ID(5, 5)
+#define M4U_PORT_L5_SVPP2_MDP_WROT MTK_M4U_ID(5, 6)
+#define M4U_PORT_L5_FAKE MTK_M4U_ID(5, 7)
+
+/* larb6 */
+#define M4U_PORT_L6_SVPP3_MDP_RDMA MTK_M4U_ID(6, 0)
+#define M4U_PORT_L6_SVPP3_MDP_FG MTK_M4U_ID(6, 1)
+#define M4U_PORT_L6_SVPP3_MDP_WROT MTK_M4U_ID(6, 2)
+#define M4U_PORT_L6_FAKE MTK_M4U_ID(6, 3)
+
+/* larb7 */
+#define M4U_PORT_L7_IMG_WPE_RDMA0 MTK_M4U_ID(7, 0)
+#define M4U_PORT_L7_IMG_WPE_RDMA1 MTK_M4U_ID(7, 1)
+#define M4U_PORT_L7_IMG_WPE_WDMA0 MTK_M4U_ID(7, 2)
+
+/* larb8 */
+#define M4U_PORT_L8_IMG_WPE_RDMA0 MTK_M4U_ID(8, 0)
+#define M4U_PORT_L8_IMG_WPE_RDMA1 MTK_M4U_ID(8, 1)
+#define M4U_PORT_L8_IMG_WPE_WDMA0 MTK_M4U_ID(8, 2)
+
+/* larb9 */
+#define M4U_PORT_L9_IMG_IMGI_T1_A MTK_M4U_ID(9, 0)
+#define M4U_PORT_L9_IMG_IMGBI_T1_A MTK_M4U_ID(9, 1)
+#define M4U_PORT_L9_IMG_IMGCI_T1_A MTK_M4U_ID(9, 2)
+#define M4U_PORT_L9_IMG_SMTI_T1_A MTK_M4U_ID(9, 3)
+#define M4U_PORT_L9_IMG_TNCSTI_T1_A MTK_M4U_ID(9, 4)
+#define M4U_PORT_L9_IMG_TNCSTI_T4_A MTK_M4U_ID(9, 5)
+#define M4U_PORT_L9_IMG_YUVO_T1_A MTK_M4U_ID(9, 6)
+#define M4U_PORT_L9_IMG_TIMGO_T1_A MTK_M4U_ID(9, 7)
+#define M4U_PORT_L9_IMG_YUVO_T2_A MTK_M4U_ID(9, 8)
+#define M4U_PORT_L9_IMG_IMGI_T1_B MTK_M4U_ID(9, 9)
+#define M4U_PORT_L9_IMG_IMGBI_T1_B MTK_M4U_ID(9, 10)
+#define M4U_PORT_L9_IMG_IMGCI_T1_B MTK_M4U_ID(9, 11)
+#define M4U_PORT_L9_IMG_YUVO_T5_A MTK_M4U_ID(9, 12)
+#define M4U_PORT_L9_IMG_SMTI_T1_B MTK_M4U_ID(9, 13)
+#define M4U_PORT_L9_IMG_TNCSO_T1_A MTK_M4U_ID(9, 14)
+#define M4U_PORT_L9_IMG_SMTO_T1_A MTK_M4U_ID(9, 15)
+#define M4U_PORT_L9_IMG_TNCSTO_T1_A MTK_M4U_ID(9, 16)
+#define M4U_PORT_L9_IMG_YUVO_T2_B MTK_M4U_ID(9, 17)
+#define M4U_PORT_L9_IMG_YUVO_T5_B MTK_M4U_ID(9, 18)
+#define M4U_PORT_L9_IMG_SMTO_T1_B MTK_M4U_ID(9, 19)
+
+/* larb10 */
+#define M4U_PORT_L10_IMG_IMGI_D1_A MTK_M4U_ID(10, 0)
+#define M4U_PORT_L10_IMG_IMGCI_D1_A MTK_M4U_ID(10, 1)
+#define M4U_PORT_L10_IMG_DEPI_D1_A MTK_M4U_ID(10, 2)
+#define M4U_PORT_L10_IMG_DMGI_D1_A MTK_M4U_ID(10, 3)
+#define M4U_PORT_L10_IMG_VIPI_D1_A MTK_M4U_ID(10, 4)
+#define M4U_PORT_L10_IMG_TNRWI_D1_A MTK_M4U_ID(10, 5)
+#define M4U_PORT_L10_IMG_RECI_D1_A MTK_M4U_ID(10, 6)
+#define M4U_PORT_L10_IMG_SMTI_D1_A MTK_M4U_ID(10, 7)
+#define M4U_PORT_L10_IMG_SMTI_D6_A MTK_M4U_ID(10, 8)
+#define M4U_PORT_L10_IMG_PIMGI_P1_A MTK_M4U_ID(10, 9)
+#define M4U_PORT_L10_IMG_PIMGBI_P1_A MTK_M4U_ID(10, 10)
+#define M4U_PORT_L10_IMG_PIMGCI_P1_A MTK_M4U_ID(10, 11)
+#define M4U_PORT_L10_IMG_PIMGI_P1_B MTK_M4U_ID(10, 12)
+#define M4U_PORT_L10_IMG_PIMGBI_P1_B MTK_M4U_ID(10, 13)
+#define M4U_PORT_L10_IMG_PIMGCI_P1_B MTK_M4U_ID(10, 14)
+#define M4U_PORT_L10_IMG_IMG3O_D1_A MTK_M4U_ID(10, 15)
+#define M4U_PORT_L10_IMG_IMG4O_D1_A MTK_M4U_ID(10, 16)
+#define M4U_PORT_L10_IMG_IMG3CO_D1_A MTK_M4U_ID(10, 17)
+#define M4U_PORT_L10_IMG_FEO_D1_A MTK_M4U_ID(10, 18)
+#define M4U_PORT_L10_IMG_IMG2O_D1_A MTK_M4U_ID(10, 19)
+#define M4U_PORT_L10_IMG_TNRWO_D1_A MTK_M4U_ID(10, 20)
+#define M4U_PORT_L10_IMG_SMTO_D1_A MTK_M4U_ID(10, 21)
+#define M4U_PORT_L10_IMG_WROT_P1_A MTK_M4U_ID(10, 22)
+#define M4U_PORT_L10_IMG_WROT_P1_B MTK_M4U_ID(10, 23)
+
+/* larb11 */
+#define M4U_PORT_L11_IMG_WPE_EIS_RDMA0_A MTK_M4U_ID(11, 0)
+#define M4U_PORT_L11_IMG_WPE_EIS_RDMA1_A MTK_M4U_ID(11, 1)
+#define M4U_PORT_L11_IMG_WPE_EIS_WDMA0_A MTK_M4U_ID(11, 2)
+#define M4U_PORT_L11_IMG_WPE_TNR_RDMA0_A MTK_M4U_ID(11, 3)
+#define M4U_PORT_L11_IMG_WPE_TNR_RDMA1_A MTK_M4U_ID(11, 4)
+#define M4U_PORT_L11_IMG_WPE_TNR_WDMA0_A MTK_M4U_ID(11, 5)
+#define M4U_PORT_L11_IMG_WPE_EIS_CQ0_A MTK_M4U_ID(11, 6)
+#define M4U_PORT_L11_IMG_WPE_EIS_CQ1_A MTK_M4U_ID(11, 7)
+#define M4U_PORT_L11_IMG_WPE_TNR_CQ0_A MTK_M4U_ID(11, 8)
+#define M4U_PORT_L11_IMG_WPE_TNR_CQ1_A MTK_M4U_ID(11, 9)
+
+/* larb12 */
+#define M4U_PORT_L12_IMG_FDVT_RDA MTK_M4U_ID(12, 0)
+#define M4U_PORT_L12_IMG_FDVT_RDB MTK_M4U_ID(12, 1)
+#define M4U_PORT_L12_IMG_FDVT_WRA MTK_M4U_ID(12, 2)
+#define M4U_PORT_L12_IMG_FDVT_WRB MTK_M4U_ID(12, 3)
+#define M4U_PORT_L12_IMG_ME_RDMA MTK_M4U_ID(12, 4)
+#define M4U_PORT_L12_IMG_ME_WDMA MTK_M4U_ID(12, 5)
+#define M4U_PORT_L12_IMG_DVS_RDMA MTK_M4U_ID(12, 6)
+#define M4U_PORT_L12_IMG_DVS_WDMA MTK_M4U_ID(12, 7)
+#define M4U_PORT_L12_IMG_DVP_RDMA MTK_M4U_ID(12, 8)
+#define M4U_PORT_L12_IMG_DVP_WDMA MTK_M4U_ID(12, 9)
+
+/* larb13 */
+#define M4U_PORT_L13_CAM_CAMSV_CQI_E1 MTK_M4U_ID(13, 0)
+#define M4U_PORT_L13_CAM_CAMSV_CQI_E2 MTK_M4U_ID(13, 1)
+#define M4U_PORT_L13_CAM_GCAMSV_A_IMGO_0 MTK_M4U_ID(13, 2)
+#define M4U_PORT_L13_CAM_SCAMSV_A_IMGO_0 MTK_M4U_ID(13, 3)
+#define M4U_PORT_L13_CAM_GCAMSV_B_IMGO_0 MTK_M4U_ID(13, 4)
+#define M4U_PORT_L13_CAM_GCAMSV_B_IMGO_1 MTK_M4U_ID(13, 5)
+#define M4U_PORT_L13_CAM_GCAMSV_A_UFEO_0 MTK_M4U_ID(13, 6)
+#define M4U_PORT_L13_CAM_GCAMSV_B_UFEO_0 MTK_M4U_ID(13, 7)
+#define M4U_PORT_L13_CAM_PDAI_0 MTK_M4U_ID(13, 8)
+#define M4U_PORT_L13_CAM_FAKE MTK_M4U_ID(13, 9)
+
+/* larb14 */
+#define M4U_PORT_L14_CAM_GCAMSV_A_IMGO_1 MTK_M4U_ID(14, 0)
+#define M4U_PORT_L14_CAM_SCAMSV_A_IMGO_1 MTK_M4U_ID(14, 1)
+#define M4U_PORT_L14_CAM_GCAMSV_B_IMGO_0 MTK_M4U_ID(14, 2)
+#define M4U_PORT_L14_CAM_GCAMSV_B_IMGO_1 MTK_M4U_ID(14, 3)
+#define M4U_PORT_L14_CAM_SCAMSV_B_IMGO_0 MTK_M4U_ID(14, 4)
+#define M4U_PORT_L14_CAM_SCAMSV_B_IMGO_1 MTK_M4U_ID(14, 5)
+#define M4U_PORT_L14_CAM_IPUI MTK_M4U_ID(14, 6)
+#define M4U_PORT_L14_CAM_IPU2I MTK_M4U_ID(14, 7)
+#define M4U_PORT_L14_CAM_IPUO MTK_M4U_ID(14, 8)
+#define M4U_PORT_L14_CAM_IPU2O MTK_M4U_ID(14, 9)
+#define M4U_PORT_L14_CAM_IPU3O MTK_M4U_ID(14, 10)
+#define M4U_PORT_L14_CAM_GCAMSV_A_UFEO_1 MTK_M4U_ID(14, 11)
+#define M4U_PORT_L14_CAM_GCAMSV_B_UFEO_1 MTK_M4U_ID(14, 12)
+#define M4U_PORT_L14_CAM_PDAI_1 MTK_M4U_ID(14, 13)
+#define M4U_PORT_L14_CAM_PDAO MTK_M4U_ID(14, 14)
+
+/* larb15: null */
+
+/* larb16 */
+#define M4U_PORT_L16_CAM_IMGO_R1 MTK_M4U_ID(16, 0)
+#define M4U_PORT_L16_CAM_CQI_R1 MTK_M4U_ID(16, 1)
+#define M4U_PORT_L16_CAM_CQI_R2 MTK_M4U_ID(16, 2)
+#define M4U_PORT_L16_CAM_BPCI_R1 MTK_M4U_ID(16, 3)
+#define M4U_PORT_L16_CAM_LSCI_R1 MTK_M4U_ID(16, 4)
+#define M4U_PORT_L16_CAM_RAWI_R2 MTK_M4U_ID(16, 5)
+#define M4U_PORT_L16_CAM_RAWI_R3 MTK_M4U_ID(16, 6)
+#define M4U_PORT_L16_CAM_UFDI_R2 MTK_M4U_ID(16, 7)
+#define M4U_PORT_L16_CAM_UFDI_R3 MTK_M4U_ID(16, 8)
+#define M4U_PORT_L16_CAM_RAWI_R4 MTK_M4U_ID(16, 9)
+#define M4U_PORT_L16_CAM_RAWI_R5 MTK_M4U_ID(16, 10)
+#define M4U_PORT_L16_CAM_AAI_R1 MTK_M4U_ID(16, 11)
+#define M4U_PORT_L16_CAM_FHO_R1 MTK_M4U_ID(16, 12)
+#define M4U_PORT_L16_CAM_AAO_R1 MTK_M4U_ID(16, 13)
+#define M4U_PORT_L16_CAM_TSFSO_R1 MTK_M4U_ID(16, 14)
+#define M4U_PORT_L16_CAM_FLKO_R1 MTK_M4U_ID(16, 15)
+
+/* larb17 */
+#define M4U_PORT_L17_CAM_YUVO_R1 MTK_M4U_ID(17, 0)
+#define M4U_PORT_L17_CAM_YUVO_R3 MTK_M4U_ID(17, 1)
+#define M4U_PORT_L17_CAM_YUVCO_R1 MTK_M4U_ID(17, 2)
+#define M4U_PORT_L17_CAM_YUVO_R2 MTK_M4U_ID(17, 3)
+#define M4U_PORT_L17_CAM_RZH1N2TO_R1 MTK_M4U_ID(17, 4)
+#define M4U_PORT_L17_CAM_DRZS4NO_R1 MTK_M4U_ID(17, 5)
+#define M4U_PORT_L17_CAM_TNCSO_R1 MTK_M4U_ID(17, 6)
+
+/* larb18 */
+#define M4U_PORT_L18_CAM_CCUI MTK_M4U_ID(18, 0)
+#define M4U_PORT_L18_CAM_CCUO MTK_M4U_ID(18, 1)
+#define M4U_PORT_L18_CAM_CCUI2 MTK_M4U_ID(18, 2)
+#define M4U_PORT_L18_CAM_CCUO2 MTK_M4U_ID(18, 3)
+
+/* larb19 */
+#define M4U_PORT_L19_VENC_RCPU MTK_M4U_ID(19, 0)
+#define M4U_PORT_L19_VENC_REC MTK_M4U_ID(19, 1)
+#define M4U_PORT_L19_VENC_BSDMA MTK_M4U_ID(19, 2)
+#define M4U_PORT_L19_VENC_SV_COMV MTK_M4U_ID(19, 3)
+#define M4U_PORT_L19_VENC_RD_COMV MTK_M4U_ID(19, 4)
+#define M4U_PORT_L19_VENC_NBM_RDMA MTK_M4U_ID(19, 5)
+#define M4U_PORT_L19_VENC_NBM_RDMA_LITE MTK_M4U_ID(19, 6)
+#define M4U_PORT_L19_JPGENC_Y_RDMA MTK_M4U_ID(19, 7)
+#define M4U_PORT_L19_JPGENC_C_RDMA MTK_M4U_ID(19, 8)
+#define M4U_PORT_L19_JPGENC_Q_TABLE MTK_M4U_ID(19, 9)
+#define M4U_PORT_L19_VENC_SUB_W_LUMA MTK_M4U_ID(19, 10)
+#define M4U_PORT_L19_VENC_FCS_NBM_RDMA MTK_M4U_ID(19, 11)
+#define M4U_PORT_L19_JPGENC_BSDMA MTK_M4U_ID(19, 12)
+#define M4U_PORT_L19_JPGDEC_WDMA0 MTK_M4U_ID(19, 13)
+#define M4U_PORT_L19_JPGDEC_BSDMA0 MTK_M4U_ID(19, 14)
+#define M4U_PORT_L19_VENC_NBM_WDMA MTK_M4U_ID(19, 15)
+#define M4U_PORT_L19_VENC_NBM_WDMA_LITE MTK_M4U_ID(19, 16)
+#define M4U_PORT_L19_VENC_FCS_NBM_WDMA MTK_M4U_ID(19, 17)
+#define M4U_PORT_L19_JPGDEC_WDMA1 MTK_M4U_ID(19, 18)
+#define M4U_PORT_L19_JPGDEC_BSDMA1 MTK_M4U_ID(19, 19)
+#define M4U_PORT_L19_JPGDEC_BUFF_OFFSET1 MTK_M4U_ID(19, 20)
+#define M4U_PORT_L19_JPGDEC_BUFF_OFFSET0 MTK_M4U_ID(19, 21)
+#define M4U_PORT_L19_VENC_CUR_LUMA MTK_M4U_ID(19, 22)
+#define M4U_PORT_L19_VENC_CUR_CHROMA MTK_M4U_ID(19, 23)
+#define M4U_PORT_L19_VENC_REF_LUMA MTK_M4U_ID(19, 24)
+#define M4U_PORT_L19_VENC_REF_CHROMA MTK_M4U_ID(19, 25)
+#define M4U_PORT_L19_VENC_SUB_R_CHROMA MTK_M4U_ID(19, 26)
+
+/* larb20 */
+#define M4U_PORT_L20_VENC_RCPU MTK_M4U_ID(20, 0)
+#define M4U_PORT_L20_VENC_REC MTK_M4U_ID(20, 1)
+#define M4U_PORT_L20_VENC_BSDMA MTK_M4U_ID(20, 2)
+#define M4U_PORT_L20_VENC_SV_COMV MTK_M4U_ID(20, 3)
+#define M4U_PORT_L20_VENC_RD_COMV MTK_M4U_ID(20, 4)
+#define M4U_PORT_L20_VENC_NBM_RDMA MTK_M4U_ID(20, 5)
+#define M4U_PORT_L20_VENC_NBM_RDMA_LITE MTK_M4U_ID(20, 6)
+#define M4U_PORT_L20_JPGENC_Y_RDMA MTK_M4U_ID(20, 7)
+#define M4U_PORT_L20_JPGENC_C_RDMA MTK_M4U_ID(20, 8)
+#define M4U_PORT_L20_JPGENC_Q_TABLE MTK_M4U_ID(20, 9)
+#define M4U_PORT_L20_VENC_SUB_W_LUMA MTK_M4U_ID(20, 10)
+#define M4U_PORT_L20_VENC_FCS_NBM_RDMA MTK_M4U_ID(20, 11)
+#define M4U_PORT_L20_JPGENC_BSDMA MTK_M4U_ID(20, 12)
+#define M4U_PORT_L20_JPGDEC_WDMA0 MTK_M4U_ID(20, 13)
+#define M4U_PORT_L20_JPGDEC_BSDMA0 MTK_M4U_ID(20, 14)
+#define M4U_PORT_L20_VENC_NBM_WDMA MTK_M4U_ID(20, 15)
+#define M4U_PORT_L20_VENC_NBM_WDMA_LITE MTK_M4U_ID(20, 16)
+#define M4U_PORT_L20_VENC_FCS_NBM_WDMA MTK_M4U_ID(20, 17)
+#define M4U_PORT_L20_JPGDEC_WDMA1 MTK_M4U_ID(20, 18)
+#define M4U_PORT_L20_JPGDEC_BSDMA1 MTK_M4U_ID(20, 19)
+#define M4U_PORT_L20_JPGDEC_BUFF_OFFSET1 MTK_M4U_ID(20, 20)
+#define M4U_PORT_L20_JPGDEC_BUFF_OFFSET0 MTK_M4U_ID(20, 21)
+#define M4U_PORT_L20_VENC_CUR_LUMA MTK_M4U_ID(20, 22)
+#define M4U_PORT_L20_VENC_CUR_CHROMA MTK_M4U_ID(20, 23)
+#define M4U_PORT_L20_VENC_REF_LUMA MTK_M4U_ID(20, 24)
+#define M4U_PORT_L20_VENC_REF_CHROMA MTK_M4U_ID(20, 25)
+#define M4U_PORT_L20_VENC_SUB_R_CHROMA MTK_M4U_ID(20, 26)
+
+/* larb21 */
+#define M4U_PORT_L21_VDEC_MC_EXT MTK_M4U_ID(21, 0)
+#define M4U_PORT_L21_VDEC_UFO_EXT MTK_M4U_ID(21, 1)
+#define M4U_PORT_L21_VDEC_PP_EXT MTK_M4U_ID(21, 2)
+#define M4U_PORT_L21_VDEC_PRED_RD_EXT MTK_M4U_ID(21, 3)
+#define M4U_PORT_L21_VDEC_PRED_WR_EXT MTK_M4U_ID(21, 4)
+#define M4U_PORT_L21_VDEC_PPWRAP_EXT MTK_M4U_ID(21, 5)
+#define M4U_PORT_L21_VDEC_TILE_EXT MTK_M4U_ID(21, 6)
+#define M4U_PORT_L21_VDEC_VLD_EXT MTK_M4U_ID(21, 7)
+#define M4U_PORT_L21_VDEC_VLD2_EXT MTK_M4U_ID(21, 8)
+#define M4U_PORT_L21_VDEC_AVC_MV_EXT MTK_M4U_ID(21, 9)
+
+/* larb22 */
+#define M4U_PORT_L22_VDEC_MC_EXT MTK_M4U_ID(22, 0)
+#define M4U_PORT_L22_VDEC_UFO_EXT MTK_M4U_ID(22, 1)
+#define M4U_PORT_L22_VDEC_PP_EXT MTK_M4U_ID(22, 2)
+#define M4U_PORT_L22_VDEC_PRED_RD_EXT MTK_M4U_ID(22, 3)
+#define M4U_PORT_L22_VDEC_PRED_WR_EXT MTK_M4U_ID(22, 4)
+#define M4U_PORT_L22_VDEC_PPWRAP_EXT MTK_M4U_ID(22, 5)
+#define M4U_PORT_L22_VDEC_TILE_EXT MTK_M4U_ID(22, 6)
+#define M4U_PORT_L22_VDEC_VLD_EXT MTK_M4U_ID(22, 7)
+#define M4U_PORT_L22_VDEC_VLD2_EXT MTK_M4U_ID(22, 8)
+#define M4U_PORT_L22_VDEC_AVC_MV_EXT MTK_M4U_ID(22, 9)
+
+/* larb23 */
+#define M4U_PORT_L23_VDEC_UFO_ENC_EXT MTK_M4U_ID(23, 0)
+#define M4U_PORT_L23_VDEC_RDMA_EXT MTK_M4U_ID(23, 1)
+
+/* larb24 */
+#define M4U_PORT_L24_VDEC_LAT0_VLD_EXT MTK_M4U_ID(24, 0)
+#define M4U_PORT_L24_VDEC_LAT0_VLD2_EXT MTK_M4U_ID(24, 1)
+#define M4U_PORT_L24_VDEC_LAT0_AVC_MC_EXT MTK_M4U_ID(24, 2)
+#define M4U_PORT_L24_VDEC_LAT0_PRED_RD_EXT MTK_M4U_ID(24, 3)
+#define M4U_PORT_L24_VDEC_LAT0_TILE_EXT MTK_M4U_ID(24, 4)
+#define M4U_PORT_L24_VDEC_LAT0_WDMA_EXT MTK_M4U_ID(24, 5)
+#define M4U_PORT_L24_VDEC_LAT1_VLD_EXT MTK_M4U_ID(24, 6)
+#define M4U_PORT_L24_VDEC_LAT1_VLD2_EXT MTK_M4U_ID(24, 7)
+#define M4U_PORT_L24_VDEC_LAT1_AVC_MC_EXT MTK_M4U_ID(24, 8)
+#define M4U_PORT_L24_VDEC_LAT1_PRED_RD_EXT MTK_M4U_ID(24, 9)
+#define M4U_PORT_L24_VDEC_LAT1_TILE_EXT MTK_M4U_ID(24, 10)
+#define M4U_PORT_L24_VDEC_LAT1_WDMA_EXT MTK_M4U_ID(24, 11)
+
+/* larb25 */
+#define M4U_PORT_L25_CAM_MRAW0_LSCI_M1 MTK_M4U_ID(25, 0)
+#define M4U_PORT_L25_CAM_MRAW0_CQI_M1 MTK_M4U_ID(25, 1)
+#define M4U_PORT_L25_CAM_MRAW0_CQI_M2 MTK_M4U_ID(25, 2)
+#define M4U_PORT_L25_CAM_MRAW0_IMGO_M1 MTK_M4U_ID(25, 3)
+#define M4U_PORT_L25_CAM_MRAW0_IMGBO_M1 MTK_M4U_ID(25, 4)
+#define M4U_PORT_L25_CAM_MRAW2_LSCI_M1 MTK_M4U_ID(25, 5)
+#define M4U_PORT_L25_CAM_MRAW2_CQI_M1 MTK_M4U_ID(25, 6)
+#define M4U_PORT_L25_CAM_MRAW2_CQI_M2 MTK_M4U_ID(25, 7)
+#define M4U_PORT_L25_CAM_MRAW2_IMGO_M1 MTK_M4U_ID(25, 8)
+#define M4U_PORT_L25_CAM_MRAW2_IMGBO_M1 MTK_M4U_ID(25, 9)
+#define M4U_PORT_L25_CAM_MRAW0_AFO_M1 MTK_M4U_ID(25, 10)
+#define M4U_PORT_L25_CAM_MRAW2_AFO_M1 MTK_M4U_ID(25, 11)
+
+/* larb26 */
+#define M4U_PORT_L26_CAM_MRAW1_LSCI_M1 MTK_M4U_ID(26, 0)
+#define M4U_PORT_L26_CAM_MRAW1_CQI_M1 MTK_M4U_ID(26, 1)
+#define M4U_PORT_L26_CAM_MRAW1_CQI_M2 MTK_M4U_ID(26, 2)
+#define M4U_PORT_L26_CAM_MRAW1_IMGO_M1 MTK_M4U_ID(26, 3)
+#define M4U_PORT_L26_CAM_MRAW1_IMGBO_M1 MTK_M4U_ID(26, 4)
+#define M4U_PORT_L26_CAM_MRAW3_LSCI_M1 MTK_M4U_ID(26, 5)
+#define M4U_PORT_L26_CAM_MRAW3_CQI_M1 MTK_M4U_ID(26, 6)
+#define M4U_PORT_L26_CAM_MRAW3_CQI_M2 MTK_M4U_ID(26, 7)
+#define M4U_PORT_L26_CAM_MRAW3_IMGO_M1 MTK_M4U_ID(26, 8)
+#define M4U_PORT_L26_CAM_MRAW3_IMGBO_M1 MTK_M4U_ID(26, 9)
+#define M4U_PORT_L26_CAM_MRAW1_AFO_M1 MTK_M4U_ID(26, 10)
+#define M4U_PORT_L26_CAM_MRAW3_AFO_M1 MTK_M4U_ID(26, 11)
+
+/* larb27 */
+#define M4U_PORT_L27_CAM_IMGO_R1 MTK_M4U_ID(27, 0)
+#define M4U_PORT_L27_CAM_CQI_R1 MTK_M4U_ID(27, 1)
+#define M4U_PORT_L27_CAM_CQI_R2 MTK_M4U_ID(27, 2)
+#define M4U_PORT_L27_CAM_BPCI_R1 MTK_M4U_ID(27, 3)
+#define M4U_PORT_L27_CAM_LSCI_R1 MTK_M4U_ID(27, 4)
+#define M4U_PORT_L27_CAM_RAWI_R2 MTK_M4U_ID(27, 5)
+#define M4U_PORT_L27_CAM_RAWI_R3 MTK_M4U_ID(27, 6)
+#define M4U_PORT_L27_CAM_UFDI_R2 MTK_M4U_ID(27, 7)
+#define M4U_PORT_L27_CAM_UFDI_R3 MTK_M4U_ID(27, 8)
+#define M4U_PORT_L27_CAM_RAWI_R4 MTK_M4U_ID(27, 9)
+#define M4U_PORT_L27_CAM_RAWI_R5 MTK_M4U_ID(27, 10)
+#define M4U_PORT_L27_CAM_AAI_R1 MTK_M4U_ID(27, 11)
+#define M4U_PORT_L27_CAM_FHO_R1 MTK_M4U_ID(27, 12)
+#define M4U_PORT_L27_CAM_AAO_R1 MTK_M4U_ID(27, 13)
+#define M4U_PORT_L27_CAM_TSFSO_R1 MTK_M4U_ID(27, 14)
+#define M4U_PORT_L27_CAM_FLKO_R1 MTK_M4U_ID(27, 15)
+
+/* larb28 */
+#define M4U_PORT_L28_CAM_YUVO_R1 MTK_M4U_ID(28, 0)
+#define M4U_PORT_L28_CAM_YUVO_R3 MTK_M4U_ID(28, 1)
+#define M4U_PORT_L28_CAM_YUVCO_R1 MTK_M4U_ID(28, 2)
+#define M4U_PORT_L28_CAM_YUVO_R2 MTK_M4U_ID(28, 3)
+#define M4U_PORT_L28_CAM_RZH1N2TO_R1 MTK_M4U_ID(28, 4)
+#define M4U_PORT_L28_CAM_DRZS4NO_R1 MTK_M4U_ID(28, 5)
+#define M4U_PORT_L28_CAM_TNCSO_R1 MTK_M4U_ID(28, 6)
+
+#endif
--
2.18.0

2021-06-30 02:37:34

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 03/24] iommu/mediatek: Fix 2 HW sharing pgtable issue

In the this commit 4f956c97d26b ("iommu/mediatek: Move domain_finalise
into attach_device"), I overlooked the sharing pgtable case.
After that commit, the "data" in the mtk_iommu_domain_finalise always is
the data of the current IOMMU HW, If it's sharing pgtable case, here is
not right. This patch fix this. In sharing pgable case, we will loop the
list to find if there already is the exist domain.

this only affect mt2712 which is the only SoC that sharing pgtable.

Fixes: 4f956c97d26b ("iommu/mediatek: Move domain_finalise into attach_device")
Signed-off-by: Chao Hao <[email protected]>
Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/mtk_iommu.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index e06b8a0e2b56..013dbcc87d49 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -390,12 +390,19 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
unsigned int domid)
{
const struct mtk_iommu_iova_region *region;
+ struct mtk_iommu_data *tmpdata;

- /* Use the exist domain as there is only one pgtable here. */
- if (data->m4u_dom) {
- dom->iop = data->m4u_dom->iop;
- dom->cfg = data->m4u_dom->cfg;
- dom->domain.pgsize_bitmap = data->m4u_dom->cfg.pgsize_bitmap;
+ /*
+ * Loop to find if there is already the exist domain.
+ * Use it when 2 iommu HWs share the pgtable.
+ */
+ for_each_m4u(tmpdata) {
+ if (!tmpdata->m4u_dom)
+ continue;
+
+ dom->iop = tmpdata->m4u_dom->iop;
+ dom->cfg = tmpdata->m4u_dom->cfg;
+ dom->domain.pgsize_bitmap = tmpdata->m4u_dom->cfg.pgsize_bitmap;
goto update_iova_region;
}

--
2.18.0

2021-06-30 02:37:34

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 04/24] iommu/mediatek: Adapt sharing and non-sharing pgtable case

In previous mt2712, Both are MM IOMMU, they will share pgtable.
But in the later SoC, another is infra IOMMU, there is no reason to
share pgtable between MM with INFRA IOMMU. This patch try to manage
the two case(sharing or non-sharing pgtable).

Currently we use for_each_m4u to loop the 2 HW. I add the list_head into
this macro.
In the sharing pgtable case, the list_head is the global "m4ulist".
In the non-sharing pgtable case, the list_head is hw_list_head which is a
variable in the "data". then for_each_m4u will only loop itself.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 013dbcc87d49..4689b65fdb03 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -120,6 +120,7 @@
#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 MTK_IOMMU_HAS_FLAG(pdata, _x) \
((((pdata)->flags) & (_x)) == (_x))
@@ -167,7 +168,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data);

static LIST_HEAD(m4ulist); /* List all the M4U HWs */

-#define for_each_m4u(data) list_for_each_entry(data, &m4ulist, list)
+#define for_each_m4u(data, head) list_for_each_entry(data, head, list)

struct mtk_iommu_iova_region {
dma_addr_t iova_base;
@@ -188,21 +189,10 @@ static const struct mtk_iommu_iova_region mt8192_multi_dom[] = {
#endif
};

-/*
- * There may be 1 or 2 M4U HWs, But we always expect they are in the same domain
- * for the performance.
- *
- * Here always return the mtk_iommu_data of the first probed M4U where the
- * iommu domain information is recorded.
- */
-static struct mtk_iommu_data *mtk_iommu_get_m4u_data(void)
+/* If 2 M4U share a domain(use the same hwlist), Put the corresponding info in first data.*/
+static struct mtk_iommu_data *mtk_iommu_get_frst_data(struct list_head *hwlist)
{
- struct mtk_iommu_data *data;
-
- for_each_m4u(data)
- return data;
-
- return NULL;
+ return list_first_entry(hwlist, struct mtk_iommu_data, list);
}

static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
@@ -212,7 +202,9 @@ static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)

static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data)
{
- for_each_m4u(data) {
+ struct list_head *head = data->hw_list;
+
+ for_each_m4u(data, head) {
if (pm_runtime_get_if_in_use(data->dev) <= 0)
continue;

@@ -229,12 +221,13 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
size_t granule,
struct mtk_iommu_data *data)
{
+ struct list_head *head = data->hw_list;
bool has_pm = !!data->dev->pm_domain;
unsigned long flags;
int ret;
u32 tmp;

- for_each_m4u(data) {
+ for_each_m4u(data, head) {
if (has_pm) {
if (pm_runtime_get_if_in_use(data->dev) <= 0)
continue;
@@ -390,13 +383,14 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
unsigned int domid)
{
const struct mtk_iommu_iova_region *region;
+ struct list_head *head = data->hw_list;
struct mtk_iommu_data *tmpdata;

/*
* Loop to find if there is already the exist domain.
* Use it when 2 iommu HWs share the pgtable.
*/
- for_each_m4u(tmpdata) {
+ for_each_m4u(tmpdata, head) {
if (!tmpdata->m4u_dom)
continue;

@@ -600,10 +594,12 @@ static void mtk_iommu_release_device(struct device *dev)

static struct iommu_group *mtk_iommu_device_group(struct device *dev)
{
- struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
+ struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data;
+ struct list_head *hw_list = c_data->hw_list;
struct iommu_group *group;
int domid;

+ data = mtk_iommu_get_frst_data(hw_list);
if (!data)
return ERR_PTR(-ENODEV);

@@ -904,7 +900,15 @@ static int mtk_iommu_probe(struct platform_device *pdev)
goto out_sysfs_remove;

spin_lock_init(&data->tlb_lock);
- list_add_tail(&data->list, &m4ulist);
+
+ if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE)) {
+ list_add_tail(&data->list, data->plat_data->hw_list);
+ data->hw_list = data->plat_data->hw_list;
+ } else {
+ INIT_LIST_HEAD(&data->hw_list_head);
+ list_add_tail(&data->list, &data->hw_list_head);
+ data->hw_list = &data->hw_list_head;
+ }

if (!iommu_present(&platform_bus_type)) {
ret = bus_set_iommu(&platform_bus_type, &mtk_iommu_ops);
@@ -1008,7 +1012,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,
+ .flags = HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG | SHARE_PGTABLE,
+ .hw_list = &m4ulist,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index f81fa8862ed0..a41334b12b20 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -55,6 +55,7 @@ struct mtk_iommu_plat_data {
u32 flags;
u32 inv_sel_reg;

+ struct list_head *hw_list;
unsigned int iova_region_nr;
const struct mtk_iommu_iova_region *iova_region;
unsigned char larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX];
@@ -80,6 +81,8 @@ struct mtk_iommu_data {

struct dma_iommu_mapping *mapping; /* For mtk_iommu_v1.c */

+ struct list_head *hw_list;
+ struct list_head hw_list_head;
struct list_head list;
struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX];
};
--
2.18.0

2021-06-30 02:37:55

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 05/24] iommu/mediatek: Add 12G~16G support for mult domain

In mt8192, we preassign 0-4G; 4G-8G; 8G-12G for different multimedia
engines. This depend on the dma-ranges in the iommu consumer's dtsi
node.

This patch only add 12G-16G region. and reword the prevous comment.
we don't limit which master local in which regions.

CCU still is 8G-12G. Don't change it here.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 4689b65fdb03..78b35e187c78 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -180,10 +180,12 @@ static const struct mtk_iommu_iova_region single_domain[] = {
};

static const struct mtk_iommu_iova_region mt8192_multi_dom[] = {
- { .iova_base = 0x0, .size = SZ_4G}, /* disp: 0 ~ 4G */
+ { .iova_base = 0x0, .size = SZ_4G}, /* 0 ~ 4G */
#if IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT)
- { .iova_base = SZ_4G, .size = SZ_4G}, /* vdec: 4G ~ 8G */
- { .iova_base = SZ_4G * 2, .size = SZ_4G}, /* CAM/MDP: 8G ~ 12G */
+ { .iova_base = SZ_4G, .size = SZ_4G}, /* 4G ~ 8G */
+ { .iova_base = SZ_4G * 2, .size = SZ_4G}, /* 8G ~ 12G */
+ { .iova_base = SZ_4G * 3, .size = SZ_4G}, /* 12G ~ 16G */
+
{ .iova_base = 0x240000000ULL, .size = 0x4000000}, /* CCU0 */
{ .iova_base = 0x244000000ULL, .size = 0x4000000}, /* CCU1 */
#endif
--
2.18.0

2021-06-30 02:37:58

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 06/24] iommu/mediatek: Add a flag DCM_DISABLE

In the infra iommu, we should disable DCM. add a new flag for this.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 78b35e187c78..a026e2ee4007 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -53,6 +53,8 @@
#define F_MMU_STANDARD_AXI_MODE_MASK (BIT(3) | BIT(19))

#define REG_MMU_DCM_DIS 0x050
+#define F_MMU_DCM BIT(8)
+
#define REG_MMU_WR_LEN_CTRL 0x054
#define F_MMU_WR_THROT_DIS_MASK (BIT(5) | BIT(21))

@@ -121,6 +123,7 @@
#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 MTK_IOMMU_HAS_FLAG(pdata, _x) \
((((pdata)->flags) & (_x)) == (_x))
@@ -738,7 +741,11 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
regval = F_MMU_VLD_PA_RNG(7, 4);
writel_relaxed(regval, data->base + REG_MMU_VLD_PA_RNG);
}
- writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
+ if (MTK_IOMMU_HAS_FLAG(data->plat_data, DCM_DISABLE))
+ writel_relaxed(F_MMU_DCM, data->base + REG_MMU_DCM_DIS);
+ else
+ writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
+
if (MTK_IOMMU_HAS_FLAG(data->plat_data, WR_THROT_EN)) {
/* write command throttling mode */
regval = readl_relaxed(data->base + REG_MMU_WR_LEN_CTRL);
--
2.18.0

2021-06-30 02:38:32

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 08/24] iommu/mediatek: Remove for_each_m4u in tlb_sync_all

The tlb_sync_all only is called in
a) flush_iotlb_all: it will called for each iommu HW.
b) tlb_flush_range_sync: it already has for_each_m4u.
c) in irq: it has already fail. no need for_each_m4u to flush

thus, No need for_each_m4u in this tlb_sync_all.
This patch remove it.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 7fe9ebd879fe..ed3455b5cef0 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -208,19 +208,15 @@ static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)

static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data)
{
- struct list_head *head = data->hw_list;
-
- for_each_m4u(data, head) {
- if (pm_runtime_get_if_in_use(data->dev) <= 0)
- continue;
+ if (pm_runtime_get_if_in_use(data->dev) <= 0)
+ return;

- writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
- data->base + data->plat_data->inv_sel_reg);
- writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
- wmb(); /* Make sure the tlb flush all done */
+ writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
+ data->base + data->plat_data->inv_sel_reg);
+ writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
+ wmb(); /* Make sure the tlb flush all done */

- pm_runtime_put(data->dev);
- }
+ pm_runtime_put(data->dev);
}

static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
--
2.18.0

2021-06-30 02:38:47

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 10/24] iommu/mediatek: Always enable output PA over 32bits in isr

Currently the output PA[32:33] is contained by the flag IOVA_34.
This is not right. the iova_34 has no relation with pa[32:33].
the 32bits iova still could map to pa[32:33], This patch move it
out of the flag.

This patch no need fix tag since currently only mt8192 use the
calulation and it always has this IOVA_34 flag.

This is preparing for the IOMMU that still use IOVA 32bits.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index fcf70787d3d1..35e321ed6d3d 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -287,11 +287,11 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT;
if (MTK_IOMMU_HAS_FLAG(data->plat_data, IOVA_34_EN)) {
va34_32 = FIELD_GET(F_MMU_INVAL_VA_34_32_MASK, fault_iova);
- pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova);
fault_iova = fault_iova & F_MMU_INVAL_VA_31_12_MASK;
fault_iova |= (u64)va34_32 << 32;
- fault_pa |= (u64)pa34_32 << 32;
}
+ pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova);
+ 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)) {
--
2.18.0

2021-06-30 02:39:12

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 12/24] iommu/mediatek: Add IOMMU_TYPE flag

This patch has no functional change, It only adds MM IOMMU_TYPE for
the previous SoC. All the current supported HW are for MM(multimedia)
engines.

In the mt8195, we have another IOMMU_TYPE: infra iommu, and there is
another APU_IOMMU, thus, use 2bits for the IOMMU_TYPE.

For the other IOMMU TYPEs, it doesn't have the "larb""port". thus, I use
the MM flag contain the MM_IOMMU special code, Also, it moves a big
chunk code about parsing the mediatek,larbs into a function, it only
needed for MM IOMMU.

this is preparing for supporting INFRA_IOMMU, and APU_IOMMU later.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index b770cb5893b2..365732309486 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -128,9 +128,17 @@
#define SHARE_PGTABLE BIT(10) /* 2 HW share pgtable */
#define DCM_DISABLE BIT(11)
#define NOT_STD_AXI_MODE BIT(12)
+/* 2 bits: iommu type */
+#define MTK_IOMMU_TYPE_MM (0x0 << 13)
+#define MTK_IOMMU_TYPE_INFRA (0x1 << 13)
+#define MTK_IOMMU_TYPE_MASK (0x3 << 13)

-#define MTK_IOMMU_HAS_FLAG(pdata, _x) \
- ((((pdata)->flags) & (_x)) == (_x))
+#define MTK_IOMMU_HAS_FLAG(pdata, _x) (!!(((pdata)->flags) & (_x)))
+
+#define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask) \
+ ((((pdata)->flags) & (mask)) == (_x))
+#define MTK_IOMMU_IS_TYPE(pdata, _x) MTK_IOMMU_HAS_FLAG_MASK(pdata, _x,\
+ MTK_IOMMU_TYPE_MASK)

struct mtk_iommu_domain {
struct io_pgtable_cfg cfg;
@@ -270,7 +278,7 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
{
struct mtk_iommu_data *data = dev_id;
struct mtk_iommu_domain *dom = data->m4u_dom;
- unsigned int fault_larb, fault_port, sub_comm = 0;
+ unsigned int fault_larb = 0, fault_port = 0, sub_comm = 0;
u32 int_state, regval, va34_32, pa34_32;
u64 fault_iova, fault_pa;
bool layer, write;
@@ -296,17 +304,19 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova);
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_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);
+ if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
+ fault_port = F_MMU_INT_ID_PORT_ID(regval);
+ 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);
+ }
+ fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm];
}
- fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm];

if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) {
@@ -370,19 +380,21 @@ static void mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev,
larbid = MTK_M4U_TO_LARB(fwspec->ids[i]);
portid = MTK_M4U_TO_PORT(fwspec->ids[i]);

- larb_mmu = &data->larb_imu[larbid];
+ if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
+ larb_mmu = &data->larb_imu[larbid];

- region = data->plat_data->iova_region + domid;
- larb_mmu->bank[portid] = upper_32_bits(region->iova_base);
+ region = data->plat_data->iova_region + domid;
+ larb_mmu->bank[portid] = upper_32_bits(region->iova_base);

- dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank %d.\n",
- enable ? "enable" : "disable", dev_name(larb_mmu->dev),
- portid, domid, larb_mmu->bank[portid]);
+ dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank %d.\n",
+ enable ? "enable" : "disable", dev_name(larb_mmu->dev),
+ portid, domid, larb_mmu->bank[portid]);

- if (enable)
- larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
- else
- larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
+ if (enable)
+ larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
+ else
+ larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
+ }
}
}

@@ -783,19 +795,75 @@ static const struct component_master_ops mtk_iommu_com_ops = {
.unbind = mtk_iommu_unbind,
};

+static int mtk_iommu_mm_dts_parse(struct device *dev,
+ struct component_match **match,
+ struct mtk_iommu_data *data)
+{
+ struct platform_device *plarbdev;
+ struct device_link *link;
+ struct device_node *larbnode, *smicomm_node;
+ int i, larb_nr, ret;
+
+ larb_nr = of_count_phandle_with_args(dev->of_node, "mediatek,larbs", NULL);
+ if (larb_nr < 0)
+ return larb_nr;
+
+ for (i = 0; i < larb_nr; i++) {
+ u32 id;
+
+ larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
+ if (!larbnode)
+ return -EINVAL;
+
+ if (!of_device_is_available(larbnode)) {
+ of_node_put(larbnode);
+ continue;
+ }
+
+ ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id);
+ if (ret)/* The id is consecutive if there is no this property */
+ id = i;
+
+ plarbdev = of_find_device_by_node(larbnode);
+ if (!plarbdev) {
+ of_node_put(larbnode);
+ return -EPROBE_DEFER;
+ }
+ data->larb_imu[id].dev = &plarbdev->dev;
+
+ component_match_add_release(dev, match, release_of,
+ compare_of, larbnode);
+ }
+
+ /* Get smi-common dev from the last larb. */
+ smicomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0);
+ if (!smicomm_node)
+ return -EINVAL;
+
+ plarbdev = of_find_device_by_node(smicomm_node);
+ of_node_put(smicomm_node);
+ data->smicomm_dev = &plarbdev->dev;
+
+ link = device_link_add(data->smicomm_dev, dev,
+ DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
+
+ if (!link) {
+ dev_err(dev, "Unable link %s.\n", dev_name(data->smicomm_dev));
+ return PTR_ERR(link);
+ }
+ return 0;
+}
+
static int mtk_iommu_probe(struct platform_device *pdev)
{
struct mtk_iommu_data *data;
struct device *dev = &pdev->dev;
- struct device_node *larbnode, *smicomm_node;
- struct platform_device *plarbdev;
- struct device_link *link;
struct resource *res;
resource_size_t ioaddr;
struct component_match *match = NULL;
struct regmap *infracfg;
void *protect;
- int i, larb_nr, ret;
+ int ret;
u32 val;
char *p;

@@ -850,55 +918,12 @@ static int mtk_iommu_probe(struct platform_device *pdev)
return PTR_ERR(data->bclk);
}

- larb_nr = of_count_phandle_with_args(dev->of_node,
- "mediatek,larbs", NULL);
- if (larb_nr < 0)
- return larb_nr;
-
- for (i = 0; i < larb_nr; i++) {
- u32 id;
-
- larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
- if (!larbnode)
- return -EINVAL;
-
- if (!of_device_is_available(larbnode)) {
- of_node_put(larbnode);
- continue;
- }
-
- ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id);
- if (ret)/* The id is consecutive if there is no this property */
- id = i;
-
- plarbdev = of_find_device_by_node(larbnode);
- if (!plarbdev) {
- of_node_put(larbnode);
- return -EPROBE_DEFER;
- }
- data->larb_imu[id].dev = &plarbdev->dev;
-
- component_match_add_release(dev, &match, release_of,
- compare_of, larbnode);
- }
-
- /* Get smi-common dev from the last larb. */
- smicomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0);
- if (!smicomm_node)
- return -EINVAL;
-
- plarbdev = of_find_device_by_node(smicomm_node);
- of_node_put(smicomm_node);
- data->smicomm_dev = &plarbdev->dev;
-
pm_runtime_enable(dev);

- link = device_link_add(data->smicomm_dev, dev,
- DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
- if (!link) {
- dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev));
- ret = -EINVAL;
- goto out_runtime_disable;
+ if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
+ ret = mtk_iommu_mm_dts_parse(dev, &match, data);
+ if (ret)
+ goto out_runtime_disable;
}

platform_set_drvdata(pdev, data);
@@ -929,9 +954,11 @@ static int mtk_iommu_probe(struct platform_device *pdev)
goto out_list_del;
}

- ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
- if (ret)
- goto out_bus_set_null;
+ if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
+ ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
+ if (ret)
+ goto out_bus_set_null;
+ }
return ret;

out_bus_set_null:
@@ -942,7 +969,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
out_sysfs_remove:
iommu_device_sysfs_remove(&data->iommu);
out_link_remove:
- device_link_remove(data->smicomm_dev, dev);
+ if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM))
+ device_link_remove(data->smicomm_dev, dev);
out_runtime_disable:
pm_runtime_disable(dev);
return ret;
@@ -959,7 +987,8 @@ static int mtk_iommu_remove(struct platform_device *pdev)
bus_set_iommu(&platform_bus_type, NULL);

clk_disable_unprepare(data->bclk);
- device_link_remove(data->smicomm_dev, &pdev->dev);
+ if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM))
+ device_link_remove(data->smicomm_dev, &pdev->dev);
pm_runtime_disable(&pdev->dev);
devm_free_irq(&pdev->dev, data->irq, data);
component_master_del(&pdev->dev, &mtk_iommu_com_ops);
@@ -1026,7 +1055,7 @@ 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 |
- NOT_STD_AXI_MODE,
+ NOT_STD_AXI_MODE | MTK_IOMMU_TYPE_MM,
.hw_list = &m4ulist,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
.iova_region = single_domain,
@@ -1037,7 +1066,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_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN |
- NOT_STD_AXI_MODE,
+ NOT_STD_AXI_MODE | MTK_IOMMU_TYPE_MM,
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1046,7 +1075,8 @@ 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 | NOT_STD_AXI_MODE,
+ .flags = RESET_AXI | HAS_LEGACY_IVRP_PADDR | NOT_STD_AXI_MODE |
+ MTK_IOMMU_TYPE_MM,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1056,7 +1086,8 @@ 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 | NOT_STD_AXI_MODE,
+ HAS_LEGACY_IVRP_PADDR | NOT_STD_AXI_MODE |
+ MTK_IOMMU_TYPE_MM,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1065,7 +1096,7 @@ static const struct mtk_iommu_plat_data mt8173_data = {

static const struct mtk_iommu_plat_data mt8183_data = {
.m4u_plat = M4U_MT8183,
- .flags = RESET_AXI,
+ .flags = RESET_AXI | MTK_IOMMU_TYPE_MM,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1075,7 +1106,8 @@ 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_2BITS | OUT_ORDER_WR_EN |
- WR_THROT_EN | IOVA_34_EN | NOT_STD_AXI_MODE,
+ WR_THROT_EN | IOVA_34_EN | NOT_STD_AXI_MODE |
+ MTK_IOMMU_TYPE_MM,
.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-06-30 02:39:38

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 14/24] iommu/mediatek: Add PCIe support

Currently the code for of_iommu_configure_dev_id is like this:

static int of_iommu_configure_dev_id(struct device_node *master_np,
struct device *dev,
const u32 *id)
{
struct of_phandle_args iommu_spec = { .args_count = 1 };

err = of_map_id(master_np, *id, "iommu-map",
"iommu-map-mask", &iommu_spec.np,
iommu_spec.args);
...
}

it can only support only one id output. BUT our PCIe HW has two ID(one is
for writing, the other is for reading). I'm not sure if we should change
of_map_id to support output MAX_PHANDLE_ARGS.

In this patch I add the solution in ourselve drivers. If it's pcie case,
enable one more bit.

Not all infra iommu support PCIe, thus I add a PCIe support flag here.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 1b62896c6666..33303243771b 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -22,6 +22,7 @@
#include <linux/of_iommu.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
@@ -134,6 +135,7 @@
#define MTK_IOMMU_TYPE_MM (0x0 << 13)
#define MTK_IOMMU_TYPE_INFRA (0x1 << 13)
#define MTK_IOMMU_TYPE_MASK (0x3 << 13)
+#define IFA_IOMMU_PCIe_SUPPORT BIT(15)

#define MTK_IOMMU_HAS_FLAG(pdata, _x) (!!(((pdata)->flags) & (_x)))

@@ -399,8 +401,12 @@ static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev,
larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
} else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA)) {
peri_mmuen_msk = BIT(portid);
- peri_mmuen = enable ? peri_mmuen_msk : 0;

+ /* PCIdev has only one output id, enable the next writing bit for PCIe */
+ if (dev_is_pci(dev))
+ peri_mmuen_msk |= BIT(portid + 1);
+
+ peri_mmuen = enable ? peri_mmuen_msk : 0;
ret = regmap_update_bits(data->pericfg, PERICFG_IOMMU_1,
peri_mmuen_msk, peri_mmuen);
if (ret)
@@ -980,6 +986,15 @@ static int mtk_iommu_probe(struct platform_device *pdev)
ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
if (ret)
goto out_bus_set_null;
+ } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) &&
+ MTK_IOMMU_HAS_FLAG(data->plat_data, IFA_IOMMU_PCIe_SUPPORT)) {
+ #ifdef CONFIG_PCI
+ if (!iommu_present(&pci_bus_type)) {
+ ret = bus_set_iommu(&pci_bus_type, &mtk_iommu_ops);
+ if (ret) /* PCIe fail don't affect platform_bus. */
+ goto out_list_del;
+ }
+ #endif
}
return ret;

--
2.18.0

2021-06-30 02:39:38

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 13/24] iommu/mediatek: Add infra iommu support

This patch adds infra iommu supports, the infra iommu enable bits in
mt8195 is in the pericfg register segment. use regmap to update it.

If infra iommu master translation fault, It don't have the
larbid/portid, thus I print the whole register value output.

Since regmap_update_bits may fail, add return value for
mtk_iommu_config.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 365732309486..1b62896c6666 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -114,6 +114,8 @@

#define MTK_PROTECT_PA_ALIGN 256

+#define PERICFG_IOMMU_1 0x714
+
#define HAS_4GB_MODE BIT(0)
/* HW will use the EMI clock if there isn't the "bclk". */
#define HAS_BCLK BIT(1)
@@ -322,8 +324,8 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) {
dev_err_ratelimited(
data->dev,
- "fault type=0x%x iova=0x%llx pa=0x%llx larb=%d port=%d layer=%d %s\n",
- int_state, fault_iova, fault_pa, fault_larb, fault_port,
+ "fault type=0x%x iova=0x%llx pa=0x%llx master=0x%x(larb=%d port=%d) layer=%d %s\n",
+ int_state, fault_iova, fault_pa, regval, fault_larb, fault_port,
layer, write ? "write" : "read");
}

@@ -367,14 +369,15 @@ static int mtk_iommu_get_domain_id(struct device *dev,
return -EINVAL;
}

-static void mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev,
- bool enable, unsigned int domid)
+static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev,
+ bool enable, unsigned int domid)
{
struct mtk_smi_larb_iommu *larb_mmu;
unsigned int larbid, portid;
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
const struct mtk_iommu_iova_region *region;
- int i;
+ u32 peri_mmuen, peri_mmuen_msk;
+ int i, ret = 0;

for (i = 0; i < fwspec->num_ids; ++i) {
larbid = MTK_M4U_TO_LARB(fwspec->ids[i]);
@@ -394,8 +397,19 @@ static void mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev,
larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
else
larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
+ } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA)) {
+ peri_mmuen_msk = BIT(portid);
+ peri_mmuen = enable ? peri_mmuen_msk : 0;
+
+ ret = regmap_update_bits(data->pericfg, PERICFG_IOMMU_1,
+ peri_mmuen_msk, peri_mmuen);
+ if (ret)
+ dev_err(dev, "%s iommu(%s) inframaster 0x%x fail(%d).\n",
+ enable ? "enable" : "disable",
+ dev_name(data->dev), peri_mmuen_msk, ret);
}
}
+ return ret;
}

static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
@@ -512,8 +526,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
pm_runtime_put(m4udev);
}

- mtk_iommu_config(data, dev, true, domid);
- return 0;
+ return mtk_iommu_config(data, dev, true, domid);
}

static void mtk_iommu_detach_device(struct iommu_domain *domain,
@@ -924,6 +937,15 @@ static int mtk_iommu_probe(struct platform_device *pdev)
ret = mtk_iommu_mm_dts_parse(dev, &match, data);
if (ret)
goto out_runtime_disable;
+ } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) &&
+ data->plat_data->pericfg_comp_str) {
+ infracfg = syscon_regmap_lookup_by_compatible(data->plat_data->pericfg_comp_str);
+ if (IS_ERR(infracfg)) {
+ ret = PTR_ERR(infracfg);
+ goto out_runtime_disable;
+ }
+
+ data->pericfg = infracfg;
}

platform_set_drvdata(pdev, data);
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index ce11e260d1d7..cdc241a51c2f 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -55,6 +55,7 @@ struct mtk_iommu_plat_data {
u32 flags;
u32 inv_sel_reg;

+ char *pericfg_comp_str;
struct list_head *hw_list;
unsigned int iova_region_nr;
const struct mtk_iommu_iova_region *iova_region;
@@ -80,6 +81,8 @@ struct mtk_iommu_data {
struct device *smicomm_dev;

struct dma_iommu_mapping *mapping; /* For mtk_iommu_v1.c */
+ struct regmap *pericfg;
+

struct list_head *hw_list;
struct list_head hw_list_head;
--
2.18.0

2021-06-30 02:40:41

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 22/24] iommu/mediatek: Get the proper bankid for multi banks

We preassign some portes in a special bank via the new defined
bank_portmsk.

If the iommu id in the iommu consumer's dtsi node is inside this
bank_portmsk, then we switch it to this special iommu bank, and initialise
the IOMMU bank HW.

Each a bank has the independent pgtable(4GB iova range). Each a bank
is a independent iommu domain/group. Currently we don't separate different
iova ranges inside a bank.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 8137cfc9c8b9..e297a50adced 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -344,6 +344,30 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}

+static unsigned int mtk_iommu_get_bank_id(struct device *dev,
+ const struct mtk_iommu_plat_data *plat_data)
+{
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+ unsigned int i, portmsk = 0, bankid = 0; /* bank default is 0 */
+
+ if (plat_data->bank_nr == 1)
+ return bankid;
+
+ for (i = 0; i < fwspec->num_ids; i++)
+ portmsk |= BIT(MTK_M4U_TO_PORT(fwspec->ids[i]));
+
+ for (i = 0; i < plat_data->bank_nr; i++) {
+ if (!plat_data->bank_enable[i])
+ continue;
+
+ if (portmsk & plat_data->bank_portmsk[i]) {
+ bankid = i;
+ break;
+ }
+ }
+ return bankid;
+}
+
static int mtk_iommu_get_iova_region_id(struct device *dev,
const struct mtk_iommu_plat_data *plat_data)
{
@@ -509,13 +533,14 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
struct mtk_iommu_bank_data *bank;
struct device *m4udev = data->dev;
- unsigned int bankid = 0;
+ unsigned int bankid;
int ret, region_id;

region_id = mtk_iommu_get_iova_region_id(dev, data->plat_data);
if (region_id < 0)
return region_id;

+ bankid = mtk_iommu_get_bank_id(dev, data->plat_data);
bank = &data->bank[bankid];
if (!dom->bank) {
if (mtk_iommu_domain_finalise(dom, data, region_id))
@@ -644,6 +669,7 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev)
struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data;
struct list_head *hw_list = c_data->hw_list;
struct iommu_group *group;
+ unsigned int bankid, groupid;
int regionid;

data = mtk_iommu_get_frst_data(hw_list);
@@ -653,12 +679,18 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev)
regionid = mtk_iommu_get_iova_region_id(dev, data->plat_data);
if (regionid < 0)
return ERR_PTR(regionid);
+ bankid = mtk_iommu_get_bank_id(dev, data->plat_data);

- group = data->m4u_group[regionid];
+ /*
+ * If the bank function is enabled, each a bank is a iommu group/domain.
+ * otherwise, each a iova region is a iommu group/domain.
+ */
+ groupid = bankid ? bankid : regionid;
+ group = data->m4u_group[groupid];
if (!group) {
group = iommu_group_alloc();
if (!IS_ERR(group))
- data->m4u_group[regionid] = group;
+ data->m4u_group[groupid] = group;
} else {
iommu_group_ref_get(group);
}
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 78d9481d67b5..8235957f1592 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -65,6 +65,7 @@ struct mtk_iommu_plat_data {

u32 bank_nr;
bool bank_enable[MTK_IOMMU_BANK_MAX];
+ unsigned int bank_portmsk[MTK_IOMMU_BANK_MAX];
unsigned char larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX];
};

--
2.18.0

2021-06-30 02:41:20

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 21/24] iommu/mediatek: Change the domid to iova_region_id

This patch also have no functional change.

In the previous SoC, each a iova_region is a domain; In the multi-banks
case, each a bank is a domain; then the original function name
"mtk_iommu_get_domain_id" is not proper. the name "iova_region_id"
should be proper. this patch only rename the domid to iova_region_id.
This is preparing for adding bankid.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 042489b8e402..8137cfc9c8b9 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -344,8 +344,8 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}

-static int mtk_iommu_get_domain_id(struct device *dev,
- const struct mtk_iommu_plat_data *plat_data)
+static int mtk_iommu_get_iova_region_id(struct device *dev,
+ const struct mtk_iommu_plat_data *plat_data)
{
const struct mtk_iommu_iova_region *rgn = plat_data->iova_region;
const struct bus_dma_region *dma_rgn = dev->dma_range_map;
@@ -375,7 +375,7 @@ static int mtk_iommu_get_domain_id(struct device *dev,
}

static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev,
- bool enable, unsigned int domid)
+ bool enable, unsigned int regionid)
{
struct mtk_smi_larb_iommu *larb_mmu;
unsigned int larbid, portid;
@@ -391,12 +391,12 @@ static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev,
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
larb_mmu = &data->larb_imu[larbid];

- region = data->plat_data->iova_region + domid;
+ region = data->plat_data->iova_region + regionid;
larb_mmu->bank[portid] = upper_32_bits(region->iova_base);

- dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank %d.\n",
+ dev_dbg(dev, "%s iommu for larb(%s) port %d region %d bank %d.\n",
enable ? "enable" : "disable", dev_name(larb_mmu->dev),
- portid, domid, larb_mmu->bank[portid]);
+ portid, regionid, larb_mmu->bank[portid]);

if (enable)
larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
@@ -423,7 +423,7 @@ static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev,

static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
struct mtk_iommu_data *data,
- unsigned int domid)
+ unsigned int region_id)
{
const struct mtk_iommu_iova_region *region;
struct list_head *head = data->hw_list;
@@ -470,7 +470,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,

update_iova_region:
/* Update the iova region for this domain */
- region = data->plat_data->iova_region + domid;
+ region = data->plat_data->iova_region + region_id;
dom->domain.geometry.aperture_start = region->iova_base;
dom->domain.geometry.aperture_end = region->iova_base + region->size - 1;
dom->domain.geometry.force_aperture = true;
@@ -510,15 +510,15 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
struct mtk_iommu_bank_data *bank;
struct device *m4udev = data->dev;
unsigned int bankid = 0;
- int ret, domid;
+ int ret, region_id;

- domid = mtk_iommu_get_domain_id(dev, data->plat_data);
- if (domid < 0)
- return domid;
+ region_id = mtk_iommu_get_iova_region_id(dev, data->plat_data);
+ if (region_id < 0)
+ return region_id;

bank = &data->bank[bankid];
if (!dom->bank) {
- if (mtk_iommu_domain_finalise(dom, data, domid))
+ if (mtk_iommu_domain_finalise(dom, data, region_id))
return -ENODEV;
dom->bank = bank;
}
@@ -540,7 +540,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
pm_runtime_put(m4udev);
}

- return mtk_iommu_config(data, dev, true, domid);
+ return mtk_iommu_config(data, dev, true, region_id);
}

static void mtk_iommu_detach_device(struct iommu_domain *domain,
@@ -644,21 +644,21 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev)
struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data;
struct list_head *hw_list = c_data->hw_list;
struct iommu_group *group;
- int domid;
+ int regionid;

data = mtk_iommu_get_frst_data(hw_list);
if (!data)
return ERR_PTR(-ENODEV);

- domid = mtk_iommu_get_domain_id(dev, data->plat_data);
- if (domid < 0)
- return ERR_PTR(domid);
+ regionid = mtk_iommu_get_iova_region_id(dev, data->plat_data);
+ if (regionid < 0)
+ return ERR_PTR(regionid);

- group = data->m4u_group[domid];
+ group = data->m4u_group[regionid];
if (!group) {
group = iommu_group_alloc();
if (!IS_ERR(group))
- data->m4u_group[domid] = group;
+ data->m4u_group[regionid] = group;
} else {
iommu_group_ref_get(group);
}
@@ -691,14 +691,14 @@ static void mtk_iommu_get_resv_regions(struct device *dev,
struct list_head *head)
{
struct mtk_iommu_data *data = dev_iommu_priv_get(dev);
- unsigned int domid = mtk_iommu_get_domain_id(dev, data->plat_data), i;
+ unsigned int regionid = mtk_iommu_get_iova_region_id(dev, data->plat_data), i;
const struct mtk_iommu_iova_region *resv, *curdom;
struct iommu_resv_region *region;
int prot = IOMMU_WRITE | IOMMU_READ;

- if ((int)domid < 0)
+ if ((int)regionid < 0)
return;
- curdom = data->plat_data->iova_region + domid;
+ curdom = data->plat_data->iova_region + regionid;
for (i = 0; i < data->plat_data->iova_region_nr; i++) {
resv = data->plat_data->iova_region + i;

--
2.18.0

2021-06-30 02:41:47

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 18/24] iommu/mediatek: Add mtk_iommu_bank_data structure

This patch touchs many lines code, But it has no functional change.
It's a preparing for support multi-bank for the IOMMU HW.

This patch adds a new structure(mtk_iommu_bank_data) for each a bank.
Each a bank have the independent HW base/IRQ, and each a bank has its
special iommu-domain(independent pgtable), thus, also move the domain
information and tlb_lock into it.

In previous SoC, we have only one bank which could be treated as bank0(
bankid always is 0 for the previous SoC).

After adding this structure, the tlb operations and irq could use
bank_data as unit.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 5237c837128e..78c458bb8cc8 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -148,7 +148,7 @@ struct mtk_iommu_domain {
struct io_pgtable_cfg cfg;
struct io_pgtable_ops *iop;

- struct mtk_iommu_data *data;
+ struct mtk_iommu_bank_data *bank;
struct iommu_domain domain;
};

@@ -221,26 +221,27 @@ static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
return container_of(dom, struct mtk_iommu_domain, domain);
}

-static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data)
+static void mtk_iommu_tlb_flush_all(struct mtk_iommu_bank_data *bank)
{
- if (pm_runtime_get_if_in_use(data->dev) <= 0)
+ if (pm_runtime_get_if_in_use(bank->pdev) <= 0)
return;

writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
- data->base + data->plat_data->inv_sel_reg);
- writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
+ bank->base + bank->pdata->plat_data->inv_sel_reg);
+ writel_relaxed(F_ALL_INVLD, bank->base + REG_MMU_INVALIDATE);
wmb(); /* Make sure the tlb flush all done */

- pm_runtime_put(data->dev);
+ pm_runtime_put(bank->pdev);
}

static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
size_t granule,
- struct mtk_iommu_data *data)
+ struct mtk_iommu_bank_data *bank)
{
- struct list_head *head = data->hw_list;
- bool has_pm = !!data->dev->pm_domain;
- void __iomem *base = data->base;
+ struct list_head *head = bank->pdata->hw_list;
+ bool has_pm = !!bank->pdev->pm_domain;
+ void __iomem *base = bank->base;
+ struct mtk_iommu_data *data;
unsigned long flags;
int ret;
u32 tmp;
@@ -251,7 +252,7 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
continue;
}

- spin_lock_irqsave(&data->tlb_lock, flags);
+ spin_lock_irqsave(&bank->tlb_lock, flags);
writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
base + data->plat_data->inv_sel_reg);

@@ -266,25 +267,26 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
if (ret) {
dev_warn(data->dev,
"Partial TLB flush timed out, falling back to full flush\n");
- mtk_iommu_tlb_flush_all(data);
+ mtk_iommu_tlb_flush_all(bank);
}
/* Clear the CPE status */
writel_relaxed(0, base + REG_MMU_CPE_DONE);
- spin_unlock_irqrestore(&data->tlb_lock, flags);
+ spin_unlock_irqrestore(&bank->tlb_lock, flags);

if (has_pm)
- pm_runtime_put(data->dev);
+ pm_runtime_put(bank->pdev);
}
}

static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
{
- struct mtk_iommu_data *data = dev_id;
- struct mtk_iommu_domain *dom = data->m4u_dom;
+ struct mtk_iommu_bank_data *bank = dev_id;
+ struct mtk_iommu_data *data = bank->pdata;
+ struct mtk_iommu_domain *dom = bank->m4u_dom;
unsigned int fault_larb = 0, fault_port = 0, sub_comm = 0;
u32 int_state, regval, va34_32, pa34_32;
const struct mtk_iommu_plat_data *plat_data = data->plat_data;
- void __iomem *base = data->base;
+ void __iomem *base = bank->base;
u64 fault_iova, fault_pa;
bool layer, write;

@@ -323,10 +325,10 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm];
}

- if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
+ if (report_iommu_fault(&dom->domain, bank->pdev, fault_iova,
write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) {
dev_err_ratelimited(
- data->dev,
+ bank->pdev,
"fault type=0x%x iova=0x%llx pa=0x%llx master=0x%x(larb=%d port=%d) layer=%d %s\n",
int_state, fault_iova, fault_pa, regval, fault_larb, fault_port,
layer, write ? "write" : "read");
@@ -337,7 +339,7 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
regval |= F_INT_CLR_BIT;
writel_relaxed(regval, base + REG_MMU_INT_CONTROL0);

- mtk_iommu_tlb_flush_all(data);
+ mtk_iommu_tlb_flush_all(bank);

return IRQ_HANDLED;
}
@@ -425,6 +427,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
{
const struct mtk_iommu_iova_region *region;
struct list_head *head = data->hw_list;
+ struct mtk_iommu_domain *tmpm4udom;
struct mtk_iommu_data *tmpdata;

/*
@@ -432,12 +435,13 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
* Use it when 2 iommu HWs share the pgtable.
*/
for_each_m4u(tmpdata, head) {
- if (!tmpdata->m4u_dom)
+ tmpm4udom = tmpdata->bank[0].m4u_dom;
+ if (!tmpm4udom)
continue;

- dom->iop = tmpdata->m4u_dom->iop;
- dom->cfg = tmpdata->m4u_dom->cfg;
- dom->domain.pgsize_bitmap = tmpdata->m4u_dom->cfg.pgsize_bitmap;
+ dom->iop = tmpm4udom->iop;
+ dom->cfg = tmpm4udom->cfg;
+ dom->domain.pgsize_bitmap = tmpm4udom->cfg.pgsize_bitmap;
goto update_iova_region;
}

@@ -503,20 +507,23 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
{
struct mtk_iommu_data *data = dev_iommu_priv_get(dev);
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+ struct mtk_iommu_bank_data *bank;
struct device *m4udev = data->dev;
+ unsigned int bankid = 0;
int ret, domid;

domid = mtk_iommu_get_domain_id(dev, data->plat_data);
if (domid < 0)
return domid;

- if (!dom->data) {
+ bank = &data->bank[bankid];
+ if (!dom->bank) {
if (mtk_iommu_domain_finalise(dom, data, domid))
return -ENODEV;
- dom->data = data;
+ dom->bank = bank;
}

- if (!data->m4u_dom) { /* Initialize the M4U HW */
+ if (!bank->m4u_dom) { /* Initialize the M4U HW */
ret = pm_runtime_resume_and_get(m4udev);
if (ret < 0)
return ret;
@@ -526,9 +533,9 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
pm_runtime_put(m4udev);
return ret;
}
- data->m4u_dom = dom;
+ bank->m4u_dom = dom;
writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
- data->base + REG_MMU_PT_BASE_ADDR);
+ bank->base + REG_MMU_PT_BASE_ADDR);

pm_runtime_put(m4udev);
}
@@ -550,7 +557,7 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
struct mtk_iommu_domain *dom = to_mtk_domain(domain);

/* The "4GB mode" M4U physically can not use the lower remap of Dram. */
- if (dom->data->enable_4GB)
+ if (dom->bank->pdata->enable_4GB)
paddr |= BIT_ULL(32);

/* Synchronize with the tlb_lock */
@@ -575,7 +582,7 @@ static void mtk_iommu_flush_iotlb_all(struct iommu_domain *domain)
{
struct mtk_iommu_domain *dom = to_mtk_domain(domain);

- mtk_iommu_tlb_flush_all(dom->data);
+ mtk_iommu_tlb_flush_all(dom->bank);
}

static void mtk_iommu_iotlb_sync(struct iommu_domain *domain,
@@ -585,7 +592,7 @@ static void mtk_iommu_iotlb_sync(struct iommu_domain *domain,
size_t length = gather->end - gather->start + 1;

mtk_iommu_tlb_flush_range_sync(gather->start, length, gather->pgsize,
- dom->data);
+ dom->bank);
}

static void mtk_iommu_sync_map(struct iommu_domain *domain, unsigned long iova,
@@ -593,7 +600,7 @@ static void mtk_iommu_sync_map(struct iommu_domain *domain, unsigned long iova,
{
struct mtk_iommu_domain *dom = to_mtk_domain(domain);

- mtk_iommu_tlb_flush_range_sync(iova, size, size, dom->data);
+ mtk_iommu_tlb_flush_range_sync(iova, size, size, dom->bank);
}

static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
@@ -603,7 +610,7 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
phys_addr_t pa;

pa = dom->iop->iova_to_phys(dom->iop, iova);
- if (dom->data->enable_4GB && pa >= MTK_IOMMU_4GB_MODE_REMAP_BASE)
+ if (dom->bank->pdata->enable_4GB && pa >= MTK_IOMMU_4GB_MODE_REMAP_BASE)
pa &= ~BIT_ULL(32);

return pa;
@@ -732,16 +739,17 @@ static const struct iommu_ops mtk_iommu_ops = {

static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
{
+ const struct mtk_iommu_bank_data *bank0 = &data->bank[0];
u32 regval;

if (data->plat_data->m4u_plat == M4U_MT8173) {
regval = F_MMU_PREFETCH_RT_REPLACE_MOD |
F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173;
} else {
- regval = readl_relaxed(data->base + REG_MMU_CTRL_REG);
+ regval = readl_relaxed(bank0->base + REG_MMU_CTRL_REG);
regval |= F_MMU_TF_PROT_TO_PROGRAM_ADDR;
}
- writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
+ writel_relaxed(regval, bank0->base + REG_MMU_CTRL_REG);

if (data->enable_4GB &&
MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_VLD_PA_RNG)) {
@@ -750,31 +758,31 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
* 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
*/
regval = F_MMU_VLD_PA_RNG(7, 4);
- writel_relaxed(regval, data->base + REG_MMU_VLD_PA_RNG);
+ writel_relaxed(regval, bank0->base + REG_MMU_VLD_PA_RNG);
}
if (MTK_IOMMU_HAS_FLAG(data->plat_data, DCM_DISABLE))
- writel_relaxed(F_MMU_DCM, data->base + REG_MMU_DCM_DIS);
+ writel_relaxed(F_MMU_DCM, bank0->base + REG_MMU_DCM_DIS);
else
- writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
+ writel_relaxed(0, bank0->base + REG_MMU_DCM_DIS);

if (MTK_IOMMU_HAS_FLAG(data->plat_data, WR_THROT_EN)) {
/* write command throttling mode */
- regval = readl_relaxed(data->base + REG_MMU_WR_LEN_CTRL);
+ regval = readl_relaxed(bank0->base + REG_MMU_WR_LEN_CTRL);
regval &= ~F_MMU_WR_THROT_DIS_MASK;
- writel_relaxed(regval, data->base + REG_MMU_WR_LEN_CTRL);
+ writel_relaxed(regval, bank0->base + REG_MMU_WR_LEN_CTRL);
}

if (MTK_IOMMU_HAS_FLAG(data->plat_data, RESET_AXI)) {
/* The register is called STANDARD_AXI_MODE in this case */
regval = 0;
} else {
- regval = readl_relaxed(data->base + REG_MMU_MISC_CTRL);
+ regval = readl_relaxed(bank0->base + REG_MMU_MISC_CTRL);
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;
}
- writel_relaxed(regval, data->base + REG_MMU_MISC_CTRL);
+ writel_relaxed(regval, bank0->base + REG_MMU_MISC_CTRL);

regval = F_L2_MULIT_HIT_EN |
F_TABLE_WALK_FAULT_INT_EN |
@@ -782,7 +790,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
F_MISS_FIFO_OVERFLOW_INT_EN |
F_PREFETCH_FIFO_ERR_INT_EN |
F_MISS_FIFO_ERR_INT_EN;
- writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL0);
+ writel_relaxed(regval, bank0->base + REG_MMU_INT_CONTROL0);

regval = F_INT_TRANSLATION_FAULT |
F_INT_MAIN_MULTI_HIT_FAULT |
@@ -791,19 +799,19 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
F_INT_TLB_MISS_FAULT |
F_INT_MISS_TRANSACTION_FIFO_FAULT |
F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
- writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
+ writel_relaxed(regval, bank0->base + REG_MMU_INT_MAIN_CONTROL);

if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR))
regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
else
regval = lower_32_bits(data->protect_base) |
upper_32_bits(data->protect_base);
- writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
+ writel_relaxed(regval, bank0->base + REG_MMU_IVRP_PADDR);

- if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
- dev_name(data->dev), (void *)data)) {
- writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR);
- dev_err(data->dev, "Failed @ IRQ-%d Request\n", data->irq);
+ if (devm_request_irq(bank0->pdev, bank0->irq, mtk_iommu_isr, 0,
+ dev_name(bank0->pdev), (void *)bank0)) {
+ writel_relaxed(0, bank0->base + REG_MMU_PT_BASE_ADDR);
+ dev_err(bank0->pdev, "Failed @ IRQ-%d Request\n", bank0->irq);
return -ENODEV;
}

@@ -886,6 +894,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
int ret;
u32 val;
char *p;
+ struct mtk_iommu_bank_data *bank;
+ void __iomem *base;

data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
@@ -923,14 +933,19 @@ static int mtk_iommu_probe(struct platform_device *pdev)
}

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- data->base = devm_ioremap_resource(dev, res);
- if (IS_ERR(data->base))
- return PTR_ERR(data->base);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
ioaddr = res->start;

- data->irq = platform_get_irq(pdev, 0);
- if (data->irq < 0)
- return data->irq;
+ bank = &data->bank[0];
+ bank->base = base;
+ bank->irq = platform_get_irq(pdev, 0);
+ if (bank->irq < 0)
+ return bank->irq;
+ bank->pdev = dev;
+ bank->pdata = data;
+ spin_lock_init(&bank->tlb_lock);

if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_BCLK)) {
data->bclk = devm_clk_get(dev, "bclk");
@@ -966,8 +981,6 @@ static int mtk_iommu_probe(struct platform_device *pdev)
if (ret)
goto out_sysfs_remove;

- spin_lock_init(&data->tlb_lock);
-
if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE)) {
list_add_tail(&data->list, data->plat_data->hw_list);
data->hw_list = data->plat_data->hw_list;
@@ -1017,6 +1030,7 @@ 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];

iommu_device_sysfs_remove(&data->iommu);
iommu_device_unregister(&data->iommu);
@@ -1028,7 +1042,7 @@ static int mtk_iommu_remove(struct platform_device *pdev)
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM))
device_link_remove(data->smicomm_dev, &pdev->dev);
pm_runtime_disable(&pdev->dev);
- devm_free_irq(&pdev->dev, data->irq, data);
+ devm_free_irq(&pdev->dev, bank->irq, bank);
component_master_del(&pdev->dev, &mtk_iommu_com_ops);
return 0;
}
@@ -1037,7 +1051,7 @@ static int __maybe_unused mtk_iommu_runtime_suspend(struct device *dev)
{
struct mtk_iommu_data *data = dev_get_drvdata(dev);
struct mtk_iommu_suspend_reg *reg = &data->reg;
- void __iomem *base = data->base;
+ void __iomem *base = data->bank[0].base;

reg->wr_len_ctrl = readl_relaxed(base + REG_MMU_WR_LEN_CTRL);
reg->misc_ctrl = readl_relaxed(base + REG_MMU_MISC_CTRL);
@@ -1055,8 +1069,8 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
{
struct mtk_iommu_data *data = dev_get_drvdata(dev);
struct mtk_iommu_suspend_reg *reg = &data->reg;
- struct mtk_iommu_domain *m4u_dom = data->m4u_dom;
- void __iomem *base = data->base;
+ struct mtk_iommu_domain *m4u_dom = data->bank[0].m4u_dom;
+ void __iomem *base = data->bank[0].base;
int ret;

ret = clk_prepare_enable(data->bclk);
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index d9425807e980..7193278501dd 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -24,6 +24,8 @@

#define MTK_IOMMU_GROUP_MAX 8

+#define MTK_IOMMU_BANK_MAX 5
+
struct mtk_iommu_suspend_reg {
union {
u32 standard_axi_mode;/* v1 */
@@ -65,17 +67,23 @@ struct mtk_iommu_plat_data {

struct mtk_iommu_domain;

-struct mtk_iommu_data {
+struct mtk_iommu_bank_data {
void __iomem *base;
int irq;
+ struct device *pdev;
+ struct mtk_iommu_data *pdata; /* parent data */
+ spinlock_t tlb_lock; /* lock for tlb range flush */
+ struct mtk_iommu_domain *m4u_dom; /* Each bank has a domain */
+};
+
+struct mtk_iommu_data {
+ struct mtk_iommu_bank_data bank[MTK_IOMMU_BANK_MAX];
struct device *dev;
struct clk *bclk;
phys_addr_t protect_base; /* protect memory base */
struct mtk_iommu_suspend_reg reg;
- struct mtk_iommu_domain *m4u_dom;
struct iommu_group *m4u_group[MTK_IOMMU_GROUP_MAX];
bool enable_4GB;
- spinlock_t tlb_lock; /* lock for tlb range flush */

struct iommu_device iommu;
const struct mtk_iommu_plat_data *plat_data;
--
2.18.0

2021-06-30 02:41:57

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 24/24] iommu/mediatek: mt8195: Enable multi-bank for infra iommu

Enable the multi-bank functions for infra-iommu. We put PCIE in bank0
and USB in the last bank(bank4). and we don't use the other banks
currently, disable them.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 3aaf425d5a18..435bb0fdd73f 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -1260,8 +1260,11 @@ static const struct mtk_iommu_plat_data mt8195_data_infra = {
.flags = WR_THROT_EN | DCM_DISABLE |
MTK_IOMMU_TYPE_INFRA | IFA_IOMMU_PCIe_SUPPORT,
.pericfg_comp_str = "mediatek,mt8195-pericfg_ao",
- .bank_nr = 1,
- .bank_enable = {true},
+ .bank_nr = 5,
+ .bank_enable = {true, false, false, false, true},
+ .bank_portmsk = {[0] = GENMASK(19, 16), /* PCIe */
+ [4] = GENMASK(31, 20), /* USB */
+ },
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
--
2.18.0

2021-06-30 02:42:04

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 19/24] iommu/mediatek: Initialise bank HW for each a bank

The mt8195 IOMMU HW max support 5 banks, and regarding the banks'
registers, it looks like:

----------------------------------------
|bank0 | bank1 | bank2 | bank3 | bank4|
----------------------------------------
|global |
|control| null
|regs |
-----------------------------------------
|bank |bank |bank |bank |bank |
|regs |regs |regs |regs |regs |
| | | | | |
-----------------------------------------

Each bank has some special bank registers and it share bank0's global
control registers. this patch initialise the bank hw with the bankid.

In the hw_init, we always initialise bank0's control register since
we don't know if the bank0 is initialised.

Additionally, About each bank's register base, always delta 0x1000.
like bank[x + 1] = bank[x] + 0x1000.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 78c458bb8cc8..ed3cf75850ce 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -154,7 +154,7 @@ struct mtk_iommu_domain {

static const struct iommu_ops mtk_iommu_ops;

-static int mtk_iommu_hw_init(const struct mtk_iommu_data *data);
+static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, unsigned int bankid);

#define MTK_IOMMU_TLB_ADDR(iova) ({ \
dma_addr_t _addr = iova; \
@@ -523,12 +523,12 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
dom->bank = bank;
}

- if (!bank->m4u_dom) { /* Initialize the M4U HW */
+ if (!bank->m4u_dom) { /* Initialize the M4U HW for each a BANK */
ret = pm_runtime_resume_and_get(m4udev);
if (ret < 0)
return ret;

- ret = mtk_iommu_hw_init(data);
+ ret = mtk_iommu_hw_init(data, bankid);
if (ret) {
pm_runtime_put(m4udev);
return ret;
@@ -737,11 +737,16 @@ static const struct iommu_ops mtk_iommu_ops = {
.owner = THIS_MODULE,
};

-static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
+static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, unsigned int bankid)
{
+ const struct mtk_iommu_bank_data *bankx = &data->bank[bankid];
const struct mtk_iommu_bank_data *bank0 = &data->bank[0];
u32 regval;

+ /*
+ * global control setting is in bank0. May re-init these global registers
+ * since no sure if there is bank0 consumers.
+ */
if (data->plat_data->m4u_plat == M4U_MT8173) {
regval = F_MMU_PREFETCH_RT_REPLACE_MOD |
F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173;
@@ -784,13 +789,14 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
}
writel_relaxed(regval, bank0->base + REG_MMU_MISC_CTRL);

+ /* independent setting for each bank */
regval = F_L2_MULIT_HIT_EN |
F_TABLE_WALK_FAULT_INT_EN |
F_PREETCH_FIFO_OVERFLOW_INT_EN |
F_MISS_FIFO_OVERFLOW_INT_EN |
F_PREFETCH_FIFO_ERR_INT_EN |
F_MISS_FIFO_ERR_INT_EN;
- writel_relaxed(regval, bank0->base + REG_MMU_INT_CONTROL0);
+ writel_relaxed(regval, bankx->base + REG_MMU_INT_CONTROL0);

regval = F_INT_TRANSLATION_FAULT |
F_INT_MAIN_MULTI_HIT_FAULT |
@@ -799,19 +805,19 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
F_INT_TLB_MISS_FAULT |
F_INT_MISS_TRANSACTION_FIFO_FAULT |
F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
- writel_relaxed(regval, bank0->base + REG_MMU_INT_MAIN_CONTROL);
+ writel_relaxed(regval, bankx->base + REG_MMU_INT_MAIN_CONTROL);

if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR))
regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
else
regval = lower_32_bits(data->protect_base) |
upper_32_bits(data->protect_base);
- writel_relaxed(regval, bank0->base + REG_MMU_IVRP_PADDR);
+ writel_relaxed(regval, bankx->base + REG_MMU_IVRP_PADDR);

- if (devm_request_irq(bank0->pdev, bank0->irq, mtk_iommu_isr, 0,
- dev_name(bank0->pdev), (void *)bank0)) {
- writel_relaxed(0, bank0->base + REG_MMU_PT_BASE_ADDR);
- dev_err(bank0->pdev, "Failed @ IRQ-%d Request\n", bank0->irq);
+ if (devm_request_irq(bankx->pdev, bankx->irq, mtk_iommu_isr, 0,
+ dev_name(bankx->pdev), (void *)bankx)) {
+ writel_relaxed(0, bankx->base + REG_MMU_PT_BASE_ADDR);
+ dev_err(bankx->pdev, "Failed @ IRQ-%d Request\n", bankx->irq);
return -ENODEV;
}

--
2.18.0

2021-06-30 02:42:08

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 20/24] iommu/mediatek: Add bank_nr and bank_enable

This patch adds two variables in the plat_data:
bank_nr: the bank number that this SoC support;
bank_enable: list if the banks is enabled.

This patch add them for all the current SoC, bank_nr always is 1 and
only bank_enable[0] is enabled. it is preparing for supporting
multi banks.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index ed3cf75850ce..042489b8e402 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -1116,6 +1116,8 @@ static const struct mtk_iommu_plat_data mt2712_data = {
NOT_STD_AXI_MODE | MTK_IOMMU_TYPE_MM,
.hw_list = &m4ulist,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
+ .bank_nr = 1,
+ .bank_enable = {true},
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
.larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}},
@@ -1126,6 +1128,8 @@ static const struct mtk_iommu_plat_data mt6779_data = {
.flags = HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN |
NOT_STD_AXI_MODE | MTK_IOMMU_TYPE_MM,
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
+ .bank_nr = 1,
+ .bank_enable = {true},
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
.larbid_remap = {{0}, {1}, {2}, {3}, {5}, {7, 8}, {10}, {9}},
@@ -1136,6 +1140,8 @@ static const struct mtk_iommu_plat_data mt8167_data = {
.flags = RESET_AXI | HAS_LEGACY_IVRP_PADDR | NOT_STD_AXI_MODE |
MTK_IOMMU_TYPE_MM,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
+ .bank_nr = 1,
+ .bank_enable = {true},
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
.larbid_remap = {{0}, {1}, {2}}, /* Linear mapping. */
@@ -1147,6 +1153,8 @@ static const struct mtk_iommu_plat_data mt8173_data = {
HAS_LEGACY_IVRP_PADDR | NOT_STD_AXI_MODE |
MTK_IOMMU_TYPE_MM,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
+ .bank_nr = 1,
+ .bank_enable = {true},
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
.larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}}, /* Linear mapping. */
@@ -1156,6 +1164,8 @@ static const struct mtk_iommu_plat_data mt8183_data = {
.m4u_plat = M4U_MT8183,
.flags = RESET_AXI | MTK_IOMMU_TYPE_MM,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
+ .bank_nr = 1,
+ .bank_enable = {true},
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
.larbid_remap = {{0}, {4}, {5}, {6}, {7}, {2}, {3}, {1}},
@@ -1167,6 +1177,8 @@ static const struct mtk_iommu_plat_data mt8192_data = {
WR_THROT_EN | IOVA_34_EN | NOT_STD_AXI_MODE |
MTK_IOMMU_TYPE_MM,
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
+ .bank_nr = 1,
+ .bank_enable = {true},
.iova_region = mt8192_multi_dom,
.iova_region_nr = ARRAY_SIZE(mt8192_multi_dom),
.larbid_remap = {{0}, {1}, {4, 5}, {7}, {2}, {9, 11, 19, 20},
@@ -1178,6 +1190,8 @@ static const struct mtk_iommu_plat_data mt8195_data_infra = {
.flags = WR_THROT_EN | DCM_DISABLE |
MTK_IOMMU_TYPE_INFRA | IFA_IOMMU_PCIe_SUPPORT,
.pericfg_comp_str = "mediatek,mt8195-pericfg_ao",
+ .bank_nr = 1,
+ .bank_enable = {true},
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
.iova_region = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1190,6 +1204,8 @@ static const struct mtk_iommu_plat_data mt8195_data_vdo = {
MTK_IOMMU_TYPE_MM,
.hw_list = &m4ulist,
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
+ .bank_nr = 1,
+ .bank_enable = {true},
.iova_region = mt8192_multi_dom,
.iova_region_nr = ARRAY_SIZE(mt8192_multi_dom),
.larbid_remap = {{2, 0}, {21}, {24}, {7}, {19}, {9, 10, 11},
@@ -1203,6 +1219,8 @@ static const struct mtk_iommu_plat_data mt8195_data_vdp = {
MTK_IOMMU_TYPE_MM,
.hw_list = &m4ulist,
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
+ .bank_nr = 1,
+ .bank_enable = {true},
.iova_region = mt8192_multi_dom,
.iova_region_nr = ARRAY_SIZE(mt8192_multi_dom),
.larbid_remap = {{1}, {3}, {22, 0, 0, 0, 23}, {8},
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 7193278501dd..78d9481d67b5 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -62,6 +62,9 @@ struct mtk_iommu_plat_data {
struct list_head *hw_list;
unsigned int iova_region_nr;
const struct mtk_iommu_iova_region *iova_region;
+
+ u32 bank_nr;
+ bool bank_enable[MTK_IOMMU_BANK_MAX];
unsigned char larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX];
};

--
2.18.0

2021-06-30 03:10:58

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 11/24] 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 35e321ed6d3d..b770cb5893b2 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -107,6 +107,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)

@@ -118,13 +120,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))
@@ -294,9 +297,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);
}
@@ -1030,7 +1036,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,
@@ -1068,7 +1074,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 a41334b12b20..ce11e260d1d7 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-06-30 03:12:45

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 23/24] iommu/mediatek: Add multi bank support

The registers for each bank of the IOMMU base are in order, delta is
0x1000. Initialise the base for each bank.

Meanwhile, Each bank has some independent registers. thus,
backup/restore them for each a bank.

For all the previous SoC, we only have bank0. thus use "do {} while()"
to allow bank0 always go.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index e297a50adced..3aaf425d5a18 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -114,6 +114,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

@@ -925,11 +926,11 @@ static int mtk_iommu_probe(struct platform_device *pdev)
struct mtk_iommu_data *data;
struct device *dev = &pdev->dev;
struct resource *res;
- resource_size_t ioaddr;
+ resource_size_t ioaddr, size;
struct component_match *match = NULL;
struct regmap *infracfg;
void *protect;
- int ret;
+ int ret, i = 0;
u32 val;
char *p;
struct mtk_iommu_bank_data *bank;
@@ -971,19 +972,30 @@ static int mtk_iommu_probe(struct platform_device *pdev)
}

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ size = resource_size(res);
+ if (size < data->plat_data->bank_nr * MTK_IOMMU_BANK_SZ) {
+ dev_err(dev, "banknr %d. res %pR is not enough.\n",
+ data->plat_data->bank_nr, res);
+ return -EINVAL;
+ }
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
ioaddr = res->start;

- bank = &data->bank[0];
- bank->base = base;
- bank->irq = platform_get_irq(pdev, 0);
- if (bank->irq < 0)
- return bank->irq;
- bank->pdev = dev;
- bank->pdata = data;
- spin_lock_init(&bank->tlb_lock);
+ do {
+ if (!data->plat_data->bank_enable[i])
+ continue;
+ bank = &data->bank[i];
+ bank->base = base + i * MTK_IOMMU_BANK_SZ;
+
+ bank->irq = platform_get_irq(pdev, i);
+ if (bank->irq < 0)
+ return bank->irq;
+ bank->pdev = dev;
+ bank->pdata = data;
+ spin_lock_init(&bank->tlb_lock);
+ } while (++i < data->plat_data->bank_nr);

if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_BCLK)) {
data->bclk = devm_clk_get(dev, "bclk");
@@ -1068,7 +1080,9 @@ 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;
+ bool bank_hwinit;
+ int i;

iommu_device_sysfs_remove(&data->iommu);
iommu_device_unregister(&data->iommu);
@@ -1080,7 +1094,18 @@ static int mtk_iommu_remove(struct platform_device *pdev)
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM))
device_link_remove(data->smicomm_dev, &pdev->dev);
pm_runtime_disable(&pdev->dev);
- devm_free_irq(&pdev->dev, bank->irq, bank);
+ for (i = 0; i < data->plat_data->bank_nr; i++) {
+ bank = &data->bank[i];
+ /*
+ * Use a register value to confirm if this bank HW is initialised.
+ * If the bank has no consumer, the bank HW still won't be
+ * initialised even though bank_enable is true.
+ */
+ bank_hwinit = !!readl_relaxed(bank->base + REG_MMU_PT_BASE_ADDR);
+ if (!bank_hwinit)
+ continue;
+ devm_free_irq(&pdev->dev, bank->irq, bank);
+ }
component_master_del(&pdev->dev, &mtk_iommu_com_ops);
return 0;
}
@@ -1090,15 +1115,21 @@ static int __maybe_unused mtk_iommu_runtime_suspend(struct device *dev)
struct mtk_iommu_data *data = dev_get_drvdata(dev);
struct mtk_iommu_suspend_reg *reg = &data->reg;
void __iomem *base = data->bank[0].base;
+ int i = 0;

reg->wr_len_ctrl = readl_relaxed(base + REG_MMU_WR_LEN_CTRL);
reg->misc_ctrl = readl_relaxed(base + REG_MMU_MISC_CTRL);
reg->dcm_dis = readl_relaxed(base + REG_MMU_DCM_DIS);
reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG);
- reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0);
- reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL);
- reg->ivrp_paddr = readl_relaxed(base + REG_MMU_IVRP_PADDR);
reg->vld_pa_rng = readl_relaxed(base + REG_MMU_VLD_PA_RNG);
+ do {
+ if (!data->plat_data->bank_enable[i])
+ continue;
+ base = data->bank[i].base;
+ reg->int_control0[i] = readl_relaxed(base + REG_MMU_INT_CONTROL0);
+ reg->int_main_control[i] = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL);
+ reg->ivrp_paddr[i] = readl_relaxed(base + REG_MMU_IVRP_PADDR);
+ } while (++i < data->plat_data->bank_nr);
clk_disable_unprepare(data->bclk);
return 0;
}
@@ -1109,7 +1140,7 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
struct mtk_iommu_suspend_reg *reg = &data->reg;
struct mtk_iommu_domain *m4u_dom = data->bank[0].m4u_dom;
void __iomem *base = data->bank[0].base;
- int ret;
+ int ret, i = 0;

ret = clk_prepare_enable(data->bclk);
if (ret) {
@@ -1128,11 +1159,18 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
writel_relaxed(reg->misc_ctrl, base + REG_MMU_MISC_CTRL);
writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM_DIS);
writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG);
- writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0);
- writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
- writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG);
- writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, base + REG_MMU_PT_BASE_ADDR);
+ do {
+ if (!data->plat_data->bank_enable[i])
+ continue;
+ base = data->bank[i].base;
+ m4u_dom = data->bank[i].m4u_dom;
+ writel_relaxed(reg->int_control0[i], base + REG_MMU_INT_CONTROL0);
+ writel_relaxed(reg->int_main_control[i], base + REG_MMU_INT_MAIN_CONTROL);
+ writel_relaxed(reg->ivrp_paddr[i], base + REG_MMU_IVRP_PADDR);
+ writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
+ base + REG_MMU_PT_BASE_ADDR);
+ } while (++i < data->plat_data->bank_nr);
return 0;
}

diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 8235957f1592..813e60de89d6 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -33,11 +33,11 @@ struct mtk_iommu_suspend_reg {
};
u32 dcm_dis;
u32 ctrl_reg;
- u32 int_control0;
- u32 int_main_control;
- u32 ivrp_paddr;
u32 vld_pa_rng;
u32 wr_len_ctrl;
+ u32 int_control0[MTK_IOMMU_BANK_MAX];
+ u32 int_main_control[MTK_IOMMU_BANK_MAX];
+ u32 ivrp_paddr[MTK_IOMMU_BANK_MAX];
};

enum mtk_iommu_plat {
--
2.18.0

2021-06-30 03:19:11

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 07/24] iommu/mediatek: Add flag NON_STD_AXI

This patch add a new flag NON_STD_AXI, All the previous SoC support
this flag. this is a preparing patch for adding infra iommu and apu
iommu which don't support this flag.

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 a026e2ee4007..7fe9ebd879fe 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -124,6 +124,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))
@@ -758,7 +759,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;
}
@@ -1021,7 +1023,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,
@@ -1031,7 +1034,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),
@@ -1040,7 +1044,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),
@@ -1050,7 +1054,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),
@@ -1069,7 +1073,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-06-30 03:31:51

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 09/24] iommu/mediatek: Always pm_runtime_get while tlb flush

In previous soc, some SoC don't have PM. Only mt8192 has power-domain,
and it's display's power-domain which nearly always is enabled.

When there are 2 M4U HW, it may has problem.
In this function, we get the pm_status via the m4u dev, but it don't
reflect the real power-domain status of the HW since there may be other
HW also use that power-domain.

Currently We can not get the real power-domain status, thus I always
pm_runtime_get here.

This pach is only a preparing patch for 2 HW sharing pgtable in different
power-domains, like mt8195 case. thus, no need fix tags here.

this patch may drop the performance, we expect the user could
pm_runtime_get_sync before dma_alloc_attrs.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index ed3455b5cef0..fcf70787d3d1 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -231,7 +231,7 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,

for_each_m4u(data, head) {
if (has_pm) {
- if (pm_runtime_get_if_in_use(data->dev) <= 0)
+ if (pm_runtime_resume_and_get(data->dev) < 0)
continue;
}

--
2.18.0

2021-06-30 03:32:29

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 17/24] iommu/mediatek: Just move code position in hw_init

No functional change too. mt8195 IOMMU support bank functions.
some global control etting is in bank0. and the other banks have its
bank independent setting. this patch only moves the control settings
and the independent registers together.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 1072a10e36ce..5237c837128e 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -743,30 +743,6 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
}
writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);

- regval = F_L2_MULIT_HIT_EN |
- F_TABLE_WALK_FAULT_INT_EN |
- F_PREETCH_FIFO_OVERFLOW_INT_EN |
- F_MISS_FIFO_OVERFLOW_INT_EN |
- F_PREFETCH_FIFO_ERR_INT_EN |
- F_MISS_FIFO_ERR_INT_EN;
- writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL0);
-
- regval = F_INT_TRANSLATION_FAULT |
- F_INT_MAIN_MULTI_HIT_FAULT |
- F_INT_INVALID_PA_FAULT |
- F_INT_ENTRY_REPLACEMENT_FAULT |
- F_INT_TLB_MISS_FAULT |
- F_INT_MISS_TRANSACTION_FIFO_FAULT |
- F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
- writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
-
- if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR))
- regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
- else
- regval = lower_32_bits(data->protect_base) |
- upper_32_bits(data->protect_base);
- writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
-
if (data->enable_4GB &&
MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_VLD_PA_RNG)) {
/*
@@ -800,6 +776,30 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
}
writel_relaxed(regval, data->base + REG_MMU_MISC_CTRL);

+ regval = F_L2_MULIT_HIT_EN |
+ F_TABLE_WALK_FAULT_INT_EN |
+ F_PREETCH_FIFO_OVERFLOW_INT_EN |
+ F_MISS_FIFO_OVERFLOW_INT_EN |
+ F_PREFETCH_FIFO_ERR_INT_EN |
+ F_MISS_FIFO_ERR_INT_EN;
+ writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL0);
+
+ regval = F_INT_TRANSLATION_FAULT |
+ F_INT_MAIN_MULTI_HIT_FAULT |
+ F_INT_INVALID_PA_FAULT |
+ F_INT_ENTRY_REPLACEMENT_FAULT |
+ F_INT_TLB_MISS_FAULT |
+ F_INT_MISS_TRANSACTION_FIFO_FAULT |
+ F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
+ writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
+
+ if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR))
+ regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
+ else
+ regval = lower_32_bits(data->protect_base) |
+ upper_32_bits(data->protect_base);
+ writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
+
if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
dev_name(data->dev), (void *)data)) {
writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR);
--
2.18.0

2021-06-30 03:32:34

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 15/24] iommu/mediatek: Add mt8195 support

mt8195 has 3 IOMMU, containing 2 MM IOMMUs, one is for vdo, the other
is for vpp. and 1 INFRA IOMMU.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 33303243771b..5e046587eef4 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -1152,6 +1152,45 @@ static const struct mtk_iommu_plat_data mt8192_data = {
{0, 14, 16}, {0, 13, 18, 17}},
};

+static const struct mtk_iommu_plat_data mt8195_data_infra = {
+ .m4u_plat = M4U_MT8195,
+ .flags = WR_THROT_EN | DCM_DISABLE |
+ MTK_IOMMU_TYPE_INFRA | IFA_IOMMU_PCIe_SUPPORT,
+ .pericfg_comp_str = "mediatek,mt8195-pericfg_ao",
+ .inv_sel_reg = REG_MMU_INV_SEL_GEN2,
+ .iova_region = single_domain,
+ .iova_region_nr = ARRAY_SIZE(single_domain),
+};
+
+static const struct mtk_iommu_plat_data mt8195_data_vdo = {
+ .m4u_plat = M4U_MT8195,
+ .flags = HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN |
+ NOT_STD_AXI_MODE | IOVA_34_EN | SHARE_PGTABLE |
+ MTK_IOMMU_TYPE_MM,
+ .hw_list = &m4ulist,
+ .inv_sel_reg = REG_MMU_INV_SEL_GEN2,
+ .iova_region = mt8192_multi_dom,
+ .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom),
+ .larbid_remap = {{2, 0}, {21}, {24}, {7}, {19}, {9, 10, 11},
+ {13, 17, 15/* 17b */, 25}, {5}},
+};
+
+static const struct mtk_iommu_plat_data mt8195_data_vdp = {
+ .m4u_plat = M4U_MT8195,
+ .flags = HAS_SUB_COMM_3BITS | OUT_ORDER_WR_EN | WR_THROT_EN |
+ NOT_STD_AXI_MODE | IOVA_34_EN | SHARE_PGTABLE |
+ MTK_IOMMU_TYPE_MM,
+ .hw_list = &m4ulist,
+ .inv_sel_reg = REG_MMU_INV_SEL_GEN2,
+ .iova_region = mt8192_multi_dom,
+ .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom),
+ .larbid_remap = {{1}, {3}, {22, 0, 0, 0, 23}, {8},
+ {20}, {12},
+ /* 16: 16a; 29: 16b; 30: CCUtop0; 31: CCUtop1 */
+ {14, 16, 29, 26, 30, 31, 18},
+ {4, 0, 0, 0, 6}},
+};
+
static const struct of_device_id mtk_iommu_of_ids[] = {
{ .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data},
{ .compatible = "mediatek,mt6779-m4u", .data = &mt6779_data},
@@ -1159,6 +1198,9 @@ static const struct of_device_id mtk_iommu_of_ids[] = {
{ .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data},
{ .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data},
{ .compatible = "mediatek,mt8192-m4u", .data = &mt8192_data},
+ { .compatible = "mediatek,mt8195-iommu-infra", .data = &mt8195_data_infra},
+ { .compatible = "mediatek,mt8195-iommu-vdo", .data = &mt8195_data_vdo},
+ { .compatible = "mediatek,mt8195-iommu-vpp", .data = &mt8195_data_vdp},
{}
};

diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index cdc241a51c2f..d9425807e980 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -46,6 +46,7 @@ enum mtk_iommu_plat {
M4U_MT8173,
M4U_MT8183,
M4U_MT8192,
+ M4U_MT8195,
};

struct mtk_iommu_iova_region;
--
2.18.0

2021-06-30 03:33:40

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH 16/24] iommu/mediatek: Only adjust code about register base

This patch have no functional change. Use "base" instead of the
data->base. This is avoid to touch too many lines in the next patches.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 5e046587eef4..1072a10e36ce 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -240,6 +240,7 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
{
struct list_head *head = data->hw_list;
bool has_pm = !!data->dev->pm_domain;
+ void __iomem *base = data->base;
unsigned long flags;
int ret;
u32 tmp;
@@ -252,17 +253,15 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,

spin_lock_irqsave(&data->tlb_lock, flags);
writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
- data->base + data->plat_data->inv_sel_reg);
+ base + data->plat_data->inv_sel_reg);

- writel_relaxed(MTK_IOMMU_TLB_ADDR(iova),
- data->base + REG_MMU_INVLD_START_A);
+ writel_relaxed(MTK_IOMMU_TLB_ADDR(iova), base + REG_MMU_INVLD_START_A);
writel_relaxed(MTK_IOMMU_TLB_ADDR(iova + size - 1),
- data->base + REG_MMU_INVLD_END_A);
- writel_relaxed(F_MMU_INV_RANGE,
- data->base + REG_MMU_INVALIDATE);
+ base + REG_MMU_INVLD_END_A);
+ writel_relaxed(F_MMU_INV_RANGE, base + REG_MMU_INVALIDATE);

/* tlb sync */
- ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE,
+ ret = readl_poll_timeout_atomic(base + REG_MMU_CPE_DONE,
tmp, tmp != 0, 10, 1000);
if (ret) {
dev_warn(data->dev,
@@ -270,7 +269,7 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
mtk_iommu_tlb_flush_all(data);
}
/* Clear the CPE status */
- writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
+ writel_relaxed(0, base + REG_MMU_CPE_DONE);
spin_unlock_irqrestore(&data->tlb_lock, flags);

if (has_pm)
@@ -284,23 +283,25 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
struct mtk_iommu_domain *dom = data->m4u_dom;
unsigned int fault_larb = 0, fault_port = 0, sub_comm = 0;
u32 int_state, regval, va34_32, pa34_32;
+ const struct mtk_iommu_plat_data *plat_data = data->plat_data;
+ void __iomem *base = data->base;
u64 fault_iova, fault_pa;
bool layer, write;

/* Read error info from registers */
- int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST1);
+ int_state = readl_relaxed(base + REG_MMU_FAULT_ST1);
if (int_state & F_REG_MMU0_FAULT_MASK) {
- regval = readl_relaxed(data->base + REG_MMU0_INT_ID);
- fault_iova = readl_relaxed(data->base + REG_MMU0_FAULT_VA);
- fault_pa = readl_relaxed(data->base + REG_MMU0_INVLD_PA);
+ regval = readl_relaxed(base + REG_MMU0_INT_ID);
+ fault_iova = readl_relaxed(base + REG_MMU0_FAULT_VA);
+ fault_pa = readl_relaxed(base + REG_MMU0_INVLD_PA);
} else {
- regval = readl_relaxed(data->base + REG_MMU1_INT_ID);
- fault_iova = readl_relaxed(data->base + REG_MMU1_FAULT_VA);
- fault_pa = readl_relaxed(data->base + REG_MMU1_INVLD_PA);
+ regval = readl_relaxed(base + REG_MMU1_INT_ID);
+ fault_iova = readl_relaxed(base + REG_MMU1_FAULT_VA);
+ fault_pa = readl_relaxed(base + REG_MMU1_INVLD_PA);
}
layer = fault_iova & F_MMU_FAULT_VA_LAYER_BIT;
write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT;
- if (MTK_IOMMU_HAS_FLAG(data->plat_data, IOVA_34_EN)) {
+ if (MTK_IOMMU_HAS_FLAG(plat_data, IOVA_34_EN)) {
va34_32 = FIELD_GET(F_MMU_INVAL_VA_34_32_MASK, fault_iova);
fault_iova = fault_iova & F_MMU_INVAL_VA_31_12_MASK;
fault_iova |= (u64)va34_32 << 32;
@@ -308,12 +309,12 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova);
fault_pa |= (u64)pa34_32 << 32;

- if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
+ if (MTK_IOMMU_IS_TYPE(plat_data, MTK_IOMMU_TYPE_MM)) {
fault_port = F_MMU_INT_ID_PORT_ID(regval);
- if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_2BITS)) {
+ if (MTK_IOMMU_HAS_FLAG(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)) {
+ } else if (MTK_IOMMU_HAS_FLAG(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 {
@@ -332,9 +333,9 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
}

/* Interrupt clear */
- regval = readl_relaxed(data->base + REG_MMU_INT_CONTROL0);
+ regval = readl_relaxed(base + REG_MMU_INT_CONTROL0);
regval |= F_INT_CLR_BIT;
- writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL0);
+ writel_relaxed(regval, base + REG_MMU_INT_CONTROL0);

mtk_iommu_tlb_flush_all(data);

--
2.18.0

2021-06-30 06:28:08

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH 01/24] dt-bindings: mediatek: mt8195: Add binding for MM IOMMU

On 30/06/2021 04:34, Yong Wu wrote:
> This patch adds descriptions for mt8195 IOMMU which also use ARM
> Short-Descriptor translation table format.
>
> In mt8195, there are two smi-common HW and IOMMU, one is for vdo(video
> output), the other is for vpp(video processing pipe). They connects
> with different smi-larbs, then some setting(larbid_remap) is different.
> Differentiate them with the compatible string.
>
> Something like this:
>
> IOMMU(VDO) IOMMU(VPP)
> | |
> SMI_COMMON_VDO SMI_COMMON_VPP
> --------------- ----------------
> | | ... | | ...
> larb0 larb2 ... larb1 larb3 ...
>
> Another change is that we have a new IOMMU that is for infra master like
> PCIe and USB. The infra master don't have the larb and ports, thus we
> rename the port header file to mt8195-memory-port.h rather than
> mt8195-larb-port.h.
>
> Also, the IOMMU is not only for MM, thus, we don't call it "m4u" which
> means "MultiMedia Memory Management UNIT". thus, use the "iommu" as the
> compatiable string.
>
> Signed-off-by: Yong Wu <[email protected]>
> ---
> .../bindings/iommu/mediatek,iommu.yaml | 7 +
> .../dt-bindings/memory/mt8195-memory-port.h | 390 ++++++++++++++++++
> 2 files changed, 397 insertions(+)
> create mode 100644 include/dt-bindings/memory/mt8195-memory-port.h
>

I understand this will go through IOMMU tree. Do you know about any
further patches for memory controllers which will need the header?

Acked-by: Krzysztof Kozlowski <[email protected]>


Best regards,
Krzysztof

2021-06-30 06:29:43

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH 02/24] dt-bindings: mediatek: mt8195: Add binding for infra IOMMU

On 30/06/2021 04:34, Yong Wu wrote:
> In mt8195, we have a new IOMMU that is for INFRA IOMMU. its masters
> mainly are PCIe and USB. Different with MM IOMMU, all these masters
> connect with IOMMU directly, there is no mediatek,larbs property for
> infra IOMMU.
>
> Another thing is about PCIe ports. currently the function
> "of_iommu_configure_dev_id" only support the id number is 1, But our
> PCIe have two ports, one is for reading and the other is for writing.
> see more about the PCIe patch in this patchset. Thus, I only list
> the reading id here and add the other id in our driver.
>
> Signed-off-by: Yong Wu <[email protected]>
> ---
> .../bindings/iommu/mediatek,iommu.yaml | 14 +++++++++++++-
> .../dt-bindings/memory/mt8195-memory-port.h | 18 ++++++++++++++++++
> include/dt-bindings/memory/mtk-memory-port.h | 2 ++
> 3 files changed, 33 insertions(+), 1 deletion(-)
>


Acked-by: Krzysztof Kozlowski <[email protected]>


Best regards,
Krzysztof

2021-06-30 07:32:55

by Yong Wu (吴勇)

[permalink] [raw]
Subject: Re: [PATCH 01/24] dt-bindings: mediatek: mt8195: Add binding for MM IOMMU

On Wed, 2021-06-30 at 08:26 +0200, Krzysztof Kozlowski wrote:
> On 30/06/2021 04:34, Yong Wu wrote:
> > This patch adds descriptions for mt8195 IOMMU which also use ARM
> > Short-Descriptor translation table format.
> >
> > In mt8195, there are two smi-common HW and IOMMU, one is for vdo(video
> > output), the other is for vpp(video processing pipe). They connects
> > with different smi-larbs, then some setting(larbid_remap) is different.
> > Differentiate them with the compatible string.
> >
> > Something like this:
> >
> > IOMMU(VDO) IOMMU(VPP)
> > | |
> > SMI_COMMON_VDO SMI_COMMON_VPP
> > --------------- ----------------
> > | | ... | | ...
> > larb0 larb2 ... larb1 larb3 ...
> >
> > Another change is that we have a new IOMMU that is for infra master like
> > PCIe and USB. The infra master don't have the larb and ports, thus we
> > rename the port header file to mt8195-memory-port.h rather than
> > mt8195-larb-port.h.
> >
> > Also, the IOMMU is not only for MM, thus, we don't call it "m4u" which
> > means "MultiMedia Memory Management UNIT". thus, use the "iommu" as the
> > compatiable string.
> >
> > Signed-off-by: Yong Wu <[email protected]>
> > ---
> > .../bindings/iommu/mediatek,iommu.yaml | 7 +
> > .../dt-bindings/memory/mt8195-memory-port.h | 390 ++++++++++++++++++
> > 2 files changed, 397 insertions(+)
> > create mode 100644 include/dt-bindings/memory/mt8195-memory-port.h
> >
>
> I understand this will go through IOMMU tree. Do you know about any
> further patches for memory controllers which will need the header?

This header file will only be used in dtsi file. the iommu masters will
use these port definitions in the dtsi.

The SMI driver no need include this header file.

By the way, the mt8195 SMI patches is at:

https://lore.kernel.org/linux-mediatek/[email protected]/

>
> Acked-by: Krzysztof Kozlowski <[email protected]>

Thanks very much for your quick review.

>
>
> Best regards,
> Krzysztof
>
> _______________________________________________
> Linux-mediatek mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

2021-07-14 22:22:24

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH 01/24] dt-bindings: mediatek: mt8195: Add binding for MM IOMMU

On Wed, 30 Jun 2021 10:34:41 +0800, Yong Wu wrote:
> This patch adds descriptions for mt8195 IOMMU which also use ARM
> Short-Descriptor translation table format.
>
> In mt8195, there are two smi-common HW and IOMMU, one is for vdo(video
> output), the other is for vpp(video processing pipe). They connects
> with different smi-larbs, then some setting(larbid_remap) is different.
> Differentiate them with the compatible string.
>
> Something like this:
>
> IOMMU(VDO) IOMMU(VPP)
> | |
> SMI_COMMON_VDO SMI_COMMON_VPP
> --------------- ----------------
> | | ... | | ...
> larb0 larb2 ... larb1 larb3 ...
>
> Another change is that we have a new IOMMU that is for infra master like
> PCIe and USB. The infra master don't have the larb and ports, thus we
> rename the port header file to mt8195-memory-port.h rather than
> mt8195-larb-port.h.
>
> Also, the IOMMU is not only for MM, thus, we don't call it "m4u" which
> means "MultiMedia Memory Management UNIT". thus, use the "iommu" as the
> compatiable string.
>
> Signed-off-by: Yong Wu <[email protected]>
> ---
> .../bindings/iommu/mediatek,iommu.yaml | 7 +
> .../dt-bindings/memory/mt8195-memory-port.h | 390 ++++++++++++++++++
> 2 files changed, 397 insertions(+)
> create mode 100644 include/dt-bindings/memory/mt8195-memory-port.h
>

Reviewed-by: Rob Herring <[email protected]>

2021-07-14 22:22:24

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH 02/24] dt-bindings: mediatek: mt8195: Add binding for infra IOMMU

On Wed, Jun 30, 2021 at 10:34:42AM +0800, Yong Wu wrote:
> In mt8195, we have a new IOMMU that is for INFRA IOMMU. its masters
> mainly are PCIe and USB. Different with MM IOMMU, all these masters
> connect with IOMMU directly, there is no mediatek,larbs property for
> infra IOMMU.
>
> Another thing is about PCIe ports. currently the function
> "of_iommu_configure_dev_id" only support the id number is 1, But our
> PCIe have two ports, one is for reading and the other is for writing.
> see more about the PCIe patch in this patchset. Thus, I only list
> the reading id here and add the other id in our driver.
>
> Signed-off-by: Yong Wu <[email protected]>
> ---
> .../bindings/iommu/mediatek,iommu.yaml | 14 +++++++++++++-
> .../dt-bindings/memory/mt8195-memory-port.h | 18 ++++++++++++++++++
> include/dt-bindings/memory/mtk-memory-port.h | 2 ++
> 3 files changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
> index 9b04630158c8..6f3ff631c06b 100644
> --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
> +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
> @@ -79,6 +79,7 @@ properties:
> - mediatek,mt8192-m4u # generation two
> - mediatek,mt8195-iommu-vdo # generation two
> - mediatek,mt8195-iommu-vpp # generation two
> + - mediatek,mt8195-iommu-infra # generation two
>
> - description: mt7623 generation one
> items:
> @@ -129,7 +130,6 @@ required:
> - compatible
> - reg
> - interrupts
> - - mediatek,larbs
> - '#iommu-cells'
>
> allOf:
> @@ -161,6 +161,18 @@ allOf:
> required:
> - power-domains
>
> + - if:
> + not:
> + properties:
> + compatible:
> + items:
> + enum:
> + - mediatek,mt8195-iommu-infra

This is saying all items are 'mediatek,mt8195-iommu-infra'. Other
schemas prevent that, but really this should be:

compatible:
contains:
const: mediatek,mt8195-iommu-infra

> +
> + then:
> + required:
> + - mediatek,larbs
> +
> additionalProperties: false
>
> examples:
> diff --git a/include/dt-bindings/memory/mt8195-memory-port.h b/include/dt-bindings/memory/mt8195-memory-port.h
> index 783bcae8cdea..67afad848725 100644
> --- a/include/dt-bindings/memory/mt8195-memory-port.h
> +++ b/include/dt-bindings/memory/mt8195-memory-port.h
> @@ -387,4 +387,22 @@
> #define M4U_PORT_L28_CAM_DRZS4NO_R1 MTK_M4U_ID(28, 5)
> #define M4U_PORT_L28_CAM_TNCSO_R1 MTK_M4U_ID(28, 6)
>
> +/* infra iommu ports */
> +/* PCIe1: read: BIT16; write BIT17. */
> +#define M4U_PORT_INFRA_PCIE1 MTK_IFAIOMMU_PERI_ID(16)
> +/* PCIe0: read: BIT18; write BIT19. */
> +#define M4U_PORT_INFRA_PCIE0 MTK_IFAIOMMU_PERI_ID(18)
> +#define M4U_PORT_INFRA_SSUSB_P3_R MTK_IFAIOMMU_PERI_ID(20)
> +#define M4U_PORT_INFRA_SSUSB_P3_W MTK_IFAIOMMU_PERI_ID(21)
> +#define M4U_PORT_INFRA_SSUSB_P2_R MTK_IFAIOMMU_PERI_ID(22)
> +#define M4U_PORT_INFRA_SSUSB_P2_W MTK_IFAIOMMU_PERI_ID(23)
> +#define M4U_PORT_INFRA_SSUSB_P1_1_R MTK_IFAIOMMU_PERI_ID(24)
> +#define M4U_PORT_INFRA_SSUSB_P1_1_W MTK_IFAIOMMU_PERI_ID(25)
> +#define M4U_PORT_INFRA_SSUSB_P1_0_R MTK_IFAIOMMU_PERI_ID(26)
> +#define M4U_PORT_INFRA_SSUSB_P1_0_W MTK_IFAIOMMU_PERI_ID(27)
> +#define M4U_PORT_INFRA_SSUSB2_R MTK_IFAIOMMU_PERI_ID(28)
> +#define M4U_PORT_INFRA_SSUSB2_W MTK_IFAIOMMU_PERI_ID(29)
> +#define M4U_PORT_INFRA_SSUSB_R MTK_IFAIOMMU_PERI_ID(30)
> +#define M4U_PORT_INFRA_SSUSB_W MTK_IFAIOMMU_PERI_ID(31)
> +
> #endif
> diff --git a/include/dt-bindings/memory/mtk-memory-port.h b/include/dt-bindings/memory/mtk-memory-port.h
> index 7d64103209af..2f68a0511a25 100644
> --- a/include/dt-bindings/memory/mtk-memory-port.h
> +++ b/include/dt-bindings/memory/mtk-memory-port.h
> @@ -12,4 +12,6 @@
> #define MTK_M4U_TO_LARB(id) (((id) >> 5) & 0x1f)
> #define MTK_M4U_TO_PORT(id) ((id) & 0x1f)
>
> +#define MTK_IFAIOMMU_PERI_ID(port) MTK_M4U_ID(0, port)
> +
> #endif
> --
> 2.18.0
>
>