2019-06-10 12:20:16

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 00/21] MT8183 IOMMU SUPPORT

This patchset mainly adds support for mt8183 IOMMU and SMI.

mt8183 has only one M4U like mt8173 and is also MTK IOMMU gen2 which
uses ARM Short-Descriptor translation table format.

The mt8183 M4U-SMI HW diagram is as below:

EMI
|
M4U
|
----------
| |
gals0-rx gals1-rx
| |
| |
gals0-tx gals1-tx
| |
------------
SMI Common
------------
|
+-----+-----+--------+-----+-----+-------+-------+
| | | | | | | |
| | gals-rx gals-rx | gals-rx gals-rx gals-rx
| | | | | | | |
| | | | | | | |
| | gals-tx gals-tx | gals-tx gals-tx gals-tx
| | | | | | | |
larb0 larb1 IPU0 IPU1 larb4 larb5 larb6 CCU
disp vdec img cam venc img cam

All the connections are HW fixed, SW can NOT adjust it.

Compared with mt8173, we add a GALS(Global Async Local Sync) module
between SMI-common and M4U, and additional GALS between larb2/3/5/6
and SMI-common. GALS can help synchronize for the modules in different
clock frequency, it can be seen as a "asynchronous fifo".

GALS can only help transfer the command/data while it doesn't have
the configuring register, thus it has the special "smi" clock and it
doesn't have the "apb" clock. From the diagram above, we add "gals0"
and "gals1" clocks for smi-common and add a "gals" clock for smi-larb.

From the diagram above, IPU0/IPU1(Image Processor Unit) and CCU(Camera
Control Unit) is connected with smi-common directly, we can take them
as "larb2", "larb3" and "larb7", and their register spaces are
different with the normal larb.

This is the general purpose of each patch in this patchset:
the patch 1..13 add the iommu/smi support for mt8183;
the patch 14..16 add mmu1 support;
the last patches contain some minor changes:
-patch 17 cleanup some smi codes(delete need_larbid).
-patch 18 fix a issue(fix vld_pa_rng).
-patch 19/20 improve the 4GB mode.
-patch 21 switch to SPDX license.
The dtsi was sent at [1].

[1] https://lore.kernel.org/patchwork/patch/1054099/

Change notes:
v7:
1) rebase on v5.2-rc1.
2) Add fixed tags in patch 20.
3) Remove shutdown patch. I will send it independently if necessary.

v6: https://lists.linuxfoundation.org/pipermail/iommu/2019-February/033685.html
1) rebase on v5.0-rc1.
2) About the register name (VLD_PA_RNG), Keep consistent in the patches.
3) In the 4GB mode, Always add MTK_4GB_quirk.
4) Reword some commit message helped from Evan. like common->smi_ao_base is
completely different from common->base; STANDARD_AXI_MODE reg is completely
different from CTRL_MISC; commit in the shutdown patch.
5) Add 2 new patches again:
iommu/mediatek: Rename enable_4GB to dram_is_4gb
iommu/mediatek: Fix iova_to_phys PA start for 4GB mode

v5: https://lists.linuxfoundation.org/pipermail/iommu/2019-January/032387.html
1) Remove this patch "iommu/mediatek: Constify iommu_ops" from here as it
was applied for v5.0.
2) Again, add 3 preparing patches. Move two property into the plat_data.
iommu/mediatek: Move vld_pa_rng into plat_data
iommu/mediatek: Move reset_axi into plat_data
iommu/mediatek: Refine protect memory definition
3) Add shutdown callback for mtk_iommu_v1 in patch[19/20].

v4: http://lists.infradead.org/pipermail/linux-mediatek/2018-December/016205.html
1) Add 3 preparing patches. Seperate some minor meaningful code into
a new patch according to Matthias's suggestion.
memory: mtk-smi: Add gals support
iommu/mediatek: Add larb-id remapped support
iommu/mediatek: Add bclk can be supported optionally
2) rebase on "iommu/mediatek: Make it explicitly non-modular"
which was applied.
https://lore.kernel.org/patchwork/patch/1020125/
3) add some comment about "mediatek,larb-id" in the commit message of
the patch "mtk-smi: Get rid of need_larbid".
4) Fix bus_sel value.

v3: https://lists.linuxfoundation.org/pipermail/iommu/2018-November/031121.html
1) rebase on v4.20-rc1.
2) In the dt-binding, add a minor string "mt7623" which also use gen1
since Matthias added it in v4.20.
3) About v7s:
a) for paddr_to_pte, change the param from "arm_v7s_io_pgtable" to
"arm_pgtable_cfg", according to Robin suggestion.
b) Don't use CONFIG_PHYS_ADDR_T_64BIT.
c) add a little comment(pgtable address still don't over 4GB) in the
commit message of the patch "Extend MediaTek 4GB Mode".
4) add "iommu/mediatek: Constify iommu_ops" into this patchset. this may
be helpful for review and merge.
https://lists.linuxfoundation.org/pipermail/iommu/2018-October/030637.html

v2: https://lists.linuxfoundation.org/pipermail/iommu/2018-September/030164.html
1) Fix typo in the commit message of dt-binding.
2) Change larb2/larb3 to the special larbs.
3) Refactor the larb-id remapped array(larbid_remapped), then we
don't need add the new function(mtk_iommu_get_larbid).
4) Add a new patch for v7s two helpers(paddr_to_iopte and
iopte_to_paddr).
5) Change some comment for MTK 4GB mode.

v1: base on v4.19-rc1.
http://lists.infradead.org/pipermail/linux-mediatek/2018-September/014881.html

Yong Wu (21):
dt-bindings: mediatek: Add binding for mt8183 IOMMU and SMI
iommu/mediatek: Use a struct as the platform data
memory: mtk-smi: Use a general config_port interface
memory: mtk-smi: Use a struct for the platform data for smi-common
iommu/io-pgtable-arm-v7s: Add paddr_to_iopte and iopte_to_paddr
helpers
iommu/io-pgtable-arm-v7s: Extend MediaTek 4GB Mode
iommu/mediatek: Add bclk can be supported optionally
iommu/mediatek: Add larb-id remapped support
iommu/mediatek: Refine protect memory definition
iommu/mediatek: Move reset_axi into plat_data
iommu/mediatek: Move vld_pa_rng into plat_data
memory: mtk-smi: Add gals support
iommu/mediatek: Add mt8183 IOMMU support
iommu/mediatek: Add mmu1 support
memory: mtk-smi: Invoke pm runtime_callback to enable clocks
memory: mtk-smi: Add bus_sel for mt8183
memory: mtk-smi: Get rid of need_larbid
iommu/mediatek: Fix VLD_PA_RNG register backup when suspend
iommu/mediatek: Rename enable_4GB to dram_is_4gb
iommu/mediatek: Fix iova_to_phys PA start for 4GB mode
iommu/mediatek: Switch to SPDX license identifier

.../devicetree/bindings/iommu/mediatek,iommu.txt | 30 ++-
.../memory-controllers/mediatek,smi-common.txt | 12 +-
.../memory-controllers/mediatek,smi-larb.txt | 4 +
drivers/iommu/io-pgtable-arm-v7s.c | 72 ++++--
drivers/iommu/mtk_iommu.c | 166 ++++++++-----
drivers/iommu/mtk_iommu.h | 27 ++-
drivers/iommu/mtk_iommu_v1.c | 12 +-
drivers/memory/mtk-smi.c | 270 ++++++++++++++-------
include/dt-bindings/memory/mt2701-larb-port.h | 10 +-
include/dt-bindings/memory/mt8173-larb-port.h | 10 +-
include/dt-bindings/memory/mt8183-larb-port.h | 130 ++++++++++
include/soc/mediatek/smi.h | 11 +-
12 files changed, 530 insertions(+), 224 deletions(-)
create mode 100644 include/dt-bindings/memory/mt8183-larb-port.h

--
1.9.1


2019-06-10 12:20:28

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 01/21] dt-bindings: mediatek: Add binding for mt8183 IOMMU and SMI

This patch adds decriptions for mt8183 IOMMU and SMI.

mt8183 has only one M4U like mt8173 and is also MTK IOMMU gen2 which
uses ARM Short-Descriptor translation table format.

The mt8183 M4U-SMI HW diagram is as below:

EMI
|
M4U
|
----------
| |
gals0-rx gals1-rx
| |
| |
gals0-tx gals1-tx
| |
------------
SMI Common
------------
|
+-----+-----+--------+-----+-----+-------+-------+
| | | | | | | |
| | gals-rx gals-rx | gals-rx gals-rx gals-rx
| | | | | | | |
| | | | | | | |
| | gals-tx gals-tx | gals-tx gals-tx gals-tx
| | | | | | | |
larb0 larb1 IPU0 IPU1 larb4 larb5 larb6 CCU
disp vdec img cam venc img cam

All the connections are HW fixed, SW can NOT adjust it.

Compared with mt8173, we add a GALS(Global Async Local Sync) module
between SMI-common and M4U, and additional GALS between larb2/3/5/6
and SMI-common. GALS can help synchronize for the modules in different
clock frequency, it can be seen as a "asynchronous fifo".

GALS can only help transfer the command/data while it doesn't have
the configuring register, thus it has the special "smi" clock and it
doesn't have the "apb" clock. From the diagram above, we add "gals0"
and "gals1" clocks for smi-common and add a "gals" clock for smi-larb.

From the diagram above, IPU0/IPU1(Image Processor Unit) and CCU(Camera
Control Unit) is connected with smi-common directly, we can take them
as "larb2", "larb3" and "larb7", and their register spaces are
different with the normal larb.

Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
.../devicetree/bindings/iommu/mediatek,iommu.txt | 30 ++++-
.../memory-controllers/mediatek,smi-common.txt | 12 +-
.../memory-controllers/mediatek,smi-larb.txt | 4 +
include/dt-bindings/memory/mt8183-larb-port.h | 130 +++++++++++++++++++++
4 files changed, 170 insertions(+), 6 deletions(-)
create mode 100644 include/dt-bindings/memory/mt8183-larb-port.h

diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
index 6922db5..ce59a50 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
@@ -11,10 +11,23 @@ ARM Short-Descriptor translation table format for address translation.
|
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)
@@ -36,6 +49,10 @@ each local arbiter.
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:
@@ -44,18 +61,25 @@ Required properties:
"mediatek,mt7623-m4u", "mediatek,mt2701-m4u" for mt7623 which uses
generation one 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 : must be "bclk", It is the block clock of m4u.
+- 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, and
- dt-binding/memory/mt8173-larb-port.h for mt8173.
+ dt-binding/memory/mt2712-larb-port.h for mt2712,
+ dt-binding/memory/mt8173-larb-port.h for mt8173, and
+ dt-binding/memory/mt8183-larb-port.h for mt8183.

Example:
iommu: iommu@10205000 {
diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
index e937ddd..b478ade 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
@@ -2,9 +2,10 @@ SMI (Smart Multimedia Interface) Common

The hardware block diagram please check bindings/iommu/mediatek,iommu.txt

-Mediatek SMI have two generations of HW architecture, mt2712 and mt8173 use
-the second generation of SMI HW while mt2701 uses the first generation HW of
-SMI.
+Mediatek SMI have two generations of HW architecture, here is the list
+which generation the SoCs use:
+generation 1: mt2701 and mt7623.
+generation 2: mt2712, mt8173 and mt8183.

There's slight differences between the two SMI, for generation 2, the
register which control the iommu port is at each larb's register base. But
@@ -19,6 +20,7 @@ Required properties:
"mediatek,mt2712-smi-common"
"mediatek,mt7623-smi-common", "mediatek,mt2701-smi-common"
"mediatek,mt8173-smi-common"
+ "mediatek,mt8183-smi-common"
- reg : the register and size of the SMI block.
- power-domains : a phandle to the power domain of this local arbiter.
- clocks : Must contain an entry for each entry in clock-names.
@@ -30,6 +32,10 @@ Required properties:
They may be the same if both source clocks are the same.
- "async" : asynchronous clock, it help transform the smi clock into the emi
clock domain, this clock is only needed by generation 1 smi HW.
+ and these 2 option clocks for generation 2 smi HW:
+ - "gals0": the path0 clock of GALS(Global Async Local Sync).
+ - "gals1": the path1 clock of GALS(Global Async Local Sync).
+ Here is the list which has this GALS: mt8183.

Example:
smi_common: smi@14022000 {
diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
index 94eddca..4b369b3 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
@@ -8,6 +8,7 @@ Required properties:
"mediatek,mt2712-smi-larb"
"mediatek,mt7623-smi-larb", "mediatek,mt2701-smi-larb"
"mediatek,mt8173-smi-larb"
+ "mediatek,mt8183-smi-larb"
- reg : the register and size of this local arbiter.
- mediatek,smi : a phandle to the smi_common node.
- power-domains : a phandle to the power domain of this local arbiter.
@@ -16,6 +17,9 @@ Required properties:
- "apb" : Advanced Peripheral Bus clock, It's the clock for setting
the register.
- "smi" : It's the clock for transfer data and command.
+ and this optional clock name:
+ - "gals": the clock for GALS(Global Async Local Sync).
+ Here is the list which has this GALS: mt8183.

Required property for mt2701, mt2712 and mt7623:
- mediatek,larb-id :the hardware id of this larb.
diff --git a/include/dt-bindings/memory/mt8183-larb-port.h b/include/dt-bindings/memory/mt8183-larb-port.h
new file mode 100644
index 0000000..2c579f3
--- /dev/null
+++ b/include/dt-bindings/memory/mt8183-larb-port.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Yong Wu <[email protected]>
+ */
+#ifndef __DTS_IOMMU_PORT_MT8183_H
+#define __DTS_IOMMU_PORT_MT8183_H
+
+#define MTK_M4U_ID(larb, port) (((larb) << 5) | (port))
+
+#define M4U_LARB0_ID 0
+#define M4U_LARB1_ID 1
+#define M4U_LARB2_ID 2
+#define M4U_LARB3_ID 3
+#define M4U_LARB4_ID 4
+#define M4U_LARB5_ID 5
+#define M4U_LARB6_ID 6
+#define M4U_LARB7_ID 7
+
+/* larb0 */
+#define M4U_PORT_DISP_OVL0 MTK_M4U_ID(M4U_LARB0_ID, 0)
+#define M4U_PORT_DISP_2L_OVL0_LARB0 MTK_M4U_ID(M4U_LARB0_ID, 1)
+#define M4U_PORT_DISP_2L_OVL1_LARB0 MTK_M4U_ID(M4U_LARB0_ID, 2)
+#define M4U_PORT_DISP_RDMA0 MTK_M4U_ID(M4U_LARB0_ID, 3)
+#define M4U_PORT_DISP_RDMA1 MTK_M4U_ID(M4U_LARB0_ID, 4)
+#define M4U_PORT_DISP_WDMA0 MTK_M4U_ID(M4U_LARB0_ID, 5)
+#define M4U_PORT_MDP_RDMA0 MTK_M4U_ID(M4U_LARB0_ID, 6)
+#define M4U_PORT_MDP_WROT0 MTK_M4U_ID(M4U_LARB0_ID, 7)
+#define M4U_PORT_MDP_WDMA0 MTK_M4U_ID(M4U_LARB0_ID, 8)
+#define M4U_PORT_DISP_FAKE0 MTK_M4U_ID(M4U_LARB0_ID, 9)
+
+/* larb1 */
+#define M4U_PORT_HW_VDEC_MC_EXT MTK_M4U_ID(M4U_LARB1_ID, 0)
+#define M4U_PORT_HW_VDEC_PP_EXT MTK_M4U_ID(M4U_LARB1_ID, 1)
+#define M4U_PORT_HW_VDEC_VLD_EXT MTK_M4U_ID(M4U_LARB1_ID, 2)
+#define M4U_PORT_HW_VDEC_AVC_MV_EXT MTK_M4U_ID(M4U_LARB1_ID, 3)
+#define M4U_PORT_HW_VDEC_PRED_RD_EXT MTK_M4U_ID(M4U_LARB1_ID, 4)
+#define M4U_PORT_HW_VDEC_PRED_WR_EXT MTK_M4U_ID(M4U_LARB1_ID, 5)
+#define M4U_PORT_HW_VDEC_PPWRAP_EXT MTK_M4U_ID(M4U_LARB1_ID, 6)
+
+/* larb2 VPU0 */
+#define M4U_PORT_IMG_IPUO MTK_M4U_ID(M4U_LARB2_ID, 0)
+#define M4U_PORT_IMG_IPU3O MTK_M4U_ID(M4U_LARB2_ID, 1)
+#define M4U_PORT_IMG_IPUI MTK_M4U_ID(M4U_LARB2_ID, 2)
+
+/* larb3 VPU1 */
+#define M4U_PORT_CAM_IPUO MTK_M4U_ID(M4U_LARB3_ID, 0)
+#define M4U_PORT_CAM_IPU2O MTK_M4U_ID(M4U_LARB3_ID, 1)
+#define M4U_PORT_CAM_IPU3O MTK_M4U_ID(M4U_LARB3_ID, 2)
+#define M4U_PORT_CAM_IPUI MTK_M4U_ID(M4U_LARB3_ID, 3)
+#define M4U_PORT_CAM_IPU2I MTK_M4U_ID(M4U_LARB3_ID, 4)
+
+/* larb4 */
+#define M4U_PORT_VENC_RCPU MTK_M4U_ID(M4U_LARB4_ID, 0)
+#define M4U_PORT_VENC_REC MTK_M4U_ID(M4U_LARB4_ID, 1)
+#define M4U_PORT_VENC_BSDMA MTK_M4U_ID(M4U_LARB4_ID, 2)
+#define M4U_PORT_VENC_SV_COMV MTK_M4U_ID(M4U_LARB4_ID, 3)
+#define M4U_PORT_VENC_RD_COMV MTK_M4U_ID(M4U_LARB4_ID, 4)
+#define M4U_PORT_JPGENC_RDMA MTK_M4U_ID(M4U_LARB4_ID, 5)
+#define M4U_PORT_JPGENC_BSDMA MTK_M4U_ID(M4U_LARB4_ID, 6)
+#define M4U_PORT_VENC_CUR_LUMA MTK_M4U_ID(M4U_LARB4_ID, 7)
+#define M4U_PORT_VENC_CUR_CHROMA MTK_M4U_ID(M4U_LARB4_ID, 8)
+#define M4U_PORT_VENC_REF_LUMA MTK_M4U_ID(M4U_LARB4_ID, 9)
+#define M4U_PORT_VENC_REF_CHROMA MTK_M4U_ID(M4U_LARB4_ID, 10)
+
+/* larb5 */
+#define M4U_PORT_CAM_IMGI MTK_M4U_ID(M4U_LARB5_ID, 0)
+#define M4U_PORT_CAM_IMG2O MTK_M4U_ID(M4U_LARB5_ID, 1)
+#define M4U_PORT_CAM_IMG3O MTK_M4U_ID(M4U_LARB5_ID, 2)
+#define M4U_PORT_CAM_VIPI MTK_M4U_ID(M4U_LARB5_ID, 3)
+#define M4U_PORT_CAM_LCEI MTK_M4U_ID(M4U_LARB5_ID, 4)
+#define M4U_PORT_CAM_SMXI MTK_M4U_ID(M4U_LARB5_ID, 5)
+#define M4U_PORT_CAM_SMXO MTK_M4U_ID(M4U_LARB5_ID, 6)
+#define M4U_PORT_CAM_WPE0_RDMA1 MTK_M4U_ID(M4U_LARB5_ID, 7)
+#define M4U_PORT_CAM_WPE0_RDMA0 MTK_M4U_ID(M4U_LARB5_ID, 8)
+#define M4U_PORT_CAM_WPE0_WDMA MTK_M4U_ID(M4U_LARB5_ID, 9)
+#define M4U_PORT_CAM_FDVT_RP MTK_M4U_ID(M4U_LARB5_ID, 10)
+#define M4U_PORT_CAM_FDVT_WR MTK_M4U_ID(M4U_LARB5_ID, 11)
+#define M4U_PORT_CAM_FDVT_RB MTK_M4U_ID(M4U_LARB5_ID, 12)
+#define M4U_PORT_CAM_WPE1_RDMA0 MTK_M4U_ID(M4U_LARB5_ID, 13)
+#define M4U_PORT_CAM_WPE1_RDMA1 MTK_M4U_ID(M4U_LARB5_ID, 14)
+#define M4U_PORT_CAM_WPE1_WDMA MTK_M4U_ID(M4U_LARB5_ID, 15)
+#define M4U_PORT_CAM_DPE_RDMA MTK_M4U_ID(M4U_LARB5_ID, 16)
+#define M4U_PORT_CAM_DPE_WDMA MTK_M4U_ID(M4U_LARB5_ID, 17)
+#define M4U_PORT_CAM_MFB_RDMA0 MTK_M4U_ID(M4U_LARB5_ID, 18)
+#define M4U_PORT_CAM_MFB_RDMA1 MTK_M4U_ID(M4U_LARB5_ID, 19)
+#define M4U_PORT_CAM_MFB_WDMA MTK_M4U_ID(M4U_LARB5_ID, 20)
+#define M4U_PORT_CAM_RSC_RDMA0 MTK_M4U_ID(M4U_LARB5_ID, 21)
+#define M4U_PORT_CAM_RSC_WDMA MTK_M4U_ID(M4U_LARB5_ID, 22)
+#define M4U_PORT_CAM_OWE_RDMA MTK_M4U_ID(M4U_LARB5_ID, 23)
+#define M4U_PORT_CAM_OWE_WDMA MTK_M4U_ID(M4U_LARB5_ID, 24)
+
+/* larb6 */
+#define M4U_PORT_CAM_IMGO MTK_M4U_ID(M4U_LARB6_ID, 0)
+#define M4U_PORT_CAM_RRZO MTK_M4U_ID(M4U_LARB6_ID, 1)
+#define M4U_PORT_CAM_AAO MTK_M4U_ID(M4U_LARB6_ID, 2)
+#define M4U_PORT_CAM_AFO MTK_M4U_ID(M4U_LARB6_ID, 3)
+#define M4U_PORT_CAM_LSCI0 MTK_M4U_ID(M4U_LARB6_ID, 4)
+#define M4U_PORT_CAM_LSCI1 MTK_M4U_ID(M4U_LARB6_ID, 5)
+#define M4U_PORT_CAM_PDO MTK_M4U_ID(M4U_LARB6_ID, 6)
+#define M4U_PORT_CAM_BPCI MTK_M4U_ID(M4U_LARB6_ID, 7)
+#define M4U_PORT_CAM_LCSO MTK_M4U_ID(M4U_LARB6_ID, 8)
+#define M4U_PORT_CAM_CAM_RSSO_A MTK_M4U_ID(M4U_LARB6_ID, 9)
+#define M4U_PORT_CAM_UFEO MTK_M4U_ID(M4U_LARB6_ID, 10)
+#define M4U_PORT_CAM_SOCO MTK_M4U_ID(M4U_LARB6_ID, 11)
+#define M4U_PORT_CAM_SOC1 MTK_M4U_ID(M4U_LARB6_ID, 12)
+#define M4U_PORT_CAM_SOC2 MTK_M4U_ID(M4U_LARB6_ID, 13)
+#define M4U_PORT_CAM_CCUI MTK_M4U_ID(M4U_LARB6_ID, 14)
+#define M4U_PORT_CAM_CCUO MTK_M4U_ID(M4U_LARB6_ID, 15)
+#define M4U_PORT_CAM_RAWI_A MTK_M4U_ID(M4U_LARB6_ID, 16)
+#define M4U_PORT_CAM_CCUG MTK_M4U_ID(M4U_LARB6_ID, 17)
+#define M4U_PORT_CAM_PSO MTK_M4U_ID(M4U_LARB6_ID, 18)
+#define M4U_PORT_CAM_AFO_1 MTK_M4U_ID(M4U_LARB6_ID, 19)
+#define M4U_PORT_CAM_LSCI_2 MTK_M4U_ID(M4U_LARB6_ID, 20)
+#define M4U_PORT_CAM_PDI MTK_M4U_ID(M4U_LARB6_ID, 21)
+#define M4U_PORT_CAM_FLKO MTK_M4U_ID(M4U_LARB6_ID, 22)
+#define M4U_PORT_CAM_LMVO MTK_M4U_ID(M4U_LARB6_ID, 23)
+#define M4U_PORT_CAM_UFGO MTK_M4U_ID(M4U_LARB6_ID, 24)
+#define M4U_PORT_CAM_SPARE MTK_M4U_ID(M4U_LARB6_ID, 25)
+#define M4U_PORT_CAM_SPARE_2 MTK_M4U_ID(M4U_LARB6_ID, 26)
+#define M4U_PORT_CAM_SPARE_3 MTK_M4U_ID(M4U_LARB6_ID, 27)
+#define M4U_PORT_CAM_SPARE_4 MTK_M4U_ID(M4U_LARB6_ID, 28)
+#define M4U_PORT_CAM_SPARE_5 MTK_M4U_ID(M4U_LARB6_ID, 29)
+#define M4U_PORT_CAM_SPARE_6 MTK_M4U_ID(M4U_LARB6_ID, 30)
+
+/* CCU */
+#define M4U_PORT_CCU0 MTK_M4U_ID(M4U_LARB7_ID, 0)
+#define M4U_PORT_CCU1 MTK_M4U_ID(M4U_LARB7_ID, 1)
+
+#endif
--
1.9.1

2019-06-10 12:20:37

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 03/21] memory: mtk-smi: Use a general config_port interface

The config_port of mt2712 and mt8183 are the same. Use a general
config_port interface instead.

In addition, in mt2712, larb8 and larb9 are the bdpsys larbs which
are not the normal larb, their register space are different from the
normal one. thus, we can not call the general config_port. In mt8183,
IPU0/1 and CCU connect with smi-common directly, they also are not
the normal larb. Hence, we add a "larb_direct_to_common_mask" for these
larbs which connect to smi-commmon directly.

This is also a preparing patch for adding mt8183 SMI support.

Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Matthias Brugger <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/memory/mtk-smi.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 8f2d152..9fd6b3d 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -53,6 +53,7 @@ struct mtk_smi_larb_gen {
bool need_larbid;
int port_in_larb[MTK_LARB_NR_MAX + 1];
void (*config_port)(struct device *);
+ unsigned int larb_direct_to_common_mask;
};

struct mtk_smi {
@@ -176,17 +177,13 @@ void mtk_smi_larb_put(struct device *larbdev)
return -ENODEV;
}

-static void mtk_smi_larb_config_port_mt2712(struct device *dev)
+static void mtk_smi_larb_config_port_gen2_general(struct device *dev)
{
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
u32 reg;
int i;

- /*
- * larb 8/9 is the bdpsys larb, the iommu_en is enabled defaultly.
- * Don't need to set it again.
- */
- if (larb->larbid == 8 || larb->larbid == 9)
+ if (BIT(larb->larbid) & larb->larb_gen->larb_direct_to_common_mask)
return;

for_each_set_bit(i, (unsigned long *)larb->mmu, 32) {
@@ -261,7 +258,8 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev)

static const struct mtk_smi_larb_gen mtk_smi_larb_mt2712 = {
.need_larbid = true,
- .config_port = mtk_smi_larb_config_port_mt2712,
+ .config_port = mtk_smi_larb_config_port_gen2_general,
+ .larb_direct_to_common_mask = BIT(8) | BIT(9), /* bdpsys */
};

static const struct of_device_id mtk_smi_larb_of_ids[] = {
--
1.9.1

2019-06-10 12:20:43

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 04/21] memory: mtk-smi: Use a struct for the platform data for smi-common

Use a struct as the platform special data instead of the enumeration.

Also there is a minor change that moving the position of
"enum mtk_smi_gen" definition, this is because we expect define
"struct mtk_smi_common_plat" before it is referred.

This is a preparing patch for mt8183.

Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Matthias Brugger <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/memory/mtk-smi.c | 35 ++++++++++++++++++++++++-----------
1 file changed, 24 insertions(+), 11 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 9fd6b3d..8a2f968 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -49,6 +49,15 @@
#define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4))
#define F_MMU_EN BIT(0)

+enum mtk_smi_gen {
+ MTK_SMI_GEN1,
+ MTK_SMI_GEN2
+};
+
+struct mtk_smi_common_plat {
+ enum mtk_smi_gen gen;
+};
+
struct mtk_smi_larb_gen {
bool need_larbid;
int port_in_larb[MTK_LARB_NR_MAX + 1];
@@ -61,6 +70,8 @@ struct mtk_smi {
struct clk *clk_apb, *clk_smi;
struct clk *clk_async; /*only needed by mt2701*/
void __iomem *smi_ao_base;
+
+ const struct mtk_smi_common_plat *plat;
};

struct mtk_smi_larb { /* larb: local arbiter */
@@ -72,11 +83,6 @@ struct mtk_smi_larb { /* larb: local arbiter */
u32 *mmu;
};

-enum mtk_smi_gen {
- MTK_SMI_GEN1,
- MTK_SMI_GEN2
-};
-
static int mtk_smi_enable(const struct mtk_smi *smi)
{
int ret;
@@ -351,18 +357,26 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
}
};

+static const struct mtk_smi_common_plat mtk_smi_common_gen1 = {
+ .gen = MTK_SMI_GEN1,
+};
+
+static const struct mtk_smi_common_plat mtk_smi_common_gen2 = {
+ .gen = MTK_SMI_GEN2,
+};
+
static const struct of_device_id mtk_smi_common_of_ids[] = {
{
.compatible = "mediatek,mt8173-smi-common",
- .data = (void *)MTK_SMI_GEN2
+ .data = &mtk_smi_common_gen2,
},
{
.compatible = "mediatek,mt2701-smi-common",
- .data = (void *)MTK_SMI_GEN1
+ .data = &mtk_smi_common_gen1,
},
{
.compatible = "mediatek,mt2712-smi-common",
- .data = (void *)MTK_SMI_GEN2
+ .data = &mtk_smi_common_gen2,
},
{}
};
@@ -372,13 +386,13 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct mtk_smi *common;
struct resource *res;
- enum mtk_smi_gen smi_gen;
int ret;

common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL);
if (!common)
return -ENOMEM;
common->dev = dev;
+ common->plat = of_device_get_match_data(dev);

common->clk_apb = devm_clk_get(dev, "apb");
if (IS_ERR(common->clk_apb))
@@ -394,8 +408,7 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
* clock into emi clock domain, but for mtk smi gen2, there's no smi ao
* base.
*/
- smi_gen = (enum mtk_smi_gen)of_device_get_match_data(dev);
- if (smi_gen == MTK_SMI_GEN1) {
+ if (common->plat->gen == MTK_SMI_GEN1) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
common->smi_ao_base = devm_ioremap_resource(dev, res);
if (IS_ERR(common->smi_ao_base))
--
1.9.1

2019-06-10 12:20:48

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 05/21] iommu/io-pgtable-arm-v7s: Add paddr_to_iopte and iopte_to_paddr helpers

Add two helper functions: paddr_to_iopte and iopte_to_paddr.

Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Robin Murphy <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/iommu/io-pgtable-arm-v7s.c | 45 ++++++++++++++++++++++++++++----------
1 file changed, 33 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
index 9a8a887..94c38db 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -180,18 +180,38 @@ struct arm_v7s_io_pgtable {
spinlock_t split_lock;
};

+static bool arm_v7s_pte_is_cont(arm_v7s_iopte pte, int lvl);
+
static dma_addr_t __arm_v7s_dma_addr(void *pages)
{
return (dma_addr_t)virt_to_phys(pages);
}

-static arm_v7s_iopte *iopte_deref(arm_v7s_iopte pte, int lvl)
+static arm_v7s_iopte paddr_to_iopte(phys_addr_t paddr, int lvl,
+ struct io_pgtable_cfg *cfg)
{
+ return paddr & ARM_V7S_LVL_MASK(lvl);
+}
+
+static phys_addr_t iopte_to_paddr(arm_v7s_iopte pte, int lvl,
+ struct io_pgtable_cfg *cfg)
+{
+ arm_v7s_iopte mask;
+
if (ARM_V7S_PTE_IS_TABLE(pte, lvl))
- pte &= ARM_V7S_TABLE_MASK;
+ mask = ARM_V7S_TABLE_MASK;
+ else if (arm_v7s_pte_is_cont(pte, lvl))
+ mask = ARM_V7S_LVL_MASK(lvl) * ARM_V7S_CONT_PAGES;
else
- pte &= ARM_V7S_LVL_MASK(lvl);
- return phys_to_virt(pte);
+ mask = ARM_V7S_LVL_MASK(lvl);
+
+ return pte & mask;
+}
+
+static arm_v7s_iopte *iopte_deref(arm_v7s_iopte pte, int lvl,
+ struct arm_v7s_io_pgtable *data)
+{
+ return phys_to_virt(iopte_to_paddr(pte, lvl, &data->iop.cfg));
}

static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
@@ -407,7 +427,7 @@ static int arm_v7s_init_pte(struct arm_v7s_io_pgtable *data,
if (num_entries > 1)
pte = arm_v7s_pte_to_cont(pte, lvl);

- pte |= paddr & ARM_V7S_LVL_MASK(lvl);
+ pte |= paddr_to_iopte(paddr, lvl, cfg);

__arm_v7s_set_pte(ptep, pte, num_entries, cfg);
return 0;
@@ -473,7 +493,7 @@ static int __arm_v7s_map(struct arm_v7s_io_pgtable *data, unsigned long iova,
}

if (ARM_V7S_PTE_IS_TABLE(pte, lvl)) {
- cptep = iopte_deref(pte, lvl);
+ cptep = iopte_deref(pte, lvl, data);
} else if (pte) {
/* We require an unmap first */
WARN_ON(!selftest_running);
@@ -523,7 +543,8 @@ static void arm_v7s_free_pgtable(struct io_pgtable *iop)
arm_v7s_iopte pte = data->pgd[i];

if (ARM_V7S_PTE_IS_TABLE(pte, 1))
- __arm_v7s_free_table(iopte_deref(pte, 1), 2, data);
+ __arm_v7s_free_table(iopte_deref(pte, 1, data),
+ 2, data);
}
__arm_v7s_free_table(data->pgd, 1, data);
kmem_cache_destroy(data->l2_tables);
@@ -593,7 +614,7 @@ static size_t arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data,
if (!ARM_V7S_PTE_IS_TABLE(pte, 1))
return 0;

- tablep = iopte_deref(pte, 1);
+ tablep = iopte_deref(pte, 1, data);
return __arm_v7s_unmap(data, iova, size, 2, tablep);
}

@@ -652,7 +673,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
io_pgtable_tlb_add_flush(iop, iova, blk_size,
ARM_V7S_BLOCK_SIZE(lvl + 1), false);
io_pgtable_tlb_sync(iop);
- ptep = iopte_deref(pte[i], lvl);
+ ptep = iopte_deref(pte[i], lvl, data);
__arm_v7s_free_table(ptep, lvl + 1, data);
} else if (iop->cfg.quirks & IO_PGTABLE_QUIRK_NON_STRICT) {
/*
@@ -677,7 +698,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
}

/* Keep on walkin' */
- ptep = iopte_deref(pte[0], lvl);
+ ptep = iopte_deref(pte[0], lvl, data);
return __arm_v7s_unmap(data, iova, size, lvl + 1, ptep);
}

@@ -703,7 +724,7 @@ static phys_addr_t arm_v7s_iova_to_phys(struct io_pgtable_ops *ops,
do {
ptep += ARM_V7S_LVL_IDX(iova, ++lvl);
pte = READ_ONCE(*ptep);
- ptep = iopte_deref(pte, lvl);
+ ptep = iopte_deref(pte, lvl, data);
} while (ARM_V7S_PTE_IS_TABLE(pte, lvl));

if (!ARM_V7S_PTE_IS_VALID(pte))
@@ -712,7 +733,7 @@ static phys_addr_t arm_v7s_iova_to_phys(struct io_pgtable_ops *ops,
mask = ARM_V7S_LVL_MASK(lvl);
if (arm_v7s_pte_is_cont(pte, lvl))
mask *= ARM_V7S_CONT_PAGES;
- return (pte & mask) | (iova & ~mask);
+ return iopte_to_paddr(pte, lvl, &data->iop.cfg) | (iova & ~mask);
}

static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
--
1.9.1

2019-06-10 12:21:09

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 07/21] iommu/mediatek: Add bclk can be supported optionally

In some SoCs, M4U doesn't have its "bclk", it will use the EMI
clock instead which has always been enabled when entering kernel.

Currently mt2712 and mt8173 have this bclk while mt8183 doesn't.

This also is a preparing patch for mt8183.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index aff5004..264dda4 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -611,9 +611,11 @@ static int mtk_iommu_probe(struct platform_device *pdev)
if (data->irq < 0)
return data->irq;

- data->bclk = devm_clk_get(dev, "bclk");
- if (IS_ERR(data->bclk))
- return PTR_ERR(data->bclk);
+ if (data->plat_data->has_bclk) {
+ data->bclk = devm_clk_get(dev, "bclk");
+ if (IS_ERR(data->bclk))
+ return PTR_ERR(data->bclk);
+ }

larb_nr = of_count_phandle_with_args(dev->of_node,
"mediatek,larbs", NULL);
@@ -741,11 +743,13 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
static const struct mtk_iommu_plat_data mt2712_data = {
.m4u_plat = M4U_MT2712,
.has_4gb_mode = true,
+ .has_bclk = true,
};

static const struct mtk_iommu_plat_data mt8173_data = {
.m4u_plat = M4U_MT8173,
.has_4gb_mode = true,
+ .has_bclk = true,
};

static const struct of_device_id mtk_iommu_of_ids[] = {
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index d7a001a..63e235e 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -43,6 +43,9 @@ enum mtk_iommu_plat {
struct mtk_iommu_plat_data {
enum mtk_iommu_plat m4u_plat;
bool has_4gb_mode;
+
+ /* HW will use the EMI clock if there isn't the "bclk". */
+ bool has_bclk;
};

struct mtk_iommu_domain;
--
1.9.1

2019-06-10 12:21:12

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 08/21] iommu/mediatek: Add larb-id remapped support

The larb-id may be remapped in the smi-common, this means the
larb-id reported in the mtk_iommu_isr isn't the real larb-id,

Take mt8183 as a example:
M4U
|
---------------------------------------------
| SMI common |
-0-----7-----5-----6-----1-----2------3-----4- <- Id remapped
| | | | | | | |
larb0 larb1 IPU0 IPU1 larb4 larb5 larb6 CCU
disp vdec img cam venc img cam
As above, larb0 connects with the id 0 in smi-common.
larb1 connects with the id 7 in smi-common.
...
If the larb-id reported in the isr is 7, actually it's larb1(vdec).
In order to output the right larb-id in the isr, we add a larb-id
remapping relationship in this patch.

If there is no this larb-id remapping in some SoCs, use the linear
mapping array instead.

This also is a preparing patch for mt8183.

Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Nicolas Boichat <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/iommu/mtk_iommu.c | 4 ++++
drivers/iommu/mtk_iommu.h | 2 ++
2 files changed, 6 insertions(+)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 264dda4..ad838b9 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -220,6 +220,8 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
fault_larb = F_MMU0_INT_ID_LARB_ID(regval);
fault_port = F_MMU0_INT_ID_PORT_ID(regval);

+ fault_larb = data->plat_data->larbid_remap[fault_larb];
+
if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) {
dev_err_ratelimited(
@@ -744,12 +746,14 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
.m4u_plat = M4U_MT2712,
.has_4gb_mode = true,
.has_bclk = true,
+ .larbid_remap = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
};

static const struct mtk_iommu_plat_data mt8173_data = {
.m4u_plat = M4U_MT8173,
.has_4gb_mode = true,
.has_bclk = true,
+ .larbid_remap = {0, 1, 2, 3, 4, 5}, /* Linear mapping. */
};

static const struct of_device_id mtk_iommu_of_ids[] = {
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 63e235e..61fd5d6 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -46,6 +46,8 @@ struct mtk_iommu_plat_data {

/* HW will use the EMI clock if there isn't the "bclk". */
bool has_bclk;
+
+ unsigned char larbid_remap[MTK_LARB_NR_MAX];
};

struct mtk_iommu_domain;
--
1.9.1

2019-06-10 12:21:36

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 10/21] iommu/mediatek: Move reset_axi into plat_data

In mt8173 and mt8183, 0x48 is REG_MMU_STANDARD_AXI_MODE while it is
REG_MMU_CTRL in the other SoCs, and the bits meaning is completely
different with the REG_MMU_STANDARD_AXI_MODE.

This patch moves this property to plat_data, it's also a preparing
patch for mt8183.

Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Nicolas Boichat <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/iommu/mtk_iommu.c | 4 ++--
drivers/iommu/mtk_iommu.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index d38dfa2..8ac7034 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -557,8 +557,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
}
writel_relaxed(0, data->base + REG_MMU_DCM_DIS);

- /* It's MISC control register whose default value is ok except mt8173.*/
- if (data->plat_data->m4u_plat == M4U_MT8173)
+ if (data->plat_data->reset_axi)
writel_relaxed(0, data->base + REG_MMU_STANDARD_AXI_MODE);

if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
@@ -752,6 +751,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
.m4u_plat = M4U_MT8173,
.has_4gb_mode = true,
.has_bclk = true,
+ .reset_axi = true,
.larbid_remap = {0, 1, 2, 3, 4, 5}, /* Linear mapping. */
};

diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 61fd5d6..55d73c1 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -46,7 +46,7 @@ struct mtk_iommu_plat_data {

/* HW will use the EMI clock if there isn't the "bclk". */
bool has_bclk;
-
+ bool reset_axi;
unsigned char larbid_remap[MTK_LARB_NR_MAX];
};

--
1.9.1

2019-06-10 12:21:51

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 11/21] iommu/mediatek: Move vld_pa_rng into plat_data

Both mt8173 and mt8183 don't have this vld_pa_rng(valid physical address
range) register while mt2712 have. Move it into the plat_data.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 8ac7034..a535dcd 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -547,7 +547,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
upper_32_bits(data->protect_base);
writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);

- if (data->enable_4GB && data->plat_data->m4u_plat != M4U_MT8173) {
+ if (data->enable_4GB && data->plat_data->has_vld_pa_rng) {
/*
* If 4GB mode is enabled, the validate PA range is from
* 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
@@ -744,6 +744,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
.m4u_plat = M4U_MT2712,
.has_4gb_mode = true,
.has_bclk = true,
+ .has_vld_pa_rng = true,
.larbid_remap = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
};

diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 55d73c1..e5c9dde 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -47,6 +47,7 @@ struct mtk_iommu_plat_data {
/* HW will use the EMI clock if there isn't the "bclk". */
bool has_bclk;
bool reset_axi;
+ bool has_vld_pa_rng;
unsigned char larbid_remap[MTK_LARB_NR_MAX];
};

--
1.9.1

2019-06-10 12:21:51

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 02/21] iommu/mediatek: Use a struct as the platform data

Use a struct as the platform special data instead of the enumeration.
This is a prepare patch for adding mt8183 iommu support.

Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Matthias Brugger <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/iommu/mtk_iommu.c | 24 ++++++++++++++++--------
drivers/iommu/mtk_iommu.h | 6 +++++-
2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index b66d11b..1ddb2b7 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -54,7 +54,7 @@
#define REG_MMU_CTRL_REG 0x110
#define F_MMU_PREFETCH_RT_REPLACE_MOD BIT(4)
#define F_MMU_TF_PROTECT_SEL_SHIFT(data) \
- ((data)->m4u_plat == M4U_MT2712 ? 4 : 5)
+ ((data)->plat_data->m4u_plat == M4U_MT2712 ? 4 : 5)
/* It's named by F_MMU_TF_PROT_SEL in mt2712. */
#define F_MMU_TF_PROTECT_SEL(prot, data) \
(((prot) & 0x3) << F_MMU_TF_PROTECT_SEL_SHIFT(data))
@@ -520,7 +520,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
}

regval = F_MMU_TF_PROTECT_SEL(2, data);
- if (data->m4u_plat == M4U_MT8173)
+ if (data->plat_data->m4u_plat == M4U_MT8173)
regval |= F_MMU_PREFETCH_RT_REPLACE_MOD;
writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);

@@ -541,14 +541,14 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);

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

- if (data->enable_4GB && data->m4u_plat != M4U_MT8173) {
+ if (data->enable_4GB && data->plat_data->m4u_plat != M4U_MT8173) {
/*
* If 4GB mode is enabled, the validate PA range is from
* 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
@@ -559,7 +559,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
writel_relaxed(0, data->base + REG_MMU_DCM_DIS);

/* It's MISC control register whose default value is ok except mt8173.*/
- if (data->m4u_plat == M4U_MT8173)
+ if (data->plat_data->m4u_plat == M4U_MT8173)
writel_relaxed(0, data->base + REG_MMU_STANDARD_AXI_MODE);

if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
@@ -592,7 +592,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
data->dev = dev;
- data->m4u_plat = (enum mtk_iommu_plat)of_device_get_match_data(dev);
+ data->plat_data = of_device_get_match_data(dev);

/* Protect memory. HW will access here while translation fault.*/
protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL);
@@ -740,9 +740,17 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume)
};

+static const struct mtk_iommu_plat_data mt2712_data = {
+ .m4u_plat = M4U_MT2712,
+};
+
+static const struct mtk_iommu_plat_data mt8173_data = {
+ .m4u_plat = M4U_MT8173,
+};
+
static const struct of_device_id mtk_iommu_of_ids[] = {
- { .compatible = "mediatek,mt2712-m4u", .data = (void *)M4U_MT2712},
- { .compatible = "mediatek,mt8173-m4u", .data = (void *)M4U_MT8173},
+ { .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data},
+ { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data},
{}
};

diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 62c2c3e..483d210 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -40,6 +40,10 @@ enum mtk_iommu_plat {
M4U_MT8173,
};

+struct mtk_iommu_plat_data {
+ enum mtk_iommu_plat m4u_plat;
+};
+
struct mtk_iommu_domain;

struct mtk_iommu_data {
@@ -56,7 +60,7 @@ struct mtk_iommu_data {
bool tlb_flush_active;

struct iommu_device iommu;
- enum mtk_iommu_plat m4u_plat;
+ const struct mtk_iommu_plat_data *plat_data;

struct list_head list;
};
--
1.9.1

2019-06-10 12:22:00

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 12/21] memory: mtk-smi: Add gals support

In some SoCs like mt8183, SMI add GALS(Global Async Local Sync) module
which can help synchronize for the modules in different clock frequency.
It can be seen as a "asynchronous fifo". This is a example diagram:

M4U
|
----------
| |
gals0-rx gals1-rx
| |
| |
gals0-tx gals1-tx
| |
------------
SMI Common
------------
|
+-----+--------+-----+- ...
| | | |
| gals-rx gals-rx |
| | | |
| | | |
| gals-tx gals-tx |
| | | |
larb1 larb2 larb3 larb4

GALS only help transfer the command/data while it doesn't have the
configuring register, thus it has the special "smi" clock and doesn't
have the "apb" clock. From the diagram above, we add "gals0" and
"gals1" clocks for smi-common and add a "gals" clock for smi-larb.

This patch adds gals clock supporting in the SMI. Note that some larbs
may still don't have the "gals" clock like larb1 and larb4 above.

This is also a preparing patch for mt8183 which has GALS.

CC: Matthias Brugger <[email protected]>
Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/memory/mtk-smi.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 8a2f968..91634d7 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -56,6 +56,7 @@ enum mtk_smi_gen {

struct mtk_smi_common_plat {
enum mtk_smi_gen gen;
+ bool has_gals;
};

struct mtk_smi_larb_gen {
@@ -63,11 +64,13 @@ struct mtk_smi_larb_gen {
int port_in_larb[MTK_LARB_NR_MAX + 1];
void (*config_port)(struct device *);
unsigned int larb_direct_to_common_mask;
+ bool has_gals;
};

struct mtk_smi {
struct device *dev;
struct clk *clk_apb, *clk_smi;
+ struct clk *clk_gals0, *clk_gals1;
struct clk *clk_async; /*only needed by mt2701*/
void __iomem *smi_ao_base;

@@ -99,8 +102,20 @@ static int mtk_smi_enable(const struct mtk_smi *smi)
if (ret)
goto err_disable_apb;

+ ret = clk_prepare_enable(smi->clk_gals0);
+ if (ret)
+ goto err_disable_smi;
+
+ ret = clk_prepare_enable(smi->clk_gals1);
+ if (ret)
+ goto err_disable_gals0;
+
return 0;

+err_disable_gals0:
+ clk_disable_unprepare(smi->clk_gals0);
+err_disable_smi:
+ clk_disable_unprepare(smi->clk_smi);
err_disable_apb:
clk_disable_unprepare(smi->clk_apb);
err_put_pm:
@@ -110,6 +125,8 @@ static int mtk_smi_enable(const struct mtk_smi *smi)

static void mtk_smi_disable(const struct mtk_smi *smi)
{
+ clk_disable_unprepare(smi->clk_gals1);
+ clk_disable_unprepare(smi->clk_gals0);
clk_disable_unprepare(smi->clk_smi);
clk_disable_unprepare(smi->clk_apb);
pm_runtime_put_sync(smi->dev);
@@ -310,6 +327,15 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
larb->smi.clk_smi = devm_clk_get(dev, "smi");
if (IS_ERR(larb->smi.clk_smi))
return PTR_ERR(larb->smi.clk_smi);
+
+ if (larb->larb_gen->has_gals) {
+ /* The larbs may still haven't gals even if the SoC support.*/
+ larb->smi.clk_gals0 = devm_clk_get(dev, "gals");
+ if (PTR_ERR(larb->smi.clk_gals0) == -ENOENT)
+ larb->smi.clk_gals0 = NULL;
+ else if (IS_ERR(larb->smi.clk_gals0))
+ return PTR_ERR(larb->smi.clk_gals0);
+ }
larb->smi.dev = dev;

if (larb->larb_gen->need_larbid) {
@@ -402,6 +428,16 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
if (IS_ERR(common->clk_smi))
return PTR_ERR(common->clk_smi);

+ if (common->plat->has_gals) {
+ common->clk_gals0 = devm_clk_get(dev, "gals0");
+ if (IS_ERR(common->clk_gals0))
+ return PTR_ERR(common->clk_gals0);
+
+ common->clk_gals1 = devm_clk_get(dev, "gals1");
+ if (IS_ERR(common->clk_gals1))
+ return PTR_ERR(common->clk_gals1);
+ }
+
/*
* for mtk smi gen 1, we need to get the ao(always on) base to config
* m4u port, and we need to enable the aync clock for transform the smi
--
1.9.1

2019-06-10 12:22:09

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 06/21] iommu/io-pgtable-arm-v7s: Extend MediaTek 4GB Mode

MediaTek extend the arm v7s descriptor to support the dram over 4GB.

In the mt2712 and mt8173, it's called "4GB mode", the physical address
is from 0x4000_0000 to 0x1_3fff_ffff, but from EMI point of view, it
is remapped to high address from 0x1_0000_0000 to 0x1_ffff_ffff, the
bit32 is always enabled. thus, in the M4U, we always enable the bit9
for all PTEs which means to enable bit32 of physical address.

but in mt8183, M4U support the dram from 0x4000_0000 to 0x3_ffff_ffff
which isn't remaped. We extend the PTEs: the bit9 represent bit32 of
PA and the bit4 represent bit33 of PA. Meanwhile the iova still is
32bits.

In order to unify code, in the "4GB mode", we add the bit32 for the
physical address manually in our driver.

Correspondingly, Adding bit32 and bit33 for the PA in the iova_to_phys
has to been moved into v7s.

Regarding whether the pagetable address could be over 4GB, the mt8183
support it while the previous mt8173 don't. thus keep it as is.

Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Robin Murphy <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/iommu/io-pgtable-arm-v7s.c | 31 ++++++++++++++++++++++++-------
drivers/iommu/mtk_iommu.c | 20 ++++++++++----------
drivers/iommu/mtk_iommu.h | 1 +
3 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
index 94c38db..4077822 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -123,7 +123,9 @@
#define ARM_V7S_TEX_MASK 0x7
#define ARM_V7S_ATTR_TEX(val) (((val) & ARM_V7S_TEX_MASK) << ARM_V7S_TEX_SHIFT)

-#define ARM_V7S_ATTR_MTK_4GB BIT(9) /* MTK extend it for 4GB mode */
+/* MediaTek extend the two bits below for over 4GB mode */
+#define ARM_V7S_ATTR_MTK_PA_BIT32 BIT(9)
+#define ARM_V7S_ATTR_MTK_PA_BIT33 BIT(4)

/* *well, except for TEX on level 2 large pages, of course :( */
#define ARM_V7S_CONT_PAGE_TEX_SHIFT 6
@@ -190,13 +192,22 @@ static dma_addr_t __arm_v7s_dma_addr(void *pages)
static arm_v7s_iopte paddr_to_iopte(phys_addr_t paddr, int lvl,
struct io_pgtable_cfg *cfg)
{
- return paddr & ARM_V7S_LVL_MASK(lvl);
+ arm_v7s_iopte pte = paddr & ARM_V7S_LVL_MASK(lvl);
+
+ if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB) {
+ if (paddr & BIT_ULL(32))
+ pte |= ARM_V7S_ATTR_MTK_PA_BIT32;
+ if (paddr & BIT_ULL(33))
+ pte |= ARM_V7S_ATTR_MTK_PA_BIT33;
+ }
+ return pte;
}

static phys_addr_t iopte_to_paddr(arm_v7s_iopte pte, int lvl,
struct io_pgtable_cfg *cfg)
{
arm_v7s_iopte mask;
+ phys_addr_t paddr;

if (ARM_V7S_PTE_IS_TABLE(pte, lvl))
mask = ARM_V7S_TABLE_MASK;
@@ -205,7 +216,14 @@ static phys_addr_t iopte_to_paddr(arm_v7s_iopte pte, int lvl,
else
mask = ARM_V7S_LVL_MASK(lvl);

- return pte & mask;
+ paddr = pte & mask;
+ if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB) {
+ if (pte & ARM_V7S_ATTR_MTK_PA_BIT32)
+ paddr |= BIT_ULL(32);
+ if (pte & ARM_V7S_ATTR_MTK_PA_BIT33)
+ paddr |= BIT_ULL(33);
+ }
+ return paddr;
}

static arm_v7s_iopte *iopte_deref(arm_v7s_iopte pte, int lvl,
@@ -326,9 +344,6 @@ static arm_v7s_iopte arm_v7s_prot_to_pte(int prot, int lvl,
if (lvl == 1 && (cfg->quirks & IO_PGTABLE_QUIRK_ARM_NS))
pte |= ARM_V7S_ATTR_NS_SECTION;

- if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB)
- pte |= ARM_V7S_ATTR_MTK_4GB;
-
return pte;
}

@@ -515,7 +530,9 @@ static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova,
if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
return 0;

- if (WARN_ON(upper_32_bits(iova) || upper_32_bits(paddr)))
+ if (WARN_ON(upper_32_bits(iova)) ||
+ WARN_ON(upper_32_bits(paddr) &&
+ !(iop->cfg.quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB)))
return -ERANGE;

ret = __arm_v7s_map(data, iova, paddr, size, prot, 1, data->pgd);
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 1ddb2b7..aff5004 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -271,7 +271,8 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom)
dom->cfg = (struct io_pgtable_cfg) {
.quirks = IO_PGTABLE_QUIRK_ARM_NS |
IO_PGTABLE_QUIRK_NO_PERMS |
- IO_PGTABLE_QUIRK_TLBI_ON_MAP,
+ IO_PGTABLE_QUIRK_TLBI_ON_MAP |
+ IO_PGTABLE_QUIRK_ARM_MTK_4GB,
.pgsize_bitmap = mtk_iommu_ops.pgsize_bitmap,
.ias = 32,
.oas = 32,
@@ -279,9 +280,6 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom)
.iommu_dev = data->dev,
};

- if (data->enable_4GB)
- dom->cfg.quirks |= IO_PGTABLE_QUIRK_ARM_MTK_4GB;
-
dom->iop = alloc_io_pgtable_ops(ARM_V7S, &dom->cfg, data);
if (!dom->iop) {
dev_err(data->dev, "Failed to alloc io pgtable\n");
@@ -367,12 +365,16 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot)
{
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+ struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
unsigned long flags;
int ret;

+ /* The "4GB mode" M4U physically can not use the lower remap of Dram. */
+ if (data->plat_data->has_4gb_mode && data->enable_4GB)
+ paddr |= BIT_ULL(32);
+
spin_lock_irqsave(&dom->pgtlock, flags);
- ret = dom->iop->map(dom->iop, iova, paddr & DMA_BIT_MASK(32),
- size, prot);
+ ret = dom->iop->map(dom->iop, iova, paddr, size, prot);
spin_unlock_irqrestore(&dom->pgtlock, flags);

return ret;
@@ -401,7 +403,6 @@ 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();
unsigned long flags;
phys_addr_t pa;

@@ -409,9 +410,6 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
pa = dom->iop->iova_to_phys(dom->iop, iova);
spin_unlock_irqrestore(&dom->pgtlock, flags);

- if (data->enable_4GB)
- pa |= BIT_ULL(32);
-
return pa;
}

@@ -742,10 +740,12 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)

static const struct mtk_iommu_plat_data mt2712_data = {
.m4u_plat = M4U_MT2712,
+ .has_4gb_mode = true,
};

static const struct mtk_iommu_plat_data mt8173_data = {
.m4u_plat = M4U_MT8173,
+ .has_4gb_mode = true,
};

static const struct of_device_id mtk_iommu_of_ids[] = {
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 483d210..d7a001a 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -42,6 +42,7 @@ enum mtk_iommu_plat {

struct mtk_iommu_plat_data {
enum mtk_iommu_plat m4u_plat;
+ bool has_4gb_mode;
};

struct mtk_iommu_domain;
--
1.9.1

2019-06-10 12:22:33

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 14/21] iommu/mediatek: Add mmu1 support

Normally the M4U HW connect EMI with smi. the diagram is like below:
EMI
|
M4U
|
smi-common
|
-----------------
| | | | ...
larb0 larb1 larb2 larb3

Actually there are 2 mmu cells in the M4U HW, like this diagram:

EMI
---------
| |
mmu0 mmu1 <- M4U
| |
---------
|
smi-common
|
-----------------
| | | | ...
larb0 larb1 larb2 larb3

This patch add support for mmu1. In order to get better performance,
we could adjust some larbs go to mmu1 while the others still go to
mmu0. This is controlled by a SMI COMMON register SMI_BUS_SEL(0x220).

mt2712, mt8173 and mt8183 M4U HW all have 2 mmu cells. the default
value of that register is 0 which means all the larbs go to mmu0
defaultly.

This is a preparing patch for adjusting SMI_BUS_SEL for mt8183.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 3a14301..ec4ce74 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -72,26 +72,32 @@
#define F_INT_CLR_BIT BIT(12)

#define REG_MMU_INT_MAIN_CONTROL 0x124
-#define F_INT_TRANSLATION_FAULT BIT(0)
-#define F_INT_MAIN_MULTI_HIT_FAULT BIT(1)
-#define F_INT_INVALID_PA_FAULT BIT(2)
-#define F_INT_ENTRY_REPLACEMENT_FAULT BIT(3)
-#define F_INT_TLB_MISS_FAULT BIT(4)
-#define F_INT_MISS_TRANSACTION_FIFO_FAULT BIT(5)
-#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT BIT(6)
+ /* mmu0 | mmu1 */
+#define F_INT_TRANSLATION_FAULT (BIT(0) | BIT(7))
+#define F_INT_MAIN_MULTI_HIT_FAULT (BIT(1) | BIT(8))
+#define F_INT_INVALID_PA_FAULT (BIT(2) | BIT(9))
+#define F_INT_ENTRY_REPLACEMENT_FAULT (BIT(3) | BIT(10))
+#define F_INT_TLB_MISS_FAULT (BIT(4) | BIT(11))
+#define F_INT_MISS_TRANSACTION_FIFO_FAULT (BIT(5) | BIT(12))
+#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT (BIT(6) | BIT(13))

#define REG_MMU_CPE_DONE 0x12C

#define REG_MMU_FAULT_ST1 0x134
+#define F_REG_MMU0_FAULT_MASK GENMASK(6, 0)
+#define F_REG_MMU1_FAULT_MASK GENMASK(13, 7)

-#define REG_MMU_FAULT_VA 0x13c
+#define REG_MMU0_FAULT_VA 0x13c
#define F_MMU_FAULT_VA_WRITE_BIT BIT(1)
#define F_MMU_FAULT_VA_LAYER_BIT BIT(0)

-#define REG_MMU_INVLD_PA 0x140
-#define REG_MMU_INT_ID 0x150
-#define F_MMU0_INT_ID_LARB_ID(a) (((a) >> 7) & 0x7)
-#define F_MMU0_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f)
+#define REG_MMU0_INVLD_PA 0x140
+#define REG_MMU1_FAULT_VA 0x144
+#define REG_MMU1_INVLD_PA 0x148
+#define REG_MMU0_INT_ID 0x150
+#define REG_MMU1_INT_ID 0x154
+#define F_MMU_INT_ID_LARB_ID(a) (((a) >> 7) & 0x7)
+#define F_MMU_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f)

#define MTK_PROTECT_PA_ALIGN 128

@@ -210,13 +216,19 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)

/* Read error info from registers */
int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST1);
- fault_iova = readl_relaxed(data->base + REG_MMU_FAULT_VA);
+ if (int_state & F_REG_MMU0_FAULT_MASK) {
+ regval = readl_relaxed(data->base + REG_MMU0_INT_ID);
+ fault_iova = readl_relaxed(data->base + REG_MMU0_FAULT_VA);
+ fault_pa = readl_relaxed(data->base + REG_MMU0_INVLD_PA);
+ } else {
+ regval = readl_relaxed(data->base + REG_MMU1_INT_ID);
+ fault_iova = readl_relaxed(data->base + REG_MMU1_FAULT_VA);
+ fault_pa = readl_relaxed(data->base + REG_MMU1_INVLD_PA);
+ }
layer = fault_iova & F_MMU_FAULT_VA_LAYER_BIT;
write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT;
- fault_pa = readl_relaxed(data->base + REG_MMU_INVLD_PA);
- regval = readl_relaxed(data->base + REG_MMU_INT_ID);
- fault_larb = F_MMU0_INT_ID_LARB_ID(regval);
- fault_port = F_MMU0_INT_ID_PORT_ID(regval);
+ fault_larb = F_MMU_INT_ID_LARB_ID(regval);
+ fault_port = F_MMU_INT_ID_PORT_ID(regval);

fault_larb = data->plat_data->larbid_remap[fault_larb];

--
1.9.1

2019-06-10 12:22:39

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 15/21] memory: mtk-smi: Invoke pm runtime_callback to enable clocks

This patch only move the clk_prepare_enable and config_port into the
runtime suspend/resume callback. It doesn't change the code content
and sequence.

