198 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2//3// Copyright (c) 2022 MediaTek Inc.4// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>5 6#include <linux/clk-provider.h>7#include <linux/platform_device.h>8#include <dt-bindings/clock/mt8186-clk.h>9 10#include "clk-fhctl.h"11#include "clk-mtk.h"12#include "clk-pll.h"13#include "clk-pllfh.h"14 15#define MT8186_PLL_FMAX (3800UL * MHZ)16#define MT8186_PLL_FMIN (1500UL * MHZ)17#define MT8186_INTEGER_BITS (8)18 19#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \20 _rst_bar_mask, _pcwbits, _pd_reg, _pd_shift, \21 _tuner_reg, _tuner_en_reg, _tuner_en_bit, \22 _pcw_reg) { \23 .id = _id, \24 .name = _name, \25 .reg = _reg, \26 .pwr_reg = _pwr_reg, \27 .en_mask = _en_mask, \28 .flags = _flags, \29 .rst_bar_mask = _rst_bar_mask, \30 .fmax = MT8186_PLL_FMAX, \31 .fmin = MT8186_PLL_FMIN, \32 .pcwbits = _pcwbits, \33 .pcwibits = MT8186_INTEGER_BITS, \34 .pd_reg = _pd_reg, \35 .pd_shift = _pd_shift, \36 .tuner_reg = _tuner_reg, \37 .tuner_en_reg = _tuner_en_reg, \38 .tuner_en_bit = _tuner_en_bit, \39 .pcw_reg = _pcw_reg, \40 .pcw_shift = 0, \41 .pcw_chg_reg = 0, \42 .en_reg = 0, \43 .pll_en_bit = 0, \44 }45 46static const struct mtk_pll_data plls[] = {47 /*48 * armpll_ll/armpll_bl/ccipll are main clock source of AP MCU,49 * should not be closed in Linux world.50 */51 PLL(CLK_APMIXED_ARMPLL_LL, "armpll_ll", 0x0204, 0x0210, 0,52 PLL_AO, 0, 22, 0x0208, 24, 0, 0, 0, 0x0208),53 PLL(CLK_APMIXED_ARMPLL_BL, "armpll_bl", 0x0214, 0x0220, 0,54 PLL_AO, 0, 22, 0x0218, 24, 0, 0, 0, 0x0218),55 PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x0224, 0x0230, 0,56 PLL_AO, 0, 22, 0x0228, 24, 0, 0, 0, 0x0228),57 PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0244, 0x0250, 0xff000000,58 HAVE_RST_BAR, BIT(23), 22, 0x0248, 24, 0, 0, 0, 0x0248),59 PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0324, 0x0330, 0xff000000,60 HAVE_RST_BAR, BIT(23), 22, 0x0328, 24, 0, 0, 0, 0x0328),61 PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x038C, 0x0398, 0,62 0, 0, 22, 0x0390, 24, 0, 0, 0, 0x0390),63 PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0254, 0x0260, 0,64 0, 0, 22, 0x0258, 24, 0, 0, 0, 0x0258),65 PLL(CLK_APMIXED_NNAPLL, "nnapll", 0x035C, 0x0368, 0,66 0, 0, 22, 0x0360, 24, 0, 0, 0, 0x0360),67 PLL(CLK_APMIXED_NNA2PLL, "nna2pll", 0x036C, 0x0378, 0,68 0, 0, 22, 0x0370, 24, 0, 0, 0, 0x0370),69 PLL(CLK_APMIXED_ADSPPLL, "adsppll", 0x0304, 0x0310, 0,70 0, 0, 22, 0x0308, 24, 0, 0, 0, 0x0308),71 PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0314, 0x0320, 0,72 0, 0, 22, 0x0318, 24, 0, 0, 0, 0x0318),73 PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0264, 0x0270, 0,74 0, 0, 22, 0x0268, 24, 0, 0, 0, 0x0268),75 PLL(CLK_APMIXED_APLL1, "apll1", 0x0334, 0x0344, 0,76 0, 0, 32, 0x0338, 24, 0x0040, 0x000C, 0, 0x033C),77 PLL(CLK_APMIXED_APLL2, "apll2", 0x0348, 0x0358, 0,78 0, 0, 32, 0x034C, 24, 0x0044, 0x000C, 5, 0x0350),79};80 81enum fh_pll_id {82 FH_ARMPLL_LL,83 FH_ARMPLL_BL,84 FH_CCIPLL,85 FH_MAINPLL,86 FH_MMPLL,87 FH_TVDPLL,88 FH_RESERVE6,89 FH_ADSPPLL,90 FH_MFGPLL,91 FH_NNAPLL,92 FH_NNA2PLL,93 FH_MSDCPLL,94 FH_RESERVE12,95 FH_NR_FH,96};97 98#define FH(_pllid, _fhid, _offset) { \99 .data = { \100 .pll_id = _pllid, \101 .fh_id = _fhid, \102 .fh_ver = FHCTL_PLLFH_V2, \103 .fhx_offset = _offset, \104 .dds_mask = GENMASK(21, 0), \105 .slope0_value = 0x6003c97, \106 .slope1_value = 0x6003c97, \107 .sfstrx_en = BIT(2), \108 .frddsx_en = BIT(1), \109 .fhctlx_en = BIT(0), \110 .tgl_org = BIT(31), \111 .dvfs_tri = BIT(31), \112 .pcwchg = BIT(31), \113 .dt_val = 0x0, \114 .df_val = 0x9, \115 .updnlmt_shft = 16, \116 .msk_frddsx_dys = GENMASK(23, 20), \117 .msk_frddsx_dts = GENMASK(19, 16), \118 }, \119 }120 121static struct mtk_pllfh_data pllfhs[] = {122 FH(CLK_APMIXED_ARMPLL_LL, FH_ARMPLL_LL, 0x003C),123 FH(CLK_APMIXED_ARMPLL_BL, FH_ARMPLL_BL, 0x0050),124 FH(CLK_APMIXED_CCIPLL, FH_CCIPLL, 0x0064),125 FH(CLK_APMIXED_MAINPLL, FH_MAINPLL, 0x0078),126 FH(CLK_APMIXED_MMPLL, FH_MMPLL, 0x008C),127 FH(CLK_APMIXED_TVDPLL, FH_TVDPLL, 0x00A0),128 FH(CLK_APMIXED_ADSPPLL, FH_ADSPPLL, 0x00C8),129 FH(CLK_APMIXED_MFGPLL, FH_MFGPLL, 0x00DC),130 FH(CLK_APMIXED_NNAPLL, FH_NNAPLL, 0x00F0),131 FH(CLK_APMIXED_NNA2PLL, FH_NNA2PLL, 0x0104),132 FH(CLK_APMIXED_MSDCPLL, FH_MSDCPLL, 0x0118),133};134 135static const struct of_device_id of_match_clk_mt8186_apmixed[] = {136 { .compatible = "mediatek,mt8186-apmixedsys", },137 {}138};139MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_apmixed);140 141static int clk_mt8186_apmixed_probe(struct platform_device *pdev)142{143 struct clk_hw_onecell_data *clk_data;144 struct device_node *node = pdev->dev.of_node;145 const u8 *fhctl_node = "mediatek,mt8186-fhctl";146 int r;147 148 clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);149 if (!clk_data)150 return -ENOMEM;151 152 fhctl_parse_dt(fhctl_node, pllfhs, ARRAY_SIZE(pllfhs));153 154 r = mtk_clk_register_pllfhs(node, plls, ARRAY_SIZE(plls),155 pllfhs, ARRAY_SIZE(pllfhs), clk_data);156 if (r)157 goto free_apmixed_data;158 159 r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);160 if (r)161 goto unregister_plls;162 163 platform_set_drvdata(pdev, clk_data);164 165 return r;166 167unregister_plls:168 mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs,169 ARRAY_SIZE(pllfhs), clk_data);170free_apmixed_data:171 mtk_free_clk_data(clk_data);172 return r;173}174 175static void clk_mt8186_apmixed_remove(struct platform_device *pdev)176{177 struct device_node *node = pdev->dev.of_node;178 struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);179 180 of_clk_del_provider(node);181 mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs,182 ARRAY_SIZE(pllfhs), clk_data);183 mtk_free_clk_data(clk_data);184}185 186static struct platform_driver clk_mt8186_apmixed_drv = {187 .probe = clk_mt8186_apmixed_probe,188 .remove = clk_mt8186_apmixed_remove,189 .driver = {190 .name = "clk-mt8186-apmixed",191 .of_match_table = of_match_clk_mt8186_apmixed,192 },193};194module_platform_driver(clk_mt8186_apmixed_drv);195 196MODULE_DESCRIPTION("MediaTek MT8186 apmixedsys clocks driver");197MODULE_LICENSE("GPL");198