1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2019, Intel Corporation
4 */
5#include <linux/slab.h>
6#include <linux/clk-provider.h>
7#include <linux/of.h>
8#include <linux/platform_device.h>
9
10#include <dt-bindings/clock/agilex-clock.h>
11
12#include "stratix10-clk.h"
13
14static const struct clk_parent_data pll_mux[] = {
15	{ .fw_name = "osc1",
16	  .name = "osc1", },
17	{ .fw_name = "cb-intosc-hs-div2-clk",
18	  .name = "cb-intosc-hs-div2-clk", },
19	{ .fw_name = "f2s-free-clk",
20	  .name = "f2s-free-clk", },
21};
22
23static const struct clk_parent_data boot_mux[] = {
24	{ .fw_name = "osc1",
25	  .name = "osc1", },
26	{ .fw_name = "cb-intosc-hs-div2-clk",
27	  .name = "cb-intosc-hs-div2-clk", },
28};
29
30static const struct clk_parent_data mpu_free_mux[] = {
31	{ .fw_name = "main_pll_c0",
32	  .name = "main_pll_c0", },
33	{ .fw_name = "peri_pll_c0",
34	  .name = "peri_pll_c0", },
35	{ .fw_name = "osc1",
36	  .name = "osc1", },
37	{ .fw_name = "cb-intosc-hs-div2-clk",
38	  .name = "cb-intosc-hs-div2-clk", },
39	{ .fw_name = "f2s-free-clk",
40	  .name = "f2s-free-clk", },
41};
42
43static const struct clk_parent_data noc_free_mux[] = {
44	{ .fw_name = "main_pll_c1",
45	  .name = "main_pll_c1", },
46	{ .fw_name = "peri_pll_c1",
47	  .name = "peri_pll_c1", },
48	{ .fw_name = "osc1",
49	  .name = "osc1", },
50	{ .fw_name = "cb-intosc-hs-div2-clk",
51	  .name = "cb-intosc-hs-div2-clk", },
52	{ .fw_name = "f2s-free-clk",
53	  .name = "f2s-free-clk", },
54};
55
56static const struct clk_parent_data emaca_free_mux[] = {
57	{ .fw_name = "main_pll_c2",
58	  .name = "main_pll_c2", },
59	{ .fw_name = "peri_pll_c2",
60	  .name = "peri_pll_c2", },
61	{ .fw_name = "osc1",
62	  .name = "osc1", },
63	{ .fw_name = "cb-intosc-hs-div2-clk",
64	  .name = "cb-intosc-hs-div2-clk", },
65	{ .fw_name = "f2s-free-clk",
66	  .name = "f2s-free-clk", },
67};
68
69static const struct clk_parent_data emacb_free_mux[] = {
70	{ .fw_name = "main_pll_c3",
71	  .name = "main_pll_c3", },
72	{ .fw_name = "peri_pll_c3",
73	  .name = "peri_pll_c3", },
74	{ .fw_name = "osc1",
75	  .name = "osc1", },
76	{ .fw_name = "cb-intosc-hs-div2-clk",
77	  .name = "cb-intosc-hs-div2-clk", },
78	{ .fw_name = "f2s-free-clk",
79	  .name = "f2s-free-clk", },
80};
81
82static const struct clk_parent_data emac_ptp_free_mux[] = {
83	{ .fw_name = "main_pll_c3",
84	  .name = "main_pll_c3", },
85	{ .fw_name = "peri_pll_c3",
86	  .name = "peri_pll_c3", },
87	{ .fw_name = "osc1",
88	  .name = "osc1", },
89	{ .fw_name = "cb-intosc-hs-div2-clk",
90	  .name = "cb-intosc-hs-div2-clk", },
91	{ .fw_name = "f2s-free-clk",
92	  .name = "f2s-free-clk", },
93};
94
95static const struct clk_parent_data gpio_db_free_mux[] = {
96	{ .fw_name = "main_pll_c3",
97	  .name = "main_pll_c3", },
98	{ .fw_name = "peri_pll_c3",
99	  .name = "peri_pll_c3", },
100	{ .fw_name = "osc1",
101	  .name = "osc1", },
102	{ .fw_name = "cb-intosc-hs-div2-clk",
103	  .name = "cb-intosc-hs-div2-clk", },
104	{ .fw_name = "f2s-free-clk",
105	  .name = "f2s-free-clk", },
106};
107
108static const struct clk_parent_data psi_ref_free_mux[] = {
109	{ .fw_name = "main_pll_c2",
110	  .name = "main_pll_c2", },
111	{ .fw_name = "peri_pll_c2",
112	  .name = "peri_pll_c2", },
113	{ .fw_name = "osc1",
114	  .name = "osc1", },
115	{ .fw_name = "cb-intosc-hs-div2-clk",
116	  .name = "cb-intosc-hs-div2-clk", },
117	{ .fw_name = "f2s-free-clk",
118	  .name = "f2s-free-clk", },
119};
120
121static const struct clk_parent_data sdmmc_free_mux[] = {
122	{ .fw_name = "main_pll_c3",
123	  .name = "main_pll_c3", },
124	{ .fw_name = "peri_pll_c3",
125	  .name = "peri_pll_c3", },
126	{ .fw_name = "osc1",
127	  .name = "osc1", },
128	{ .fw_name = "cb-intosc-hs-div2-clk",
129	  .name = "cb-intosc-hs-div2-clk", },
130	{ .fw_name = "f2s-free-clk",
131	  .name = "f2s-free-clk", },
132};
133
134static const struct clk_parent_data s2f_usr0_free_mux[] = {
135	{ .fw_name = "main_pll_c2",
136	  .name = "main_pll_c2", },
137	{ .fw_name = "peri_pll_c2",
138	  .name = "peri_pll_c2", },
139	{ .fw_name = "osc1",
140	  .name = "osc1", },
141	{ .fw_name = "cb-intosc-hs-div2-clk",
142	  .name = "cb-intosc-hs-div2-clk", },
143	{ .fw_name = "f2s-free-clk",
144	  .name = "f2s-free-clk", },
145};
146
147static const struct clk_parent_data s2f_usr1_free_mux[] = {
148	{ .fw_name = "main_pll_c2",
149	  .name = "main_pll_c2", },
150	{ .fw_name = "peri_pll_c2",
151	  .name = "peri_pll_c2", },
152	{ .fw_name = "osc1",
153	  .name = "osc1", },
154	{ .fw_name = "cb-intosc-hs-div2-clk",
155	  .name = "cb-intosc-hs-div2-clk", },
156	{ .fw_name = "f2s-free-clk",
157	  .name = "f2s-free-clk", },
158};
159
160static const struct clk_parent_data mpu_mux[] = {
161	{ .fw_name = "mpu_free_clk",
162	  .name = "mpu_free_clk", },
163	{ .fw_name = "boot_clk",
164	  .name = "boot_clk", },
165};
166
167static const struct clk_parent_data emac_mux[] = {
168	{ .fw_name = "emaca_free_clk",
169	  .name = "emaca_free_clk", },
170	{ .fw_name = "emacb_free_clk",
171	  .name = "emacb_free_clk", },
172	{ .fw_name = "boot_clk",
173	  .name = "boot_clk", },
174};
175
176static const struct clk_parent_data noc_mux[] = {
177	{ .fw_name = "noc_free_clk",
178	  .name = "noc_free_clk", },
179	{ .fw_name = "boot_clk",
180	  .name = "boot_clk", },
181};
182
183static const struct clk_parent_data sdmmc_mux[] = {
184	{ .fw_name = "sdmmc_free_clk",
185	  .name = "sdmmc_free_clk", },
186	{ .fw_name = "boot_clk",
187	  .name = "boot_clk", },
188};
189
190static const struct clk_parent_data s2f_user0_mux[] = {
191	{ .fw_name = "s2f_user0_free_clk",
192	  .name = "s2f_user0_free_clk", },
193	{ .fw_name = "boot_clk",
194	  .name = "boot_clk", },
195};
196
197static const struct clk_parent_data s2f_user1_mux[] = {
198	{ .fw_name = "s2f_user1_free_clk",
199	  .name = "s2f_user1_free_clk", },
200	{ .fw_name = "boot_clk",
201	  .name = "boot_clk", },
202};
203
204static const struct clk_parent_data psi_mux[] = {
205	{ .fw_name = "psi_ref_free_clk",
206	  .name = "psi_ref_free_clk", },
207	{ .fw_name = "boot_clk",
208	  .name = "boot_clk", },
209};
210
211static const struct clk_parent_data gpio_db_mux[] = {
212	{ .fw_name = "gpio_db_free_clk",
213	  .name = "gpio_db_free_clk", },
214	{ .fw_name = "boot_clk",
215	  .name = "boot_clk", },
216};
217
218static const struct clk_parent_data emac_ptp_mux[] = {
219	{ .fw_name = "emac_ptp_free_clk",
220	  .name = "emac_ptp_free_clk", },
221	{ .fw_name = "boot_clk",
222	  .name = "boot_clk", },
223};
224
225/* clocks in AO (always on) controller */
226static const struct stratix10_pll_clock agilex_pll_clks[] = {
227	{ AGILEX_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
228	  0x0},
229	{ AGILEX_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
230	  0, 0x48},
231	{ AGILEX_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
232	  0, 0x9c},
233};
234
235static const struct n5x_perip_c_clock n5x_main_perip_c_clks[] = {
236	{ AGILEX_MAIN_PLL_C0_CLK, "main_pll_c0", "main_pll", NULL, 1, 0, 0x54, 0},
237	{ AGILEX_MAIN_PLL_C1_CLK, "main_pll_c1", "main_pll", NULL, 1, 0, 0x54, 8},
238	{ AGILEX_MAIN_PLL_C2_CLK, "main_pll_c2", "main_pll", NULL, 1, 0, 0x54, 16},
239	{ AGILEX_MAIN_PLL_C3_CLK, "main_pll_c3", "main_pll", NULL, 1, 0, 0x54, 24},
240	{ AGILEX_PERIPH_PLL_C0_CLK, "peri_pll_c0", "periph_pll", NULL, 1, 0, 0xA8, 0},
241	{ AGILEX_PERIPH_PLL_C1_CLK, "peri_pll_c1", "periph_pll", NULL, 1, 0, 0xA8, 8},
242	{ AGILEX_PERIPH_PLL_C2_CLK, "peri_pll_c2", "periph_pll", NULL, 1, 0, 0xA8, 16},
243	{ AGILEX_PERIPH_PLL_C3_CLK, "peri_pll_c3", "periph_pll", NULL, 1, 0, 0xA8, 24},
244};
245
246static const struct stratix10_perip_c_clock agilex_main_perip_c_clks[] = {
247	{ AGILEX_MAIN_PLL_C0_CLK, "main_pll_c0", "main_pll", NULL, 1, 0, 0x58},
248	{ AGILEX_MAIN_PLL_C1_CLK, "main_pll_c1", "main_pll", NULL, 1, 0, 0x5C},
249	{ AGILEX_MAIN_PLL_C2_CLK, "main_pll_c2", "main_pll", NULL, 1, 0, 0x64},
250	{ AGILEX_MAIN_PLL_C3_CLK, "main_pll_c3", "main_pll", NULL, 1, 0, 0x68},
251	{ AGILEX_PERIPH_PLL_C0_CLK, "peri_pll_c0", "periph_pll", NULL, 1, 0, 0xAC},
252	{ AGILEX_PERIPH_PLL_C1_CLK, "peri_pll_c1", "periph_pll", NULL, 1, 0, 0xB0},
253	{ AGILEX_PERIPH_PLL_C2_CLK, "peri_pll_c2", "periph_pll", NULL, 1, 0, 0xB8},
254	{ AGILEX_PERIPH_PLL_C3_CLK, "peri_pll_c3", "periph_pll", NULL, 1, 0, 0xBC},
255};
256
257static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = {
258	{ AGILEX_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux),
259	   0, 0x3C, 0, 0, 0},
260	{ AGILEX_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
261	  0, 0x40, 0, 0, 0},
262	{ AGILEX_L4_SYS_FREE_CLK, "l4_sys_free_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0,
263	  0, 4, 0x30, 1},
264	{ AGILEX_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
265	  0, 0xD4, 0, 0x88, 0},
266	{ AGILEX_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
267	  0, 0xD8, 0, 0x88, 1},
268	{ AGILEX_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
269	  ARRAY_SIZE(emac_ptp_free_mux), 0, 0xDC, 0, 0x88, 2},
270	{ AGILEX_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
271	  ARRAY_SIZE(gpio_db_free_mux), 0, 0xE0, 0, 0x88, 3},
272	{ AGILEX_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
273	  ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0, 0},
274	{ AGILEX_S2F_USER0_FREE_CLK, "s2f_user0_free_clk", NULL, s2f_usr0_free_mux,
275	  ARRAY_SIZE(s2f_usr0_free_mux), 0, 0xE8, 0, 0x30, 2},
276	{ AGILEX_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
277	  ARRAY_SIZE(s2f_usr1_free_mux), 0, 0xEC, 0, 0x88, 5},
278	{ AGILEX_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
279	  ARRAY_SIZE(psi_ref_free_mux), 0, 0xF0, 0, 0x88, 6},
280};
281
282static const struct stratix10_gate_clock agilex_gate_clks[] = {
283	{ AGILEX_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x24,
284	  0, 0, 0, 0, 0x30, 0, 0},
285	{ AGILEX_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x24,
286	  0, 0, 0, 0, 0, 0, 4},
287	{ AGILEX_MPU_CCU_CLK, "mpu_ccu_clk", "mpu_clk", NULL, 1, 0, 0x24,
288	  0, 0, 0, 0, 0, 0, 2},
289	{ AGILEX_L4_MAIN_CLK, "l4_main_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
290	  1, 0x44, 0, 2, 0x30, 1, 0},
291	{ AGILEX_L4_MP_CLK, "l4_mp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
292	  2, 0x44, 8, 2, 0x30, 1, 0},
293	/*
294	 * The l4_sp_clk feeds a 100 MHz clock to various peripherals, one of them
295	 * being the SP timers, thus cannot get gated.
296	 */
297	{ AGILEX_L4_SP_CLK, "l4_sp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), CLK_IS_CRITICAL, 0x24,
298	  3, 0x44, 16, 2, 0x30, 1, 0},
299	{ AGILEX_CS_AT_CLK, "cs_at_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
300	  4, 0x44, 24, 2, 0x30, 1, 0},
301	{ AGILEX_CS_TRACE_CLK, "cs_trace_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
302	  4, 0x44, 26, 2, 0x30, 1, 0},
303	{ AGILEX_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x24,
304	  4, 0x44, 28, 1, 0, 0, 0},
305	{ AGILEX_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
306	  5, 0, 0, 0, 0x30, 1, 0},
307	{ AGILEX_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C,
308	  0, 0, 0, 0, 0x94, 26, 0},
309	{ AGILEX_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C,
310	  1, 0, 0, 0, 0x94, 27, 0},
311	{ AGILEX_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C,
312	  2, 0, 0, 0, 0x94, 28, 0},
313	{ AGILEX_EMAC_PTP_CLK, "emac_ptp_clk", NULL, emac_ptp_mux, ARRAY_SIZE(emac_ptp_mux), 0, 0x7C,
314	  3, 0, 0, 0, 0x88, 2, 0},
315	{ AGILEX_GPIO_DB_CLK, "gpio_db_clk", NULL, gpio_db_mux, ARRAY_SIZE(gpio_db_mux), 0, 0x7C,
316	  4, 0x98, 0, 16, 0x88, 3, 0},
317	{ AGILEX_SDMMC_CLK, "sdmmc_clk", NULL, sdmmc_mux, ARRAY_SIZE(sdmmc_mux), 0, 0x7C,
318	  5, 0, 0, 0, 0x88, 4, 4},
319	{ AGILEX_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_user0_mux, ARRAY_SIZE(s2f_user0_mux), 0, 0x24,
320	  6, 0, 0, 0, 0x30, 2, 0},
321	{ AGILEX_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux, ARRAY_SIZE(s2f_user1_mux), 0, 0x7C,
322	  6, 0, 0, 0, 0x88, 5, 0},
323	{ AGILEX_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux, ARRAY_SIZE(psi_mux), 0, 0x7C,
324	  7, 0, 0, 0, 0x88, 6, 0},
325	{ AGILEX_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0x7C,
326	  8, 0, 0, 0, 0, 0, 0},
327	{ AGILEX_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0x7C,
328	  9, 0, 0, 0, 0, 0, 0},
329	{ AGILEX_NAND_X_CLK, "nand_x_clk", "l4_mp_clk", NULL, 1, 0, 0x7C,
330	  10, 0, 0, 0, 0, 0, 0},
331	{ AGILEX_NAND_CLK, "nand_clk", "nand_x_clk", NULL, 1, 0, 0x7C,
332	  10, 0, 0, 0, 0, 0, 4},
333	{ AGILEX_NAND_ECC_CLK, "nand_ecc_clk", "nand_x_clk", NULL, 1, 0, 0x7C,
334	  10, 0, 0, 0, 0, 0, 4},
335};
336
337static int n5x_clk_register_c_perip(const struct n5x_perip_c_clock *clks,
338				       int nums, struct stratix10_clock_data *data)
339{
340	struct clk_hw *hw_clk;
341	void __iomem *base = data->base;
342	int i;
343
344	for (i = 0; i < nums; i++) {
345		hw_clk = n5x_register_periph(&clks[i], base);
346		if (IS_ERR(hw_clk)) {
347			pr_err("%s: failed to register clock %s\n",
348			       __func__, clks[i].name);
349			continue;
350		}
351		data->clk_data.hws[clks[i].id] = hw_clk;
352	}
353	return 0;
354}
355
356static int agilex_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
357				       int nums, struct stratix10_clock_data *data)
358{
359	struct clk_hw *hw_clk;
360	void __iomem *base = data->base;
361	int i;
362
363	for (i = 0; i < nums; i++) {
364		hw_clk = s10_register_periph(&clks[i], base);
365		if (IS_ERR(hw_clk)) {
366			pr_err("%s: failed to register clock %s\n",
367			       __func__, clks[i].name);
368			continue;
369		}
370		data->clk_data.hws[clks[i].id] = hw_clk;
371	}
372	return 0;
373}
374
375static int agilex_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
376					 int nums, struct stratix10_clock_data *data)
377{
378	struct clk_hw *hw_clk;
379	void __iomem *base = data->base;
380	int i;
381
382	for (i = 0; i < nums; i++) {
383		hw_clk = s10_register_cnt_periph(&clks[i], base);
384		if (IS_ERR(hw_clk)) {
385			pr_err("%s: failed to register clock %s\n",
386			       __func__, clks[i].name);
387			continue;
388		}
389		data->clk_data.hws[clks[i].id] = hw_clk;
390	}
391
392	return 0;
393}
394
395static int agilex_clk_register_gate(const struct stratix10_gate_clock *clks,
396				    int nums, struct stratix10_clock_data *data)
397{
398	struct clk_hw *hw_clk;
399	void __iomem *base = data->base;
400	int i;
401
402	for (i = 0; i < nums; i++) {
403		hw_clk = agilex_register_gate(&clks[i], base);
404		if (IS_ERR(hw_clk)) {
405			pr_err("%s: failed to register clock %s\n",
406			       __func__, clks[i].name);
407			continue;
408		}
409		data->clk_data.hws[clks[i].id] = hw_clk;
410	}
411
412	return 0;
413}
414
415static int agilex_clk_register_pll(const struct stratix10_pll_clock *clks,
416				 int nums, struct stratix10_clock_data *data)
417{
418	struct clk_hw *hw_clk;
419	void __iomem *base = data->base;
420	int i;
421
422	for (i = 0; i < nums; i++) {
423		hw_clk = agilex_register_pll(&clks[i], base);
424		if (IS_ERR(hw_clk)) {
425			pr_err("%s: failed to register clock %s\n",
426			       __func__, clks[i].name);
427			continue;
428		}
429		data->clk_data.hws[clks[i].id] = hw_clk;
430	}
431
432	return 0;
433}
434
435static int n5x_clk_register_pll(const struct stratix10_pll_clock *clks,
436				 int nums, struct stratix10_clock_data *data)
437{
438	struct clk_hw *hw_clk;
439	void __iomem *base = data->base;
440	int i;
441
442	for (i = 0; i < nums; i++) {
443		hw_clk = n5x_register_pll(&clks[i], base);
444		if (IS_ERR(hw_clk)) {
445			pr_err("%s: failed to register clock %s\n",
446			       __func__, clks[i].name);
447			continue;
448		}
449		data->clk_data.hws[clks[i].id] = hw_clk;
450	}
451
452	return 0;
453}
454
455static int agilex_clkmgr_init(struct platform_device *pdev)
456{
457	struct device_node *np = pdev->dev.of_node;
458	struct device *dev = &pdev->dev;
459	struct stratix10_clock_data *clk_data;
460	void __iomem *base;
461	int i, num_clks;
462
463	base = devm_platform_ioremap_resource(pdev, 0);
464	if (IS_ERR(base))
465		return PTR_ERR(base);
466
467	num_clks = AGILEX_NUM_CLKS;
468
469	clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws,
470				num_clks), GFP_KERNEL);
471	if (!clk_data)
472		return -ENOMEM;
473
474	clk_data->clk_data.num = num_clks;
475	clk_data->base = base;
476
477	for (i = 0; i < num_clks; i++)
478		clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
479
480	agilex_clk_register_pll(agilex_pll_clks, ARRAY_SIZE(agilex_pll_clks), clk_data);
481
482	agilex_clk_register_c_perip(agilex_main_perip_c_clks,
483				 ARRAY_SIZE(agilex_main_perip_c_clks), clk_data);
484
485	agilex_clk_register_cnt_perip(agilex_main_perip_cnt_clks,
486				   ARRAY_SIZE(agilex_main_perip_cnt_clks),
487				   clk_data);
488
489	agilex_clk_register_gate(agilex_gate_clks, ARRAY_SIZE(agilex_gate_clks),
490			      clk_data);
491	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &clk_data->clk_data);
492	return 0;
493}
494
495static int n5x_clkmgr_init(struct platform_device *pdev)
496{
497	struct device_node *np = pdev->dev.of_node;
498	struct device *dev = &pdev->dev;
499	struct stratix10_clock_data *clk_data;
500	void __iomem *base;
501	int i, num_clks;
502
503	base = devm_platform_ioremap_resource(pdev, 0);
504	if (IS_ERR(base))
505		return PTR_ERR(base);
506
507	num_clks = AGILEX_NUM_CLKS;
508
509	clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws,
510				num_clks), GFP_KERNEL);
511	if (!clk_data)
512		return -ENOMEM;
513
514	clk_data->base = base;
515	clk_data->clk_data.num = num_clks;
516
517	for (i = 0; i < num_clks; i++)
518		clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
519
520	n5x_clk_register_pll(agilex_pll_clks, ARRAY_SIZE(agilex_pll_clks), clk_data);
521
522	n5x_clk_register_c_perip(n5x_main_perip_c_clks,
523				 ARRAY_SIZE(n5x_main_perip_c_clks), clk_data);
524
525	agilex_clk_register_cnt_perip(agilex_main_perip_cnt_clks,
526				   ARRAY_SIZE(agilex_main_perip_cnt_clks),
527				   clk_data);
528
529	agilex_clk_register_gate(agilex_gate_clks, ARRAY_SIZE(agilex_gate_clks),
530			      clk_data);
531	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &clk_data->clk_data);
532	return 0;
533}
534
535static int agilex_clkmgr_probe(struct platform_device *pdev)
536{
537	int (*probe_func)(struct platform_device *init_func);
538
539	probe_func = of_device_get_match_data(&pdev->dev);
540	if (!probe_func)
541		return -ENODEV;
542	return	probe_func(pdev);
543}
544
545static const struct of_device_id agilex_clkmgr_match_table[] = {
546	{ .compatible = "intel,agilex-clkmgr",
547	  .data = agilex_clkmgr_init },
548	{ .compatible = "intel,easic-n5x-clkmgr",
549	  .data = n5x_clkmgr_init },
550	{ }
551};
552
553static struct platform_driver agilex_clkmgr_driver = {
554	.probe		= agilex_clkmgr_probe,
555	.driver		= {
556		.name	= "agilex-clkmgr",
557		.suppress_bind_attrs = true,
558		.of_match_table = agilex_clkmgr_match_table,
559	},
560};
561
562static int __init agilex_clk_init(void)
563{
564	return platform_driver_register(&agilex_clkmgr_driver);
565}
566core_initcall(agilex_clk_init);
567