Skip to contentSkip to conversation

ARM: tegra: don't exceed AVP limits when configuring PLLP

PATCH Superseded Stephen Warren 2 participants 3 messages Jan 23, 2014 – Jan 24, 2014

Subsystems (2)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 ARM: tegra: don't exceed AVP limits when configuring PLLP

From: Jimmy Zhang <[email protected]>

Based on the Tegra TRM, the system clock (which is the AVP clock) can run up to 275MHz. On power on, the default sytem clock source is set to PLLP_OUT0. In function clock_early_init(), PLLP_OUT0 will be set to 408MHz which is beyond system clock's upper limit.

The fix is to set the system clock to CLK_M before initializing PLLP, and then switch back to PLLP_OUT4, which has an appropriate divider configured, after PLLP has been configured

Implement this logic in new function tegra30_or_later_adjust_pllp(), which sets up PLLP and all PLLP_OUT* dividers, and handles the AVP clock switching. Remove the duplicate PLLP setup from pllx_set_rate() and adjust_pllp_out_freqs().

[swarren, significantly refactored the change]

---
v2:
* Remove duplicate adjustment of PLLP dividers from pllx_set_rate()
* Adjust PLLP_OUT1/PLLP_OUT2 dividers from clock_early_init() so that everything related to PLLP is set up at once.
* Initialize PLLP from a new common function tegra30_or_later_adjust_pllp() so the code isn't duplicated.

---
 arch/arm/cpu/arm720t/tegra-common/cpu.c   | 26 +--------
 arch/arm/cpu/arm720t/tegra114/cpu.c       | 14 +----
 arch/arm/cpu/arm720t/tegra30/cpu.c        | 14 +----
 arch/arm/cpu/tegra-common/clock.c         | 90 ++++++++++++++++++++++++++++++-
 arch/arm/cpu/tegra114-common/clock.c      |  8 ++-
 arch/arm/cpu/tegra30-common/clock.c       | 31 +----------
 arch/arm/include/asm/arch-tegra/clk_rst.h | 16 +++++-
 arch/arm/include/asm/arch-tegra/clock.h   |  2 +
 8 files changed, 114 insertions(+), 87 deletions(-)
arch/arm/cpu/arm720t/tegra-common/cpu.c +1 -25
index 72c69b914c7f..03f67b163cc5 100644
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2014, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -114,24 +114,6 @@ struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_CNT][CLOCK_OSC_FREQ_COUNT] = {
 	},
 };
 
-void adjust_pllp_out_freqs(void)
-{
-	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-	struct clk_pll *pll = &clkrst->crc_pll[CLOCK_ID_PERIPH];
-	u32 reg;
-
-	/* Set T30 PLLP_OUT1, 2, 3 & 4 freqs to 9.6, 48, 102 & 204MHz */
-	reg = readl(&pll->pll_out[0]);	/* OUTA, contains OUT2 / OUT1 */
-	reg |= (IN_408_OUT_48_DIVISOR << PLLP_OUT2_RATIO) | PLLP_OUT2_OVR
-		| (IN_408_OUT_9_6_DIVISOR << PLLP_OUT1_RATIO) | PLLP_OUT1_OVR;
-	writel(reg, &pll->pll_out[0]);
-
-	reg = readl(&pll->pll_out[1]);   /* OUTB, contains OUT4 / OUT3 */
-	reg |= (IN_408_OUT_204_DIVISOR << PLLP_OUT4_RATIO) | PLLP_OUT4_OVR
-		| (IN_408_OUT_102_DIVISOR << PLLP_OUT3_RATIO) | PLLP_OUT3_OVR;
-	writel(reg, &pll->pll_out[1]);
-}
-
 int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm,
 		u32 divp, u32 cpcon)
 {
@@ -207,12 +189,6 @@ void init_pllx(void)
 	/* set pllx */
 	sel = &tegra_pll_x_table[chip_sku][osc];
 	pllx_set_rate(pll, sel->n, sel->m, sel->p, sel->cpcon);
-
-	/* adjust PLLP_out1-4 on T3x/T114 */
-	if (soc_type >= CHIPID_TEGRA30) {
-		debug("  init_pllx: adjusting PLLP out freqs\n");
-		adjust_pllp_out_freqs();
-	}
 }
 
 void enable_cpu_clock(int enable)
arch/arm/cpu/arm720t/tegra114/cpu.c +1 -13
index 7a1747a3beb8..385e1a1c86e0 100644
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2014, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -126,18 +126,6 @@ void t114_init_clocks(void)
 	/* Set active CPU cluster to G */
 	clrbits_le32(&flow->cluster_control, 1);
 
