TEGRA: Fix CPU frequency switching.
The PLL_X, base CPU frequency source, doesn't have a bypass switch and thus we must use another frequency source for CPU while changing its frequency. PLL_P is ideal for this, it runs at 480MHz and CPU can be clocked at this frequency at any CPU voltage.
This commit is contained in:
parent
cc8a3448d9
commit
b799783990
@ -823,12 +823,10 @@ pllx_set_freq(struct pll_sc *sc, uint64_t fin, uint64_t *fout, int flags)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Set bypass. */
|
||||
/* PLLX doesn't have bypass, disable it first. */
|
||||
RD4(sc, sc->base_reg, ®);
|
||||
reg |= PLL_BASE_BYPASS;
|
||||
reg &= ~PLL_BASE_ENABLE;
|
||||
WR4(sc, sc->base_reg, reg);
|
||||
RD4(sc, sc->base_reg, ®);
|
||||
DELAY(100);
|
||||
|
||||
/* Set PLL. */
|
||||
RD4(sc, sc->base_reg, ®);
|
||||
@ -840,16 +838,16 @@ pllx_set_freq(struct pll_sc *sc, uint64_t fin, uint64_t *fout, int flags)
|
||||
RD4(sc, sc->base_reg, ®);
|
||||
DELAY(100);
|
||||
|
||||
/* Enable lock detection. */
|
||||
RD4(sc, sc->misc_reg, ®);
|
||||
reg |= sc->lock_enable;
|
||||
WR4(sc, sc->misc_reg, reg);
|
||||
|
||||
/* Enable PLL. */
|
||||
RD4(sc, sc->base_reg, ®);
|
||||
reg |= PLL_BASE_ENABLE;
|
||||
WR4(sc, sc->base_reg, reg);
|
||||
|
||||
/* Enable lock detection */
|
||||
RD4(sc, sc->misc_reg, ®);
|
||||
reg |= sc->lock_enable;
|
||||
WR4(sc, sc->misc_reg, reg);
|
||||
|
||||
rv = wait_for_lock(sc);
|
||||
if (rv != 0) {
|
||||
/* Disable PLL */
|
||||
@ -860,10 +858,6 @@ pllx_set_freq(struct pll_sc *sc, uint64_t fin, uint64_t *fout, int flags)
|
||||
}
|
||||
RD4(sc, sc->misc_reg, ®);
|
||||
|
||||
/* Clear bypass. */
|
||||
RD4(sc, sc->base_reg, ®);
|
||||
reg &= ~PLL_BASE_BYPASS;
|
||||
WR4(sc, sc->base_reg, reg);
|
||||
*fout = ((fin / m) * n) / p;
|
||||
return (0);
|
||||
}
|
||||
|
@ -205,8 +205,7 @@ super_mux_set_mux(struct clknode *clk, int idx)
|
||||
(state != SUPER_MUX_STATE_IDLE)) {
|
||||
panic("Unexpected super mux state: %u", state);
|
||||
}
|
||||
|
||||
shift = state * SUPER_MUX_MUX_WIDTH;
|
||||
shift = (state - 1) * SUPER_MUX_MUX_WIDTH;
|
||||
sc->mux = idx;
|
||||
if (sc->flags & SMF_HAVE_DIVIDER_2) {
|
||||
if (idx == sc->src_div2) {
|
||||
@ -222,6 +221,7 @@ super_mux_set_mux(struct clknode *clk, int idx)
|
||||
}
|
||||
reg &= ~(((1 << SUPER_MUX_MUX_WIDTH) - 1) << shift);
|
||||
reg |= idx << shift;
|
||||
|
||||
WR4(sc, sc->base_reg, reg);
|
||||
RD4(sc, sc->base_reg, &dummy);
|
||||
DEVICE_UNLOCK(sc);
|
||||
|
@ -335,12 +335,27 @@ set_cpu_freq(struct tegra124_cpufreq_softc *sc, uint64_t freq)
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
}
|
||||
rv = clk_set_freq(sc->clk_cpu_g, point->freq, CLK_SET_ROUND_DOWN);
|
||||
|
||||
/* Switch supermux to PLLP first */
|
||||
rv = clk_set_parent_by_clk(sc->clk_cpu_g, sc->clk_pll_p);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Can't set parent to PLLP\n");
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/* Set PLLX frequency */
|
||||
rv = clk_set_freq(sc->clk_pll_x, point->freq, CLK_SET_ROUND_DOWN);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Can't set CPU clock frequency\n");
|
||||
return (rv);
|
||||
}
|
||||
|
||||
rv = clk_set_parent_by_clk(sc->clk_cpu_g, sc->clk_pll_x);
|
||||
if (rv != 0) {
|
||||
device_printf(sc->dev, "Can't set parent to PLLX\n");
|
||||
return (rv);
|
||||
}
|
||||
|
||||
if (sc->act_speed_point->uvolt > point->uvolt) {
|
||||
/* set cpu voltage */
|
||||
rv = regulator_set_voltage(sc->supply_vdd_cpu,
|
||||
|
Loading…
Reference in New Issue
Block a user