diff options
Diffstat (limited to 'drivers/clk/ti/fapll.c')
| -rw-r--r-- | drivers/clk/ti/fapll.c | 94 |
1 files changed, 51 insertions, 43 deletions
diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c index 66a0d0ed8b55..4f28138d2d8a 100644 --- a/drivers/clk/ti/fapll.c +++ b/drivers/clk/ti/fapll.c @@ -1,23 +1,17 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ +// SPDX-License-Identifier: GPL-2.0-only #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/delay.h> #include <linux/err.h> +#include <linux/io.h> #include <linux/math64.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/clk/ti.h> +#include "clock.h" + /* FAPLL Control Register PLL_CTRL */ #define FAPLL_MAIN_MULT_N_SHIFT 16 #define FAPLL_MAIN_DIV_P_SHIFT 8 @@ -220,24 +214,27 @@ static int ti_fapll_set_div_mult(unsigned long rate, return 0; } -static long ti_fapll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int ti_fapll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { u32 pre_div_p, mult_n; int error; - if (!rate) + if (!req->rate) return -EINVAL; - error = ti_fapll_set_div_mult(rate, *parent_rate, + error = ti_fapll_set_div_mult(req->rate, req->best_parent_rate, &pre_div_p, &mult_n); - if (error) - return error; + if (error) { + req->rate = error; + + return 0; + } - rate = *parent_rate / pre_div_p; - rate *= mult_n; + req->rate = req->best_parent_rate / pre_div_p; + req->rate *= mult_n; - return rate; + return 0; } static int ti_fapll_set_rate(struct clk_hw *hw, unsigned long rate, @@ -268,13 +265,13 @@ static int ti_fapll_set_rate(struct clk_hw *hw, unsigned long rate, return 0; } -static struct clk_ops ti_fapll_ops = { +static const struct clk_ops ti_fapll_ops = { .enable = ti_fapll_enable, .disable = ti_fapll_disable, .is_enabled = ti_fapll_is_enabled, .recalc_rate = ti_fapll_recalc_rate, .get_parent = ti_fapll_get_parent, - .round_rate = ti_fapll_round_rate, + .determine_rate = ti_fapll_determine_rate, .set_rate = ti_fapll_set_rate, }; @@ -405,14 +402,14 @@ static u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth, return post_div_m; } -static long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int ti_fapll_synth_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct fapll_synth *synth = to_synth(hw); struct fapll_data *fd = synth->fd; unsigned long r; - if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate) + if (ti_fapll_clock_is_bypass(fd) || !synth->div || !req->rate) return -EINVAL; /* Only post divider m available with no fractional divider? */ @@ -420,23 +417,26 @@ static long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long frac_rate; u32 synth_post_div_m; - frac_rate = ti_fapll_synth_get_frac_rate(hw, *parent_rate); - synth_post_div_m = DIV_ROUND_UP(frac_rate, rate); + frac_rate = ti_fapll_synth_get_frac_rate(hw, + req->best_parent_rate); + synth_post_div_m = DIV_ROUND_UP(frac_rate, req->rate); r = DIV_ROUND_UP(frac_rate, synth_post_div_m); goto out; } - r = *parent_rate * SYNTH_PHASE_K; - if (rate > r) + r = req->best_parent_rate * SYNTH_PHASE_K; + if (req->rate > r) goto out; r = DIV_ROUND_UP_ULL(r, SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M); - if (rate < r) + if (req->rate < r) goto out; - r = rate; + r = req->rate; out: - return r; + req->rate = r; + + return 0; } static int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate, @@ -478,12 +478,12 @@ static int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate, return 0; } -static struct clk_ops ti_fapll_synt_ops = { +static const struct clk_ops ti_fapll_synt_ops = { .enable = ti_fapll_synth_enable, .disable = ti_fapll_synth_disable, .is_enabled = ti_fapll_synth_is_enabled, .recalc_rate = ti_fapll_synth_recalc_rate, - .round_rate = ti_fapll_synth_round_rate, + .determine_rate = ti_fapll_synth_determine_rate, .set_rate = ti_fapll_synth_set_rate, }; @@ -497,6 +497,7 @@ static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd, { struct clk_init_data *init; struct fapll_synth *synth; + struct clk *clk = ERR_PTR(-ENOMEM); init = kzalloc(sizeof(*init), GFP_KERNEL); if (!init) @@ -519,13 +520,19 @@ static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd, synth->hw.init = init; synth->clk_pll = pll_clk; - return clk_register(NULL, &synth->hw); + clk = clk_register(NULL, &synth->hw); + if (IS_ERR(clk)) { + pr_err("failed to register clock\n"); + goto free; + } + + return clk; free: kfree(synth); kfree(init); - return ERR_PTR(-ENOMEM); + return clk; } static void __init ti_fapll_setup(struct device_node *node) @@ -534,6 +541,7 @@ static void __init ti_fapll_setup(struct device_node *node) struct clk_init_data *init = NULL; const char *parent_name[2]; struct clk *pll_clk; + const char *name; int i; fd = kzalloc(sizeof(*fd), GFP_KERNEL); @@ -551,11 +559,12 @@ static void __init ti_fapll_setup(struct device_node *node) goto free; init->ops = &ti_fapll_ops; - init->name = node->name; + name = ti_dt_clk_name(node); + init->name = name; init->num_parents = of_clk_get_parent_count(node); if (init->num_parents != 2) { - pr_err("%s must have two parents\n", node->name); + pr_err("%pOFn must have two parents\n", node); goto free; } @@ -564,26 +573,26 @@ static void __init ti_fapll_setup(struct device_node *node) fd->clk_ref = of_clk_get(node, 0); if (IS_ERR(fd->clk_ref)) { - pr_err("%s could not get clk_ref\n", node->name); + pr_err("%pOFn could not get clk_ref\n", node); goto free; } fd->clk_bypass = of_clk_get(node, 1); if (IS_ERR(fd->clk_bypass)) { - pr_err("%s could not get clk_bypass\n", node->name); + pr_err("%pOFn could not get clk_bypass\n", node); goto free; } fd->base = of_iomap(node, 0); if (!fd->base) { - pr_err("%s could not get IO base\n", node->name); + pr_err("%pOFn could not get IO base\n", node); goto free; } if (fapll_is_ddr_pll(fd->base)) fd->bypass_bit_inverted = true; - fd->name = node->name; + fd->name = name; fd->hw.init = init; /* Register the parent PLL */ @@ -630,8 +639,7 @@ static void __init ti_fapll_setup(struct device_node *node) freq = NULL; } synth_clk = ti_fapll_synth_setup(fd, freq, div, output_instance, - output_name, node->name, - pll_clk); + output_name, name, pll_clk); if (IS_ERR(synth_clk)) continue; |
