ARM: tegra: Implement tegra_plle_enable()

This function is required by PCIe and SATA. This patch implements it on
Tegra20, Tegra30 and Tegra124. It isn't implemented for Tegra114 because
it doesn't support PCIe or SATA.

Acked-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Tom Warren <twarren@nvidia.com>
master
Thierry Reding 10 years ago committed by Tom Warren
parent 6173c45b21
commit a723074550
  1. 109
      arch/arm/cpu/tegra124-common/clock.c
  2. 137
      arch/arm/cpu/tegra20-common/clock.c
  3. 154
      arch/arm/cpu/tegra30-common/clock.c
  4. 2
      arch/arm/include/asm/arch-tegra124/clock.h
  5. 2
      arch/arm/include/asm/arch-tegra20/clock.h
  6. 2
      arch/arm/include/asm/arch-tegra30/clock.h

@ -824,3 +824,112 @@ void arch_timer_init(void)
writel(val, &sysctr->cntcr);
debug("%s: TSC CNTCR = 0x%08X\n", __func__, val);
}
#define PLLE_SS_CNTL 0x68
#define PLLE_SS_CNTL_SSCINCINTR(x) (((x) & 0x3f) << 24)
#define PLLE_SS_CNTL_SSCINC(x) (((x) & 0xff) << 16)
#define PLLE_SS_CNTL_SSCINVERT (1 << 15)
#define PLLE_SS_CNTL_SSCCENTER (1 << 14)
#define PLLE_SS_CNTL_SSCBYP (1 << 12)
#define PLLE_SS_CNTL_INTERP_RESET (1 << 11)
#define PLLE_SS_CNTL_BYPASS_SS (1 << 10)
#define PLLE_SS_CNTL_SSCMAX(x) (((x) & 0x1ff) << 0)
#define PLLE_BASE 0x0e8
#define PLLE_BASE_ENABLE (1 << 30)
#define PLLE_BASE_LOCK_OVERRIDE (1 << 29)
#define PLLE_BASE_PLDIV_CML(x) (((x) & 0xf) << 24)
#define PLLE_BASE_NDIV(x) (((x) & 0xff) << 8)
#define PLLE_BASE_MDIV(x) (((x) & 0xff) << 0)
#define PLLE_MISC 0x0ec
#define PLLE_MISC_IDDQ_SWCTL (1 << 14)
#define PLLE_MISC_IDDQ_OVERRIDE (1 << 13)
#define PLLE_MISC_LOCK_ENABLE (1 << 9)
#define PLLE_MISC_PTS (1 << 8)
#define PLLE_MISC_VREG_BG_CTRL(x) (((x) & 0x3) << 4)
#define PLLE_MISC_VREG_CTRL(x) (((x) & 0x3) << 2)
#define PLLE_AUX 0x48c
#define PLLE_AUX_SEQ_ENABLE (1 << 24)
#define PLLE_AUX_ENABLE_SWCTL (1 << 4)
int tegra_plle_enable(void)
{
unsigned int m = 1, n = 200, cpcon = 13;
u32 value;
value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
value &= ~PLLE_BASE_LOCK_OVERRIDE;
writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
value = readl(NV_PA_CLK_RST_BASE + PLLE_AUX);
value |= PLLE_AUX_ENABLE_SWCTL;
value &= ~PLLE_AUX_SEQ_ENABLE;
writel(value, NV_PA_CLK_RST_BASE + PLLE_AUX);
udelay(1);
value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
value |= PLLE_MISC_IDDQ_SWCTL;
value &= ~PLLE_MISC_IDDQ_OVERRIDE;
value |= PLLE_MISC_LOCK_ENABLE;
value |= PLLE_MISC_PTS;
value |= PLLE_MISC_VREG_BG_CTRL(3);
value |= PLLE_MISC_VREG_CTRL(2);
writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
udelay(5);
value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
value |= PLLE_SS_CNTL_SSCBYP | PLLE_SS_CNTL_INTERP_RESET |
PLLE_SS_CNTL_BYPASS_SS;
writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
value &= ~PLLE_BASE_PLDIV_CML(0xf);
value &= ~PLLE_BASE_NDIV(0xff);
value &= ~PLLE_BASE_MDIV(0xff);
value |= PLLE_BASE_PLDIV_CML(cpcon);
value |= PLLE_BASE_NDIV(n);
value |= PLLE_BASE_MDIV(m);
writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
udelay(1);
value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
value |= PLLE_BASE_ENABLE;
writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
/* wait for lock */
udelay(300);
value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
value &= ~PLLE_SS_CNTL_SSCINVERT;
value &= ~PLLE_SS_CNTL_SSCCENTER;
value &= ~PLLE_SS_CNTL_SSCINCINTR(0x3f);
value &= ~PLLE_SS_CNTL_SSCINC(0xff);
value &= ~PLLE_SS_CNTL_SSCMAX(0x1ff);
value |= PLLE_SS_CNTL_SSCINCINTR(0x20);
value |= PLLE_SS_CNTL_SSCINC(0x01);
value |= PLLE_SS_CNTL_SSCMAX(0x25);
writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
value &= ~PLLE_SS_CNTL_SSCBYP;
value &= ~PLLE_SS_CNTL_BYPASS_SS;
writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
udelay(1);
value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
value &= ~PLLE_SS_CNTL_INTERP_RESET;
writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
udelay(1);
return 0;
}

