diff mbox series

[2/5] t210: do not enable PLLE and UPHY PLL HW PWRSEQ

Message ID 1584387649-20959-3-git-send-email-twarren@nvidia.com
State Accepted
Commit d491dc09e4cfb7e513d3d6f448d811f1297753d9
Headers show
Series Misc fixes for Tegra | expand

Commit Message

Tom Warren March 16, 2020, 7:40 p.m. UTC
From: JC Kuo <jckuo at nvidia.com>

This commit removes the programming sequence that enables PLLE and UPHY
PLL hardware power sequencers. Per TRM, boot software should enable PLLE
and UPHY PLLs in software controlled power-on state and should power
down PLL before jumping into kernel or the next stage boot software.

Adds call to board_cleanup_before_linux to facilitate this.

Signed-off-by: JC Kuo <jckuo at nvidia.com>
Signed-off-by: Tom Warren <twarren at nvidia.com>
---
 arch/arm/cpu/armv8/cpu.c                      |  5 ++
 arch/arm/include/asm/arch-tegra/xusb-padctl.h |  1 +
 arch/arm/mach-tegra/board2.c                  |  6 +++
 arch/arm/mach-tegra/tegra210/clock.c          | 19 --------
 arch/arm/mach-tegra/tegra210/xusb-padctl.c    | 68 +++++++++++++++++----------
 arch/arm/mach-tegra/xusb-padctl-dummy.c       |  4 ++
 6 files changed, 59 insertions(+), 44 deletions(-)

Comments

Stephen Warren March 17, 2020, 5:29 p.m. UTC | #1
On 3/16/20 1:40 PM, twarren at nvidia.com wrote:
> From: JC Kuo <jckuo at nvidia.com>
> 
> This commit removes the programming sequence that enables PLLE and UPHY
> PLL hardware power sequencers. Per TRM, boot software should enable PLLE
> and UPHY PLLs in software controlled power-on state and should power
> down PLL before jumping into kernel or the next stage boot software.
> 
> Adds call to board_cleanup_before_linux to facilitate this.

This directly contradicts what's in Tegra_X1_TRM_DP07225001_v1.3p.pdf,
pages 1340/1341, which is what the code currently implements. Was a
newer internal-only TRM published that changed the recommended
programming flow?
Tom Warren March 17, 2020, 5:44 p.m. UTC | #2
-----Original Message-----
From: Stephen Warren <swarren at wwwdotorg.org> 
Sent: Tuesday, March 17, 2020 10:30 AM
To: Tom Warren <TWarren at nvidia.com>
Cc: u-boot at lists.denx.de; Jui Chang Kuo <jckuo at nvidia.com>
Subject: Re: [PATCH 2/5] t210: do not enable PLLE and UPHY PLL HW PWRSEQ

External email: Use caution opening links or attachments


On 3/16/20 1:40 PM, twarren at nvidia.com wrote:
> From: JC Kuo <jckuo at nvidia.com>
>
> This commit removes the programming sequence that enables PLLE and 
> UPHY PLL hardware power sequencers. Per TRM, boot software should 
> enable PLLE and UPHY PLLs in software controlled power-on state and 
> should power down PLL before jumping into kernel or the next stage boot software.
>
> Adds call to board_cleanup_before_linux to facilitate this.

This directly contradicts what's in Tegra_X1_TRM_DP07225001_v1.3p.pdf,
pages 1340/1341, which is what the code currently implements. Was a newer internal-only TRM published that changed the recommended programming flow?
[Tom] JC wrote this, I'll let him answer, but I'll check my TRM to see what the most recent version is. This code is exactly what we have in downstream T210 U-Boot.


-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------
JC Kuo March 18, 2020, 1:44 a.m. UTC | #3
Please refer to "Notes" section in p1337 of Tegra_X1_TRM_DP07225001_v1.3p.pdf.
There are some implementation considerations for boot software.

Thanks,
JC

