linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/9] Mediatek MT2712 clock and scpsys support
@ 2017-08-22 10:28 Weiyi Lu
  2017-08-22 10:28 ` [PATCH 1/9] dt-bindings: ARM: Mediatek: Document bindings for MT2712 Weiyi Lu
                   ` (8 more replies)
  0 siblings, 9 replies; 13+ messages in thread
From: Weiyi Lu @ 2017-08-22 10:28 UTC (permalink / raw)
  To: Matthias Brugger, Stephen Boyd, Rob Herring
  Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-clk, srv_heupstream

This series is based on v4.13-next-soc and composed of
clock control (PATCH 1-4) and scpsys control (PATCH 5-9)

changes since v1:
- Rebase to v4.13-next-soc.
- Refine scpsys and infracfg for bus protection.

Weiyi Lu (9):
  dt-bindings: ARM: Mediatek: Document bindings for MT2712
  clk: mediatek: Add dt-bindings for MT2712 clocks
  clk: mediatek: Add MT2712 clock support
  arm: dts: mt2712: Add clock controller device nodes
  dt-bindings: soc: add MT2712 power dt-bindings
  soc: mediatek: extend bus protection API
  soc: mediatek: add dependent clock jpgdec/audio for scpsys
  soc: mediatek: add MT2712 scpsys support
  arm: dts: Add power controller device node of MT2712

 .../bindings/arm/mediatek/mediatek,apmixedsys.txt  |    1 +
 .../bindings/arm/mediatek/mediatek,bdpsys.txt      |    1 +
 .../bindings/arm/mediatek/mediatek,imgsys.txt      |    1 +
 .../bindings/arm/mediatek/mediatek,infracfg.txt    |    1 +
 .../bindings/arm/mediatek/mediatek,jpgdecsys.txt   |   22 +
 .../bindings/arm/mediatek/mediatek,mcucfg.txt      |   22 +
 .../bindings/arm/mediatek/mediatek,mfgcfg.txt      |   22 +
 .../bindings/arm/mediatek/mediatek,mmsys.txt       |    1 +
 .../bindings/arm/mediatek/mediatek,pericfg.txt     |    1 +
 .../bindings/arm/mediatek/mediatek,topckgen.txt    |    1 +
 .../bindings/arm/mediatek/mediatek,vdecsys.txt     |    1 +
 .../bindings/arm/mediatek/mediatek,vencsys.txt     |    1 +
 .../devicetree/bindings/soc/mediatek/scpsys.txt    |    3 +
 arch/arm64/boot/dts/mediatek/mt2712e.dtsi          |  131 ++
 drivers/clk/mediatek/Kconfig                       |   50 +
 drivers/clk/mediatek/Makefile                      |    8 +
 drivers/clk/mediatek/clk-mt2712-bdp.c              |  102 ++
 drivers/clk/mediatek/clk-mt2712-img.c              |   80 ++
 drivers/clk/mediatek/clk-mt2712-jpgdec.c           |   76 ++
 drivers/clk/mediatek/clk-mt2712-mfg.c              |   75 ++
 drivers/clk/mediatek/clk-mt2712-mm.c               |  170 +++
 drivers/clk/mediatek/clk-mt2712-vdec.c             |   94 ++
 drivers/clk/mediatek/clk-mt2712-venc.c             |   77 ++
 drivers/clk/mediatek/clk-mt2712.c                  | 1399 ++++++++++++++++++++
 drivers/clk/mediatek/clk-mtk.h                     |    2 +
 drivers/clk/mediatek/clk-pll.c                     |   13 +-
 drivers/soc/mediatek/mtk-infracfg.c                |   32 +-
 drivers/soc/mediatek/mtk-scpsys.c                  |  199 ++-
 include/dt-bindings/clock/mt2712-clk.h             |  427 ++++++
 include/dt-bindings/power/mt2712-power.h           |   26 +
 include/linux/soc/mediatek/infracfg.h              |   12 +-
 31 files changed, 3013 insertions(+), 38 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,jpgdecsys.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt
 create mode 100644 drivers/clk/mediatek/clk-mt2712-bdp.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712-img.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712-jpgdec.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712-mfg.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712-mm.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712-vdec.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712-venc.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712.c
 create mode 100644 include/dt-bindings/clock/mt2712-clk.h
 create mode 100644 include/dt-bindings/power/mt2712-power.h

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/9] dt-bindings: ARM: Mediatek: Document bindings for MT2712
  2017-08-22 10:28 [PATCH v2 0/9] Mediatek MT2712 clock and scpsys support Weiyi Lu
@ 2017-08-22 10:28 ` Weiyi Lu
  2017-08-22 10:28 ` [PATCH 2/9] clk: mediatek: Add dt-bindings for MT2712 clocks Weiyi Lu
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Weiyi Lu @ 2017-08-22 10:28 UTC (permalink / raw)
  To: Matthias Brugger, Stephen Boyd, Rob Herring
  Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu

This patch adds the binding documentation for apmixedsys, bdpsys,
imgsys, imgsys, infracfg, mcucfg, mfgcfg, mmsys, pericfg, topckgen,
vdecsys and vencsys for Mediatek MT2712.

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 .../bindings/arm/mediatek/mediatek,apmixedsys.txt  |  1 +
 .../bindings/arm/mediatek/mediatek,bdpsys.txt      |  1 +
 .../bindings/arm/mediatek/mediatek,imgsys.txt      |  1 +
 .../bindings/arm/mediatek/mediatek,infracfg.txt    |  1 +
 .../bindings/arm/mediatek/mediatek,jpgdecsys.txt   | 22 ++++++++++++++++++++++
 .../bindings/arm/mediatek/mediatek,mcucfg.txt      | 22 ++++++++++++++++++++++
 .../bindings/arm/mediatek/mediatek,mfgcfg.txt      | 22 ++++++++++++++++++++++
 .../bindings/arm/mediatek/mediatek,mmsys.txt       |  1 +
 .../bindings/arm/mediatek/mediatek,pericfg.txt     |  1 +
 .../bindings/arm/mediatek/mediatek,topckgen.txt    |  1 +
 .../bindings/arm/mediatek/mediatek,vdecsys.txt     |  1 +
 .../bindings/arm/mediatek/mediatek,vencsys.txt     |  1 +
 12 files changed, 75 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,jpgdecsys.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt

diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
index cd977db..19fc116 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: Should be one of:
 	- "mediatek,mt2701-apmixedsys"
+	- "mediatek,mt2712-apmixedsys", "syscon"
 	- "mediatek,mt6797-apmixedsys"
 	- "mediatek,mt8135-apmixedsys"
 	- "mediatek,mt8173-apmixedsys"
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt
index 4137196..4010e37 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: Should be:
 	- "mediatek,mt2701-bdpsys", "syscon"
+	- "mediatek,mt2712-bdpsys", "syscon"
 - #clock-cells: Must be 1
 
 The bdpsys controller uses the common clk binding from
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
index 047b11a..868bd51 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: Should be one of:
 	- "mediatek,mt2701-imgsys", "syscon"
+	- "mediatek,mt2712-imgsys", "syscon"
 	- "mediatek,mt6797-imgsys", "syscon"
 	- "mediatek,mt8173-imgsys", "syscon"
 - #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
index 58d58e2..a3430cd 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
@@ -8,6 +8,7 @@ Required Properties:
 
 - compatible: Should be one of:
 	- "mediatek,mt2701-infracfg", "syscon"
