Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 5 Apr 2016 09:20:52 +0000 (UTC)
From:      Michal Meloun <mmel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r297576 - head/sys/arm/nvidia/tegra124
Message-ID:  <201604050920.u359Kqr6033809@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
-	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_
 	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_
 	}
 	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);
 }

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,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604050920.u359Kqr6033809>