Commit 43c04ed7 authored by Yassine Oudjana's avatar Yassine Oudjana Committed by Stephen Boyd
Browse files

clk: mediatek: Add drivers for MediaTek MT6735 main clock and reset drivers



Add drivers for MT6735 apmixedsys, topckgen, infracfg and pericfg
clock and reset controllers. These provide the base clocks and resets
on the platform, enough to bring up all essential blocks including
PWRAP, MSDC and peripherals (UART, I2C, SPI).

Signed-off-by: default avatarYassine Oudjana <y.oudjana@protonmail.com>
Reviewed-by: default avatarAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://lore.kernel.org/r/20241017071708.38663-3-y.oudjana@protonmail.com


Signed-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent ea1cca02
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -14533,6 +14533,10 @@ M: Yassine Oudjana <y.oudjana@protonmail.com>
L:	linux-clk@vger.kernel.org
L:	linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S:	Maintained
F:	drivers/clk/mediatek/clk-mt6735-apmixedsys.c
F:	drivers/clk/mediatek/clk-mt6735-infracfg.c
F:	drivers/clk/mediatek/clk-mt6735-pericfg.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
F:	include/dt-bindings/clock/mediatek,mt6735-pericfg.h
+9 −0
Original line number Diff line number Diff line
@@ -124,6 +124,15 @@ config COMMON_CLK_MT2712_VENCSYS
	help
	  This driver supports MediaTek MT2712 vencsys clocks.

config COMMON_CLK_MT6735
	tristate "Main clock drivers for MediaTek MT6735"
	depends on ARCH_MEDIATEK || COMPILE_TEST
	select COMMON_CLK_MEDIATEK
	help
	  This enables drivers for clocks and resets provided
	  by apmixedsys, topckgen, infracfg and pericfg on the
	  MediaTek MT6735 SoC.

config COMMON_CLK_MT6765
       bool "Clock driver for MediaTek MT6765"
       depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
+1 −0
Original line number Diff line number Diff line
@@ -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_MEDIATEK_FHCTL) += clk-fhctl.o clk-pllfh.o

obj-$(CONFIG_COMMON_CLK_MT6735) += clk-mt6735-apmixedsys.o clk-mt6735-infracfg.o clk-mt6735-pericfg.o clk-mt6735-topckgen.o
obj-$(CONFIG_COMMON_CLK_MT6765) += clk-mt6765.o
obj-$(CONFIG_COMMON_CLK_MT6765_AUDIOSYS) += clk-mt6765-audio.o
obj-$(CONFIG_COMMON_CLK_MT6765_CAMSYS) += clk-mt6765-cam.o
+138 −0
Original line number Diff line number Diff line
// 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-mtk.h"
#include "clk-pll.h"

#include <dt-bindings/clock/mediatek,mt6735-apmixedsys.h>

#define AP_PLL_CON_5		0x014
#define ARMPLL_CON0		0x200
#define ARMPLL_CON1		0x204
#define ARMPLL_PWR_CON0		0x20c
#define MAINPLL_CON0		0x210
#define MAINPLL_CON1		0x214
#define MAINPLL_PWR_CON0	0x21c
#define UNIVPLL_CON0		0x220
#define UNIVPLL_CON1		0x224
#define UNIVPLL_PWR_CON0	0x22c
#define MMPLL_CON0		0x230
#define MMPLL_CON1		0x234
#define MMPLL_PWR_CON0		0x23c
#define MSDCPLL_CON0		0x240
#define MSDCPLL_CON1		0x244
#define MSDCPLL_PWR_CON0	0x24c
#define VENCPLL_CON0		0x250
#define VENCPLL_CON1		0x254
#define VENCPLL_PWR_CON0	0x25c
#define TVDPLL_CON0		0x260
#define TVDPLL_CON1		0x264
#define TVDPLL_PWR_CON0		0x26c
#define APLL1_CON0		0x270
#define APLL1_CON1		0x274
#define APLL1_CON2		0x278
#define APLL1_PWR_CON0		0x280
#define APLL2_CON0		0x284
#define APLL2_CON1		0x288
#define APLL2_CON2		0x28c
#define APLL2_PWR_CON0		0x294

#define CON0_RST_BAR		BIT(24)

#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _rst_bar_mask,	\
	    _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg,		\
	    _tuner_en_bit, _pcw_reg, _pcwbits, _flags) {		\
		.id = _id,						\
		.name = _name,						\
		.parent_name = "clk26m",				\
		.reg = _reg,						\
		.pwr_reg = _pwr_reg,					\
		.en_mask = _en_mask,					\
		.rst_bar_mask = _rst_bar_mask,				\
		.pd_reg = _pd_reg,					\
		.pd_shift = _pd_shift,					\
		.tuner_reg = _tuner_reg,				\
		.tuner_en_reg = _tuner_en_reg,				\
		.tuner_en_bit = _tuner_en_bit,				\
		.pcw_reg = _pcw_reg,					\
		.pcw_chg_reg = _pcw_reg,				\
		.pcwbits = _pcwbits,					\
		.flags = _flags,					\
	}