+	- "mediatek,mt2712-infracfg", "syscon"
 	- "mediatek,mt6797-infracfg", "syscon"
 	- "mediatek,mt8135-infracfg", "syscon"
 	- "mediatek,mt8173-infracfg", "syscon"
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,jpgdecsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,jpgdecsys.txt
new file mode 100644
index 0000000..2df799c
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,jpgdecsys.txt
@@ -0,0 +1,22 @@
+Mediatek jpgdecsys controller
+============================
+
+The Mediatek jpgdecsys controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt2712-jpgdecsys", "syscon"
+- #clock-cells: Must be 1
+
+The jpgdecsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+jpgdecsys: syscon@19000000 {
+	compatible = "mediatek,mt2712-jpgdecsys", "syscon";
+	reg = <0 0x19000000 0 0x1000>;
+	#clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt
new file mode 100644
index 0000000..b8fb03f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt
@@ -0,0 +1,22 @@
+Mediatek mcucfg controller
+============================
+
+The Mediatek mcucfg controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be one of:
+	- "mediatek,mt2712-mcucfg", "syscon"
+- #clock-cells: Must be 1
+
+The mcucfg controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+mcucfg: syscon@10220000 {
+	compatible = "mediatek,mt2712-mcucfg", "syscon";
+	reg = <0 0x10220000 0 0x1000>;
+	#clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt
new file mode 100644
index 0000000..859e67b
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt
@@ -0,0 +1,22 @@
+Mediatek mfgcfg controller
+============================
+
+The Mediatek mfgcfg controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be one of:
+	- "mediatek,mt2712-mfgcfg", "syscon"
+- #clock-cells: Must be 1
+
+The mfgcfg controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+mfgcfg: syscon@13000000 {
+	compatible = "mediatek,mt2712-mfgcfg", "syscon";
+	reg = <0 0x13000000 0 0x1000>;
+	#clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
index 70529e0..4eb8bbe 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: Should be one of:
 	- "mediatek,mt2701-mmsys", "syscon"
+	- "mediatek,mt2712-mmsys", "syscon"
 	- "mediatek,mt6797-mmsys", "syscon"
 	- "mediatek,mt8173-mmsys", "syscon"
 - #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
index e494366..d9f092e 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
@@ -8,6 +8,7 @@ Required Properties:
 
 - compatible: Should be one of:
 	- "mediatek,mt2701-pericfg", "syscon"
+	- "mediatek,mt2712-pericfg", "syscon"
 	- "mediatek,mt8135-pericfg", "syscon"
 	- "mediatek,mt8173-pericfg", "syscon"
 - #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
index ec93ecb..2024fc9 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: Should be one of:
 	- "mediatek,mt2701-topckgen"
+	- "mediatek,mt2712-topckgen", "syscon"
 	- "mediatek,mt6797-topckgen"
 	- "mediatek,mt8135-topckgen"
 	- "mediatek,mt8173-topckgen"
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
index d150104..ea40d05 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: Should be one of:
 	- "mediatek,mt2701-vdecsys", "syscon"
+	- "mediatek,mt2712-vdecsys", "syscon"
 	- "mediatek,mt6797-vdecsys", "syscon"
 	- "mediatek,mt8173-vdecsys", "syscon"
 - #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt
index 8a93be6..8515453 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt
@@ -6,6 +6,7 @@ The Mediatek vencsys controller provides various clocks to the system.
 Required Properties:
 
 - compatible: Should be one of:
+	- "mediatek,mt2712-vencsys", "syscon"
 	- "mediatek,mt6797-vencsys", "syscon"
 	- "mediatek,mt8173-vencsys", "syscon"
 - #clock-cells: Must be 1
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/9] clk: mediatek: Add dt-bindings for MT2712 clocks
  2017-08-22 10:28 [PATCH v2 0/9] Mediatek MT2712 clock and scpsys support Weiyi Lu
  2017-08-22 10:28 ` [PATCH 1/9] dt-bindings: ARM: Mediatek: Document bindings for MT2712 Weiyi Lu
@ 2017-08-22 10:28 ` Weiyi Lu
  2017-08-22 10:28 ` [PATCH 3/9] clk: mediatek: Add MT2712 clock support Weiyi Lu
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Weiyi Lu @ 2017-08-22 10:28 UTC (permalink / raw)
  To: Matthias Brugger, Stephen Boyd, Rob Herring
  Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu

Add MT2712 clock dt-bindings, include topckgen, apmixedsys,
infracfg, pericfg, mcucfg and subsystem clocks.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 include/dt-bindings/clock/mt2712-clk.h | 427 +++++++++++++++++++++++++++++++++
 1 file changed, 427 insertions(+)
 create mode 100644 include/dt-bindings/clock/mt2712-clk.h

diff --git a/include/dt-bindings/clock/mt2712-clk.h b/include/dt-bindings/clock/mt2712-clk.h
new file mode 100644
index 0000000..48a8e79
--- /dev/null
+++ b/include/dt-bindings/clock/mt2712-clk.h
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Weiyi Lu <weiyi.lu@mediatek.com>
+ *
+ * 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 _DT_BINDINGS_CLK_MT2712_H
+#define _DT_BINDINGS_CLK_MT2712_H
+
+/* APMIXEDSYS */
+
+#define CLK_APMIXED_MAINPLL		0
+#define CLK_APMIXED_UNIVPLL		1
+#define CLK_APMIXED_VCODECPLL		2
+#define CLK_APMIXED_VENCPLL		3
+#define CLK_APMIXED_APLL1		4
+#define CLK_APMIXED_APLL2		5
+#define CLK_APMIXED_LVDSPLL		6
+#define CLK_APMIXED_LVDSPLL2		7
+#define CLK_APMIXED_MSDCPLL		8
+#define CLK_APMIXED_MSDCPLL2		9
+#define CLK_APMIXED_TVDPLL		10
+#define CLK_APMIXED_MMPLL		11
+#define CLK_APMIXED_ARMCA35PLL		12
+#define CLK_APMIXED_ARMCA72PLL		13
+#define CLK_APMIXED_ETHERPLL		14
+#define CLK_APMIXED_NR_CLK		15
+
+/* TOPCKGEN */
+
+#define CLK_TOP_ARMCA35PLL		0
+#define CLK_TOP_ARMCA35PLL_600M		1
+#define CLK_TOP_ARMCA35PLL_400M		2
+#define CLK_TOP_ARMCA72PLL		3
+#define CLK_TOP_SYSPLL			4
+#define CLK_TOP_SYSPLL_D2		5
+#define CLK_TOP_SYSPLL1_D2		6
+#define CLK_TOP_SYSPLL1_D4		7
+#define CLK_TOP_SYSPLL1_D8		8
+#define CLK_TOP_SYSPLL1_D16		9
+#define CLK_TOP_SYSPLL_D3		10
+#define CLK_TOP_SYSPLL2_D2		11
+#define CLK_TOP_SYSPLL2_D4		12
+#define CLK_TOP_SYSPLL_D5		13
+#define CLK_TOP_SYSPLL3_D2		14
+#define CLK_TOP_SYSPLL3_D4		15
+#define CLK_TOP_SYSPLL_D7		16
+#define CLK_TOP_SYSPLL4_D2		17
+#define CLK_TOP_SYSPLL4_D4		18
+#define CLK_TOP_UNIVPLL			19
+#define CLK_TOP_UNIVPLL_D7		20
+#define CLK_TOP_UNIVPLL_D26		21
+#define CLK_TOP_UNIVPLL_D52		22
+#define CLK_TOP_UNIVPLL_D104		23
+#define CLK_TOP_UNIVPLL_D208		24
+#define CLK_TOP_UNIVPLL_D2		25
+#define CLK_TOP_UNIVPLL1_D2		26
+#define CLK_TOP_UNIVPLL1_D4		27
+#define CLK_TOP_UNIVPLL1_D8		28
+#define CLK_TOP_UNIVPLL_D3		29
+#define CLK_TOP_UNIVPLL2_D2		30
+#define CLK_TOP_UNIVPLL2_D4		31
+#define CLK_TOP_UNIVPLL2_D8		32
+#define CLK_TOP_UNIVPLL_D5		33
+#define CLK_TOP_UNIVPLL3_D2		34
+#define CLK_TOP_UNIVPLL3_D4		35
+#define CLK_TOP_UNIVPLL3_D8		36
+#define CLK_TOP_F_MP0_PLL1		37
+#define CLK_TOP_F_MP0_PLL2		38
+#define CLK_TOP_F_BIG_PLL1		39
+#define CLK_TOP_F_BIG_PLL2		40
+#define CLK_TOP_F_BUS_PLL1		41
+#define CLK_TOP_F_BUS_PLL2		42
+#define CLK_TOP_APLL1			43
+#define CLK_TOP_APLL1_D2		44
+#define CLK_TOP_APLL1_D4		45
+#define CLK_TOP_APLL1_D8		46
+#define CLK_TOP_APLL1_D16		47
+#define CLK_TOP_APLL2			48
+#define CLK_TOP_APLL2_D2		49
+#define CLK_TOP_APLL2_D4		50
+#define CLK_TOP_APLL2_D8		51
+#define CLK_TOP_APLL2_D16		52
+#define CLK_TOP_LVDSPLL			53
+#define CLK_TOP_LVDSPLL_D2		54
+#define CLK_TOP_LVDSPLL_D4		55
+#define CLK_TOP_LVDSPLL_D8		56
+#define CLK_TOP_LVDSPLL2		57
+#define CLK_TOP_LVDSPLL2_D2		58
+#define CLK_TOP_LVDSPLL2_D4		59
+#define CLK_TOP_LVDSPLL2_D8		60
+#define CLK_TOP_ETHERPLL_125M		61
+#define CLK_TOP_ETHERPLL_50M		62
+#define CLK_TOP_CVBS			63
+#define CLK_TOP_CVBS_D2			64
+#define CLK_TOP_SYS_26M			65
+#define CLK_TOP_MMPLL			66
+#define CLK_TOP_MMPLL_D2		67
+#define CLK_TOP_VENCPLL			68
+#define CLK_TOP_VENCPLL_D2		69
+#define CLK_TOP_VCODECPLL		70
+#define CLK_TOP_VCODECPLL_D2		71
+#define CLK_TOP_TVDPLL			72
+#define CLK_TOP_TVDPLL_D2		73
+#define CLK_TOP_TVDPLL_D4		74
+#define CLK_TOP_TVDPLL_D8		75
+#define CLK_TOP_TVDPLL_429M		76
+#define CLK_TOP_TVDPLL_429M_D2		77
+#define CLK_TOP_TVDPLL_429M_D4		78
+#define CLK_TOP_MSDCPLL			79
+#define CLK_TOP_MSDCPLL_D2		80
+#define CLK_TOP_MSDCPLL_D4		81
+#define CLK_TOP_MSDCPLL2		82
+#define CLK_TOP_MSDCPLL2_D2		83
+#define CLK_TOP_MSDCPLL2_D4		84
+#define CLK_TOP_CLK26M_D2		85
+#define CLK_TOP_D2A_ULCLK_6P5M		86
+#define CLK_TOP_VPLL3_DPIX		87
+#define CLK_TOP_VPLL_DPIX		88
+#define CLK_TOP_LTEPLL_FS26M		89
+#define CLK_TOP_DMPLL			90
+#define CLK_TOP_DSI0_LNTC		91
+#define CLK_TOP_DSI1_LNTC		92
+#define CLK_TOP_LVDSTX3_CLKDIG_CTS	93
+#define CLK_TOP_LVDSTX_CLKDIG_CTS	94
+#define CLK_TOP_CLKRTC_EXT		95
+#define CLK_TOP_CLKRTC_INT		96
+#define CLK_TOP_CSI0			97
+#define CLK_TOP_CVBSPLL			98
+#define CLK_TOP_AXI_SEL			99
+#define CLK_TOP_MEM_SEL			100
+#define CLK_TOP_MM_SEL			101
+#define CLK_TOP_PWM_SEL			102
+#define CLK_TOP_VDEC_SEL		103
+#define CLK_TOP_VENC_SEL		104
+#define CLK_TOP_MFG_SEL			105
+#define CLK_TOP_CAMTG_SEL		106
+#define CLK_TOP_UART_SEL		107
+#define CLK_TOP_SPI_SEL			108
+#define CLK_TOP_USB20_SEL		109
+#define CLK_TOP_USB30_SEL		110
+#define CLK_TOP_MSDC50_0_HCLK_SEL	111
+#define CLK_TOP_MSDC50_0_SEL		112
+#define CLK_TOP_MSDC30_1_SEL		113
+#define CLK_TOP_MSDC30_2_SEL		114
+#define CLK_TOP_MSDC30_3_SEL		115
+#define CLK_TOP_AUDIO_SEL		116
+#define CLK_TOP_AUD_INTBUS_SEL		117
+#define CLK_TOP_PMICSPI_SEL		118
+#define CLK_TOP_DPILVDS1_SEL		119
+#define CLK_TOP_ATB_SEL			120
+#define CLK_TOP_NR_SEL			121
+#define CLK_TOP_NFI2X_SEL		122
+#define CLK_TOP_IRDA_SEL		123
+#define CLK_TOP_CCI400_SEL		124
+#define CLK_TOP_AUD_1_SEL		125
+#define CLK_TOP_AUD_2_SEL		126
+#define CLK_TOP_MEM_MFG_IN_AS_SEL	127
+#define CLK_TOP_AXI_MFG_IN_AS_SEL	128
+#define CLK_TOP_SCAM_SEL		129
+#define CLK_TOP_NFIECC_SEL		130
+#define CLK_TOP_PE2_MAC_P0_SEL		131
+#define CLK_TOP_PE2_MAC_P1_SEL		132
+#define CLK_TOP_DPILVDS_SEL		133
+#define CLK_TOP_MSDC50_3_HCLK_SEL	134
+#define CLK_TOP_HDCP_SEL		135
+#define CLK_TOP_HDCP_24M_SEL		136
+#define CLK_TOP_RTC_SEL			137
+#define CLK_TOP_SPINOR_SEL		138
+#define CLK_TOP_APLL_SEL		139
+#define CLK_TOP_APLL2_SEL		140
+#define CLK_TOP_A1SYS_HP_SEL		141
+#define CLK_TOP_A2SYS_HP_SEL		142
+#define CLK_TOP_ASM_L_SEL		143
+#define CLK_TOP_ASM_M_SEL		144
+#define CLK_TOP_ASM_H_SEL		145
+#define CLK_TOP_I2SO1_SEL		146
+#define CLK_TOP_I2SO2_SEL		147
+#define CLK_TOP_I2SO3_SEL		148
+#define CLK_TOP_TDMO0_SEL		149
+#define CLK_TOP_TDMO1_SEL		150
+#define CLK_TOP_I2SI1_SEL		151
+#define CLK_TOP_I2SI2_SEL		152
+#define CLK_TOP_I2SI3_SEL		153
+#define CLK_TOP_ETHER_125M_SEL		154
+#define CLK_TOP_ETHER_50M_SEL		155
+#define CLK_TOP_JPGDEC_SEL		156
+#define CLK_TOP_SPISLV_SEL		157
+#define CLK_TOP_ETHER_50M_RMII_SEL	158
+#define CLK_TOP_CAM2TG_SEL		159
+#define CLK_TOP_DI_SEL			160
+#define CLK_TOP_TVD_SEL			161
+#define CLK_TOP_I2C_SEL			162
+#define CLK_TOP_PWM_INFRA_SEL		163
+#define CLK_TOP_MSDC0P_AES_SEL		164
+#define CLK_TOP_CMSYS_SEL		165
+#define CLK_TOP_GCPU_SEL		166
+#define CLK_TOP_AUD_APLL1_SEL		167
+#define CLK_TOP_AUD_APLL2_SEL		168
+#define CLK_TOP_DA_AUDULL_VTX_6P5M_SEL	169
+#define CLK_TOP_APLL_DIV0		170
+#define CLK_TOP_APLL_DIV1		171
+#define CLK_TOP_APLL_DIV2		172
+#define CLK_TOP_APLL_DIV3		173
+#define CLK_TOP_APLL_DIV4		174
+#define CLK_TOP_APLL_DIV5		175
+#define CLK_TOP_APLL_DIV6		176
+#define CLK_TOP_APLL_DIV7		177
+#define CLK_TOP_APLL_DIV_PDN0		178
+#define CLK_TOP_APLL_DIV_PDN1		179
+#define CLK_TOP_APLL_DIV_PDN2		180
+#define CLK_TOP_APLL_DIV_PDN3		181
+#define CLK_TOP_APLL_DIV_PDN4		182
+#define CLK_TOP_APLL_DIV_PDN5		183
+#define CLK_TOP_APLL_DIV_PDN6		184
+#define CLK_TOP_APLL_DIV_PDN7		185
+#define CLK_TOP_NR_CLK			186
+
+/* INFRACFG */
+
+#define CLK_INFRA_DBGCLK		0
+#define CLK_INFRA_GCE			1
+#define CLK_INFRA_M4U			2
+#define CLK_INFRA_KP			3
+#define CLK_INFRA_AO_SPI0		4
+#define CLK_INFRA_AO_SPI1		5
+#define CLK_INFRA_AO_UART5		6
+#define CLK_INFRA_NR_CLK		7
+
+/* PERICFG */
+
+#define CLK_PERI_NFI			0
+#define CLK_PERI_THERM			1
+#define CLK_PERI_PWM0			2
+#define CLK_PERI_PWM1			3
+#define CLK_PERI_PWM2			4
+#define CLK_PERI_PWM3			5
+#define CLK_PERI_PWM4			6
+#define CLK_PERI_PWM5			7
+#define CLK_PERI_PWM6			8
+#define CLK_PERI_PWM7			9
+#define CLK_PERI_PWM			10
+#define CLK_PERI_AP_DMA			11
+#define CLK_PERI_MSDC30_0		12
+#define CLK_PERI_MSDC30_1		13
+#define CLK_PERI_MSDC30_2		14
+#define CLK_PERI_MSDC30_3		15
+#define CLK_PERI_UART0			16
+#define CLK_PERI_UART1			17
+#define CLK_PERI_UART2			18
+#define CLK_PERI_UART3			19
+#define CLK_PERI_I2C0			20
+#define CLK_PERI_I2C1			21
+#define CLK_PERI_I2C2			22
+#define CLK_PERI_I2C3			23
+#define CLK_PERI_I2C4			24
+#define CLK_PERI_AUXADC			25
+#define CLK_PERI_SPI0			26
+#define CLK_PERI_SPI			27
+#define CLK_PERI_I2C5			28
+#define CLK_PERI_SPI2			29
+#define CLK_PERI_SPI3			30
+#define CLK_PERI_SPI5			31
+#define CLK_PERI_UART4			32
+#define CLK_PERI_SFLASH			33
+#define CLK_PERI_GMAC			34
+#define CLK_PERI_PCIE0			35
+#define CLK_PERI_PCIE1			36
+#define CLK_PERI_GMAC_PCLK		37
+#define CLK_PERI_MSDC50_0_EN		38
+#define CLK_PERI_MSDC30_1_EN		39
+#define CLK_PERI_MSDC30_2_EN		40
+#define CLK_PERI_MSDC30_3_EN		41
+#define CLK_PERI_MSDC50_0_HCLK_EN	42
+#define CLK_PERI_MSDC50_3_HCLK_EN	43
+#define CLK_PERI_NR_CLK			44
+
+/* MCUCFG */
+
+#define CLK_MCU_MP0_SEL			0
+#define CLK_MCU_MP2_SEL			1
+#define CLK_MCU_BUS_SEL			2
+#define CLK_MCU_NR_CLK			3
+
+/* MFGCFG */
+
+#define CLK_MFG_BG3D			0
+#define CLK_MFG_NR_CLK			1
+
+/* MMSYS */
+
+#define CLK_MM_SMI_COMMON		0
+#define CLK_MM_SMI_LARB0		1
+#define CLK_MM_CAM_MDP			2
+#define CLK_MM_MDP_RDMA0		3
+#define CLK_MM_MDP_RDMA1		4
+#define CLK_MM_MDP_RSZ0			5
+#define CLK_MM_MDP_RSZ1			6
+#define CLK_MM_MDP_RSZ2			7
+#define CLK_MM_MDP_TDSHP0		8
+#define CLK_MM_MDP_TDSHP1		9
+#define CLK_MM_MDP_CROP			10
+#define CLK_MM_MDP_WDMA			11
+#define CLK_MM_MDP_WROT0		12
+#define CLK_MM_MDP_WROT1		13
+#define CLK_MM_FAKE_ENG			14
+#define CLK_MM_MUTEX_32K		15
+#define CLK_MM_DISP_OVL0		16
+#define CLK_MM_DISP_OVL1		17
+#define CLK_MM_DISP_RDMA0		18
+#define CLK_MM_DISP_RDMA1		19
+#define CLK_MM_DISP_RDMA2		20
+#define CLK_MM_DISP_WDMA0		21
+#define CLK_MM_DISP_WDMA1		22
+#define CLK_MM_DISP_COLOR0		23
+#define CLK_MM_DISP_COLOR1		24
+#define CLK_MM_DISP_AAL			25
+#define CLK_MM_DISP_GAMMA		26
+#define CLK_MM_DISP_UFOE		27
+#define CLK_MM_DISP_SPLIT0		28
+#define CLK_MM_DISP_OD			29
+#define CLK_MM_DISP_PWM0_MM		30
+#define CLK_MM_DISP_PWM0_26M		31
+#define CLK_MM_DISP_PWM1_MM		32
+#define CLK_MM_DISP_PWM1_26M		33
+#define CLK_MM_DSI0_ENGINE		34
+#define CLK_MM_DSI0_DIGITAL		35
+#define CLK_MM_DSI1_ENGINE		36
+#define CLK_MM_DSI1_DIGITAL		37
+#define CLK_MM_DPI_PIXEL		38
+#define CLK_MM_DPI_ENGINE		39
+#define CLK_MM_DPI1_PIXEL		40
+#define CLK_MM_DPI1_ENGINE		41
+#define CLK_MM_LVDS_PIXEL		42
+#define CLK_MM_LVDS_CTS			43
+#define CLK_MM_SMI_LARB4		44
+#define CLK_MM_SMI_COMMON1		45
+#define CLK_MM_SMI_LARB5		46
+#define CLK_MM_MDP_RDMA2		47
+#define CLK_MM_MDP_TDSHP2		48
+#define CLK_MM_DISP_OVL2		49
+#define CLK_MM_DISP_WDMA2		50
+#define CLK_MM_DISP_COLOR2		51
+#define CLK_MM_DISP_AAL1		52
+#define CLK_MM_DISP_OD1			53
+#define CLK_MM_LVDS1_PIXEL		54
+#define CLK_MM_LVDS1_CTS		55
+#define CLK_MM_SMI_LARB7		56
+#define CLK_MM_MDP_RDMA3		57
+#define CLK_MM_MDP_WROT2		58
+#define CLK_MM_DSI2			59
+#define CLK_MM_DSI2_DIGITAL		60
+#define CLK_MM_DSI3			61
+#define CLK_MM_DSI3_DIGITAL		62
+#define CLK_MM_NR_CLK			63
+
+/* IMGSYS */
+
+#define CLK_IMG_SMI_LARB2		0
+#define CLK_IMG_SENINF_SCAM_EN		1
+#define CLK_IMG_SENINF_CAM_EN		2
+#define CLK_IMG_CAM_SV_EN		3
+#define CLK_IMG_CAM_SV1_EN		4
+#define CLK_IMG_CAM_SV2_EN		5
+#define CLK_IMG_NR_CLK			6
+
+/* BDPSYS */
+
+#define CLK_BDP_BRIDGE_B		0
+#define CLK_BDP_BRIDGE_DRAM		1
+#define CLK_BDP_LARB_DRAM		2
+#define CLK_BDP_WR_CHANNEL_VDI_PXL	3
+#define CLK_BDP_WR_CHANNEL_VDI_DRAM	4
+#define CLK_BDP_WR_CHANNEL_VDI_B	5
+#define CLK_BDP_MT_B			6
+#define CLK_BDP_DISPFMT_27M		7
+#define CLK_BDP_DISPFMT_27M_VDOUT	8
+#define CLK_BDP_DISPFMT_27_74_74	9
+#define CLK_BDP_DISPFMT_2FS		10
+#define CLK_BDP_DISPFMT_2FS_2FS74_148	11
+#define CLK_BDP_DISPFMT_B		12
+#define CLK_BDP_VDO_DRAM		13
+#define CLK_BDP_VDO_2FS			14
+#define CLK_BDP_VDO_B			15
+#define CLK_BDP_WR_CHANNEL_DI_PXL	16
+#define CLK_BDP_WR_CHANNEL_DI_DRAM	17
+#define CLK_BDP_WR_CHANNEL_DI_B		18
+#define CLK_BDP_NR_AGENT		19
+#define CLK_BDP_NR_DRAM			20
+#define CLK_BDP_NR_B			21
+#define CLK_BDP_BRIDGE_RT_B		22
+#define CLK_BDP_BRIDGE_RT_DRAM		23
+#define CLK_BDP_LARB_RT_DRAM		24
+#define CLK_BDP_TVD_TDC			25
+#define CLK_BDP_TVD_54			26
+#define CLK_BDP_TVD_CBUS		27
+#define CLK_BDP_NR_CLK			28
+
+/* VDECSYS */
+
+#define CLK_VDEC_CKEN			0
+#define CLK_VDEC_LARB1_CKEN		1
+#define CLK_VDEC_IMGRZ_CKEN		2
+#define CLK_VDEC_NR_CLK			3
+
+/* VENCSYS */
+
+#define CLK_VENC_SMI_COMMON_CON		0
+#define CLK_VENC_VENC			1
+#define CLK_VENC_SMI_LARB6		2
+#define CLK_VENC_NR_CLK			3
+
+/* JPGDECSYS */
+
+#define CLK_JPGDEC_JPGDEC1		0
+#define CLK_JPGDEC_JPGDEC		1
+#define CLK_JPGDEC_NR_CLK		2
+
+#endif /* _DT_BINDINGS_CLK_MT2712_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/9] clk: mediatek: Add MT2712 clock support
  2017-08-22 10:28 [PATCH v2 0/9] Mediatek MT2712 clock and scpsys support Weiyi Lu
  2017-08-22 10:28 ` [PATCH 1/9] dt-bindings: ARM: Mediatek: Document bindings for MT2712 Weiyi Lu
  2017-08-22 10:28 ` [PATCH 2/9] clk: mediatek: Add dt-bindings for MT2712 clocks Weiyi Lu
@ 2017-08-22 10:28 ` Weiyi Lu
  2017-08-22 10:28 ` [PATCH 4/9] arm: dts: mt2712: Add clock controller device nodes Weiyi Lu
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Weiyi Lu @ 2017-08-22 10:28 UTC (permalink / raw)
  To: Matthias Brugger, Stephen Boyd, Rob Herring
  Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu

Add MT2712 clock support, include topckgen, apmixedsys,
infracfg, pericfg, mcucfg and subsystem clocks.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/clk/mediatek/Kconfig             |   50 ++
 drivers/clk/mediatek/Makefile            |    8 +
 drivers/clk/mediatek/clk-mt2712-bdp.c    |  102 +++
 drivers/clk/mediatek/clk-mt2712-img.c    |   80 ++
 drivers/clk/mediatek/clk-mt2712-jpgdec.c |   76 ++
 drivers/clk/mediatek/clk-mt2712-mfg.c    |   75 ++
 drivers/clk/mediatek/clk-mt2712-mm.c     |  170 ++++
 drivers/clk/mediatek/clk-mt2712-vdec.c   |   94 ++
 drivers/clk/mediatek/clk-mt2712-venc.c   |   77 ++
 drivers/clk/mediatek/clk-mt2712.c        | 1399 ++++++++++++++++++++++++++++++
 drivers/clk/mediatek/clk-mtk.h           |    2 +
 drivers/clk/mediatek/clk-pll.c           |   13 +-
 12 files changed, 2144 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clk/mediatek/clk-mt2712-bdp.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712-img.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712-jpgdec.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712-mfg.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712-mm.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712-vdec.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712-venc.c
 create mode 100644 drivers/clk/mediatek/clk-mt2712.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 28739a9..300dbb5 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -50,6 +50,56 @@ config COMMON_CLK_MT2701_BDPSYS
 	---help---
 	  This driver supports Mediatek MT2701 bdpsys clocks.
 
+config COMMON_CLK_MT2712
+	bool "Clock driver for Mediatek MT2712"
+	depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
+	select COMMON_CLK_MEDIATEK
+	default ARCH_MEDIATEK && ARM64
+	---help---
+	  This driver supports Mediatek MT2712 basic clocks.
+
+config COMMON_CLK_MT2712_BDPSYS
+	bool "Clock driver for Mediatek MT2712 bdpsys"
+	depends on COMMON_CLK_MT2712
+	---help---
+	  This driver supports Mediatek MT2712 bdpsys clocks.
+
+config COMMON_CLK_MT2712_IMGSYS
+	bool "Clock driver for Mediatek MT2712 imgsys"
+	depends on COMMON_CLK_MT2712
+	---help---
+	  This driver supports Mediatek MT2712 imgsys clocks.
+
+config COMMON_CLK_MT2712_JPGDECSYS
+	bool "Clock driver for Mediatek MT2712 jpgdecsys"
+	depends on COMMON_CLK_MT2712
+	---help---
+	  This driver supports Mediatek MT2712 jpgdecsys clocks.
+
+config COMMON_CLK_MT2712_MFGCFG
+	bool "Clock driver for Mediatek MT2712 mfgcfg"
+	depends on COMMON_CLK_MT2712
+	---help---
+	  This driver supports Mediatek MT2712 mfgcfg clocks.
+
+config COMMON_CLK_MT2712_MMSYS
+	bool "Clock driver for Mediatek MT2712 mmsys"
+	depends on COMMON_CLK_MT2712
+	---help---
+	  This driver supports Mediatek MT2712 mmsys clocks.
+
+config COMMON_CLK_MT2712_VDECSYS
+	bool "Clock driver for Mediatek MT2712 vdecsys"
+	depends on COMMON_CLK_MT2712
+	---help---
+	  This driver supports Mediatek MT2712 vdecsys clocks.
+
+config COMMON_CLK_MT2712_VENCSYS
+	bool "Clock driver for Mediatek MT2712 vencsys"
+	depends on COMMON_CLK_MT2712
+	---help---
+	  This driver supports Mediatek MT2712 vencsys clocks.
+
 config COMMON_CLK_MT6797
        bool "Clock driver for Mediatek MT6797"
        depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 2a755b5..a4e5c47 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -12,5 +12,13 @@ obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o
 obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o
 obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o
 obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o
+obj-$(CONFIG_COMMON_CLK_MT2712) += clk-mt2712.o
+obj-$(CONFIG_COMMON_CLK_MT2712_BDPSYS) += clk-mt2712-bdp.o
+obj-$(CONFIG_COMMON_CLK_MT2712_IMGSYS) += clk-mt2712-img.o
+obj-$(CONFIG_COMMON_CLK_MT2712_JPGDECSYS) += clk-mt2712-jpgdec.o
+obj-$(CONFIG_COMMON_CLK_MT2712_MFGCFG) += clk-mt2712-mfg.o
+obj-$(CONFIG_COMMON_CLK_MT2712_MMSYS) += clk-mt2712-mm.o
+obj-$(CONFIG_COMMON_CLK_MT2712_VDECSYS) += clk-mt2712-vdec.o
+obj-$(CONFIG_COMMON_CLK_MT2712_VENCSYS) += clk-mt2712-venc.o
 obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
 obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
diff --git a/drivers/clk/mediatek/clk-mt2712-bdp.c b/drivers/clk/mediatek/clk-mt2712-bdp.c
new file mode 100644
index 0000000..5fe4728
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2712-bdp.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Weiyi Lu <weiyi.lu@mediatek.com>
+ *
+ * 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-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2712-clk.h>
+
+static const struct mtk_gate_regs bdp_cg_regs = {
+	.set_ofs = 0x100,
+	.clr_ofs = 0x100,
+	.sta_ofs = 0x100,
+};
+
+#define GATE_BDP(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &bdp_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_no_setclr,	\
+	}
+
+static const struct mtk_gate bdp_clks[] = {
+	GATE_BDP(CLK_BDP_BRIDGE_B, "bdp_bridge_b", "mm_sel", 0),
+	GATE_BDP(CLK_BDP_BRIDGE_DRAM, "bdp_bridge_d", "mm_sel", 1),
+	GATE_BDP(CLK_BDP_LARB_DRAM, "bdp_larb_d", "mm_sel", 2),
+	GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_PXL, "bdp_vdi_pxl", "tvd_sel", 3),
+	GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_DRAM, "bdp_vdi_d", "mm_sel", 4),
+	GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_B, "bdp_vdi_b", "mm_sel", 5),
+	GATE_BDP(CLK_BDP_MT_B, "bdp_fmt_b", "mm_sel", 9),
+	GATE_BDP(CLK_BDP_DISPFMT_27M, "bdp_27m", "di_sel", 10),
+	GATE_BDP(CLK_BDP_DISPFMT_27M_VDOUT, "bdp_27m_vdout", "di_sel", 11),
+	GATE_BDP(CLK_BDP_DISPFMT_27_74_74, "bdp_27_74_74", "di_sel", 12),
+	GATE_BDP(CLK_BDP_DISPFMT_2FS, "bdp_2fs", "di_sel", 13),
+	GATE_BDP(CLK_BDP_DISPFMT_2FS_2FS74_148, "bdp_2fs74_148", "di_sel", 14),
+	GATE_BDP(CLK_BDP_DISPFMT_B, "bdp_b", "mm_sel", 15),
+	GATE_BDP(CLK_BDP_VDO_DRAM, "bdp_vdo_d", "mm_sel", 16),
+	GATE_BDP(CLK_BDP_VDO_2FS, "bdp_vdo_2fs", "di_sel", 17),
+	GATE_BDP(CLK_BDP_VDO_B, "bdp_vdo_b", "mm_sel", 18),
+	GATE_BDP(CLK_BDP_WR_CHANNEL_DI_PXL, "bdp_di_pxl", "di_sel", 19),
+	GATE_BDP(CLK_BDP_WR_CHANNEL_DI_DRAM, "bdp_di_d", "mm_sel", 20),
+	GATE_BDP(CLK_BDP_WR_CHANNEL_DI_B, "bdp_di_b", "mm_sel", 21),
+	GATE_BDP(CLK_BDP_NR_AGENT, "bdp_nr_agent", "nr_sel", 22),
+	GATE_BDP(CLK_BDP_NR_DRAM, "bdp_nr_d", "mm_sel", 23),
+	GATE_BDP(CLK_BDP_NR_B, "bdp_nr_b", "mm_sel", 24),
+	GATE_BDP(CLK_BDP_BRIDGE_RT_B, "bdp_bridge_rt_b", "mm_sel", 25),
+	GATE_BDP(CLK_BDP_BRIDGE_RT_DRAM, "bdp_bridge_rt_d", "mm_sel", 26),
+	GATE_BDP(CLK_BDP_LARB_RT_DRAM, "bdp_larb_rt_d", "mm_sel", 27),
+	GATE_BDP(CLK_BDP_TVD_TDC, "bdp_tvd_tdc", "mm_sel", 28),
+	GATE_BDP(CLK_BDP_TVD_54, "bdp_tvd_clk_54", "tvd_sel", 29),
+	GATE_BDP(CLK_BDP_TVD_CBUS, "bdp_tvd_cbus", "mm_sel", 30),
+};
+
+static int clk_mt2712_bdp_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_BDP_NR_CLK);
+
+	mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
+			clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r != 0)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2712_bdp[] = {
+	{ .compatible = "mediatek,mt2712-bdpsys", },
+	{}
+};
+
+static struct platform_driver clk_mt2712_bdp_drv = {
+	.probe = clk_mt2712_bdp_probe,
+	.driver = {
+		.name = "clk-mt2712-bdp",
+		.of_match_table = of_match_clk_mt2712_bdp,
+	},
+};
+
+builtin_platform_driver(clk_mt2712_bdp_drv);
diff --git a/drivers/clk/mediatek/clk-mt2712-img.c b/drivers/clk/mediatek/clk-mt2712-img.c
new file mode 100644
index 0000000..139ff55
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2712-img.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Weiyi Lu <weiyi.lu@mediatek.com>
+ *
+ * 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-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2712-clk.h>
+
+static const struct mtk_gate_regs img_cg_regs = {
+	.set_ofs = 0x0,
+	.clr_ofs = 0x0,
+	.sta_ofs = 0x0,
+};
+
+#define GATE_IMG(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &img_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_no_setclr,	\
+	}
+
+static const struct mtk_gate img_clks[] = {
+	GATE_IMG(CLK_IMG_SMI_LARB2, "img_smi_larb2", "mm_sel", 0),
+	GATE_IMG(CLK_IMG_SENINF_SCAM_EN, "img_scam_en", "csi0", 3),
+	GATE_IMG(CLK_IMG_SENINF_CAM_EN, "img_cam_en", "mm_sel", 8),
+	GATE_IMG(CLK_IMG_CAM_SV_EN, "img_cam_sv_en", "mm_sel", 9),
+	GATE_IMG(CLK_IMG_CAM_SV1_EN, "img_cam_sv1_en", "mm_sel", 10),
+	GATE_IMG(CLK_IMG_CAM_SV2_EN, "img_cam_sv2_en", "mm_sel", 11),
+};
+
+static int clk_mt2712_img_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK);
+
+	mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
+			clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r != 0)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2712_img[] = {
+	{ .compatible = "mediatek,mt2712-imgsys", },
+	{}
+};
+
+static struct platform_driver clk_mt2712_img_drv = {
+	.probe = clk_mt2712_img_probe,
+	.driver = {
+		.name = "clk-mt2712-img",
+		.of_match_table = of_match_clk_mt2712_img,
+	},
+};
+
+builtin_platform_driver(clk_mt2712_img_drv);
diff --git a/drivers/clk/mediatek/clk-mt2712-jpgdec.c b/drivers/clk/mediatek/clk-mt2712-jpgdec.c
new file mode 100644
index 0000000..c7d4aad
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2712-jpgdec.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Weiyi Lu <weiyi.lu@mediatek.com>
+ *
+ * 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-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2712-clk.h>
+
+static const struct mtk_gate_regs jpgdec_cg_regs = {
+	.set_ofs = 0x4,
+	.clr_ofs = 0x8,
+	.sta_ofs = 0x0,
+};
+
+#define GATE_JPGDEC(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &jpgdec_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+static const struct mtk_gate jpgdec_clks[] = {
+	GATE_JPGDEC(CLK_JPGDEC_JPGDEC1, "jpgdec_jpgdec1", "jpgdec_sel", 0),
+	GATE_JPGDEC(CLK_JPGDEC_JPGDEC, "jpgdec_jpgdec", "jpgdec_sel", 4),
+};
+
+static int clk_mt2712_jpgdec_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_JPGDEC_NR_CLK);
+
+	mtk_clk_register_gates(node, jpgdec_clks, ARRAY_SIZE(jpgdec_clks),
+			clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r != 0)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2712_jpgdec[] = {
+	{ .compatible = "mediatek,mt2712-jpgdecsys", },
+	{}
+};
+
+static struct platform_driver clk_mt2712_jpgdec_drv = {
+	.probe = clk_mt2712_jpgdec_probe,
+	.driver = {
+		.name = "clk-mt2712-jpgdec",
+		.of_match_table = of_match_clk_mt2712_jpgdec,
+	},
+};
+
+builtin_platform_driver(clk_mt2712_jpgdec_drv);
diff --git a/drivers/clk/mediatek/clk-mt2712-mfg.c b/drivers/clk/mediatek/clk-mt2712-mfg.c
new file mode 100644
index 0000000..570f72d
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2712-mfg.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Weiyi Lu <weiyi.lu@mediatek.com>
+ *
+ * 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-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2712-clk.h>
+
+static const struct mtk_gate_regs mfg_cg_regs = {
+	.set_ofs = 0x4,
+	.clr_ofs = 0x8,
+	.sta_ofs = 0x0,
+};
+
+#define GATE_MFG(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &mfg_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate mfg_clks[] = {
+	GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_sel", 0),
+};
+
+static int clk_mt2712_mfg_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK);
+
+	mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks),
+			clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r != 0)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2712_mfg[] = {
+	{ .compatible = "mediatek,mt2712-mfgcfg", },
+	{}
+};
+
+static struct platform_driver clk_mt2712_mfg_drv = {
+	.probe = clk_mt2712_mfg_probe,
+	.driver = {
+		.name = "clk-mt2712-mfg",
+		.of_match_table = of_match_clk_mt2712_mfg,
+	},
+};
+
+builtin_platform_driver(clk_mt2712_mfg_drv);
diff --git a/drivers/clk/mediatek/clk-mt2712-mm.c b/drivers/clk/mediatek/clk-mt2712-mm.c
new file mode 100644
index 0000000..a8b4b6d
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2712-mm.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Weiyi Lu <weiyi.lu@mediatek.com>
+ *
+ * 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-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2712-clk.h>
+
+static const struct mtk_gate_regs mm0_cg_regs = {
+	.set_ofs = 0x104,
+	.clr_ofs = 0x108,
+	.sta_ofs = 0x100,
+};
+
+static const struct mtk_gate_regs mm1_cg_regs = {
+	.set_ofs = 0x114,
+	.clr_ofs = 0x118,
+	.sta_ofs = 0x110,
+};
+
+static const struct mtk_gate_regs mm2_cg_regs = {
+	.set_ofs = 0x224,
+	.clr_ofs = 0x228,
+	.sta_ofs = 0x220,
+};
+
+#define GATE_MM0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &mm0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_MM1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &mm1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_MM2(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &mm2_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate mm_clks[] = {
+	/* MM0 */
+	GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0),
+	GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
+	GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 2),
+	GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 3),
+	GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 4),
+	GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 5),
+	GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 6),
+	GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 7),
+	GATE_MM0(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_sel", 8),
+	GATE_MM0(CLK_MM_MDP_TDSHP1, "mm_mdp_tdshp1", "mm_sel", 9),
+	GATE_MM0(CLK_MM_MDP_CROP, "mm_mdp_crop", "mm_sel", 10),
+	GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
+	GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12),
+	GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13),
+	GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14),
+	GATE_MM0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "clk32k", 15),
+	GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 16),
+	GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 17),
+	GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 18),
+	GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19),
+	GATE_MM0(CLK_MM_DISP_RDMA2, "mm_disp_rdma2", "mm_sel", 20),
+	GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21),
+	GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22),
+	GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 23),
+	GATE_MM0(CLK_MM_DISP_COLOR1, "mm_disp_color1", "mm_sel", 24),
+	GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25),
+	GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26),
+	GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 27),
+	GATE_MM0(CLK_MM_DISP_SPLIT0, "mm_disp_split0", "mm_sel", 28),
+	GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 31),
+	/* MM1 */
+	GATE_MM1(CLK_MM_DISP_PWM0_MM, "mm_pwm0_mm", "mm_sel", 0),
+	GATE_MM1(CLK_MM_DISP_PWM0_26M, "mm_pwm0_26m", "pwm_sel", 1),
+	GATE_MM1(CLK_MM_DISP_PWM1_MM, "mm_pwm1_mm", "mm_sel", 2),
+	GATE_MM1(CLK_MM_DISP_PWM1_26M, "mm_pwm1_26m", "pwm_sel", 3),
+	GATE_MM1(CLK_MM_DSI0_ENGINE, "mm_dsi0_engine", "mm_sel", 4),
+	GATE_MM1(CLK_MM_DSI0_DIGITAL, "mm_dsi0_digital", "dsi0_lntc", 5),
+	GATE_MM1(CLK_MM_DSI1_ENGINE, "mm_dsi1_engine", "mm_sel", 6),
+	GATE_MM1(CLK_MM_DSI1_DIGITAL, "mm_dsi1_digital", "dsi1_lntc", 7),
+	GATE_MM1(CLK_MM_DPI_PIXEL, "mm_dpi_pixel", "vpll_dpix", 8),
+	GATE_MM1(CLK_MM_DPI_ENGINE, "mm_dpi_engine", "mm_sel", 9),
+	GATE_MM1(CLK_MM_DPI1_PIXEL, "mm_dpi1_pixel", "vpll3_dpix", 10),
+	GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "mm_sel", 11),
+	GATE_MM1(CLK_MM_LVDS_PIXEL, "mm_lvds_pixel", "vpll_dpix", 16),
+	GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "lvdstx", 17),
+	GATE_MM1(CLK_MM_SMI_LARB4, "mm_smi_larb4", "mm_sel", 18),
+	GATE_MM1(CLK_MM_SMI_COMMON1, "mm_smi_common1", "mm_sel", 21),
+	GATE_MM1(CLK_MM_SMI_LARB5, "mm_smi_larb5", "mm_sel", 22),
+	GATE_MM1(CLK_MM_MDP_RDMA2, "mm_mdp_rdma2", "mm_sel", 23),
+	GATE_MM1(CLK_MM_MDP_TDSHP2, "mm_mdp_tdshp2", "mm_sel", 24),
+	GATE_MM1(CLK_MM_DISP_OVL2, "mm_disp_ovl2", "mm_sel", 25),
+	GATE_MM1(CLK_MM_DISP_WDMA2, "mm_disp_wdma2", "mm_sel", 26),
+	GATE_MM1(CLK_MM_DISP_COLOR2, "mm_disp_color2", "mm_sel", 27),
+	GATE_MM1(CLK_MM_DISP_AAL1, "mm_disp_aal1", "mm_sel", 28),
+	GATE_MM1(CLK_MM_DISP_OD1, "mm_disp_od1", "mm_sel", 29),
+	GATE_MM1(CLK_MM_LVDS1_PIXEL, "mm_lvds1_pixel", "vpll3_dpix", 30),
+	GATE_MM1(CLK_MM_LVDS1_CTS, "mm_lvds1_cts", "lvdstx3", 31),
+	/* MM2 */
+	GATE_MM2(CLK_MM_SMI_LARB7, "mm_smi_larb7", "mm_sel", 0),
+	GATE_MM2(CLK_MM_MDP_RDMA3, "mm_mdp_rdma3", "mm_sel", 1),
+	GATE_MM2(CLK_MM_MDP_WROT2, "mm_mdp_wrot2", "mm_sel", 2),
+	GATE_MM2(CLK_MM_DSI2, "mm_dsi2", "mm_sel", 3),
+	GATE_MM2(CLK_MM_DSI2_DIGITAL, "mm_dsi2_digital", "dsi0_lntc", 4),
+	GATE_MM2(CLK_MM_DSI3, "mm_dsi3", "mm_sel", 5),
+	GATE_MM2(CLK_MM_DSI3_DIGITAL, "mm_dsi3_digital", "dsi1_lntc", 6),
+};
+
+static int clk_mt2712_mm_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
+
+	mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
+			clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r != 0)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2712_mm[] = {
+	{ .compatible = "mediatek,mt2712-mmsys", },
+	{}
+};
+
+static struct platform_driver clk_mt2712_mm_drv = {
+	.probe = clk_mt2712_mm_probe,
+	.driver = {
+		.name = "clk-mt2712-mm",
+		.of_match_table = of_match_clk_mt2712_mm,
+	},
+};
+
+builtin_platform_driver(clk_mt2712_mm_drv);
diff --git a/drivers/clk/mediatek/clk-mt2712-vdec.c b/drivers/clk/mediatek/clk-mt2712-vdec.c
new file mode 100644
index 0000000..55c64ee
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2712-vdec.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Weiyi Lu <weiyi.lu@mediatek.com>
+ *
+ * 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-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2712-clk.h>
+
+static const struct mtk_gate_regs vdec0_cg_regs = {
+	.set_ofs = 0x0,
+	.clr_ofs = 0x4,
+	.sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs vdec1_cg_regs = {
+	.set_ofs = 0x8,
+	.clr_ofs = 0xc,
+	.sta_ofs = 0x8,
+};
+
+#define GATE_VDEC0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vdec0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_VDEC1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vdec1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+static const struct mtk_gate vdec_clks[] = {
+	/* VDEC0 */
+	GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0),
+	/* VDEC1 */
+	GATE_VDEC1(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "vdec_sel", 0),
+	GATE_VDEC1(CLK_VDEC_IMGRZ_CKEN, "vdec_imgrz_cken", "vdec_sel", 1),
+};
+
+static int clk_mt2712_vdec_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK);
+
+	mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
+			clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r != 0)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2712_vdec[] = {
+	{ .compatible = "mediatek,mt2712-vdecsys", },
+	{}
+};
+
+static struct platform_driver clk_mt2712_vdec_drv = {
+	.probe = clk_mt2712_vdec_probe,
+	.driver = {
+		.name = "clk-mt2712-vdec",
+		.of_match_table = of_match_clk_mt2712_vdec,
+	},
+};
+
+builtin_platform_driver(clk_mt2712_vdec_drv);
diff --git a/drivers/clk/mediatek/clk-mt2712-venc.c b/drivers/clk/mediatek/clk-mt2712-venc.c
new file mode 100644
index 0000000..ccbfe98
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2712-venc.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Weiyi Lu <weiyi.lu@mediatek.com>
+ *
+ * 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-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2712-clk.h>
+
+static const struct mtk_gate_regs venc_cg_regs = {
+	.set_ofs = 0x4,
+	.clr_ofs = 0x8,
+	.sta_ofs = 0x0,
+};
+
+#define GATE_VENC(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &venc_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+static const struct mtk_gate venc_clks[] = {
+	GATE_VENC(CLK_VENC_SMI_COMMON_CON, "venc_smi", "mm_sel", 0),
+	GATE_VENC(CLK_VENC_VENC, "venc_venc", "venc_sel", 4),
+	GATE_VENC(CLK_VENC_SMI_LARB6, "venc_smi_larb6", "jpgdec_sel", 12),
+};
+
+static int clk_mt2712_venc_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK);
+
+	mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
+			clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r != 0)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2712_venc[] = {
+	{ .compatible = "mediatek,mt2712-vencsys", },
+	{}
+};
+
+static struct platform_driver clk_mt2712_venc_drv = {
+	.probe = clk_mt2712_venc_probe,
+	.driver = {
+		.name = "clk-mt2712-venc",
+		.of_match_table = of_match_clk_mt2712_venc,
+	},
+};
+
+builtin_platform_driver(clk_mt2712_venc_drv);
diff --git a/drivers/clk/mediatek/clk-mt2712.c b/drivers/clk/mediatek/clk-mt2712.c
new file mode 100644
index 0000000..1c9e5d1
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2712.c
@@ -0,0 +1,1399 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Weiyi Lu <weiyi.lu@mediatek.com>
+ *
+ * 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/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2712-clk.h>
+
+static DEFINE_SPINLOCK(mt2712_clk_lock);
+
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+	FIXED_CLK(CLK_TOP_VPLL3_DPIX, "vpll3_dpix", NULL, 200000000),
+	FIXED_CLK(CLK_TOP_VPLL_DPIX, "vpll_dpix", NULL, 200000000),
+	FIXED_CLK(CLK_TOP_LTEPLL_FS26M, "ltepll_fs26m", NULL, 26000000),
+	FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", NULL, 350000000),
+	FIXED_CLK(CLK_TOP_DSI0_LNTC, "dsi0_lntc", NULL, 143000000),
+	FIXED_CLK(CLK_TOP_DSI1_LNTC, "dsi1_lntc", NULL, 143000000),
+	FIXED_CLK(CLK_TOP_LVDSTX3_CLKDIG_CTS, "lvdstx3", NULL, 140000000),
+	FIXED_CLK(CLK_TOP_LVDSTX_CLKDIG_CTS, "lvdstx", NULL, 140000000),
+	FIXED_CLK(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", NULL, 32000),
+	FIXED_CLK(CLK_TOP_CLKRTC_INT, "clkrtc_int", NULL, 32000),
+	FIXED_CLK(CLK_TOP_CSI0, "csi0", NULL, 26000000),
+	FIXED_CLK(CLK_TOP_CVBSPLL, "cvbspll", NULL, 108000000),
+};
+
+static const struct mtk_fixed_factor top_divs[] = {
+	FACTOR(CLK_TOP_ARMCA35PLL, "armca35pll_ck", "armca35pll", 1,
+		1),
+	FACTOR(CLK_TOP_ARMCA35PLL_600M, "armca35pll_600m", "armca35pll_ck", 1,
+		2),
+	FACTOR(CLK_TOP_ARMCA35PLL_400M, "armca35pll_400m", "armca35pll_ck", 1,
+		3),
+	FACTOR(CLK_TOP_ARMCA72PLL, "armca72pll_ck", "armca72pll", 1,
+		1),
+	FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1,
+		1),
+	FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "syspll_ck", 1,
+		2),
+	FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1,
+		2),
+	FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1,
+		4),
+	FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1,
+		8),
+	FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1,
+		16),
+	FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "syspll_ck", 1,
+		3),
+	FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1,
+		2),
+	FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1,
+		4),
+	FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "syspll_ck", 1,
+		5),
+	FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1,
+		2),
+	FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1,
+		4),
+	FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "syspll_ck", 1,
+		7),
+	FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1,
+		2),
+	FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1,
+		4),
+	FACTOR(CLK_TOP_UNIVPLL, "univpll_ck", "univpll", 1,
+		1),
+	FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_ck", 1,
+		7),
+	FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_ck", 1,
+		26),
+	FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univpll_ck", 1,
+		52),
+	FACTOR(CLK_TOP_UNIVPLL_D104, "univpll_d104", "univpll_ck", 1,
+		104),
+	FACTOR(CLK_TOP_UNIVPLL_D208, "univpll_d208", "univpll_ck", 1,
+		208),
+	FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll_ck", 1,
+		2),
+	FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1,
+		2),
+	FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1,
+		4),
+	FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1,
+		8),
+	FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_ck", 1,
+		3),
+	FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1,
+		2),
+	FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1,
+		4),
+	FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1,
+		8),
+	FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_ck", 1,
+		5),
+	FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1,
+		2),
+	FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1,
+		4),
+	FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1,
+		8),
+	FACTOR(CLK_TOP_F_MP0_PLL1, "f_mp0_pll1_ck", "univpll_d2", 1,
+		1),
+	FACTOR(CLK_TOP_F_MP0_PLL2, "f_mp0_pll2_ck", "univpll1_d2", 1,
+		1),
+	FACTOR(CLK_TOP_F_BIG_PLL1, "f_big_pll1_ck", "univpll_d2", 1,
+		1),
+	FACTOR(CLK_TOP_F_BIG_PLL2, "f_big_pll2_ck", "univpll1_d2", 1,
+		1),
+	FACTOR(CLK_TOP_F_BUS_PLL1, "f_bus_pll1_ck", "univpll_d2", 1,
+		1),
+	FACTOR(CLK_TOP_F_BUS_PLL2, "f_bus_pll2_ck", "univpll1_d2", 1,
+		1),
+	FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1,
+		1),
+	FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1_ck", 1,
+		2),
+	FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1_ck", 1,
+		4),
+	FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1_ck", 1,
+		8),
+	FACTOR(CLK_TOP_APLL1_D16, "apll1_d16", "apll1_ck", 1,
+		16),
+	FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1,
+		1),
+	FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2_ck", 1,
+		2),
+	FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2_ck", 1,
+		4),
+	FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2_ck", 1,
+		8),
+	FACTOR(CLK_TOP_APLL2_D16, "apll2_d16", "apll2_ck", 1,
+		16),
+	FACTOR(CLK_TOP_LVDSPLL, "lvdspll_ck", "lvdspll", 1,
+		1),
+	FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll_ck", 1,
+		2),
+	FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll_ck", 1,
+		4),
+	FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll_ck", 1,
+		8),
+	FACTOR(CLK_TOP_LVDSPLL2, "lvdspll2_ck", "lvdspll2", 1,
+		1),
+	FACTOR(CLK_TOP_LVDSPLL2_D2, "lvdspll2_d2", "lvdspll2_ck", 1,
+		2),
+	FACTOR(CLK_TOP_LVDSPLL2_D4, "lvdspll2_d4", "lvdspll2_ck", 1,
+		4),
+	FACTOR(CLK_TOP_LVDSPLL2_D8, "lvdspll2_d8", "lvdspll2_ck", 1,
+		8),
+	FACTOR(CLK_TOP_ETHERPLL_125M, "etherpll_125m", "etherpll", 1,
+		1),
+	FACTOR(CLK_TOP_ETHERPLL_50M, "etherpll_50m", "etherpll", 1,
+		1),
+	FACTOR(CLK_TOP_CVBS, "cvbs", "cvbspll", 1,
+		1),
+	FACTOR(CLK_TOP_CVBS_D2, "cvbs_d2", "cvbs", 1,
+		2),
+	FACTOR(CLK_TOP_SYS_26M, "sys_26m", "clk26m", 1,
+		1),
+	FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1,
+		1),
+	FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll_ck", 1,
+		2),
+	FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1,
+		1),
+	FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll_ck", 1,
+		2),
+	FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1,
+		1),
+	FACTOR(CLK_TOP_VCODECPLL_D2, "vcodecpll_d2", "vcodecpll_ck", 1,
+		2),
+	FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1,
+		1),
+	FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1,
+		2),
+	FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_ck", 1,
+		4),
+	FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_ck", 1,
+		8),
+	FACTOR(CLK_TOP_TVDPLL_429M, "tvdpll_429m", "tvdpll", 1,
+		1),
+	FACTOR(CLK_TOP_TVDPLL_429M_D2, "tvdpll_429m_d2", "tvdpll_429m", 1,
+		2),
+	FACTOR(CLK_TOP_TVDPLL_429M_D4, "tvdpll_429m_d4", "tvdpll_429m", 1,
+		4),
+	FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1,
+		1),
+	FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll_ck", 1,
+		2),
+	FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll_ck", 1,
+		4),
+	FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1,
+		1),
+	FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2_ck", 1,
+		2),
+	FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2_ck", 1,
+		4),
+	FACTOR(CLK_TOP_CLK26M_D2, "clk26m_d2", "sys_26m", 1,
+		2),
+	FACTOR(CLK_TOP_D2A_ULCLK_6P5M, "d2a_ulclk_6p5m", "clk26m", 1,
+		4),
+};
+
+static const char * const axi_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"msdcpll2_ck"
+};
+
+static const char * const mem_parents[] = {
+	"clk26m",
+	"dmpll_ck"
+};
+
+static const char * const mm_parents[] = {
+	"clk26m",
+	"vencpll_ck",
+	"syspll_d3",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll1_d2",
+	"univpll2_d2"
+};
+
+static const char * const pwm_parents[] = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll3_d2",
+	"univpll1_d4"
+};
+
+static const char * const vdec_parents[] = {
+	"clk26m",
+	"vcodecpll_ck",
+	"tvdpll_429m",
+	"univpll_d3",
+	"vencpll_ck",
+	"syspll_d3",
+	"univpll1_d2",
+	"mmpll_d2",
+	"syspll3_d2",
+	"tvdpll_ck"
+};
+
+static const char * const venc_parents[] = {
+	"clk26m",
+	"univpll1_d2",
+	"mmpll_d2",
+	"tvdpll_d2",
+	"syspll1_d2",
+	"univpll_d5",
+	"vcodecpll_d2",
+	"univpll2_d2",
+	"syspll3_d2"
+};
+
+static const char * const mfg_parents[] = {
+	"clk26m",
+	"mmpll_ck",
+	"univpll_d3",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"syspll_d3",
+	"syspll1_d2",
+	"syspll_d5",
+	"univpll_d3",
+	"univpll1_d2",
+	"univpll_d5",
+	"univpll2_d2"
+};
+
+static const char * const camtg_parents[] = {
+	"clk26m",
+	"univpll_d52",
+	"univpll_d208",
+	"univpll_d104",
+	"clk26m_d2",
+	"univpll_d26",
+	"univpll2_d8",
+	"syspll3_d4",
+	"syspll3_d2",
+	"univpll1_d4",
+	"univpll2_d2"
+};
+
+static const char * const uart_parents[] = {
+	"clk26m",
+	"univpll2_d8"
+};
+
+static const char * const spi_parents[] = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll1_d4",
+	"univpll2_d2",
+	"univpll3_d2",
+	"univpll1_d8"
+};
+
+static const char * const usb20_parents[] = {
+	"clk26m",
+	"univpll1_d8",
+	"univpll3_d4"
+};
+
+static const char * const usb30_parents[] = {
+	"clk26m",
+	"univpll3_d2",
+	"univpll3_d4",
+	"univpll2_d4"
+};
+
+static const char * const msdc50_0_h_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll2_d2",
+	"syspll4_d2",
+	"univpll_d5",
+	"univpll1_d4"
+};
+
+static const char * const msdc50_0_parents[] = {
+	"clk26m",
+	"msdcpll_ck",
+	"msdcpll_d2",
+	"univpll1_d4",
+	"syspll2_d2",
+	"msdcpll_d4",
+	"vencpll_d2",
+	"univpll1_d2",
+	"msdcpll2_ck",
+	"msdcpll2_d2",
+	"msdcpll2_d4"
+};
+
+static const char * const msdc30_1_parents[] = {
+	"clk26m",
+	"univpll2_d2",
+	"msdcpll_d2",
+	"univpll1_d4",
+	"syspll2_d2",
+	"univpll_d7",
+	"vencpll_d2"
+};
+
+static const char * const msdc30_3_parents[] = {
+	"clk26m",
+	"msdcpll2_ck",
+	"msdcpll2_d2",
+	"univpll2_d2",
+	"msdcpll2_d4",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll_d7",
+	"vencpll_d2",
+	"msdcpll_ck",
+	"msdcpll_d2",
+	"msdcpll_d4"
+};
+
+static const char * const audio_parents[] = {
+	"clk26m",
+	"syspll3_d4",
+	"syspll4_d4",
+	"syspll1_d16"
+};
+
+static const char * const aud_intbus_parents[] = {
+	"clk26m",
+	"syspll1_d4",
+	"syspll4_d2",
+	"univpll3_d2",
+	"univpll2_d8",
+	"syspll3_d2",
+	"syspll3_d4"
+};
+
+static const char * const pmicspi_parents[] = {
+	"clk26m",
+	"syspll1_d8",
+	"syspll3_d4",
+	"syspll1_d16",
+	"univpll3_d4",
+	"univpll_d26",
+	"syspll3_d4"
+};
+
+static const char * const dpilvds1_parents[] = {
+	"clk26m",
+	"lvdspll2_ck",
+	"lvdspll2_d2",
+	"lvdspll2_d4",
+	"lvdspll2_d8",
+	"clkfpc"
+};
+
+static const char * const atb_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"univpll_d5",
+	"syspll_d5"
+};
+
+static const char * const nr_parents[] = {
+	"clk26m",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll1_d4",
+	"univpll1_d8",
+	"univpll3_d2",
+	"univpll2_d2",
+	"syspll_d5"
+};
+
+static const char * const nfi2x_parents[] = {
+	"clk26m",
+	"syspll4_d4",
+	"univpll3_d4",
+	"univpll1_d8",
+	"syspll2_d4",
+	"univpll3_d2",
+	"syspll_d7",
+	"syspll2_d2",
+	"univpll2_d2",
+	"syspll_d5",
+	"syspll1_d2"
+};
+
+static const char * const irda_parents[] = {
+	"clk26m",
+	"univpll2_d4",
+	"syspll2_d4",
+	"univpll2_d8"
+};
+
+static const char * const cci400_parents[] = {
+	"clk26m",
+	"vencpll_ck",
+	"armca35pll_600m",
+	"armca35pll_400m",
+	"univpll_d2",
+	"syspll_d2",
+	"msdcpll_ck",
+	"univpll_d3"
+};
+
+static const char * const aud_1_parents[] = {
+	"clk26m",
+	"apll1_ck",
+	"univpll2_d4",
+	"univpll2_d8"
+};
+
+static const char * const aud_2_parents[] = {
+	"clk26m",
+	"apll2_ck",
+	"univpll2_d4",
+	"univpll2_d8"
+};
+
+static const char * const mem_mfg_parents[] = {
+	"clk26m",
+	"mmpll_ck",
+	"univpll_d3"
+};
+
+static const char * const axi_mfg_parents[] = {
+	"clk26m",
+	"axi_sel",
+	"univpll_d5"
+};
+
+static const char * const scam_parents[] = {
+	"clk26m",
+	"syspll3_d2",
+	"univpll2_d4",
+	"syspll2_d4"
+};
+
+static const char * const nfiecc_parents[] = {
+	"clk26m",
+	"nfi2x_sel",
+	"syspll_d7",
+	"syspll2_d2",
+	"univpll2_d2",
+	"univpll_d5",
+	"syspll1_d2"
+};
+
+static const char * const pe2_mac_p0_parents[] = {
+	"clk26m",
+	"syspll1_d8",
+	"syspll4_d2",
+	"syspll2_d4",
+	"univpll2_d4",
+	"syspll3_d2"
+};
+
+static const char * const dpilvds_parents[] = {
+	"clk26m",
+	"lvdspll_ck",
+	"lvdspll_d2",
+	"lvdspll_d4",
+	"lvdspll_d8",
+	"clkfpc"
+};
+
+static const char * const hdcp_parents[] = {
+	"clk26m",
+	"syspll4_d2",
+	"syspll3_d4",
+	"univpll2_d4"
+};
+
+static const char * const hdcp_24m_parents[] = {
+	"clk26m",
+	"univpll_d26",
+	"univpll_d52",
+	"univpll2_d8"
+};
+
+static const char * const rtc_parents[] = {
+	"clkrtc_int",
+	"clkrtc_ext",
+	"clk26m",
+	"univpll3_d8"
+};
+
+static const char * const spinor_parents[] = {
+	"clk26m",
+	"clk26m_d2",
+	"syspll4_d4",
+	"univpll2_d8",
+	"univpll3_d4",
+	"syspll4_d2",
+	"syspll2_d4",
+	"univpll2_d4",
+	"etherpll_125m",
+	"syspll1_d4"
+};
+
+static const char * const apll_parents[] = {
+	"clk26m",
+	"apll1_ck",
+	"apll1_d2",
+	"apll1_d4",
+	"apll1_d8",
+	"apll1_d16",
+	"apll2_ck",
+	"apll2_d2",
+	"apll2_d4",
+	"apll2_d8",
+	"apll2_d16",
+	"clk26m",
+	"clk26m"
+};
+
+static const char * const a1sys_hp_parents[] = {
+	"clk26m",
+	"apll1_ck",
+	"apll1_d2",
+	"apll1_d4",
+	"apll1_d8"
+};
+
+static const char * const a2sys_hp_parents[] = {
+	"clk26m",
+	"apll2_ck",
+	"apll2_d2",
+	"apll2_d4",
+	"apll2_d8"
+};
+
+static const char * const asm_l_parents[] = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll2_d2",
+	"syspll_d5"
+};
+
+static const char * const i2so1_parents[] = {
+	"clk26m",
+	"apll1_ck",
+	"apll2_ck"
+};
+
+static const char * const ether_125m_parents[] = {
+	"clk26m",
+	"etherpll_125m",
+	"univpll3_d2"
+};
+
+static const char * const ether_50m_parents[] = {
+	"clk26m",
+	"etherpll_50m",
+	"univpll_d26",
+	"univpll3_d4"
+};
+
+static const char * const jpgdec_parents[] = {
+	"clk26m",
+	"univpll_d3",
+	"tvdpll_429m",
+	"vencpll_ck",
+	"syspll_d3",
+	"vcodecpll_ck",
+	"univpll1_d2",
+	"armca35pll_400m",
+	"tvdpll_429m_d2",
+	"tvdpll_429m_d4"
+};
+
+static const char * const spislv_parents[] = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll1_d4",
+	"univpll2_d2",
+	"univpll3_d2",
+	"univpll1_d8",
+	"univpll1_d2",
+	"univpll_d5"
+};
+
+static const char * const ether_parents[] = {
+	"clk26m",
+	"etherpll_50m",
+	"univpll_d26"
+};
+
+static const char * const di_parents[] = {
+	"clk26m",
+	"tvdpll_d2",
+	"tvdpll_d4",
+	"tvdpll_d8",
+	"vencpll_ck",
+	"vencpll_d2",
+	"cvbs",
+	"cvbs_d2"
+};
+
+static const char * const tvd_parents[] = {
+	"clk26m",
+	"cvbs_d2",
+	"univpll2_d8"
+};
+
+static const char * const i2c_parents[] = {
+	"clk26m",
+	"univpll_d26",
+	"univpll2_d4",
+	"univpll3_d2",
+	"univpll1_d4"
+};
+
+static const char * const msdc0p_aes_parents[] = {
+	"clk26m",
+	"msdcpll_ck",
+	"univpll_d3",
+	"vcodecpll_ck"
+};
+
+static const char * const cmsys_parents[] = {
+	"clk26m",
+	"univpll_d3",
+	"syspll_d3",
+	"syspll1_d2",
+	"syspll2_d2"
+};
+
+static const char * const gcpu_parents[] = {
+	"clk26m",
+	"syspll_d3",
+	"syspll1_d2",
+	"univpll1_d2",
+	"univpll_d5",
+	"univpll3_d2",
+	"univpll_d3"
+};
+
+static const char * const aud_apll1_parents[] = {
+	"apll1",
+	"clkaud_ext_i_1"
+};
+
+static const char * const aud_apll2_parents[] = {
+	"apll2",
+	"clkaud_ext_i_2"
+};
+
+static const char * const audull_vtx_parents[] = {
+	"d2a_ulclk_6p5m",
+	"clkaud_ext_i_0"
+};
+
+static struct mtk_composite top_muxes[] = {
+	/* CLK_CFG_0 */
+	MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x040, 0, 3,
+		7, CLK_IS_CRITICAL),
+	MUX_GATE_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x040, 8, 1,
+		15, CLK_IS_CRITICAL),
+	MUX_GATE(CLK_TOP_MM_SEL, "mm_sel",
+		mm_parents, 0x040, 24, 3, 31),
+	/* CLK_CFG_1 */
+	MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel",
+		pwm_parents, 0x050, 0, 2, 7),
+	MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel",
+		vdec_parents, 0x050, 8, 4, 15),
+	MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel",
+		venc_parents, 0x050, 16, 4, 23),
+	MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel",
+		mfg_parents, 0x050, 24, 4, 31),
+	/* CLK_CFG_2 */
+	MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel",
+		camtg_parents, 0x060, 0, 4, 7),
+	MUX_GATE(CLK_TOP_UART_SEL, "uart_sel",
+		uart_parents, 0x060, 8, 1, 15),
+	MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel",
+		spi_parents, 0x060, 16, 3, 23),
+	MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel",
+		usb20_parents, 0x060, 24, 2, 31),
+	/* CLK_CFG_3 */
+	MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel",
+		usb30_parents, 0x070, 0, 2, 7),
+	MUX_GATE(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc50_0_h_sel",
+		msdc50_0_h_parents, 0x070, 8, 3, 15),
+	MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel",
+		msdc50_0_parents, 0x070, 16, 4, 23),
+	MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel",
+		msdc30_1_parents, 0x070, 24, 3, 31),
+	/* CLK_CFG_4 */
+	MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel",
+		msdc30_1_parents, 0x080, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel",
+		msdc30_3_parents, 0x080, 8, 4, 15),
+	MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel",
+		audio_parents, 0x080, 16, 2, 23),
+	MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel",
+		aud_intbus_parents, 0x080, 24, 3, 31),
+	/* CLK_CFG_5 */
+	MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel",
+		pmicspi_parents, 0x090, 0, 3, 7),
+	MUX_GATE(CLK_TOP_DPILVDS1_SEL, "dpilvds1_sel",
+		dpilvds1_parents, 0x090, 8, 3, 15),
+	MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel",
+		atb_parents, 0x090, 16, 2, 23),
+	MUX_GATE(CLK_TOP_NR_SEL, "nr_sel",
+		nr_parents, 0x090, 24, 3, 31),
+	/* CLK_CFG_6 */
+	MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel",
+		nfi2x_parents, 0x0a0, 0, 4, 7),
+	MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel",
+		irda_parents, 0x0a0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel",
+		cci400_parents, 0x0a0, 16, 3, 23),
+	MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel",
+		aud_1_parents, 0x0a0, 24, 2, 31),
+	/* CLK_CFG_7 */
+	MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel",
+		aud_2_parents, 0x0b0, 0, 2, 7),
+	MUX_GATE(CLK_TOP_MEM_MFG_IN_AS_SEL, "mem_mfg_sel",
+		mem_mfg_parents, 0x0b0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_AXI_MFG_IN_AS_SEL, "axi_mfg_sel",
+		axi_mfg_parents, 0x0b0, 16, 2, 23),
+	MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel",
+		scam_parents, 0x0b0, 24, 2, 31),
+	/* CLK_CFG_8 */
+	MUX_GATE(CLK_TOP_NFIECC_SEL, "nfiecc_sel",
+		nfiecc_parents, 0x0c0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_PE2_MAC_P0_SEL, "pe2_mac_p0_sel",
+		pe2_mac_p0_parents, 0x0c0, 8, 3, 15),
+	MUX_GATE(CLK_TOP_PE2_MAC_P1_SEL, "pe2_mac_p1_sel",
+		pe2_mac_p0_parents, 0x0c0, 16, 3, 23),
+	MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel",
+		dpilvds_parents, 0x0c0, 24, 3, 31),
+	/* CLK_CFG_9 */
+	MUX_GATE(CLK_TOP_MSDC50_3_HCLK_SEL, "msdc50_3_h_sel",
+		msdc50_0_h_parents, 0x0d0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel",
+		hdcp_parents, 0x0d0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel",
+		hdcp_24m_parents, 0x0d0, 16, 2, 23),
+	MUX_GATE_FLAGS(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x0d0, 24, 2,
+		31, CLK_IS_CRITICAL),
+	/* CLK_CFG_10 */
+	MUX_GATE(CLK_TOP_SPINOR_SEL, "spinor_sel",
+		spinor_parents, 0x500, 0, 4, 7),
+	MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel",
+		apll_parents, 0x500, 8, 4, 15),
+	MUX_GATE(CLK_TOP_APLL2_SEL, "apll2_sel",
+		apll_parents, 0x500, 16, 4, 23),
+	MUX_GATE(CLK_TOP_A1SYS_HP_SEL, "a1sys_hp_sel",
+		a1sys_hp_parents, 0x500, 24, 3, 31),
+	/* CLK_CFG_11 */
+	MUX_GATE(CLK_TOP_A2SYS_HP_SEL, "a2sys_hp_sel",
+		a2sys_hp_parents, 0x510, 0, 3, 7),
+	MUX_GATE(CLK_TOP_ASM_L_SEL, "asm_l_sel",
+		asm_l_parents, 0x510, 8, 2, 15),
+	MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel",
+		asm_l_parents, 0x510, 16, 2, 23),
+	MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel",
+		asm_l_parents, 0x510, 24, 2, 31),
+	/* CLK_CFG_12 */
+	MUX_GATE(CLK_TOP_I2SO1_SEL, "i2so1_sel",
+		i2so1_parents, 0x520, 0, 2, 7),
+	MUX_GATE(CLK_TOP_I2SO2_SEL, "i2so2_sel",
+		i2so1_parents, 0x520, 8, 2, 15),
+	MUX_GATE(CLK_TOP_I2SO3_SEL, "i2so3_sel",
+		i2so1_parents, 0x520, 16, 2, 23),
+	MUX_GATE(CLK_TOP_TDMO0_SEL, "tdmo0_sel",
+		i2so1_parents, 0x520, 24, 2, 31),
+	/* CLK_CFG_13 */
+	MUX_GATE(CLK_TOP_TDMO1_SEL, "tdmo1_sel",
+		i2so1_parents, 0x530, 0, 2, 7),
+	MUX_GATE(CLK_TOP_I2SI1_SEL, "i2si1_sel",
+		i2so1_parents, 0x530, 8, 2, 15),
+	MUX_GATE(CLK_TOP_I2SI2_SEL, "i2si2_sel",
+		i2so1_parents, 0x530, 16, 2, 23),
+	MUX_GATE(CLK_TOP_I2SI3_SEL, "i2si3_sel",
+		i2so1_parents, 0x530, 24, 2, 31),
+	/* CLK_CFG_14 */
+	MUX_GATE(CLK_TOP_ETHER_125M_SEL, "ether_125m_sel",
+		ether_125m_parents, 0x540, 0, 2, 7),
+	MUX_GATE(CLK_TOP_ETHER_50M_SEL, "ether_50m_sel",
+		ether_50m_parents, 0x540, 8, 2, 15),
+	MUX_GATE(CLK_TOP_JPGDEC_SEL, "jpgdec_sel",
+		jpgdec_parents, 0x540, 16, 4, 23),
+	MUX_GATE(CLK_TOP_SPISLV_SEL, "spislv_sel",
+		spislv_parents, 0x540, 24, 3, 31),
+	/* CLK_CFG_15 */
+	MUX_GATE(CLK_TOP_ETHER_50M_RMII_SEL, "ether_sel",
+		ether_parents, 0x550, 0, 2, 7),
+	MUX_GATE(CLK_TOP_CAM2TG_SEL, "cam2tg_sel",
+		camtg_parents, 0x550, 8, 4, 15),
+	MUX_GATE(CLK_TOP_DI_SEL, "di_sel",
+		di_parents, 0x550, 16, 3, 23),
+	MUX_GATE(CLK_TOP_TVD_SEL, "tvd_sel",
+		tvd_parents, 0x550, 24, 2, 31),
+	/* CLK_CFG_16 */
+	MUX_GATE(CLK_TOP_I2C_SEL, "i2c_sel",
+		i2c_parents, 0x560, 0, 3, 7),
+	MUX_GATE(CLK_TOP_PWM_INFRA_SEL, "pwm_infra_sel",
+		pwm_parents, 0x560, 8, 2, 15),
+	MUX_GATE(CLK_TOP_MSDC0P_AES_SEL, "msdc0p_aes_sel",
+		msdc0p_aes_parents, 0x560, 16, 2, 23),
+	MUX_GATE(CLK_TOP_CMSYS_SEL, "cmsys_sel",
+		cmsys_parents, 0x560, 24, 3, 31),
+	/* CLK_CFG_17 */
+	MUX_GATE(CLK_TOP_GCPU_SEL, "gcpu_sel",
+		gcpu_parents, 0x570, 0, 3, 7),
+	/* CLK_AUDDIV_4 */
+	MUX(CLK_TOP_AUD_APLL1_SEL, "aud_apll1_sel",
+		aud_apll1_parents, 0x134, 0, 1),
+	MUX(CLK_TOP_AUD_APLL2_SEL, "aud_apll2_sel",
+		aud_apll2_parents, 0x134, 1, 1),
+	MUX(CLK_TOP_DA_AUDULL_VTX_6P5M_SEL, "audull_vtx_sel",
+		audull_vtx_parents, 0x134, 31, 1),
+};
+
+static const char * const mcu_mp0_parents[] = {
+	"clk26m",
+	"armca35pll_ck",
+	"f_mp0_pll1_ck",
+	"f_mp0_pll2_ck"
+};
+
+static const char * const mcu_mp2_parents[] = {
+	"clk26m",
+	"armca72pll_ck",
+	"f_big_pll1_ck",
+	"f_big_pll2_ck"
+};
+
+static const char * const mcu_bus_parents[] = {
+	"clk26m",
+	"cci400_sel",
+	"f_bus_pll1_ck",
+	"f_bus_pll2_ck"
+};
+
+static struct mtk_composite mcu_muxes[] = {
+	/* mp0_pll_divider_cfg */
+	MUX_GATE_FLAGS(CLK_MCU_MP0_SEL, "mcu_mp0_sel", mcu_mp0_parents, 0x7A0,
+		9, 2, -1, CLK_IS_CRITICAL),
+	/* mp2_pll_divider_cfg */
+	MUX_GATE_FLAGS(CLK_MCU_MP2_SEL, "mcu_mp2_sel", mcu_mp2_parents, 0x7A8,
+		9, 2, -1, CLK_IS_CRITICAL),
+	/* bus_pll_divider_cfg */
+	MUX_GATE_FLAGS(CLK_MCU_BUS_SEL, "mcu_bus_sel", mcu_bus_parents, 0x7C0,
+		9, 2, -1, CLK_IS_CRITICAL),
+};
+
+static const struct mtk_clk_divider top_adj_divs[] = {
+	DIV_ADJ(CLK_TOP_APLL_DIV0, "apll_div0", "i2so1_sel", 0x124, 0, 8),
+	DIV_ADJ(CLK_TOP_APLL_DIV1, "apll_div1", "i2so2_sel", 0x124, 8, 8),
+	DIV_ADJ(CLK_TOP_APLL_DIV2, "apll_div2", "i2so3_sel", 0x124, 16, 8),
+	DIV_ADJ(CLK_TOP_APLL_DIV3, "apll_div3", "tdmo0_sel", 0x124, 24, 8),
+	DIV_ADJ(CLK_TOP_APLL_DIV4, "apll_div4", "tdmo1_sel", 0x128, 0, 8),
+	DIV_ADJ(CLK_TOP_APLL_DIV5, "apll_div5", "i2si1_sel", 0x128, 8, 8),
+	DIV_ADJ(CLK_TOP_APLL_DIV6, "apll_div6", "i2si2_sel", 0x128, 16, 8),
+	DIV_ADJ(CLK_TOP_APLL_DIV7, "apll_div7", "i2si3_sel", 0x128, 24, 8),
+};
+
+static const struct mtk_gate_regs top_cg_regs = {
+	.set_ofs = 0x120,
+	.clr_ofs = 0x120,
+	.sta_ofs = 0x120,
+};
+
+#define GATE_TOP(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &top_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_no_setclr,	\
+	}
+
+static const struct mtk_gate top_clks[] = {
+	GATE_TOP(CLK_TOP_APLL_DIV_PDN0, "apll_div_pdn0", "i2so1_sel", 0),
+	GATE_TOP(CLK_TOP_APLL_DIV_PDN1, "apll_div_pdn1", "i2so2_sel", 1),
+	GATE_TOP(CLK_TOP_APLL_DIV_PDN2, "apll_div_pdn2", "i2so3_sel", 2),
+	GATE_TOP(CLK_TOP_APLL_DIV_PDN3, "apll_div_pdn3", "tdmo0_sel", 3),
+	GATE_TOP(CLK_TOP_APLL_DIV_PDN4, "apll_div_pdn4", "tdmo1_sel", 4),
+	GATE_TOP(CLK_TOP_APLL_DIV_PDN5, "apll_div_pdn5", "i2si1_sel", 5),
+	GATE_TOP(CLK_TOP_APLL_DIV_PDN6, "apll_div_pdn6", "i2si2_sel", 6),
+	GATE_TOP(CLK_TOP_APLL_DIV_PDN7, "apll_div_pdn7", "i2si3_sel", 7),
+};
+
+static const struct mtk_gate_regs infra_cg_regs = {
+	.set_ofs = 0x40,
+	.clr_ofs = 0x44,
+	.sta_ofs = 0x40,
+};
+
+#define GATE_INFRA(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &infra_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate infra_clks[] = {
+	GATE_INFRA(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0),
+	GATE_INFRA(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6),
+	GATE_INFRA(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8),
+	GATE_INFRA(CLK_INFRA_KP, "infra_kp", "axi_sel", 16),
+	GATE_INFRA(CLK_INFRA_AO_SPI0, "infra_ao_spi0", "spi_sel", 24),
+	GATE_INFRA(CLK_INFRA_AO_SPI1, "infra_ao_spi1", "spislv_sel", 25),
+	GATE_INFRA(CLK_INFRA_AO_UART5, "infra_ao_uart5", "axi_sel", 26),
+};
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x8,
+	.clr_ofs = 0x10,
+	.sta_ofs = 0x18,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0xc,
+	.clr_ofs = 0x14,
+	.sta_ofs = 0x1c,
+};
+
+static const struct mtk_gate_regs peri2_cg_regs = {
+	.set_ofs = 0x42c,
+	.clr_ofs = 0x42c,
+	.sta_ofs = 0x42c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &peri0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_PERI1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &peri1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_PERI2(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &peri2_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_no_setclr_inv,	\
+	}
+
+static const struct mtk_gate peri_clks[] = {
+	/* PERI0 */
+	GATE_PERI0(CLK_PERI_NFI, "per_nfi",
+		"axi_sel", 0),
+	GATE_PERI0(CLK_PERI_THERM, "per_therm",
+		"axi_sel", 1),
+	GATE_PERI0(CLK_PERI_PWM0, "per_pwm0",
+		"pwm_sel", 2),
+	GATE_PERI0(CLK_PERI_PWM1, "per_pwm1",
+		"pwm_sel", 3),
+	GATE_PERI0(CLK_PERI_PWM2, "per_pwm2",
+		"pwm_sel", 4),
+	GATE_PERI0(CLK_PERI_PWM3, "per_pwm3",
+		"pwm_sel", 5),
+	GATE_PERI0(CLK_PERI_PWM4, "per_pwm4",
+		"pwm_sel", 6),
+	GATE_PERI0(CLK_PERI_PWM5, "per_pwm5",
+		"pwm_sel", 7),
+	GATE_PERI0(CLK_PERI_PWM6, "per_pwm6",
+		"pwm_sel", 8),
+	GATE_PERI0(CLK_PERI_PWM7, "per_pwm7",
+		"pwm_sel", 9),
+	GATE_PERI0(CLK_PERI_PWM, "per_pwm",
+		"pwm_sel", 10),
+	GATE_PERI0(CLK_PERI_AP_DMA, "per_ap_dma",
+		"axi_sel", 13),
+	GATE_PERI0(CLK_PERI_MSDC30_0, "per_msdc30_0",
+		"msdc50_0_sel", 14),
+	GATE_PERI0(CLK_PERI_MSDC30_1, "per_msdc30_1",
+		"msdc30_1_sel", 15),
+	GATE_PERI0(CLK_PERI_MSDC30_2, "per_msdc30_2",
+		"msdc30_2_sel", 16),
+	GATE_PERI0(CLK_PERI_MSDC30_3, "per_msdc30_3",
+		"msdc30_3_sel", 17),
+	GATE_PERI0(CLK_PERI_UART0, "per_uart0",
+		"uart_sel", 20),
+	GATE_PERI0(CLK_PERI_UART1, "per_uart1",
+		"uart_sel", 21),
+	GATE_PERI0(CLK_PERI_UART2, "per_uart2",
+		"uart_sel", 22),
+	GATE_PERI0(CLK_PERI_UART3, "per_uart3",
+		"uart_sel", 23),
+	GATE_PERI0(CLK_PERI_I2C0, "per_i2c0",
+		"axi_sel", 24),
+	GATE_PERI0(CLK_PERI_I2C1, "per_i2c1",
+		"axi_sel", 25),
+	GATE_PERI0(CLK_PERI_I2C2, "per_i2c2",
+		"axi_sel", 26),
+	GATE_PERI0(CLK_PERI_I2C3, "per_i2c3",
+		"axi_sel", 27),
+	GATE_PERI0(CLK_PERI_I2C4, "per_i2c4",
+		"axi_sel", 28),
+	GATE_PERI0(CLK_PERI_AUXADC, "per_auxadc",
+		"ltepll_fs26m", 29),
+	GATE_PERI0(CLK_PERI_SPI0, "per_spi0",
+		"spi_sel", 30),
+	/* PERI1 */
+	GATE_PERI1(CLK_PERI_SPI, "per_spi",
+		"spinor_sel", 1),
+	GATE_PERI1(CLK_PERI_I2C5, "per_i2c5",
+		"axi_sel", 3),
+	GATE_PERI1(CLK_PERI_SPI2, "per_spi2",
+		"spi_sel", 5),
+	GATE_PERI1(CLK_PERI_SPI3, "per_spi3",
+		"spi_sel", 6),
+	GATE_PERI1(CLK_PERI_SPI5, "per_spi5",
+		"spi_sel", 8),
+	GATE_PERI1(CLK_PERI_UART4, "per_uart4",
+		"uart_sel", 9),
+	GATE_PERI1(CLK_PERI_SFLASH, "per_sflash",
+		"uart_sel", 11),
+	GATE_PERI1(CLK_PERI_GMAC, "per_gmac",
+		"uart_sel", 12),
+	GATE_PERI1(CLK_PERI_PCIE0, "per_pcie0",
+		"uart_sel", 14),
+	GATE_PERI1(CLK_PERI_PCIE1, "per_pcie1",
+		"uart_sel", 15),
+	GATE_PERI1(CLK_PERI_GMAC_PCLK, "per_gmac_pclk",
+		"uart_sel", 16),
+	/* PERI2 */
+	GATE_PERI2(CLK_PERI_MSDC50_0_EN, "per_msdc50_0_en",
+		"msdc50_0_sel", 0),
+	GATE_PERI2(CLK_PERI_MSDC30_1_EN, "per_msdc30_1_en",
+		"msdc30_1_sel", 1),
+	GATE_PERI2(CLK_PERI_MSDC30_2_EN, "per_msdc30_2_en",
+		"msdc30_2_sel", 2),
+	GATE_PERI2(CLK_PERI_MSDC30_3_EN, "per_msdc30_3_en",
+		"msdc30_3_sel", 3),
+	GATE_PERI2(CLK_PERI_MSDC50_0_HCLK_EN, "per_msdc50_0_h",
+		"msdc50_0_h_sel", 4),
+	GATE_PERI2(CLK_PERI_MSDC50_3_HCLK_EN, "per_msdc50_3_h",
+		"msdc50_3_h_sel", 5),
+};
+
+#define MT2712_PLL_FMAX		(3000UL * MHZ)
+
+#define CON0_MT2712_RST_BAR	BIT(24)
+
+#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,	\
+			_pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg,	\
+			_tuner_en_bit, _pcw_reg, _pcw_shift,		\
+			_div_table) {					\
+		.id = _id,						\
+		.name = _name,						\
+		.reg = _reg,						\
+		.pwr_reg = _pwr_reg,					\
+		.en_mask = _en_mask,					\
+		.flags = _flags,					\
+		.rst_bar_mask = CON0_MT2712_RST_BAR,			\
+		.fmax = MT2712_PLL_FMAX,				\
+		.pcwbits = _pcwbits,					\
+		.pd_reg = _pd_reg,					\
+		.pd_shift = _pd_shift,					\
+		.tuner_reg = _tuner_reg,				\
+		.tuner_en_reg = _tuner_en_reg,				\
+		.tuner_en_bit = _tuner_en_bit,				\
+		.pcw_reg = _pcw_reg,					\
+		.pcw_shift = _pcw_shift,				\
+		.div_table = _div_table,				\
+	}
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,	\
+			_pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg,	\
+			_tuner_en_bit, _pcw_reg, _pcw_shift)		\
+		PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags,	\
+			_pcwbits, _pd_reg, _pd_shift, _tuner_reg,	\
+			_tuner_en_reg, _tuner_en_bit, _pcw_reg,		\
+			_pcw_shift, NULL)
+
+static const struct mtk_pll_div_table armca35pll_div_table[] = {
+	{ .div = 0, .freq = MT2712_PLL_FMAX },
+	{ .div = 1, .freq = 1202500000 },
+	{ .div = 2, .freq = 500500000 },
+	{ .div = 3, .freq = 315250000 },
+	{ .div = 4, .freq = 157625000 },
+	{ } /* sentinel */
+};
+
+static const struct mtk_pll_div_table armca72pll_div_table[] = {
+	{ .div = 0, .freq = MT2712_PLL_FMAX },
+	{ .div = 1, .freq = 994500000 },
+	{ .div = 2, .freq = 520000000 },
+	{ .div = 3, .freq = 315250000 },
+	{ .div = 4, .freq = 157625000 },
+	{ } /* sentinel */
+};
+
+static const struct mtk_pll_div_table mmpll_div_table[] = {
+	{ .div = 0, .freq = MT2712_PLL_FMAX },
+	{ .div = 1, .freq = 1001000000 },
+	{ .div = 2, .freq = 601250000 },
+	{ .div = 3, .freq = 250250000 },
+	{ .div = 4, .freq = 125125000 },
+	{ } /* sentinel */
+};
+
+static const struct mtk_pll_data plls[] = {
+	PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0230, 0x023C, 0xf0000101,
+		HAVE_RST_BAR, 31, 0x0230, 4, 0, 0, 0, 0x0234, 0),
+	PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0240, 0x024C, 0xfe000101,
+		HAVE_RST_BAR, 31, 0x0240, 4, 0, 0, 0, 0x0244, 0),
+	PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x0320, 0x032C, 0xc0000101,
+		0, 31, 0x0320, 4, 0, 0, 0, 0x0324, 0),
+	PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x0280, 0x028C, 0x00000101,
+		0, 31, 0x0280, 4, 0, 0, 0, 0x0284, 0),
+	PLL(CLK_APMIXED_APLL1, "apll1", 0x0330, 0x0340, 0x00000101,
+		0, 31, 0x0330, 4, 0x0338, 0x0014, 0, 0x0334, 0),
+	PLL(CLK_APMIXED_APLL2, "apll2", 0x0350, 0x0360, 0x00000101,
+		0, 31, 0x0350, 4, 0x0358, 0x0014, 1, 0x0354, 0),
+	PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x0370, 0x037c, 0x00000101,
+		0, 31, 0x0370, 4, 0, 0, 0, 0x0374, 0),
+	PLL(CLK_APMIXED_LVDSPLL2, "lvdspll2", 0x0390, 0x039C, 0x00000101,
+		0, 31, 0x0390, 4, 0, 0, 0, 0x0394, 0),
+	PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0270, 0x027C, 0x00000101,
+		0, 31, 0x0270, 4, 0, 0, 0, 0x0274, 0),
+	PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x0410, 0x041C, 0x00000101,
+		0, 31, 0x0410, 4, 0, 0, 0, 0x0414, 0),
+	PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0290, 0x029C, 0xc0000101,
+		0, 31, 0x0290, 4, 0, 0, 0, 0x0294, 0),
+	PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0250, 0x0260, 0x00000101,
+		0, 31, 0x0250, 4, 0, 0, 0, 0x0254, 0,
+		mmpll_div_table),
+	PLL_B(CLK_APMIXED_ARMCA35PLL, "armca35pll", 0x0100, 0x0110, 0xf0000101,
+		HAVE_RST_BAR, 31, 0x0100, 4, 0, 0, 0, 0x0104, 0,
+		armca35pll_div_table),
+	PLL_B(CLK_APMIXED_ARMCA72PLL, "armca72pll", 0x0210, 0x0220, 0x00000101,
+		0, 31, 0x0210, 4, 0, 0, 0, 0x0214, 0,
+		armca72pll_div_table),
+	PLL(CLK_APMIXED_ETHERPLL, "etherpll", 0x0300, 0x030C, 0xc0000101,
+		0, 31, 0x0300, 4, 0, 0, 0, 0x0304, 0),
+};
+
+static int clk_mt2712_apmixed_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+
+	mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r != 0)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	return r;
+}
+
+static int clk_mt2712_top_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+	void __iomem *base;
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base)) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return PTR_ERR(base);
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+	mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
+			clk_data);
+	mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+	mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
+			&mt2712_clk_lock, clk_data);
+	mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), base,
+			&mt2712_clk_lock, clk_data);
+	mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
+			clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r != 0)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	return r;
+}
+
+static int clk_mt2712_infra_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+
+	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+			clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r != 0)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0x30);
+
+	return r;
+}
+
+static int clk_mt2712_peri_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+
+	mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
+			clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r != 0)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0);
+
+	return r;
+}
+
+static int clk_mt2712_mcu_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+	void __iomem *base;
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base)) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return PTR_ERR(base);
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK);
+
+	mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base,
+			&mt2712_clk_lock, clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r != 0)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	return r;
+}
+
+static const struct of_device_id of_match_clk_mt2712[] = {
+	{
+		.compatible = "mediatek,mt2712-apmixedsys",
+		.data = clk_mt2712_apmixed_probe,
+	}, {
+		.compatible = "mediatek,mt2712-topckgen",
+		.data = clk_mt2712_top_probe,
+	}, {
+		.compatible = "mediatek,mt2712-infracfg",
+		.data = clk_mt2712_infra_probe,
+	}, {
+		.compatible = "mediatek,mt2712-pericfg",
+		.data = clk_mt2712_peri_probe,
+	}, {
+		.compatible = "mediatek,mt2712-mcucfg",
+		.data = clk_mt2712_mcu_probe,
+	}, {
+		/* sentinel */
+	}
+};
+
+static int clk_mt2712_probe(struct platform_device *pdev)
+{
+	int (*clk_probe)(struct platform_device *);
+	int r;
+
+	clk_probe = of_device_get_match_data(&pdev->dev);
+	if (!clk_probe)
+		return -EINVAL;
+
+	r = clk_probe(pdev);
+	if (r != 0)
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+
+	return r;
+}
+
+static struct platform_driver clk_mt2712_drv = {
+	.probe = clk_mt2712_probe,
+	.driver = {
+		.name = "clk-mt2712",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_clk_mt2712,
+	},
+};
+
+static int __init clk_mt2712_init(void)
+{
+	return platform_driver_register(&clk_mt2712_drv);
+}
+
+arch_initcall(clk_mt2712_init);
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index f5d6b70..f48df75 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -207,6 +207,8 @@ struct mtk_pll_data {
 	uint32_t en_mask;
 	uint32_t pd_reg;
 	uint32_t tuner_reg;
+	uint32_t tuner_en_reg;
+	uint8_t tuner_en_bit;
 	int pd_shift;
 	unsigned int flags;
 	const struct clk_ops *ops;
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index a409142..3c546ba 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -47,6 +47,7 @@ struct mtk_clk_pll {
 	void __iomem	*pd_addr;
 	void __iomem	*pwr_addr;
 	void __iomem	*tuner_addr;
+	void __iomem	*tuner_en_addr;
 	void __iomem	*pcw_addr;
 	const struct mtk_pll_data *data;
 };
@@ -227,7 +228,10 @@ static int mtk_pll_prepare(struct clk_hw *hw)
 	r |= pll->data->en_mask;
 	writel(r, pll->base_addr + REG_CON0);
 
-	if (pll->tuner_addr) {
+	if (pll->tuner_en_addr) {
+		r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit);
+		writel(r, pll->tuner_en_addr);
+	} else if (pll->tuner_addr) {
 		r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
 		writel(r, pll->tuner_addr);
 	}
@@ -254,7 +258,10 @@ static void mtk_pll_unprepare(struct clk_hw *hw)
 		writel(r, pll->base_addr + REG_CON0);
 	}
 
-	if (pll->tuner_addr) {
+	if (pll->tuner_en_addr) {
+		r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit);
+		writel(r, pll->tuner_en_addr);
+	} else if (pll->tuner_addr) {
 		r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
 		writel(r, pll->tuner_addr);
 	}
@@ -297,6 +304,8 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
 	pll->pcw_addr = base + data->pcw_reg;
 	if (data->tuner_reg)
 		pll->tuner_addr = base + data->tuner_reg;
+	if (data->tuner_en_reg)
+		pll->tuner_en_addr = base + data->tuner_en_reg;
 	pll->hw.init = &init;
 	pll->data = data;
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 4/9] arm: dts: mt2712: Add clock controller device nodes
  2017-08-22 10:28 [PATCH v2 0/9] Mediatek MT2712 clock and scpsys support Weiyi Lu
                   ` (2 preceding siblings ...)
  2017-08-22 10:28 ` [PATCH 3/9] clk: mediatek: Add MT2712 clock support Weiyi Lu
@ 2017-08-22 10:28 ` Weiyi Lu
  2017-08-22 10:28 ` [PATCH 5/9] dt-bindings: soc: add MT2712 power dt-bindings Weiyi Lu
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Weiyi Lu @ 2017-08-22 10:28 UTC (permalink / raw)
  To: Matthias Brugger, Stephen Boyd, Rob Herring
  Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu

Add clock controller nodes for MT2712, include topckgen, infracfg,
pericfg, mcucfg and apmixedsys. This patch also add six oscillators that
provide clocks for MT2712.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt2712e.dtsi | 115 ++++++++++++++++++++++++++++++
 1 file changed, 115 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
index 92e4c50..6338a1f 100644
--- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
@@ -5,6 +5,7 @@
  * SPDX-License-Identifier: (GPL-2.0 OR MIT)
  */
 
+#include <dt-bindings/clock/mt2712-clk.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include "mt2712-pinfunc.h"
@@ -74,6 +75,48 @@
 		#clock-cells = <0>;
 	};
 
+	clk26m: oscillator@0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "clk26m";
+	};
+
+	clk32k: oscillator@1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32000>;
+		clock-output-names = "clk32k";
+	};
+
+	clkfpc: oscillator@2 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <50000000>;
+		clock-output-names = "clkfpc";
+	};
+
+	clkaud_ext_i_0: oscillator@3 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <6500000>;
+		clock-output-names = "clkaud_ext_i_0";
+	};
+
+	clkaud_ext_i_1: oscillator@4 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <196608000>;
+		clock-output-names = "clkaud_ext_i_1";
+	};
+
+	clkaud_ext_i_2: oscillator@5 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <180633600>;
+		clock-output-names = "clkaud_ext_i_2";
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupt-parent = <&gic>;
@@ -87,6 +130,24 @@
 			      (GIC_CPU_MASK_RAW(0x13) | IRQ_TYPE_LEVEL_LOW)>;
 	};
 
+	topckgen: syscon@10000000 {
+		compatible = "mediatek,mt2712-topckgen", "syscon";
+		reg = <0 0x10000000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	infracfg: syscon@10001000 {
+		compatible = "mediatek,mt2712-infracfg", "syscon";
+		reg = <0 0x10001000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	pericfg: syscon@10003000 {
+		compatible = "mediatek,mt2712-pericfg", "syscon";
+		reg = <0 0x10003000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
 	syscfg_pctl_a: syscfg_pctl_a@10005000 {
 		compatible = "mediatek,mt2712-pctl-a-syscfg", "syscon";
 		reg = <0 0x10005000 0 0x1000>;
@@ -114,6 +175,18 @@
 		status = "disabled";
 	};
 
+	apmixedsys: syscon@10209000 {
+		compatible = "mediatek,mt2712-apmixedsys", "syscon";
+		reg = <0 0x10209000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	mcucfg: syscon@10220000 {
+		compatible = "mediatek,mt2712-mcucfg", "syscon";
+		reg = <0 0x10220000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
 	sysirq: interrupt-controller@10220a80 {
 		compatible = "mediatek,mt2712-sysirq",
 			     "mediatek,mt6577-sysirq";
@@ -185,5 +258,47 @@
 		clock-names = "baud", "bus";
 		status = "disabled";
 	};
+
+	mfgcfg: syscon@13000000 {
+		compatible = "mediatek,mt2712-mfgcfg", "syscon";
+		reg = <0 0x13000000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	mmsys: syscon@14000000 {
+		compatible = "mediatek,mt2712-mmsys", "syscon";
+		reg = <0 0x14000000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	imgsys: syscon@15000000 {
+		compatible = "mediatek,mt2712-imgsys", "syscon";
+		reg = <0 0x15000000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	bdpsys: syscon@15010000 {
+		compatible = "mediatek,mt2712-bdpsys", "syscon";
+		reg = <0 0x15010000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	vdecsys: syscon@16000000 {
+		compatible = "mediatek,mt2712-vdecsys", "syscon";
+		reg = <0 0x16000000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	vencsys: syscon@18000000 {
+		compatible = "mediatek,mt2712-vencsys", "syscon";
+		reg = <0 0x18000000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	jpgdecsys: syscon@19000000 {
+		compatible = "mediatek,mt2712-jpgdecsys", "syscon";
+		reg = <0 0x19000000 0 0x1000>;
+		#clock-cells = <1>;
+	};
 };
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 5/9] dt-bindings: soc: add MT2712 power dt-bindings
  2017-08-22 10:28 [PATCH v2 0/9] Mediatek MT2712 clock and scpsys support Weiyi Lu
                   ` (3 preceding siblings ...)
  2017-08-22 10:28 ` [PATCH 4/9] arm: dts: mt2712: Add clock controller device nodes Weiyi Lu
@ 2017-08-22 10:28 ` Weiyi Lu
  2017-08-22 10:28 ` [PATCH 6/9] soc: mediatek: extend bus protection API Weiyi Lu
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Weiyi Lu @ 2017-08-22 10:28 UTC (permalink / raw)
  To: Matthias Brugger, Stephen Boyd, Rob Herring
  Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu

Add power dt-bindings for MT2712.

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 .../devicetree/bindings/soc/mediatek/scpsys.txt    |  3 +++
 include/dt-bindings/power/mt2712-power.h           | 26 ++++++++++++++++++++++
 2 files changed, 29 insertions(+)
 create mode 100644 include/dt-bindings/power/mt2712-power.h

diff --git a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
index 40056f7..76bf45b 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+++ b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
@@ -12,11 +12,13 @@ power/power_domain.txt. It provides the power domains defined in
 - include/dt-bindings/power/mt8173-power.h
 - include/dt-bindings/power/mt6797-power.h
 - include/dt-bindings/power/mt2701-power.h
+- include/dt-bindings/power/mt2712-power.h
 - include/dt-bindings/power/mt7622-power.h
 
 Required properties:
 - compatible: Should be one of:
 	- "mediatek,mt2701-scpsys"
+	- "mediatek,mt2712-scpsys"
 	- "mediatek,mt6797-scpsys"
 	- "mediatek,mt7622-scpsys"
 	- "mediatek,mt8173-scpsys"
@@ -27,6 +29,7 @@ Required properties:
                       These are clocks which hardware needs to be
                       enabled before enabling certain power domains.
 	Required clocks for MT2701: "mm", "mfg", "ethif"
+	Required clocks for MT2712: "mm", "mfg", "venc", "jpgdec", "audio", "vdec"
 	Required clocks for MT6797: "mm", "mfg", "vdec"
 	Required clocks for MT7622: "hif_sel"
 	Required clocks for MT8173: "mm", "mfg", "venc", "venc_lt"
diff --git a/include/dt-bindings/power/mt2712-power.h b/include/dt-bindings/power/mt2712-power.h
new file mode 100644
index 0000000..92b46d7
--- /dev/null
+++ b/include/dt-bindings/power/mt2712-power.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 MediaTek Inc.
+ *
+ * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+
+#ifndef _DT_BINDINGS_POWER_MT2712_POWER_H
+#define _DT_BINDINGS_POWER_MT2712_POWER_H
+
+#define MT2712_POWER_DOMAIN_MM		0
+#define MT2712_POWER_DOMAIN_VDEC	1
+#define MT2712_POWER_DOMAIN_VENC	2
+#define MT2712_POWER_DOMAIN_ISP		3
+#define MT2712_POWER_DOMAIN_AUDIO	4
+#define MT2712_POWER_DOMAIN_USB		5
+#define MT2712_POWER_DOMAIN_USB2	6
+#define MT2712_POWER_DOMAIN_MFG		7
+
+#endif /* _DT_BINDINGS_POWER_MT2712_POWER_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 6/9] soc: mediatek: extend bus protection API
  2017-08-22 10:28 [PATCH v2 0/9] Mediatek MT2712 clock and scpsys support Weiyi Lu
                   ` (4 preceding siblings ...)
  2017-08-22 10:28 ` [PATCH 5/9] dt-bindings: soc: add MT2712 power dt-bindings Weiyi Lu
@ 2017-08-22 10:28 ` Weiyi Lu
  2017-10-10 15:45   ` Matthias Brugger
  2017-08-22 10:28 ` [PATCH 7/9] soc: mediatek: add dependent clock jpgdec/audio for scpsys Weiyi Lu
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 13+ messages in thread
From: Weiyi Lu @ 2017-08-22 10:28 UTC (permalink / raw)
  To: Matthias Brugger, Stephen Boyd, Rob Herring
  Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu

MT2712 add "set/clear" bus control register to each control register set
instead of providing only one "enable" control register, we could avoid
the read-modify-write racing by using extend API with such new design.
By improving the mtk-infracfg bus protection implementation to
support set/clear bus protection control method by IC configuration.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-infracfg.c   | 32 ++++++++++----
 drivers/soc/mediatek/mtk-scpsys.c     | 81 +++++++++++++++++++++++++++--------
 include/linux/soc/mediatek/infracfg.h | 12 ++++--
 3 files changed, 96 insertions(+), 29 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c
index dba3055..f55ceaa 100644
--- a/drivers/soc/mediatek/mtk-infracfg.c
+++ b/drivers/soc/mediatek/mtk-infracfg.c
@@ -17,30 +17,35 @@
 #include <linux/soc/mediatek/infracfg.h>
 #include <asm/processor.h>
 
-#define INFRA_TOPAXI_PROTECTEN		0x0220
-#define INFRA_TOPAXI_PROTECTSTA1	0x0228
-
 /**
  * mtk_infracfg_set_bus_protection - enable bus protection
  * @regmap: The infracfg regmap
  * @mask: The mask containing the protection bits to be enabled.
+ * @reg_set: The register used to enable protection bits.
+ * @reg_en: The register used to enable protection bits when there doesn't
+ *          exist reg_set.
+ * @reg_sta: The register used to check the protection bits are enabled.
  *
  * This function enables the bus protection bits for disabled power
  * domains so that the system does not hang when some unit accesses the
  * bus while in power down.
  */
-int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
+int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
+		u32 reg_set, u32 reg_en, u32 reg_sta)
 {
 	unsigned long expired;
 	u32 val;
 	int ret;
 
-	regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, mask);
+	if (reg_set)
+		regmap_write(infracfg, reg_set, mask);
+	else
+		regmap_update_bits(infracfg, reg_en, mask, mask);
 
 	expired = jiffies + HZ;
 
 	while (1) {
-		ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
+		ret = regmap_read(infracfg, reg_sta, &val);
 		if (ret)
 			return ret;
 
@@ -59,23 +64,32 @@ int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
  * mtk_infracfg_clear_bus_protection - disable bus protection
  * @regmap: The infracfg regmap
  * @mask: The mask containing the protection bits to be disabled.
+ * @reg_clr: The register used to disable protection bits.
+ * @reg_en: The register used to disable protection bits when there doesn't
+ *          exist reg_clr.
+ * @reg_sta: The register used to check the protection bits are disabled.
  *
  * This function disables the bus protection bits previously enabled with
  * mtk_infracfg_set_bus_protection.
  */
-int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask)
+
+int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
+		u32 reg_clr, u32 reg_en, u32 reg_sta)
 {
 	unsigned long expired;
 	int ret;
 
-	regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
+	if (reg_clr)
+		regmap_write(infracfg, reg_clr, mask);
+	else
+		regmap_update_bits(infracfg, reg_en, mask, 0);
 
 	expired = jiffies + HZ;
 
 	while (1) {
 		u32 val;
 
-		ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
+		ret = regmap_read(infracfg, reg_sta, &val);
 		if (ret)
 			return ret;
 
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index e1ce8b1..2569390 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -127,13 +127,25 @@ struct scp_ctrl_reg {
 	int pwr_sta2nd_offs;
 };
 
+struct bus_prot_reg {
+	u32 set_offs;
+	u32 clr_offs;
+	u32 en_offs;
+	u32 sta_offs;
+};
+
+struct soc_reg {
+	struct scp_ctrl_reg scp_ctrl;
+	struct bus_prot_reg bus_prot;
+};
+
 struct scp {
 	struct scp_domain *domains;
 	struct genpd_onecell_data pd_data;
 	struct device *dev;
 	void __iomem *base;
 	struct regmap *infracfg;
-	struct scp_ctrl_reg ctrl_reg;
+	struct soc_reg soc_reg;
 };
 
 struct scp_subdomain {
@@ -146,16 +158,16 @@ struct scp_soc_data {
 	int num_domains;
 	const struct scp_subdomain *subdomains;
 	int num_subdomains;
-	const struct scp_ctrl_reg regs;
+	const struct soc_reg regs;
 };
 
 static int scpsys_domain_is_on(struct scp_domain *scpd)
 {
 	struct scp *scp = scpd->scp;
 
-	u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) &
+	u32 status = readl(scp->base + scp->soc_reg.scp_ctrl.pwr_sta_offs) &
 						scpd->data->sta_mask;
-	u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) &
+	u32 status2 = readl(scp->base + scp->soc_reg.scp_ctrl.pwr_sta2nd_offs) &
 						scpd->data->sta_mask;
 
 	/*
@@ -254,7 +266,10 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
 
 	if (scpd->data->bus_prot_mask) {
 		ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
-				scpd->data->bus_prot_mask);
+				scpd->data->bus_prot_mask,
+				scp->soc_reg.bus_prot.clr_offs,
+				scp->soc_reg.bus_prot.en_offs,
+				scp->soc_reg.bus_prot.sta_offs);
 		if (ret)
 			goto err_pwr_ack;
 	}
@@ -289,7 +304,10 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
 
 	if (scpd->data->bus_prot_mask) {
 		ret = mtk_infracfg_set_bus_protection(scp->infracfg,
-				scpd->data->bus_prot_mask);
+				scpd->data->bus_prot_mask,
+				scp->soc_reg.bus_prot.set_offs,
+				scp->soc_reg.bus_prot.en_offs,
+				scp->soc_reg.bus_prot.sta_offs);
 		if (ret)
 			goto out;
 	}
@@ -382,7 +400,7 @@ static void init_clks(struct platform_device *pdev, struct clk **clk)
 
 static struct scp *init_scp(struct platform_device *pdev,
 			const struct scp_domain_data *scp_domain_data, int num,
-			const struct scp_ctrl_reg *scp_ctrl_reg)
+			const struct soc_reg *soc_reg)
 {
 	struct genpd_onecell_data *pd_data;
 	struct resource *res;
@@ -394,8 +412,13 @@ static struct scp *init_scp(struct platform_device *pdev,
 	if (!scp)
 		return ERR_PTR(-ENOMEM);
 
-	scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs;
-	scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs;
+	scp->soc_reg.scp_ctrl.pwr_sta_offs = soc_reg->scp_ctrl.pwr_sta_offs;
+	scp->soc_reg.scp_ctrl.pwr_sta2nd_offs =
+			soc_reg->scp_ctrl.pwr_sta2nd_offs;
+	scp->soc_reg.bus_prot.set_offs = soc_reg->bus_prot.set_offs;
+	scp->soc_reg.bus_prot.clr_offs = soc_reg->bus_prot.clr_offs;
+	scp->soc_reg.bus_prot.en_offs = soc_reg->bus_prot.en_offs;
+	scp->soc_reg.bus_prot.sta_offs = soc_reg->bus_prot.sta_offs;
 
 	scp->dev = &pdev->dev;
 
@@ -814,8 +837,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
 	.domains = scp_domain_data_mt2701,
 	.num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
 	.regs = {
-		.pwr_sta_offs = SPM_PWR_STATUS,
-		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+		.scp_ctrl = {
+			.pwr_sta_offs = SPM_PWR_STATUS,
+			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+		},
+		.bus_prot = {
+			.en_offs = INFRA_TOPAXI_PROTECTEN,
+			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
+		},
 	}
 };
 
@@ -825,8 +854,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
 	.subdomains = scp_subdomain_mt6797,
 	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797),
 	.regs = {
-		.pwr_sta_offs = SPM_PWR_STATUS_MT6797,
-		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
+		.scp_ctrl = {
+			.pwr_sta_offs = SPM_PWR_STATUS_MT6797,
+			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
+		},
+		.bus_prot = {
+			.en_offs = INFRA_TOPAXI_PROTECTEN,
+			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
+		},
 	}
 };
 
@@ -834,8 +869,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
 	.domains = scp_domain_data_mt7622,
 	.num_domains = ARRAY_SIZE(scp_domain_data_mt7622),
 	.regs = {
-		.pwr_sta_offs = SPM_PWR_STATUS,
-		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+		.scp_ctrl = {
+			.pwr_sta_offs = SPM_PWR_STATUS,
+			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+		},
+		.bus_prot = {
+			.en_offs = INFRA_TOPAXI_PROTECTEN,
+			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
+		},
 	}
 };
 
@@ -845,8 +886,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
 	.subdomains = scp_subdomain_mt8173,
 	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173),
 	.regs = {
-		.pwr_sta_offs = SPM_PWR_STATUS,
-		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+		.scp_ctrl = {
+			.pwr_sta_offs = SPM_PWR_STATUS,
+			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+		},
+		.bus_prot = {
+			.en_offs = INFRA_TOPAXI_PROTECTEN,
+			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
+		},
 	}
 };
 
diff --git a/include/linux/soc/mediatek/infracfg.h b/include/linux/soc/mediatek/infracfg.h
index a0182ec..c704af5 100644
--- a/include/linux/soc/mediatek/infracfg.h
+++ b/include/linux/soc/mediatek/infracfg.h
@@ -1,6 +1,11 @@
 #ifndef __SOC_MEDIATEK_INFRACFG_H
 #define __SOC_MEDIATEK_INFRACFG_H
 
+#define INFRA_TOPAXI_PROTECTEN		0x0220
+#define INFRA_TOPAXI_PROTECTSTA1	0x0228
+#define INFRA_TOPAXI_PROTECTEN_SET	0x0260
+#define INFRA_TOPAXI_PROTECTEN_CLR	0x0264
+
 #define MT8173_TOP_AXI_PROT_EN_MCI_M2		BIT(0)
 #define MT8173_TOP_AXI_PROT_EN_MM_M0		BIT(1)
 #define MT8173_TOP_AXI_PROT_EN_MM_M1		BIT(2)
@@ -27,7 +32,8 @@
 #define MT7622_TOP_AXI_PROT_EN_WB		(BIT(2) | BIT(6) | \
 						 BIT(7) | BIT(8))
 
-int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask);
-int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask);
-
+int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
+		u32 reg_set, u32 reg_en, u32 reg_sta);
+int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
+		u32 reg_clr, u32 reg_en, u32 reg_sta);
 #endif /* __SOC_MEDIATEK_INFRACFG_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 7/9] soc: mediatek: add dependent clock jpgdec/audio for scpsys
  2017-08-22 10:28 [PATCH v2 0/9] Mediatek MT2712 clock and scpsys support Weiyi Lu
                   ` (5 preceding siblings ...)
  2017-08-22 10:28 ` [PATCH 6/9] soc: mediatek: extend bus protection API Weiyi Lu
@ 2017-08-22 10:28 ` Weiyi Lu
  2017-08-22 10:28 ` [PATCH 8/9] soc: mediatek: add MT2712 scpsys support Weiyi Lu
  2017-08-22 10:28 ` [PATCH 9/9] arm: dts: Add power controller device node of MT2712 Weiyi Lu
  8 siblings, 0 replies; 13+ messages in thread
From: Weiyi Lu @ 2017-08-22 10:28 UTC (permalink / raw)
  To: Matthias Brugger, Stephen Boyd, Rob Herring
  Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu

There are dependent clock jpgdec/audio in scpsys on MT2712,
and will exist three dependent clocks on MT2712 VDEC.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 2569390..28c6e6a 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -84,6 +84,8 @@ enum clk_id {
 	CLK_ETHIF,
 	CLK_VDEC,
 	CLK_HIFSEL,
+	CLK_JPGDEC,
+	CLK_AUDIO,
 	CLK_MAX,
 };
 
@@ -96,10 +98,12 @@ enum clk_id {
 	"ethif",
 	"vdec",
 	"hif_sel",
+	"jpgdec",
+	"audio",
 	NULL,
 };
 
-#define MAX_CLKS	2
+#define MAX_CLKS	3
 
 struct scp_domain_data {
 	const char *name;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 8/9] soc: mediatek: add MT2712 scpsys support
  2017-08-22 10:28 [PATCH v2 0/9] Mediatek MT2712 clock and scpsys support Weiyi Lu
                   ` (6 preceding siblings ...)
  2017-08-22 10:28 ` [PATCH 7/9] soc: mediatek: add dependent clock jpgdec/audio for scpsys Weiyi Lu
@ 2017-08-22 10:28 ` Weiyi Lu
  2017-08-22 10:28 ` [PATCH 9/9] arm: dts: Add power controller device node of MT2712 Weiyi Lu
  8 siblings, 0 replies; 13+ messages in thread
From: Weiyi Lu @ 2017-08-22 10:28 UTC (permalink / raw)
  To: Matthias Brugger, Stephen Boyd, Rob Herring
  Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu

add scpsys driver for MT2712

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 112 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 106 insertions(+), 6 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 28c6e6a..c8abd06 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -21,6 +21,7 @@
 #include <linux/soc/mediatek/infracfg.h>
 
 #include <dt-bindings/power/mt2701-power.h>
+#include <dt-bindings/power/mt2712-power.h>
 #include <dt-bindings/power/mt6797-power.h>
 #include <dt-bindings/power/mt7622-power.h>
 #include <dt-bindings/power/mt8173-power.h>
@@ -32,7 +33,7 @@
 #define SPM_DIS_PWR_CON			0x023c
 #define SPM_CONN_PWR_CON		0x0280
 #define SPM_VEN2_PWR_CON		0x0298
-#define SPM_AUDIO_PWR_CON		0x029c	/* MT8173 */
+#define SPM_AUDIO_PWR_CON		0x029c	/* MT8173, MT2712 */
 #define SPM_BDP_PWR_CON			0x029c	/* MT2701 */
 #define SPM_ETH_PWR_CON			0x02a0
 #define SPM_HIF_PWR_CON			0x02a4
@@ -40,12 +41,12 @@
 #define SPM_MFG_2D_PWR_CON		0x02c0
 #define SPM_MFG_ASYNC_PWR_CON		0x02c4
 #define SPM_USB_PWR_CON			0x02cc
+#define SPM_USB2_PWR_CON		0x02d4	/* MT2712 */
 #define SPM_ETHSYS_PWR_CON		0x02e0	/* MT7622 */
 #define SPM_HIF0_PWR_CON		0x02e4	/* MT7622 */
 #define SPM_HIF1_PWR_CON		0x02e8	/* MT7622 */
 #define SPM_WB_PWR_CON			0x02ec	/* MT7622 */
 
-
 #define SPM_PWR_STATUS			0x060c
 #define SPM_PWR_STATUS_2ND		0x0610
 
@@ -64,12 +65,13 @@
 #define PWR_STATUS_ETH			BIT(15)
 #define PWR_STATUS_HIF			BIT(16)
 #define PWR_STATUS_IFR_MSC		BIT(17)
+#define PWR_STATUS_USB2			BIT(19)	/* MT2712 */
 #define PWR_STATUS_VENC_LT		BIT(20)
 #define PWR_STATUS_VENC			BIT(21)
-#define PWR_STATUS_MFG_2D		BIT(22)
-#define PWR_STATUS_MFG_ASYNC		BIT(23)
-#define PWR_STATUS_AUDIO		BIT(24)
-#define PWR_STATUS_USB			BIT(25)
+#define PWR_STATUS_MFG_2D		BIT(22)	/* MT8173 */
+#define PWR_STATUS_MFG_ASYNC		BIT(23)	/* MT8173 */
+#define PWR_STATUS_AUDIO		BIT(24)	/* MT8173, MT2712 */
+#define PWR_STATUS_USB			BIT(25)	/* MT8173, MT2712 */
 #define PWR_STATUS_ETHSYS		BIT(24)	/* MT7622 */
 #define PWR_STATUS_HIF0			BIT(25)	/* MT7622 */
 #define PWR_STATUS_HIF1			BIT(26)	/* MT7622 */
@@ -618,6 +620,85 @@ static void mtk_register_power_domains(struct platform_device *pdev,
 };
 
 /*
+ * MT2712 power domain support
+ */
+static const struct scp_domain_data scp_domain_data_mt2712[] = {
+	[MT2712_POWER_DOMAIN_MM] = {
+		.name = "mm",
+		.sta_mask = PWR_STATUS_DISP,
+		.ctl_offs = SPM_DIS_PWR_CON,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.clk_id = {CLK_MM},
+		.active_wakeup = true,
+	},
+	[MT2712_POWER_DOMAIN_VDEC] = {
+		.name = "vdec",
+		.sta_mask = PWR_STATUS_VDEC,
+		.ctl_offs = SPM_VDE_PWR_CON,
+		.sram_pdn_bits = GENMASK(8, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.clk_id = {CLK_MM, CLK_VDEC},
+		.active_wakeup = true,
+	},
+	[MT2712_POWER_DOMAIN_VENC] = {
+		.name = "venc",
+		.sta_mask = PWR_STATUS_VENC,
+		.ctl_offs = SPM_VEN_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+		.clk_id = {CLK_MM, CLK_VENC, CLK_JPGDEC},
+		.active_wakeup = true,
+	},
+	[MT2712_POWER_DOMAIN_ISP] = {
+		.name = "isp",
+		.sta_mask = PWR_STATUS_ISP,
+		.ctl_offs = SPM_ISP_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(13, 12),
+		.clk_id = {CLK_MM},
+		.active_wakeup = true,
+	},
+	[MT2712_POWER_DOMAIN_AUDIO] = {
+		.name = "audio",
+		.sta_mask = PWR_STATUS_AUDIO,
+		.ctl_offs = SPM_AUDIO_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+		.clk_id = {CLK_AUDIO},
+		.active_wakeup = true,
+	},
+	[MT2712_POWER_DOMAIN_USB] = {
+		.name = "usb",
+		.sta_mask = PWR_STATUS_USB,
+		.ctl_offs = SPM_USB_PWR_CON,
+		.sram_pdn_bits = GENMASK(10, 8),
+		.sram_pdn_ack_bits = GENMASK(14, 12),
+		.clk_id = {CLK_NONE},
+		.active_wakeup = true,
+	},
+	[MT2712_POWER_DOMAIN_USB2] = {
+		.name = "usb2",
+		.sta_mask = PWR_STATUS_USB2,
+		.ctl_offs = SPM_USB2_PWR_CON,
+		.sram_pdn_bits = GENMASK(10, 8),
+		.sram_pdn_ack_bits = GENMASK(14, 12),
+		.clk_id = {CLK_NONE},
+		.active_wakeup = true,
+	},
+	[MT2712_POWER_DOMAIN_MFG] = {
+		.name = "mfg",
+		.sta_mask = PWR_STATUS_MFG,
+		.ctl_offs = SPM_MFG_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(19, 16),
+		.clk_id = {CLK_MFG},
+		.bus_prot_mask = BIT(14) | BIT(21) | BIT(23),
+		.active_wakeup = true,
+	},
+};
+
+/*
  * MT6797 power domain support
  */
 
@@ -852,6 +933,22 @@ static void mtk_register_power_domains(struct platform_device *pdev,
 	}
 };
 
+static const struct scp_soc_data mt2712_data = {
+	.domains = scp_domain_data_mt2712,
+	.num_domains = ARRAY_SIZE(scp_domain_data_mt2712),
+	.regs = {
+		.scp_ctrl = {
+			.pwr_sta_offs = SPM_PWR_STATUS,
+			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+		},
+		.bus_prot = {
+			.set_offs = INFRA_TOPAXI_PROTECTEN_SET,
+			.clr_offs = INFRA_TOPAXI_PROTECTEN_CLR,
+			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
+		},
+	}
+};
+
 static const struct scp_soc_data mt6797_data = {
 	.domains = scp_domain_data_mt6797,
 	.num_domains = ARRAY_SIZE(scp_domain_data_mt6797),
@@ -910,6 +1007,9 @@ static void mtk_register_power_domains(struct platform_device *pdev,
 		.compatible = "mediatek,mt2701-scpsys",
 		.data = &mt2701_data,
 	}, {
+		.compatible = "mediatek,mt2712-scpsys",
+		.data = &mt2712_data,
+	}, {
 		.compatible = "mediatek,mt6797-scpsys",
 		.data = &mt6797_data,
 	}, {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 9/9] arm: dts: Add power controller device node of MT2712
  2017-08-22 10:28 [PATCH v2 0/9] Mediatek MT2712 clock and scpsys support Weiyi Lu
                   ` (7 preceding siblings ...)
  2017-08-22 10:28 ` [PATCH 8/9] soc: mediatek: add MT2712 scpsys support Weiyi Lu
@ 2017-08-22 10:28 ` Weiyi Lu
  8 siblings, 0 replies; 13+ messages in thread
From: Weiyi Lu @ 2017-08-22 10:28 UTC (permalink / raw)
  To: Matthias Brugger, Stephen Boyd, Rob Herring
  Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu

add power controller node for MT2712

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt2712e.dtsi | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
index 6338a1f..4269ade 100644
--- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
@@ -8,6 +8,7 @@
 #include <dt-bindings/clock/mt2712-clk.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/power/mt2712-power.h>
 #include "mt2712-pinfunc.h"
 
 / {
@@ -165,6 +166,21 @@
 		interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
+	scpsys: scpsys@10006000 {
+		compatible = "mediatek,mt2712-scpsys", "syscon";
+		#power-domain-cells = <1>;
+		reg = <0 0x10006000 0 0x1000>;
+		clocks = <&topckgen CLK_TOP_MM_SEL>,
+			 <&topckgen CLK_TOP_MFG_SEL>,
+			 <&topckgen CLK_TOP_VENC_SEL>,
+			 <&topckgen CLK_TOP_JPGDEC_SEL>,
+			 <&topckgen CLK_TOP_A1SYS_HP_SEL>,
+			 <&topckgen CLK_TOP_VDEC_SEL>;
+		clock-names = "mm", "mfg", "venc",
+			"jpgdec", "audio", "vdec";
+		infracfg = <&infracfg>;
+	};
+
 	uart5: serial@1000f000 {
 		compatible = "mediatek,mt2712-uart",
 			     "mediatek,mt6577-uart";
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 6/9] soc: mediatek: extend bus protection API
  2017-08-22 10:28 ` [PATCH 6/9] soc: mediatek: extend bus protection API Weiyi Lu
@ 2017-10-10 15:45   ` Matthias Brugger
  2017-10-16  6:38     ` Weiyi Lu
  0 siblings, 1 reply; 13+ messages in thread
From: Matthias Brugger @ 2017-10-10 15:45 UTC (permalink / raw)
  To: Weiyi Lu, Stephen Boyd, Rob Herring
  Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
	linux-mediatek, linux-clk, srv_heupstream



On 08/22/2017 12:28 PM, Weiyi Lu wrote:
> MT2712 add "set/clear" bus control register to each control register set
> instead of providing only one "enable" control register, we could avoid
> the read-modify-write racing by using extend API with such new design.
> By improving the mtk-infracfg bus protection implementation to
> support set/clear bus protection control method by IC configuration.
> 
> Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> ---
>   drivers/soc/mediatek/mtk-infracfg.c   | 32 ++++++++++----
>   drivers/soc/mediatek/mtk-scpsys.c     | 81 +++++++++++++++++++++++++++--------
>   include/linux/soc/mediatek/infracfg.h | 12 ++++--
>   3 files changed, 96 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c
> index dba3055..f55ceaa 100644
> --- a/drivers/soc/mediatek/mtk-infracfg.c
> +++ b/drivers/soc/mediatek/mtk-infracfg.c
> @@ -17,30 +17,35 @@
>   #include <linux/soc/mediatek/infracfg.h>
>   #include <asm/processor.h>
>   
> -#define INFRA_TOPAXI_PROTECTEN		0x0220
> -#define INFRA_TOPAXI_PROTECTSTA1	0x0228
> -
>   /**
>    * mtk_infracfg_set_bus_protection - enable bus protection
>    * @regmap: The infracfg regmap
>    * @mask: The mask containing the protection bits to be enabled.
> + * @reg_set: The register used to enable protection bits.
> + * @reg_en: The register used to enable protection bits when there doesn't
> + *          exist reg_set.
> + * @reg_sta: The register used to check the protection bits are enabled.
>    *
>    * This function enables the bus protection bits for disabled power
>    * domains so that the system does not hang when some unit accesses the
>    * bus while in power down.
>    */
> -int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
> +int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
> +		u32 reg_set, u32 reg_en, u32 reg_sta)
>   {
>   	unsigned long expired;
>   	u32 val;
>   	int ret;
>   
> -	regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, mask);
> +	if (reg_set)
> +		regmap_write(infracfg, reg_set, mask);
> +	else
> +		regmap_update_bits(infracfg, reg_en, mask, mask);


This looks to me as if it's slightly over-engineered.
The reg_set and reg_en and reg_sta are the same on all SoCs, so no need to pass 
the value to the infra bus protection set and clear functions.
I think we could just add a boolean overwrite_mask for every SoC and check for this.

Do I miss something?

Regards,
Matthias


>   
>   	expired = jiffies + HZ;
>   
>   	while (1) {
> -		ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
> +		ret = regmap_read(infracfg, reg_sta, &val);
>   		if (ret)
>   			return ret;
>   
> @@ -59,23 +64,32 @@ int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
>    * mtk_infracfg_clear_bus_protection - disable bus protection
>    * @regmap: The infracfg regmap
>    * @mask: The mask containing the protection bits to be disabled.
> + * @reg_clr: The register used to disable protection bits.
> + * @reg_en: The register used to disable protection bits when there doesn't
> + *          exist reg_clr.
> + * @reg_sta: The register used to check the protection bits are disabled.
>    *
>    * This function disables the bus protection bits previously enabled with
>    * mtk_infracfg_set_bus_protection.
>    */
> -int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask)
> +
> +int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
> +		u32 reg_clr, u32 reg_en, u32 reg_sta)
>   {
>   	unsigned long expired;
>   	int ret;
>   
> -	regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
> +	if (reg_clr)
> +		regmap_write(infracfg, reg_clr, mask);
> +	else
> +		regmap_update_bits(infracfg, reg_en, mask, 0);
>   
>   	expired = jiffies + HZ;
>   
>   	while (1) {
>   		u32 val;
>   
> -		ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
> +		ret = regmap_read(infracfg, reg_sta, &val);
>   		if (ret)
>   			return ret;
>   
> diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> index e1ce8b1..2569390 100644
> --- a/drivers/soc/mediatek/mtk-scpsys.c
> +++ b/drivers/soc/mediatek/mtk-scpsys.c
> @@ -127,13 +127,25 @@ struct scp_ctrl_reg {
>   	int pwr_sta2nd_offs;
>   };
>   
> +struct bus_prot_reg {
> +	u32 set_offs;
> +	u32 clr_offs;
> +	u32 en_offs;
> +	u32 sta_offs;
> +};
> +
> +struct soc_reg {
> +	struct scp_ctrl_reg scp_ctrl;
> +	struct bus_prot_reg bus_prot;
> +};
> +
>   struct scp {
>   	struct scp_domain *domains;
>   	struct genpd_onecell_data pd_data;
>   	struct device *dev;
>   	void __iomem *base;
>   	struct regmap *infracfg;
> -	struct scp_ctrl_reg ctrl_reg;
> +	struct soc_reg soc_reg;
>   };
>   
>   struct scp_subdomain {
> @@ -146,16 +158,16 @@ struct scp_soc_data {
>   	int num_domains;
>   	const struct scp_subdomain *subdomains;
>   	int num_subdomains;
> -	const struct scp_ctrl_reg regs;
> +	const struct soc_reg regs;
>   };
>   
>   static int scpsys_domain_is_on(struct scp_domain *scpd)
>   {
>   	struct scp *scp = scpd->scp;
>   
> -	u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) &
> +	u32 status = readl(scp->base + scp->soc_reg.scp_ctrl.pwr_sta_offs) &
>   						scpd->data->sta_mask;
> -	u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) &
> +	u32 status2 = readl(scp->base + scp->soc_reg.scp_ctrl.pwr_sta2nd_offs) &
>   						scpd->data->sta_mask;
>   
>   	/*
> @@ -254,7 +266,10 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
>   
>   	if (scpd->data->bus_prot_mask) {
>   		ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
> -				scpd->data->bus_prot_mask);
> +				scpd->data->bus_prot_mask,
> +				scp->soc_reg.bus_prot.clr_offs,
> +				scp->soc_reg.bus_prot.en_offs,
> +				scp->soc_reg.bus_prot.sta_offs);
>   		if (ret)
>   			goto err_pwr_ack;
>   	}
> @@ -289,7 +304,10 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
>   
>   	if (scpd->data->bus_prot_mask) {
>   		ret = mtk_infracfg_set_bus_protection(scp->infracfg,
> -				scpd->data->bus_prot_mask);
> +				scpd->data->bus_prot_mask,
> +				scp->soc_reg.bus_prot.set_offs,
> +				scp->soc_reg.bus_prot.en_offs,
> +				scp->soc_reg.bus_prot.sta_offs);
>   		if (ret)
>   			goto out;
>   	}
> @@ -382,7 +400,7 @@ static void init_clks(struct platform_device *pdev, struct clk **clk)
>   
>   static struct scp *init_scp(struct platform_device *pdev,
>   			const struct scp_domain_data *scp_domain_data, int num,
> -			const struct scp_ctrl_reg *scp_ctrl_reg)
> +			const struct soc_reg *soc_reg)
>   {
>   	struct genpd_onecell_data *pd_data;
>   	struct resource *res;
> @@ -394,8 +412,13 @@ static struct scp *init_scp(struct platform_device *pdev,
>   	if (!scp)
>   		return ERR_PTR(-ENOMEM);
>   
> -	scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs;
> -	scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs;
> +	scp->soc_reg.scp_ctrl.pwr_sta_offs = soc_reg->scp_ctrl.pwr_sta_offs;
> +	scp->soc_reg.scp_ctrl.pwr_sta2nd_offs =
> +			soc_reg->scp_ctrl.pwr_sta2nd_offs;
> +	scp->soc_reg.bus_prot.set_offs = soc_reg->bus_prot.set_offs;
> +	scp->soc_reg.bus_prot.clr_offs = soc_reg->bus_prot.clr_offs;
> +	scp->soc_reg.bus_prot.en_offs = soc_reg->bus_prot.en_offs;
> +	scp->soc_reg.bus_prot.sta_offs = soc_reg->bus_prot.sta_offs;
>   
>   	scp->dev = &pdev->dev;
>   
> @@ -814,8 +837,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
>   	.domains = scp_domain_data_mt2701,
>   	.num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
>   	.regs = {
> -		.pwr_sta_offs = SPM_PWR_STATUS,
> -		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> +		.scp_ctrl = {
> +			.pwr_sta_offs = SPM_PWR_STATUS,
> +			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> +		},
> +		.bus_prot = {
> +			.en_offs = INFRA_TOPAXI_PROTECTEN,
> +			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
> +		},
>   	}
>   };
>   
> @@ -825,8 +854,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
>   	.subdomains = scp_subdomain_mt6797,
>   	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797),
>   	.regs = {
> -		.pwr_sta_offs = SPM_PWR_STATUS_MT6797,
> -		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
> +		.scp_ctrl = {
> +			.pwr_sta_offs = SPM_PWR_STATUS_MT6797,
> +			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
> +		},
> +		.bus_prot = {
> +			.en_offs = INFRA_TOPAXI_PROTECTEN,
> +			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
> +		},
>   	}
>   };
>   
> @@ -834,8 +869,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
>   	.domains = scp_domain_data_mt7622,
>   	.num_domains = ARRAY_SIZE(scp_domain_data_mt7622),
>   	.regs = {
> -		.pwr_sta_offs = SPM_PWR_STATUS,
> -		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> +		.scp_ctrl = {
> +			.pwr_sta_offs = SPM_PWR_STATUS,
> +			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> +		},
> +		.bus_prot = {
> +			.en_offs = INFRA_TOPAXI_PROTECTEN,
> +			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
> +		},
>   	}
>   };
>   
> @@ -845,8 +886,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
>   	.subdomains = scp_subdomain_mt8173,
>   	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173),
>   	.regs = {
> -		.pwr_sta_offs = SPM_PWR_STATUS,
> -		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> +		.scp_ctrl = {
> +			.pwr_sta_offs = SPM_PWR_STATUS,
> +			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> +		},
> +		.bus_prot = {
> +			.en_offs = INFRA_TOPAXI_PROTECTEN,
> +			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
> +		},
>   	}
>   };
>   
> diff --git a/include/linux/soc/mediatek/infracfg.h b/include/linux/soc/mediatek/infracfg.h
> index a0182ec..c704af5 100644
> --- a/include/linux/soc/mediatek/infracfg.h
> +++ b/include/linux/soc/mediatek/infracfg.h
> @@ -1,6 +1,11 @@
>   #ifndef __SOC_MEDIATEK_INFRACFG_H
>   #define __SOC_MEDIATEK_INFRACFG_H
>   
> +#define INFRA_TOPAXI_PROTECTEN		0x0220
> +#define INFRA_TOPAXI_PROTECTSTA1	0x0228
> +#define INFRA_TOPAXI_PROTECTEN_SET	0x0260
> +#define INFRA_TOPAXI_PROTECTEN_CLR	0x0264

The last two a never used.

> +
>   #define MT8173_TOP_AXI_PROT_EN_MCI_M2		BIT(0)
>   #define MT8173_TOP_AXI_PROT_EN_MM_M0		BIT(1)
>   #define MT8173_TOP_AXI_PROT_EN_MM_M1		BIT(2)
> @@ -27,7 +32,8 @@
>   #define MT7622_TOP_AXI_PROT_EN_WB		(BIT(2) | BIT(6) | \
>   						 BIT(7) | BIT(8))
>   
> -int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask);
> -int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask);
> -
> +int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
> +		u32 reg_set, u32 reg_en, u32 reg_sta);
> +int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
> +		u32 reg_clr, u32 reg_en, u32 reg_sta);
>   #endif /* __SOC_MEDIATEK_INFRACFG_H */
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 6/9] soc: mediatek: extend bus protection API
  2017-10-10 15:45   ` Matthias Brugger
@ 2017-10-16  6:38     ` Weiyi Lu
  2017-10-16 15:04       ` Matthias Brugger
  0 siblings, 1 reply; 13+ messages in thread
From: Weiyi Lu @ 2017-10-16  6:38 UTC (permalink / raw)
  To: Matthias Brugger
  Cc: Stephen Boyd, Rob Herring, James Liao, Fan Chen, devicetree,
	linux-arm-kernel, linux-kernel, linux-mediatek, linux-clk,
	srv_heupstream

On Tue, 2017-10-10 at 17:45 +0200, Matthias Brugger wrote:
> 
> On 08/22/2017 12:28 PM, Weiyi Lu wrote:
> > MT2712 add "set/clear" bus control register to each control register set
> > instead of providing only one "enable" control register, we could avoid
> > the read-modify-write racing by using extend API with such new design.
> > By improving the mtk-infracfg bus protection implementation to
> > support set/clear bus protection control method by IC configuration.
> > 
> > Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> > ---
> >   drivers/soc/mediatek/mtk-infracfg.c   | 32 ++++++++++----
> >   drivers/soc/mediatek/mtk-scpsys.c     | 81 +++++++++++++++++++++++++++--------
> >   include/linux/soc/mediatek/infracfg.h | 12 ++++--
> >   3 files changed, 96 insertions(+), 29 deletions(-)
> > 
> > diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c
> > index dba3055..f55ceaa 100644
> > --- a/drivers/soc/mediatek/mtk-infracfg.c
> > +++ b/drivers/soc/mediatek/mtk-infracfg.c
> > @@ -17,30 +17,35 @@
> >   #include <linux/soc/mediatek/infracfg.h>
> >   #include <asm/processor.h>
> >   with different design
> > -#define INFRA_TOPAXI_PROTECTEN		0x0220
> > -#define INFRA_TOPAXI_PROTECTSTA1	0x0228
> > -
> >   /**
> >    * mtk_infracfg_set_bus_protection - enable bus protection
> >    * @regmap: The infracfg regmap
> >    * @mask: The mask containing the protection bits to be enabled.
> > + * @reg_set: The register used to enable protection bits.
> > + * @reg_en: The register used to enable protection bits when there doesn't
> > + *          exist reg_set.
> > + * @reg_sta: The register used to check the protection bits are enabled.
> >    *
> >    * This function enables the bus protection bits for disabled power
> >    * domains so that the system does not hang when some unit accesses the
> >    * bus while in power down.
> >    */
> > -int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
> > +int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
> > +		u32 reg_set, u32 reg_en, u32 reg_sta)
> >   {
> >   	unsigned long expired;
> >   	u32 val;
> >   	int ret;
> >   
> > -	regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, mask);
> > +	if (reg_set)
> > +		regmap_write(infracfg, reg_set, mask);
> > +	else
> > +		regmap_update_bits(infracfg, reg_en, mask, mask);
> 
> 
> This looks to me as if it's slightly over-engineered.
> The reg_set and reg_en and reg_sta are the same on all SoCs, so no need to pass 
> the value to the infra bus protection set and clear functions.
> I think we could just add a boolean overwrite_mask for every SoC and check for this.
> 
> Do I miss something?
> 
> Regards,
> Matthias
> 

Yes, currently those SoCs already merged in kernel mainline are the
same, but I've checked some mediatek SoCs in near future might be
different.That's the main reason I'd like to make it more flexible by
passing the register address directly than just adding a boolean to
check.Do you think it be better to refine like Part A below, or keep it
simple like Part B only for those SoCs in mainline?

A. 
struct overwrite_reg {
	u32 reg_en;
	u32 reg_set;
	u32 reg_clr;
	u32 reg_sta;
};

int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask
	bool use_set_reg, bool use_overwrite_reg, struct overwrite_reg
new_regs)
{
	unsigned long expired;
	u32 val;
	int ret;
	u32 reg_en, reg_set, reg_sta;

	if (use_overwrite_reg) {
		reg_en = new_regs.reg_en;
		reg_set = new_regs.reg_set;
		reg_sta = new_regs.reg_sta;
	} else {
		reg_en = INFRA_TOPAXI_PROTECTEN;
		reg_set = INFRA_TOPAXI_PROTECTEN_SET;
		reg_sta = INFRA_TOPAXI_PROTECTSTA1;
	}
		
	if (!use_set_reg)
		regmap_update_bits(infracfg, reg_en, mask, mask);
	else
		regmap_write(infracfg, reg_set, mask);

...
}

B.
int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask
	bool use_set_reg)
{
	unsigned long expired;
	u32 val;
	int ret;
		
	if (!use_set_reg)
		regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, mask);
	else
		regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_SET, mask);

...
}

> >   
> >   	expired = jiffies + HZ;
> >   
> >   	while (1) {
> > -		ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
> > +		ret = regmap_read(infracfg, reg_sta, &val);
> >   		if (ret)
> >   			return ret;
> >   
> > @@ -59,23 +64,32 @@ int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
> >    * mtk_infracfg_clear_bus_protection - disable bus protection
> >    * @regmap: The infracfg regmap
> >    * @mask: The mask containing the protection bits to be disabled.
> > + * @reg_clr: The register used to disable protection bits.
> > + * @reg_en: The register used to disable protection bits when there doesn't
> > + *          exist reg_clr.
> > + * @reg_sta: The register used to check the protection bits are disabled.
> >    *
> >    * This function disables the bus protection bits previously enabled with
> >    * mtk_infracfg_set_bus_protection.
> >    */
> > -int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask)
> > +
> > +int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
> > +		u32 reg_clr, u32 reg_en, u32 reg_sta)
> >   {
> >   	unsigned long expired;
> >   	int ret;
> >   
> > -	regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
> > +	if (reg_clr)
> > +		regmap_write(infracfg, reg_clr, mask);
> > +	else
> > +		regmap_update_bits(infracfg, reg_en, mask, 0);
> >   
> >   	expired = jiffies + HZ;
> >   
> >   	while (1) {
> >   		u32 val;
> >   
> > -		ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
> > +		ret = regmap_read(infracfg, reg_sta, &val);
> >   		if (ret)
> >   			return ret;
> >   
> > diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> > index e1ce8b1..2569390 100644
> > --- a/drivers/soc/mediatek/mtk-scpsys.c
> > +++ b/drivers/soc/mediatek/mtk-scpsys.c
> > @@ -127,13 +127,25 @@ struct scp_ctrl_reg {
> >   	int pwr_sta2nd_offs;
> >   };
> >   
> > +struct bus_prot_reg {
> > +	u32 set_offs;
> > +	u32 clr_offs;
> > +	u32 en_offs;
> > +	u32 sta_offs;
> > +};
> > +
> > +struct soc_reg {
> > +	struct scp_ctrl_reg scp_ctrl;
> > +	struct bus_prot_reg bus_prot;
> > +};
> > +
> >   struct scp {
> >   	struct scp_domain *domains;
> >   	struct genpd_onecell_data pd_data;
> >   	struct device *dev;
> >   	void __iomem *base;
> >   	struct regmap *infracfg;
> > -	struct scp_ctrl_reg ctrl_reg;
> > +	struct soc_reg soc_reg;
> >   };
> >   
> >   struct scp_subdomain {
> > @@ -146,16 +158,16 @@ struct scp_soc_data {
> >   	int num_domains;
> >   	const struct scp_subdomain *subdomains;
> >   	int num_subdomains;
> > -	const struct scp_ctrl_reg regs;
> > +	const struct soc_reg regs;
> >   };
> >   
> >   static int scpsys_domain_is_on(struct scp_domain *scpd)
> >   {
> >   	struct scp *scp = scpd->scp;
> >   
> > -	u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) &
> > +	u32 status = readl(scp->base + scp->soc_reg.scp_ctrl.pwr_sta_offs) &
> >   						scpd->data->sta_mask;
> > -	u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) &
> > +	u32 status2 = readl(scp->base + scp->soc_reg.scp_ctrl.pwr_sta2nd_offs) &
> >   						scpd->data->sta_mask;
> >   
> >   	/*
> > @@ -254,7 +266,10 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> >   
> >   	if (scpd->data->bus_prot_mask) {
> >   		ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
> > -				scpd->data->bus_prot_mask);
> > +				scpd->data->bus_prot_mask,
> > +				scp->soc_reg.bus_prot.clr_offs,
> > +				scp->soc_reg.bus_prot.en_offs,
> > +				scp->soc_reg.bus_prot.sta_offs);
> >   		if (ret)
> >   			goto err_pwr_ack;
> >   	}
> > @@ -289,7 +304,10 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> >   
> >   	if (scpd->data->bus_prot_mask) {
> >   		ret = mtk_infracfg_set_bus_protection(scp->infracfg,
> > -				scpd->data->bus_prot_mask);
> > +				scpd->data->bus_prot_mask,
> > +				scp->soc_reg.bus_prot.set_offs,
> > +				scp->soc_reg.bus_prot.en_offs,
> > +				scp->soc_reg.bus_prot.sta_offs);
> >   		if (ret)
> >   			goto out;
> >   	}
> > @@ -382,7 +400,7 @@ static void init_clks(struct platform_device *pdev, struct clk **clk)
> >   
> >   static struct scp *init_scp(struct platform_device *pdev,
> >   			const struct scp_domain_data *scp_domain_data, int num,
> > -			const struct scp_ctrl_reg *scp_ctrl_reg)
> > +			const struct soc_reg *soc_reg)
> >   {
> >   	struct genpd_onecell_data *pd_data;
> >   	struct resource *res;
> > @@ -394,8 +412,13 @@ static struct scp *init_scp(struct platform_device *pdev,
> >   	if (!scp)
> >   		return ERR_PTR(-ENOMEM);
> >   
> > -	scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs;
> > -	scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs;
> > +	scp->soc_reg.scp_ctrl.pwr_sta_offs = soc_reg->scp_ctrl.pwr_sta_offs;
> > +	scp->soc_reg.scp_ctrl.pwr_sta2nd_offs =
> > +			soc_reg->scp_ctrl.pwr_sta2nd_offs;
> > +	scp->soc_reg.bus_prot.set_offs = soc_reg->bus_prot.set_offs;
> > +	scp->soc_reg.bus_prot.clr_offs = soc_reg->bus_prot.clr_offs;
> > +	scp->soc_reg.bus_prot.en_offs = soc_reg->bus_prot.en_offs;
> > +	scp->soc_reg.bus_prot.sta_offs = soc_reg->bus_prot.sta_offs;
> >   
> >   	scp->dev = &pdev->dev;
> >   
> > @@ -814,8 +837,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> >   	.domains = scp_domain_data_mt2701,
> >   	.num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
> >   	.regs = {
> > -		.pwr_sta_offs = SPM_PWR_STATUS,
> > -		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> > +		.scp_ctrl = {
> > +			.pwr_sta_offs = SPM_PWR_STATUS,
> > +			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> > +		},
> > +		.bus_prot = {
> > +			.en_offs = INFRA_TOPAXI_PROTECTEN,
> > +			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
> > +		},
> >   	}
> >   };
> >   
> > @@ -825,8 +854,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> >   	.subdomains = scp_subdomain_mt6797,
> >   	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797),
> >   	.regs = {
> > -		.pwr_sta_offs = SPM_PWR_STATUS_MT6797,
> > -		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
> > +		.scp_ctrl = {
> > +			.pwr_sta_offs = SPM_PWR_STATUS_MT6797,
> > +			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
> > +		},
> > +		.bus_prot = {
> > +			.en_offs = INFRA_TOPAXI_PROTECTEN,
> > +			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
> > +		},
> >   	}
> >   };
> >   
> > @@ -834,8 +869,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> >   	.domains = scp_domain_data_mt7622,
> >   	.num_domains = ARRAY_SIZE(scp_domain_data_mt7622),
> >   	.regs = {
> > -		.pwr_sta_offs = SPM_PWR_STATUS,
> > -		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> > +		.scp_ctrl = {
> > +			.pwr_sta_offs = SPM_PWR_STATUS,
> > +			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> > +		},
> > +		.bus_prot = {
> > +			.en_offs = INFRA_TOPAXI_PROTECTEN,
> > +			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
> > +		},
> >   	}
> >   };
> >   
> > @@ -845,8 +886,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> >   	.subdomains = scp_subdomain_mt8173,
> >   	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173),
> >   	.regs = {
> > -		.pwr_sta_offs = SPM_PWR_STATUS,
> > -		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> > +		.scp_ctrl = {
> > +			.pwr_sta_offs = SPM_PWR_STATUS,
> > +			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> > +		},
> > +		.bus_prot = {
> > +			.en_offs = INFRA_TOPAXI_PROTECTEN,
> > +			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
> > +		},
> >   	}
> >   };
> >   
> > diff --git a/include/linux/soc/mediatek/infracfg.h b/include/linux/soc/mediatek/infracfg.h
> > index a0182ec..c704af5 100644
> > --- a/include/linux/soc/mediatek/infracfg.h
> > +++ b/include/linux/soc/mediatek/infracfg.h
> > @@ -1,6 +1,11 @@
> >   #ifndef __SOC_MEDIATEK_INFRACFG_H
> >   #define __SOC_MEDIATEK_INFRACFG_H
> >   
> > +#define INFRA_TOPAXI_PROTECTEN		0x0220
> > +#define INFRA_TOPAXI_PROTECTSTA1	0x0228
> > +#define INFRA_TOPAXI_PROTECTEN_SET	0x0260
> > +#define INFRA_TOPAXI_PROTECTEN_CLR	0x0264
> 
> The last two a never used.

Currently, the last two would be used in Patch 8 like below, will be
related by how bus protect API is implemented.
+static const struct scp_soc_data mt2712_data = {
+       .domains = scp_domain_data_mt2712,
+       .num_domains = ARRAY_SIZE(scp_domain_data_mt2712),
+       .regs = {
+               .scp_ctrl = {
+                       .pwr_sta_offs = SPM_PWR_STATUS,
+                       .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+               },
+               .bus_prot = {
+                       .set_offs = INFRA_TOPAXI_PROTECTEN_SET,
+                       .clr_offs = INFRA_TOPAXI_PROTECTEN_CLR,
+                       .sta_offs = INFRA_TOPAXI_PROTECTSTA1
+               },
+       }
+};
> 
> > +
> >   #define MT8173_TOP_AXI_PROT_EN_MCI_M2		BIT(0)
> >   #define MT8173_TOP_AXI_PROT_EN_MM_M0		BIT(1)
> >   #define MT8173_TOP_AXI_PROT_EN_MM_M1		BIT(2)
> > @@ -27,7 +32,8 @@
> >   #define MT7622_TOP_AXI_PROT_EN_WB		(BIT(2) | BIT(6) | \
> >   						 BIT(7) | BIT(8))
> >   
> > -int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask);
> > -int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask);
> > -
> > +int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
> > +		u32 reg_set, u32 reg_en, u32 reg_sta);
> > +int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
> > +		u32 reg_clr, u32 reg_en, u32 reg_sta);
> >   #endif /* __SOC_MEDIATEK_INFRACFG_H */
> > 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 6/9] soc: mediatek: extend bus protection API
  2017-10-16  6:38     ` Weiyi Lu
@ 2017-10-16 15:04       ` Matthias Brugger
  0 siblings, 0 replies; 13+ messages in thread
From: Matthias Brugger @ 2017-10-16 15:04 UTC (permalink / raw)
  To: Weiyi Lu
  Cc: Stephen Boyd, Rob Herring, James Liao, Fan Chen, devicetree,
	linux-arm-kernel, linux-kernel, linux-mediatek, linux-clk,
	srv_heupstream



On 10/16/2017 08:38 AM, Weiyi Lu wrote:
> On Tue, 2017-10-10 at 17:45 +0200, Matthias Brugger wrote:
>>
>> On 08/22/2017 12:28 PM, Weiyi Lu wrote:
>>> MT2712 add "set/clear" bus control register to each control register set
>>> instead of providing only one "enable" control register, we could avoid
>>> the read-modify-write racing by using extend API with such new design.
>>> By improving the mtk-infracfg bus protection implementation to
>>> support set/clear bus protection control method by IC configuration.
>>>
>>> Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
>>> ---
>>>    drivers/soc/mediatek/mtk-infracfg.c   | 32 ++++++++++----
>>>    drivers/soc/mediatek/mtk-scpsys.c     | 81 +++++++++++++++++++++++++++--------
>>>    include/linux/soc/mediatek/infracfg.h | 12 ++++--
>>>    3 files changed, 96 insertions(+), 29 deletions(-)
>>>
>>> diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c
>>> index dba3055..f55ceaa 100644
>>> --- a/drivers/soc/mediatek/mtk-infracfg.c
>>> +++ b/drivers/soc/mediatek/mtk-infracfg.c
>>> @@ -17,30 +17,35 @@
>>>    #include <linux/soc/mediatek/infracfg.h>
>>>    #include <asm/processor.h>
>>>    with different design
>>> -#define INFRA_TOPAXI_PROTECTEN		0x0220
>>> -#define INFRA_TOPAXI_PROTECTSTA1	0x0228
>>> -
>>>    /**
>>>     * mtk_infracfg_set_bus_protection - enable bus protection
>>>     * @regmap: The infracfg regmap
>>>     * @mask: The mask containing the protection bits to be enabled.
>>> + * @reg_set: The register used to enable protection bits.
>>> + * @reg_en: The register used to enable protection bits when there doesn't
>>> + *          exist reg_set.
>>> + * @reg_sta: The register used to check the protection bits are enabled.
>>>     *
>>>     * This function enables the bus protection bits for disabled power
>>>     * domains so that the system does not hang when some unit accesses the
>>>     * bus while in power down.
>>>     */
>>> -int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
>>> +int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
>>> +		u32 reg_set, u32 reg_en, u32 reg_sta)
>>>    {
>>>    	unsigned long expired;
>>>    	u32 val;
>>>    	int ret;
>>>    
>>> -	regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, mask);
>>> +	if (reg_set)
>>> +		regmap_write(infracfg, reg_set, mask);
>>> +	else
>>> +		regmap_update_bits(infracfg, reg_en, mask, mask);
>>
>>
>> This looks to me as if it's slightly over-engineered.
>> The reg_set and reg_en and reg_sta are the same on all SoCs, so no need to pass
>> the value to the infra bus protection set and clear functions.
>> I think we could just add a boolean overwrite_mask for every SoC and check for this.
>>
>> Do I miss something?
>>
>> Regards,
>> Matthias
>>
> 
> Yes, currently those SoCs already merged in kernel mainline are the
> same, but I've checked some mediatek SoCs in near future might be
> different.That's the main reason I'd like to make it more flexible by
> passing the register address directly than just adding a boolean to
> check.Do you think it be better to refine like Part A below, or keep it
> simple like Part B only for those SoCs in mainline?
> 

Please use B for now. We can add something like A in the future when we need it.

Thanks!
Matthias


> A.
> struct overwrite_reg {
> 	u32 reg_en;
> 	u32 reg_set;
> 	u32 reg_clr;
> 	u32 reg_sta;
> };
> 
> int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask
> 	bool use_set_reg, bool use_overwrite_reg, struct overwrite_reg
> new_regs)
> {
> 	unsigned long expired;
> 	u32 val;
> 	int ret;
> 	u32 reg_en, reg_set, reg_sta;
> 
> 	if (use_overwrite_reg) {
> 		reg_en = new_regs.reg_en;
> 		reg_set = new_regs.reg_set;
> 		reg_sta = new_regs.reg_sta;
> 	} else {
> 		reg_en = INFRA_TOPAXI_PROTECTEN;
> 		reg_set = INFRA_TOPAXI_PROTECTEN_SET;
> 		reg_sta = INFRA_TOPAXI_PROTECTSTA1;
> 	}
> 		
> 	if (!use_set_reg)
> 		regmap_update_bits(infracfg, reg_en, mask, mask);
> 	else
> 		regmap_write(infracfg, reg_set, mask);
> 
> ...
> }
> 
> B.
> int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask
> 	bool use_set_reg)
> {
> 	unsigned long expired;
> 	u32 val;
> 	int ret;
> 		
> 	if (!use_set_reg)
> 		regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, mask);
> 	else
> 		regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_SET, mask);
> 
> ...
> }
> 
>>>    
>>>    	expired = jiffies + HZ;
>>>    
>>>    	while (1) {
>>> -		ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
>>> +		ret = regmap_read(infracfg, reg_sta, &val);
>>>    		if (ret)
>>>    			return ret;
>>>    
>>> @@ -59,23 +64,32 @@ int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
>>>     * mtk_infracfg_clear_bus_protection - disable bus protection
>>>     * @regmap: The infracfg regmap
>>>     * @mask: The mask containing the protection bits to be disabled.
>>> + * @reg_clr: The register used to disable protection bits.
>>> + * @reg_en: The register used to disable protection bits when there doesn't
>>> + *          exist reg_clr.
>>> + * @reg_sta: The register used to check the protection bits are disabled.
>>>     *
>>>     * This function disables the bus protection bits previously enabled with
>>>     * mtk_infracfg_set_bus_protection.
>>>     */
>>> -int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask)
>>> +
>>> +int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
>>> +		u32 reg_clr, u32 reg_en, u32 reg_sta)
>>>    {
>>>    	unsigned long expired;
>>>    	int ret;
>>>    
>>> -	regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
>>> +	if (reg_clr)
>>> +		regmap_write(infracfg, reg_clr, mask);
>>> +	else
>>> +		regmap_update_bits(infracfg, reg_en, mask, 0);
>>>    
>>>    	expired = jiffies + HZ;
>>>    
>>>    	while (1) {
>>>    		u32 val;
>>>    
>>> -		ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
>>> +		ret = regmap_read(infracfg, reg_sta, &val);
>>>    		if (ret)
>>>    			return ret;
>>>    
>>> diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
>>> index e1ce8b1..2569390 100644
>>> --- a/drivers/soc/mediatek/mtk-scpsys.c
>>> +++ b/drivers/soc/mediatek/mtk-scpsys.c
>>> @@ -127,13 +127,25 @@ struct scp_ctrl_reg {
>>>    	int pwr_sta2nd_offs;
>>>    };
>>>    
>>> +struct bus_prot_reg {
>>> +	u32 set_offs;
>>> +	u32 clr_offs;
>>> +	u32 en_offs;
>>> +	u32 sta_offs;
>>> +};
>>> +
>>> +struct soc_reg {
>>> +	struct scp_ctrl_reg scp_ctrl;
>>> +	struct bus_prot_reg bus_prot;
>>> +};
>>> +
>>>    struct scp {
>>>    	struct scp_domain *domains;
>>>    	struct genpd_onecell_data pd_data;
>>>    	struct device *dev;
>>>    	void __iomem *base;
>>>    	struct regmap *infracfg;
>>> -	struct scp_ctrl_reg ctrl_reg;
>>> +	struct soc_reg soc_reg;
>>>    };
>>>    
>>>    struct scp_subdomain {
>>> @@ -146,16 +158,16 @@ struct scp_soc_data {
>>>    	int num_domains;
>>>    	const struct scp_subdomain *subdomains;
>>>    	int num_subdomains;
>>> -	const struct scp_ctrl_reg regs;
>>> +	const struct soc_reg regs;
>>>    };
>>>    
>>>    static int scpsys_domain_is_on(struct scp_domain *scpd)
>>>    {
>>>    	struct scp *scp = scpd->scp;
>>>    
>>> -	u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) &
>>> +	u32 status = readl(scp->base + scp->soc_reg.scp_ctrl.pwr_sta_offs) &
>>>    						scpd->data->sta_mask;
>>> -	u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) &
>>> +	u32 status2 = readl(scp->base + scp->soc_reg.scp_ctrl.pwr_sta2nd_offs) &
>>>    						scpd->data->sta_mask;
>>>    
>>>    	/*
>>> @@ -254,7 +266,10 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
>>>    
>>>    	if (scpd->data->bus_prot_mask) {
>>>    		ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
>>> -				scpd->data->bus_prot_mask);
>>> +				scpd->data->bus_prot_mask,
>>> +				scp->soc_reg.bus_prot.clr_offs,
>>> +				scp->soc_reg.bus_prot.en_offs,
>>> +				scp->soc_reg.bus_prot.sta_offs);
>>>    		if (ret)
>>>    			goto err_pwr_ack;
>>>    	}
>>> @@ -289,7 +304,10 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
>>>    
>>>    	if (scpd->data->bus_prot_mask) {
>>>    		ret = mtk_infracfg_set_bus_protection(scp->infracfg,
>>> -				scpd->data->bus_prot_mask);
>>> +				scpd->data->bus_prot_mask,
>>> +				scp->soc_reg.bus_prot.set_offs,
>>> +				scp->soc_reg.bus_prot.en_offs,
>>> +				scp->soc_reg.bus_prot.sta_offs);
>>>    		if (ret)
>>>    			goto out;
>>>    	}
>>> @@ -382,7 +400,7 @@ static void init_clks(struct platform_device *pdev, struct clk **clk)
>>>    
>>>    static struct scp *init_scp(struct platform_device *pdev,
>>>    			const struct scp_domain_data *scp_domain_data, int num,
>>> -			const struct scp_ctrl_reg *scp_ctrl_reg)
>>> +			const struct soc_reg *soc_reg)
>>>    {
>>>    	struct genpd_onecell_data *pd_data;
>>>    	struct resource *res;
>>> @@ -394,8 +412,13 @@ static struct scp *init_scp(struct platform_device *pdev,
>>>    	if (!scp)
>>>    		return ERR_PTR(-ENOMEM);
>>>    
>>> -	scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs;
>>> -	scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs;
>>> +	scp->soc_reg.scp_ctrl.pwr_sta_offs = soc_reg->scp_ctrl.pwr_sta_offs;
>>> +	scp->soc_reg.scp_ctrl.pwr_sta2nd_offs =
>>> +			soc_reg->scp_ctrl.pwr_sta2nd_offs;
>>> +	scp->soc_reg.bus_prot.set_offs = soc_reg->bus_prot.set_offs;
>>> +	scp->soc_reg.bus_prot.clr_offs = soc_reg->bus_prot.clr_offs;
>>> +	scp->soc_reg.bus_prot.en_offs = soc_reg->bus_prot.en_offs;
>>> +	scp->soc_reg.bus_prot.sta_offs = soc_reg->bus_prot.sta_offs;
>>>    
>>>    	scp->dev = &pdev->dev;
>>>    
>>> @@ -814,8 +837,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
>>>    	.domains = scp_domain_data_mt2701,
>>>    	.num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
>>>    	.regs = {
>>> -		.pwr_sta_offs = SPM_PWR_STATUS,
>>> -		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
>>> +		.scp_ctrl = {
>>> +			.pwr_sta_offs = SPM_PWR_STATUS,
>>> +			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
>>> +		},
>>> +		.bus_prot = {
>>> +			.en_offs = INFRA_TOPAXI_PROTECTEN,
>>> +			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
>>> +		},
>>>    	}
>>>    };
>>>    
>>> @@ -825,8 +854,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
>>>    	.subdomains = scp_subdomain_mt6797,
>>>    	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797),
>>>    	.regs = {
>>> -		.pwr_sta_offs = SPM_PWR_STATUS_MT6797,
>>> -		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
>>> +		.scp_ctrl = {
>>> +			.pwr_sta_offs = SPM_PWR_STATUS_MT6797,
>>> +			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
>>> +		},
>>> +		.bus_prot = {
>>> +			.en_offs = INFRA_TOPAXI_PROTECTEN,
>>> +			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
>>> +		},
>>>    	}
>>>    };
>>>    
>>> @@ -834,8 +869,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
>>>    	.domains = scp_domain_data_mt7622,
>>>    	.num_domains = ARRAY_SIZE(scp_domain_data_mt7622),
>>>    	.regs = {
>>> -		.pwr_sta_offs = SPM_PWR_STATUS,
>>> -		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
>>> +		.scp_ctrl = {
>>> +			.pwr_sta_offs = SPM_PWR_STATUS,
>>> +			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
>>> +		},
>>> +		.bus_prot = {
>>> +			.en_offs = INFRA_TOPAXI_PROTECTEN,
>>> +			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
>>> +		},
>>>    	}
>>>    };
>>>    
>>> @@ -845,8 +886,14 @@ static void mtk_register_power_domains(struct platform_device *pdev,
>>>    	.subdomains = scp_subdomain_mt8173,
>>>    	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173),
>>>    	.regs = {
>>> -		.pwr_sta_offs = SPM_PWR_STATUS,
>>> -		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
>>> +		.scp_ctrl = {
>>> +			.pwr_sta_offs = SPM_PWR_STATUS,
>>> +			.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
>>> +		},
>>> +		.bus_prot = {
>>> +			.en_offs = INFRA_TOPAXI_PROTECTEN,
>>> +			.sta_offs = INFRA_TOPAXI_PROTECTSTA1
>>> +		},
>>>    	}
>>>    };
>>>    
>>> diff --git a/include/linux/soc/mediatek/infracfg.h b/include/linux/soc/mediatek/infracfg.h
>>> index a0182ec..c704af5 100644
>>> --- a/include/linux/soc/mediatek/infracfg.h
>>> +++ b/include/linux/soc/mediatek/infracfg.h
>>> @@ -1,6 +1,11 @@
>>>    #ifndef __SOC_MEDIATEK_INFRACFG_H
>>>    #define __SOC_MEDIATEK_INFRACFG_H
>>>    
>>> +#define INFRA_TOPAXI_PROTECTEN		0x0220
>>> +#define INFRA_TOPAXI_PROTECTSTA1	0x0228
>>> +#define INFRA_TOPAXI_PROTECTEN_SET	0x0260
>>> +#define INFRA_TOPAXI_PROTECTEN_CLR	0x0264
>>
>> The last two a never used.
> 
> Currently, the last two would be used in Patch 8 like below, will be
> related by how bus protect API is implemented.
> +static const struct scp_soc_data mt2712_data = {
> +       .domains = scp_domain_data_mt2712,
> +       .num_domains = ARRAY_SIZE(scp_domain_data_mt2712),
> +       .regs = {
> +               .scp_ctrl = {
> +                       .pwr_sta_offs = SPM_PWR_STATUS,
> +                       .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> +               },
> +               .bus_prot = {
> +                       .set_offs = INFRA_TOPAXI_PROTECTEN_SET,
> +                       .clr_offs = INFRA_TOPAXI_PROTECTEN_CLR,
> +                       .sta_offs = INFRA_TOPAXI_PROTECTSTA1
> +               },
> +       }
> +};
>>
>>> +
>>>    #define MT8173_TOP_AXI_PROT_EN_MCI_M2		BIT(0)
>>>    #define MT8173_TOP_AXI_PROT_EN_MM_M0		BIT(1)
>>>    #define MT8173_TOP_AXI_PROT_EN_MM_M1		BIT(2)
>>> @@ -27,7 +32,8 @@
>>>    #define MT7622_TOP_AXI_PROT_EN_WB		(BIT(2) | BIT(6) | \
>>>    						 BIT(7) | BIT(8))
>>>    
>>> -int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask);
>>> -int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask);
>>> -
>>> +int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
>>> +		u32 reg_set, u32 reg_en, u32 reg_sta);
>>> +int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
>>> +		u32 reg_clr, u32 reg_en, u32 reg_sta);
>>>    #endif /* __SOC_MEDIATEK_INFRACFG_H */
>>>
> 
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2017-10-16 15:04 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-22 10:28 [PATCH v2 0/9] Mediatek MT2712 clock and scpsys support Weiyi Lu
2017-08-22 10:28 ` [PATCH 1/9] dt-bindings: ARM: Mediatek: Document bindings for MT2712 Weiyi Lu
2017-08-22 10:28 ` [PATCH 2/9] clk: mediatek: Add dt-bindings for MT2712 clocks Weiyi Lu
2017-08-22 10:28 ` [PATCH 3/9] clk: mediatek: Add MT2712 clock support Weiyi Lu
2017-08-22 10:28 ` [PATCH 4/9] arm: dts: mt2712: Add clock controller device nodes Weiyi Lu
2017-08-22 10:28 ` [PATCH 5/9] dt-bindings: soc: add MT2712 power dt-bindings Weiyi Lu
2017-08-22 10:28 ` [PATCH 6/9] soc: mediatek: extend bus protection API Weiyi Lu
2017-10-10 15:45   ` Matthias Brugger
2017-10-16  6:38     ` Weiyi Lu
2017-10-16 15:04       ` Matthias Brugger
2017-08-22 10:28 ` [PATCH 7/9] soc: mediatek: add dependent clock jpgdec/audio for scpsys Weiyi Lu
2017-08-22 10:28 ` [PATCH 8/9] soc: mediatek: add MT2712 scpsys support Weiyi Lu
2017-08-22 10:28 ` [PATCH 9/9] arm: dts: Add power controller device node of MT2712 Weiyi Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).