hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/clk/at91/clk-audio-pll.c
....@@ -1,14 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2016 Atmel Corporation,
34 * Songjun Wu <songjun.wu@atmel.com>,
45 * Nicolas Ferre <nicolas.ferre@atmel.com>
56 * Copyright (C) 2017 Free Electrons,
67 * Quentin Schulz <quentin.schulz@free-electrons.com>
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; either version 2 of the License, or
11
- * (at your option) any later version.
128 *
139 * The Sama5d2 SoC has two audio PLLs (PMC and PAD) that shares the same parent
1410 * (FRAC). FRAC can output between 620 and 700MHz and only multiply the rate of
....@@ -32,7 +28,6 @@
3228 * rate - rate is adjustable.
3329 * clk->rate = parent->rate / (qdaudio * div))
3430 * parent - fixed parent. No clk_set_parent support
35
- *
3631 */
3732
3833 #include <linux/clk.h>
....@@ -42,6 +37,8 @@
4237 #include <linux/mfd/syscon.h>
4338 #include <linux/regmap.h>
4439 #include <linux/slab.h>
40
+
41
+#include "pmc.h"
4542
4643 #define AUDIO_PLL_DIV_FRAC BIT(22)
4744 #define AUDIO_PLL_ND_MAX (AT91_PMC_AUDIO_PLL_ND_MASK >> \
....@@ -338,7 +335,12 @@
338335 pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n", __func__,
339336 rate, *parent_rate);
340337
341
- for (div = 1; div <= AUDIO_PLL_QDPMC_MAX; div++) {
338
+ if (!rate)
339
+ return 0;
340
+
341
+ best_parent_rate = clk_round_rate(pclk->clk, 1);
342
+ div = max(best_parent_rate / rate, 1UL);
343
+ for (; div <= AUDIO_PLL_QDPMC_MAX; div++) {
342344 best_parent_rate = clk_round_rate(pclk->clk, rate * div);
343345 tmp_rate = best_parent_rate / div;
344346 tmp_diff = abs(rate - tmp_rate);
....@@ -348,6 +350,8 @@
348350 best_rate = tmp_rate;
349351 best_diff = tmp_diff;
350352 tmp_qd = div;
353
+ if (!best_diff)
354
+ break; /* got exact match */
351355 }
352356 }
353357
....@@ -444,93 +448,94 @@
444448 .set_rate = clk_audio_pll_pmc_set_rate,
445449 };
446450
447
-static int of_sama5d2_clk_audio_pll_setup(struct device_node *np,
448
- struct clk_init_data *init,
449
- struct clk_hw *hw,
450
- struct regmap **clk_audio_regmap)
451
-{
452
- struct regmap *regmap;
453
- const char *parent_names[1];
454
- int ret;
455
-
456
- regmap = syscon_node_to_regmap(of_get_parent(np));
457
- if (IS_ERR(regmap))
458
- return PTR_ERR(regmap);
459
-
460
- init->name = np->name;
461
- of_clk_parent_fill(np, parent_names, 1);
462
- init->parent_names = parent_names;
463
- init->num_parents = 1;
464
-
465
- hw->init = init;
466
- *clk_audio_regmap = regmap;
467
-
468
- ret = clk_hw_register(NULL, hw);
469
- if (ret)
470
- return ret;
471
-
472
- return of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
473
-}
474
-
475
-static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
451
+struct clk_hw * __init
452
+at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
453
+ const char *parent_name)
476454 {
477455 struct clk_audio_frac *frac_ck;
478456 struct clk_init_data init = {};
457
+ int ret;
479458
480459 frac_ck = kzalloc(sizeof(*frac_ck), GFP_KERNEL);
481460 if (!frac_ck)
482
- return;
461
+ return ERR_PTR(-ENOMEM);
483462
463
+ init.name = name;
484464 init.ops = &audio_pll_frac_ops;
465
+ init.parent_names = &parent_name;
466
+ init.num_parents = 1;
485467 init.flags = CLK_SET_RATE_GATE;
486468
487
- if (of_sama5d2_clk_audio_pll_setup(np, &init, &frac_ck->hw,
488
- &frac_ck->regmap))
469
+ frac_ck->hw.init = &init;
470
+ frac_ck->regmap = regmap;
471
+
472
+ ret = clk_hw_register(NULL, &frac_ck->hw);
473
+ if (ret) {
489474 kfree(frac_ck);
475
+ return ERR_PTR(ret);
476
+ }
477
+
478
+ return &frac_ck->hw;
490479 }
491480
492
-static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np)
481
+struct clk_hw * __init
482
+at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
483
+ const char *parent_name)
493484 {
494485 struct clk_audio_pad *apad_ck;
495
- struct clk_init_data init = {};
486
+ struct clk_init_data init;
487
+ int ret;
496488
497489 apad_ck = kzalloc(sizeof(*apad_ck), GFP_KERNEL);
498490 if (!apad_ck)
499
- return;
491
+ return ERR_PTR(-ENOMEM);
500492
493
+ init.name = name;
501494 init.ops = &audio_pll_pad_ops;
495
+ init.parent_names = &parent_name;
496
+ init.num_parents = 1;
502497 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
503498 CLK_SET_RATE_PARENT;
504499
505
- if (of_sama5d2_clk_audio_pll_setup(np, &init, &apad_ck->hw,
506
- &apad_ck->regmap))
500
+ apad_ck->hw.init = &init;
501
+ apad_ck->regmap = regmap;
502
+
503
+ ret = clk_hw_register(NULL, &apad_ck->hw);
504
+ if (ret) {
507505 kfree(apad_ck);
506
+ return ERR_PTR(ret);
507
+ }
508
+
509
+ return &apad_ck->hw;
508510 }
509511
510
-static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np)
512
+struct clk_hw * __init
513
+at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
514
+ const char *parent_name)
511515 {
512516 struct clk_audio_pmc *apmc_ck;
513
- struct clk_init_data init = {};
517
+ struct clk_init_data init;
518
+ int ret;
514519
515520 apmc_ck = kzalloc(sizeof(*apmc_ck), GFP_KERNEL);
516521 if (!apmc_ck)
517
- return;
522
+ return ERR_PTR(-ENOMEM);
518523
524
+ init.name = name;
519525 init.ops = &audio_pll_pmc_ops;
526
+ init.parent_names = &parent_name;
527
+ init.num_parents = 1;
520528 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
521529 CLK_SET_RATE_PARENT;
522530
523
- if (of_sama5d2_clk_audio_pll_setup(np, &init, &apmc_ck->hw,
524
- &apmc_ck->regmap))
525
- kfree(apmc_ck);
526
-}
531
+ apmc_ck->hw.init = &init;
532
+ apmc_ck->regmap = regmap;
527533
528
-CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup,
529
- "atmel,sama5d2-clk-audio-pll-frac",
530
- of_sama5d2_clk_audio_pll_frac_setup);
531
-CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup,
532
- "atmel,sama5d2-clk-audio-pll-pad",
533
- of_sama5d2_clk_audio_pll_pad_setup);
534
-CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup,
535
- "atmel,sama5d2-clk-audio-pll-pmc",
536
- of_sama5d2_clk_audio_pll_pmc_setup);
534
+ ret = clk_hw_register(NULL, &apmc_ck->hw);
535
+ if (ret) {
536
+ kfree(apmc_ck);
537
+ return ERR_PTR(ret);
538
+ }
539
+
540
+ return &apmc_ck->hw;
541
+}