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:
Michal Meloun 2016-04-05 09:20:52 +00:00
parent cc8a3448d9
commit b799783990
3 changed files with 25 additions and 16 deletions

View File

@ -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);
reg |= PLL_BASE_BYPASS;
reg &= ~PLL_BASE_ENABLE;
WR4(sc, sc->base_reg, reg);
RD4(sc, sc->base_reg, &reg);
DELAY(100);
/* Set PLL. */
RD4(sc, sc->base_reg, &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, &reg);
DELAY(100);
/* Enable lock detection. */
RD4(sc, sc->misc_reg, &reg);
reg |= sc->lock_enable;
WR4(sc, sc->misc_reg, reg);
/* Enable PLL. */
RD4(sc, sc->base_reg, &reg);
reg |= PLL_BASE_ENABLE;
WR4(sc, sc->base_reg, reg);
/* Enable lock detection */
RD4(sc, sc->misc_reg, &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, &reg);
/* Clear bypass. */
RD4(sc, sc->base_reg, &reg);
reg &= ~PLL_BASE_BYPASS;
WR4(sc, sc->base_reg, reg);
*fout = ((fin / m) * n) / p;
return (0);
}

View File

@ -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);

View File

@ -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,