svn commit: r297576 - head/sys/arm/nvidia/tegra124
Michal Meloun
mmel at FreeBSD.org
Tue Apr 5 09:20:54 UTC 2016
Author: mmel
Date: Tue Apr 5 09:20:52 2016
New Revision: 297576
URL: https://svnweb.freebsd.org/changeset/base/297576
Log:
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.
Modified:
head/sys/arm/nvidia/tegra124/tegra124_clk_pll.c
head/sys/arm/nvidia/tegra124/tegra124_clk_super.c
head/sys/arm/nvidia/tegra124/tegra124_cpufreq.c
Modified: head/sys/arm/nvidia/tegra124/tegra124_clk_pll.c
==============================================================================
--- head/sys/arm/nvidia/tegra124/tegra124_clk_pll.c Tue Apr 5 08:37:21 2016 (r297575)
+++ head/sys/arm/nvidia/tegra124/tegra124_clk_pll.c Tue Apr 5 09:20:52 2016 (r297576)
@@ -823,12 +823,10 @@ pllx_set_freq(struct pll_sc *sc, uint64_
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_
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_
}
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);
}
Modified: head/sys/arm/nvidia/tegra124/tegra124_clk_super.c
==============================================================================
--- head/sys/arm/nvidia/tegra124/tegra124_clk_super.c Tue Apr 5 08:37:21 2016 (r297575)
+++ head/sys/arm/nvidia/tegra124/tegra124_clk_super.c Tue Apr 5 09:20:52 2016 (r297576)
@@ -205,8 +205,7 @@ super_mux_set_mux(struct clknode *clk, i
(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, i
}
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);
Modified: head/sys/arm/nvidia/tegra124/tegra124_cpufreq.c
==============================================================================
--- head/sys/arm/nvidia/tegra124/tegra124_cpufreq.c Tue Apr 5 08:37:21 2016 (r297575)
+++ head/sys/arm/nvidia/tegra124/tegra124_cpufreq.c Tue Apr 5 09:20:52 2016 (r297576)
@@ -335,12 +335,27 @@ set_cpu_freq(struct tegra124_cpufreq_sof
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,
More information about the svn-src-head
mailing list