This is a preparing patch for adjusting SMI_BUS_SEL for mt8183.
(SMI_BUS_SEL need to be restored after smi-common resume every time.)
Also it gives a chance to get rid of mtk_smi_larb_get/put which could
be a next topic.

CC: Matthias Brugger <[email protected]>
Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/memory/mtk-smi.c | 113 ++++++++++++++++++++++++++++++-----------------
1 file changed, 72 insertions(+), 41 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index a430721..9790801 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -86,17 +86,13 @@ struct mtk_smi_larb { /* larb: local arbiter */
u32 *mmu;
};

-static int mtk_smi_enable(const struct mtk_smi *smi)
+static int mtk_smi_clk_enable(const struct mtk_smi *smi)
{
int ret;

- ret = pm_runtime_get_sync(smi->dev);
- if (ret < 0)
- return ret;
-
ret = clk_prepare_enable(smi->clk_apb);
if (ret)
- goto err_put_pm;
+ return ret;

ret = clk_prepare_enable(smi->clk_smi);
if (ret)
@@ -118,59 +114,28 @@ static int mtk_smi_enable(const struct mtk_smi *smi)
clk_disable_unprepare(smi->clk_smi);
err_disable_apb:
clk_disable_unprepare(smi->clk_apb);
-err_put_pm:
- pm_runtime_put_sync(smi->dev);
return ret;
}

-static void mtk_smi_disable(const struct mtk_smi *smi)
+static void mtk_smi_clk_disable(const struct mtk_smi *smi)
{
clk_disable_unprepare(smi->clk_gals1);
clk_disable_unprepare(smi->clk_gals0);
clk_disable_unprepare(smi->clk_smi);
clk_disable_unprepare(smi->clk_apb);
- pm_runtime_put_sync(smi->dev);
}

int mtk_smi_larb_get(struct device *larbdev)
{
- struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
- const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
- struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
- int ret;
+ int ret = pm_runtime_get_sync(larbdev);

- /* Enable the smi-common's power and clocks */
- ret = mtk_smi_enable(common);
- if (ret)
- return ret;
-
- /* Enable the larb's power and clocks */
- ret = mtk_smi_enable(&larb->smi);
- if (ret) {
- mtk_smi_disable(common);
- return ret;
- }
-
- /* Configure the iommu info for this larb */
- larb_gen->config_port(larbdev);
-
- return 0;
+ return (ret < 0) ? ret : 0;
}
EXPORT_SYMBOL_GPL(mtk_smi_larb_get);

void mtk_smi_larb_put(struct device *larbdev)
{
- struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
- struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
-
- /*
- * Don't de-configure the iommu info for this larb since there may be
- * several modules in this larb.
- * The iommu info will be reset after power off.
- */
-
- mtk_smi_disable(&larb->smi);
- mtk_smi_disable(common);
+ pm_runtime_put_sync(larbdev);
}
EXPORT_SYMBOL_GPL(mtk_smi_larb_put);

@@ -385,12 +350,52 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
return 0;
}

+static int __maybe_unused mtk_smi_larb_resume(struct device *dev)
+{
+ struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+ const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
+ int ret;
+
+ /* Power on smi-common. */
+ ret = pm_runtime_get_sync(larb->smi_common_dev);
+ if (ret < 0) {
+ dev_err(dev, "Failed to pm get for smi-common(%d).\n", ret);
+ return ret;
+ }
+
+ ret = mtk_smi_clk_enable(&larb->smi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable clock(%d).\n", ret);
+ pm_runtime_put_sync(larb->smi_common_dev);
+ return ret;
+ }
+
+ /* Configure the basic setting for this larb */
+ larb_gen->config_port(dev);
+
+ return 0;
+}
+
+static int __maybe_unused mtk_smi_larb_suspend(struct device *dev)
+{
+ struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+
+ mtk_smi_clk_disable(&larb->smi);
+ pm_runtime_put_sync(larb->smi_common_dev);
+ return 0;
+}
+
+static const struct dev_pm_ops smi_larb_pm_ops = {
+ SET_RUNTIME_PM_OPS(mtk_smi_larb_suspend, mtk_smi_larb_resume, NULL)
+};
+
static struct platform_driver mtk_smi_larb_driver = {
.probe = mtk_smi_larb_probe,
.remove = mtk_smi_larb_remove,
.driver = {
.name = "mtk-smi-larb",
.of_match_table = mtk_smi_larb_of_ids,
+ .pm = &smi_larb_pm_ops,
}
};

@@ -489,12 +494,38 @@ static int mtk_smi_common_remove(struct platform_device *pdev)
return 0;
}

+static int __maybe_unused mtk_smi_common_resume(struct device *dev)
+{
+ struct mtk_smi *common = dev_get_drvdata(dev);
+ int ret;
+
+ ret = mtk_smi_clk_enable(common);
+ if (ret) {
+ dev_err(common->dev, "Failed to enable clock(%d).\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
+static int __maybe_unused mtk_smi_common_suspend(struct device *dev)
+{
+ struct mtk_smi *common = dev_get_drvdata(dev);
+
+ mtk_smi_clk_disable(common);
+ return 0;
+}
+
+static const struct dev_pm_ops smi_common_pm_ops = {
+ SET_RUNTIME_PM_OPS(mtk_smi_common_suspend, mtk_smi_common_resume, NULL)
+};
+
static struct platform_driver mtk_smi_common_driver = {
.probe = mtk_smi_common_probe,
.remove = mtk_smi_common_remove,
.driver = {
.name = "mtk-smi-common",
.of_match_table = mtk_smi_common_of_ids,
+ .pm = &smi_common_pm_ops,
}
};

--
1.9.1

2019-06-10 12:22:50

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 09/21] iommu/mediatek: Refine protect memory definition

The protect memory setting is a little different in the different SoCs.
In the register REG_MMU_CTRL_REG(0x110), the TF_PROT(translation fault
protect) shift bit is normally 4 while it shift 5 bits only in the
mt8173. This patch delete the complex MACRO and use a common if-else
instead.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index ad838b9..d38dfa2 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -52,12 +52,9 @@
#define REG_MMU_DCM_DIS 0x050

#define REG_MMU_CTRL_REG 0x110
+#define F_MMU_TF_PROT_TO_PROGRAM_ADDR (2 << 4)
#define F_MMU_PREFETCH_RT_REPLACE_MOD BIT(4)
-#define F_MMU_TF_PROTECT_SEL_SHIFT(data) \
- ((data)->plat_data->m4u_plat == M4U_MT2712 ? 4 : 5)
-/* It's named by F_MMU_TF_PROT_SEL in mt2712. */
-#define F_MMU_TF_PROTECT_SEL(prot, data) \
- (((prot) & 0x3) << F_MMU_TF_PROTECT_SEL_SHIFT(data))
+#define F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173 (2 << 5)

#define REG_MMU_IVRP_PADDR 0x114

@@ -519,9 +516,11 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
return ret;
}

- regval = F_MMU_TF_PROTECT_SEL(2, data);
if (data->plat_data->m4u_plat == M4U_MT8173)
- regval |= F_MMU_PREFETCH_RT_REPLACE_MOD;
+ regval = F_MMU_PREFETCH_RT_REPLACE_MOD |
+ F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173;
+ else
+ regval = F_MMU_TF_PROT_TO_PROGRAM_ADDR;
writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);

regval = F_L2_MULIT_HIT_EN |
--
1.9.1

2019-06-10 12:23:06

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 17/21] memory: mtk-smi: Get rid of need_larbid

The "mediatek,larb-id" has already been parsed in MTK IOMMU driver.
It's no need to parse it again in SMI driver. Only clean some codes.
This patch is fit for all the current mt2701, mt2712, mt7623, mt8173
and mt8183.

After this patch, the "mediatek,larb-id" only be needed for mt2712
which have 2 M4Us. In the other SoCs, we can get the larb-id from M4U
in which the larbs in the "mediatek,larbs" always are ordered.

Correspondingly, the larb_nr in the "struct mtk_smi_iommu" could also
be deleted.

CC: Matthias Brugger <[email protected]>
Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/iommu/mtk_iommu.c | 1 -
drivers/iommu/mtk_iommu_v1.c | 2 --
drivers/memory/mtk-smi.c | 26 ++------------------------
include/soc/mediatek/smi.h | 1 -
4 files changed, 2 insertions(+), 28 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index ec4ce74..6053b8b 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -634,7 +634,6 @@ static int mtk_iommu_probe(struct platform_device *pdev)
"mediatek,larbs", NULL);
if (larb_nr < 0)
return larb_nr;
- data->smi_imu.larb_nr = larb_nr;

for (i = 0; i < larb_nr; i++) {
struct device_node *larbnode;
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 52b01e3..73308ad 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -624,8 +624,6 @@ static int mtk_iommu_probe(struct platform_device *pdev)
larb_nr++;
}

- data->smi_imu.larb_nr = larb_nr;
-
platform_set_drvdata(pdev, data);

ret = mtk_iommu_hw_init(data);
diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 08cf40d..10e6493 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -67,7 +67,6 @@ struct mtk_smi_common_plat {
};

struct mtk_smi_larb_gen {
- bool need_larbid;
int port_in_larb[MTK_LARB_NR_MAX + 1];
void (*config_port)(struct device *);
unsigned int larb_direct_to_common_mask;
@@ -153,18 +152,9 @@ void mtk_smi_larb_put(struct device *larbdev)
struct mtk_smi_iommu *smi_iommu = data;
unsigned int i;

- if (larb->larb_gen->need_larbid) {
- larb->mmu = &smi_iommu->larb_imu[larb->larbid].mmu;
- return 0;
- }
-
- /*
- * If there is no larbid property, Loop to find the corresponding
- * iommu information.
- */
- for (i = 0; i < smi_iommu->larb_nr; i++) {
+ for (i = 0; i < MTK_LARB_NR_MAX; i++) {
if (dev == smi_iommu->larb_imu[i].dev) {
- /* The 'mmu' may be updated in iommu-attach/detach. */
+ larb->larbid = i;
larb->mmu = &smi_iommu->larb_imu[i].mmu;
return 0;
}
@@ -243,7 +233,6 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev)
};

static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
- .need_larbid = true,
.port_in_larb = {
LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
@@ -252,7 +241,6 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev)
};

static const struct mtk_smi_larb_gen mtk_smi_larb_mt2712 = {
- .need_larbid = true,
.config_port = mtk_smi_larb_config_port_gen2_general,
.larb_direct_to_common_mask = BIT(8) | BIT(9), /* bdpsys */
};
@@ -291,7 +279,6 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *smi_node;
struct platform_device *smi_pdev;
- int err;

larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL);
if (!larb)
@@ -321,15 +308,6 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
}
larb->smi.dev = dev;

- if (larb->larb_gen->need_larbid) {
- err = of_property_read_u32(dev->of_node, "mediatek,larb-id",
- &larb->larbid);
- if (err) {
- dev_err(dev, "missing larbid property\n");
- return err;
- }
- }
-
smi_node = of_parse_phandle(dev->of_node, "mediatek,smi", 0);
if (!smi_node)
return -EINVAL;
diff --git a/include/soc/mediatek/smi.h b/include/soc/mediatek/smi.h
index 5201e90..a65324d 100644
--- a/include/soc/mediatek/smi.h
+++ b/include/soc/mediatek/smi.h
@@ -29,7 +29,6 @@ struct mtk_smi_larb_iommu {
};

struct mtk_smi_iommu {
- unsigned int larb_nr;
struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX];
};

--
1.9.1

2019-06-10 12:23:21

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 13/21] iommu/mediatek: Add mt8183 IOMMU support

The M4U IP blocks in mt8183 is MediaTek's generation2 M4U which use
the ARM Short-descriptor like mt8173, and most of the HW registers
are the same.

Here list main differences between mt8183 and mt8173/mt2712:
1) mt8183 has only one M4U HW like mt8173 while mt2712 has two.
2) mt8183 don't have the "bclk" clock, it use the EMI clock instead.
3) mt8183 can support the dram over 4GB, but it doesn't call this "4GB
mode".
4) mt8183 pgtable base register(0x0) extend bit[1:0] which represent
the bit[33:32] in the physical address of the pgtable base, But the
standard ttbr0[1] means the S bit which is enabled defaultly, Hence,
we add a mask.
5) mt8183 HW has a GALS modules, SMI should enable "has_gals" support.
6) mt8183 need reset_axi like mt8173.
7) the larb-id in smi-common is remapped. M4U should add its larbid_remap.

Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/iommu/mtk_iommu.c | 15 ++++++++++++---
drivers/iommu/mtk_iommu.h | 1 +
drivers/memory/mtk-smi.c | 20 ++++++++++++++++++++
3 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index a535dcd..3a14301 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -36,6 +36,7 @@
#include "mtk_iommu.h"

#define REG_MMU_PT_BASE_ADDR 0x000
+#define MMU_PT_ADDR_MASK GENMASK(31, 7)

#define REG_MMU_INVALIDATE 0x020
#define F_ALL_INVLD 0x2
@@ -341,7 +342,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
/* Update the pgtable base address register of the M4U HW */
if (!data->m4u_dom) {
data->m4u_dom = dom;
- writel(dom->cfg.arm_v7s_cfg.ttbr[0],
+ writel(dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
data->base + REG_MMU_PT_BASE_ADDR);
}

@@ -715,6 +716,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
{
struct mtk_iommu_data *data = dev_get_drvdata(dev);
struct mtk_iommu_suspend_reg *reg = &data->reg;
+ struct mtk_iommu_domain *m4u_dom = data->m4u_dom;
void __iomem *base = data->base;
int ret;

@@ -730,8 +732,8 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0);
writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
- if (data->m4u_dom)
- writel(data->m4u_dom->cfg.arm_v7s_cfg.ttbr[0],
+ if (m4u_dom)
+ writel(m4u_dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
base + REG_MMU_PT_BASE_ADDR);
return 0;
}
@@ -756,9 +758,16 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
.larbid_remap = {0, 1, 2, 3, 4, 5}, /* Linear mapping. */
};

+static const struct mtk_iommu_plat_data mt8183_data = {
+ .m4u_plat = M4U_MT8183,
+ .reset_axi = true,
+ .larbid_remap = {0, 4, 5, 6, 7, 2, 3, 1},
+};
+
static const struct of_device_id mtk_iommu_of_ids[] = {
{ .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data},
{ .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data},
+ { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data},
{}
};

diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index e5c9dde..c0b5c65 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -38,6 +38,7 @@ enum mtk_iommu_plat {
M4U_MT2701,
M4U_MT2712,
M4U_MT8173,
+ M4U_MT8183,
};

struct mtk_iommu_plat_data {
diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 91634d7..a430721 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -285,6 +285,13 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev)
.larb_direct_to_common_mask = BIT(8) | BIT(9), /* bdpsys */
};

+static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = {
+ .has_gals = true,
+ .config_port = mtk_smi_larb_config_port_gen2_general,
+ .larb_direct_to_common_mask = BIT(2) | BIT(3) | BIT(7),
+ /* IPU0 | IPU1 | CCU */
+};
+
static const struct of_device_id mtk_smi_larb_of_ids[] = {
{
.compatible = "mediatek,mt8173-smi-larb",
@@ -298,6 +305,10 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev)
.compatible = "mediatek,mt2712-smi-larb",
.data = &mtk_smi_larb_mt2712
},
+ {
+ .compatible = "mediatek,mt8183-smi-larb",
+ .data = &mtk_smi_larb_mt8183
+ },
{}
};

@@ -391,6 +402,11 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
.gen = MTK_SMI_GEN2,
};

+static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
+ .gen = MTK_SMI_GEN2,
+ .has_gals = true,
+};
+
static const struct of_device_id mtk_smi_common_of_ids[] = {
{
.compatible = "mediatek,mt8173-smi-common",
@@ -404,6 +420,10 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
.compatible = "mediatek,mt2712-smi-common",
.data = &mtk_smi_common_gen2,
},
+ {
+ .compatible = "mediatek,mt8183-smi-common",
+ .data = &mtk_smi_common_mt8183,
+ },
{}
};

--
1.9.1

2019-06-10 12:23:36

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 19/21] iommu/mediatek: Rename enable_4GB to dram_is_4gb

This patch only rename the variable name from enable_4GB to
dram_is_4gb for readable.

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

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 86158d8..67cab2d 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -382,7 +382,7 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
int ret;

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

spin_lock_irqsave(&dom->pgtlock, flags);
@@ -554,13 +554,13 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);

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

- if (data->enable_4GB && data->plat_data->has_vld_pa_rng) {
+ if (data->dram_is_4gb && data->plat_data->has_vld_pa_rng) {
/*
* If 4GB mode is enabled, the validate PA range is from
* 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
@@ -611,8 +611,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
return -ENOMEM;
data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);

- /* Whether the current dram is over 4GB */
- data->enable_4GB = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
+ /* Whether the current dram is 4GB. */
+ data->dram_is_4gb = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->base = devm_ioremap_resource(dev, res);
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 753266b..e8114b2 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -65,7 +65,7 @@ struct mtk_iommu_data {
struct mtk_iommu_domain *m4u_dom;
struct iommu_group *m4u_group;
struct mtk_smi_iommu smi_imu; /* SMI larb iommu info */
- bool enable_4GB;
+ bool dram_is_4gb;
bool tlb_flush_active;

struct iommu_device iommu;
--
1.9.1

2019-06-10 12:24:12

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 16/21] memory: mtk-smi: Add bus_sel for mt8183

There are 2 mmu cells in a M4U HW. we could adjust some larbs entering
mmu0 or mmu1 to balance the bandwidth via the smi-common register
SMI_BUS_SEL(0x220)(Each larb occupy 2 bits).

In mt8183, For better performance, we switch larb1/2/5/7 to enter
mmu1 while the others still keep enter mmu0.

In mt8173 and mt2712, we don't get the performance issue,
Keep its default value(0x0), that means all the larbs enter mmu0.

Note: smi gen1(mt2701/mt7623) don't have this bus_sel.

And, the base of smi-common is completely different with smi_ao_base
of gen1, thus I add new variable for that.

CC: Matthias Brugger <[email protected]>
Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/memory/mtk-smi.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 9790801..08cf40d 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -49,6 +49,12 @@
#define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4))
#define F_MMU_EN BIT(0)

+/* SMI COMMON */
+#define SMI_BUS_SEL 0x220
+#define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1)
+/* All are MMU0 defaultly. Only specialize mmu1 here. */
+#define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid))
+
enum mtk_smi_gen {
MTK_SMI_GEN1,
MTK_SMI_GEN2
@@ -57,6 +63,7 @@ enum mtk_smi_gen {
struct mtk_smi_common_plat {
enum mtk_smi_gen gen;
bool has_gals;
+ u32 bus_sel; /* Balance some larbs to enter mmu0 or mmu1 */
};

struct mtk_smi_larb_gen {
@@ -72,8 +79,8 @@ struct mtk_smi {
struct clk *clk_apb, *clk_smi;
struct clk *clk_gals0, *clk_gals1;
struct clk *clk_async; /*only needed by mt2701*/
- void __iomem *smi_ao_base;
-
+ void __iomem *smi_ao_base; /* only for gen1 */
+ void __iomem *base; /* only for gen2 */
const struct mtk_smi_common_plat *plat;
};

@@ -410,6 +417,8 @@ static int __maybe_unused mtk_smi_larb_suspend(struct device *dev)
static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
.gen = MTK_SMI_GEN2,
.has_gals = true,
+ .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(5) |
+ F_MMU1_LARB(7),
};

static const struct of_device_id mtk_smi_common_of_ids[] = {
@@ -482,6 +491,11 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
ret = clk_prepare_enable(common->clk_async);
if (ret)
return ret;
+ } else {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ common->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(common->base))
+ return PTR_ERR(common->base);
}
pm_runtime_enable(dev);
platform_set_drvdata(pdev, common);
@@ -497,6 +511,7 @@ static int mtk_smi_common_remove(struct platform_device *pdev)
static int __maybe_unused mtk_smi_common_resume(struct device *dev)
{
struct mtk_smi *common = dev_get_drvdata(dev);
+ u32 bus_sel = common->plat->bus_sel;
int ret;

ret = mtk_smi_clk_enable(common);
@@ -504,6 +519,9 @@ static int __maybe_unused mtk_smi_common_resume(struct device *dev)
dev_err(common->dev, "Failed to enable clock(%d).\n", ret);
return ret;
}
+
+ if (common->plat->gen == MTK_SMI_GEN2 && bus_sel)
+ writel(bus_sel, common->base + SMI_BUS_SEL);
return 0;
}

--
1.9.1

2019-06-10 12:24:34

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 18/21] iommu/mediatek: Fix VLD_PA_RNG register backup when suspend

The register VLD_PA_RNG(0x118) was forgot to backup while adding 4GB
mode support for mt2712. this patch add it.

Fixes: 30e2fccf9512 ("iommu/mediatek: Enlarge the validate PA range
for 4GB mode")
Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/iommu/mtk_iommu.c | 2 ++
drivers/iommu/mtk_iommu.h | 1 +
2 files changed, 3 insertions(+)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 6053b8b..86158d8 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -719,6 +719,7 @@ static int __maybe_unused mtk_iommu_suspend(struct device *dev)
reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0);
reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL);
reg->ivrp_paddr = readl_relaxed(base + REG_MMU_IVRP_PADDR);
+ reg->vld_pa_rng = readl_relaxed(base + REG_MMU_VLD_PA_RNG);
clk_disable_unprepare(data->bclk);
return 0;
}
@@ -743,6 +744,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0);
writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
+ writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG);
if (m4u_dom)
writel(m4u_dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
base + REG_MMU_PT_BASE_ADDR);
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index c0b5c65..753266b 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -32,6 +32,7 @@ struct mtk_iommu_suspend_reg {
u32 int_control0;
u32 int_main_control;
u32 ivrp_paddr;
+ u32 vld_pa_rng;
};

enum mtk_iommu_plat {
--
1.9.1

2019-06-10 12:25:00

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 20/21] iommu/mediatek: Fix iova_to_phys PA start for 4GB mode

In the 4GB mode, the physical address is remapped,

Here is the detailed remap relationship.
CPU PA -> HW PA
0x4000_0000 0x1_4000_0000 (Add bit32)
0x8000_0000 0x1_8000_0000 ...
0xc000_0000 0x1_c000_0000 ...
0x1_0000_0000 0x1_0000_0000 (No change)

Thus, we always add bit32 for PA when entering mtk_iommu_map.
But in the iova_to_phys, the CPU don't need this bit32 if the
PA is from 0x1_4000_0000 to 0x1_ffff_ffff.
This patch discards the bit32 in this iova_to_phys in the 4GB mode.

Fixes: 30e2fccf9512 ("iommu/mediatek: Enlarge the validate PA range
for 4GB mode")
Signed-off-by: Yong Wu <[email protected]>
---
drivers/iommu/mtk_iommu.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 67cab2d..34f2e40 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -119,6 +119,19 @@ struct mtk_iommu_domain {

static const struct iommu_ops mtk_iommu_ops;

+/*
+ * In M4U 4GB mode, the physical address is remapped as below:
+ * CPU PA -> M4U HW PA
+ * 0x4000_0000 0x1_4000_0000 (Add bit32)
+ * 0x8000_0000 0x1_8000_0000 ...
+ * 0xc000_0000 0x1_c000_0000 ...
+ * 0x1_0000_0000 0x1_0000_0000 (No change)
+ *
+ * Thus, We always add BIT32 in the iommu_map and disable BIT32 if PA is >=
+ * 0x1_4000_0000 in the iova_to_phys.
+ */
+#define MTK_IOMMU_4GB_MODE_PA_140000000 0x140000000UL
+
static LIST_HEAD(m4ulist); /* List all the M4U HWs */

#define for_each_m4u(data) list_for_each_entry(data, &m4ulist, list)
@@ -415,6 +428,7 @@ 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();
unsigned long flags;
phys_addr_t pa;

@@ -422,6 +436,10 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
pa = dom->iop->iova_to_phys(dom->iop, iova);
spin_unlock_irqrestore(&dom->pgtlock, flags);

+ if (data->plat_data->has_4gb_mode && data->dram_is_4gb &&
+ pa >= MTK_IOMMU_4GB_MODE_PA_140000000)
+ pa &= ~BIT_ULL(32);
+
return pa;
}

--
1.9.1

2019-06-10 12:25:31

by Yong Wu (吴勇)

[permalink] [raw]
Subject: [PATCH v7 21/21] iommu/mediatek: Switch to SPDX license identifier

Switch to SPDX license identifier for MediaTek iommu/smi and their
header files.

Signed-off-by: Yong Wu <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Reviewed-by: Evan Green <[email protected]>
---
drivers/iommu/mtk_iommu.c | 10 +---------
drivers/iommu/mtk_iommu.h | 10 +---------
drivers/iommu/mtk_iommu_v1.c | 10 +---------
drivers/memory/mtk-smi.c | 10 +---------
include/dt-bindings/memory/mt2701-larb-port.h | 10 +---------
include/dt-bindings/memory/mt8173-larb-port.h | 10 +---------
include/soc/mediatek/smi.h | 10 +---------
7 files changed, 7 insertions(+), 63 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 34f2e40..6fe3369 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -1,15 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2015-2016 MediaTek Inc.
* Author: Yong Wu <[email protected]>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/memblock.h>
#include <linux/bug.h>
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index e8114b2..b24cfd3 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -1,15 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2015-2016 MediaTek Inc.
* Author: Honghui Zhang <[email protected]>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/

#ifndef _MTK_IOMMU_H_
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 73308ad..0b0908c 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* IOMMU API for MTK architected m4u v1 implementations
*
@@ -5,15 +6,6 @@
* Author: Honghui Zhang <[email protected]>
*
* Based on driver/iommu/mtk_iommu.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/memblock.h>
#include <linux/bug.h>
diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 10e6493..9688341 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -1,15 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2015-2016 MediaTek Inc.
* Author: Yong Wu <[email protected]>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/component.h>
diff --git a/include/dt-bindings/memory/mt2701-larb-port.h b/include/dt-bindings/memory/mt2701-larb-port.h
index 6764d74..c511f0f 100644
--- a/include/dt-bindings/memory/mt2701-larb-port.h
+++ b/include/dt-bindings/memory/mt2701-larb-port.h
@@ -1,15 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2015 MediaTek Inc.
* Author: Honghui Zhang <[email protected]>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/

#ifndef _MT2701_LARB_PORT_H_
diff --git a/include/dt-bindings/memory/mt8173-larb-port.h b/include/dt-bindings/memory/mt8173-larb-port.h
index 111b4b0..a62bfeb 100644
--- a/include/dt-bindings/memory/mt8173-larb-port.h
+++ b/include/dt-bindings/memory/mt8173-larb-port.h
@@ -1,15 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2015-2016 MediaTek Inc.
* Author: Yong Wu <[email protected]>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#ifndef __DTS_IOMMU_PORT_MT8173_H
#define __DTS_IOMMU_PORT_MT8173_H
diff --git a/include/soc/mediatek/smi.h b/include/soc/mediatek/smi.h
index a65324d..7a8d870 100644
--- a/include/soc/mediatek/smi.h
+++ b/include/soc/mediatek/smi.h
@@ -1,15 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2015-2016 MediaTek Inc.
* Author: Yong Wu <[email protected]>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#ifndef MTK_IOMMU_SMI_H
#define MTK_IOMMU_SMI_H
--
1.9.1

2019-06-13 16:33:40

by Pi-Hsun Shih

[permalink] [raw]
Subject: Re: [PATCH v7 16/21] memory: mtk-smi: Add bus_sel for mt8183

(Sorry for the possibly double-posting, my last mail got rejected by
some mailing lists.)

Hi,
When I tested this patch series (Based on linux 5.2.0-rc2, and with
various other patch series about MT8183) with lockdep enabled, and I'm
seeing the following lockdep warning on boot.

By bisecting the commits, the first commit that introduce this warning
is this patch. The warning also doesn't appear if
https://lore.kernel.org/patchwork/patch/1086582/ and
https://lore.kernel.org/patchwork/patch/1086583/ are not applied.

Do anyone have idea on why this is happening, or any suggestion on
which part I should be digging into to figure this out? Thanks.

[ 4.664194] ======================================================
[ 4.670368] WARNING: possible circular locking dependency detected
[ 4.676545] 5.2.0-rc2-next-20190528-44527-g6c94b6475c04 #20 Tainted: G S
[ 4.684539] ------------------------------------------------------
[ 4.690714] kworker/4:1/51 is trying to acquire lock:
[ 4.695760] (____ptrval____) (regulator_list_mutex){+.+.},
at:regulator_lock_dependent+0xdc/0x6c4
[ 4.704732]
[ 4.704732] but task is already holding lock:
[ 4.710556] (____ptrval____) (&genpd->mlock/1){+.+.},
at:genpd_lock_nested_mtx+0x24/0x30
[ 4.718740]
[ 4.718740] which lock already depends on the new lock.
[ 4.718740]
[ 4.726908]
[ 4.726908] the existing dependency chain (in reverse order) is:
[ 4.734382]
[ 4.734382] -> #4 (&genpd->mlock/1){+.+.}:
[ 4.739963] __mutex_lock_common+0x1a0/0x1fe8
[ 4.744836] mutex_lock_nested+0x40/0x50
[ 4.749275] genpd_lock_nested_mtx+0x24/0x30
[ 4.754063] genpd_add_subdomain+0x150/0x524
[ 4.758850] pm_genpd_add_subdomain+0x3c/0x5c
[ 4.763723] scpsys_probe+0x520/0xe78
[ 4.767902] platform_drv_probe+0xf4/0x134
[ 4.772517] really_probe+0x214/0x4dc
[ 4.776696] driver_probe_device+0xcc/0x1d4
[ 4.781396] __device_attach_driver+0x10c/0x180
[ 4.786442] bus_for_each_drv+0x124/0x184
[ 4.790968] __device_attach+0x1c0/0x2d8
[ 4.795407] device_initial_probe+0x20/0x2c
[ 4.800106] bus_probe_device+0x80/0x16c
[ 4.804546] deferred_probe_work_func+0x120/0x168
[ 4.809767] process_one_work+0x858/0x1208
[ 4.814379] worker_thread+0x9ec/0xcb8
[ 4.818644] kthread+0x2b8/0x2d0
[ 4.822391] ret_from_fork+0x10/0x18
[ 4.826480]
[ 4.826480] -> #3 (&genpd->mlock){+.+.}:
[ 4.831880] __mutex_lock_common+0x1a0/0x1fe8
[ 4.836752] mutex_lock_nested+0x40/0x50
[ 4.841190] genpd_lock_mtx+0x20/0x2c
[ 4.845369] genpd_runtime_resume+0x140/0x434
[ 4.850241] __rpm_callback+0xb0/0x1e4
[ 4.854506] rpm_callback+0x54/0x1a8
[ 4.858597] rpm_resume+0xc6c/0x10c4
[ 4.862689] __pm_runtime_resume+0xb4/0x124
[ 4.867387] device_link_add+0x598/0x8d0
[ 4.871829] mtk_smi_larb_probe+0x2b0/0x340
[ 4.876528] platform_drv_probe+0xf4/0x134
[ 4.881141] really_probe+0x214/0x4dc
[ 4.885320] driver_probe_device+0xcc/0x1d4
[ 4.890020] __device_attach_driver+0x10c/0x180
[ 4.895066] bus_for_each_drv+0x124/0x184
[ 4.899591] __device_attach+0x1c0/0x2d8
[ 4.904031] device_initial_probe+0x20/0x2c
[ 4.908730] bus_probe_device+0x80/0x16c
[ 4.913169] deferred_probe_work_func+0x120/0x168
[ 4.918387] process_one_work+0x858/0x1208
[ 4.923000] worker_thread+0x9ec/0xcb8
[ 4.927264] kthread+0x2b8/0x2d0
[ 4.931009] ret_from_fork+0x10/0x18
[ 4.935098]
[ 4.935098] -> #2 (dpm_list_mtx){+.+.}:
[ 4.940412] __mutex_lock_common+0x1a0/0x1fe8
[ 4.945284] mutex_lock_nested+0x40/0x50
[ 4.949722] device_pm_lock+0x1c/0x24
[ 4.953900] device_link_add+0x98/0x8d0
[ 4.958252] _regulator_get+0x3f0/0x504
[ 4.962606] _devm_regulator_get+0x58/0xb8
[ 4.967218] devm_regulator_get+0x28/0x34
[ 4.971746] pwm_backlight_probe+0x61c/0x1b90
[ 4.976617] platform_drv_probe+0xf4/0x134
[ 4.981230] really_probe+0x214/0x4dc
[ 4.985409] driver_probe_device+0xcc/0x1d4
[ 4.990108] device_driver_attach+0xe4/0x104
[ 4.994894] __driver_attach+0x134/0x14c
[ 4.999333] bus_for_each_dev+0x120/0x180
[ 5.003859] driver_attach+0x48/0x54
[ 5.007950] bus_add_driver+0x2ac/0x44c
[ 5.012303] driver_register+0x160/0x288
[ 5.016742] __platform_driver_register+0xcc/0xdc
[ 5.021964] pwm_backlight_driver_init+0x1c/0x24
[ 5.027097] do_one_initcall+0x38c/0x994
[ 5.031536] do_initcall_level+0x3a4/0x4b8
[ 5.036148] do_basic_setup+0x84/0xa0
[ 5.036153] kernel_init_freeable+0x23c/0x324
[ 5.036158] kernel_init+0x14/0x110
[ 5.036164] ret_from_fork+0x10/0x18
[ 5.036166]
[ 5.036166] -> #1 (device_links_lock){+.+.}:
[ 5.065905] __mutex_lock_common+0x1a0/0x1fe8
[ 5.070777] mutex_lock_nested+0x40/0x50
[ 5.075215] device_link_remove+0x40/0xe0
[ 5.079740] _regulator_put+0x104/0x2d8
[ 5.084093] regulator_put+0x30/0x44
[ 5.088184] devm_regulator_release+0x38/0x44
[ 5.093056] release_nodes+0x604/0x670
[ 5.097320] devres_release_all+0x70/0x8c
[ 5.101846] really_probe+0x270/0x4dc
[ 5.106024] driver_probe_device+0xcc/0x1d4
[ 5.110724] device_driver_attach+0xe4/0x104
[ 5.115510] __driver_attach+0x134/0x14c
[ 5.119949] bus_for_each_dev+0x120/0x180
[ 5.124474] driver_attach+0x48/0x54
[ 5.128566] bus_add_driver+0x2ac/0x44c
[ 5.132919] driver_register+0x160/0x288
[ 5.137357] __platform_driver_register+0xcc/0xdc
[ 5.142576] pwm_backlight_driver_init+0x1c/0x24
[ 5.147708] do_one_initcall+0x38c/0x994
[ 5.152146] do_initcall_level+0x3a4/0x4b8
[ 5.156758] do_basic_setup+0x84/0xa0
[ 5.160936] kernel_init_freeable+0x23c/0x324
[ 5.165807] kernel_init+0x14/0x110
[ 5.169813] ret_from_fork+0x10/0x18
[ 5.173901]
[ 5.173901] -> #0 (regulator_list_mutex){+.+.}:
[ 5.179910] lock_acquire+0x350/0x4d4
[ 5.184088] __mutex_lock_common+0x1a0/0x1fe8
[ 5.184095] mutex_lock_nested+0x40/0x50
[ 5.197475] regulator_lock_dependent+0xdc/0x6c4
[ 5.197482] regulator_disable+0xa0/0x138
[ 5.197487] scpsys_power_off+0x38c/0x4bc
[ 5.197495] genpd_power_off+0x3d8/0x6a0
[ 5.209399] genpd_power_off+0x530/0x6a0
[ 5.209406] genpd_power_off_work_fn+0x74/0xc0
[ 5.209411] process_one_work+0x858/0x1208
[ 5.209419] worker_thread+0x9ec/0xcb8
[ 5.219067] kthread+0x2b8/0x2d0
[ 5.219073] ret_from_fork+0x10/0x18
[ 5.219077]
[ 5.219077] other info that might help us debug this:
[ 5.219077]
[ 5.219080] Chain exists of:
[ 5.219080] regulator_list_mutex --> &genpd->mlock --> &genpd->mlock/1
[ 5.219080]
[ 5.228039] Possible unsafe locking scenario:
[ 5.228039]
[ 5.228042] CPU0 CPU1
[ 5.228046] ---- ----
[ 5.228048] lock(&genpd->mlock/1);
[ 5.228058] lock(&genpd->mlock);
[ 5.311647] lock(&genpd->mlock/1);
[ 5.317736] lock(regulator_list_mutex);
[ 5.321742]
[ 5.321742] *** DEADLOCK ***
[ 5.321742]
[ 5.327655] 4 locks held by kworker/4:1/51:
[ 5.331831] #0: (____ptrval____) ((wq_completion)pm){+.+.},
at:process_one_work+0x57c/0x1208
[ 5.340444] #1: (____ptrval____)
((work_completion)(&genpd->power_off_work)){+.+.},
at:process_one_work+0x5b8/0x1208
[ 5.351139] #2: (____ptrval____) (&genpd->mlock){+.+.},
at:genpd_lock_mtx+0x20/0x2c
[ 5.358970] #3: (____ptrval____) (&genpd->mlock/1){+.+.},
at:genpd_lock_nested_mtx+0x24/0x30
[ 5.367584]
[ 5.367584] stack backtrace:
[ 5.371939] CPU: 4 PID: 51 Comm: kworker/4:1 Tainted: G S
5.2.0-rc2-next-20190528-44527-g6c94b6475c04 #20
[ 5.382809] Workqueue: pm genpd_power_off_work_fn
[ 5.382816] Call trace:
[ 5.382822] dump_backtrace+0x0/0x2c0
[ 5.382830] show_stack+0x20/0x2c
[ 5.409174] dump_stack+0x10c/0x17c
[ 5.412659] print_circular_bug+0x42c/0x4d0
[ 5.416838] __lock_acquire+0x4c88/0x5484
[ 5.420843] lock_acquire+0x350/0x4d4
[ 5.424500] __mutex_lock_common+0x1a0/0x1fe8
[ 5.428851] mutex_lock_nested+0x40/0x50
[ 5.432770] regulator_lock_dependent+0xdc/0x6c4
[ 5.437383] regulator_disable+0xa0/0x138
[ 5.441389] scpsys_power_off+0x38c/0x4bc
[ 5.445393] genpd_power_off+0x3d8/0x6a0
[ 5.449310] genpd_power_off+0x530/0x6a0
[ 5.453229] genpd_power_off_work_fn+0x74/0xc0
[ 5.457667] process_one_work+0x858/0x1208
[ 5.461758] worker_thread+0x9ec/0xcb8
[ 5.465503] kthread+0x2b8/0x2d0
[ 5.468727] ret_from_fork+0x10/0x18

On Mon, Jun 10, 2019 at 8:21 PM Yong Wu <[email protected]> wrote:
> ...
> + } else {
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + common->base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(common->base))
> + return PTR_ERR(common->base);
> }
> pm_runtime_enable(dev);
> platform_set_drvdata(pdev, common);

