* [PATCH v4 1/8] dt-bindings: clock: Add MT8192 APU clock bindings
2021-12-10 17:01 [PATCH v4 0/8] Add Support for MediaTek MT8192 APU Power Domain Flora Fu
@ 2021-12-10 17:01 ` Flora Fu
2021-12-10 17:01 ` [PATCH v4 2/8] clk: mediatek: mt8192: Add APU clocks support Flora Fu
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Flora Fu @ 2021-12-10 17:01 UTC (permalink / raw)
To: Matthias Brugger, Liam Girdwood, Mark Brown
Cc: linux-kernel, linux-arm-kernel, linux-mediatek, Flora Fu,
Yong Wu, JB Tsai, Pi-Cheng Chen, Chun-Jie Chen
Add clock bindings for APU on MT8192.
Signed-off-by: Flora Fu <flora.fu@mediatek.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Stephen Boyd <sboyd@kernel.org>
---
include/dt-bindings/clock/mt8192-clk.h | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/include/dt-bindings/clock/mt8192-clk.h b/include/dt-bindings/clock/mt8192-clk.h
index 5ab68f15a256..d5ac7b6c1d5c 100644
--- a/include/dt-bindings/clock/mt8192-clk.h
+++ b/include/dt-bindings/clock/mt8192-clk.h
@@ -164,7 +164,15 @@
#define CLK_TOP_APLL12_DIV9 152
#define CLK_TOP_SSUSB_TOP_REF 153
#define CLK_TOP_SSUSB_PHY_REF 154
-#define CLK_TOP_NR_CLK 155
+#define CLK_TOP_DSP_SEL 155
+#define CLK_TOP_DSP1_SEL 156
+#define CLK_TOP_DSP1_NPUPLL_SEL 157
+#define CLK_TOP_DSP2_SEL 158
+#define CLK_TOP_DSP2_NPUPLL_SEL 159
+#define CLK_TOP_DSP5_SEL 160
+#define CLK_TOP_DSP5_APUPLL_SEL 161
+#define CLK_TOP_IPU_IF_SEL 162
+#define CLK_TOP_NR_CLK 163
/* INFRACFG */
@@ -309,7 +317,9 @@
#define CLK_APMIXED_APLL1 8
#define CLK_APMIXED_APLL2 9
#define CLK_APMIXED_MIPID26M 10
-#define CLK_APMIXED_NR_CLK 11
+#define CLK_APMIXED_APUPLL 11
+#define CLK_APMIXED_NPUPLL 12
+#define CLK_APMIXED_NR_CLK 13
/* SCP_ADSP */
--
2.18.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v4 2/8] clk: mediatek: mt8192: Add APU clocks support
2021-12-10 17:01 [PATCH v4 0/8] Add Support for MediaTek MT8192 APU Power Domain Flora Fu
2021-12-10 17:01 ` [PATCH v4 1/8] dt-bindings: clock: Add MT8192 APU clock bindings Flora Fu
@ 2021-12-10 17:01 ` Flora Fu
2021-12-10 17:01 ` [PATCH v4 3/8] dt-bindings: arm: mediatek: Add new document bindings for APU Flora Fu
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Flora Fu @ 2021-12-10 17:01 UTC (permalink / raw)
To: Matthias Brugger, Liam Girdwood, Mark Brown
Cc: linux-kernel, linux-arm-kernel, linux-mediatek, Flora Fu,
Yong Wu, JB Tsai, Pi-Cheng Chen, Chun-Jie Chen
Add APU clocks support on MT8192.
Signed-off-by: Flora Fu <flora.fu@mediatek.com>
Acked-by: Stephen Boyd <sboyd@kernel.org>
---
drivers/clk/mediatek/clk-mt8192.c | 91 +++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)
diff --git a/drivers/clk/mediatek/clk-mt8192.c b/drivers/clk/mediatek/clk-mt8192.c
index cbc7c6dbe0f4..8bc4e85780c6 100644
--- a/drivers/clk/mediatek/clk-mt8192.c
+++ b/drivers/clk/mediatek/clk-mt8192.c
@@ -244,6 +244,65 @@ static const char * const ccu_parents[] = {
"univpll_d6_d2"
};
+static const char * const dsp_parents[] = {
+ "clk26m",
+ "univpll_d6_d2",
+ "univpll_d4_d2",
+ "univpll_d5",
+ "univpll_d4",
+ "mmpll_d4",
+ "mainpll_d3",
+ "univpll_d3"
+};
+
+static const char * const dsp1_parents[] = {
+ "clk26m",
+ "npupll_ck",
+ "mainpll_d4_d2",
+ "univpll_d5",
+ "univpll_d4",
+ "mainpll_d3",
+ "univpll_d3",
+ "apupll_ck"
+};
+
+static const char * const dsp1_npupll_parents[] = {
+ "dsp1_sel",
+ "npupll_ck"
+};
+
+static const char * const dsp2_parents[] = {
+ "clk26m",
+ "npupll_ck",
+ "mainpll_d4_d2",
+ "univpll_d5",
+ "univpll_d4",
+ "mainpll_d3",
+ "univpll_d3",
+ "apupll_ck"
+};
+
+static const char * const dsp2_npupll_parents[] = {
+ "dsp2_sel",
+ "npupll_ck"
+};
+
+static const char * const dsp5_parents[] = {
+ "clk26m",
+ "apupll_ck",
+ "univpll_d4_d2",
+ "mainpll_d4",
+ "univpll_d4",
+ "mmpll_d4",
+ "mainpll_d3",
+ "univpll_d3"
+};
+
+static const char * const dsp5_apupll_parents[] = {
+ "dsp5_sel",
+ "apupll_ck"
+};
+
static const char * const dsp7_parents[] = {
"clk26m",
"mainpll_d4_d2",
@@ -255,6 +314,17 @@ static const char * const dsp7_parents[] = {
"mmpll_d4"
};
+static const char * const ipu_if_parents[] = {
+ "clk26m",
+ "univpll_d6_d2",
+ "mainpll_d4_d2",
+ "univpll_d4_d2",
+ "univpll_d5",
+ "mainpll_d4",
+ "tvdpll_ck",
+ "univpll_d4"
+};
+
static const char * const mfg_ref_parents[] = {
"clk26m",
"clk26m",
@@ -734,9 +804,26 @@ static const struct mtk_mux top_mtk_muxes[] = {
cam_parents, 0x030, 0x034, 0x038, 16, 4, 23, 0x004, 10),
MUX_GATE_CLR_SET_UPD(CLK_TOP_CCU_SEL, "ccu_sel",
ccu_parents, 0x030, 0x034, 0x038, 24, 4, 31, 0x004, 11),
+ /* CLK_CFG_3 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP_SEL, "dsp_sel",
+ dsp_parents, 0x040, 0x044, 0x048, 0, 3, 7, 0x004, 12),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP1_SEL, "dsp1_sel",
+ dsp1_parents, 0x040, 0x044, 0x048, 8, 3, 15, 0x004, 13),
+ MUX_CLR_SET_UPD(CLK_TOP_DSP1_NPUPLL_SEL, "dsp1_npupll_sel",
+ dsp1_npupll_parents, 0x040, 0x044, 0x048, 11, 1, -1, -1),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP2_SEL, "dsp2_sel",
+ dsp2_parents, 0x040, 0x044, 0x048, 16, 3, 23, 0x004, 14),
+ MUX_CLR_SET_UPD(CLK_TOP_DSP2_NPUPLL_SEL, "dsp2_npupll_sel",
+ dsp2_npupll_parents, 0x040, 0x044, 0x048, 19, 1, -1, -1),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP5_SEL, "dsp5_sel",
+ dsp5_parents, 0x040, 0x044, 0x048, 24, 3, 31, 0x004, 15),
+ MUX_CLR_SET_UPD(CLK_TOP_DSP5_APUPLL_SEL, "dsp5_apupll_sel",
+ dsp5_apupll_parents, 0x040, 0x044, 0x048, 27, 1, -1, -1),
/* CLK_CFG_4 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP7_SEL, "dsp7_sel",
dsp7_parents, 0x050, 0x054, 0x058, 0, 3, 7, 0x004, 16),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_IPU_IF_SEL, "ipu_if_sel",
+ ipu_if_parents, 0x050, 0x054, 0x058, 8, 3, 15, 0x004, 17),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG_REF_SEL, "mfg_ref_sel",
mfg_ref_parents, 0x050, 0x054, 0x058, 16, 2, 23, 0x004, 18),
MUX_CLR_SET_UPD(CLK_TOP_MFG_PLL_SEL, "mfg_pll_sel",
@@ -1175,6 +1262,10 @@ static const struct mtk_pll_data plls[] = {
0, 0, 32, 0x031c, 24, 0x0040, 0x000c, 0, 0x0320, 0),
PLL_B(CLK_APMIXED_APLL2, "apll2", 0x032c, 0x033c, 0x00000000,
0, 0, 32, 0x0330, 24, 0, 0, 0, 0x0334, 0),
+ PLL_B(CLK_APMIXED_APUPLL, "apupll", 0x03a0, 0x03ac, 0xff000001,
+ HAVE_RST_BAR, BIT(23), 22, 0x03a4, 24, 0, 0, 0, 0x03a4, 0),
+ PLL_B(CLK_APMIXED_NPUPLL, "npupll", 0x03b4, 0x03c0, 0x00000001,
+ 0, 0, 22, 0x03b8, 24, 0, 0, 0, 0x03b8, 0),
};
static struct clk_onecell_data *top_clk_data;
--
2.18.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v4 3/8] dt-bindings: arm: mediatek: Add new document bindings for APU
2021-12-10 17:01 [PATCH v4 0/8] Add Support for MediaTek MT8192 APU Power Domain Flora Fu
2021-12-10 17:01 ` [PATCH v4 1/8] dt-bindings: clock: Add MT8192 APU clock bindings Flora Fu
2021-12-10 17:01 ` [PATCH v4 2/8] clk: mediatek: mt8192: Add APU clocks support Flora Fu
@ 2021-12-10 17:01 ` Flora Fu
2021-12-10 17:01 ` [PATCH v4 4/8] dt-bindings: soc: mediatek: apusys: Add new document for APU power domain Flora Fu
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Flora Fu @ 2021-12-10 17:01 UTC (permalink / raw)
To: Matthias Brugger, Liam Girdwood, Mark Brown
Cc: linux-kernel, linux-arm-kernel, linux-mediatek, Flora Fu,
Yong Wu, JB Tsai, Pi-Cheng Chen, Chun-Jie Chen
Document the apusys bindings.
Signed-off-by: Flora Fu <flora.fu@mediatek.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
.../arm/mediatek/mediatek,apusys.yaml | 50 +++++++++++++++++++
1 file changed, 50 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,apusys.yaml
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apusys.yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apusys.yaml
new file mode 100644
index 000000000000..7643c66dfaa2
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apusys.yaml
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright (C) 2021 MediaTek Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/mediatek/mediatek,apusys.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek APUSYS Controller
+
+maintainers:
+ - Flora Fu <flora.fu@mediatek.com>
+
+description:
+ The MediaTek apusys controller provides functional configurations and clocks
+ to the system.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - mediatek,mt8192-apu-conn
+ - mediatek,mt8192-apu-vcore
+ - const: syscon
+
+ reg:
+ maxItems: 1
+
+ '#clock-cells':
+ const: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ apu_conn: apu_conn@19020000 {
+ compatible = "mediatek,mt8192-apu-conn", "syscon";
+ reg = <0x19020000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ apu_vcore: apu_vcore@19029000 {
+ compatible = "mediatek,mt8192-apu-vcore", "syscon";
+ reg = <0x19029000 0x1000>;
+ #clock-cells = <1>;
+ };
--
2.18.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v4 4/8] dt-bindings: soc: mediatek: apusys: Add new document for APU power domain
2021-12-10 17:01 [PATCH v4 0/8] Add Support for MediaTek MT8192 APU Power Domain Flora Fu
` (2 preceding siblings ...)
2021-12-10 17:01 ` [PATCH v4 3/8] dt-bindings: arm: mediatek: Add new document bindings for APU Flora Fu
@ 2021-12-10 17:01 ` Flora Fu
2021-12-10 17:01 ` [PATCH v4 5/8] soc: mediatek: apu: Add apusys and add apu power domain driver Flora Fu
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Flora Fu @ 2021-12-10 17:01 UTC (permalink / raw)
To: Matthias Brugger, Liam Girdwood, Mark Brown
Cc: linux-kernel, linux-arm-kernel, linux-mediatek, Flora Fu,
Yong Wu, JB Tsai, Pi-Cheng Chen, Chun-Jie Chen
Document the bindings for APU power domain on MediaTek SoC.
Signed-off-by: Flora Fu <flora.fu@mediatek.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
.../soc/mediatek/mediatek,apu-pm.yaml | 144 ++++++++++++++++++
1 file changed, 144 insertions(+)
create mode 100644 Documentation/devicetree/bindings/soc/mediatek/mediatek,apu-pm.yaml
diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,apu-pm.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,apu-pm.yaml
new file mode 100644
index 000000000000..e1b7d4030dc9
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,apu-pm.yaml
@@ -0,0 +1,144 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2021 (C) MediaTek Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/mediatek/mediatek,apu-pm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek APU Power Domains
+
+maintainers:
+ - Flora Fu <flora.fu@mediatek.com>
+
+description: |
+ MediaTek AI Process Unit (APU) include support for power domains which can be
+ powered up/down by software.
+ APU subsys belonging to a power domain should contain a 'power-domains'
+ property that is a phandle for apuspm node representing the domain.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - mediatek,mt8192-apu-pm
+ - const: syscon
+
+ reg:
+ description: Address range of the APU power domain controller.
+ maxItems: 1
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ '#power-domain-cells':
+ const: 1
+
+ vsram-supply:
+ description: apu sram regulator supply.
+
+ mediatek,scpsys:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: |
+ phandle to the device containing the scpsys register range.
+
+ mediatek,apu-conn:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: |
+ phandle to the device containing the scpsys apu conn register range.
+
+ mediatek,apu-conn1:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: |
+ phandle to the device containing the scpsys apu conn1 register range.
+
+ mediatek,apu-vcore:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: |
+ phandle to the device containing the scpsys apu vcore register range.
+
+patternProperties:
+ "^power-domain@[0-9a-f]+$":
+ type: object
+ description: |
+ Represents the power domains within the power controller node as
+ documented in Documentation/devicetree/bindings/power/power-domain.yaml.
+
+ properties:
+ reg:
+ description: Power domain index.
+ maxItems: 1
+
+ '#power-domain-cells':
+ description: |
+ Must be 0 for nodes representing a single PM domain and 1 for nodes
+ providing multiple PM.
+
+ clocks:
+ description: |
+ List of phandles of clocks list. Specify by order according to
+ power-up sequence.
+
+ clock-names:
+ description: |
+ List of names of clocks. Specify by order according to power-up
+ sequence.
+
+ assigned-clocks:
+ maxItems: 2
+
+ assigned-clock-parents:
+ maxItems: 2
+
+ domain-supply:
+ description: domain regulator supply.
+
+ required:
+ - reg
+ - '#power-domain-cells'
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - '#power-domain-cells'
+ - vsram-supply
+ - mediatek,scpsys
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/mt8192-clk.h>
+ apuspm: power-domain@190f0000 {
+ compatible = "mediatek,mt8192-apu-pm", "syscon";
+ reg = <0x190f0000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+ vsram-supply = <&mt6359_vsram_md_ldo_reg>;
+ mediatek,scpsys = <&scpsys>;
+ mediatek,apu-conn = <&apu_conn>;
+ mediatek,apu-vcore = <&apu_vcore>;
+
+ apu_top: power-domain@0 {
+ reg = <0>;
+ #power-domain-cells = <0>;
+ clocks = <&topckgen CLK_TOP_DSP_SEL>,
+ <&topckgen CLK_TOP_IPU_IF_SEL>,
+ <&clk26m>,
+ <&topckgen CLK_TOP_UNIVPLL_D6_D2>;
+ clock-names = "clk_top_conn",
+ "clk_top_ipu_if",
+ "clk_off",
+ "clk_on_default";
+ assigned-clocks = <&topckgen CLK_TOP_DSP_SEL>,
+ <&topckgen CLK_TOP_IPU_IF_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D6_D2>,
+ <&topckgen CLK_TOP_UNIVPLL_D6_D2>;
+ domain-supply = <&mt6359_vproc1_buck_reg>;
+ };
+ };
--
2.18.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v4 5/8] soc: mediatek: apu: Add apusys and add apu power domain driver
2021-12-10 17:01 [PATCH v4 0/8] Add Support for MediaTek MT8192 APU Power Domain Flora Fu
` (3 preceding siblings ...)
2021-12-10 17:01 ` [PATCH v4 4/8] dt-bindings: soc: mediatek: apusys: Add new document for APU power domain Flora Fu
@ 2021-12-10 17:01 ` Flora Fu
2021-12-10 17:01 ` [PATCH v4 6/8] arm64: dts: mt8192: Add APU node Flora Fu
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Flora Fu @ 2021-12-10 17:01 UTC (permalink / raw)
To: Matthias Brugger, Liam Girdwood, Mark Brown
Cc: linux-kernel, linux-arm-kernel, linux-mediatek, Flora Fu,
Yong Wu, JB Tsai, Pi-Cheng Chen, Chun-Jie Chen
Add the apusys in soc.
Add driver for apu power domains.
APU power domain shall be enabled before accessing the
internal sub modules.
Signed-off-by: Flora Fu <flora.fu@mediatek.com>
---
drivers/soc/mediatek/Kconfig | 12 +
drivers/soc/mediatek/Makefile | 1 +
drivers/soc/mediatek/apusys/Kconfig | 14 +
drivers/soc/mediatek/apusys/Makefile | 2 +
drivers/soc/mediatek/apusys/mtk-apu-pm.c | 727 +++++++++++++++++++++++
5 files changed, 756 insertions(+)
create mode 100644 drivers/soc/mediatek/apusys/Kconfig
create mode 100644 drivers/soc/mediatek/apusys/Makefile
create mode 100644 drivers/soc/mediatek/apusys/mtk-apu-pm.c
diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index fdd8bc08569e..47f003ba2e28 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -5,6 +5,18 @@
menu "MediaTek SoC drivers"
depends on ARCH_MEDIATEK || COMPILE_TEST
+config MTK_APUSYS
+ bool "MediaTek APUSYS Support"
+ select REGMAP
+ help
+ Say yes here to add support for the MediaTek AI Processing Unit
+ Subsystem (APUSYS).
+ The APUSYS is a proprietary hardware in SoC to support AI
+ operations. The drivers can be enabled individually within this menu.
+ If unsure, say N.
+
+source "drivers/soc/mediatek/apusys/Kconfig"
+
config MTK_CMDQ
tristate "MediaTek CMDQ Support"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index 90270f8114ed..e46e7a3c21e7 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_MTK_APUSYS) += apusys/
obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
obj-$(CONFIG_MTK_DEVAPC) += mtk-devapc.o
obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
diff --git a/drivers/soc/mediatek/apusys/Kconfig b/drivers/soc/mediatek/apusys/Kconfig
new file mode 100644
index 000000000000..332e323e02ae
--- /dev/null
+++ b/drivers/soc/mediatek/apusys/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only
+if MTK_APUSYS
+
+config MTK_APU_PM
+ tristate "MediaTek APU power management support"
+ select REGMAP
+ select PM_GENERIC_DOMAINS if PM
+ help
+ Say yes here to add support for power management control
+ to MediaTek AI Processing Unit Subsystem (APUSYS).
+ APU power domain shall be enabled before accessing the
+ internal sub modules.
+
+endif # MTK_APUSYS
diff --git a/drivers/soc/mediatek/apusys/Makefile b/drivers/soc/mediatek/apusys/Makefile
new file mode 100644
index 000000000000..8821c0f0b7b7
--- /dev/null
+++ b/drivers/soc/mediatek/apusys/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_MTK_APU_PM) += mtk-apu-pm.o
diff --git a/drivers/soc/mediatek/apusys/mtk-apu-pm.c b/drivers/soc/mediatek/apusys/mtk-apu-pm.c
new file mode 100644
index 000000000000..10dd30052c46
--- /dev/null
+++ b/drivers/soc/mediatek/apusys/mtk-apu-pm.c
@@ -0,0 +1,727 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_clk.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#define APU_PD_IPUIF_HW_CG BIT(0)
+#define APU_PD_RPC_AUTO_BUCK BIT(1)
+#define APU_PD_CAPS(_pd, _x) ((_pd)->data->caps & (_x))
+
+#define MTK_POLL_DELAY_US 10
+#define MTK_POLL_TIMEOUT USEC_PER_SEC
+
+/* rpc_top_con*/
+#define SLEEP_REQ BIT(0)
+#define APU_BUCK_ELS_EN BIT(3)
+
+/*conn_clr, conn1_clr, vcore_clr */
+#define CG_CLR (0xFFFFFFFF)
+
+/* mt8192 rpc_sw_type (0..7) */
+#define MT8192_RPC_SW_TYPE(x) (0x200 + ((x) * 0x10))
+
+/* rpc_sw_type*/
+static const struct reg_sequence mt8192_rpc_sw_type[] = {
+ { MT8192_RPC_SW_TYPE(0), 0xFF },
+ { MT8192_RPC_SW_TYPE(2), 0x7 },
+ { MT8192_RPC_SW_TYPE(3), 0x7 },
+ { MT8192_RPC_SW_TYPE(6), 0x3 },
+};
+
+struct apu_top_domain {
+ u32 spm_ext_buck_iso;
+ u32 spm_ext_buck_iso_mask;
+ u32 spm_cross_wake_m01;
+ u32 wake_apu;
+ u32 spm_other_pwr;
+ u32 pwr_status;
+ u32 conn_clr;
+ u32 conn1_clr;
+ u32 vcore_clr;
+ u32 rpc_top_con;
+ u32 rpc_top_con_init_mask;
+ u32 rpc_top_sel;
+ u32 rpc_top_intf_pwr_rdy;
+ u32 pwr_rdy;
+ const struct reg_sequence *rpc_sw_type;
+ int num_rpc_sw;
+};
+
+static struct apu_top_domain mt8192_top_reg = {
+ .spm_ext_buck_iso = 0x39C,
+ .spm_ext_buck_iso_mask = 0x21,
+ .spm_cross_wake_m01 = 0x670,
+ .wake_apu = BIT(0),
+ .spm_other_pwr = 0x178,
+ .pwr_status = BIT(5),
+ .conn_clr = 0x8,
+ .vcore_clr = 0x8,
+ .rpc_top_con = 0x0,
+ .rpc_top_con_init_mask = 0x49E,
+ .rpc_top_sel = 0x4,
+ .rpc_top_intf_pwr_rdy = 0x44,
+ .pwr_rdy = BIT(0),
+ .rpc_sw_type = mt8192_rpc_sw_type,
+ .num_rpc_sw = ARRAY_SIZE(mt8192_rpc_sw_type),
+};
+
+struct apusys {
+ struct device *dev;
+ struct regmap *scpsys;
+ struct regmap *conn;
+ struct regmap *conn1;
+ struct regmap *vcore;
+ struct regmap *rpc;
+ struct regulator *vsram_supply;
+ const struct apu_pm_data *data;
+ struct genpd_onecell_data pd_data;
+ struct generic_pm_domain *domains[];
+};
+
+struct apu_domain {
+ struct generic_pm_domain genpd;
+ const struct apu_domain_data *data;
+ struct apusys *apusys;
+ struct regulator *domain_supply;
+ int num_clks;
+ struct clk_bulk_data *clks;
+ struct clk *clk_top_conn;
+ struct clk *clk_top_ipu_if;
+ struct clk *clk_off;
+ struct clk *clk_on_def;
+};
+
+struct apu_domain_data {
+ int domain_idx;
+ char *name;
+ struct apu_top_domain *topd;
+ u8 caps;
+};
+
+struct apu_pm_data {
+ const struct apu_domain_data *domains_data;
+ int num_domains;
+};
+
+#define to_apu_domain(gpd) container_of(gpd, struct apu_domain, genpd)
+
+static int apu_top_init_hw(struct apu_domain *pd)
+{
+ struct apusys *apusys = pd->apusys;
+ int ret;
+
+ if (APU_PD_CAPS(pd, APU_PD_IPUIF_HW_CG)) {
+ ret = clk_prepare_enable(pd->clk_top_conn);
+ if (ret) {
+ dev_err(apusys->dev, "Failed enable top_conn clk\n");
+ return ret;
+ }
+
+ ret = clk_set_parent(pd->clk_top_ipu_if, pd->clk_on_def);
+ if (ret) {
+ dev_err(apusys->dev, "Failed set ipu_if mux\n");
+ goto err_clk;
+ }
+
+ /* The ipu_if clock is gating by HW. Only enable once. */
+ if (!__clk_is_enabled(pd->clk_top_ipu_if)) {
+ ret = clk_prepare_enable(pd->clk_top_ipu_if);
+ if (ret) {
+ dev_err(apusys->dev, "Failed enable ipu_if\n");
+ goto err_clk;
+ }
+ }
+ } else {
+ ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks);
+ if (ret)
+ goto err_clk;
+ }
+
+ /*
+ * set memory type to PD or sleep group
+ * sw_type register for each memory group, set to PD mode default
+ */
+ if (pd->data->topd->num_rpc_sw) {
+ ret = regmap_register_patch(apusys->rpc,
+ pd->data->topd->rpc_sw_type,
+ pd->data->topd->num_rpc_sw);
+ if (ret) {
+ dev_err(apusys->dev, "Failed to rpc patch: %d\n", ret);
+ goto err_clk;
+ }
+ }
+
+ /* mask RPC IRQ and bypass WFI */
+ ret = regmap_set_bits(apusys->rpc, pd->data->topd->rpc_top_sel,
+ pd->data->topd->rpc_top_con_init_mask);
+ if (ret)
+ goto err_clk;
+
+ if (APU_PD_CAPS(pd, APU_PD_RPC_AUTO_BUCK)) {
+ ret = regmap_set_bits(apusys->rpc,
+ pd->data->topd->rpc_top_con,
+ APU_BUCK_ELS_EN);
+ if (ret)
+ goto err_clk;
+ }
+
+ if (APU_PD_CAPS(pd, APU_PD_IPUIF_HW_CG)) {
+ clk_disable_unprepare(pd->clk_top_conn);
+ ret = clk_set_parent(pd->clk_top_ipu_if, pd->clk_off);
+ if (ret) {
+ dev_err(apusys->dev, "Failed set ipu_if rate\n");
+ goto err_clk;
+ }
+ } else {
+ clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
+ }
+
+ return 0;
+
+err_clk:
+ if (APU_PD_CAPS(pd, APU_PD_IPUIF_HW_CG)) {
+ clk_disable_unprepare(pd->clk_top_conn);
+ clk_disable_unprepare(pd->clk_top_ipu_if);
+ } else {
+ clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
+ }
+
+ return ret;
+}
+
+static const struct apu_domain_data apu_domain_data_mt8192[] = {
+ {
+ .domain_idx = 0,
+ .name = "apu-top",
+ .caps = APU_PD_IPUIF_HW_CG,
+ .topd = &mt8192_top_reg,
+ }
+};
+
+static const struct apu_pm_data mt8192_apu_pm_data = {
+ .domains_data = apu_domain_data_mt8192,
+ .num_domains = ARRAY_SIZE(apu_domain_data_mt8192),
+};
+
+static int apu_top_power_on(struct generic_pm_domain *genpd)
+{
+ struct apu_domain *pd = to_apu_domain(genpd);
+ struct apusys *apusys = pd->apusys;
+ int ret, tmp;
+
+ if (apusys->vsram_supply) {
+ ret = regulator_enable(apusys->vsram_supply);
+ if (ret)
+ return ret;
+ }
+
+ if (pd->domain_supply) {
+ ret = regulator_enable(pd->domain_supply);
+ if (ret)
+ goto err_regulator;
+ }
+
+ ret = regmap_clear_bits(apusys->scpsys,
+ pd->data->topd->spm_ext_buck_iso,
+ pd->data->topd->spm_ext_buck_iso_mask);
+ if (ret)
+ goto err_regulator;
+
+ ret = regmap_set_bits(apusys->rpc, pd->data->topd->rpc_top_sel,
+ pd->data->topd->rpc_top_con_init_mask);
+ if (ret)
+ goto err_regulator;
+
+ if (APU_PD_CAPS(pd, APU_PD_IPUIF_HW_CG)) {
+ ret = clk_prepare_enable(pd->clk_top_conn);
+ if (ret) {
+ dev_err(apusys->dev, "Failed enable top_conn clk\n");
+ goto err_clk;
+ }
+
+ ret = clk_set_parent(pd->clk_top_ipu_if, pd->clk_on_def);
+ if (ret) {
+ dev_err(apusys->dev, "Failed set ipu_if mux\n");
+ goto err_clk;
+ }
+
+ if (!__clk_is_enabled(pd->clk_top_ipu_if)) {
+ ret = clk_prepare_enable(pd->clk_top_ipu_if);
+ if (ret) {
+ dev_err(apusys->dev, "Failed enable ipu_if\n");
+ goto err_clk;
+ }
+ }
+ } else {
+ ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks);
+ if (ret)
+ goto err_clk;
+ }
+
+ ret = regmap_set_bits(apusys->scpsys,
+ pd->data->topd->spm_cross_wake_m01,
+ pd->data->topd->wake_apu);
+ if (ret)
+ goto err_clk;
+
+ ret = regmap_read_poll_timeout(apusys->scpsys,
+ pd->data->topd->spm_other_pwr,
+ tmp,
+ (tmp & pd->data->topd->pwr_status) ==
+ pd->data->topd->pwr_status,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ if (ret) {
+ dev_err(apusys->dev, "apu top on wait SPM PWR_ACK != 0\n");
+ goto err_clk;
+ }
+
+ ret = regmap_read_poll_timeout(apusys->rpc,
+ pd->data->topd->rpc_top_intf_pwr_rdy,
+ tmp, (tmp & pd->data->topd->pwr_rdy) ==
+ pd->data->topd->pwr_rdy,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ if (ret) {
+ dev_err(apusys->dev, "apu top on wait RPC PWR_RDY != 0\n");
+ goto err_clk;
+ }
+
+ if (apusys->vcore) {
+ ret = regmap_write(apusys->vcore,
+ pd->data->topd->vcore_clr, CG_CLR);
+ if (ret)
+ goto err_clk;
+ }
+
+ if (apusys->conn) {
+ ret = regmap_write(apusys->conn,
+ pd->data->topd->conn_clr, CG_CLR);
+ if (ret)
+ goto err_clk;
+ }
+
+ if (apusys->conn1) {
+ ret = regmap_write(apusys->conn1,
+ pd->data->topd->conn1_clr, CG_CLR);
+ if (ret)
+ goto err_clk;
+ }
+
+ return 0;
+
+err_clk:
+ if (APU_PD_CAPS(pd, APU_PD_IPUIF_HW_CG)) {
+ clk_disable_unprepare(pd->clk_top_conn);
+ clk_disable_unprepare(pd->clk_top_ipu_if);
+ } else {
+ clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
+ }
+ if (pd->domain_supply)
+ ret = regulator_disable(pd->domain_supply);
+err_regulator:
+ if (apusys->vsram_supply)
+ ret = regulator_disable(apusys->vsram_supply);
+
+ return ret;
+}
+
+static int apu_top_power_off(struct generic_pm_domain *genpd)
+{
+ struct apu_domain *pd = to_apu_domain(genpd);
+ struct apusys *apusys = pd->apusys;
+ int ret, tmp;
+
+ if (apusys->vcore) {
+ ret = regmap_write(apusys->vcore,
+ pd->data->topd->vcore_clr, CG_CLR);
+ if (ret)
+ return ret;
+ }
+
+ if (apusys->conn) {
+ ret = regmap_write(apusys->conn,
+ pd->data->topd->conn_clr, CG_CLR);
+ if (ret)
+ return ret;
+ }
+
+ if (apusys->conn1) {
+ ret = regmap_write(apusys->conn1,
+ pd->data->topd->conn1_clr, CG_CLR);
+ if (ret)
+ return ret;
+ }
+
+ ret = regmap_clear_bits(apusys->scpsys,
+ pd->data->topd->spm_cross_wake_m01,
+ pd->data->topd->wake_apu);
+ if (ret)
+ return ret;
+
+ ret = regmap_set_bits(apusys->rpc,
+ pd->data->topd->rpc_top_con, SLEEP_REQ);
+ if (ret)
+ return ret;
+
+ ret = regmap_read_poll_timeout(apusys->rpc,
+ pd->data->topd->rpc_top_intf_pwr_rdy,
+ tmp,
+ (tmp & pd->data->topd->pwr_rdy) == 0x0,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ if (ret) {
+ dev_err(apusys->dev, "apu top off wait RPC PWR_RDY != 0\n");
+ return ret;
+ }
+
+ ret = regmap_read_poll_timeout(apusys->scpsys,
+ pd->data->topd->spm_other_pwr, tmp,
+ (tmp & pd->data->topd->pwr_status) == 0x0,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ if (ret) {
+ dev_err(apusys->dev, "apu top off wait SPM PWR_ACK != 0\n");
+ return ret;
+ }
+
+ if (APU_PD_CAPS(pd, APU_PD_IPUIF_HW_CG)) {
+ clk_disable_unprepare(pd->clk_top_conn);
+ ret = clk_set_parent(pd->clk_top_ipu_if, pd->clk_off);
+ if (ret) {
+ dev_err(apusys->dev, "Failed set ipu_if rate\n");
+ return ret;
+ }
+ } else {
+ clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
+ }
+
+ ret = regmap_set_bits(apusys->scpsys,
+ pd->data->topd->spm_ext_buck_iso,
+ pd->data->topd->spm_ext_buck_iso_mask);
+ if (ret)
+ return ret;
+
+ if (apusys->vsram_supply) {
+ ret = regulator_disable(apusys->vsram_supply);
+ if (ret)
+ return ret;
+ }
+
+ if (pd->domain_supply) {
+ ret = regulator_disable(pd->domain_supply);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct generic_pm_domain *apu_add_one_domain(struct apusys *apusys,
+ struct device_node *node)
+{
+ const struct apu_domain_data *domain_data;
+ struct apu_domain *pd;
+ int ret;
+ u32 id;
+ int i;
+ struct clk *clk;
+
+ ret = of_property_read_u32(node, "reg", &id);
+ if (ret) {
+ dev_dbg(apusys->dev, "%pOF: invalid reg: %d\n", node, ret);
+ return ERR_PTR(ret);
+ }
+
+ if (id >= apusys->data->num_domains) {
+ dev_dbg(apusys->dev, "%pOF: invalid id %d\n", node, id);
+ return ERR_PTR(-EINVAL);
+ }
+
+ domain_data = &apusys->data->domains_data[id];
+
+ pd = devm_kzalloc(apusys->dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return ERR_PTR(-ENOMEM);
+
+ pd->data = domain_data;
+ pd->apusys = apusys;
+
+ pd->domain_supply = devm_regulator_get_optional(apusys->dev, "domain");
+ if (IS_ERR(pd->domain_supply)) {
+ ret = PTR_ERR(pd->domain_supply);
+ if (ret != -EPROBE_DEFER) {
+ dev_dbg(apusys->dev, "domain_supply fail, ret=%d", ret);
+ apusys->vsram_supply = NULL;
+ }
+ return ERR_PTR(ret);
+ }
+
+ /*
+ * For HW using ipu_if, the clock is switched to 26M
+ * when power down top domain and switch to default clock rate
+ * before power on.
+ */
+ if (APU_PD_CAPS(pd, APU_PD_IPUIF_HW_CG)) {
+ pd->clk_top_conn = of_clk_get_by_name(node, "clk_top_conn");
+ if (IS_ERR(pd->clk_top_conn)) {
+ dev_err(apusys->dev, "Fail to get clk_top_conn clock\n");
+ ret = PTR_ERR(pd->clk_top_conn);
+ goto err_put_clocks;
+ }
+
+ pd->clk_top_ipu_if = of_clk_get_by_name(node, "clk_top_ipu_if");
+ if (IS_ERR(pd->clk_top_ipu_if)) {
+ dev_err(apusys->dev, "Fail to get clk_top_ipu_if clock\n");
+ ret = PTR_ERR(pd->clk_top_ipu_if);
+ goto err_put_clocks;
+ }
+
+ pd->clk_off = of_clk_get_by_name(node, "clk_off");
+ if (IS_ERR(pd->clk_off)) {
+ dev_err(apusys->dev, "Fail to get clk_off clock\n");
+ ret = PTR_ERR(pd->clk_off);
+ goto err_put_clocks;
+ }
+
+ pd->clk_on_def = of_clk_get_by_name(node, "clk_on_default");
+ if (IS_ERR(pd->clk_on_def)) {
+ dev_err(apusys->dev, "Fail to get clk_on_default clock\n");
+ ret = PTR_ERR(pd->clk_on_def);
+ goto err_put_clocks;
+ }
+ } else {
+ pd->num_clks = of_clk_get_parent_count(node);
+ if (pd->num_clks > 0) {
+ pd->clks = devm_kcalloc(apusys->dev, pd->num_clks,
+ sizeof(*pd->clks), GFP_KERNEL);
+ if (!pd->clks)
+ return ERR_PTR(-ENOMEM);
+ }
+
+ for (i = 0; i < pd->num_clks; i++) {
+ clk = of_clk_get(node, i);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ dev_dbg(apusys->dev,
+ "%pOF: failed to get clk at index %d: %d\n",
+ node, i, ret);
+ goto err_put_clocks;
+ }
+ pd->clks[i].clk = clk;
+ }
+ }
+
+ if (apusys->domains[id]) {
+ ret = -EEXIST;
+ dev_err(apusys->dev, "domain id %d already exists\n", id);
+ goto err_put_clocks;
+ }
+
+ /* set rpc hw init status */
+ ret = apu_top_init_hw(pd);
+ if (ret) {
+ dev_err(apusys->dev, "top init fail ret = %d\n", ret);
+ goto err_put_clocks;
+ }
+
+ if (!pd->data->name)
+ pd->genpd.name = node->name;
+ else
+ pd->genpd.name = pd->data->name;
+ pd->genpd.power_off = apu_top_power_off;
+ pd->genpd.power_on = apu_top_power_on;
+
+ ret = pm_genpd_init(&pd->genpd, NULL, true);
+ if (ret) {
+ dev_err(apusys->dev, "init power domain fail\n");
+ goto err_put_clocks;
+ }
+
+ apusys->domains[id] = &pd->genpd;
+
+ return apusys->pd_data.domains[id];
+
+err_put_clocks:
+ if (APU_PD_CAPS(pd, APU_PD_IPUIF_HW_CG)) {
+ clk_put(pd->clk_top_conn);
+ clk_put(pd->clk_top_ipu_if);
+ clk_put(pd->clk_off);
+ clk_put(pd->clk_on_def);
+ } else {
+ clk_bulk_put(pd->num_clks, pd->clks);
+ }
+ return ERR_PTR(ret);
+}
+
+static void apu_remove_one_domain(struct apu_domain *pd)
+{
+ int ret;
+
+ /*
+ * We're in the error cleanup already, so we only complain,
+ * but won't emit another error on top of the original one.
+ */
+ ret = pm_genpd_remove(&pd->genpd);
+ if (ret)
+ dev_dbg(pd->apusys->dev,
+ "Remove domain '%s' : %d - state may be inconsistent\n",
+ pd->genpd.name, ret);
+
+ if (APU_PD_CAPS(pd, APU_PD_IPUIF_HW_CG)) {
+ clk_put(pd->clk_top_conn);
+ clk_put(pd->clk_top_ipu_if);
+ clk_put(pd->clk_off);
+ clk_put(pd->clk_on_def);
+ } else {
+ clk_bulk_put(pd->num_clks, pd->clks);
+ }
+}
+
+static void apu_domain_cleanup(struct apusys *apusys)
+{
+ struct generic_pm_domain *genpd;
+ struct apu_domain *pd;
+ int i;
+
+ for (i = apusys->pd_data.num_domains - 1; i >= 0; i--) {
+ genpd = apusys->pd_data.domains[i];
+ if (genpd) {
+ pd = to_apu_domain(genpd);
+ apu_remove_one_domain(pd);
+ }
+ }
+}
+
+static const struct of_device_id apu_pm_of_match[] = {
+ {
+ .compatible = "mediatek,mt8192-apu-pm",
+ .data = &mt8192_apu_pm_data,
+ },
+ { }
+};
+
+static int apu_pm_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct apu_pm_data *data;
+ struct device_node *node;
+ struct apusys *apusys;
+ int ret;
+
+ data = of_device_get_match_data(&pdev->dev);
+ if (!data) {
+ dev_dbg(dev, "no power domain data\n");
+ return -EINVAL;
+ }
+
+ apusys = devm_kzalloc(dev,
+ struct_size(apusys, domains, data->num_domains),
+ GFP_KERNEL);
+ if (!apusys)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, apusys);
+ apusys->dev = dev;
+ apusys->data = data;
+ apusys->pd_data.domains = apusys->domains;
+ apusys->pd_data.num_domains = data->num_domains;
+
+ apusys->vsram_supply = devm_regulator_get_optional(dev, "vsram");
+ if (IS_ERR(apusys->vsram_supply)) {
+ ret = PTR_ERR(apusys->vsram_supply);
+ if (ret != -EPROBE_DEFER) {
+ dev_err(dev, "vsram_supply fail, ret=%d", ret);
+ apusys->vsram_supply = NULL;
+ }
+ return ret;
+ }
+
+ /* rpc */
+ apusys->rpc = syscon_node_to_regmap(np);
+ if (IS_ERR(apusys->rpc)) {
+ dev_err(dev, "Unable to get rpc\n");
+ return PTR_ERR(apusys->rpc);
+ }
+
+ /* scpsys */
+ apusys->scpsys = syscon_regmap_lookup_by_phandle(np, "mediatek,scpsys");
+ if (IS_ERR(apusys->scpsys)) {
+ dev_err(dev, "Unable to get scpsys\n");
+ return PTR_ERR(apusys->scpsys);
+ }
+
+ /* apusys conn */
+ apusys->conn = syscon_regmap_lookup_by_phandle_optional(np, "mediatek,apu-conn");
+ if (IS_ERR(apusys->conn))
+ dev_dbg(dev, "No optional phandle apu-conn\n");
+
+ /* apusys conn1 */
+ apusys->conn1 = syscon_regmap_lookup_by_phandle_optional(np, "mediatek,apu-conn1");
+ if (IS_ERR(apusys->conn1))
+ dev_dbg(dev, "No optional phandle apu-conn1\n");
+
+ /* apusys vcore */
+ apusys->vcore = syscon_regmap_lookup_by_phandle_optional(np, "mediatek,apu-vcore");
+ if (IS_ERR(apusys->vcore))
+ dev_dbg(dev, "No optional phandle apu-vcore\n");
+
+ for_each_available_child_of_node(np, node) {
+ struct generic_pm_domain *domain;
+
+ domain = apu_add_one_domain(apusys, node);
+ if (IS_ERR(domain)) {
+ ret = PTR_ERR(domain);
+ of_node_put(node);
+ goto err_cleanup_domains;
+ }
+ }
+
+ ret = of_genpd_add_provider_onecell(np, &apusys->pd_data);
+ if (ret) {
+ dev_dbg(dev, "failed to add provider: %d\n", ret);
+ goto err_cleanup_domains;
+ }
+
+ return 0;
+
+err_cleanup_domains:
+ apu_domain_cleanup(apusys);
+ return ret;
+}
+
+static int apu_pm_remove(struct platform_device *pdev)
+{
+ struct apusys *apusys = platform_get_drvdata(pdev);
+
+ of_genpd_del_provider(pdev->dev.of_node);
+ apu_domain_cleanup(apusys);
+
+ return 0;
+}
+
+static struct platform_driver apu_pm_driver = {
+ .probe = apu_pm_probe,
+ .remove = apu_pm_remove,
+ .driver = {
+ .name = "mtk-apu-pm",
+ .suppress_bind_attrs = true,
+ .of_match_table = apu_pm_of_match,
+ },
+};
+module_platform_driver(apu_pm_driver);
+MODULE_DESCRIPTION("APU Power Domain Driver");
+MODULE_LICENSE("GPL v2");
--
2.18.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v4 6/8] arm64: dts: mt8192: Add APU node
2021-12-10 17:01 [PATCH v4 0/8] Add Support for MediaTek MT8192 APU Power Domain Flora Fu
` (4 preceding siblings ...)
2021-12-10 17:01 ` [PATCH v4 5/8] soc: mediatek: apu: Add apusys and add apu power domain driver Flora Fu
@ 2021-12-10 17:01 ` Flora Fu
2021-12-10 17:01 ` [PATCH v4 7/8] arm64: dts: mt8192: Add APU power domain node Flora Fu
2021-12-10 17:01 ` [PATCH v4 8/8] arm64: dts: mt8192: Set up apu power domain regulators Flora Fu
7 siblings, 0 replies; 9+ messages in thread
From: Flora Fu @ 2021-12-10 17:01 UTC (permalink / raw)
To: Matthias Brugger, Liam Girdwood, Mark Brown
Cc: linux-kernel, linux-arm-kernel, linux-mediatek, Flora Fu,
Yong Wu, JB Tsai, Pi-Cheng Chen, Chun-Jie Chen
Add APU node to MT8192.
Signed-off-by: Flora Fu <flora.fu@mediatek.com>
---
arch/arm64/boot/dts/mediatek/mt8192.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt8192.dtsi b/arch/arm64/boot/dts/mediatek/mt8192.dtsi
index ed4a5749c45a..9e4057d4e1ac 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8192.dtsi
@@ -906,6 +906,18 @@
#clock-cells = <1>;
};
+ apu_conn: apu_conn@19020000 {
+ compatible = "mediatek,mt8192-apu-conn", "syscon";
+ reg = <0 0x19020000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ apu_vcore: apu_vcore@19029000 {
+ compatible = "mediatek,mt8192-apu-vcore", "syscon";
+ reg = <0 0x19029000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
camsys: clock-controller@1a000000 {
compatible = "mediatek,mt8192-camsys";
reg = <0 0x1a000000 0 0x1000>;
--
2.18.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v4 7/8] arm64: dts: mt8192: Add APU power domain node
2021-12-10 17:01 [PATCH v4 0/8] Add Support for MediaTek MT8192 APU Power Domain Flora Fu
` (5 preceding siblings ...)
2021-12-10 17:01 ` [PATCH v4 6/8] arm64: dts: mt8192: Add APU node Flora Fu
@ 2021-12-10 17:01 ` Flora Fu
2021-12-10 17:01 ` [PATCH v4 8/8] arm64: dts: mt8192: Set up apu power domain regulators Flora Fu
7 siblings, 0 replies; 9+ messages in thread
From: Flora Fu @ 2021-12-10 17:01 UTC (permalink / raw)
To: Matthias Brugger, Liam Girdwood, Mark Brown
Cc: linux-kernel, linux-arm-kernel, linux-mediatek, Flora Fu,
Yong Wu, JB Tsai, Pi-Cheng Chen, Chun-Jie Chen
Add APU power domain node to MT8192.
Signed-off-by: Flora Fu <flora.fu@mediatek.com>
---
Note:
This patch depends on mt8192/mt6359 dts patches which haven't yet
been accepted. This series is based on MT8192 power domain[1], PWRAP[2]
and PMIC MT6359[3] patches.
[1] https://patchwork.kernel.org/patch/12456165
[2] https://patchwork.kernel.org/patch/12134935
[3] https://patchwork.kernel.org/patch/12140237
---
arch/arm64/boot/dts/mediatek/mt8192.dtsi | 27 ++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt8192.dtsi b/arch/arm64/boot/dts/mediatek/mt8192.dtsi
index 9e4057d4e1ac..cb2b171e0080 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8192.dtsi
@@ -918,6 +918,33 @@
#clock-cells = <1>;
};
+ apuspm: power-domain@190f0000 {
+ compatible = "mediatek,mt8192-apu-pm", "syscon";
+ reg = <0 0x190f0000 0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+ mediatek,scpsys = <&scpsys>;
+ mediatek,apu-conn = <&apu_conn>;
+ mediatek,apu-vcore = <&apu_vcore>;
+ apu_top: power-domain@0 {
+ reg = <0>;
+ #power-domain-cells = <0>;
+ clocks = <&topckgen CLK_TOP_DSP_SEL>,
+ <&topckgen CLK_TOP_IPU_IF_SEL>,
+ <&clk26m>,
+ <&topckgen CLK_TOP_UNIVPLL_D6_D2>;
+ clock-names = "clk_top_conn",
+ "clk_top_ipu_if",
+ "clk_off",
+ "clk_on_default";
+ assigned-clocks = <&topckgen CLK_TOP_DSP_SEL>,
+ <&topckgen CLK_TOP_IPU_IF_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D6_D2>,
+ <&topckgen CLK_TOP_UNIVPLL_D6_D2>;
+ };
+ };
+
camsys: clock-controller@1a000000 {
compatible = "mediatek,mt8192-camsys";
reg = <0 0x1a000000 0 0x1000>;
--
2.18.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v4 8/8] arm64: dts: mt8192: Set up apu power domain regulators
2021-12-10 17:01 [PATCH v4 0/8] Add Support for MediaTek MT8192 APU Power Domain Flora Fu
` (6 preceding siblings ...)
2021-12-10 17:01 ` [PATCH v4 7/8] arm64: dts: mt8192: Add APU power domain node Flora Fu
@ 2021-12-10 17:01 ` Flora Fu
7 siblings, 0 replies; 9+ messages in thread
From: Flora Fu @ 2021-12-10 17:01 UTC (permalink / raw)
To: Matthias Brugger, Liam Girdwood, Mark Brown
Cc: linux-kernel, linux-arm-kernel, linux-mediatek, Flora Fu,
Yong Wu, JB Tsai, Pi-Cheng Chen, Chun-Jie Chen
Set up apu power domain related regulators.
Signed-off-by: Flora Fu <flora.fu@mediatek.com>
---
Note:
This patch depends on mt6359[3] dts patches which haven't yet been accepted.
[1] https://patchwork.kernel.org/patch/12140237
---
arch/arm64/boot/dts/mediatek/mt8192-evb.dts | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-evb.dts b/arch/arm64/boot/dts/mediatek/mt8192-evb.dts
index 808be492e970..5d9e108e41f5 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8192-evb.dts
@@ -28,3 +28,10 @@
&uart0 {
status = "okay";
};
+
+&apuspm {
+ vsram-supply = <&mt6359_vsram_md_ldo_reg>;
+ apu_top: power-domain@0 {
+ domain-supply = <&mt6359_vproc1_buck_reg>;
+ };
+};
--
2.18.0
^ permalink raw reply [flat|nested] 9+ messages in thread