diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 2d42eb6289267711c15f5e8275599e5c80995b76..315c4457c4325c9d1fcb07bc73c4e7e9fc57f4e7 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -38,6 +38,7 @@ struct rockchip_clk_pll { u8 flags; const struct rockchip_pll_rate_table *rate_table; unsigned int rate_count; + int sel; spinlock_t *lock; struct rockchip_clk_provider *ctx; @@ -61,6 +62,72 @@ static const struct rockchip_pll_rate_table *rockchip_get_pll_settings( return NULL; } +int rockchip_pll_clk_adaptive_scaling(struct clk *clk, int sel) +{ + struct clk *parent = clk_get_parent(clk); + struct rockchip_clk_pll *pll; + + if (IS_ERR_OR_NULL(parent)) + return -EINVAL; + + pll = to_rockchip_clk_pll(__clk_get_hw(parent)); + if (!pll) + return -EINVAL; + + pll->sel = sel; + + return 0; +} +EXPORT_SYMBOL(rockchip_pll_clk_adaptive_scaling); + +int rockchip_pll_clk_rate_to_scale(struct clk *clk, unsigned long rate) +{ + const struct rockchip_pll_rate_table *rate_table; + struct clk *parent = clk_get_parent(clk); + struct rockchip_clk_pll *pll; + unsigned int i; + + if (IS_ERR_OR_NULL(parent)) + return -EINVAL; + + pll = to_rockchip_clk_pll(__clk_get_hw(parent)); + if (!pll) + return -EINVAL; + + rate_table = pll->rate_table; + for (i = 0; i < pll->rate_count; i++) { + if (rate >= rate_table[i].rate) + return i; + } + + return -EINVAL; +} +EXPORT_SYMBOL(rockchip_pll_clk_rate_to_scale); + +int rockchip_pll_clk_scale_to_rate(struct clk *clk, unsigned int scale) +{ + const struct rockchip_pll_rate_table *rate_table; + struct clk *parent = clk_get_parent(clk); + struct rockchip_clk_pll *pll; + unsigned int i; + + if (IS_ERR_OR_NULL(parent)) + return -EINVAL; + + pll = to_rockchip_clk_pll(__clk_get_hw(parent)); + if (!pll) + return -EINVAL; + + rate_table = pll->rate_table; + for (i = 0; i < pll->rate_count; i++) { + if (i == scale) + return rate_table[i].rate; + } + + return -EINVAL; +} +EXPORT_SYMBOL(rockchip_pll_clk_scale_to_rate); + static long rockchip_pll_round_rate(struct clk_hw *hw, unsigned long drate, unsigned long *prate) { diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index fd3b476dedda9a8620fa4be2b1f7a7ece2da2be2..1bcfc39fb3a8fa617ad0963c9f2ae112da8f342e 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -987,6 +987,9 @@ void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, const struct rockchip_cpuclk_reg_data *reg_data, const struct rockchip_cpuclk_rate_table *rates, int nrates); +int rockchip_pll_clk_rate_to_scale(struct clk *clk, unsigned long rate); +int rockchip_pll_clk_scale_to_rate(struct clk *clk, unsigned int scale); +int rockchip_pll_clk_adaptive_scaling(struct clk *clk, int sel); void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, unsigned int reg, void (*cb)(void));