@ -8,6 +8,7 @@
/* Tegra210 Clock control functions */
# include <common.h>
# include <errno.h>
# include <asm/io.h>
# include <asm/arch/clock.h>
# include <asm/arch/sysctr.h>
@ -1030,6 +1031,59 @@ void arch_timer_init(void)
debug ( " %s: TSC CNTCR = 0x%08X \n " , __func__ , val ) ;
}
# define PLLREFE_MISC 0x4c8
# define PLLREFE_MISC_LOCK BIT(27)
# define PLLREFE_MISC_IDDQ BIT(24)
# define PLLREFE_BASE 0x4c4
# define PLLREFE_BASE_BYPASS BIT(31)
# define PLLREFE_BASE_ENABLE BIT(30)
# define PLLREFE_BASE_REF_DIS BIT(29)
# define PLLREFE_BASE_KCP(kcp) (((kcp) & 0x3) << 27)
# define PLLREFE_BASE_KVCO BIT(26)
# define PLLREFE_BASE_DIVP(p) (((p) & 0x1f) << 16)
# define PLLREFE_BASE_DIVN(n) (((n) & 0xff) << 8)
# define PLLREFE_BASE_DIVM(m) (((m) & 0xff) << 0)
static int tegra_pllref_enable ( void )
{
u32 value ;
unsigned long start ;
/*
* This sequence comes from Tegra X1 TRM section " Cold Boot, with no
* Recovery Mode or Boot from USB " , sub-section " PLLREFE " .
*/
value = readl ( NV_PA_CLK_RST_BASE + PLLREFE_MISC ) ;
value & = ~ PLLREFE_MISC_IDDQ ;
writel ( value , NV_PA_CLK_RST_BASE + PLLREFE_MISC ) ;
udelay ( 5 ) ;
value = PLLREFE_BASE_ENABLE |
PLLREFE_BASE_KCP ( 0 ) |
PLLREFE_BASE_DIVP ( 0 ) |
PLLREFE_BASE_DIVN ( 0x41 ) |
PLLREFE_BASE_DIVM ( 4 ) ;
writel ( value , NV_PA_CLK_RST_BASE + PLLREFE_BASE ) ;
debug ( " waiting for pllrefe lock \n " ) ;
start = get_timer ( 0 ) ;
while ( get_timer ( start ) < 250 ) {
value = readl ( NV_PA_CLK_RST_BASE + PLLREFE_MISC ) ;
if ( value & PLLREFE_MISC_LOCK )
break ;
}
if ( ! ( value & PLLREFE_MISC_LOCK ) ) {
debug ( " timeout \n " ) ;
return - ETIMEDOUT ;
}
debug ( " done \n " ) ;
return 0 ;
}
# define PLLE_SS_CNTL 0x68
# define PLLE_SS_CNTL_SSCINCINTR(x) (((x) & 0x3f) << 24)
# define PLLE_SS_CNTL_SSCINC(x) (((x) & 0xff) << 16)
@ -1041,100 +1095,131 @@ void arch_timer_init(void)
# 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_ENABLE (1 << 31)
# define PLLE_BASE_PLDIV_CML(x) (((x) & 0x1f) << 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_IDDQ_OVERRIDE_VALUE (1 << 13)
# define PLLE_MISC_LOCK (1 << 11)
# define PLLE_MISC_KCP(x) (((x) & 0x3) << 6)
# define PLLE_MISC_VREG_CTRL(x) (((x) & 0x3) << 2)
# define PLLE_MISC_KVCO (1 << 0)
# define PLLE_AUX 0x48c
# define PLLE_AUX_SS_SEQ_INCLUDE (1 << 31)
# define PLLE_AUX_REF_SEL_PLLREFE (1 << 28)
# define PLLE_AUX_SEQ_ENABLE (1 << 24)
# define PLLE_AUX_SS_SWCTL (1 << 6)
# define PLLE_AUX_ENABLE_SWCTL (1 << 4)
# define PLLE_AUX_USE_LOCKDET (1 << 3)
int tegra_plle_enable ( void )
{
unsigned int m = 1 , n = 200 , cpcon = 13 ;
u32 value ;
unsigned long start ;
value = readl ( NV_PA_CLK_RST_BASE + PLLE_BASE ) ;
value & = ~ PLLE_BASE_LOCK_OVERRIDE ;
writel ( value , NV_PA_CLK_RST_BASE + PLLE_BASE ) ;
/* PLLREF feeds PLLE */
tegra_pllref_enable ( ) ;
/*
* This sequence comes from Tegra X1 TRM section " Cold Boot, with no
* Recovery Mode or Boot from USB " , sub-section " PLLEs " .
*/
/* 1. Select XTAL as the source */
value = readl ( NV_PA_CLK_RST_BASE + PLLE_AUX ) ;
value | = PLLE_AUX_ENABLE_SWCTL ;
value & = ~ PLLE_AUX_SEQ_ENABLE ;
value & = ~ PLLE_AUX_REF_SEL_PLLREFE ;
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 ) ;
value & = ~ PLLE_MISC_IDDQ_OVERRIDE_VALUE ;
writel ( value , NV_PA_CLK_RST_BASE + PLLE_MISC ) ;
/* 2. Wait 5 us */
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 ) ;
/*
* 3. Program the following registers to generate a low jitter 100 MHz
* clock .
*/
value = readl ( NV_PA_CLK_RST_BASE + PLLE_BASE ) ;
value & = ~ PLLE_BASE_PLDIV_CML ( 0xf ) ;
value & = ~ PLLE_BASE_PLDIV_CML ( 0x1 f ) ;
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 ) ;
value | = PLLE_BASE_PLDIV_CML ( 0xe ) ;
value | = PLLE_BASE_NDIV ( 0x7d ) ;
value | = PLLE_BASE_MDIV ( 2 ) ;
writel ( value , NV_PA_CLK_RST_BASE + PLLE_BASE ) ;
udelay ( 1 ) ;
value = readl ( NV_PA_CLK_RST_BASE + PLLE_MISC ) ;
value & = ~ PLLE_MISC_KCP ( 3 ) ;
value & = ~ PLLE_MISC_VREG_CTRL ( 3 ) ;
value & = ~ PLLE_MISC_KVCO ;
writel ( value , NV_PA_CLK_RST_BASE + PLLE_MISC ) ;
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 ) ;
/* 4. Wait for LOCK */
value | = PLLE_SS_CNTL_SSCINCINTR ( 0x20 ) ;
value | = PLLE_SS_CNTL_SSCINC ( 0x01 ) ;
value | = PLLE_SS_CNTL_SSCMAX ( 0x25 ) ;
debug ( " waiting for plle lock \n " ) ;
start = get_timer ( 0 ) ;
while ( get_timer ( start ) < 250 ) {
value = readl ( NV_PA_CLK_RST_BASE + PLLE_MISC ) ;
if ( value & PLLE_MISC_LOCK )
break ;
}
if ( ! ( value & PLLE_MISC_LOCK ) ) {
debug ( " timeout \n " ) ;
return - ETIMEDOUT ;
}
debug ( " done \n " ) ;
writel ( value , NV_PA_CLK_RST_BASE + PLLE_SS_CNTL ) ;
/* 5. Enable SSA */
value = readl ( NV_PA_CLK_RST_BASE + PLLE_SS_CNTL ) ;
value & = ~ PLLE_SS_CNTL_SSCBYP ;
value & = ~ PLLE_SS_CNTL_SSCINC ( 0xff ) ;
value | = PLLE_SS_CNTL_SSCINC ( 1 ) ;
value & = ~ PLLE_SS_CNTL_SSCINCINTR ( 0x3f ) ;
value | = PLLE_SS_CNTL_SSCINCINTR ( 0x23 ) ;
value & = ~ PLLE_SS_CNTL_SSCMAX ( 0x1fff ) ;
value | = PLLE_SS_CNTL_SSCMAX ( 0x21 ) ;
value & = ~ PLLE_SS_CNTL_SSCINVERT ;
value & = ~ PLLE_SS_CNTL_SSCCENTER ;
value & = ~ PLLE_SS_CNTL_BYPASS_SS ;
value & = ~ PLLE_SS_CNTL_SSCBYP ;
writel ( value , NV_PA_CLK_RST_BASE + PLLE_SS_CNTL ) ;
udelay ( 1 ) ;
/* 6. Wait 300 ns */
value = readl ( NV_PA_CLK_RST_BASE + PLLE_SS_CNTL ) ;
udelay ( 1 ) ;
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 ;
}