Source
static unsigned long usb_pll_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
/*
* common clks module for all SiRF SoCs
*
* Copyright (c) 2011 - 2014 Cambridge Silicon Radio Limited, a CSR plc group
* company.
*
* Licensed under GPLv2 or later.
*/
static void __iomem *sirfsoc_clk_vbase;
static void __iomem *sirfsoc_rsc_vbase;
static struct clk_onecell_data clk_data;
/*
* SiRFprimaII clock controller
* - 2 oscillators: osc-26MHz, rtc-32.768KHz
* - 3 standard configurable plls: pll1, pll2 & pll3
* - 2 exclusive plls: usb phy pll and sata phy pll
* - 8 clock domains: cpu/cpudiv, mem/memdiv, sys/io, dsp, graphic, multimedia,
* display and sdphy.
* Each clock domain can select its own clock source from five clock sources,
* X_XIN, X_XINW, PLL1, PLL2 and PLL3. The domain clock is used as the source
* clock of the group clock.
* - dsp domain: gps, mf
* - io domain: dmac, nand, audio, uart, i2c, spi, usp, pwm, pulse
* - sys domain: security
*/
struct clk_pll {
struct clk_hw hw;
unsigned short regofs; /* register offset */
};
struct clk_dmn {
struct clk_hw hw;
signed char enable_bit; /* enable bit: 0 ~ 63 */
unsigned short regofs; /* register offset */
};
struct clk_std {
struct clk_hw hw;
signed char enable_bit; /* enable bit: 0 ~ 63 */
};
static int std_clk_is_enabled(struct clk_hw *hw);
static int std_clk_enable(struct clk_hw *hw);
static void std_clk_disable(struct clk_hw *hw);
static inline unsigned long clkc_readl(unsigned reg)
{
return readl(sirfsoc_clk_vbase + reg);
}
static inline void clkc_writel(u32 val, unsigned reg)
{
writel(val, sirfsoc_clk_vbase + reg);
}
/*
* std pll
*/
static unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long fin = parent_rate;
struct clk_pll *clk = to_pllclk(hw);
u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 -
SIRFSOC_CLKC_PLL1_CFG0;
if (clkc_readl(regcfg2) & BIT(2)) {
/* pll bypass mode */
return fin;
} else {
/* fout = fin * nf / nr / od */
u32 cfg0 = clkc_readl(clk->regofs);
u32 nf = (cfg0 & (BIT(13) - 1)) + 1;
u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1;
u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1;
WARN_ON(fin % MHZ);
return fin / MHZ * nf / nr / od * MHZ;