static const struct mtk_pll_data apmixedsys_plls[] = {
	PLL(CLK_APMIXED_ARMPLL, "armpll", ARMPLL_CON0, ARMPLL_PWR_CON0, 0x00000001, 0, ARMPLL_CON1, 24, 0, 0, 0, ARMPLL_CON1, 21, PLL_AO),
	PLL(CLK_APMIXED_MAINPLL, "mainpll", MAINPLL_CON0, MAINPLL_PWR_CON0, 0xf0000101, CON0_RST_BAR, MAINPLL_CON1, 24, 0, 0, 0, MAINPLL_CON1, 21, HAVE_RST_BAR),
	PLL(CLK_APMIXED_UNIVPLL, "univpll", UNIVPLL_CON0, UNIVPLL_PWR_CON0, 0xfc000001, CON0_RST_BAR, UNIVPLL_CON1, 24, 0, 0, 0, UNIVPLL_CON1, 21, HAVE_RST_BAR),
	PLL(CLK_APMIXED_MMPLL, "mmpll", MMPLL_CON0, MMPLL_PWR_CON0, 0x00000001, 0, MMPLL_CON1, 24, 0, 0, 0, MMPLL_CON1, 21, 0),
	PLL(CLK_APMIXED_MSDCPLL, "msdcpll", MSDCPLL_CON0, MSDCPLL_PWR_CON0, 0x00000001, 0, MSDCPLL_CON1, 24, 0, 0, 0, MSDCPLL_CON1, 21, 0),
	PLL(CLK_APMIXED_VENCPLL, "vencpll", VENCPLL_CON0, VENCPLL_PWR_CON0, 0x00000001, CON0_RST_BAR, VENCPLL_CON1, 24, 0, 0, 0, VENCPLL_CON1, 21, HAVE_RST_BAR),
	PLL(CLK_APMIXED_TVDPLL, "tvdpll", TVDPLL_CON0, TVDPLL_PWR_CON0, 0x00000001, 0, TVDPLL_CON1, 24, 0, 0, 0, TVDPLL_CON1, 21, 0),
	PLL(CLK_APMIXED_APLL1, "apll1", APLL1_CON0, APLL1_PWR_CON0, 0x00000001, 0, APLL1_CON0, 4, APLL1_CON2, AP_PLL_CON_5, 0, APLL1_CON1, 31, 0),
	PLL(CLK_APMIXED_APLL2, "apll2", APLL2_CON0, APLL2_PWR_CON0, 0x00000001, 0, APLL2_CON0, 4, APLL2_CON2, AP_PLL_CON_5, 1, APLL2_CON1, 31, 0)
};

static int clk_mt6735_apmixed_probe(struct platform_device *pdev)
{
	void __iomem *base;
	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	struct clk_hw_onecell_data *clk_data;
	int ret;

	base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(base))
		return PTR_ERR(base);

	clk_data = mtk_alloc_clk_data(ARRAY_SIZE(apmixedsys_plls));
	if (!clk_data)
		return -ENOMEM;
	platform_set_drvdata(pdev, clk_data);

	ret = mtk_clk_register_plls(pdev->dev.of_node, apmixedsys_plls,
				   ARRAY_SIZE(apmixedsys_plls), clk_data);
	if (ret) {
		dev_err(&pdev->dev, "Failed to register PLLs: %d\n", ret);
		return ret;
	}

	ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get,
					  clk_data);
	if (ret)
		dev_err(&pdev->dev,
			"Failed to register clock provider: %d\n", ret);

	return ret;
}

static void clk_mt6735_apmixed_remove(struct platform_device *pdev)
{
	struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);

	mtk_clk_unregister_plls(apmixedsys_plls, ARRAY_SIZE(apmixedsys_plls), clk_data);
	mtk_free_clk_data(clk_data);
}

static const struct of_device_id of_match_mt6735_apmixedsys[] = {
	{ .compatible = "mediatek,mt6735-apmixedsys" },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_match_mt6735_apmixedsys);

static struct platform_driver clk_mt6735_apmixedsys = {
	.probe = clk_mt6735_apmixed_probe,
	.remove = clk_mt6735_apmixed_remove,
	.driver = {
		.name = "clk-mt6735-apmixedsys",
		.of_match_table = of_match_mt6735_apmixedsys,
	},
};
module_platform_driver(clk_mt6735_apmixedsys);

MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
MODULE_DESCRIPTION("MediaTek MT6735 apmixedsys clock driver");
MODULE_LICENSE("GPL");
+107 −0
Original line number Diff line number Diff line
// 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>
#include <dt-bindings/reset/mediatek,mt6735-infracfg.h>

#define INFRA_RST0			0x30
#define INFRA_GLOBALCON_PDN0		0x40
#define INFRA_PDN1			0x44
#define INFRA_PDN_STA			0x48