-	/*
-	 * Switch system clock to PLLP_OUT4 (108 MHz), AVP will now run
-	 * at 108 MHz. This is glitch free as only the source is changed, no
-	 * special precaution needed.
-	 */
-	val = (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT) |
-		(SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IRQ_SOURCE_SHIFT) |
-		(SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_RUN_SOURCE_SHIFT) |
-		(SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IDLE_SOURCE_SHIFT) |
-		(SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT);
-	writel(val, &clkrst->crc_sclk_brst_pol);
-
 	writel(SUPER_SCLK_ENB_MASK, &clkrst->crc_super_sclk_div);
 
 	debug("Setting up PLLX\n");
arch/arm/cpu/arm720t/tegra30/cpu.c +1 -13
index e16235748449..a80648389c7c 100644
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2014, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -84,18 +84,6 @@ void t30_init_clocks(void)
 	/* Set active CPU cluster to G */
 	clrbits_le32(flow->cluster_control, 1 << 0);
 
-	/*
-	 * Switch system clock to PLLP_OUT4 (108 MHz), AVP will now run
-	 *@108 MHz. This is glitch free as only the source is changed, no
-	 * special precaution needed.
-	 */
-	val = (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT) |
-		(SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IRQ_SOURCE_SHIFT) |
-		(SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_RUN_SOURCE_SHIFT) |
-		(SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IDLE_SOURCE_SHIFT) |
-		(SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT);
-	writel(val, &clkrst->crc_sclk_brst_pol);
-
 	writel(SUPER_SCLK_ENB_MASK, &clkrst->crc_super_sclk_div);
 
 	val = (0 << CLK_SYS_RATE_HCLK_DISABLE_SHIFT) |
arch/arm/cpu/tegra-common/clock.c +89 -1

97 lines not on this page · raw message

arch/arm/cpu/tegra114-common/clock.c +3 -5
index 3bede71a7a1f..8bc6e816cf95 100644
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2014, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -604,26 +604,24 @@ void clock_early_init(void)
 	struct clk_rst_ctlr *clkrst =
 		(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
 
+	tegra30_or_later_adjust_pllp();
+
 	/*
-	 * PLLP output frequency set to 408Mhz
 	 * PLLC output frequency set to 600Mhz
 	 * PLLD output frequency set to 925Mhz
 	 */
 	switch (clock_get_osc_freq()) {
 	case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
-		clock_set_rate(CLOCK_ID_PERIPH, 408, 12, 0, 8);
 		clock_set_rate(CLOCK_ID_CGENERAL, 600, 12, 0, 8);
 		clock_set_rate(CLOCK_ID_DISPLAY, 925, 12, 0, 12);
 		break;
 
 	case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */
-		clock_set_rate(CLOCK_ID_PERIPH, 408, 26, 0, 8);
 		clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8);
 		clock_set_rate(CLOCK_ID_DISPLAY, 925, 26, 0, 12);
 		break;
 
 	case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */
-		clock_set_rate(CLOCK_ID_PERIPH, 408, 13, 0, 8);
 		clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8);
 		clock_set_rate(CLOCK_ID_DISPLAY, 925, 13, 0, 12);
 		break;
arch/arm/cpu/tegra30-common/clock.c +2 -29
index 33528702185e..60b99347d1c0 100644
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2014, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -581,34 +581,7 @@ enum periph_id clk_id_to_periph_id(int clk_id)
 
 void clock_early_init(void)
 {
-	/*
-	 * PLLP output frequency set to 408Mhz
-	 * PLLC output frequency set to 228Mhz
-	 */
-	switch (clock_get_osc_freq()) {
-	case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
-		clock_set_rate(CLOCK_ID_PERIPH, 408, 12, 0, 8);
-		clock_set_rate(CLOCK_ID_CGENERAL, 456, 12, 1, 8);
-		break;
-
-	case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */
-		clock_set_rate(CLOCK_ID_PERIPH, 408, 26, 0, 8);
-		clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8);
-		break;
-
-	case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */
-		clock_set_rate(CLOCK_ID_PERIPH, 408, 13, 0, 8);
-		clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8);
-		break;
-	case CLOCK_OSC_FREQ_19_2:
-	default:
-		/*
-		 * These are not supported. It is too early to print a
-		 * message and the UART likely won't work anyway due to the
-		 * oscillator being wrong.
-		 */
-		break;
-	}
+	tegra30_or_later_adjust_pllp();
 }
 
 void arch_timer_init(void)
