@@ -12443,6 +12443,7 @@ L: linux-clk@vger.kernel.org
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/clk/mediatek/clk-mt6735-apmixed.c
+F: drivers/clk/mediatek/clk-mt6735-infracfg.c
F: drivers/clk/mediatek/clk-mt6735-topckgen.c
F: include/dt-bindings/clock/mediatek,mt6735-apmixedsys.h
F: include/dt-bindings/clock/mediatek,mt6735-infracfg.h
@@ -124,6 +124,13 @@ config COMMON_CLK_MT6735_APMIXED
help
This driver supports MediaTek MT6735 apmixedsys clocks.
+config COMMON_CLK_MT6735_INFRACFG
+ tristate "Clock driver for MediaTek MT6735 infracfg"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ select COMMON_CLK_MEDIATEK
+ help
+ This driver supports MediaTek MT6735 infracfg clocks and resets.
+
config COMMON_CLK_MT6735_TOPCKGEN
tristate "Clock driver for MediaTek MT6735 topckgen"
depends on ARCH_MEDIATEK || COMPILE_TEST
@@ -2,6 +2,7 @@
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_MT6735_APMIXED) += clk-mt6735-apmixed.o
+obj-$(CONFIG_COMMON_CLK_MT6735_INFRACFG) += clk-mt6735-infracfg.o
obj-$(CONFIG_COMMON_CLK_MT6735_TOPCKGEN) += clk-mt6735-topckgen.o
obj-$(CONFIG_COMMON_CLK_MT6765) += clk-mt6765.o
obj-$(CONFIG_COMMON_CLK_MT6765_AUDIOSYS) += clk-mt6765-audio.o
new file mode 100644
@@ -0,0 +1,265 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+#include <dt-bindings/clock/mediatek,mt6735-infracfg.h>
+
+#define INFRA_RST0 0x30
+#define INFRA_GLOBALCON_PDN0 0x40
+#define INFRA_PDN1 0x44
+#define INFRA_PDN_STA 0x48
+
+struct mt6735_infracfg {
+ struct clk_onecell_data *clk_data;
+ struct mtk_reset *reset_data;
+};
+
+static struct mtk_gate_regs infra_cg_regs = {
+ .set_ofs = INFRA_GLOBALCON_PDN0,
+ .clr_ofs = INFRA_PDN1,
+ .sta_ofs = INFRA_PDN_STA,
+};
+
+static const struct mtk_gate infracfg_gates[] = {
+ {
+ .id = DBGCLK,
+ .name = "dbgclk",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 0,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = GCE,
+ .name = "gce",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 1,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = TRBG,
+ .name = "trbg",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 2,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = CPUM,
+ .name = "cpum",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 3,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = DEVAPC,
+ .name = "devapc",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 4,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = AUDIO,
+ .name = "audio",
+ .parent_name = "aud_intbus_sel",
+ .regs = &infra_cg_regs,
+ .shift = 5,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = GCPU,
+ .name = "gcpu",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 6,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = L2C_SRAM,
+ .name = "l2csram",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 7,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = M4U,
+ .name = "m4u",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 8,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = CLDMA,
+ .name = "cldma",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 12,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = CONNMCU_BUS,
+ .name = "connmcu_bus",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 15,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = KP,
+ .name = "kp",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 16,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = APXGPT,
+ .name = "apxgpt",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 18,
+ .ops = &mtk_clk_gate_ops_setclr,
+ .flags = CLK_IS_CRITICAL
+ },
+ {
+ .id = SEJ,
+ .name = "sej",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 19,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = CCIF0_AP,
+ .name = "ccif0ap",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 20,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = CCIF1_AP,
+ .name = "ccif1ap",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 21,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = PMIC_SPI,
+ .name = "pmicspi",
+ .parent_name = "pmicspi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 22,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+ {
+ .id = PMIC_WRAP,
+ .name = "pmicwrap",
+ .parent_name = "axi_sel",
+ .regs = &infra_cg_regs,
+ .shift = 23,
+ .ops = &mtk_clk_gate_ops_setclr
+ },
+};
+
+int clk_mt6735_infracfg_probe(struct platform_device *pdev)
+{
+ void __iomem *base;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct mt6735_infracfg *infracfg;
+ int ret;
+
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ infracfg = devm_kmalloc(&pdev->dev, sizeof(struct mt6735_infracfg),
+ GFP_KERNEL);
+ if (!infracfg)
+ return -ENOMEM;
+
+ infracfg->clk_data = mtk_alloc_clk_data(ARRAY_SIZE(infracfg_gates));
+ if (!infracfg->clk_data)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, infracfg);
+
+ ret = mtk_clk_register_gates_with_dev(pdev->dev.of_node, infracfg_gates,
+ ARRAY_SIZE(infracfg_gates),
+ infracfg->clk_data, &pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register gates: %pe\n",
+ ERR_PTR(ret));
+ goto free_clk_data;
+ }
+
+ ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
+ infracfg->clk_data);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register clock provider: %pe\n",
+ ERR_PTR(ret));
+ goto unregister_gates;
+ }
+
+ infracfg->reset_data = mtk_register_reset_controller(pdev->dev.of_node,
+ 1, INFRA_RST0);
+ if (IS_ERR(infracfg->reset_data)) {
+ dev_err(&pdev->dev, "Failed to register reset controller: %pe\n",
+ infracfg->reset_data);
+ return PTR_ERR(infracfg->reset_data);
+ }
+
+ return 0;
+
+unregister_gates:
+ mtk_clk_unregister_gates(infracfg_gates, ARRAY_SIZE(infracfg_gates),
+ infracfg->clk_data);
+free_clk_data:
+ mtk_free_clk_data(infracfg->clk_data);
+
+ return ret;
+}
+
+int clk_mt6735_infracfg_remove(struct platform_device *pdev)
+{
+ struct mt6735_infracfg *infracfg = platform_get_drvdata(pdev);
+
+ mtk_unregister_reset_controller(infracfg->reset_data);
+ of_clk_del_provider(pdev->dev.of_node);
+ mtk_clk_unregister_gates(infracfg_gates, ARRAY_SIZE(infracfg_gates),
+ infracfg->clk_data);
+ mtk_free_clk_data(infracfg->clk_data);
+
+ return 0;
+}
+
+static const struct of_device_id of_match_mt6735_infracfg[] = {
+ { .compatible = "mediatek,mt6735-infracfg" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver clk_mt6735_infracfg = {
+ .probe = clk_mt6735_infracfg_probe,
+ .remove = clk_mt6735_infracfg_remove,
+ .driver = {
+ .name = "clk-mt6735-infracfg",
+ .of_match_table = of_match_mt6735_infracfg,
+ },
+};
+module_platform_driver(clk_mt6735_infracfg);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("Mediatek MT6735 infracfg clock and reset driver");
+MODULE_LICENSE("GPL");