This patch mainly adds support for mt8192 Multimedia IOMMU and SMI.
mt8192 also is MTK IOMMU gen2 which uses ARM Short-Descriptor translation
table format. The M4U-SMI HW diagram is as below:
EMI
|
M4U
|
------------
SMI Common
------------
|
+-------+------+------+----------------------+-------+
| | | | ...... | |
| | | | | |
larb0 larb1 larb2 larb4 ...... larb19 larb20
disp0 disp1 mdp vdec IPE IPE
All the connections are HW fixed, SW can NOT adjust it.
Comparing with the preview SoC, this patchset mainly adds two new functions:
a) add iova 34 bits support.
b) add multi domains support since several HW has the special iova
region requirement.
change note:
v4: a) rebase on v5.10-rc1
b) Move the smi part to a independent patchset.
c) Improve v7s code from Robin and Will.
d) Add a mediatek iommu entry patch in MAINTAINERS.
v3: https://lore.kernel.org/linux-iommu/[email protected]/
a) Fix DT schema issue commented from Rob.
b) Fix a v7s issue. Use "_lvl" instead of "_l" in the macro(ARM_V7S_PTES_PER_LVL) since
it is called in ARM_V7S_LVL_IDX which has already used "_l".
c) Fix a PM suspend issue: Avoid pm suspend in pm runtime case.
v2: https://lore.kernel.org/linux-iommu/[email protected]/
a) Convert IOMMU/SMI dt-binding to DT schema.
b) Fix some comment from Pi-Hsun and Nicolas. like use
generic_iommu_put_resv_regions.
c) Reword some comment, like add how to use domain-id.
v1: https://lore.kernel.org/linux-iommu/[email protected]/
Yong Wu (24):
dt-bindings: iommu: mediatek: Convert IOMMU to DT schema
dt-bindings: memory: mediatek: Add a common larb-port header file
dt-bindings: memory: mediatek: Extend LARB_NR_MAX to 32
dt-bindings: memory: mediatek: Add domain definition
dt-bindings: mediatek: Add binding for mt8192 IOMMU
iommu/mediatek: Use the common mtk-smi-larb-port.h
iommu/io-pgtable-arm-v7s: Use ias to check the valid iova in unmap
iommu/io-pgtable-arm-v7s: Extend PA34 for MediaTek
iommu/io-pgtable-arm-v7s: Clear LVL_SHIFT/BITS macro instead of the
formula
iommu/io-pgtable-arm-v7s: Add cfg as a param in some macros
iommu/io-pgtable-arm-v7s: Quad lvl1 pgtable for MediaTek
iommu/mediatek: Move hw_init into attach_device
iommu/mediatek: Add device link for smi-common and m4u
iommu/mediatek: Add pm runtime callback
iommu/mediatek: Add power-domain operation
iommu/mediatek: Add iova reserved function
iommu/mediatek: Add single domain
iommu/mediatek: Support master use iova over 32bit
iommu/mediatek: Support up to 34bit iova in tlb flush
iommu/mediatek: Support report iova 34bit translation fault in ISR
iommu/mediatek: Add support for multi domain
iommu/mediatek: Adjust the structure
iommu/mediatek: Add mt8192 support
MAINTAINERS: Add entry for MediaTek IOMMU
.../bindings/iommu/mediatek,iommu.txt | 105 -------
.../bindings/iommu/mediatek,iommu.yaml | 183 ++++++++++++
MAINTAINERS | 9 +
drivers/iommu/io-pgtable-arm-v7s.c | 56 ++--
drivers/iommu/mtk_iommu.c | 271 +++++++++++++++---
drivers/iommu/mtk_iommu.h | 11 +-
drivers/memory/mtk-smi.c | 8 +
include/dt-bindings/memory/mt2712-larb-port.h | 2 +-
include/dt-bindings/memory/mt6779-larb-port.h | 2 +-
include/dt-bindings/memory/mt8167-larb-port.h | 2 +-
include/dt-bindings/memory/mt8173-larb-port.h | 2 +-
include/dt-bindings/memory/mt8183-larb-port.h | 2 +-
include/dt-bindings/memory/mt8192-larb-port.h | 240 ++++++++++++++++
.../dt-bindings/memory/mtk-smi-larb-port.h | 22 ++
include/linux/io-pgtable.h | 4 +-
include/soc/mediatek/smi.h | 3 +-
16 files changed, 735 insertions(+), 187 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
create mode 100644 Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
create mode 100644 include/dt-bindings/memory/mt8192-larb-port.h
create mode 100644 include/dt-bindings/memory/mtk-smi-larb-port.h
--
2.18.0
Extend the max larb number definition as mt8192 has larb_nr over 16.
Signed-off-by: Yong Wu <[email protected]>
Acked-by: Rob Herring <[email protected]>
---
Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml | 2 +-
include/dt-bindings/memory/mtk-smi-larb-port.h | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
index b9946809fc2b..ba6626347381 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
@@ -99,7 +99,7 @@ properties:
mediatek,larbs:
$ref: /schemas/types.yaml#/definitions/phandle-array
minItems: 1
- maxItems: 16
+ maxItems: 32
description: |
List of phandle to the local arbiters in the current Socs.
Refer to bindings/memory-controllers/mediatek,smi-larb.yaml. It must sort
diff --git a/include/dt-bindings/memory/mtk-smi-larb-port.h b/include/dt-bindings/memory/mtk-smi-larb-port.h
index 2ec7fe5ce4e9..f4d8e3aed0bc 100644
--- a/include/dt-bindings/memory/mtk-smi-larb-port.h
+++ b/include/dt-bindings/memory/mtk-smi-larb-port.h
@@ -6,10 +6,10 @@
#ifndef __DTS_MTK_IOMMU_PORT_H_
#define __DTS_MTK_IOMMU_PORT_H_
-#define MTK_LARB_NR_MAX 16
+#define MTK_LARB_NR_MAX 32
#define MTK_M4U_ID(larb, port) (((larb) << 5) | (port))
-#define MTK_M4U_TO_LARB(id) (((id) >> 5) & 0xf)
+#define MTK_M4U_TO_LARB(id) (((id) >> 5) & 0x1f)
#define MTK_M4U_TO_PORT(id) ((id) & 0x1f)
#endif
--
2.18.0
In the latest SoC, there are several HW IP require a sepecial iova
range, mainly CCU and VPU has this requirement. Take CCU as a example,
CCU require its iova locate in the range(0x4000_0000 ~ 0x43ff_ffff).
In this patch we add a domain definition for the special port. In the
example of CCU, If we preassign CCU port in domain1, then iommu driver
will prepare a independent iommu domain of the special iova range for it,
then the iova got from dma_alloc_attrs(ccu-dev) will locate in its special
range.
This is a preparing patch for multi-domain support.
Signed-off-by: Yong Wu <[email protected]>
---
include/dt-bindings/memory/mtk-smi-larb-port.h | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/include/dt-bindings/memory/mtk-smi-larb-port.h b/include/dt-bindings/memory/mtk-smi-larb-port.h
index f4d8e3aed0bc..d00f5de8438b 100644
--- a/include/dt-bindings/memory/mtk-smi-larb-port.h
+++ b/include/dt-bindings/memory/mtk-smi-larb-port.h
@@ -7,9 +7,16 @@
#define __DTS_MTK_IOMMU_PORT_H_
#define MTK_LARB_NR_MAX 32
+#define MTK_M4U_DOM_NR_MAX 8
+
+#define MTK_M4U_DOM_ID(domid, larb, port) \
+ (((domid) & 0x7) << 16 | (((larb) & 0x1f) << 5) | ((port) & 0x1f))
+
+/* The default dom id is 0. */
+#define MTK_M4U_ID(larb, port) MTK_M4U_DOM_ID(0, larb, port)
-#define MTK_M4U_ID(larb, port) (((larb) << 5) | (port))
#define MTK_M4U_TO_LARB(id) (((id) >> 5) & 0x1f)
#define MTK_M4U_TO_PORT(id) ((id) & 0x1f)
+#define MTK_M4U_TO_DOM(id) (((id) >> 16) & 0x7)
#endif
--
2.18.0
This patch adds decriptions for mt8192 IOMMU and SMI.
mt8192 also is MTK IOMMU gen2 which uses ARM Short-Descriptor translation
table format. The M4U-SMI HW diagram is as below:
EMI
|
M4U
|
------------
SMI Common
------------
|
+-------+------+------+----------------------+-------+
| | | | ...... | |
| | | | | |
larb0 larb1 larb2 larb4 ...... larb19 larb20
disp0 disp1 mdp vdec IPE IPE
All the connections are HW fixed, SW can NOT adjust it.
mt8192 M4U support 0~16GB iova range. we preassign different engines
into different iova ranges:
domain-id module iova-range larbs
0 disp 0 ~ 4G larb0/1
1 vcodec 4G ~ 8G larb4/5/7
2 cam/mdp 8G ~ 12G larb2/9/11/13/14/16/17/18/19/20
3 CCU0 0x4000_0000 ~ 0x43ff_ffff larb13: port 9/10
4 CCU1 0x4400_0000 ~ 0x47ff_ffff larb14: port 4/5
The iova range for CCU0/1(camera control unit) is HW requirement.
Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---
.../bindings/iommu/mediatek,iommu.yaml | 18 +-
include/dt-bindings/memory/mt8192-larb-port.h | 240 ++++++++++++++++++
2 files changed, 257 insertions(+), 1 deletion(-)
create mode 100644 include/dt-bindings/memory/mt8192-larb-port.h
diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
index ba6626347381..0f26fe14c8e2 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
@@ -76,6 +76,7 @@ properties:
- mediatek,mt8167-m4u # generation two
- mediatek,mt8173-m4u # generation two
- mediatek,mt8183-m4u # generation two
+ - mediatek,mt8192-m4u # generation two
- description: mt7623 generation one
items:
@@ -115,7 +116,11 @@ properties:
dt-binding/memory/mt6779-larb-port.h for mt6779,
dt-binding/memory/mt8167-larb-port.h for mt8167,
dt-binding/memory/mt8173-larb-port.h for mt8173,
- dt-binding/memory/mt8183-larb-port.h for mt8183.
+ dt-binding/memory/mt8183-larb-port.h for mt8183,
+ dt-binding/memory/mt8192-larb-port.h for mt8192.
+
+ power-domains:
+ maxItems: 1
required:
- compatible
@@ -133,11 +138,22 @@ allOf:
- mediatek,mt2701-m4u
- mediatek,mt2712-m4u
- mediatek,mt8173-m4u
+ - mediatek,mt8192-m4u
then:
required:
- clocks
+ - if:
+ properties:
+ compatible:
+ enum:
+ - mediatek,mt8192-m4u
+
+ then:
+ required:
+ - power-domains
+
additionalProperties: false
examples:
diff --git a/include/dt-bindings/memory/mt8192-larb-port.h b/include/dt-bindings/memory/mt8192-larb-port.h
new file mode 100644
index 000000000000..7437fa62654e
--- /dev/null
+++ b/include/dt-bindings/memory/mt8192-larb-port.h
@@ -0,0 +1,240 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ *
+ * Author: Chao Hao <[email protected]>
+ * Author: Yong Wu <[email protected]>
+ */
+#ifndef _DTS_IOMMU_PORT_MT8192_H_
+#define _DTS_IOMMU_PORT_MT8192_H_
+
+#include <dt-bindings/memory/mtk-smi-larb-port.h>
+
+/*
+ * MM IOMMU:
+ * domain 0: display: larb0, larb1.
+ * domain 1: vcodec: larb4, larb5, larb7.
+ * domain 2: CAM/MDP: larb2, larb9, larb11, larb13, larb14, larb16,
+ * larb17, larb18, larb19, larb20,
+ * domain 3: CCU0: larb13 - port9/10.
+ * domain 4: CCU1: larb14 - port4/5.
+ *
+ * larb3/6/8/10/12/15 is null.
+ */
+
+/* larb0 */
+#define M4U_PORT_L0_DISP_POSTMASK0 MTK_M4U_DOM_ID(0, 0, 0)
+#define M4U_PORT_L0_OVL_RDMA0_HDR MTK_M4U_DOM_ID(0, 0, 1)
+#define M4U_PORT_L0_OVL_RDMA0 MTK_M4U_DOM_ID(0, 0, 2)
+#define M4U_PORT_L0_DISP_RDMA0 MTK_M4U_DOM_ID(0, 0, 3)
+#define M4U_PORT_L0_DISP_WDMA0 MTK_M4U_DOM_ID(0, 0, 4)
+#define M4U_PORT_L0_DISP_FAKE0 MTK_M4U_DOM_ID(0, 0, 5)
+
+/* larb1 */
+#define M4U_PORT_L1_OVL_2L_RDMA0_HDR MTK_M4U_DOM_ID(0, 1, 0)
+#define M4U_PORT_L1_OVL_2L_RDMA2_HDR MTK_M4U_DOM_ID(0, 1, 1)
+#define M4U_PORT_L1_OVL_2L_RDMA0 MTK_M4U_DOM_ID(0, 1, 2)
+#define M4U_PORT_L1_OVL_2L_RDMA2 MTK_M4U_DOM_ID(0, 1, 3)
+#define M4U_PORT_L1_DISP_MDP_RDMA4 MTK_M4U_DOM_ID(0, 1, 4)
+#define M4U_PORT_L1_DISP_RDMA4 MTK_M4U_DOM_ID(0, 1, 5)
+#define M4U_PORT_L1_DISP_UFBC_WDMA0 MTK_M4U_DOM_ID(0, 1, 6)
+#define M4U_PORT_L1_DISP_FAKE1 MTK_M4U_DOM_ID(0, 1, 7)
+
+/* larb2 */
+#define M4U_PORT_L2_MDP_RDMA0 MTK_M4U_DOM_ID(2, 2, 0)
+#define M4U_PORT_L2_MDP_RDMA1 MTK_M4U_DOM_ID(2, 2, 1)
+#define M4U_PORT_L2_MDP_WROT0 MTK_M4U_DOM_ID(2, 2, 2)
+#define M4U_PORT_L2_MDP_WROT1 MTK_M4U_DOM_ID(2, 2, 3)
+#define M4U_PORT_L2_MDP_DISP_FAKE0 MTK_M4U_DOM_ID(2, 2, 4)
+
+/* larb3: null */
+
+/* larb4 */
+#define M4U_PORT_L4_VDEC_MC_EXT MTK_M4U_DOM_ID(1, 4, 0)
+#define M4U_PORT_L4_VDEC_UFO_EXT MTK_M4U_DOM_ID(1, 4, 1)
+#define M4U_PORT_L4_VDEC_PP_EXT MTK_M4U_DOM_ID(1, 4, 2)
+#define M4U_PORT_L4_VDEC_PRED_RD_EXT MTK_M4U_DOM_ID(1, 4, 3)
+#define M4U_PORT_L4_VDEC_PRED_WR_EXT MTK_M4U_DOM_ID(1, 4, 4)
+#define M4U_PORT_L4_VDEC_PPWRAP_EXT MTK_M4U_DOM_ID(1, 4, 5)
+#define M4U_PORT_L4_VDEC_TILE_EXT MTK_M4U_DOM_ID(1, 4, 6)
+#define M4U_PORT_L4_VDEC_VLD_EXT MTK_M4U_DOM_ID(1, 4, 7)
+#define M4U_PORT_L4_VDEC_VLD2_EXT MTK_M4U_DOM_ID(1, 4, 8)
+#define M4U_PORT_L4_VDEC_AVC_MV_EXT MTK_M4U_DOM_ID(1, 4, 9)
+#define M4U_PORT_L4_VDEC_RG_CTRL_DMA_EXT MTK_M4U_DOM_ID(1, 4, 10)
+
+/* larb5 */
+#define M4U_PORT_L5_VDEC_LAT0_VLD_EXT MTK_M4U_DOM_ID(1, 5, 0)
+#define M4U_PORT_L5_VDEC_LAT0_VLD2_EXT MTK_M4U_DOM_ID(1, 5, 1)
+#define M4U_PORT_L5_VDEC_LAT0_AVC_MV_EXT MTK_M4U_DOM_ID(1, 5, 2)
+#define M4U_PORT_L5_VDEC_LAT0_PRED_RD_EXT MTK_M4U_DOM_ID(1, 5, 3)
+#define M4U_PORT_L5_VDEC_LAT0_TILE_EXT MTK_M4U_DOM_ID(1, 5, 4)
+#define M4U_PORT_L5_VDEC_LAT0_WDMA_EXT MTK_M4U_DOM_ID(1, 5, 5)
+#define M4U_PORT_L5_VDEC_LAT0_RG_CTRL_DMA_EXT MTK_M4U_DOM_ID(1, 5, 6)
+#define M4U_PORT_L5_VDEC_UFO_ENC_EXT MTK_M4U_DOM_ID(1, 5, 7)
+
+/* larb6: null */
+
+/* larb7 */
+#define M4U_PORT_L7_VENC_RCPU MTK_M4U_DOM_ID(1, 7, 0)
+#define M4U_PORT_L7_VENC_REC MTK_M4U_DOM_ID(1, 7, 1)
+#define M4U_PORT_L7_VENC_BSDMA MTK_M4U_DOM_ID(1, 7, 2)
+#define M4U_PORT_L7_VENC_SV_COMV MTK_M4U_DOM_ID(1, 7, 3)
+#define M4U_PORT_L7_VENC_RD_COMV MTK_M4U_DOM_ID(1, 7, 4)
+#define M4U_PORT_L7_VENC_CUR_LUMA MTK_M4U_DOM_ID(1, 7, 5)
+#define M4U_PORT_L7_VENC_CUR_CHROMA MTK_M4U_DOM_ID(1, 7, 6)
+#define M4U_PORT_L7_VENC_REF_LUMA MTK_M4U_DOM_ID(1, 7, 7)
+#define M4U_PORT_L7_VENC_REF_CHROMA MTK_M4U_DOM_ID(1, 7, 8)
+#define M4U_PORT_L7_JPGENC_Y_RDMA MTK_M4U_DOM_ID(1, 7, 9)
+#define M4U_PORT_L7_JPGENC_Q_RDMA MTK_M4U_DOM_ID(1, 7, 10)
+#define M4U_PORT_L7_JPGENC_C_TABLE MTK_M4U_DOM_ID(1, 7, 11)
+#define M4U_PORT_L7_JPGENC_BSDMA MTK_M4U_DOM_ID(1, 7, 12)
+#define M4U_PORT_L7_VENC_SUB_R_LUMA MTK_M4U_DOM_ID(1, 7, 13)
+#define M4U_PORT_L7_VENC_SUB_W_LUMA MTK_M4U_DOM_ID(1, 7, 14)
+
+/* larb8: null */
+
+/* larb9 */
+#define M4U_PORT_L9_IMG_IMGI_D1 MTK_M4U_DOM_ID(2, 9, 0)
+#define M4U_PORT_L9_IMG_IMGBI_D1 MTK_M4U_DOM_ID(2, 9, 1)
+#define M4U_PORT_L9_IMG_DMGI_D1 MTK_M4U_DOM_ID(2, 9, 2)
+#define M4U_PORT_L9_IMG_DEPI_D1 MTK_M4U_DOM_ID(2, 9, 3)
+#define M4U_PORT_L9_IMG_ICE_D1 MTK_M4U_DOM_ID(2, 9, 4)
+#define M4U_PORT_L9_IMG_SMTI_D1 MTK_M4U_DOM_ID(2, 9, 5)
+#define M4U_PORT_L9_IMG_SMTO_D2 MTK_M4U_DOM_ID(2, 9, 6)
+#define M4U_PORT_L9_IMG_SMTO_D1 MTK_M4U_DOM_ID(2, 9, 7)
+#define M4U_PORT_L9_IMG_CRZO_D1 MTK_M4U_DOM_ID(2, 9, 8)
+#define M4U_PORT_L9_IMG_IMG3O_D1 MTK_M4U_DOM_ID(2, 9, 9)
+#define M4U_PORT_L9_IMG_VIPI_D1 MTK_M4U_DOM_ID(2, 9, 10)
+#define M4U_PORT_L9_IMG_SMTI_D5 MTK_M4U_DOM_ID(2, 9, 11)
+#define M4U_PORT_L9_IMG_TIMGO_D1 MTK_M4U_DOM_ID(2, 9, 12)
+#define M4U_PORT_L9_IMG_UFBC_W0 MTK_M4U_DOM_ID(2, 9, 13)
+#define M4U_PORT_L9_IMG_UFBC_R0 MTK_M4U_DOM_ID(2, 9, 14)
+
+/* larb10: null */
+
+/* larb11 */
+#define M4U_PORT_L11_IMG_IMGI_D1 MTK_M4U_DOM_ID(2, 11, 0)
+#define M4U_PORT_L11_IMG_IMGBI_D1 MTK_M4U_DOM_ID(2, 11, 1)
+#define M4U_PORT_L11_IMG_DMGI_D1 MTK_M4U_DOM_ID(2, 11, 2)
+#define M4U_PORT_L11_IMG_DEPI_D1 MTK_M4U_DOM_ID(2, 11, 3)
+#define M4U_PORT_L11_IMG_ICE_D1 MTK_M4U_DOM_ID(2, 11, 4)
+#define M4U_PORT_L11_IMG_SMTI_D1 MTK_M4U_DOM_ID(2, 11, 5)
+#define M4U_PORT_L11_IMG_SMTO_D2 MTK_M4U_DOM_ID(2, 11, 6)
+#define M4U_PORT_L11_IMG_SMTO_D1 MTK_M4U_DOM_ID(2, 11, 7)
+#define M4U_PORT_L11_IMG_CRZO_D1 MTK_M4U_DOM_ID(2, 11, 8)
+#define M4U_PORT_L11_IMG_IMG3O_D1 MTK_M4U_DOM_ID(2, 11, 9)
+#define M4U_PORT_L11_IMG_VIPI_D1 MTK_M4U_DOM_ID(2, 11, 10)
+#define M4U_PORT_L11_IMG_SMTI_D5 MTK_M4U_DOM_ID(2, 11, 11)
+#define M4U_PORT_L11_IMG_TIMGO_D1 MTK_M4U_DOM_ID(2, 11, 12)
+#define M4U_PORT_L11_IMG_UFBC_W0 MTK_M4U_DOM_ID(2, 11, 13)
+#define M4U_PORT_L11_IMG_UFBC_R0 MTK_M4U_DOM_ID(2, 11, 14)
+#define M4U_PORT_L11_IMG_WPE_RDMA1 MTK_M4U_DOM_ID(2, 11, 15)
+#define M4U_PORT_L11_IMG_WPE_RDMA0 MTK_M4U_DOM_ID(2, 11, 16)
+#define M4U_PORT_L11_IMG_WPE_WDMA MTK_M4U_DOM_ID(2, 11, 17)
+#define M4U_PORT_L11_IMG_MFB_RDMA0 MTK_M4U_DOM_ID(2, 11, 18)
+#define M4U_PORT_L11_IMG_MFB_RDMA1 MTK_M4U_DOM_ID(2, 11, 19)
+#define M4U_PORT_L11_IMG_MFB_RDMA2 MTK_M4U_DOM_ID(2, 11, 20)
+#define M4U_PORT_L11_IMG_MFB_RDMA3 MTK_M4U_DOM_ID(2, 11, 21)
+#define M4U_PORT_L11_IMG_MFB_RDMA4 MTK_M4U_DOM_ID(2, 11, 22)
+#define M4U_PORT_L11_IMG_MFB_RDMA5 MTK_M4U_DOM_ID(2, 11, 23)
+#define M4U_PORT_L11_IMG_MFB_WDMA0 MTK_M4U_DOM_ID(2, 11, 24)
+#define M4U_PORT_L11_IMG_MFB_WDMA1 MTK_M4U_DOM_ID(2, 11, 25)
+
+/* larb12: null */
+
+/* larb13 */
+#define M4U_PORT_L13_CAM_MRAWI MTK_M4U_DOM_ID(2, 13, 0)
+#define M4U_PORT_L13_CAM_MRAWO0 MTK_M4U_DOM_ID(2, 13, 1)
+#define M4U_PORT_L13_CAM_MRAWO1 MTK_M4U_DOM_ID(2, 13, 2)
+#define M4U_PORT_L13_CAM_CAMSV1 MTK_M4U_DOM_ID(2, 13, 3)
+#define M4U_PORT_L13_CAM_CAMSV2 MTK_M4U_DOM_ID(2, 13, 4)
+#define M4U_PORT_L13_CAM_CAMSV3 MTK_M4U_DOM_ID(2, 13, 5)
+#define M4U_PORT_L13_CAM_CAMSV4 MTK_M4U_DOM_ID(2, 13, 6)
+#define M4U_PORT_L13_CAM_CAMSV5 MTK_M4U_DOM_ID(2, 13, 7)
+#define M4U_PORT_L13_CAM_CAMSV6 MTK_M4U_DOM_ID(2, 13, 8)
+#define M4U_PORT_L13_CAM_CCUI MTK_M4U_DOM_ID(3, 13, 9)
+#define M4U_PORT_L13_CAM_CCUO MTK_M4U_DOM_ID(3, 13, 10)
+#define M4U_PORT_L13_CAM_FAKE MTK_M4U_DOM_ID(2, 13, 11)
+
+/* larb14 */
+#define M4U_PORT_L14_CAM_RESERVE1 MTK_M4U_DOM_ID(2, 14, 0)
+#define M4U_PORT_L14_CAM_RESERVE2 MTK_M4U_DOM_ID(2, 14, 1)
+#define M4U_PORT_L14_CAM_RESERVE3 MTK_M4U_DOM_ID(2, 14, 2)
+#define M4U_PORT_L14_CAM_CAMSV0 MTK_M4U_DOM_ID(2, 14, 3)
+#define M4U_PORT_L14_CAM_CCUI MTK_M4U_DOM_ID(4, 14, 4)
+#define M4U_PORT_L14_CAM_CCUO MTK_M4U_DOM_ID(4, 14, 5)
+
+/* larb15: null */
+
+/* larb16 */
+#define M4U_PORT_L16_CAM_IMGO_R1_A MTK_M4U_DOM_ID(2, 16, 0)
+#define M4U_PORT_L16_CAM_RRZO_R1_A MTK_M4U_DOM_ID(2, 16, 1)
+#define M4U_PORT_L16_CAM_CQI_R1_A MTK_M4U_DOM_ID(2, 16, 2)
+#define M4U_PORT_L16_CAM_BPCI_R1_A MTK_M4U_DOM_ID(2, 16, 3)
+#define M4U_PORT_L16_CAM_YUVO_R1_A MTK_M4U_DOM_ID(2, 16, 4)
+#define M4U_PORT_L16_CAM_UFDI_R2_A MTK_M4U_DOM_ID(2, 16, 5)
+#define M4U_PORT_L16_CAM_RAWI_R2_A MTK_M4U_DOM_ID(2, 16, 6)
+#define M4U_PORT_L16_CAM_RAWI_R3_A MTK_M4U_DOM_ID(2, 16, 7)
+#define M4U_PORT_L16_CAM_AAO_R1_A MTK_M4U_DOM_ID(2, 16, 8)
+#define M4U_PORT_L16_CAM_AFO_R1_A MTK_M4U_DOM_ID(2, 16, 9)
+#define M4U_PORT_L16_CAM_FLKO_R1_A MTK_M4U_DOM_ID(2, 16, 10)
+#define M4U_PORT_L16_CAM_LCESO_R1_A MTK_M4U_DOM_ID(2, 16, 11)
+#define M4U_PORT_L16_CAM_CRZO_R1_A MTK_M4U_DOM_ID(2, 16, 12)
+#define M4U_PORT_L16_CAM_LTMSO_R1_A MTK_M4U_DOM_ID(2, 16, 13)
+#define M4U_PORT_L16_CAM_RSSO_R1_A MTK_M4U_DOM_ID(2, 16, 14)
+#define M4U_PORT_L16_CAM_AAHO_R1_A MTK_M4U_DOM_ID(2, 16, 15)
+#define M4U_PORT_L16_CAM_LSCI_R1_A MTK_M4U_DOM_ID(2, 16, 16)
+
+/* larb17 */
+#define M4U_PORT_L17_CAM_IMGO_R1_B MTK_M4U_DOM_ID(2, 17, 0)
+#define M4U_PORT_L17_CAM_RRZO_R1_B MTK_M4U_DOM_ID(2, 17, 1)
+#define M4U_PORT_L17_CAM_CQI_R1_B MTK_M4U_DOM_ID(2, 17, 2)
+#define M4U_PORT_L17_CAM_BPCI_R1_B MTK_M4U_DOM_ID(2, 17, 3)
+#define M4U_PORT_L17_CAM_YUVO_R1_B MTK_M4U_DOM_ID(2, 17, 4)
+#define M4U_PORT_L17_CAM_UFDI_R2_B MTK_M4U_DOM_ID(2, 17, 5)
+#define M4U_PORT_L17_CAM_RAWI_R2_B MTK_M4U_DOM_ID(2, 17, 6)
+#define M4U_PORT_L17_CAM_RAWI_R3_B MTK_M4U_DOM_ID(2, 17, 7)
+#define M4U_PORT_L17_CAM_AAO_R1_B MTK_M4U_DOM_ID(2, 17, 8)
+#define M4U_PORT_L17_CAM_AFO_R1_B MTK_M4U_DOM_ID(2, 17, 9)
+#define M4U_PORT_L17_CAM_FLKO_R1_B MTK_M4U_DOM_ID(2, 17, 10)
+#define M4U_PORT_L17_CAM_LCESO_R1_B MTK_M4U_DOM_ID(2, 17, 11)
+#define M4U_PORT_L17_CAM_CRZO_R1_B MTK_M4U_DOM_ID(2, 17, 12)
+#define M4U_PORT_L17_CAM_LTMSO_R1_B MTK_M4U_DOM_ID(2, 17, 13)
+#define M4U_PORT_L17_CAM_RSSO_R1_B MTK_M4U_DOM_ID(2, 17, 14)
+#define M4U_PORT_L17_CAM_AAHO_R1_B MTK_M4U_DOM_ID(2, 17, 15)
+#define M4U_PORT_L17_CAM_LSCI_R1_B MTK_M4U_DOM_ID(2, 17, 16)
+
+/* larb18 */
+#define M4U_PORT_L18_CAM_IMGO_R1_C MTK_M4U_DOM_ID(2, 18, 0)
+#define M4U_PORT_L18_CAM_RRZO_R1_C MTK_M4U_DOM_ID(2, 18, 1)
+#define M4U_PORT_L18_CAM_CQI_R1_C MTK_M4U_DOM_ID(2, 18, 2)
+#define M4U_PORT_L18_CAM_BPCI_R1_C MTK_M4U_DOM_ID(2, 18, 3)
+#define M4U_PORT_L18_CAM_YUVO_R1_C MTK_M4U_DOM_ID(2, 18, 4)
+#define M4U_PORT_L18_CAM_UFDI_R2_C MTK_M4U_DOM_ID(2, 18, 5)
+#define M4U_PORT_L18_CAM_RAWI_R2_C MTK_M4U_DOM_ID(2, 18, 6)
+#define M4U_PORT_L18_CAM_RAWI_R3_C MTK_M4U_DOM_ID(2, 18, 7)
+#define M4U_PORT_L18_CAM_AAO_R1_C MTK_M4U_DOM_ID(2, 18, 8)
+#define M4U_PORT_L18_CAM_AFO_R1_C MTK_M4U_DOM_ID(2, 18, 9)
+#define M4U_PORT_L18_CAM_FLKO_R1_C MTK_M4U_DOM_ID(2, 18, 10)
+#define M4U_PORT_L18_CAM_LCESO_R1_C MTK_M4U_DOM_ID(2, 18, 11)
+#define M4U_PORT_L18_CAM_CRZO_R1_C MTK_M4U_DOM_ID(2, 18, 12)
+#define M4U_PORT_L18_CAM_LTMSO_R1_C MTK_M4U_DOM_ID(2, 18, 13)
+#define M4U_PORT_L18_CAM_RSSO_R1_C MTK_M4U_DOM_ID(2, 18, 14)
+#define M4U_PORT_L18_CAM_AAHO_R1_C MTK_M4U_DOM_ID(2, 18, 15)
+#define M4U_PORT_L18_CAM_LSCI_R1_C MTK_M4U_DOM_ID(2, 18, 16)
+
+/* larb19 */
+#define M4U_PORT_L19_IPE_DVS_RDMA MTK_M4U_DOM_ID(2, 19, 0)
+#define M4U_PORT_L19_IPE_DVS_WDMA MTK_M4U_DOM_ID(2, 19, 1)
+#define M4U_PORT_L19_IPE_DVP_RDMA MTK_M4U_DOM_ID(2, 19, 2)
+#define M4U_PORT_L19_IPE_DVP_WDMA MTK_M4U_DOM_ID(2, 19, 3)
+
+/* larb20 */
+#define M4U_PORT_L20_IPE_FDVT_RDA MTK_M4U_DOM_ID(2, 20, 0)
+#define M4U_PORT_L20_IPE_FDVT_RDB MTK_M4U_DOM_ID(2, 20, 1)
+#define M4U_PORT_L20_IPE_FDVT_WRA MTK_M4U_DOM_ID(2, 20, 2)
+#define M4U_PORT_L20_IPE_FDVT_WRB MTK_M4U_DOM_ID(2, 20, 3)
+#define M4U_PORT_L20_IPE_RSC_RDMA0 MTK_M4U_DOM_ID(2, 20, 4)
+#define M4U_PORT_L20_IPE_RSC_WDMA MTK_M4U_DOM_ID(2, 20, 5)
+
+#endif
--
2.18.0
Put all the macros about smi larb/port togethers, this is a preparing
patch for extending LARB_NR and adding new dom-id support.
Signed-off-by: Yong Wu <[email protected]>
Acked-by: Rob Herring <[email protected]>
---
include/dt-bindings/memory/mt2712-larb-port.h | 2 +-
include/dt-bindings/memory/mt6779-larb-port.h | 2 +-
include/dt-bindings/memory/mt8167-larb-port.h | 2 +-
include/dt-bindings/memory/mt8173-larb-port.h | 2 +-
include/dt-bindings/memory/mt8183-larb-port.h | 2 +-
include/dt-bindings/memory/mtk-smi-larb-port.h | 15 +++++++++++++++
6 files changed, 20 insertions(+), 5 deletions(-)
create mode 100644 include/dt-bindings/memory/mtk-smi-larb-port.h
diff --git a/include/dt-bindings/memory/mt2712-larb-port.h b/include/dt-bindings/memory/mt2712-larb-port.h
index 6f9aa7349cef..b6b2c6bf4459 100644
--- a/include/dt-bindings/memory/mt2712-larb-port.h
+++ b/include/dt-bindings/memory/mt2712-larb-port.h
@@ -6,7 +6,7 @@
#ifndef __DTS_IOMMU_PORT_MT2712_H
#define __DTS_IOMMU_PORT_MT2712_H
-#define MTK_M4U_ID(larb, port) (((larb) << 5) | (port))
+#include <dt-bindings/memory/mtk-smi-larb-port.h>
#define M4U_LARB0_ID 0
#define M4U_LARB1_ID 1
diff --git a/include/dt-bindings/memory/mt6779-larb-port.h b/include/dt-bindings/memory/mt6779-larb-port.h
index 2ad0899fbf2f..60f57f54393e 100644
--- a/include/dt-bindings/memory/mt6779-larb-port.h
+++ b/include/dt-bindings/memory/mt6779-larb-port.h
@@ -7,7 +7,7 @@
#ifndef _DTS_IOMMU_PORT_MT6779_H_
#define _DTS_IOMMU_PORT_MT6779_H_
-#define MTK_M4U_ID(larb, port) (((larb) << 5) | (port))
+#include <dt-bindings/memory/mtk-smi-larb-port.h>
#define M4U_LARB0_ID 0
#define M4U_LARB1_ID 1
diff --git a/include/dt-bindings/memory/mt8167-larb-port.h b/include/dt-bindings/memory/mt8167-larb-port.h
index 000fb299a408..fcb9a49ec60e 100644
--- a/include/dt-bindings/memory/mt8167-larb-port.h
+++ b/include/dt-bindings/memory/mt8167-larb-port.h
@@ -8,7 +8,7 @@
#ifndef __DTS_IOMMU_PORT_MT8167_H
#define __DTS_IOMMU_PORT_MT8167_H
-#define MTK_M4U_ID(larb, port) (((larb) << 5) | (port))
+#include <dt-bindings/memory/mtk-smi-larb-port.h>
#define M4U_LARB0_ID 0
#define M4U_LARB1_ID 1
diff --git a/include/dt-bindings/memory/mt8173-larb-port.h b/include/dt-bindings/memory/mt8173-larb-port.h
index 9f31ccfeca21..d8c99c946053 100644
--- a/include/dt-bindings/memory/mt8173-larb-port.h
+++ b/include/dt-bindings/memory/mt8173-larb-port.h
@@ -6,7 +6,7 @@
#ifndef __DTS_IOMMU_PORT_MT8173_H
#define __DTS_IOMMU_PORT_MT8173_H
-#define MTK_M4U_ID(larb, port) (((larb) << 5) | (port))
+#include <dt-bindings/memory/mtk-smi-larb-port.h>
#define M4U_LARB0_ID 0
#define M4U_LARB1_ID 1
diff --git a/include/dt-bindings/memory/mt8183-larb-port.h b/include/dt-bindings/memory/mt8183-larb-port.h
index 2c579f305162..275c095a6fd6 100644
--- a/include/dt-bindings/memory/mt8183-larb-port.h
+++ b/include/dt-bindings/memory/mt8183-larb-port.h
@@ -6,7 +6,7 @@
#ifndef __DTS_IOMMU_PORT_MT8183_H
#define __DTS_IOMMU_PORT_MT8183_H
-#define MTK_M4U_ID(larb, port) (((larb) << 5) | (port))
+#include <dt-bindings/memory/mtk-smi-larb-port.h>
#define M4U_LARB0_ID 0
#define M4U_LARB1_ID 1
diff --git a/include/dt-bindings/memory/mtk-smi-larb-port.h b/include/dt-bindings/memory/mtk-smi-larb-port.h
new file mode 100644
index 000000000000..2ec7fe5ce4e9
--- /dev/null
+++ b/include/dt-bindings/memory/mtk-smi-larb-port.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ * Author: Yong Wu <[email protected]>
+ */
+#ifndef __DTS_MTK_IOMMU_PORT_H_
+#define __DTS_MTK_IOMMU_PORT_H_
+
+#define MTK_LARB_NR_MAX 16
+
+#define MTK_M4U_ID(larb, port) (((larb) << 5) | (port))
+#define MTK_M4U_TO_LARB(id) (((id) >> 5) & 0xf)
+#define MTK_M4U_TO_PORT(id) ((id) & 0x1f)
+
+#endif
--
2.18.0
Use the ias for the valid iova checking in arm_v7s_unmap. This is a
preparing patch for supporting iova 34bit for MediaTek.
Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/io-pgtable-arm-v7s.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
index a688f22cbe3b..e880745ab1e8 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -717,7 +717,7 @@ static size_t arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova,
{
struct arm_v7s_io_pgtable *data = io_pgtable_ops_to_data(ops);
- if (WARN_ON(upper_32_bits(iova)))
+ if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias)))
return 0;
return __arm_v7s_unmap(data, gather, iova, size, 1, data->pgd);
--
2.18.0
Add "cfg" as a parameter for some macros. This is a preparing patch for
mediatek extend the lvl1 pgtable. No functional change.
Signed-off-by: Yong Wu <[email protected]>
Acked-by: Will Deacon <[email protected]>
---
drivers/iommu/io-pgtable-arm-v7s.c | 36 +++++++++++++++---------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
index 58cc201c10a3..0b3c5b904ddc 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -47,21 +47,21 @@
* and 12 bits in a page.
*/
#define ARM_V7S_ADDR_BITS 32
-#define _ARM_V7S_LVL_BITS(lvl) ((lvl) == 1 ? 12 : 8)
+#define _ARM_V7S_LVL_BITS(lvl, cfg) ((lvl) == 1 ? 12 : 8)
#define ARM_V7S_LVL_SHIFT(lvl) ((lvl) == 1 ? 20 : 12)
#define ARM_V7S_TABLE_SHIFT 10
-#define ARM_V7S_PTES_PER_LVL(lvl) (1 << _ARM_V7S_LVL_BITS(lvl))
-#define ARM_V7S_TABLE_SIZE(lvl) \
- (ARM_V7S_PTES_PER_LVL(lvl) * sizeof(arm_v7s_iopte))
+#define ARM_V7S_PTES_PER_LVL(lvl, cfg) (1 << _ARM_V7S_LVL_BITS(lvl, cfg))
+#define ARM_V7S_TABLE_SIZE(lvl, cfg) \
+ (ARM_V7S_PTES_PER_LVL(lvl, cfg) * sizeof(arm_v7s_iopte))
#define ARM_V7S_BLOCK_SIZE(lvl) (1UL << ARM_V7S_LVL_SHIFT(lvl))
#define ARM_V7S_LVL_MASK(lvl) ((u32)(~0U << ARM_V7S_LVL_SHIFT(lvl)))
#define ARM_V7S_TABLE_MASK ((u32)(~0U << ARM_V7S_TABLE_SHIFT))
-#define _ARM_V7S_IDX_MASK(lvl) (ARM_V7S_PTES_PER_LVL(lvl) - 1)
-#define ARM_V7S_LVL_IDX(addr, lvl) ({ \
+#define _ARM_V7S_IDX_MASK(lvl, cfg) (ARM_V7S_PTES_PER_LVL(lvl, cfg) - 1)
+#define ARM_V7S_LVL_IDX(addr, lvl, cfg) ({ \
int _l = lvl; \
- ((u32)(addr) >> ARM_V7S_LVL_SHIFT(_l)) & _ARM_V7S_IDX_MASK(_l); \
+ ((u32)(addr) >> ARM_V7S_LVL_SHIFT(_l)) & _ARM_V7S_IDX_MASK(_l, cfg); \
})
/*
@@ -237,7 +237,7 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
struct device *dev = cfg->iommu_dev;
phys_addr_t phys;
dma_addr_t dma;
- size_t size = ARM_V7S_TABLE_SIZE(lvl);
+ size_t size = ARM_V7S_TABLE_SIZE(lvl, cfg);
void *table = NULL;
if (lvl == 1)
@@ -283,7 +283,7 @@ static void __arm_v7s_free_table(void *table, int lvl,
{
struct io_pgtable_cfg *cfg = &data->iop.cfg;
struct device *dev = cfg->iommu_dev;
- size_t size = ARM_V7S_TABLE_SIZE(lvl);
+ size_t size = ARM_V7S_TABLE_SIZE(lvl, cfg);
if (!cfg->coherent_walk)
dma_unmap_single(dev, __arm_v7s_dma_addr(table), size,
@@ -427,7 +427,7 @@ static int arm_v7s_init_pte(struct arm_v7s_io_pgtable *data,
arm_v7s_iopte *tblp;
size_t sz = ARM_V7S_BLOCK_SIZE(lvl);
- tblp = ptep - ARM_V7S_LVL_IDX(iova, lvl);
+ tblp = ptep - ARM_V7S_LVL_IDX(iova, lvl, cfg);
if (WARN_ON(__arm_v7s_unmap(data, NULL, iova + i * sz,
sz, lvl, tblp) != sz))
return -EINVAL;
@@ -480,7 +480,7 @@ static int __arm_v7s_map(struct arm_v7s_io_pgtable *data, unsigned long iova,
int num_entries = size >> ARM_V7S_LVL_SHIFT(lvl);
/* Find our entry at the current level */
- ptep += ARM_V7S_LVL_IDX(iova, lvl);
+ ptep += ARM_V7S_LVL_IDX(iova, lvl, cfg);
/* If we can install a leaf entry at this level, then do so */
if (num_entries)
@@ -553,7 +553,7 @@ static void arm_v7s_free_pgtable(struct io_pgtable *iop)
struct arm_v7s_io_pgtable *data = io_pgtable_to_data(iop);
int i;
- for (i = 0; i < ARM_V7S_PTES_PER_LVL(1); i++) {
+ for (i = 0; i < ARM_V7S_PTES_PER_LVL(1, &data->iop.cfg); i++) {
arm_v7s_iopte pte = data->pgd[i];
if (ARM_V7S_PTE_IS_TABLE(pte, 1))
@@ -605,9 +605,9 @@ static size_t arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data,
if (!tablep)
return 0; /* Bytes unmapped */
- num_ptes = ARM_V7S_PTES_PER_LVL(2);
+ num_ptes = ARM_V7S_PTES_PER_LVL(2, cfg);
num_entries = size >> ARM_V7S_LVL_SHIFT(2);
- unmap_idx = ARM_V7S_LVL_IDX(iova, 2);
+ unmap_idx = ARM_V7S_LVL_IDX(iova, 2, cfg);
pte = arm_v7s_prot_to_pte(arm_v7s_pte_to_prot(blk_pte, 1), 2, cfg);
if (num_entries > 1)
@@ -649,7 +649,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
if (WARN_ON(lvl > 2))
return 0;
- idx = ARM_V7S_LVL_IDX(iova, lvl);
+ idx = ARM_V7S_LVL_IDX(iova, lvl, &iop->cfg);
ptep += idx;
do {
pte[i] = READ_ONCE(ptep[i]);
@@ -735,7 +735,7 @@ static phys_addr_t arm_v7s_iova_to_phys(struct io_pgtable_ops *ops,
u32 mask;
do {
- ptep += ARM_V7S_LVL_IDX(iova, ++lvl);
+ ptep += ARM_V7S_LVL_IDX(iova, ++lvl, &data->iop.cfg);
pte = READ_ONCE(*ptep);
ptep = iopte_deref(pte, lvl, data);
} while (ARM_V7S_PTE_IS_TABLE(pte, lvl));
@@ -778,8 +778,8 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
spin_lock_init(&data->split_lock);
data->l2_tables = kmem_cache_create("io-pgtable_armv7s_l2",
- ARM_V7S_TABLE_SIZE(2),
- ARM_V7S_TABLE_SIZE(2),
+ ARM_V7S_TABLE_SIZE(2, cfg),
+ ARM_V7S_TABLE_SIZE(2, cfg),
ARM_V7S_TABLE_SLAB_FLAGS, NULL);
if (!data->l2_tables)
goto out_free_data;
--
2.18.0
Convert MediaTek IOMMU to DT schema.
Signed-off-by: Yong Wu <[email protected]>
---
.../bindings/iommu/mediatek,iommu.txt | 105 -----------
.../bindings/iommu/mediatek,iommu.yaml | 167 ++++++++++++++++++
2 files changed, 167 insertions(+), 105 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
create mode 100644 Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
deleted file mode 100644
index ac949f7fe3d4..000000000000
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+++ /dev/null
@@ -1,105 +0,0 @@
-* Mediatek IOMMU Architecture Implementation
-
- Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U), and
-this M4U have two generations of HW architecture. Generation one uses flat
-pagetable, and only supports 4K size page mapping. Generation two uses the
-ARM Short-Descriptor translation table format for address translation.
-
- About the M4U Hardware Block Diagram, please check below:
-
- EMI (External Memory Interface)
- |
- m4u (Multimedia Memory Management Unit)
- |
- +--------+
- | |
- gals0-rx gals1-rx (Global Async Local Sync rx)
- | |
- | |
- gals0-tx gals1-tx (Global Async Local Sync tx)
- | | Some SoCs may have GALS.
- +--------+
- |
- SMI Common(Smart Multimedia Interface Common)
- |
- +----------------+-------
- | |
- | gals-rx There may be GALS in some larbs.
- | |
- | |
- | gals-tx
- | |
- SMI larb0 SMI larb1 ... SoCs have several SMI local arbiter(larb).
- (display) (vdec)
- | |
- | |
- +-----+-----+ +----+----+
- | | | | | |
- | | |... | | | ... There are different ports in each larb.
- | | | | | |
-OVL0 RDMA0 WDMA0 MC PP VLD
-
- As above, The Multimedia HW will go through SMI and M4U while it
-access EMI. SMI is a bridge between m4u and the Multimedia HW. It contain
-smi local arbiter and smi common. It will control whether the Multimedia
-HW should go though the m4u for translation or bypass it and talk
-directly with EMI. And also SMI help control the power domain and clocks for
-each local arbiter.
- Normally we specify a local arbiter(larb) for each multimedia HW
-like display, video decode, and camera. And there are different ports
-in each larb. Take a example, There are many ports like MC, PP, VLD in the
-video decode local arbiter, all these ports are according to the video HW.
- In some SoCs, there may be a GALS(Global Async Local Sync) module between
-smi-common and m4u, and additional GALS module between smi-larb and
-smi-common. GALS can been seen as a "asynchronous fifo" which could help
-synchronize for the modules in different clock frequency.
-
-Required properties:
-- compatible : must be one of the following string:
- "mediatek,mt2701-m4u" for mt2701 which uses generation one m4u HW.
- "mediatek,mt2712-m4u" for mt2712 which uses generation two m4u HW.
- "mediatek,mt6779-m4u" for mt6779 which uses generation two m4u HW.
- "mediatek,mt7623-m4u", "mediatek,mt2701-m4u" for mt7623 which uses
- generation one m4u HW.
- "mediatek,mt8167-m4u" for mt8167 which uses generation two m4u HW.
- "mediatek,mt8173-m4u" for mt8173 which uses generation two m4u HW.
- "mediatek,mt8183-m4u" for mt8183 which uses generation two m4u HW.
-- reg : m4u register base and size.
-- interrupts : the interrupt of m4u.
-- clocks : must contain one entry for each clock-names.
-- clock-names : Only 1 optional clock:
- - "bclk": the block clock of m4u.
- Here is the list which require this "bclk":
- - mt2701, mt2712, mt7623 and mt8173.
- Note that m4u use the EMI clock which always has been enabled before kernel
- if there is no this "bclk".
-- mediatek,larbs : List of phandle to the local arbiters in the current Socs.
- Refer to bindings/memory-controllers/mediatek,smi-larb.txt. It must sort
- according to the local arbiter index, like larb0, larb1, larb2...
-- iommu-cells : must be 1. This is the mtk_m4u_id according to the HW.
- Specifies the mtk_m4u_id as defined in
- dt-binding/memory/mt2701-larb-port.h for mt2701, mt7623
- dt-binding/memory/mt2712-larb-port.h for mt2712,
- dt-binding/memory/mt6779-larb-port.h for mt6779,
- dt-binding/memory/mt8167-larb-port.h for mt8167,
- dt-binding/memory/mt8173-larb-port.h for mt8173, and
- dt-binding/memory/mt8183-larb-port.h for mt8183.
-
-Example:
- iommu: iommu@10205000 {
- compatible = "mediatek,mt8173-m4u";
- reg = <0 0x10205000 0 0x1000>;
- interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_LOW>;
- clocks = <&infracfg CLK_INFRA_M4U>;
- clock-names = "bclk";
- mediatek,larbs = <&larb0 &larb1 &larb2 &larb3 &larb4 &larb5>;
- #iommu-cells = <1>;
- };
-
-Example for a client device:
- display {
- compatible = "mediatek,mt8173-disp";
- iommus = <&iommu M4U_PORT_DISP_OVL0>,
- <&iommu M4U_PORT_DISP_RDMA0>;
- ...
- };
diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
new file mode 100644
index 000000000000..b9946809fc2b
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
@@ -0,0 +1,167 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iommu/mediatek,iommu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek IOMMU Architecture Implementation
+
+maintainers:
+ - Yong Wu <[email protected]>
+
+description: |+
+ Some MediaTek SOCs contain a Multimedia Memory Management Unit (M4U), and
+ this M4U have two generations of HW architecture. Generation one uses flat
+ pagetable, and only supports 4K size page mapping. Generation two uses the
+ ARM Short-Descriptor translation table format for address translation.
+
+ About the M4U Hardware Block Diagram, please check below:
+
+ EMI (External Memory Interface)
+ |
+ m4u (Multimedia Memory Management Unit)
+ |
+ +--------+
+ | |
+ gals0-rx gals1-rx (Global Async Local Sync rx)
+ | |
+ | |
+ gals0-tx gals1-tx (Global Async Local Sync tx)
+ | | Some SoCs may have GALS.
+ +--------+
+ |
+ SMI Common(Smart Multimedia Interface Common)
+ |
+ +----------------+-------
+ | |
+ | gals-rx There may be GALS in some larbs.
+ | |
+ | |
+ | gals-tx
+ | |
+ SMI larb0 SMI larb1 ... SoCs have several SMI local arbiter(larb).
+ (display) (vdec)
+ | |
+ | |
+ +-----+-----+ +----+----+
+ | | | | | |
+ | | |... | | | ... There are different ports in each larb.
+ | | | | | |
+ OVL0 RDMA0 WDMA0 MC PP VLD
+
+ As above, The Multimedia HW will go through SMI and M4U while it
+ access EMI. SMI is a bridge between m4u and the Multimedia HW. It contain
+ smi local arbiter and smi common. It will control whether the Multimedia
+ HW should go though the m4u for translation or bypass it and talk
+ directly with EMI. And also SMI help control the power domain and clocks for
+ each local arbiter.
+
+ Normally we specify a local arbiter(larb) for each multimedia HW
+ like display, video decode, and camera. And there are different ports
+ in each larb. Take a example, There are many ports like MC, PP, VLD in the
+ video decode local arbiter, all these ports are according to the video HW.
+
+ In some SoCs, there may be a GALS(Global Async Local Sync) module between
+ smi-common and m4u, and additional GALS module between smi-larb and
+ smi-common. GALS can been seen as a "asynchronous fifo" which could help
+ synchronize for the modules in different clock frequency.
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - mediatek,mt2701-m4u # generation one
+ - mediatek,mt2712-m4u # generation two
+ - mediatek,mt6779-m4u # generation two
+ - mediatek,mt8167-m4u # generation two
+ - mediatek,mt8173-m4u # generation two
+ - mediatek,mt8183-m4u # generation two
+
+ - description: mt7623 generation one
+ items:
+ - const: mediatek,mt7623-m4u
+ - const: mediatek,mt2701-m4u
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: bclk is the block clock.
+
+ clock-names:
+ items:
+ - const: bclk
+
+ mediatek,larbs:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ minItems: 1
+ maxItems: 16
+ description: |
+ List of phandle to the local arbiters in the current Socs.
+ Refer to bindings/memory-controllers/mediatek,smi-larb.yaml. It must sort
+ according to the local arbiter index, like larb0, larb1, larb2...
+
+ '#iommu-cells':
+ const: 1
+ description: |
+ This is the mtk_m4u_id according to the HW. Specifies the mtk_m4u_id as
+ defined in
+ dt-binding/memory/mt2701-larb-port.h for mt2701 and mt7623,
+ dt-binding/memory/mt2712-larb-port.h for mt2712,
+ dt-binding/memory/mt6779-larb-port.h for mt6779,
+ dt-binding/memory/mt8167-larb-port.h for mt8167,
+ dt-binding/memory/mt8173-larb-port.h for mt8173,
+ dt-binding/memory/mt8183-larb-port.h for mt8183.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - mediatek,larbs
+ - '#iommu-cells'
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - mediatek,mt2701-m4u
+ - mediatek,mt2712-m4u
+ - mediatek,mt8173-m4u
+
+ then:
+ required:
+ - clocks
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/mt8173-clk.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ iommu: iommu@10205000 {
+ compatible = "mediatek,mt8173-m4u";
+ reg = <0x10205000 0x1000>;
+ interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_M4U>;
+ clock-names = "bclk";
+ mediatek,larbs = <&larb0 &larb1 &larb2
+ &larb3 &larb4 &larb5>;
+ #iommu-cells = <1>;
+ };
+
+ - |
+ #include <dt-bindings/memory/mt8173-larb-port.h>
+
+ /* Example for a client device */
+ display {
+ compatible = "mediatek,mt8173-disp";
+ iommus = <&iommu M4U_PORT_DISP_OVL0>,
+ <&iommu M4U_PORT_DISP_RDMA0>;
+ };
--
2.18.0
The standard input iova bits is 32. MediaTek quad the lvl1 pagetable
(4 * lvl1). No change for lvl2 pagetable. Then the iova bits can reach
34bit.
Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/io-pgtable-arm-v7s.c | 7 ++++---
drivers/iommu/mtk_iommu.c | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
index 0b3c5b904ddc..5601dc8bf810 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -45,9 +45,10 @@
/*
* We have 32 bits total; 12 bits resolved at level 1, 8 bits at level 2,
* and 12 bits in a page.
+ * MediaTek extend 2 bits to reach 34bits, 14 bits at lvl1 and 8 bits at lvl2.
*/
#define ARM_V7S_ADDR_BITS 32
-#define _ARM_V7S_LVL_BITS(lvl, cfg) ((lvl) == 1 ? 12 : 8)
+#define _ARM_V7S_LVL_BITS(lvl, cfg) ((lvl) == 1 ? ((cfg)->ias - 20) : 8)
#define ARM_V7S_LVL_SHIFT(lvl) ((lvl) == 1 ? 20 : 12)
#define ARM_V7S_TABLE_SHIFT 10
@@ -61,7 +62,7 @@
#define _ARM_V7S_IDX_MASK(lvl, cfg) (ARM_V7S_PTES_PER_LVL(lvl, cfg) - 1)
#define ARM_V7S_LVL_IDX(addr, lvl, cfg) ({ \
int _l = lvl; \
- ((u32)(addr) >> ARM_V7S_LVL_SHIFT(_l)) & _ARM_V7S_IDX_MASK(_l, cfg); \
+ ((addr) >> ARM_V7S_LVL_SHIFT(_l)) & _ARM_V7S_IDX_MASK(_l, cfg); \
})
/*
@@ -754,7 +755,7 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
{
struct arm_v7s_io_pgtable *data;
- if (cfg->ias > ARM_V7S_ADDR_BITS)
+ if (cfg->ias > (arm_v7s_is_mtk_enabled(cfg) ? 34 : ARM_V7S_ADDR_BITS))
return NULL;
if (cfg->oas > (arm_v7s_is_mtk_enabled(cfg) ? 35 : ARM_V7S_ADDR_BITS))
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index ec3c87d4b172..55f9b329e637 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -319,7 +319,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom)
IO_PGTABLE_QUIRK_TLBI_ON_MAP |
IO_PGTABLE_QUIRK_ARM_MTK_EXT,
.pgsize_bitmap = mtk_iommu_ops.pgsize_bitmap,
- .ias = 32,
+ .ias = 34,
.oas = 35,
.tlb = &mtk_iommu_flush_ops,
.iommu_dev = data->dev,
--
2.18.0
In attach device, it will update the pagetable base address register.
Move the hw_init function also here. Then it only need call
pm_runtime_get/put one time here if m4u has power domain.
Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/mtk_iommu.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 55f9b329e637..cfdf5ce696fd 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -125,6 +125,8 @@ struct mtk_iommu_domain {
static const struct iommu_ops mtk_iommu_ops;
+static int mtk_iommu_hw_init(const struct mtk_iommu_data *data);
+
/*
* In M4U 4GB mode, the physical address is remapped as below:
*
@@ -380,12 +382,16 @@ 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);
+ int ret;
if (!data)
return -ENODEV;
/* Update the pgtable base address register of the M4U HW */
if (!data->m4u_dom) {
+ ret = mtk_iommu_hw_init(data);
+ if (ret)
+ return ret;
data->m4u_dom = dom;
writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
data->base + REG_MMU_PT_BASE_ADDR);
@@ -729,10 +735,6 @@ static int mtk_iommu_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
- ret = mtk_iommu_hw_init(data);
- if (ret)
- return ret;
-
ret = iommu_device_sysfs_add(&data->iommu, dev, NULL,
"mtk-iommu.%pa", &ioaddr);
if (ret)
--
2.18.0
This patch adds pm runtime callback.
In pm runtime case, all the registers backup/restore and bclk are
controlled in the pm_runtime callback, then pm_suspend is not needed in
this case.
runtime PM is disabled when suspend, thus we call
pm_runtime_status_suspended instead of pm_runtime_suspended.
And, m4u doesn't have its special pm runtime domain in previous SoC, in
this case dev->power.runtime_status is RPM_SUSPENDED defaultly, thus add
a "dev->pm_domain" checking for the SoC that has pm runtime domain.
Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/mtk_iommu.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 4ce7e0883e4d..fe16053eda48 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -802,7 +802,7 @@ static int mtk_iommu_remove(struct platform_device *pdev)
return 0;
}
-static int __maybe_unused mtk_iommu_suspend(struct device *dev)
+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;
@@ -820,7 +820,7 @@ static int __maybe_unused mtk_iommu_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused mtk_iommu_resume(struct device *dev)
+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;
@@ -847,7 +847,25 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
return 0;
}
+static int __maybe_unused mtk_iommu_suspend(struct device *dev)
+{
+ /* runtime PM is disabled when suspend in pm_runtime case. */
+ if (dev->pm_domain && pm_runtime_status_suspended(dev))
+ return 0;
+
+ return mtk_iommu_runtime_suspend(dev);
+}
+
+static int __maybe_unused mtk_iommu_resume(struct device *dev)
+{
+ if (dev->pm_domain && pm_runtime_status_suspended(dev))
+ return 0;
+
+ return mtk_iommu_runtime_resume(dev);
+}
+
static const struct dev_pm_ops mtk_iommu_pm_ops = {
+ SET_RUNTIME_PM_OPS(mtk_iommu_runtime_suspend, mtk_iommu_runtime_resume, NULL)
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume)
};
--
2.18.0
For multiple iommu_domains, we need to reserve some iova regions. Take a
example, If the default iova region is 0 ~ 4G, but the 0x4000_0000 ~
0x43ff_ffff is only for the special CCU0 domain. Thus we should exclude
this region for the default iova region.
This patch adds iova reserved flow. It's a preparing patch for supporting
multi-domain.
Signed-off-by: Anan sun <[email protected]>
Signed-off-by: Chao Hao <[email protected]>
Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/mtk_iommu.c | 28 ++++++++++++++++++++++++++++
drivers/iommu/mtk_iommu.h | 5 +++++
2 files changed, 33 insertions(+)
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 90aae34f4da0..bf3f4e0f4748 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -156,6 +156,11 @@ static LIST_HEAD(m4ulist); /* List all the M4U HWs */
#define for_each_m4u(data) list_for_each_entry(data, &m4ulist, list)
+struct mtk_iommu_iova_region {
+ dma_addr_t iova_base;
+ unsigned long long size;
+};
+
/*
* There may be 1 or 2 M4U HWs, But we always expect they are in the same domain
* for the performance.
@@ -544,6 +549,27 @@ static int mtk_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
return iommu_fwspec_add_ids(dev, args->args, 1);
}
+static void mtk_iommu_get_resv_regions(struct device *dev,
+ struct list_head *head)
+{
+ struct mtk_iommu_data *data = dev_iommu_priv_get(dev);
+ const struct mtk_iommu_iova_region *resv;
+ struct iommu_resv_region *region;
+ int prot = IOMMU_WRITE | IOMMU_READ;
+ unsigned int i;
+
+ for (i = 0; i < data->plat_data->iova_region_nr; i++) {
+ resv = data->plat_data->iova_region + i;
+
+ region = iommu_alloc_resv_region(resv->iova_base, resv->size,
+ prot, IOMMU_RESV_RESERVED);
+ if (!region)
+ return;
+
+ list_add_tail(®ion->list, head);
+ }
+}
+
static const struct iommu_ops mtk_iommu_ops = {
.domain_alloc = mtk_iommu_domain_alloc,
.domain_free = mtk_iommu_domain_free,
@@ -558,6 +584,8 @@ static const struct iommu_ops mtk_iommu_ops = {
.release_device = mtk_iommu_release_device,
.device_group = mtk_iommu_device_group,
.of_xlate = mtk_iommu_of_xlate,
+ .get_resv_regions = mtk_iommu_get_resv_regions,
+ .put_resv_regions = generic_iommu_put_resv_regions,
.pgsize_bitmap = SZ_4K | SZ_64K | SZ_1M | SZ_16M,
};
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 5e03a029c4dc..e867cd3aeeac 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -45,10 +45,15 @@ enum mtk_iommu_plat {
M4U_MT8183,
};
+struct mtk_iommu_iova_region;
+
struct mtk_iommu_plat_data {
enum mtk_iommu_plat m4u_plat;
u32 flags;
u32 inv_sel_reg;
+
+ 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];
};
--
2.18.0
Defaultly the iova range is 0-4G. here we add a single-domain(0-4G)
for the previous SoC. this also is a preparing patch for supporting
multi-domains.
Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/mtk_iommu.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index bf3f4e0f4748..a7727a3899d1 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -161,6 +161,10 @@ struct mtk_iommu_iova_region {
unsigned long long size;
};
+static const struct mtk_iommu_iova_region single_domain[] = {
+ {.iova_base = 0, .size = SZ_4G},
+};
+
/*
* There may be 1 or 2 M4U HWs, But we always expect they are in the same domain
* for the performance.
@@ -922,6 +926,8 @@ static const struct mtk_iommu_plat_data mt2712_data = {
.m4u_plat = M4U_MT2712,
.flags = HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
+ .iova_region = single_domain,
+ .iova_region_nr = ARRAY_SIZE(single_domain),
.larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}},
};
@@ -929,6 +935,8 @@ static const struct mtk_iommu_plat_data mt6779_data = {
.m4u_plat = M4U_MT6779,
.flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN,
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
+ .iova_region = single_domain,
+ .iova_region_nr = ARRAY_SIZE(single_domain),
.larbid_remap = {{0}, {1}, {2}, {3}, {5}, {7, 8}, {10}, {9}},
};
@@ -944,6 +952,8 @@ static const struct mtk_iommu_plat_data mt8173_data = {
.flags = HAS_4GB_MODE | HAS_BCLK | RESET_AXI |
HAS_LEGACY_IVRP_PADDR,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
+ .iova_region = single_domain,
+ .iova_region_nr = ARRAY_SIZE(single_domain),
.larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}}, /* Linear mapping. */
};
@@ -951,6 +961,8 @@ static const struct mtk_iommu_plat_data mt8183_data = {
.m4u_plat = M4U_MT8183,
.flags = RESET_AXI,
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
+ .iova_region = single_domain,
+ .iova_region_nr = ARRAY_SIZE(single_domain),
.larbid_remap = {{0}, {4}, {5}, {6}, {7}, {2}, {3}, {1}},
};
--
2.18.0
If the iova is 34bit, the iova[32][33] is the bit0/1 in the tlb flush
register. Add a new macro for this.
there is a minor change unrelated with this patch. it also use the new
macro.
Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/mtk_iommu.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 46c9143703a9..11af0780e4dd 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -128,6 +128,9 @@ static const struct iommu_ops mtk_iommu_ops;
static int mtk_iommu_hw_init(const struct mtk_iommu_data *data);
+#define MTK_IOMMU_ADDR(addr) ({unsigned long _addr = addr; \
+ (lower_32_bits(_addr) | upper_32_bits(_addr)); })
+
/*
* In M4U 4GB mode, the physical address is remapped as below:
*
@@ -218,8 +221,9 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
data->base + data->plat_data->inv_sel_reg);
- writel_relaxed(iova, data->base + REG_MMU_INVLD_START_A);
- writel_relaxed(iova + size - 1,
+ writel_relaxed(MTK_IOMMU_ADDR(iova),
+ data->base + REG_MMU_INVLD_START_A);
+ writel_relaxed(MTK_IOMMU_ADDR(iova + size - 1),
data->base + REG_MMU_INVLD_END_A);
writel_relaxed(F_MMU_INV_RANGE,
data->base + REG_MMU_INVALIDATE);
@@ -639,8 +643,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
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);
+ regval = MTK_IOMMU_ADDR(data->protect_base);
writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
if (data->enable_4GB &&
--
2.18.0
MediaTek extend the bit5 in lvl1 and lvl2 descriptor as PA34.
Signed-off-by: Yong Wu <[email protected]>
Acked-by: Will Deacon <[email protected]>
---
drivers/iommu/io-pgtable-arm-v7s.c | 9 +++++++--
drivers/iommu/mtk_iommu.c | 2 +-
include/linux/io-pgtable.h | 4 ++--
3 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
index e880745ab1e8..4d0aa079470f 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -112,9 +112,10 @@
#define ARM_V7S_TEX_MASK 0x7
#define ARM_V7S_ATTR_TEX(val) (((val) & ARM_V7S_TEX_MASK) << ARM_V7S_TEX_SHIFT)
-/* MediaTek extend the two bits for PA 32bit/33bit */
+/* MediaTek extend the bits below for PA 32bit/33bit/34bit */
#define ARM_V7S_ATTR_MTK_PA_BIT32 BIT(9)
#define ARM_V7S_ATTR_MTK_PA_BIT33 BIT(4)
+#define ARM_V7S_ATTR_MTK_PA_BIT34 BIT(5)
/* *well, except for TEX on level 2 large pages, of course :( */
#define ARM_V7S_CONT_PAGE_TEX_SHIFT 6
@@ -194,6 +195,8 @@ static arm_v7s_iopte paddr_to_iopte(phys_addr_t paddr, int lvl,
pte |= ARM_V7S_ATTR_MTK_PA_BIT32;
if (paddr & BIT_ULL(33))
pte |= ARM_V7S_ATTR_MTK_PA_BIT33;
+ if (paddr & BIT_ULL(34))
+ pte |= ARM_V7S_ATTR_MTK_PA_BIT34;
return pte;
}
@@ -218,6 +221,8 @@ static phys_addr_t iopte_to_paddr(arm_v7s_iopte pte, int lvl,
paddr |= BIT_ULL(32);
if (pte & ARM_V7S_ATTR_MTK_PA_BIT33)
paddr |= BIT_ULL(33);
+ if (pte & ARM_V7S_ATTR_MTK_PA_BIT34)
+ paddr |= BIT_ULL(34);
return paddr;
}
@@ -754,7 +759,7 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
if (cfg->ias > ARM_V7S_ADDR_BITS)
return NULL;
- if (cfg->oas > (arm_v7s_is_mtk_enabled(cfg) ? 34 : ARM_V7S_ADDR_BITS))
+ if (cfg->oas > (arm_v7s_is_mtk_enabled(cfg) ? 35 : ARM_V7S_ADDR_BITS))
return NULL;
if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS |
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 6451d83753e1..ec3c87d4b172 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -320,7 +320,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom)
IO_PGTABLE_QUIRK_ARM_MTK_EXT,
.pgsize_bitmap = mtk_iommu_ops.pgsize_bitmap,
.ias = 32,
- .oas = 34,
+ .oas = 35,
.tlb = &mtk_iommu_flush_ops,
.iommu_dev = data->dev,
};
diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h
index 4cde111e425b..1ae0757f4f94 100644
--- a/include/linux/io-pgtable.h
+++ b/include/linux/io-pgtable.h
@@ -77,8 +77,8 @@ struct io_pgtable_cfg {
* TLB maintenance when mapping as well as when unmapping.
*
* IO_PGTABLE_QUIRK_ARM_MTK_EXT: (ARM v7s format) MediaTek IOMMUs extend
- * to support up to 34 bits PA where the bit32 and bit33 are
- * encoded in the bit9 and bit4 of the PTE respectively.
+ * to support up to 35 bits PA where the bit32, bit33 and bit34 are
+ * encoded in the bit9, bit4 and bit5 of the PTE respectively.
*
* IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs
* on unmap, for DMA domains using the flush queue mechanism for
--
2.18.0
Add "struct mtk_iommu_data *" in the "struct mtk_iommu_domain",
reduce the call mtk_iommu_get_m4u_data().
No functional change.
Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/mtk_iommu.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index d9a66b2d55e9..355052a98b14 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -125,6 +125,7 @@ struct mtk_iommu_domain {
struct io_pgtable_cfg cfg;
struct io_pgtable_ops *iop;
+ struct mtk_iommu_data *data;
struct iommu_domain domain;
};
@@ -352,7 +353,7 @@ static void mtk_iommu_config(struct mtk_iommu_data *data,
static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom)
{
- struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
+ struct mtk_iommu_data *data = dom->data;
/* Use the exist domain as there is only one m4u pgtable here. */
if (data->m4u_dom) {
@@ -401,6 +402,7 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type)
if (iommu_get_dma_cookie(&dom->domain))
goto free_dom;
+ dom->data = data;
if (mtk_iommu_domain_finalise(dom))
goto put_dma_cookie;
@@ -473,10 +475,9 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
{
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
- struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
/* The "4GB mode" M4U physically can not use the lower remap of Dram. */
- if (data->enable_4GB)
+ if (dom->data->enable_4GB)
paddr |= BIT_ULL(32);
/* Synchronize with the tlb_lock */
@@ -494,31 +495,32 @@ static size_t mtk_iommu_unmap(struct iommu_domain *domain,
static void mtk_iommu_flush_iotlb_all(struct iommu_domain *domain)
{
- mtk_iommu_tlb_flush_all(mtk_iommu_get_m4u_data());
+ struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+
+ mtk_iommu_tlb_flush_all(dom->data);
}
static void mtk_iommu_iotlb_sync(struct iommu_domain *domain,
struct iommu_iotlb_gather *gather)
{
- struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
+ struct mtk_iommu_domain *dom = to_mtk_domain(domain);
size_t length = gather->end - gather->start;
if (gather->start == ULONG_MAX)
return;
mtk_iommu_tlb_flush_range_sync(gather->start, length, gather->pgsize,
- data);
+ dom->data);
}
static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
dma_addr_t iova)
{
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
- struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
phys_addr_t pa;
pa = dom->iop->iova_to_phys(dom->iop, iova);
- if (data->enable_4GB && pa >= MTK_IOMMU_4GB_MODE_REMAP_BASE)
+ if (dom->data->enable_4GB && pa >= MTK_IOMMU_4GB_MODE_REMAP_BASE)
pa &= ~BIT_ULL(32);
return pa;
--
2.18.0
Some HW IP(ex: CCU) require the special iova range. That means the
iova got from dma_alloc_attrs for that devices must locate in his
special range. In this patch, we allocate a special iova_range for
each a special requirement and create each a iommu domain for each
a iova_range.
meanwhile we still use one pagetable which support 16GB iova.
After this patch, If the iova range of a master is over 4G, the master
should:
a) Declare its special dma_ranges in its dtsi node. For example, If we
preassign the iova 4G-8G for vcodec, then the vcodec dtsi node should
add this:
/*
* iova start at 0x1_0000_0000, pa still start at 0x4000_0000
* size is 0x1_0000_0000.
*/
dma-ranges = <0x1 0x0 0x0 0x40000000 0x1 0x0>; /* 4G ~ 8G */
Note: we don't have a actual bus concept here. the master doesn't have its
special parent node, thus this dma-ranges can only be put in the master's
node.
b) Update the dma_mask:
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(33));
Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/mtk_iommu.c | 47 +++++++++++++++++++++++++++++++--------
drivers/iommu/mtk_iommu.h | 3 ++-
2 files changed, 40 insertions(+), 10 deletions(-)
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index fdf08e2d9ed5..d9a66b2d55e9 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -354,6 +354,14 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom)
{
struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
+ /* Use the exist domain as there is only one m4u 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;
+ return 0;
+ }
+
dom->cfg = (struct io_pgtable_cfg) {
.quirks = IO_PGTABLE_QUIRK_ARM_NS |
IO_PGTABLE_QUIRK_NO_PERMS |
@@ -379,6 +387,8 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom)
static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type)
{
+ struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
+ const struct mtk_iommu_iova_region *region;
struct mtk_iommu_domain *dom;
if (type != IOMMU_DOMAIN_DMA)
@@ -394,8 +404,9 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type)
if (mtk_iommu_domain_finalise(dom))
goto put_dma_cookie;
- dom->domain.geometry.aperture_start = 0;
- dom->domain.geometry.aperture_end = DMA_BIT_MASK(32);
+ region = data->plat_data->iova_region + data->cur_domid;
+ 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;
return &dom->domain;
@@ -539,19 +550,31 @@ 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 iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+ struct iommu_group *group;
+ int domid;
if (!data)
return ERR_PTR(-ENODEV);
- /* All the client devices are in the same m4u iommu-group */
- if (!data->m4u_group) {
- data->m4u_group = iommu_group_alloc();
- if (IS_ERR(data->m4u_group))
+ domid = MTK_M4U_TO_DOM(fwspec->ids[0]);
+ if (domid >= data->plat_data->iova_region_nr) {
+ dev_err(dev, "iommu domain id(%d/%d) is error.\n", domid,
+ data->plat_data->iova_region_nr);
+ return ERR_PTR(-EINVAL);
+ }
+
+ group = data->m4u_group[domid];
+ if (!group) {
+ group = iommu_group_alloc();
+ if (IS_ERR(group))
dev_err(dev, "Failed to allocate M4U IOMMU group\n");
+ data->m4u_group[domid] = group;
} else {
- iommu_group_ref_get(data->m4u_group);
+ iommu_group_ref_get(group);
}
- return data->m4u_group;
+ data->cur_domid = domid;
+ return group;
}
static int mtk_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
@@ -580,14 +603,20 @@ static void mtk_iommu_get_resv_regions(struct device *dev,
struct list_head *head)
{
struct mtk_iommu_data *data = dev_iommu_priv_get(dev);
- const struct mtk_iommu_iova_region *resv;
+ const struct mtk_iommu_iova_region *resv, *curdom;
struct iommu_resv_region *region;
int prot = IOMMU_WRITE | IOMMU_READ;
unsigned int i;
+ curdom = data->plat_data->iova_region + data->cur_domid;
for (i = 0; i < data->plat_data->iova_region_nr; i++) {
resv = data->plat_data->iova_region + i;
+ /* Only reserve when the region is in the current domain */
+ if (resv->iova_base <= curdom->iova_base ||
+ resv->iova_base + resv->size >= curdom->iova_base + curdom->size)
+ continue;
+
region = iommu_alloc_resv_region(resv->iova_base, resv->size,
prot, IOMMU_RESV_RESERVED);
if (!region)
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index e867cd3aeeac..b54862307128 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -67,7 +67,7 @@ struct mtk_iommu_data {
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;
+ struct iommu_group *m4u_group[MTK_M4U_DOM_NR_MAX];
bool enable_4GB;
spinlock_t tlb_lock; /* lock for tlb range flush */
@@ -77,6 +77,7 @@ struct mtk_iommu_data {
struct dma_iommu_mapping *mapping; /* For mtk_iommu_v1.c */
+ unsigned int cur_domid;
struct list_head list;
struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX];
};
--
2.18.0
Add mt8192 iommu support.
For multi domain, Add 1M gap for the vdec domain size. That is because
vdec HW has a end address register which require (start_addr +
len) rather than (start_addr + len - 1). Take a example, if the start_addr
is 0xfff00000, size is 0x100000, then the end_address is 0xfff00000 +
0x100000 = 0x1 0000 0000. but the register only is 32bit. thus HW will get
the end address is 0. To avoid this issue, I add 1M gap for this.
Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/mtk_iommu.c | 22 ++++++++++++++++++++++
drivers/iommu/mtk_iommu.h | 1 +
2 files changed, 23 insertions(+)
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 355052a98b14..22f01eea0a61 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -173,6 +173,16 @@ static const struct mtk_iommu_iova_region single_domain[] = {
{.iova_base = 0, .size = SZ_4G},
};
+static const struct mtk_iommu_iova_region mt8192_multi_dom[] = {
+ { .iova_base = 0x0, .size = SZ_4G}, /* disp: 0 ~ 4G */
+ #if IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT)
+ { .iova_base = SZ_4G, .size = SZ_4G - SZ_1M}, /* vdec: 4G ~ 8G gap: 1M */
+ { .iova_base = SZ_4G * 2, .size = SZ_4G - SZ_1M}, /* CAM/MDP: 8G ~ 12G */
+ { .iova_base = 0x240000000ULL, .size = 0x4000000}, /* CCU0 */
+ { .iova_base = 0x244000000ULL, .size = 0x4000000}, /* CCU1 */
+ #endif
+};
+
/*
* There may be 1 or 2 M4U HWs, But we always expect they are in the same domain
* for the performance.
@@ -1019,12 +1029,24 @@ static const struct mtk_iommu_plat_data mt8183_data = {
.larbid_remap = {{0}, {4}, {5}, {6}, {7}, {2}, {3}, {1}},
};
+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,
+ .inv_sel_reg = REG_MMU_INV_SEL_GEN2,
+ .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},
+ {0, 14, 16}, {0, 13, 18, 17}},
+};
+
static const struct of_device_id mtk_iommu_of_ids[] = {
{ .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data},
{ .compatible = "mediatek,mt6779-m4u", .data = &mt6779_data},
{ .compatible = "mediatek,mt8167-m4u", .data = &mt8167_data},
{ .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data},
{ .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data},
+ { .compatible = "mediatek,mt8192-m4u", .data = &mt8192_data},
{}
};
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index b54862307128..e96b1b8639f4 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -43,6 +43,7 @@ enum mtk_iommu_plat {
M4U_MT8167,
M4U_MT8173,
M4U_MT8183,
+ M4U_MT8192,
};
struct mtk_iommu_iova_region;
--
2.18.0
I am the author of MediaTek iommu driver, and will to maintain and
develop it further.
Add myself to cover these items.
Signed-off-by: Yong Wu <[email protected]>
---
MAINTAINERS | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index e73636b75f29..462a87ee19c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11056,6 +11056,15 @@ S: Maintained
F: Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
F: drivers/i2c/busses/i2c-mt65xx.c
+MEDIATEK IOMMU DRIVER
+M: Yong Wu <[email protected]>
+L: [email protected]
+L: [email protected] (moderated for non-subscribers)
+S: Supported
+F: Documentation/devicetree/bindings/iommu/mediatek*
+F: drivers/iommu/mtk-iommu*
+F: include/dt-bindings/memory/mt*-larb-port.h
+
MEDIATEK JPEG DRIVER
M: Rick Chang <[email protected]>
M: Bin Liu <[email protected]>
--
2.18.0
Hi Yong:
Yong Wu <[email protected]> 於 2020年11月11日 週三 下午8:53寫道:
>
> I am the author of MediaTek iommu driver, and will to maintain and
> develop it further.
> Add myself to cover these items.
Reviewed-by: Chun-Kuang Hu <[email protected]>
>
> Signed-off-by: Yong Wu <[email protected]>
> ---
> MAINTAINERS | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e73636b75f29..462a87ee19c8 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -11056,6 +11056,15 @@ S: Maintained
> F: Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
> F: drivers/i2c/busses/i2c-mt65xx.c
>
> +MEDIATEK IOMMU DRIVER
> +M: Yong Wu <[email protected]>
> +L: [email protected]
> +L: [email protected] (moderated for non-subscribers)
> +S: Supported
> +F: Documentation/devicetree/bindings/iommu/mediatek*
> +F: drivers/iommu/mtk-iommu*
> +F: include/dt-bindings/memory/mt*-larb-port.h
> +
> MEDIATEK JPEG DRIVER
> M: Rick Chang <[email protected]>
> M: Bin Liu <[email protected]>
> --
> 2.18.0
> _______________________________________________
> Linux-mediatek mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
On Wed, Nov 11, 2020 at 08:38:16PM +0800, Yong Wu wrote:
> Put all the macros about smi larb/port togethers, this is a preparing
> patch for extending LARB_NR and adding new dom-id support.
>
> Signed-off-by: Yong Wu <[email protected]>
> Acked-by: Rob Herring <[email protected]>
> ---
> include/dt-bindings/memory/mt2712-larb-port.h | 2 +-
> include/dt-bindings/memory/mt6779-larb-port.h | 2 +-
> include/dt-bindings/memory/mt8167-larb-port.h | 2 +-
> include/dt-bindings/memory/mt8173-larb-port.h | 2 +-
> include/dt-bindings/memory/mt8183-larb-port.h | 2 +-
> include/dt-bindings/memory/mtk-smi-larb-port.h | 15 +++++++++++++++
> 6 files changed, 20 insertions(+), 5 deletions(-)
> create mode 100644 include/dt-bindings/memory/mtk-smi-larb-port.h
>
> diff --git a/include/dt-bindings/memory/mt2712-larb-port.h b/include/dt-bindings/memory/mt2712-larb-port.h
Acked-by: Krzysztof Kozlowski <[email protected]>
Best regards,
Krzysztof
On Wed, Nov 11, 2020 at 08:38:17PM +0800, Yong Wu wrote:
> Extend the max larb number definition as mt8192 has larb_nr over 16.
>
> Signed-off-by: Yong Wu <[email protected]>
> Acked-by: Rob Herring <[email protected]>
> ---
> Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml | 2 +-
> include/dt-bindings/memory/mtk-smi-larb-port.h | 4 ++--
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
Acked-by: Krzysztof Kozlowski <[email protected]>
Best regards,
Krzysztof
On Wed, Nov 11, 2020 at 08:38:18PM +0800, Yong Wu wrote:
> In the latest SoC, there are several HW IP require a sepecial iova
> range, mainly CCU and VPU has this requirement. Take CCU as a example,
> CCU require its iova locate in the range(0x4000_0000 ~ 0x43ff_ffff).
>
> In this patch we add a domain definition for the special port. In the
> example of CCU, If we preassign CCU port in domain1, then iommu driver
> will prepare a independent iommu domain of the special iova range for it,
> then the iova got from dma_alloc_attrs(ccu-dev) will locate in its special
> range.
>
> This is a preparing patch for multi-domain support.
>
> Signed-off-by: Yong Wu <[email protected]>
> ---
> include/dt-bindings/memory/mtk-smi-larb-port.h | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
Acked-by: Krzysztof Kozlowski <[email protected]>
Best regards,
Krzysztof
On Wed, Nov 11, 2020 at 08:38:19PM +0800, Yong Wu wrote:
> This patch adds decriptions for mt8192 IOMMU and SMI.
>
> mt8192 also is MTK IOMMU gen2 which uses ARM Short-Descriptor translation
> table format. The M4U-SMI HW diagram is as below:
>
> EMI
> |
> M4U
> |
> ------------
> SMI Common
> ------------
> |
> +-------+------+------+----------------------+-------+
> | | | | ...... | |
> | | | | | |
> larb0 larb1 larb2 larb4 ...... larb19 larb20
> disp0 disp1 mdp vdec IPE IPE
>
> All the connections are HW fixed, SW can NOT adjust it.
>
> mt8192 M4U support 0~16GB iova range. we preassign different engines
> into different iova ranges:
>
> domain-id module iova-range larbs
> 0 disp 0 ~ 4G larb0/1
> 1 vcodec 4G ~ 8G larb4/5/7
> 2 cam/mdp 8G ~ 12G larb2/9/11/13/14/16/17/18/19/20
> 3 CCU0 0x4000_0000 ~ 0x43ff_ffff larb13: port 9/10
> 4 CCU1 0x4400_0000 ~ 0x47ff_ffff larb14: port 4/5
>
> The iova range for CCU0/1(camera control unit) is HW requirement.
>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Rob Herring <[email protected]>
> ---
> .../bindings/iommu/mediatek,iommu.yaml | 18 +-
> include/dt-bindings/memory/mt8192-larb-port.h | 240 ++++++++++++++++++
> 2 files changed, 257 insertions(+), 1 deletion(-)
> create mode 100644 include/dt-bindings/memory/mt8192-larb-port.h
>
> diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
> index ba6626347381..0f26fe14c8e2 100644
> --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
> +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
> @@ -76,6 +76,7 @@ properties:
> - mediatek,mt8167-m4u # generation two
> - mediatek,mt8173-m4u # generation two
> - mediatek,mt8183-m4u # generation two
> + - mediatek,mt8192-m4u # generation two
>
> - description: mt7623 generation one
> items:
> @@ -115,7 +116,11 @@ properties:
> dt-binding/memory/mt6779-larb-port.h for mt6779,
> dt-binding/memory/mt8167-larb-port.h for mt8167,
> dt-binding/memory/mt8173-larb-port.h for mt8173,
> - dt-binding/memory/mt8183-larb-port.h for mt8183.
> + dt-binding/memory/mt8183-larb-port.h for mt8183,
> + dt-binding/memory/mt8192-larb-port.h for mt8192.
> +
> + power-domains:
> + maxItems: 1
>
> required:
> - compatible
> @@ -133,11 +138,22 @@ allOf:
> - mediatek,mt2701-m4u
> - mediatek,mt2712-m4u
> - mediatek,mt8173-m4u
> + - mediatek,mt8192-m4u
>
> then:
> required:
> - clocks
>
> + - if:
> + properties:
> + compatible:
> + enum:
> + - mediatek,mt8192-m4u
> +
> + then:
> + required:
> + - power-domains
> +
> additionalProperties: false
>
> examples:
> diff --git a/include/dt-bindings/memory/mt8192-larb-port.h b/include/dt-bindings/memory/mt8192-larb-port.h
> new file mode 100644
> index 000000000000..7437fa62654e
> --- /dev/null
> +++ b/include/dt-bindings/memory/mt8192-larb-port.h
> @@ -0,0 +1,240 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2020 MediaTek Inc.
> + *
> + * Author: Chao Hao <[email protected]>
> + * Author: Yong Wu <[email protected]>
> + */
> +#ifndef _DTS_IOMMU_PORT_MT8192_H_
> +#define _DTS_IOMMU_PORT_MT8192_H_
Not accurate header guard. Shoud be:
_DT_BINDINGS_MEMORY_MT8192_LARB_PORT_H_
Probably you copied it from some other Mediatek headers - all of them
have header guard pointing to different directory.
Best regards,
Krzysztof
Hi Krzysztof,
On Wed, 2020-11-11 at 22:33 +0100, Krzysztof Kozlowski wrote:
> On Wed, Nov 11, 2020 at 08:38:19PM +0800, Yong Wu wrote:
> > This patch adds decriptions for mt8192 IOMMU and SMI.
> >
> > mt8192 also is MTK IOMMU gen2 which uses ARM Short-Descriptor translation
> > table format. The M4U-SMI HW diagram is as below:
> >
> > EMI
> > |
> > M4U
> > |
> > ------------
> > SMI Common
> > ------------
> > |
> > +-------+------+------+----------------------+-------+
> > | | | | ...... | |
> > | | | | | |
> > larb0 larb1 larb2 larb4 ...... larb19 larb20
> > disp0 disp1 mdp vdec IPE IPE
> >
> > All the connections are HW fixed, SW can NOT adjust it.
> >
> > mt8192 M4U support 0~16GB iova range. we preassign different engines
> > into different iova ranges:
> >
> > domain-id module iova-range larbs
> > 0 disp 0 ~ 4G larb0/1
> > 1 vcodec 4G ~ 8G larb4/5/7
> > 2 cam/mdp 8G ~ 12G larb2/9/11/13/14/16/17/18/19/20
> > 3 CCU0 0x4000_0000 ~ 0x43ff_ffff larb13: port 9/10
> > 4 CCU1 0x4400_0000 ~ 0x47ff_ffff larb14: port 4/5
> >
> > The iova range for CCU0/1(camera control unit) is HW requirement.
> >
> > Signed-off-by: Yong Wu <[email protected]>
> > Reviewed-by: Rob Herring <[email protected]>
> > ---
[...]
> > +#ifndef _DTS_IOMMU_PORT_MT8192_H_
> > +#define _DTS_IOMMU_PORT_MT8192_H_
>
> Not accurate header guard. Shoud be:
> _DT_BINDINGS_MEMORY_MT8192_LARB_PORT_H_
>
> Probably you copied it from some other Mediatek headers - all of them
> have header guard pointing to different directory.
Thanks very much for your reviewing so many patches.
This name like this when it was in the first version. Since it is only
used when the consumer devices enable IOMMU, thus called it
_IOMMU_PORT...
I will use a new patch to rename all of them.
>
> Best regards,
> Krzysztof
On Wed, 11 Nov 2020 20:38:15 +0800, Yong Wu wrote:
> Convert MediaTek IOMMU to DT schema.
>
> Signed-off-by: Yong Wu <[email protected]>
> ---
> .../bindings/iommu/mediatek,iommu.txt | 105 -----------
> .../bindings/iommu/mediatek,iommu.yaml | 167 ++++++++++++++++++
> 2 files changed, 167 insertions(+), 105 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
> create mode 100644 Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
>
Reviewed-by: Rob Herring <[email protected]>
On Wed, 11 Nov 2020 20:38:18 +0800, Yong Wu wrote:
> In the latest SoC, there are several HW IP require a sepecial iova
> range, mainly CCU and VPU has this requirement. Take CCU as a example,
> CCU require its iova locate in the range(0x4000_0000 ~ 0x43ff_ffff).
>
> In this patch we add a domain definition for the special port. In the
> example of CCU, If we preassign CCU port in domain1, then iommu driver
> will prepare a independent iommu domain of the special iova range for it,
> then the iova got from dma_alloc_attrs(ccu-dev) will locate in its special
> range.
>
> This is a preparing patch for multi-domain support.
>
> Signed-off-by: Yong Wu <[email protected]>
> ---
> include/dt-bindings/memory/mtk-smi-larb-port.h | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
Acked-by: Rob Herring <[email protected]>
On Wed, Nov 11, 2020 at 08:38:14PM +0800, Yong Wu wrote:
> This patch mainly adds support for mt8192 Multimedia IOMMU and SMI.
>
> mt8192 also is MTK IOMMU gen2 which uses ARM Short-Descriptor translation
> table format. The M4U-SMI HW diagram is as below:
>
> EMI
> |
> M4U
> |
> ------------
> SMI Common
> ------------
> |
> +-------+------+------+----------------------+-------+
> | | | | ...... | |
> | | | | | |
> larb0 larb1 larb2 larb4 ...... larb19 larb20
> disp0 disp1 mdp vdec IPE IPE
>
> All the connections are HW fixed, SW can NOT adjust it.
>
> Comparing with the preview SoC, this patchset mainly adds two new functions:
> a) add iova 34 bits support.
> b) add multi domains support since several HW has the special iova
> region requirement.
>
> change note:
> v4: a) rebase on v5.10-rc1
> b) Move the smi part to a independent patchset.
> c) Improve v7s code from Robin and Will.
> d) Add a mediatek iommu entry patch in MAINTAINERS.
Please can you post a v5 of this, adding the Acks from v4 and addressing
the build failures reported by the kbuild robot on patch 20?
Thanks,
Will
On 2020-11-11 12:38, Yong Wu wrote:
> MediaTek extend the bit5 in lvl1 and lvl2 descriptor as PA34.
Reviewed-by: Robin Murphy <[email protected]>
> Signed-off-by: Yong Wu <[email protected]>
> Acked-by: Will Deacon <[email protected]>
> ---
> drivers/iommu/io-pgtable-arm-v7s.c | 9 +++++++--
> drivers/iommu/mtk_iommu.c | 2 +-
> include/linux/io-pgtable.h | 4 ++--
> 3 files changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
> index e880745ab1e8..4d0aa079470f 100644
> --- a/drivers/iommu/io-pgtable-arm-v7s.c
> +++ b/drivers/iommu/io-pgtable-arm-v7s.c
> @@ -112,9 +112,10 @@
> #define ARM_V7S_TEX_MASK 0x7
> #define ARM_V7S_ATTR_TEX(val) (((val) & ARM_V7S_TEX_MASK) << ARM_V7S_TEX_SHIFT)
>
> -/* MediaTek extend the two bits for PA 32bit/33bit */
> +/* MediaTek extend the bits below for PA 32bit/33bit/34bit */
> #define ARM_V7S_ATTR_MTK_PA_BIT32 BIT(9)
> #define ARM_V7S_ATTR_MTK_PA_BIT33 BIT(4)
> +#define ARM_V7S_ATTR_MTK_PA_BIT34 BIT(5)
>
> /* *well, except for TEX on level 2 large pages, of course :( */
> #define ARM_V7S_CONT_PAGE_TEX_SHIFT 6
> @@ -194,6 +195,8 @@ static arm_v7s_iopte paddr_to_iopte(phys_addr_t paddr, int lvl,
> pte |= ARM_V7S_ATTR_MTK_PA_BIT32;
> if (paddr & BIT_ULL(33))
> pte |= ARM_V7S_ATTR_MTK_PA_BIT33;
> + if (paddr & BIT_ULL(34))
> + pte |= ARM_V7S_ATTR_MTK_PA_BIT34;
> return pte;
> }
>
> @@ -218,6 +221,8 @@ static phys_addr_t iopte_to_paddr(arm_v7s_iopte pte, int lvl,
> paddr |= BIT_ULL(32);
> if (pte & ARM_V7S_ATTR_MTK_PA_BIT33)
> paddr |= BIT_ULL(33);
> + if (pte & ARM_V7S_ATTR_MTK_PA_BIT34)
> + paddr |= BIT_ULL(34);
> return paddr;
> }
>
> @@ -754,7 +759,7 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
> if (cfg->ias > ARM_V7S_ADDR_BITS)
> return NULL;
>
> - if (cfg->oas > (arm_v7s_is_mtk_enabled(cfg) ? 34 : ARM_V7S_ADDR_BITS))
> + if (cfg->oas > (arm_v7s_is_mtk_enabled(cfg) ? 35 : ARM_V7S_ADDR_BITS))
> return NULL;
>
> if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS |
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 6451d83753e1..ec3c87d4b172 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -320,7 +320,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom)
> IO_PGTABLE_QUIRK_ARM_MTK_EXT,
> .pgsize_bitmap = mtk_iommu_ops.pgsize_bitmap,
> .ias = 32,
> - .oas = 34,
> + .oas = 35,
> .tlb = &mtk_iommu_flush_ops,
> .iommu_dev = data->dev,
> };
> diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h
> index 4cde111e425b..1ae0757f4f94 100644
> --- a/include/linux/io-pgtable.h
> +++ b/include/linux/io-pgtable.h
> @@ -77,8 +77,8 @@ struct io_pgtable_cfg {
> * TLB maintenance when mapping as well as when unmapping.
> *
> * IO_PGTABLE_QUIRK_ARM_MTK_EXT: (ARM v7s format) MediaTek IOMMUs extend
> - * to support up to 34 bits PA where the bit32 and bit33 are
> - * encoded in the bit9 and bit4 of the PTE respectively.
> + * to support up to 35 bits PA where the bit32, bit33 and bit34 are
> + * encoded in the bit9, bit4 and bit5 of the PTE respectively.
> *
> * IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs
> * on unmap, for DMA domains using the flush queue mechanism for
>
On 2020-11-11 12:38, Yong Wu wrote:
> Add "cfg" as a parameter for some macros. This is a preparing patch for
> mediatek extend the lvl1 pgtable. No functional change.
Reviewed-by: Robin Murphy <[email protected]>
> Signed-off-by: Yong Wu <[email protected]>
> Acked-by: Will Deacon <[email protected]>
> ---
> drivers/iommu/io-pgtable-arm-v7s.c | 36 +++++++++++++++---------------
> 1 file changed, 18 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
> index 58cc201c10a3..0b3c5b904ddc 100644
> --- a/drivers/iommu/io-pgtable-arm-v7s.c
> +++ b/drivers/iommu/io-pgtable-arm-v7s.c
> @@ -47,21 +47,21 @@
> * and 12 bits in a page.
> */
> #define ARM_V7S_ADDR_BITS 32
> -#define _ARM_V7S_LVL_BITS(lvl) ((lvl) == 1 ? 12 : 8)
> +#define _ARM_V7S_LVL_BITS(lvl, cfg) ((lvl) == 1 ? 12 : 8)
> #define ARM_V7S_LVL_SHIFT(lvl) ((lvl) == 1 ? 20 : 12)
> #define ARM_V7S_TABLE_SHIFT 10
>
> -#define ARM_V7S_PTES_PER_LVL(lvl) (1 << _ARM_V7S_LVL_BITS(lvl))
> -#define ARM_V7S_TABLE_SIZE(lvl) \
> - (ARM_V7S_PTES_PER_LVL(lvl) * sizeof(arm_v7s_iopte))
> +#define ARM_V7S_PTES_PER_LVL(lvl, cfg) (1 << _ARM_V7S_LVL_BITS(lvl, cfg))
> +#define ARM_V7S_TABLE_SIZE(lvl, cfg) \
> + (ARM_V7S_PTES_PER_LVL(lvl, cfg) * sizeof(arm_v7s_iopte))
>
> #define ARM_V7S_BLOCK_SIZE(lvl) (1UL << ARM_V7S_LVL_SHIFT(lvl))
> #define ARM_V7S_LVL_MASK(lvl) ((u32)(~0U << ARM_V7S_LVL_SHIFT(lvl)))
> #define ARM_V7S_TABLE_MASK ((u32)(~0U << ARM_V7S_TABLE_SHIFT))
> -#define _ARM_V7S_IDX_MASK(lvl) (ARM_V7S_PTES_PER_LVL(lvl) - 1)
> -#define ARM_V7S_LVL_IDX(addr, lvl) ({ \
> +#define _ARM_V7S_IDX_MASK(lvl, cfg) (ARM_V7S_PTES_PER_LVL(lvl, cfg) - 1)
> +#define ARM_V7S_LVL_IDX(addr, lvl, cfg) ({ \
> int _l = lvl; \
> - ((u32)(addr) >> ARM_V7S_LVL_SHIFT(_l)) & _ARM_V7S_IDX_MASK(_l); \
> + ((u32)(addr) >> ARM_V7S_LVL_SHIFT(_l)) & _ARM_V7S_IDX_MASK(_l, cfg); \
> })
>
> /*
> @@ -237,7 +237,7 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
> struct device *dev = cfg->iommu_dev;
> phys_addr_t phys;
> dma_addr_t dma;
> - size_t size = ARM_V7S_TABLE_SIZE(lvl);
> + size_t size = ARM_V7S_TABLE_SIZE(lvl, cfg);
> void *table = NULL;
>
> if (lvl == 1)
> @@ -283,7 +283,7 @@ static void __arm_v7s_free_table(void *table, int lvl,
> {
> struct io_pgtable_cfg *cfg = &data->iop.cfg;
> struct device *dev = cfg->iommu_dev;
> - size_t size = ARM_V7S_TABLE_SIZE(lvl);
> + size_t size = ARM_V7S_TABLE_SIZE(lvl, cfg);
>
> if (!cfg->coherent_walk)
> dma_unmap_single(dev, __arm_v7s_dma_addr(table), size,
> @@ -427,7 +427,7 @@ static int arm_v7s_init_pte(struct arm_v7s_io_pgtable *data,
> arm_v7s_iopte *tblp;
> size_t sz = ARM_V7S_BLOCK_SIZE(lvl);
>
> - tblp = ptep - ARM_V7S_LVL_IDX(iova, lvl);
> + tblp = ptep - ARM_V7S_LVL_IDX(iova, lvl, cfg);
> if (WARN_ON(__arm_v7s_unmap(data, NULL, iova + i * sz,
> sz, lvl, tblp) != sz))
> return -EINVAL;
> @@ -480,7 +480,7 @@ static int __arm_v7s_map(struct arm_v7s_io_pgtable *data, unsigned long iova,
> int num_entries = size >> ARM_V7S_LVL_SHIFT(lvl);
>
> /* Find our entry at the current level */
> - ptep += ARM_V7S_LVL_IDX(iova, lvl);
> + ptep += ARM_V7S_LVL_IDX(iova, lvl, cfg);
>
> /* If we can install a leaf entry at this level, then do so */
> if (num_entries)
> @@ -553,7 +553,7 @@ static void arm_v7s_free_pgtable(struct io_pgtable *iop)
> struct arm_v7s_io_pgtable *data = io_pgtable_to_data(iop);
> int i;
>
> - for (i = 0; i < ARM_V7S_PTES_PER_LVL(1); i++) {
> + for (i = 0; i < ARM_V7S_PTES_PER_LVL(1, &data->iop.cfg); i++) {
> arm_v7s_iopte pte = data->pgd[i];
>
> if (ARM_V7S_PTE_IS_TABLE(pte, 1))
> @@ -605,9 +605,9 @@ static size_t arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data,
> if (!tablep)
> return 0; /* Bytes unmapped */
>
> - num_ptes = ARM_V7S_PTES_PER_LVL(2);
> + num_ptes = ARM_V7S_PTES_PER_LVL(2, cfg);
> num_entries = size >> ARM_V7S_LVL_SHIFT(2);
> - unmap_idx = ARM_V7S_LVL_IDX(iova, 2);
> + unmap_idx = ARM_V7S_LVL_IDX(iova, 2, cfg);
>
> pte = arm_v7s_prot_to_pte(arm_v7s_pte_to_prot(blk_pte, 1), 2, cfg);
> if (num_entries > 1)
> @@ -649,7 +649,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
> if (WARN_ON(lvl > 2))
> return 0;
>
> - idx = ARM_V7S_LVL_IDX(iova, lvl);
> + idx = ARM_V7S_LVL_IDX(iova, lvl, &iop->cfg);
> ptep += idx;
> do {
> pte[i] = READ_ONCE(ptep[i]);
> @@ -735,7 +735,7 @@ static phys_addr_t arm_v7s_iova_to_phys(struct io_pgtable_ops *ops,
> u32 mask;
>
> do {
> - ptep += ARM_V7S_LVL_IDX(iova, ++lvl);
> + ptep += ARM_V7S_LVL_IDX(iova, ++lvl, &data->iop.cfg);
> pte = READ_ONCE(*ptep);
> ptep = iopte_deref(pte, lvl, data);
> } while (ARM_V7S_PTE_IS_TABLE(pte, lvl));
> @@ -778,8 +778,8 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
>
> spin_lock_init(&data->split_lock);
> data->l2_tables = kmem_cache_create("io-pgtable_armv7s_l2",
> - ARM_V7S_TABLE_SIZE(2),
> - ARM_V7S_TABLE_SIZE(2),
> + ARM_V7S_TABLE_SIZE(2, cfg),
> + ARM_V7S_TABLE_SIZE(2, cfg),
> ARM_V7S_TABLE_SLAB_FLAGS, NULL);
> if (!data->l2_tables)
> goto out_free_data;
>
On 2020-11-11 12:38, Yong Wu wrote:
> In attach device, it will update the pagetable base address register.
> Move the hw_init function also here. Then it only need call
> pm_runtime_get/put one time here if m4u has power domain.
Doesn't that mean you'll end up writing most of the registers twice
every time? (first from mtk_iommu_resume(), then again from
mtk_iommu_hw_init())
It might be neater to have mtk_iommu_hw_init() simply populate the
mtk_iommu_suspend_reg data with the initial values at probe time and
manually call mtk_iommu_resume() if the hardware is already powered up
at that point. Or maybe just don't bother saving those registers on
suspend and put the initialisation directly in the resume path.
Robin.
> Signed-off-by: Yong Wu <[email protected]>
> ---
> drivers/iommu/mtk_iommu.c | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 55f9b329e637..cfdf5ce696fd 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -125,6 +125,8 @@ struct mtk_iommu_domain {
>
> static const struct iommu_ops mtk_iommu_ops;
>
> +static int mtk_iommu_hw_init(const struct mtk_iommu_data *data);
> +
> /*
> * In M4U 4GB mode, the physical address is remapped as below:
> *
> @@ -380,12 +382,16 @@ 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);
> + int ret;
>
> if (!data)
> return -ENODEV;
>
> /* Update the pgtable base address register of the M4U HW */
> if (!data->m4u_dom) {
> + ret = mtk_iommu_hw_init(data);
> + if (ret)
> + return ret;
> data->m4u_dom = dom;
> writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
> data->base + REG_MMU_PT_BASE_ADDR);
> @@ -729,10 +735,6 @@ static int mtk_iommu_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, data);
>
> - ret = mtk_iommu_hw_init(data);
> - if (ret)
> - return ret;
> -
> ret = iommu_device_sysfs_add(&data->iommu, dev, NULL,
> "mtk-iommu.%pa", &ioaddr);
> if (ret)
>
On 2020-11-11 12:38, Yong Wu wrote:
> Defaultly the iova range is 0-4G. here we add a single-domain(0-4G)
> for the previous SoC. this also is a preparing patch for supporting
> multi-domains.
>
> Signed-off-by: Yong Wu <[email protected]>
> ---
> drivers/iommu/mtk_iommu.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index bf3f4e0f4748..a7727a3899d1 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -161,6 +161,10 @@ struct mtk_iommu_iova_region {
> unsigned long long size;
> };
>
> +static const struct mtk_iommu_iova_region single_domain[] = {
> + {.iova_base = 0, .size = SZ_4G},
> +};
Hang on, given how the previous patch works, surely this means you're
now going to *reserve* the entire address space? That doesn't seem
right... :/
Robin.
> +
> /*
> * There may be 1 or 2 M4U HWs, But we always expect they are in the same domain
> * for the performance.
> @@ -922,6 +926,8 @@ static const struct mtk_iommu_plat_data mt2712_data = {
> .m4u_plat = M4U_MT2712,
> .flags = HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG,
> .inv_sel_reg = REG_MMU_INV_SEL_GEN1,
> + .iova_region = single_domain,
> + .iova_region_nr = ARRAY_SIZE(single_domain),
> .larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}},
> };
>
> @@ -929,6 +935,8 @@ static const struct mtk_iommu_plat_data mt6779_data = {
> .m4u_plat = M4U_MT6779,
> .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN,
> .inv_sel_reg = REG_MMU_INV_SEL_GEN2,
> + .iova_region = single_domain,
> + .iova_region_nr = ARRAY_SIZE(single_domain),
> .larbid_remap = {{0}, {1}, {2}, {3}, {5}, {7, 8}, {10}, {9}},
> };
>
> @@ -944,6 +952,8 @@ static const struct mtk_iommu_plat_data mt8173_data = {
> .flags = HAS_4GB_MODE | HAS_BCLK | RESET_AXI |
> HAS_LEGACY_IVRP_PADDR,
> .inv_sel_reg = REG_MMU_INV_SEL_GEN1,
> + .iova_region = single_domain,
> + .iova_region_nr = ARRAY_SIZE(single_domain),
> .larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}}, /* Linear mapping. */
> };
>
> @@ -951,6 +961,8 @@ static const struct mtk_iommu_plat_data mt8183_data = {
> .m4u_plat = M4U_MT8183,
> .flags = RESET_AXI,
> .inv_sel_reg = REG_MMU_INV_SEL_GEN1,
> + .iova_region = single_domain,
> + .iova_region_nr = ARRAY_SIZE(single_domain),
> .larbid_remap = {{0}, {4}, {5}, {6}, {7}, {2}, {3}, {1}},
> };
>
>
On 2020-11-11 12:38, Yong Wu wrote:
> Use the ias for the valid iova checking in arm_v7s_unmap. This is a
> preparing patch for supporting iova 34bit for MediaTek.
I can't help thinking of weird ways to generate better code here, but
being consistent with what we already have on the map path is probably
more valuable for now.
Reviewed-by: Robin Murphy <[email protected]>
> Signed-off-by: Yong Wu <[email protected]>
> ---
> drivers/iommu/io-pgtable-arm-v7s.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
> index a688f22cbe3b..e880745ab1e8 100644
> --- a/drivers/iommu/io-pgtable-arm-v7s.c
> +++ b/drivers/iommu/io-pgtable-arm-v7s.c
> @@ -717,7 +717,7 @@ static size_t arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova,
> {
> struct arm_v7s_io_pgtable *data = io_pgtable_ops_to_data(ops);
>
> - if (WARN_ON(upper_32_bits(iova)))
> + if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias)))
> return 0;
>
> return __arm_v7s_unmap(data, gather, iova, size, 1, data->pgd);
>
On 2020-11-11 12:38, Yong Wu wrote:
> The standard input iova bits is 32. MediaTek quad the lvl1 pagetable
> (4 * lvl1). No change for lvl2 pagetable. Then the iova bits can reach
> 34bit.
Yay, I love how simple the actual change becomes now!
Reviewed-by: Robin Murphy <[email protected]>
> Signed-off-by: Yong Wu <[email protected]>
> ---
> drivers/iommu/io-pgtable-arm-v7s.c | 7 ++++---
> drivers/iommu/mtk_iommu.c | 2 +-
> 2 files changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
> index 0b3c5b904ddc..5601dc8bf810 100644
> --- a/drivers/iommu/io-pgtable-arm-v7s.c
> +++ b/drivers/iommu/io-pgtable-arm-v7s.c
> @@ -45,9 +45,10 @@
> /*
> * We have 32 bits total; 12 bits resolved at level 1, 8 bits at level 2,
> * and 12 bits in a page.
> + * MediaTek extend 2 bits to reach 34bits, 14 bits at lvl1 and 8 bits at lvl2.
> */
> #define ARM_V7S_ADDR_BITS 32
> -#define _ARM_V7S_LVL_BITS(lvl, cfg) ((lvl) == 1 ? 12 : 8)
> +#define _ARM_V7S_LVL_BITS(lvl, cfg) ((lvl) == 1 ? ((cfg)->ias - 20) : 8)
> #define ARM_V7S_LVL_SHIFT(lvl) ((lvl) == 1 ? 20 : 12)
> #define ARM_V7S_TABLE_SHIFT 10
>
> @@ -61,7 +62,7 @@
> #define _ARM_V7S_IDX_MASK(lvl, cfg) (ARM_V7S_PTES_PER_LVL(lvl, cfg) - 1)
> #define ARM_V7S_LVL_IDX(addr, lvl, cfg) ({ \
> int _l = lvl; \
> - ((u32)(addr) >> ARM_V7S_LVL_SHIFT(_l)) & _ARM_V7S_IDX_MASK(_l, cfg); \
> + ((addr) >> ARM_V7S_LVL_SHIFT(_l)) & _ARM_V7S_IDX_MASK(_l, cfg); \
> })
>
> /*
> @@ -754,7 +755,7 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
> {
> struct arm_v7s_io_pgtable *data;
>
> - if (cfg->ias > ARM_V7S_ADDR_BITS)
> + if (cfg->ias > (arm_v7s_is_mtk_enabled(cfg) ? 34 : ARM_V7S_ADDR_BITS))
> return NULL;
>
> if (cfg->oas > (arm_v7s_is_mtk_enabled(cfg) ? 35 : ARM_V7S_ADDR_BITS))
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index ec3c87d4b172..55f9b329e637 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -319,7 +319,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom)
> IO_PGTABLE_QUIRK_TLBI_ON_MAP |
> IO_PGTABLE_QUIRK_ARM_MTK_EXT,
> .pgsize_bitmap = mtk_iommu_ops.pgsize_bitmap,
> - .ias = 32,
> + .ias = 34,
> .oas = 35,
> .tlb = &mtk_iommu_flush_ops,
> .iommu_dev = data->dev,
>
On Thu, 2020-11-26 at 17:11 +0000, Robin Murphy wrote:
> On 2020-11-11 12:38, Yong Wu wrote:
> > Defaultly the iova range is 0-4G. here we add a single-domain(0-4G)
> > for the previous SoC. this also is a preparing patch for supporting
> > multi-domains.
> >
> > Signed-off-by: Yong Wu <[email protected]>
> > ---
> > drivers/iommu/mtk_iommu.c | 12 ++++++++++++
> > 1 file changed, 12 insertions(+)
> >
> > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> > index bf3f4e0f4748..a7727a3899d1 100644
> > --- a/drivers/iommu/mtk_iommu.c
> > +++ b/drivers/iommu/mtk_iommu.c
> > @@ -161,6 +161,10 @@ struct mtk_iommu_iova_region {
> > unsigned long long size;
> > };
> >
> > +static const struct mtk_iommu_iova_region single_domain[] = {
> > + {.iova_base = 0, .size = SZ_4G},
> > +};
>
> Hang on, given how the previous patch works, surely this means you're
> now going to *reserve* the entire address space? That doesn't seem
> right... :/
Could you help share more? in which case it is not right?
In the code:
domain->geometry.aperture_end = iova_base + size - 1.
this is same with DMA_BIT_MASK(32). It looks don't change anything.
>
> Robin.
>
> > +
> > /*
> > * There may be 1 or 2 M4U HWs, But we always expect they are in the same domain
> > * for the performance.
> > @@ -922,6 +926,8 @@ static const struct mtk_iommu_plat_data mt2712_data = {
> > .m4u_plat = M4U_MT2712,
> > .flags = HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG,
> > .inv_sel_reg = REG_MMU_INV_SEL_GEN1,
> > + .iova_region = single_domain,
> > + .iova_region_nr = ARRAY_SIZE(single_domain),
> > .larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}},
> > };
> >
> > @@ -929,6 +935,8 @@ static const struct mtk_iommu_plat_data mt6779_data = {
> > .m4u_plat = M4U_MT6779,
> > .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN,
> > .inv_sel_reg = REG_MMU_INV_SEL_GEN2,
> > + .iova_region = single_domain,
> > + .iova_region_nr = ARRAY_SIZE(single_domain),
> > .larbid_remap = {{0}, {1}, {2}, {3}, {5}, {7, 8}, {10}, {9}},
> > };
> >
> > @@ -944,6 +952,8 @@ static const struct mtk_iommu_plat_data mt8173_data = {
> > .flags = HAS_4GB_MODE | HAS_BCLK | RESET_AXI |
> > HAS_LEGACY_IVRP_PADDR,
> > .inv_sel_reg = REG_MMU_INV_SEL_GEN1,
> > + .iova_region = single_domain,
> > + .iova_region_nr = ARRAY_SIZE(single_domain),
> > .larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}}, /* Linear mapping. */
> > };
> >
> > @@ -951,6 +961,8 @@ static const struct mtk_iommu_plat_data mt8183_data = {
> > .m4u_plat = M4U_MT8183,
> > .flags = RESET_AXI,
> > .inv_sel_reg = REG_MMU_INV_SEL_GEN1,
> > + .iova_region = single_domain,
> > + .iova_region_nr = ARRAY_SIZE(single_domain),
> > .larbid_remap = {{0}, {4}, {5}, {6}, {7}, {2}, {3}, {1}},
> > };
> >
> >
On Thu, 2020-11-26 at 16:43 +0000, Robin Murphy wrote:
> On 2020-11-11 12:38, Yong Wu wrote:
> > In attach device, it will update the pagetable base address register.
> > Move the hw_init function also here. Then it only need call
> > pm_runtime_get/put one time here if m4u has power domain.
>
> Doesn't that mean you'll end up writing most of the registers twice
> every time? (first from mtk_iommu_resume(), then again from
> mtk_iommu_hw_init())
I have skipped the first resume from mtk_iommu_resume with the code in
[15/24]:
@@ -828,6 +848,9 @@ static int __maybe_unused
mtk_iommu_runtime_resume(struct device *dev)
+/* Avoid first resume to affect the default value of registers below.*/
+if (!m4u_dom)
+ return 0;
> It might be neater to have mtk_iommu_hw_init() simply populate the
> mtk_iommu_suspend_reg data with the initial values at probe time and
> manually call mtk_iommu_resume() if the hardware is already powered up
> at that point. Or maybe just don't bother saving those registers on
Yes. All the power-domains are enabled in lk when bootup.
Actually I have plan to remove the pm_runtime_get in this attach_device
in the later patchset.
This is for fixing a issue that the screen is turned off when bootup.
In android project. we always show boot image. If iommu call
pm_runtime_get/put here, the display power-domain will be turned off
here given that iommu always probe before display drivers and iommu's
power-domain always is display's power-domain.
Even I plan to move the device's pm_runtime_enable into this
attach_device in the case all the drivers(iommu and display...) build as
modules. it is for skipping turn off display's power-domain in
genpd_power_off_unused.
This is only a plan, I'm not sure if power-domain could fix it like[1].
In this patchset, I'd like to keep current status.
[1]
https://patchwork.kernel.org/project/linux-clk/patch/[email protected]/
> suspend and put the initialisation directly in the resume path.
>
> Robin.
>
> > Signed-off-by: Yong Wu <[email protected]>
> > ---
> > drivers/iommu/mtk_iommu.c | 10 ++++++----
> > 1 file changed, 6 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> > index 55f9b329e637..cfdf5ce696fd 100644
> > --- a/drivers/iommu/mtk_iommu.c
> > +++ b/drivers/iommu/mtk_iommu.c
> > @@ -125,6 +125,8 @@ struct mtk_iommu_domain {
> >
> > static const struct iommu_ops mtk_iommu_ops;
> >
> > +static int mtk_iommu_hw_init(const struct mtk_iommu_data *data);
> > +
> > /*
> > * In M4U 4GB mode, the physical address is remapped as below:
> > *
> > @@ -380,12 +382,16 @@ 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);
> > + int ret;
> >
> > if (!data)
> > return -ENODEV;
> >
> > /* Update the pgtable base address register of the M4U HW */
> > if (!data->m4u_dom) {
> > + ret = mtk_iommu_hw_init(data);
> > + if (ret)
> > + return ret;
> > data->m4u_dom = dom;
> > writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
> > data->base + REG_MMU_PT_BASE_ADDR);
> > @@ -729,10 +735,6 @@ static int mtk_iommu_probe(struct platform_device *pdev)
> >
> > platform_set_drvdata(pdev, data);
> >
> > - ret = mtk_iommu_hw_init(data);
> > - if (ret)
> > - return ret;
> > -
> > ret = iommu_device_sysfs_add(&data->iommu, dev, NULL,
> > "mtk-iommu.%pa", &ioaddr);
> > if (ret)
> >