#define RST_NR_PER_BANK			32

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[] = {
	GATE_MTK(CLK_INFRA_DBG, "dbg", "axi_sel", &infra_cg_regs, 0, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_GCE, "gce", "axi_sel", &infra_cg_regs, 1, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_TRBG, "trbg", "axi_sel", &infra_cg_regs, 2, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_CPUM, "cpum", "axi_sel", &infra_cg_regs, 3, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_DEVAPC, "devapc", "axi_sel", &infra_cg_regs, 4, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_AUDIO, "audio", "aud_intbus_sel", &infra_cg_regs, 5, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_GCPU, "gcpu", "axi_sel", &infra_cg_regs, 6, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_L2C_SRAM, "l2csram", "axi_sel", &infra_cg_regs, 7, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_M4U, "m4u", "axi_sel", &infra_cg_regs, 8, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_CLDMA, "cldma", "axi_sel", &infra_cg_regs, 12, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_CONNMCU_BUS, "connmcu_bus", "axi_sel", &infra_cg_regs, 15, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_KP, "kp", "axi_sel", &infra_cg_regs, 16, &mtk_clk_gate_ops_setclr),
	GATE_MTK_FLAGS(CLK_INFRA_APXGPT, "apxgpt", "axi_sel", &infra_cg_regs, 18, &mtk_clk_gate_ops_setclr, CLK_IS_CRITICAL),
	GATE_MTK(CLK_INFRA_SEJ, "sej", "axi_sel", &infra_cg_regs, 19, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_CCIF0_AP, "ccif0ap", "axi_sel", &infra_cg_regs, 20, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_CCIF1_AP, "ccif1ap", "axi_sel", &infra_cg_regs, 21, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_PMIC_SPI, "pmicspi", "pmicspi_sel", &infra_cg_regs, 22, &mtk_clk_gate_ops_setclr),
	GATE_MTK(CLK_INFRA_PMIC_WRAP, "pmicwrap", "axi_sel", &infra_cg_regs, 23, &mtk_clk_gate_ops_setclr)
};

static u16 infracfg_rst_bank_ofs[] = { INFRA_RST0 };

static u16 infracfg_rst_idx_map[] = {
	[MT6735_INFRA_RST0_EMI_REG]		= 0 * RST_NR_PER_BANK + 0,
	[MT6735_INFRA_RST0_DRAMC0_AO]		= 0 * RST_NR_PER_BANK + 1,
	[MT6735_INFRA_RST0_AP_CIRQ_EINT]	= 0 * RST_NR_PER_BANK + 3,
	[MT6735_INFRA_RST0_APXGPT]		= 0 * RST_NR_PER_BANK + 4,
	[MT6735_INFRA_RST0_SCPSYS]		= 0 * RST_NR_PER_BANK + 5,
	[MT6735_INFRA_RST0_KP]			= 0 * RST_NR_PER_BANK + 6,
	[MT6735_INFRA_RST0_PMIC_WRAP]		= 0 * RST_NR_PER_BANK + 7,
	[MT6735_INFRA_RST0_CLDMA_AO_TOP]	= 0 * RST_NR_PER_BANK + 8,
	[MT6735_INFRA_RST0_USBSIF_TOP]		= 0 * RST_NR_PER_BANK + 9,
	[MT6735_INFRA_RST0_EMI]			= 0 * RST_NR_PER_BANK + 16,
	[MT6735_INFRA_RST0_CCIF]		= 0 * RST_NR_PER_BANK + 17,
	[MT6735_INFRA_RST0_DRAMC0]		= 0 * RST_NR_PER_BANK + 18,
	[MT6735_INFRA_RST0_EMI_AO_REG]		= 0 * RST_NR_PER_BANK + 19,
	[MT6735_INFRA_RST0_CCIF_AO]		= 0 * RST_NR_PER_BANK + 20,
	[MT6735_INFRA_RST0_TRNG]		= 0 * RST_NR_PER_BANK + 21,
	[MT6735_INFRA_RST0_SYS_CIRQ]		= 0 * RST_NR_PER_BANK + 22,
	[MT6735_INFRA_RST0_GCE]			= 0 * RST_NR_PER_BANK + 23,
	[MT6735_INFRA_RST0_M4U]			= 0 * RST_NR_PER_BANK + 24,
	[MT6735_INFRA_RST0_CCIF1]		= 0 * RST_NR_PER_BANK + 25,
	[MT6735_INFRA_RST0_CLDMA_TOP_PD]	= 0 * RST_NR_PER_BANK + 26
};

static const struct mtk_clk_rst_desc infracfg_resets = {
	.version = MTK_RST_SIMPLE,
	.rst_bank_ofs = infracfg_rst_bank_ofs,
	.rst_bank_nr = ARRAY_SIZE(infracfg_rst_bank_ofs),
	.rst_idx_map = infracfg_rst_idx_map,
	.rst_idx_map_nr = ARRAY_SIZE(infracfg_rst_idx_map)
};

static const struct mtk_clk_desc infracfg_clks = {
	.clks = infracfg_gates,
	.num_clks = ARRAY_SIZE(infracfg_gates),

	.rst_desc = &infracfg_resets
};

static const struct of_device_id of_match_mt6735_infracfg[] = {
	{ .compatible = "mediatek,mt6735-infracfg", .data = &infracfg_clks },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_match_mt6735_infracfg);

static struct platform_driver clk_mt6735_infracfg = {
	.probe = mtk_clk_simple_probe,
	.remove = mtk_clk_simple_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");
Loading