summaryrefslogtreecommitdiff
path: root/drivers/clk/st/clkgen-pll.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/st/clkgen-pll.c')
-rw-r--r--drivers/clk/st/clkgen-pll.c162
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, &params))
- clk_pll3200c32_get_rate(*prate, &params, &rate);
+ if (!clk_pll3200c32_get_params(req->best_parent_rate, req->rate, &params))
+ clk_pll3200c32_get_rate(req->best_parent_rate, &params,
+ &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, &params)) {
- clk_pll4600c28_get_rate(*prate, &params, &rate);
+ if (!clk_pll4600c28_get_params(req->best_parent_rate, req->rate, &params)) {
+ clk_pll4600c28_get_rate(req->best_parent_rate, &params,
+ &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);