This patch adds basic SoC support for Mediatek's new 8-core SoC,
MT6765, which is mainly for smartphone application.
Changes in V5:
1. add clk support
Changes in V4:
1. add gic's settings in reg properties
2. remove some patches about dt-bindings since GKH already took them
Changes in V3:
1. split dt-binding document patchs
2. fix mt6765.dtsi warnings with W=12
3. remove uncessary PPI affinity for timer
4. add gicc base for gic dt node
Changes in V2:
1. fix clk properties in uart dts node
2. fix typo in submit title
3. add simple-bus in mt6765.dtsi
4. use correct SPDX license format
Mars Cheng (7):
dt-bindings: clock: mediatek: document clk bindings for Mediatek
MT6765 SoC
dt-bindings: mediatek: Add smi dts binding for Mediatek MT6765 SoC
dt-bindings: mediatek: add MT6765 power dt-bindings
soc: mediatek: add MT6765 scpsys support
clk: mediatek: add mt6765 clock IDs
soc: mediatek: add MT6765 subdomain support
arm64: dts: mediatek: add mt6765 support
Owen Chen (4):
soc: mediatek: add new flow for mtcmos power.
clk: mediatek: fix pll setting
clk: mediatek: add new clkmux register API
clk: mediatek: Add MT6765 clock support
.../bindings/arm/mediatek/mediatek,apmixedsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,audsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,camsys.txt | 27 +
.../bindings/arm/mediatek/mediatek,imgsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,infracfg.txt | 1 +
.../bindings/arm/mediatek/mediatek,mipi0a.txt | 23 +
.../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,vcodecsys.txt | 22 +
.../memory-controllers/mediatek,smi-common.txt | 1 +
.../devicetree/bindings/soc/mediatek/scpsys.txt | 6 +
arch/arm64/boot/dts/mediatek/Makefile | 1 +
arch/arm64/boot/dts/mediatek/mt6765-evb.dts | 33 +
arch/arm64/boot/dts/mediatek/mt6765.dtsi | 253 ++++++
drivers/clk/mediatek/Kconfig | 87 ++
drivers/clk/mediatek/Makefile | 9 +-
drivers/clk/mediatek/clk-mt6765-audio.c | 109 +++
drivers/clk/mediatek/clk-mt6765-cam.c | 83 ++
drivers/clk/mediatek/clk-mt6765-img.c | 79 ++
drivers/clk/mediatek/clk-mt6765-mipi0a.c | 77 ++
drivers/clk/mediatek/clk-mt6765-mm.c | 105 +++
drivers/clk/mediatek/clk-mt6765-vcodec.c | 79 ++
drivers/clk/mediatek/clk-mt6765.c | 963 +++++++++++++++++++++
drivers/clk/mediatek/clk-mtk.c | 41 +
drivers/clk/mediatek/clk-mtk.h | 87 +-
drivers/clk/mediatek/clk-mux.c | 236 +++++
drivers/clk/mediatek/clk-mux.h | 38 +
drivers/clk/mediatek/clk-pll.c | 45 +-
drivers/soc/mediatek/Makefile | 2 +-
drivers/soc/mediatek/mtk-infracfg.c | 178 +++-
drivers/soc/mediatek/mtk-scpsys-ext.c | 535 ++++++++++++
drivers/soc/mediatek/mtk-scpsys.c | 235 ++++-
include/dt-bindings/clock/mt6765-clk.h | 313 +++++++
include/dt-bindings/power/mt6765-power.h | 14 +
include/linux/soc/mediatek/infracfg.h | 9 +-
include/linux/soc/mediatek/scpsys-ext.h | 66 ++
37 files changed, 3681 insertions(+), 82 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mipi0a.txt
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,vcodecsys.txt
create mode 100644 arch/arm64/boot/dts/mediatek/mt6765-evb.dts
create mode 100644 arch/arm64/boot/dts/mediatek/mt6765.dtsi
create mode 100644 drivers/clk/mediatek/clk-mt6765-audio.c
create mode 100644 drivers/clk/mediatek/clk-mt6765-cam.c
create mode 100644 drivers/clk/mediatek/clk-mt6765-img.c
create mode 100644 drivers/clk/mediatek/clk-mt6765-mipi0a.c
create mode 100644 drivers/clk/mediatek/clk-mt6765-mm.c
create mode 100644 drivers/clk/mediatek/clk-mt6765-vcodec.c
create mode 100644 drivers/clk/mediatek/clk-mt6765.c
create mode 100644 drivers/clk/mediatek/clk-mux.c
create mode 100644 drivers/clk/mediatek/clk-mux.h
create mode 100644 drivers/soc/mediatek/mtk-scpsys-ext.c
create mode 100644 include/dt-bindings/clock/mt6765-clk.h
create mode 100644 include/dt-bindings/power/mt6765-power.h
create mode 100644 include/linux/soc/mediatek/scpsys-ext.h
This patch adds the binding documentation for apmixedsys, audsys, camsys,
imgsys, infracfg, mipi0a, topckgen, vcodecsys
Signed-off-by: Mars Cheng <[email protected]>
Signed-off-by: Owen Chen <[email protected]>
---
.../bindings/arm/mediatek/mediatek,apmixedsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,audsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,camsys.txt | 27 ++++++++++++++++++++
.../bindings/arm/mediatek/mediatek,imgsys.txt | 1 +
.../bindings/arm/mediatek/mediatek,infracfg.txt | 1 +
.../bindings/arm/mediatek/mediatek,mipi0a.txt | 23 +++++++++++++++++
.../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,vcodecsys.txt | 22 ++++++++++++++++
10 files changed, 79 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mipi0a.txt
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,vcodecsys.txt
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
index b404d59..44eaeac 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
@@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-apmixedsys"
- "mediatek,mt2712-apmixedsys", "syscon"
+ - "mediatek,mt6765-apmixedsys", "syscon"
- "mediatek,mt6797-apmixedsys"
- "mediatek,mt7622-apmixedsys"
- "mediatek,mt8135-apmixedsys"
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
index 34a69ba..9a8672a 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
@@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-audsys", "syscon"
+ - "mediatek,mt6765-audsys", "syscon"
- "mediatek,mt7622-audsys", "syscon"
- #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt
new file mode 100644
index 0000000..dc75783
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt
@@ -0,0 +1,27 @@
+MediaTek CAMSYS controller
+============================
+
+The MediaTek CAMSYS controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be one of:
+ - "mediatek,mt6765-camsys", "syscon"
+- #clock-cells: Must be 1
+
+The AUDSYS 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.
+
+Required sub-nodes:
+-------
+For common binding part and usage, refer to
+../sonud/mt2701-afe-pcm.txt.
+
+Example:
+
+camsys: camsys@1a000000 {
+ compatible = "mediatek,mt6765-camsys", "syscon";
+ reg = <0 0x1a000000 0 0x1000>;
+ #clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
index 868bd51..c7057d0 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
@@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-imgsys", "syscon"
- "mediatek,mt2712-imgsys", "syscon"
+ - "mediatek,mt6765-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 566f153..ac6aae5 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
@@ -9,6 +9,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-infracfg", "syscon"
- "mediatek,mt2712-infracfg", "syscon"
+ - "mediatek,mt6765-infracfg", "syscon"
- "mediatek,mt6797-infracfg", "syscon"
- "mediatek,mt7622-infracfg", "syscon"
- "mediatek,mt8135-infracfg", "syscon"
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mipi0a.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mipi0a.txt
new file mode 100644
index 0000000..ba5ee7a
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mipi0a.txt
@@ -0,0 +1,23 @@
+Mediatek mipi_rx_ana_csi0a controller
+============================
+
+The Mediatek mipi_rx_ana_csi0a controller provides various clocks
+to the system.
+
+Required Properties:
+
+- compatible: Should be one of:
+ - "mediatek,mt6765-mipi_rx_ana_csi0a", "syscon"
+- #clock-cells: Must be 1
+
+The vencsys 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:
+
+mipi_rx_ana_csi0a: mipi_rx_ana_csi0a@11c10000 {
+ compatible = "mediatek,mt6765-mipi_rx_ana_csi0a", "syscon";
+ reg = <0 0x11c10000 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 4eb8bbe..184f159 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
@@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-mmsys", "syscon"
- "mediatek,mt2712-mmsys", "syscon"
+ - "mediatek,mt6765-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 fb58ca8..8eeb84b 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
@@ -9,6 +9,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-pericfg", "syscon"
- "mediatek,mt2712-pericfg", "syscon"
+ - "mediatek,mt6765-pericfg", "syscon"
- "mediatek,mt7622-pericfg", "syscon"
- "mediatek,mt8135-pericfg", "syscon"
- "mediatek,mt8173-pericfg", "syscon"
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
index 24014a7..3a5cad6 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
@@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-topckgen"
- "mediatek,mt2712-topckgen", "syscon"
+ - "mediatek,mt6765-topckgen", "syscon"
- "mediatek,mt6797-topckgen"
- "mediatek,mt7622-topckgen"
- "mediatek,mt8135-topckgen"
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vcodecsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vcodecsys.txt
new file mode 100644
index 0000000..462889b
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vcodecsys.txt
@@ -0,0 +1,22 @@
+Mediatek vcodecsys controller
+============================
+
+The Mediatek vcodecsys controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be one of:
+ - "mediatek,mt6765-vcodecsys", "syscon"
+- #clock-cells: Must be 1
+
+The vencsys 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:
+
+venc_gcon: venc_gcon@17000000 {
+ compatible = "mediatek,mt6765-vcodecsys", "syscon";
+ reg = <0 0x17000000 0 0x10000>;
+ #clock-cells = <1>;
+};
--
1.7.9.5
Signed-off-by: Mars Cheng <[email protected]>
Signed-off-by: Owen Chen <[email protected]>
---
include/dt-bindings/clock/mt6765-clk.h | 313 ++++++++++++++++++++++++++++++++
1 file changed, 313 insertions(+)
create mode 100644 include/dt-bindings/clock/mt6765-clk.h
diff --git a/include/dt-bindings/clock/mt6765-clk.h b/include/dt-bindings/clock/mt6765-clk.h
new file mode 100644
index 0000000..eb97e56
--- /dev/null
+++ b/include/dt-bindings/clock/mt6765-clk.h
@@ -0,0 +1,313 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _DT_BINDINGS_CLK_MT6765_H
+#define _DT_BINDINGS_CLK_MT6765_H
+
+/* FIX Clks */
+#define CLK_TOP_CLK26M 0
+
+/* APMIXEDSYS */
+#define CLK_APMIXED_ARMPLL_L 0
+#define CLK_APMIXED_ARMPLL 1
+#define CLK_APMIXED_CCIPLL 2
+#define CLK_APMIXED_MAINPLL 3
+#define CLK_APMIXED_MFGPLL 4
+#define CLK_APMIXED_MMPLL 5
+#define CLK_APMIXED_UNIV2PLL 6
+#define CLK_APMIXED_MSDCPLL 7
+#define CLK_APMIXED_APLL1 8
+#define CLK_APMIXED_MPLL 9
+#define CLK_APMIXED_ULPOSC1 10
+#define CLK_APMIXED_ULPOSC2 11
+#define CLK_APMIXED_SSUSB26M 12
+#define CLK_APMIXED_APPLL26M 13
+#define CLK_APMIXED_MIPIC0_26M 14
+#define CLK_APMIXED_MDPLLGP26M 15
+#define CLK_APMIXED_MMSYS_F26M 16
+#define CLK_APMIXED_UFS26M 17
+#define CLK_APMIXED_MIPIC1_26M 18
+#define CLK_APMIXED_MEMPLL26M 19
+#define CLK_APMIXED_CLKSQ_LVPLL_26M 20
+#define CLK_APMIXED_MIPID0_26M 21
+#define CLK_APMIXED_NR_CLK 22
+
+/* TOPCKGEN */
+#define CLK_TOP_SYSPLL 0
+#define CLK_TOP_SYSPLL_D2 1
+#define CLK_TOP_SYSPLL1_D2 2
+#define CLK_TOP_SYSPLL1_D4 3
+#define CLK_TOP_SYSPLL1_D8 4
+#define CLK_TOP_SYSPLL1_D16 5
+#define CLK_TOP_SYSPLL_D3 6
+#define CLK_TOP_SYSPLL2_D2 7
+#define CLK_TOP_SYSPLL2_D4 8
+#define CLK_TOP_SYSPLL2_D8 9
+#define CLK_TOP_SYSPLL_D5 10
+#define CLK_TOP_SYSPLL3_D2 11
+#define CLK_TOP_SYSPLL3_D4 12
+#define CLK_TOP_SYSPLL_D7 13
+#define CLK_TOP_SYSPLL4_D2 14
+#define CLK_TOP_SYSPLL4_D4 15
+#define CLK_TOP_USB20_192M 16
+#define CLK_TOP_USB20_192M_D4 17
+#define CLK_TOP_USB20_192M_D8 18
+#define CLK_TOP_USB20_192M_D16 19
+#define CLK_TOP_USB20_192M_D32 20
+#define CLK_TOP_UNIVPLL 21
+#define CLK_TOP_UNIVPLL_D2 22
+#define CLK_TOP_UNIVPLL1_D2 23
+#define CLK_TOP_UNIVPLL1_D4 24
+#define CLK_TOP_UNIVPLL_D3 25
+#define CLK_TOP_UNIVPLL2_D2 26
+#define CLK_TOP_UNIVPLL2_D4 27
+#define CLK_TOP_UNIVPLL2_D8 28
+#define CLK_TOP_UNIVPLL2_D32 29
+#define CLK_TOP_UNIVPLL_D5 30
+#define CLK_TOP_UNIVPLL3_D2 31
+#define CLK_TOP_UNIVPLL3_D4 32
+#define CLK_TOP_MMPLL 33
+#define CLK_TOP_MMPLL_D2 34
+#define CLK_TOP_MPLL 35
+#define CLK_TOP_DA_MPLL_104M_DIV 36
+#define CLK_TOP_DA_MPLL_52M_DIV 37
+#define CLK_TOP_MFGPLL 38
+#define CLK_TOP_MSDCPLL 39
+#define CLK_TOP_MSDCPLL_D2 40
+#define CLK_TOP_APLL1 41
+#define CLK_TOP_APLL1_D2 42
+#define CLK_TOP_APLL1_D4 43
+#define CLK_TOP_APLL1_D8 44
+#define CLK_TOP_ULPOSC1 45
+#define CLK_TOP_ULPOSC1_D2 46
+#define CLK_TOP_ULPOSC1_D4 47
+#define CLK_TOP_ULPOSC1_D8 48
+#define CLK_TOP_ULPOSC1_D16 49
+#define CLK_TOP_ULPOSC1_D32 50
+#define CLK_TOP_DMPLL 51
+#define CLK_TOP_F_FRTC 52
+#define CLK_TOP_F_F26M 53
+#define CLK_TOP_AXI 54
+#define CLK_TOP_MM 55
+#define CLK_TOP_SCP 56
+#define CLK_TOP_MFG 57
+#define CLK_TOP_F_FUART 58
+#define CLK_TOP_SPI 59
+#define CLK_TOP_MSDC50_0 60
+#define CLK_TOP_MSDC30_1 61
+#define CLK_TOP_AUDIO 62
+#define CLK_TOP_AUD_1 63
+#define CLK_TOP_AUD_ENGEN1 64
+#define CLK_TOP_F_FDISP_PWM 65
+#define CLK_TOP_SSPM 66
+#define CLK_TOP_DXCC 67
+#define CLK_TOP_I2C 68
+#define CLK_TOP_F_FPWM 69
+#define CLK_TOP_F_FSENINF 70
+#define CLK_TOP_AES_FDE 71
+#define CLK_TOP_F_BIST2FPC 72
+#define CLK_TOP_ARMPLL_DIVIDER_PLL0 73
+#define CLK_TOP_ARMPLL_DIVIDER_PLL1 74
+#define CLK_TOP_ARMPLL_DIVIDER_PLL2 75
+#define CLK_TOP_DA_USB20_48M_DIV 76
+#define CLK_TOP_DA_UNIV_48M_DIV 77
+#define CLK_TOP_APLL12_DIV0 78
+#define CLK_TOP_APLL12_DIV1 79
+#define CLK_TOP_APLL12_DIV2 80
+#define CLK_TOP_APLL12_DIV3 81
+#define CLK_TOP_ARMPLL_DIVIDER_PLL0_EN 82
+#define CLK_TOP_ARMPLL_DIVIDER_PLL1_EN 83
+#define CLK_TOP_ARMPLL_DIVIDER_PLL2_EN 84
+#define CLK_TOP_FMEM_OCC_DRC_EN 85
+#define CLK_TOP_USB20_48M_EN 86
+#define CLK_TOP_UNIVPLL_48M_EN 87
+#define CLK_TOP_MPLL_104M_EN 88
+#define CLK_TOP_MPLL_52M_EN 89
+#define CLK_TOP_F_UFS_MP_SAP_CFG_EN 90
+#define CLK_TOP_F_BIST2FPC_EN 91
+#define CLK_TOP_MD_32K 92
+#define CLK_TOP_MD_26M 93
+#define CLK_TOP_MD2_32K 94
+#define CLK_TOP_MD2_26M 95
+#define CLK_TOP_AXI_SEL 96
+#define CLK_TOP_MEM_SEL 97
+#define CLK_TOP_MM_SEL 98
+#define CLK_TOP_SCP_SEL 99
+#define CLK_TOP_MFG_SEL 100
+#define CLK_TOP_ATB_SEL 101
+#define CLK_TOP_CAMTG_SEL 102
+#define CLK_TOP_CAMTG1_SEL 103
+#define CLK_TOP_CAMTG2_SEL 104
+#define CLK_TOP_CAMTG3_SEL 105
+#define CLK_TOP_UART_SEL 106
+#define CLK_TOP_SPI_SEL 107
+#define CLK_TOP_MSDC50_0_HCLK_SEL 108
+#define CLK_TOP_MSDC50_0_SEL 109
+#define CLK_TOP_MSDC30_1_SEL 110
+#define CLK_TOP_AUDIO_SEL 111
+#define CLK_TOP_AUD_INTBUS_SEL 112
+#define CLK_TOP_AUD_1_SEL 113
+#define CLK_TOP_AUD_ENGEN1_SEL 114
+#define CLK_TOP_DISP_PWM_SEL 115
+#define CLK_TOP_SSPM_SEL 116
+#define CLK_TOP_DXCC_SEL 117
+#define CLK_TOP_USB_TOP_SEL 118
+#define CLK_TOP_SPM_SEL 119
+#define CLK_TOP_I2C_SEL 120
+#define CLK_TOP_PWM_SEL 121
+#define CLK_TOP_SENINF_SEL 122
+#define CLK_TOP_AES_FDE_SEL 123
+#define CLK_TOP_PWRAP_ULPOSC_SEL 124
+#define CLK_TOP_CAMTM_SEL 125
+#define CLK_TOP_NR_CLK 126
+
+/* INFRACFG */
+#define CLK_IFR_ICUSB 0
+#define CLK_IFR_GCE 1
+#define CLK_IFR_THERM 2
+#define CLK_IFR_I2C_AP 3
+#define CLK_IFR_I2C_CCU 4
+#define CLK_IFR_I2C_SSPM 5
+#define CLK_IFR_I2C_RSV 6
+#define CLK_IFR_PWM_HCLK 7
+#define CLK_IFR_PWM1 8
+#define CLK_IFR_PWM2 9
+#define CLK_IFR_PWM3 10
+#define CLK_IFR_PWM4 11
+#define CLK_IFR_PWM5 12
+#define CLK_IFR_PWM 13
+#define CLK_IFR_UART0 14
+#define CLK_IFR_UART1 15
+#define CLK_IFR_GCE_26M 16
+#define CLK_IFR_CQ_DMA_FPC 17
+#define CLK_IFR_BTIF 18
+#define CLK_IFR_SPI0 19
+#define CLK_IFR_MSDC0 20
+#define CLK_IFR_MSDC1 21
+#define CLK_IFR_TRNG 22
+#define CLK_IFR_AUXADC 23
+#define CLK_IFR_CCIF1_AP 24
+#define CLK_IFR_CCIF1_MD 25
+#define CLK_IFR_AUXADC_MD 26
+#define CLK_IFR_AP_DMA 27
+#define CLK_IFR_DEVICE_APC 28
+#define CLK_IFR_CCIF_AP 29
+#define CLK_IFR_AUDIO 30
+#define CLK_IFR_CCIF_MD 31
+#define CLK_IFR_RG_PWM_FBCLK6 32
+#define CLK_IFR_DISP_PWM 33
+#define CLK_IFR_CLDMA_BCLK 34
+#define CLK_IFR_AUDIO_26M_BCLK 35
+#define CLK_IFR_SPI1 36
+#define CLK_IFR_I2C4 37
+#define CLK_IFR_SPI2 38
+#define CLK_IFR_SPI3 39
+#define CLK_IFR_I2C5 40
+#define CLK_IFR_I2C5_ARBITER 41
+#define CLK_IFR_I2C5_IMM 42
+#define CLK_IFR_I2C1_ARBITER 43
+#define CLK_IFR_I2C1_IMM 44
+#define CLK_IFR_I2C2_ARBITER 45
+#define CLK_IFR_I2C2_IMM 46
+#define CLK_IFR_SPI4 47
+#define CLK_IFR_SPI5 48
+#define CLK_IFR_CQ_DMA 49
+#define CLK_IFR_FAES_FDE 50
+#define CLK_IFR_MSDC0_SELF 51
+#define CLK_IFR_MSDC1_SELF 52
+#define CLK_IFR_I2C6 53
+#define CLK_IFR_AP_MSDC0 54
+#define CLK_IFR_MD_MSDC0 55
+#define CLK_IFR_MSDC0_SRC 56
+#define CLK_IFR_MSDC1_SRC 57
+#define CLK_IFR_AES_TOP0_BCLK 58
+#define CLK_IFR_MCU_PM_BCLK 59
+#define CLK_IFR_CCIF2_AP 60
+#define CLK_IFR_CCIF2_MD 61
+#define CLK_IFR_CCIF3_AP 62
+#define CLK_IFR_CCIF3_MD 63
+#define CLK_IFR_NR_CLK 64
+
+/* AUDIO */
+#define CLK_AUDIO_AFE 0
+#define CLK_AUDIO_22M 1
+#define CLK_AUDIO_APLL_TUNER 2
+#define CLK_AUDIO_ADC 3
+#define CLK_AUDIO_DAC 4
+#define CLK_AUDIO_DAC_PREDIS 5
+#define CLK_AUDIO_TML 6
+#define CLK_AUDIO_I2S1_BCLK 7
+#define CLK_AUDIO_I2S2_BCLK 8
+#define CLK_AUDIO_I2S3_BCLK 9
+#define CLK_AUDIO_I2S4_BCLK 10
+#define CLK_AUDIO_NR_CLK 11
+
+/* MIPI_RX_ANA_CSI0A */
+
+#define CLK_MIPI0A_CSR_CSI_EN_0A 0
+#define CLK_MIPI0A_NR_CLK 1
+
+/* MMSYS_CONFIG */
+
+#define CLK_MM_MDP_RDMA0 0
+#define CLK_MM_MDP_CCORR0 1
+#define CLK_MM_MDP_RSZ0 2
+#define CLK_MM_MDP_RSZ1 3
+#define CLK_MM_MDP_TDSHP0 4
+#define CLK_MM_MDP_WROT0 5
+#define CLK_MM_MDP_WDMA0 6
+#define CLK_MM_DISP_OVL0 7
+#define CLK_MM_DISP_OVL0_2L 8
+#define CLK_MM_DISP_RSZ0 9
+#define CLK_MM_DISP_RDMA0 10
+#define CLK_MM_DISP_WDMA0 11
+#define CLK_MM_DISP_COLOR0 12
+#define CLK_MM_DISP_CCORR0 13
+#define CLK_MM_DISP_AAL0 14
+#define CLK_MM_DISP_GAMMA0 15
+#define CLK_MM_DISP_DITHER0 16
+#define CLK_MM_DSI0 17
+#define CLK_MM_FAKE_ENG 18
+#define CLK_MM_SMI_COMMON 19
+#define CLK_MM_SMI_LARB0 20
+#define CLK_MM_SMI_COMM0 21
+#define CLK_MM_SMI_COMM1 22
+#define CLK_MM_CAM_MDP 23
+#define CLK_MM_SMI_IMG 24
+#define CLK_MM_SMI_CAM 25
+#define CLK_MM_IMG_DL_RELAY 26
+#define CLK_MM_IMG_DL_ASYNC_TOP 27
+#define CLK_MM_DIG_DSI 28
+#define CLK_MM_F26M_HRTWT 29
+#define CLK_MM_NR_CLK 30
+
+/* IMGSYS */
+
+#define CLK_IMG_LARB2 0
+#define CLK_IMG_DIP 1
+#define CLK_IMG_FDVT 2
+#define CLK_IMG_DPE 3
+#define CLK_IMG_RSC 4
+#define CLK_IMG_NR_CLK 5
+
+/* VENCSYS */
+
+#define CLK_VENC_SET0_LARB 0
+#define CLK_VENC_SET1_VENC 1
+#define CLK_VENC_SET2_JPGENC 2
+#define CLK_VENC_SET3_VDEC 3
+#define CLK_VENC_NR_CLK 4
+
+/* CAMSYS */
+
+#define CLK_CAM_LARB3 0
+#define CLK_CAM_DFP_VAD 1
+#define CLK_CAM 2
+#define CLK_CAMTG 3
+#define CLK_CAM_SENINF 4
+#define CLK_CAMSV0 5
+#define CLK_CAMSV1 6
+#define CLK_CAMSV2 7
+#define CLK_CAM_CCU 8
+#define CLK_CAM_NR_CLK 9
+
+#endif /* _DT_BINDINGS_CLK_MT6765_H */
--
1.7.9.5
This adds basic chip support for MT6765 SoC.
Signed-off-by: Mars Cheng <[email protected]>
Signed-off-by: Owen Chen <[email protected]>
Acked-by: Marc Zyngier <[email protected]>
---
arch/arm64/boot/dts/mediatek/Makefile | 1 +
arch/arm64/boot/dts/mediatek/mt6765-evb.dts | 33 ++++
arch/arm64/boot/dts/mediatek/mt6765.dtsi | 253 +++++++++++++++++++++++++++
3 files changed, 287 insertions(+)
create mode 100644 arch/arm64/boot/dts/mediatek/mt6765-evb.dts
create mode 100644 arch/arm64/boot/dts/mediatek/mt6765.dtsi
diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index ac17f60..7506b0d 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_MEDIATEK) += mt2712-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6755-evb.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt6765-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb
diff --git a/arch/arm64/boot/dts/mediatek/mt6765-evb.dts b/arch/arm64/boot/dts/mediatek/mt6765-evb.dts
new file mode 100644
index 0000000..36dddff2
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt6765-evb.dts
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dts file for Mediatek MT6765
+ *
+ * (C) Copyright 2018. Mediatek, Inc.
+ *
+ * Mars Cheng <[email protected]>
+ */
+
+/dts-v1/;
+#include "mt6765.dtsi"
+
+/ {
+ model = "MediaTek MT6765 EVB";
+ compatible = "mediatek,mt6765-evb", "mediatek,mt6765";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0 0x40000000 0 0x1e800000>;
+ };
+
+ chosen {
+ stdout-path = "serial0:921600n8";
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt6765.dtsi b/arch/arm64/boot/dts/mediatek/mt6765.dtsi
new file mode 100644
index 0000000..37f9f3a
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt6765.dtsi
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dts file for Mediatek MT6765
+ *
+ * (C) Copyright 2018. Mediatek, Inc.
+ *
+ * Mars Cheng <[email protected]>
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/mt6765-clk.h>
+
+/ {
+ compatible = "mediatek,mt6765";
+ interrupt-parent = <&sysirq>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x000>;
+ };
+
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x001>;
+ };
+
+ cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x002>;
+ };
+
+ cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x003>;
+ };
+
+ cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x100>;
+ };
+
+ cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x101>;
+ };
+
+ cpu@102 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x102>;
+ };
+
+ cpu@103 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ enable-method = "psci";
+ reg = <0x103>;
+ };
+ };
+
+ clocks {
+ clk26m: clk26m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <26000000>;
+ };
+
+ clk32k: clk32k {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32000>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "simple-bus";
+ ranges;
+
+ gic: interrupt-controller@c000000 {
+ compatible = "arm,gic-v3";
+ #interrupt-cells = <3>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&gic>;
+ interrupt-controller;
+ reg = <0 0x0c000000 0 0x40000>, /* GICD */
+ <0 0x0c100000 0 0x200000>, /* GICR */
+ <0 0x0c400000 0 0x2000>, /* GICC */
+ <0 0x0c410000 0 0x2000>, /* GICH */
+ <0 0x0c420000 0 0x20000>; /* GICV */
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ topckgen: topckgen@10000000 {
+ compatible = "mediatek,mt6765-topckgen", "syscon";
+ reg = <0 0x10000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ infracfg: infracfg@10001000 {
+ compatible = "mediatek,mt6765-infracfg", "syscon";
+ reg = <0 0x10001000 0 0x1000>;
+ interrupts = <GIC_SPI 147 IRQ_TYPE_EDGE_RISING>;
+ #clock-cells = <1>;
+ };
+
+ pericfg: pericfg@10003000 {
+ compatible = "mediatek,mt6765-pericfg", "syscon";
+ reg = <0 0x10003000 0 0x1000>;
+ };
+
+ scpsys: scpsys@10006000 {
+ compatible = "mediatek,mt6765-scpsys";
+ reg = <0 0x10006000 0 0x1000>; /* spm */
+ #power-domain-cells = <1>;
+ clocks = <&topckgen CLK_TOP_MFG_SEL>,
+ <&topckgen CLK_TOP_MM_SEL>,
+ <&mmsys_config CLK_MM_SMI_COMMON>,
+ <&mmsys_config CLK_MM_SMI_COMM0>,
+ <&mmsys_config CLK_MM_SMI_COMM1>,
+ <&mmsys_config CLK_MM_SMI_LARB0>,
+ <&imgsys CLK_IMG_LARB2>,
+ <&mmsys_config CLK_MM_SMI_IMG>,
+ <&camsys CLK_CAM_LARB3>,
+ <&camsys CLK_CAM_DFP_VAD>,
+ <&camsys CLK_CAM>,
+ <&camsys CLK_CAM_CCU>,
+ <&mmsys_config CLK_MM_SMI_CAM>;
+ clock-names = "mfg", "mm",
+ "mm-0", "mm-1", "mm-2", "mm-3",
+ "isp-0", "isp-1", "cam-0", "cam-1",
+ "cam-2", "cam-3", "cam-4";
+ infracfg = <&infracfg>;
+ smi_comm = <&smi_common>;
+ };
+
+ apmixed: apmixed@1000c000 {
+ compatible = "mediatek,mt6765-apmixedsys", "syscon";
+ reg = <0 0x1000c000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ sysirq: interrupt-controller@10200a80 {
+ compatible = "mediatek,mt6765-sysirq",
+ "mediatek,mt6577-sysirq";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&gic>;
+ reg = <0 0x10200a80 0 0x50>;
+ };
+
+ uart0: serial@11002000 {
+ compatible = "mediatek,mt6765-uart",
+ "mediatek,mt6577-uart";
+ reg = <0 0x11002000 0 0x400>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_IFR_UART0>,
+ <&infracfg CLK_IFR_AP_DMA>;
+ clock-names = "baud", "bus";
+ status = "disabled";
+ };
+
+ uart1: serial@11003000 {
+ compatible = "mediatek,mt6765-uart",
+ "mediatek,mt6577-uart";
+ reg = <0 0x11003000 0 0x400>;
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_IFR_UART1>,
+ <&infracfg CLK_IFR_AP_DMA>;
+ clock-names = "baud", "bus";
+ status = "disabled";
+ };
+
+ audio: audio@11220000 {
+ compatible = "mediatek,mt6765-audsys", "syscon";
+ reg = <0 0x11220000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ mipi_rx_ana_csi0a: mipi_rx_ana_csi0a@11c10000 {
+ compatible = "mediatek,mt6765-mipi_rx_ana_csi0a",
+ "syscon";
+ reg = <0 0x11c10000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ mmsys_config: mmsys_config@14000000 {
+ compatible = "mediatek,mt6765-mmsys", "syscon";
+ reg = <0 0x14000000 0 0x1000>;
+ interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_LOW>;
+ #clock-cells = <1>;
+ };
+
+ smi_common: smi_common@14002000 {
+ compatible = "mediatek,mt6765-smi-common", "syscon";
+ reg = <0 0x14002000 0 0x1000>;
+ };
+
+ imgsys: imgsys@15020000 {
+ compatible = "mediatek,mt6765-imgsys", "syscon";
+ reg = <0 0x15020000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ venc_gcon: venc_gcon@17000000 {
+ compatible = "mediatek,mt6765-vcodecsys", "syscon";
+ reg = <0 0x17000000 0 0x10000>;
+ #clock-cells = <1>;
+ };
+
+ camsys: camsys@1a000000 {
+ compatible = "mediatek,mt6765-camsys", "syscon";
+ reg = <0 0x1a000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+ }; /* end of soc */
+};
--
1.7.9.5
From: Owen Chen <[email protected]>
MT6765 add "set/clr" register for each clkmux setting, and
one update register to trigger value change. It is designed
to prevent read-modify-write racing issue. The sw design
need to add a new API to handle this hw change with a new
mtk_clk_mux/mtk_clk_upd struct in new file "clk-mux"and
clk-upd".
Signed-off-by: Owen Chen <[email protected]>
---
drivers/clk/mediatek/Makefile | 2 +-
drivers/clk/mediatek/clk-mtk.c | 41 +++++++
drivers/clk/mediatek/clk-mtk.h | 85 ++++++++++++---
drivers/clk/mediatek/clk-mux.c | 236 ++++++++++++++++++++++++++++++++++++++++
drivers/clk/mediatek/clk-mux.h | 38 +++++++
5 files changed, 388 insertions(+), 14 deletions(-)
create mode 100644 drivers/clk/mediatek/clk-mux.c
create mode 100644 drivers/clk/mediatek/clk-mux.h
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 844b55d..b97980d 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o
+obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o clk-mux.o
obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index 9c0ae42..50becd0 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -22,6 +22,7 @@
#include <linux/mfd/syscon.h>
#include "clk-mtk.h"
+#include "clk-mux.h"
#include "clk-gate.h"
struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
@@ -144,6 +145,46 @@ int mtk_clk_register_gates(struct device_node *node,
return 0;
}
+int mtk_clk_register_muxes(const struct mtk_mux *muxes,
+ int num, struct device_node *node,
+ spinlock_t *lock,
+ struct clk_onecell_data *clk_data)
+{
+ struct regmap *regmap;
+ struct clk *clk;
+ int i;
+
+ if (!clk_data)
+ return -ENOMEM;
+
+ regmap = syscon_node_to_regmap(node);
+ if (IS_ERR(regmap)) {
+ pr_err("Cannot find regmap for %pOF: %ld\n", node,
+ PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
+
+ for (i = 0; i < num; i++) {
+ const struct mtk_mux *mux = &muxes[i];
+
+ if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mux->id]))
+ continue;
+
+ clk = mtk_clk_register_mux(mux, regmap, lock);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n",
+ mux->name, PTR_ERR(clk));
+ continue;
+ }
+
+ if (clk_data)
+ clk_data->clks[mux->id] = clk;
+ }
+
+ return 0;
+}
+
struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
void __iomem *base, spinlock_t *lock)
{
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index 1882221..61693f6 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -24,7 +24,9 @@
#define MAX_MUX_GATE_BIT 31
#define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1)
-
+#define INVALID_OFS -1
+#define INVALID_SHFT -1
+#define INVALID_WIDTH -1
#define MHZ (1000 * 1000)
struct mtk_fixed_clk {
@@ -84,10 +86,72 @@ struct mtk_composite {
signed char num_parents;
};
+struct mtk_mux {
+ int id;
+ const char *name;
+ const char * const *parent_names;
+ unsigned int flags;
+
+ u32 mux_ofs;
+ u32 set_ofs;
+ u32 clr_ofs;
+ u32 upd_ofs;
+
+ signed char mux_shift;
+ signed char mux_width;
+ signed char gate_shift;
+ signed char upd_shift;
+
+ const struct clk_ops *ops;
+
+ signed char num_parents;
+};
+
/*
* In case the rate change propagation to parent clocks is undesirable,
* this macro allows to specify the clock flags manually.
*/
+#define CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, _mux_set_ofs,\
+ _mux_clr_ofs, _shift, _width, _gate, \
+ _upd_ofs, _upd, _flags, _ops) { \
+ .id = _id, \
+ .name = _name, \
+ .mux_ofs = _mux_ofs, \
+ .set_ofs = _mux_set_ofs, \
+ .clr_ofs = _mux_clr_ofs, \
+ .upd_ofs = _upd_ofs, \
+ .mux_shift = _shift, \
+ .mux_width = _width, \
+ .gate_shift = _gate, \
+ .upd_shift = _upd, \
+ .parent_names = _parents, \
+ .num_parents = ARRAY_SIZE(_parents), \
+ .flags = _flags, \
+ .ops = &_ops, \
+ }
+
+#define MUX_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, _mux_set_ofs,\
+ _mux_clr_ofs, _shift, _width, _gate, \
+ _upd_ofs, _upd, _flags) \
+ CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
+ _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
+ _gate, _upd_ofs, _upd, _flags, \
+ mtk_mux_clr_set_upd_ops)
+
+#define MUX_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, _mux_set_ofs, \
+ _mux_clr_ofs, _shift, _width, _gate, \
+ _upd_ofs, _upd) \
+ MUX_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
+ _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
+ _gate, _upd_ofs, _upd, CLK_SET_RATE_PARENT)
+
+#define MUX_UPD(_id, _name, _parents, _mux_ofs, _shift, _width, _gate, \
+ _upd_ofs, _upd) \
+ CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
+ INVALID_OFS, INVALID_OFS, _shift, _width, \
+ _gate, _upd_ofs, _upd, CLK_SET_RATE_PARENT, \
+ mtk_mux_upd_ops)
+
#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \
_gate, _flags) { \
.id = _id, \
@@ -111,18 +175,8 @@ struct mtk_composite {
MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \
_gate, CLK_SET_RATE_PARENT)
-#define MUX(_id, _name, _parents, _reg, _shift, _width) { \
- .id = _id, \
- .name = _name, \
- .mux_reg = _reg, \
- .mux_shift = _shift, \
- .mux_width = _width, \
- .gate_shift = -1, \
- .divider_shift = -1, \
- .parent_names = _parents, \
- .num_parents = ARRAY_SIZE(_parents), \
- .flags = CLK_SET_RATE_PARENT, \
- }
+#define MUX(_id, _name, _parents, _reg, _shift, _width) \
+ MUX_GATE(_id, _name, _parents, _reg, _shift, _width, INVALID_SHFT)
#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \
_div_width, _div_shift) { \
@@ -138,6 +192,11 @@ struct mtk_composite {
.flags = 0, \
}
+int mtk_clk_register_muxes(const struct mtk_mux *muxes,
+ int num, struct device_node *node,
+ spinlock_t *lock,
+ struct clk_onecell_data *clk_data);
+
struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
void __iomem *base, spinlock_t *lock);
diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c
new file mode 100644
index 0000000..219181b
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mux.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Owen Chen <[email protected]>
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+#include "clk-mux.h"
+
+static inline struct mtk_clk_mux
+ *to_mtk_clk_mux(struct clk_hw *hw)
+{
+ return container_of(hw, struct mtk_clk_mux, hw);
+}
+
+static int mtk_mux_enable(struct clk_hw *hw)
+{
+ struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+ u32 mask = BIT(mux->gate_shift);
+ unsigned long flags = 0;
+
+ if (mux->lock)
+ spin_lock_irqsave(mux->lock, flags);
+
+ regmap_update_bits(mux->regmap, mux->mux_ofs, mask, 0);
+
+ if (mux->lock)
+ spin_unlock_irqrestore(mux->lock, flags);
+ return 0;
+}
+
+static void mtk_mux_disable(struct clk_hw *hw)
+{
+ struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+ u32 mask = BIT(mux->gate_shift);
+ unsigned long flags = 0;
+
+ if (mux->lock)
+ spin_lock_irqsave(mux->lock, flags);
+
+ regmap_update_bits(mux->regmap, mux->mux_ofs, mask, mask);
+
+ if (mux->lock)
+ spin_unlock_irqrestore(mux->lock, flags);
+}
+
+static int mtk_mux_enable_setclr(struct clk_hw *hw)
+{
+ struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+ u32 val;
+ unsigned long flags = 0;
+
+ if (mux->lock)
+ spin_lock_irqsave(mux->lock, flags);
+
+ val = BIT(mux->gate_shift);
+ regmap_write(mux->regmap, mux->mux_clr_ofs, val);
+
+ if (mux->lock)
+ spin_unlock_irqrestore(mux->lock, flags);
+ return 0;
+}
+
+static void mtk_mux_disable_setclr(struct clk_hw *hw)
+{
+ struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+ u32 val;
+ unsigned long flags = 0;
+
+ if (mux->lock)
+ spin_lock_irqsave(mux->lock, flags);
+
+ val = BIT(mux->gate_shift);
+ regmap_write(mux->regmap, mux->mux_set_ofs, val);
+
+ if (mux->lock)
+ spin_unlock_irqrestore(mux->lock, flags);
+}
+
+static int mtk_mux_is_enabled(struct clk_hw *hw)
+{
+ struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+ u32 val = 0;
+
+ if (mux->gate_shift < 0)
+ return true;
+
+ regmap_read(mux->regmap, mux->mux_ofs, &val);
+
+ return (val & BIT(mux->gate_shift)) == 0;
+}
+
+static u8 mtk_mux_get_parent(struct clk_hw *hw)
+{
+ struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+ int num_parents = clk_hw_get_num_parents(hw);
+ u32 mask = GENMASK(mux->mux_width - 1, 0);
+ u32 val;
+
+ regmap_read(mux->regmap, mux->mux_ofs, &val);
+ val = (val >> mux->mux_shift) & mask;
+
+ if (val >= num_parents)
+ return -EINVAL;
+
+ return val;
+}
+
+static int mtk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+ u32 mask = GENMASK(mux->mux_width - 1, 0);
+ u32 val, orig;
+ unsigned long flags = 0;
+
+ if (mux->lock)
+ spin_lock_irqsave(mux->lock, flags);
+
+ regmap_read(mux->regmap, mux->mux_ofs, &val);
+ orig = val;
+ val &= ~(mask << mux->mux_shift);
+ val |= index << mux->mux_shift;
+
+ if (val != orig) {
+ regmap_write(mux->regmap, mux->mux_ofs, val);
+
+ if (mux->upd_shift >= 0)
+ regmap_write(mux->regmap, mux->upd_ofs,
+ BIT(mux->upd_shift));
+ }
+
+ if (mux->lock)
+ spin_unlock_irqrestore(mux->lock, flags);
+
+ return 0;
+}
+
+static int mtk_mux_set_parent_setclr(struct clk_hw *hw, u8 index)
+{
+ struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+ u32 mask = GENMASK(mux->mux_width - 1, 0);
+ u32 val, orig;
+ unsigned long flags = 0;
+
+ if (mux->lock)
+ spin_lock_irqsave(mux->lock, flags);
+
+ regmap_read(mux->regmap, mux->mux_ofs, &val);
+ orig = val;
+ val &= ~(mask << mux->mux_shift);
+ val |= index << mux->mux_shift;
+
+ if (val != orig) {
+ val = (mask << mux->mux_shift);
+ regmap_write(mux->regmap, mux->mux_clr_ofs, val);
+ val = (index << mux->mux_shift);
+ regmap_write(mux->regmap, mux->mux_set_ofs, val);
+
+ if (mux->upd_shift >= 0)
+ regmap_write(mux->regmap, mux->upd_ofs,
+ BIT(mux->upd_shift));
+ }
+
+ if (mux->lock)
+ spin_unlock_irqrestore(mux->lock, flags);
+
+ return 0;
+}
+
+const struct clk_ops mtk_mux_upd_ops = {
+ .enable = mtk_mux_enable,
+ .disable = mtk_mux_disable,
+ .is_enabled = mtk_mux_is_enabled,
+ .get_parent = mtk_mux_get_parent,
+ .set_parent = mtk_mux_set_parent,
+ .determine_rate = NULL,
+};
+
+const struct clk_ops mtk_mux_clr_set_upd_ops = {
+ .enable = mtk_mux_enable_setclr,
+ .disable = mtk_mux_disable_setclr,
+ .is_enabled = mtk_mux_is_enabled,
+ .get_parent = mtk_mux_get_parent,
+ .set_parent = mtk_mux_set_parent_setclr,
+ .determine_rate = NULL,
+};
+
+struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
+ struct regmap *regmap,
+ spinlock_t *lock)
+{
+ struct clk *clk;
+ struct clk_init_data init;
+ struct mtk_clk_mux *mtk_mux = NULL;
+ int ret;
+
+ mtk_mux = kzalloc(sizeof(*mtk_mux), GFP_KERNEL);
+ if (!mtk_mux)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = mux->name;
+ init.flags = (mux->flags) | CLK_SET_RATE_PARENT;
+ init.parent_names = mux->parent_names;
+ init.num_parents = mux->num_parents;
+ init.ops = mux->ops;
+
+ mtk_mux->regmap = regmap;
+ mtk_mux->name = mux->name;
+ mtk_mux->mux_ofs = mux->mux_ofs;
+ mtk_mux->mux_set_ofs = mux->set_ofs;
+ mtk_mux->mux_clr_ofs = mux->clr_ofs;
+ mtk_mux->upd_ofs = mux->upd_ofs;
+ mtk_mux->mux_shift = mux->mux_shift;
+ mtk_mux->mux_width = mux->mux_width;
+ mtk_mux->gate_shift = mux->gate_shift;
+ mtk_mux->upd_shift = mux->upd_shift;
+
+ mtk_mux->lock = lock;
+ mtk_mux->hw.init = &init;
+
+ clk = clk_register(NULL, &mtk_mux->hw);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ goto err_out;
+ }
+
+ return clk;
+err_out:
+ kfree(mtk_mux);
+
+ return ERR_PTR(ret);
+}
diff --git a/drivers/clk/mediatek/clk-mux.h b/drivers/clk/mediatek/clk-mux.h
new file mode 100644
index 0000000..64f8e7c
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mux.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Owen Chen <[email protected]>
+ */
+
+#ifndef __DRV_CLK_MUX_H
+#define __DRV_CLK_MUX_H
+
+#include <linux/clk-provider.h>
+
+struct mtk_clk_mux {
+ struct clk_hw hw;
+ struct regmap *regmap;
+
+ const char *name;
+
+ int mux_set_ofs;
+ int mux_clr_ofs;
+ int mux_ofs;
+ int upd_ofs;
+
+ s8 mux_shift;
+ s8 mux_width;
+ s8 gate_shift;
+ s8 upd_shift;
+
+ spinlock_t *lock;
+};
+
+extern const struct clk_ops mtk_mux_upd_ops;
+extern const struct clk_ops mtk_mux_clr_set_upd_ops;
+
+struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
+ struct regmap *regmap,
+ spinlock_t *lock);
+
+#endif /* __DRV_CLK_MUX_H */
--
1.7.9.5
From: Owen Chen <[email protected]>
MT6765 need multiple register and actions to setup bus
protect.
1. turn on subsys CG before release bus protect to receive
ack.
2. turn off subsys CG after set bus protect and receive
ack.
3. bus protect need not only infracfg but other domain
register to setup. Therefore we add a set/clr APIs
with more customize arguments.
Signed-off-by: Owen Chen <[email protected]>
Signed-off-by: Mars Cheng <[email protected]>
---
drivers/soc/mediatek/Makefile | 2 +-
drivers/soc/mediatek/mtk-infracfg.c | 178 +++++++++++---
drivers/soc/mediatek/mtk-scpsys-ext.c | 405 +++++++++++++++++++++++++++++++
drivers/soc/mediatek/mtk-scpsys.c | 147 +++++++++--
include/linux/soc/mediatek/infracfg.h | 9 +-
include/linux/soc/mediatek/scpsys-ext.h | 66 +++++
6 files changed, 745 insertions(+), 62 deletions(-)
create mode 100644 drivers/soc/mediatek/mtk-scpsys-ext.c
create mode 100644 include/linux/soc/mediatek/scpsys-ext.h
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index 12998b0..9dc6670 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,3 +1,3 @@
-obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
+obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o mtk-scpsys-ext.o
obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c
index 958861c..11eadf8 100644
--- a/drivers/soc/mediatek/mtk-infracfg.c
+++ b/drivers/soc/mediatek/mtk-infracfg.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2015 Pengutronix, Sascha Hauer <[email protected]>
*
@@ -15,6 +16,7 @@
#include <linux/jiffies.h>
#include <linux/regmap.h>
#include <linux/soc/mediatek/infracfg.h>
+#include <linux/soc/mediatek/scpsys-ext.h>
#include <asm/processor.h>
#define MTK_POLL_DELAY_US 10
@@ -26,62 +28,176 @@
#define INFRA_TOPAXI_PROTECTEN_CLR 0x0264
/**
- * mtk_infracfg_set_bus_protection - enable bus protection
- * @regmap: The infracfg regmap
- * @mask: The mask containing the protection bits to be enabled.
- * @reg_update: The boolean flag determines to set the protection bits
- * by regmap_update_bits with enable register(PROTECTEN) or
- * by regmap_write with set register(PROTECTEN_SET).
+ * mtk_generic_set_cmd - enable bus protection with set register
+ * @regmap: The bus protect regmap
+ * @set_ofs: The set register offset to set corresponding bit to 1.
+ * @sta_ofs: The status register offset to show bus protect enable/disable.
+ * @mask: The mask containing the protection bits to be disabled.
*
* 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,
- bool reg_update)
+int mtk_generic_set_cmd(struct regmap *regmap, u32 set_ofs,
+ u32 sta_ofs, u32 mask)
{
u32 val;
int ret;
- if (reg_update)
- regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask,
- mask);
- else
- regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_SET, mask);
+ regmap_write(regmap, set_ofs, mask);
- ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1,
- val, (val & mask) == mask,
- MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ ret = regmap_read_poll_timeout(regmap, sta_ofs, val,
+ (val & mask) == mask,
+ MTK_POLL_DELAY_US,
+ MTK_POLL_TIMEOUT);
return ret;
}
/**
- * mtk_infracfg_clear_bus_protection - disable bus protection
- * @regmap: The infracfg regmap
+ * mtk_generic_clr_cmd - disable bus protection with clr register
+ * @regmap: The bus protect regmap
+ * @clr_ofs: The clr register offset to clear corresponding bit to 0.
+ * @sta_ofs: The status register offset to show bus protect enable/disable.
* @mask: The mask containing the protection bits to be disabled.
- * @reg_update: The boolean flag determines to clear the protection bits
- * by regmap_update_bits with enable register(PROTECTEN) or
- * by regmap_write with clear register(PROTECTEN_CLR).
*
* This function disables the bus protection bits previously enabled with
- * mtk_infracfg_set_bus_protection.
+ * mtk_set_bus_protection.
*/
-int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
- bool reg_update)
+int mtk_generic_clr_cmd(struct regmap *regmap, u32 clr_ofs,
+ u32 sta_ofs, u32 mask)
{
int ret;
u32 val;
- if (reg_update)
- regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
- else
- regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_CLR, mask);
+ regmap_write(regmap, clr_ofs, mask);
- ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1,
- val, !(val & mask),
- MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ ret = regmap_read_poll_timeout(regmap, sta_ofs, val,
+ !(val & mask),
+ MTK_POLL_DELAY_US,
+ MTK_POLL_TIMEOUT);
+ return ret;
+}
+
+/**
+ * mtk_generic_enable_cmd - enable bus protection with upd register
+ * @regmap: The bus protect regmap
+ * @upd_ofs: The update register offset to directly rewrite value to
+ * corresponding bit.
+ * @sta_ofs: The status register offset to show bus protect enable/disable.
+ * @mask: The mask containing the protection bits to be disabled.
+ *
+ * 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_generic_enable_cmd(struct regmap *regmap, u32 upd_ofs,
+ u32 sta_ofs, u32 mask)
+{
+ u32 val;
+ int ret;
+
+ regmap_update_bits(regmap, upd_ofs, mask, mask);
+ ret = regmap_read_poll_timeout(regmap, sta_ofs, val,
+ (val & mask) == mask,
+ MTK_POLL_DELAY_US,
+ MTK_POLL_TIMEOUT);
return ret;
}
+
+/**
+ * mtk_generic_disable_cmd - disable bus protection with updd register
+ * @regmap: The bus protect regmap
+ * @upd_ofs: The update register offset to directly rewrite value to
+ * corresponding bit.
+ * @sta_ofs: The status register offset to show bus protect enable/disable.
+ * @mask: The mask containing the protection bits to be disabled.
+ *
+ * This function disables the bus protection bits previously enabled with
+ * mtk_set_bus_protection.
+ */
+
+int mtk_generic_disable_cmd(struct regmap *regmap, u32 upd_ofs,
+ u32 sta_ofs, u32 mask)
+{
+ int ret;
+ u32 val;
+
+ regmap_update_bits(regmap, upd_ofs, mask, 0);
+
+ ret = regmap_read_poll_timeout(regmap, sta_ofs,
+ val, !(val & mask),
+ MTK_POLL_DELAY_US,
+ MTK_POLL_TIMEOUT);
+ return ret;
+}
+
+/**
+ * mtk_set_bus_protection - enable bus protection
+ * @infracfg: The bus protect regmap, default use infracfg
+ * @mask: The mask containing the protection bits to be 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)
+{
+ return mtk_generic_set_cmd(infracfg,
+ INFRA_TOPAXI_PROTECTEN_SET,
+ INFRA_TOPAXI_PROTECTSTA1,
+ mask);
+}
+
+/**
+ * mtk_clear_bus_protection - disable bus protection
+ * @infracfg: The bus protect regmap, default use infracfg
+ * @mask: The mask containing the protection bits to be disabled.
+ *
+ * This function disables the bus protection bits previously enabled with
+ * mtk_set_bus_protection.
+ */
+
+int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask)
+{
+ return mtk_generic_clr_cmd(infracfg,
+ INFRA_TOPAXI_PROTECTEN_CLR,
+ INFRA_TOPAXI_PROTECTSTA1,
+ mask);
+}
+
+/**
+ * mtk_infracfg_enable_bus_protection - enable bus protection
+ * @infracfg: The bus protect regmap, default use infracfg
+ * @mask: The mask containing the protection bits to be disabled.
+ *
+ * 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_enable_bus_protection(struct regmap *infracfg, u32 mask)
+{
+ return mtk_generic_enable_cmd(infracfg,
+ INFRA_TOPAXI_PROTECTEN,
+ INFRA_TOPAXI_PROTECTSTA1,
+ mask);
+}
+
+/**
+ * mtk_infracfg_disable_bus_protection - disable bus protection
+ * @infracfg: The bus protect regmap, default use infracfg
+ * @mask: The mask containing the protection bits to be disabled.
+ *
+ * This function disables the bus protection bits previously enabled with
+ * mtk_infracfg_set_bus_protection.
+ */
+
+int mtk_infracfg_disable_bus_protection(struct regmap *infracfg, u32 mask)
+{
+ return mtk_generic_disable_cmd(infracfg,
+ INFRA_TOPAXI_PROTECTEN,
+ INFRA_TOPAXI_PROTECTSTA1,
+ mask);
+}
diff --git a/drivers/soc/mediatek/mtk-scpsys-ext.c b/drivers/soc/mediatek/mtk-scpsys-ext.c
new file mode 100644
index 0000000..965e64d
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-scpsys-ext.c
@@ -0,0 +1,405 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Owen Chen <[email protected]>
+ */
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/soc/mediatek/infracfg.h>
+#include <linux/soc/mediatek/scpsys-ext.h>
+
+
+#define MAX_CLKS 10
+#define INFRA "infracfg"
+#define SMIC "smi_comm"
+
+static LIST_HEAD(ext_clk_map_list);
+static LIST_HEAD(ext_attr_map_list);
+
+static struct regmap *infracfg;
+static struct regmap *smi_comm;
+
+enum regmap_type {
+ IFR_TYPE,
+ SMI_TYPE,
+ MAX_REGMAP_TYPE,
+};
+
+/**
+ * struct ext_reg_ctrl - set multiple register for bus protect
+ * @regmap: The bus protect regmap, 1: infracfg, 2: other master regmap
+ * such as SMI.
+ * @set_ofs: The set register offset to set corresponding bit to 1.
+ * @clr_ofs: The clr register offset to clear corresponding bit to 0.
+ * @sta_ofs: The status register offset to show bus protect enable/disable.
+ */
+struct ext_reg_ctrl {
+ enum regmap_type type;
+ u32 set_ofs;
+ u32 clr_ofs;
+ u32 sta_ofs;
+};
+
+/**
+ * struct ext_clk_ctrl - enable multiple clks for bus protect
+ * @clk: The clk need to enable before pwr on/bus protect.
+ * @scpd_n: The name present the scpsys domain where the clks belongs to.
+ * @clk_list: The list node linked to ext_clk_map_list.
+ */
+struct ext_clk_ctrl {
+ struct clk *clk;
+ const char *scpd_n;
+ struct list_head clk_list;
+};
+
+struct bus_mask_ops {
+ int (*set)(struct regmap *regmap, u32 set_ofs,
+ u32 sta_ofs, u32 mask);
+ int (*release)(struct regmap *regmap, u32 clr_ofs,
+ u32 sta_ofs, u32 mask);
+};
+
+static struct scpsys_ext_attr *__get_attr_parent(const char *parent_n)
+{
+ struct scpsys_ext_attr *attr;
+
+ if (!parent_n)
+ return ERR_PTR(-EINVAL);
+
+ list_for_each_entry(attr, &ext_attr_map_list, attr_list) {
+ if (attr->scpd_n && !strcmp(parent_n, attr->scpd_n))
+ return attr;
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+int bus_ctrl_set_release(struct scpsys_ext_attr *attr, bool set)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < MAX_STEP_NUM && attr->mask[i].mask; i++) {
+ struct ext_reg_ctrl *rc = attr->mask[i].regs;
+ struct regmap *regmap;
+
+ if (rc->type == IFR_TYPE)
+ regmap = infracfg;
+ else if (rc->type == SMI_TYPE)
+ regmap = smi_comm;
+ else
+ return -EINVAL;
+
+ if (set)
+ ret = attr->mask[i].ops->set(regmap,
+ rc->set_ofs,
+ rc->sta_ofs,
+ attr->mask[i].mask);
+ else
+ ret = attr->mask[i].ops->release(regmap,
+ rc->clr_ofs,
+ rc->sta_ofs,
+ attr->mask[i].mask);
+ }
+
+ return ret;
+}
+
+int bus_ctrl_set(struct scpsys_ext_attr *attr)
+{
+ return bus_ctrl_set_release(attr, CMD_ENABLE);
+}
+
+int bus_ctrl_release(struct scpsys_ext_attr *attr)
+{
+ return bus_ctrl_set_release(attr, CMD_DISABLE);
+}
+
+int bus_clk_enable_disable(struct scpsys_ext_attr *attr, bool enable)
+{
+ int i = 0;
+ int ret = 0;
+ struct ext_clk_ctrl *cc;
+ struct clk *clk[MAX_CLKS];
+
+ list_for_each_entry(cc, &ext_clk_map_list, clk_list) {
+ if (!strcmp(cc->scpd_n, attr->scpd_n)) {
+ if (enable)
+ ret = clk_prepare_enable(cc->clk);
+ else
+ clk_disable_unprepare(cc->clk);
+
+ if (ret) {
+ pr_err("Failed to %s %s\n",
+ enable ? "enable" : "disable",
+ __clk_get_name(cc->clk));
+ goto err;
+ } else {
+ clk[i] = cc->clk;
+ i++;
+ }
+ }
+ }
+
+ return ret;
+
+err:
+ for (--i; i >= 0; i--)
+ if (enable)
+ clk_disable_unprepare(clk[i]);
+ else
+ clk_prepare_enable(clk[i]);
+ return ret;
+}
+
+int bus_clk_enable(struct scpsys_ext_attr *attr)
+{
+ struct scpsys_ext_attr *attr_p;
+ int ret = 0;
+
+ attr_p = __get_attr_parent(attr->parent_n);
+ if (!IS_ERR(attr_p)) {
+ ret = bus_clk_enable_disable(attr_p, CMD_ENABLE);
+ if (ret)
+ return ret;
+ }
+
+ return bus_clk_enable_disable(attr, CMD_ENABLE);
+}
+
+int bus_clk_disable(struct scpsys_ext_attr *attr)
+{
+ struct scpsys_ext_attr *attr_p;
+ int ret = 0;
+
+ ret = bus_clk_enable_disable(attr, CMD_DISABLE);
+ if (ret)
+ return ret;
+
+ attr_p = __get_attr_parent(attr->parent_n);
+ if (!IS_ERR(attr_p))
+ ret = bus_clk_enable_disable(attr_p, CMD_DISABLE);
+
+ return ret;
+}
+
+const struct bus_mask_ops bus_mask_set_clr_ctrl = {
+ .set = &mtk_generic_set_cmd,
+ .release = &mtk_generic_clr_cmd,
+};
+
+const struct bus_ext_ops ext_bus_ctrl = {
+ .enable = &bus_ctrl_set,
+ .disable = &bus_ctrl_release,
+};
+
+const struct bus_ext_ops ext_cg_ctrl = {
+ .enable = &bus_clk_enable,
+ .disable = &bus_clk_disable,
+};
+
+/*
+ * scpsys bus driver init
+ */
+struct regmap *syscon_regmap_lookup_by_phandle_idx(struct device_node *np,
+ const char *property,
+ int index)
+{
+ struct device_node *syscon_np;
+ struct regmap *regmap;
+
+ if (property)
+ syscon_np = of_parse_phandle(np, property, index);
+ else
+ syscon_np = np;
+
+ if (!syscon_np)
+ return ERR_PTR(-ENODEV);
+
+ regmap = syscon_node_to_regmap(syscon_np);
+ of_node_put(syscon_np);
+
+ return regmap;
+}
+
+int scpsys_ext_regmap_init(struct platform_device *pdev)
+{
+ infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ INFRA);
+ if (IS_ERR(infracfg)) {
+ dev_err(&pdev->dev,
+ "Cannot find bus infracfg controller: %ld\n",
+ PTR_ERR(infracfg));
+ return PTR_ERR(infracfg);
+ }
+
+ smi_comm = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ SMIC);
+ if (IS_ERR(smi_comm)) {
+ dev_err(&pdev->dev,
+ "Cannot find bus smi_comm controller: %ld\n",
+ PTR_ERR(smi_comm));
+ return PTR_ERR(smi_comm);
+ }
+
+ return 0;
+}
+
+static int add_clk_to_list(struct platform_device *pdev,
+ const char *name,
+ const char *scpd_n)
+{
+ struct clk *clk;
+ struct ext_clk_ctrl *cc;
+
+ clk = devm_clk_get(&pdev->dev, name);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "Failed add clk %ld\n", PTR_ERR(clk));
+ return PTR_ERR(clk);
+ }
+
+ cc = kzalloc(sizeof(*cc), GFP_KERNEL);
+ cc->clk = clk;
+ cc->scpd_n = kstrdup(scpd_n, GFP_KERNEL);
+
+ list_add(&cc->clk_list, &ext_clk_map_list);
+
+ return 0;
+}
+
+static int add_cg_to_list(struct platform_device *pdev)
+{
+ int i = 0;
+
+ struct device_node *node = pdev->dev.of_node;
+
+ if (!node) {
+ dev_err(&pdev->dev, "Cannot find topcksys node: %ld\n",
+ PTR_ERR(node));
+ return PTR_ERR(node);
+ }
+
+ do {
+ const char *ck_name;
+ char *temp_str;
+ char *tok[2] = {NULL};
+ int cg_idx = 0;
+ int idx = 0;
+ int ret = 0;
+
+ ret = of_property_read_string_index(node, "clock-names", i,
+ &ck_name);
+ if (ret < 0)
+ break;
+
+ temp_str = kmalloc_array(strlen(ck_name), sizeof(char),
+ GFP_KERNEL | __GFP_ZERO);
+ memcpy(temp_str, ck_name, strlen(ck_name));
+ temp_str[strlen(ck_name)] = '\0';
+ do {
+ tok[idx] = strsep(&temp_str, "-");
+ idx++;
+ } while (temp_str);
+
+ if (idx == 2) {
+ if (kstrtouint(tok[1], 10, &cg_idx))
+ return -EINVAL;
+
+ if (add_clk_to_list(pdev, ck_name, tok[0]))
+ return -EINVAL;
+ }
+ kfree(temp_str);
+ i++;
+ } while (1);
+
+ return 0;
+}
+
+int scpsys_ext_clk_init(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = add_cg_to_list(pdev);
+ if (ret)
+ goto err;
+
+err:
+ return ret;
+}
+
+int scpsys_ext_attr_init(const struct scpsys_ext_data *data)
+{
+ int i, count = 0;
+
+ for (i = 0; i < data->num_attr; i++) {
+ struct scpsys_ext_attr *node = data->attr + i;
+
+ if (!node)
+ continue;
+
+ list_add(&node->attr_list, &ext_attr_map_list);
+ count++;
+ }
+
+ if (!count)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct of_device_id of_scpsys_ext_match_tbl[] = {
+ {
+ /* sentinel */
+ }
+};
+
+struct scpsys_ext_data *scpsys_ext_init(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ struct scpsys_ext_data *data;
+ int ret;
+
+ match = of_match_device(of_scpsys_ext_match_tbl, &pdev->dev);
+
+ if (!match) {
+ dev_err(&pdev->dev, "no match\n");
+ return ERR_CAST(match);
+ }
+
+ data = (struct scpsys_ext_data *)match->data;
+ if (IS_ERR(data)) {
+ dev_err(&pdev->dev, "no match scpext data\n");
+ return ERR_CAST(data);
+ }
+
+ ret = scpsys_ext_attr_init(data);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to init bus attr: %d\n",
+ ret);
+ return ERR_PTR(ret);
+ }
+
+ ret = scpsys_ext_regmap_init(pdev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to init bus register: %d\n",
+ ret);
+ return ERR_PTR(ret);
+ }
+
+ ret = scpsys_ext_clk_init(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to init bus clks: %d\n",
+ ret);
+ return ERR_PTR(ret);
+ }
+
+ return data;
+}
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 4bb6c7a..03df2d6 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2015 Pengutronix, Sascha Hauer <[email protected]>
*
@@ -20,6 +21,7 @@
#include <linux/pm_domain.h>
#include <linux/regulator/consumer.h>
#include <linux/soc/mediatek/infracfg.h>
+#include <linux/soc/mediatek/scpsys-ext.h>
#include <dt-bindings/power/mt2701-power.h>
#include <dt-bindings/power/mt2712-power.h>
@@ -117,6 +119,15 @@ enum clk_id {
#define MAX_CLKS 3
+/**
+ * struct scp_domain_data - scp domain data for power on/off flow
+ * @name: The domain name.
+ * @sta_mask: The mask for power on/off status bit.
+ * @ctl_offs: The offset for main power control register.
+ * @sram_pdn_bits: The mask for sram power control bits.
+ * @sram_pdn_ack_bits The mask for sram power control acked bits.
+ * @caps: The flag for active wake-up action.
+ */
struct scp_domain_data {
const char *name;
u32 sta_mask;
@@ -150,7 +161,7 @@ struct scp {
void __iomem *base;
struct regmap *infracfg;
struct scp_ctrl_reg ctrl_reg;
- bool bus_prot_reg_update;
+ struct scpsys_ext_data *ext_data;
};
struct scp_subdomain {
@@ -164,7 +175,6 @@ struct scp_soc_data {
const struct scp_subdomain *subdomains;
int num_subdomains;
const struct scp_ctrl_reg regs;
- bool bus_prot_reg_update;
};
static int scpsys_domain_is_on(struct scp_domain *scpd)
@@ -236,6 +246,31 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
val |= PWR_RST_B_BIT;
writel(val, ctl_addr);
+ if (!IS_ERR(scp->ext_data)) {
+ struct scpsys_ext_attr *attr;
+
+ attr = scp->ext_data->get_attr(scpd->data->name);
+ if (!IS_ERR(attr) && attr->cg_ops) {
+ ret = attr->cg_ops->enable(attr);
+ if (ret)
+ goto err_ext_clk;
+ }
+ }
+
+ val &= ~scpd->data->sram_pdn_bits;
+ writel(val, ctl_addr);
+
+ if (!IS_ERR(scp->ext_data)) {
+ struct scpsys_ext_attr *attr;
+
+ attr = scp->ext_data->get_attr(scpd->data->name);
+ if (!IS_ERR(attr) && attr->cg_ops) {
+ ret = attr->cg_ops->enable(attr);
+ if (ret)
+ goto err_ext_clk;
+ }
+ }
+
val &= ~scpd->data->sram_pdn_bits;
writel(val, ctl_addr);
@@ -247,25 +282,65 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
* applied here.
*/
usleep_range(12000, 12100);
-
} else {
ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == 0,
MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
if (ret < 0)
- goto err_pwr_ack;
+ goto err_sram;
}
if (scpd->data->bus_prot_mask) {
ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
- scpd->data->bus_prot_mask,
- scp->bus_prot_reg_update);
+ scpd->data->bus_prot_mask);
if (ret)
- goto err_pwr_ack;
+ goto err_sram;
+ }
+
+ if (!IS_ERR(scp->ext_data)) {
+ struct scpsys_ext_attr *attr;
+
+ attr = scp->ext_data->get_attr(scpd->data->name);
+ if (!IS_ERR(attr) && attr->bus_ops) {
+ ret = attr->bus_ops->disable(attr);
+ if (ret)
+ goto err_sram;
+ }
+ }
+
+ if (!IS_ERR(scp->ext_data)) {
+ struct scpsys_ext_attr *attr;
+
+ attr = scp->ext_data->get_attr(scpd->data->name);
+ if (!IS_ERR(attr) && attr->cg_ops) {
+ ret = attr->cg_ops->disable(attr);
+ if (ret)
+ goto err_sram;
+ }
}
return 0;
+err_sram:
+ val = readl(ctl_addr);
+ val |= scpd->data->sram_pdn_bits;
+ writel(val, ctl_addr);
+err_ext_clk:
+ val = readl(ctl_addr);
+ val |= PWR_ISO_BIT;
+ writel(val, ctl_addr);
+
+ val &= ~PWR_RST_B_BIT;
+ writel(val, ctl_addr);
+
+ val |= PWR_CLK_DIS_BIT;
+ writel(val, ctl_addr);
err_pwr_ack:
+ val &= ~PWR_ON_BIT;
+ writel(val, ctl_addr);
+
+ val &= ~PWR_ON_2ND_BIT;
+ writel(val, ctl_addr);
+
for (i = MAX_CLKS - 1; i >= 0; i--) {
if (scpd->clk[i])
clk_disable_unprepare(scpd->clk[i]);
@@ -274,8 +349,6 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
if (scpd->supply)
regulator_disable(scpd->supply);
- dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
-
return ret;
}
@@ -289,14 +362,35 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
int ret, tmp;
int i;
+ if (!IS_ERR(scp->ext_data)) {
+ struct scpsys_ext_attr *attr;
+
+ attr = scp->ext_data->get_attr(scpd->data->name);
+ if (!IS_ERR(attr) && attr->cg_ops) {
+ ret = attr->cg_ops->enable(attr);
+ if (ret)
+ goto out;
+ }
+ }
+
if (scpd->data->bus_prot_mask) {
ret = mtk_infracfg_set_bus_protection(scp->infracfg,
- scpd->data->bus_prot_mask,
- scp->bus_prot_reg_update);
+ scpd->data->bus_prot_mask);
if (ret)
goto out;
}
+ if (!IS_ERR(scp->ext_data)) {
+ struct scpsys_ext_attr *attr;
+
+ attr = scp->ext_data->get_attr(scpd->data->name);
+ if (!IS_ERR(attr) && attr->bus_ops) {
+ ret = attr->bus_ops->enable(attr);
+ if (ret)
+ goto out;
+ }
+ }
+
val = readl(ctl_addr);
val |= scpd->data->sram_pdn_bits;
writel(val, ctl_addr);
@@ -307,6 +401,17 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
if (ret < 0)
goto out;
+ if (!IS_ERR(scp->ext_data)) {
+ struct scpsys_ext_attr *attr;
+
+ attr = scp->ext_data->get_attr(scpd->data->name);
+ if (!IS_ERR(attr) && attr->cg_ops) {
+ ret = attr->cg_ops->disable(attr);
+ if (ret)
+ goto out;
+ }
+ }
+
val |= PWR_ISO_BIT;
writel(val, ctl_addr);
@@ -337,8 +442,6 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
return 0;
out:
- dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name);
-
return ret;
}
@@ -352,8 +455,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,
- bool bus_prot_reg_update)
+ const struct scp_ctrl_reg *scp_ctrl_reg)
{
struct genpd_onecell_data *pd_data;
struct resource *res;
@@ -367,11 +469,10 @@ static struct scp *init_scp(struct platform_device *pdev,
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->bus_prot_reg_update = bus_prot_reg_update;
-
scp->dev = &pdev->dev;
+ scp->ext_data = scpsys_ext_init(pdev);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
scp->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(scp->base))
@@ -1021,7 +1122,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
},
- .bus_prot_reg_update = true,
};
static const struct scp_soc_data mt2712_data = {
@@ -1033,7 +1133,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
},
- .bus_prot_reg_update = false,
};
static const struct scp_soc_data mt6765_data = {
@@ -1056,7 +1155,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.pwr_sta_offs = SPM_PWR_STATUS_MT6797,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
},
- .bus_prot_reg_update = true,
};
static const struct scp_soc_data mt7622_data = {
@@ -1066,7 +1164,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
},
- .bus_prot_reg_update = true,
};
static const struct scp_soc_data mt7623a_data = {
@@ -1076,7 +1173,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
},
- .bus_prot_reg_update = true,
};
static const struct scp_soc_data mt8173_data = {
@@ -1088,7 +1184,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
},
- .bus_prot_reg_update = true,
};
/*
@@ -1132,8 +1227,8 @@ static int scpsys_probe(struct platform_device *pdev)
soc = of_device_get_match_data(&pdev->dev);
- scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs,
- soc->bus_prot_reg_update);
+ scp = init_scp(pdev, soc->domains, soc->num_domains,
+ &soc->regs);
if (IS_ERR(scp))
return PTR_ERR(scp);
diff --git a/include/linux/soc/mediatek/infracfg.h b/include/linux/soc/mediatek/infracfg.h
index fd25f01..bfad082 100644
--- a/include/linux/soc/mediatek/infracfg.h
+++ b/include/linux/soc/mediatek/infracfg.h
@@ -32,8 +32,9 @@
#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,
- bool reg_update);
-int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
- bool reg_update);
+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_enable_bus_protection(struct regmap *infracfg, u32 mask);
+int mtk_infracfg_disable_bus_protection(struct regmap *infracfg, u32 mask);
+
#endif /* __SOC_MEDIATEK_INFRACFG_H */
diff --git a/include/linux/soc/mediatek/scpsys-ext.h b/include/linux/soc/mediatek/scpsys-ext.h
new file mode 100644
index 0000000..99b5ff1
--- /dev/null
+++ b/include/linux/soc/mediatek/scpsys-ext.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SOC_MEDIATEK_SCPSYS_EXT_H
+#define __SOC_MEDIATEK_SCPSYS_EXT_H
+
+#include <linux/platform_device.h>
+
+#define CMD_ENABLE 1
+#define CMD_DISABLE 0
+
+#define MAX_STEP_NUM 4
+
+/**
+ * struct bus_mask - set mask and corresponding operation for bus protect
+ * @regs: The register set of bus register control, including set/clr/sta.
+ * @mask: The mask set for bus protect.
+ * @flag: The flag to idetify which operation we take for bus protect.
+ */
+struct bus_mask {
+ struct ext_reg_ctrl *regs;
+ u32 mask;
+ const struct bus_mask_ops *ops;
+};
+
+/**
+ * struct scpsys_ext_attr - extended attribute for bus protect and further
+ * operand.
+ *
+ * @scpd_n: The name present the scpsys domain where the clks belongs to.
+ * @mask: The mask set for bus protect.
+ * @bus_ops: The operation we take for bus protect.
+ * @cg_ops: The operation we take for cg on/off.
+ * @attr_list: The list node linked to ext_attr_map_list.
+ */
+struct scpsys_ext_attr {
+ const char *scpd_n;
+ struct bus_mask mask[MAX_STEP_NUM];
+ const char *parent_n;
+ const struct bus_ext_ops *bus_ops;
+ const struct bus_ext_ops *cg_ops;
+
+ struct list_head attr_list;
+};
+
+struct scpsys_ext_data {
+ struct scpsys_ext_attr *attr;
+ u8 num_attr;
+ struct scpsys_ext_attr * (*get_attr)(const char *scpd_n);
+};
+
+struct bus_ext_ops {
+ int (*enable)(struct scpsys_ext_attr *attr);
+ int (*disable)(struct scpsys_ext_attr *attr);
+};
+
+int mtk_generic_set_cmd(struct regmap *regmap, u32 set_ofs,
+ u32 sta_ofs, u32 mask);
+int mtk_generic_clr_cmd(struct regmap *regmap, u32 clr_ofs,
+ u32 sta_ofs, u32 mask);
+int mtk_generic_enable_cmd(struct regmap *regmap, u32 upd_ofs,
+ u32 sta_ofs, u32 mask);
+int mtk_generic_disable_cmd(struct regmap *regmap, u32 upd_ofs,
+ u32 sta_ofs, u32 mask);
+
+struct scpsys_ext_data *scpsys_ext_init(struct platform_device *pdev);
+
+#endif /* __SOC_MEDIATEK_SCPSYS_EXT_H */
--
1.7.9.5
This patch adds MT6765 smi binding document
Signed-off-by: Mars Cheng <[email protected]>
Signed-off-by: Owen Chen <[email protected]>
---
.../memory-controllers/mediatek,smi-common.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
index aa614b2..0bf64f5 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
@@ -15,6 +15,7 @@ not needed for SMI generation 2.
Required properties:
- compatible : must be one of :
"mediatek,mt2701-smi-common"
+ "mediatek,mt6765-smi-common", "syscon"
"mediatek,mt8173-smi-common"
- reg : the register and size of the SMI block.
- power-domains : a phandle to the power domain of this local arbiter.
--
1.7.9.5
From: Owen Chen <[email protected]>
Add MT6765 clock support, include topckgen, apmixedsys,
infracfg, and subsystem clocks.
Signed-off-by: Owen Chen <[email protected]>
Signed-off-by: Mars Cheng <[email protected]>
---
drivers/clk/mediatek/Kconfig | 87 +++
drivers/clk/mediatek/Makefile | 7 +
drivers/clk/mediatek/clk-mt6765-audio.c | 109 ++++
drivers/clk/mediatek/clk-mt6765-cam.c | 83 +++
drivers/clk/mediatek/clk-mt6765-img.c | 79 +++
drivers/clk/mediatek/clk-mt6765-mipi0a.c | 77 +++
drivers/clk/mediatek/clk-mt6765-mm.c | 105 ++++
drivers/clk/mediatek/clk-mt6765-vcodec.c | 79 +++
drivers/clk/mediatek/clk-mt6765.c | 963 ++++++++++++++++++++++++++++++
9 files changed, 1589 insertions(+)
create mode 100644 drivers/clk/mediatek/clk-mt6765-audio.c
create mode 100644 drivers/clk/mediatek/clk-mt6765-cam.c
create mode 100644 drivers/clk/mediatek/clk-mt6765-img.c
create mode 100644 drivers/clk/mediatek/clk-mt6765-mipi0a.c
create mode 100644 drivers/clk/mediatek/clk-mt6765-mm.c
create mode 100644 drivers/clk/mediatek/clk-mt6765-vcodec.c
create mode 100644 drivers/clk/mediatek/clk-mt6765.c
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 3dd1dab..95e5e52 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -193,4 +193,91 @@ config COMMON_CLK_MT8173
default ARCH_MEDIATEK
---help---
This driver supports MediaTek MT8173 clocks.
+
+config COMMON_CLK_MT6765
+ bool "Clock driver for MediaTek MT6765"
+ depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
+ select COMMON_CLK_MEDIATEK
+ default ARCH_MEDIATEK && ARM64
+ help
+ This driver supports MediaTek MT6765 basic clocks.
+
+config COMMON_CLK_MT6765_AUDIOSYS
+ bool "Clock driver for MediaTek MT6765 audiosys"
+ depends on COMMON_CLK_MT6765
+ help
+ This driver supports MediaTek MT6765 audiosys clocks.
+
+config COMMON_CLK_MT6765_CAMSYS
+ bool "Clock driver for MediaTek MT6765 camsys"
+ depends on COMMON_CLK_MT6765
+ help
+ This driver supports MediaTek MT6765 camsys clocks.
+
+config COMMON_CLK_MT6765_GCESYS
+ bool "Clock driver for MediaTek MT6765 gcesys"
+ depends on COMMON_CLK_MT6765
+ help
+ This driver supports MediaTek MT6765 gcesys clocks.
+
+config COMMON_CLK_MT6765_MMSYS
+ bool "Clock driver for MediaTek MT6765 mmsys"
+ depends on COMMON_CLK_MT6765
+ help
+ This driver supports MediaTek MT6765 mmsys clocks.
+
+config COMMON_CLK_MT6765_IMGSYS
+ bool "Clock driver for MediaTek MT6765 imgsys"
+ depends on COMMON_CLK_MT6765
+ help
+ This driver supports MediaTek MT6765 imgsys clocks.
+
+config COMMON_CLK_MT6765_VCODECSYS
+ bool "Clock driver for MediaTek MT6765 vcodecsys"
+ depends on COMMON_CLK_MT6765
+ help
+ This driver supports MediaTek MT6765 vcodecsys clocks.
+
+config COMMON_CLK_MT6765_MFGSYS
+ bool "Clock driver for MediaTek MT6765 mfgsys"
+ depends on COMMON_CLK_MT6765
+ help
+ This driver supports MediaTek MT6765 mfgsys clocks.
+
+config COMMON_CLK_MT6765_MIPI0ASYS
+ bool "Clock driver for MediaTek MT6765 mipi0asys"
+ depends on COMMON_CLK_MT6765
+ help
+ This driver supports MediaTek MT6765 mipi0asys clocks.
+
+config COMMON_CLK_MT6765_MIPI0BSYS
+ bool "Clock driver for MediaTek MT6765 mipi0bsys"
+ depends on COMMON_CLK_MT6765
+ help
+ This driver supports MediaTek MT6765 mipi0bsys clocks.
+
+config COMMON_CLK_MT6765_MIPI1ASYS
+ bool "Clock driver for MediaTek MT6765 mipi1asys"
+ depends on COMMON_CLK_MT6765
+ help
+ This driver supports MediaTek MT6765 mipi1asys clocks.
+
+config COMMON_CLK_MT6765_MIPI1BSYS
+ bool "Clock driver for MediaTek MT6765 mipi1bsys"
+ depends on COMMON_CLK_MT6765
+ help
+ This driver supports MediaTek MT6765 mipi1bsys clocks.
+
+config COMMON_CLK_MT6765_MIPI2ASYS
+ bool "Clock driver for MediaTek MT6765 mipi2asys"
+ depends on COMMON_CLK_MT6765
+ help
+ This driver supports MediaTek MT6765 mipi2asys clocks.
+
+config COMMON_CLK_MT6765_MIPI2BSYS
+ bool "Clock driver for MediaTek MT6765 mipi2bsys"
+ depends on COMMON_CLK_MT6765
+ help
+ This driver supports MediaTek MT6765 mipi2bsys clocks.
+
endmenu
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index b97980d..b455a8e 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,5 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o clk-mux.o
+obj-$(CONFIG_COMMON_CLK_MT6765) += clk-mt6765.o
+obj-$(CONFIG_COMMON_CLK_MT6765_AUDIOSYS) += clk-mt6765-audio.o
+obj-$(CONFIG_COMMON_CLK_MT6765_CAMSYS) += clk-mt6765-cam.o
+obj-$(CONFIG_COMMON_CLK_MT6765_IMGSYS) += clk-mt6765-img.o
+obj-$(CONFIG_COMMON_CLK_MT6765_MIPI0ASYS) += clk-mt6765-mipi0a.o
+obj-$(CONFIG_COMMON_CLK_MT6765_MMSYS) += clk-mt6765-mm.o
+obj-$(CONFIG_COMMON_CLK_MT6765_VCODECSYS) += clk-mt6765-vcodec.o
obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o
diff --git a/drivers/clk/mediatek/clk-mt6765-audio.c b/drivers/clk/mediatek/clk-mt6765-audio.c
new file mode 100644
index 0000000..0515e2b
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6765-audio.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Owen Chen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt6765-clk.h>
+
+static const struct mtk_gate_regs audio0_cg_regs = {
+ .set_ofs = 0x0,
+ .clr_ofs = 0x0,
+ .sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs audio1_cg_regs = {
+ .set_ofs = 0x4,
+ .clr_ofs = 0x4,
+ .sta_ofs = 0x4,
+};
+
+#define GATE_AUDIO0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &audio0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr, \
+ }
+
+#define GATE_AUDIO1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &audio1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr, \
+ }
+
+static const struct mtk_gate audio_clks[] __initconst = {
+ /* AUDIO0 */
+ GATE_AUDIO0(CLK_AUDIO_AFE, "aud_afe", "audio_ck", 2),
+ GATE_AUDIO0(CLK_AUDIO_22M, "aud_22m", "aud_engen1_ck", 8),
+ GATE_AUDIO0(CLK_AUDIO_APLL_TUNER, "aud_apll_tuner",
+ "aud_engen1_ck", 19),
+ GATE_AUDIO0(CLK_AUDIO_ADC, "aud_adc", "audio_ck", 24),
+ GATE_AUDIO0(CLK_AUDIO_DAC, "aud_dac", "audio_ck", 25),
+ GATE_AUDIO0(CLK_AUDIO_DAC_PREDIS, "aud_dac_predis",
+ "audio_ck", 26),
+ GATE_AUDIO0(CLK_AUDIO_TML, "aud_tml", "audio_ck", 27),
+ /* AUDIO1 */
+ GATE_AUDIO1(CLK_AUDIO_I2S1_BCLK, "aud_i2s1_bclk",
+ "audio_ck", 4),
+ GATE_AUDIO1(CLK_AUDIO_I2S2_BCLK, "aud_i2s2_bclk",
+ "audio_ck", 5),
+ GATE_AUDIO1(CLK_AUDIO_I2S3_BCLK, "aud_i2s3_bclk",
+ "audio_ck", 6),
+ GATE_AUDIO1(CLK_AUDIO_I2S4_BCLK, "aud_i2s4_bclk",
+ "audio_ck", 7),
+};
+
+static int clk_mt6765_audio_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_AUDIO_NR_CLK);
+
+ mtk_clk_register_gates(node, audio_clks,
+ ARRAY_SIZE(audio_clks), clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ return r;
+}
+
+static const struct of_device_id of_match_clk_mt6765_audio[] = {
+ { .compatible = "mediatek,mt6765-audsys", },
+ {}
+};
+
+static struct platform_driver clk_mt6765_audio_drv = {
+ .probe = clk_mt6765_audio_probe,
+ .driver = {
+ .name = "clk-mt6765-audio",
+ .of_match_table = of_match_clk_mt6765_audio,
+ },
+};
+
+builtin_platform_driver(clk_mt6765_audio_drv);
diff --git a/drivers/clk/mediatek/clk-mt6765-cam.c b/drivers/clk/mediatek/clk-mt6765-cam.c
new file mode 100644
index 0000000..e36721b
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6765-cam.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Owen Chen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt6765-clk.h>
+
+static const struct mtk_gate_regs cam_cg_regs = {
+ .set_ofs = 0x4,
+ .clr_ofs = 0x8,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_CAM(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &cam_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate cam_clks[] __initconst = {
+ GATE_CAM(CLK_CAM_LARB3, "cam_larb3", "mm_ck", 0),
+ GATE_CAM(CLK_CAM_DFP_VAD, "cam_dfp_vad", "mm_ck", 1),
+ GATE_CAM(CLK_CAM, "cam", "mm_ck", 6),
+ GATE_CAM(CLK_CAMTG, "camtg", "mm_ck", 7),
+ GATE_CAM(CLK_CAM_SENINF, "cam_seninf", "mm_ck", 8),
+ GATE_CAM(CLK_CAMSV0, "camsv0", "mm_ck", 9),
+ GATE_CAM(CLK_CAMSV1, "camsv1", "mm_ck", 10),
+ GATE_CAM(CLK_CAMSV2, "camsv2", "mm_ck", 11),
+ GATE_CAM(CLK_CAM_CCU, "cam_ccu", "mm_ck", 12),
+};
+
+static int clk_mt6765_cam_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_CAM_NR_CLK);
+
+ mtk_clk_register_gates(node, cam_clks, ARRAY_SIZE(cam_clks), clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ return r;
+}
+
+static const struct of_device_id of_match_clk_mt6765_cam[] = {
+ { .compatible = "mediatek,mt6765-camsys", },
+ {}
+};
+
+static struct platform_driver clk_mt6765_cam_drv = {
+ .probe = clk_mt6765_cam_probe,
+ .driver = {
+ .name = "clk-mt6765-cam",
+ .of_match_table = of_match_clk_mt6765_cam,
+ },
+};
+
+builtin_platform_driver(clk_mt6765_cam_drv);
diff --git a/drivers/clk/mediatek/clk-mt6765-img.c b/drivers/clk/mediatek/clk-mt6765-img.c
new file mode 100644
index 0000000..a0c35ce
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6765-img.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Owen Chen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt6765-clk.h>
+
+static const struct mtk_gate_regs img_cg_regs = {
+ .set_ofs = 0x4,
+ .clr_ofs = 0x8,
+ .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_setclr, \
+ }
+
+static const struct mtk_gate img_clks[] __initconst = {
+ GATE_IMG(CLK_IMG_LARB2, "img_larb2", "mm_ck", 0),
+ GATE_IMG(CLK_IMG_DIP, "img_dip", "mm_ck", 2),
+ GATE_IMG(CLK_IMG_FDVT, "img_fdvt", "mm_ck", 3),
+ GATE_IMG(CLK_IMG_DPE, "img_dpe", "mm_ck", 4),
+ GATE_IMG(CLK_IMG_RSC, "img_rsc", "mm_ck", 5),
+};
+
+static int clk_mt6765_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)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ return r;
+}
+
+static const struct of_device_id of_match_clk_mt6765_img[] = {
+ { .compatible = "mediatek,mt6765-imgsys", },
+ {}
+};
+
+static struct platform_driver clk_mt6765_img_drv = {
+ .probe = clk_mt6765_img_probe,
+ .driver = {
+ .name = "clk-mt6765-img",
+ .of_match_table = of_match_clk_mt6765_img,
+ },
+};
+
+builtin_platform_driver(clk_mt6765_img_drv);
diff --git a/drivers/clk/mediatek/clk-mt6765-mipi0a.c b/drivers/clk/mediatek/clk-mt6765-mipi0a.c
new file mode 100644
index 0000000..7366be6
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6765-mipi0a.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Owen Chen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt6765-clk.h>
+
+static const struct mtk_gate_regs mipi0a_cg_regs = {
+ .set_ofs = 0x80,
+ .clr_ofs = 0x80,
+ .sta_ofs = 0x80,
+};
+
+#define GATE_MIPI0A(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &mipi0a_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
+static const struct mtk_gate mipi0a_clks[] __initconst = {
+ GATE_MIPI0A(CLK_MIPI0A_CSR_CSI_EN_0A,
+ "mipi0a_csr_0a", "f_fseninf_ck", 1),
+};
+
+static int clk_mt6765_mipi0a_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_MIPI0A_NR_CLK);
+
+ mtk_clk_register_gates(node, mipi0a_clks,
+ ARRAY_SIZE(mipi0a_clks), clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ return r;
+}
+
+static const struct of_device_id of_match_clk_mt6765_mipi0a[] = {
+ { .compatible = "mediatek,mt6765-mipi_rx_ana_csi0a", },
+ {}
+};
+
+static struct platform_driver clk_mt6765_mipi0a_drv = {
+ .probe = clk_mt6765_mipi0a_probe,
+ .driver = {
+ .name = "clk-mt6765-mipi0a",
+ .of_match_table = of_match_clk_mt6765_mipi0a,
+ },
+};
+
+builtin_platform_driver(clk_mt6765_mipi0a_drv);
diff --git a/drivers/clk/mediatek/clk-mt6765-mm.c b/drivers/clk/mediatek/clk-mt6765-mm.c
new file mode 100644
index 0000000..5ad1e0d
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6765-mm.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Owen Chen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt6765-clk.h>
+
+static const struct mtk_gate_regs mm_cg_regs = {
+ .set_ofs = 0x104,
+ .clr_ofs = 0x108,
+ .sta_ofs = 0x100,
+};
+
+#define GATE_MM(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &mm_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate mm_clks[] __initconst = {
+ /* MM */
+ GATE_MM(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_ck", 0),
+ GATE_MM(CLK_MM_MDP_CCORR0, "mm_mdp_ccorr0", "mm_ck", 1),
+ GATE_MM(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_ck", 2),
+ GATE_MM(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_ck", 3),
+ GATE_MM(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_ck", 4),
+ GATE_MM(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_ck", 5),
+ GATE_MM(CLK_MM_MDP_WDMA0, "mm_mdp_wdma0", "mm_ck", 6),
+ GATE_MM(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_ck", 7),
+ GATE_MM(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_ck", 8),
+ GATE_MM(CLK_MM_DISP_RSZ0, "mm_disp_rsz0", "mm_ck", 9),
+ GATE_MM(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_ck", 10),
+ GATE_MM(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_ck", 11),
+ GATE_MM(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_ck", 12),
+ GATE_MM(CLK_MM_DISP_CCORR0, "mm_disp_ccorr0", "mm_ck", 13),
+ GATE_MM(CLK_MM_DISP_AAL0, "mm_disp_aal0", "mm_ck", 14),
+ GATE_MM(CLK_MM_DISP_GAMMA0, "mm_disp_gamma0", "mm_ck", 15),
+ GATE_MM(CLK_MM_DISP_DITHER0, "mm_disp_dither0", "mm_ck", 16),
+ GATE_MM(CLK_MM_DSI0, "mm_dsi0", "mm_ck", 17),
+ GATE_MM(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_ck", 18),
+ GATE_MM(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_ck", 19),
+ GATE_MM(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_ck", 20),
+ GATE_MM(CLK_MM_SMI_COMM0, "mm_smi_comm0", "mm_ck", 21),
+ GATE_MM(CLK_MM_SMI_COMM1, "mm_smi_comm1", "mm_ck", 22),
+ GATE_MM(CLK_MM_CAM_MDP, "mm_cam_mdp_ck", "mm_ck", 23),
+ GATE_MM(CLK_MM_SMI_IMG, "mm_smi_img_ck", "mm_ck", 24),
+ GATE_MM(CLK_MM_SMI_CAM, "mm_smi_cam_ck", "mm_ck", 25),
+ GATE_MM(CLK_MM_IMG_DL_RELAY, "mm_img_dl_relay", "mm_ck", 26),
+ GATE_MM(CLK_MM_IMG_DL_ASYNC_TOP, "mm_imgdl_async", "mm_ck", 27),
+ GATE_MM(CLK_MM_DIG_DSI, "mm_dig_dsi_ck", "mm_ck", 28),
+ GATE_MM(CLK_MM_F26M_HRTWT, "mm_hrtwt", "f_f26m_ck", 29),
+};
+
+static int clk_mt6765_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)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ return r;
+}
+
+static const struct of_device_id of_match_clk_mt6765_mm[] = {
+ { .compatible = "mediatek,mt6765-mmsys", },
+ {}
+};
+
+static struct platform_driver clk_mt6765_mm_drv = {
+ .probe = clk_mt6765_mm_probe,
+ .driver = {
+ .name = "clk-mt6765-mm",
+ .of_match_table = of_match_clk_mt6765_mm,
+ },
+};
+
+builtin_platform_driver(clk_mt6765_mm_drv);
diff --git a/drivers/clk/mediatek/clk-mt6765-vcodec.c b/drivers/clk/mediatek/clk-mt6765-vcodec.c
new file mode 100644
index 0000000..fb690c2
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6765-vcodec.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Owen Chen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt6765-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[] __initconst = {
+ GATE_VENC(CLK_VENC_SET0_LARB, "venc_set0_larb", "mm_ck", 0),
+ GATE_VENC(CLK_VENC_SET1_VENC, "venc_set1_venc", "mm_ck", 4),
+ GATE_VENC(CLK_VENC_SET2_JPGENC, "jpgenc", "mm_ck", 8),
+ GATE_VENC(CLK_VENC_SET3_VDEC, "venc_set3_vdec", "mm_ck", 12),
+};
+
+static int clk_mt6765_vcodec_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)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ return r;
+}
+
+static const struct of_device_id of_match_clk_mt6765_venc[] = {
+ { .compatible = "mediatek,mt6765-vcodecsys", },
+ {}
+};
+
+static struct platform_driver clk_mt6765_vcodec_drv = {
+ .probe = clk_mt6765_vcodec_probe,
+ .driver = {
+ .name = "clk-mt6765-vcodec",
+ .of_match_table = of_match_clk_mt6765_vcodec,
+ },
+};
+
+builtin_platform_driver(clk_mt6765_vcodec_drv);
diff --git a/drivers/clk/mediatek/clk-mt6765.c b/drivers/clk/mediatek/clk-mt6765.c
new file mode 100644
index 0000000..7b360b9
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6765.c
@@ -0,0 +1,963 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Owen Chen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+#include "clk-mux.h"
+
+#include <dt-bindings/clock/mt6765-clk.h>
+
+/*fmeter div select 4*/
+#define _DIV4_ 1
+
+static DEFINE_SPINLOCK(mt6765_clk_lock);
+
+/* Total 12 subsys */
+void __iomem *cksys_base;
+void __iomem *apmixed_base;
+
+/* CKSYS */
+#define CLK_SCP_CFG_0 (cksys_base + 0x200)
+#define CLK_SCP_CFG_1 (cksys_base + 0x204)
+
+/* CG */
+#define AP_PLL_CON3 (apmixed_base + 0x0C)
+#define PLLON_CON0 (apmixed_base + 0x44)
+#define PLLON_CON1 (apmixed_base + 0x48)
+
+/* clk cfg update */
+#define CLK_CFG_0 0x40
+#define CLK_CFG_0_SET 0x44
+#define CLK_CFG_0_CLR 0x48
+#define CLK_CFG_1 0x50
+#define CLK_CFG_1_SET 0x54
+#define CLK_CFG_1_CLR 0x58
+#define CLK_CFG_2 0x60
+#define CLK_CFG_2_SET 0x64
+#define CLK_CFG_2_CLR 0x68
+#define CLK_CFG_3 0x70
+#define CLK_CFG_3_SET 0x74
+#define CLK_CFG_3_CLR 0x78
+#define CLK_CFG_4 0x80
+#define CLK_CFG_4_SET 0x84
+#define CLK_CFG_4_CLR 0x88
+#define CLK_CFG_5 0x90
+#define CLK_CFG_5_SET 0x94
+#define CLK_CFG_5_CLR 0x98
+#define CLK_CFG_6 0xa0
+#define CLK_CFG_6_SET 0xa4
+#define CLK_CFG_6_CLR 0xa8
+#define CLK_CFG_7 0xb0
+#define CLK_CFG_7_SET 0xb4
+#define CLK_CFG_7_CLR 0xb8
+#define CLK_CFG_8 0xc0
+#define CLK_CFG_8_SET 0xc4
+#define CLK_CFG_8_CLR 0xc8
+#define CLK_CFG_9 0xd0
+#define CLK_CFG_9_SET 0xd4
+#define CLK_CFG_9_CLR 0xd8
+#define CLK_CFG_10 0xe0
+#define CLK_CFG_10_SET 0xe4
+#define CLK_CFG_10_CLR 0xe8
+#define CLK_CFG_UPDATE 0x004
+
+static const struct mtk_fixed_clk fixed_clks[] __initconst = {
+ FIXED_CLK(CLK_TOP_F_FRTC, "f_frtc_ck", "clk32k", 32768),
+ FIXED_CLK(CLK_TOP_CLK26M, "clk_26m_ck", "clk26m", 26000000),
+ FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", NULL, 466000000),
+};
+
+static const struct mtk_fixed_factor top_divs[] __initconst = {
+ FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, 1),
+ FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 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", "mainpll", 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_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8),
+ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 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", "mainpll", 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", "univ2pll", 1, 2),
+ FACTOR(CLK_TOP_USB20_192M, "usb20_192m_ck", "univpll", 2, 13),
+ FACTOR(CLK_TOP_USB20_192M_D4, "usb20_192m_d4", "usb20_192m_ck", 1, 4),
+ FACTOR(CLK_TOP_USB20_192M_D8, "usb20_192m_d8", "usb20_192m_ck", 1, 8),
+ FACTOR(CLK_TOP_USB20_192M_D16,
+ "usb20_192m_d16", "usb20_192m_ck", 1, 16),
+ FACTOR(CLK_TOP_USB20_192M_D32,
+ "usb20_192m_d32", "usb20_192m_ck", 1, 32),
+ FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 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_UNIVPLL_D3, "univpll_d3", "univpll", 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_UNIVPLL2_D32, "univpll2_d32", "univpll_d3", 1, 32),
+ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 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_MMPLL, "mmpll_ck", "mmpll", 1, 1),
+ FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll_ck", 1, 2),
+ FACTOR(CLK_TOP_MPLL, "mpll_ck", "mpll", 1, 1),
+ FACTOR(CLK_TOP_DA_MPLL_104M_DIV, "mpll_104m_div", "mpll_ck", 1, 2),
+ FACTOR(CLK_TOP_DA_MPLL_52M_DIV, "mpll_52m_div", "mpll_ck", 1, 4),
+ FACTOR(CLK_TOP_MFGPLL, "mfgpll_ck", "mfgpll", 1, 1),
+ FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
+ FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll_ck", 1, 2),
+ 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_ULPOSC1, "ulposc1_ck", "ulposc1", 1, 1),
+ FACTOR(CLK_TOP_ULPOSC1_D2, "ulposc1_d2", "ulposc1_ck", 1, 2),
+ FACTOR(CLK_TOP_ULPOSC1_D4, "ulposc1_d4", "ulposc1_ck", 1, 4),
+ FACTOR(CLK_TOP_ULPOSC1_D8, "ulposc1_d8", "ulposc1_ck", 1, 8),
+ FACTOR(CLK_TOP_ULPOSC1_D16, "ulposc1_d16", "ulposc1_ck", 1, 16),
+ FACTOR(CLK_TOP_ULPOSC1_D32, "ulposc1_d32", "ulposc1_ck", 1, 32),
+ FACTOR(CLK_TOP_F_F26M, "f_f26m_ck", "clk_26m_ck", 1, 1),
+ FACTOR(CLK_TOP_AXI, "axi_ck", "axi_sel", 1, 1),
+ FACTOR(CLK_TOP_MM, "mm_ck", "mm_sel", 1, 1),
+ FACTOR(CLK_TOP_SCP, "scp_ck", "scp_sel", 1, 1),
+ FACTOR(CLK_TOP_MFG, "mfg_ck", "mfg_sel", 1, 1),
+ FACTOR(CLK_TOP_F_FUART, "f_fuart_ck", "uart_sel", 1, 1),
+ FACTOR(CLK_TOP_SPI, "spi_ck", "spi_sel", 1, 1),
+ FACTOR(CLK_TOP_MSDC50_0, "msdc50_0_ck", "msdc50_0_sel", 1, 1),
+ FACTOR(CLK_TOP_MSDC30_1, "msdc30_1_ck", "msdc30_1_sel", 1, 1),
+ FACTOR(CLK_TOP_AUDIO, "audio_ck", "audio_sel", 1, 1),
+ FACTOR(CLK_TOP_AUD_1, "aud_1_ck", "aud_1_sel", 1, 1),
+ FACTOR(CLK_TOP_AUD_ENGEN1, "aud_engen1_ck", "aud_engen1_sel", 1, 1),
+ FACTOR(CLK_TOP_F_FDISP_PWM, "f_fdisp_pwm_ck", "disp_pwm_sel", 1, 1),
+ FACTOR(CLK_TOP_SSPM, "sspm_ck", "sspm_sel", 1, 1),
+ FACTOR(CLK_TOP_DXCC, "dxcc_ck", "dxcc_sel", 1, 1),
+ FACTOR(CLK_TOP_I2C, "i2c_ck", "i2c_sel", 1, 1),
+ FACTOR(CLK_TOP_F_FPWM, "f_fpwm_ck", "pwm_sel", 1, 1),
+ FACTOR(CLK_TOP_F_FSENINF, "f_fseninf_ck", "seninf_sel", 1, 1),
+ FACTOR(CLK_TOP_AES_FDE, "aes_fde_ck", "aes_fde_sel", 1, 1),
+ FACTOR(CLK_TOP_F_BIST2FPC, "f_bist2fpc_ck", "univpll2_d2", 1, 1),
+ FACTOR(CLK_TOP_ARMPLL_DIVIDER_PLL0, "arm_div_pll0", "syspll_d2", 1, 1),
+ FACTOR(CLK_TOP_ARMPLL_DIVIDER_PLL1, "arm_div_pll1", "syspll_ck", 1, 1),
+ FACTOR(CLK_TOP_ARMPLL_DIVIDER_PLL2, "arm_div_pll2", "univpll_d2", 1, 1),
+ FACTOR(CLK_TOP_DA_USB20_48M_DIV,
+ "usb20_48m_div", "usb20_192m_d4", 1, 1),
+ FACTOR(CLK_TOP_DA_UNIV_48M_DIV, "univ_48m_div", "usb20_192m_d4", 1, 1),
+};
+
+static const char * const axi_parents[] __initconst = {
+ "clk26m",
+ "syspll_d7",
+ "syspll1_d4",
+ "syspll3_d2"
+};
+
+static const char * const mem_parents[] __initconst = {
+ "clk26m",
+ "dmpll_ck",
+ "apll1_ck"
+};
+
+static const char * const mm_parents[] __initconst = {
+ "clk26m",
+ "mmpll_ck",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll1_d2",
+ "mmpll_d2"
+};
+
+static const char * const scp_parents[] __initconst = {
+ "clk26m",
+ "syspll4_d2",
+ "univpll2_d2",
+ "syspll1_d2",
+ "univpll1_d2",
+ "syspll_d3",
+ "univpll_d3"
+};
+
+static const char * const mfg_parents[] __initconst = {
+ "clk26m",
+ "mfgpll_ck",
+ "syspll_d3",
+ "univpll_d3"
+};
+
+static const char * const atb_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d4",
+ "syspll1_d2"
+};
+
+static const char * const camtg_parents[] __initconst = {
+ "clk26m",
+ "usb20_192m_d8",
+ "univpll2_d8",
+ "usb20_192m_d4",
+ "univpll2_d32",
+ "usb20_192m_d16",
+ "usb20_192m_d32"
+};
+
+static const char * const uart_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d8"
+};
+
+static const char * const spi_parents[] __initconst = {
+ "clk26m",
+ "syspll3_d2",
+ "syspll4_d2",
+ "syspll2_d4"
+};
+
+static const char * const msdc5hclk_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d2",
+ "univpll1_d4",
+ "syspll2_d2"
+};
+
+static const char * const msdc50_0_parents[] __initconst = {
+ "clk26m",
+ "msdcpll_ck",
+ "syspll2_d2",
+ "syspll4_d2",
+ "univpll1_d2",
+ "syspll1_d2",
+ "univpll_d5",
+ "univpll1_d4"
+};
+
+static const char * const msdc30_1_parents[] __initconst = {
+ "clk26m",
+ "msdcpll_d2",
+ "univpll2_d2",
+ "syspll2_d2",
+ "syspll1_d4",
+ "univpll1_d4",
+ "usb20_192m_d4",
+ "syspll2_d4"
+};
+
+static const char * const audio_parents[] __initconst = {
+ "clk26m",
+ "syspll3_d4",
+ "syspll4_d4",
+ "syspll1_d16"
+};
+
+static const char * const aud_intbus_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d4",
+ "syspll4_d2"
+};
+
+static const char * const aud_1_parents[] __initconst = {
+ "clk26m",
+ "apll1_ck"
+};
+
+static const char * const aud_engen1_parents[] __initconst = {
+ "clk26m",
+ "apll1_d2",
+ "apll1_d4",
+ "apll1_d8"
+};
+
+static const char * const disp_pwm_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d4",
+ "ulposc1_d2",
+ "ulposc1_d8"
+};
+
+static const char * const sspm_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll_d3"
+};
+
+static const char * const dxcc_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll1_d4",
+ "syspll1_d8"
+};
+
+static const char * const usb_top_parents[] __initconst = {
+ "clk26m",
+ "univpll3_d4"
+};
+
+static const char * const spm_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d8"
+};
+
+static const char * const i2c_parents[] __initconst = {
+ "clk26m",
+ "univpll3_d4",
+ "univpll3_d2",
+ "syspll1_d8",
+ "syspll2_d8"
+};
+
+static const char * const pwm_parents[] __initconst = {
+ "clk26m",
+ "univpll3_d4",
+ "syspll1_d8"
+};
+
+static const char * const seninf_parents[] __initconst = {
+ "clk26m",
+ "univpll1_d4",
+ "univpll1_d2",
+ "univpll2_d2"
+};
+
+static const char * const aes_fde_parents[] __initconst = {
+ "clk26m",
+ "msdcpll_ck",
+ "univpll_d3",
+ "univpll2_d2",
+ "univpll1_d2",
+ "syspll1_d2"
+};
+
+static const char * const ulposc_parents[] __initconst = {
+ "clk26m",
+ "ulposc1_d4",
+ "ulposc1_d8",
+ "ulposc1_d16",
+ "ulposc1_d32"
+};
+
+static const char * const camtm_parents[] __initconst = {
+ "clk26m",
+ "univpll1_d4",
+ "univpll1_d2",
+ "univpll2_d2"
+};
+
+#define INVALID_UPDATE_REG 0xFFFFFFFF
+#define INVALID_UPDATE_SHIFT -1
+#define INVALID_MUX_GATE -1
+
+static const struct mtk_mux top_muxes[] __initconst = {
+ /* CLK_CFG_0 */
+ MUX_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
+ CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR,
+ 0, 2, 7, CLK_CFG_UPDATE, 0, CLK_IS_CRITICAL),
+ MUX_CLR_SET_UPD_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents,
+ CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR,
+ 8, 2, 15, CLK_CFG_UPDATE, 1, CLK_IS_CRITICAL),
+ MUX_CLR_SET_UPD(CLK_TOP_MM_SEL, "mm_sel", mm_parents, CLK_CFG_0,
+ CLK_CFG_0_SET, CLK_CFG_0_CLR, 16, 3, 23,
+ CLK_CFG_UPDATE, 2),
+ MUX_CLR_SET_UPD(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, CLK_CFG_0,
+ CLK_CFG_0_SET, CLK_CFG_0_CLR, 24, 3, 31,
+ CLK_CFG_UPDATE, 3),
+ /* CLK_CFG_1 */
+ MUX_CLR_SET_UPD(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, CLK_CFG_1,
+ CLK_CFG_1_SET, CLK_CFG_1_CLR, 0, 2, 7,
+ CLK_CFG_UPDATE, 4),
+ MUX_CLR_SET_UPD(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, CLK_CFG_1,
+ CLK_CFG_1_SET, CLK_CFG_1_CLR, 8, 2, 15,
+ CLK_CFG_UPDATE, 5),
+ MUX_CLR_SET_UPD(CLK_TOP_CAMTG_SEL, "camtg_sel",
+ camtg_parents, CLK_CFG_1, CLK_CFG_1_SET,
+ CLK_CFG_1_CLR, 16, 3, 23, CLK_CFG_UPDATE, 6),
+ MUX_CLR_SET_UPD(CLK_TOP_CAMTG1_SEL, "camtg1_sel", camtg_parents,
+ CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR,
+ 24, 3, 31, CLK_CFG_UPDATE, 7),
+ /* CLK_CFG_2 */
+ MUX_CLR_SET_UPD(CLK_TOP_CAMTG2_SEL, "camtg2_sel",
+ camtg_parents, CLK_CFG_2, CLK_CFG_2_SET,
+ CLK_CFG_2_CLR, 0, 3, 7, CLK_CFG_UPDATE, 8),
+ MUX_CLR_SET_UPD(CLK_TOP_CAMTG3_SEL, "camtg3_sel", camtg_parents,
+ CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR,
+ 8, 3, 15, CLK_CFG_UPDATE, 9),
+ MUX_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents,
+ CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 16, 1, 23,
+ CLK_CFG_UPDATE, 10),
+ MUX_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, CLK_CFG_2,
+ CLK_CFG_2_SET, CLK_CFG_2_CLR, 24, 2, 31,
+ CLK_CFG_UPDATE, 11),
+ /* CLK_CFG_3 */
+ MUX_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc5hclk",
+ msdc5hclk_parents, CLK_CFG_3, CLK_CFG_3_SET,
+ CLK_CFG_3_CLR, 0, 2, 7, CLK_CFG_UPDATE, 12),
+ MUX_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel",
+ msdc50_0_parents, CLK_CFG_3, CLK_CFG_3_SET,
+ CLK_CFG_3_CLR, 8, 3, 15, CLK_CFG_UPDATE, 13),
+ MUX_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel",
+ msdc30_1_parents, CLK_CFG_3, CLK_CFG_3_SET,
+ CLK_CFG_3_CLR, 16, 3, 23, CLK_CFG_UPDATE, 14),
+ MUX_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents,
+ CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR,
+ 24, 2, 31, CLK_CFG_UPDATE, 15),
+ /* CLK_CFG_4 */
+ MUX_CLR_SET_UPD(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel",
+ aud_intbus_parents, CLK_CFG_4, CLK_CFG_4_SET,
+ CLK_CFG_4_CLR, 0, 2, 7, CLK_CFG_UPDATE, 16),
+ MUX_CLR_SET_UPD(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents,
+ CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR,
+ 8, 1, 15, CLK_CFG_UPDATE, 17),
+ MUX_CLR_SET_UPD(CLK_TOP_AUD_ENGEN1_SEL, "aud_engen1_sel",
+ aud_engen1_parents, CLK_CFG_4, CLK_CFG_4_SET,
+ CLK_CFG_4_CLR, 16, 2, 23, CLK_CFG_UPDATE, 18),
+ MUX_CLR_SET_UPD(CLK_TOP_DISP_PWM_SEL, "disp_pwm_sel",
+ disp_pwm_parents, CLK_CFG_4, CLK_CFG_4_SET,
+ CLK_CFG_4_CLR, 24, 2, 31, CLK_CFG_UPDATE, 19),
+ /* CLK_CFG_5 */
+ MUX_CLR_SET_UPD(CLK_TOP_SSPM_SEL, "sspm_sel", sspm_parents,
+ CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 0, 2, 7,
+ CLK_CFG_UPDATE, 20),
+ MUX_CLR_SET_UPD(CLK_TOP_DXCC_SEL, "dxcc_sel", dxcc_parents,
+ CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 8, 2, 15,
+ CLK_CFG_UPDATE, 21),
+ MUX_CLR_SET_UPD(CLK_TOP_USB_TOP_SEL, "usb_top_sel", usb_top_parents,
+ CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 16, 1, 23,
+ CLK_CFG_UPDATE, 22),
+ MUX_CLR_SET_UPD(CLK_TOP_SPM_SEL, "spm_sel", spm_parents, CLK_CFG_5,
+ CLK_CFG_5_SET, CLK_CFG_5_CLR, 24, 1, 31,
+ CLK_CFG_UPDATE, 23),
+ /* CLK_CFG_6 */
+ MUX_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, CLK_CFG_6,
+ CLK_CFG_6_SET, CLK_CFG_6_CLR, 0, 3, 7, CLK_CFG_UPDATE,
+ 24),
+ MUX_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, CLK_CFG_6,
+ CLK_CFG_6_SET, CLK_CFG_6_CLR, 8, 2, 15, CLK_CFG_UPDATE,
+ 25),
+ MUX_CLR_SET_UPD(CLK_TOP_SENINF_SEL, "seninf_sel", seninf_parents,
+ CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 16, 2, 23,
+ CLK_CFG_UPDATE, 26),
+ MUX_CLR_SET_UPD(CLK_TOP_AES_FDE_SEL, "aes_fde_sel", aes_fde_parents,
+ CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 24, 3, 31,
+ CLK_CFG_UPDATE, 27),
+ /* CLK_CFG_7 */
+ MUX_CLR_SET_UPD_FLAGS(CLK_TOP_PWRAP_ULPOSC_SEL, "ulposc_sel",
+ ulposc_parents, CLK_CFG_7, CLK_CFG_7_SET,
+ CLK_CFG_7_CLR, 0, 3, 7, CLK_CFG_UPDATE, 28,
+ CLK_IS_CRITICAL),
+ MUX_CLR_SET_UPD(CLK_TOP_CAMTM_SEL, "camtm_sel", camtm_parents,
+ CLK_CFG_7, CLK_CFG_7_SET, CLK_CFG_7_CLR, 8, 2, 15,
+ CLK_CFG_UPDATE, 29),
+};
+
+static const struct mtk_gate_regs top0_cg_regs = {
+ .set_ofs = 0x0,
+ .clr_ofs = 0x0,
+ .sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs top1_cg_regs = {
+ .set_ofs = 0x104,
+ .clr_ofs = 0x104,
+ .sta_ofs = 0x104,
+};
+
+static const struct mtk_gate_regs top2_cg_regs = {
+ .set_ofs = 0x320,
+ .clr_ofs = 0x320,
+ .sta_ofs = 0x320,
+};
+
+#define GATE_TOP0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &top0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr, \
+ }
+
+#define GATE_TOP1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &top1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
+#define GATE_TOP2(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &top2_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr, \
+ }
+
+static const struct mtk_gate top_clks[] __initconst = {
+ /* TOP0 */
+ GATE_TOP0(CLK_TOP_MD_32K, "md_32k", "f_frtc_ck", 8),
+ GATE_TOP0(CLK_TOP_MD_26M, "md_26m", "f_f26m_ck", 9),
+ GATE_TOP0(CLK_TOP_MD2_32K, "md2_32k", "f_frtc_ck", 10),
+ GATE_TOP0(CLK_TOP_MD2_26M, "md2_26m", "f_f26m_ck", 11),
+ /* TOP1 */
+ GATE_TOP1(CLK_TOP_ARMPLL_DIVIDER_PLL0_EN,
+ "arm_div_pll0_en", "arm_div_pll0", 3),
+ GATE_TOP1(CLK_TOP_ARMPLL_DIVIDER_PLL1_EN,
+ "arm_div_pll1_en", "arm_div_pll1", 4),
+ GATE_TOP1(CLK_TOP_ARMPLL_DIVIDER_PLL2_EN,
+ "arm_div_pll2_en", "arm_div_pll2", 5),
+ GATE_TOP1(CLK_TOP_FMEM_OCC_DRC_EN, "drc_en", "univpll2_d2", 6),
+ GATE_TOP1(CLK_TOP_USB20_48M_EN, "usb20_48m_en", "usb20_48m_div", 8),
+ GATE_TOP1(CLK_TOP_UNIVPLL_48M_EN, "univpll_48m_en", "univ_48m_div", 9),
+ GATE_TOP1(CLK_TOP_F_UFS_MP_SAP_CFG_EN, "ufs_sap", "f_f26m_ck", 12),
+ GATE_TOP1(CLK_TOP_F_BIST2FPC_EN, "bist2fpc", "f_bist2fpc_ck", 16),
+ /* TOP2 */
+ GATE_TOP2(CLK_TOP_APLL12_DIV0, "apll12_div0", "aud_1_ck", 2),
+ GATE_TOP2(CLK_TOP_APLL12_DIV1, "apll12_div1", "aud_1_ck", 3),
+ GATE_TOP2(CLK_TOP_APLL12_DIV2, "apll12_div2", "aud_1_ck", 4),
+ GATE_TOP2(CLK_TOP_APLL12_DIV3, "apll12_div3", "aud_1_ck", 5),
+};
+
+static const struct mtk_gate_regs ifr0_cg_regs = {
+ .set_ofs = 0x200,
+ .clr_ofs = 0x200,
+ .sta_ofs = 0x200,
+};
+
+static const struct mtk_gate_regs ifr1_cg_regs = {
+ .set_ofs = 0x74,
+ .clr_ofs = 0x74,
+ .sta_ofs = 0x74,
+};
+
+static const struct mtk_gate_regs ifr2_cg_regs = {
+ .set_ofs = 0x80,
+ .clr_ofs = 0x84,
+ .sta_ofs = 0x90,
+};
+
+static const struct mtk_gate_regs ifr3_cg_regs = {
+ .set_ofs = 0x88,
+ .clr_ofs = 0x8c,
+ .sta_ofs = 0x94,
+};
+
+static const struct mtk_gate_regs ifr4_cg_regs = {
+ .set_ofs = 0xa4,
+ .clr_ofs = 0xa8,
+ .sta_ofs = 0xac,
+};
+
+static const struct mtk_gate_regs ifr5_cg_regs = {
+ .set_ofs = 0xc0,
+ .clr_ofs = 0xc4,
+ .sta_ofs = 0xc8,
+};
+
+#define GATE_IFR0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &ifr0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
+#define GATE_IFR1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &ifr1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr, \
+ }
+
+#define GATE_IFR2(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &ifr2_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+#define GATE_IFR3(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &ifr3_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+#define GATE_IFR4(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &ifr4_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+#define GATE_IFR5(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &ifr5_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate ifr_clks[] __initconst = {
+ /* INFRA_TOPAXI */
+ /* INFRA PERI */
+ /* INFRA mode 0 */
+ GATE_IFR2(CLK_IFR_ICUSB, "ifr_icusb", "axi_ck", 8),
+ GATE_IFR2(CLK_IFR_GCE, "ifr_gce", "axi_ck", 9),
+ GATE_IFR2(CLK_IFR_THERM, "ifr_therm", "axi_ck", 10),
+ GATE_IFR2(CLK_IFR_I2C_AP, "ifr_i2c_ap", "i2c_ck", 11),
+ GATE_IFR2(CLK_IFR_I2C_CCU, "ifr_i2c_ccu", "i2c_ck", 12),
+ GATE_IFR2(CLK_IFR_I2C_SSPM, "ifr_i2c_sspm", "i2c_ck", 13),
+ GATE_IFR2(CLK_IFR_I2C_RSV, "ifr_i2c_rsv", "i2c_ck", 14),
+ GATE_IFR2(CLK_IFR_PWM_HCLK, "ifr_pwm_hclk", "axi_ck", 15),
+ GATE_IFR2(CLK_IFR_PWM1, "ifr_pwm1", "f_fpwm_ck", 16),
+ GATE_IFR2(CLK_IFR_PWM2, "ifr_pwm2", "f_fpwm_ck", 17),
+ GATE_IFR2(CLK_IFR_PWM3, "ifr_pwm3", "f_fpwm_ck", 18),
+ GATE_IFR2(CLK_IFR_PWM4, "ifr_pwm4", "f_fpwm_ck", 19),
+ GATE_IFR2(CLK_IFR_PWM5, "ifr_pwm5", "f_fpwm_ck", 20),
+ GATE_IFR2(CLK_IFR_PWM, "ifr_pwm", "f_fpwm_ck", 21),
+ GATE_IFR2(CLK_IFR_UART0, "ifr_uart0", "f_fuart_ck", 22),
+ GATE_IFR2(CLK_IFR_UART1, "ifr_uart1", "f_fuart_ck", 23),
+ GATE_IFR2(CLK_IFR_GCE_26M, "ifr_gce_26m", "f_f26m_ck", 27),
+ GATE_IFR2(CLK_IFR_CQ_DMA_FPC, "ifr_dma", "axi_ck", 28),
+ GATE_IFR2(CLK_IFR_BTIF, "ifr_btif", "axi_ck", 31),
+ /* INFRA mode 1 */
+ GATE_IFR3(CLK_IFR_SPI0, "ifr_spi0", "spi_ck", 1),
+ GATE_IFR3(CLK_IFR_MSDC0, "ifr_msdc0", "msdc5hclk", 2),
+ GATE_IFR3(CLK_IFR_MSDC1, "ifr_msdc1", "axi_ck", 4),
+ GATE_IFR3(CLK_IFR_TRNG, "ifr_trng", "axi_ck", 9),
+ GATE_IFR3(CLK_IFR_AUXADC, "ifr_auxadc", "f_f26m_ck", 10),
+ GATE_IFR3(CLK_IFR_CCIF1_AP, "ifr_ccif1_ap", "axi_ck", 12),
+ GATE_IFR3(CLK_IFR_CCIF1_MD, "ifr_ccif1_md", "axi_ck", 13),
+ GATE_IFR3(CLK_IFR_AUXADC_MD, "ifr_auxadc_md", "f_f26m_ck", 14),
+ GATE_IFR3(CLK_IFR_AP_DMA, "ifr_ap_dma", "axi_ck", 18),
+ GATE_IFR3(CLK_IFR_DEVICE_APC, "ifr_dapc", "axi_ck", 20),
+ GATE_IFR3(CLK_IFR_CCIF_AP, "ifr_ccif_ap", "axi_ck", 23),
+ GATE_IFR3(CLK_IFR_AUDIO, "ifr_audio", "axi_ck", 25),
+ GATE_IFR3(CLK_IFR_CCIF_MD, "ifr_ccif_md", "axi_ck", 26),
+ /* INFRA mode 2 */
+ GATE_IFR4(CLK_IFR_RG_PWM_FBCLK6, "ifr_pwmfb", "f_f26m_ck", 0),
+ GATE_IFR4(CLK_IFR_DISP_PWM, "ifr_disp_pwm", "f_fdisp_pwm_ck", 2),
+ GATE_IFR4(CLK_IFR_CLDMA_BCLK, "ifr_cldmabclk", "axi_ck", 3),
+ GATE_IFR4(CLK_IFR_AUDIO_26M_BCLK, "ifr_audio26m", "f_f26m_ck", 4),
+ GATE_IFR4(CLK_IFR_SPI1, "ifr_spi1", "spi_ck", 6),
+ GATE_IFR4(CLK_IFR_I2C4, "ifr_i2c4", "i2c_ck", 7),
+ GATE_IFR4(CLK_IFR_SPI2, "ifr_spi2", "spi_ck", 9),
+ GATE_IFR4(CLK_IFR_SPI3, "ifr_spi3", "spi_ck", 10),
+ GATE_IFR4(CLK_IFR_I2C5, "ifr_i2c5", "i2c_ck", 18),
+ GATE_IFR4(CLK_IFR_I2C5_ARBITER, "ifr_i2c5a", "i2c_ck", 19),
+ GATE_IFR4(CLK_IFR_I2C5_IMM, "ifr_i2c5_imm", "i2c_ck", 20),
+ GATE_IFR4(CLK_IFR_I2C1_ARBITER, "ifr_i2c1a", "i2c_ck", 21),
+ GATE_IFR4(CLK_IFR_I2C1_IMM, "ifr_i2c1_imm", "i2c_ck", 22),
+ GATE_IFR4(CLK_IFR_I2C2_ARBITER, "ifr_i2c2a", "i2c_ck", 23),
+ GATE_IFR4(CLK_IFR_I2C2_IMM, "ifr_i2c2_imm", "i2c_ck", 24),
+ GATE_IFR4(CLK_IFR_SPI4, "ifr_spi4", "spi_ck", 25),
+ GATE_IFR4(CLK_IFR_SPI5, "ifr_spi5", "spi_ck", 26),
+ GATE_IFR4(CLK_IFR_CQ_DMA, "ifr_cq_dma", "axi_ck", 27),
+ GATE_IFR4(CLK_IFR_FAES_FDE, "ifr_faes_fde_ck", "aes_fde_ck", 29),
+ /* INFRA mode 3 */
+ GATE_IFR5(CLK_IFR_MSDC0_SELF, "ifr_msdc0sf", "msdc50_0_ck", 0),
+ GATE_IFR5(CLK_IFR_MSDC1_SELF, "ifr_msdc1sf", "msdc50_0_ck", 1),
+ GATE_IFR5(CLK_IFR_I2C6, "ifr_i2c6", "i2c_ck", 6),
+ GATE_IFR5(CLK_IFR_AP_MSDC0, "ifr_ap_msdc0", "msdc50_0_ck", 7),
+ GATE_IFR5(CLK_IFR_MD_MSDC0, "ifr_md_msdc0", "msdc50_0_ck", 8),
+ GATE_IFR5(CLK_IFR_MSDC0_SRC, "ifr_msdc0_clk", "msdc50_0_ck", 9),
+ GATE_IFR5(CLK_IFR_MSDC1_SRC, "ifr_msdc1_clk", "msdc30_1_ck", 10),
+ GATE_IFR5(CLK_IFR_MCU_PM_BCLK, "ifr_mcu_pm_bclk", "axi_ck", 17),
+ GATE_IFR5(CLK_IFR_CCIF2_AP, "ifr_ccif2_ap", "axi_ck", 18),
+ GATE_IFR5(CLK_IFR_CCIF2_MD, "ifr_ccif2_md", "axi_ck", 19),
+ GATE_IFR5(CLK_IFR_CCIF3_AP, "ifr_ccif3_ap", "axi_ck", 20),
+ GATE_IFR5(CLK_IFR_CCIF3_MD, "ifr_ccif3_md", "axi_ck", 21),
+};
+
+/* additional CCF control for mipi26M race condition(disp/camera) */
+static const struct mtk_gate_regs apmixed_cg_regs = {
+ .set_ofs = 0x14,
+ .clr_ofs = 0x14,
+ .sta_ofs = 0x14,
+};
+
+#define GATE_APMIXED(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &apmixed_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
+static const struct mtk_gate apmixed_clks[] __initconst = {
+ /* AUDIO0 */
+ GATE_APMIXED(CLK_APMIXED_SSUSB26M, "apmixed_ssusb26m", "f_f26m_ck",
+ 4),
+ GATE_APMIXED(CLK_APMIXED_APPLL26M, "apmixed_appll26m", "f_f26m_ck",
+ 5),
+ GATE_APMIXED(CLK_APMIXED_MIPIC0_26M, "apmixed_mipic026m", "f_f26m_ck",
+ 6),
+ GATE_APMIXED(CLK_APMIXED_MDPLLGP26M, "apmixed_mdpll26m", "f_f26m_ck",
+ 7),
+ GATE_APMIXED(CLK_APMIXED_MMSYS_F26M, "apmixed_mmsys26m", "f_f26m_ck",
+ 8),
+ GATE_APMIXED(CLK_APMIXED_UFS26M, "apmixed_ufs26m", "f_f26m_ck",
+ 9),
+ GATE_APMIXED(CLK_APMIXED_MIPIC1_26M, "apmixed_mipic126m", "f_f26m_ck",
+ 11),
+ GATE_APMIXED(CLK_APMIXED_MEMPLL26M, "apmixed_mempll26m", "f_f26m_ck",
+ 13),
+ GATE_APMIXED(CLK_APMIXED_CLKSQ_LVPLL_26M, "apmixed_lvpll26m",
+ "f_f26m_ck", 14),
+ GATE_APMIXED(CLK_APMIXED_MIPID0_26M, "apmixed_mipid026m", "f_f26m_ck",
+ 16),
+};
+
+#define MT6765_PLL_FMAX (3800UL * MHZ)
+#define MT6765_PLL_FMIN (1500UL * MHZ)
+
+#define CON0_MT6765_RST_BAR BIT(23)
+
+#define PLL_INFO_NULL (0xFF)
+
+#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
+ _pcwibits, _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_MT6765_RST_BAR, \
+ .fmax = MT6765_PLL_FMAX, \
+ .fmin = MT6765_PLL_FMIN, \
+ .pcwbits = _pcwbits, \
+ .pcwibits = _pcwibits, \
+ .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, \
+ _pcwibits, _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, _pcwibits, _pd_reg, _pd_shift, \
+ _tuner_reg, _tuner_en_reg, _tuner_en_bit, \
+ _pcw_reg, _pcw_shift, NULL) \
+
+static const struct mtk_pll_data plls[] = {
+ PLL(CLK_APMIXED_ARMPLL_L, "armpll_l", 0x021C, 0x0228, BIT(0),
+ PLL_AO, 22, 8, 0x0220, 24, 0, 0, 0, 0x0220, 0),
+ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x020C, 0x0218, BIT(0),
+ PLL_AO, 22, 8, 0x0210, 24, 0, 0, 0, 0x0210, 0),
+ PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x022C, 0x0238, BIT(0),
+ PLL_AO, 22, 8, 0x0230, 24, 0, 0, 0, 0x0230, 0),
+ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x023C, 0x0248, BIT(0),
+ (HAVE_RST_BAR | PLL_AO), 22, 8, 0x0240, 24, 0, 0, 0, 0x0240,
+ 0),
+ PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x024C, 0x0258, BIT(0),
+ 0, 22, 8, 0x0250, 24, 0, 0, 0, 0x0250, 0),
+ PLL(CLK_APMIXED_MMPLL, "mmpll", 0x025C, 0x0268, BIT(0),
+ 0, 22, 8, 0x0260, 24, 0, 0, 0, 0x0260, 0),
+ PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x026C, 0x0278, BIT(0),
+ HAVE_RST_BAR, 22, 8, 0x0270, 24, 0, 0, 0, 0x0270, 0),
+ PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x027C, 0x0288, BIT(0),
+ 0, 22, 8, 0x0280, 24, 0, 0, 0, 0x0280, 0),
+ PLL(CLK_APMIXED_APLL1, "apll1", 0x028C, 0x029C, BIT(0),
+ 0, 32, 8, 0x0290, 24, 0x0040, 0x000C, 0, 0x0294, 0),
+ PLL(CLK_APMIXED_MPLL, "mpll", 0x02A0, 0x02AC, BIT(0),
+ PLL_AO, 22, 8, 0x02A4, 24, 0, 0, 0, 0x02A4, 0),
+};
+
+static int clk_mt6765_apmixed_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_APMIXED_NR_CLK);
+
+ mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+
+ mtk_clk_register_gates(node, apmixed_clks,
+ ARRAY_SIZE(apmixed_clks), clk_data);
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ apmixed_base = base;
+ /* MPLL, CCIPLL, MAINPLL set HW mode, TDCLKSQ, CLKSQ1 */
+ clk_writel(clk_readl(AP_PLL_CON3) & 0xFFFFFFE1, AP_PLL_CON3);
+ clk_writel(clk_readl(PLLON_CON0) & 0x01041041, PLLON_CON0);
+ clk_writel(clk_readl(PLLON_CON1) & 0x01041041, PLLON_CON1);
+
+ return r;
+}
+
+static struct clk_onecell_data *mt6765_top_clk_data;
+
+static int clk_mt6765_top_probe(struct platform_device *pdev)
+{
+ 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);
+ }
+
+ mt6765_top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+ mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks),
+ mt6765_top_clk_data);
+ mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs),
+ mt6765_top_clk_data);
+ mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node,
+ &mt6765_clk_lock, mt6765_top_clk_data);
+ mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
+ mt6765_top_clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get,
+ mt6765_top_clk_data);
+
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ cksys_base = base;
+ /* [4]:no need */
+ clk_writel(clk_readl(CLK_SCP_CFG_0) | 0x3EF, CLK_SCP_CFG_0);
+ /*[1,2,3,8]: no need*/
+ clk_writel(clk_readl(CLK_SCP_CFG_1) | 0x1, CLK_SCP_CFG_1);
+
+ return r;
+}
+
+static int clk_mt6765_ifr_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_IFR_NR_CLK);
+
+ mtk_clk_register_gates(node, ifr_clks, ARRAY_SIZE(ifr_clks),
+ clk_data);
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ return r;
+}
+
+static const struct of_device_id of_match_clk_mt6765[] = {
+ {
+ .compatible = "mediatek,mt6765-apmixedsys",
+ .data = clk_mt6765_apmixed_probe,
+ }, {
+ .compatible = "mediatek,mt6765-topckgen",
+ .data = clk_mt6765_top_probe,
+ }, {
+ .compatible = "mediatek,mt6765-infracfg",
+ .data = clk_mt6765_ifr_probe,
+ }, {
+ /* sentinel */
+ }
+};
+
+static int clk_mt6765_probe(struct platform_device *pdev)
+{
+ int (*clk_probe)(struct platform_device *d);
+ int r;
+
+ clk_probe = of_device_get_match_data(&pdev->dev);
+ if (!clk_probe)
+ return -EINVAL;
+
+ r = clk_probe(pdev);
+ if (r)
+ dev_err(&pdev->dev,
+ "could not register clock provider: %s: %d\n",
+ pdev->name, r);
+
+ return r;
+}
+
+static struct platform_driver clk_mt6765_drv = {
+ .probe = clk_mt6765_probe,
+ .driver = {
+ .name = "clk-mt6765",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_clk_mt6765,
+ },
+};
+
+static int __init clk_mt6765_init(void)
+{
+ return platform_driver_register(&clk_mt6765_drv);
+}
+
+arch_initcall(clk_mt6765_init);
--
1.7.9.5
From: Owen Chen <[email protected]>
1. pcwibits: The integer bits of pcw for plls is extend to 8 bits,
add a variable to indicate this change and
backward-compatible.
2. fmin: The pll freqency lower-bound is vary from 1GMhz to
1.5Ghz, add a variable to indicate platform-dependent.
Signed-off-by: Owen Chen <[email protected]>
---
drivers/clk/mediatek/clk-mtk.h | 2 ++
drivers/clk/mediatek/clk-pll.c | 45 ++++++++++++++++++++++++++++++++++------
2 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index f83c2bb..1882221 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -215,7 +215,9 @@ struct mtk_pll_data {
const struct clk_ops *ops;
u32 rst_bar_mask;
unsigned long fmax;
+ unsigned long fmin;
int pcwbits;
+ int pcwibits;
uint32_t pcw_reg;
int pcw_shift;
const struct mtk_pll_div_table *div_table;
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index f54e401..df571e5 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -27,7 +27,7 @@
#define CON0_BASE_EN BIT(0)
#define CON0_PWR_ON BIT(0)
#define CON0_ISO_EN BIT(1)
-#define CON0_PCW_CHG BIT(31)
+#define CON1_PCW_CHG BIT(31)
#define AUDPLL_TUNER_EN BIT(31)
@@ -69,11 +69,13 @@ static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
{
int pcwbits = pll->data->pcwbits;
int pcwfbits;
+ int ibits;
u64 vco;
u8 c = 0;
/* The fractional part of the PLL divider. */
- pcwfbits = pcwbits > INTEGER_BITS ? pcwbits - INTEGER_BITS : 0;
+ ibits = pll->data->pcwibits ? pll->data->pcwibits : INTEGER_BITS;
+ pcwfbits = pcwbits > ibits ? pcwbits - ibits : 0;
vco = (u64)fin * pcw;
@@ -93,9 +95,31 @@ static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
{
u32 con1, val;
int pll_en;
+ u32 tuner_en = 0;
+ u32 tuner_en_mask;
+ void __iomem *tuner_en_addr = NULL;
pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN;
+ /* disable tuner */
+ if (pll->tuner_en_addr) {
+ tuner_en_addr = pll->tuner_en_addr;
+ tuner_en_mask = BIT(pll->data->tuner_en_bit);
+ } else if (pll->tuner_addr) {
+ tuner_en_addr = pll->tuner_addr;
+ tuner_en_mask = AUDPLL_TUNER_EN;
+ }
+
+ if (tuner_en_addr) {
+ val = readl(tuner_en_addr);
+ tuner_en = val & tuner_en_mask;
+
+ if (tuner_en) {
+ val &= ~tuner_en_mask;
+ writel(val, tuner_en_addr);
+ }
+ }
+
/* set postdiv */
val = readl(pll->pd_addr);
val &= ~(POSTDIV_MASK << pll->data->pd_shift);
@@ -116,12 +140,20 @@ static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
con1 = readl(pll->base_addr + REG_CON1);
if (pll_en)
- con1 |= CON0_PCW_CHG;
+ con1 |= CON1_PCW_CHG;
writel(con1, pll->base_addr + REG_CON1);
+
if (pll->tuner_addr)
writel(con1 + 1, pll->tuner_addr);
+ /* restore tuner_en */
+ if (tuner_en_addr && tuner_en) {
+ val = readl(tuner_en_addr);
+ val |= tuner_en_mask;
+ writel(val, tuner_en_addr);
+ }
+
if (pll_en)
udelay(20);
}
@@ -138,9 +170,10 @@ static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
u32 freq, u32 fin)
{
- unsigned long fmin = 1000 * MHZ;
+ unsigned long fmin = pll->data->fmin ? pll->data->fmin : 1000 * MHZ;
const struct mtk_pll_div_table *div_table = pll->data->div_table;
u64 _pcw;
+ int ibits;
u32 val;
if (freq > pll->data->fmax)
@@ -164,7 +197,8 @@ static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
}
/* _pcw = freq * postdiv / fin * 2^pcwfbits */
- _pcw = ((u64)freq << val) << (pll->data->pcwbits - INTEGER_BITS);
+ ibits = pll->data->pcwibits ? pll->data->pcwibits : INTEGER_BITS;
+ _pcw = ((u64)freq << val) << (pll->data->pcwbits - ibits);
do_div(_pcw, fin);
*pcw = (u32)_pcw;
@@ -192,7 +226,6 @@ static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw,
postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & POSTDIV_MASK;
postdiv = 1 << postdiv;
-
pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift;
pcw &= GENMASK(pll->data->pcwbits - 1, 0);
--
1.7.9.5
add extend data, parent_n for domain-subdomain corresponse.
Signed-off-by: Mars Cheng <[email protected]>
Signed-off-by: Owen Chen <[email protected]>
---
drivers/soc/mediatek/mtk-scpsys-ext.c | 132 ++++++++++++++++++++++++++++++++-
1 file changed, 131 insertions(+), 1 deletion(-)
diff --git a/drivers/soc/mediatek/mtk-scpsys-ext.c b/drivers/soc/mediatek/mtk-scpsys-ext.c
index 965e64d..e649a06 100644
--- a/drivers/soc/mediatek/mtk-scpsys-ext.c
+++ b/drivers/soc/mediatek/mtk-scpsys-ext.c
@@ -13,7 +13,7 @@
#include <linux/regmap.h>
#include <linux/soc/mediatek/infracfg.h>
#include <linux/soc/mediatek/scpsys-ext.h>
-
+#include <dt-bindings/power/mt6765-power.h>
#define MAX_CLKS 10
#define INFRA "infracfg"
@@ -65,6 +65,21 @@ struct bus_mask_ops {
u32 sta_ofs, u32 mask);
};
+static struct scpsys_ext_attr *__get_attr_node(const char *scpd_n)
+{
+ struct scpsys_ext_attr *attr;
+
+ if (!scpd_n)
+ return ERR_PTR(-EINVAL);
+
+ list_for_each_entry(attr, &ext_attr_map_list, attr_list) {
+ if (attr->scpd_n && !strcmp(scpd_n, attr->scpd_n))
+ return attr;
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
static struct scpsys_ext_attr *__get_attr_parent(const char *parent_n)
{
struct scpsys_ext_attr *attr;
@@ -353,8 +368,123 @@ int scpsys_ext_attr_init(const struct scpsys_ext_data *data)
return 0;
}
+/*
+ * MT6765 extend power domain support
+ */
+
+#define INFRA_TOPAXI_PROTECTEN_SET_MT6765 0x02A0
+#define INFRA_TOPAXI_PROTECTEN_STA1_MT6765 0x0228
+#define INFRA_TOPAXI_PROTECTEN_CLR_MT6765 0x02A4
+
+#define INFRA_TOPAXI_PROTECTEN_1_SET_MT6765 0x02A8
+#define INFRA_TOPAXI_PROTECTEN_STA1_1_MT6765 0x0258
+#define INFRA_TOPAXI_PROTECTEN_1_CLR_MT6765 0x02AC
+
+#define SMI_COMMON_SMI_CLAMP_MT6765 0x03C0
+#define SMI_COMMON_SMI_CLAMP_SET_MT6765 0x03C4
+#define SMI_COMMON_SMI_CLAMP_CLR_MT6765 0x03C8
+
+static struct ext_reg_ctrl infra_bus_regs_0_mt6765 = {
+ .type = IFR_TYPE,
+ .set_ofs = INFRA_TOPAXI_PROTECTEN_SET_MT6765,
+ .clr_ofs = INFRA_TOPAXI_PROTECTEN_CLR_MT6765,
+ .sta_ofs = INFRA_TOPAXI_PROTECTEN_STA1_MT6765,
+};
+
+#define BUS_IFR0_MT6765(_mask) { \
+ .regs = &infra_bus_regs_0_mt6765, \
+ .mask = _mask, \
+ .ops = &bus_mask_set_clr_ctrl, \
+ }
+
+static struct ext_reg_ctrl infra_bus_regs_1_mt6765 = {
+ .type = IFR_TYPE,
+ .set_ofs = INFRA_TOPAXI_PROTECTEN_1_SET_MT6765,
+ .clr_ofs = INFRA_TOPAXI_PROTECTEN_1_CLR_MT6765,
+ .sta_ofs = INFRA_TOPAXI_PROTECTEN_STA1_1_MT6765,
+};
+
+#define BUS_IFR1_MT6765(_mask) { \
+ .regs = &infra_bus_regs_1_mt6765, \
+ .mask = _mask, \
+ .ops = &bus_mask_set_clr_ctrl, \
+ }
+
+static struct ext_reg_ctrl smi_bus_regs_0_mt6765 = {
+ .type = SMI_TYPE,
+ .set_ofs = SMI_COMMON_SMI_CLAMP_SET_MT6765,
+ .clr_ofs = SMI_COMMON_SMI_CLAMP_CLR_MT6765,
+ .sta_ofs = SMI_COMMON_SMI_CLAMP_MT6765,
+};
+
+#define BUS_SMI0_MT6765(_mask) { \
+ .regs = &smi_bus_regs_0_mt6765, \
+ .mask = _mask, \
+ .ops = &bus_mask_set_clr_ctrl, \
+ }
+
+static struct scpsys_ext_attr scp_ext_attr_mt6765[] = {
+ [MT6765_POWER_DOMAIN_ISP] = {
+ .scpd_n = "isp",
+ .mask = {
+ BUS_IFR1_MT6765(BIT(20)),
+ BUS_SMI0_MT6765(BIT(2)),
+ },
+ .parent_n = "mm",
+ .bus_ops = &ext_bus_ctrl,
+ .cg_ops = &ext_cg_ctrl,
+ },
+ [MT6765_POWER_DOMAIN_MM] = {
+ .scpd_n = "mm",
+ .mask = {
+ BUS_IFR1_MT6765(BIT(16) | BIT(17)),
+ BUS_IFR0_MT6765(BIT(10) | BIT(11)),
+ BUS_IFR0_MT6765(BIT(1) | BIT(2)),
+ },
+ .bus_ops = &ext_bus_ctrl,
+ .cg_ops = &ext_cg_ctrl,
+ },
+ [MT6765_POWER_DOMAIN_CONN] = {
+ .scpd_n = "conn",
+ .mask = {
+ BUS_IFR0_MT6765(BIT(13)),
+ BUS_IFR1_MT6765(BIT(18)),
+ BUS_IFR0_MT6765(BIT(14) | BIT(16)),
+ },
+ .bus_ops = &ext_bus_ctrl,
+ },
+ [MT6765_POWER_DOMAIN_MFG] = {
+ .scpd_n = "mfg",
+ .mask = {
+ BUS_IFR0_MT6765(BIT(25)),
+ BUS_IFR0_MT6765(BIT(21) | BIT(22)),
+ },
+ .bus_ops = &ext_bus_ctrl,
+ },
+ [MT6765_POWER_DOMAIN_CAM] = {
+ .scpd_n = "cam",
+ .mask = {
+ BUS_IFR1_MT6765(BIT(19) | BIT(21)),
+ BUS_IFR0_MT6765(BIT(20)),
+ BUS_SMI0_MT6765(BIT(3)),
+ },
+ .parent_n = "mm",
+ .bus_ops = &ext_bus_ctrl,
+ .cg_ops = &ext_cg_ctrl,
+ },
+};
+
+static const struct scpsys_ext_data scp_ext_data_mt6765 = {
+ .attr = scp_ext_attr_mt6765,
+ .num_attr = ARRAY_SIZE(scp_ext_attr_mt6765),
+ .get_attr = __get_attr_node,
+};
+
static const struct of_device_id of_scpsys_ext_match_tbl[] = {
{
+ .compatible = "mediatek,mt6765-scpsys",
+ .data = &scp_ext_data_mt6765,
+ }, {
/* sentinel */
}
};
--
1.7.9.5
This adds scpsys support for MT6765
Signed-off-by: Mars Cheng <[email protected]>
Signed-off-by: Owen Chen <[email protected]>
---
drivers/soc/mediatek/mtk-scpsys.c | 88 ++++++++++++++++++++++++++++++
include/dt-bindings/power/mt6765-power.h | 14 +++++
2 files changed, 102 insertions(+)
create mode 100644 include/dt-bindings/power/mt6765-power.h
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 5b24bb4..4bb6c7a 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -23,6 +23,7 @@
#include <dt-bindings/power/mt2701-power.h>
#include <dt-bindings/power/mt2712-power.h>
+#include <dt-bindings/power/mt6765-power.h>
#include <dt-bindings/power/mt6797-power.h>
#include <dt-bindings/power/mt7622-power.h>
#include <dt-bindings/power/mt7623a-power.h>
@@ -680,6 +681,79 @@ static void mtk_register_power_domains(struct platform_device *pdev,
};
/*
+ * MT6765 power domain support
+ */
+#define SPM_PWR_STATUS_MT6765 0x0180
+#define SPM_PWR_STATUS_2ND_MT6765 0x0184
+
+static const struct scp_domain_data scp_domain_data_mt6765[] = {
+ [MT6765_POWER_DOMAIN_VCODEC] = {
+ .name = "vcodec",
+ .sta_mask = BIT(26),
+ .ctl_offs = 0x300,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT6765_POWER_DOMAIN_ISP] = {
+ .name = "isp",
+ .sta_mask = BIT(5),
+ .ctl_offs = 0x308,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT6765_POWER_DOMAIN_MM] = {
+ .name = "mm",
+ .sta_mask = BIT(3),
+ .ctl_offs = 0x30C,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT6765_POWER_DOMAIN_CONN] = {
+ .name = "conn",
+ .sta_mask = BIT(1),
+ .ctl_offs = 0x32C,
+ .sram_pdn_bits = 0,
+ .sram_pdn_ack_bits = 0,
+ },
+ [MT6765_POWER_DOMAIN_MFG_ASYNC] = {
+ .name = "mfg_async",
+ .sta_mask = BIT(23),
+ .ctl_offs = 0x334,
+ .sram_pdn_bits = 0,
+ .sram_pdn_ack_bits = 0,
+ },
+ [MT6765_POWER_DOMAIN_MFG] = {
+ .name = "mfg",
+ .sta_mask = BIT(4),
+ .ctl_offs = 0x338,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+ [MT6765_POWER_DOMAIN_CAM] = {
+ .name = "cam",
+ .sta_mask = BIT(25),
+ .ctl_offs = 0x344,
+ .sram_pdn_bits = GENMASK(8, 9),
+ .sram_pdn_ack_bits = GENMASK(12, 13),
+ },
+ [MT6765_POWER_DOMAIN_MFG_CORE0] = {
+ .name = "mfg_core0",
+ .sta_mask = BIT(7),
+ .ctl_offs = 0x34C,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ },
+};
+
+static const struct scp_subdomain scp_subdomain_mt6765[] = {
+ {MT6765_POWER_DOMAIN_MM, MT6765_POWER_DOMAIN_CAM},
+ {MT6765_POWER_DOMAIN_MM, MT6765_POWER_DOMAIN_ISP},
+ {MT6765_POWER_DOMAIN_MM, MT6765_POWER_DOMAIN_VCODEC},
+ {MT6765_POWER_DOMAIN_MFG_ASYNC, MT6765_POWER_DOMAIN_MFG},
+ {MT6765_POWER_DOMAIN_MFG, MT6765_POWER_DOMAIN_MFG_CORE0},
+};
+
+/*
* MT6797 power domain support
*/
@@ -962,6 +1036,17 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.bus_prot_reg_update = false,
};
+static const struct scp_soc_data mt6765_data = {
+ .domains = scp_domain_data_mt6765,
+ .num_domains = ARRAY_SIZE(scp_domain_data_mt6765),
+ .subdomains = scp_subdomain_mt6765,
+ .num_subdomains = ARRAY_SIZE(scp_subdomain_mt6765),
+ .regs = {
+ .pwr_sta_offs = SPM_PWR_STATUS_MT6765,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6765,
+ },
+};
+
static const struct scp_soc_data mt6797_data = {
.domains = scp_domain_data_mt6797,
.num_domains = ARRAY_SIZE(scp_domain_data_mt6797),
@@ -1018,6 +1103,9 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.compatible = "mediatek,mt2712-scpsys",
.data = &mt2712_data,
}, {
+ .compatible = "mediatek,mt6765-scpsys",
+ .data = &mt6765_data,
+ }, {
.compatible = "mediatek,mt6797-scpsys",
.data = &mt6797_data,
}, {
diff --git a/include/dt-bindings/power/mt6765-power.h b/include/dt-bindings/power/mt6765-power.h
new file mode 100644
index 0000000..d347b4e
--- /dev/null
+++ b/include/dt-bindings/power/mt6765-power.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _DT_BINDINGS_POWER_MT6765_POWER_H
+#define _DT_BINDINGS_POWER_MT6765_POWER_H
+
+#define MT6765_POWER_DOMAIN_CONN 0
+#define MT6765_POWER_DOMAIN_MM 1
+#define MT6765_POWER_DOMAIN_MFG_ASYNC 2
+#define MT6765_POWER_DOMAIN_ISP 3
+#define MT6765_POWER_DOMAIN_MFG 4
+#define MT6765_POWER_DOMAIN_MFG_CORE0 5
+#define MT6765_POWER_DOMAIN_CAM 6
+#define MT6765_POWER_DOMAIN_VCODEC 7
+
+#endif /* _DT_BINDINGS_POWER_MT6765_POWER_H */
--
1.7.9.5
This adds power dt-bindings for MT6765
Signed-off-by: Mars Cheng <[email protected]>
Signed-off-by: Owen Chen <[email protected]>
---
.../devicetree/bindings/soc/mediatek/scpsys.txt | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
index d6fe16f..62a416a 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+++ b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
@@ -11,6 +11,7 @@ The driver implements the Generic PM domain bindings described in
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/mt6765-power.h
- include/dt-bindings/power/mt2701-power.h
- include/dt-bindings/power/mt2712-power.h
- include/dt-bindings/power/mt7622-power.h
@@ -19,6 +20,7 @@ Required properties:
- compatible: Should be one of:
- "mediatek,mt2701-scpsys"
- "mediatek,mt2712-scpsys"
+ - "mediatek,mt6765-scpsys"
- "mediatek,mt6797-scpsys"
- "mediatek,mt7622-scpsys"
- "mediatek,mt7623-scpsys", "mediatek,mt2701-scpsys": For MT7623 SoC
@@ -32,6 +34,10 @@ Required properties:
enabled before enabling certain power domains.
Required clocks for MT2701 or MT7623: "mm", "mfg", "ethif"
Required clocks for MT2712: "mm", "mfg", "venc", "jpgdec", "audio", "vdec"
+ Required clocks for MT6765: MUX: "mm", "mfg"
+ CG: "mm-0", "mm-1", "mm-2", "mm-3", "isp-0",
+ "isp-1", "cam-0", "cam-1", "cam-2",
+ "cam-3","cam-4"
Required clocks for MT6797: "mm", "mfg", "vdec"
Required clocks for MT7622: "hif_sel"
Required clocks for MT7622A: "ethif"
--
1.7.9.5
On 17/07/18 10:52, Mars Cheng wrote:
> Signed-off-by: Mars Cheng <[email protected]>
> Signed-off-by: Owen Chen <[email protected]>
Please provide a commit message.
Thanks,
Matthias
> ---
> include/dt-bindings/clock/mt6765-clk.h | 313 ++++++++++++++++++++++++++++++++
> 1 file changed, 313 insertions(+)
> create mode 100644 include/dt-bindings/clock/mt6765-clk.h
>
> diff --git a/include/dt-bindings/clock/mt6765-clk.h b/include/dt-bindings/clock/mt6765-clk.h
> new file mode 100644
> index 0000000..eb97e56
> --- /dev/null
> +++ b/include/dt-bindings/clock/mt6765-clk.h
> @@ -0,0 +1,313 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#ifndef _DT_BINDINGS_CLK_MT6765_H
> +#define _DT_BINDINGS_CLK_MT6765_H
> +
> +/* FIX Clks */
> +#define CLK_TOP_CLK26M 0
> +
> +/* APMIXEDSYS */
> +#define CLK_APMIXED_ARMPLL_L 0
> +#define CLK_APMIXED_ARMPLL 1
> +#define CLK_APMIXED_CCIPLL 2
> +#define CLK_APMIXED_MAINPLL 3
> +#define CLK_APMIXED_MFGPLL 4
> +#define CLK_APMIXED_MMPLL 5
> +#define CLK_APMIXED_UNIV2PLL 6
> +#define CLK_APMIXED_MSDCPLL 7
> +#define CLK_APMIXED_APLL1 8
> +#define CLK_APMIXED_MPLL 9
> +#define CLK_APMIXED_ULPOSC1 10
> +#define CLK_APMIXED_ULPOSC2 11
> +#define CLK_APMIXED_SSUSB26M 12
> +#define CLK_APMIXED_APPLL26M 13
> +#define CLK_APMIXED_MIPIC0_26M 14
> +#define CLK_APMIXED_MDPLLGP26M 15
> +#define CLK_APMIXED_MMSYS_F26M 16
> +#define CLK_APMIXED_UFS26M 17
> +#define CLK_APMIXED_MIPIC1_26M 18
> +#define CLK_APMIXED_MEMPLL26M 19
> +#define CLK_APMIXED_CLKSQ_LVPLL_26M 20
> +#define CLK_APMIXED_MIPID0_26M 21
> +#define CLK_APMIXED_NR_CLK 22
> +
> +/* TOPCKGEN */
> +#define CLK_TOP_SYSPLL 0
> +#define CLK_TOP_SYSPLL_D2 1
> +#define CLK_TOP_SYSPLL1_D2 2
> +#define CLK_TOP_SYSPLL1_D4 3
> +#define CLK_TOP_SYSPLL1_D8 4
> +#define CLK_TOP_SYSPLL1_D16 5
> +#define CLK_TOP_SYSPLL_D3 6
> +#define CLK_TOP_SYSPLL2_D2 7
> +#define CLK_TOP_SYSPLL2_D4 8
> +#define CLK_TOP_SYSPLL2_D8 9
> +#define CLK_TOP_SYSPLL_D5 10
> +#define CLK_TOP_SYSPLL3_D2 11
> +#define CLK_TOP_SYSPLL3_D4 12
> +#define CLK_TOP_SYSPLL_D7 13
> +#define CLK_TOP_SYSPLL4_D2 14
> +#define CLK_TOP_SYSPLL4_D4 15
> +#define CLK_TOP_USB20_192M 16
> +#define CLK_TOP_USB20_192M_D4 17
> +#define CLK_TOP_USB20_192M_D8 18
> +#define CLK_TOP_USB20_192M_D16 19
> +#define CLK_TOP_USB20_192M_D32 20
> +#define CLK_TOP_UNIVPLL 21
> +#define CLK_TOP_UNIVPLL_D2 22
> +#define CLK_TOP_UNIVPLL1_D2 23
> +#define CLK_TOP_UNIVPLL1_D4 24
> +#define CLK_TOP_UNIVPLL_D3 25
> +#define CLK_TOP_UNIVPLL2_D2 26
> +#define CLK_TOP_UNIVPLL2_D4 27
> +#define CLK_TOP_UNIVPLL2_D8 28
> +#define CLK_TOP_UNIVPLL2_D32 29
> +#define CLK_TOP_UNIVPLL_D5 30
> +#define CLK_TOP_UNIVPLL3_D2 31
> +#define CLK_TOP_UNIVPLL3_D4 32
> +#define CLK_TOP_MMPLL 33
> +#define CLK_TOP_MMPLL_D2 34
> +#define CLK_TOP_MPLL 35
> +#define CLK_TOP_DA_MPLL_104M_DIV 36
> +#define CLK_TOP_DA_MPLL_52M_DIV 37
> +#define CLK_TOP_MFGPLL 38
> +#define CLK_TOP_MSDCPLL 39
> +#define CLK_TOP_MSDCPLL_D2 40
> +#define CLK_TOP_APLL1 41
> +#define CLK_TOP_APLL1_D2 42
> +#define CLK_TOP_APLL1_D4 43
> +#define CLK_TOP_APLL1_D8 44
> +#define CLK_TOP_ULPOSC1 45
> +#define CLK_TOP_ULPOSC1_D2 46
> +#define CLK_TOP_ULPOSC1_D4 47
> +#define CLK_TOP_ULPOSC1_D8 48
> +#define CLK_TOP_ULPOSC1_D16 49
> +#define CLK_TOP_ULPOSC1_D32 50
> +#define CLK_TOP_DMPLL 51
> +#define CLK_TOP_F_FRTC 52
> +#define CLK_TOP_F_F26M 53
> +#define CLK_TOP_AXI 54
> +#define CLK_TOP_MM 55
> +#define CLK_TOP_SCP 56
> +#define CLK_TOP_MFG 57
> +#define CLK_TOP_F_FUART 58
> +#define CLK_TOP_SPI 59
> +#define CLK_TOP_MSDC50_0 60
> +#define CLK_TOP_MSDC30_1 61
> +#define CLK_TOP_AUDIO 62
> +#define CLK_TOP_AUD_1 63
> +#define CLK_TOP_AUD_ENGEN1 64
> +#define CLK_TOP_F_FDISP_PWM 65
> +#define CLK_TOP_SSPM 66
> +#define CLK_TOP_DXCC 67
> +#define CLK_TOP_I2C 68
> +#define CLK_TOP_F_FPWM 69
> +#define CLK_TOP_F_FSENINF 70
> +#define CLK_TOP_AES_FDE 71
> +#define CLK_TOP_F_BIST2FPC 72
> +#define CLK_TOP_ARMPLL_DIVIDER_PLL0 73
> +#define CLK_TOP_ARMPLL_DIVIDER_PLL1 74
> +#define CLK_TOP_ARMPLL_DIVIDER_PLL2 75
> +#define CLK_TOP_DA_USB20_48M_DIV 76
> +#define CLK_TOP_DA_UNIV_48M_DIV 77
> +#define CLK_TOP_APLL12_DIV0 78
> +#define CLK_TOP_APLL12_DIV1 79
> +#define CLK_TOP_APLL12_DIV2 80
> +#define CLK_TOP_APLL12_DIV3 81
> +#define CLK_TOP_ARMPLL_DIVIDER_PLL0_EN 82
> +#define CLK_TOP_ARMPLL_DIVIDER_PLL1_EN 83
> +#define CLK_TOP_ARMPLL_DIVIDER_PLL2_EN 84
> +#define CLK_TOP_FMEM_OCC_DRC_EN 85
> +#define CLK_TOP_USB20_48M_EN 86
> +#define CLK_TOP_UNIVPLL_48M_EN 87
> +#define CLK_TOP_MPLL_104M_EN 88
> +#define CLK_TOP_MPLL_52M_EN 89
> +#define CLK_TOP_F_UFS_MP_SAP_CFG_EN 90
> +#define CLK_TOP_F_BIST2FPC_EN 91
> +#define CLK_TOP_MD_32K 92
> +#define CLK_TOP_MD_26M 93
> +#define CLK_TOP_MD2_32K 94
> +#define CLK_TOP_MD2_26M 95
> +#define CLK_TOP_AXI_SEL 96
> +#define CLK_TOP_MEM_SEL 97
> +#define CLK_TOP_MM_SEL 98
> +#define CLK_TOP_SCP_SEL 99
> +#define CLK_TOP_MFG_SEL 100
> +#define CLK_TOP_ATB_SEL 101
> +#define CLK_TOP_CAMTG_SEL 102
> +#define CLK_TOP_CAMTG1_SEL 103
> +#define CLK_TOP_CAMTG2_SEL 104
> +#define CLK_TOP_CAMTG3_SEL 105
> +#define CLK_TOP_UART_SEL 106
> +#define CLK_TOP_SPI_SEL 107
> +#define CLK_TOP_MSDC50_0_HCLK_SEL 108
> +#define CLK_TOP_MSDC50_0_SEL 109
> +#define CLK_TOP_MSDC30_1_SEL 110
> +#define CLK_TOP_AUDIO_SEL 111
> +#define CLK_TOP_AUD_INTBUS_SEL 112
> +#define CLK_TOP_AUD_1_SEL 113
> +#define CLK_TOP_AUD_ENGEN1_SEL 114
> +#define CLK_TOP_DISP_PWM_SEL 115
> +#define CLK_TOP_SSPM_SEL 116
> +#define CLK_TOP_DXCC_SEL 117
> +#define CLK_TOP_USB_TOP_SEL 118
> +#define CLK_TOP_SPM_SEL 119
> +#define CLK_TOP_I2C_SEL 120
> +#define CLK_TOP_PWM_SEL 121
> +#define CLK_TOP_SENINF_SEL 122
> +#define CLK_TOP_AES_FDE_SEL 123
> +#define CLK_TOP_PWRAP_ULPOSC_SEL 124
> +#define CLK_TOP_CAMTM_SEL 125
> +#define CLK_TOP_NR_CLK 126
> +
> +/* INFRACFG */
> +#define CLK_IFR_ICUSB 0
> +#define CLK_IFR_GCE 1
> +#define CLK_IFR_THERM 2
> +#define CLK_IFR_I2C_AP 3
> +#define CLK_IFR_I2C_CCU 4
> +#define CLK_IFR_I2C_SSPM 5
> +#define CLK_IFR_I2C_RSV 6
> +#define CLK_IFR_PWM_HCLK 7
> +#define CLK_IFR_PWM1 8
> +#define CLK_IFR_PWM2 9
> +#define CLK_IFR_PWM3 10
> +#define CLK_IFR_PWM4 11
> +#define CLK_IFR_PWM5 12
> +#define CLK_IFR_PWM 13
> +#define CLK_IFR_UART0 14
> +#define CLK_IFR_UART1 15
> +#define CLK_IFR_GCE_26M 16
> +#define CLK_IFR_CQ_DMA_FPC 17
> +#define CLK_IFR_BTIF 18
> +#define CLK_IFR_SPI0 19
> +#define CLK_IFR_MSDC0 20
> +#define CLK_IFR_MSDC1 21
> +#define CLK_IFR_TRNG 22
> +#define CLK_IFR_AUXADC 23
> +#define CLK_IFR_CCIF1_AP 24
> +#define CLK_IFR_CCIF1_MD 25
> +#define CLK_IFR_AUXADC_MD 26
> +#define CLK_IFR_AP_DMA 27
> +#define CLK_IFR_DEVICE_APC 28
> +#define CLK_IFR_CCIF_AP 29
> +#define CLK_IFR_AUDIO 30
> +#define CLK_IFR_CCIF_MD 31
> +#define CLK_IFR_RG_PWM_FBCLK6 32
> +#define CLK_IFR_DISP_PWM 33
> +#define CLK_IFR_CLDMA_BCLK 34
> +#define CLK_IFR_AUDIO_26M_BCLK 35
> +#define CLK_IFR_SPI1 36
> +#define CLK_IFR_I2C4 37
> +#define CLK_IFR_SPI2 38
> +#define CLK_IFR_SPI3 39
> +#define CLK_IFR_I2C5 40
> +#define CLK_IFR_I2C5_ARBITER 41
> +#define CLK_IFR_I2C5_IMM 42
> +#define CLK_IFR_I2C1_ARBITER 43
> +#define CLK_IFR_I2C1_IMM 44
> +#define CLK_IFR_I2C2_ARBITER 45
> +#define CLK_IFR_I2C2_IMM 46
> +#define CLK_IFR_SPI4 47
> +#define CLK_IFR_SPI5 48
> +#define CLK_IFR_CQ_DMA 49
> +#define CLK_IFR_FAES_FDE 50
> +#define CLK_IFR_MSDC0_SELF 51
> +#define CLK_IFR_MSDC1_SELF 52
> +#define CLK_IFR_I2C6 53
> +#define CLK_IFR_AP_MSDC0 54
> +#define CLK_IFR_MD_MSDC0 55
> +#define CLK_IFR_MSDC0_SRC 56
> +#define CLK_IFR_MSDC1_SRC 57
> +#define CLK_IFR_AES_TOP0_BCLK 58
> +#define CLK_IFR_MCU_PM_BCLK 59
> +#define CLK_IFR_CCIF2_AP 60
> +#define CLK_IFR_CCIF2_MD 61
> +#define CLK_IFR_CCIF3_AP 62
> +#define CLK_IFR_CCIF3_MD 63
> +#define CLK_IFR_NR_CLK 64
> +
> +/* AUDIO */
> +#define CLK_AUDIO_AFE 0
> +#define CLK_AUDIO_22M 1
> +#define CLK_AUDIO_APLL_TUNER 2
> +#define CLK_AUDIO_ADC 3
> +#define CLK_AUDIO_DAC 4
> +#define CLK_AUDIO_DAC_PREDIS 5
> +#define CLK_AUDIO_TML 6
> +#define CLK_AUDIO_I2S1_BCLK 7
> +#define CLK_AUDIO_I2S2_BCLK 8
> +#define CLK_AUDIO_I2S3_BCLK 9
> +#define CLK_AUDIO_I2S4_BCLK 10
> +#define CLK_AUDIO_NR_CLK 11
> +
> +/* MIPI_RX_ANA_CSI0A */
> +
> +#define CLK_MIPI0A_CSR_CSI_EN_0A 0
> +#define CLK_MIPI0A_NR_CLK 1
> +
> +/* MMSYS_CONFIG */
> +
> +#define CLK_MM_MDP_RDMA0 0
> +#define CLK_MM_MDP_CCORR0 1
> +#define CLK_MM_MDP_RSZ0 2
> +#define CLK_MM_MDP_RSZ1 3
> +#define CLK_MM_MDP_TDSHP0 4
> +#define CLK_MM_MDP_WROT0 5
> +#define CLK_MM_MDP_WDMA0 6
> +#define CLK_MM_DISP_OVL0 7
> +#define CLK_MM_DISP_OVL0_2L 8
> +#define CLK_MM_DISP_RSZ0 9
> +#define CLK_MM_DISP_RDMA0 10
> +#define CLK_MM_DISP_WDMA0 11
> +#define CLK_MM_DISP_COLOR0 12
> +#define CLK_MM_DISP_CCORR0 13
> +#define CLK_MM_DISP_AAL0 14
> +#define CLK_MM_DISP_GAMMA0 15
> +#define CLK_MM_DISP_DITHER0 16
> +#define CLK_MM_DSI0 17
> +#define CLK_MM_FAKE_ENG 18
> +#define CLK_MM_SMI_COMMON 19
> +#define CLK_MM_SMI_LARB0 20
> +#define CLK_MM_SMI_COMM0 21
> +#define CLK_MM_SMI_COMM1 22
> +#define CLK_MM_CAM_MDP 23
> +#define CLK_MM_SMI_IMG 24
> +#define CLK_MM_SMI_CAM 25
> +#define CLK_MM_IMG_DL_RELAY 26
> +#define CLK_MM_IMG_DL_ASYNC_TOP 27
> +#define CLK_MM_DIG_DSI 28
> +#define CLK_MM_F26M_HRTWT 29
> +#define CLK_MM_NR_CLK 30
> +
> +/* IMGSYS */
> +
> +#define CLK_IMG_LARB2 0
> +#define CLK_IMG_DIP 1
> +#define CLK_IMG_FDVT 2
> +#define CLK_IMG_DPE 3
> +#define CLK_IMG_RSC 4
> +#define CLK_IMG_NR_CLK 5
> +
> +/* VENCSYS */
> +
> +#define CLK_VENC_SET0_LARB 0
> +#define CLK_VENC_SET1_VENC 1
> +#define CLK_VENC_SET2_JPGENC 2
> +#define CLK_VENC_SET3_VDEC 3
> +#define CLK_VENC_NR_CLK 4
> +
> +/* CAMSYS */
> +
> +#define CLK_CAM_LARB3 0
> +#define CLK_CAM_DFP_VAD 1
> +#define CLK_CAM 2
> +#define CLK_CAMTG 3
> +#define CLK_CAM_SENINF 4
> +#define CLK_CAMSV0 5
> +#define CLK_CAMSV1 6
> +#define CLK_CAMSV2 7
> +#define CLK_CAM_CCU 8
> +#define CLK_CAM_NR_CLK 9
> +
> +#endif /* _DT_BINDINGS_CLK_MT6765_H */
>
On Tue, 2018-07-17 at 16:52 +0800, Mars Cheng wrote:
> This adds scpsys support for MT6765
>
it looks like 4/11 have to depend on 6/11 and 7/11 to get a full function on scpsys for MT6765.
you should keep dependency in order to submit these patches
> Signed-off-by: Mars Cheng <[email protected]>
> Signed-off-by: Owen Chen <[email protected]>
> ---
> drivers/soc/mediatek/mtk-scpsys.c | 88 ++++++++++++++++++++++++++++++
> include/dt-bindings/power/mt6765-power.h | 14 +++++
> 2 files changed, 102 insertions(+)
> create mode 100644 include/dt-bindings/power/mt6765-power.h
>
> diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> index 5b24bb4..4bb6c7a 100644
> --- a/drivers/soc/mediatek/mtk-scpsys.c
> +++ b/drivers/soc/mediatek/mtk-scpsys.c
> @@ -23,6 +23,7 @@
>
> #include <dt-bindings/power/mt2701-power.h>
> #include <dt-bindings/power/mt2712-power.h>
> +#include <dt-bindings/power/mt6765-power.h>
> #include <dt-bindings/power/mt6797-power.h>
> #include <dt-bindings/power/mt7622-power.h>
> #include <dt-bindings/power/mt7623a-power.h>
> @@ -680,6 +681,79 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> };
>
> /*
> + * MT6765 power domain support
> + */
> +#define SPM_PWR_STATUS_MT6765 0x0180
> +#define SPM_PWR_STATUS_2ND_MT6765 0x0184
> +
> +static const struct scp_domain_data scp_domain_data_mt6765[] = {
> + [MT6765_POWER_DOMAIN_VCODEC] = {
> + .name = "vcodec",
> + .sta_mask = BIT(26),
> + .ctl_offs = 0x300,
> + .sram_pdn_bits = GENMASK(8, 8),
> + .sram_pdn_ack_bits = GENMASK(12, 12),
> + },
> + [MT6765_POWER_DOMAIN_ISP] = {
> + .name = "isp",
> + .sta_mask = BIT(5),
> + .ctl_offs = 0x308,
> + .sram_pdn_bits = GENMASK(8, 8),
> + .sram_pdn_ack_bits = GENMASK(12, 12),
> + },
> + [MT6765_POWER_DOMAIN_MM] = {
> + .name = "mm",
> + .sta_mask = BIT(3),
> + .ctl_offs = 0x30C,
> + .sram_pdn_bits = GENMASK(8, 8),
> + .sram_pdn_ack_bits = GENMASK(12, 12),
> + },
> + [MT6765_POWER_DOMAIN_CONN] = {
> + .name = "conn",
> + .sta_mask = BIT(1),
> + .ctl_offs = 0x32C,
> + .sram_pdn_bits = 0,
> + .sram_pdn_ack_bits = 0,
> + },
> + [MT6765_POWER_DOMAIN_MFG_ASYNC] = {
> + .name = "mfg_async",
> + .sta_mask = BIT(23),
> + .ctl_offs = 0x334,
> + .sram_pdn_bits = 0,
> + .sram_pdn_ack_bits = 0,
> + },
> + [MT6765_POWER_DOMAIN_MFG] = {
> + .name = "mfg",
> + .sta_mask = BIT(4),
> + .ctl_offs = 0x338,
> + .sram_pdn_bits = GENMASK(8, 8),
> + .sram_pdn_ack_bits = GENMASK(12, 12),
> + },
> + [MT6765_POWER_DOMAIN_CAM] = {
> + .name = "cam",
> + .sta_mask = BIT(25),
> + .ctl_offs = 0x344,
> + .sram_pdn_bits = GENMASK(8, 9),
> + .sram_pdn_ack_bits = GENMASK(12, 13),
> + },
> + [MT6765_POWER_DOMAIN_MFG_CORE0] = {
> + .name = "mfg_core0",
> + .sta_mask = BIT(7),
> + .ctl_offs = 0x34C,
> + .sram_pdn_bits = GENMASK(8, 8),
> + .sram_pdn_ack_bits = GENMASK(12, 12),
> + },
Above power domains really don't require any clock controlled with
clk_id before any access on them?
> +};
> +
> +static const struct scp_subdomain scp_subdomain_mt6765[] = {
> + {MT6765_POWER_DOMAIN_MM, MT6765_POWER_DOMAIN_CAM},
> + {MT6765_POWER_DOMAIN_MM, MT6765_POWER_DOMAIN_ISP},
> + {MT6765_POWER_DOMAIN_MM, MT6765_POWER_DOMAIN_VCODEC},
> + {MT6765_POWER_DOMAIN_MFG_ASYNC, MT6765_POWER_DOMAIN_MFG},
> + {MT6765_POWER_DOMAIN_MFG, MT6765_POWER_DOMAIN_MFG_CORE0},
> +};
> +
> +/*
> * MT6797 power domain support
> */
>
> @@ -962,6 +1036,17 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> .bus_prot_reg_update = false,
> };
>
> +static const struct scp_soc_data mt6765_data = {
> + .domains = scp_domain_data_mt6765,
> + .num_domains = ARRAY_SIZE(scp_domain_data_mt6765),
> + .subdomains = scp_subdomain_mt6765,
> + .num_subdomains = ARRAY_SIZE(scp_subdomain_mt6765),
> + .regs = {
> + .pwr_sta_offs = SPM_PWR_STATUS_MT6765,
> + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6765,
> + },
> +};
> +
> static const struct scp_soc_data mt6797_data = {
> .domains = scp_domain_data_mt6797,
> .num_domains = ARRAY_SIZE(scp_domain_data_mt6797),
> @@ -1018,6 +1103,9 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> .compatible = "mediatek,mt2712-scpsys",
> .data = &mt2712_data,
> }, {
> + .compatible = "mediatek,mt6765-scpsys",
> + .data = &mt6765_data,
> + }, {
> .compatible = "mediatek,mt6797-scpsys",
> .data = &mt6797_data,
> }, {
> diff --git a/include/dt-bindings/power/mt6765-power.h b/include/dt-bindings/power/mt6765-power.h
> new file mode 100644
> index 0000000..d347b4e
> --- /dev/null
> +++ b/include/dt-bindings/power/mt6765-power.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _DT_BINDINGS_POWER_MT6765_POWER_H
> +#define _DT_BINDINGS_POWER_MT6765_POWER_H
> +
> +#define MT6765_POWER_DOMAIN_CONN 0
> +#define MT6765_POWER_DOMAIN_MM 1
> +#define MT6765_POWER_DOMAIN_MFG_ASYNC 2
> +#define MT6765_POWER_DOMAIN_ISP 3
> +#define MT6765_POWER_DOMAIN_MFG 4
> +#define MT6765_POWER_DOMAIN_MFG_CORE0 5
> +#define MT6765_POWER_DOMAIN_CAM 6
> +#define MT6765_POWER_DOMAIN_VCODEC 7
> +
> +#endif /* _DT_BINDINGS_POWER_MT6765_POWER_H */
Hi Owen,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on robh/for-next]
[also build test ERROR on v4.18-rc5 next-20180717]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Mars-Cheng/Add-basic-SoC-support-for-mt6765/20180717-205540
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: powerpc-allyesconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.2.0 make.cross ARCH=powerpc
All error/warnings (new ones prefixed by >>):
In file included from include/linux/kernel.h:14:0,
from include/linux/clk.h:16,
from drivers/soc/mediatek/mtk-scpsys-ext.c:6:
drivers/soc/mediatek/mtk-scpsys-ext.c: In function 'bus_clk_enable_disable':
>> drivers/soc/mediatek/mtk-scpsys-ext.c:141:12: error: implicit declaration of function '__clk_get_name'; did you mean 'clk_get_rate'? [-Werror=implicit-function-declaration]
__clk_get_name(cc->clk));
^
include/linux/printk.h:304:33: note: in definition of macro 'pr_err'
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
^~~~~~~~~~~
In file included from include/linux/printk.h:7:0,
from include/linux/kernel.h:14,
from include/linux/clk.h:16,
from drivers/soc/mediatek/mtk-scpsys-ext.c:6:
>> include/linux/kern_levels.h:5:18: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'int' [-Wformat=]
#define KERN_SOH "\001" /* ASCII Start Of Header */
^
include/linux/kern_levels.h:11:18: note: in expansion of macro 'KERN_SOH'
#define KERN_ERR KERN_SOH "3" /* error conditions */
^~~~~~~~
include/linux/printk.h:304:9: note: in expansion of macro 'KERN_ERR'
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
^~~~~~~~
>> drivers/soc/mediatek/mtk-scpsys-ext.c:139:5: note: in expansion of macro 'pr_err'
pr_err("Failed to %s %s\n",
^~~~~~
drivers/soc/mediatek/mtk-scpsys-ext.c:139:28: note: format string is defined here
pr_err("Failed to %s %s\n",
~^
%d
cc1: some warnings being treated as errors
--
In file included from include/linux/kernel.h:14:0,
from include/linux/clk.h:16,
from drivers/soc//mediatek/mtk-scpsys-ext.c:6:
drivers/soc//mediatek/mtk-scpsys-ext.c: In function 'bus_clk_enable_disable':
drivers/soc//mediatek/mtk-scpsys-ext.c:141:12: error: implicit declaration of function '__clk_get_name'; did you mean 'clk_get_rate'? [-Werror=implicit-function-declaration]
__clk_get_name(cc->clk));
^
include/linux/printk.h:304:33: note: in definition of macro 'pr_err'
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
^~~~~~~~~~~
In file included from include/linux/printk.h:7:0,
from include/linux/kernel.h:14,
from include/linux/clk.h:16,
from drivers/soc//mediatek/mtk-scpsys-ext.c:6:
>> include/linux/kern_levels.h:5:18: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'int' [-Wformat=]
#define KERN_SOH "\001" /* ASCII Start Of Header */
^
include/linux/kern_levels.h:11:18: note: in expansion of macro 'KERN_SOH'
#define KERN_ERR KERN_SOH "3" /* error conditions */
^~~~~~~~
include/linux/printk.h:304:9: note: in expansion of macro 'KERN_ERR'
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
^~~~~~~~
drivers/soc//mediatek/mtk-scpsys-ext.c:139:5: note: in expansion of macro 'pr_err'
pr_err("Failed to %s %s\n",
^~~~~~
drivers/soc//mediatek/mtk-scpsys-ext.c:139:28: note: format string is defined here
pr_err("Failed to %s %s\n",
~^
%d
cc1: some warnings being treated as errors
vim +141 drivers/soc/mediatek/mtk-scpsys-ext.c
> 6 #include <linux/clk.h>
7 #include <linux/clk-provider.h>
8 #include <linux/slab.h>
9 #include <linux/export.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/of_device.h>
12 #include <linux/platform_device.h>
13 #include <linux/regmap.h>
14 #include <linux/soc/mediatek/infracfg.h>
15 #include <linux/soc/mediatek/scpsys-ext.h>
16
17
18 #define MAX_CLKS 10
19 #define INFRA "infracfg"
20 #define SMIC "smi_comm"
21
22 static LIST_HEAD(ext_clk_map_list);
23 static LIST_HEAD(ext_attr_map_list);
24
25 static struct regmap *infracfg;
26 static struct regmap *smi_comm;
27
28 enum regmap_type {
29 IFR_TYPE,
30 SMI_TYPE,
31 MAX_REGMAP_TYPE,
32 };
33
34 /**
35 * struct ext_reg_ctrl - set multiple register for bus protect
36 * @regmap: The bus protect regmap, 1: infracfg, 2: other master regmap
37 * such as SMI.
38 * @set_ofs: The set register offset to set corresponding bit to 1.
39 * @clr_ofs: The clr register offset to clear corresponding bit to 0.
40 * @sta_ofs: The status register offset to show bus protect enable/disable.
41 */
42 struct ext_reg_ctrl {
43 enum regmap_type type;
44 u32 set_ofs;
45 u32 clr_ofs;
46 u32 sta_ofs;
47 };
48
49 /**
50 * struct ext_clk_ctrl - enable multiple clks for bus protect
51 * @clk: The clk need to enable before pwr on/bus protect.
52 * @scpd_n: The name present the scpsys domain where the clks belongs to.
53 * @clk_list: The list node linked to ext_clk_map_list.
54 */
55 struct ext_clk_ctrl {
56 struct clk *clk;
57 const char *scpd_n;
58 struct list_head clk_list;
59 };
60
61 struct bus_mask_ops {
62 int (*set)(struct regmap *regmap, u32 set_ofs,
63 u32 sta_ofs, u32 mask);
64 int (*release)(struct regmap *regmap, u32 clr_ofs,
65 u32 sta_ofs, u32 mask);
66 };
67
68 static struct scpsys_ext_attr *__get_attr_parent(const char *parent_n)
69 {
70 struct scpsys_ext_attr *attr;
71
72 if (!parent_n)
73 return ERR_PTR(-EINVAL);
74
75 list_for_each_entry(attr, &ext_attr_map_list, attr_list) {
76 if (attr->scpd_n && !strcmp(parent_n, attr->scpd_n))
77 return attr;
78 }
79
80 return ERR_PTR(-EINVAL);
81 }
82
83 int bus_ctrl_set_release(struct scpsys_ext_attr *attr, bool set)
84 {
85 int i;
86 int ret = 0;
87
88 for (i = 0; i < MAX_STEP_NUM && attr->mask[i].mask; i++) {
89 struct ext_reg_ctrl *rc = attr->mask[i].regs;
90 struct regmap *regmap;
91
92 if (rc->type == IFR_TYPE)
93 regmap = infracfg;
94 else if (rc->type == SMI_TYPE)
95 regmap = smi_comm;
96 else
97 return -EINVAL;
98
99 if (set)
100 ret = attr->mask[i].ops->set(regmap,
101 rc->set_ofs,
102 rc->sta_ofs,
103 attr->mask[i].mask);
104 else
105 ret = attr->mask[i].ops->release(regmap,
106 rc->clr_ofs,
107 rc->sta_ofs,
108 attr->mask[i].mask);
109 }
110
111 return ret;
112 }
113
114 int bus_ctrl_set(struct scpsys_ext_attr *attr)
115 {
116 return bus_ctrl_set_release(attr, CMD_ENABLE);
117 }
118
119 int bus_ctrl_release(struct scpsys_ext_attr *attr)
120 {
121 return bus_ctrl_set_release(attr, CMD_DISABLE);
122 }
123
124 int bus_clk_enable_disable(struct scpsys_ext_attr *attr, bool enable)
125 {
126 int i = 0;
127 int ret = 0;
128 struct ext_clk_ctrl *cc;
129 struct clk *clk[MAX_CLKS];
130
131 list_for_each_entry(cc, &ext_clk_map_list, clk_list) {
132 if (!strcmp(cc->scpd_n, attr->scpd_n)) {
133 if (enable)
134 ret = clk_prepare_enable(cc->clk);
135 else
136 clk_disable_unprepare(cc->clk);
137
138 if (ret) {
> 139 pr_err("Failed to %s %s\n",
140 enable ? "enable" : "disable",
> 141 __clk_get_name(cc->clk));
142 goto err;
143 } else {
144 clk[i] = cc->clk;
145 i++;
146 }
147 }
148 }
149
150 return ret;
151
152 err:
153 for (--i; i >= 0; i--)
154 if (enable)
155 clk_disable_unprepare(clk[i]);
156 else
157 clk_prepare_enable(clk[i]);
158 return ret;
159 }
160
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Owen,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on robh/for-next]
[also build test ERROR on v4.18-rc5 next-20180717]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Mars-Cheng/Add-basic-SoC-support-for-mt6765/20180717-205540
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: i386-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All errors (new ones prefixed by >>):
>> drivers/clk/mediatek/clk-mt6765-vcodec.c:75:21: error: 'of_match_clk_mt6765_vcodec' undeclared here (not in a function); did you mean 'of_match_clk_mt6765_venc'?
.of_match_table = of_match_clk_mt6765_vcodec,
^~~~~~~~~~~~~~~~~~~~~~~~~~
of_match_clk_mt6765_venc
vim +75 drivers/clk/mediatek/clk-mt6765-vcodec.c
70
71 static struct platform_driver clk_mt6765_vcodec_drv = {
72 .probe = clk_mt6765_vcodec_probe,
73 .driver = {
74 .name = "clk-mt6765-vcodec",
> 75 .of_match_table = of_match_clk_mt6765_vcodec,
76 },
77 };
78
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Owen,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on robh/for-next]
[also build test WARNING on v4.18-rc5 next-20180717]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Mars-Cheng/Add-basic-SoC-support-for-mt6765/20180717-205540
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
>> drivers/soc/mediatek/mtk-scpsys-ext.c:83:5: sparse: symbol 'bus_ctrl_set_release' was not declared. Should it be static?
>> drivers/soc/mediatek/mtk-scpsys-ext.c:114:5: sparse: symbol 'bus_ctrl_set' was not declared. Should it be static?
>> drivers/soc/mediatek/mtk-scpsys-ext.c:119:5: sparse: symbol 'bus_ctrl_release' was not declared. Should it be static?
>> drivers/soc/mediatek/mtk-scpsys-ext.c:124:5: sparse: symbol 'bus_clk_enable_disable' was not declared. Should it be static?
>> drivers/soc/mediatek/mtk-scpsys-ext.c:161:5: sparse: symbol 'bus_clk_enable' was not declared. Should it be static?
>> drivers/soc/mediatek/mtk-scpsys-ext.c:192:27: sparse: symbol 'bus_mask_set_clr_ctrl' was not declared. Should it be static?
>> drivers/soc/mediatek/mtk-scpsys-ext.c:197:26: sparse: symbol 'ext_bus_ctrl' was not declared. Should it be static?
>> drivers/soc/mediatek/mtk-scpsys-ext.c:202:26: sparse: symbol 'ext_cg_ctrl' was not declared. Should it be static?
>> drivers/soc/mediatek/mtk-scpsys-ext.c:210:15: sparse: symbol 'syscon_regmap_lookup_by_phandle_idx' was not declared. Should it be static?
>> drivers/soc/mediatek/mtk-scpsys-ext.c:231:5: sparse: symbol 'scpsys_ext_regmap_init' was not declared. Should it be static?
include/linux/slab.h:631:13: sparse: undefined identifier '__builtin_mul_overflow'
>> drivers/soc/mediatek/mtk-scpsys-ext.c:324:5: sparse: symbol 'scpsys_ext_clk_init' was not declared. Should it be static?
>> drivers/soc/mediatek/mtk-scpsys-ext.c:336:5: sparse: symbol 'scpsys_ext_attr_init' was not declared. Should it be static?
include/linux/slab.h:631:13: sparse: call with no type!
Please review and possibly fold the followup patch.
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Fixes: 4666e05d0237 ("soc: mediatek: add new flow for mtcmos power.")
Signed-off-by: kbuild test robot <[email protected]>
---
mtk-scpsys-ext.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/soc/mediatek/mtk-scpsys-ext.c b/drivers/soc/mediatek/mtk-scpsys-ext.c
index 965e64d..e4ceb38 100644
--- a/drivers/soc/mediatek/mtk-scpsys-ext.c
+++ b/drivers/soc/mediatek/mtk-scpsys-ext.c
@@ -80,7 +80,7 @@ static struct scpsys_ext_attr *__get_attr_parent(const char *parent_n)
return ERR_PTR(-EINVAL);
}
-int bus_ctrl_set_release(struct scpsys_ext_attr *attr, bool set)
+static int bus_ctrl_set_release(struct scpsys_ext_attr *attr, bool set)
{
int i;
int ret = 0;
@@ -111,17 +111,17 @@ int bus_ctrl_set_release(struct scpsys_ext_attr *attr, bool set)
return ret;
}
-int bus_ctrl_set(struct scpsys_ext_attr *attr)
+static int bus_ctrl_set(struct scpsys_ext_attr *attr)
{
return bus_ctrl_set_release(attr, CMD_ENABLE);
}
-int bus_ctrl_release(struct scpsys_ext_attr *attr)
+static int bus_ctrl_release(struct scpsys_ext_attr *attr)
{
return bus_ctrl_set_release(attr, CMD_DISABLE);
}
-int bus_clk_enable_disable(struct scpsys_ext_attr *attr, bool enable)
+static int bus_clk_enable_disable(struct scpsys_ext_attr *attr, bool enable)
{
int i = 0;
int ret = 0;
@@ -158,7 +158,7 @@ int bus_clk_enable_disable(struct scpsys_ext_attr *attr, bool enable)
return ret;
}
-int bus_clk_enable(struct scpsys_ext_attr *attr)
+static int bus_clk_enable(struct scpsys_ext_attr *attr)
{
struct scpsys_ext_attr *attr_p;
int ret = 0;
@@ -189,17 +189,17 @@ int bus_clk_disable(struct scpsys_ext_attr *attr)
return ret;
}
-const struct bus_mask_ops bus_mask_set_clr_ctrl = {
+static const struct bus_mask_ops bus_mask_set_clr_ctrl = {
.set = &mtk_generic_set_cmd,
.release = &mtk_generic_clr_cmd,
};
-const struct bus_ext_ops ext_bus_ctrl = {
+static const struct bus_ext_ops ext_bus_ctrl = {
.enable = &bus_ctrl_set,
.disable = &bus_ctrl_release,
};
-const struct bus_ext_ops ext_cg_ctrl = {
+static const struct bus_ext_ops ext_cg_ctrl = {
.enable = &bus_clk_enable,
.disable = &bus_clk_disable,
};
@@ -207,9 +207,9 @@ const struct bus_ext_ops ext_cg_ctrl = {
/*
* scpsys bus driver init
*/
-struct regmap *syscon_regmap_lookup_by_phandle_idx(struct device_node *np,
- const char *property,
- int index)
+static struct regmap *syscon_regmap_lookup_by_phandle_idx(struct device_node *np,
+ const char *property,
+ int index)
{
struct device_node *syscon_np;
struct regmap *regmap;
@@ -228,7 +228,7 @@ struct regmap *syscon_regmap_lookup_by_phandle_idx(struct device_node *np,
return regmap;
}
-int scpsys_ext_regmap_init(struct platform_device *pdev)
+static int scpsys_ext_regmap_init(struct platform_device *pdev)
{
infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
INFRA);
@@ -321,7 +321,7 @@ static int add_cg_to_list(struct platform_device *pdev)
return 0;
}
-int scpsys_ext_clk_init(struct platform_device *pdev)
+static int scpsys_ext_clk_init(struct platform_device *pdev)
{
int ret = 0;
@@ -333,7 +333,7 @@ int scpsys_ext_clk_init(struct platform_device *pdev)
return ret;
}
-int scpsys_ext_attr_init(const struct scpsys_ext_data *data)
+static int scpsys_ext_attr_init(const struct scpsys_ext_data *data)
{
int i, count = 0;
Fixes: 3cff52bad99d ("clk: mediatek: Add MT6765 clock support")
Signed-off-by: kbuild test robot <[email protected]>
---
clk-mt6765.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/mediatek/clk-mt6765.c b/drivers/clk/mediatek/clk-mt6765.c
index 7b360b9..2f90511 100644
--- a/drivers/clk/mediatek/clk-mt6765.c
+++ b/drivers/clk/mediatek/clk-mt6765.c
@@ -33,8 +33,8 @@
static DEFINE_SPINLOCK(mt6765_clk_lock);
/* Total 12 subsys */
-void __iomem *cksys_base;
-void __iomem *apmixed_base;
+static void __iomem *cksys_base;
+static void __iomem *apmixed_base;
/* CKSYS */
#define CLK_SCP_CFG_0 (cksys_base + 0x200)
Hi Owen,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on robh/for-next]
[also build test WARNING on v4.18-rc5 next-20180717]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Mars-Cheng/Add-basic-SoC-support-for-mt6765/20180717-205540
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
>> drivers/clk/mediatek/clk-mt6765.c:36:14: sparse: symbol 'cksys_base' was not declared. Should it be static?
>> drivers/clk/mediatek/clk-mt6765.c:37:14: sparse: symbol 'apmixed_base' was not declared. Should it be static?
Please review and possibly fold the followup patch.
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Owen,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on robh/for-next]
[also build test ERROR on v4.18-rc5 next-20180717]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Mars-Cheng/Add-basic-SoC-support-for-mt6765/20180717-205540
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: openrisc-allyesconfig (attached as .config)
compiler: or1k-linux-gcc (GCC) 6.0.0 20160327 (experimental)
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=openrisc
All errors (new ones prefixed by >>):
In file included from include/linux/kernel.h:14:0,
from include/linux/clk.h:16,
from drivers/soc/mediatek/mtk-scpsys-ext.c:6:
drivers/soc/mediatek/mtk-scpsys-ext.c: In function 'bus_clk_enable_disable':
>> drivers/soc/mediatek/mtk-scpsys-ext.c:141:12: error: implicit declaration of function '__clk_get_name' [-Werror=implicit-function-declaration]
__clk_get_name(cc->clk));
^
include/linux/printk.h:304:33: note: in definition of macro 'pr_err'
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
^~~~~~~~~~~
In file included from include/linux/printk.h:7:0,
from include/linux/kernel.h:14,
from include/linux/clk.h:16,
from drivers/soc/mediatek/mtk-scpsys-ext.c:6:
include/linux/kern_levels.h:5:18: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'int' [-Wformat=]
#define KERN_SOH "\001" /* ASCII Start Of Header */
^
include/linux/kern_levels.h:11:18: note: in expansion of macro 'KERN_SOH'
#define KERN_ERR KERN_SOH "3" /* error conditions */
^~~~~~~~
include/linux/printk.h:304:9: note: in expansion of macro 'KERN_ERR'
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
^~~~~~~~
drivers/soc/mediatek/mtk-scpsys-ext.c:139:5: note: in expansion of macro 'pr_err'
pr_err("Failed to %s %s\n",
^~~~~~
cc1: some warnings being treated as errors
vim +/__clk_get_name +141 drivers/soc/mediatek/mtk-scpsys-ext.c
> 6 #include <linux/clk.h>
7 #include <linux/clk-provider.h>
8 #include <linux/slab.h>
9 #include <linux/export.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/of_device.h>
12 #include <linux/platform_device.h>
13 #include <linux/regmap.h>
14 #include <linux/soc/mediatek/infracfg.h>
15 #include <linux/soc/mediatek/scpsys-ext.h>
16
17
18 #define MAX_CLKS 10
19 #define INFRA "infracfg"
20 #define SMIC "smi_comm"
21
22 static LIST_HEAD(ext_clk_map_list);
23 static LIST_HEAD(ext_attr_map_list);
24
25 static struct regmap *infracfg;
26 static struct regmap *smi_comm;
27
28 enum regmap_type {
29 IFR_TYPE,
30 SMI_TYPE,
31 MAX_REGMAP_TYPE,
32 };
33
34 /**
35 * struct ext_reg_ctrl - set multiple register for bus protect
36 * @regmap: The bus protect regmap, 1: infracfg, 2: other master regmap
37 * such as SMI.
38 * @set_ofs: The set register offset to set corresponding bit to 1.
39 * @clr_ofs: The clr register offset to clear corresponding bit to 0.
40 * @sta_ofs: The status register offset to show bus protect enable/disable.
41 */
42 struct ext_reg_ctrl {
43 enum regmap_type type;
44 u32 set_ofs;
45 u32 clr_ofs;
46 u32 sta_ofs;
47 };
48
49 /**
50 * struct ext_clk_ctrl - enable multiple clks for bus protect
51 * @clk: The clk need to enable before pwr on/bus protect.
52 * @scpd_n: The name present the scpsys domain where the clks belongs to.
53 * @clk_list: The list node linked to ext_clk_map_list.
54 */
55 struct ext_clk_ctrl {
56 struct clk *clk;
57 const char *scpd_n;
58 struct list_head clk_list;
59 };
60
61 struct bus_mask_ops {
62 int (*set)(struct regmap *regmap, u32 set_ofs,
63 u32 sta_ofs, u32 mask);
64 int (*release)(struct regmap *regmap, u32 clr_ofs,
65 u32 sta_ofs, u32 mask);
66 };
67
68 static struct scpsys_ext_attr *__get_attr_parent(const char *parent_n)
69 {
70 struct scpsys_ext_attr *attr;
71
72 if (!parent_n)
73 return ERR_PTR(-EINVAL);
74
75 list_for_each_entry(attr, &ext_attr_map_list, attr_list) {
76 if (attr->scpd_n && !strcmp(parent_n, attr->scpd_n))
77 return attr;
78 }
79
80 return ERR_PTR(-EINVAL);
81 }
82
83 int bus_ctrl_set_release(struct scpsys_ext_attr *attr, bool set)
84 {
85 int i;
86 int ret = 0;
87
88 for (i = 0; i < MAX_STEP_NUM && attr->mask[i].mask; i++) {
89 struct ext_reg_ctrl *rc = attr->mask[i].regs;
90 struct regmap *regmap;
91
92 if (rc->type == IFR_TYPE)
93 regmap = infracfg;
94 else if (rc->type == SMI_TYPE)
95 regmap = smi_comm;
96 else
97 return -EINVAL;
98
99 if (set)
100 ret = attr->mask[i].ops->set(regmap,
101 rc->set_ofs,
102 rc->sta_ofs,
103 attr->mask[i].mask);
104 else
105 ret = attr->mask[i].ops->release(regmap,
106 rc->clr_ofs,
107 rc->sta_ofs,
108 attr->mask[i].mask);
109 }
110
111 return ret;
112 }
113
114 int bus_ctrl_set(struct scpsys_ext_attr *attr)
115 {
116 return bus_ctrl_set_release(attr, CMD_ENABLE);
117 }
118
119 int bus_ctrl_release(struct scpsys_ext_attr *attr)
120 {
121 return bus_ctrl_set_release(attr, CMD_DISABLE);
122 }
123
124 int bus_clk_enable_disable(struct scpsys_ext_attr *attr, bool enable)
125 {
126 int i = 0;
127 int ret = 0;
128 struct ext_clk_ctrl *cc;
129 struct clk *clk[MAX_CLKS];
130
131 list_for_each_entry(cc, &ext_clk_map_list, clk_list) {
132 if (!strcmp(cc->scpd_n, attr->scpd_n)) {
133 if (enable)
134 ret = clk_prepare_enable(cc->clk);
135 else
136 clk_disable_unprepare(cc->clk);
137
138 if (ret) {
139 pr_err("Failed to %s %s\n",
140 enable ? "enable" : "disable",
> 141 __clk_get_name(cc->clk));
142 goto err;
143 } else {
144 clk[i] = cc->clk;
145 i++;
146 }
147 }
148 }
149
150 return ret;
151
152 err:
153 for (--i; i >= 0; i--)
154 if (enable)
155 clk_disable_unprepare(clk[i]);
156 else
157 clk_prepare_enable(clk[i]);
158 return ret;
159 }
160
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Matthias
On Tue, 2018-07-17 at 12:24 +0200, Matthias Brugger wrote:
>
> On 17/07/18 10:52, Mars Cheng wrote:
> > Signed-off-by: Mars Cheng <[email protected]>
> > Signed-off-by: Owen Chen <[email protected]>
>
> Please provide a commit message.
>
> Thanks,
> Matthias
Got it, it is my bad, will add it.
Thanks.
>
> > ---
> > include/dt-bindings/clock/mt6765-clk.h | 313 ++++++++++++++++++++++++++++++++
> > 1 file changed, 313 insertions(+)
> > create mode 100644 include/dt-bindings/clock/mt6765-clk.h
> >
> > diff --git a/include/dt-bindings/clock/mt6765-clk.h b/include/dt-bindings/clock/mt6765-clk.h
> > new file mode 100644
> > index 0000000..eb97e56
> > --- /dev/null
> > +++ b/include/dt-bindings/clock/mt6765-clk.h
> > @@ -0,0 +1,313 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +
> > +#ifndef _DT_BINDINGS_CLK_MT6765_H
> > +#define _DT_BINDINGS_CLK_MT6765_H
> > +
> > +/* FIX Clks */
> > +#define CLK_TOP_CLK26M 0
> > +
> > +/* APMIXEDSYS */
> > +#define CLK_APMIXED_ARMPLL_L 0
> > +#define CLK_APMIXED_ARMPLL 1
> > +#define CLK_APMIXED_CCIPLL 2
> > +#define CLK_APMIXED_MAINPLL 3
> > +#define CLK_APMIXED_MFGPLL 4
> > +#define CLK_APMIXED_MMPLL 5
> > +#define CLK_APMIXED_UNIV2PLL 6
> > +#define CLK_APMIXED_MSDCPLL 7
> > +#define CLK_APMIXED_APLL1 8
> > +#define CLK_APMIXED_MPLL 9
> > +#define CLK_APMIXED_ULPOSC1 10
> > +#define CLK_APMIXED_ULPOSC2 11
> > +#define CLK_APMIXED_SSUSB26M 12
> > +#define CLK_APMIXED_APPLL26M 13
> > +#define CLK_APMIXED_MIPIC0_26M 14
> > +#define CLK_APMIXED_MDPLLGP26M 15
> > +#define CLK_APMIXED_MMSYS_F26M 16
> > +#define CLK_APMIXED_UFS26M 17
> > +#define CLK_APMIXED_MIPIC1_26M 18
> > +#define CLK_APMIXED_MEMPLL26M 19
> > +#define CLK_APMIXED_CLKSQ_LVPLL_26M 20
> > +#define CLK_APMIXED_MIPID0_26M 21
> > +#define CLK_APMIXED_NR_CLK 22
> > +
> > +/* TOPCKGEN */
> > +#define CLK_TOP_SYSPLL 0
> > +#define CLK_TOP_SYSPLL_D2 1
> > +#define CLK_TOP_SYSPLL1_D2 2
> > +#define CLK_TOP_SYSPLL1_D4 3
> > +#define CLK_TOP_SYSPLL1_D8 4
> > +#define CLK_TOP_SYSPLL1_D16 5
> > +#define CLK_TOP_SYSPLL_D3 6
> > +#define CLK_TOP_SYSPLL2_D2 7
> > +#define CLK_TOP_SYSPLL2_D4 8
> > +#define CLK_TOP_SYSPLL2_D8 9
> > +#define CLK_TOP_SYSPLL_D5 10
> > +#define CLK_TOP_SYSPLL3_D2 11
> > +#define CLK_TOP_SYSPLL3_D4 12
> > +#define CLK_TOP_SYSPLL_D7 13
> > +#define CLK_TOP_SYSPLL4_D2 14
> > +#define CLK_TOP_SYSPLL4_D4 15
> > +#define CLK_TOP_USB20_192M 16
> > +#define CLK_TOP_USB20_192M_D4 17
> > +#define CLK_TOP_USB20_192M_D8 18
> > +#define CLK_TOP_USB20_192M_D16 19
> > +#define CLK_TOP_USB20_192M_D32 20
> > +#define CLK_TOP_UNIVPLL 21
> > +#define CLK_TOP_UNIVPLL_D2 22
> > +#define CLK_TOP_UNIVPLL1_D2 23
> > +#define CLK_TOP_UNIVPLL1_D4 24
> > +#define CLK_TOP_UNIVPLL_D3 25
> > +#define CLK_TOP_UNIVPLL2_D2 26
> > +#define CLK_TOP_UNIVPLL2_D4 27
> > +#define CLK_TOP_UNIVPLL2_D8 28
> > +#define CLK_TOP_UNIVPLL2_D32 29
> > +#define CLK_TOP_UNIVPLL_D5 30
> > +#define CLK_TOP_UNIVPLL3_D2 31
> > +#define CLK_TOP_UNIVPLL3_D4 32
> > +#define CLK_TOP_MMPLL 33
> > +#define CLK_TOP_MMPLL_D2 34
> > +#define CLK_TOP_MPLL 35
> > +#define CLK_TOP_DA_MPLL_104M_DIV 36
> > +#define CLK_TOP_DA_MPLL_52M_DIV 37
> > +#define CLK_TOP_MFGPLL 38
> > +#define CLK_TOP_MSDCPLL 39
> > +#define CLK_TOP_MSDCPLL_D2 40
> > +#define CLK_TOP_APLL1 41
> > +#define CLK_TOP_APLL1_D2 42
> > +#define CLK_TOP_APLL1_D4 43
> > +#define CLK_TOP_APLL1_D8 44
> > +#define CLK_TOP_ULPOSC1 45
> > +#define CLK_TOP_ULPOSC1_D2 46
> > +#define CLK_TOP_ULPOSC1_D4 47
> > +#define CLK_TOP_ULPOSC1_D8 48
> > +#define CLK_TOP_ULPOSC1_D16 49
> > +#define CLK_TOP_ULPOSC1_D32 50
> > +#define CLK_TOP_DMPLL 51
> > +#define CLK_TOP_F_FRTC 52
> > +#define CLK_TOP_F_F26M 53
> > +#define CLK_TOP_AXI 54
> > +#define CLK_TOP_MM 55
> > +#define CLK_TOP_SCP 56
> > +#define CLK_TOP_MFG 57
> > +#define CLK_TOP_F_FUART 58
> > +#define CLK_TOP_SPI 59
> > +#define CLK_TOP_MSDC50_0 60
> > +#define CLK_TOP_MSDC30_1 61
> > +#define CLK_TOP_AUDIO 62
> > +#define CLK_TOP_AUD_1 63
> > +#define CLK_TOP_AUD_ENGEN1 64
> > +#define CLK_TOP_F_FDISP_PWM 65
> > +#define CLK_TOP_SSPM 66
> > +#define CLK_TOP_DXCC 67
> > +#define CLK_TOP_I2C 68
> > +#define CLK_TOP_F_FPWM 69
> > +#define CLK_TOP_F_FSENINF 70
> > +#define CLK_TOP_AES_FDE 71
> > +#define CLK_TOP_F_BIST2FPC 72
> > +#define CLK_TOP_ARMPLL_DIVIDER_PLL0 73
> > +#define CLK_TOP_ARMPLL_DIVIDER_PLL1 74
> > +#define CLK_TOP_ARMPLL_DIVIDER_PLL2 75
> > +#define CLK_TOP_DA_USB20_48M_DIV 76
> > +#define CLK_TOP_DA_UNIV_48M_DIV 77
> > +#define CLK_TOP_APLL12_DIV0 78
> > +#define CLK_TOP_APLL12_DIV1 79
> > +#define CLK_TOP_APLL12_DIV2 80
> > +#define CLK_TOP_APLL12_DIV3 81
> > +#define CLK_TOP_ARMPLL_DIVIDER_PLL0_EN 82
> > +#define CLK_TOP_ARMPLL_DIVIDER_PLL1_EN 83
> > +#define CLK_TOP_ARMPLL_DIVIDER_PLL2_EN 84
> > +#define CLK_TOP_FMEM_OCC_DRC_EN 85
> > +#define CLK_TOP_USB20_48M_EN 86
> > +#define CLK_TOP_UNIVPLL_48M_EN 87
> > +#define CLK_TOP_MPLL_104M_EN 88
> > +#define CLK_TOP_MPLL_52M_EN 89
> > +#define CLK_TOP_F_UFS_MP_SAP_CFG_EN 90
> > +#define CLK_TOP_F_BIST2FPC_EN 91
> > +#define CLK_TOP_MD_32K 92
> > +#define CLK_TOP_MD_26M 93
> > +#define CLK_TOP_MD2_32K 94
> > +#define CLK_TOP_MD2_26M 95
> > +#define CLK_TOP_AXI_SEL 96
> > +#define CLK_TOP_MEM_SEL 97
> > +#define CLK_TOP_MM_SEL 98
> > +#define CLK_TOP_SCP_SEL 99
> > +#define CLK_TOP_MFG_SEL 100
> > +#define CLK_TOP_ATB_SEL 101
> > +#define CLK_TOP_CAMTG_SEL 102
> > +#define CLK_TOP_CAMTG1_SEL 103
> > +#define CLK_TOP_CAMTG2_SEL 104
> > +#define CLK_TOP_CAMTG3_SEL 105
> > +#define CLK_TOP_UART_SEL 106
> > +#define CLK_TOP_SPI_SEL 107
> > +#define CLK_TOP_MSDC50_0_HCLK_SEL 108
> > +#define CLK_TOP_MSDC50_0_SEL 109
> > +#define CLK_TOP_MSDC30_1_SEL 110
> > +#define CLK_TOP_AUDIO_SEL 111
> > +#define CLK_TOP_AUD_INTBUS_SEL 112
> > +#define CLK_TOP_AUD_1_SEL 113
> > +#define CLK_TOP_AUD_ENGEN1_SEL 114
> > +#define CLK_TOP_DISP_PWM_SEL 115
> > +#define CLK_TOP_SSPM_SEL 116
> > +#define CLK_TOP_DXCC_SEL 117
> > +#define CLK_TOP_USB_TOP_SEL 118
> > +#define CLK_TOP_SPM_SEL 119
> > +#define CLK_TOP_I2C_SEL 120
> > +#define CLK_TOP_PWM_SEL 121
> > +#define CLK_TOP_SENINF_SEL 122
> > +#define CLK_TOP_AES_FDE_SEL 123
> > +#define CLK_TOP_PWRAP_ULPOSC_SEL 124
> > +#define CLK_TOP_CAMTM_SEL 125
> > +#define CLK_TOP_NR_CLK 126
> > +
> > +/* INFRACFG */
> > +#define CLK_IFR_ICUSB 0
> > +#define CLK_IFR_GCE 1
> > +#define CLK_IFR_THERM 2
> > +#define CLK_IFR_I2C_AP 3
> > +#define CLK_IFR_I2C_CCU 4
> > +#define CLK_IFR_I2C_SSPM 5
> > +#define CLK_IFR_I2C_RSV 6
> > +#define CLK_IFR_PWM_HCLK 7
> > +#define CLK_IFR_PWM1 8
> > +#define CLK_IFR_PWM2 9
> > +#define CLK_IFR_PWM3 10
> > +#define CLK_IFR_PWM4 11
> > +#define CLK_IFR_PWM5 12
> > +#define CLK_IFR_PWM 13
> > +#define CLK_IFR_UART0 14
> > +#define CLK_IFR_UART1 15
> > +#define CLK_IFR_GCE_26M 16
> > +#define CLK_IFR_CQ_DMA_FPC 17
> > +#define CLK_IFR_BTIF 18
> > +#define CLK_IFR_SPI0 19
> > +#define CLK_IFR_MSDC0 20
> > +#define CLK_IFR_MSDC1 21
> > +#define CLK_IFR_TRNG 22
> > +#define CLK_IFR_AUXADC 23
> > +#define CLK_IFR_CCIF1_AP 24
> > +#define CLK_IFR_CCIF1_MD 25
> > +#define CLK_IFR_AUXADC_MD 26
> > +#define CLK_IFR_AP_DMA 27
> > +#define CLK_IFR_DEVICE_APC 28
> > +#define CLK_IFR_CCIF_AP 29
> > +#define CLK_IFR_AUDIO 30
> > +#define CLK_IFR_CCIF_MD 31
> > +#define CLK_IFR_RG_PWM_FBCLK6 32
> > +#define CLK_IFR_DISP_PWM 33
> > +#define CLK_IFR_CLDMA_BCLK 34
> > +#define CLK_IFR_AUDIO_26M_BCLK 35
> > +#define CLK_IFR_SPI1 36
> > +#define CLK_IFR_I2C4 37
> > +#define CLK_IFR_SPI2 38
> > +#define CLK_IFR_SPI3 39
> > +#define CLK_IFR_I2C5 40
> > +#define CLK_IFR_I2C5_ARBITER 41
> > +#define CLK_IFR_I2C5_IMM 42
> > +#define CLK_IFR_I2C1_ARBITER 43
> > +#define CLK_IFR_I2C1_IMM 44
> > +#define CLK_IFR_I2C2_ARBITER 45
> > +#define CLK_IFR_I2C2_IMM 46
> > +#define CLK_IFR_SPI4 47
> > +#define CLK_IFR_SPI5 48
> > +#define CLK_IFR_CQ_DMA 49
> > +#define CLK_IFR_FAES_FDE 50
> > +#define CLK_IFR_MSDC0_SELF 51
> > +#define CLK_IFR_MSDC1_SELF 52
> > +#define CLK_IFR_I2C6 53
> > +#define CLK_IFR_AP_MSDC0 54
> > +#define CLK_IFR_MD_MSDC0 55
> > +#define CLK_IFR_MSDC0_SRC 56
> > +#define CLK_IFR_MSDC1_SRC 57
> > +#define CLK_IFR_AES_TOP0_BCLK 58
> > +#define CLK_IFR_MCU_PM_BCLK 59
> > +#define CLK_IFR_CCIF2_AP 60
> > +#define CLK_IFR_CCIF2_MD 61
> > +#define CLK_IFR_CCIF3_AP 62
> > +#define CLK_IFR_CCIF3_MD 63
> > +#define CLK_IFR_NR_CLK 64
> > +
> > +/* AUDIO */
> > +#define CLK_AUDIO_AFE 0
> > +#define CLK_AUDIO_22M 1
> > +#define CLK_AUDIO_APLL_TUNER 2
> > +#define CLK_AUDIO_ADC 3
> > +#define CLK_AUDIO_DAC 4
> > +#define CLK_AUDIO_DAC_PREDIS 5
> > +#define CLK_AUDIO_TML 6
> > +#define CLK_AUDIO_I2S1_BCLK 7
> > +#define CLK_AUDIO_I2S2_BCLK 8
> > +#define CLK_AUDIO_I2S3_BCLK 9
> > +#define CLK_AUDIO_I2S4_BCLK 10
> > +#define CLK_AUDIO_NR_CLK 11
> > +
> > +/* MIPI_RX_ANA_CSI0A */
> > +
> > +#define CLK_MIPI0A_CSR_CSI_EN_0A 0
> > +#define CLK_MIPI0A_NR_CLK 1
> > +
> > +/* MMSYS_CONFIG */
> > +
> > +#define CLK_MM_MDP_RDMA0 0
> > +#define CLK_MM_MDP_CCORR0 1
> > +#define CLK_MM_MDP_RSZ0 2
> > +#define CLK_MM_MDP_RSZ1 3
> > +#define CLK_MM_MDP_TDSHP0 4
> > +#define CLK_MM_MDP_WROT0 5
> > +#define CLK_MM_MDP_WDMA0 6
> > +#define CLK_MM_DISP_OVL0 7
> > +#define CLK_MM_DISP_OVL0_2L 8
> > +#define CLK_MM_DISP_RSZ0 9
> > +#define CLK_MM_DISP_RDMA0 10
> > +#define CLK_MM_DISP_WDMA0 11
> > +#define CLK_MM_DISP_COLOR0 12
> > +#define CLK_MM_DISP_CCORR0 13
> > +#define CLK_MM_DISP_AAL0 14
> > +#define CLK_MM_DISP_GAMMA0 15
> > +#define CLK_MM_DISP_DITHER0 16
> > +#define CLK_MM_DSI0 17
> > +#define CLK_MM_FAKE_ENG 18
> > +#define CLK_MM_SMI_COMMON 19
> > +#define CLK_MM_SMI_LARB0 20
> > +#define CLK_MM_SMI_COMM0 21
> > +#define CLK_MM_SMI_COMM1 22
> > +#define CLK_MM_CAM_MDP 23
> > +#define CLK_MM_SMI_IMG 24
> > +#define CLK_MM_SMI_CAM 25
> > +#define CLK_MM_IMG_DL_RELAY 26
> > +#define CLK_MM_IMG_DL_ASYNC_TOP 27
> > +#define CLK_MM_DIG_DSI 28
> > +#define CLK_MM_F26M_HRTWT 29
> > +#define CLK_MM_NR_CLK 30
> > +
> > +/* IMGSYS */
> > +
> > +#define CLK_IMG_LARB2 0
> > +#define CLK_IMG_DIP 1
> > +#define CLK_IMG_FDVT 2
> > +#define CLK_IMG_DPE 3
> > +#define CLK_IMG_RSC 4
> > +#define CLK_IMG_NR_CLK 5
> > +
> > +/* VENCSYS */
> > +
> > +#define CLK_VENC_SET0_LARB 0
> > +#define CLK_VENC_SET1_VENC 1
> > +#define CLK_VENC_SET2_JPGENC 2
> > +#define CLK_VENC_SET3_VDEC 3
> > +#define CLK_VENC_NR_CLK 4
> > +
> > +/* CAMSYS */
> > +
> > +#define CLK_CAM_LARB3 0
> > +#define CLK_CAM_DFP_VAD 1
> > +#define CLK_CAM 2
> > +#define CLK_CAMTG 3
> > +#define CLK_CAM_SENINF 4
> > +#define CLK_CAMSV0 5
> > +#define CLK_CAMSV1 6
> > +#define CLK_CAMSV2 7
> > +#define CLK_CAM_CCU 8
> > +#define CLK_CAM_NR_CLK 9
> > +
> > +#endif /* _DT_BINDINGS_CLK_MT6765_H */
> >
Hi Sean
On Tue, 2018-07-17 at 21:00 +0800, Sean Wang wrote:
> On Tue, 2018-07-17 at 16:52 +0800, Mars Cheng wrote:
> > This adds scpsys support for MT6765
> >
>
> it looks like 4/11 have to depend on 6/11 and 7/11 to get a full function on scpsys for MT6765.
>
> you should keep dependency in order to submit these patches
>
Got it, will reorder the sequence.
> > Signed-off-by: Mars Cheng <[email protected]>
> > Signed-off-by: Owen Chen <[email protected]>
> > ---
> > drivers/soc/mediatek/mtk-scpsys.c | 88 ++++++++++++++++++++++++++++++
> > include/dt-bindings/power/mt6765-power.h | 14 +++++
> > 2 files changed, 102 insertions(+)
> > create mode 100644 include/dt-bindings/power/mt6765-power.h
> >
> > diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> > index 5b24bb4..4bb6c7a 100644
> > --- a/drivers/soc/mediatek/mtk-scpsys.c
> > +++ b/drivers/soc/mediatek/mtk-scpsys.c
> > @@ -23,6 +23,7 @@
> >
> > #include <dt-bindings/power/mt2701-power.h>
> > #include <dt-bindings/power/mt2712-power.h>
> > +#include <dt-bindings/power/mt6765-power.h>
> > #include <dt-bindings/power/mt6797-power.h>
> > #include <dt-bindings/power/mt7622-power.h>
> > #include <dt-bindings/power/mt7623a-power.h>
> > @@ -680,6 +681,79 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> > };
> >
> > /*
> > + * MT6765 power domain support
> > + */
> > +#define SPM_PWR_STATUS_MT6765 0x0180
> > +#define SPM_PWR_STATUS_2ND_MT6765 0x0184
> > +
> > +static const struct scp_domain_data scp_domain_data_mt6765[] = {
> > + [MT6765_POWER_DOMAIN_VCODEC] = {
> > + .name = "vcodec",
> > + .sta_mask = BIT(26),
> > + .ctl_offs = 0x300,
> > + .sram_pdn_bits = GENMASK(8, 8),
> > + .sram_pdn_ack_bits = GENMASK(12, 12),
> > + },
> > + [MT6765_POWER_DOMAIN_ISP] = {
> > + .name = "isp",
> > + .sta_mask = BIT(5),
> > + .ctl_offs = 0x308,
> > + .sram_pdn_bits = GENMASK(8, 8),
> > + .sram_pdn_ack_bits = GENMASK(12, 12),
> > + },
> > + [MT6765_POWER_DOMAIN_MM] = {
> > + .name = "mm",
> > + .sta_mask = BIT(3),
> > + .ctl_offs = 0x30C,
> > + .sram_pdn_bits = GENMASK(8, 8),
> > + .sram_pdn_ack_bits = GENMASK(12, 12),
> > + },
> > + [MT6765_POWER_DOMAIN_CONN] = {
> > + .name = "conn",
> > + .sta_mask = BIT(1),
> > + .ctl_offs = 0x32C,
> > + .sram_pdn_bits = 0,
> > + .sram_pdn_ack_bits = 0,
> > + },
> > + [MT6765_POWER_DOMAIN_MFG_ASYNC] = {
> > + .name = "mfg_async",
> > + .sta_mask = BIT(23),
> > + .ctl_offs = 0x334,
> > + .sram_pdn_bits = 0,
> > + .sram_pdn_ack_bits = 0,
> > + },
> > + [MT6765_POWER_DOMAIN_MFG] = {
> > + .name = "mfg",
> > + .sta_mask = BIT(4),
> > + .ctl_offs = 0x338,
> > + .sram_pdn_bits = GENMASK(8, 8),
> > + .sram_pdn_ack_bits = GENMASK(12, 12),
> > + },
> > + [MT6765_POWER_DOMAIN_CAM] = {
> > + .name = "cam",
> > + .sta_mask = BIT(25),
> > + .ctl_offs = 0x344,
> > + .sram_pdn_bits = GENMASK(8, 9),
> > + .sram_pdn_ack_bits = GENMASK(12, 13),
> > + },
> > + [MT6765_POWER_DOMAIN_MFG_CORE0] = {
> > + .name = "mfg_core0",
> > + .sta_mask = BIT(7),
> > + .ctl_offs = 0x34C,
> > + .sram_pdn_bits = GENMASK(8, 8),
> > + .sram_pdn_ack_bits = GENMASK(12, 12),
> > + },
>
> Above power domains really don't require any clock controlled with
> clk_id before any access on them?
>
Yes, already sync with Owen, they are lost. will add them.
Thanks.
> > +};
> > +
> > +static const struct scp_subdomain scp_subdomain_mt6765[] = {
> > + {MT6765_POWER_DOMAIN_MM, MT6765_POWER_DOMAIN_CAM},
> > + {MT6765_POWER_DOMAIN_MM, MT6765_POWER_DOMAIN_ISP},
> > + {MT6765_POWER_DOMAIN_MM, MT6765_POWER_DOMAIN_VCODEC},
> > + {MT6765_POWER_DOMAIN_MFG_ASYNC, MT6765_POWER_DOMAIN_MFG},
> > + {MT6765_POWER_DOMAIN_MFG, MT6765_POWER_DOMAIN_MFG_CORE0},
> > +};
> > +
> > +/*
> > * MT6797 power domain support
> > */
> >
> > @@ -962,6 +1036,17 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> > .bus_prot_reg_update = false,
> > };
> >
> > +static const struct scp_soc_data mt6765_data = {
> > + .domains = scp_domain_data_mt6765,
> > + .num_domains = ARRAY_SIZE(scp_domain_data_mt6765),
> > + .subdomains = scp_subdomain_mt6765,
> > + .num_subdomains = ARRAY_SIZE(scp_subdomain_mt6765),
> > + .regs = {
> > + .pwr_sta_offs = SPM_PWR_STATUS_MT6765,
> > + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6765,
> > + },
> > +};
> > +
> > static const struct scp_soc_data mt6797_data = {
> > .domains = scp_domain_data_mt6797,
> > .num_domains = ARRAY_SIZE(scp_domain_data_mt6797),
> > @@ -1018,6 +1103,9 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> > .compatible = "mediatek,mt2712-scpsys",
> > .data = &mt2712_data,
> > }, {
> > + .compatible = "mediatek,mt6765-scpsys",
> > + .data = &mt6765_data,
> > + }, {
> > .compatible = "mediatek,mt6797-scpsys",
> > .data = &mt6797_data,
> > }, {
> > diff --git a/include/dt-bindings/power/mt6765-power.h b/include/dt-bindings/power/mt6765-power.h
> > new file mode 100644
> > index 0000000..d347b4e
> > --- /dev/null
> > +++ b/include/dt-bindings/power/mt6765-power.h
> > @@ -0,0 +1,14 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +#ifndef _DT_BINDINGS_POWER_MT6765_POWER_H
> > +#define _DT_BINDINGS_POWER_MT6765_POWER_H
> > +
> > +#define MT6765_POWER_DOMAIN_CONN 0
> > +#define MT6765_POWER_DOMAIN_MM 1
> > +#define MT6765_POWER_DOMAIN_MFG_ASYNC 2
> > +#define MT6765_POWER_DOMAIN_ISP 3
> > +#define MT6765_POWER_DOMAIN_MFG 4
> > +#define MT6765_POWER_DOMAIN_MFG_CORE0 5
> > +#define MT6765_POWER_DOMAIN_CAM 6
> > +#define MT6765_POWER_DOMAIN_VCODEC 7
> > +
> > +#endif /* _DT_BINDINGS_POWER_MT6765_POWER_H */
>
>
On 17/07/18 10:52, Mars Cheng wrote:
> From: Owen Chen <[email protected]>
>
> MT6765 need multiple register and actions to setup bus
> protect.
> 1. turn on subsys CG before release bus protect to receive
> ack.
> 2. turn off subsys CG after set bus protect and receive
> ack.
> 3. bus protect need not only infracfg but other domain
> register to setup. Therefore we add a set/clr APIs
> with more customize arguments.
>
> Signed-off-by: Owen Chen <[email protected]>
> Signed-off-by: Mars Cheng <[email protected]>
> ---
> drivers/soc/mediatek/Makefile | 2 +-
> drivers/soc/mediatek/mtk-infracfg.c | 178 +++++++++++---
> drivers/soc/mediatek/mtk-scpsys-ext.c | 405 +++++++++++++++++++++++++++++++
> drivers/soc/mediatek/mtk-scpsys.c | 147 +++++++++--
> include/linux/soc/mediatek/infracfg.h | 9 +-
> include/linux/soc/mediatek/scpsys-ext.h | 66 +++++
> 6 files changed, 745 insertions(+), 62 deletions(-)
> create mode 100644 drivers/soc/mediatek/mtk-scpsys-ext.c
> create mode 100644 include/linux/soc/mediatek/scpsys-ext.h
>
> diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
> index 12998b0..9dc6670 100644
> --- a/drivers/soc/mediatek/Makefile
> +++ b/drivers/soc/mediatek/Makefile
> @@ -1,3 +1,3 @@
> -obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
> +obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o mtk-scpsys-ext.o
> obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
> obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
> diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c
> index 958861c..11eadf8 100644
> --- a/drivers/soc/mediatek/mtk-infracfg.c
> +++ b/drivers/soc/mediatek/mtk-infracfg.c
> @@ -1,3 +1,4 @@
> +// SPDX-License-Identifier: GPL-2.0
> /*
> * Copyright (c) 2015 Pengutronix, Sascha Hauer <[email protected]>
> *
> @@ -15,6 +16,7 @@
> #include <linux/jiffies.h>
> #include <linux/regmap.h>
> #include <linux/soc/mediatek/infracfg.h>
> +#include <linux/soc/mediatek/scpsys-ext.h>
> #include <asm/processor.h>
>
> #define MTK_POLL_DELAY_US 10
> @@ -26,62 +28,176 @@
> #define INFRA_TOPAXI_PROTECTEN_CLR 0x0264
>
> /**
> - * mtk_infracfg_set_bus_protection - enable bus protection
> - * @regmap: The infracfg regmap
> - * @mask: The mask containing the protection bits to be enabled.
> - * @reg_update: The boolean flag determines to set the protection bits
> - * by regmap_update_bits with enable register(PROTECTEN) or
> - * by regmap_write with set register(PROTECTEN_SET).
> + * mtk_generic_set_cmd - enable bus protection with set register
> + * @regmap: The bus protect regmap
> + * @set_ofs: The set register offset to set corresponding bit to 1.
> + * @sta_ofs: The status register offset to show bus protect enable/disable.
> + * @mask: The mask containing the protection bits to be disabled.
> *
> * 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,
> - bool reg_update)
> +int mtk_generic_set_cmd(struct regmap *regmap, u32 set_ofs,
> + u32 sta_ofs, u32 mask)
> {
> u32 val;
> int ret;
>
> - if (reg_update)
> - regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask,
> - mask);
> - else
> - regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_SET, mask);
> + regmap_write(regmap, set_ofs, mask);
>
> - ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1,
> - val, (val & mask) == mask,
> - MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> + ret = regmap_read_poll_timeout(regmap, sta_ofs, val,
> + (val & mask) == mask,
> + MTK_POLL_DELAY_US,
> + MTK_POLL_TIMEOUT);
>
> return ret;
> }
>
> /**
> - * mtk_infracfg_clear_bus_protection - disable bus protection
> - * @regmap: The infracfg regmap
> + * mtk_generic_clr_cmd - disable bus protection with clr register
> + * @regmap: The bus protect regmap
> + * @clr_ofs: The clr register offset to clear corresponding bit to 0.
> + * @sta_ofs: The status register offset to show bus protect enable/disable.
> * @mask: The mask containing the protection bits to be disabled.
> - * @reg_update: The boolean flag determines to clear the protection bits
> - * by regmap_update_bits with enable register(PROTECTEN) or
> - * by regmap_write with clear register(PROTECTEN_CLR).
> *
> * This function disables the bus protection bits previously enabled with
> - * mtk_infracfg_set_bus_protection.
> + * mtk_set_bus_protection.
> */
>
> -int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
> - bool reg_update)
> +int mtk_generic_clr_cmd(struct regmap *regmap, u32 clr_ofs,
> + u32 sta_ofs, u32 mask)
> {
> int ret;
> u32 val;
>
> - if (reg_update)
> - regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
> - else
> - regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_CLR, mask);
> + regmap_write(regmap, clr_ofs, mask);
>
> - ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1,
> - val, !(val & mask),
> - MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> + ret = regmap_read_poll_timeout(regmap, sta_ofs, val,
> + !(val & mask),
> + MTK_POLL_DELAY_US,
> + MTK_POLL_TIMEOUT);
> + return ret;
> +}
> +
> +/**
> + * mtk_generic_enable_cmd - enable bus protection with upd register
> + * @regmap: The bus protect regmap
> + * @upd_ofs: The update register offset to directly rewrite value to
> + * corresponding bit.
> + * @sta_ofs: The status register offset to show bus protect enable/disable.
> + * @mask: The mask containing the protection bits to be disabled.
> + *
> + * 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_generic_enable_cmd(struct regmap *regmap, u32 upd_ofs,
> + u32 sta_ofs, u32 mask)
> +{
> + u32 val;
> + int ret;
> +
> + regmap_update_bits(regmap, upd_ofs, mask, mask);
>
> + ret = regmap_read_poll_timeout(regmap, sta_ofs, val,
> + (val & mask) == mask,
> + MTK_POLL_DELAY_US,
> + MTK_POLL_TIMEOUT);
> return ret;
> }
> +
> +/**
> + * mtk_generic_disable_cmd - disable bus protection with updd register
> + * @regmap: The bus protect regmap
> + * @upd_ofs: The update register offset to directly rewrite value to
> + * corresponding bit.
> + * @sta_ofs: The status register offset to show bus protect enable/disable.
> + * @mask: The mask containing the protection bits to be disabled.
> + *
> + * This function disables the bus protection bits previously enabled with
> + * mtk_set_bus_protection.
> + */
> +
> +int mtk_generic_disable_cmd(struct regmap *regmap, u32 upd_ofs,
> + u32 sta_ofs, u32 mask)
> +{
> + int ret;
> + u32 val;
> +
> + regmap_update_bits(regmap, upd_ofs, mask, 0);
> +
> + ret = regmap_read_poll_timeout(regmap, sta_ofs,
> + val, !(val & mask),
> + MTK_POLL_DELAY_US,
> + MTK_POLL_TIMEOUT);
> + return ret;
> +}
> +
> +/**
> + * mtk_set_bus_protection - enable bus protection
> + * @infracfg: The bus protect regmap, default use infracfg
> + * @mask: The mask containing the protection bits to be 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)
> +{
> + return mtk_generic_set_cmd(infracfg,
> + INFRA_TOPAXI_PROTECTEN_SET,
> + INFRA_TOPAXI_PROTECTSTA1,
> + mask);
> +}
> +
> +/**
> + * mtk_clear_bus_protection - disable bus protection
> + * @infracfg: The bus protect regmap, default use infracfg
> + * @mask: The mask containing the protection bits to be disabled.
> + *
> + * This function disables the bus protection bits previously enabled with
> + * mtk_set_bus_protection.
> + */
> +
> +int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask)
> +{
> + return mtk_generic_clr_cmd(infracfg,
> + INFRA_TOPAXI_PROTECTEN_CLR,
> + INFRA_TOPAXI_PROTECTSTA1,
> + mask);
> +}
> +
> +/**
> + * mtk_infracfg_enable_bus_protection - enable bus protection
> + * @infracfg: The bus protect regmap, default use infracfg
> + * @mask: The mask containing the protection bits to be disabled.
> + *
> + * 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_enable_bus_protection(struct regmap *infracfg, u32 mask)
> +{
> + return mtk_generic_enable_cmd(infracfg,
> + INFRA_TOPAXI_PROTECTEN,
> + INFRA_TOPAXI_PROTECTSTA1,
> + mask);
> +}
> +
> +/**
> + * mtk_infracfg_disable_bus_protection - disable bus protection
> + * @infracfg: The bus protect regmap, default use infracfg
> + * @mask: The mask containing the protection bits to be disabled.
> + *
> + * This function disables the bus protection bits previously enabled with
> + * mtk_infracfg_set_bus_protection.
> + */
> +
> +int mtk_infracfg_disable_bus_protection(struct regmap *infracfg, u32 mask)
> +{
> + return mtk_generic_disable_cmd(infracfg,
> + INFRA_TOPAXI_PROTECTEN,
> + INFRA_TOPAXI_PROTECTSTA1,
> + mask);
> +}
> diff --git a/drivers/soc/mediatek/mtk-scpsys-ext.c b/drivers/soc/mediatek/mtk-scpsys-ext.c
> new file mode 100644
> index 0000000..965e64d
> --- /dev/null
> +++ b/drivers/soc/mediatek/mtk-scpsys-ext.c
> @@ -0,0 +1,405 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 MediaTek Inc.
> + * Author: Owen Chen <[email protected]>
> + */
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include <linux/export.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/soc/mediatek/infracfg.h>
> +#include <linux/soc/mediatek/scpsys-ext.h>
> +
> +
> +#define MAX_CLKS 10
> +#define INFRA "infracfg"
> +#define SMIC "smi_comm"
Don't use defines for this. While at it I suppose it should be "smi_common"
> +
> +static LIST_HEAD(ext_clk_map_list);
> +static LIST_HEAD(ext_attr_map_list);
> +
> +static struct regmap *infracfg;
> +static struct regmap *smi_comm;
> +
> +enum regmap_type {
> + IFR_TYPE,
> + SMI_TYPE,
> + MAX_REGMAP_TYPE,
> +};
> +
> +/**
> + * struct ext_reg_ctrl - set multiple register for bus protect
> + * @regmap: The bus protect regmap, 1: infracfg, 2: other master regmap
> + * such as SMI.
> + * @set_ofs: The set register offset to set corresponding bit to 1.
> + * @clr_ofs: The clr register offset to clear corresponding bit to 0.
> + * @sta_ofs: The status register offset to show bus protect enable/disable.
> + */
> +struct ext_reg_ctrl {
> + enum regmap_type type;
> + u32 set_ofs;
> + u32 clr_ofs;
> + u32 sta_ofs;
> +};
> +
> +/**
> + * struct ext_clk_ctrl - enable multiple clks for bus protect
> + * @clk: The clk need to enable before pwr on/bus protect.
> + * @scpd_n: The name present the scpsys domain where the clks belongs to.
> + * @clk_list: The list node linked to ext_clk_map_list.
> + */
> +struct ext_clk_ctrl {
> + struct clk *clk;
> + const char *scpd_n;
> + struct list_head clk_list;
> +};
> +
> +struct bus_mask_ops {
> + int (*set)(struct regmap *regmap, u32 set_ofs,
> + u32 sta_ofs, u32 mask);
> + int (*release)(struct regmap *regmap, u32 clr_ofs,
> + u32 sta_ofs, u32 mask);
> +};
> +
> +static struct scpsys_ext_attr *__get_attr_parent(const char *parent_n)
> +{
> + struct scpsys_ext_attr *attr;
> +
> + if (!parent_n)
> + return ERR_PTR(-EINVAL);
> +
> + list_for_each_entry(attr, &ext_attr_map_list, attr_list) {
> + if (attr->scpd_n && !strcmp(parent_n, attr->scpd_n))
> + return attr;
> + }
> +
> + return ERR_PTR(-EINVAL);
> +}
> +
> +int bus_ctrl_set_release(struct scpsys_ext_attr *attr, bool set)
> +{
> + int i;
> + int ret = 0;
> +
> + for (i = 0; i < MAX_STEP_NUM && attr->mask[i].mask; i++) {
> + struct ext_reg_ctrl *rc = attr->mask[i].regs;
> + struct regmap *regmap;
> +
> + if (rc->type == IFR_TYPE)
> + regmap = infracfg;
> + else if (rc->type == SMI_TYPE)
> + regmap = smi_comm;
> + else
> + return -EINVAL;
> +
> + if (set)
> + ret = attr->mask[i].ops->set(regmap,
> + rc->set_ofs,
> + rc->sta_ofs,
> + attr->mask[i].mask);
> + else
> + ret = attr->mask[i].ops->release(regmap,
> + rc->clr_ofs,
> + rc->sta_ofs,
> + attr->mask[i].mask);
> + }
> +
> + return ret;
> +}
> +
> +int bus_ctrl_set(struct scpsys_ext_attr *attr)
> +{
> + return bus_ctrl_set_release(attr, CMD_ENABLE);
> +}
> +
> +int bus_ctrl_release(struct scpsys_ext_attr *attr)
> +{
> + return bus_ctrl_set_release(attr, CMD_DISABLE);
> +}
> +
> +int bus_clk_enable_disable(struct scpsys_ext_attr *attr, bool enable)
> +{
> + int i = 0;
> + int ret = 0;
> + struct ext_clk_ctrl *cc;
> + struct clk *clk[MAX_CLKS];
> +
> + list_for_each_entry(cc, &ext_clk_map_list, clk_list) {
Why can't we handle this in the same way as we do in mtk-scpsys.c ?
> + if (!strcmp(cc->scpd_n, attr->scpd_n)) {
> + if (enable)
> + ret = clk_prepare_enable(cc->clk);
> + else
> + clk_disable_unprepare(cc->clk);
> +
> + if (ret) {
> + pr_err("Failed to %s %s\n",
> + enable ? "enable" : "disable",
> + __clk_get_name(cc->clk));
> + goto err;
> + } else {
> + clk[i] = cc->clk;
> + i++;
> + }
> + }
> + }
> +
> + return ret;
> +
> +err:
> + for (--i; i >= 0; i--)
> + if (enable)
> + clk_disable_unprepare(clk[i]);
> + else
> + clk_prepare_enable(clk[i]);
> + return ret;
> +}
> +
> +int bus_clk_enable(struct scpsys_ext_attr *attr)
> +{
> + struct scpsys_ext_attr *attr_p;
> + int ret = 0;
> +
> + attr_p = __get_attr_parent(attr->parent_n);
Why can't we implement this using the pg_genpd_add_subdomain approach?
> + if (!IS_ERR(attr_p)) {
> + ret = bus_clk_enable_disable(attr_p, CMD_ENABLE);
> + if (ret)
> + return ret;
> + }
> +
> + return bus_clk_enable_disable(attr, CMD_ENABLE);
> +}
> +
> +int bus_clk_disable(struct scpsys_ext_attr *attr)
> +{
> + struct scpsys_ext_attr *attr_p;
> + int ret = 0;
> +
> + ret = bus_clk_enable_disable(attr, CMD_DISABLE);
> + if (ret)
> + return ret;
> +
> + attr_p = __get_attr_parent(attr->parent_n);
> + if (!IS_ERR(attr_p))
> + ret = bus_clk_enable_disable(attr_p, CMD_DISABLE);
Same here.
> +
> + return ret;
> +}
> +
> +const struct bus_mask_ops bus_mask_set_clr_ctrl = {
> + .set = &mtk_generic_set_cmd,
> + .release = &mtk_generic_clr_cmd,
> +};
> +
> +const struct bus_ext_ops ext_bus_ctrl = {
> + .enable = &bus_ctrl_set,
> + .disable = &bus_ctrl_release,
> +};
> +
> +const struct bus_ext_ops ext_cg_ctrl = {
> + .enable = &bus_clk_enable,
> + .disable = &bus_clk_disable,
> +};
> +
> +/*
> + * scpsys bus driver init
> + */
> +struct regmap *syscon_regmap_lookup_by_phandle_idx(struct device_node *np,
> + const char *property,
> + int index)
> +{
> + struct device_node *syscon_np;
> + struct regmap *regmap;
> +
> + if (property)
> + syscon_np = of_parse_phandle(np, property, index);
> + else
> + syscon_np = np;
> +
> + if (!syscon_np)
> + return ERR_PTR(-ENODEV);
> +
> + regmap = syscon_node_to_regmap(syscon_np);
> + of_node_put(syscon_np);
> +
> + return regmap;
> +}
Why do we need this? It is never called...
> +
> +int scpsys_ext_regmap_init(struct platform_device *pdev)
> +{
> + infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
> + INFRA);
> + if (IS_ERR(infracfg)) {
> + dev_err(&pdev->dev,
> + "Cannot find bus infracfg controller: %ld\n",
> + PTR_ERR(infracfg));
> + return PTR_ERR(infracfg);
> + }
> +
> + smi_comm = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
> + SMIC);
> + if (IS_ERR(smi_comm)) {
> + dev_err(&pdev->dev,
> + "Cannot find bus smi_comm controller: %ld\n",
> + PTR_ERR(smi_comm));
> + return PTR_ERR(smi_comm);
> + }
> +
> + return 0;
> +}
> +
> +static int add_clk_to_list(struct platform_device *pdev,
> + const char *name,
> + const char *scpd_n)
> +{
> + struct clk *clk;
> + struct ext_clk_ctrl *cc;
> +
> + clk = devm_clk_get(&pdev->dev, name);
> + if (IS_ERR(clk)) {
> + dev_err(&pdev->dev, "Failed add clk %ld\n", PTR_ERR(clk));
> + return PTR_ERR(clk);
> + }
> +
> + cc = kzalloc(sizeof(*cc), GFP_KERNEL);
> + cc->clk = clk;
> + cc->scpd_n = kstrdup(scpd_n, GFP_KERNEL);
> +
> + list_add(&cc->clk_list, &ext_clk_map_list);
> +
> + return 0;
> +}
> +
> +static int add_cg_to_list(struct platform_device *pdev)
> +{
> + int i = 0;
> +
> + struct device_node *node = pdev->dev.of_node;
> +
> + if (!node) {
> + dev_err(&pdev->dev, "Cannot find topcksys node: %ld\n",
Why topcksys? Shouldn't that be the node of scpsys?
> + PTR_ERR(node));
> + return PTR_ERR(node);
> + }
> +
> + do {
> + const char *ck_name;
> + char *temp_str;
> + char *tok[2] = {NULL};
> + int cg_idx = 0;
> + int idx = 0;
> + int ret = 0;
> +
> + ret = of_property_read_string_index(node, "clock-names", i,
> + &ck_name);
> + if (ret < 0)
> + break;
> +
> + temp_str = kmalloc_array(strlen(ck_name), sizeof(char),
> + GFP_KERNEL | __GFP_ZERO);
> + memcpy(temp_str, ck_name, strlen(ck_name));
> + temp_str[strlen(ck_name)] = '\0';
why don't you use kstrdup or similar?
> + do {
> + tok[idx] = strsep(&temp_str, "-");
> + idx++;
> + } while (temp_str);
You want to split the clock name like "mm-2" in
char **tok = {"mm", "2"};
correct? That can be done easier AFAIK:
tok[0] = strsep(&temp_str, "-");
tok[1] = &temp_str;
> +
> + if (idx == 2) {
You don't add clocks like "mfg" and "mm". Why?
> + if (kstrtouint(tok[1], 10, &cg_idx))
And then? You don't do anything with cg_idx...
> + return -EINVAL;
> +
> + if (add_clk_to_list(pdev, ck_name, tok[0]))
add_clk_to_list third parameter is the name of the scp domain, but you pass the
clock name here. I'm puzzled.
> + return -EINVAL;
> + }
> + kfree(temp_str);
> + i++;
> + } while (1);
> +
> + return 0;
> +}
> +
> +int scpsys_ext_clk_init(struct platform_device *pdev)
> +{
> + int ret = 0;
> +
> + ret = add_cg_to_list(pdev);
> + if (ret)
> + goto err;
> +
> +err:
> + return ret;
> +}
Why do we need add_cg_to_list, it can be implemented directly here. Why is here
a goto to a return statement that will be executed anyway? Please go through the
code and check that it is clean before submitting.
> +
> +int scpsys_ext_attr_init(const struct scpsys_ext_data *data)
> +{
> + int i, count = 0;
> +
> + for (i = 0; i < data->num_attr; i++) {
> + struct scpsys_ext_attr *node = data->attr + i;
> +
> + if (!node)
> + continue;
> +
> + list_add(&node->attr_list, &ext_attr_map_list);
> + count++;
> + }
> +
> + if (!count)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +static const struct of_device_id of_scpsys_ext_match_tbl[] = {
> + {
> + /* sentinel */
> + }
> +};
> +
> +struct scpsys_ext_data *scpsys_ext_init(struct platform_device *pdev)
> +{
> + const struct of_device_id *match;
> + struct scpsys_ext_data *data;
> + int ret;
> +
> + match = of_match_device(of_scpsys_ext_match_tbl, &pdev->dev);
> +
> + if (!match) {
> + dev_err(&pdev->dev, "no match\n");
> + return ERR_CAST(match);
> + }
> +
> + data = (struct scpsys_ext_data *)match->data;
> + if (IS_ERR(data)) {
> + dev_err(&pdev->dev, "no match scpext data\n");
> + return ERR_CAST(data);
> + }
> +
> + ret = scpsys_ext_attr_init(data);
> + if (ret) {
> + dev_err(&pdev->dev,
> + "Failed to init bus attr: %d\n",
> + ret);
> + return ERR_PTR(ret);
> + }
> +
> + ret = scpsys_ext_regmap_init(pdev);
> + if (ret) {
> + dev_err(&pdev->dev,
> + "Failed to init bus register: %d\n",
> + ret);
> + return ERR_PTR(ret);
> + }
> +
> + ret = scpsys_ext_clk_init(pdev);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to init bus clks: %d\n",
> + ret);
> + return ERR_PTR(ret);
> + }
> +
> + return data;
> +}
> diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> index 4bb6c7a..03df2d6 100644
> --- a/drivers/soc/mediatek/mtk-scpsys.c
> +++ b/drivers/soc/mediatek/mtk-scpsys.c
> @@ -1,3 +1,4 @@
> +// SPDX-License-Identifier: GPL-2.0
> /*
> * Copyright (c) 2015 Pengutronix, Sascha Hauer <[email protected]>
> *
> @@ -20,6 +21,7 @@
> #include <linux/pm_domain.h>
> #include <linux/regulator/consumer.h>
> #include <linux/soc/mediatek/infracfg.h>
> +#include <linux/soc/mediatek/scpsys-ext.h>
>
> #include <dt-bindings/power/mt2701-power.h>
> #include <dt-bindings/power/mt2712-power.h>
> @@ -117,6 +119,15 @@ enum clk_id {
>
> #define MAX_CLKS 3
>
> +/**
> + * struct scp_domain_data - scp domain data for power on/off flow
> + * @name: The domain name.
> + * @sta_mask: The mask for power on/off status bit.
> + * @ctl_offs: The offset for main power control register.
> + * @sram_pdn_bits: The mask for sram power control bits.
> + * @sram_pdn_ack_bits The mask for sram power control acked bits.
> + * @caps: The flag for active wake-up action.
> + */
> struct scp_domain_data {
> const char *name;
> u32 sta_mask;
> @@ -150,7 +161,7 @@ struct scp {
> void __iomem *base;
> struct regmap *infracfg;
> struct scp_ctrl_reg ctrl_reg;
> - bool bus_prot_reg_update;
> + struct scpsys_ext_data *ext_data;
> };
>
> struct scp_subdomain {
> @@ -164,7 +175,6 @@ struct scp_soc_data {
> const struct scp_subdomain *subdomains;
> int num_subdomains;
> const struct scp_ctrl_reg regs;
> - bool bus_prot_reg_update;
> };
>
> static int scpsys_domain_is_on(struct scp_domain *scpd)
> @@ -236,6 +246,31 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> val |= PWR_RST_B_BIT;
> writel(val, ctl_addr);
>
> + if (!IS_ERR(scp->ext_data)) {
> + struct scpsys_ext_attr *attr;
> +
> + attr = scp->ext_data->get_attr(scpd->data->name);
> + if (!IS_ERR(attr) && attr->cg_ops) {
> + ret = attr->cg_ops->enable(attr);
> + if (ret)
> + goto err_ext_clk;
> + }
> + }
> +
> + val &= ~scpd->data->sram_pdn_bits;
> + writel(val, ctl_addr);
> +
> + if (!IS_ERR(scp->ext_data)) {
> + struct scpsys_ext_attr *attr;
> +
> + attr = scp->ext_data->get_attr(scpd->data->name);
> + if (!IS_ERR(attr) && attr->cg_ops) {
> + ret = attr->cg_ops->enable(attr);
> + if (ret)
> + goto err_ext_clk;
> + }
> + }
> +
> val &= ~scpd->data->sram_pdn_bits;
> writel(val, ctl_addr);
>
> @@ -247,25 +282,65 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> * applied here.
> */
> usleep_range(12000, 12100);
> -
> } else {
> ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == 0,
> MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> if (ret < 0)
> - goto err_pwr_ack;
> + goto err_sram;
> }
>
> if (scpd->data->bus_prot_mask) {
> ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
> - scpd->data->bus_prot_mask,
> - scp->bus_prot_reg_update);
> + scpd->data->bus_prot_mask);
> if (ret)
> - goto err_pwr_ack;
> + goto err_sram;
> + }
> +
> + if (!IS_ERR(scp->ext_data)) {
> + struct scpsys_ext_attr *attr;
> +
> + attr = scp->ext_data->get_attr(scpd->data->name);
> + if (!IS_ERR(attr) && attr->bus_ops) {
> + ret = attr->bus_ops->disable(attr);
> + if (ret)
> + goto err_sram;
> + }
> + }
> +
> + if (!IS_ERR(scp->ext_data)) {
> + struct scpsys_ext_attr *attr;
> +
> + attr = scp->ext_data->get_attr(scpd->data->name);
> + if (!IS_ERR(attr) && attr->cg_ops) {
> + ret = attr->cg_ops->disable(attr);
> + if (ret)
> + goto err_sram;
> + }
> }
>
> return 0;
>
> +err_sram:
> + val = readl(ctl_addr);
> + val |= scpd->data->sram_pdn_bits;
> + writel(val, ctl_addr);
> +err_ext_clk:
> + val = readl(ctl_addr);
> + val |= PWR_ISO_BIT;
> + writel(val, ctl_addr);
> +
> + val &= ~PWR_RST_B_BIT;
> + writel(val, ctl_addr);
> +
> + val |= PWR_CLK_DIS_BIT;
> + writel(val, ctl_addr);
> err_pwr_ack:
> + val &= ~PWR_ON_BIT;
> + writel(val, ctl_addr);
> +
> + val &= ~PWR_ON_2ND_BIT;
> + writel(val, ctl_addr);
> +
> for (i = MAX_CLKS - 1; i >= 0; i--) {
> if (scpd->clk[i])
> clk_disable_unprepare(scpd->clk[i]);
> @@ -274,8 +349,6 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> if (scpd->supply)
> regulator_disable(scpd->supply);
>
> - dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
> -
> return ret;
> }
>
> @@ -289,14 +362,35 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> int ret, tmp;
> int i;
>
> + if (!IS_ERR(scp->ext_data)) {
> + struct scpsys_ext_attr *attr;
> +
> + attr = scp->ext_data->get_attr(scpd->data->name);
> + if (!IS_ERR(attr) && attr->cg_ops) {
> + ret = attr->cg_ops->enable(attr);
> + if (ret)
> + goto out;
> + }
> + }
> +
> if (scpd->data->bus_prot_mask) {
> ret = mtk_infracfg_set_bus_protection(scp->infracfg,
> - scpd->data->bus_prot_mask,
> - scp->bus_prot_reg_update);
> + scpd->data->bus_prot_mask);
> if (ret)
> goto out;
> }
>
> + if (!IS_ERR(scp->ext_data)) {
> + struct scpsys_ext_attr *attr;
> +
> + attr = scp->ext_data->get_attr(scpd->data->name);
> + if (!IS_ERR(attr) && attr->bus_ops) {
> + ret = attr->bus_ops->enable(attr);
> + if (ret)
> + goto out;
> + }
> + }
> +
> val = readl(ctl_addr);
> val |= scpd->data->sram_pdn_bits;
> writel(val, ctl_addr);
> @@ -307,6 +401,17 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> if (ret < 0)
> goto out;
>
> + if (!IS_ERR(scp->ext_data)) {
> + struct scpsys_ext_attr *attr;
> +
> + attr = scp->ext_data->get_attr(scpd->data->name);
> + if (!IS_ERR(attr) && attr->cg_ops) {
> + ret = attr->cg_ops->disable(attr);
> + if (ret)
> + goto out;
> + }
> + }
> +
> val |= PWR_ISO_BIT;
> writel(val, ctl_addr);
>
> @@ -337,8 +442,6 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> return 0;
>
> out:
> - dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name);
> -
> return ret;
> }
>
> @@ -352,8 +455,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,
> - bool bus_prot_reg_update)
> + const struct scp_ctrl_reg *scp_ctrl_reg)
> {
> struct genpd_onecell_data *pd_data;
> struct resource *res;
> @@ -367,11 +469,10 @@ static struct scp *init_scp(struct platform_device *pdev,
>
> 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->bus_prot_reg_update = bus_prot_reg_update;
> -
> scp->dev = &pdev->dev;
>
> + scp->ext_data = scpsys_ext_init(pdev);
> +
> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> scp->base = devm_ioremap_resource(&pdev->dev, res);
> if (IS_ERR(scp->base))
> @@ -1021,7 +1122,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> .pwr_sta_offs = SPM_PWR_STATUS,
> .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> },
> - .bus_prot_reg_update = true,
> };
>
> static const struct scp_soc_data mt2712_data = {
> @@ -1033,7 +1133,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> .pwr_sta_offs = SPM_PWR_STATUS,
> .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> },
> - .bus_prot_reg_update = false,
> };
>
> static const struct scp_soc_data mt6765_data = {
> @@ -1056,7 +1155,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> .pwr_sta_offs = SPM_PWR_STATUS_MT6797,
> .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
> },
> - .bus_prot_reg_update = true,
I don't understand why you can delete this flag if you don't change anything
else in the data structure. For me this looks like you will break other chips.
Please explain.
I have the gut feeling that this can be implemented in the existing mtk-scpsys
driver. Can you please explain what are the points that this is not possible.
I want to understand the design decisions you made here, because they seem
really odd to me.
Best regards,
Matthias
> };
>
> static const struct scp_soc_data mt7622_data = {
> @@ -1066,7 +1164,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> .pwr_sta_offs = SPM_PWR_STATUS,
> .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> },
> - .bus_prot_reg_update = true,
> };
>
> static const struct scp_soc_data mt7623a_data = {
> @@ -1076,7 +1173,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> .pwr_sta_offs = SPM_PWR_STATUS,
> .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> },
> - .bus_prot_reg_update = true,
> };
>
> static const struct scp_soc_data mt8173_data = {
> @@ -1088,7 +1184,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> .pwr_sta_offs = SPM_PWR_STATUS,
> .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> },
> - .bus_prot_reg_update = true,
> };
>
> /*
> @@ -1132,8 +1227,8 @@ static int scpsys_probe(struct platform_device *pdev)
>
> soc = of_device_get_match_data(&pdev->dev);
>
> - scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs,
> - soc->bus_prot_reg_update);
> + scp = init_scp(pdev, soc->domains, soc->num_domains,
> + &soc->regs);
> if (IS_ERR(scp))
> return PTR_ERR(scp);
>
> diff --git a/include/linux/soc/mediatek/infracfg.h b/include/linux/soc/mediatek/infracfg.h
> index fd25f01..bfad082 100644
> --- a/include/linux/soc/mediatek/infracfg.h
> +++ b/include/linux/soc/mediatek/infracfg.h
> @@ -32,8 +32,9 @@
> #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,
> - bool reg_update);
> -int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
> - bool reg_update);
> +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_enable_bus_protection(struct regmap *infracfg, u32 mask);
> +int mtk_infracfg_disable_bus_protection(struct regmap *infracfg, u32 mask);
> +
> #endif /* __SOC_MEDIATEK_INFRACFG_H */
> diff --git a/include/linux/soc/mediatek/scpsys-ext.h b/include/linux/soc/mediatek/scpsys-ext.h
> new file mode 100644
> index 0000000..99b5ff1
> --- /dev/null
> +++ b/include/linux/soc/mediatek/scpsys-ext.h
> @@ -0,0 +1,66 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __SOC_MEDIATEK_SCPSYS_EXT_H
> +#define __SOC_MEDIATEK_SCPSYS_EXT_H
> +
> +#include <linux/platform_device.h>
> +
> +#define CMD_ENABLE 1
> +#define CMD_DISABLE 0
> +
> +#define MAX_STEP_NUM 4
> +
> +/**
> + * struct bus_mask - set mask and corresponding operation for bus protect
> + * @regs: The register set of bus register control, including set/clr/sta.
> + * @mask: The mask set for bus protect.
> + * @flag: The flag to idetify which operation we take for bus protect.
> + */
> +struct bus_mask {
> + struct ext_reg_ctrl *regs;
> + u32 mask;
> + const struct bus_mask_ops *ops;
> +};
> +
> +/**
> + * struct scpsys_ext_attr - extended attribute for bus protect and further
> + * operand.
> + *
> + * @scpd_n: The name present the scpsys domain where the clks belongs to.
> + * @mask: The mask set for bus protect.
> + * @bus_ops: The operation we take for bus protect.
> + * @cg_ops: The operation we take for cg on/off.
> + * @attr_list: The list node linked to ext_attr_map_list.
> + */
> +struct scpsys_ext_attr {
> + const char *scpd_n;
> + struct bus_mask mask[MAX_STEP_NUM];
> + const char *parent_n;
> + const struct bus_ext_ops *bus_ops;
> + const struct bus_ext_ops *cg_ops;
> +
> + struct list_head attr_list;
> +};
> +
> +struct scpsys_ext_data {
> + struct scpsys_ext_attr *attr;
> + u8 num_attr;
> + struct scpsys_ext_attr * (*get_attr)(const char *scpd_n);
> +};
> +
> +struct bus_ext_ops {
> + int (*enable)(struct scpsys_ext_attr *attr);
> + int (*disable)(struct scpsys_ext_attr *attr);
> +};
> +
> +int mtk_generic_set_cmd(struct regmap *regmap, u32 set_ofs,
> + u32 sta_ofs, u32 mask);
> +int mtk_generic_clr_cmd(struct regmap *regmap, u32 clr_ofs,
> + u32 sta_ofs, u32 mask);
> +int mtk_generic_enable_cmd(struct regmap *regmap, u32 upd_ofs,
> + u32 sta_ofs, u32 mask);
> +int mtk_generic_disable_cmd(struct regmap *regmap, u32 upd_ofs,
> + u32 sta_ofs, u32 mask);
> +
> +struct scpsys_ext_data *scpsys_ext_init(struct platform_device *pdev);
> +
> +#endif /* __SOC_MEDIATEK_SCPSYS_EXT_H */
>
On Tue, 2018-07-17 at 16:52 +0800, Mars Cheng wrote:
> From: Owen Chen <[email protected]>
>
> MT6765 add "set/clr" register for each clkmux setting, and
> one update register to trigger value change. It is designed
> to prevent read-modify-write racing issue. The sw design
> need to add a new API to handle this hw change with a new
> mtk_clk_mux/mtk_clk_upd struct in new file "clk-mux"and
> clk-upd".
>
I don't see any word mtk_clk_upd or clk-upd in the patch
and the patch needs to be split into more patches
> Signed-off-by: Owen Chen <[email protected]>
> ---
> drivers/clk/mediatek/Makefile | 2 +-
> drivers/clk/mediatek/clk-mtk.c | 41 +++++++
> drivers/clk/mediatek/clk-mtk.h | 85 ++++++++++++---
> drivers/clk/mediatek/clk-mux.c | 236 ++++++++++++++++++++++++++++++++++++++++
> drivers/clk/mediatek/clk-mux.h | 38 +++++++
> 5 files changed, 388 insertions(+), 14 deletions(-)
> create mode 100644 drivers/clk/mediatek/clk-mux.c
> create mode 100644 drivers/clk/mediatek/clk-mux.h
>
> diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
> index 844b55d..b97980d 100644
> --- a/drivers/clk/mediatek/Makefile
> +++ b/drivers/clk/mediatek/Makefile
> @@ -1,5 +1,5 @@
> # SPDX-License-Identifier: GPL-2.0
> -obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o
> +obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o clk-mux.o
> obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
> obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
> obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o
> diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
> index 9c0ae42..50becd0 100644
> --- a/drivers/clk/mediatek/clk-mtk.c
> +++ b/drivers/clk/mediatek/clk-mtk.c
> @@ -22,6 +22,7 @@
> #include <linux/mfd/syscon.h>
>
> #include "clk-mtk.h"
> +#include "clk-mux.h"
> #include "clk-gate.h"
>
> struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
> @@ -144,6 +145,46 @@ int mtk_clk_register_gates(struct device_node *node,
> return 0;
> }
>
> +int mtk_clk_register_muxes(const struct mtk_mux *muxes,
> + int num, struct device_node *node,
> + spinlock_t *lock,
> + struct clk_onecell_data *clk_data)
> +{
> + struct regmap *regmap;
> + struct clk *clk;
> + int i;
> +
> + if (!clk_data)
> + return -ENOMEM;
> +
general register function is able to handle that there is no clk_data.
It looks like a optional, not a mandatory
> + regmap = syscon_node_to_regmap(node);
> + if (IS_ERR(regmap)) {
> + pr_err("Cannot find regmap for %pOF: %ld\n", node,
> + PTR_ERR(regmap));
> + return PTR_ERR(regmap);
> + }
> +
> + for (i = 0; i < num; i++) {
> + const struct mtk_mux *mux = &muxes[i];
> +
> + if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mux->id]))
> + continue;
> +
it seems not necessary to check clk data every time
and always use positive check is good to read
> + clk = mtk_clk_register_mux(mux, regmap, lock);
> +
> + if (IS_ERR(clk)) {
> + pr_err("Failed to register clk %s: %ld\n",
> + mux->name, PTR_ERR(clk));
> + continue;
> + }
> +
> + if (clk_data)
> + clk_data->clks[mux->id] = clk;
don't alter any data from input, that is a surprise for users
> + }
> +
> + return 0;
> +}
> +
> struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
> void __iomem *base, spinlock_t *lock)
> {
> diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
> index 1882221..61693f6 100644
> --- a/drivers/clk/mediatek/clk-mtk.h
> +++ b/drivers/clk/mediatek/clk-mtk.h
> @@ -24,7 +24,9 @@
>
> #define MAX_MUX_GATE_BIT 31
> #define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1)
> -
> +#define INVALID_OFS -1
> +#define INVALID_SHFT -1
> +#define INVALID_WIDTH -1
> #define MHZ (1000 * 1000)
>
> struct mtk_fixed_clk {
> @@ -84,10 +86,72 @@ struct mtk_composite {
> signed char num_parents;
> };
>
> +struct mtk_mux {
> + int id;
> + const char *name;
> + const char * const *parent_names;
> + unsigned int flags;
> +
> + u32 mux_ofs;
> + u32 set_ofs;
> + u32 clr_ofs;
> + u32 upd_ofs;
> +
> + signed char mux_shift;
> + signed char mux_width;
> + signed char gate_shift;
> + signed char upd_shift;
> +
> + const struct clk_ops *ops;
> +
> + signed char num_parents;
> +};
> +
you have created a mtk-mux.h, why is you don't move the newly create
struct in?
> /*
> * In case the rate change propagation to parent clocks is undesirable,
> * this macro allows to specify the clock flags manually.
> */
> +#define CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, _mux_set_ofs,\
> + _mux_clr_ofs, _shift, _width, _gate, \
> + _upd_ofs, _upd, _flags, _ops) { \
> + .id = _id, \
> + .name = _name, \
> + .mux_ofs = _mux_ofs, \
> + .set_ofs = _mux_set_ofs, \
> + .clr_ofs = _mux_clr_ofs, \
> + .upd_ofs = _upd_ofs, \
> + .mux_shift = _shift, \
> + .mux_width = _width, \
> + .gate_shift = _gate, \
> + .upd_shift = _upd, \
> + .parent_names = _parents, \
> + .num_parents = ARRAY_SIZE(_parents), \
> + .flags = _flags, \
> + .ops = &_ops, \
> + }
> +
> +#define MUX_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, _mux_set_ofs,\
> + _mux_clr_ofs, _shift, _width, _gate, \
> + _upd_ofs, _upd, _flags) \
> + CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
> + _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
> + _gate, _upd_ofs, _upd, _flags, \
> + mtk_mux_clr_set_upd_ops)
> +
> +#define MUX_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, _mux_set_ofs, \
> + _mux_clr_ofs, _shift, _width, _gate, \
> + _upd_ofs, _upd) \
> + MUX_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
> + _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
> + _gate, _upd_ofs, _upd, CLK_SET_RATE_PARENT)
> +
> +#define MUX_UPD(_id, _name, _parents, _mux_ofs, _shift, _width, _gate, \
> + _upd_ofs, _upd) \
> + CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
> + INVALID_OFS, INVALID_OFS, _shift, _width, \
> + _gate, _upd_ofs, _upd, CLK_SET_RATE_PARENT, \
> + mtk_mux_upd_ops)
> +
> #define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \
> _gate, _flags) { \
> .id = _id, \
> @@ -111,18 +175,8 @@ struct mtk_composite {
> MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \
> _gate, CLK_SET_RATE_PARENT)
>
> -#define MUX(_id, _name, _parents, _reg, _shift, _width) { \
> - .id = _id, \
> - .name = _name, \
> - .mux_reg = _reg, \
> - .mux_shift = _shift, \
> - .mux_width = _width, \
> - .gate_shift = -1, \
> - .divider_shift = -1, \
> - .parent_names = _parents, \
> - .num_parents = ARRAY_SIZE(_parents), \
> - .flags = CLK_SET_RATE_PARENT, \
> - }
As Matthias always said that, you alter the common thing that is already
used by a lot of SoC.
You should have a dedicate patch to state why you need it, provide the
way you propose. and use another patches for migrating old SoC, finally
then add the patch for your own SoC.
Don't mix everything in a single patch. The patch can't become reusable
hard to read it, even hard to backport to the other SoC picking up
patches they are really wanting.
> +#define MUX(_id, _name, _parents, _reg, _shift, _width) \
> + MUX_GATE(_id, _name, _parents, _reg, _shift, _width, INVALID_SHFT)
>
> #define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \
> _div_width, _div_shift) { \
> @@ -138,6 +192,11 @@ struct mtk_composite {
> .flags = 0, \
> }
>
> +int mtk_clk_register_muxes(const struct mtk_mux *muxes,
> + int num, struct device_node *node,
> + spinlock_t *lock,
> + struct clk_onecell_data *clk_data);
> +
move to mtk-mux.h
> struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
> void __iomem *base, spinlock_t *lock);
>
> diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c
> new file mode 100644
> index 0000000..219181b
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mux.c
> @@ -0,0 +1,236 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 MediaTek Inc.
> + * Author: Owen Chen <[email protected]>
> + */
> +
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +
> +#include "clk-mtk.h"
> +#include "clk-mux.h"
> +
> +static inline struct mtk_clk_mux
> + *to_mtk_clk_mux(struct clk_hw *hw)
> +{
> + return container_of(hw, struct mtk_clk_mux, hw);
> +}
> +
> +static int mtk_mux_enable(struct clk_hw *hw)
> +{
> + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> + u32 mask = BIT(mux->gate_shift);
> + unsigned long flags = 0;
> +
> + if (mux->lock)
> + spin_lock_irqsave(mux->lock, flags);
> +
we can see many functions in kernel, similar to your need, they always
be defined as two versions. for example.
mtk_mux_enable refer to lock version
mtk_mux_enable_nolock for lock-free version
that makes less condition, more readable, and users don't care much
about what stuff is put inside
> + regmap_update_bits(mux->regmap, mux->mux_ofs, mask, 0);
> +
> + if (mux->lock)
> + spin_unlock_irqrestore(mux->lock, flags);
> + return 0;
> +}
> +
> +static void mtk_mux_disable(struct clk_hw *hw)
> +{
> + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> + u32 mask = BIT(mux->gate_shift);
> + unsigned long flags = 0;
> +
> + if (mux->lock)
> + spin_lock_irqsave(mux->lock, flags);
> +
ditto
> + regmap_update_bits(mux->regmap, mux->mux_ofs, mask, mask);
> +
> + if (mux->lock)
> + spin_unlock_irqrestore(mux->lock, flags);
> +}
> +
> +static int mtk_mux_enable_setclr(struct clk_hw *hw)
> +{
> + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> + u32 val;
> + unsigned long flags = 0;
> +
> + if (mux->lock)
> + spin_lock_irqsave(mux->lock, flags);
> +
ditto
> + val = BIT(mux->gate_shift);
> + regmap_write(mux->regmap, mux->mux_clr_ofs, val);
> +
> + if (mux->lock)
> + spin_unlock_irqrestore(mux->lock, flags);
> + return 0;
> +}
> +
> +static void mtk_mux_disable_setclr(struct clk_hw *hw)
> +{
> + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> + u32 val;
> + unsigned long flags = 0;
> +
> + if (mux->lock)
> + spin_lock_irqsave(mux->lock, flags);
> +
ditto
> + val = BIT(mux->gate_shift);
> + regmap_write(mux->regmap, mux->mux_set_ofs, val);
> +
> + if (mux->lock)
> + spin_unlock_irqrestore(mux->lock, flags);
> +}
> +
> +static int mtk_mux_is_enabled(struct clk_hw *hw)
> +{
> + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> + u32 val = 0;
> +
> + if (mux->gate_shift < 0)
> + return true;
> +
return value should be bool
> + regmap_read(mux->regmap, mux->mux_ofs, &val);
> +
> + return (val & BIT(mux->gate_shift)) == 0;
> +}
> +
> +static u8 mtk_mux_get_parent(struct clk_hw *hw)
> +{
return value should be int
> + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> + int num_parents = clk_hw_get_num_parents(hw);
> + u32 mask = GENMASK(mux->mux_width - 1, 0);
> + u32 val;
> +
> + regmap_read(mux->regmap, mux->mux_ofs, &val);
> + val = (val >> mux->mux_shift) & mask;
> +
> + if (val >= num_parents)
> + return -EINVAL;
> +
> + return val;
> +}
> +
> +static int mtk_mux_set_parent(struct clk_hw *hw, u8 index)
> +{
> + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> + u32 mask = GENMASK(mux->mux_width - 1, 0);
> + u32 val, orig;
> + unsigned long flags = 0;
> +
> + if (mux->lock)
> + spin_lock_irqsave(mux->lock, flags);
> +
use lock-free-or-not funciton
> + regmap_read(mux->regmap, mux->mux_ofs, &val);
> + orig = val;
> + val &= ~(mask << mux->mux_shift);
> + val |= index << mux->mux_shift;
> +
> + if (val != orig) {
> + regmap_write(mux->regmap, mux->mux_ofs, val);
> +
> + if (mux->upd_shift >= 0)
> + regmap_write(mux->regmap, mux->upd_ofs,
> + BIT(mux->upd_shift));
why not use regmap_update_bits like function ?
> + }
> +
> + if (mux->lock)
> + spin_unlock_irqrestore(mux->lock, flags);
> +
> + return 0;
> +}
> +
> +static int mtk_mux_set_parent_setclr(struct clk_hw *hw, u8 index)
> +{
> + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> + u32 mask = GENMASK(mux->mux_width - 1, 0);
> + u32 val, orig;
> + unsigned long flags = 0;
> +
> + if (mux->lock)
> + spin_lock_irqsave(mux->lock, flags);
> +
use lock-free-or-not funciton
> + regmap_read(mux->regmap, mux->mux_ofs, &val);
> + orig = val;
> + val &= ~(mask << mux->mux_shift);
> + val |= index << mux->mux_shift;
> +
> + if (val != orig) {
> + val = (mask << mux->mux_shift);
> + regmap_write(mux->regmap, mux->mux_clr_ofs, val);
> + val = (index << mux->mux_shift);
> + regmap_write(mux->regmap, mux->mux_set_ofs, val);
> +
why not use regmap_update_bits like function ?
> + if (mux->upd_shift >= 0)
> + regmap_write(mux->regmap, mux->upd_ofs,
> + BIT(mux->upd_shift));
> + }
> +
> + if (mux->lock)
> + spin_unlock_irqrestore(mux->lock, flags);
> +
> + return 0;
> +}
> +
> +const struct clk_ops mtk_mux_upd_ops = {
> + .enable = mtk_mux_enable,
> + .disable = mtk_mux_disable,
> + .is_enabled = mtk_mux_is_enabled,
> + .get_parent = mtk_mux_get_parent,
> + .set_parent = mtk_mux_set_parent,
> + .determine_rate = NULL,
explicitly set as NULL can be removed
> +};
> +
> +const struct clk_ops mtk_mux_clr_set_upd_ops = {
> + .enable = mtk_mux_enable_setclr,
> + .disable = mtk_mux_disable_setclr,
> + .is_enabled = mtk_mux_is_enabled,
> + .get_parent = mtk_mux_get_parent,
> + .set_parent = mtk_mux_set_parent_setclr,
> + .determine_rate = NULL,
explicitly set as NULL can be removed
> +};
> +
> +struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
> + struct regmap *regmap,
> + spinlock_t *lock)
> +{
> + struct clk *clk;
> + struct clk_init_data init;
> + struct mtk_clk_mux *mtk_mux = NULL;
> + int ret;
> +
make declaration as reverse xmas tree
> + mtk_mux = kzalloc(sizeof(*mtk_mux), GFP_KERNEL);
> + if (!mtk_mux)
> + return ERR_PTR(-ENOMEM);
> +
> + init.name = mux->name;
> + init.flags = (mux->flags) | CLK_SET_RATE_PARENT;
> + init.parent_names = mux->parent_names;
> + init.num_parents = mux->num_parents;
> + init.ops = mux->ops;
> +
> + mtk_mux->regmap = regmap;
> + mtk_mux->name = mux->name;
> + mtk_mux->mux_ofs = mux->mux_ofs;
> + mtk_mux->mux_set_ofs = mux->set_ofs;
> + mtk_mux->mux_clr_ofs = mux->clr_ofs;
> + mtk_mux->upd_ofs = mux->upd_ofs;
> + mtk_mux->mux_shift = mux->mux_shift;
> + mtk_mux->mux_width = mux->mux_width;
> + mtk_mux->gate_shift = mux->gate_shift;
> + mtk_mux->upd_shift = mux->upd_shift;
> +
> + mtk_mux->lock = lock;
> + mtk_mux->hw.init = &init;
> +
> + clk = clk_register(NULL, &mtk_mux->hw);
> + if (IS_ERR(clk)) {
> + ret = PTR_ERR(clk);
ret is superfluous
> + goto err_out;
> + }
> +
> + return clk;
> +err_out:
> + kfree(mtk_mux);
> +
I felt err path can be optimized
> + return ERR_PTR(ret);
> +}
> diff --git a/drivers/clk/mediatek/clk-mux.h b/drivers/clk/mediatek/clk-mux.h
> new file mode 100644
> index 0000000..64f8e7c
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mux.h
> @@ -0,0 +1,38 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2018 MediaTek Inc.
> + * Author: Owen Chen <[email protected]>
> + */
> +
> +#ifndef __DRV_CLK_MUX_H
> +#define __DRV_CLK_MUX_H
> +
> +#include <linux/clk-provider.h>
> +
> +struct mtk_clk_mux {
> + struct clk_hw hw;
> + struct regmap *regmap;
> +
> + const char *name;
> +
> + int mux_set_ofs;
> + int mux_clr_ofs;
> + int mux_ofs;
> + int upd_ofs;
> +
> + s8 mux_shift;
> + s8 mux_width;
> + s8 gate_shift;
> + s8 upd_shift;
> +
> + spinlock_t *lock;
> +};
> +
> +extern const struct clk_ops mtk_mux_upd_ops;
> +extern const struct clk_ops mtk_mux_clr_set_upd_ops;
> +
extern is superfluous
> +struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
> + struct regmap *regmap,
> + spinlock_t *lock);
> +
> +#endif /* __DRV_CLK_MUX_H */
On Tue, Jul 17, 2018 at 04:52:23PM +0800, Mars Cheng wrote:
> This patch adds MT6765 smi binding document
>
> Signed-off-by: Mars Cheng <[email protected]>
> Signed-off-by: Owen Chen <[email protected]>
> ---
> .../memory-controllers/mediatek,smi-common.txt | 1 +
> 1 file changed, 1 insertion(+)
Acked-by: Rob Herring <[email protected]>
On Tue, Jul 17, 2018 at 04:52:22PM +0800, Mars Cheng wrote:
> This patch adds the binding documentation for apmixedsys, audsys, camsys,
> imgsys, infracfg, mipi0a, topckgen, vcodecsys
>
> Signed-off-by: Mars Cheng <[email protected]>
> Signed-off-by: Owen Chen <[email protected]>
> ---
> .../bindings/arm/mediatek/mediatek,apmixedsys.txt | 1 +
> .../bindings/arm/mediatek/mediatek,audsys.txt | 1 +
> .../bindings/arm/mediatek/mediatek,camsys.txt | 27 ++++++++++++++++++++
> .../bindings/arm/mediatek/mediatek,imgsys.txt | 1 +
> .../bindings/arm/mediatek/mediatek,infracfg.txt | 1 +
> .../bindings/arm/mediatek/mediatek,mipi0a.txt | 23 +++++++++++++++++
> .../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,vcodecsys.txt | 22 ++++++++++++++++
> 10 files changed, 79 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt
> create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mipi0a.txt
> create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,vcodecsys.txt
>
> diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
> index b404d59..44eaeac 100644
> --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
> +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
> @@ -8,6 +8,7 @@ Required Properties:
> - compatible: Should be one of:
> - "mediatek,mt2701-apmixedsys"
> - "mediatek,mt2712-apmixedsys", "syscon"
> + - "mediatek,mt6765-apmixedsys", "syscon"
> - "mediatek,mt6797-apmixedsys"
> - "mediatek,mt7622-apmixedsys"
> - "mediatek,mt8135-apmixedsys"
> diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
> index 34a69ba..9a8672a 100644
> --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
> +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
> @@ -7,6 +7,7 @@ Required Properties:
>
> - compatible: Should be one of:
> - "mediatek,mt2701-audsys", "syscon"
> + - "mediatek,mt6765-audsys", "syscon"
> - "mediatek,mt7622-audsys", "syscon"
> - #clock-cells: Must be 1
>
> diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt
> new file mode 100644
> index 0000000..dc75783
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt
> @@ -0,0 +1,27 @@
> +MediaTek CAMSYS controller
> +============================
> +
> +The MediaTek CAMSYS controller provides various clocks to the system.
Only clocks? If so, then this should be moved to bindings/clocks/.
> +
> +Required Properties:
> +
> +- compatible: Should be one of:
> + - "mediatek,mt6765-camsys", "syscon"
> +- #clock-cells: Must be 1
> +
> +The AUDSYS 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.
> +
> +Required sub-nodes:
> +-------
> +For common binding part and usage, refer to
> +../sonud/mt2701-afe-pcm.txt.
> +
> +Example:
> +
> +camsys: camsys@1a000000 {
clock-controller@...
if the above answer is yes.
Same comments on the other docs.
On Tue, Jul 17, 2018 at 04:52:24PM +0800, Mars Cheng wrote:
> This adds power dt-bindings for MT6765
>
> Signed-off-by: Mars Cheng <[email protected]>
> Signed-off-by: Owen Chen <[email protected]>
> ---
> .../devicetree/bindings/soc/mediatek/scpsys.txt | 6 ++++++
> 1 file changed, 6 insertions(+)
Reviewed-by: Rob Herring <[email protected]>
On Tue, Jul 17, 2018 at 04:52:25PM +0800, Mars Cheng wrote:
> This adds scpsys support for MT6765
>
> Signed-off-by: Mars Cheng <[email protected]>
> Signed-off-by: Owen Chen <[email protected]>
> ---
> drivers/soc/mediatek/mtk-scpsys.c | 88 ++++++++++++++++++++++++++++++
> include/dt-bindings/power/mt6765-power.h | 14 +++++
This file goes in the binding patch.
> 2 files changed, 102 insertions(+)
> create mode 100644 include/dt-bindings/power/mt6765-power.h
Hi Matthias
On Wed, 2018-07-18 at 16:50 +0200, Matthias Brugger wrote:
>
> On 17/07/18 10:52, Mars Cheng wrote:
> > From: Owen Chen <[email protected]>
> >
> > MT6765 need multiple register and actions to setup bus
> > protect.
> > 1. turn on subsys CG before release bus protect to receive
> > ack.
> > 2. turn off subsys CG after set bus protect and receive
> > ack.
> > 3. bus protect need not only infracfg but other domain
> > register to setup. Therefore we add a set/clr APIs
> > with more customize arguments.
> >
> > Signed-off-by: Owen Chen <[email protected]>
> > Signed-off-by: Mars Cheng <[email protected]>
> > ---
> > drivers/soc/mediatek/Makefile | 2 +-
> > drivers/soc/mediatek/mtk-infracfg.c | 178 +++++++++++---
> > drivers/soc/mediatek/mtk-scpsys-ext.c | 405 +++++++++++++++++++++++++++++++
> > drivers/soc/mediatek/mtk-scpsys.c | 147 +++++++++--
> > include/linux/soc/mediatek/infracfg.h | 9 +-
> > include/linux/soc/mediatek/scpsys-ext.h | 66 +++++
> > 6 files changed, 745 insertions(+), 62 deletions(-)
> > create mode 100644 drivers/soc/mediatek/mtk-scpsys-ext.c
> > create mode 100644 include/linux/soc/mediatek/scpsys-ext.h
> >
> > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
> > index 12998b0..9dc6670 100644
> > --- a/drivers/soc/mediatek/Makefile
> > +++ b/drivers/soc/mediatek/Makefile
> > @@ -1,3 +1,3 @@
> > -obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
> > +obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o mtk-scpsys-ext.o
> > obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
> > obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
> > diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c
> > index 958861c..11eadf8 100644
> > --- a/drivers/soc/mediatek/mtk-infracfg.c
> > +++ b/drivers/soc/mediatek/mtk-infracfg.c
> > @@ -1,3 +1,4 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > /*
> > * Copyright (c) 2015 Pengutronix, Sascha Hauer <[email protected]>
> > *
> > @@ -15,6 +16,7 @@
> > #include <linux/jiffies.h>
> > #include <linux/regmap.h>
> > #include <linux/soc/mediatek/infracfg.h>
> > +#include <linux/soc/mediatek/scpsys-ext.h>
> > #include <asm/processor.h>
> >
> > #define MTK_POLL_DELAY_US 10
> > @@ -26,62 +28,176 @@
> > #define INFRA_TOPAXI_PROTECTEN_CLR 0x0264
> >
> > /**
> > - * mtk_infracfg_set_bus_protection - enable bus protection
> > - * @regmap: The infracfg regmap
> > - * @mask: The mask containing the protection bits to be enabled.
> > - * @reg_update: The boolean flag determines to set the protection bits
> > - * by regmap_update_bits with enable register(PROTECTEN) or
> > - * by regmap_write with set register(PROTECTEN_SET).
> > + * mtk_generic_set_cmd - enable bus protection with set register
> > + * @regmap: The bus protect regmap
> > + * @set_ofs: The set register offset to set corresponding bit to 1.
> > + * @sta_ofs: The status register offset to show bus protect enable/disable.
> > + * @mask: The mask containing the protection bits to be disabled.
> > *
> > * 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,
> > - bool reg_update)
> > +int mtk_generic_set_cmd(struct regmap *regmap, u32 set_ofs,
> > + u32 sta_ofs, u32 mask)
> > {
> > u32 val;
> > int ret;
> >
> > - if (reg_update)
> > - regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask,
> > - mask);
> > - else
> > - regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_SET, mask);
> > + regmap_write(regmap, set_ofs, mask);
> >
> > - ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1,
> > - val, (val & mask) == mask,
> > - MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> > + ret = regmap_read_poll_timeout(regmap, sta_ofs, val,
> > + (val & mask) == mask,
> > + MTK_POLL_DELAY_US,
> > + MTK_POLL_TIMEOUT);
> >
> > return ret;
> > }
> >
> > /**
> > - * mtk_infracfg_clear_bus_protection - disable bus protection
> > - * @regmap: The infracfg regmap
> > + * mtk_generic_clr_cmd - disable bus protection with clr register
> > + * @regmap: The bus protect regmap
> > + * @clr_ofs: The clr register offset to clear corresponding bit to 0.
> > + * @sta_ofs: The status register offset to show bus protect enable/disable.
> > * @mask: The mask containing the protection bits to be disabled.
> > - * @reg_update: The boolean flag determines to clear the protection bits
> > - * by regmap_update_bits with enable register(PROTECTEN) or
> > - * by regmap_write with clear register(PROTECTEN_CLR).
> > *
> > * This function disables the bus protection bits previously enabled with
> > - * mtk_infracfg_set_bus_protection.
> > + * mtk_set_bus_protection.
> > */
> >
> > -int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
> > - bool reg_update)
> > +int mtk_generic_clr_cmd(struct regmap *regmap, u32 clr_ofs,
> > + u32 sta_ofs, u32 mask)
> > {
> > int ret;
> > u32 val;
> >
> > - if (reg_update)
> > - regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
> > - else
> > - regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_CLR, mask);
> > + regmap_write(regmap, clr_ofs, mask);
> >
> > - ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1,
> > - val, !(val & mask),
> > - MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> > + ret = regmap_read_poll_timeout(regmap, sta_ofs, val,
> > + !(val & mask),
> > + MTK_POLL_DELAY_US,
> > + MTK_POLL_TIMEOUT);
> > + return ret;
> > +}
> > +
> > +/**
> > + * mtk_generic_enable_cmd - enable bus protection with upd register
> > + * @regmap: The bus protect regmap
> > + * @upd_ofs: The update register offset to directly rewrite value to
> > + * corresponding bit.
> > + * @sta_ofs: The status register offset to show bus protect enable/disable.
> > + * @mask: The mask containing the protection bits to be disabled.
> > + *
> > + * 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_generic_enable_cmd(struct regmap *regmap, u32 upd_ofs,
> > + u32 sta_ofs, u32 mask)
> > +{
> > + u32 val;
> > + int ret;
> > +
> > + regmap_update_bits(regmap, upd_ofs, mask, mask);
> >
> > + ret = regmap_read_poll_timeout(regmap, sta_ofs, val,
> > + (val & mask) == mask,
> > + MTK_POLL_DELAY_US,
> > + MTK_POLL_TIMEOUT);
> > return ret;
> > }
> > +
> > +/**
> > + * mtk_generic_disable_cmd - disable bus protection with updd register
> > + * @regmap: The bus protect regmap
> > + * @upd_ofs: The update register offset to directly rewrite value to
> > + * corresponding bit.
> > + * @sta_ofs: The status register offset to show bus protect enable/disable.
> > + * @mask: The mask containing the protection bits to be disabled.
> > + *
> > + * This function disables the bus protection bits previously enabled with
> > + * mtk_set_bus_protection.
> > + */
> > +
> > +int mtk_generic_disable_cmd(struct regmap *regmap, u32 upd_ofs,
> > + u32 sta_ofs, u32 mask)
> > +{
> > + int ret;
> > + u32 val;
> > +
> > + regmap_update_bits(regmap, upd_ofs, mask, 0);
> > +
> > + ret = regmap_read_poll_timeout(regmap, sta_ofs,
> > + val, !(val & mask),
> > + MTK_POLL_DELAY_US,
> > + MTK_POLL_TIMEOUT);
> > + return ret;
> > +}
> > +
> > +/**
> > + * mtk_set_bus_protection - enable bus protection
> > + * @infracfg: The bus protect regmap, default use infracfg
> > + * @mask: The mask containing the protection bits to be 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)
> > +{
> > + return mtk_generic_set_cmd(infracfg,
> > + INFRA_TOPAXI_PROTECTEN_SET,
> > + INFRA_TOPAXI_PROTECTSTA1,
> > + mask);
> > +}
> > +
> > +/**
> > + * mtk_clear_bus_protection - disable bus protection
> > + * @infracfg: The bus protect regmap, default use infracfg
> > + * @mask: The mask containing the protection bits to be disabled.
> > + *
> > + * This function disables the bus protection bits previously enabled with
> > + * mtk_set_bus_protection.
> > + */
> > +
> > +int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask)
> > +{
> > + return mtk_generic_clr_cmd(infracfg,
> > + INFRA_TOPAXI_PROTECTEN_CLR,
> > + INFRA_TOPAXI_PROTECTSTA1,
> > + mask);
> > +}
> > +
> > +/**
> > + * mtk_infracfg_enable_bus_protection - enable bus protection
> > + * @infracfg: The bus protect regmap, default use infracfg
> > + * @mask: The mask containing the protection bits to be disabled.
> > + *
> > + * 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_enable_bus_protection(struct regmap *infracfg, u32 mask)
> > +{
> > + return mtk_generic_enable_cmd(infracfg,
> > + INFRA_TOPAXI_PROTECTEN,
> > + INFRA_TOPAXI_PROTECTSTA1,
> > + mask);
> > +}
> > +
> > +/**
> > + * mtk_infracfg_disable_bus_protection - disable bus protection
> > + * @infracfg: The bus protect regmap, default use infracfg
> > + * @mask: The mask containing the protection bits to be disabled.
> > + *
> > + * This function disables the bus protection bits previously enabled with
> > + * mtk_infracfg_set_bus_protection.
> > + */
> > +
> > +int mtk_infracfg_disable_bus_protection(struct regmap *infracfg, u32 mask)
> > +{
> > + return mtk_generic_disable_cmd(infracfg,
> > + INFRA_TOPAXI_PROTECTEN,
> > + INFRA_TOPAXI_PROTECTSTA1,
> > + mask);
> > +}
> > diff --git a/drivers/soc/mediatek/mtk-scpsys-ext.c b/drivers/soc/mediatek/mtk-scpsys-ext.c
> > new file mode 100644
> > index 0000000..965e64d
> > --- /dev/null
> > +++ b/drivers/soc/mediatek/mtk-scpsys-ext.c
> > @@ -0,0 +1,405 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2018 MediaTek Inc.
> > + * Author: Owen Chen <[email protected]>
> > + */
> > +#include <linux/clk.h>
> > +#include <linux/clk-provider.h>
> > +#include <linux/slab.h>
> > +#include <linux/export.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/of_device.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +#include <linux/soc/mediatek/infracfg.h>
> > +#include <linux/soc/mediatek/scpsys-ext.h>
> > +
> > +
> > +#define MAX_CLKS 10
> > +#define INFRA "infracfg"
> > +#define SMIC "smi_comm"
>
> Don't use defines for this. While at it I suppose it should be "smi_common"
OK. I will fix it.
>
> > +
> > +static LIST_HEAD(ext_clk_map_list);
> > +static LIST_HEAD(ext_attr_map_list);
> > +
> > +static struct regmap *infracfg;
> > +static struct regmap *smi_comm;
> > +
> > +enum regmap_type {
> > + IFR_TYPE,
> > + SMI_TYPE,
> > + MAX_REGMAP_TYPE,
> > +};
> > +
> > +/**
> > + * struct ext_reg_ctrl - set multiple register for bus protect
> > + * @regmap: The bus protect regmap, 1: infracfg, 2: other master regmap
> > + * such as SMI.
> > + * @set_ofs: The set register offset to set corresponding bit to 1.
> > + * @clr_ofs: The clr register offset to clear corresponding bit to 0.
> > + * @sta_ofs: The status register offset to show bus protect enable/disable.
> > + */
> > +struct ext_reg_ctrl {
> > + enum regmap_type type;
> > + u32 set_ofs;
> > + u32 clr_ofs;
> > + u32 sta_ofs;
> > +};
> > +
> > +/**
> > + * struct ext_clk_ctrl - enable multiple clks for bus protect
> > + * @clk: The clk need to enable before pwr on/bus protect.
> > + * @scpd_n: The name present the scpsys domain where the clks belongs to.
> > + * @clk_list: The list node linked to ext_clk_map_list.
> > + */
> > +struct ext_clk_ctrl {
> > + struct clk *clk;
> > + const char *scpd_n;
> > + struct list_head clk_list;
> > +};
> > +
> > +struct bus_mask_ops {
> > + int (*set)(struct regmap *regmap, u32 set_ofs,
> > + u32 sta_ofs, u32 mask);
> > + int (*release)(struct regmap *regmap, u32 clr_ofs,
> > + u32 sta_ofs, u32 mask);
> > +};
> > +
> > +static struct scpsys_ext_attr *__get_attr_parent(const char *parent_n)
> > +{
> > + struct scpsys_ext_attr *attr;
> > +
> > + if (!parent_n)
> > + return ERR_PTR(-EINVAL);
> > +
> > + list_for_each_entry(attr, &ext_attr_map_list, attr_list) {
> > + if (attr->scpd_n && !strcmp(parent_n, attr->scpd_n))
> > + return attr;
> > + }
> > +
> > + return ERR_PTR(-EINVAL);
> > +}
> > +
> > +int bus_ctrl_set_release(struct scpsys_ext_attr *attr, bool set)
> > +{
> > + int i;
> > + int ret = 0;
> > +
> > + for (i = 0; i < MAX_STEP_NUM && attr->mask[i].mask; i++) {
> > + struct ext_reg_ctrl *rc = attr->mask[i].regs;
> > + struct regmap *regmap;
> > +
> > + if (rc->type == IFR_TYPE)
> > + regmap = infracfg;
> > + else if (rc->type == SMI_TYPE)
> > + regmap = smi_comm;
> > + else
> > + return -EINVAL;
> > +
> > + if (set)
> > + ret = attr->mask[i].ops->set(regmap,
> > + rc->set_ofs,
> > + rc->sta_ofs,
> > + attr->mask[i].mask);
> > + else
> > + ret = attr->mask[i].ops->release(regmap,
> > + rc->clr_ofs,
> > + rc->sta_ofs,
> > + attr->mask[i].mask);
> > + }
> > +
> > + return ret;
> > +}
> > +
> > +int bus_ctrl_set(struct scpsys_ext_attr *attr)
> > +{
> > + return bus_ctrl_set_release(attr, CMD_ENABLE);
> > +}
> > +
> > +int bus_ctrl_release(struct scpsys_ext_attr *attr)
> > +{
> > + return bus_ctrl_set_release(attr, CMD_DISABLE);
> > +}
> > +
> > +int bus_clk_enable_disable(struct scpsys_ext_attr *attr, bool enable)
> > +{
> > + int i = 0;
> > + int ret = 0;
> > + struct ext_clk_ctrl *cc;
> > + struct clk *clk[MAX_CLKS];
> > +
> > + list_for_each_entry(cc, &ext_clk_map_list, clk_list) {
>
> Why can't we handle this in the same way as we do in mtk-scpsys.c ?
We originally thought it would be better to put all the additional flow
at new created file, but after consider the readability of code flow, we
would put this cg operation back to mtk_scpsys.c.
>
> > + if (!strcmp(cc->scpd_n, attr->scpd_n)) {
> > + if (enable)
> > + ret = clk_prepare_enable(cc->clk);
> > + else
> > + clk_disable_unprepare(cc->clk);
> > +
> > + if (ret) {
> > + pr_err("Failed to %s %s\n",
> > + enable ? "enable" : "disable",
> > + __clk_get_name(cc->clk));
> > + goto err;
> > + } else {
> > + clk[i] = cc->clk;
> > + i++;
> > + }
> > + }
> > + }
> > +
> > + return ret;
> > +
> > +err:
> > + for (--i; i >= 0; i--)
> > + if (enable)
> > + clk_disable_unprepare(clk[i]);
> > + else
> > + clk_prepare_enable(clk[i]);
> > + return ret;
> > +}
> > +
> > +int bus_clk_enable(struct scpsys_ext_attr *attr)
> > +{
> > + struct scpsys_ext_attr *attr_p;
> > + int ret = 0;
> > +
> > + attr_p = __get_attr_parent(attr->parent_n);
>
> Why can't we implement this using the pg_genpd_add_subdomain approach?
OK, we will follow it.
>
> > + if (!IS_ERR(attr_p)) {
> > + ret = bus_clk_enable_disable(attr_p, CMD_ENABLE);
> > + if (ret)
> > + return ret;
> > + }
> > +
> > + return bus_clk_enable_disable(attr, CMD_ENABLE);
> > +}
> > +
> > +int bus_clk_disable(struct scpsys_ext_attr *attr)
> > +{
> > + struct scpsys_ext_attr *attr_p;
> > + int ret = 0;
> > +
> > + ret = bus_clk_enable_disable(attr, CMD_DISABLE);
> > + if (ret)
> > + return ret;
> > +
> > + attr_p = __get_attr_parent(attr->parent_n);
> > + if (!IS_ERR(attr_p))
> > + ret = bus_clk_enable_disable(attr_p, CMD_DISABLE);
>
> Same here.
>
> > +
> > + return ret;
> > +}
> > +
> > +const struct bus_mask_ops bus_mask_set_clr_ctrl = {
> > + .set = &mtk_generic_set_cmd,
> > + .release = &mtk_generic_clr_cmd,
> > +};
> > +
> > +const struct bus_ext_ops ext_bus_ctrl = {
> > + .enable = &bus_ctrl_set,
> > + .disable = &bus_ctrl_release,
> > +};
> > +
> > +const struct bus_ext_ops ext_cg_ctrl = {
> > + .enable = &bus_clk_enable,
> > + .disable = &bus_clk_disable,
> > +};
> > +
> > +/*
> > + * scpsys bus driver init
> > + */
> > +struct regmap *syscon_regmap_lookup_by_phandle_idx(struct device_node *np,
> > + const char *property,
> > + int index)
> > +{
> > + struct device_node *syscon_np;
> > + struct regmap *regmap;
> > +
> > + if (property)
> > + syscon_np = of_parse_phandle(np, property, index);
> > + else
> > + syscon_np = np;
> > +
> > + if (!syscon_np)
> > + return ERR_PTR(-ENODEV);
> > +
> > + regmap = syscon_node_to_regmap(syscon_np);
> > + of_node_put(syscon_np);
> > +
> > + return regmap;
> > +}
>
> Why do we need this? It is never called...
Sorry, Forgot to delete it.
>
> > +
> > +int scpsys_ext_regmap_init(struct platform_device *pdev)
> > +{
> > + infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
> > + INFRA);
> > + if (IS_ERR(infracfg)) {
> > + dev_err(&pdev->dev,
> > + "Cannot find bus infracfg controller: %ld\n",
> > + PTR_ERR(infracfg));
> > + return PTR_ERR(infracfg);
> > + }
> > +
> > + smi_comm = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
> > + SMIC);
> > + if (IS_ERR(smi_comm)) {
> > + dev_err(&pdev->dev,
> > + "Cannot find bus smi_comm controller: %ld\n",
> > + PTR_ERR(smi_comm));
> > + return PTR_ERR(smi_comm);
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int add_clk_to_list(struct platform_device *pdev,
> > + const char *name,
> > + const char *scpd_n)
> > +{
> > + struct clk *clk;
> > + struct ext_clk_ctrl *cc;
> > +
> > + clk = devm_clk_get(&pdev->dev, name);
> > + if (IS_ERR(clk)) {
> > + dev_err(&pdev->dev, "Failed add clk %ld\n", PTR_ERR(clk));
> > + return PTR_ERR(clk);
> > + }
> > +
> > + cc = kzalloc(sizeof(*cc), GFP_KERNEL);
> > + cc->clk = clk;
> > + cc->scpd_n = kstrdup(scpd_n, GFP_KERNEL);
> > +
> > + list_add(&cc->clk_list, &ext_clk_map_list);
> > +
> > + return 0;
> > +}
> > +
> > +static int add_cg_to_list(struct platform_device *pdev)
> > +{
> > + int i = 0;
> > +
> > + struct device_node *node = pdev->dev.of_node;
> > +
> > + if (!node) {
> > + dev_err(&pdev->dev, "Cannot find topcksys node: %ld\n",
>
> Why topcksys? Shouldn't that be the node of scpsys?
it's typo.we will fix it.
>
> > + PTR_ERR(node));
> > + return PTR_ERR(node);
> > + }
> > +
> > + do {
> > + const char *ck_name;
> > + char *temp_str;
> > + char *tok[2] = {NULL};
> > + int cg_idx = 0;
> > + int idx = 0;
> > + int ret = 0;
> > +
> > + ret = of_property_read_string_index(node, "clock-names", i,
> > + &ck_name);
> > + if (ret < 0)
> > + break;
> > +
> > + temp_str = kmalloc_array(strlen(ck_name), sizeof(char),
> > + GFP_KERNEL | __GFP_ZERO);
> > + memcpy(temp_str, ck_name, strlen(ck_name));
> > + temp_str[strlen(ck_name)] = '\0';
>
> why don't you use kstrdup or similar?
we will fix it.
>
> > + do {
> > + tok[idx] = strsep(&temp_str, "-");
> > + idx++;
> > + } while (temp_str);
>
> You want to split the clock name like "mm-2" in
> char **tok = {"mm", "2"};
> correct? That can be done easier AFAIK:
> tok[0] = strsep(&temp_str, "-");
> tok[1] = &temp_str;
we will fix it.
>
> > +
> > + if (idx == 2) {
>
> You don't add clocks like "mfg" and "mm". Why?
it's not the same, "mm" and "mfg" belong to mux, not a cg.and mux is
handle by mtk_scpsys.c
>
> > + if (kstrtouint(tok[1], 10, &cg_idx))
> i
> And then? You don't do anything with cg_idx..t
yes, we will delete this check.
>
> > + return -EINVAL;
> > +
> > + if (add_clk_to_list(pdev, ck_name, tok[0]))
>
> add_clk_to_list third parameter is the name of the scp domain, but you pass the
> clock name here. I'm puzzled.
yes, our idea is to set the prefix same as scp domain name, so we can
find the correct cg clks which belong to relative scp domain.
ex: "mm-0""mm-1" need to enable for "mm" scp domain power control flow.
>
> > + return -EINVAL;
> > + }
> > + kfree(temp_str);
> > + i++;
> > + } while (1);
> > +
> > + return 0;
> > +}
> > +
> > +int scpsys_ext_clk_init(struct platform_device *pdev)
> > +{
> > + int ret = 0;
> > +
> > + ret = add_cg_to_list(pdev);
> > + if (ret)
> > + goto err;
> > +
> > +err:
> > + return ret;
> > +}
>
> Why do we need add_cg_to_list, it can be implemented directly here. Why is here
> a goto to a return statement that will be executed anyway? Please go through the
> code and check that it is clean before submitting.
yes, we will fix it.
>
> > +
> > +int scpsys_ext_attr_init(const struct scpsys_ext_data *data)
> > +{
> > + int i, count = 0;
> > +
> > + for (i = 0; i < data->num_attr; i++) {
> > + struct scpsys_ext_attr *node = data->attr + i;
> > +
> > + if (!node)
> > + continue;
> > +
> > + list_add(&node->attr_list, &ext_attr_map_list);
> > + count++;
> > + }
> > +
> > + if (!count)
> > + return -EINVAL;
> > +
> > + return 0;
> > +}
> > +
> > +static const struct of_device_id of_scpsys_ext_match_tbl[] = {
> > + {
> > + /* sentinel */
> > + }
> > +};
> > +
> > +struct scpsys_ext_data *scpsys_ext_init(struct platform_device *pdev)
> > +{
> > + const struct of_device_id *match;
> > + struct scpsys_ext_data *data;
> > + int ret;
> > +
> > + match = of_match_device(of_scpsys_ext_match_tbl, &pdev->dev);
> > +
> > + if (!match) {
> > + dev_err(&pdev->dev, "no match\n");
> > + return ERR_CAST(match);
> > + }
> > +
> > + data = (struct scpsys_ext_data *)match->data;
> > + if (IS_ERR(data)) {
> > + dev_err(&pdev->dev, "no match scpext data\n");
> > + return ERR_CAST(data);
> > + }
> > +
> > + ret = scpsys_ext_attr_init(data);
> > + if (ret) {
> > + dev_err(&pdev->dev,
> > + "Failed to init bus attr: %d\n",
> > + ret);
> > + return ERR_PTR(ret);
> > + }
> > +
> > + ret = scpsys_ext_regmap_init(pdev);
> > + if (ret) {
> > + dev_err(&pdev->dev,
> > + "Failed to init bus register: %d\n",
> > + ret);
> > + return ERR_PTR(ret);
> > + }
> > +
> > + ret = scpsys_ext_clk_init(pdev);
> > + if (ret) {
> > + dev_err(&pdev->dev, "Failed to init bus clks: %d\n",
> > + ret);
> > + return ERR_PTR(ret);
> > + }
> > +
> > + return data;
> > +}
> > diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> > index 4bb6c7a..03df2d6 100644
> > --- a/drivers/soc/mediatek/mtk-scpsys.c
> > +++ b/drivers/soc/mediatek/mtk-scpsys.c
> > @@ -1,3 +1,4 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > /*
> > * Copyright (c) 2015 Pengutronix, Sascha Hauer <[email protected]>
> > *
> > @@ -20,6 +21,7 @@
> > #include <linux/pm_domain.h>
> > #include <linux/regulator/consumer.h>
> > #include <linux/soc/mediatek/infracfg.h>
> > +#include <linux/soc/mediatek/scpsys-ext.h>
> >
> > #include <dt-bindings/power/mt2701-power.h>
> > #include <dt-bindings/power/mt2712-power.h>
> > @@ -117,6 +119,15 @@ enum clk_id {
> >
> > #define MAX_CLKS 3
> >
> > +/**
> > + * struct scp_domain_data - scp domain data for power on/off flow
> > + * @name: The domain name.
> > + * @sta_mask: The mask for power on/off status bit.
> > + * @ctl_offs: The offset for main power control register.
> > + * @sram_pdn_bits: The mask for sram power control bits.
> > + * @sram_pdn_ack_bits The mask for sram power control acked bits.
> > + * @caps: The flag for active wake-up action.
> > + */
> > struct scp_domain_data {
> > const char *name;
> > u32 sta_mask;
> > @@ -150,7 +161,7 @@ struct scp {
> > void __iomem *base;
> > struct regmap *infracfg;
> > struct scp_ctrl_reg ctrl_reg;
> > - bool bus_prot_reg_update;
> > + struct scpsys_ext_data *ext_data;
> > };
> >
> > struct scp_subdomain {
> > @@ -164,7 +175,6 @@ struct scp_soc_data {
> > const struct scp_subdomain *subdomains;
> > int num_subdomains;
> > const struct scp_ctrl_reg regs;
> > - bool bus_prot_reg_update;
> > };
> >
> > static int scpsys_domain_is_on(struct scp_domain *scpd)
> > @@ -236,6 +246,31 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> > val |= PWR_RST_B_BIT;
> > writel(val, ctl_addr);
> >
> > + if (!IS_ERR(scp->ext_data)) {
> > + struct scpsys_ext_attr *attr;
> > +
> > + attr = scp->ext_data->get_attr(scpd->data->name);
> > + if (!IS_ERR(attr) && attr->cg_ops) {
> > + ret = attr->cg_ops->enable(attr);
> > + if (ret)
> > + goto err_ext_clk;
> > + }
> > + }
> > +
> > + val &= ~scpd->data->sram_pdn_bits;
> > + writel(val, ctl_addr);
> > +
> > + if (!IS_ERR(scp->ext_data)) {
> > + struct scpsys_ext_attr *attr;
> > +
> > + attr = scp->ext_data->get_attr(scpd->data->name);
> > + if (!IS_ERR(attr) && attr->cg_ops) {
> > + ret = attr->cg_ops->enable(attr);
> > + if (ret)
> > + goto err_ext_clk;
> > + }
> > + }
> > +
> > val &= ~scpd->data->sram_pdn_bits;
> > writel(val, ctl_addr);
> >
> > @@ -247,25 +282,65 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> > * applied here.
> > */
> > usleep_range(12000, 12100);
> > -
> > } else {
> > ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == 0,
> > MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
> > if (ret < 0)
> > - goto err_pwr_ack;
> > + goto err_sram;
> > }
> >
> > if (scpd->data->bus_prot_mask) {
> > ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
> > - scpd->data->bus_prot_mask,
> > - scp->bus_prot_reg_update);
> > + scpd->data->bus_prot_mask);
> > if (ret)
> > - goto err_pwr_ack;
> > + goto err_sram;
> > + }
> > +
> > + if (!IS_ERR(scp->ext_data)) {
> > + struct scpsys_ext_attr *attr;
> > +
> > + attr = scp->ext_data->get_attr(scpd->data->name);
> > + if (!IS_ERR(attr) && attr->bus_ops) {
> > + ret = attr->bus_ops->disable(attr);
> > + if (ret)
> > + goto err_sram;
> > + }
> > + }
> > +
> > + if (!IS_ERR(scp->ext_data)) {
> > + struct scpsys_ext_attr *attr;
> > +
> > + attr = scp->ext_data->get_attr(scpd->data->name);
> > + if (!IS_ERR(attr) && attr->cg_ops) {
> > + ret = attr->cg_ops->disable(attr);
> > + if (ret)
> > + goto err_sram;
> > + }
> > }
> >
> > return 0;
> >
> > +err_sram:
> > + val = readl(ctl_addr);
> > + val |= scpd->data->sram_pdn_bits;
> > + writel(val, ctl_addr);
> > +err_ext_clk:
> > + val = readl(ctl_addr);
> > + val |= PWR_ISO_BIT;
> > + writel(val, ctl_addr);
> > +
> > + val &= ~PWR_RST_B_BIT;
> > + writel(val, ctl_addr);
> > +
> > + val |= PWR_CLK_DIS_BIT;
> > + writel(val, ctl_addr);
> > err_pwr_ack:
> > + val &= ~PWR_ON_BIT;
> > + writel(val, ctl_addr);
> > +
> > + val &= ~PWR_ON_2ND_BIT;
> > + writel(val, ctl_addr);
> > +
> > for (i = MAX_CLKS - 1; i >= 0; i--) {
> > if (scpd->clk[i])
> > clk_disable_unprepare(scpd->clk[i]);
> > @@ -274,8 +349,6 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
> > if (scpd->supply)
> > regulator_disable(scpd->supply);
> >
> > - dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
> > -
> > return ret;
> > }
> >
> > @@ -289,14 +362,35 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> > int ret, tmp;
> > int i;
> >
> > + if (!IS_ERR(scp->ext_data)) {
> > + struct scpsys_ext_attr *attr;
> > +
> > + attr = scp->ext_data->get_attr(scpd->data->name);
> > + if (!IS_ERR(attr) && attr->cg_ops) {
> > + ret = attr->cg_ops->enable(attr);
> > + if (ret)
> > + goto out;
> > + }
> > + }
> > +
> > if (scpd->data->bus_prot_mask) {
> > ret = mtk_infracfg_set_bus_protection(scp->infracfg,
> > - scpd->data->bus_prot_mask,
> > - scp->bus_prot_reg_update);
> > + scpd->data->bus_prot_mask);
> > if (ret)
> > goto out;
> > }
> >
> > + if (!IS_ERR(scp->ext_data)) {
> > + struct scpsys_ext_attr *attr;
> > +
> > + attr = scp->ext_data->get_attr(scpd->data->name);
> > + if (!IS_ERR(attr) && attr->bus_ops) {
> > + ret = attr->bus_ops->enable(attr);
> > + if (ret)
> > + goto out;
> > + }
> > + }
> > +
> > val = readl(ctl_addr);
> > val |= scpd->data->sram_pdn_bits;
> > writel(val, ctl_addr);
> > @@ -307,6 +401,17 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> > if (ret < 0)
> > goto out;
> >
> > + if (!IS_ERR(scp->ext_data)) {
> > + struct scpsys_ext_attr *attr;
> > +
> > + attr = scp->ext_data->get_attr(scpd->data->name);
> > + if (!IS_ERR(attr) && attr->cg_ops) {
> > + ret = attr->cg_ops->disable(attr);
> > + if (ret)
> > + goto out;
> > + }
> > + }
> > +
> > val |= PWR_ISO_BIT;
> > writel(val, ctl_addr);
> >
> > @@ -337,8 +442,6 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
> > return 0;
> >
> > out:
> > - dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name);
> > -
> > return ret;
> > }
> >
> > @@ -352,8 +455,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,
> > - bool bus_prot_reg_update)
> > + const struct scp_ctrl_reg *scp_ctrl_reg)
> > {
> > struct genpd_onecell_data *pd_data;
> > struct resource *res;
> > @@ -367,11 +469,10 @@ static struct scp *init_scp(struct platform_device *pdev,
> >
> > 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->bus_prot_reg_update = bus_prot_reg_update;
> > -
> > scp->dev = &pdev->dev;
> >
> > + scp->ext_data = scpsys_ext_init(pdev);
> > +
> > res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > scp->base = devm_ioremap_resource(&pdev->dev, res);
> > if (IS_ERR(scp->base))
> > @@ -1021,7 +1122,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> > .pwr_sta_offs = SPM_PWR_STATUS,
> > .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> > },
> > - .bus_prot_reg_update = true,
> > };
> >
> > static const struct scp_soc_data mt2712_data = {
> > @@ -1033,7 +1133,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> > .pwr_sta_offs = SPM_PWR_STATUS,
> > .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> > },
> > - .bus_prot_reg_update = false,
> > };
> >
> > static const struct scp_soc_data mt6765_data = {
> > @@ -1056,7 +1155,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> > .pwr_sta_offs = SPM_PWR_STATUS_MT6797,
> > .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
> > },
> > - .bus_prot_reg_update = true,
>
> I don't understand why you can delete this flag if you don't change anything
> else in the data structure. For me this looks like you will break other chips.
> Please explain.
>
> I have the gut feeling that this can be implemented in the existing mtk-scpsys
> driver. Can you please explain what are the points that this is not possible.
> I want to understand the design decisions you made here, because they seem
> really odd to me.
>
> Best regards,
> Matthias
>
sorry, it should not be deleted. we will fix it.
> > };
> >
> > static const struct scp_soc_data mt7622_data = {
> > @@ -1066,7 +1164,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> > .pwr_sta_offs = SPM_PWR_STATUS,
> > .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> > },
> > - .bus_prot_reg_update = true,
> > };
> >
> > static const struct scp_soc_data mt7623a_data = {
> > @@ -1076,7 +1173,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> > .pwr_sta_offs = SPM_PWR_STATUS,
> > .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> > },
> > - .bus_prot_reg_update = true,
> > };
> >
> > static const struct scp_soc_data mt8173_data = {
> > @@ -1088,7 +1184,6 @@ static void mtk_register_power_domains(struct platform_device *pdev,
> > .pwr_sta_offs = SPM_PWR_STATUS,
> > .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
> > },
> > - .bus_prot_reg_update = true,
> > };
> >
> > /*
> > @@ -1132,8 +1227,8 @@ static int scpsys_probe(struct platform_device *pdev)
> >
> > soc = of_device_get_match_data(&pdev->dev);
> >
> > - scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs,
> > - soc->bus_prot_reg_update);
> > + scp = init_scp(pdev, soc->domains, soc->num_domains,
> > + &soc->regs);
> > if (IS_ERR(scp))
> > return PTR_ERR(scp);
> >
> > diff --git a/include/linux/soc/mediatek/infracfg.h b/include/linux/soc/mediatek/infracfg.h
> > index fd25f01..bfad082 100644
> > --- a/include/linux/soc/mediatek/infracfg.h
> > +++ b/include/linux/soc/mediatek/infracfg.h
> > @@ -32,8 +32,9 @@
> > #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,
> > - bool reg_update);
> > -int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
> > - bool reg_update);
> > +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_enable_bus_protection(struct regmap *infracfg, u32 mask);
> > +int mtk_infracfg_disable_bus_protection(struct regmap *infracfg, u32 mask);
> > +
> > #endif /* __SOC_MEDIATEK_INFRACFG_H */
> > diff --git a/include/linux/soc/mediatek/scpsys-ext.h b/include/linux/soc/mediatek/scpsys-ext.h
> > new file mode 100644
> > index 0000000..99b5ff1
> > --- /dev/null
> > +++ b/include/linux/soc/mediatek/scpsys-ext.h
> > @@ -0,0 +1,66 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +#ifndef __SOC_MEDIATEK_SCPSYS_EXT_H
> > +#define __SOC_MEDIATEK_SCPSYS_EXT_H
> > +
> > +#include <linux/platform_device.h>
> > +
> > +#define CMD_ENABLE 1
> > +#define CMD_DISABLE 0
> > +
> > +#define MAX_STEP_NUM 4
> > +
> > +/**
> > + * struct bus_mask - set mask and corresponding operation for bus protect
> > + * @regs: The register set of bus register control, including set/clr/sta.
> > + * @mask: The mask set for bus protect.
> > + * @flag: The flag to idetify which operation we take for bus protect.
> > + */
> > +struct bus_mask {
> > + struct ext_reg_ctrl *regs;
> > + u32 mask;
> > + const struct bus_mask_ops *ops;
> > +};
> > +
> > +/**
> > + * struct scpsys_ext_attr - extended attribute for bus protect and further
> > + * operand.
> > + *
> > + * @scpd_n: The name present the scpsys domain where the clks belongs to.
> > + * @mask: The mask set for bus protect.
> > + * @bus_ops: The operation we take for bus protect.
> > + * @cg_ops: The operation we take for cg on/off.
> > + * @attr_list: The list node linked to ext_attr_map_list.
> > + */
> > +struct scpsys_ext_attr {
> > + const char *scpd_n;
> > + struct bus_mask mask[MAX_STEP_NUM];
> > + const char *parent_n;
> > + const struct bus_ext_ops *bus_ops;
> > + const struct bus_ext_ops *cg_ops;
> > +
> > + struct list_head attr_list;
> > +};
> > +
> > +struct scpsys_ext_data {
> > + struct scpsys_ext_attr *attr;
> > + u8 num_attr;
> > + struct scpsys_ext_attr * (*get_attr)(const char *scpd_n);
> > +};
> > +
> > +struct bus_ext_ops {
> > + int (*enable)(struct scpsys_ext_attr *attr);
> > + int (*disable)(struct scpsys_ext_attr *attr);
> > +};
> > +
> > +int mtk_generic_set_cmd(struct regmap *regmap, u32 set_ofs,
> > + u32 sta_ofs, u32 mask);
> > +int mtk_generic_clr_cmd(struct regmap *regmap, u32 clr_ofs,
> > + u32 sta_ofs, u32 mask);
> > +int mtk_generic_enable_cmd(struct regmap *regmap, u32 upd_ofs,
> > + u32 sta_ofs, u32 mask);
> > +int mtk_generic_disable_cmd(struct regmap *regmap, u32 upd_ofs,
> > + u32 sta_ofs, u32 mask);
> > +
> > +struct scpsys_ext_data *scpsys_ext_init(struct platform_device *pdev);
> > +
> > +#endif /* __SOC_MEDIATEK_SCPSYS_EXT_H */
> >
On Fri, 2018-07-20 at 11:43 -0600, Rob Herring wrote:
> On Tue, Jul 17, 2018 at 04:52:22PM +0800, Mars Cheng wrote:
> > This patch adds the binding documentation for apmixedsys, audsys, camsys,
> > imgsys, infracfg, mipi0a, topckgen, vcodecsys
> >
> > Signed-off-by: Mars Cheng <[email protected]>
> > Signed-off-by: Owen Chen <[email protected]>
> > ---
> > .../bindings/arm/mediatek/mediatek,apmixedsys.txt | 1 +
> > .../bindings/arm/mediatek/mediatek,audsys.txt | 1 +
> > .../bindings/arm/mediatek/mediatek,camsys.txt | 27 ++++++++++++++++++++
> > .../bindings/arm/mediatek/mediatek,imgsys.txt | 1 +
> > .../bindings/arm/mediatek/mediatek,infracfg.txt | 1 +
> > .../bindings/arm/mediatek/mediatek,mipi0a.txt | 23 +++++++++++++++++
> > .../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,vcodecsys.txt | 22 ++++++++++++++++
> > 10 files changed, 79 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt
> > create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mipi0a.txt
> > create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,vcodecsys.txt
> >
> > diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
> > index b404d59..44eaeac 100644
> > --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
> > +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
> > @@ -8,6 +8,7 @@ Required Properties:
> > - compatible: Should be one of:
> > - "mediatek,mt2701-apmixedsys"
> > - "mediatek,mt2712-apmixedsys", "syscon"
> > + - "mediatek,mt6765-apmixedsys", "syscon"
> > - "mediatek,mt6797-apmixedsys"
> > - "mediatek,mt7622-apmixedsys"
> > - "mediatek,mt8135-apmixedsys"
> > diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
> > index 34a69ba..9a8672a 100644
> > --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
> > +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
> > @@ -7,6 +7,7 @@ Required Properties:
> >
> > - compatible: Should be one of:
> > - "mediatek,mt2701-audsys", "syscon"
> > + - "mediatek,mt6765-audsys", "syscon"
> > - "mediatek,mt7622-audsys", "syscon"
> > - #clock-cells: Must be 1
> >
> > diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt
> > new file mode 100644
> > index 0000000..dc75783
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt
> > @@ -0,0 +1,27 @@
> > +MediaTek CAMSYS controller
> > +============================
> > +
> > +The MediaTek CAMSYS controller provides various clocks to the system.
>
> Only clocks? If so, then this should be moved to bindings/clocks/.
>
camsys conclude not only clks but also mtcmos, so it's better to put
this node in this path.
> > +
> > +Required Properties:
> > +
> > +- compatible: Should be one of:
> > + - "mediatek,mt6765-camsys", "syscon"
> > +- #clock-cells: Must be 1
> > +
> > +The AUDSYS 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.
> > +
> > +Required sub-nodes:
> > +-------
> > +For common binding part and usage, refer to
> > +../sonud/mt2701-afe-pcm.txt.
> > +
> > +Example:
> > +
> > +camsys: camsys@1a000000 {
>
> clock-controller@...
>
> if the above answer is yes.
>
> Same comments on the other docs.
On Thu, 2018-07-19 at 14:57 +0800, Sean Wang wrote:
> On Tue, 2018-07-17 at 16:52 +0800, Mars Cheng wrote:
> > From: Owen Chen <[email protected]>
> >
> > MT6765 add "set/clr" register for each clkmux setting, and
> > one update register to trigger value change. It is designed
> > to prevent read-modify-write racing issue. The sw design
> > need to add a new API to handle this hw change with a new
> > mtk_clk_mux/mtk_clk_upd struct in new file "clk-mux"and
> > clk-upd".
> >
>
> I don't see any word mtk_clk_upd or clk-upd in the patch
>
> and the patch needs to be split into more patches
>
clk-upd is old description, no more clk-upd for handling update bit.
I will remove it next version.
> > Signed-off-by: Owen Chen <[email protected]>
> > ---
> > drivers/clk/mediatek/Makefile | 2 +-
> > drivers/clk/mediatek/clk-mtk.c | 41 +++++++
> > drivers/clk/mediatek/clk-mtk.h | 85 ++++++++++++---
> > drivers/clk/mediatek/clk-mux.c | 236 ++++++++++++++++++++++++++++++++++++++++
> > drivers/clk/mediatek/clk-mux.h | 38 +++++++
> > 5 files changed, 388 insertions(+), 14 deletions(-)
> > create mode 100644 drivers/clk/mediatek/clk-mux.c
> > create mode 100644 drivers/clk/mediatek/clk-mux.h
> >
> > diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
> > index 844b55d..b97980d 100644
> > --- a/drivers/clk/mediatek/Makefile
> > +++ b/drivers/clk/mediatek/Makefile
> > @@ -1,5 +1,5 @@
> > # SPDX-License-Identifier: GPL-2.0
> > -obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o
> > +obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o clk-mux.o
> > obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
> > obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
> > obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o
> > diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
> > index 9c0ae42..50becd0 100644
> > --- a/drivers/clk/mediatek/clk-mtk.c
> > +++ b/drivers/clk/mediatek/clk-mtk.c
> > @@ -22,6 +22,7 @@
> > #include <linux/mfd/syscon.h>
> >
> > #include "clk-mtk.h"
> > +#include "clk-mux.h"
> > #include "clk-gate.h"
> >
> > struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
> > @@ -144,6 +145,46 @@ int mtk_clk_register_gates(struct device_node *node,
> > return 0;
> > }
> >
> > +int mtk_clk_register_muxes(const struct mtk_mux *muxes,
> > + int num, struct device_node *node,
> > + spinlock_t *lock,
> > + struct clk_onecell_data *clk_data)
> > +{
> > + struct regmap *regmap;
> > + struct clk *clk;
> > + int i;
> > +
> > + if (!clk_data)
> > + return -ENOMEM;
> > +
>
> general register function is able to handle that there is no clk_data.
> It looks like a optional, not a mandatory
>
clk_data is reused in topcksys clk registration, because of the
registration include muxes/gates/dividers/fixed_clks, so we need to make
sure clk_data is not NULL pointer so we can use to store the clk
structure we allocated.
> > + regmap = syscon_node_to_regmap(node);
> > + if (IS_ERR(regmap)) {
> > + pr_err("Cannot find regmap for %pOF: %ld\n", node,
> > + PTR_ERR(regmap));
> > + return PTR_ERR(regmap);
> > + }
> > +
> > + for (i = 0; i < num; i++) {
> > + const struct mtk_mux *mux = &muxes[i];
> > +
> > + if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mux->id]))
> > + continue;
> > +
>
> it seems not necessary to check clk data every time
>
> and always use positive check is good to read
>
Yes, we will remove clk_data check at this point since not necessary.
the if condition check would alter next version.
> > + clk = mtk_clk_register_mux(mux, regmap, lock);
> > +
> > + if (IS_ERR(clk)) {
> > + pr_err("Failed to register clk %s: %ld\n",
> > + mux->name, PTR_ERR(clk));
> > + continue;
> > + }
> > +
> > + if (clk_data)
> > + clk_data->clks[mux->id] = clk;
>
> don't alter any data from input, that is a surprise for users
>
As I mentioned on previous question, clk_data need to be alterd because
of after registration done, we need to offer clk_data as input of
of_clk_add_provider(...,clk_data)
> > + }
> > +
> > + return 0;
> > +}
> > +
> > struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
> > void __iomem *base, spinlock_t *lock)
> > {
> > diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
> > index 1882221..61693f6 100644
> > --- a/drivers/clk/mediatek/clk-mtk.h
> > +++ b/drivers/clk/mediatek/clk-mtk.h
> > @@ -24,7 +24,9 @@
> >
> > #define MAX_MUX_GATE_BIT 31
> > #define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1)
> > -
> > +#define INVALID_OFS -1
> > +#define INVALID_SHFT -1
> > +#define INVALID_WIDTH -1
> > #define MHZ (1000 * 1000)
> >
> > struct mtk_fixed_clk {
> > @@ -84,10 +86,72 @@ struct mtk_composite {
> > signed char num_parents;
> > };
> >
> > +struct mtk_mux {
> > + int id;
> > + const char *name;
> > + const char * const *parent_names;
> > + unsigned int flags;
> > +
> > + u32 mux_ofs;
> > + u32 set_ofs;
> > + u32 clr_ofs;
> > + u32 upd_ofs;
> > +
> > + signed char mux_shift;
> > + signed char mux_width;
> > + signed char gate_shift;
> > + signed char upd_shift;
> > +
> > + const struct clk_ops *ops;
> > +
> > + signed char num_parents;
> > +};
> > +
>
> you have created a mtk-mux.h, why is you don't move the newly create
> struct in?
>
Okay, I would remove mtk_mux structure and only preserve mtk_clk_mux in
clk_mux.h.
> > /*
> > * In case the rate change propagation to parent clocks is undesirable,
> > * this macro allows to specify the clock flags manually.
> > */
> > +#define CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, _mux_set_ofs,\
> > + _mux_clr_ofs, _shift, _width, _gate, \
> > + _upd_ofs, _upd, _flags, _ops) { \
> > + .id = _id, \
> > + .name = _name, \
> > + .mux_ofs = _mux_ofs, \
> > + .set_ofs = _mux_set_ofs, \
> > + .clr_ofs = _mux_clr_ofs, \
> > + .upd_ofs = _upd_ofs, \
> > + .mux_shift = _shift, \
> > + .mux_width = _width, \
> > + .gate_shift = _gate, \
> > + .upd_shift = _upd, \
> > + .parent_names = _parents, \
> > + .num_parents = ARRAY_SIZE(_parents), \
> > + .flags = _flags, \
> > + .ops = &_ops, \
> > + }
> > +
> > +#define MUX_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, _mux_set_ofs,\
> > + _mux_clr_ofs, _shift, _width, _gate, \
> > + _upd_ofs, _upd, _flags) \
> > + CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
> > + _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
> > + _gate, _upd_ofs, _upd, _flags, \
> > + mtk_mux_clr_set_upd_ops)
> > +
> > +#define MUX_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, _mux_set_ofs, \
> > + _mux_clr_ofs, _shift, _width, _gate, \
> > + _upd_ofs, _upd) \
> > + MUX_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
> > + _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
> > + _gate, _upd_ofs, _upd, CLK_SET_RATE_PARENT)
> > +
> > +#define MUX_UPD(_id, _name, _parents, _mux_ofs, _shift, _width, _gate, \
> > + _upd_ofs, _upd) \
> > + CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
> > + INVALID_OFS, INVALID_OFS, _shift, _width, \
> > + _gate, _upd_ofs, _upd, CLK_SET_RATE_PARENT, \
> > + mtk_mux_upd_ops)
> > +
> > #define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \
> > _gate, _flags) { \
> > .id = _id, \
> > @@ -111,18 +175,8 @@ struct mtk_composite {
> > MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \
> > _gate, CLK_SET_RATE_PARENT)
> >
> > -#define MUX(_id, _name, _parents, _reg, _shift, _width) { \
> > - .id = _id, \
> > - .name = _name, \
> > - .mux_reg = _reg, \
> > - .mux_shift = _shift, \
> > - .mux_width = _width, \
> > - .gate_shift = -1, \
> > - .divider_shift = -1, \
> > - .parent_names = _parents, \
> > - .num_parents = ARRAY_SIZE(_parents), \
> > - .flags = CLK_SET_RATE_PARENT, \
> > - }
>
> As Matthias always said that, you alter the common thing that is already
> used by a lot of SoC.
>
> You should have a dedicate patch to state why you need it, provide the
> way you propose. and use another patches for migrating old SoC, finally
> then add the patch for your own SoC.
>
> Don't mix everything in a single patch. The patch can't become reusable
> hard to read it, even hard to backport to the other SoC picking up
> patches they are really wanting.
>
Okay, I will restore it to original version.
> > +#define MUX(_id, _name, _parents, _reg, _shift, _width) \
> > + MUX_GATE(_id, _name, _parents, _reg, _shift, _width, INVALID_SHFT)
> >
> > #define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \
> > _div_width, _div_shift) { \
> > @@ -138,6 +192,11 @@ struct mtk_composite {
> > .flags = 0, \
> > }
> >
> > +int mtk_clk_register_muxes(const struct mtk_mux *muxes,
> > + int num, struct device_node *node,
> > + spinlock_t *lock,
> > + struct clk_onecell_data *clk_data);
> > +
>
> move to mtk-mux.h
>
Again, we can observe that other(gate/divider/fixed_clk) registration
functions all gather together in clk_mtk.h, if we want to move mtk_mux
to clk_mux.h, I think we may start a new patch to move all other three
registration functions and distribute it to their own driver code such
as clk_gate.h/clk_divider.h...etc.
> > struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
> > void __iomem *base, spinlock_t *lock);
> >
> > diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c
> > new file mode 100644
> > index 0000000..219181b
> > --- /dev/null
> > +++ b/drivers/clk/mediatek/clk-mux.c
> > @@ -0,0 +1,236 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2018 MediaTek Inc.
> > + * Author: Owen Chen <[email protected]>
> > + */
> > +
> > +#include <linux/of.h>
> > +#include <linux/of_address.h>
> > +#include <linux/slab.h>
> > +
> > +#include "clk-mtk.h"
> > +#include "clk-mux.h"
> > +
> > +static inline struct mtk_clk_mux
> > + *to_mtk_clk_mux(struct clk_hw *hw)
> > +{
> > + return container_of(hw, struct mtk_clk_mux, hw);
> > +}
> > +
> > +static int mtk_mux_enable(struct clk_hw *hw)
> > +{
> > + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> > + u32 mask = BIT(mux->gate_shift);
> > + unsigned long flags = 0;
> > +
> > + if (mux->lock)
> > + spin_lock_irqsave(mux->lock, flags);
> > +
>
> we can see many functions in kernel, similar to your need, they always
> be defined as two versions. for example.
>
> mtk_mux_enable refer to lock version
>
> mtk_mux_enable_nolock for lock-free version
>
> that makes less condition, more readable, and users don't care much
> about what stuff is put inside
>
clk.c already provides spin_lock at entrance of clk_enable/clk_disalbe
API, so the lock version seems redundant here, I would remove the lock
version and keep this API lock-free as my next modification.
> > + regmap_update_bits(mux->regmap, mux->mux_ofs, mask, 0);
> > +
> > + if (mux->lock)
> > + spin_unlock_irqrestore(mux->lock, flags);
> > + return 0;
> > +}
> > +
> > +static void mtk_mux_disable(struct clk_hw *hw)
> > +{
> > + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> > + u32 mask = BIT(mux->gate_shift);
> > + unsigned long flags = 0;
> > +
> > + if (mux->lock)
> > + spin_lock_irqsave(mux->lock, flags);
> > +
>
> ditto
>
I would remove lock next modification.
> > + regmap_update_bits(mux->regmap, mux->mux_ofs, mask, mask);
> > +
> > + if (mux->lock)
> > + spin_unlock_irqrestore(mux->lock, flags);
> > +}
> > +
> > +static int mtk_mux_enable_setclr(struct clk_hw *hw)
> > +{
> > + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> > + u32 val;
> > + unsigned long flags = 0;
> > +
> > + if (mux->lock)
> > + spin_lock_irqsave(mux->lock, flags);
> > +
>
> ditto
>
I would remove lock next modification.
> > + val = BIT(mux->gate_shift);
> > + regmap_write(mux->regmap, mux->mux_clr_ofs, val);
> > +
> > + if (mux->lock)
> > + spin_unlock_irqrestore(mux->lock, flags);
> > + return 0;
> > +}
> > +
> > +static void mtk_mux_disable_setclr(struct clk_hw *hw)
> > +{
> > + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> > + u32 val;
> > + unsigned long flags = 0;
> > +
> > + if (mux->lock)
> > + spin_lock_irqsave(mux->lock, flags);
> > +
>
> ditto
>
I would remove lock next modification.
> > + val = BIT(mux->gate_shift);
> > + regmap_write(mux->regmap, mux->mux_set_ofs, val);
> > +
> > + if (mux->lock)
> > + spin_unlock_irqrestore(mux->lock, flags);
> > +}
> > +
> > +static int mtk_mux_is_enabled(struct clk_hw *hw)
> > +{
> > + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> > + u32 val = 0;
> > +
> > + if (mux->gate_shift < 0)
> > + return true;
> > +
>
> return value should be bool
>
due to the proto type of is_enabled function is defined to return
integer. I will alter the return value to 1 or 0.
> > + regmap_read(mux->regmap, mux->mux_ofs, &val);
> > +
> > + return (val & BIT(mux->gate_shift)) == 0;
> > +}
> > +
> > +static u8 mtk_mux_get_parent(struct clk_hw *hw)
> > +{
>
>
> return value should be int
Okay, I would alter it next version.
> > + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> > + int num_parents = clk_hw_get_num_parents(hw);
> > + u32 mask = GENMASK(mux->mux_width - 1, 0);
> > + u32 val;
> > +
> > + regmap_read(mux->regmap, mux->mux_ofs, &val);
> > + val = (val >> mux->mux_shift) & mask;
> > +
> > + if (val >= num_parents)
> > + return -EINVAL;
> > +
> > + return val;
> > +}
> > +
> > +static int mtk_mux_set_parent(struct clk_hw *hw, u8 index)
> > +{
> > + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> > + u32 mask = GENMASK(mux->mux_width - 1, 0);
> > + u32 val, orig;
> > + unsigned long flags = 0;
> > +
> > + if (mux->lock)
> > + spin_lock_irqsave(mux->lock, flags);
> > +
>
> use lock-free-or-not funciton
>
I would remove lock next modification.
> > + regmap_read(mux->regmap, mux->mux_ofs, &val);
> > + orig = val;
> > + val &= ~(mask << mux->mux_shift);
> > + val |= index << mux->mux_shift;
> > +
> > + if (val != orig) {
> > + regmap_write(mux->regmap, mux->mux_ofs, val);
> > +
> > + if (mux->upd_shift >= 0)
> > + regmap_write(mux->regmap, mux->upd_ofs,
> > + BIT(mux->upd_shift));
>
>
> why not use regmap_update_bits like function ?
>
Okay, I would alter it next version..
> > + }
> > +
> > + if (mux->lock)
> > + spin_unlock_irqrestore(mux->lock, flags);
> > +
> > + return 0;
> > +}
> > +
> > +static int mtk_mux_set_parent_setclr(struct clk_hw *hw, u8 index)
> > +{
> > + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
> > + u32 mask = GENMASK(mux->mux_width - 1, 0);
> > + u32 val, orig;
> > + unsigned long flags = 0;
> > +
> > + if (mux->lock)
> > + spin_lock_irqsave(mux->lock, flags);
> > +
>
> use lock-free-or-not funciton
>
I would remove lock next modification.
> > + regmap_read(mux->regmap, mux->mux_ofs, &val);
> > + orig = val;
> > + val &= ~(mask << mux->mux_shift);
> > + val |= index << mux->mux_shift;
> > +
> > + if (val != orig) {
> > + val = (mask << mux->mux_shift);
> > + regmap_write(mux->regmap, mux->mux_clr_ofs, val);
> > + val = (index << mux->mux_shift);
> > + regmap_write(mux->regmap, mux->mux_set_ofs, val);
> > +
>
> why not use regmap_update_bits like function ?
This function specified that mux use set/clr register to update, so it
would be better to use regmap_write to write the whole register instead
of regmap_update_bit.
> > + if (mux->upd_shift >= 0)
> > + regmap_write(mux->regmap, mux->upd_ofs,
> > + BIT(mux->upd_shift));
> > + }
> > +
> > + if (mux->lock)
> > + spin_unlock_irqrestore(mux->lock, flags);
> > +
> > + return 0;
> > +}
> > +
> > +const struct clk_ops mtk_mux_upd_ops = {
> > + .enable = mtk_mux_enable,
> > + .disable = mtk_mux_disable,
> > + .is_enabled = mtk_mux_is_enabled,
> > + .get_parent = mtk_mux_get_parent,
> > + .set_parent = mtk_mux_set_parent,
> > + .determine_rate = NULL,
>
> explicitly set as NULL can be removed
Okay, I would remove it next version.
> > +};
> > +
> > +const struct clk_ops mtk_mux_clr_set_upd_ops = {
> > + .enable = mtk_mux_enable_setclr,
> > + .disable = mtk_mux_disable_setclr,
> > + .is_enabled = mtk_mux_is_enabled,
> > + .get_parent = mtk_mux_get_parent,
> > + .set_parent = mtk_mux_set_parent_setclr,
> > + .determine_rate = NULL,
>
> explicitly set as NULL can be removed
Okay, I would remove it next version.
> > +};
> > +
> > +struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
> > + struct regmap *regmap,
> > + spinlock_t *lock)
> > +{
> > + struct clk *clk;
> > + struct clk_init_data init;
> > + struct mtk_clk_mux *mtk_mux = NULL;
> > + int ret;
> > +
> make declaration as reverse xmas tree
>
Okay, I would alter it next version.
> > + mtk_mux = kzalloc(sizeof(*mtk_mux), GFP_KERNEL);
> > + if (!mtk_mux)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + init.name = mux->name;
> > + init.flags = (mux->flags) | CLK_SET_RATE_PARENT;
> > + init.parent_names = mux->parent_names;
> > + init.num_parents = mux->num_parents;
> > + init.ops = mux->ops;
> > +
> > + mtk_mux->regmap = regmap;
> > + mtk_mux->name = mux->name;
> > + mtk_mux->mux_ofs = mux->mux_ofs;
> > + mtk_mux->mux_set_ofs = mux->set_ofs;
> > + mtk_mux->mux_clr_ofs = mux->clr_ofs;
> > + mtk_mux->upd_ofs = mux->upd_ofs;
> > + mtk_mux->mux_shift = mux->mux_shift;
> > + mtk_mux->mux_width = mux->mux_width;
> > + mtk_mux->gate_shift = mux->gate_shift;
> > + mtk_mux->upd_shift = mux->upd_shift;
> > +
> > + mtk_mux->lock = lock;
> > + mtk_mux->hw.init = &init;
> > +
> > + clk = clk_register(NULL, &mtk_mux->hw);
> > + if (IS_ERR(clk)) {
> > + ret = PTR_ERR(clk);
>
>
> ret is superfluous
>
Okay, I would remove it next version.
> > + goto err_out;
> > + }
> > +
> > + return clk;
> > +err_out:
> > + kfree(mtk_mux);
> > +
>
> I felt err path can be optimized
>
Okay, I would remove it next version.
> > + return ERR_PTR(ret);
> > +}
> > diff --git a/drivers/clk/mediatek/clk-mux.h b/drivers/clk/mediatek/clk-mux.h
> > new file mode 100644
> > index 0000000..64f8e7c
> > --- /dev/null
> > +++ b/drivers/clk/mediatek/clk-mux.h
> > @@ -0,0 +1,38 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (c) 2018 MediaTek Inc.
> > + * Author: Owen Chen <[email protected]>
> > + */
> > +
> > +#ifndef __DRV_CLK_MUX_H
> > +#define __DRV_CLK_MUX_H
> > +
> > +#include <linux/clk-provider.h>
> > +
> > +struct mtk_clk_mux {
> > + struct clk_hw hw;
> > + struct regmap *regmap;
> > +
> > + const char *name;
> > +
> > + int mux_set_ofs;
> > + int mux_clr_ofs;
> > + int mux_ofs;
> > + int upd_ofs;
> > +
> > + s8 mux_shift;
> > + s8 mux_width;
> > + s8 gate_shift;
> > + s8 upd_shift;
> > +
> > + spinlock_t *lock;
> > +};
> > +
> > +extern const struct clk_ops mtk_mux_upd_ops;
> > +extern const struct clk_ops mtk_mux_clr_set_upd_ops;
> > +
>
>
> extern is superfluous
>
Okay, I would remove it next version.
> > +struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
> > + struct regmap *regmap,
> > + spinlock_t *lock);
> > +
> > +#endif /* __DRV_CLK_MUX_H */
>
>