arch/arm/include/asm/arch-tegra/clk_rst.h +15 -1
index f07b83d26af4..021cfcc3c602 100644
@@ -1,5 +1,5 @@
 /*
- *  (C) Copyright 2010,2011
+ *  (C) Copyright 2010-2014
  *  NVIDIA Corporation <www.nvidia.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
@@ -209,6 +209,20 @@ enum {
 	IN_408_OUT_9_6_DIVISOR = 83,
 };
 
+#define PLLP_OUT1_RSTN_DIS	(1 << 0)
+#define PLLP_OUT1_RSTN_EN	(0 << 0)
+#define PLLP_OUT1_CLKEN		(1 << 1)
+#define PLLP_OUT2_RSTN_DIS	(1 << 16)
+#define PLLP_OUT2_RSTN_EN	(0 << 16)
+#define PLLP_OUT2_CLKEN		(1 << 17)
+
+#define PLLP_OUT3_RSTN_DIS	(1 << 0)
+#define PLLP_OUT3_RSTN_EN	(0 << 0)
+#define PLLP_OUT3_CLKEN		(1 << 1)
+#define PLLP_OUT4_RSTN_DIS	(1 << 16)
+#define PLLP_OUT4_RSTN_EN	(0 << 16)
+#define PLLP_OUT4_CLKEN		(1 << 17)
+
 /* CLK_RST_CONTROLLER_UTMIP_PLL_CFG1_0 */
 #define PLLU_POWERDOWN		(1 << 16)
 #define PLL_ENABLE_POWERDOWN	(1 << 14)
arch/arm/include/asm/arch-tegra/clock.h +2 -0
index 357d9c592b55..6c2fc7851198 100644
@@ -320,4 +320,6 @@ int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon);
 /* SoC-specific TSC init */
 void arch_timer_init(void);
 
+void tegra30_or_later_adjust_pllp(void);
+
 #endif  /* _TEGRA_CLOCK_H_ */
Signature · 1 line
1.8.1.5
#1 lore raw

PATCH v2 1/1 ARM: tegra: don't exceed AVP limits when configuring PLLP

On Thu, Jan 23, 2014 at 11:58:13AM -0700, Stephen Warren wrote:
[...]

Quoted 1 line
arch/arm/cpu/tegra-common/clock.c +0 -0

[...]

arch/arm/cpu/tegra-common/clock.c void clock_init(void) · line 579

Quoted 6 lines
arch/arm/cpu/tegra-common/clock.c +2 -0
@@ -575,3 +575,91 @@ void clock_init(void)
 	/* Do any special system timer/TSC setup */
 	arch_timer_init();
 }
+
+static void set_avp_clock_to(u32 src)

Perhaps a better name would be "set_avp_clock_source()"? _to had me confused at first because I assumed it would be setting a frequency.

arch/arm/cpu/tegra-common/clock.c void clock_init(void) · line 594

Quoted 1 line
arch/arm/cpu/tegra-common/clock.c +1 -0
+void tegra30_or_later_adjust_pllp(void)

I would've called this simply tegra30_adjust_pllp(), where it's implied that when you call tegra30_*() from code targetted at later generations these would be compatible with Tegra30.

But if you'd rather make it implicit that's fine too.

Either way:

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140124/903f6173/attachment.pgp>

#2 lore raw

PATCH v2 1/1 ARM: tegra: don't exceed AVP limits when configuring PLLP

Quoted 4 lines · Thierry Reding

On Thu, Jan 23, 2014 at 11:58:13AM -0700, Stephen Warren wrote:
[...]

Quoted 1 line
arch/arm/cpu/tegra-common/clock.c +0 -0

[...]

Quoted 9 lines

arch/arm/cpu/tegra-common/clock.c void clock_init(void) · line 579

Quoted 6 lines
arch/arm/cpu/tegra-common/clock.c +2 -0
@@ -575,3 +575,91 @@ void clock_init(void)
 	/* Do any special system timer/TSC setup */
 	arch_timer_init();
 }
+
+static void set_avp_clock_to(u32 src)

Perhaps a better name would be "set_avp_clock_source()"? _to had me confused at first because I assumed it would be setting a frequency.

Yes, that name is better.

Quoted 7 lines

arch/arm/cpu/tegra-common/clock.c void clock_init(void) · line 594

Quoted 1 line
arch/arm/cpu/tegra-common/clock.c +1 -0
+void tegra30_or_later_adjust_pllp(void)

I would've called this simply tegra30_adjust_pllp(), where it's implied that when you call tegra30_*() from code targetted at later generations these would be compatible with Tegra30.

But if you'd rather make it implicit that's fine too.

I wondered about that, and thought it'd be odd for e.g. Tegra114 clock code to be calling Tegra30 functions. That said, if we start encoding into function names a complete description of which chips they support, we'll have very long function names, so I guess renaming it makes sense. I'll post V3.