1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2022 MediaTek Inc.
4 * Copyright (c) 2023 Collabora Ltd.
7 #include <dt-bindings/clock/mediatek,mt8365-clk.h>
10 #include <linux/platform_device.h>
15 #define MT8365_PLL_FMAX (3800UL * MHZ)
16 #define MT8365_PLL_FMIN (1500UL * MHZ)
17 #define CON0_MT8365_RST_BAR BIT(23)
19 #define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
20 _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \
21 _tuner_en_bit, _pcw_reg, _pcw_shift, _div_table, \
22 _rst_bar_mask, _pcw_chg_reg) { \
26 .pwr_reg = _pwr_reg, \
27 .en_mask = _en_mask, \
29 .rst_bar_mask = _rst_bar_mask, \
30 .fmax = MT8365_PLL_FMAX, \
31 .fmin = MT8365_PLL_FMIN, \
32 .pcwbits = _pcwbits, \
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 = _pcw_shift, \
41 .pcw_chg_reg = _pcw_chg_reg, \
42 .div_table = _div_table, \
45 #define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
46 _pd_reg, _pd_shift, _tuner_reg, \
47 _tuner_en_reg, _tuner_en_bit, _pcw_reg, \
48 _pcw_shift, _rst_bar_mask, _pcw_chg_reg) \
49 PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \
50 _pcwbits, _pd_reg, _pd_shift, \
51 _tuner_reg, _tuner_en_reg, _tuner_en_bit, \
52 _pcw_reg, _pcw_shift, NULL, _rst_bar_mask, \
55 static const struct mtk_pll_div_table armpll_div_table[] = {
56 { .div
= 0, .freq
= MT8365_PLL_FMAX
},
57 { .div
= 1, .freq
= 1500 * MHZ
},
58 { .div
= 2, .freq
= 750 * MHZ
},
59 { .div
= 3, .freq
= 375 * MHZ
},
60 { .div
= 4, .freq
= 182500000 },
64 static const struct mtk_pll_div_table mfgpll_div_table
[] = {
65 { .div
= 0, .freq
= MT8365_PLL_FMAX
},
66 { .div
= 1, .freq
= 1600 * MHZ
},
67 { .div
= 2, .freq
= 800 * MHZ
},
68 { .div
= 3, .freq
= 400 * MHZ
},
69 { .div
= 4, .freq
= 200 * MHZ
},
73 static const struct mtk_pll_div_table dsppll_div_table
[] = {
74 { .div
= 0, .freq
= MT8365_PLL_FMAX
},
75 { .div
= 1, .freq
= 1600 * MHZ
},
76 { .div
= 2, .freq
= 600 * MHZ
},
77 { .div
= 3, .freq
= 400 * MHZ
},
78 { .div
= 4, .freq
= 200 * MHZ
},
82 static const struct mtk_pll_data plls
[] = {
83 PLL_B(CLK_APMIXED_ARMPLL
, "armpll", 0x030C, 0x0318, 0x00000001, PLL_AO
,
84 22, 0x0310, 24, 0, 0, 0, 0x0310, 0, armpll_div_table
, 0, 0),
85 PLL(CLK_APMIXED_MAINPLL
, "mainpll", 0x0228, 0x0234, 0xFF000001,
86 HAVE_RST_BAR
, 22, 0x022C, 24, 0, 0, 0, 0x022C, 0, CON0_MT8365_RST_BAR
, 0),
87 PLL(CLK_APMIXED_UNIVPLL
, "univpll2", 0x0208, 0x0214, 0xFF000001,
88 HAVE_RST_BAR
, 22, 0x020C, 24, 0, 0, 0, 0x020C, 0, CON0_MT8365_RST_BAR
, 0),
89 PLL_B(CLK_APMIXED_MFGPLL
, "mfgpll", 0x0218, 0x0224, 0x00000001, 0, 22,
90 0x021C, 24, 0, 0, 0, 0x021C, 0, mfgpll_div_table
, 0, 0),
91 PLL(CLK_APMIXED_MSDCPLL
, "msdcpll", 0x0350, 0x035C, 0x00000001, 0, 22,
92 0x0354, 24, 0, 0, 0, 0x0354, 0, 0, 0),
93 PLL(CLK_APMIXED_MMPLL
, "mmpll", 0x0330, 0x033C, 0x00000001, 0, 22,
94 0x0334, 24, 0, 0, 0, 0x0334, 0, 0, 0),
95 PLL(CLK_APMIXED_APLL1
, "apll1", 0x031C, 0x032C, 0x00000001, 0, 32,
96 0x0320, 24, 0x0040, 0x000C, 0, 0x0324, 0, 0, 0x0320),
97 PLL(CLK_APMIXED_APLL2
, "apll2", 0x0360, 0x0370, 0x00000001, 0, 32,
98 0x0364, 24, 0x004C, 0x000C, 5, 0x0368, 0, 0, 0x0364),
99 PLL(CLK_APMIXED_LVDSPLL
, "lvdspll", 0x0374, 0x0380, 0x00000001, 0, 22,
100 0x0378, 24, 0, 0, 0, 0x0378, 0, 0, 0),
101 PLL_B(CLK_APMIXED_DSPPLL
, "dsppll", 0x0390, 0x039C, 0x00000001, 0, 22,
102 0x0394, 24, 0, 0, 0, 0x0394, 0, dsppll_div_table
, 0, 0),
103 PLL(CLK_APMIXED_APUPLL
, "apupll", 0x03A0, 0x03AC, 0x00000001, 0, 22,
104 0x03A4, 24, 0, 0, 0, 0x03A4, 0, 0, 0),
107 static int clk_mt8365_apmixed_probe(struct platform_device
*pdev
)
110 struct clk_hw_onecell_data
*clk_data
;
111 struct device_node
*node
= pdev
->dev
.of_node
;
112 struct device
*dev
= &pdev
->dev
;
116 base
= devm_platform_ioremap_resource(pdev
, 0);
118 return PTR_ERR(base
);
120 clk_data
= mtk_devm_alloc_clk_data(dev
, CLK_APMIXED_NR_CLK
);
124 hw
= devm_clk_hw_register_gate(dev
, "univ_en", "univpll2", 0,
125 base
+ 0x204, 0, 0, NULL
);
128 clk_data
->hws
[CLK_APMIXED_UNIV_EN
] = hw
;
130 hw
= devm_clk_hw_register_gate(dev
, "usb20_en", "univ_en", 0,
131 base
+ 0x204, 1, 0, NULL
);
134 clk_data
->hws
[CLK_APMIXED_USB20_EN
] = hw
;
136 ret
= mtk_clk_register_plls(node
, plls
, ARRAY_SIZE(plls
), clk_data
);
140 ret
= of_clk_add_hw_provider(node
, of_clk_hw_onecell_get
, clk_data
);
142 goto unregister_plls
;
147 mtk_clk_unregister_plls(plls
, ARRAY_SIZE(plls
), clk_data
);
152 static const struct of_device_id of_match_clk_mt8365_apmixed
[] = {
153 { .compatible
= "mediatek,mt8365-apmixedsys" },
156 MODULE_DEVICE_TABLE(of
, of_match_clk_mt8365_apmixed
);
158 static struct platform_driver clk_mt8365_apmixed_drv
= {
159 .probe
= clk_mt8365_apmixed_probe
,
161 .name
= "clk-mt8365-apmixed",
162 .of_match_table
= of_match_clk_mt8365_apmixed
,
165 builtin_platform_driver(clk_mt8365_apmixed_drv
)
167 MODULE_DESCRIPTION("MediaTek MT8365 apmixedsys clocks driver");
168 MODULE_LICENSE("GPL");