@ -7,6 +7,7 @@
/* Tegra20 Clock control functions */
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/tegra.h>
@ -548,3 +549,139 @@ void clock_early_init(void)
void arch_timer_init(void)
{
}
#define PMC_SATA_PWRGT 0x1ac
#define PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE (1 << 5)
#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL (1 << 4)
#define PLLE_SS_CNTL 0x68
#define PLLE_SS_CNTL_SSCINCINTRV(x) (((x) & 0x3f) << 24)
#define PLLE_SS_CNTL_SSCINC(x) (((x) & 0xff) << 16)
#define PLLE_SS_CNTL_SSCBYP (1 << 12)
#define PLLE_SS_CNTL_INTERP_RESET (1 << 11)
#define PLLE_SS_CNTL_BYPASS_SS (1 << 10)
#define PLLE_SS_CNTL_SSCMAX(x) (((x) & 0x1ff) << 0)
#define PLLE_BASE 0x0e8
#define PLLE_BASE_ENABLE_CML (1 << 31)
#define PLLE_BASE_ENABLE (1 << 30)
#define PLLE_BASE_PLDIV_CML(x) (((x) & 0xf) << 24)
#define PLLE_BASE_PLDIV(x) (((x) & 0x3f) << 16)
#define PLLE_BASE_NDIV(x) (((x) & 0xff) << 8)
#define PLLE_BASE_MDIV(x) (((x) & 0xff) << 0)
#define PLLE_MISC 0x0ec
#define PLLE_MISC_SETUP_BASE(x) (((x) & 0xffff) << 16)
#define PLLE_MISC_PLL_READY (1 << 15)
#define PLLE_MISC_LOCK (1 << 11)
#define PLLE_MISC_LOCK_ENABLE (1 << 9)
#define PLLE_MISC_SETUP_EXT(x) (((x) & 0x3) << 2)
static int tegra_plle_train(void)
{
unsigned int timeout = 2000;
unsigned long value;
value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
value |= PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE;
writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
value |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL;
writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
value &= ~PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE;
writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
do {
value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
if (value & PLLE_MISC_PLL_READY)
break;
udelay(100);
} while (--timeout);
if (timeout == 0) {
error("timeout waiting for PLLE to become ready");
return -ETIMEDOUT;
}
return 0;
}
int tegra_plle_enable(void)
{
unsigned int timeout = 1000;
u32 value;
int err;
/* disable PLLE clock */
value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
value &= ~PLLE_BASE_ENABLE_CML;
value &= ~PLLE_BASE_ENABLE;
writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
/* clear lock enable and setup field */
value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
value &= ~PLLE_MISC_LOCK_ENABLE;
value &= ~PLLE_MISC_SETUP_BASE(0xffff);
value &= ~PLLE_MISC_SETUP_EXT(0x3);
writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
if ((value & PLLE_MISC_PLL_READY) == 0) {
err = tegra_plle_train();
if (err < 0) {
error("failed to train PLLE: %d", err);
return err;
}
}
value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
value |= PLLE_MISC_SETUP_BASE(0x7);
value |= PLLE_MISC_LOCK_ENABLE;
value |= PLLE_MISC_SETUP_EXT(0);
writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
value |= PLLE_SS_CNTL_SSCBYP | PLLE_SS_CNTL_INTERP_RESET |
PLLE_SS_CNTL_BYPASS_SS;
writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
value |= PLLE_BASE_ENABLE_CML | PLLE_BASE_ENABLE;
writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
do {
value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
if (value & PLLE_MISC_LOCK)
break;
udelay(2);
} while (--timeout);
if (timeout == 0) {
error("timeout waiting for PLLE to lock");
return -ETIMEDOUT;
}
udelay(50);
value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
value &= ~PLLE_SS_CNTL_SSCINCINTRV(0x3f);
value |= PLLE_SS_CNTL_SSCINCINTRV(0x18);
value &= ~PLLE_SS_CNTL_SSCINC(0xff);
value |= PLLE_SS_CNTL_SSCINC(0x01);
value &= ~PLLE_SS_CNTL_SSCBYP;
value &= ~PLLE_SS_CNTL_INTERP_RESET;
value &= ~PLLE_SS_CNTL_BYPASS_SS;
value &= ~PLLE_SS_CNTL_SSCMAX(0x1ff);
value |= PLLE_SS_CNTL_SSCMAX(0x24);
writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
return 0;
}

