xref: /openbmc/linux/drivers/clk/socfpga/clk-s10.c (revision 98ddec80)
1 // SPDX-License-Identifier:	GPL-2.0
2 /*
3  * Copyright (C) 2017, Intel Corporation
4  */
5 #include <linux/slab.h>
6 #include <linux/clk-provider.h>
7 #include <linux/of_device.h>
8 #include <linux/of_address.h>
9 #include <linux/platform_device.h>
10 
11 #include <dt-bindings/clock/stratix10-clock.h>
12 
13 #include "stratix10-clk.h"
14 
15 static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
16 					"f2s_free_clk",};
17 static const char * const cntr_mux[] = { "main_pll", "periph_pll",
18 					 "osc1", "cb_intosc_hs_div2_clk",
19 					 "f2s_free_clk"};
20 static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
21 
22 static const char * const noc_free_mux[] = {"main_noc_base_clk",
23 					    "peri_noc_base_clk",
24 					    "osc1", "cb_intosc_hs_div2_clk",
25 					    "f2s_free_clk"};
26 
27 static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
28 static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
29 static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"};
30 static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"};
31 static const char * const sdmmc_free_mux[] = {"peri_sdmmc_clk", "boot_clk"};
32 static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"};
33 static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
34 static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
35 
36 static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
37 static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
38 static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
39 
40 /* clocks in AO (always on) controller */
41 static const struct stratix10_pll_clock s10_pll_clks[] = {
42 	{ STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
43 	  0x0},
44 	{ STRATIX10_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
45 	  0, 0x74},
46 	{ STRATIX10_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
47 	  0, 0xe4},
48 };
49 
50 static const struct stratix10_perip_c_clock s10_main_perip_c_clks[] = {
51 	{ STRATIX10_MAIN_MPU_BASE_CLK, "main_mpu_base_clk", "main_pll", NULL, 1, 0, 0x84},
52 	{ STRATIX10_MAIN_NOC_BASE_CLK, "main_noc_base_clk", "main_pll", NULL, 1, 0, 0x88},
53 	{ STRATIX10_PERI_MPU_BASE_CLK, "peri_mpu_base_clk", "periph_pll", NULL, 1, 0,
54 	  0xF4},
55 	{ STRATIX10_PERI_NOC_BASE_CLK, "peri_noc_base_clk", "periph_pll", NULL, 1, 0,
56 	  0xF8},
57 };
58 
59 static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
60 	{ STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
61 	   0, 0x48, 0, 0, 0},
62 	{ STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
63 	  0, 0x4C, 0, 0, 0},
64 	{ STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
65 	  0x50, 0, 0, 0},
66 	{ STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
67 	  0x54, 0, 0, 0},
68 	{ STRATIX10_MAIN_EMAC_PTP_CLK, "main_emac_ptp_clk", "main_noc_base_clk", NULL, 1, 0,
69 	  0x58, 0, 0, 0},
70 	{ STRATIX10_MAIN_GPIO_DB_CLK, "main_gpio_db_clk", "main_noc_base_clk", NULL, 1, 0,
71 	  0x5C, 0, 0, 0},
72 	{ STRATIX10_MAIN_SDMMC_CLK, "main_sdmmc_clk", "main_noc_base_clk", NULL, 1, 0,
73 	  0x60, 0, 0, 0},
74 	{ STRATIX10_MAIN_S2F_USR0_CLK, "main_s2f_usr0_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
75 	  0, 0x64, 0, 0, 0},
76 	{ STRATIX10_MAIN_S2F_USR1_CLK, "main_s2f_usr1_clk", "main_noc_base_clk", NULL, 1, 0,
77 	  0x68, 0, 0, 0},
78 	{ STRATIX10_MAIN_PSI_REF_CLK, "main_psi_ref_clk", "main_noc_base_clk", NULL, 1, 0,
79 	  0x6C, 0, 0, 0},
80 	{ STRATIX10_PERI_EMACA_CLK, "peri_emaca_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
81 	  0, 0xBC, 0, 0, 0},
82 	{ STRATIX10_PERI_EMACB_CLK, "peri_emacb_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
83 	  0, 0xC0, 0, 0, 0},
84 	{ STRATIX10_PERI_EMAC_PTP_CLK, "peri_emac_ptp_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
85 	  0, 0xC4, 0, 0, 0},
86 	{ STRATIX10_PERI_GPIO_DB_CLK, "peri_gpio_db_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
87 	  0, 0xC8, 0, 0, 0},
88 	{ STRATIX10_PERI_SDMMC_CLK, "peri_sdmmc_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
89 	  0, 0xCC, 0, 0, 0},
90 	{ STRATIX10_PERI_S2F_USR0_CLK, "peri_s2f_usr0_clk", "peri_noc_base_clk", NULL, 1, 0,
91 	  0xD0, 0, 0, 0},
92 	{ STRATIX10_PERI_S2F_USR1_CLK, "peri_s2f_usr1_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
93 	  0, 0xD4, 0, 0, 0},
94 	{ STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
95 	  0xD8, 0, 0, 0},
96 	{ STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
97 	  0, 4, 0, 0},
98 	{ STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
99 	  0, 0, 0, 0x3C, 1},
100 	{ STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
101 	  0, 0, 4, 0xB0, 0},
102 	{ STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
103 	  0, 0, 4, 0xB0, 1},
104 	{ STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
105 	  ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
106 	{ STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
107 	  ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
108 	{ STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
109 	  ARRAY_SIZE(sdmmc_free_mux), 0, 0, 0, 0xB0, 4},
110 	{ STRATIX10_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
111 	  ARRAY_SIZE(s2f_usr1_free_mux), 0, 0, 0, 0xB0, 5},
112 	{ STRATIX10_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
113 	  ARRAY_SIZE(psi_ref_free_mux), 0, 0, 0, 0xB0, 6},
114 };
115 
116 static const struct stratix10_gate_clock s10_gate_clks[] = {
117 	{ STRATIX10_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x30,
118 	  0, 0, 0, 0, 0x3C, 0, 0},
119 	{ STRATIX10_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x30,
120 	  0, 0, 0, 0, 0, 0, 4},
121 	{ STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
122 	  0, 0, 0, 0, 0, 0, 2},
123 	{ STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
124 	  1, 0x70, 0, 2, 0, 0, 0},
125 	{ STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
126 	  2, 0x70, 8, 2, 0, 0, 0},
127 	{ STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
128 	  3, 0x70, 16, 2, 0, 0, 0},
129 	{ STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
130 	  4, 0x70, 24, 2, 0, 0, 0},
131 	{ STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
132 	  4, 0x70, 26, 2, 0, 0, 0},
133 	{ STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
134 	  4, 0x70, 28, 1, 0, 0, 0},
135 	{ STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
136 	  5, 0, 0, 0, 0, 0, 0},
137 	{ STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
138 	  6, 0, 0, 0, 0, 0, 0},
139 	{ STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
140 	  0, 0, 0, 0, 0xDC, 26, 0},
141 	{ STRATIX10_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
142 	  1, 0, 0, 0, 0xDC, 27, 0},
143 	{ STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
144 	  2, 0, 0, 0, 0xDC, 28, 0},
145 	{ STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
146 	  3, 0, 0, 0, 0, 0, 0},
147 	{ STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
148 	  4, 0xE0, 0, 16, 0, 0, 0},
149 	{ STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
150 	  5, 0, 0, 0, 0, 0, 4},
151 	{ STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
152 	  6, 0, 0, 0, 0, 0, 0},
153 	{ STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
154 	  7, 0, 0, 0, 0, 0, 0},
155 	{ STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
156 	  8, 0, 0, 0, 0, 0, 0},
157 	{ STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
158 	  9, 0, 0, 0, 0, 0, 0},
159 	{ STRATIX10_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0xA4,
160 	  10, 0, 0, 0, 0, 0, 0},
161 };
162 
163 static int s10_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
164 				    int nums, struct stratix10_clock_data *data)
165 {
166 	struct clk *clk;
167 	void __iomem *base = data->base;
168 	int i;
169 
170 	for (i = 0; i < nums; i++) {
171 		clk = s10_register_periph(clks[i].name, clks[i].parent_name,
172 					  clks[i].parent_names, clks[i].num_parents,
173 					  clks[i].flags, base, clks[i].offset);
174 		if (IS_ERR(clk)) {
175 			pr_err("%s: failed to register clock %s\n",
176 			       __func__, clks[i].name);
177 			continue;
178 		}
179 		data->clk_data.clks[clks[i].id] = clk;
180 	}
181 	return 0;
182 }
183 
184 static int s10_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
185 				      int nums, struct stratix10_clock_data *data)
186 {
187 	struct clk *clk;
188 	void __iomem *base = data->base;
189 	int i;
190 
191 	for (i = 0; i < nums; i++) {
192 		clk = s10_register_cnt_periph(clks[i].name, clks[i].parent_name,
193 					      clks[i].parent_names,
194 					      clks[i].num_parents,
195 					      clks[i].flags, base,
196 					      clks[i].offset,
197 					      clks[i].fixed_divider,
198 					      clks[i].bypass_reg,
199 					      clks[i].bypass_shift);
200 		if (IS_ERR(clk)) {
201 			pr_err("%s: failed to register clock %s\n",
202 			       __func__, clks[i].name);
203 			continue;
204 		}
205 		data->clk_data.clks[clks[i].id] = clk;
206 	}
207 
208 	return 0;
209 }
210 
211 static int s10_clk_register_gate(const struct stratix10_gate_clock *clks,
212 				 int nums, struct stratix10_clock_data *data)
213 {
214 	struct clk *clk;
215 	void __iomem *base = data->base;
216 	int i;
217 
218 	for (i = 0; i < nums; i++) {
219 		clk = s10_register_gate(clks[i].name, clks[i].parent_name,
220 					clks[i].parent_names,
221 					clks[i].num_parents,
222 					clks[i].flags, base,
223 					clks[i].gate_reg,
224 					clks[i].gate_idx, clks[i].div_reg,
225 					clks[i].div_offset, clks[i].div_width,
226 					clks[i].bypass_reg,
227 					clks[i].bypass_shift,
228 					clks[i].fixed_div);
229 		if (IS_ERR(clk)) {
230 			pr_err("%s: failed to register clock %s\n",
231 			       __func__, clks[i].name);
232 			continue;
233 		}
234 		data->clk_data.clks[clks[i].id] = clk;
235 	}
236 
237 	return 0;
238 }
239 
240 static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
241 				 int nums, struct stratix10_clock_data *data)
242 {
243 	struct clk *clk;
244 	void __iomem *base = data->base;
245 	int i;
246 
247 	for (i = 0; i < nums; i++) {
248 		clk = s10_register_pll(clks[i].name, clks[i].parent_names,
249 				    clks[i].num_parents,
250 				    clks[i].flags, base,
251 				    clks[i].offset);
252 		if (IS_ERR(clk)) {
253 			pr_err("%s: failed to register clock %s\n",
254 			       __func__, clks[i].name);
255 			continue;
256 		}
257 		data->clk_data.clks[clks[i].id] = clk;
258 	}
259 
260 	return 0;
261 }
262 
263 static struct stratix10_clock_data *__socfpga_s10_clk_init(struct platform_device *pdev,
264 						    int nr_clks)
265 {
266 	struct device_node *np = pdev->dev.of_node;
267 	struct device *dev = &pdev->dev;
268 	struct stratix10_clock_data *clk_data;
269 	struct clk **clk_table;
270 	struct resource *res;
271 	void __iomem *base;
272 
273 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
274 	base = devm_ioremap_resource(dev, res);
275 	if (IS_ERR(base)) {
276 		pr_err("%s: failed to map clock registers\n", __func__);
277 		return ERR_CAST(base);
278 	}
279 
280 	clk_data = devm_kzalloc(dev, sizeof(*clk_data), GFP_KERNEL);
281 	if (!clk_data)
282 		return ERR_PTR(-ENOMEM);
283 
284 	clk_data->base = base;
285 	clk_table = devm_kcalloc(dev, nr_clks, sizeof(*clk_table), GFP_KERNEL);
286 	if (!clk_table)
287 		return ERR_PTR(-ENOMEM);
288 
289 	clk_data->clk_data.clks = clk_table;
290 	clk_data->clk_data.clk_num = nr_clks;
291 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
292 	return clk_data;
293 }
294 
295 static int s10_clkmgr_init(struct platform_device *pdev)
296 {
297 	struct stratix10_clock_data *clk_data;
298 
299 	clk_data = __socfpga_s10_clk_init(pdev, STRATIX10_NUM_CLKS);
300 	if (IS_ERR(clk_data))
301 		return PTR_ERR(clk_data);
302 
303 	s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
304 
305 	s10_clk_register_c_perip(s10_main_perip_c_clks,
306 				 ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
307 
308 	s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
309 				   ARRAY_SIZE(s10_main_perip_cnt_clks),
310 				   clk_data);
311 
312 	s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
313 			      clk_data);
314 	return 0;
315 }
316 
317 static int s10_clkmgr_probe(struct platform_device *pdev)
318 {
319 	return	s10_clkmgr_init(pdev);
320 }
321 
322 static const struct of_device_id stratix10_clkmgr_match_table[] = {
323 	{ .compatible = "intel,stratix10-clkmgr",
324 	  .data = s10_clkmgr_init },
325 	{ }
326 };
327 
328 static struct platform_driver stratix10_clkmgr_driver = {
329 	.probe		= s10_clkmgr_probe,
330 	.driver		= {
331 		.name	= "stratix10-clkmgr",
332 		.suppress_bind_attrs = true,
333 		.of_match_table = stratix10_clkmgr_match_table,
334 	},
335 };
336 
337 static int __init s10_clk_init(void)
338 {
339 	return platform_driver_register(&stratix10_clkmgr_driver);
340 }
341 core_initcall(s10_clk_init);
342