diff options
Diffstat (limited to 'drivers/clk/st/clkgen-pll.c')
| -rw-r--r-- | drivers/clk/st/clkgen-pll.c | 162 |
1 files changed, 129 insertions, 33 deletions
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c index c3952f2c42ba..c258ff87a171 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c @@ -57,6 +57,17 @@ struct clkgen_pll_data { const struct clk_ops *ops; }; +struct clkgen_clk_out { + const char *name; + unsigned long flags; +}; + +struct clkgen_pll_data_clks { + struct clkgen_pll_data *data; + const struct clkgen_clk_out *outputs; +}; + + static const struct clk_ops stm_pll3200c32_ops; static const struct clk_ops stm_pll3200c32_a9_ops; static const struct clk_ops stm_pll4600c28_ops; @@ -74,6 +85,28 @@ static const struct clkgen_pll_data st_pll3200c32_cx_0 = { .ops = &stm_pll3200c32_ops, }; +static const struct clkgen_pll_data_clks st_pll3200c32_cx_0_legacy_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0, +}; + +static const struct clkgen_clk_out st_pll3200c32_ax_0_clks[] = { + { .name = "clk-s-a0-pll-odf-0", }, +}; + +static const struct clkgen_pll_data_clks st_pll3200c32_a0_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0, + .outputs = st_pll3200c32_ax_0_clks, +}; + +static const struct clkgen_clk_out st_pll3200c32_cx_0_clks[] = { + { .name = "clk-s-c0-pll0-odf-0", }, +}; + +static const struct clkgen_pll_data_clks st_pll3200c32_c0_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0, + .outputs = st_pll3200c32_cx_0_clks, +}; + static const struct clkgen_pll_data st_pll3200c32_cx_1 = { /* 407 C0 PLL1 */ .pdn_status = CLKGEN_FIELD(0x2c8, 0x1, 8), @@ -87,6 +120,19 @@ static const struct clkgen_pll_data st_pll3200c32_cx_1 = { .ops = &stm_pll3200c32_ops, }; +static const struct clkgen_pll_data_clks st_pll3200c32_cx_1_legacy_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_1, +}; + +static const struct clkgen_clk_out st_pll3200c32_cx_1_clks[] = { + { .name = "clk-s-c0-pll1-odf-0", }, +}; + +static const struct clkgen_pll_data_clks st_pll3200c32_c1_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_1, + .outputs = st_pll3200c32_cx_1_clks, +}; + static const struct clkgen_pll_data st_pll3200c32_407_a9 = { /* 407 A9 */ .pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0), @@ -104,6 +150,15 @@ static const struct clkgen_pll_data st_pll3200c32_407_a9 = { .ops = &stm_pll3200c32_a9_ops, }; +static const struct clkgen_clk_out st_pll3200c32_407_a9_clks[] = { + { .name = "clockgen-a9-pll-odf", }, +}; + +static const struct clkgen_pll_data_clks st_pll3200c32_407_a9_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_407_a9, + .outputs = st_pll3200c32_407_a9_clks, +}; + static struct clkgen_pll_data st_pll4600c28_418_a9 = { /* 418 A9 */ .pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0), @@ -120,6 +175,15 @@ static struct clkgen_pll_data st_pll4600c28_418_a9 = { .ops = &stm_pll4600c28_ops, }; +static const struct clkgen_clk_out st_pll4600c28_418_a9_clks[] = { + { .name = "clockgen-a9-pll-odf", }, +}; + +static const struct clkgen_pll_data_clks st_pll4600c28_418_a9_data = { + .data = (struct clkgen_pll_data *)&st_pll4600c28_418_a9, + .outputs = st_pll4600c28_418_a9_clks, +}; + /** * DOC: Clock Generated by PLL, rate set and enabled by bootloader * @@ -130,12 +194,11 @@ static struct clkgen_pll_data st_pll4600c28_418_a9 = { * parent - fixed parent. No clk_set_parent support */ -/** +/* * PLL clock that is integrated in the ClockGenA instances on the STiH415 * and STiH416. * * @hw: handle between common and hardware-specific interfaces. - * @type: PLL instance type. * @regs_base: base of the PLL configuration register(s). * */ @@ -147,7 +210,6 @@ struct clkgen_pll { u32 ndiv; u32 idf; - u32 odf; u32 cp; }; @@ -333,25 +395,28 @@ static unsigned long recalc_stm_pll3200c32(struct clk_hw *hw, return rate; } -static long round_rate_stm_pll3200c32(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int stm_pll3200c32_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct stm_pll params; - if (!clk_pll3200c32_get_params(*prate, rate, ¶ms)) - clk_pll3200c32_get_rate(*prate, ¶ms, &rate); + if (!clk_pll3200c32_get_params(req->best_parent_rate, req->rate, ¶ms)) + clk_pll3200c32_get_rate(req->best_parent_rate, ¶ms, + &req->rate); else { pr_debug("%s: %s rate %ld Invalid\n", __func__, - __clk_get_name(hw->clk), rate); + __clk_get_name(hw->clk), req->rate); + req->rate = 0; + return 0; } pr_debug("%s: %s new rate %ld [ndiv=%u] [idf=%u]\n", __func__, __clk_get_name(hw->clk), - rate, (unsigned int)params.ndiv, + req->rate, (unsigned int)params.ndiv, (unsigned int)params.idf); - return rate; + return 0; } static int set_rate_stm_pll3200c32(struct clk_hw *hw, unsigned long rate, @@ -487,25 +552,28 @@ static unsigned long recalc_stm_pll4600c28(struct clk_hw *hw, return rate; } -static long round_rate_stm_pll4600c28(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int stm_pll4600c28_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct stm_pll params; - if (!clk_pll4600c28_get_params(*prate, rate, ¶ms)) { - clk_pll4600c28_get_rate(*prate, ¶ms, &rate); + if (!clk_pll4600c28_get_params(req->best_parent_rate, req->rate, ¶ms)) { + clk_pll4600c28_get_rate(req->best_parent_rate, ¶ms, + &req->rate); } else { pr_debug("%s: %s rate %ld Invalid\n", __func__, - __clk_get_name(hw->clk), rate); + __clk_get_name(hw->clk), req->rate); + req->rate = 0; + return 0; } pr_debug("%s: %s new rate %ld [ndiv=%u] [idf=%u]\n", __func__, __clk_get_name(hw->clk), - rate, (unsigned int)params.ndiv, + req->rate, (unsigned int)params.ndiv, (unsigned int)params.idf); - return rate; + return 0; } static int set_rate_stm_pll4600c28(struct clk_hw *hw, unsigned long rate, @@ -566,7 +634,7 @@ static const struct clk_ops stm_pll3200c32_a9_ops = { .disable = clkgen_pll_disable, .is_enabled = clkgen_pll_is_enabled, .recalc_rate = recalc_stm_pll3200c32, - .round_rate = round_rate_stm_pll3200c32, + .determine_rate = stm_pll3200c32_determine_rate, .set_rate = set_rate_stm_pll3200c32, }; @@ -575,7 +643,7 @@ static const struct clk_ops stm_pll4600c28_ops = { .disable = clkgen_pll_disable, .is_enabled = clkgen_pll_is_enabled, .recalc_rate = recalc_stm_pll4600c28, - .round_rate = round_rate_stm_pll4600c28, + .determine_rate = stm_pll4600c28_determine_rate, .set_rate = set_rate_stm_pll4600c28, }; @@ -686,7 +754,7 @@ static struct clk * __init clkgen_odf_register(const char *parent_name, static void __init clkgen_c32_pll_setup(struct device_node *np, - struct clkgen_pll_data *data) + struct clkgen_pll_data_clks *datac) { struct clk *clk; const char *parent_name, *pll_name; @@ -706,14 +774,14 @@ static void __init clkgen_c32_pll_setup(struct device_node *np, of_clk_detect_critical(np, 0, &pll_flags); - clk = clkgen_pll_register(parent_name, data, pll_base, pll_flags, - np->name, data->lock); + clk = clkgen_pll_register(parent_name, datac->data, pll_base, pll_flags, + np->name, datac->data->lock); if (IS_ERR(clk)) return; pll_name = __clk_get_name(clk); - num_odfs = data->num_odfs; + num_odfs = datac->data->num_odfs; clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); if (!clk_data) @@ -731,14 +799,21 @@ static void __init clkgen_c32_pll_setup(struct device_node *np, const char *clk_name; unsigned long odf_flags = 0; - if (of_property_read_string_index(np, "clock-output-names", - odf, &clk_name)) - return; + if (datac->outputs) { + clk_name = datac->outputs[odf].name; + odf_flags = datac->outputs[odf].flags; + } else { + if (of_property_read_string_index(np, + "clock-output-names", + odf, &clk_name)) + return; - of_clk_detect_critical(np, odf, &odf_flags); + of_clk_detect_critical(np, odf, &odf_flags); + } - clk = clkgen_odf_register(pll_name, pll_base, data, odf_flags, - odf, &clkgena_c32_odf_lock, clk_name); + clk = clkgen_odf_register(pll_name, pll_base, datac->data, + odf_flags, odf, &clkgena_c32_odf_lock, + clk_name); if (IS_ERR(clk)) goto err; @@ -756,27 +831,48 @@ err: static void __init clkgen_c32_pll0_setup(struct device_node *np) { clkgen_c32_pll_setup(np, - (struct clkgen_pll_data *) &st_pll3200c32_cx_0); + (struct clkgen_pll_data_clks *) &st_pll3200c32_cx_0_legacy_data); } CLK_OF_DECLARE(c32_pll0, "st,clkgen-pll0", clkgen_c32_pll0_setup); +static void __init clkgen_c32_pll0_a0_setup(struct device_node *np) +{ + clkgen_c32_pll_setup(np, + (struct clkgen_pll_data_clks *) &st_pll3200c32_a0_data); +} +CLK_OF_DECLARE(c32_pll0_a0, "st,clkgen-pll0-a0", clkgen_c32_pll0_a0_setup); + +static void __init clkgen_c32_pll0_c0_setup(struct device_node *np) +{ + clkgen_c32_pll_setup(np, + (struct clkgen_pll_data_clks *) &st_pll3200c32_c0_data); +} +CLK_OF_DECLARE(c32_pll0_c0, "st,clkgen-pll0-c0", clkgen_c32_pll0_c0_setup); + static void __init clkgen_c32_pll1_setup(struct device_node *np) { clkgen_c32_pll_setup(np, - (struct clkgen_pll_data *) &st_pll3200c32_cx_1); + (struct clkgen_pll_data_clks *) &st_pll3200c32_cx_1_legacy_data); } CLK_OF_DECLARE(c32_pll1, "st,clkgen-pll1", clkgen_c32_pll1_setup); +static void __init clkgen_c32_pll1_c0_setup(struct device_node *np) +{ + clkgen_c32_pll_setup(np, + (struct clkgen_pll_data_clks *) &st_pll3200c32_c1_data); +} +CLK_OF_DECLARE(c32_pll1_c0, "st,clkgen-pll1-c0", clkgen_c32_pll1_c0_setup); + static void __init clkgen_c32_plla9_setup(struct device_node *np) { clkgen_c32_pll_setup(np, - (struct clkgen_pll_data *) &st_pll3200c32_407_a9); + (struct clkgen_pll_data_clks *) &st_pll3200c32_407_a9_data); } CLK_OF_DECLARE(c32_plla9, "st,stih407-clkgen-plla9", clkgen_c32_plla9_setup); static void __init clkgen_c28_plla9_setup(struct device_node *np) { clkgen_c32_pll_setup(np, - (struct clkgen_pll_data *) &st_pll4600c28_418_a9); + (struct clkgen_pll_data_clks *) &st_pll4600c28_418_a9_data); } CLK_OF_DECLARE(c28_plla9, "st,stih418-clkgen-plla9", clkgen_c28_plla9_setup); |
