1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (c) 2021 MediaTek Inc. |
4 | * Author: Sam Shih <sam.shih@mediatek.com> |
5 | * Author: Wenzhen Yu <wenzhen.yu@mediatek.com> |
6 | */ |
7 | |
8 | #include <linux/clk-provider.h> |
9 | #include <linux/mod_devicetable.h> |
10 | #include <linux/platform_device.h> |
11 | #include "clk-mtk.h" |
12 | #include "clk-gate.h" |
13 | #include "clk-mux.h" |
14 | |
15 | #include <dt-bindings/clock/mt7986-clk.h> |
16 | #include <linux/clk.h> |
17 | |
18 | static DEFINE_SPINLOCK(mt7986_clk_lock); |
19 | |
20 | static const struct mtk_fixed_clk top_fixed_clks[] = { |
21 | FIXED_CLK(CLK_TOP_XTAL, "top_xtal" , "clkxtal" , 40000000), |
22 | FIXED_CLK(CLK_TOP_JTAG, "top_jtag" , "clkxtal" , 50000000), |
23 | }; |
24 | |
25 | static const struct mtk_fixed_factor top_divs[] = { |
26 | /* XTAL */ |
27 | FACTOR(CLK_TOP_XTAL_D2, "top_xtal_d2" , "top_xtal" , 1, 2), |
28 | FACTOR(CLK_TOP_RTC_32K, "top_rtc_32k" , "top_xtal" , 1, 1250), |
29 | FACTOR(CLK_TOP_RTC_32P7K, "top_rtc_32p7k" , "top_xtal" , 1, 1220), |
30 | /* MPLL */ |
31 | FACTOR(CLK_TOP_MPLL_D2, "top_mpll_d2" , "mpll" , 1, 2), |
32 | FACTOR(CLK_TOP_MPLL_D4, "top_mpll_d4" , "mpll" , 1, 4), |
33 | FACTOR(CLK_TOP_MPLL_D8, "top_mpll_d8" , "mpll" , 1, 8), |
34 | FACTOR(CLK_TOP_MPLL_D8_D2, "top_mpll_d8_d2" , "mpll" , 1, 16), |
35 | FACTOR(CLK_TOP_MPLL_D3_D2, "top_mpll_d3_d2" , "mpll" , 1, 6), |
36 | /* MMPLL */ |
37 | FACTOR(CLK_TOP_MMPLL_D2, "top_mmpll_d2" , "mmpll" , 1, 2), |
38 | FACTOR(CLK_TOP_MMPLL_D4, "top_mmpll_d4" , "mmpll" , 1, 4), |
39 | FACTOR(CLK_TOP_MMPLL_D8, "top_mmpll_d8" , "mmpll" , 1, 8), |
40 | FACTOR(CLK_TOP_MMPLL_D8_D2, "top_mmpll_d8_d2" , "mmpll" , 1, 16), |
41 | FACTOR(CLK_TOP_MMPLL_D3_D8, "top_mmpll_d3_d8" , "mmpll" , 1, 24), |
42 | FACTOR(CLK_TOP_MMPLL_U2PHY, "top_mmpll_u2phy" , "mmpll" , 1, 30), |
43 | /* APLL2 */ |
44 | FACTOR(CLK_TOP_APLL2_D4, "top_apll2_d4" , "apll2" , 1, 4), |
45 | /* NET1PLL */ |
46 | FACTOR(CLK_TOP_NET1PLL_D4, "top_net1pll_d4" , "net1pll" , 1, 4), |
47 | FACTOR(CLK_TOP_NET1PLL_D5, "top_net1pll_d5" , "net1pll" , 1, 5), |
48 | FACTOR(CLK_TOP_NET1PLL_D5_D2, "top_net1pll_d5_d2" , "net1pll" , 1, 10), |
49 | FACTOR(CLK_TOP_NET1PLL_D5_D4, "top_net1pll_d5_d4" , "net1pll" , 1, 20), |
50 | FACTOR(CLK_TOP_NET1PLL_D8_D2, "top_net1pll_d8_d2" , "net1pll" , 1, 16), |
51 | FACTOR(CLK_TOP_NET1PLL_D8_D4, "top_net1pll_d8_d4" , "net1pll" , 1, 32), |
52 | /* NET2PLL */ |
53 | FACTOR(CLK_TOP_NET2PLL_D4, "top_net2pll_d4" , "net2pll" , 1, 4), |
54 | FACTOR(CLK_TOP_NET2PLL_D4_D2, "top_net2pll_d4_d2" , "net2pll" , 1, 8), |
55 | FACTOR(CLK_TOP_NET2PLL_D3_D2, "top_net2pll_d3_d2" , "net2pll" , 1, 2), |
56 | /* WEDMCUPLL */ |
57 | FACTOR(CLK_TOP_WEDMCUPLL_D5_D2, "top_wedmcupll_d5_d2" , "wedmcupll" , 1, |
58 | 10), |
59 | }; |
60 | |
61 | static const char *const nfi1x_parents[] __initconst = { "top_xtal" , |
62 | "top_mmpll_d8" , |
63 | "top_net1pll_d8_d2" , |
64 | "top_net2pll_d3_d2" , |
65 | "top_mpll_d4" , |
66 | "top_mmpll_d8_d2" , |
67 | "top_wedmcupll_d5_d2" , |
68 | "top_mpll_d8" }; |
69 | |
70 | static const char *const spinfi_parents[] __initconst = { |
71 | "top_xtal_d2" , "top_xtal" , "top_net1pll_d5_d4" , |
72 | "top_mpll_d4" , "top_mmpll_d8_d2" , "top_wedmcupll_d5_d2" , |
73 | "top_mmpll_d3_d8" , "top_mpll_d8" |
74 | }; |
75 | |
76 | static const char *const spi_parents[] __initconst = { |
77 | "top_xtal" , "top_mpll_d2" , "top_mmpll_d8" , |
78 | "top_net1pll_d8_d2" , "top_net2pll_d3_d2" , "top_net1pll_d5_d4" , |
79 | "top_mpll_d4" , "top_wedmcupll_d5_d2" |
80 | }; |
81 | |
82 | static const char *const uart_parents[] __initconst = { "top_xtal" , |
83 | "top_mpll_d8" , |
84 | "top_mpll_d8_d2" }; |
85 | |
86 | static const char *const pwm_parents[] __initconst = { |
87 | "top_xtal" , "top_net1pll_d8_d2" , "top_net1pll_d5_d4" , "top_mpll_d4" |
88 | }; |
89 | |
90 | static const char *const i2c_parents[] __initconst = { |
91 | "top_xtal" , "top_net1pll_d5_d4" , "top_mpll_d4" , "top_net1pll_d8_d4" |
92 | }; |
93 | |
94 | static const char *const pextp_tl_ck_parents[] __initconst = { |
95 | "top_xtal" , "top_net1pll_d5_d4" , "top_net2pll_d4_d2" , "top_rtc_32k" |
96 | }; |
97 | |
98 | static const char *const emmc_250m_parents[] __initconst = { |
99 | "top_xtal" , "top_net1pll_d5_d2" |
100 | }; |
101 | |
102 | static const char *const emmc_416m_parents[] __initconst = { "top_xtal" , |
103 | "mpll" }; |
104 | |
105 | static const char *const f_26m_adc_parents[] __initconst = { "top_xtal" , |
106 | "top_mpll_d8_d2" }; |
107 | |
108 | static const char *const dramc_md32_parents[] __initconst = { "top_xtal" , |
109 | "top_mpll_d2" }; |
110 | |
111 | static const char *const sysaxi_parents[] __initconst = { "top_xtal" , |
112 | "top_net1pll_d8_d2" , |
113 | "top_net2pll_d4" }; |
114 | |
115 | static const char *const sysapb_parents[] __initconst = { "top_xtal" , |
116 | "top_mpll_d3_d2" , |
117 | "top_net2pll_d4_d2" }; |
118 | |
119 | static const char *const arm_db_main_parents[] __initconst = { |
120 | "top_xtal" , "top_net2pll_d3_d2" |
121 | }; |
122 | |
123 | static const char *const arm_db_jtsel_parents[] __initconst = { "top_jtag" , |
124 | "top_xtal" }; |
125 | |
126 | static const char *const netsys_parents[] __initconst = { "top_xtal" , |
127 | "top_mmpll_d4" }; |
128 | |
129 | static const char *const netsys_500m_parents[] __initconst = { |
130 | "top_xtal" , "top_net1pll_d5" |
131 | }; |
132 | |
133 | static const char *const netsys_mcu_parents[] __initconst = { |
134 | "top_xtal" , "wedmcupll" , "top_mmpll_d2" , "top_net1pll_d4" , |
135 | "top_net1pll_d5" |
136 | }; |
137 | |
138 | static const char *const netsys_2x_parents[] __initconst = { |
139 | "top_xtal" , "net2pll" , "wedmcupll" , "top_mmpll_d2" |
140 | }; |
141 | |
142 | static const char *const sgm_325m_parents[] __initconst = { "top_xtal" , |
143 | "sgmpll" }; |
144 | |
145 | static const char *const sgm_reg_parents[] __initconst = { |
146 | "top_xtal" , "top_net1pll_d8_d4" |
147 | }; |
148 | |
149 | static const char *const a1sys_parents[] __initconst = { "top_xtal" , |
150 | "top_apll2_d4" }; |
151 | |
152 | static const char *const conn_mcusys_parents[] __initconst = { "top_xtal" , |
153 | "top_mmpll_d2" }; |
154 | |
155 | static const char *const eip_b_parents[] __initconst = { "top_xtal" , |
156 | "net2pll" }; |
157 | |
158 | static const char *const aud_l_parents[] __initconst = { "top_xtal" , "apll2" , |
159 | "top_mpll_d8_d2" }; |
160 | |
161 | static const char *const a_tuner_parents[] __initconst = { "top_xtal" , |
162 | "top_apll2_d4" , |
163 | "top_mpll_d8_d2" }; |
164 | |
165 | static const char *const u2u3_sys_parents[] __initconst = { |
166 | "top_xtal" , "top_net1pll_d5_d4" |
167 | }; |
168 | |
169 | static const char *const da_u2_refsel_parents[] __initconst = { |
170 | "top_xtal" , "top_mmpll_u2phy" |
171 | }; |
172 | |
173 | static const struct mtk_mux top_muxes[] = { |
174 | /* CLK_CFG_0 */ |
175 | MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel" , nfi1x_parents, |
176 | 0x000, 0x004, 0x008, 0, 3, 7, 0x1C0, 0), |
177 | MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel" , spinfi_parents, |
178 | 0x000, 0x004, 0x008, 8, 3, 15, 0x1C0, 1), |
179 | MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel" , spi_parents, 0x000, |
180 | 0x004, 0x008, 16, 3, 23, 0x1C0, 2), |
181 | MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel" , spi_parents, |
182 | 0x000, 0x004, 0x008, 24, 3, 31, 0x1C0, 3), |
183 | /* CLK_CFG_1 */ |
184 | MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel" , uart_parents, 0x010, |
185 | 0x014, 0x018, 0, 2, 7, 0x1C0, 4), |
186 | MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel" , pwm_parents, 0x010, |
187 | 0x014, 0x018, 8, 2, 15, 0x1C0, 5), |
188 | MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel" , i2c_parents, 0x010, |
189 | 0x014, 0x018, 16, 2, 23, 0x1C0, 6), |
190 | MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel" , |
191 | pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2, |
192 | 31, 0x1C0, 7), |
193 | /* CLK_CFG_2 */ |
194 | MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel" , |
195 | emmc_250m_parents, 0x020, 0x024, 0x028, 0, 1, 7, |
196 | 0x1C0, 8, 0), |
197 | MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_EMMC_416M_SEL, "emmc_416m_sel" , |
198 | emmc_416m_parents, 0x020, 0x024, 0x028, 8, 1, 15, |
199 | 0x1C0, 9, 0), |
200 | MUX_GATE_CLR_SET_UPD(CLK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel" , |
201 | f_26m_adc_parents, 0x020, 0x024, 0x028, 16, 1, 23, |
202 | 0x1C0, 10), |
203 | MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_SEL, "dramc_sel" , |
204 | f_26m_adc_parents, 0x020, 0x024, 0x028, |
205 | 24, 1, 31, 0x1C0, 11, |
206 | CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), |
207 | /* CLK_CFG_3 */ |
208 | MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel" , |
209 | dramc_md32_parents, 0x030, 0x034, 0x038, |
210 | 0, 1, 7, 0x1C0, 12, |
211 | CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), |
212 | MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAXI_SEL, "sysaxi_sel" , |
213 | sysaxi_parents, 0x030, 0x034, 0x038, |
214 | 8, 2, 15, 0x1C0, 13, |
215 | CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), |
216 | MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAPB_SEL, "sysapb_sel" , |
217 | sysapb_parents, 0x030, 0x034, 0x038, |
218 | 16, 2, 23, 0x1C0, 14, |
219 | CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), |
220 | MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel" , |
221 | arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1, |
222 | 31, 0x1C0, 15), |
223 | /* CLK_CFG_4 */ |
224 | MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_JTSEL, "arm_db_jtsel" , |
225 | arm_db_jtsel_parents, 0x040, 0x044, 0x048, 0, 1, 7, |
226 | 0x1C0, 16), |
227 | MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel" , netsys_parents, |
228 | 0x040, 0x044, 0x048, 8, 1, 15, 0x1C0, 17), |
229 | MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel" , |
230 | netsys_500m_parents, 0x040, 0x044, 0x048, 16, 1, |
231 | 23, 0x1C0, 18), |
232 | MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel" , |
233 | netsys_mcu_parents, 0x040, 0x044, 0x048, 24, 3, 31, |
234 | 0x1C0, 19), |
235 | /* CLK_CFG_5 */ |
236 | MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel" , |
237 | netsys_2x_parents, 0x050, 0x054, 0x058, 0, 2, 7, |
238 | 0x1C0, 20), |
239 | MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel" , |
240 | sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15, |
241 | 0x1C0, 21), |
242 | MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel" , |
243 | sgm_reg_parents, 0x050, 0x054, 0x058, |
244 | 16, 1, 23, 0x1C0, 22, |
245 | CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), |
246 | MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel" , a1sys_parents, |
247 | 0x050, 0x054, 0x058, 24, 1, 31, 0x1C0, 23), |
248 | /* CLK_CFG_6 */ |
249 | MUX_GATE_CLR_SET_UPD(CLK_TOP_CONN_MCUSYS_SEL, "conn_mcusys_sel" , |
250 | conn_mcusys_parents, 0x060, 0x064, 0x068, 0, 1, 7, |
251 | 0x1C0, 24), |
252 | MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP_B_SEL, "eip_b_sel" , eip_b_parents, |
253 | 0x060, 0x064, 0x068, 8, 1, 15, 0x1C0, 25), |
254 | MUX_GATE_CLR_SET_UPD(CLK_TOP_PCIE_PHY_SEL, "pcie_phy_sel" , |
255 | f_26m_adc_parents, 0x060, 0x064, 0x068, 16, 1, 23, |
256 | 0x1C0, 26), |
257 | MUX_GATE_CLR_SET_UPD(CLK_TOP_USB3_PHY_SEL, "usb3_phy_sel" , |
258 | f_26m_adc_parents, 0x060, 0x064, 0x068, 24, 1, 31, |
259 | 0x1C0, 27), |
260 | /* CLK_CFG_7 */ |
261 | MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_F26M_SEL, "csw_f26m_sel" , |
262 | f_26m_adc_parents, 0x070, 0x074, 0x078, |
263 | 0, 1, 7, 0x1C0, 28, |
264 | CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), |
265 | MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel" , aud_l_parents, |
266 | 0x070, 0x074, 0x078, 8, 2, 15, 0x1C0, 29), |
267 | MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel" , |
268 | a_tuner_parents, 0x070, 0x074, 0x078, 16, 2, 23, |
269 | 0x1C0, 30), |
270 | MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SEL, "u2u3_sel" , f_26m_adc_parents, |
271 | 0x070, 0x074, 0x078, 24, 1, 31, 0x1C4, 0), |
272 | /* CLK_CFG_8 */ |
273 | MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel" , |
274 | u2u3_sys_parents, 0x080, 0x084, 0x088, 0, 1, 7, |
275 | 0x1C4, 1), |
276 | MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel" , |
277 | u2u3_sys_parents, 0x080, 0x084, 0x088, 8, 1, 15, |
278 | 0x1C4, 2), |
279 | MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_U2_REFSEL, "da_u2_refsel" , |
280 | da_u2_refsel_parents, 0x080, 0x084, 0x088, 16, 1, |
281 | 23, 0x1C4, 3), |
282 | MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_U2_CK_1P_SEL, "da_u2_ck_1p_sel" , |
283 | da_u2_refsel_parents, 0x080, 0x084, 0x088, 24, 1, |
284 | 31, 0x1C4, 4), |
285 | /* CLK_CFG_9 */ |
286 | MUX_GATE_CLR_SET_UPD(CLK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel" , |
287 | sgm_reg_parents, 0x090, 0x094, 0x098, 0, 1, 7, |
288 | 0x1C4, 5), |
289 | }; |
290 | |
291 | static const struct mtk_clk_desc topck_desc = { |
292 | .fixed_clks = top_fixed_clks, |
293 | .num_fixed_clks = ARRAY_SIZE(top_fixed_clks), |
294 | .factor_clks = top_divs, |
295 | .num_factor_clks = ARRAY_SIZE(top_divs), |
296 | .mux_clks = top_muxes, |
297 | .num_mux_clks = ARRAY_SIZE(top_muxes), |
298 | .clk_lock = &mt7986_clk_lock, |
299 | }; |
300 | |
301 | static const struct of_device_id of_match_clk_mt7986_topckgen[] = { |
302 | { .compatible = "mediatek,mt7986-topckgen" , .data = &topck_desc }, |
303 | { /* sentinel */ } |
304 | }; |
305 | MODULE_DEVICE_TABLE(of, of_match_clk_mt7986_topckgen); |
306 | |
307 | static struct platform_driver clk_mt7986_topckgen_drv = { |
308 | .probe = mtk_clk_simple_probe, |
309 | .remove_new = mtk_clk_simple_remove, |
310 | .driver = { |
311 | .name = "clk-mt7986-topckgen" , |
312 | .of_match_table = of_match_clk_mt7986_topckgen, |
313 | }, |
314 | }; |
315 | module_platform_driver(clk_mt7986_topckgen_drv); |
316 | MODULE_LICENSE("GPL" ); |
317 | |