diff mbox series

[12/13] clk: mediatek: Add driver for MT6735 infracfg

Message ID 20220504122601.335495-13-y.oudjana@protonmail.com (mailing list archive)
State New
Headers show
Series Mediatek MT6735 main clock and reset drivers | expand

Commit Message

Yassine Oudjana May 4, 2022, 12:26 p.m. UTC
From: Yassine Oudjana <y.oudjana@protonmail.com>

Add a driver for MT6735 infracfg clock gates and resets.

Signed-off-by: Yassine Oudjana <y.oudjana@protonmail.com>
---
 MAINTAINERS                                |   1 +
 drivers/clk/mediatek/Kconfig               |   7 +
 drivers/clk/mediatek/Makefile              |   1 +
 drivers/clk/mediatek/clk-mt6735-infracfg.c | 265 +++++++++++++++++++++
 4 files changed, 274 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt6735-infracfg.c
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index d9d6449f910e..8662f12f34a2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -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
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 7c19e2d7bb02..62195e5d90a0 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -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
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index e8e892c4145f..e5c1da6e2711 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -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
diff --git a/drivers/clk/mediatek/clk-mt6735-infracfg.c b/drivers/clk/mediatek/clk-mt6735-infracfg.c
new file mode 100644
index 000000000000..ce1a5739b3b2
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6735-infracfg.c
@@ -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");