Skip to content

Commit 14aba8d

Browse files
finley1226rkhuangtao
authored andcommitted
clk: rockchip: Fix cpu frequency overflowing
If change parent to alternate parent and the old parent clock speed is less than the clock speed of the alternate parent, add dividers first and then select alternate parent. If change parent to primary parent, select primary parent first and then remove dividers. Change-Id: Ib82de9a936effe5c885639799f3bb5629dc89f8d Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
1 parent 2c1c86d commit 14aba8d

1 file changed

Lines changed: 15 additions & 27 deletions

File tree

drivers/clk/rockchip/clk-cpu.c

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -158,30 +158,21 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
158158
alt_div = reg_data->div_core_mask;
159159
}
160160

161-
/*
162-
* Change parents and add dividers in a single transaction.
163-
*
164-
* NOTE: we do this in a single transaction so we're never
165-
* dividing the primary parent by the extra dividers that were
166-
* needed for the alt.
167-
*/
168161
pr_debug("%s: setting div %lu as alt-rate %lu > old-rate %lu\n",
169162
__func__, alt_div, alt_prate, ndata->old_rate);
170163

164+
/* add dividers */
171165
writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask,
172-
reg_data->div_core_shift) |
173-
HIWORD_UPDATE(reg_data->mux_core_alt,
174-
reg_data->mux_core_mask,
175-
reg_data->mux_core_shift),
176-
cpuclk->reg_base + reg_data->core_reg);
177-
} else {
178-
/* select alternate parent */
179-
writel(HIWORD_UPDATE(reg_data->mux_core_alt,
180-
reg_data->mux_core_mask,
181-
reg_data->mux_core_shift),
166+
reg_data->div_core_shift),
182167
cpuclk->reg_base + reg_data->core_reg);
183168
}
184169

170+
/* select alternate parent */
171+
writel(HIWORD_UPDATE(reg_data->mux_core_alt,
172+
reg_data->mux_core_mask,
173+
reg_data->mux_core_shift),
174+
cpuclk->reg_base + reg_data->core_reg);
175+
185176
spin_unlock_irqrestore(cpuclk->lock, flags);
186177
return 0;
187178
}
@@ -206,18 +197,15 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk,
206197
if (ndata->old_rate < ndata->new_rate)
207198
rockchip_cpuclk_set_dividers(cpuclk, rate);
208199

209-
/*
210-
* post-rate change event, re-mux to primary parent and remove dividers.
211-
*
212-
* NOTE: we do this in a single transaction so we're never dividing the
213-
* primary parent by the extra dividers that were needed for the alt.
214-
*/
200+
/* re-mux to primary parent */
201+
writel(HIWORD_UPDATE(reg_data->mux_core_main,
202+
reg_data->mux_core_mask,
203+
reg_data->mux_core_shift),
204+
cpuclk->reg_base + reg_data->core_reg);
215205

206+
/* remove dividers */
216207
writel(HIWORD_UPDATE(0, reg_data->div_core_mask,
217-
reg_data->div_core_shift) |
218-
HIWORD_UPDATE(reg_data->mux_core_main,
219-
reg_data->mux_core_mask,
220-
reg_data->mux_core_shift),
208+
reg_data->div_core_shift),
221209
cpuclk->reg_base + reg_data->core_reg);
222210

223211
if (ndata->old_rate > ndata->new_rate)

0 commit comments

Comments
 (0)