.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2016 Maxime Ripard. All rights reserved. |
---|
3 | | - * |
---|
4 | | - * This software is licensed under the terms of the GNU General Public |
---|
5 | | - * License version 2, as published by the Free Software Foundation, and |
---|
6 | | - * may be copied, distributed, and modified under those terms. |
---|
7 | | - * |
---|
8 | | - * This program is distributed in the hope that it will be useful, |
---|
9 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
10 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
11 | | - * GNU General Public License for more details. |
---|
12 | 4 | */ |
---|
13 | 5 | |
---|
14 | 6 | #include <linux/clk-provider.h> |
---|
| 7 | +#include <linux/io.h> |
---|
15 | 8 | #include <linux/of_address.h> |
---|
16 | 9 | #include <linux/platform_device.h> |
---|
17 | 10 | |
---|
.. | .. |
---|
51 | 44 | * the base (2x, 4x and 8x), and one variable divider (the one true |
---|
52 | 45 | * pll audio). |
---|
53 | 46 | * |
---|
54 | | - * We don't have any need for the variable divider for now, so we just |
---|
55 | | - * hardcode it to match with the clock names |
---|
| 47 | + * With sigma-delta modulation for fractional-N on the audio PLL, |
---|
| 48 | + * we have to use specific dividers. This means the variable divider |
---|
| 49 | + * can no longer be used, as the audio codec requests the exact clock |
---|
| 50 | + * rates we support through this mechanism. So we now hard code the |
---|
| 51 | + * variable divider to 1. This means the clock rates will no longer |
---|
| 52 | + * match the clock names. |
---|
56 | 53 | */ |
---|
57 | 54 | #define SUN50I_A64_PLL_AUDIO_REG 0x008 |
---|
58 | 55 | |
---|
59 | | -static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", |
---|
60 | | - "osc24M", 0x008, |
---|
61 | | - 8, 7, /* N */ |
---|
62 | | - 0, 5, /* M */ |
---|
63 | | - BIT(31), /* gate */ |
---|
64 | | - BIT(28), /* lock */ |
---|
65 | | - CLK_SET_RATE_UNGATE); |
---|
| 56 | +static struct ccu_sdm_setting pll_audio_sdm_table[] = { |
---|
| 57 | + { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 }, |
---|
| 58 | + { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 }, |
---|
| 59 | +}; |
---|
66 | 60 | |
---|
67 | | -static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0", |
---|
68 | | - "osc24M", 0x010, |
---|
69 | | - 8, 7, /* N */ |
---|
70 | | - 0, 4, /* M */ |
---|
71 | | - BIT(24), /* frac enable */ |
---|
72 | | - BIT(25), /* frac select */ |
---|
73 | | - 270000000, /* frac rate 0 */ |
---|
74 | | - 297000000, /* frac rate 1 */ |
---|
75 | | - BIT(31), /* gate */ |
---|
76 | | - BIT(28), /* lock */ |
---|
77 | | - CLK_SET_RATE_UNGATE); |
---|
| 61 | +static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", |
---|
| 62 | + "osc24M", 0x008, |
---|
| 63 | + 8, 7, /* N */ |
---|
| 64 | + 0, 5, /* M */ |
---|
| 65 | + pll_audio_sdm_table, BIT(24), |
---|
| 66 | + 0x284, BIT(31), |
---|
| 67 | + BIT(31), /* gate */ |
---|
| 68 | + BIT(28), /* lock */ |
---|
| 69 | + CLK_SET_RATE_UNGATE); |
---|
| 70 | + |
---|
| 71 | +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video0_clk, "pll-video0", |
---|
| 72 | + "osc24M", 0x010, |
---|
| 73 | + 192000000, /* Minimum rate */ |
---|
| 74 | + 1008000000, /* Maximum rate */ |
---|
| 75 | + 8, 7, /* N */ |
---|
| 76 | + 0, 4, /* M */ |
---|
| 77 | + BIT(24), /* frac enable */ |
---|
| 78 | + BIT(25), /* frac select */ |
---|
| 79 | + 270000000, /* frac rate 0 */ |
---|
| 80 | + 297000000, /* frac rate 1 */ |
---|
| 81 | + BIT(31), /* gate */ |
---|
| 82 | + BIT(28), /* lock */ |
---|
| 83 | + CLK_SET_RATE_UNGATE); |
---|
78 | 84 | |
---|
79 | 85 | static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", |
---|
80 | 86 | "osc24M", 0x018, |
---|
.. | .. |
---|
125 | 131 | }, |
---|
126 | 132 | }; |
---|
127 | 133 | |
---|
128 | | -static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1", |
---|
129 | | - "osc24M", 0x030, |
---|
130 | | - 8, 7, /* N */ |
---|
131 | | - 0, 4, /* M */ |
---|
132 | | - BIT(24), /* frac enable */ |
---|
133 | | - BIT(25), /* frac select */ |
---|
134 | | - 270000000, /* frac rate 0 */ |
---|
135 | | - 297000000, /* frac rate 1 */ |
---|
136 | | - BIT(31), /* gate */ |
---|
137 | | - BIT(28), /* lock */ |
---|
138 | | - CLK_SET_RATE_UNGATE); |
---|
| 134 | +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video1_clk, "pll-video1", |
---|
| 135 | + "osc24M", 0x030, |
---|
| 136 | + 192000000, /* Minimum rate */ |
---|
| 137 | + 1008000000, /* Maximum rate */ |
---|
| 138 | + 8, 7, /* N */ |
---|
| 139 | + 0, 4, /* M */ |
---|
| 140 | + BIT(24), /* frac enable */ |
---|
| 141 | + BIT(25), /* frac select */ |
---|
| 142 | + 270000000, /* frac rate 0 */ |
---|
| 143 | + 297000000, /* frac rate 1 */ |
---|
| 144 | + BIT(31), /* gate */ |
---|
| 145 | + BIT(28), /* lock */ |
---|
| 146 | + CLK_SET_RATE_UNGATE); |
---|
139 | 147 | |
---|
140 | 148 | static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", |
---|
141 | 149 | "osc24M", 0x038, |
---|
.. | .. |
---|
517 | 525 | |
---|
518 | 526 | static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" }; |
---|
519 | 527 | static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, |
---|
520 | | - 0x104, 0, 4, 24, 3, BIT(31), 0); |
---|
| 528 | + 0x104, 0, 4, 24, 3, BIT(31), |
---|
| 529 | + CLK_SET_RATE_PARENT); |
---|
521 | 530 | |
---|
522 | 531 | static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" }; |
---|
523 | 532 | static const u8 tcon0_table[] = { 0, 2, }; |
---|
.. | .. |
---|
556 | 565 | 0x134, 0, 5, 8, 3, BIT(15), 0); |
---|
557 | 566 | |
---|
558 | 567 | static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", |
---|
559 | | - 0x13c, 16, 3, BIT(31), 0); |
---|
| 568 | + 0x13c, 16, 3, BIT(31), CLK_SET_RATE_PARENT); |
---|
560 | 569 | |
---|
561 | 570 | static SUNXI_CCU_GATE(ac_dig_clk, "ac-dig", "pll-audio", |
---|
562 | 571 | 0x140, BIT(31), CLK_SET_RATE_PARENT); |
---|
.. | .. |
---|
589 | 598 | 0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT); |
---|
590 | 599 | |
---|
591 | 600 | /* Fixed Factor clocks */ |
---|
592 | | -static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 2, 1, 0); |
---|
| 601 | +static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0); |
---|
593 | 602 | |
---|
594 | | -/* We hardcode the divider to 4 for now */ |
---|
595 | | -static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", |
---|
596 | | - "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); |
---|
597 | | -static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", |
---|
598 | | - "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); |
---|
599 | | -static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", |
---|
600 | | - "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); |
---|
601 | | -static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x", |
---|
602 | | - "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT); |
---|
603 | | -static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x", |
---|
604 | | - "pll-periph0", 1, 2, 0); |
---|
605 | | -static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x", |
---|
606 | | - "pll-periph1", 1, 2, 0); |
---|
607 | | -static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x", |
---|
608 | | - "pll-video0", 1, 2, CLK_SET_RATE_PARENT); |
---|
| 603 | +static const struct clk_hw *clk_parent_pll_audio[] = { |
---|
| 604 | + &pll_audio_base_clk.common.hw |
---|
| 605 | +}; |
---|
| 606 | + |
---|
| 607 | +/* We hardcode the divider to 1 for now */ |
---|
| 608 | +static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio", |
---|
| 609 | + clk_parent_pll_audio, |
---|
| 610 | + 1, 1, CLK_SET_RATE_PARENT); |
---|
| 611 | +static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x", |
---|
| 612 | + clk_parent_pll_audio, |
---|
| 613 | + 2, 1, CLK_SET_RATE_PARENT); |
---|
| 614 | +static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x", |
---|
| 615 | + clk_parent_pll_audio, |
---|
| 616 | + 1, 1, CLK_SET_RATE_PARENT); |
---|
| 617 | +static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x", |
---|
| 618 | + clk_parent_pll_audio, |
---|
| 619 | + 1, 2, CLK_SET_RATE_PARENT); |
---|
| 620 | +static CLK_FIXED_FACTOR_HW(pll_periph0_2x_clk, "pll-periph0-2x", |
---|
| 621 | + &pll_periph0_clk.common.hw, |
---|
| 622 | + 1, 2, 0); |
---|
| 623 | +static CLK_FIXED_FACTOR_HW(pll_periph1_2x_clk, "pll-periph1-2x", |
---|
| 624 | + &pll_periph1_clk.common.hw, |
---|
| 625 | + 1, 2, 0); |
---|
| 626 | +static CLK_FIXED_FACTOR_HW(pll_video0_2x_clk, "pll-video0-2x", |
---|
| 627 | + &pll_video0_clk.common.hw, |
---|
| 628 | + 1, 2, CLK_SET_RATE_PARENT); |
---|
609 | 629 | |
---|
610 | 630 | static struct ccu_common *sun50i_a64_ccu_clks[] = { |
---|
611 | 631 | &pll_cpux_clk.common, |
---|
.. | .. |
---|
928 | 948 | if (IS_ERR(reg)) |
---|
929 | 949 | return PTR_ERR(reg); |
---|
930 | 950 | |
---|
931 | | - /* Force the PLL-Audio-1x divider to 4 */ |
---|
| 951 | + /* Force the PLL-Audio-1x divider to 1 */ |
---|
932 | 952 | val = readl(reg + SUN50I_A64_PLL_AUDIO_REG); |
---|
933 | 953 | val &= ~GENMASK(19, 16); |
---|
934 | | - writel(val | (3 << 16), reg + SUN50I_A64_PLL_AUDIO_REG); |
---|
| 954 | + writel(val | (0 << 16), reg + SUN50I_A64_PLL_AUDIO_REG); |
---|
935 | 955 | |
---|
936 | 956 | writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG); |
---|
937 | 957 | |
---|