162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#include <linux/clk.h> 462306a36Sopenharmony_ci#include <linux/clk-provider.h> 562306a36Sopenharmony_ci#include <linux/delay.h> 662306a36Sopenharmony_ci#include <linux/err.h> 762306a36Sopenharmony_ci#include <linux/io.h> 862306a36Sopenharmony_ci#include <linux/math64.h> 962306a36Sopenharmony_ci#include <linux/of.h> 1062306a36Sopenharmony_ci#include <linux/of_address.h> 1162306a36Sopenharmony_ci#include <linux/clk/ti.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include "clock.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* FAPLL Control Register PLL_CTRL */ 1662306a36Sopenharmony_ci#define FAPLL_MAIN_MULT_N_SHIFT 16 1762306a36Sopenharmony_ci#define FAPLL_MAIN_DIV_P_SHIFT 8 1862306a36Sopenharmony_ci#define FAPLL_MAIN_LOCK BIT(7) 1962306a36Sopenharmony_ci#define FAPLL_MAIN_PLLEN BIT(3) 2062306a36Sopenharmony_ci#define FAPLL_MAIN_BP BIT(2) 2162306a36Sopenharmony_ci#define FAPLL_MAIN_LOC_CTL BIT(0) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define FAPLL_MAIN_MAX_MULT_N 0xffff 2462306a36Sopenharmony_ci#define FAPLL_MAIN_MAX_DIV_P 0xff 2562306a36Sopenharmony_ci#define FAPLL_MAIN_CLEAR_MASK \ 2662306a36Sopenharmony_ci ((FAPLL_MAIN_MAX_MULT_N << FAPLL_MAIN_MULT_N_SHIFT) | \ 2762306a36Sopenharmony_ci (FAPLL_MAIN_DIV_P_SHIFT << FAPLL_MAIN_DIV_P_SHIFT) | \ 2862306a36Sopenharmony_ci FAPLL_MAIN_LOC_CTL) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* FAPLL powerdown register PWD */ 3162306a36Sopenharmony_ci#define FAPLL_PWD_OFFSET 4 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define MAX_FAPLL_OUTPUTS 7 3462306a36Sopenharmony_ci#define FAPLL_MAX_RETRIES 1000 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define to_fapll(_hw) container_of(_hw, struct fapll_data, hw) 3762306a36Sopenharmony_ci#define to_synth(_hw) container_of(_hw, struct fapll_synth, hw) 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* The bypass bit is inverted on the ddr_pll.. */ 4062306a36Sopenharmony_ci#define fapll_is_ddr_pll(va) (((u32)(va) & 0xffff) == 0x0440) 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* 4362306a36Sopenharmony_ci * The audio_pll_clk1 input is hard wired to the 27MHz bypass clock, 4462306a36Sopenharmony_ci * and the audio_pll_clk1 synthesizer is hardwared to 32KiHz output. 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_ci#define is_ddr_pll_clk1(va) (((u32)(va) & 0xffff) == 0x044c) 4762306a36Sopenharmony_ci#define is_audio_pll_clk1(va) (((u32)(va) & 0xffff) == 0x04a8) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* Synthesizer divider register */ 5062306a36Sopenharmony_ci#define SYNTH_LDMDIV1 BIT(8) 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* Synthesizer frequency register */ 5362306a36Sopenharmony_ci#define SYNTH_LDFREQ BIT(31) 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define SYNTH_PHASE_K 8 5662306a36Sopenharmony_ci#define SYNTH_MAX_INT_DIV 0xf 5762306a36Sopenharmony_ci#define SYNTH_MAX_DIV_M 0xff 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistruct fapll_data { 6062306a36Sopenharmony_ci struct clk_hw hw; 6162306a36Sopenharmony_ci void __iomem *base; 6262306a36Sopenharmony_ci const char *name; 6362306a36Sopenharmony_ci struct clk *clk_ref; 6462306a36Sopenharmony_ci struct clk *clk_bypass; 6562306a36Sopenharmony_ci struct clk_onecell_data outputs; 6662306a36Sopenharmony_ci bool bypass_bit_inverted; 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistruct fapll_synth { 7062306a36Sopenharmony_ci struct clk_hw hw; 7162306a36Sopenharmony_ci struct fapll_data *fd; 7262306a36Sopenharmony_ci int index; 7362306a36Sopenharmony_ci void __iomem *freq; 7462306a36Sopenharmony_ci void __iomem *div; 7562306a36Sopenharmony_ci const char *name; 7662306a36Sopenharmony_ci struct clk *clk_pll; 7762306a36Sopenharmony_ci}; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic bool ti_fapll_clock_is_bypass(struct fapll_data *fd) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci u32 v = readl_relaxed(fd->base); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci if (fd->bypass_bit_inverted) 8462306a36Sopenharmony_ci return !(v & FAPLL_MAIN_BP); 8562306a36Sopenharmony_ci else 8662306a36Sopenharmony_ci return !!(v & FAPLL_MAIN_BP); 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic void ti_fapll_set_bypass(struct fapll_data *fd) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci u32 v = readl_relaxed(fd->base); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (fd->bypass_bit_inverted) 9462306a36Sopenharmony_ci v &= ~FAPLL_MAIN_BP; 9562306a36Sopenharmony_ci else 9662306a36Sopenharmony_ci v |= FAPLL_MAIN_BP; 9762306a36Sopenharmony_ci writel_relaxed(v, fd->base); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic void ti_fapll_clear_bypass(struct fapll_data *fd) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci u32 v = readl_relaxed(fd->base); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if (fd->bypass_bit_inverted) 10562306a36Sopenharmony_ci v |= FAPLL_MAIN_BP; 10662306a36Sopenharmony_ci else 10762306a36Sopenharmony_ci v &= ~FAPLL_MAIN_BP; 10862306a36Sopenharmony_ci writel_relaxed(v, fd->base); 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic int ti_fapll_wait_lock(struct fapll_data *fd) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci int retries = FAPLL_MAX_RETRIES; 11462306a36Sopenharmony_ci u32 v; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci while ((v = readl_relaxed(fd->base))) { 11762306a36Sopenharmony_ci if (v & FAPLL_MAIN_LOCK) 11862306a36Sopenharmony_ci return 0; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci if (retries-- <= 0) 12162306a36Sopenharmony_ci break; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci udelay(1); 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci pr_err("%s failed to lock\n", fd->name); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci return -ETIMEDOUT; 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic int ti_fapll_enable(struct clk_hw *hw) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci struct fapll_data *fd = to_fapll(hw); 13462306a36Sopenharmony_ci u32 v = readl_relaxed(fd->base); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci v |= FAPLL_MAIN_PLLEN; 13762306a36Sopenharmony_ci writel_relaxed(v, fd->base); 13862306a36Sopenharmony_ci ti_fapll_wait_lock(fd); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci return 0; 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic void ti_fapll_disable(struct clk_hw *hw) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci struct fapll_data *fd = to_fapll(hw); 14662306a36Sopenharmony_ci u32 v = readl_relaxed(fd->base); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci v &= ~FAPLL_MAIN_PLLEN; 14962306a36Sopenharmony_ci writel_relaxed(v, fd->base); 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic int ti_fapll_is_enabled(struct clk_hw *hw) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci struct fapll_data *fd = to_fapll(hw); 15562306a36Sopenharmony_ci u32 v = readl_relaxed(fd->base); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci return v & FAPLL_MAIN_PLLEN; 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic unsigned long ti_fapll_recalc_rate(struct clk_hw *hw, 16162306a36Sopenharmony_ci unsigned long parent_rate) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci struct fapll_data *fd = to_fapll(hw); 16462306a36Sopenharmony_ci u32 fapll_n, fapll_p, v; 16562306a36Sopenharmony_ci u64 rate; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (ti_fapll_clock_is_bypass(fd)) 16862306a36Sopenharmony_ci return parent_rate; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci rate = parent_rate; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci /* PLL pre-divider is P and multiplier is N */ 17362306a36Sopenharmony_ci v = readl_relaxed(fd->base); 17462306a36Sopenharmony_ci fapll_p = (v >> 8) & 0xff; 17562306a36Sopenharmony_ci if (fapll_p) 17662306a36Sopenharmony_ci do_div(rate, fapll_p); 17762306a36Sopenharmony_ci fapll_n = v >> 16; 17862306a36Sopenharmony_ci if (fapll_n) 17962306a36Sopenharmony_ci rate *= fapll_n; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci return rate; 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic u8 ti_fapll_get_parent(struct clk_hw *hw) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci struct fapll_data *fd = to_fapll(hw); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci if (ti_fapll_clock_is_bypass(fd)) 18962306a36Sopenharmony_ci return 1; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return 0; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistatic int ti_fapll_set_div_mult(unsigned long rate, 19562306a36Sopenharmony_ci unsigned long parent_rate, 19662306a36Sopenharmony_ci u32 *pre_div_p, u32 *mult_n) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci /* 19962306a36Sopenharmony_ci * So far no luck getting decent clock with PLL divider, 20062306a36Sopenharmony_ci * PLL does not seem to lock and the signal does not look 20162306a36Sopenharmony_ci * right. It seems the divider can only be used together 20262306a36Sopenharmony_ci * with the multiplier? 20362306a36Sopenharmony_ci */ 20462306a36Sopenharmony_ci if (rate < parent_rate) { 20562306a36Sopenharmony_ci pr_warn("FAPLL main divider rates unsupported\n"); 20662306a36Sopenharmony_ci return -EINVAL; 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci *mult_n = rate / parent_rate; 21062306a36Sopenharmony_ci if (*mult_n > FAPLL_MAIN_MAX_MULT_N) 21162306a36Sopenharmony_ci return -EINVAL; 21262306a36Sopenharmony_ci *pre_div_p = 1; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci return 0; 21562306a36Sopenharmony_ci} 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic long ti_fapll_round_rate(struct clk_hw *hw, unsigned long rate, 21862306a36Sopenharmony_ci unsigned long *parent_rate) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci u32 pre_div_p, mult_n; 22162306a36Sopenharmony_ci int error; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci if (!rate) 22462306a36Sopenharmony_ci return -EINVAL; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci error = ti_fapll_set_div_mult(rate, *parent_rate, 22762306a36Sopenharmony_ci &pre_div_p, &mult_n); 22862306a36Sopenharmony_ci if (error) 22962306a36Sopenharmony_ci return error; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci rate = *parent_rate / pre_div_p; 23262306a36Sopenharmony_ci rate *= mult_n; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci return rate; 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic int ti_fapll_set_rate(struct clk_hw *hw, unsigned long rate, 23862306a36Sopenharmony_ci unsigned long parent_rate) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci struct fapll_data *fd = to_fapll(hw); 24162306a36Sopenharmony_ci u32 pre_div_p, mult_n, v; 24262306a36Sopenharmony_ci int error; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (!rate) 24562306a36Sopenharmony_ci return -EINVAL; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci error = ti_fapll_set_div_mult(rate, parent_rate, 24862306a36Sopenharmony_ci &pre_div_p, &mult_n); 24962306a36Sopenharmony_ci if (error) 25062306a36Sopenharmony_ci return error; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci ti_fapll_set_bypass(fd); 25362306a36Sopenharmony_ci v = readl_relaxed(fd->base); 25462306a36Sopenharmony_ci v &= ~FAPLL_MAIN_CLEAR_MASK; 25562306a36Sopenharmony_ci v |= pre_div_p << FAPLL_MAIN_DIV_P_SHIFT; 25662306a36Sopenharmony_ci v |= mult_n << FAPLL_MAIN_MULT_N_SHIFT; 25762306a36Sopenharmony_ci writel_relaxed(v, fd->base); 25862306a36Sopenharmony_ci if (ti_fapll_is_enabled(hw)) 25962306a36Sopenharmony_ci ti_fapll_wait_lock(fd); 26062306a36Sopenharmony_ci ti_fapll_clear_bypass(fd); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci return 0; 26362306a36Sopenharmony_ci} 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_cistatic const struct clk_ops ti_fapll_ops = { 26662306a36Sopenharmony_ci .enable = ti_fapll_enable, 26762306a36Sopenharmony_ci .disable = ti_fapll_disable, 26862306a36Sopenharmony_ci .is_enabled = ti_fapll_is_enabled, 26962306a36Sopenharmony_ci .recalc_rate = ti_fapll_recalc_rate, 27062306a36Sopenharmony_ci .get_parent = ti_fapll_get_parent, 27162306a36Sopenharmony_ci .round_rate = ti_fapll_round_rate, 27262306a36Sopenharmony_ci .set_rate = ti_fapll_set_rate, 27362306a36Sopenharmony_ci}; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_cistatic int ti_fapll_synth_enable(struct clk_hw *hw) 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci struct fapll_synth *synth = to_synth(hw); 27862306a36Sopenharmony_ci u32 v = readl_relaxed(synth->fd->base + FAPLL_PWD_OFFSET); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci v &= ~(1 << synth->index); 28162306a36Sopenharmony_ci writel_relaxed(v, synth->fd->base + FAPLL_PWD_OFFSET); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci return 0; 28462306a36Sopenharmony_ci} 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_cistatic void ti_fapll_synth_disable(struct clk_hw *hw) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci struct fapll_synth *synth = to_synth(hw); 28962306a36Sopenharmony_ci u32 v = readl_relaxed(synth->fd->base + FAPLL_PWD_OFFSET); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci v |= 1 << synth->index; 29262306a36Sopenharmony_ci writel_relaxed(v, synth->fd->base + FAPLL_PWD_OFFSET); 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic int ti_fapll_synth_is_enabled(struct clk_hw *hw) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci struct fapll_synth *synth = to_synth(hw); 29862306a36Sopenharmony_ci u32 v = readl_relaxed(synth->fd->base + FAPLL_PWD_OFFSET); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci return !(v & (1 << synth->index)); 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci/* 30462306a36Sopenharmony_ci * See dm816x TRM chapter 1.10.3 Flying Adder PLL fore more info 30562306a36Sopenharmony_ci */ 30662306a36Sopenharmony_cistatic unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw, 30762306a36Sopenharmony_ci unsigned long parent_rate) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci struct fapll_synth *synth = to_synth(hw); 31062306a36Sopenharmony_ci u32 synth_div_m; 31162306a36Sopenharmony_ci u64 rate; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci /* The audio_pll_clk1 is hardwired to produce 32.768KiHz clock */ 31462306a36Sopenharmony_ci if (!synth->div) 31562306a36Sopenharmony_ci return 32768; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci /* 31862306a36Sopenharmony_ci * PLL in bypass sets the synths in bypass mode too. The PLL rate 31962306a36Sopenharmony_ci * can be also be set to 27MHz, so we can't use parent_rate to 32062306a36Sopenharmony_ci * check for bypass mode. 32162306a36Sopenharmony_ci */ 32262306a36Sopenharmony_ci if (ti_fapll_clock_is_bypass(synth->fd)) 32362306a36Sopenharmony_ci return parent_rate; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci rate = parent_rate; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* 32862306a36Sopenharmony_ci * Synth frequency integer and fractional divider. 32962306a36Sopenharmony_ci * Note that the phase output K is 8, so the result needs 33062306a36Sopenharmony_ci * to be multiplied by SYNTH_PHASE_K. 33162306a36Sopenharmony_ci */ 33262306a36Sopenharmony_ci if (synth->freq) { 33362306a36Sopenharmony_ci u32 v, synth_int_div, synth_frac_div, synth_div_freq; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci v = readl_relaxed(synth->freq); 33662306a36Sopenharmony_ci synth_int_div = (v >> 24) & 0xf; 33762306a36Sopenharmony_ci synth_frac_div = v & 0xffffff; 33862306a36Sopenharmony_ci synth_div_freq = (synth_int_div * 10000000) + synth_frac_div; 33962306a36Sopenharmony_ci rate *= 10000000; 34062306a36Sopenharmony_ci do_div(rate, synth_div_freq); 34162306a36Sopenharmony_ci rate *= SYNTH_PHASE_K; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* Synth post-divider M */ 34562306a36Sopenharmony_ci synth_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci return DIV_ROUND_UP_ULL(rate, synth_div_m); 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic unsigned long ti_fapll_synth_get_frac_rate(struct clk_hw *hw, 35162306a36Sopenharmony_ci unsigned long parent_rate) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci struct fapll_synth *synth = to_synth(hw); 35462306a36Sopenharmony_ci unsigned long current_rate, frac_rate; 35562306a36Sopenharmony_ci u32 post_div_m; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci current_rate = ti_fapll_synth_recalc_rate(hw, parent_rate); 35862306a36Sopenharmony_ci post_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M; 35962306a36Sopenharmony_ci frac_rate = current_rate * post_div_m; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci return frac_rate; 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cistatic u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth, 36562306a36Sopenharmony_ci unsigned long rate, 36662306a36Sopenharmony_ci unsigned long parent_rate) 36762306a36Sopenharmony_ci{ 36862306a36Sopenharmony_ci u32 post_div_m, synth_int_div = 0, synth_frac_div = 0, v; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci post_div_m = DIV_ROUND_UP_ULL((u64)parent_rate * SYNTH_PHASE_K, rate); 37162306a36Sopenharmony_ci post_div_m = post_div_m / SYNTH_MAX_INT_DIV; 37262306a36Sopenharmony_ci if (post_div_m > SYNTH_MAX_DIV_M) 37362306a36Sopenharmony_ci return -EINVAL; 37462306a36Sopenharmony_ci if (!post_div_m) 37562306a36Sopenharmony_ci post_div_m = 1; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci for (; post_div_m < SYNTH_MAX_DIV_M; post_div_m++) { 37862306a36Sopenharmony_ci synth_int_div = DIV_ROUND_UP_ULL((u64)parent_rate * 37962306a36Sopenharmony_ci SYNTH_PHASE_K * 38062306a36Sopenharmony_ci 10000000, 38162306a36Sopenharmony_ci rate * post_div_m); 38262306a36Sopenharmony_ci synth_frac_div = synth_int_div % 10000000; 38362306a36Sopenharmony_ci synth_int_div /= 10000000; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci if (synth_int_div <= SYNTH_MAX_INT_DIV) 38662306a36Sopenharmony_ci break; 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci if (synth_int_div > SYNTH_MAX_INT_DIV) 39062306a36Sopenharmony_ci return -EINVAL; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci v = readl_relaxed(synth->freq); 39362306a36Sopenharmony_ci v &= ~0x1fffffff; 39462306a36Sopenharmony_ci v |= (synth_int_div & SYNTH_MAX_INT_DIV) << 24; 39562306a36Sopenharmony_ci v |= (synth_frac_div & 0xffffff); 39662306a36Sopenharmony_ci v |= SYNTH_LDFREQ; 39762306a36Sopenharmony_ci writel_relaxed(v, synth->freq); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci return post_div_m; 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cistatic long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate, 40362306a36Sopenharmony_ci unsigned long *parent_rate) 40462306a36Sopenharmony_ci{ 40562306a36Sopenharmony_ci struct fapll_synth *synth = to_synth(hw); 40662306a36Sopenharmony_ci struct fapll_data *fd = synth->fd; 40762306a36Sopenharmony_ci unsigned long r; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate) 41062306a36Sopenharmony_ci return -EINVAL; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci /* Only post divider m available with no fractional divider? */ 41362306a36Sopenharmony_ci if (!synth->freq) { 41462306a36Sopenharmony_ci unsigned long frac_rate; 41562306a36Sopenharmony_ci u32 synth_post_div_m; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci frac_rate = ti_fapll_synth_get_frac_rate(hw, *parent_rate); 41862306a36Sopenharmony_ci synth_post_div_m = DIV_ROUND_UP(frac_rate, rate); 41962306a36Sopenharmony_ci r = DIV_ROUND_UP(frac_rate, synth_post_div_m); 42062306a36Sopenharmony_ci goto out; 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci r = *parent_rate * SYNTH_PHASE_K; 42462306a36Sopenharmony_ci if (rate > r) 42562306a36Sopenharmony_ci goto out; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci r = DIV_ROUND_UP_ULL(r, SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M); 42862306a36Sopenharmony_ci if (rate < r) 42962306a36Sopenharmony_ci goto out; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci r = rate; 43262306a36Sopenharmony_ciout: 43362306a36Sopenharmony_ci return r; 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cistatic int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate, 43762306a36Sopenharmony_ci unsigned long parent_rate) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci struct fapll_synth *synth = to_synth(hw); 44062306a36Sopenharmony_ci struct fapll_data *fd = synth->fd; 44162306a36Sopenharmony_ci unsigned long frac_rate, post_rate = 0; 44262306a36Sopenharmony_ci u32 post_div_m = 0, v; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate) 44562306a36Sopenharmony_ci return -EINVAL; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci /* Produce the rate with just post divider M? */ 44862306a36Sopenharmony_ci frac_rate = ti_fapll_synth_get_frac_rate(hw, parent_rate); 44962306a36Sopenharmony_ci if (frac_rate < rate) { 45062306a36Sopenharmony_ci if (!synth->freq) 45162306a36Sopenharmony_ci return -EINVAL; 45262306a36Sopenharmony_ci } else { 45362306a36Sopenharmony_ci post_div_m = DIV_ROUND_UP(frac_rate, rate); 45462306a36Sopenharmony_ci if (post_div_m && (post_div_m <= SYNTH_MAX_DIV_M)) 45562306a36Sopenharmony_ci post_rate = DIV_ROUND_UP(frac_rate, post_div_m); 45662306a36Sopenharmony_ci if (!synth->freq && !post_rate) 45762306a36Sopenharmony_ci return -EINVAL; 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci /* Need to recalculate the fractional divider? */ 46162306a36Sopenharmony_ci if ((post_rate != rate) && synth->freq) 46262306a36Sopenharmony_ci post_div_m = ti_fapll_synth_set_frac_rate(synth, 46362306a36Sopenharmony_ci rate, 46462306a36Sopenharmony_ci parent_rate); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci v = readl_relaxed(synth->div); 46762306a36Sopenharmony_ci v &= ~SYNTH_MAX_DIV_M; 46862306a36Sopenharmony_ci v |= post_div_m; 46962306a36Sopenharmony_ci v |= SYNTH_LDMDIV1; 47062306a36Sopenharmony_ci writel_relaxed(v, synth->div); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci return 0; 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_cistatic const struct clk_ops ti_fapll_synt_ops = { 47662306a36Sopenharmony_ci .enable = ti_fapll_synth_enable, 47762306a36Sopenharmony_ci .disable = ti_fapll_synth_disable, 47862306a36Sopenharmony_ci .is_enabled = ti_fapll_synth_is_enabled, 47962306a36Sopenharmony_ci .recalc_rate = ti_fapll_synth_recalc_rate, 48062306a36Sopenharmony_ci .round_rate = ti_fapll_synth_round_rate, 48162306a36Sopenharmony_ci .set_rate = ti_fapll_synth_set_rate, 48262306a36Sopenharmony_ci}; 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_cistatic struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd, 48562306a36Sopenharmony_ci void __iomem *freq, 48662306a36Sopenharmony_ci void __iomem *div, 48762306a36Sopenharmony_ci int index, 48862306a36Sopenharmony_ci const char *name, 48962306a36Sopenharmony_ci const char *parent, 49062306a36Sopenharmony_ci struct clk *pll_clk) 49162306a36Sopenharmony_ci{ 49262306a36Sopenharmony_ci struct clk_init_data *init; 49362306a36Sopenharmony_ci struct fapll_synth *synth; 49462306a36Sopenharmony_ci struct clk *clk = ERR_PTR(-ENOMEM); 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci init = kzalloc(sizeof(*init), GFP_KERNEL); 49762306a36Sopenharmony_ci if (!init) 49862306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci init->ops = &ti_fapll_synt_ops; 50162306a36Sopenharmony_ci init->name = name; 50262306a36Sopenharmony_ci init->parent_names = &parent; 50362306a36Sopenharmony_ci init->num_parents = 1; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci synth = kzalloc(sizeof(*synth), GFP_KERNEL); 50662306a36Sopenharmony_ci if (!synth) 50762306a36Sopenharmony_ci goto free; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci synth->fd = fd; 51062306a36Sopenharmony_ci synth->index = index; 51162306a36Sopenharmony_ci synth->freq = freq; 51262306a36Sopenharmony_ci synth->div = div; 51362306a36Sopenharmony_ci synth->name = name; 51462306a36Sopenharmony_ci synth->hw.init = init; 51562306a36Sopenharmony_ci synth->clk_pll = pll_clk; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci clk = clk_register(NULL, &synth->hw); 51862306a36Sopenharmony_ci if (IS_ERR(clk)) { 51962306a36Sopenharmony_ci pr_err("failed to register clock\n"); 52062306a36Sopenharmony_ci goto free; 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci return clk; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_cifree: 52662306a36Sopenharmony_ci kfree(synth); 52762306a36Sopenharmony_ci kfree(init); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci return clk; 53062306a36Sopenharmony_ci} 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_cistatic void __init ti_fapll_setup(struct device_node *node) 53362306a36Sopenharmony_ci{ 53462306a36Sopenharmony_ci struct fapll_data *fd; 53562306a36Sopenharmony_ci struct clk_init_data *init = NULL; 53662306a36Sopenharmony_ci const char *parent_name[2]; 53762306a36Sopenharmony_ci struct clk *pll_clk; 53862306a36Sopenharmony_ci const char *name; 53962306a36Sopenharmony_ci int i; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci fd = kzalloc(sizeof(*fd), GFP_KERNEL); 54262306a36Sopenharmony_ci if (!fd) 54362306a36Sopenharmony_ci return; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci fd->outputs.clks = kzalloc(sizeof(struct clk *) * 54662306a36Sopenharmony_ci MAX_FAPLL_OUTPUTS + 1, 54762306a36Sopenharmony_ci GFP_KERNEL); 54862306a36Sopenharmony_ci if (!fd->outputs.clks) 54962306a36Sopenharmony_ci goto free; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci init = kzalloc(sizeof(*init), GFP_KERNEL); 55262306a36Sopenharmony_ci if (!init) 55362306a36Sopenharmony_ci goto free; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci init->ops = &ti_fapll_ops; 55662306a36Sopenharmony_ci name = ti_dt_clk_name(node); 55762306a36Sopenharmony_ci init->name = name; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci init->num_parents = of_clk_get_parent_count(node); 56062306a36Sopenharmony_ci if (init->num_parents != 2) { 56162306a36Sopenharmony_ci pr_err("%pOFn must have two parents\n", node); 56262306a36Sopenharmony_ci goto free; 56362306a36Sopenharmony_ci } 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci of_clk_parent_fill(node, parent_name, 2); 56662306a36Sopenharmony_ci init->parent_names = parent_name; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci fd->clk_ref = of_clk_get(node, 0); 56962306a36Sopenharmony_ci if (IS_ERR(fd->clk_ref)) { 57062306a36Sopenharmony_ci pr_err("%pOFn could not get clk_ref\n", node); 57162306a36Sopenharmony_ci goto free; 57262306a36Sopenharmony_ci } 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci fd->clk_bypass = of_clk_get(node, 1); 57562306a36Sopenharmony_ci if (IS_ERR(fd->clk_bypass)) { 57662306a36Sopenharmony_ci pr_err("%pOFn could not get clk_bypass\n", node); 57762306a36Sopenharmony_ci goto free; 57862306a36Sopenharmony_ci } 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci fd->base = of_iomap(node, 0); 58162306a36Sopenharmony_ci if (!fd->base) { 58262306a36Sopenharmony_ci pr_err("%pOFn could not get IO base\n", node); 58362306a36Sopenharmony_ci goto free; 58462306a36Sopenharmony_ci } 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci if (fapll_is_ddr_pll(fd->base)) 58762306a36Sopenharmony_ci fd->bypass_bit_inverted = true; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci fd->name = name; 59062306a36Sopenharmony_ci fd->hw.init = init; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci /* Register the parent PLL */ 59362306a36Sopenharmony_ci pll_clk = clk_register(NULL, &fd->hw); 59462306a36Sopenharmony_ci if (IS_ERR(pll_clk)) 59562306a36Sopenharmony_ci goto unmap; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci fd->outputs.clks[0] = pll_clk; 59862306a36Sopenharmony_ci fd->outputs.clk_num++; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci /* 60162306a36Sopenharmony_ci * Set up the child synthesizers starting at index 1 as the 60262306a36Sopenharmony_ci * PLL output is at index 0. We need to check the clock-indices 60362306a36Sopenharmony_ci * for numbering in case there are holes in the synth mapping, 60462306a36Sopenharmony_ci * and then probe the synth register to see if it has a FREQ 60562306a36Sopenharmony_ci * register available. 60662306a36Sopenharmony_ci */ 60762306a36Sopenharmony_ci for (i = 0; i < MAX_FAPLL_OUTPUTS; i++) { 60862306a36Sopenharmony_ci const char *output_name; 60962306a36Sopenharmony_ci void __iomem *freq, *div; 61062306a36Sopenharmony_ci struct clk *synth_clk; 61162306a36Sopenharmony_ci int output_instance; 61262306a36Sopenharmony_ci u32 v; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci if (of_property_read_string_index(node, "clock-output-names", 61562306a36Sopenharmony_ci i, &output_name)) 61662306a36Sopenharmony_ci continue; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci if (of_property_read_u32_index(node, "clock-indices", i, 61962306a36Sopenharmony_ci &output_instance)) 62062306a36Sopenharmony_ci output_instance = i; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci freq = fd->base + (output_instance * 8); 62362306a36Sopenharmony_ci div = freq + 4; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci /* Check for hardwired audio_pll_clk1 */ 62662306a36Sopenharmony_ci if (is_audio_pll_clk1(freq)) { 62762306a36Sopenharmony_ci freq = NULL; 62862306a36Sopenharmony_ci div = NULL; 62962306a36Sopenharmony_ci } else { 63062306a36Sopenharmony_ci /* Does the synthesizer have a FREQ register? */ 63162306a36Sopenharmony_ci v = readl_relaxed(freq); 63262306a36Sopenharmony_ci if (!v) 63362306a36Sopenharmony_ci freq = NULL; 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci synth_clk = ti_fapll_synth_setup(fd, freq, div, output_instance, 63662306a36Sopenharmony_ci output_name, name, pll_clk); 63762306a36Sopenharmony_ci if (IS_ERR(synth_clk)) 63862306a36Sopenharmony_ci continue; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci fd->outputs.clks[output_instance] = synth_clk; 64162306a36Sopenharmony_ci fd->outputs.clk_num++; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci clk_register_clkdev(synth_clk, output_name, NULL); 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci /* Register the child synthesizers as the FAPLL outputs */ 64762306a36Sopenharmony_ci of_clk_add_provider(node, of_clk_src_onecell_get, &fd->outputs); 64862306a36Sopenharmony_ci /* Add clock alias for the outputs */ 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci kfree(init); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci return; 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ciunmap: 65562306a36Sopenharmony_ci iounmap(fd->base); 65662306a36Sopenharmony_cifree: 65762306a36Sopenharmony_ci if (fd->clk_bypass) 65862306a36Sopenharmony_ci clk_put(fd->clk_bypass); 65962306a36Sopenharmony_ci if (fd->clk_ref) 66062306a36Sopenharmony_ci clk_put(fd->clk_ref); 66162306a36Sopenharmony_ci kfree(fd->outputs.clks); 66262306a36Sopenharmony_ci kfree(fd); 66362306a36Sopenharmony_ci kfree(init); 66462306a36Sopenharmony_ci} 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ciCLK_OF_DECLARE(ti_fapll_clock, "ti,dm816-fapll-clock", ti_fapll_setup); 667