xref: /linux/drivers/clk/qcom/ipq-cmn-pll.c (revision 6e9a12f85a7567bb9a41d5230468886bd6a27b20)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
4  */
5 
6 /*
7  * CMN PLL block expects the reference clock from on-board Wi-Fi block,
8  * and supplies fixed rate clocks as output to the networking hardware
9  * blocks and to GCC. The networking related blocks include PPE (packet
10  * process engine), the externally connected PHY or switch devices, and
11  * the PCS.
12  *
13  * On the IPQ9574 SoC, there are three clocks with 50 MHZ and one clock
14  * with 25 MHZ which are output from the CMN PLL to Ethernet PHY (or switch),
15  * and one clock with 353 MHZ to PPE. The other fixed rate output clocks
16  * are supplied to GCC (24 MHZ as XO and 32 KHZ as sleep clock), and to PCS
17  * with 31.25 MHZ.
18  *
19  * On the IPQ5424 SoC, there is an output clock from CMN PLL to PPE at 375 MHZ,
20  * and an output clock to NSS (network subsystem) at 300 MHZ. The other output
21  * clocks from CMN PLL on IPQ5424 are the same as IPQ9574.
22  *
23  *               +---------+
24  *               |   GCC   |
25  *               +--+---+--+
26  *           AHB CLK|   |SYS CLK
27  *                  V   V
28  *          +-------+---+------+
29  *          |                  +-------------> eth0-50mhz
30  * REF CLK  |     IPQ9574      |
31  * -------->+                  +-------------> eth1-50mhz
32  *          |  CMN PLL block   |
33  *          |                  +-------------> eth2-50mhz
34  *          |                  |
35  *          +----+----+----+---+-------------> eth-25mhz
36  *               |    |    |
37  *               V    V    V
38  *              GCC  PCS  NSS/PPE
39  */
40 
41 #include <linux/bitfield.h>
42 #include <linux/clk-provider.h>
43 #include <linux/delay.h>
44 #include <linux/err.h>
45 #include <linux/mod_devicetable.h>
46 #include <linux/module.h>
47 #include <linux/platform_device.h>
48 #include <linux/pm_clock.h>
49 #include <linux/pm_runtime.h>
50 #include <linux/regmap.h>
51 
52 #include <dt-bindings/clock/qcom,ipq-cmn-pll.h>
53 #include <dt-bindings/clock/qcom,ipq5018-cmn-pll.h>
54 #include <dt-bindings/clock/qcom,ipq5424-cmn-pll.h>
55 
56 #define CMN_PLL_REFCLK_SRC_SELECTION		0x28
57 #define CMN_PLL_REFCLK_SRC_DIV			GENMASK(9, 8)
58 
59 #define CMN_PLL_LOCKED				0x64
60 #define CMN_PLL_CLKS_LOCKED			BIT(8)
61 
62 #define CMN_PLL_POWER_ON_AND_RESET		0x780
63 #define CMN_ANA_EN_SW_RSTN			BIT(6)
64 
65 #define CMN_PLL_REFCLK_CONFIG			0x784
66 #define CMN_PLL_REFCLK_EXTERNAL			BIT(9)
67 #define CMN_PLL_REFCLK_DIV			GENMASK(8, 4)
68 #define CMN_PLL_REFCLK_INDEX			GENMASK(3, 0)
69 
70 #define CMN_PLL_CTRL				0x78c
71 #define CMN_PLL_CTRL_LOCK_DETECT_EN		BIT(15)
72 
73 #define CMN_PLL_DIVIDER_CTRL			0x794
74 #define CMN_PLL_DIVIDER_CTRL_FACTOR		GENMASK(9, 0)
75 
76 /**
77  * struct cmn_pll_fixed_output_clk - CMN PLL output clocks information
78  * @id:	Clock specifier to be supplied
79  * @name: Clock name to be registered
80  * @rate: Clock rate
81  */
82 struct cmn_pll_fixed_output_clk {
83 	unsigned int id;
84 	const char *name;
85 	unsigned long rate;
86 };
87 
88 /**
89  * struct clk_cmn_pll - CMN PLL hardware specific data
90  * @regmap: hardware regmap.
91  * @hw: handle between common and hardware-specific interfaces
92  */
93 struct clk_cmn_pll {
94 	struct regmap *regmap;
95 	struct clk_hw hw;
96 };
97 
98 #define CLK_PLL_OUTPUT(_id, _name, _rate) {		\
99 	.id =		_id,				\
100 	.name =		_name,				\
101 	.rate =		_rate,				\
102 }
103 
104 #define to_clk_cmn_pll(_hw) container_of(_hw, struct clk_cmn_pll, hw)
105 
106 static const struct regmap_config ipq_cmn_pll_regmap_config = {
107 	.reg_bits = 32,
108 	.reg_stride = 4,
109 	.val_bits = 32,
110 	.max_register = 0x7fc,
111 	.fast_io = true,
112 };
113 
114 static const struct cmn_pll_fixed_output_clk ipq5018_output_clks[] = {
115 	CLK_PLL_OUTPUT(IPQ5018_XO_24MHZ_CLK, "xo-24mhz", 24000000UL),
116 	CLK_PLL_OUTPUT(IPQ5018_SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL),
117 	CLK_PLL_OUTPUT(IPQ5018_ETH_50MHZ_CLK, "eth-50mhz", 50000000UL),
118 	{ /* Sentinel */ }
119 };
120 
121 static const struct cmn_pll_fixed_output_clk ipq5424_output_clks[] = {
122 	CLK_PLL_OUTPUT(IPQ5424_XO_24MHZ_CLK, "xo-24mhz", 24000000UL),
123 	CLK_PLL_OUTPUT(IPQ5424_SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL),
124 	CLK_PLL_OUTPUT(IPQ5424_PCS_31P25MHZ_CLK, "pcs-31p25mhz", 31250000UL),
125 	CLK_PLL_OUTPUT(IPQ5424_NSS_300MHZ_CLK, "nss-300mhz", 300000000UL),
126 	CLK_PLL_OUTPUT(IPQ5424_PPE_375MHZ_CLK, "ppe-375mhz", 375000000UL),
127 	CLK_PLL_OUTPUT(IPQ5424_ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL),
128 	CLK_PLL_OUTPUT(IPQ5424_ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL),
129 	CLK_PLL_OUTPUT(IPQ5424_ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL),
130 	CLK_PLL_OUTPUT(IPQ5424_ETH_25MHZ_CLK, "eth-25mhz", 25000000UL),
131 	{ /* Sentinel */ }
132 };
133 
134 static const struct cmn_pll_fixed_output_clk ipq9574_output_clks[] = {
135 	CLK_PLL_OUTPUT(XO_24MHZ_CLK, "xo-24mhz", 24000000UL),
136 	CLK_PLL_OUTPUT(SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL),
137 	CLK_PLL_OUTPUT(PCS_31P25MHZ_CLK, "pcs-31p25mhz", 31250000UL),
138 	CLK_PLL_OUTPUT(NSS_1200MHZ_CLK, "nss-1200mhz", 1200000000UL),
139 	CLK_PLL_OUTPUT(PPE_353MHZ_CLK, "ppe-353mhz", 353000000UL),
140 	CLK_PLL_OUTPUT(ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL),
141 	CLK_PLL_OUTPUT(ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL),
142 	CLK_PLL_OUTPUT(ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL),
143 	CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL),
144 	{ /* Sentinel */ }
145 };
146 
147 /*
148  * CMN PLL has the single parent clock, which supports the several
149  * possible parent clock rates, each parent clock rate is reflected
150  * by the specific reference index value in the hardware.
151  */
152 static int ipq_cmn_pll_find_freq_index(unsigned long parent_rate)
153 {
154 	int index = -EINVAL;
155 
156 	switch (parent_rate) {
157 	case 25000000:
158 		index = 3;
159 		break;
160 	case 31250000:
161 		index = 4;
162 		break;
163 	case 40000000:
164 		index = 6;
165 		break;
166 	case 48000000:
167 	case 96000000:
168 		/*
169 		 * Parent clock rate 48 MHZ and 96 MHZ take the same value
170 		 * of reference clock index. 96 MHZ needs the source clock
171 		 * divider to be programmed as 2.
172 		 */
173 		index = 7;
174 		break;
175 	case 50000000:
176 		index = 8;
177 		break;
178 	default:
179 		break;
180 	}
181 
182 	return index;
183 }
184 
185 static unsigned long clk_cmn_pll_recalc_rate(struct clk_hw *hw,
186 					     unsigned long parent_rate)
187 {
188 	struct clk_cmn_pll *cmn_pll = to_clk_cmn_pll(hw);
189 	u32 val, factor;
190 
191 	/*
192 	 * The value of CMN_PLL_DIVIDER_CTRL_FACTOR is automatically adjusted
193 	 * by HW according to the parent clock rate.
194 	 */
195 	regmap_read(cmn_pll->regmap, CMN_PLL_DIVIDER_CTRL, &val);
196 	factor = FIELD_GET(CMN_PLL_DIVIDER_CTRL_FACTOR, val);
197 
198 	return parent_rate * 2 * factor;
199 }
200 
201 static int clk_cmn_pll_determine_rate(struct clk_hw *hw,
202 				      struct clk_rate_request *req)
203 {
204 	int ret;
205 
206 	/* Validate the rate of the single parent clock. */
207 	ret = ipq_cmn_pll_find_freq_index(req->best_parent_rate);
208 
209 	return ret < 0 ? ret : 0;
210 }
211 
212 /*
213  * This function is used to initialize the CMN PLL to enable the fixed
214  * rate output clocks. It is expected to be configured once.
215  */
216 static int clk_cmn_pll_set_rate(struct clk_hw *hw, unsigned long rate,
217 				unsigned long parent_rate)
218 {
219 	struct clk_cmn_pll *cmn_pll = to_clk_cmn_pll(hw);
220 	int ret, index;
221 	u32 val;
222 
223 	/*
224 	 * Configure the reference input clock selection as per the given
225 	 * parent clock. The output clock rates are always of fixed value.
226 	 */
227 	index = ipq_cmn_pll_find_freq_index(parent_rate);
228 	if (index < 0)
229 		return index;
230 
231 	ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_CONFIG,
232 				 CMN_PLL_REFCLK_INDEX,
233 				 FIELD_PREP(CMN_PLL_REFCLK_INDEX, index));
234 	if (ret)
235 		return ret;
236 
237 	/*
238 	 * Update the source clock rate selection and source clock
239 	 * divider as 2 when the parent clock rate is 96 MHZ.
240 	 */
241 	if (parent_rate == 96000000) {
242 		ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_CONFIG,
243 					 CMN_PLL_REFCLK_DIV,
244 					 FIELD_PREP(CMN_PLL_REFCLK_DIV, 2));
245 		if (ret)
246 			return ret;
247 
248 		ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_SRC_SELECTION,
249 					 CMN_PLL_REFCLK_SRC_DIV,
250 					 FIELD_PREP(CMN_PLL_REFCLK_SRC_DIV, 0));
251 		if (ret)
252 			return ret;
253 	}
254 
255 	/* Enable PLL locked detect. */
256 	ret = regmap_set_bits(cmn_pll->regmap, CMN_PLL_CTRL,
257 			      CMN_PLL_CTRL_LOCK_DETECT_EN);
258 	if (ret)
259 		return ret;
260 
261 	/*
262 	 * Reset the CMN PLL block to ensure the updated configurations
263 	 * take effect.
264 	 */
265 	ret = regmap_clear_bits(cmn_pll->regmap, CMN_PLL_POWER_ON_AND_RESET,
266 				CMN_ANA_EN_SW_RSTN);
267 	if (ret)
268 		return ret;
269 
270 	usleep_range(1000, 1200);
271 	ret = regmap_set_bits(cmn_pll->regmap, CMN_PLL_POWER_ON_AND_RESET,
272 			      CMN_ANA_EN_SW_RSTN);
273 	if (ret)
274 		return ret;
275 
276 	/* Stability check of CMN PLL output clocks. */
277 	return regmap_read_poll_timeout(cmn_pll->regmap, CMN_PLL_LOCKED, val,
278 					(val & CMN_PLL_CLKS_LOCKED),
279 					100, 100 * USEC_PER_MSEC);
280 }
281 
282 static const struct clk_ops clk_cmn_pll_ops = {
283 	.recalc_rate = clk_cmn_pll_recalc_rate,
284 	.determine_rate = clk_cmn_pll_determine_rate,
285 	.set_rate = clk_cmn_pll_set_rate,
286 };
287 
288 static struct clk_hw *ipq_cmn_pll_clk_hw_register(struct platform_device *pdev)
289 {
290 	struct clk_parent_data pdata = { .index = 0 };
291 	struct device *dev = &pdev->dev;
292 	struct clk_init_data init = {};
293 	struct clk_cmn_pll *cmn_pll;
294 	struct regmap *regmap;
295 	void __iomem *base;
296 	int ret;
297 
298 	base = devm_platform_ioremap_resource(pdev, 0);
299 	if (IS_ERR(base))
300 		return ERR_CAST(base);
301 
302 	regmap = devm_regmap_init_mmio(dev, base, &ipq_cmn_pll_regmap_config);
303 	if (IS_ERR(regmap))
304 		return ERR_CAST(regmap);
305 
306 	cmn_pll = devm_kzalloc(dev, sizeof(*cmn_pll), GFP_KERNEL);
307 	if (!cmn_pll)
308 		return ERR_PTR(-ENOMEM);
309 
310 	init.name = "cmn_pll";
311 	init.parent_data = &pdata;
312 	init.num_parents = 1;
313 	init.ops = &clk_cmn_pll_ops;
314 
315 	cmn_pll->hw.init = &init;
316 	cmn_pll->regmap = regmap;
317 
318 	ret = devm_clk_hw_register(dev, &cmn_pll->hw);
319 	if (ret)
320 		return ERR_PTR(ret);
321 
322 	return &cmn_pll->hw;
323 }
324 
325 static int ipq_cmn_pll_register_clks(struct platform_device *pdev)
326 {
327 	const struct cmn_pll_fixed_output_clk *p, *fixed_clk;
328 	struct clk_hw_onecell_data *hw_data;
329 	struct device *dev = &pdev->dev;
330 	struct clk_hw *cmn_pll_hw;
331 	unsigned int num_clks;
332 	struct clk_hw *hw;
333 	int ret, i;
334 
335 	fixed_clk = device_get_match_data(dev);
336 	if (!fixed_clk)
337 		return -EINVAL;
338 
339 	num_clks = 0;
340 	for (p = fixed_clk; p->name; p++)
341 		num_clks++;
342 
343 	hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, num_clks + 1),
344 			       GFP_KERNEL);
345 	if (!hw_data)
346 		return -ENOMEM;
347 
348 	/*
349 	 * Register the CMN PLL clock, which is the parent clock of
350 	 * the fixed rate output clocks.
351 	 */
352 	cmn_pll_hw = ipq_cmn_pll_clk_hw_register(pdev);
353 	if (IS_ERR(cmn_pll_hw))
354 		return PTR_ERR(cmn_pll_hw);
355 
356 	/* Register the fixed rate output clocks. */
357 	for (i = 0; i < num_clks; i++) {
358 		hw = clk_hw_register_fixed_rate_parent_hw(dev, fixed_clk[i].name,
359 							  cmn_pll_hw, 0,
360 							  fixed_clk[i].rate);
361 		if (IS_ERR(hw)) {
362 			ret = PTR_ERR(hw);
363 			goto unregister_fixed_clk;
364 		}
365 
366 		hw_data->hws[fixed_clk[i].id] = hw;
367 	}
368 
369 	/*
370 	 * Provide the CMN PLL clock. The clock rate of CMN PLL
371 	 * is configured to 12 GHZ by DT property assigned-clock-rates-u64.
372 	 */
373 	hw_data->hws[CMN_PLL_CLK] = cmn_pll_hw;
374 	hw_data->num = num_clks + 1;
375 
376 	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data);
377 	if (ret)
378 		goto unregister_fixed_clk;
379 
380 	platform_set_drvdata(pdev, hw_data);
381 
382 	return 0;
383 
384 unregister_fixed_clk:
385 	while (i > 0)
386 		clk_hw_unregister(hw_data->hws[fixed_clk[--i].id]);
387 
388 	return ret;
389 }
390 
391 static int ipq_cmn_pll_clk_probe(struct platform_device *pdev)
392 {
393 	struct device *dev = &pdev->dev;
394 	int ret;
395 
396 	ret = devm_pm_runtime_enable(dev);
397 	if (ret)
398 		return ret;
399 
400 	ret = devm_pm_clk_create(dev);
401 	if (ret)
402 		return ret;
403 
404 	/*
405 	 * To access the CMN PLL registers, the GCC AHB & SYS clocks
406 	 * of CMN PLL block need to be enabled.
407 	 */
408 	ret = pm_clk_add(dev, "ahb");
409 	if (ret)
410 		return dev_err_probe(dev, ret, "Failed to add AHB clock\n");
411 
412 	ret = pm_clk_add(dev, "sys");
413 	if (ret)
414 		return dev_err_probe(dev, ret, "Failed to add SYS clock\n");
415 
416 	ret = pm_runtime_resume_and_get(dev);
417 	if (ret)
418 		return ret;
419 
420 	/* Register CMN PLL clock and fixed rate output clocks. */
421 	ret = ipq_cmn_pll_register_clks(pdev);
422 	pm_runtime_put(dev);
423 	if (ret)
424 		return dev_err_probe(dev, ret,
425 				     "Failed to register CMN PLL clocks\n");
426 
427 	return 0;
428 }
429 
430 static void ipq_cmn_pll_clk_remove(struct platform_device *pdev)
431 {
432 	struct clk_hw_onecell_data *hw_data = platform_get_drvdata(pdev);
433 	int i;
434 
435 	/*
436 	 * The clock with index CMN_PLL_CLK is unregistered by
437 	 * device management.
438 	 */
439 	for (i = 0; i < hw_data->num; i++) {
440 		if (i != CMN_PLL_CLK)
441 			clk_hw_unregister(hw_data->hws[i]);
442 	}
443 }
444 
445 static const struct dev_pm_ops ipq_cmn_pll_pm_ops = {
446 	SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
447 };
448 
449 static const struct of_device_id ipq_cmn_pll_clk_ids[] = {
450 	{ .compatible = "qcom,ipq5018-cmn-pll", .data = &ipq5018_output_clks },
451 	{ .compatible = "qcom,ipq5424-cmn-pll", .data = &ipq5424_output_clks },
452 	{ .compatible = "qcom,ipq9574-cmn-pll", .data = &ipq9574_output_clks },
453 	{ }
454 };
455 MODULE_DEVICE_TABLE(of, ipq_cmn_pll_clk_ids);
456 
457 static struct platform_driver ipq_cmn_pll_clk_driver = {
458 	.probe = ipq_cmn_pll_clk_probe,
459 	.remove = ipq_cmn_pll_clk_remove,
460 	.driver = {
461 		.name = "ipq_cmn_pll",
462 		.of_match_table = ipq_cmn_pll_clk_ids,
463 		.pm = &ipq_cmn_pll_pm_ops,
464 	},
465 };
466 module_platform_driver(ipq_cmn_pll_clk_driver);
467 
468 MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ CMN PLL Driver");
469 MODULE_LICENSE("GPL");
470