On 3/18/20 1:44 AM, Tom Warren wrote:
> -----Original Message-----
> From: Stephen Warren <swarren at wwwdotorg.org> 
> Sent: Tuesday, March 17, 2020 10:30 AM
> To: Tom Warren <TWarren at nvidia.com>
> Cc: u-boot at lists.denx.de; Jui Chang Kuo <jckuo at nvidia.com>
> Subject: Re: [PATCH 2/5] t210: do not enable PLLE and UPHY PLL HW PWRSEQ
> 
> External email: Use caution opening links or attachments
> 
> 
> On 3/16/20 1:40 PM, twarren at nvidia.com wrote:
>> From: JC Kuo <jckuo at nvidia.com>
>>
>> This commit removes the programming sequence that enables PLLE and 
>> UPHY PLL hardware power sequencers. Per TRM, boot software should 
>> enable PLLE and UPHY PLLs in software controlled power-on state and 
>> should power down PLL before jumping into kernel or the next stage boot software.
>>
>> Adds call to board_cleanup_before_linux to facilitate this.
> 
> This directly contradicts what's in Tegra_X1_TRM_DP07225001_v1.3p.pdf,
> pages 1340/1341, which is what the code currently implements. Was a newer internal-only TRM published that changed the recommended programming flow?
> [Tom] JC wrote this, I'll let him answer, but I'll check my TRM to see what the most recent version is. This code is exactly what we have in downstream T210 U-Boot.
> 

-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------
Stephen Warren March 18, 2020, 11:25 p.m. UTC | #4
On 3/17/20 7:44 PM, JC Kuo wrote:
> Please refer to "Notes" section in p1337 of Tegra_X1_TRM_DP07225001_v1.3p.pdf.
> There are some implementation considerations for boot software.

OK, I assume you mean this note:

Boot loader should not enable hardware power sequencer. Boot loader
should enable the required PLLs in software controlled state.

That's interesting, since I explicitly added the code to program PLLE in
HW controlled mode after discussing with the relevant HW engineers the
need to clean up the programming sequence in the following pages, and it
was clearly communicated that this was in the context of a bootloader,
and they pointed out that the bootloader needed to enable HW control but
didn't. Sigh. I guess I should have read the sections prior to the
programming sequence too.

So I guess this change is OK, and since we have it downstream it seems
to operate OK in practice too.

Acked-by: Stephen Warren <swarren at nvidia.com>

> Thanks,
> JC
> 
> On 3/18/20 1:44 AM, Tom Warren wrote:
>> -----Original Message-----
>> From: Stephen Warren <swarren at wwwdotorg.org> 
>> Sent: Tuesday, March 17, 2020 10:30 AM
>> To: Tom Warren <TWarren at nvidia.com>
>> Cc: u-boot at lists.denx.de; Jui Chang Kuo <jckuo at nvidia.com>
>> Subject: Re: [PATCH 2/5] t210: do not enable PLLE and UPHY PLL HW PWRSEQ
>>
>> External email: Use caution opening links or attachments
>>
>>
>> On 3/16/20 1:40 PM, twarren at nvidia.com wrote:
>>> From: JC Kuo <jckuo at nvidia.com>
>>>
>>> This commit removes the programming sequence that enables PLLE and 
>>> UPHY PLL hardware power sequencers. Per TRM, boot software should 
>>> enable PLLE and UPHY PLLs in software controlled power-on state and 
>>> should power down PLL before jumping into kernel or the next stage boot software.
>>>
>>> Adds call to board_cleanup_before_linux to facilitate this.
>>
>> This directly contradicts what's in Tegra_X1_TRM_DP07225001_v1.3p.pdf,
>> pages 1340/1341, which is what the code currently implements. Was a newer internal-only TRM published that changed the recommended programming flow?
>> [Tom] JC wrote this, I'll let him answer, but I'll check my TRM to see what the most recent version is. This code is exactly what we have in downstream T210 U-Boot.
>>
> 
> -----------------------------------------------------------------------------------
> This email message is for the sole use of the intended recipient(s) and may contain
> confidential information.  Any unauthorized review, use, disclosure or distribution
> is prohibited.  If you are not the intended recipient, please contact the sender by
> reply email and destroy all copies of the original message.
> -----------------------------------------------------------------------------------
>
diff mbox series

Patch