@ -17,6 +17,7 @@
/* Tegra30 Clock control functions */
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/tegra.h>
@ -587,3 +588,156 @@ void clock_early_init(void)
void arch_timer_init(void)
{
}
#define PMC_SATA_PWRGT 0x1ac
#define PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE (1 << 5)
#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL (1 << 4)
#define PLLE_SS_CNTL 0x68
#define PLLE_SS_CNTL_SSCINCINTRV(x) (((x) & 0x3f) << 24)
#define PLLE_SS_CNTL_SSCINC(x) (((x) & 0xff) << 16)
#define PLLE_SS_CNTL_SSCBYP (1 << 12)
#define PLLE_SS_CNTL_INTERP_RESET (1 << 11)
#define PLLE_SS_CNTL_BYPASS_SS (1 << 10)
#define PLLE_SS_CNTL_SSCMAX(x) (((x) & 0x1ff) << 0)
#define PLLE_BASE 0x0e8
#define PLLE_BASE_ENABLE_CML (1 << 31)
#define PLLE_BASE_ENABLE (1 << 30)
#define PLLE_BASE_PLDIV_CML(x) (((x) & 0xf) << 24)
#define PLLE_BASE_PLDIV(x) (((x) & 0x3f) << 16)
#define PLLE_BASE_NDIV(x) (((x) & 0xff) << 8)
#define PLLE_BASE_MDIV(x) (((x) & 0xff) << 0)
#define PLLE_MISC 0x0ec
#define PLLE_MISC_SETUP_BASE(x) (((x) & 0xffff) << 16)
#define PLLE_MISC_PLL_READY (1 << 15)
#define PLLE_MISC_LOCK (1 << 11)
#define PLLE_MISC_LOCK_ENABLE (1 << 9)
#define PLLE_MISC_SETUP_EXT(x) (((x) & 0x3) << 2)
static int tegra_plle_train(void)
{
unsigned int timeout = 2000;
unsigned long value;
value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
value |= PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE;
writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
value |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL;
writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
value &= ~PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE;
writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
do {
value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
if (value & PLLE_MISC_PLL_READY)
break;
udelay(100);
} while (--timeout);
if (timeout == 0) {
error("timeout waiting for PLLE to become ready");
return -ETIMEDOUT;
}
return 0;
}
int tegra_plle_enable(void)
{
unsigned int cpcon = 11, p = 18, n = 150, m = 1, timeout = 1000;
u32 value;
int err;
/* disable PLLE clock */
value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
value &= ~PLLE_BASE_ENABLE_CML;
value &= ~PLLE_BASE_ENABLE;
writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
/* clear lock enable and setup field */
value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
value &= ~PLLE_MISC_LOCK_ENABLE;
value &= ~PLLE_MISC_SETUP_BASE(0xffff);
value &= ~PLLE_MISC_SETUP_EXT(0x3);
writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
if ((value & PLLE_MISC_PLL_READY) == 0) {
err = tegra_plle_train();
if (err < 0) {
error("failed to train PLLE: %d", err);
return err;
}
}
/* configure PLLE */
value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
value &= ~PLLE_BASE_PLDIV_CML(0x0f);
value |= PLLE_BASE_PLDIV_CML(cpcon);
value &= ~PLLE_BASE_PLDIV(0x3f);
value |= PLLE_BASE_PLDIV(p);
value &= ~PLLE_BASE_NDIV(0xff);
value |= PLLE_BASE_NDIV(n);
value &= ~PLLE_BASE_MDIV(0xff);
value |= PLLE_BASE_MDIV(m);
writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
value |= PLLE_MISC_SETUP_BASE(0x7);
value |= PLLE_MISC_LOCK_ENABLE;
value |= PLLE_MISC_SETUP_EXT(0);
writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
value |= PLLE_SS_CNTL_SSCBYP | PLLE_SS_CNTL_INTERP_RESET |
PLLE_SS_CNTL_BYPASS_SS;
writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
value |= PLLE_BASE_ENABLE_CML | PLLE_BASE_ENABLE;
writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
do {
value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
if (value & PLLE_MISC_LOCK)
break;
udelay(2);
} while (--timeout);
if (timeout == 0) {
error("timeout waiting for PLLE to lock");
return -ETIMEDOUT;
}
udelay(50);
value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
value &= ~PLLE_SS_CNTL_SSCINCINTRV(0x3f);
value |= PLLE_SS_CNTL_SSCINCINTRV(0x18);
value &= ~PLLE_SS_CNTL_SSCINC(0xff);
value |= PLLE_SS_CNTL_SSCINC(0x01);
value &= ~PLLE_SS_CNTL_SSCBYP;
value &= ~PLLE_SS_CNTL_INTERP_RESET;
value &= ~PLLE_SS_CNTL_BYPASS_SS;
value &= ~PLLE_SS_CNTL_SSCMAX(0x1ff);
value |= PLLE_SS_CNTL_SSCMAX(0x24);
writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
return 0;
}

@ -16,4 +16,6 @@
#define OSC_FREQ_SHIFT 28
#define OSC_FREQ_MASK (0xF << OSC_FREQ_SHIFT)
int tegra_plle_enable(void);
#endif /* _TEGRA124_CLOCK_H_ */

@ -15,4 +15,6 @@
#define OSC_FREQ_SHIFT 30
#define OSC_FREQ_MASK (3U << OSC_FREQ_SHIFT)
int tegra_plle_enable(void);
#endif /* _TEGRA20_CLOCK_H */

@ -25,4 +25,6 @@
#define OSC_FREQ_SHIFT 28
#define OSC_FREQ_MASK (0xF << OSC_FREQ_SHIFT)
int tegra_plle_enable(void);
#endif /* _TEGRA30_CLOCK_H_ */

Loading…
Cancel
Save