2019-06-15 19:20:09

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 07/21] iommu/mediatek: Add bclk can be supported optionally



On 10/06/2019 14:17, Yong Wu wrote:
> In some SoCs, M4U doesn't have its "bclk", it will use the EMI
> clock instead which has always been enabled when entering kernel.
>
> Currently mt2712 and mt8173 have this bclk while mt8183 doesn't.
>
> This also is a preparing patch for mt8183.
>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Evan Green <[email protected]>

Reviewed-by: Matthias Brugger <[email protected]>

> ---
> drivers/iommu/mtk_iommu.c | 10 +++++++---
> drivers/iommu/mtk_iommu.h | 3 +++
> 2 files changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index aff5004..264dda4 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -611,9 +611,11 @@ static int mtk_iommu_probe(struct platform_device *pdev)
> if (data->irq < 0)
> return data->irq;
>
> - data->bclk = devm_clk_get(dev, "bclk");
> - if (IS_ERR(data->bclk))
> - return PTR_ERR(data->bclk);
> + if (data->plat_data->has_bclk) {
> + data->bclk = devm_clk_get(dev, "bclk");
> + if (IS_ERR(data->bclk))
> + return PTR_ERR(data->bclk);
> + }
>
> larb_nr = of_count_phandle_with_args(dev->of_node,
> "mediatek,larbs", NULL);
> @@ -741,11 +743,13 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
> static const struct mtk_iommu_plat_data mt2712_data = {
> .m4u_plat = M4U_MT2712,
> .has_4gb_mode = true,
> + .has_bclk = true,
> };
>
> static const struct mtk_iommu_plat_data mt8173_data = {
> .m4u_plat = M4U_MT8173,
> .has_4gb_mode = true,
> + .has_bclk = true,
> };
>
> static const struct of_device_id mtk_iommu_of_ids[] = {
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index d7a001a..63e235e 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -43,6 +43,9 @@ enum mtk_iommu_plat {
> struct mtk_iommu_plat_data {
> enum mtk_iommu_plat m4u_plat;
> bool has_4gb_mode;
> +
> + /* HW will use the EMI clock if there isn't the "bclk". */
> + bool has_bclk;
> };
>
> struct mtk_iommu_domain;
>

2019-06-17 09:25:56

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 08/21] iommu/mediatek: Add larb-id remapped support



On 10/06/2019 14:17, Yong Wu wrote:
> The larb-id may be remapped in the smi-common, this means the
> larb-id reported in the mtk_iommu_isr isn't the real larb-id,
>
> Take mt8183 as a example:
> M4U
> |
> ---------------------------------------------
> | SMI common |
> -0-----7-----5-----6-----1-----2------3-----4- <- Id remapped
> | | | | | | | |
> larb0 larb1 IPU0 IPU1 larb4 larb5 larb6 CCU
> disp vdec img cam venc img cam
> As above, larb0 connects with the id 0 in smi-common.
> larb1 connects with the id 7 in smi-common.
> ...
> If the larb-id reported in the isr is 7, actually it's larb1(vdec).
> In order to output the right larb-id in the isr, we add a larb-id
> remapping relationship in this patch.
>
> If there is no this larb-id remapping in some SoCs, use the linear
> mapping array instead.
>
> This also is a preparing patch for mt8183.
>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Nicolas Boichat <[email protected]>
> Reviewed-by: Evan Green <[email protected]>

Reviewed-by: Matthias Brugger <[email protected]>

> ---
> drivers/iommu/mtk_iommu.c | 4 ++++
> drivers/iommu/mtk_iommu.h | 2 ++
> 2 files changed, 6 insertions(+)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 264dda4..ad838b9 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -220,6 +220,8 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
> fault_larb = F_MMU0_INT_ID_LARB_ID(regval);
> fault_port = F_MMU0_INT_ID_PORT_ID(regval);
>
> + fault_larb = data->plat_data->larbid_remap[fault_larb];
> +
> if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
> write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) {
> dev_err_ratelimited(
> @@ -744,12 +746,14 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
> .m4u_plat = M4U_MT2712,
> .has_4gb_mode = true,
> .has_bclk = true,
> + .larbid_remap = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
> };
>
> static const struct mtk_iommu_plat_data mt8173_data = {
> .m4u_plat = M4U_MT8173,
> .has_4gb_mode = true,
> .has_bclk = true,
> + .larbid_remap = {0, 1, 2, 3, 4, 5}, /* Linear mapping. */
> };
>
> static const struct of_device_id mtk_iommu_of_ids[] = {
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index 63e235e..61fd5d6 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -46,6 +46,8 @@ struct mtk_iommu_plat_data {
>
> /* HW will use the EMI clock if there isn't the "bclk". */
> bool has_bclk;
> +
> + unsigned char larbid_remap[MTK_LARB_NR_MAX];
> };
>
> struct mtk_iommu_domain;
>

2019-06-17 10:00:43

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 09/21] iommu/mediatek: Refine protect memory definition



On 10/06/2019 14:17, Yong Wu wrote:
> The protect memory setting is a little different in the different SoCs.
> In the register REG_MMU_CTRL_REG(0x110), the TF_PROT(translation fault
> protect) shift bit is normally 4 while it shift 5 bits only in the
> mt8173. This patch delete the complex MACRO and use a common if-else
> instead.
>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Evan Green <[email protected]>

Reviewed-by: Matthias Brugger <[email protected]>

> ---
> drivers/iommu/mtk_iommu.c | 13 ++++++-------
> 1 file changed, 6 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index ad838b9..d38dfa2 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -52,12 +52,9 @@
> #define REG_MMU_DCM_DIS 0x050
>
> #define REG_MMU_CTRL_REG 0x110
> +#define F_MMU_TF_PROT_TO_PROGRAM_ADDR (2 << 4)
> #define F_MMU_PREFETCH_RT_REPLACE_MOD BIT(4)
> -#define F_MMU_TF_PROTECT_SEL_SHIFT(data) \
> - ((data)->plat_data->m4u_plat == M4U_MT2712 ? 4 : 5)
> -/* It's named by F_MMU_TF_PROT_SEL in mt2712. */
> -#define F_MMU_TF_PROTECT_SEL(prot, data) \
> - (((prot) & 0x3) << F_MMU_TF_PROTECT_SEL_SHIFT(data))
> +#define F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173 (2 << 5)
>
> #define REG_MMU_IVRP_PADDR 0x114
>
> @@ -519,9 +516,11 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
> return ret;
> }
>
> - regval = F_MMU_TF_PROTECT_SEL(2, data);
> if (data->plat_data->m4u_plat == M4U_MT8173)
> - regval |= F_MMU_PREFETCH_RT_REPLACE_MOD;
> + regval = F_MMU_PREFETCH_RT_REPLACE_MOD |
> + F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173;
> + else
> + regval = F_MMU_TF_PROT_TO_PROGRAM_ADDR;
> writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
>
> regval = F_L2_MULIT_HIT_EN |
>

2019-06-17 10:20:03

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 10/21] iommu/mediatek: Move reset_axi into plat_data



On 10/06/2019 14:17, Yong Wu wrote:
> In mt8173 and mt8183, 0x48 is REG_MMU_STANDARD_AXI_MODE while it is
> REG_MMU_CTRL in the other SoCs, and the bits meaning is completely
> different with the REG_MMU_STANDARD_AXI_MODE.
>
> This patch moves this property to plat_data, it's also a preparing
> patch for mt8183.
>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Nicolas Boichat <[email protected]>
> Reviewed-by: Evan Green <[email protected]>

Reviewed-by: Matthias Brugger <[email protected]>

> ---
> drivers/iommu/mtk_iommu.c | 4 ++--
> drivers/iommu/mtk_iommu.h | 2 +-
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index d38dfa2..8ac7034 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -557,8 +557,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
> }
> writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
>
> - /* It's MISC control register whose default value is ok except mt8173.*/
> - if (data->plat_data->m4u_plat == M4U_MT8173)
> + if (data->plat_data->reset_axi)
> writel_relaxed(0, data->base + REG_MMU_STANDARD_AXI_MODE);
>
> if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
> @@ -752,6 +751,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
> .m4u_plat = M4U_MT8173,
> .has_4gb_mode = true,
> .has_bclk = true,
> + .reset_axi = true,
> .larbid_remap = {0, 1, 2, 3, 4, 5}, /* Linear mapping. */
> };
>
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index 61fd5d6..55d73c1 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -46,7 +46,7 @@ struct mtk_iommu_plat_data {
>
> /* HW will use the EMI clock if there isn't the "bclk". */
> bool has_bclk;
> -
> + bool reset_axi;
> unsigned char larbid_remap[MTK_LARB_NR_MAX];
> };
>
>

2019-06-17 10:28:30

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 11/21] iommu/mediatek: Move vld_pa_rng into plat_data



On 10/06/2019 14:17, Yong Wu wrote:
> Both mt8173 and mt8183 don't have this vld_pa_rng(valid physical address
> range) register while mt2712 have. Move it into the plat_data.
>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Evan Green <[email protected]>

Reviewed-by: Matthias Brugger <[email protected]>

> ---
> drivers/iommu/mtk_iommu.c | 3 ++-
> drivers/iommu/mtk_iommu.h | 1 +
> 2 files changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 8ac7034..a535dcd 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -547,7 +547,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
> upper_32_bits(data->protect_base);
> writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
>
> - if (data->enable_4GB && data->plat_data->m4u_plat != M4U_MT8173) {
> + if (data->enable_4GB && data->plat_data->has_vld_pa_rng) {
> /*
> * If 4GB mode is enabled, the validate PA range is from
> * 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
> @@ -744,6 +744,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
> .m4u_plat = M4U_MT2712,
> .has_4gb_mode = true,
> .has_bclk = true,
> + .has_vld_pa_rng = true,
> .larbid_remap = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
> };
>
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index 55d73c1..e5c9dde 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -47,6 +47,7 @@ struct mtk_iommu_plat_data {
> /* HW will use the EMI clock if there isn't the "bclk". */
> bool has_bclk;
> bool reset_axi;
> + bool has_vld_pa_rng;
> unsigned char larbid_remap[MTK_LARB_NR_MAX];
> };
>
>

2019-06-17 15:44:16

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 12/21] memory: mtk-smi: Add gals support



On 10/06/2019 14:17, Yong Wu wrote:
> In some SoCs like mt8183, SMI add GALS(Global Async Local Sync) module
> which can help synchronize for the modules in different clock frequency.
> It can be seen as a "asynchronous fifo". This is a example diagram:
>
> M4U
> |
> ----------
> | |
> gals0-rx gals1-rx
> | |
> | |
> gals0-tx gals1-tx
> | |
> ------------
> SMI Common
> ------------
> |
> +-----+--------+-----+- ...
> | | | |
> | gals-rx gals-rx |
> | | | |
> | | | |
> | gals-tx gals-tx |
> | | | |
> larb1 larb2 larb3 larb4
>
> GALS only help transfer the command/data while it doesn't have the
> configuring register, thus it has the special "smi" clock and doesn't
> have the "apb" clock. From the diagram above, we add "gals0" and
> "gals1" clocks for smi-common and add a "gals" clock for smi-larb.
>
> This patch adds gals clock supporting in the SMI. Note that some larbs
> may still don't have the "gals" clock like larb1 and larb4 above.
>
> This is also a preparing patch for mt8183 which has GALS.
>
> CC: Matthias Brugger <[email protected]>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Evan Green <[email protected]>

Reviewed-by: Matthias Brugger <[email protected]>

> ---
> drivers/memory/mtk-smi.c | 36 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 36 insertions(+)
>
> diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
> index 8a2f968..91634d7 100644
> --- a/drivers/memory/mtk-smi.c
> +++ b/drivers/memory/mtk-smi.c
> @@ -56,6 +56,7 @@ enum mtk_smi_gen {
>
> struct mtk_smi_common_plat {
> enum mtk_smi_gen gen;
> + bool has_gals;
> };
>
> struct mtk_smi_larb_gen {
> @@ -63,11 +64,13 @@ struct mtk_smi_larb_gen {
> int port_in_larb[MTK_LARB_NR_MAX + 1];
> void (*config_port)(struct device *);
> unsigned int larb_direct_to_common_mask;
> + bool has_gals;
> };
>
> struct mtk_smi {
> struct device *dev;
> struct clk *clk_apb, *clk_smi;
> + struct clk *clk_gals0, *clk_gals1;
> struct clk *clk_async; /*only needed by mt2701*/
> void __iomem *smi_ao_base;
>
> @@ -99,8 +102,20 @@ static int mtk_smi_enable(const struct mtk_smi *smi)
> if (ret)
> goto err_disable_apb;
>
> + ret = clk_prepare_enable(smi->clk_gals0);
> + if (ret)
> + goto err_disable_smi;
> +
> + ret = clk_prepare_enable(smi->clk_gals1);
> + if (ret)
> + goto err_disable_gals0;
> +
> return 0;
>
> +err_disable_gals0:
> + clk_disable_unprepare(smi->clk_gals0);
> +err_disable_smi:
> + clk_disable_unprepare(smi->clk_smi);
> err_disable_apb:
> clk_disable_unprepare(smi->clk_apb);
> err_put_pm:
> @@ -110,6 +125,8 @@ static int mtk_smi_enable(const struct mtk_smi *smi)
>
> static void mtk_smi_disable(const struct mtk_smi *smi)
> {
> + clk_disable_unprepare(smi->clk_gals1);
> + clk_disable_unprepare(smi->clk_gals0);
> clk_disable_unprepare(smi->clk_smi);
> clk_disable_unprepare(smi->clk_apb);
> pm_runtime_put_sync(smi->dev);
> @@ -310,6 +327,15 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
> larb->smi.clk_smi = devm_clk_get(dev, "smi");
> if (IS_ERR(larb->smi.clk_smi))
> return PTR_ERR(larb->smi.clk_smi);
> +
> + if (larb->larb_gen->has_gals) {
> + /* The larbs may still haven't gals even if the SoC support.*/
> + larb->smi.clk_gals0 = devm_clk_get(dev, "gals");
> + if (PTR_ERR(larb->smi.clk_gals0) == -ENOENT)
> + larb->smi.clk_gals0 = NULL;
> + else if (IS_ERR(larb->smi.clk_gals0))
> + return PTR_ERR(larb->smi.clk_gals0);
> + }
> larb->smi.dev = dev;
>
> if (larb->larb_gen->need_larbid) {
> @@ -402,6 +428,16 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
> if (IS_ERR(common->clk_smi))
> return PTR_ERR(common->clk_smi);
>
> + if (common->plat->has_gals) {
> + common->clk_gals0 = devm_clk_get(dev, "gals0");
> + if (IS_ERR(common->clk_gals0))
> + return PTR_ERR(common->clk_gals0);
> +
> + common->clk_gals1 = devm_clk_get(dev, "gals1");
> + if (IS_ERR(common->clk_gals1))
> + return PTR_ERR(common->clk_gals1);
> + }
> +
> /*
> * for mtk smi gen 1, we need to get the ao(always on) base to config
> * m4u port, and we need to enable the aync clock for transform the smi
>

2019-06-17 15:52:16

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 13/21] iommu/mediatek: Add mt8183 IOMMU support



On 10/06/2019 14:17, Yong Wu wrote:
> The M4U IP blocks in mt8183 is MediaTek's generation2 M4U which use
> the ARM Short-descriptor like mt8173, and most of the HW registers
> are the same.
>
> Here list main differences between mt8183 and mt8173/mt2712:
> 1) mt8183 has only one M4U HW like mt8173 while mt2712 has two.
> 2) mt8183 don't have the "bclk" clock, it use the EMI clock instead.
> 3) mt8183 can support the dram over 4GB, but it doesn't call this "4GB
> mode".
> 4) mt8183 pgtable base register(0x0) extend bit[1:0] which represent
> the bit[33:32] in the physical address of the pgtable base, But the
> standard ttbr0[1] means the S bit which is enabled defaultly, Hence,
> we add a mask.
> 5) mt8183 HW has a GALS modules, SMI should enable "has_gals" support.
> 6) mt8183 need reset_axi like mt8173.
> 7) the larb-id in smi-common is remapped. M4U should add its larbid_remap.
>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Evan Green <[email protected]>

Reviewed-by: Matthias Brugger <[email protected]>

> ---
> drivers/iommu/mtk_iommu.c | 15 ++++++++++++---
> drivers/iommu/mtk_iommu.h | 1 +
> drivers/memory/mtk-smi.c | 20 ++++++++++++++++++++
> 3 files changed, 33 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index a535dcd..3a14301 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -36,6 +36,7 @@
> #include "mtk_iommu.h"
>
> #define REG_MMU_PT_BASE_ADDR 0x000
> +#define MMU_PT_ADDR_MASK GENMASK(31, 7)
>
> #define REG_MMU_INVALIDATE 0x020
> #define F_ALL_INVLD 0x2
> @@ -341,7 +342,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
> /* Update the pgtable base address register of the M4U HW */
> if (!data->m4u_dom) {
> data->m4u_dom = dom;
> - writel(dom->cfg.arm_v7s_cfg.ttbr[0],
> + writel(dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
> data->base + REG_MMU_PT_BASE_ADDR);
> }
>
> @@ -715,6 +716,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
> {
> struct mtk_iommu_data *data = dev_get_drvdata(dev);
> struct mtk_iommu_suspend_reg *reg = &data->reg;
> + struct mtk_iommu_domain *m4u_dom = data->m4u_dom;
> void __iomem *base = data->base;
> int ret;
>
> @@ -730,8 +732,8 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
> writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0);
> writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
> writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
> - if (data->m4u_dom)
> - writel(data->m4u_dom->cfg.arm_v7s_cfg.ttbr[0],
> + if (m4u_dom)
> + writel(m4u_dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
> base + REG_MMU_PT_BASE_ADDR);
> return 0;
> }
> @@ -756,9 +758,16 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
> .larbid_remap = {0, 1, 2, 3, 4, 5}, /* Linear mapping. */
> };
>
> +static const struct mtk_iommu_plat_data mt8183_data = {
> + .m4u_plat = M4U_MT8183,
> + .reset_axi = true,
> + .larbid_remap = {0, 4, 5, 6, 7, 2, 3, 1},
> +};
> +
> static const struct of_device_id mtk_iommu_of_ids[] = {
> { .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data},
> { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data},
> + { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data},
> {}
> };
>
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index e5c9dde..c0b5c65 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -38,6 +38,7 @@ enum mtk_iommu_plat {
> M4U_MT2701,
> M4U_MT2712,
> M4U_MT8173,
> + M4U_MT8183,
> };
>
> struct mtk_iommu_plat_data {
> diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
> index 91634d7..a430721 100644
> --- a/drivers/memory/mtk-smi.c
> +++ b/drivers/memory/mtk-smi.c
> @@ -285,6 +285,13 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev)
> .larb_direct_to_common_mask = BIT(8) | BIT(9), /* bdpsys */
> };
>
> +static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = {
> + .has_gals = true,
> + .config_port = mtk_smi_larb_config_port_gen2_general,
> + .larb_direct_to_common_mask = BIT(2) | BIT(3) | BIT(7),
> + /* IPU0 | IPU1 | CCU */
> +};
> +
> static const struct of_device_id mtk_smi_larb_of_ids[] = {
> {
> .compatible = "mediatek,mt8173-smi-larb",
> @@ -298,6 +305,10 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev)
> .compatible = "mediatek,mt2712-smi-larb",
> .data = &mtk_smi_larb_mt2712
> },
> + {
> + .compatible = "mediatek,mt8183-smi-larb",
> + .data = &mtk_smi_larb_mt8183
> + },
> {}
> };
>
> @@ -391,6 +402,11 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
> .gen = MTK_SMI_GEN2,
> };
>
> +static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
> + .gen = MTK_SMI_GEN2,
> + .has_gals = true,
> +};
> +
> static const struct of_device_id mtk_smi_common_of_ids[] = {
> {
> .compatible = "mediatek,mt8173-smi-common",
> @@ -404,6 +420,10 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
> .compatible = "mediatek,mt2712-smi-common",
> .data = &mtk_smi_common_gen2,
> },
> + {
> + .compatible = "mediatek,mt8183-smi-common",
> + .data = &mtk_smi_common_mt8183,
> + },
> {}
> };
>
>

2019-06-17 15:58:52

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 14/21] iommu/mediatek: Add mmu1 support



On 10/06/2019 14:17, Yong Wu wrote:
> Normally the M4U HW connect EMI with smi. the diagram is like below:
> EMI
> |
> M4U
> |
> smi-common
> |
> -----------------
> | | | | ...
> larb0 larb1 larb2 larb3
>
> Actually there are 2 mmu cells in the M4U HW, like this diagram:
>
> EMI
> ---------
> | |
> mmu0 mmu1 <- M4U
> | |
> ---------
> |
> smi-common
> |
> -----------------
> | | | | ...
> larb0 larb1 larb2 larb3
>
> This patch add support for mmu1. In order to get better performance,
> we could adjust some larbs go to mmu1 while the others still go to
> mmu0. This is controlled by a SMI COMMON register SMI_BUS_SEL(0x220).
>
> mt2712, mt8173 and mt8183 M4U HW all have 2 mmu cells. the default
> value of that register is 0 which means all the larbs go to mmu0
> defaultly.
>
> This is a preparing patch for adjusting SMI_BUS_SEL for mt8183.
>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Evan Green <[email protected]>

Reviewed-by: Matthias Brugger <[email protected]>

> ---
> drivers/iommu/mtk_iommu.c | 46 +++++++++++++++++++++++++++++-----------------
> 1 file changed, 29 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 3a14301..ec4ce74 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -72,26 +72,32 @@
> #define F_INT_CLR_BIT BIT(12)
>
> #define REG_MMU_INT_MAIN_CONTROL 0x124
> -#define F_INT_TRANSLATION_FAULT BIT(0)
> -#define F_INT_MAIN_MULTI_HIT_FAULT BIT(1)
> -#define F_INT_INVALID_PA_FAULT BIT(2)
> -#define F_INT_ENTRY_REPLACEMENT_FAULT BIT(3)
> -#define F_INT_TLB_MISS_FAULT BIT(4)
> -#define F_INT_MISS_TRANSACTION_FIFO_FAULT BIT(5)
> -#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT BIT(6)
> + /* mmu0 | mmu1 */
> +#define F_INT_TRANSLATION_FAULT (BIT(0) | BIT(7))
> +#define F_INT_MAIN_MULTI_HIT_FAULT (BIT(1) | BIT(8))
> +#define F_INT_INVALID_PA_FAULT (BIT(2) | BIT(9))
> +#define F_INT_ENTRY_REPLACEMENT_FAULT (BIT(3) | BIT(10))
> +#define F_INT_TLB_MISS_FAULT (BIT(4) | BIT(11))
> +#define F_INT_MISS_TRANSACTION_FIFO_FAULT (BIT(5) | BIT(12))
> +#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT (BIT(6) | BIT(13))
>
> #define REG_MMU_CPE_DONE 0x12C
>
> #define REG_MMU_FAULT_ST1 0x134
> +#define F_REG_MMU0_FAULT_MASK GENMASK(6, 0)
> +#define F_REG_MMU1_FAULT_MASK GENMASK(13, 7)
>
> -#define REG_MMU_FAULT_VA 0x13c
> +#define REG_MMU0_FAULT_VA 0x13c
> #define F_MMU_FAULT_VA_WRITE_BIT BIT(1)
> #define F_MMU_FAULT_VA_LAYER_BIT BIT(0)
>
> -#define REG_MMU_INVLD_PA 0x140
> -#define REG_MMU_INT_ID 0x150
> -#define F_MMU0_INT_ID_LARB_ID(a) (((a) >> 7) & 0x7)
> -#define F_MMU0_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f)
> +#define REG_MMU0_INVLD_PA 0x140
> +#define REG_MMU1_FAULT_VA 0x144
> +#define REG_MMU1_INVLD_PA 0x148
> +#define REG_MMU0_INT_ID 0x150
> +#define REG_MMU1_INT_ID 0x154
> +#define F_MMU_INT_ID_LARB_ID(a) (((a) >> 7) & 0x7)
> +#define F_MMU_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f)
>
> #define MTK_PROTECT_PA_ALIGN 128
>
> @@ -210,13 +216,19 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
>
> /* Read error info from registers */
> int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST1);
> - fault_iova = readl_relaxed(data->base + REG_MMU_FAULT_VA);
> + if (int_state & F_REG_MMU0_FAULT_MASK) {
> + regval = readl_relaxed(data->base + REG_MMU0_INT_ID);
> + fault_iova = readl_relaxed(data->base + REG_MMU0_FAULT_VA);
> + fault_pa = readl_relaxed(data->base + REG_MMU0_INVLD_PA);
> + } else {
> + regval = readl_relaxed(data->base + REG_MMU1_INT_ID);
> + fault_iova = readl_relaxed(data->base + REG_MMU1_FAULT_VA);
> + fault_pa = readl_relaxed(data->base + REG_MMU1_INVLD_PA);
> + }
> layer = fault_iova & F_MMU_FAULT_VA_LAYER_BIT;
> write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT;
> - fault_pa = readl_relaxed(data->base + REG_MMU_INVLD_PA);
> - regval = readl_relaxed(data->base + REG_MMU_INT_ID);
> - fault_larb = F_MMU0_INT_ID_LARB_ID(regval);
> - fault_port = F_MMU0_INT_ID_PORT_ID(regval);
> + fault_larb = F_MMU_INT_ID_LARB_ID(regval);
> + fault_port = F_MMU_INT_ID_PORT_ID(regval);
>
> fault_larb = data->plat_data->larbid_remap[fault_larb];
>
>