diff --git a/arch/arm/cpu/armv8/cpu.c b/arch/arm/cpu/armv8/cpu.c
index 2467e0b..3575203 100644
--- a/arch/arm/cpu/armv8/cpu.c
+++ b/arch/arm/cpu/armv8/cpu.c
@@ -32,6 +32,8 @@  void sdelay(unsigned long loops)
 			  "b.ne 1b" : "=r" (loops) : "0"(loops) : "cc");
 }
 
+void __weak board_cleanup_before_linux(void){}
+
 int cleanup_before_linux(void)
 {
 	/*
@@ -40,6 +42,9 @@  int cleanup_before_linux(void)
 	 *
 	 * disable interrupt and turn off caches etc ...
 	 */
+
+	board_cleanup_before_linux();
+
 	disable_interrupts();
 
 	/*
diff --git a/arch/arm/include/asm/arch-tegra/xusb-padctl.h b/arch/arm/include/asm/arch-tegra/xusb-padctl.h
index deccdf4..7e14d81 100644
--- a/arch/arm/include/asm/arch-tegra/xusb-padctl.h
+++ b/arch/arm/include/asm/arch-tegra/xusb-padctl.h
@@ -16,6 +16,7 @@  struct tegra_xusb_phy;
 struct tegra_xusb_phy *tegra_xusb_phy_get(unsigned int type);
 
 void tegra_xusb_padctl_init(void);
+void tegra_xusb_padctl_exit(void);
 int tegra_xusb_phy_prepare(struct tegra_xusb_phy *phy);
 int tegra_xusb_phy_enable(struct tegra_xusb_phy *phy);
 int tegra_xusb_phy_disable(struct tegra_xusb_phy *phy);
diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c
index d3497a2..787ff97 100644
--- a/arch/arm/mach-tegra/board2.c
+++ b/arch/arm/mach-tegra/board2.c
@@ -181,6 +181,12 @@  int board_init(void)
 	return nvidia_board_init();
 }
 
+void board_cleanup_before_linux(void)
+{
+	/* power down UPHY PLL */
+	tegra_xusb_padctl_exit();
+}
+
 #ifdef CONFIG_BOARD_EARLY_INIT_F
 static void __gpio_early_init(void)
 {
diff --git a/arch/arm/mach-tegra/tegra210/clock.c b/arch/arm/mach-tegra/tegra210/clock.c
index b240860..f1b25e2 100644
--- a/arch/arm/mach-tegra/tegra210/clock.c
+++ b/arch/arm/mach-tegra/tegra210/clock.c
@@ -1235,25 +1235,6 @@  int tegra_plle_enable(void)
 	value &= ~PLLE_SS_CNTL_INTERP_RESET;
 	writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
 
-	/* 7. Enable HW power sequencer for PLLE */
-
-	value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
-	value &= ~PLLE_MISC_IDDQ_SWCTL;
-	writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
-
-	value = readl(NV_PA_CLK_RST_BASE + PLLE_AUX);
-	value &= ~PLLE_AUX_SS_SWCTL;
-	value &= ~PLLE_AUX_ENABLE_SWCTL;
-	value |= PLLE_AUX_SS_SEQ_INCLUDE;
-	value |= PLLE_AUX_USE_LOCKDET;
-	writel(value, NV_PA_CLK_RST_BASE + PLLE_AUX);
-
-	/* 8. Wait 1 us */
-
-	udelay(1);
-	value |= PLLE_AUX_SEQ_ENABLE;
-	writel(value, NV_PA_CLK_RST_BASE + PLLE_AUX);
-
 	return 0;
 }
 
diff --git a/arch/arm/mach-tegra/tegra210/xusb-padctl.c b/arch/arm/mach-tegra/tegra210/xusb-padctl.c
index ab6684f..64dc297 100644
--- a/arch/arm/mach-tegra/tegra210/xusb-padctl.c
+++ b/arch/arm/mach-tegra/tegra210/xusb-padctl.c
@@ -170,6 +170,17 @@  static int phy_unprepare(struct tegra_xusb_phy *phy)
 	return tegra_xusb_padctl_disable(phy->padctl);
 }
 
