static void clk_pll_disable(struct clk *clk) { struct clk_pll *pll = to_clk_pll(clk); unsigned int mask = pll->layout->pllr_mask; regmap_write_bits(pll->regmap, PLL_REG(pll->id), mask, ~mask); }
static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_pll *pll = to_clk_pll(hw); u32 l, m, n, config; unsigned long rate; u64 tmp; regmap_read(pll->clkr.regmap, pll->l_reg, &l); regmap_read(pll->clkr.regmap, pll->m_reg, &m); regmap_read(pll->clkr.regmap, pll->n_reg, &n); l &= 0x3ff; m &= 0x7ffff; n &= 0x7ffff; rate = parent_rate * l; if (n) { tmp = parent_rate; tmp *= m; do_div(tmp, n); rate += tmp; } if (pll->post_div_width) { regmap_read(pll->clkr.regmap, pll->config_reg, &config); config >>= pll->post_div_shift; config &= BIT(pll->post_div_width) - 1; rate /= config + 1; }
static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { struct clk_pll *pll = to_clk_pll(hw); u32 filter, mul, div1, div2; long round_rate; switch (pll->type) { case PLL_TYPE_VT8500: vt8500_find_pll_bits(rate, *prate, &mul, &div1); round_rate = VT8500_BITS_TO_FREQ(*prate, mul, div1); break; case PLL_TYPE_WM8650: wm8650_find_pll_bits(rate, *prate, &mul, &div1, &div2); round_rate = WM8650_BITS_TO_FREQ(*prate, mul, div1, div2); break; case PLL_TYPE_WM8750: wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2); round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2); break; case PLL_TYPE_WM8850: wm8850_find_pll_bits(rate, *prate, &mul, &div1, &div2); round_rate = WM8850_BITS_TO_FREQ(*prate, mul, div1, div2); break; default: round_rate = 0; } return round_rate; }
static unsigned long vtwm_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_pll *pll = to_clk_pll(hw); u32 pll_val = readl(pll->reg); unsigned long pll_freq; switch (pll->type) { case PLL_TYPE_VT8500: pll_freq = parent_rate * VT8500_PLL_MUL(pll_val); pll_freq /= VT8500_PLL_DIV(pll_val); break; case PLL_TYPE_WM8650: pll_freq = parent_rate * WM8650_PLL_MUL(pll_val); pll_freq /= WM8650_PLL_DIV(pll_val); break; case PLL_TYPE_WM8750: pll_freq = parent_rate * WM8750_PLL_MUL(pll_val); pll_freq /= WM8750_PLL_DIV(pll_val); break; case PLL_TYPE_WM8850: pll_freq = parent_rate * WM8850_PLL_MUL(pll_val); pll_freq /= WM8850_PLL_DIV(pll_val); break; default: pll_freq = 0; } return pll_freq; }
static long clk_pll_round_rate(struct clk *clk, unsigned long rate, unsigned long *parent_rate) { struct clk_pll *pll = to_clk_pll(clk); return clk_pll_get_best_div_mul(pll, rate, *parent_rate, NULL, NULL, NULL); }
static void clk_pll_disable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); unsigned long flags = 0; if (pll->lock) spin_lock_irqsave(pll->lock, flags); _clk_pll_disable(hw); if (pll->lock) spin_unlock_irqrestore(pll->lock, flags); }
static void clk_pll_disable(struct clk_hw *hw) { struct clk_pll *pll = to_clk_pll(hw); u32 mask; u32 val; regmap_read(pll->clkr.regmap, pll->mode_reg, &val); /* Skip if in FSM mode */ if (val & PLL_VOTE_FSM_ENA) return; mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL; regmap_update_bits(pll->clkr.regmap, pll->mode_reg, mask, 0); }
static int clk_pll_is_enabled(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); u32 val; if (pll->params->flags & TEGRA_PLLM) { val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE); if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE) return val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE ? 1 : 0; } val = pll_readl_base(pll); return val & PLL_BASE_ENABLE ? 1 : 0; }
static int _p_div_to_hw(struct clk_hw *hw, u8 p_div) { struct tegra_clk_pll *pll = to_clk_pll(hw); struct pdiv_map *p_tohw = pll->params->pdiv_tohw; if (p_tohw) { while (p_tohw->pdiv) { if (p_div <= p_tohw->pdiv) return p_tohw->hw_val; p_tohw++; } return -EINVAL; } return -EINVAL; }
static void _clk_pll_disable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); u32 val; val = pll_readl_base(pll); if (pll->params->flags & TEGRA_PLL_BYPASS) val &= ~PLL_BASE_BYPASS; val &= ~PLL_BASE_ENABLE; pll_writel_base(val, pll); if (pll->params->flags & TEGRA_PLLM) { val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE); val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE; writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE); } }
static unsigned long clk_pll_recalc_rate(struct clk *clk, unsigned long parent_rate) { struct clk_pll *pll = to_clk_pll(clk); unsigned int pllr; u16 mul; u8 div; regmap_read(pll->regmap, PLL_REG(pll->id), &pllr); div = PLL_DIV(pllr); mul = PLL_MUL(pllr, pll->layout); if (!div || !mul) return 0; return (parent_rate / div) * (mul + 1); }
static int clk_pll_enable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); unsigned long flags = 0; int ret; if (pll->lock) spin_lock_irqsave(pll->lock, flags); _clk_pll_enable(hw); ret = clk_pll_wait_for_lock(pll); if (pll->lock) spin_unlock_irqrestore(pll->lock, flags); return ret; }
static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_pll *pll = to_clk_pll(hw); u32 filter, mul, div1, div2; u32 pll_val; unsigned long flags = 0; /* sanity check */ switch (pll->type) { case PLL_TYPE_VT8500: vt8500_find_pll_bits(rate, parent_rate, &mul, &div1); pll_val = VT8500_BITS_TO_VAL(mul, div1); break; case PLL_TYPE_WM8650: wm8650_find_pll_bits(rate, parent_rate, &mul, &div1, &div2); pll_val = WM8650_BITS_TO_VAL(mul, div1, div2); break; case PLL_TYPE_WM8750: wm8750_find_pll_bits(rate, parent_rate, &filter, &mul, &div1, &div2); pll_val = WM8750_BITS_TO_VAL(filter, mul, div1, div2); break; case PLL_TYPE_WM8850: wm8850_find_pll_bits(rate, parent_rate, &mul, &div1, &div2); pll_val = WM8850_BITS_TO_VAL(mul, div1, div2); break; default: pr_err("%s: invalid pll type\n", __func__); return 0; } spin_lock_irqsave(pll->lock, flags); vt8500_pmc_wait_busy(); writel(pll_val, pll->reg); vt8500_pmc_wait_busy(); spin_unlock_irqrestore(pll->lock, flags); return 0; }
static int clk_pll_enable(struct clk *clk) { struct clk_pll *pll = to_clk_pll(clk); struct regmap *regmap = pll->regmap; const struct clk_pll_layout *layout = pll->layout; const struct clk_pll_characteristics *characteristics = pll->characteristics; u8 id = pll->id; u32 mask = PLL_STATUS_MASK(id); int offset = PLL_REG(id); u8 out = 0; unsigned int pllr; unsigned int status; u8 div; u16 mul; regmap_read(regmap, offset, &pllr); div = PLL_DIV(pllr); mul = PLL_MUL(pllr, layout); regmap_read(regmap, AT91_PMC_SR, &status); if ((status & mask) && (div == pll->div && mul == pll->mul)) return 0; if (characteristics->out) out = characteristics->out[pll->range]; if (characteristics->icpll) regmap_write_bits(regmap, AT91_PMC_PLLICPR, PLL_ICPR_MASK(id), characteristics->icpll[pll->range] << PLL_ICPR_SHIFT(id)); regmap_write_bits(regmap, offset, layout->pllr_mask, pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) | (out << PLL_OUT_SHIFT) | ((pll->mul & layout->mul_mask) << layout->mul_shift)); while (!clk_pll_ready(regmap, pll->id)) barrier(); return 0; }
static int clk_pll_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { struct clk_pll *pll = to_clk_pll(clk); long ret; u32 div; u32 mul; u32 index; ret = clk_pll_get_best_div_mul(pll, rate, parent_rate, &div, &mul, &index); if (ret < 0) return ret; pll->range = index; pll->div = div; pll->mul = mul; return 0; }
static int clk_pll_enable(struct clk_hw *hw) { struct clk_pll *pll = to_clk_pll(hw); int ret; u32 mask, val; mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL; ret = regmap_read(pll->clkr.regmap, pll->mode_reg, &val); if (ret) return ret; /* Skip if already enabled or in FSM mode */ if ((val & mask) == mask || val & PLL_VOTE_FSM_ENA) return 0; /* Disable PLL bypass mode. */ ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_BYPASSNL, PLL_BYPASSNL); if (ret) return ret; /* * H/W requires a 5us delay between disabling the bypass and * de-asserting the reset. Delay 10us just to be safe. */ udelay(10); /* De-assert active-low PLL reset. */ ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_RESET_N, PLL_RESET_N); if (ret) return ret; /* Wait until PLL is locked. */ udelay(50); /* Enable PLL output. */ return regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_OUTCTRL, PLL_OUTCTRL); }
static int _get_table_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, unsigned long rate, unsigned long parent_rate) { struct tegra_clk_pll *pll = to_clk_pll(hw); struct tegra_clk_pll_freq_table *sel; for (sel = pll->params->freq_table; sel->input_rate != 0; sel++) if (sel->input_rate == parent_rate && sel->output_rate == rate) break; if (sel->input_rate == 0) return -EINVAL; cfg->input_rate = sel->input_rate; cfg->output_rate = sel->output_rate; cfg->m = sel->m; cfg->n = sel->n; cfg->p = sel->p; cfg->cpcon = sel->cpcon; return 0; }
static int clk_pll_is_enabled(struct clk *clk) { struct clk_pll *pll = to_clk_pll(clk); return clk_pll_ready(pll->regmap, pll->id); }
static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, unsigned long rate, unsigned long parent_rate) { struct tegra_clk_pll *pll = to_clk_pll(hw); unsigned long cfreq; u32 p_div = 0; int ret; switch (parent_rate) { case 12000000: case 26000000: cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2000000; break; case 13000000: cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2600000; break; case 16800000: case 19200000: cfreq = (rate <= 1200000 * 1000) ? 1200000 : 2400000; break; case 9600000: case 28800000: /* * PLL_P_OUT1 rate is not listed in PLLA table */ cfreq = parent_rate/(parent_rate/1000000); break; default: pr_err("%s Unexpected reference rate %lu\n", __func__, parent_rate); BUG(); } /* Raise VCO to guarantee 0.5% accuracy */ for (cfg->output_rate = rate; cfg->output_rate < 200 * cfreq; cfg->output_rate <<= 1) p_div++; cfg->m = parent_rate / cfreq; cfg->n = cfg->output_rate / cfreq; cfg->cpcon = OUT_OF_TABLE_CPCON; if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) || (1 << p_div) > divp_max(pll) || cfg->output_rate > pll->params->vco_max) { return -EINVAL; } cfg->output_rate >>= p_div; if (pll->params->pdiv_tohw) { ret = _p_div_to_hw(hw, 1 << p_div); if (ret < 0) return ret; else cfg->p = ret; } else cfg->p = p_div; return 0; }