diff options
Diffstat (limited to 'drivers/clk/versatile/clk-icst.c')
| -rw-r--r-- | drivers/clk/versatile/clk-icst.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index 8cbfcf88fae3..a820b0cfcf57 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c | |||
| @@ -33,7 +33,7 @@ struct clk_icst { | |||
| 33 | struct clk_hw hw; | 33 | struct clk_hw hw; |
| 34 | void __iomem *vcoreg; | 34 | void __iomem *vcoreg; |
| 35 | void __iomem *lockreg; | 35 | void __iomem *lockreg; |
| 36 | const struct icst_params *params; | 36 | struct icst_params *params; |
| 37 | unsigned long rate; | 37 | unsigned long rate; |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| @@ -84,6 +84,8 @@ static unsigned long icst_recalc_rate(struct clk_hw *hw, | |||
| 84 | struct clk_icst *icst = to_icst(hw); | 84 | struct clk_icst *icst = to_icst(hw); |
| 85 | struct icst_vco vco; | 85 | struct icst_vco vco; |
| 86 | 86 | ||
| 87 | if (parent_rate) | ||
| 88 | icst->params->ref = parent_rate; | ||
| 87 | vco = vco_get(icst->vcoreg); | 89 | vco = vco_get(icst->vcoreg); |
| 88 | icst->rate = icst_hz(icst->params, vco); | 90 | icst->rate = icst_hz(icst->params, vco); |
| 89 | return icst->rate; | 91 | return icst->rate; |
| @@ -105,6 +107,8 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 105 | struct clk_icst *icst = to_icst(hw); | 107 | struct clk_icst *icst = to_icst(hw); |
| 106 | struct icst_vco vco; | 108 | struct icst_vco vco; |
| 107 | 109 | ||
| 110 | if (parent_rate) | ||
| 111 | icst->params->ref = parent_rate; | ||
| 108 | vco = icst_hz_to_vco(icst->params, rate); | 112 | vco = icst_hz_to_vco(icst->params, rate); |
| 109 | icst->rate = icst_hz(icst->params, vco); | 113 | icst->rate = icst_hz(icst->params, vco); |
| 110 | vco_set(icst->lockreg, icst->vcoreg, vco); | 114 | vco_set(icst->lockreg, icst->vcoreg, vco); |
| @@ -120,24 +124,33 @@ static const struct clk_ops icst_ops = { | |||
| 120 | struct clk *icst_clk_register(struct device *dev, | 124 | struct clk *icst_clk_register(struct device *dev, |
| 121 | const struct clk_icst_desc *desc, | 125 | const struct clk_icst_desc *desc, |
| 122 | const char *name, | 126 | const char *name, |
| 127 | const char *parent_name, | ||
| 123 | void __iomem *base) | 128 | void __iomem *base) |
| 124 | { | 129 | { |
| 125 | struct clk *clk; | 130 | struct clk *clk; |
| 126 | struct clk_icst *icst; | 131 | struct clk_icst *icst; |
| 127 | struct clk_init_data init; | 132 | struct clk_init_data init; |
| 133 | struct icst_params *pclone; | ||
| 128 | 134 | ||
| 129 | icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); | 135 | icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); |
| 130 | if (!icst) { | 136 | if (!icst) { |
| 131 | pr_err("could not allocate ICST clock!\n"); | 137 | pr_err("could not allocate ICST clock!\n"); |
| 132 | return ERR_PTR(-ENOMEM); | 138 | return ERR_PTR(-ENOMEM); |
| 133 | } | 139 | } |
| 140 | |||
| 141 | pclone = kmemdup(desc->params, sizeof(*pclone), GFP_KERNEL); | ||
| 142 | if (!pclone) { | ||
| 143 | pr_err("could not clone ICST params\n"); | ||
| 144 | return ERR_PTR(-ENOMEM); | ||
| 145 | } | ||
| 146 | |||
| 134 | init.name = name; | 147 | init.name = name; |
| 135 | init.ops = &icst_ops; | 148 | init.ops = &icst_ops; |
| 136 | init.flags = CLK_IS_ROOT; | 149 | init.flags = CLK_IS_ROOT; |
| 137 | init.parent_names = NULL; | 150 | init.parent_names = (parent_name ? &parent_name : NULL); |
| 138 | init.num_parents = 0; | 151 | init.num_parents = (parent_name ? 1 : 0); |
| 139 | icst->hw.init = &init; | 152 | icst->hw.init = &init; |
| 140 | icst->params = desc->params; | 153 | icst->params = pclone; |
| 141 | icst->vcoreg = base + desc->vco_offset; | 154 | icst->vcoreg = base + desc->vco_offset; |
| 142 | icst->lockreg = base + desc->lock_offset; | 155 | icst->lockreg = base + desc->lock_offset; |
| 143 | 156 | ||