+#define XUSB_PADCTL_USB3_PAD_MUX 0x28
+#define  XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE (1 << 0)
+#define  XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK0 (1 << 1)
+#define  XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK1 (1 << 2)
+#define  XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK2 (1 << 3)
+#define  XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK3 (1 << 4)
+#define  XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK4 (1 << 5)
+#define  XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK5 (1 << 6)
+#define  XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK6 (1 << 7)
+#define  XUSB_PADCTL_USB3_PAD_MUX_FORCE_SATA_PAD_IDDQ_DISABLE_MASK0 (1 << 8)
+
 #define XUSB_PADCTL_UPHY_PLL_P0_CTL1 0x360
 #define  XUSB_PADCTL_UPHY_PLL_P0_CTL1_FREQ_NDIV_MASK (0xff << 20)
 #define  XUSB_PADCTL_UPHY_PLL_P0_CTL1_FREQ_NDIV(x) (((x) & 0xff) << 20)
@@ -366,31 +377,6 @@  static int pcie_phy_enable(struct tegra_xusb_phy *phy)
 	value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_CLK_EN;
 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
 
-	value = readl(NV_PA_CLK_RST_BASE + CLK_RST_XUSBIO_PLL_CFG0);
-	value &= ~CLK_RST_XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL;
-	value &= ~CLK_RST_XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL;
-	value |= CLK_RST_XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET;
-	value |= CLK_RST_XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ;
-	writel(value, NV_PA_CLK_RST_BASE + CLK_RST_XUSBIO_PLL_CFG0);
-
-	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
-	value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL1_PWR_OVRD;
-	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
-
-	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
-	value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL2_CAL_OVRD;
-	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
-
-	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
-	value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL8_RCAL_OVRD;
-	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
-
-	udelay(1);
-
-	value = readl(NV_PA_CLK_RST_BASE + CLK_RST_XUSBIO_PLL_CFG0);
-	value |= CLK_RST_XUSBIO_PLL_CFG0_SEQ_ENABLE;
-	writel(value, NV_PA_CLK_RST_BASE + CLK_RST_XUSBIO_PLL_CFG0);
-
 	debug("< %s()\n", __func__);
 	return 0;
 }
@@ -454,3 +440,35 @@  void tegra_xusb_padctl_init(void)
 	ret = tegra_xusb_process_nodes(nodes, count, &tegra210_socdata);
 	debug("%s: done, ret=%d\n", __func__, ret);
 }
+
+void tegra_xusb_padctl_exit(void)
+{
+	u32 value;
+
+	debug("> %s\n", __func__);
+
+	value = padctl_readl(&padctl, XUSB_PADCTL_USB3_PAD_MUX);
+	value &= ~XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE;
+	value &= ~XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK0;
+	value &= ~XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK1;
+	value &= ~XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK2;
+	value &= ~XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK3;
+	value &= ~XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK4;
+	value &= ~XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK5;
+	value &= ~XUSB_PADCTL_USB3_PAD_MUX_FORCE_PCIE_PAD_IDDQ_DISABLE_MASK6;
+	value &= ~XUSB_PADCTL_USB3_PAD_MUX_FORCE_SATA_PAD_IDDQ_DISABLE_MASK0;
+	padctl_writel(&padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
+
+	value = padctl_readl(&padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
+	value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL1_IDDQ;
+	value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL1_SLEEP_MASK;
+	value |= XUSB_PADCTL_UPHY_PLL_P0_CTL1_SLEEP(3);
+	value &= ~XUSB_PADCTL_UPHY_PLL_P0_CTL1_ENABLE;
+	padctl_writel(&padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
+
+	reset_set_enable(PERIPH_ID_PEX_USB_UPHY, 1);
+	while (padctl.enable)
+		tegra_xusb_padctl_disable(&padctl);
+
+	debug("< %s()\n", __func__);
+}
diff --git a/arch/arm/mach-tegra/xusb-padctl-dummy.c b/arch/arm/mach-tegra/xusb-padctl-dummy.c
index 3ec27a2..f2d9030 100644
--- a/arch/arm/mach-tegra/xusb-padctl-dummy.c
+++ b/arch/arm/mach-tegra/xusb-padctl-dummy.c
@@ -36,3 +36,7 @@  int __weak tegra_xusb_phy_unprepare(struct tegra_xusb_phy *phy)
 void __weak tegra_xusb_padctl_init(void)
 {
 }
+
+void __weak tegra_xusb_padctl_exit(void)
+{
+}