The MFG (GPU) block on the MT8173 has a small glue layer, named MFG_TOP
in the datasheet, that contains clock gates, some power sequence signal
delays, and other unknown registers that get toggled when the GPU is
powered on.
The clock gates are exposed as clocks provided by a clock controller,
while the power sequencing bits are exposed as one singular power domain.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
Changes since v1:
- Reduce tab after GATE_MFG() by one tab
- Move of_match_clk_mt8173_mfgtop to just before clk_mt8173_mfgtop_drv
- Rename power domain to "mfg-top"
- Add FORCE_ABORT and ACTIVE_PWRCTL_EN bits and explicitly clear
ACTIVE_PWRCTL_EN bit
---
drivers/clk/mediatek/Kconfig | 9 +
drivers/clk/mediatek/Makefile | 1 +
drivers/clk/mediatek/clk-mt8173-mfgtop.c | 243 +++++++++++++++++++++++
3 files changed, 253 insertions(+)
create mode 100644 drivers/clk/mediatek/clk-mt8173-mfgtop.c
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 2c09fd729bab..8dbd9f14be62 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -537,6 +537,15 @@ config COMMON_CLK_MT8173_IMGSYS
help
This driver supports MediaTek MT8173 imgsys clocks.
+config COMMON_CLK_MT8173_MFGTOP
+ tristate "Clock and power driver for MediaTek MT8173 mfgtop"
+ depends on COMMON_CLK_MT8173
+ default COMMON_CLK_MT8173
+ select PM_GENERIC_DOMAINS
+ select PM_GENERIC_DOMAINS_OF
+ help
+ This driver supports MediaTek MT8173 mfgtop clocks and power domain.
+
config COMMON_CLK_MT8173_MMSYS
tristate "Clock driver for MediaTek MT8173 mmsys"
depends on COMMON_CLK_MT8173
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index d8736a060dbd..892a54eeb281 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_COMMON_CLK_MT8167_VDECSYS) += clk-mt8167-vdec.o
obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173-apmixedsys.o clk-mt8173-infracfg.o \
clk-mt8173-pericfg.o clk-mt8173-topckgen.o
obj-$(CONFIG_COMMON_CLK_MT8173_IMGSYS) += clk-mt8173-img.o
+obj-$(CONFIG_COMMON_CLK_MT8173_MFGTOP) += clk-mt8173-mfgtop.o
obj-$(CONFIG_COMMON_CLK_MT8173_MMSYS) += clk-mt8173-mm.o
obj-$(CONFIG_COMMON_CLK_MT8173_VDECSYS) += clk-mt8173-vdecsys.o
obj-$(CONFIG_COMMON_CLK_MT8173_VENCSYS) += clk-mt8173-vencsys.o
diff --git a/drivers/clk/mediatek/clk-mt8173-mfgtop.c b/drivers/clk/mediatek/clk-mt8173-mfgtop.c
new file mode 100644
index 000000000000..9e18f34166ae
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8173-mfgtop.c
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 Google LLC
+ * Author: Chen-Yu Tsai <wenst@chromium.org>
+ *
+ * Based on driver in downstream ChromeOS v5.15 kernel.
+ *
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Chiawen Lee <chiawen.lee@mediatek.com>
+ */
+
+#include <dt-bindings/clock/mt8173-clk.h>
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+static const struct mtk_gate_regs mfg_cg_regs = {
+ .sta_ofs = 0x0000,
+ .clr_ofs = 0x0008,
+ .set_ofs = 0x0004,
+};
+
+#define GATE_MFG(_id, _name, _parent, _shift, _flags) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &mfg_cg_regs, _shift, &mtk_clk_gate_ops_setclr, _flags)
+
+/* TODO: The block actually has dividers for the core and mem clocks. */
+static const struct mtk_gate mfg_clks[] = {
+ GATE_MFG(CLK_MFG_AXI, "mfg_axi", "axi_mfg_in_sel", 0, CLK_SET_RATE_PARENT),
+ GATE_MFG(CLK_MFG_MEM, "mfg_mem", "mem_mfg_in_sel", 1, CLK_SET_RATE_PARENT),
+ GATE_MFG(CLK_MFG_G3D, "mfg_g3d", "mfg_sel", 2, CLK_SET_RATE_PARENT),
+ GATE_MFG(CLK_MFG_26M, "mfg_26m", "clk26m", 3, 0),
+};
+
+static const struct mtk_clk_desc mfg_desc = {
+ .clks = mfg_clks,
+ .num_clks = ARRAY_SIZE(mfg_clks),
+};
+
+struct mt8173_mfgtop_data {
+ struct clk_hw_onecell_data *clk_data;
+ struct regmap *regmap;
+ struct generic_pm_domain genpd;
+ struct of_phandle_args parent_pd, child_pd;
+ struct clk *clk_26m;
+};
+
+/* Delay count in clock cycles */
+#define MFG_ACTIVE_POWER_CON0 0x24
+ #define RST_B_DELAY_CNT GENMASK(7, 0) /* pwr_rst_b de-assert delay during power-up */
+ #define CLK_EN_DELAY_CNT GENMASK(15, 8) /* CLK_DIS deassert delay during power-up */
+ #define CLK_DIS_DELAY_CNT GENMASK(23, 16) /* CLK_DIS assert delay during power-down */
+ #define FORCE_ABORT BIT(30) /* write 1 to force abort a power event */
+ #define ACTIVE_PWRCTL_EN BIT(31) /* enable ACTIVE_POWER */
+
+#define MFG_ACTIVE_POWER_CON1 0x28
+ #define PWR_ON_S_DELAY_CNT GENMASK(7, 0) /* pwr_on_s assert delay during power-up */
+ #define ISO_DELAY_CNT GENMASK(15, 8) /* ISO assert delay during power-down */
+ #define ISOOFF_DELAY_CNT GENMASK(23, 16) /* ISO de-assert delay during power-up */
+ #define RST__DELAY_CNT GENMASK(31, 24) /* pwr_rsb_b assert delay during power-down */
+
+static int clk_mt8173_mfgtop_power_on(struct generic_pm_domain *domain)
+{
+ struct mt8173_mfgtop_data *data = container_of(domain, struct mt8173_mfgtop_data, genpd);
+
+ /* drives internal power management */
+ clk_prepare_enable(data->clk_26m);
+
+ /* Power on/off delays for various signals */
+ regmap_write(data->regmap, MFG_ACTIVE_POWER_CON0,
+ FIELD_PREP(RST_B_DELAY_CNT, 77) |
+ FIELD_PREP(CLK_EN_DELAY_CNT, 61) |
+ FIELD_PREP(CLK_DIS_DELAY_CNT, 60) |
+ FIELD_PREP(ACTIVE_PWRCTL_EN, 0));
+ regmap_write(data->regmap, MFG_ACTIVE_POWER_CON1,
+ FIELD_PREP(PWR_ON_S_DELAY_CNT, 11) |
+ FIELD_PREP(ISO_DELAY_CNT, 68) |
+ FIELD_PREP(ISOOFF_DELAY_CNT, 69) |
+ FIELD_PREP(RST__DELAY_CNT, 77));
+
+ /* Magic numbers related to core switch sequence and delays */
+ regmap_write(data->regmap, 0xe0, 0x7a710184);
+ regmap_write(data->regmap, 0xe4, 0x835f6856);
+ regmap_write(data->regmap, 0xe8, 0x002b0234);
+ regmap_write(data->regmap, 0xec, 0x80000000);
+ regmap_write(data->regmap, 0xa0, 0x08000000);
+
+ return 0;
+}
+
+static int clk_mt8173_mfgtop_power_off(struct generic_pm_domain *domain)
+{
+ struct mt8173_mfgtop_data *data = container_of(domain, struct mt8173_mfgtop_data, genpd);
+
+ /* Magic numbers related to core switch sequence and delays */
+ regmap_write(data->regmap, 0xec, 0);
+
+ /* drives internal power management */
+ clk_disable_unprepare(data->clk_26m);
+
+ return 0;
+}
+
+static int clk_mt8173_mfgtop_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct mt8173_mfgtop_data *data;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, data);
+
+ data->clk_data = mtk_devm_alloc_clk_data(dev, ARRAY_SIZE(mfg_clks));
+ if (!data->clk_data)
+ return -ENOMEM;
+
+ /* MTK clock gates also uses regmap */
+ data->regmap = device_node_to_regmap(node);
+ if (IS_ERR(data->regmap))
+ return dev_err_probe(dev, PTR_ERR(data->regmap), "Failed to get regmap\n");
+
+ data->child_pd.np = node;
+ data->child_pd.args_count = 0;
+ ret = of_parse_phandle_with_args(node, "power-domains", "#power-domain-cells", 0,
+ &data->parent_pd);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to parse power domain\n");
+
+ devm_pm_runtime_enable(dev);
+ /*
+ * Do a pm_runtime_resume_and_get() to workaround a possible
+ * deadlock between clk_register() and the genpd framework.
+ */
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to runtime resume device\n");
+ goto put_of_node;
+ }
+
+ ret = mtk_clk_register_gates(dev, node, mfg_clks, ARRAY_SIZE(mfg_clks),
+ data->clk_data);
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to register clock gates\n");
+ goto put_pm_runtime;
+ }
+
+ data->clk_26m = clk_hw_get_clk(data->clk_data->hws[CLK_MFG_26M], "26m");
+ if (IS_ERR(data->clk_26m)) {
+ dev_err_probe(dev, PTR_ERR(data->clk_26m), "Failed to get 26 MHz clock\n");
+ goto unregister_clks;
+ }
+
+ ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, data->clk_data);
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to add clk OF provider\n");
+ goto put_26m_clk;
+ }
+
+ data->genpd.name = "mfg-top";
+ data->genpd.power_on = clk_mt8173_mfgtop_power_on;
+ data->genpd.power_off = clk_mt8173_mfgtop_power_off;
+ ret = pm_genpd_init(&data->genpd, NULL, true);
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to add power domain\n");
+ goto del_clk_provider;
+ }
+
+ ret = of_genpd_add_provider_simple(node, &data->genpd);
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to add power domain OF provider\n");
+ goto remove_pd;
+ }
+
+ ret = of_genpd_add_subdomain(&data->parent_pd, &data->child_pd);
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to link PM domains\n");
+ goto del_pd_provider;
+ }
+
+ pm_runtime_put(dev);
+ return 0;
+
+del_pd_provider:
+ of_genpd_del_provider(node);
+remove_pd:
+ pm_genpd_remove(&data->genpd);
+del_clk_provider:
+ of_clk_del_provider(node);
+put_26m_clk:
+ clk_put(data->clk_26m);
+unregister_clks:
+ mtk_clk_unregister_gates(mfg_clks, ARRAY_SIZE(mfg_clks), data->clk_data);
+put_pm_runtime:
+ pm_runtime_put(dev);
+put_of_node:
+ of_node_put(data->parent_pd.np);
+ return ret;
+}
+
+static void clk_mt8173_mfgtop_remove(struct platform_device *pdev)
+{
+ struct mt8173_mfgtop_data *data = platform_get_drvdata(pdev);
+ struct device_node *node = pdev->dev.of_node;
+
+ of_genpd_remove_subdomain(&data->parent_pd, &data->child_pd);
+ of_genpd_del_provider(node);
+ pm_genpd_remove(&data->genpd);
+ of_clk_del_provider(node);
+ clk_put(data->clk_26m);
+ mtk_clk_unregister_gates(mfg_clks, ARRAY_SIZE(mfg_clks), data->clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8173_mfgtop[] = {
+ { .compatible = "mediatek,mt8173-mfgtop", .data = &mfg_desc },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match_clk_mt8173_mfgtop);
+
+static struct platform_driver clk_mt8173_mfgtop_drv = {
+ .probe = clk_mt8173_mfgtop_probe,
+ .remove = clk_mt8173_mfgtop_remove,
+ .driver = {
+ .name = "clk-mt8173-mfgtop",
+ .of_match_table = of_match_clk_mt8173_mfgtop,
+ },
+};
+module_platform_driver(clk_mt8173_mfgtop_drv);
+
+MODULE_DESCRIPTION("MediaTek MT8173 mfgtop clock driver");
+MODULE_LICENSE("GPL");
--
2.53.0.1018.g2bb0e51243-goog
Hi Chen-Yu,
kernel test robot noticed the following build warnings:
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Chen-Yu-Tsai/dt-bindings-clock-mediatek-Add-mt8173-mfgtop/20260325-202618
base: https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next
patch link: https://lore.kernel.org/r/20260325071951.544031-3-wenst%40chromium.org
patch subject: [PATCH v2 2/5] clk: mediatek: Add mt8173-mfgtop driver
config: csky-randconfig-r073-20260326 (https://download.01.org/0day-ci/archive/20260326/202603261444.jANdMbNC-lkp@intel.com/config)
compiler: csky-linux-gcc (GCC) 11.5.0
smatch: v0.5.0-9004-gb810ac53
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
| Closes: https://lore.kernel.org/r/202603261444.jANdMbNC-lkp@intel.com/
smatch warnings:
drivers/clk/mediatek/clk-mt8173-mfgtop.c:163 clk_mt8173_mfgtop_probe() warn: missing error code 'ret'
vim +/ret +163 drivers/clk/mediatek/clk-mt8173-mfgtop.c
edc2074329e271 Chen-Yu Tsai 2026-03-25 153 ret = mtk_clk_register_gates(dev, node, mfg_clks, ARRAY_SIZE(mfg_clks),
edc2074329e271 Chen-Yu Tsai 2026-03-25 154 data->clk_data);
edc2074329e271 Chen-Yu Tsai 2026-03-25 155 if (ret) {
edc2074329e271 Chen-Yu Tsai 2026-03-25 156 dev_err_probe(dev, ret, "Failed to register clock gates\n");
edc2074329e271 Chen-Yu Tsai 2026-03-25 157 goto put_pm_runtime;
edc2074329e271 Chen-Yu Tsai 2026-03-25 158 }
edc2074329e271 Chen-Yu Tsai 2026-03-25 159
edc2074329e271 Chen-Yu Tsai 2026-03-25 160 data->clk_26m = clk_hw_get_clk(data->clk_data->hws[CLK_MFG_26M], "26m");
edc2074329e271 Chen-Yu Tsai 2026-03-25 161 if (IS_ERR(data->clk_26m)) {
edc2074329e271 Chen-Yu Tsai 2026-03-25 162 dev_err_probe(dev, PTR_ERR(data->clk_26m), "Failed to get 26 MHz clock\n");
edc2074329e271 Chen-Yu Tsai 2026-03-25 @163 goto unregister_clks;
ret = dev_err_probe() or ret = PTR_ERR(data->clk_26m)?
edc2074329e271 Chen-Yu Tsai 2026-03-25 164 }
edc2074329e271 Chen-Yu Tsai 2026-03-25 165
edc2074329e271 Chen-Yu Tsai 2026-03-25 166 ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, data->clk_data);
edc2074329e271 Chen-Yu Tsai 2026-03-25 167 if (ret) {
edc2074329e271 Chen-Yu Tsai 2026-03-25 168 dev_err_probe(dev, ret, "Failed to add clk OF provider\n");
edc2074329e271 Chen-Yu Tsai 2026-03-25 169 goto put_26m_clk;
edc2074329e271 Chen-Yu Tsai 2026-03-25 170 }
edc2074329e271 Chen-Yu Tsai 2026-03-25 171
edc2074329e271 Chen-Yu Tsai 2026-03-25 172 data->genpd.name = "mfg-top";
edc2074329e271 Chen-Yu Tsai 2026-03-25 173 data->genpd.power_on = clk_mt8173_mfgtop_power_on;
edc2074329e271 Chen-Yu Tsai 2026-03-25 174 data->genpd.power_off = clk_mt8173_mfgtop_power_off;
edc2074329e271 Chen-Yu Tsai 2026-03-25 175 ret = pm_genpd_init(&data->genpd, NULL, true);
edc2074329e271 Chen-Yu Tsai 2026-03-25 176 if (ret) {
edc2074329e271 Chen-Yu Tsai 2026-03-25 177 dev_err_probe(dev, ret, "Failed to add power domain\n");
edc2074329e271 Chen-Yu Tsai 2026-03-25 178 goto del_clk_provider;
edc2074329e271 Chen-Yu Tsai 2026-03-25 179 }
edc2074329e271 Chen-Yu Tsai 2026-03-25 180
edc2074329e271 Chen-Yu Tsai 2026-03-25 181 ret = of_genpd_add_provider_simple(node, &data->genpd);
edc2074329e271 Chen-Yu Tsai 2026-03-25 182 if (ret) {
edc2074329e271 Chen-Yu Tsai 2026-03-25 183 dev_err_probe(dev, ret, "Failed to add power domain OF provider\n");
edc2074329e271 Chen-Yu Tsai 2026-03-25 184 goto remove_pd;
edc2074329e271 Chen-Yu Tsai 2026-03-25 185 }
edc2074329e271 Chen-Yu Tsai 2026-03-25 186
edc2074329e271 Chen-Yu Tsai 2026-03-25 187 ret = of_genpd_add_subdomain(&data->parent_pd, &data->child_pd);
edc2074329e271 Chen-Yu Tsai 2026-03-25 188 if (ret) {
edc2074329e271 Chen-Yu Tsai 2026-03-25 189 dev_err_probe(dev, ret, "Failed to link PM domains\n");
edc2074329e271 Chen-Yu Tsai 2026-03-25 190 goto del_pd_provider;
edc2074329e271 Chen-Yu Tsai 2026-03-25 191 }
edc2074329e271 Chen-Yu Tsai 2026-03-25 192
edc2074329e271 Chen-Yu Tsai 2026-03-25 193 pm_runtime_put(dev);
edc2074329e271 Chen-Yu Tsai 2026-03-25 194 return 0;
edc2074329e271 Chen-Yu Tsai 2026-03-25 195
edc2074329e271 Chen-Yu Tsai 2026-03-25 196 del_pd_provider:
edc2074329e271 Chen-Yu Tsai 2026-03-25 197 of_genpd_del_provider(node);
edc2074329e271 Chen-Yu Tsai 2026-03-25 198 remove_pd:
edc2074329e271 Chen-Yu Tsai 2026-03-25 199 pm_genpd_remove(&data->genpd);
edc2074329e271 Chen-Yu Tsai 2026-03-25 200 del_clk_provider:
edc2074329e271 Chen-Yu Tsai 2026-03-25 201 of_clk_del_provider(node);
edc2074329e271 Chen-Yu Tsai 2026-03-25 202 put_26m_clk:
edc2074329e271 Chen-Yu Tsai 2026-03-25 203 clk_put(data->clk_26m);
edc2074329e271 Chen-Yu Tsai 2026-03-25 204 unregister_clks:
edc2074329e271 Chen-Yu Tsai 2026-03-25 205 mtk_clk_unregister_gates(mfg_clks, ARRAY_SIZE(mfg_clks), data->clk_data);
edc2074329e271 Chen-Yu Tsai 2026-03-25 206 put_pm_runtime:
edc2074329e271 Chen-Yu Tsai 2026-03-25 207 pm_runtime_put(dev);
edc2074329e271 Chen-Yu Tsai 2026-03-25 208 put_of_node:
edc2074329e271 Chen-Yu Tsai 2026-03-25 209 of_node_put(data->parent_pd.np);
edc2074329e271 Chen-Yu Tsai 2026-03-25 210 return ret;
edc2074329e271 Chen-Yu Tsai 2026-03-25 211 }
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Hi Chen-Yu,
kernel test robot noticed the following build errors:
[auto build test ERROR on clk/clk-next]
[also build test ERROR on robh/for-next drm-misc/drm-misc-next linus/master v7.0-rc5 next-20260325]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Chen-Yu-Tsai/dt-bindings-clock-mediatek-Add-mt8173-mfgtop/20260325-202618
base: https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next
patch link: https://lore.kernel.org/r/20260325071951.544031-3-wenst%40chromium.org
patch subject: [PATCH v2 2/5] clk: mediatek: Add mt8173-mfgtop driver
config: loongarch-randconfig-002-20260326 (https://download.01.org/0day-ci/archive/20260326/202603260926.gAEaAK0A-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 14.3.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260326/202603260926.gAEaAK0A-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603260926.gAEaAK0A-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/pmdomain/governor.c: In function 'default_suspend_ok':
>> drivers/pmdomain/governor.c:88:24: error: 'struct dev_pm_info' has no member named 'ignore_children'
88 | if (!dev->power.ignore_children)
| ^
--
drivers/pmdomain/core.c: In function 'genpd_queue_power_off_work':
>> drivers/pmdomain/core.c:941:20: error: 'pm_wq' undeclared (first use in this function)
941 | queue_work(pm_wq, &genpd->power_off_work);
| ^~~~~
drivers/pmdomain/core.c:941:20: note: each undeclared identifier is reported only once for each function it appears in
drivers/pmdomain/core.c: In function 'genpd_dev_pm_qos_notifier':
>> drivers/pmdomain/core.c:1138:39: error: 'struct dev_pm_info' has no member named 'ignore_children'
1138 | if (!dev || dev->power.ignore_children)
| ^
drivers/pmdomain/core.c: In function 'rtpm_status_str':
>> drivers/pmdomain/core.c:3614:23: error: 'struct dev_pm_info' has no member named 'runtime_error'
3614 | if (dev->power.runtime_error)
| ^
>> drivers/pmdomain/core.c:3616:28: error: 'struct dev_pm_info' has no member named 'disable_depth'
3616 | else if (dev->power.disable_depth)
| ^
>> drivers/pmdomain/core.c:3618:28: error: 'struct dev_pm_info' has no member named 'runtime_status'
3618 | else if (dev->power.runtime_status < ARRAY_SIZE(status_lookup))
| ^
drivers/pmdomain/core.c:3619:45: error: 'struct dev_pm_info' has no member named 'runtime_status'
3619 | p = status_lookup[dev->power.runtime_status];
| ^
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for PM_GENERIC_DOMAINS
Depends on [n]: PM [=n]
Selected by [m]:
- COMMON_CLK_MT8173_MFGTOP [=m] && COMMON_CLK [=y] && (ARCH_MEDIATEK || COMPILE_TEST [=y]) && COMMON_CLK_MT8173 [=m]
vim +88 drivers/pmdomain/governor.c
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 49
b02c999ac325e9 drivers/base/power/domain_governor.c Rafael J. Wysocki 2011-12-01 50 /**
9df3921e026532 drivers/base/power/domain_governor.c Ulf Hansson 2016-03-31 51 * default_suspend_ok - Default PM domain governor routine to suspend devices.
b02c999ac325e9 drivers/base/power/domain_governor.c Rafael J. Wysocki 2011-12-01 52 * @dev: Device to check.
3b2714c5d2d26d drivers/base/power/domain_governor.c Randy Dunlap 2023-12-05 53 *
3b2714c5d2d26d drivers/base/power/domain_governor.c Randy Dunlap 2023-12-05 54 * Returns: true if OK to suspend, false if not OK to suspend
b02c999ac325e9 drivers/base/power/domain_governor.c Rafael J. Wysocki 2011-12-01 55 */
9df3921e026532 drivers/base/power/domain_governor.c Ulf Hansson 2016-03-31 56 static bool default_suspend_ok(struct device *dev)
b02c999ac325e9 drivers/base/power/domain_governor.c Rafael J. Wysocki 2011-12-01 57 {
66d29d802ef3bf drivers/base/power/domain_governor.c Ulf Hansson 2022-05-11 58 struct gpd_timing_data *td = dev_gpd_data(dev)->td;
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 59 unsigned long flags;
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 60 s64 constraint_ns;
b02c999ac325e9 drivers/base/power/domain_governor.c Rafael J. Wysocki 2011-12-01 61
b02c999ac325e9 drivers/base/power/domain_governor.c Rafael J. Wysocki 2011-12-01 62 dev_dbg(dev, "%s()\n", __func__);
b02c999ac325e9 drivers/base/power/domain_governor.c Rafael J. Wysocki 2011-12-01 63
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 64 spin_lock_irqsave(&dev->power.lock, flags);
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 65
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 66 if (!td->constraint_changed) {
9df3921e026532 drivers/base/power/domain_governor.c Ulf Hansson 2016-03-31 67 bool ret = td->cached_suspend_ok;
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 68
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 69 spin_unlock_irqrestore(&dev->power.lock, flags);
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 70 return ret;
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 71 }
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 72 td->constraint_changed = false;
9df3921e026532 drivers/base/power/domain_governor.c Ulf Hansson 2016-03-31 73 td->cached_suspend_ok = false;
0759e80b84e34a drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 74 td->effective_constraint_ns = 0;
8262331eaaf751 drivers/base/power/domain_governor.c Viresh Kumar 2019-07-04 75 constraint_ns = __dev_pm_qos_resume_latency(dev);
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 76
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 77 spin_unlock_irqrestore(&dev->power.lock, flags);
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 78
0759e80b84e34a drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 79 if (constraint_ns == 0)
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 80 return false;
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 81
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 82 constraint_ns *= NSEC_PER_USEC;
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 83 /*
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 84 * We can walk the children without any additional locking, because
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 85 * they all have been suspended at this point and their
6ff7bb0d02f829 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-05-01 86 * effective_constraint_ns fields won't be modified in parallel with us.
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 87 */
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 @88 if (!dev->power.ignore_children)
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 89 device_for_each_child(dev, &constraint_ns,
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 90 dev_update_qos_constraint);
b02c999ac325e9 drivers/base/power/domain_governor.c Rafael J. Wysocki 2011-12-01 91
0759e80b84e34a drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 92 if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS) {
704d2ce6603f7e drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 93 /* "No restriction", so the device is allowed to suspend. */
0759e80b84e34a drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 94 td->effective_constraint_ns = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS;
704d2ce6603f7e drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 95 td->cached_suspend_ok = true;
0759e80b84e34a drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 96 } else if (constraint_ns == 0) {
704d2ce6603f7e drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 97 /*
704d2ce6603f7e drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 98 * This triggers if one of the children that don't belong to a
0759e80b84e34a drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 99 * domain has a zero PM QoS constraint and it's better not to
0759e80b84e34a drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 100 * suspend then. effective_constraint_ns is zero already and
0759e80b84e34a drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 101 * cached_suspend_ok is false, so bail out.
704d2ce6603f7e drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 102 */
704d2ce6603f7e drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 103 return false;
704d2ce6603f7e drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 104 } else {
2b1d88cda32f81 drivers/base/power/domain_governor.c Ulf Hansson 2015-10-15 105 constraint_ns -= td->suspend_latency_ns +
2b1d88cda32f81 drivers/base/power/domain_governor.c Ulf Hansson 2015-10-15 106 td->resume_latency_ns;
704d2ce6603f7e drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 107 /*
0759e80b84e34a drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 108 * effective_constraint_ns is zero already and cached_suspend_ok
0759e80b84e34a drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 109 * is false, so if the computed value is not positive, return
0759e80b84e34a drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 110 * right away.
704d2ce6603f7e drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 111 */
704d2ce6603f7e drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 112 if (constraint_ns <= 0)
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 113 return false;
704d2ce6603f7e drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 114
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 115 td->effective_constraint_ns = constraint_ns;
704d2ce6603f7e drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 116 td->cached_suspend_ok = true;
704d2ce6603f7e drivers/base/power/domain_governor.c Rafael J. Wysocki 2017-11-07 117 }
a98f1b78ecf325 drivers/base/power/domain_governor.c Ulf Hansson 2015-10-13 118
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 119 /*
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 120 * The children have been suspended already, so we don't need to take
9df3921e026532 drivers/base/power/domain_governor.c Ulf Hansson 2016-03-31 121 * their suspend latencies into account here.
a5bef810ad9816 drivers/base/power/domain_governor.c Rafael J. Wysocki 2012-04-29 122 */
9df3921e026532 drivers/base/power/domain_governor.c Ulf Hansson 2016-03-31 123 return td->cached_suspend_ok;
b02c999ac325e9 drivers/base/power/domain_governor.c Rafael J. Wysocki 2011-12-01 124 }
b02c999ac325e9 drivers/base/power/domain_governor.c Rafael J. Wysocki 2011-12-01 125
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
On Wed, Mar 25, 2026 at 03:19:46PM +0800, Chen-Yu Tsai wrote:
> The MFG (GPU) block on the MT8173 has a small glue layer, named MFG_TOP
> in the datasheet, that contains clock gates, some power sequence signal
> delays, and other unknown registers that get toggled when the GPU is
> powered on.
>
> The clock gates are exposed as clocks provided by a clock controller,
> while the power sequencing bits are exposed as one singular power domain.
>
> Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
> ---
> Changes since v1:
> - Reduce tab after GATE_MFG() by one tab
> - Move of_match_clk_mt8173_mfgtop to just before clk_mt8173_mfgtop_drv
> - Rename power domain to "mfg-top"
> - Add FORCE_ABORT and ACTIVE_PWRCTL_EN bits and explicitly clear
> ACTIVE_PWRCTL_EN bit
> ---
> drivers/clk/mediatek/Kconfig | 9 +
> drivers/clk/mediatek/Makefile | 1 +
> drivers/clk/mediatek/clk-mt8173-mfgtop.c | 243 +++++++++++++++++++++++
> 3 files changed, 253 insertions(+)
> create mode 100644 drivers/clk/mediatek/clk-mt8173-mfgtop.c
>
> diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
> index 2c09fd729bab..8dbd9f14be62 100644
> --- a/drivers/clk/mediatek/Kconfig
> +++ b/drivers/clk/mediatek/Kconfig
> @@ -537,6 +537,15 @@ config COMMON_CLK_MT8173_IMGSYS
> help
> This driver supports MediaTek MT8173 imgsys clocks.
>
> +config COMMON_CLK_MT8173_MFGTOP
> + tristate "Clock and power driver for MediaTek MT8173 mfgtop"
> + depends on COMMON_CLK_MT8173
> + default COMMON_CLK_MT8173
> + select PM_GENERIC_DOMAINS
> + select PM_GENERIC_DOMAINS_OF
> + help
> + This driver supports MediaTek MT8173 mfgtop clocks and power domain.
> +
> config COMMON_CLK_MT8173_MMSYS
> tristate "Clock driver for MediaTek MT8173 mmsys"
> depends on COMMON_CLK_MT8173
> diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
> index d8736a060dbd..892a54eeb281 100644
> --- a/drivers/clk/mediatek/Makefile
> +++ b/drivers/clk/mediatek/Makefile
> @@ -82,6 +82,7 @@ obj-$(CONFIG_COMMON_CLK_MT8167_VDECSYS) += clk-mt8167-vdec.o
> obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173-apmixedsys.o clk-mt8173-infracfg.o \
> clk-mt8173-pericfg.o clk-mt8173-topckgen.o
> obj-$(CONFIG_COMMON_CLK_MT8173_IMGSYS) += clk-mt8173-img.o
> +obj-$(CONFIG_COMMON_CLK_MT8173_MFGTOP) += clk-mt8173-mfgtop.o
> obj-$(CONFIG_COMMON_CLK_MT8173_MMSYS) += clk-mt8173-mm.o
> obj-$(CONFIG_COMMON_CLK_MT8173_VDECSYS) += clk-mt8173-vdecsys.o
> obj-$(CONFIG_COMMON_CLK_MT8173_VENCSYS) += clk-mt8173-vencsys.o
> diff --git a/drivers/clk/mediatek/clk-mt8173-mfgtop.c b/drivers/clk/mediatek/clk-mt8173-mfgtop.c
> new file mode 100644
> index 000000000000..9e18f34166ae
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mt8173-mfgtop.c
> @@ -0,0 +1,243 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2024 Google LLC
> + * Author: Chen-Yu Tsai <wenst@chromium.org>
> + *
> + * Based on driver in downstream ChromeOS v5.15 kernel.
> + *
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: Chiawen Lee <chiawen.lee@mediatek.com>
> + */
> +
> +#include <dt-bindings/clock/mt8173-clk.h>
> +
> +#include <linux/bitfield.h>
> +#include <linux/clk.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_domain.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
> +
> +#include "clk-gate.h"
> +#include "clk-mtk.h"
> +
> +static const struct mtk_gate_regs mfg_cg_regs = {
> + .sta_ofs = 0x0000,
> + .clr_ofs = 0x0008,
> + .set_ofs = 0x0004,
> +};
> +
> +#define GATE_MFG(_id, _name, _parent, _shift, _flags) \
> + GATE_MTK_FLAGS(_id, _name, _parent, &mfg_cg_regs, _shift, &mtk_clk_gate_ops_setclr, _flags)
> +
> +/* TODO: The block actually has dividers for the core and mem clocks. */
> +static const struct mtk_gate mfg_clks[] = {
> + GATE_MFG(CLK_MFG_AXI, "mfg_axi", "axi_mfg_in_sel", 0, CLK_SET_RATE_PARENT),
> + GATE_MFG(CLK_MFG_MEM, "mfg_mem", "mem_mfg_in_sel", 1, CLK_SET_RATE_PARENT),
> + GATE_MFG(CLK_MFG_G3D, "mfg_g3d", "mfg_sel", 2, CLK_SET_RATE_PARENT),
> + GATE_MFG(CLK_MFG_26M, "mfg_26m", "clk26m", 3, 0),
> +};
> +
> +static const struct mtk_clk_desc mfg_desc = {
> + .clks = mfg_clks,
> + .num_clks = ARRAY_SIZE(mfg_clks),
> +};
> +
> +struct mt8173_mfgtop_data {
> + struct clk_hw_onecell_data *clk_data;
> + struct regmap *regmap;
> + struct generic_pm_domain genpd;
> + struct of_phandle_args parent_pd, child_pd;
> + struct clk *clk_26m;
> +};
> +
> +/* Delay count in clock cycles */
> +#define MFG_ACTIVE_POWER_CON0 0x24
> + #define RST_B_DELAY_CNT GENMASK(7, 0) /* pwr_rst_b de-assert delay during power-up */
> + #define CLK_EN_DELAY_CNT GENMASK(15, 8) /* CLK_DIS deassert delay during power-up */
> + #define CLK_DIS_DELAY_CNT GENMASK(23, 16) /* CLK_DIS assert delay during power-down */
> + #define FORCE_ABORT BIT(30) /* write 1 to force abort a power event */
> + #define ACTIVE_PWRCTL_EN BIT(31) /* enable ACTIVE_POWER */
> +
> +#define MFG_ACTIVE_POWER_CON1 0x28
> + #define PWR_ON_S_DELAY_CNT GENMASK(7, 0) /* pwr_on_s assert delay during power-up */
> + #define ISO_DELAY_CNT GENMASK(15, 8) /* ISO assert delay during power-down */
> + #define ISOOFF_DELAY_CNT GENMASK(23, 16) /* ISO de-assert delay during power-up */
> + #define RST__DELAY_CNT GENMASK(31, 24) /* pwr_rsb_b assert delay during power-down */
Is the double underscore expected in the name?
> +
> +static int clk_mt8173_mfgtop_power_on(struct generic_pm_domain *domain)
> +{
> + struct mt8173_mfgtop_data *data = container_of(domain, struct mt8173_mfgtop_data, genpd);
> +
> + /* drives internal power management */
> + clk_prepare_enable(data->clk_26m);
> +
> + /* Power on/off delays for various signals */
> + regmap_write(data->regmap, MFG_ACTIVE_POWER_CON0,
Should the return value of clk_prepare_enable() and regmap_write() be
checked?
> + FIELD_PREP(RST_B_DELAY_CNT, 77) |
> + FIELD_PREP(CLK_EN_DELAY_CNT, 61) |
> + FIELD_PREP(CLK_DIS_DELAY_CNT, 60) |
> + FIELD_PREP(ACTIVE_PWRCTL_EN, 0));
> + regmap_write(data->regmap, MFG_ACTIVE_POWER_CON1,
> + FIELD_PREP(PWR_ON_S_DELAY_CNT, 11) |
> + FIELD_PREP(ISO_DELAY_CNT, 68) |
> + FIELD_PREP(ISOOFF_DELAY_CNT, 69) |
> + FIELD_PREP(RST__DELAY_CNT, 77));
> +
> + /* Magic numbers related to core switch sequence and delays */
> + regmap_write(data->regmap, 0xe0, 0x7a710184);
> + regmap_write(data->regmap, 0xe4, 0x835f6856);
> + regmap_write(data->regmap, 0xe8, 0x002b0234);
> + regmap_write(data->regmap, 0xec, 0x80000000);
> + regmap_write(data->regmap, 0xa0, 0x08000000);
> +
> + return 0;
> +}
> +
> +static int clk_mt8173_mfgtop_power_off(struct generic_pm_domain *domain)
> +{
> + struct mt8173_mfgtop_data *data = container_of(domain, struct mt8173_mfgtop_data, genpd);
> +
> + /* Magic numbers related to core switch sequence and delays */
> + regmap_write(data->regmap, 0xec, 0);
> +
> + /* drives internal power management */
> + clk_disable_unprepare(data->clk_26m);
> +
> + return 0;
> +}
> +
> +static int clk_mt8173_mfgtop_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *node = dev->of_node;
> + struct mt8173_mfgtop_data *data;
> + int ret;
> +
> + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + platform_set_drvdata(pdev, data);
> +
> + data->clk_data = mtk_devm_alloc_clk_data(dev, ARRAY_SIZE(mfg_clks));
> + if (!data->clk_data)
> + return -ENOMEM;
> +
> + /* MTK clock gates also uses regmap */
> + data->regmap = device_node_to_regmap(node);
> + if (IS_ERR(data->regmap))
> + return dev_err_probe(dev, PTR_ERR(data->regmap), "Failed to get regmap\n");
> +
> + data->child_pd.np = node;
> + data->child_pd.args_count = 0;
> + ret = of_parse_phandle_with_args(node, "power-domains", "#power-domain-cells", 0,
> + &data->parent_pd);
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to parse power domain\n");
> +
> + devm_pm_runtime_enable(dev);
> + /*
> + * Do a pm_runtime_resume_and_get() to workaround a possible
> + * deadlock between clk_register() and the genpd framework.
> + */
> + ret = pm_runtime_resume_and_get(dev);
> + if (ret) {
> + dev_err_probe(dev, ret, "Failed to runtime resume device\n");
> + goto put_of_node;
> + }
> +
> + ret = mtk_clk_register_gates(dev, node, mfg_clks, ARRAY_SIZE(mfg_clks),
> + data->clk_data);
> + if (ret) {
> + dev_err_probe(dev, ret, "Failed to register clock gates\n");
> + goto put_pm_runtime;
> + }
> +
> + data->clk_26m = clk_hw_get_clk(data->clk_data->hws[CLK_MFG_26M], "26m");
> + if (IS_ERR(data->clk_26m)) {
> + dev_err_probe(dev, PTR_ERR(data->clk_26m), "Failed to get 26 MHz clock\n");
> + goto unregister_clks;
> + }
> +
> + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, data->clk_data);
> + if (ret) {
> + dev_err_probe(dev, ret, "Failed to add clk OF provider\n");
> + goto put_26m_clk;
> + }
> +
> + data->genpd.name = "mfg-top";
> + data->genpd.power_on = clk_mt8173_mfgtop_power_on;
> + data->genpd.power_off = clk_mt8173_mfgtop_power_off;
> + ret = pm_genpd_init(&data->genpd, NULL, true);
> + if (ret) {
> + dev_err_probe(dev, ret, "Failed to add power domain\n");
> + goto del_clk_provider;
> + }
> +
> + ret = of_genpd_add_provider_simple(node, &data->genpd);
> + if (ret) {
> + dev_err_probe(dev, ret, "Failed to add power domain OF provider\n");
> + goto remove_pd;
> + }
> +
> + ret = of_genpd_add_subdomain(&data->parent_pd, &data->child_pd);
> + if (ret) {
> + dev_err_probe(dev, ret, "Failed to link PM domains\n");
> + goto del_pd_provider;
> + }
> +
> + pm_runtime_put(dev);
> + return 0;
> +
> +del_pd_provider:
> + of_genpd_del_provider(node);
> +remove_pd:
> + pm_genpd_remove(&data->genpd);
> +del_clk_provider:
> + of_clk_del_provider(node);
> +put_26m_clk:
> + clk_put(data->clk_26m);
> +unregister_clks:
> + mtk_clk_unregister_gates(mfg_clks, ARRAY_SIZE(mfg_clks), data->clk_data);
> +put_pm_runtime:
> + pm_runtime_put(dev);
> +put_of_node:
> + of_node_put(data->parent_pd.np);
> + return ret;
> +}
> +
> +static void clk_mt8173_mfgtop_remove(struct platform_device *pdev)
> +{
> + struct mt8173_mfgtop_data *data = platform_get_drvdata(pdev);
> + struct device_node *node = pdev->dev.of_node;
> +
> + of_genpd_remove_subdomain(&data->parent_pd, &data->child_pd);
> + of_genpd_del_provider(node);
> + pm_genpd_remove(&data->genpd);
> + of_clk_del_provider(node);
> + clk_put(data->clk_26m);
> + mtk_clk_unregister_gates(mfg_clks, ARRAY_SIZE(mfg_clks), data->clk_data);
> +}
> +
> +static const struct of_device_id of_match_clk_mt8173_mfgtop[] = {
> + { .compatible = "mediatek,mt8173-mfgtop", .data = &mfg_desc },
Is the match data and mfg_desc used?
Brian
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, of_match_clk_mt8173_mfgtop);
> +
> +static struct platform_driver clk_mt8173_mfgtop_drv = {
> + .probe = clk_mt8173_mfgtop_probe,
> + .remove = clk_mt8173_mfgtop_remove,
> + .driver = {
> + .name = "clk-mt8173-mfgtop",
> + .of_match_table = of_match_clk_mt8173_mfgtop,
> + },
> +};
> +module_platform_driver(clk_mt8173_mfgtop_drv);
> +
> +MODULE_DESCRIPTION("MediaTek MT8173 mfgtop clock driver");
> +MODULE_LICENSE("GPL");
> --
> 2.53.0.1018.g2bb0e51243-goog
>
© 2016 - 2026 Red Hat, Inc.