mirror of https://gitee.com/openkylin/linux.git
clk: versatile: respect parent rate in ICST clock
If the ICST clock has a parent, respect the rate of the parent when calculating the clock frequency. As this involves modifying the ICST parameter struct, make a cloned copy (the divisor arrays should be safe) so we can update the .ref field. Do not define the reference clock on the Integrator as we have the reference clock from the device tree. Keep it everywhere else. Cc: Mike Turquette <mturquette@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
bf6edb4bb1
commit
a183da637c
|
@ -33,7 +33,7 @@ struct clk_icst {
|
||||||
struct clk_hw hw;
|
struct clk_hw hw;
|
||||||
void __iomem *vcoreg;
|
void __iomem *vcoreg;
|
||||||
void __iomem *lockreg;
|
void __iomem *lockreg;
|
||||||
const struct icst_params *params;
|
struct icst_params *params;
|
||||||
unsigned long rate;
|
unsigned long rate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,6 +84,8 @@ static unsigned long icst_recalc_rate(struct clk_hw *hw,
|
||||||
struct clk_icst *icst = to_icst(hw);
|
struct clk_icst *icst = to_icst(hw);
|
||||||
struct icst_vco vco;
|
struct icst_vco vco;
|
||||||
|
|
||||||
|
if (parent_rate)
|
||||||
|
icst->params->ref = parent_rate;
|
||||||
vco = vco_get(icst->vcoreg);
|
vco = vco_get(icst->vcoreg);
|
||||||
icst->rate = icst_hz(icst->params, vco);
|
icst->rate = icst_hz(icst->params, vco);
|
||||||
return icst->rate;
|
return icst->rate;
|
||||||
|
@ -105,6 +107,8 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
struct clk_icst *icst = to_icst(hw);
|
struct clk_icst *icst = to_icst(hw);
|
||||||
struct icst_vco vco;
|
struct icst_vco vco;
|
||||||
|
|
||||||
|
if (parent_rate)
|
||||||
|
icst->params->ref = parent_rate;
|
||||||
vco = icst_hz_to_vco(icst->params, rate);
|
vco = icst_hz_to_vco(icst->params, rate);
|
||||||
icst->rate = icst_hz(icst->params, vco);
|
icst->rate = icst_hz(icst->params, vco);
|
||||||
vco_set(icst->lockreg, icst->vcoreg, vco);
|
vco_set(icst->lockreg, icst->vcoreg, vco);
|
||||||
|
@ -126,19 +130,27 @@ struct clk *icst_clk_register(struct device *dev,
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct clk_icst *icst;
|
struct clk_icst *icst;
|
||||||
struct clk_init_data init;
|
struct clk_init_data init;
|
||||||
|
struct icst_params *pclone;
|
||||||
|
|
||||||
icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL);
|
icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL);
|
||||||
if (!icst) {
|
if (!icst) {
|
||||||
pr_err("could not allocate ICST clock!\n");
|
pr_err("could not allocate ICST clock!\n");
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pclone = kmemdup(desc->params, sizeof(*pclone), GFP_KERNEL);
|
||||||
|
if (!pclone) {
|
||||||
|
pr_err("could not clone ICST params\n");
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
init.name = name;
|
init.name = name;
|
||||||
init.ops = &icst_ops;
|
init.ops = &icst_ops;
|
||||||
init.flags = CLK_IS_ROOT;
|
init.flags = CLK_IS_ROOT;
|
||||||
init.parent_names = NULL;
|
init.parent_names = (parent_name ? &parent_name : NULL);
|
||||||
init.num_parents = 0;
|
init.num_parents = (parent_name ? 1 : 0);
|
||||||
icst->hw.init = &init;
|
icst->hw.init = &init;
|
||||||
icst->params = desc->params;
|
icst->params = pclone;
|
||||||
icst->vcoreg = base + desc->vco_offset;
|
icst->vcoreg = base + desc->vco_offset;
|
||||||
icst->lockreg = base + desc->lock_offset;
|
icst->lockreg = base + desc->lock_offset;
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
static void __iomem *cm_base;
|
static void __iomem *cm_base;
|
||||||
|
|
||||||
static const struct icst_params cp_auxosc_params = {
|
static const struct icst_params cp_auxosc_params = {
|
||||||
.ref = 24000000,
|
|
||||||
.vco_max = ICST525_VCO_MAX_5V,
|
.vco_max = ICST525_VCO_MAX_5V,
|
||||||
.vco_min = ICST525_VCO_MIN,
|
.vco_min = ICST525_VCO_MIN,
|
||||||
.vd_min = 8,
|
.vd_min = 8,
|
||||||
|
|
Loading…
Reference in New Issue