2019-06-17 16:15:56

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 15/21] memory: mtk-smi: Invoke pm runtime_callback to enable clocks



On 10/06/2019 14:17, Yong Wu wrote:
> This patch only move the clk_prepare_enable and config_port into the
> runtime suspend/resume callback. It doesn't change the code content
> and sequence.
>
> This is a preparing patch for adjusting SMI_BUS_SEL for mt8183.
> (SMI_BUS_SEL need to be restored after smi-common resume every time.)
> Also it gives a chance to get rid of mtk_smi_larb_get/put which could
> be a next topic.
>
> CC: Matthias Brugger <[email protected]>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Evan Green <[email protected]>

Reviewed-by: Matthias Brugger <[email protected]>

> ---
> drivers/memory/mtk-smi.c | 113 ++++++++++++++++++++++++++++++-----------------
> 1 file changed, 72 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
> index a430721..9790801 100644
> --- a/drivers/memory/mtk-smi.c
> +++ b/drivers/memory/mtk-smi.c
> @@ -86,17 +86,13 @@ struct mtk_smi_larb { /* larb: local arbiter */
> u32 *mmu;
> };
>
> -static int mtk_smi_enable(const struct mtk_smi *smi)
> +static int mtk_smi_clk_enable(const struct mtk_smi *smi)
> {
> int ret;
>
> - ret = pm_runtime_get_sync(smi->dev);
> - if (ret < 0)
> - return ret;
> -
> ret = clk_prepare_enable(smi->clk_apb);
> if (ret)
> - goto err_put_pm;
> + return ret;
>
> ret = clk_prepare_enable(smi->clk_smi);
> if (ret)
> @@ -118,59 +114,28 @@ static int mtk_smi_enable(const struct mtk_smi *smi)
> clk_disable_unprepare(smi->clk_smi);
> err_disable_apb:
> clk_disable_unprepare(smi->clk_apb);
> -err_put_pm:
> - pm_runtime_put_sync(smi->dev);
> return ret;
> }
>
> -static void mtk_smi_disable(const struct mtk_smi *smi)
> +static void mtk_smi_clk_disable(const struct mtk_smi *smi)
> {
> clk_disable_unprepare(smi->clk_gals1);
> clk_disable_unprepare(smi->clk_gals0);
> clk_disable_unprepare(smi->clk_smi);
> clk_disable_unprepare(smi->clk_apb);
> - pm_runtime_put_sync(smi->dev);
> }
>
> int mtk_smi_larb_get(struct device *larbdev)
> {
> - struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
> - const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
> - struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
> - int ret;
> + int ret = pm_runtime_get_sync(larbdev);
>
> - /* Enable the smi-common's power and clocks */
> - ret = mtk_smi_enable(common);
> - if (ret)
> - return ret;
> -
> - /* Enable the larb's power and clocks */
> - ret = mtk_smi_enable(&larb->smi);
> - if (ret) {
> - mtk_smi_disable(common);
> - return ret;
> - }
> -
> - /* Configure the iommu info for this larb */
> - larb_gen->config_port(larbdev);
> -
> - return 0;
> + return (ret < 0) ? ret : 0;
> }
> EXPORT_SYMBOL_GPL(mtk_smi_larb_get);
>
> void mtk_smi_larb_put(struct device *larbdev)
> {
> - struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
> - struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
> -
> - /*
> - * Don't de-configure the iommu info for this larb since there may be
> - * several modules in this larb.
> - * The iommu info will be reset after power off.
> - */
> -
> - mtk_smi_disable(&larb->smi);
> - mtk_smi_disable(common);
> + pm_runtime_put_sync(larbdev);
> }
> EXPORT_SYMBOL_GPL(mtk_smi_larb_put);
>
> @@ -385,12 +350,52 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
> return 0;
> }
>
> +static int __maybe_unused mtk_smi_larb_resume(struct device *dev)
> +{
> + struct mtk_smi_larb *larb = dev_get_drvdata(dev);
> + const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
> + int ret;
> +
> + /* Power on smi-common. */
> + ret = pm_runtime_get_sync(larb->smi_common_dev);
> + if (ret < 0) {
> + dev_err(dev, "Failed to pm get for smi-common(%d).\n", ret);
> + return ret;
> + }
> +
> + ret = mtk_smi_clk_enable(&larb->smi);
> + if (ret < 0) {
> + dev_err(dev, "Failed to enable clock(%d).\n", ret);
> + pm_runtime_put_sync(larb->smi_common_dev);
> + return ret;
> + }
> +
> + /* Configure the basic setting for this larb */
> + larb_gen->config_port(dev);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused mtk_smi_larb_suspend(struct device *dev)
> +{
> + struct mtk_smi_larb *larb = dev_get_drvdata(dev);
> +
> + mtk_smi_clk_disable(&larb->smi);
> + pm_runtime_put_sync(larb->smi_common_dev);
> + return 0;
> +}
> +
> +static const struct dev_pm_ops smi_larb_pm_ops = {
> + SET_RUNTIME_PM_OPS(mtk_smi_larb_suspend, mtk_smi_larb_resume, NULL)
> +};
> +
> static struct platform_driver mtk_smi_larb_driver = {
> .probe = mtk_smi_larb_probe,
> .remove = mtk_smi_larb_remove,
> .driver = {
> .name = "mtk-smi-larb",
> .of_match_table = mtk_smi_larb_of_ids,
> + .pm = &smi_larb_pm_ops,
> }
> };
>
> @@ -489,12 +494,38 @@ static int mtk_smi_common_remove(struct platform_device *pdev)
> return 0;
> }
>
> +static int __maybe_unused mtk_smi_common_resume(struct device *dev)
> +{
> + struct mtk_smi *common = dev_get_drvdata(dev);
> + int ret;
> +
> + ret = mtk_smi_clk_enable(common);
> + if (ret) {
> + dev_err(common->dev, "Failed to enable clock(%d).\n", ret);
> + return ret;
> + }
> + return 0;
> +}
> +
> +static int __maybe_unused mtk_smi_common_suspend(struct device *dev)
> +{
> + struct mtk_smi *common = dev_get_drvdata(dev);
> +
> + mtk_smi_clk_disable(common);
> + return 0;
> +}
> +
> +static const struct dev_pm_ops smi_common_pm_ops = {
> + SET_RUNTIME_PM_OPS(mtk_smi_common_suspend, mtk_smi_common_resume, NULL)
> +};
> +
> static struct platform_driver mtk_smi_common_driver = {
> .probe = mtk_smi_common_probe,
> .remove = mtk_smi_common_remove,
> .driver = {
> .name = "mtk-smi-common",
> .of_match_table = mtk_smi_common_of_ids,
> + .pm = &smi_common_pm_ops,
> }
> };
>
>

2019-06-17 16:24:00

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 16/21] memory: mtk-smi: Add bus_sel for mt8183



On 10/06/2019 14:17, Yong Wu wrote:
> There are 2 mmu cells in a M4U HW. we could adjust some larbs entering
> mmu0 or mmu1 to balance the bandwidth via the smi-common register
> SMI_BUS_SEL(0x220)(Each larb occupy 2 bits).
>
> In mt8183, For better performance, we switch larb1/2/5/7 to enter
> mmu1 while the others still keep enter mmu0.
>
> In mt8173 and mt2712, we don't get the performance issue,
> Keep its default value(0x0), that means all the larbs enter mmu0.
>
> Note: smi gen1(mt2701/mt7623) don't have this bus_sel.
>
> And, the base of smi-common is completely different with smi_ao_base
> of gen1, thus I add new variable for that.
>
> CC: Matthias Brugger <[email protected]>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Evan Green <[email protected]>
> ---
> drivers/memory/mtk-smi.c | 22 ++++++++++++++++++++--
> 1 file changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
> index 9790801..08cf40d 100644
> --- a/drivers/memory/mtk-smi.c
> +++ b/drivers/memory/mtk-smi.c
> @@ -49,6 +49,12 @@
> #define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4))
> #define F_MMU_EN BIT(0)
>
> +/* SMI COMMON */
> +#define SMI_BUS_SEL 0x220
> +#define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1)
> +/* All are MMU0 defaultly. Only specialize mmu1 here. */
> +#define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid))
> +
> enum mtk_smi_gen {
> MTK_SMI_GEN1,
> MTK_SMI_GEN2
> @@ -57,6 +63,7 @@ enum mtk_smi_gen {
> struct mtk_smi_common_plat {
> enum mtk_smi_gen gen;
> bool has_gals;
> + u32 bus_sel; /* Balance some larbs to enter mmu0 or mmu1 */
> };
>
> struct mtk_smi_larb_gen {
> @@ -72,8 +79,8 @@ struct mtk_smi {
> struct clk *clk_apb, *clk_smi;
> struct clk *clk_gals0, *clk_gals1;
> struct clk *clk_async; /*only needed by mt2701*/
> - void __iomem *smi_ao_base;
> -
> + void __iomem *smi_ao_base; /* only for gen1 */
> + void __iomem *base; /* only for gen2 */

union {} maybe?

> const struct mtk_smi_common_plat *plat;
> };
>
> @@ -410,6 +417,8 @@ static int __maybe_unused mtk_smi_larb_suspend(struct device *dev)
> static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
> .gen = MTK_SMI_GEN2,
> .has_gals = true,
> + .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(5) |
> + F_MMU1_LARB(7),
> };
>
> static const struct of_device_id mtk_smi_common_of_ids[] = {
> @@ -482,6 +491,11 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
> ret = clk_prepare_enable(common->clk_async);
> if (ret)
> return ret;
> + } else {
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + common->base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(common->base))
> + return PTR_ERR(common->base);

We must be backwards compatible with DT which does not have the base defined.

Regards,
Matthias

> }
> pm_runtime_enable(dev);
> platform_set_drvdata(pdev, common);
> @@ -497,6 +511,7 @@ static int mtk_smi_common_remove(struct platform_device *pdev)
> static int __maybe_unused mtk_smi_common_resume(struct device *dev)
> {
> struct mtk_smi *common = dev_get_drvdata(dev);
> + u32 bus_sel = common->plat->bus_sel;
> int ret;
>
> ret = mtk_smi_clk_enable(common);
> @@ -504,6 +519,9 @@ static int __maybe_unused mtk_smi_common_resume(struct device *dev)
> dev_err(common->dev, "Failed to enable clock(%d).\n", ret);
> return ret;
> }
> +
> + if (common->plat->gen == MTK_SMI_GEN2 && bus_sel)
> + writel(bus_sel, common->base + SMI_BUS_SEL);
> return 0;
> }
>
>

2019-06-17 16:29:44

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 16/21] memory: mtk-smi: Add bus_sel for mt8183



On 13/06/2019 10:20, Pi-Hsun Shih wrote:
> (Sorry for the possibly double-posting, my last mail got rejected by
> some mailing lists.)
>
> Hi,
> When I tested this patch series (Based on linux 5.2.0-rc2, and with
> various other patch series about MT8183) with lockdep enabled, and I'm
> seeing the following lockdep warning on boot.
>
> By bisecting the commits, the first commit that introduce this warning
> is this patch. The warning also doesn't appear if

Are you sure about this?
From the lockdep call graph it looks more like patch
[PATCH v7 15/21] memory: mtk-smi: Invoke pm runtime_callback to enable clocks
has something to do with it.

But not an expert either, sorry.

Regards,
Matthias

> https://lore.kernel.org/patchwork/patch/1086582/ and
> https://lore.kernel.org/patchwork/patch/1086583/ are not applied.
>
> Do anyone have idea on why this is happening, or any suggestion on
> which part I should be digging into to figure this out? Thanks.
>
> [ 4.664194] ======================================================
> [ 4.670368] WARNING: possible circular locking dependency detected
> [ 4.676545] 5.2.0-rc2-next-20190528-44527-g6c94b6475c04 #20 Tainted: G S
> [ 4.684539] ------------------------------------------------------
> [ 4.690714] kworker/4:1/51 is trying to acquire lock:
> [ 4.695760] (____ptrval____) (regulator_list_mutex){+.+.},
> at:regulator_lock_dependent+0xdc/0x6c4
> [ 4.704732]
> [ 4.704732] but task is already holding lock:
> [ 4.710556] (____ptrval____) (&genpd->mlock/1){+.+.},
> at:genpd_lock_nested_mtx+0x24/0x30
> [ 4.718740]
> [ 4.718740] which lock already depends on the new lock.
> [ 4.718740]
> [ 4.726908]
> [ 4.726908] the existing dependency chain (in reverse order) is:
> [ 4.734382]
> [ 4.734382] -> #4 (&genpd->mlock/1){+.+.}:
> [ 4.739963] __mutex_lock_common+0x1a0/0x1fe8
> [ 4.744836] mutex_lock_nested+0x40/0x50
> [ 4.749275] genpd_lock_nested_mtx+0x24/0x30
> [ 4.754063] genpd_add_subdomain+0x150/0x524
> [ 4.758850] pm_genpd_add_subdomain+0x3c/0x5c
> [ 4.763723] scpsys_probe+0x520/0xe78
> [ 4.767902] platform_drv_probe+0xf4/0x134
> [ 4.772517] really_probe+0x214/0x4dc
> [ 4.776696] driver_probe_device+0xcc/0x1d4
> [ 4.781396] __device_attach_driver+0x10c/0x180
> [ 4.786442] bus_for_each_drv+0x124/0x184
> [ 4.790968] __device_attach+0x1c0/0x2d8
> [ 4.795407] device_initial_probe+0x20/0x2c
> [ 4.800106] bus_probe_device+0x80/0x16c
> [ 4.804546] deferred_probe_work_func+0x120/0x168
> [ 4.809767] process_one_work+0x858/0x1208
> [ 4.814379] worker_thread+0x9ec/0xcb8
> [ 4.818644] kthread+0x2b8/0x2d0
> [ 4.822391] ret_from_fork+0x10/0x18
> [ 4.826480]
> [ 4.826480] -> #3 (&genpd->mlock){+.+.}:
> [ 4.831880] __mutex_lock_common+0x1a0/0x1fe8
> [ 4.836752] mutex_lock_nested+0x40/0x50
> [ 4.841190] genpd_lock_mtx+0x20/0x2c
> [ 4.845369] genpd_runtime_resume+0x140/0x434
> [ 4.850241] __rpm_callback+0xb0/0x1e4
> [ 4.854506] rpm_callback+0x54/0x1a8
> [ 4.858597] rpm_resume+0xc6c/0x10c4
> [ 4.862689] __pm_runtime_resume+0xb4/0x124
> [ 4.867387] device_link_add+0x598/0x8d0
> [ 4.871829] mtk_smi_larb_probe+0x2b0/0x340
> [ 4.876528] platform_drv_probe+0xf4/0x134
> [ 4.881141] really_probe+0x214/0x4dc
> [ 4.885320] driver_probe_device+0xcc/0x1d4
> [ 4.890020] __device_attach_driver+0x10c/0x180
> [ 4.895066] bus_for_each_drv+0x124/0x184
> [ 4.899591] __device_attach+0x1c0/0x2d8
> [ 4.904031] device_initial_probe+0x20/0x2c
> [ 4.908730] bus_probe_device+0x80/0x16c
> [ 4.913169] deferred_probe_work_func+0x120/0x168
> [ 4.918387] process_one_work+0x858/0x1208
> [ 4.923000] worker_thread+0x9ec/0xcb8
> [ 4.927264] kthread+0x2b8/0x2d0
> [ 4.931009] ret_from_fork+0x10/0x18
> [ 4.935098]
> [ 4.935098] -> #2 (dpm_list_mtx){+.+.}:
> [ 4.940412] __mutex_lock_common+0x1a0/0x1fe8
> [ 4.945284] mutex_lock_nested+0x40/0x50
> [ 4.949722] device_pm_lock+0x1c/0x24
> [ 4.953900] device_link_add+0x98/0x8d0
> [ 4.958252] _regulator_get+0x3f0/0x504
> [ 4.962606] _devm_regulator_get+0x58/0xb8
> [ 4.967218] devm_regulator_get+0x28/0x34
> [ 4.971746] pwm_backlight_probe+0x61c/0x1b90
> [ 4.976617] platform_drv_probe+0xf4/0x134
> [ 4.981230] really_probe+0x214/0x4dc
> [ 4.985409] driver_probe_device+0xcc/0x1d4
> [ 4.990108] device_driver_attach+0xe4/0x104
> [ 4.994894] __driver_attach+0x134/0x14c
> [ 4.999333] bus_for_each_dev+0x120/0x180
> [ 5.003859] driver_attach+0x48/0x54
> [ 5.007950] bus_add_driver+0x2ac/0x44c
> [ 5.012303] driver_register+0x160/0x288
> [ 5.016742] __platform_driver_register+0xcc/0xdc
> [ 5.021964] pwm_backlight_driver_init+0x1c/0x24
> [ 5.027097] do_one_initcall+0x38c/0x994
> [ 5.031536] do_initcall_level+0x3a4/0x4b8
> [ 5.036148] do_basic_setup+0x84/0xa0
> [ 5.036153] kernel_init_freeable+0x23c/0x324
> [ 5.036158] kernel_init+0x14/0x110
> [ 5.036164] ret_from_fork+0x10/0x18
> [ 5.036166]
> [ 5.036166] -> #1 (device_links_lock){+.+.}:
> [ 5.065905] __mutex_lock_common+0x1a0/0x1fe8
> [ 5.070777] mutex_lock_nested+0x40/0x50
> [ 5.075215] device_link_remove+0x40/0xe0
> [ 5.079740] _regulator_put+0x104/0x2d8
> [ 5.084093] regulator_put+0x30/0x44
> [ 5.088184] devm_regulator_release+0x38/0x44
> [ 5.093056] release_nodes+0x604/0x670
> [ 5.097320] devres_release_all+0x70/0x8c
> [ 5.101846] really_probe+0x270/0x4dc
> [ 5.106024] driver_probe_device+0xcc/0x1d4
> [ 5.110724] device_driver_attach+0xe4/0x104
> [ 5.115510] __driver_attach+0x134/0x14c
> [ 5.119949] bus_for_each_dev+0x120/0x180
> [ 5.124474] driver_attach+0x48/0x54
> [ 5.128566] bus_add_driver+0x2ac/0x44c
> [ 5.132919] driver_register+0x160/0x288
> [ 5.137357] __platform_driver_register+0xcc/0xdc
> [ 5.142576] pwm_backlight_driver_init+0x1c/0x24
> [ 5.147708] do_one_initcall+0x38c/0x994
> [ 5.152146] do_initcall_level+0x3a4/0x4b8
> [ 5.156758] do_basic_setup+0x84/0xa0
> [ 5.160936] kernel_init_freeable+0x23c/0x324
> [ 5.165807] kernel_init+0x14/0x110
> [ 5.169813] ret_from_fork+0x10/0x18
> [ 5.173901]
> [ 5.173901] -> #0 (regulator_list_mutex){+.+.}:
> [ 5.179910] lock_acquire+0x350/0x4d4
> [ 5.184088] __mutex_lock_common+0x1a0/0x1fe8
> [ 5.184095] mutex_lock_nested+0x40/0x50
> [ 5.197475] regulator_lock_dependent+0xdc/0x6c4
> [ 5.197482] regulator_disable+0xa0/0x138
> [ 5.197487] scpsys_power_off+0x38c/0x4bc
> [ 5.197495] genpd_power_off+0x3d8/0x6a0
> [ 5.209399] genpd_power_off+0x530/0x6a0
> [ 5.209406] genpd_power_off_work_fn+0x74/0xc0
> [ 5.209411] process_one_work+0x858/0x1208
> [ 5.209419] worker_thread+0x9ec/0xcb8
> [ 5.219067] kthread+0x2b8/0x2d0
> [ 5.219073] ret_from_fork+0x10/0x18
> [ 5.219077]
> [ 5.219077] other info that might help us debug this:
> [ 5.219077]
> [ 5.219080] Chain exists of:
> [ 5.219080] regulator_list_mutex --> &genpd->mlock --> &genpd->mlock/1
> [ 5.219080]
> [ 5.228039] Possible unsafe locking scenario:
> [ 5.228039]
> [ 5.228042] CPU0 CPU1
> [ 5.228046] ---- ----
> [ 5.228048] lock(&genpd->mlock/1);
> [ 5.228058] lock(&genpd->mlock);
> [ 5.311647] lock(&genpd->mlock/1);
> [ 5.317736] lock(regulator_list_mutex);
> [ 5.321742]
> [ 5.321742] *** DEADLOCK ***
> [ 5.321742]
> [ 5.327655] 4 locks held by kworker/4:1/51:
> [ 5.331831] #0: (____ptrval____) ((wq_completion)pm){+.+.},
> at:process_one_work+0x57c/0x1208
> [ 5.340444] #1: (____ptrval____)
> ((work_completion)(&genpd->power_off_work)){+.+.},
> at:process_one_work+0x5b8/0x1208
> [ 5.351139] #2: (____ptrval____) (&genpd->mlock){+.+.},
> at:genpd_lock_mtx+0x20/0x2c
> [ 5.358970] #3: (____ptrval____) (&genpd->mlock/1){+.+.},
> at:genpd_lock_nested_mtx+0x24/0x30
> [ 5.367584]
> [ 5.367584] stack backtrace:
> [ 5.371939] CPU: 4 PID: 51 Comm: kworker/4:1 Tainted: G S
> 5.2.0-rc2-next-20190528-44527-g6c94b6475c04 #20
> [ 5.382809] Workqueue: pm genpd_power_off_work_fn
> [ 5.382816] Call trace:
> [ 5.382822] dump_backtrace+0x0/0x2c0
> [ 5.382830] show_stack+0x20/0x2c
> [ 5.409174] dump_stack+0x10c/0x17c
> [ 5.412659] print_circular_bug+0x42c/0x4d0
> [ 5.416838] __lock_acquire+0x4c88/0x5484
> [ 5.420843] lock_acquire+0x350/0x4d4
> [ 5.424500] __mutex_lock_common+0x1a0/0x1fe8
> [ 5.428851] mutex_lock_nested+0x40/0x50
> [ 5.432770] regulator_lock_dependent+0xdc/0x6c4
> [ 5.437383] regulator_disable+0xa0/0x138
> [ 5.441389] scpsys_power_off+0x38c/0x4bc
> [ 5.445393] genpd_power_off+0x3d8/0x6a0
> [ 5.449310] genpd_power_off+0x530/0x6a0
> [ 5.453229] genpd_power_off_work_fn+0x74/0xc0
> [ 5.457667] process_one_work+0x858/0x1208
> [ 5.461758] worker_thread+0x9ec/0xcb8
> [ 5.465503] kthread+0x2b8/0x2d0
> [ 5.468727] ret_from_fork+0x10/0x18
>
> On Mon, Jun 10, 2019 at 8:21 PM Yong Wu <[email protected]> wrote:
>> ...
>> + } else {
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + common->base = devm_ioremap_resource(dev, res);
>> + if (IS_ERR(common->base))
>> + return PTR_ERR(common->base);
>> }
>> pm_runtime_enable(dev);
>> platform_set_drvdata(pdev, common);

2019-06-17 16:31:48

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 18/21] iommu/mediatek: Fix VLD_PA_RNG register backup when suspend



On 10/06/2019 14:17, Yong Wu wrote:
> The register VLD_PA_RNG(0x118) was forgot to backup while adding 4GB
> mode support for mt2712. this patch add it.
>
> Fixes: 30e2fccf9512 ("iommu/mediatek: Enlarge the validate PA range
> for 4GB mode")
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Evan Green <[email protected]>

Reviewed-by: Matthias Brugger <[email protected]>

> ---
> drivers/iommu/mtk_iommu.c | 2 ++
> drivers/iommu/mtk_iommu.h | 1 +
> 2 files changed, 3 insertions(+)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 6053b8b..86158d8 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -719,6 +719,7 @@ static int __maybe_unused mtk_iommu_suspend(struct device *dev)
> reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0);
> reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL);
> reg->ivrp_paddr = readl_relaxed(base + REG_MMU_IVRP_PADDR);
> + reg->vld_pa_rng = readl_relaxed(base + REG_MMU_VLD_PA_RNG);
> clk_disable_unprepare(data->bclk);
> return 0;
> }
> @@ -743,6 +744,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
> writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0);
> writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
> writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
> + writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG);
> if (m4u_dom)
> writel(m4u_dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
> base + REG_MMU_PT_BASE_ADDR);
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index c0b5c65..753266b 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -32,6 +32,7 @@ struct mtk_iommu_suspend_reg {
> u32 int_control0;
> u32 int_main_control;
> u32 ivrp_paddr;
> + u32 vld_pa_rng;
> };
>
> enum mtk_iommu_plat {
>

2019-06-17 16:34:12

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 21/21] iommu/mediatek: Switch to SPDX license identifier



On 10/06/2019 14:18, Yong Wu wrote:
> Switch to SPDX license identifier for MediaTek iommu/smi and their
> header files.
>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Rob Herring <[email protected]>
> Reviewed-by: Evan Green <[email protected]>

Reviewed-by: Matthias Brugger <[email protected]>

> ---
> drivers/iommu/mtk_iommu.c | 10 +---------
> drivers/iommu/mtk_iommu.h | 10 +---------
> drivers/iommu/mtk_iommu_v1.c | 10 +---------
> drivers/memory/mtk-smi.c | 10 +---------
> include/dt-bindings/memory/mt2701-larb-port.h | 10 +---------
> include/dt-bindings/memory/mt8173-larb-port.h | 10 +---------
> include/soc/mediatek/smi.h | 10 +---------
> 7 files changed, 7 insertions(+), 63 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 34f2e40..6fe3369 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -1,15 +1,7 @@
> +// SPDX-License-Identifier: GPL-2.0
> /*
> * Copyright (c) 2015-2016 MediaTek Inc.
> * Author: Yong Wu <[email protected]>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> */
> #include <linux/memblock.h>
> #include <linux/bug.h>
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index e8114b2..b24cfd3 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -1,15 +1,7 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> /*
> * Copyright (c) 2015-2016 MediaTek Inc.
> * Author: Honghui Zhang <[email protected]>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> */
>
> #ifndef _MTK_IOMMU_H_
> diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
> index 73308ad..0b0908c 100644
> --- a/drivers/iommu/mtk_iommu_v1.c
> +++ b/drivers/iommu/mtk_iommu_v1.c
> @@ -1,3 +1,4 @@
> +// SPDX-License-Identifier: GPL-2.0
> /*
> * IOMMU API for MTK architected m4u v1 implementations
> *
> @@ -5,15 +6,6 @@
> * Author: Honghui Zhang <[email protected]>
> *
> * Based on driver/iommu/mtk_iommu.c
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> */
> #include <linux/memblock.h>
> #include <linux/bug.h>
> diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
> index 10e6493..9688341 100644
> --- a/drivers/memory/mtk-smi.c
> +++ b/drivers/memory/mtk-smi.c
> @@ -1,15 +1,7 @@
> +// SPDX-License-Identifier: GPL-2.0
> /*
> * Copyright (c) 2015-2016 MediaTek Inc.
> * Author: Yong Wu <[email protected]>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> */
> #include <linux/clk.h>
> #include <linux/component.h>
> diff --git a/include/dt-bindings/memory/mt2701-larb-port.h b/include/dt-bindings/memory/mt2701-larb-port.h
> index 6764d74..c511f0f 100644
> --- a/include/dt-bindings/memory/mt2701-larb-port.h
> +++ b/include/dt-bindings/memory/mt2701-larb-port.h
> @@ -1,15 +1,7 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> /*
> * Copyright (c) 2015 MediaTek Inc.
> * Author: Honghui Zhang <[email protected]>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> */
>
> #ifndef _MT2701_LARB_PORT_H_
> diff --git a/include/dt-bindings/memory/mt8173-larb-port.h b/include/dt-bindings/memory/mt8173-larb-port.h
> index 111b4b0..a62bfeb 100644
> --- a/include/dt-bindings/memory/mt8173-larb-port.h
> +++ b/include/dt-bindings/memory/mt8173-larb-port.h
> @@ -1,15 +1,7 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> /*
> * Copyright (c) 2015-2016 MediaTek Inc.
> * Author: Yong Wu <[email protected]>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> */
> #ifndef __DTS_IOMMU_PORT_MT8173_H
> #define __DTS_IOMMU_PORT_MT8173_H
> diff --git a/include/soc/mediatek/smi.h b/include/soc/mediatek/smi.h
> index a65324d..7a8d870 100644
> --- a/include/soc/mediatek/smi.h
> +++ b/include/soc/mediatek/smi.h
> @@ -1,15 +1,7 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> /*
> * Copyright (c) 2015-2016 MediaTek Inc.
> * Author: Yong Wu <[email protected]>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> */
> #ifndef MTK_IOMMU_SMI_H
> #define MTK_IOMMU_SMI_H
>

2019-06-18 06:45:24

by Tomasz Figa

[permalink] [raw]
Subject: Re: [PATCH v7 14/21] iommu/mediatek: Add mmu1 support

