brintos

brintos / linux-shallow public Read only

0
0
Text · 6.4 KiB · 91665d7 Raw
214 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2022 Collabora Ltd.4 * Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>5 */6 7#include <dt-bindings/clock/mediatek,mt6795-clk.h>8#include <linux/module.h>9#include <linux/platform_device.h>10#include "clk-fhctl.h"11#include "clk-mtk.h"12#include "clk-pll.h"13#include "clk-pllfh.h"14 15#define REG_REF2USB		0x816#define REG_AP_PLL_CON7		0x1c17 #define MD1_MTCMOS_OFF		BIT(0)18 #define MD1_MEM_OFF		BIT(1)19 #define MD1_CLK_OFF		BIT(4)20 #define MD1_ISO_OFF		BIT(8)21 22#define MT6795_PLL_FMAX		(3000UL * MHZ)23#define MT6795_CON0_EN		BIT(0)24#define MT6795_CON0_RST_BAR	BIT(24)25 26#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,	\27	    _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) {	\28		.id = _id,						\29		.name = _name,						\30		.reg = _reg,						\31		.pwr_reg = _pwr_reg,					\32		.en_mask = MT6795_CON0_EN | _en_mask,			\33		.flags = _flags,					\34		.rst_bar_mask = MT6795_CON0_RST_BAR,			\35		.fmax = MT6795_PLL_FMAX,				\36		.pcwbits = _pcwbits,					\37		.pd_reg = _pd_reg,					\38		.pd_shift = _pd_shift,					\39		.tuner_reg = _tuner_reg,				\40		.pcw_reg = _pcw_reg,					\41		.pcw_shift = _pcw_shift,				\42		.div_table = NULL,					\43		.pll_en_bit = 0,					\44	}45 46static const struct mtk_pll_data plls[] = {47	PLL(CLK_APMIXED_ARMCA53PLL, "armca53pll", 0x200, 0x20c, 0, PLL_AO,48	    21, 0x204, 24, 0x0, 0x204, 0),49	PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR,50	    21, 0x220, 4, 0x0, 0x224, 0),51	PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000101, HAVE_RST_BAR,52	    7, 0x230, 4, 0x0, 0x234, 14),53	PLL(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0, 0, 21, 0x244, 24, 0x0, 0x244, 0),54	PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0, 0, 21, 0x250, 4, 0x0, 0x254, 0),55	PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0, 0, 21, 0x260, 4, 0x0, 0x264, 0),56	PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0, 0, 21, 0x270, 4, 0x0, 0x274, 0),57	PLL(CLK_APMIXED_MPLL, "mpll", 0x280, 0x28c, 0, 0, 21, 0x280, 4, 0x0, 0x284, 0),58	PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0, 0, 21, 0x290, 4, 0x0, 0x294, 0),59	PLL(CLK_APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0, 0, 31, 0x2a0, 4, 0x2a8, 0x2a4, 0),60	PLL(CLK_APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0, 0, 31, 0x2b4, 4, 0x2bc, 0x2b8, 0),61};62 63enum fh_pll_id {64	FH_CA53PLL_LL,65	FH_CA53PLL_BL,66	FH_MAINPLL,67	FH_MPLL,68	FH_MSDCPLL,69	FH_MMPLL,70	FH_VENCPLL,71	FH_TVDPLL,72	FH_VCODECPLL,73	FH_NR_FH,74};75 76#define _FH(_pllid, _fhid, _slope, _offset) {				\77		.data = {						\78			.pll_id = _pllid,				\79			.fh_id = _fhid,					\80			.fh_ver = FHCTL_PLLFH_V1,			\81			.fhx_offset = _offset,				\82			.dds_mask = GENMASK(21, 0),			\83			.slope0_value = _slope,				\84			.slope1_value = _slope,				\85			.sfstrx_en = BIT(2),				\86			.frddsx_en = BIT(1),				\87			.fhctlx_en = BIT(0),				\88			.tgl_org = BIT(31),				\89			.dvfs_tri = BIT(31),				\90			.pcwchg = BIT(31),				\91			.dt_val = 0x0,					\92			.df_val = 0x9,					\93			.updnlmt_shft = 16,				\94			.msk_frddsx_dys = GENMASK(23, 20),		\95			.msk_frddsx_dts = GENMASK(19, 16),		\96		},							\97	}98 99#define FH(_pllid, _fhid, _offset)	_FH(_pllid, _fhid, 0x6003c97, _offset)100#define FH_M(_pllid, _fhid, _offset)	_FH(_pllid, _fhid, 0x6000140, _offset)101 102static struct mtk_pllfh_data pllfhs[] = {103	FH(CLK_APMIXED_ARMCA53PLL, FH_CA53PLL_BL, 0x38),104	FH(CLK_APMIXED_MAINPLL, FH_MAINPLL, 0x60),105	FH_M(CLK_APMIXED_MPLL, FH_MPLL, 0x74),106	FH(CLK_APMIXED_MSDCPLL, FH_MSDCPLL, 0x88),107	FH(CLK_APMIXED_MMPLL, FH_MMPLL, 0x9c),108	FH(CLK_APMIXED_VENCPLL, FH_VENCPLL, 0xb0),109	FH(CLK_APMIXED_TVDPLL, FH_TVDPLL, 0xc4),110	FH(CLK_APMIXED_VCODECPLL, FH_VCODECPLL, 0xd8),111};112 113static void clk_mt6795_apmixed_setup_md1(void __iomem *base)114{115	void __iomem *reg = base + REG_AP_PLL_CON7;116 117	/* Turn on MD1 internal clock */118	writel(readl(reg) & ~MD1_CLK_OFF, reg);119 120	/* Unlock MD1's MTCMOS power path */121	writel(readl(reg) & ~MD1_MTCMOS_OFF, reg);122 123	/* Turn on ISO */124	writel(readl(reg) & ~MD1_ISO_OFF, reg);125 126	/* Turn on memory */127	writel(readl(reg) & ~MD1_MEM_OFF, reg);128}129 130static const struct of_device_id of_match_clk_mt6795_apmixed[] = {131	{ .compatible = "mediatek,mt6795-apmixedsys" },132	{ /* sentinel */ }133};134MODULE_DEVICE_TABLE(of, of_match_clk_mt6795_apmixed);135 136static int clk_mt6795_apmixed_probe(struct platform_device *pdev)137{138	struct clk_hw_onecell_data *clk_data;139	struct device *dev = &pdev->dev;140	struct device_node *node = dev->of_node;141	const u8 *fhctl_node = "mediatek,mt6795-fhctl";142	void __iomem *base;143	struct clk_hw *hw;144	int ret;145 146	base = devm_platform_ioremap_resource(pdev, 0);147	if (IS_ERR(base))148		return PTR_ERR(base);149 150	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);151	if (!clk_data)152		return -ENOMEM;153 154	fhctl_parse_dt(fhctl_node, pllfhs, ARRAY_SIZE(pllfhs));155	ret = mtk_clk_register_pllfhs(node, plls, ARRAY_SIZE(plls),156				      pllfhs, ARRAY_SIZE(pllfhs), clk_data);157	if (ret)158		goto free_clk_data;159 160	hw = mtk_clk_register_ref2usb_tx("ref2usb_tx", "clk26m", base + REG_REF2USB);161	if (IS_ERR(hw)) {162		ret = PTR_ERR(hw);163		dev_err(dev, "Failed to register ref2usb_tx: %d\n", ret);164		goto unregister_plls;165	}166	clk_data->hws[CLK_APMIXED_REF2USB_TX] = hw;167 168	ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);169	if (ret) {170		dev_err(dev, "Cannot register clock provider: %d\n", ret);171		goto unregister_ref2usb;172	}173 174	/* Setup MD1 to avoid random crashes */175	dev_dbg(dev, "Performing initial setup for MD1\n");176	clk_mt6795_apmixed_setup_md1(base);177 178	return 0;179 180unregister_ref2usb:181	mtk_clk_unregister_ref2usb_tx(clk_data->hws[CLK_APMIXED_REF2USB_TX]);182unregister_plls:183	mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs,184				  ARRAY_SIZE(pllfhs), clk_data);185free_clk_data:186	mtk_free_clk_data(clk_data);187	return ret;188}189 190static void clk_mt6795_apmixed_remove(struct platform_device *pdev)191{192	struct device_node *node = pdev->dev.of_node;193	struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);194 195	of_clk_del_provider(node);196	mtk_clk_unregister_ref2usb_tx(clk_data->hws[CLK_APMIXED_REF2USB_TX]);197	mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs,198				  ARRAY_SIZE(pllfhs), clk_data);199	mtk_free_clk_data(clk_data);200}201 202static struct platform_driver clk_mt6795_apmixed_drv = {203	.probe = clk_mt6795_apmixed_probe,204	.remove = clk_mt6795_apmixed_remove,205	.driver = {206		.name = "clk-mt6795-apmixed",207		.of_match_table = of_match_clk_mt6795_apmixed,208	},209};210module_platform_driver(clk_mt6795_apmixed_drv);211 212MODULE_DESCRIPTION("MediaTek MT6795 apmixed clocks driver");213MODULE_LICENSE("GPL");214