diff options
Diffstat (limited to 'drivers/clk/sunxi-ng/ccu-sun8i-h3.c')
-rw-r--r-- | drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 56 |
1 files changed, 34 insertions, 22 deletions
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index 1729ff6a5aae..29bc0566b776 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -26,6 +26,7 @@ #include "ccu_nkmp.h" #include "ccu_nm.h" #include "ccu_phase.h" +#include "ccu_sdm.h" #include "ccu-sun8i-h3.h" @@ -37,25 +38,36 @@ static SUNXI_CCU_NKMP_WITH_GATE_LOCK(pll_cpux_clk, "pll-cpux", 16, 2, /* P */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); /* * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from * the base (2x, 4x and 8x), and one variable divider (the one true * pll audio). * - * We don't have any need for the variable divider for now, so we just - * hardcode it to match with the clock names + * With sigma-delta modulation for fractional-N on the audio PLL, + * we have to use specific dividers. This means the variable divider + * can no longer be used, as the audio codec requests the exact clock + * rates we support through this mechanism. So we now hard code the + * variable divider to 1. This means the clock rates will no longer + * match the clock names. */ #define SUN8I_H3_PLL_AUDIO_REG 0x008 -static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", - "osc24M", 0x008, - 8, 7, /* N */ - 0, 5, /* M */ - BIT(31), /* gate */ - BIT(28), /* lock */ - 0); +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 }, + { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 }, +}; + +static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", + "osc24M", 0x008, + 8, 7, /* N */ + 0, 5, /* M */ + pll_audio_sdm_table, BIT(24), + 0x284, BIT(31), + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video", "osc24M", 0x0010, @@ -67,7 +79,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video", 297000000, /* frac rate 1 */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", "osc24M", 0x0018, @@ -79,7 +91,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", 297000000, /* frac rate 1 */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr_clk, "pll-ddr", "osc24M", 0x020, @@ -88,7 +100,7 @@ static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr_clk, "pll-ddr", 0, 2, /* M */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph0_clk, "pll-periph0", "osc24M", 0x028, @@ -97,7 +109,7 @@ static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph0_clk, "pll-periph0", BIT(31), /* gate */ BIT(28), /* lock */ 2, /* post-div */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", "osc24M", 0x0038, @@ -109,7 +121,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", 297000000, /* frac rate 1 */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph1_clk, "pll-periph1", "osc24M", 0x044, @@ -118,7 +130,7 @@ static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph1_clk, "pll-periph1", BIT(31), /* gate */ BIT(28), /* lock */ 2, /* post-div */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", "osc24M", 0x0048, @@ -130,7 +142,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", 297000000, /* frac rate 1 */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static const char * const cpux_parents[] = { "osc32k", "osc24M", "pll-cpux" , "pll-cpux" }; @@ -484,7 +496,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL); static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu", - 0x1a0, 0, 3, BIT(31), 0); + 0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT); static struct ccu_common *sun8i_h3_ccu_clks[] = { &pll_cpux_clk.common, @@ -707,9 +719,9 @@ static struct ccu_common *sun50i_h5_ccu_clks[] = { &gpu_clk.common, }; -/* We hardcode the divider to 4 for now */ +/* We hardcode the divider to 1 for now */ static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", - "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", @@ -1129,10 +1141,10 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node, return; } - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN8I_H3_PLL_AUDIO_REG); val &= ~GENMASK(19, 16); - writel(val | (3 << 16), reg + SUN8I_H3_PLL_AUDIO_REG); + writel(val | (0 << 16), reg + SUN8I_H3_PLL_AUDIO_REG); sunxi_ccu_probe(node, reg, desc); |