On Mon, Jun 10, 2019 at 9:21 PM Yong Wu <[email protected]> wrote:
>
> Normally the M4U HW connect EMI with smi. the diagram is like below:
> EMI
> |
> M4U
> |
> smi-common
> |
> -----------------
> | | | | ...
> larb0 larb1 larb2 larb3
>
> Actually there are 2 mmu cells in the M4U HW, like this diagram:
>
> EMI
> ---------
> | |
> mmu0 mmu1 <- M4U
> | |
> ---------
> |
> smi-common
> |
> -----------------
> | | | | ...
> larb0 larb1 larb2 larb3
>
> This patch add support for mmu1. In order to get better performance,
> we could adjust some larbs go to mmu1 while the others still go to
> mmu0. This is controlled by a SMI COMMON register SMI_BUS_SEL(0x220).
>
> mt2712, mt8173 and mt8183 M4U HW all have 2 mmu cells. the default
> value of that register is 0 which means all the larbs go to mmu0
> defaultly.
>
> This is a preparing patch for adjusting SMI_BUS_SEL for mt8183.
>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Evan Green <[email protected]>
> ---
> drivers/iommu/mtk_iommu.c | 46 +++++++++++++++++++++++++++++-----------------
> 1 file changed, 29 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 3a14301..ec4ce74 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -72,26 +72,32 @@
> #define F_INT_CLR_BIT BIT(12)
>
> #define REG_MMU_INT_MAIN_CONTROL 0x124
> -#define F_INT_TRANSLATION_FAULT BIT(0)
> -#define F_INT_MAIN_MULTI_HIT_FAULT BIT(1)
> -#define F_INT_INVALID_PA_FAULT BIT(2)
> -#define F_INT_ENTRY_REPLACEMENT_FAULT BIT(3)
> -#define F_INT_TLB_MISS_FAULT BIT(4)
> -#define F_INT_MISS_TRANSACTION_FIFO_FAULT BIT(5)
> -#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT BIT(6)
> + /* mmu0 | mmu1 */
> +#define F_INT_TRANSLATION_FAULT (BIT(0) | BIT(7))
> +#define F_INT_MAIN_MULTI_HIT_FAULT (BIT(1) | BIT(8))
> +#define F_INT_INVALID_PA_FAULT (BIT(2) | BIT(9))
> +#define F_INT_ENTRY_REPLACEMENT_FAULT (BIT(3) | BIT(10))
> +#define F_INT_TLB_MISS_FAULT (BIT(4) | BIT(11))
> +#define F_INT_MISS_TRANSACTION_FIFO_FAULT (BIT(5) | BIT(12))
> +#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT (BIT(6) | BIT(13))

If there are two IOMMUs, shouldn't we have two driver instances handle
them, instead of making the driver combine them two internally?

And, what is even more important from security point of view actually,
have two separate page tables (aka IOMMU groups) for them?

Best regards,
Tomasz

2019-06-18 12:11:42

by Yong Wu (吴勇)

[permalink] [raw]
Subject: Re: [PATCH v7 14/21] iommu/mediatek: Add mmu1 support

On Tue, 2019-06-18 at 15:19 +0900, Tomasz Figa wrote:
> On Mon, Jun 10, 2019 at 9:21 PM Yong Wu <[email protected]> wrote:
> >
> > Normally the M4U HW connect EMI with smi. the diagram is like below:
> > EMI
> > |
> > M4U
> > |
> > smi-common
> > |
> > -----------------
> > | | | | ...
> > larb0 larb1 larb2 larb3
> >
> > Actually there are 2 mmu cells in the M4U HW, like this diagram:
> >
> > EMI
> > ---------
> > | |
> > mmu0 mmu1 <- M4U
> > | |
> > ---------
> > |
> > smi-common
> > |
> > -----------------
> > | | | | ...
> > larb0 larb1 larb2 larb3
> >
> > This patch add support for mmu1. In order to get better performance,
> > we could adjust some larbs go to mmu1 while the others still go to
> > mmu0. This is controlled by a SMI COMMON register SMI_BUS_SEL(0x220).
> >
> > mt2712, mt8173 and mt8183 M4U HW all have 2 mmu cells. the default
> > value of that register is 0 which means all the larbs go to mmu0
> > defaultly.
> >
> > This is a preparing patch for adjusting SMI_BUS_SEL for mt8183.
> >
> > Signed-off-by: Yong Wu <[email protected]>
> > Reviewed-by: Evan Green <[email protected]>
> > ---
> > drivers/iommu/mtk_iommu.c | 46 +++++++++++++++++++++++++++++-----------------
> > 1 file changed, 29 insertions(+), 17 deletions(-)
> >
> > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> > index 3a14301..ec4ce74 100644
> > --- a/drivers/iommu/mtk_iommu.c
> > +++ b/drivers/iommu/mtk_iommu.c
> > @@ -72,26 +72,32 @@
> > #define F_INT_CLR_BIT BIT(12)
> >
> > #define REG_MMU_INT_MAIN_CONTROL 0x124
> > -#define F_INT_TRANSLATION_FAULT BIT(0)
> > -#define F_INT_MAIN_MULTI_HIT_FAULT BIT(1)
> > -#define F_INT_INVALID_PA_FAULT BIT(2)
> > -#define F_INT_ENTRY_REPLACEMENT_FAULT BIT(3)
> > -#define F_INT_TLB_MISS_FAULT BIT(4)
> > -#define F_INT_MISS_TRANSACTION_FIFO_FAULT BIT(5)
> > -#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT BIT(6)
> > + /* mmu0 | mmu1 */
> > +#define F_INT_TRANSLATION_FAULT (BIT(0) | BIT(7))
> > +#define F_INT_MAIN_MULTI_HIT_FAULT (BIT(1) | BIT(8))
> > +#define F_INT_INVALID_PA_FAULT (BIT(2) | BIT(9))
> > +#define F_INT_ENTRY_REPLACEMENT_FAULT (BIT(3) | BIT(10))
> > +#define F_INT_TLB_MISS_FAULT (BIT(4) | BIT(11))
> > +#define F_INT_MISS_TRANSACTION_FIFO_FAULT (BIT(5) | BIT(12))
> > +#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT (BIT(6) | BIT(13))
>
> If there are two IOMMUs, shouldn't we have two driver instances handle
> them, instead of making the driver combine them two internally?

Actually it means only one IOMMU(M4U) HW here. Each a M4U HW has two
small iommu cells which have independent MTLB. As the diagram above, M4U
contain mmu0 and mmu1.

MT8173 and MT8183 have only one M4U HW while MT2712 have 2 M4U HWs(two
driver instances).

>
> And, what is even more important from security point of view actually,
> have two separate page tables (aka IOMMU groups) for them?

Each a IOMMU(M4U) have its own pagetable, thus, mt8183 have only one
pagetable while mt2712 have two.

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


2019-06-18 12:12:38

by Yong Wu (吴勇)

[permalink] [raw]
Subject: Re: [PATCH v7 16/21] memory: mtk-smi: Add bus_sel for mt8183

On Mon, 2019-06-17 at 18:23 +0200, Matthias Brugger wrote:
>
> On 10/06/2019 14:17, Yong Wu wrote:
> > There are 2 mmu cells in a M4U HW. we could adjust some larbs entering
> > mmu0 or mmu1 to balance the bandwidth via the smi-common register
> > SMI_BUS_SEL(0x220)(Each larb occupy 2 bits).
> >
> > In mt8183, For better performance, we switch larb1/2/5/7 to enter
> > mmu1 while the others still keep enter mmu0.
> >
> > In mt8173 and mt2712, we don't get the performance issue,
> > Keep its default value(0x0), that means all the larbs enter mmu0.
> >
> > Note: smi gen1(mt2701/mt7623) don't have this bus_sel.
> >
> > And, the base of smi-common is completely different with smi_ao_base
> > of gen1, thus I add new variable for that.
> >
> > CC: Matthias Brugger <[email protected]>
> > Signed-off-by: Yong Wu <[email protected]>
> > Reviewed-by: Evan Green <[email protected]>
> > ---
> > drivers/memory/mtk-smi.c | 22 ++++++++++++++++++++--
> > 1 file changed, 20 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
> > index 9790801..08cf40d 100644
> > --- a/drivers/memory/mtk-smi.c
> > +++ b/drivers/memory/mtk-smi.c
> > @@ -49,6 +49,12 @@
> > #define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4))
> > #define F_MMU_EN BIT(0)
> >
> > +/* SMI COMMON */
> > +#define SMI_BUS_SEL 0x220
> > +#define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1)
> > +/* All are MMU0 defaultly. Only specialize mmu1 here. */
> > +#define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid))
> > +
> > enum mtk_smi_gen {
> > MTK_SMI_GEN1,
> > MTK_SMI_GEN2
> > @@ -57,6 +63,7 @@ enum mtk_smi_gen {
> > struct mtk_smi_common_plat {
> > enum mtk_smi_gen gen;
> > bool has_gals;
> > + u32 bus_sel; /* Balance some larbs to enter mmu0 or mmu1 */
> > };
> >
> > struct mtk_smi_larb_gen {
> > @@ -72,8 +79,8 @@ struct mtk_smi {
> > struct clk *clk_apb, *clk_smi;
> > struct clk *clk_gals0, *clk_gals1;
> > struct clk *clk_async; /*only needed by mt2701*/
> > - void __iomem *smi_ao_base;
> > -
> > + void __iomem *smi_ao_base; /* only for gen1 */
> > + void __iomem *base; /* only for gen2 */
>
> union {} maybe?

Yes. Thanks.

I will add it.

>
> > const struct mtk_smi_common_plat *plat;
> > };
> >
> > @@ -410,6 +417,8 @@ static int __maybe_unused mtk_smi_larb_suspend(struct device *dev)
> > static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
> > .gen = MTK_SMI_GEN2,
> > .has_gals = true,
> > + .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(5) |
> > + F_MMU1_LARB(7),
> > };
> >
> > static const struct of_device_id mtk_smi_common_of_ids[] = {
> > @@ -482,6 +491,11 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
> > ret = clk_prepare_enable(common->clk_async);
> > if (ret)
> > return ret;
> > + } else {
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + common->base = devm_ioremap_resource(dev, res);
> > + if (IS_ERR(common->base))
> > + return PTR_ERR(common->base);
>
> We must be backwards compatible with DT which does not have the base defined.

The smi-common node in the previous mt2712 and mt8173 also have the
"reg" property even though they didn't use this base, Thus, It looks ok
for all the cases.

>
> Regards,
> Matthias
>
> > }
> > pm_runtime_enable(dev);
> > platform_set_drvdata(pdev, common);
> > @@ -497,6 +511,7 @@ static int mtk_smi_common_remove(struct platform_device *pdev)
> > static int __maybe_unused mtk_smi_common_resume(struct device *dev)
> > {
> > struct mtk_smi *common = dev_get_drvdata(dev);
> > + u32 bus_sel = common->plat->bus_sel;
> > int ret;
> >
> > ret = mtk_smi_clk_enable(common);
> > @@ -504,6 +519,9 @@ static int __maybe_unused mtk_smi_common_resume(struct device *dev)
> > dev_err(common->dev, "Failed to enable clock(%d).\n", ret);
> > return ret;
> > }
> > +
> > + if (common->plat->gen == MTK_SMI_GEN2 && bus_sel)
> > + writel(bus_sel, common->base + SMI_BUS_SEL);
> > return 0;
> > }
> >
> >


2019-06-18 13:45:56

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 17/21] memory: mtk-smi: Get rid of need_larbid



On 10/06/2019 14:17, Yong Wu wrote:
> The "mediatek,larb-id" has already been parsed in MTK IOMMU driver.
> It's no need to parse it again in SMI driver. Only clean some codes.
> This patch is fit for all the current mt2701, mt2712, mt7623, mt8173
> and mt8183.
>
> After this patch, the "mediatek,larb-id" only be needed for mt2712
> which have 2 M4Us. In the other SoCs, we can get the larb-id from M4U
> in which the larbs in the "mediatek,larbs" always are ordered.
>
> Correspondingly, the larb_nr in the "struct mtk_smi_iommu" could also
> be deleted.
>

I think we can get rid of struct mtk_smi_iommu and just add the
struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX] directly to mtk_iommu_data,
passing just that array to the components bind function.

Never the less this patch looks fine:
Reviewed-by: Matthias Brugger <[email protected]>

> CC: Matthias Brugger <[email protected]>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Evan Green <[email protected]>
> ---
> drivers/iommu/mtk_iommu.c | 1 -
> drivers/iommu/mtk_iommu_v1.c | 2 --
> drivers/memory/mtk-smi.c | 26 ++------------------------
> include/soc/mediatek/smi.h | 1 -
> 4 files changed, 2 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index ec4ce74..6053b8b 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -634,7 +634,6 @@ static int mtk_iommu_probe(struct platform_device *pdev)
> "mediatek,larbs", NULL);
> if (larb_nr < 0)
> return larb_nr;
> - data->smi_imu.larb_nr = larb_nr;
>
> for (i = 0; i < larb_nr; i++) {
> struct device_node *larbnode;
> diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
> index 52b01e3..73308ad 100644
> --- a/drivers/iommu/mtk_iommu_v1.c
> +++ b/drivers/iommu/mtk_iommu_v1.c
> @@ -624,8 +624,6 @@ static int mtk_iommu_probe(struct platform_device *pdev)
> larb_nr++;
> }
>
> - data->smi_imu.larb_nr = larb_nr;
> -
> platform_set_drvdata(pdev, data);
>
> ret = mtk_iommu_hw_init(data);
> diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
> index 08cf40d..10e6493 100644
> --- a/drivers/memory/mtk-smi.c
> +++ b/drivers/memory/mtk-smi.c
> @@ -67,7 +67,6 @@ struct mtk_smi_common_plat {
> };
>
> struct mtk_smi_larb_gen {
> - bool need_larbid;
> int port_in_larb[MTK_LARB_NR_MAX + 1];
> void (*config_port)(struct device *);
> unsigned int larb_direct_to_common_mask;
> @@ -153,18 +152,9 @@ void mtk_smi_larb_put(struct device *larbdev)
> struct mtk_smi_iommu *smi_iommu = data;
> unsigned int i;
>
> - if (larb->larb_gen->need_larbid) {
> - larb->mmu = &smi_iommu->larb_imu[larb->larbid].mmu;
> - return 0;
> - }
> -
> - /*
> - * If there is no larbid property, Loop to find the corresponding
> - * iommu information.
> - */
> - for (i = 0; i < smi_iommu->larb_nr; i++) {
> + for (i = 0; i < MTK_LARB_NR_MAX; i++) {
> if (dev == smi_iommu->larb_imu[i].dev) {
> - /* The 'mmu' may be updated in iommu-attach/detach. */
> + larb->larbid = i;
> larb->mmu = &smi_iommu->larb_imu[i].mmu;
> return 0;
> }
> @@ -243,7 +233,6 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev)
> };
>
> static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
> - .need_larbid = true,
> .port_in_larb = {
> LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
> LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
> @@ -252,7 +241,6 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev)
> };
>
> static const struct mtk_smi_larb_gen mtk_smi_larb_mt2712 = {
> - .need_larbid = true,
> .config_port = mtk_smi_larb_config_port_gen2_general,
> .larb_direct_to_common_mask = BIT(8) | BIT(9), /* bdpsys */
> };
> @@ -291,7 +279,6 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
> struct device *dev = &pdev->dev;
> struct device_node *smi_node;
> struct platform_device *smi_pdev;
> - int err;
>
> larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL);
> if (!larb)
> @@ -321,15 +308,6 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
> }
> larb->smi.dev = dev;
>
> - if (larb->larb_gen->need_larbid) {
> - err = of_property_read_u32(dev->of_node, "mediatek,larb-id",
> - &larb->larbid);
> - if (err) {
> - dev_err(dev, "missing larbid property\n");
> - return err;
> - }
> - }
> -
> smi_node = of_parse_phandle(dev->of_node, "mediatek,smi", 0);
> if (!smi_node)
> return -EINVAL;
> diff --git a/include/soc/mediatek/smi.h b/include/soc/mediatek/smi.h
> index 5201e90..a65324d 100644
> --- a/include/soc/mediatek/smi.h
> +++ b/include/soc/mediatek/smi.h
> @@ -29,7 +29,6 @@ struct mtk_smi_larb_iommu {
> };
>
> struct mtk_smi_iommu {
> - unsigned int larb_nr;
> struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX];
> };
>
>

2019-06-18 14:08:21

by Tomasz Figa

[permalink] [raw]
Subject: Re: [PATCH v7 14/21] iommu/mediatek: Add mmu1 support

On Tue, Jun 18, 2019 at 9:09 PM Yong Wu <[email protected]> wrote:
>
> On Tue, 2019-06-18 at 15:19 +0900, Tomasz Figa wrote:
> > On Mon, Jun 10, 2019 at 9:21 PM Yong Wu <[email protected]> wrote:
> > >
> > > Normally the M4U HW connect EMI with smi. the diagram is like below:
> > > EMI
> > > |
> > > M4U
> > > |
> > > smi-common
> > > |
> > > -----------------
> > > | | | | ...
> > > larb0 larb1 larb2 larb3
> > >
> > > Actually there are 2 mmu cells in the M4U HW, like this diagram:
> > >
> > > EMI
> > > ---------
> > > | |
> > > mmu0 mmu1 <- M4U
> > > | |
> > > ---------
> > > |
> > > smi-common
> > > |
> > > -----------------
> > > | | | | ...
> > > larb0 larb1 larb2 larb3
> > >
> > > This patch add support for mmu1. In order to get better performance,
> > > we could adjust some larbs go to mmu1 while the others still go to
> > > mmu0. This is controlled by a SMI COMMON register SMI_BUS_SEL(0x220).
> > >
> > > mt2712, mt8173 and mt8183 M4U HW all have 2 mmu cells. the default
> > > value of that register is 0 which means all the larbs go to mmu0
> > > defaultly.
> > >
> > > This is a preparing patch for adjusting SMI_BUS_SEL for mt8183.
> > >
> > > Signed-off-by: Yong Wu <[email protected]>
> > > Reviewed-by: Evan Green <[email protected]>
> > > ---
> > > drivers/iommu/mtk_iommu.c | 46 +++++++++++++++++++++++++++++-----------------
> > > 1 file changed, 29 insertions(+), 17 deletions(-)
> > >
> > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> > > index 3a14301..ec4ce74 100644
> > > --- a/drivers/iommu/mtk_iommu.c
> > > +++ b/drivers/iommu/mtk_iommu.c
> > > @@ -72,26 +72,32 @@
> > > #define F_INT_CLR_BIT BIT(12)
> > >
> > > #define REG_MMU_INT_MAIN_CONTROL 0x124
> > > -#define F_INT_TRANSLATION_FAULT BIT(0)
> > > -#define F_INT_MAIN_MULTI_HIT_FAULT BIT(1)
> > > -#define F_INT_INVALID_PA_FAULT BIT(2)
> > > -#define F_INT_ENTRY_REPLACEMENT_FAULT BIT(3)
> > > -#define F_INT_TLB_MISS_FAULT BIT(4)
> > > -#define F_INT_MISS_TRANSACTION_FIFO_FAULT BIT(5)
> > > -#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT BIT(6)
> > > + /* mmu0 | mmu1 */
> > > +#define F_INT_TRANSLATION_FAULT (BIT(0) | BIT(7))
> > > +#define F_INT_MAIN_MULTI_HIT_FAULT (BIT(1) | BIT(8))
> > > +#define F_INT_INVALID_PA_FAULT (BIT(2) | BIT(9))
> > > +#define F_INT_ENTRY_REPLACEMENT_FAULT (BIT(3) | BIT(10))
> > > +#define F_INT_TLB_MISS_FAULT (BIT(4) | BIT(11))
> > > +#define F_INT_MISS_TRANSACTION_FIFO_FAULT (BIT(5) | BIT(12))
> > > +#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT (BIT(6) | BIT(13))
> >
> > If there are two IOMMUs, shouldn't we have two driver instances handle
> > them, instead of making the driver combine them two internally?
>
> Actually it means only one IOMMU(M4U) HW here. Each a M4U HW has two
> small iommu cells which have independent MTLB. As the diagram above, M4U
> contain mmu0 and mmu1.
>
> MT8173 and MT8183 have only one M4U HW while MT2712 have 2 M4U HWs(two
> driver instances).
>
> >
> > And, what is even more important from security point of view actually,
> > have two separate page tables (aka IOMMU groups) for them?
>
> Each a IOMMU(M4U) have its own pagetable, thus, mt8183 have only one
> pagetable while mt2712 have two.

I see, thanks for clarifying.

Best regards,
Tomasz

2019-06-18 16:07:34

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 19/21] iommu/mediatek: Rename enable_4GB to dram_is_4gb



On 10/06/2019 14:17, Yong Wu wrote:
> This patch only rename the variable name from enable_4GB to
> dram_is_4gb for readable.

From my understanding this is true when available RAM > 4GB so I think the name
should be something like dram_bigger_4gb otherwise it may create confusion again.

Also from my point of view this patch should be done before
"[PATCH 06/21] iommu/io-pgtable-arm-v7s: Extend MediaTek 4GB Mode"

Regards,
Matthias

