Message ID | 1584387649-20959-3-git-send-email-twarren@nvidia.com |
---|---|
State | Accepted |
Commit | d491dc09e4cfb7e513d3d6f448d811f1297753d9 |
Headers | show |
Series | Misc fixes for Tegra | expand |
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?
-----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. -----------------------------------------------------------------------------------
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. -----------------------------------------------------------------------------------
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 --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) +{ +}