>
> Signed-off-by: Yong Wu <[email protected]>
> Reviewed-by: Evan Green <[email protected]>
> ---
> drivers/iommu/mtk_iommu.c | 10 +++++-----
> drivers/iommu/mtk_iommu.h | 2 +-
> 2 files changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 86158d8..67cab2d 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -382,7 +382,7 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
> int ret;
>
> /* The "4GB mode" M4U physically can not use the lower remap of Dram. */
> - if (data->plat_data->has_4gb_mode && data->enable_4GB)
> + if (data->plat_data->has_4gb_mode && data->dram_is_4gb)
> paddr |= BIT_ULL(32);
>
> spin_lock_irqsave(&dom->pgtlock, flags);
> @@ -554,13 +554,13 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
> writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
>
> if (data->plat_data->m4u_plat == M4U_MT8173)
> - regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
> + regval = (data->protect_base >> 1) | (data->dram_is_4gb << 31);
> else
> regval = lower_32_bits(data->protect_base) |
> upper_32_bits(data->protect_base);
> writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
>
> - if (data->enable_4GB && data->plat_data->has_vld_pa_rng) {
> + if (data->dram_is_4gb && data->plat_data->has_vld_pa_rng) {
> /*
> * If 4GB mode is enabled, the validate PA range is from
> * 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
> @@ -611,8 +611,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
> return -ENOMEM;
> data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
>
> - /* Whether the current dram is over 4GB */
> - data->enable_4GB = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
> + /* Whether the current dram is 4GB. */
> + data->dram_is_4gb = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
>
> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> data->base = devm_ioremap_resource(dev, res);
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index 753266b..e8114b2 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -65,7 +65,7 @@ struct mtk_iommu_data {
> struct mtk_iommu_domain *m4u_dom;
> struct iommu_group *m4u_group;
> struct mtk_smi_iommu smi_imu; /* SMI larb iommu info */
> - bool enable_4GB;
> + bool dram_is_4gb;
> bool tlb_flush_active;
>
> struct iommu_device iommu;
>

2019-06-18 16:36:31

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 20/21] iommu/mediatek: Fix iova_to_phys PA start for 4GB mode



On 10/06/2019 14:17, Yong Wu wrote:
> In the 4GB mode, the physical address is remapped,
>
> Here is the detailed remap relationship.
> CPU PA -> HW PA
> 0x4000_0000 0x1_4000_0000 (Add bit32)
> 0x8000_0000 0x1_8000_0000 ...
> 0xc000_0000 0x1_c000_0000 ...
> 0x1_0000_0000 0x1_0000_0000 (No change)
>
> Thus, we always add bit32 for PA when entering mtk_iommu_map.
> But in the iova_to_phys, the CPU don't need this bit32 if the
> PA is from 0x1_4000_0000 to 0x1_ffff_ffff.
> This patch discards the bit32 in this iova_to_phys in the 4GB mode.
>
> Fixes: 30e2fccf9512 ("iommu/mediatek: Enlarge the validate PA range
> for 4GB mode")
> Signed-off-by: Yong Wu <[email protected]>
> ---
> drivers/iommu/mtk_iommu.c | 18 ++++++++++++++++++
> 1 file changed, 18 insertions(+)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 67cab2d..34f2e40 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -119,6 +119,19 @@ struct mtk_iommu_domain {
>
> static const struct iommu_ops mtk_iommu_ops;
>
> +/*
> + * In M4U 4GB mode, the physical address is remapped as below:
> + * CPU PA -> M4U HW PA
> + * 0x4000_0000 0x1_4000_0000 (Add bit32)
> + * 0x8000_0000 0x1_8000_0000 ...
> + * 0xc000_0000 0x1_c000_0000 ...
> + * 0x1_0000_0000 0x1_0000_0000 (No change)
> + *
> + * Thus, We always add BIT32 in the iommu_map and disable BIT32 if PA is >=
> + * 0x1_4000_0000 in the iova_to_phys.
> + */
> +#define MTK_IOMMU_4GB_MODE_PA_140000000 0x140000000UL
> +
> static LIST_HEAD(m4ulist); /* List all the M4U HWs */
>
> #define for_each_m4u(data) list_for_each_entry(data, &m4ulist, list)
> @@ -415,6 +428,7 @@ 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();
> unsigned long flags;
> phys_addr_t pa;
>
> @@ -422,6 +436,10 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
> pa = dom->iop->iova_to_phys(dom->iop, iova);
> spin_unlock_irqrestore(&dom->pgtlock, flags);
>
> + if (data->plat_data->has_4gb_mode && data->dram_is_4gb &&
> + pa >= MTK_IOMMU_4GB_MODE_PA_140000000)
> + pa &= ~BIT_ULL(32);
> +

Hm, I wonder if we could fix this as first patch in the series, especially before:
"[PATCH 06/21] iommu/io-pgtable-arm-v7s: Extend MediaTek 4GB Mode"

This would make it easier for the stable maintainer to cherry-pick the fix.
Without 100% understanding the code, it seems suspicious to me, that you first
move the setting of the bit32 and bit33 into v7s and later explicitly clean the
bits here.

So my take on this is, that patch 6/21 introduced the regression you are trying
to fix here. As said that is speculation as I don't understand the code in its
whole.

Any clarification would be useful.

Regards,
Matthias

> return pa;
> }
>
>

2019-06-18 21:08:27

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 16/21] memory: mtk-smi: Add bus_sel for mt8183



On 18/06/2019 14:10, Yong Wu wrote:
> On Mon, 2019-06-17 at 18:23 +0200, Matthias Brugger wrote:
>>
>> On 10/06/2019 14:17, Yong Wu wrote:
>>> There are 2 mmu cells in a M4U HW. we could adjust some larbs entering
>>> mmu0 or mmu1 to balance the bandwidth via the smi-common register
>>> SMI_BUS_SEL(0x220)(Each larb occupy 2 bits).
>>>
>>> In mt8183, For better performance, we switch larb1/2/5/7 to enter
>>> mmu1 while the others still keep enter mmu0.
>>>
>>> In mt8173 and mt2712, we don't get the performance issue,
>>> Keep its default value(0x0), that means all the larbs enter mmu0.
>>>
>>> Note: smi gen1(mt2701/mt7623) don't have this bus_sel.
>>>
>>> And, the base of smi-common is completely different with smi_ao_base
>>> of gen1, thus I add new variable for that.
>>>
>>> CC: Matthias Brugger <[email protected]>
>>> Signed-off-by: Yong Wu <[email protected]>
>>> Reviewed-by: Evan Green <[email protected]>
>>> ---
>>> drivers/memory/mtk-smi.c | 22 ++++++++++++++++++++--
>>> 1 file changed, 20 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
>>> index 9790801..08cf40d 100644
>>> --- a/drivers/memory/mtk-smi.c
>>> +++ b/drivers/memory/mtk-smi.c
>>> @@ -49,6 +49,12 @@
>>> #define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4))
>>> #define F_MMU_EN BIT(0)
>>>
>>> +/* SMI COMMON */
>>> +#define SMI_BUS_SEL 0x220
>>> +#define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1)
>>> +/* All are MMU0 defaultly. Only specialize mmu1 here. */
>>> +#define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid))
>>> +
>>> enum mtk_smi_gen {
>>> MTK_SMI_GEN1,
>>> MTK_SMI_GEN2
>>> @@ -57,6 +63,7 @@ enum mtk_smi_gen {
>>> struct mtk_smi_common_plat {
>>> enum mtk_smi_gen gen;
>>> bool has_gals;
>>> + u32 bus_sel; /* Balance some larbs to enter mmu0 or mmu1 */
>>> };
>>>
>>> struct mtk_smi_larb_gen {
>>> @@ -72,8 +79,8 @@ struct mtk_smi {
>>> struct clk *clk_apb, *clk_smi;
>>> struct clk *clk_gals0, *clk_gals1;
>>> struct clk *clk_async; /*only needed by mt2701*/
>>> - void __iomem *smi_ao_base;
>>> -
>>> + void __iomem *smi_ao_base; /* only for gen1 */
>>> + void __iomem *base; /* only for gen2 */
>>
>> union {} maybe?
>
> Yes. Thanks.
>
> I will add it.
>
>>
>>> const struct mtk_smi_common_plat *plat;
>>> };
>>>
>>> @@ -410,6 +417,8 @@ static int __maybe_unused mtk_smi_larb_suspend(struct device *dev)
>>> static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
>>> .gen = MTK_SMI_GEN2,
>>> .has_gals = true,
>>> + .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(5) |
>>> + F_MMU1_LARB(7),
>>> };
>>>
>>> static const struct of_device_id mtk_smi_common_of_ids[] = {
>>> @@ -482,6 +491,11 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
>>> ret = clk_prepare_enable(common->clk_async);
>>> if (ret)
>>> return ret;
>>> + } else {
>>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> + common->base = devm_ioremap_resource(dev, res);
>>> + if (IS_ERR(common->base))
>>> + return PTR_ERR(common->base);
>>
>> We must be backwards compatible with DT which does not have the base defined.
>
> The smi-common node in the previous mt2712 and mt8173 also have the
> "reg" property even though they didn't use this base, Thus, It looks ok
> for all the cases.
>

Correct, it is defined as a required property in the binding description so we
are good.
Sorry for the noise.

With the union added you can add:
Reviewed-by: Matthias Brugger <[email protected]>

>>
>> Regards,
>> Matthias
>>
>>> }
>>> pm_runtime_enable(dev);
>>> platform_set_drvdata(pdev, common);
>>> @@ -497,6 +511,7 @@ static int mtk_smi_common_remove(struct platform_device *pdev)
>>> static int __maybe_unused mtk_smi_common_resume(struct device *dev)
>>> {
>>> struct mtk_smi *common = dev_get_drvdata(dev);
>>> + u32 bus_sel = common->plat->bus_sel;
>>> int ret;
>>>
>>> ret = mtk_smi_clk_enable(common);
>>> @@ -504,6 +519,9 @@ static int __maybe_unused mtk_smi_common_resume(struct device *dev)
>>> dev_err(common->dev, "Failed to enable clock(%d).\n", ret);
>>> return ret;
>>> }
>>> +
>>> + if (common->plat->gen == MTK_SMI_GEN2 && bus_sel)
>>> + writel(bus_sel, common->base + SMI_BUS_SEL);
>>> return 0;
>>> }
>>>
>>>
>
>

2019-06-20 09:37:47

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 16/21] memory: mtk-smi: Add bus_sel for mt8183



On 13/06/2019 10:14, Pi-Hsun Shih wrote:
> Hi,
> When I tested this patch series (Based on linux 5.2.0-rc2, and with
> various other patch series about MT8183) with lockdep enabled, and I'm
> seeing the following lockdep warning on boot.
>
> By bisecting the commits, the first commit that introduce this warning
> is this patch. The warning also doesn't appear if
> https://lore.kernel.org/patchwork/patch/1086582/ and
> https://lore.kernel.org/patchwork/patch/1086583/ are not applied.
>
> Do anyone have idea on why this is happening, or any suggestion on
> which part I should be digging into to figure this out? Thanks.
>
> [ 4.664194] ======================================================
> [ 4.670368] WARNING: possible circular locking dependency detected
> [ 4.676545] 5.2.0-rc2-next-20190528-44527-g6c94b6475c04 #20 Tainted: G S
> [ 4.684539] ------------------------------------------------------
> [ 4.690714] kworker/4:1/51 is trying to acquire lock:
> [ 4.695760] (____ptrval____) (regulator_list_mutex){+.+.},
> at:regulator_lock_dependent+0xdc/0x6c4
> [ 4.704732]
> [ 4.704732] but task is already holding lock:
> [ 4.710556] (____ptrval____) (&genpd->mlock/1){+.+.},
> at:genpd_lock_nested_mtx+0x24/0x30
> [ 4.718740]
> [ 4.718740] which lock already depends on the new lock.
> [ 4.718740]
> [ 4.726908]
> [ 4.726908] the existing dependency chain (in reverse order) is:
> [ 4.734382]
> [ 4.734382] -> #4 (&genpd->mlock/1){+.+.}:
> [ 4.739963] __mutex_lock_common+0x1a0/0x1fe8
> [ 4.744836] mutex_lock_nested+0x40/0x50
> [ 4.749275] genpd_lock_nested_mtx+0x24/0x30
> [ 4.754063] genpd_add_subdomain+0x150/0x524
> [ 4.758850] pm_genpd_add_subdomain+0x3c/0x5c
> [ 4.763723] scpsys_probe+0x520/0xe78
> [ 4.767902] platform_drv_probe+0xf4/0x134
> [ 4.772517] really_probe+0x214/0x4dc
> [ 4.776696] driver_probe_device+0xcc/0x1d4
> [ 4.781396] __device_attach_driver+0x10c/0x180
> [ 4.786442] bus_for_each_drv+0x124/0x184
> [ 4.790968] __device_attach+0x1c0/0x2d8
> [ 4.795407] device_initial_probe+0x20/0x2c
> [ 4.800106] bus_probe_device+0x80/0x16c
> [ 4.804546] deferred_probe_work_func+0x120/0x168
> [ 4.809767] process_one_work+0x858/0x1208
> [ 4.814379] worker_thread+0x9ec/0xcb8
> [ 4.818644] kthread+0x2b8/0x2d0
> [ 4.822391] ret_from_fork+0x10/0x18
> [ 4.826480]
> [ 4.826480] -> #3 (&genpd->mlock){+.+.}:
> [ 4.831880] __mutex_lock_common+0x1a0/0x1fe8
> [ 4.836752] mutex_lock_nested+0x40/0x50
> [ 4.841190] genpd_lock_mtx+0x20/0x2c
> [ 4.845369] genpd_runtime_resume+0x140/0x434
> [ 4.850241] __rpm_callback+0xb0/0x1e4
> [ 4.854506] rpm_callback+0x54/0x1a8
> [ 4.858597] rpm_resume+0xc6c/0x10c4
> [ 4.862689] __pm_runtime_resume+0xb4/0x124
> [ 4.867387] device_link_add+0x598/0x8d0

For this looks as if you have also patch
[PATCH v2 04/12] memory: mtk-smi: Add device-link between smi-larb and smi-common
from series
[PATCH v2 00/12] Clean up "mediatek,larb" after adding device_link
applied.

Regards,
Matthias

> [ 4.871829] mtk_smi_larb_probe+0x2b0/0x340
> [ 4.876528] platform_drv_probe+0xf4/0x134
> [ 4.881141] really_probe+0x214/0x4dc
> [ 4.885320] driver_probe_device+0xcc/0x1d4
> [ 4.890020] __device_attach_driver+0x10c/0x180
> [ 4.895066] bus_for_each_drv+0x124/0x184
> [ 4.899591] __device_attach+0x1c0/0x2d8
> [ 4.904031] device_initial_probe+0x20/0x2c
> [ 4.908730] bus_probe_device+0x80/0x16c
> [ 4.913169] deferred_probe_work_func+0x120/0x168
> [ 4.918387] process_one_work+0x858/0x1208
> [ 4.923000] worker_thread+0x9ec/0xcb8
> [ 4.927264] kthread+0x2b8/0x2d0
> [ 4.931009] ret_from_fork+0x10/0x18
> [ 4.935098]
> [ 4.935098] -> #2 (dpm_list_mtx){+.+.}:
> [ 4.940412] __mutex_lock_common+0x1a0/0x1fe8
> [ 4.945284] mutex_lock_nested+0x40/0x50
> [ 4.949722] device_pm_lock+0x1c/0x24
> [ 4.953900] device_link_add+0x98/0x8d0
> [ 4.958252] _regulator_get+0x3f0/0x504
> [ 4.962606] _devm_regulator_get+0x58/0xb8
> [ 4.967218] devm_regulator_get+0x28/0x34
> [ 4.971746] pwm_backlight_probe+0x61c/0x1b90
> [ 4.976617] platform_drv_probe+0xf4/0x134
> [ 4.981230] really_probe+0x214/0x4dc
> [ 4.985409] driver_probe_device+0xcc/0x1d4
> [ 4.990108] device_driver_attach+0xe4/0x104
> [ 4.994894] __driver_attach+0x134/0x14c
> [ 4.999333] bus_for_each_dev+0x120/0x180
> [ 5.003859] driver_attach+0x48/0x54
> [ 5.007950] bus_add_driver+0x2ac/0x44c
> [ 5.012303] driver_register+0x160/0x288
> [ 5.016742] __platform_driver_register+0xcc/0xdc
> [ 5.021964] pwm_backlight_driver_init+0x1c/0x24
> [ 5.027097] do_one_initcall+0x38c/0x994
> [ 5.031536] do_initcall_level+0x3a4/0x4b8
> [ 5.036148] do_basic_setup+0x84/0xa0
> [ 5.036153] kernel_init_freeable+0x23c/0x324
> [ 5.036158] kernel_init+0x14/0x110
> [ 5.036164] ret_from_fork+0x10/0x18
> [ 5.036166]
> [ 5.036166] -> #1 (device_links_lock){+.+.}:
> [ 5.065905] __mutex_lock_common+0x1a0/0x1fe8
> [ 5.070777] mutex_lock_nested+0x40/0x50
> [ 5.075215] device_link_remove+0x40/0xe0
> [ 5.079740] _regulator_put+0x104/0x2d8
> [ 5.084093] regulator_put+0x30/0x44
> [ 5.088184] devm_regulator_release+0x38/0x44
> [ 5.093056] release_nodes+0x604/0x670
> [ 5.097320] devres_release_all+0x70/0x8c
> [ 5.101846] really_probe+0x270/0x4dc
> [ 5.106024] driver_probe_device+0xcc/0x1d4
> [ 5.110724] device_driver_attach+0xe4/0x104
> [ 5.115510] __driver_attach+0x134/0x14c
> [ 5.119949] bus_for_each_dev+0x120/0x180
> [ 5.124474] driver_attach+0x48/0x54
> [ 5.128566] bus_add_driver+0x2ac/0x44c
> [ 5.132919] driver_register+0x160/0x288
> [ 5.137357] __platform_driver_register+0xcc/0xdc
> [ 5.142576] pwm_backlight_driver_init+0x1c/0x24
> [ 5.147708] do_one_initcall+0x38c/0x994
> [ 5.152146] do_initcall_level+0x3a4/0x4b8
> [ 5.156758] do_basic_setup+0x84/0xa0
> [ 5.160936] kernel_init_freeable+0x23c/0x324
> [ 5.165807] kernel_init+0x14/0x110
> [ 5.169813] ret_from_fork+0x10/0x18
> [ 5.173901]
> [ 5.173901] -> #0 (regulator_list_mutex){+.+.}:
> [ 5.179910] lock_acquire+0x350/0x4d4
> [ 5.184088] __mutex_lock_common+0x1a0/0x1fe8
> [ 5.184095] mutex_lock_nested+0x40/0x50
> [ 5.197475] regulator_lock_dependent+0xdc/0x6c4
> [ 5.197482] regulator_disable+0xa0/0x138
> [ 5.197487] scpsys_power_off+0x38c/0x4bc
> [ 5.197495] genpd_power_off+0x3d8/0x6a0
> [ 5.209399] genpd_power_off+0x530/0x6a0
> [ 5.209406] genpd_power_off_work_fn+0x74/0xc0
> [ 5.209411] process_one_work+0x858/0x1208
> [ 5.209419] worker_thread+0x9ec/0xcb8
> [ 5.219067] kthread+0x2b8/0x2d0
> [ 5.219073] ret_from_fork+0x10/0x18
> [ 5.219077]
> [ 5.219077] other info that might help us debug this:
> [ 5.219077]
> [ 5.219080] Chain exists of:
> [ 5.219080] regulator_list_mutex --> &genpd->mlock --> &genpd->mlock/1
> [ 5.219080]
> [ 5.228039] Possible unsafe locking scenario:
> [ 5.228039]
> [ 5.228042] CPU0 CPU1
> [ 5.228046] ---- ----
> [ 5.228048] lock(&genpd->mlock/1);
> [ 5.228058] lock(&genpd->mlock);
> [ 5.311647] lock(&genpd->mlock/1);
> [ 5.317736] lock(regulator_list_mutex);
> [ 5.321742]
> [ 5.321742] *** DEADLOCK ***
> [ 5.321742]
> [ 5.327655] 4 locks held by kworker/4:1/51:
> [ 5.331831] #0: (____ptrval____) ((wq_completion)pm){+.+.},
> at:process_one_work+0x57c/0x1208
> [ 5.340444] #1: (____ptrval____)
> ((work_completion)(&genpd->power_off_work)){+.+.},
> at:process_one_work+0x5b8/0x1208
> [ 5.351139] #2: (____ptrval____) (&genpd->mlock){+.+.},
> at:genpd_lock_mtx+0x20/0x2c
> [ 5.358970] #3: (____ptrval____) (&genpd->mlock/1){+.+.},
> at:genpd_lock_nested_mtx+0x24/0x30
> [ 5.367584]
> [ 5.367584] stack backtrace:
> [ 5.371939] CPU: 4 PID: 51 Comm: kworker/4:1 Tainted: G S
> 5.2.0-rc2-next-20190528-44527-g6c94b6475c04 #20
> [ 5.382809] Workqueue: pm genpd_power_off_work_fn
> [ 5.382816] Call trace:
> [ 5.382822] dump_backtrace+0x0/0x2c0
> [ 5.382830] show_stack+0x20/0x2c
> [ 5.409174] dump_stack+0x10c/0x17c
> [ 5.412659] print_circular_bug+0x42c/0x4d0
> [ 5.416838] __lock_acquire+0x4c88/0x5484
> [ 5.420843] lock_acquire+0x350/0x4d4
> [ 5.424500] __mutex_lock_common+0x1a0/0x1fe8
> [ 5.428851] mutex_lock_nested+0x40/0x50
> [ 5.432770] regulator_lock_dependent+0xdc/0x6c4
> [ 5.437383] regulator_disable+0xa0/0x138
> [ 5.441389] scpsys_power_off+0x38c/0x4bc
> [ 5.445393] genpd_power_off+0x3d8/0x6a0
> [ 5.449310] genpd_power_off+0x530/0x6a0
> [ 5.453229] genpd_power_off_work_fn+0x74/0xc0
> [ 5.457667] process_one_work+0x858/0x1208
> [ 5.461758] worker_thread+0x9ec/0xcb8
> [ 5.465503] kthread+0x2b8/0x2d0
> [ 5.468727] ret_from_fork+0x10/0x18
>
> On Mon, Jun 10, 2019 at 8:21 PM Yong Wu <[email protected]> wrote:
>> ...
>
>
> On Mon, Jun 10, 2019 at 8:21 PM Yong Wu <[email protected]> wrote:
>
>> There are 2 mmu cells in a M4U HW. we could adjust some larbs entering
>> mmu0 or mmu1 to balance the bandwidth via the smi-common register
>> SMI_BUS_SEL(0x220)(Each larb occupy 2 bits).
>>
>> In mt8183, For better performance, we switch larb1/2/5/7 to enter
>> mmu1 while the others still keep enter mmu0.
>>
>> In mt8173 and mt2712, we don't get the performance issue,
>> Keep its default value(0x0), that means all the larbs enter mmu0.
>>
>> Note: smi gen1(mt2701/mt7623) don't have this bus_sel.
>>
>> And, the base of smi-common is completely different with smi_ao_base
>> of gen1, thus I add new variable for that.
>>
>> CC: Matthias Brugger <[email protected]>
>> Signed-off-by: Yong Wu <[email protected]>
>> Reviewed-by: Evan Green <[email protected]>
>> ---
>> drivers/memory/mtk-smi.c | 22 ++++++++++++++++++++--
>> 1 file changed, 20 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
>> index 9790801..08cf40d 100644
>> --- a/drivers/memory/mtk-smi.c
>> +++ b/drivers/memory/mtk-smi.c
>> @@ -49,6 +49,12 @@
>> #define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4))
>> #define F_MMU_EN BIT(0)
>>
>> +/* SMI COMMON */
>> +#define SMI_BUS_SEL 0x220
>> +#define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1)
>> +/* All are MMU0 defaultly. Only specialize mmu1 here. */
>> +#define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid))
>> +
>> enum mtk_smi_gen {
>> MTK_SMI_GEN1,
>> MTK_SMI_GEN2
>> @@ -57,6 +63,7 @@ enum mtk_smi_gen {
>> struct mtk_smi_common_plat {
>> enum mtk_smi_gen gen;
>> bool has_gals;
>> + u32 bus_sel; /* Balance some larbs to enter mmu0 or
>> mmu1 */
>> };
>>
>> struct mtk_smi_larb_gen {
>> @@ -72,8 +79,8 @@ struct mtk_smi {
>> struct clk *clk_apb, *clk_smi;
>> struct clk *clk_gals0, *clk_gals1;
>> struct clk *clk_async; /*only needed by
>> mt2701*/
>> - void __iomem *smi_ao_base;
>> -
>> + void __iomem *smi_ao_base; /* only for gen1 */
>> + void __iomem *base; /* only for gen2 */
>> const struct mtk_smi_common_plat *plat;
>> };
>>
>> @@ -410,6 +417,8 @@ static int __maybe_unused mtk_smi_larb_suspend(struct
>> device *dev)
>> static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
>> .gen = MTK_SMI_GEN2,
>> .has_gals = true,
>> + .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(5) |
>> + F_MMU1_LARB(7),
>> };
>>
>> static const struct of_device_id mtk_smi_common_of_ids[] = {
>> @@ -482,6 +491,11 @@ static int mtk_smi_common_probe(struct
>> platform_device *pdev)
>> ret = clk_prepare_enable(common->clk_async);
>> if (ret)
>> return ret;
>> + } else {
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + common->base = devm_ioremap_resource(dev, res);
>> + if (IS_ERR(common->base))
>> + return PTR_ERR(common->base);
>> }
>> pm_runtime_enable(dev);
>> platform_set_drvdata(pdev, common);
>> @@ -497,6 +511,7 @@ static int mtk_smi_common_remove(struct
>> platform_device *pdev)
>> static int __maybe_unused mtk_smi_common_resume(struct device *dev)
>> {
>> struct mtk_smi *common = dev_get_drvdata(dev);
>> + u32 bus_sel = common->plat->bus_sel;
>> int ret;
>>
>> ret = mtk_smi_clk_enable(common);
>> @@ -504,6 +519,9 @@ static int __maybe_unused mtk_smi_common_resume(struct
>> device *dev)
>> dev_err(common->dev, "Failed to enable clock(%d).\n", ret);
>> return ret;
>> }
>> +
>> + if (common->plat->gen == MTK_SMI_GEN2 && bus_sel)
>> + writel(bus_sel, common->base + SMI_BUS_SEL);
>> return 0;
>> }
>>
>> --
>> 1.9.1
>>
>>
>

2019-06-20 11:39:49

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 16/21] memory: mtk-smi: Add bus_sel for mt8183

CCing Sascha

On 20/06/2019 11:35, Matthias Brugger wrote:
>
>
> On 13/06/2019 10:14, Pi-Hsun Shih wrote:
>> Hi,
>> When I tested this patch series (Based on linux 5.2.0-rc2, and with
>> various other patch series about MT8183) with lockdep enabled, and I'm
>> seeing the following lockdep warning on boot.
>>
>> By bisecting the commits, the first commit that introduce this warning
>> is this patch. The warning also doesn't appear if
>> https://lore.kernel.org/patchwork/patch/1086582/ and
>> https://lore.kernel.org/patchwork/patch/1086583/ are not applied.
>>
>> Do anyone have idea on why this is happening, or any suggestion on
>> which part I should be digging into to figure this out? Thanks.
>>
>> [ 4.664194] ======================================================
>> [ 4.670368] WARNING: possible circular locking dependency detected
>> [ 4.676545] 5.2.0-rc2-next-20190528-44527-g6c94b6475c04 #20 Tainted: G S
>> [ 4.684539] ------------------------------------------------------
>> [ 4.690714] kworker/4:1/51 is trying to acquire lock:
>> [ 4.695760] (____ptrval____) (regulator_list_mutex){+.+.},
>> at:regulator_lock_dependent+0xdc/0x6c4
>> [ 4.704732]
>> [ 4.704732] but task is already holding lock:
>> [ 4.710556] (____ptrval____) (&genpd->mlock/1){+.+.},
>> at:genpd_lock_nested_mtx+0x24/0x30
>> [ 4.718740]
>> [ 4.718740] which lock already depends on the new lock.
>> [ 4.718740]
>> [ 4.726908]
>> [ 4.726908] the existing dependency chain (in reverse order) is:
>> [ 4.734382]
>> [ 4.734382] -> #4 (&genpd->mlock/1){+.+.}:
>> [ 4.739963] __mutex_lock_common+0x1a0/0x1fe8
>> [ 4.744836] mutex_lock_nested+0x40/0x50
>> [ 4.749275] genpd_lock_nested_mtx+0x24/0x30
>> [ 4.754063] genpd_add_subdomain+0x150/0x524
>> [ 4.758850] pm_genpd_add_subdomain+0x3c/0x5c
>> [ 4.763723] scpsys_probe+0x520/0xe78
>> [ 4.767902] platform_drv_probe+0xf4/0x134
>> [ 4.772517] really_probe+0x214/0x4dc
>> [ 4.776696] driver_probe_device+0xcc/0x1d4
>> [ 4.781396] __device_attach_driver+0x10c/0x180
>> [ 4.786442] bus_for_each_drv+0x124/0x184
>> [ 4.790968] __device_attach+0x1c0/0x2d8
>> [ 4.795407] device_initial_probe+0x20/0x2c
>> [ 4.800106] bus_probe_device+0x80/0x16c
>> [ 4.804546] deferred_probe_work_func+0x120/0x168
>> [ 4.809767] process_one_work+0x858/0x1208
>> [ 4.814379] worker_thread+0x9ec/0xcb8
>> [ 4.818644] kthread+0x2b8/0x2d0
>> [ 4.822391] ret_from_fork+0x10/0x18
>> [ 4.826480]
>> [ 4.826480] -> #3 (&genpd->mlock){+.+.}:
>> [ 4.831880] __mutex_lock_common+0x1a0/0x1fe8
>> [ 4.836752] mutex_lock_nested+0x40/0x50
>> [ 4.841190] genpd_lock_mtx+0x20/0x2c
>> [ 4.845369] genpd_runtime_resume+0x140/0x434
>> [ 4.850241] __rpm_callback+0xb0/0x1e4
>> [ 4.854506] rpm_callback+0x54/0x1a8
>> [ 4.858597] rpm_resume+0xc6c/0x10c4
>> [ 4.862689] __pm_runtime_resume+0xb4/0x124
>> [ 4.867387] device_link_add+0x598/0x8d0
>
> For this looks as if you have also patch
> [PATCH v2 04/12] memory: mtk-smi: Add device-link between smi-larb and smi-common
> from series
> [PATCH v2 00/12] Clean up "mediatek,larb" after adding device_link
> applied.
>

My guess is, that we run into this, because we call genpd_runtime_resume before
we have finished the subdomain registration in scpsys_probe.
That implies that you also have the scpsys series for mt8183 added to your tree.

Anyway it looks to me as if we have to add the subdomains before we call
of_genpd_add_provider_onecell().

Regards,
Matthias

> Regards,
> Matthias
>
>> [ 4.871829] mtk_smi_larb_probe+0x2b0/0x340
>> [ 4.876528] platform_drv_probe+0xf4/0x134
>> [ 4.881141] really_probe+0x214/0x4dc
>> [ 4.885320] driver_probe_device+0xcc/0x1d4
>> [ 4.890020] __device_attach_driver+0x10c/0x180
>> [ 4.895066] bus_for_each_drv+0x124/0x184
>> [ 4.899591] __device_attach+0x1c0/0x2d8
>> [ 4.904031] device_initial_probe+0x20/0x2c
>> [ 4.908730] bus_probe_device+0x80/0x16c
>> [ 4.913169] deferred_probe_work_func+0x120/0x168
>> [ 4.918387] process_one_work+0x858/0x1208
>> [ 4.923000] worker_thread+0x9ec/0xcb8
>> [ 4.927264] kthread+0x2b8/0x2d0
>> [ 4.931009] ret_from_fork+0x10/0x18
>> [ 4.935098]
>> [ 4.935098] -> #2 (dpm_list_mtx){+.+.}:
>> [ 4.940412] __mutex_lock_common+0x1a0/0x1fe8
>> [ 4.945284] mutex_lock_nested+0x40/0x50
>> [ 4.949722] device_pm_lock+0x1c/0x24
>> [ 4.953900] device_link_add+0x98/0x8d0
>> [ 4.958252] _regulator_get+0x3f0/0x504
>> [ 4.962606] _devm_regulator_get+0x58/0xb8
>> [ 4.967218] devm_regulator_get+0x28/0x34
>> [ 4.971746] pwm_backlight_probe+0x61c/0x1b90
>> [ 4.976617] platform_drv_probe+0xf4/0x134
>> [ 4.981230] really_probe+0x214/0x4dc
>> [ 4.985409] driver_probe_device+0xcc/0x1d4
>> [ 4.990108] device_driver_attach+0xe4/0x104
>> [ 4.994894] __driver_attach+0x134/0x14c
>> [ 4.999333] bus_for_each_dev+0x120/0x180
>> [ 5.003859] driver_attach+0x48/0x54
>> [ 5.007950] bus_add_driver+0x2ac/0x44c
>> [ 5.012303] driver_register+0x160/0x288
>> [ 5.016742] __platform_driver_register+0xcc/0xdc
>> [ 5.021964] pwm_backlight_driver_init+0x1c/0x24
>> [ 5.027097] do_one_initcall+0x38c/0x994
>> [ 5.031536] do_initcall_level+0x3a4/0x4b8
>> [ 5.036148] do_basic_setup+0x84/0xa0
>> [ 5.036153] kernel_init_freeable+0x23c/0x324
>> [ 5.036158] kernel_init+0x14/0x110
>> [ 5.036164] ret_from_fork+0x10/0x18
>> [ 5.036166]
>> [ 5.036166] -> #1 (device_links_lock){+.+.}:
>> [ 5.065905] __mutex_lock_common+0x1a0/0x1fe8
>> [ 5.070777] mutex_lock_nested+0x40/0x50
>> [ 5.075215] device_link_remove+0x40/0xe0
>> [ 5.079740] _regulator_put+0x104/0x2d8
>> [ 5.084093] regulator_put+0x30/0x44
>> [ 5.088184] devm_regulator_release+0x38/0x44
>> [ 5.093056] release_nodes+0x604/0x670
>> [ 5.097320] devres_release_all+0x70/0x8c
>> [ 5.101846] really_probe+0x270/0x4dc
>> [ 5.106024] driver_probe_device+0xcc/0x1d4
>> [ 5.110724] device_driver_attach+0xe4/0x104
>> [ 5.115510] __driver_attach+0x134/0x14c
>> [ 5.119949] bus_for_each_dev+0x120/0x180
>> [ 5.124474] driver_attach+0x48/0x54
>> [ 5.128566] bus_add_driver+0x2ac/0x44c
>> [ 5.132919] driver_register+0x160/0x288
>> [ 5.137357] __platform_driver_register+0xcc/0xdc
>> [ 5.142576] pwm_backlight_driver_init+0x1c/0x24
>> [ 5.147708] do_one_initcall+0x38c/0x994
>> [ 5.152146] do_initcall_level+0x3a4/0x4b8
>> [ 5.156758] do_basic_setup+0x84/0xa0
>> [ 5.160936] kernel_init_freeable+0x23c/0x324
>> [ 5.165807] kernel_init+0x14/0x110
>> [ 5.169813] ret_from_fork+0x10/0x18
>> [ 5.173901]
>> [ 5.173901] -> #0 (regulator_list_mutex){+.+.}:
>> [ 5.179910] lock_acquire+0x350/0x4d4
>> [ 5.184088] __mutex_lock_common+0x1a0/0x1fe8
>> [ 5.184095] mutex_lock_nested+0x40/0x50
>> [ 5.197475] regulator_lock_dependent+0xdc/0x6c4
>> [ 5.197482] regulator_disable+0xa0/0x138
>> [ 5.197487] scpsys_power_off+0x38c/0x4bc
>> [ 5.197495] genpd_power_off+0x3d8/0x6a0
>> [ 5.209399] genpd_power_off+0x530/0x6a0
>> [ 5.209406] genpd_power_off_work_fn+0x74/0xc0
>> [ 5.209411] process_one_work+0x858/0x1208
>> [ 5.209419] worker_thread+0x9ec/0xcb8
>> [ 5.219067] kthread+0x2b8/0x2d0
>> [ 5.219073] ret_from_fork+0x10/0x18
>> [ 5.219077]
>> [ 5.219077] other info that might help us debug this:
>> [ 5.219077]
>> [ 5.219080] Chain exists of:
>> [ 5.219080] regulator_list_mutex --> &genpd->mlock --> &genpd->mlock/1
>> [ 5.219080]
>> [ 5.228039] Possible unsafe locking scenario:
>> [ 5.228039]
>> [ 5.228042] CPU0 CPU1
>> [ 5.228046] ---- ----
>> [ 5.228048] lock(&genpd->mlock/1);
>> [ 5.228058] lock(&genpd->mlock);
>> [ 5.311647] lock(&genpd->mlock/1);
>> [ 5.317736] lock(regulator_list_mutex);
>> [ 5.321742]
>> [ 5.321742] *** DEADLOCK ***
>> [ 5.321742]
>> [ 5.327655] 4 locks held by kworker/4:1/51:
>> [ 5.331831] #0: (____ptrval____) ((wq_completion)pm){+.+.},
>> at:process_one_work+0x57c/0x1208
>> [ 5.340444] #1: (____ptrval____)
>> ((work_completion)(&genpd->power_off_work)){+.+.},
>> at:process_one_work+0x5b8/0x1208
>> [ 5.351139] #2: (____ptrval____) (&genpd->mlock){+.+.},
>> at:genpd_lock_mtx+0x20/0x2c
>> [ 5.358970] #3: (____ptrval____) (&genpd->mlock/1){+.+.},
>> at:genpd_lock_nested_mtx+0x24/0x30
>> [ 5.367584]
>> [ 5.367584] stack backtrace:
>> [ 5.371939] CPU: 4 PID: 51 Comm: kworker/4:1 Tainted: G S
>> 5.2.0-rc2-next-20190528-44527-g6c94b6475c04 #20
>> [ 5.382809] Workqueue: pm genpd_power_off_work_fn
>> [ 5.382816] Call trace:
>> [ 5.382822] dump_backtrace+0x0/0x2c0
>> [ 5.382830] show_stack+0x20/0x2c
>> [ 5.409174] dump_stack+0x10c/0x17c
>> [ 5.412659] print_circular_bug+0x42c/0x4d0
>> [ 5.416838] __lock_acquire+0x4c88/0x5484
>> [ 5.420843] lock_acquire+0x350/0x4d4
>> [ 5.424500] __mutex_lock_common+0x1a0/0x1fe8
>> [ 5.428851] mutex_lock_nested+0x40/0x50
>> [ 5.432770] regulator_lock_dependent+0xdc/0x6c4
>> [ 5.437383] regulator_disable+0xa0/0x138
>> [ 5.441389] scpsys_power_off+0x38c/0x4bc
>> [ 5.445393] genpd_power_off+0x3d8/0x6a0
>> [ 5.449310] genpd_power_off+0x530/0x6a0
>> [ 5.453229] genpd_power_off_work_fn+0x74/0xc0
>> [ 5.457667] process_one_work+0x858/0x1208
>> [ 5.461758] worker_thread+0x9ec/0xcb8
>> [ 5.465503] kthread+0x2b8/0x2d0
>> [ 5.468727] ret_from_fork+0x10/0x18
>>
>> On Mon, Jun 10, 2019 at 8:21 PM Yong Wu <[email protected]> wrote:
>>> ...
>>
>>
>> On Mon, Jun 10, 2019 at 8:21 PM Yong Wu <[email protected]> wrote:
>>
>>> There are 2 mmu cells in a M4U HW. we could adjust some larbs entering
>>> mmu0 or mmu1 to balance the bandwidth via the smi-common register
>>> SMI_BUS_SEL(0x220)(Each larb occupy 2 bits).
>>>
>>> In mt8183, For better performance, we switch larb1/2/5/7 to enter
>>> mmu1 while the others still keep enter mmu0.
>>>
>>> In mt8173 and mt2712, we don't get the performance issue,
>>> Keep its default value(0x0), that means all the larbs enter mmu0.
>>>
>>> Note: smi gen1(mt2701/mt7623) don't have this bus_sel.
>>>
>>> And, the base of smi-common is completely different with smi_ao_base
>>> of gen1, thus I add new variable for that.
>>>
>>> CC: Matthias Brugger <[email protected]>
>>> Signed-off-by: Yong Wu <[email protected]>
>>> Reviewed-by: Evan Green <[email protected]>
>>> ---
>>> drivers/memory/mtk-smi.c | 22 ++++++++++++++++++++--
>>> 1 file changed, 20 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
>>> index 9790801..08cf40d 100644
>>> --- a/drivers/memory/mtk-smi.c
>>> +++ b/drivers/memory/mtk-smi.c
>>> @@ -49,6 +49,12 @@
>>> #define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4))
>>> #define F_MMU_EN BIT(0)
>>>
>>> +/* SMI COMMON */
>>> +#define SMI_BUS_SEL 0x220
>>> +#define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1)
>>> +/* All are MMU0 defaultly. Only specialize mmu1 here. */
>>> +#define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid))
>>> +
>>> enum mtk_smi_gen {
>>> MTK_SMI_GEN1,
>>> MTK_SMI_GEN2
>>> @@ -57,6 +63,7 @@ enum mtk_smi_gen {
>>> struct mtk_smi_common_plat {
>>> enum mtk_smi_gen gen;
>>> bool has_gals;
>>> + u32 bus_sel; /* Balance some larbs to enter mmu0 or
>>> mmu1 */
>>> };
>>>
>>> struct mtk_smi_larb_gen {
>>> @@ -72,8 +79,8 @@ struct mtk_smi {
>>> struct clk *clk_apb, *clk_smi;
>>> struct clk *clk_gals0, *clk_gals1;
>>> struct clk *clk_async; /*only needed by
>>> mt2701*/
>>> - void __iomem *smi_ao_base;
>>> -
>>> + void __iomem *smi_ao_base; /* only for gen1 */
>>> + void __iomem *base; /* only for gen2 */
>>> const struct mtk_smi_common_plat *plat;
>>> };
>>>
>>> @@ -410,6 +417,8 @@ static int __maybe_unused mtk_smi_larb_suspend(struct
>>> device *dev)
>>> static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
>>> .gen = MTK_SMI_GEN2,
>>> .has_gals = true,
>>> + .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(5) |
>>> + F_MMU1_LARB(7),
>>> };
>>>
>>> static const struct of_device_id mtk_smi_common_of_ids[] = {
>>> @@ -482,6 +491,11 @@ static int mtk_smi_common_probe(struct
>>> platform_device *pdev)
>>> ret = clk_prepare_enable(common->clk_async);
>>> if (ret)
>>> return ret;
>>> + } else {
>>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> + common->base = devm_ioremap_resource(dev, res);
>>> + if (IS_ERR(common->base))
>>> + return PTR_ERR(common->base);
>>> }
>>> pm_runtime_enable(dev);
>>> platform_set_drvdata(pdev, common);
>>> @@ -497,6 +511,7 @@ static int mtk_smi_common_remove(struct
>>> platform_device *pdev)
>>> static int __maybe_unused mtk_smi_common_resume(struct device *dev)
>>> {
>>> struct mtk_smi *common = dev_get_drvdata(dev);
>>> + u32 bus_sel = common->plat->bus_sel;
>>> int ret;
>>>
>>> ret = mtk_smi_clk_enable(common);
>>> @@ -504,6 +519,9 @@ static int __maybe_unused mtk_smi_common_resume(struct
>>> device *dev)
>>> dev_err(common->dev, "Failed to enable clock(%d).\n", ret);
>>> return ret;
>>> }
>>> +
>>> + if (common->plat->gen == MTK_SMI_GEN2 && bus_sel)
>>> + writel(bus_sel, common->base + SMI_BUS_SEL);
>>> return 0;
>>> }
>>>
>>> --
>>> 1.9.1
>>>
>>>
>>

2019-06-20 14:00:15

by Yong Wu (吴勇)

[permalink] [raw]
Subject: Re: [PATCH v7 17/21] memory: mtk-smi: Get rid of need_larbid

On Tue, 2019-06-18 at 15:45 +0200, Matthias Brugger wrote:
>
> On 10/06/2019 14:17, Yong Wu wrote:
> > The "mediatek,larb-id" has already been parsed in MTK IOMMU driver.
> > It's no need to parse it again in SMI driver. Only clean some codes.
> > This patch is fit for all the current mt2701, mt2712, mt7623, mt8173
> > and mt8183.
> >
> > After this patch, the "mediatek,larb-id" only be needed for mt2712
> > which have 2 M4Us. In the other SoCs, we can get the larb-id from M4U
> > in which the larbs in the "mediatek,larbs" always are ordered.
> >
> > Correspondingly, the larb_nr in the "struct mtk_smi_iommu" could also
> > be deleted.
> >
>
> I think we can get rid of struct mtk_smi_iommu and just add the
> struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX] directly to mtk_iommu_data,
> passing just that array to the components bind function.

Thanks. I will try this in a new patch.

>
> Never the less this patch looks fine:
> Reviewed-by: Matthias Brugger <[email protected]>

Really appreciate for reviewing so many patches.

>
> > CC: Matthias Brugger <[email protected]>
> > Signed-off-by: Yong Wu <[email protected]>
> > Reviewed-by: Evan Green <[email protected]>
> > ---
> > drivers/iommu/mtk_iommu.c | 1 -
> > drivers/iommu/mtk_iommu_v1.c | 2 --
> > drivers/memory/mtk-smi.c | 26 ++------------------------
> > include/soc/mediatek/smi.h | 1 -
> > 4 files changed, 2 insertions(+), 28 deletions(-)
> >
> > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> > index ec4ce74..6053b8b 100644
> > --- a/drivers/iommu/mtk_iommu.c
> > +++ b/drivers/iommu/mtk_iommu.c
> > @@ -634,7 +634,6 @@ static int mtk_iommu_probe(struct platform_device *pdev)
> > "mediatek,larbs", NULL);
> > if (larb_nr < 0)
> > return larb_nr;
> > - data->smi_imu.larb_nr = larb_nr;
> >
> > for (i = 0; i < larb_nr; i++) {
> > struct device_node *larbnode;
> > diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
> > index 52b01e3..73308ad 100644
> > --- a/drivers/iommu/mtk_iommu_v1.c
> > +++ b/drivers/iommu/mtk_iommu_v1.c
> > @@ -624,8 +624,6 @@ static int mtk_iommu_probe(struct platform_device *pdev)
> > larb_nr++;
> > }
> >
> > - data->smi_imu.larb_nr = larb_nr;
> > -
> > platform_set_drvdata(pdev, data);
> >
> > ret = mtk_iommu_hw_init(data);
> > diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
> > index 08cf40d..10e6493 100644
> > --- a/drivers/memory/mtk-smi.c
> > +++ b/drivers/memory/mtk-smi.c
> > @@ -67,7 +67,6 @@ struct mtk_smi_common_plat {
> > };
> >
> > struct mtk_smi_larb_gen {
> > - bool need_larbid;
> > int port_in_larb[MTK_LARB_NR_MAX + 1];
> > void (*config_port)(struct device *);
> > unsigned int larb_direct_to_common_mask;
> > @@ -153,18 +152,9 @@ void mtk_smi_larb_put(struct device *larbdev)
> > struct mtk_smi_iommu *smi_iommu = data;
> > unsigned int i;
> >
> > - if (larb->larb_gen->need_larbid) {
> > - larb->mmu = &smi_iommu->larb_imu[larb->larbid].mmu;
> > - return 0;
> > - }
> > -
> > - /*
> > - * If there is no larbid property, Loop to find the corresponding
> > - * iommu information.
> > - */
> > - for (i = 0; i < smi_iommu->larb_nr; i++) {
> > + for (i = 0; i < MTK_LARB_NR_MAX; i++) {
> > if (dev == smi_iommu->larb_imu[i].dev) {
> > - /* The 'mmu' may be updated in iommu-attach/detach. */
> > + larb->larbid = i;
> > larb->mmu = &smi_iommu->larb_imu[i].mmu;
> > return 0;
> > }
> > @@ -243,7 +233,6 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev)
> > };
> >
> > static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
> > - .need_larbid = true,
> > .port_in_larb = {
> > LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
> > LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
> > @@ -252,7 +241,6 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev)
> > };
> >
> > static const struct mtk_smi_larb_gen mtk_smi_larb_mt2712 = {
> > - .need_larbid = true,
> > .config_port = mtk_smi_larb_config_port_gen2_general,
> > .larb_direct_to_common_mask = BIT(8) | BIT(9), /* bdpsys */
> > };
> > @@ -291,7 +279,6 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
> > struct device *dev = &pdev->dev;
> > struct device_node *smi_node;
> > struct platform_device *smi_pdev;
> > - int err;
> >
> > larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL);
> > if (!larb)
> > @@ -321,15 +308,6 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
> > }
> > larb->smi.dev = dev;
> >
> > - if (larb->larb_gen->need_larbid) {
> > - err = of_property_read_u32(dev->of_node, "mediatek,larb-id",
> > - &larb->larbid);
> > - if (err) {
> > - dev_err(dev, "missing larbid property\n");
> > - return err;
> > - }
> > - }
> > -
> > smi_node = of_parse_phandle(dev->of_node, "mediatek,smi", 0);
> > if (!smi_node)
> > return -EINVAL;
> > diff --git a/include/soc/mediatek/smi.h b/include/soc/mediatek/smi.h
> > index 5201e90..a65324d 100644
> > --- a/include/soc/mediatek/smi.h
> > +++ b/include/soc/mediatek/smi.h
> > @@ -29,7 +29,6 @@ struct mtk_smi_larb_iommu {
> > };
> >
> > struct mtk_smi_iommu {
> > - unsigned int larb_nr;
> > struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX];
> > };
> >
> >


2019-06-20 14:00:30

by Yong Wu (吴勇)

[permalink] [raw]
Subject: Re: [PATCH v7 19/21] iommu/mediatek: Rename enable_4GB to dram_is_4gb

On Tue, 2019-06-18 at 18:06 +0200, Matthias Brugger wrote:
>
> On 10/06/2019 14:17, Yong Wu wrote:
> > This patch only rename the variable name from enable_4GB to
> > dram_is_4gb for readable.
>
> From my understanding this is true when available RAM > 4GB so I think the name
> should be something like dram_bigger_4gb otherwise it may create confusion again.

Strictly, It is not "dram_bigger_4gb". actually if the dram size is over
3GB (the first 1GB is the register space), the "4GB mode" will be
enabled. then how about the name "dram_enable_32bit"?(the PA 32bit will
be enabled in the 4GB mode.)

There is another option, please see the last part in [1] suggested by
Evan, something like below:
----
data->enable_4GB = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
if (!data->plat_data->has_4gb_mode)
data->enable_4GB = false;
Then mtk_iommu_map would only have:
if (data->enable_4GB)
paddr |= BIT_ULL(32);
----

Which one do you prefer?

[1] https://lore.kernel.org/patchwork/patch/1028421/

>
> Also from my point of view this patch should be done before
> "[PATCH 06/21] iommu/io-pgtable-arm-v7s: Extend MediaTek 4GB Mode"

OK.

>
> Regards,
> Matthias
>
> >
> > Signed-off-by: Yong Wu <[email protected]>
> > Reviewed-by: Evan Green <[email protected]>
> > ---
> > drivers/iommu/mtk_iommu.c | 10 +++++-----
> > drivers/iommu/mtk_iommu.h | 2 +-
> > 2 files changed, 6 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> > index 86158d8..67cab2d 100644
> > --- a/drivers/iommu/mtk_iommu.c
> > +++ b/drivers/iommu/mtk_iommu.c
> > @@ -382,7 +382,7 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
> > int ret;
> >
> > /* The "4GB mode" M4U physically can not use the lower remap of Dram. */
> > - if (data->plat_data->has_4gb_mode && data->enable_4GB)
> > + if (data->plat_data->has_4gb_mode && data->dram_is_4gb)
> > paddr |= BIT_ULL(32);
> >
> > spin_lock_irqsave(&dom->pgtlock, flags);
> > @@ -554,13 +554,13 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
> > writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
> >
> > if (data->plat_data->m4u_plat == M4U_MT8173)
> > - regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
> > + regval = (data->protect_base >> 1) | (data->dram_is_4gb << 31);
> > else
> > regval = lower_32_bits(data->protect_base) |
> > upper_32_bits(data->protect_base);
> > writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
> >
> > - if (data->enable_4GB && data->plat_data->has_vld_pa_rng) {
> > + if (data->dram_is_4gb && data->plat_data->has_vld_pa_rng) {
> > /*
> > * If 4GB mode is enabled, the validate PA range is from
> > * 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
> > @@ -611,8 +611,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
> > return -ENOMEM;
> > data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
> >
> > - /* Whether the current dram is over 4GB */
> > - data->enable_4GB = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
> > + /* Whether the current dram is 4GB. */
> > + data->dram_is_4gb = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
> >
> > res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > data->base = devm_ioremap_resource(dev, res);
> > diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> > index 753266b..e8114b2 100644
> > --- a/drivers/iommu/mtk_iommu.h
> > +++ b/drivers/iommu/mtk_iommu.h
> > @@ -65,7 +65,7 @@ struct mtk_iommu_data {
> > struct mtk_iommu_domain *m4u_dom;
> > struct iommu_group *m4u_group;
> > struct mtk_smi_iommu smi_imu; /* SMI larb iommu info */
> > - bool enable_4GB;
> > + bool dram_is_4gb;
> > bool tlb_flush_active;
> >
> > struct iommu_device iommu;
> >


2019-06-20 14:01:47

by Yong Wu (吴勇)

[permalink] [raw]
Subject: Re: [PATCH v7 20/21] iommu/mediatek: Fix iova_to_phys PA start for 4GB mode

On Tue, 2019-06-18 at 18:35 +0200, Matthias Brugger wrote:
>
> On 10/06/2019 14:17, Yong Wu wrote:
> > In the 4GB mode, the physical address is remapped,
> >
> > Here is the detailed remap relationship.
> > CPU PA -> HW PA
> > 0x4000_0000 0x1_4000_0000 (Add bit32)
> > 0x8000_0000 0x1_8000_0000 ...
> > 0xc000_0000 0x1_c000_0000 ...
> > 0x1_0000_0000 0x1_0000_0000 (No change)
> >
> > Thus, we always add bit32 for PA when entering mtk_iommu_map.
> > But in the iova_to_phys, the CPU don't need this bit32 if the
> > PA is from 0x1_4000_0000 to 0x1_ffff_ffff.
> > This patch discards the bit32 in this iova_to_phys in the 4GB mode.
> >
> > Fixes: 30e2fccf9512 ("iommu/mediatek: Enlarge the validate PA range
> > for 4GB mode")
> > Signed-off-by: Yong Wu <[email protected]>
> > ---
> > drivers/iommu/mtk_iommu.c | 18 ++++++++++++++++++
> > 1 file changed, 18 insertions(+)
> >
> > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> > index 67cab2d..34f2e40 100644
> > --- a/drivers/iommu/mtk_iommu.c
> > +++ b/drivers/iommu/mtk_iommu.c
> > @@ -119,6 +119,19 @@ struct mtk_iommu_domain {
> >
> > static const struct iommu_ops mtk_iommu_ops;
> >
> > +/*
> > + * In M4U 4GB mode, the physical address is remapped as below:
> > + * CPU PA -> M4U HW PA
> > + * 0x4000_0000 0x1_4000_0000 (Add bit32)
> > + * 0x8000_0000 0x1_8000_0000 ...
> > + * 0xc000_0000 0x1_c000_0000 ...
> > + * 0x1_0000_0000 0x1_0000_0000 (No change)
> > + *
> > + * Thus, We always add BIT32 in the iommu_map and disable BIT32 if PA is >=
> > + * 0x1_4000_0000 in the iova_to_phys.
> > + */
> > +#define MTK_IOMMU_4GB_MODE_PA_140000000 0x140000000UL
> > +
> > static LIST_HEAD(m4ulist); /* List all the M4U HWs */
> >
> > #define for_each_m4u(data) list_for_each_entry(data, &m4ulist, list)
> > @@ -415,6 +428,7 @@ 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();
> > unsigned long flags;
> > phys_addr_t pa;
> >
> > @@ -422,6 +436,10 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
> > pa = dom->iop->iova_to_phys(dom->iop, iova);
> > spin_unlock_irqrestore(&dom->pgtlock, flags);
> >
> > + if (data->plat_data->has_4gb_mode && data->dram_is_4gb &&
> > + pa >= MTK_IOMMU_4GB_MODE_PA_140000000)
> > + pa &= ~BIT_ULL(32);
> > +
>
> Hm, I wonder if we could fix this as first patch in the series, especially before:
> "[PATCH 06/21] iommu/io-pgtable-arm-v7s: Extend MediaTek 4GB Mode"

OK.

>
> This would make it easier for the stable maintainer to cherry-pick the fix.
> Without 100% understanding the code, it seems suspicious to me, that you first
> move the setting of the bit32 and bit33 into v7s and later explicitly clean the
> bits here.
>
> So my take on this is, that patch 6/21 introduced the regression you are trying
> to fix here. As said that is speculation as I don't understand the code in its
> whole.
>
> Any clarification would be useful.

I guess the commit message in [06/21] will be helpful.

In the previous mt8173 and mt2712, the M4U HW support "4GB mode" in
which the range of dram is from 0x4000_0000 to 0x1_3fff_ffff and it was
remapped to 0x1_0000_0000 ~0x1_ffff_ffff(For readable, I have wrote the
re-map relationship into the code in this patch.). but mt8183 don't need
remap the dram address(0x4000_0000 ~ 0x3_ffff_ffff).

In order to unify the code, we add bit32 for "4GB mode". But actually
the PA doesn't always have bit32, thus, I have to remove bit32 when PA >
0x1_4000_0000.

So sorry that the "4GB mode" is a little unreadable and special, And the
4GB patch(30e2fccf9512 ("iommu/mediatek: Enlarge the validate PA range
for 4GB mode") has introduced several fix patches.

>
> Regards,
> Matthias
>
> > return pa;
> > }
> >
> >
>
> _______________________________________________
> Linux-mediatek mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-mediatek


2019-06-21 03:59:13

by Pi-Hsun Shih

[permalink] [raw]
Subject: Re: [PATCH v7 16/21] memory: mtk-smi: Add bus_sel for mt8183

On Thu, Jun 20, 2019 at 7:38 PM Matthias Brugger <[email protected]> wrote:
>
> CCing Sascha
>
> On 20/06/2019 11:35, Matthias Brugger wrote:
> >
> >
> > On 13/06/2019 10:14, Pi-Hsun Shih wrote:
> >> Hi,
> >> When I tested this patch series (Based on linux 5.2.0-rc2, and with
> >> various other patch series about MT8183) with lockdep enabled, and I'm
> >> seeing the following lockdep warning on boot.
> >>
> >> By bisecting the commits, the first commit that introduce this warning
> >> is this patch. The warning also doesn't appear if
> >> https://lore.kernel.org/patchwork/patch/1086582/ and
> >> https://lore.kernel.org/patchwork/patch/1086583/ are not applied.
> >>
> >> Do anyone have idea on why this is happening, or any suggestion on
> >> which part I should be digging into to figure this out? Thanks.
> >>
> >> [ 4.664194] ======================================================
> >> [ 4.670368] WARNING: possible circular locking dependency detected
> >> [ 4.676545] 5.2.0-rc2-next-20190528-44527-g6c94b6475c04 #20 Tainted: G S
> >> [ 4.684539] ------------------------------------------------------
> >> [ 4.690714] kworker/4:1/51 is trying to acquire lock:
> >> [ 4.695760] (____ptrval____) (regulator_list_mutex){+.+.},
> >> at:regulator_lock_dependent+0xdc/0x6c4
> >> [ 4.704732]
> >> [ 4.704732] but task is already holding lock:
> >> [ 4.710556] (____ptrval____) (&genpd->mlock/1){+.+.},
> >> at:genpd_lock_nested_mtx+0x24/0x30
> >> [ 4.718740]
> >> [ 4.718740] which lock already depends on the new lock.
> >> [ 4.718740]
> >> [ 4.726908]
> >> [ 4.726908] the existing dependency chain (in reverse order) is:
> >> [ 4.734382]
> >> [ 4.734382] -> #4 (&genpd->mlock/1){+.+.}:
> >> [ 4.739963] __mutex_lock_common+0x1a0/0x1fe8
> >> [ 4.744836] mutex_lock_nested+0x40/0x50
> >> [ 4.749275] genpd_lock_nested_mtx+0x24/0x30
> >> [ 4.754063] genpd_add_subdomain+0x150/0x524
> >> [ 4.758850] pm_genpd_add_subdomain+0x3c/0x5c
> >> [ 4.763723] scpsys_probe+0x520/0xe78
> >> [ 4.767902] platform_drv_probe+0xf4/0x134
> >> [ 4.772517] really_probe+0x214/0x4dc
> >> [ 4.776696] driver_probe_device+0xcc/0x1d4
> >> [ 4.781396] __device_attach_driver+0x10c/0x180
> >> [ 4.786442] bus_for_each_drv+0x124/0x184
> >> [ 4.790968] __device_attach+0x1c0/0x2d8
> >> [ 4.795407] device_initial_probe+0x20/0x2c
> >> [ 4.800106] bus_probe_device+0x80/0x16c
> >> [ 4.804546] deferred_probe_work_func+0x120/0x168
> >> [ 4.809767] process_one_work+0x858/0x1208
> >> [ 4.814379] worker_thread+0x9ec/0xcb8
> >> [ 4.818644] kthread+0x2b8/0x2d0
> >> [ 4.822391] ret_from_fork+0x10/0x18
> >> [ 4.826480]
> >> [ 4.826480] -> #3 (&genpd->mlock){+.+.}:
> >> [ 4.831880] __mutex_lock_common+0x1a0/0x1fe8
> >> [ 4.836752] mutex_lock_nested+0x40/0x50
> >> [ 4.841190] genpd_lock_mtx+0x20/0x2c
> >> [ 4.845369] genpd_runtime_resume+0x140/0x434
> >> [ 4.850241] __rpm_callback+0xb0/0x1e4
> >> [ 4.854506] rpm_callback+0x54/0x1a8
> >> [ 4.858597] rpm_resume+0xc6c/0x10c4
> >> [ 4.862689] __pm_runtime_resume+0xb4/0x124
> >> [ 4.867387] device_link_add+0x598/0x8d0
> >
> > For this looks as if you have also patch
> > [PATCH v2 04/12] memory: mtk-smi: Add device-link between smi-larb and smi-common
> > from series
> > [PATCH v2 00/12] Clean up "mediatek,larb" after adding device_link
> > applied.
> >
>
> My guess is, that we run into this, because we call genpd_runtime_resume before
> we have finished the subdomain registration in scpsys_probe.
> That implies that you also have the scpsys series for mt8183 added to your tree.
>
> Anyway it looks to me as if we have to add the subdomains before we call
> of_genpd_add_provider_onecell().
>
> Regards,
> Matthias

Yes I do have scpsys series for mt8183 added in my tree. (I have about
125 patches from list on top of 531b0a360899 "Add linux-next specific
files for 20190528" to make the board boot)
However the exact same warning still exists after I changed the order
of of_genpd_add_provider_onecell and pm_genpd_add_subdomain, patch as
follow:
(Patch is based on commit f4788d37bc84 "Add linux-next specific files
for 20190614")

diff --git a/drivers/soc/mediatek/mtk-scpsys.c
b/drivers/soc/mediatek/mtk-scpsys.c
index 503222d0d0da..0cd9bdd4004e 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -440,8 +440,7 @@ static struct scp *init_scp(struct platform_device *pdev,
static void mtk_register_power_domains(struct platform_device *pdev,
struct scp *scp, int num)
{
- struct genpd_onecell_data *pd_data;
- int i, ret;
+ int i;

for (i = 0; i < num; i++) {
struct scp_domain *scpd = &scp->domains[i];
@@ -457,18 +456,6 @@ static void mtk_register_power_domains(struct
platform_device *pdev,

pm_genpd_init(genpd, NULL, false);
}
-
- /*
- * We are not allowed to fail here since there is no way to unregister
- * a power domain. Once registered above we have to keep the domains
- * valid.
- */
-
- pd_data = &scp->pd_data;
-
- ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
- if (ret)
- dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
}

/*
@@ -1053,6 +1040,16 @@ static int scpsys_probe(struct platform_device *pdev)
ret);
}

+ /*
+ * We are not allowed to fail here since there is no way to unregister
+ * a power domain. Once registered above we have to keep the domains
+ * valid.
+ */
+
+ ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
+ if (ret)
+ dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
+
return 0;
}

>
>
> > Regards,
> > Matthias
> >

2019-06-21 10:10:28

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v7 19/21] iommu/mediatek: Rename enable_4GB to dram_is_4gb



On 20/06/2019 15:59, Yong Wu wrote:
> On Tue, 2019-06-18 at 18:06 +0200, Matthias Brugger wrote:
>>
>> On 10/06/2019 14:17, Yong Wu wrote:
>>> This patch only rename the variable name from enable_4GB to
>>> dram_is_4gb for readable.
>>
>> From my understanding this is true when available RAM > 4GB so I think the name
>> should be something like dram_bigger_4gb otherwise it may create confusion again.
>
> Strictly, It is not "dram_bigger_4gb". actually if the dram size is over
> 3GB (the first 1GB is the register space), the "4GB mode" will be
> enabled. then how about the name "dram_enable_32bit"?(the PA 32bit will
> be enabled in the 4GB mode.)

Ok I think dram_is_4gb is ok then. But I'd suggest to add an explanation above
the struct mtk_iommu_data to explain exactly what this means.

>
> There is another option, please see the last part in [1] suggested by
> Evan, something like below:
> ----
> data->enable_4GB = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
> if (!data->plat_data->has_4gb_mode)
> data->enable_4GB = false;
> Then mtk_iommu_map would only have:
> if (data->enable_4GB)
> paddr |= BIT_ULL(32);
> ----

I think that's a nicer way to handle it.

Regards,
Matthias

>
> Which one do you prefer?
>
> [1] https://lore.kernel.org/patchwork/patch/1028421/
>
>>
>> Also from my point of view this patch should be done before
>> "[PATCH 06/21] iommu/io-pgtable-arm-v7s: Extend MediaTek 4GB Mode"
>
> OK.
>
>>
>> Regards,
>> Matthias
>>
>>>
>>> Signed-off-by: Yong Wu <[email protected]>
>>> Reviewed-by: Evan Green <[email protected]>
>>> ---
>>> drivers/iommu/mtk_iommu.c | 10 +++++-----
>>> drivers/iommu/mtk_iommu.h | 2 +-
>>> 2 files changed, 6 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
>>> index 86158d8..67cab2d 100644
>>> --- a/drivers/iommu/mtk_iommu.c
>>> +++ b/drivers/iommu/mtk_iommu.c
>>> @@ -382,7 +382,7 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
>>> int ret;
>>>
>>> /* The "4GB mode" M4U physically can not use the lower remap of Dram. */
>>> - if (data->plat_data->has_4gb_mode && data->enable_4GB)
>>> + if (data->plat_data->has_4gb_mode && data->dram_is_4gb)
>>> paddr |= BIT_ULL(32);
>>>
>>> spin_lock_irqsave(&dom->pgtlock, flags);
>>> @@ -554,13 +554,13 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
>>> writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
>>>
>>> if (data->plat_data->m4u_plat == M4U_MT8173)
>>> - regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
>>> + regval = (data->protect_base >> 1) | (data->dram_is_4gb << 31);
>>> else
>>> regval = lower_32_bits(data->protect_base) |
>>> upper_32_bits(data->protect_base);
>>> writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
>>>
>>> - if (data->enable_4GB && data->plat_data->has_vld_pa_rng) {
>>> + if (data->dram_is_4gb && data->plat_data->has_vld_pa_rng) {
>>> /*
>>> * If 4GB mode is enabled, the validate PA range is from
>>> * 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
>>> @@ -611,8 +611,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
>>> return -ENOMEM;
>>> data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
>>>
>>> - /* Whether the current dram is over 4GB */
>>> - data->enable_4GB = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
>>> + /* Whether the current dram is 4GB. */
>>> + data->dram_is_4gb = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
>>>
>>> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> data->base = devm_ioremap_resource(dev, res);
>>> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
>>> index 753266b..e8114b2 100644
>>> --- a/drivers/iommu/mtk_iommu.h
>>> +++ b/drivers/iommu/mtk_iommu.h
>>> @@ -65,7 +65,7 @@ struct mtk_iommu_data {
>>> struct mtk_iommu_domain *m4u_dom;
>>> struct iommu_group *m4u_group;
>>> struct mtk_smi_iommu smi_imu; /* SMI larb iommu info */
>>> - bool enable_4GB;
>>> + bool dram_is_4gb;
>>> bool tlb_flush_active;
>>>
>>> struct iommu_device iommu;
>>>
>
>

2019-06-22 02:43:38

by Yong Wu (吴勇)

[permalink] [raw]
Subject: Re: [PATCH v7 19/21] iommu/mediatek: Rename enable_4GB to dram_is_4gb


On Fri, 2019-06-21 at 12:10 +0200, Matthias Brugger wrote:
>
> On 20/06/2019 15:59, Yong Wu wrote:
> > On Tue, 2019-06-18 at 18:06 +0200, Matthias Brugger wrote:
> >>
> >> On 10/06/2019 14:17, Yong Wu wrote:
> >>> This patch only rename the variable name from enable_4GB to
> >>> dram_is_4gb for readable.
> >>
> >> From my understanding this is true when available RAM > 4GB so I think the name
> >> should be something like dram_bigger_4gb otherwise it may create confusion again.
> >
> > Strictly, It is not "dram_bigger_4gb". actually if the dram size is over
> > 3GB (the first 1GB is the register space), the "4GB mode" will be
> > enabled. then how about the name "dram_enable_32bit"?(the PA 32bit will
> > be enabled in the 4GB mode.)
>
> Ok I think dram_is_4gb is ok then. But I'd suggest to add an explanation above
> the struct mtk_iommu_data to explain exactly what this means.
>
> >
> > There is another option, please see the last part in [1] suggested by
> > Evan, something like below:
> > ----
> > data->enable_4GB = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
> > if (!data->plat_data->has_4gb_mode)
> > data->enable_4GB = false;
> > Then mtk_iommu_map would only have:
> > if (data->enable_4GB)
> > paddr |= BIT_ULL(32);
> > ----
>
> I think that's a nicer way to handle it.

Thanks your feedback. then I will use this way.

>
> Regards,
> Matthias
>
> >
> > Which one do you prefer?
> >
> > [1] https://lore.kernel.org/patchwork/patch/1028421/
> >
> >>
> >> Also from my point of view this patch should be done before
> >> "[PATCH 06/21] iommu/io-pgtable-arm-v7s: Extend MediaTek 4GB Mode"
> >
> > OK.
> >
> >>
> >> Regards,
> >> Matthias
> >>
> >>>
> >>> Signed-off-by: Yong Wu <[email protected]>
> >>> Reviewed-by: Evan Green <[email protected]>
> >>> ---
> >>> drivers/iommu/mtk_iommu.c | 10 +++++-----
> >>> drivers/iommu/mtk_iommu.h | 2 +-
> >>> 2 files changed, 6 insertions(+), 6 deletions(-)
> >>>
> >>> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> >>> index 86158d8..67cab2d 100644
> >>> --- a/drivers/iommu/mtk_iommu.c
> >>> +++ b/drivers/iommu/mtk_iommu.c
> >>> @@ -382,7 +382,7 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
> >>> int ret;
> >>>
> >>> /* The "4GB mode" M4U physically can not use the lower remap of Dram. */
> >>> - if (data->plat_data->has_4gb_mode && data->enable_4GB)
> >>> + if (data->plat_data->has_4gb_mode && data->dram_is_4gb)
> >>> paddr |= BIT_ULL(32);
> >>>
> >>> spin_lock_irqsave(&dom->pgtlock, flags);
> >>> @@ -554,13 +554,13 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
> >>> writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
> >>>
> >>> if (data->plat_data->m4u_plat == M4U_MT8173)
> >>> - regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
> >>> + regval = (data->protect_base >> 1) | (data->dram_is_4gb << 31);
> >>> else
> >>> regval = lower_32_bits(data->protect_base) |
> >>> upper_32_bits(data->protect_base);
> >>> writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
> >>>
> >>> - if (data->enable_4GB && data->plat_data->has_vld_pa_rng) {
> >>> + if (data->dram_is_4gb && data->plat_data->has_vld_pa_rng) {
> >>> /*
> >>> * If 4GB mode is enabled, the validate PA range is from
> >>> * 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
> >>> @@ -611,8 +611,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
> >>> return -ENOMEM;
> >>> data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
> >>>
> >>> - /* Whether the current dram is over 4GB */
> >>> - data->enable_4GB = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
> >>> + /* Whether the current dram is 4GB. */
> >>> + data->dram_is_4gb = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
> >>>
> >>> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >>> data->base = devm_ioremap_resource(dev, res);
> >>> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> >>> index 753266b..e8114b2 100644
> >>> --- a/drivers/iommu/mtk_iommu.h
> >>> +++ b/drivers/iommu/mtk_iommu.h
> >>> @@ -65,7 +65,7 @@ struct mtk_iommu_data {
> >>> struct mtk_iommu_domain *m4u_dom;
> >>> struct iommu_group *m4u_group;
> >>> struct mtk_smi_iommu smi_imu; /* SMI larb iommu info */
> >>> - bool enable_4GB;
> >>> + bool dram_is_4gb;
> >>> bool tlb_flush_active;
> >>>
> >>> struct iommu_device iommu;
> >>>
> >
> >