@ -15,20 +15,141 @@
# include <asm/blackfin.h>
# include <asm/mach-common/bits/bootrom.h>
# include <asm/mach-common/bits/core.h>
# include <asm/mach-common/bits/ebiu.h>
# include <asm/mach-common/bits/pll.h>
# include <asm/mach-common/bits/uart.h>
# define BUG() while (1) { asm volatile("emuexcpt;"); }
# include "serial.h"
# ifndef __ADSPBF60x__
# include <asm/mach-common/bits/ebiu.h>
# include <asm/mach-common/bits/pll.h>
# else /* __ADSPBF60x__ */
# include <asm/mach-common/bits/cgu.h>
# define CONFIG_BFIN_GET_DCLK_M \
( ( CONFIG_CLKIN_HZ * CONFIG_VCO_MULT ) / ( CONFIG_DCLK_DIV * 1000000 ) )
# ifndef CONFIG_DMC_DDRCFG
# if ((CONFIG_BFIN_GET_DCLK_M != 125) && \
( CONFIG_BFIN_GET_DCLK_M ! = 133 ) & & \
( CONFIG_BFIN_GET_DCLK_M ! = 150 ) & & \
( CONFIG_BFIN_GET_DCLK_M ! = 166 ) & & \
( CONFIG_BFIN_GET_DCLK_M ! = 200 ) & & \
( CONFIG_BFIN_GET_DCLK_M ! = 225 ) & & \
( CONFIG_BFIN_GET_DCLK_M ! = 250 ) )
# error "DDR2 CLK must be in (125, 133, 150, 166, 200, 225, 250)MHz"
# endif
# endif
/* DMC control bits */
# define SRREQ 0x8
/* DMC status bits */
# define IDLE 0x1
# define MEMINITDONE 0x4
# define SRACK 0x8
# define PDACK 0x10
# define DPDACK 0x20
# define DLLCALDONE 0x2000
# define PENDREF 0xF0000
# define PHYRDPHASE 0xF00000
# define PHYRDPHASE_OFFSET 20
/* DMC DLL control bits */
# define DLLCALRDCNT 0xFF
# define DATACYC_OFFSET 8
struct ddr_config {
u32 ddr_clk ;
u32 dmc_ddrctl ;
u32 dmc_ddrcfg ;
u32 dmc_ddrtr0 ;
u32 dmc_ddrtr1 ;
u32 dmc_ddrtr2 ;
u32 dmc_ddrmr ;
u32 dmc_ddrmr1 ;
} ;
static struct ddr_config ddr_config_table [ ] = {
[ 0 ] = {
. ddr_clk = 125 , /* 125MHz */
. dmc_ddrctl = 0x00000904 ,
. dmc_ddrcfg = 0x00000422 ,
. dmc_ddrtr0 = 0x20705212 ,
. dmc_ddrtr1 = 0x201003CF ,
. dmc_ddrtr2 = 0x00320107 ,
. dmc_ddrmr = 0x00000422 ,
. dmc_ddrmr1 = 0x4 ,
} ,
[ 1 ] = {
. ddr_clk = 133 , /* 133MHz */
. dmc_ddrctl = 0x00000904 ,
. dmc_ddrcfg = 0x00000422 ,
. dmc_ddrtr0 = 0x20806313 ,
. dmc_ddrtr1 = 0x2013040D ,
. dmc_ddrtr2 = 0x00320108 ,
. dmc_ddrmr = 0x00000632 ,
. dmc_ddrmr1 = 0x4 ,
} ,
[ 2 ] = {
. ddr_clk = 150 , /* 150MHz */
. dmc_ddrctl = 0x00000904 ,
. dmc_ddrcfg = 0x00000422 ,
. dmc_ddrtr0 = 0x20A07323 ,
. dmc_ddrtr1 = 0x20160492 ,
. dmc_ddrtr2 = 0x00320209 ,
. dmc_ddrmr = 0x00000632 ,
. dmc_ddrmr1 = 0x4 ,
} ,
[ 3 ] = {
. ddr_clk = 166 , /* 166MHz */
. dmc_ddrctl = 0x00000904 ,
. dmc_ddrcfg = 0x00000422 ,
. dmc_ddrtr0 = 0x20A07323 ,
. dmc_ddrtr1 = 0x2016050E ,
. dmc_ddrtr2 = 0x00320209 ,
. dmc_ddrmr = 0x00000632 ,
. dmc_ddrmr1 = 0x4 ,
} ,
[ 4 ] = {
. ddr_clk = 200 , /* 200MHz */
. dmc_ddrctl = 0x00000904 ,
. dmc_ddrcfg = 0x00000422 ,
. dmc_ddrtr0 = 0x20a07323 ,
. dmc_ddrtr1 = 0x2016050f ,
. dmc_ddrtr2 = 0x00320509 ,
. dmc_ddrmr = 0x00000632 ,
. dmc_ddrmr1 = 0x4 ,
} ,
[ 5 ] = {
. ddr_clk = 225 , /* 225MHz */
. dmc_ddrctl = 0x00000904 ,
. dmc_ddrcfg = 0x00000422 ,
. dmc_ddrtr0 = 0x20E0A424 ,
. dmc_ddrtr1 = 0x302006DB ,
. dmc_ddrtr2 = 0x0032020D ,
. dmc_ddrmr = 0x00000842 ,
. dmc_ddrmr1 = 0x4 ,
} ,
[ 6 ] = {
. ddr_clk = 250 , /* 250MHz */
. dmc_ddrctl = 0x00000904 ,
. dmc_ddrcfg = 0x00000422 ,
. dmc_ddrtr0 = 0x20E0A424 ,
. dmc_ddrtr1 = 0x3020079E ,
. dmc_ddrtr2 = 0x0032050D ,
. dmc_ddrmr = 0x00000842 ,
. dmc_ddrmr1 = 0x4 ,
} ,
} ;
# endif /* __ADSPBF60x__ */
__attribute__ ( ( always_inline ) )
static inline void serial_init ( void )
{
uint32_t uart_base = UART_DLL ;
uint32_t uart_base = UART_BASE ;
# ifdef __ADSPBF54x__
# if defined(__ADSPBF54x__) || defined(__ADSPBF60x__)
# ifdef BFIN_BOOT_UART_USE_RTS
# define BFIN_UART_USE_RTS 1
# else
@ -38,7 +159,12 @@ static inline void serial_init(void)
size_t i ;
/* force RTS rather than relying on auto RTS */
# if BFIN_UART_HW_VER < 4
bfin_write16 ( & pUART - > mcr , bfin_read16 ( & pUART - > mcr ) | FCPOL ) ;
# else
bfin_write32 ( & pUART - > control , bfin_read32 ( & pUART - > control ) |
FCPOL ) ;
# endif
/* Wait for the line to clear up. We cannot rely on UART
* registers as none of them reflect the status of the RSR .
@ -68,13 +194,14 @@ static inline void serial_init(void)
# endif
if ( BFIN_DEBUG_EARLY_SERIAL ) {
int ucen = bfin_read16 ( & pUART - > gctl ) & UCEN ;
int enabled = serial_early_enabled ( uart_base ) ;
serial_early_init ( uart_base ) ;
/* If the UART is off, that means we need to program
* the baud rate ourselves initially .
*/
if ( ucen ! = UCEN )
if ( ! enabled )
serial_early_set_baud ( uart_base , CONFIG_BAUDRATE ) ;
}
}
@ -82,12 +209,17 @@ static inline void serial_init(void)
__attribute__ ( ( always_inline ) )
static inline void serial_deinit ( void )
{
# ifdef __ADSPBF54x__
uint32_t uart_base = UART_DLL ;
# if defined(__ADSPBF54x__) || defined(__ADSPBF60x__)
uint32_t uart_base = UART_BASE ;
if ( BFIN_UART_USE_RTS & & CONFIG_BFIN_BOOT_MODE = = BFIN_BOOT_UART ) {
/* clear forced RTS rather than relying on auto RTS */
# if BFIN_UART_HW_VER < 4
bfin_write16 ( & pUART - > mcr , bfin_read16 ( & pUART - > mcr ) & ~ FCPOL ) ;
# else
bfin_write32 ( & pUART - > control , bfin_read32 ( & pUART - > control ) &
~ FCPOL ) ;
# endif
}
# endif
}
@ -95,7 +227,7 @@ static inline void serial_deinit(void)
__attribute__ ( ( always_inline ) )
static inline void serial_putc ( char c )
{
uint32_t uart_base = UART_DLL ;
uint32_t uart_base = UART_BASE ;
if ( ! BFIN_DEBUG_EARLY_SERIAL )
return ;
@ -103,9 +235,9 @@ static inline void serial_putc(char c)
if ( c = = ' \n ' )
serial_putc ( ' \r ' ) ;
bfin_write16 ( & pUART - > thr , c ) ;
bfin_write ( & pUART - > thr , c ) ;
while ( ! ( bfin_read16 ( & pUART - > lsr ) & TEMT ) )
while ( ! ( _lsr_read ( pUART ) & TEMT ) )
continue ;
}
@ -152,6 +284,24 @@ program_nmi_handler(void)
# define bfin_write_SPI_BAUD bfin_write_SPI0_BAUD
# endif
# ifdef __ADSPBF60x__
# ifndef CONFIG_CGU_CTL_VAL
# define CONFIG_CGU_CTL_VAL ((CONFIG_VCO_MULT << 8) | CONFIG_CLKIN_HALF)
# endif
# ifndef CONFIG_CGU_DIV_VAL
# define CONFIG_CGU_DIV_VAL \
( ( CONFIG_CCLK_DIV < < CSEL_P ) | \
( CONFIG_SCLK0_DIV < < S0SEL_P ) | \
( CONFIG_SCLK_DIV < < SYSSEL_P ) | \
( CONFIG_SCLK1_DIV < < S1SEL_P ) | \
( CONFIG_DCLK_DIV < < DSEL_P ) | \
( CONFIG_OCLK_DIV < < OSEL_P ) )
# endif
# else /* __ADSPBF60x__ */
/* PLL_DIV defines */
# ifndef CONFIG_PLL_DIV_VAL
# if (CONFIG_CCLK_DIV == 1)
@ -275,6 +425,8 @@ program_nmi_handler(void)
# endif
# endif
# endif /* __ADSPBF60x__ */
__attribute__ ( ( always_inline ) ) static inline void
program_early_devices ( ADI_BOOT_DATA * bs , uint * sdivB , uint * divB , uint * vcoB )
{
@ -283,8 +435,14 @@ program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB)
/* Save the clock pieces that are used in baud rate calculation */
if ( BFIN_DEBUG_EARLY_SERIAL | | CONFIG_BFIN_BOOT_MODE = = BFIN_BOOT_UART ) {
serial_putc ( ' b ' ) ;
# ifdef __ADSPBF60x__
* sdivB = bfin_read_CGU_DIV ( ) ;
* sdivB = ( ( * sdivB > > 8 ) & 0x1f ) * ( ( * sdivB > > 5 ) & 0x7 ) ;
* vcoB = ( bfin_read_CGU_CTL ( ) > > 8 ) & 0x7f ;
# else
* sdivB = bfin_read_PLL_DIV ( ) & 0xf ;
* vcoB = ( bfin_read_PLL_CTL ( ) > > 9 ) & 0x3f ;
# endif
* divB = serial_early_get_div ( ) ;
serial_putc ( ' c ' ) ;
}
@ -316,6 +474,7 @@ program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB)
* boot . Once we switch over to u - boot ' s SPI flash driver , we ' ll
* increase the speed appropriately .
*/
# ifdef SPI_BAUD
if ( CONFIG_BFIN_BOOT_MODE = = BFIN_BOOT_SPI_MASTER ) {
serial_putc ( ' h ' ) ;
if ( BOOTROM_SUPPORTS_SPI_FAST_READ & & CONFIG_SPI_BAUD_INITBLOCK < 4 )
@ -323,6 +482,7 @@ program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB)
bfin_write_SPI_BAUD ( CONFIG_SPI_BAUD_INITBLOCK ) ;
serial_putc ( ' i ' ) ;
}
# endif
serial_putc ( ' j ' ) ;
}
@ -335,6 +495,10 @@ maybe_self_refresh(ADI_BOOT_DATA *bs)
if ( ! CONFIG_MEM_SIZE )
return false ;
# ifdef __ADSPBF60x__
# else /* __ADSPBF60x__ */
/* If external memory is enabled, put it into self refresh first. */
# if defined(EBIU_RSTCTL)
if ( bfin_read_EBIU_RSTCTL ( ) & DDR_SRESET ) {
@ -350,6 +514,7 @@ maybe_self_refresh(ADI_BOOT_DATA *bs)
}
# endif
# endif /* __ADSPBF60x__ */
serial_putc ( ' c ' ) ;
return false ;
@ -362,6 +527,37 @@ program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs)
serial_putc ( ' a ' ) ;
# ifdef __ADSPBF60x__
if ( bfin_read_DMC0_STAT ( ) & MEMINITDONE ) {
bfin_write_DMC0_CTL ( bfin_read_DMC0_CTL ( ) | SRREQ ) ;
SSYNC ( ) ;
while ( ! ( bfin_read_DMC0_STAT ( ) & SRACK ) )
continue ;
}
/* Don't set the same value of MSEL and DF to CGU_CTL */
if ( ( bfin_read_CGU_CTL ( ) & ( MSEL_MASK | DF_MASK ) )
! = CONFIG_CGU_CTL_VAL ) {
bfin_write_CGU_DIV ( CONFIG_CGU_DIV_VAL ) ;
bfin_write_CGU_CTL ( CONFIG_CGU_CTL_VAL ) ;
while ( ( bfin_read_CGU_STAT ( ) & ( CLKSALGN | PLLBP ) ) | |
! ( bfin_read_CGU_STAT ( ) & PLLLK ) )
continue ;
}
bfin_write_CGU_DIV ( CONFIG_CGU_DIV_VAL | UPDT ) ;
while ( bfin_read_CGU_STAT ( ) & CLKSALGN )
continue ;
if ( bfin_read_DMC0_STAT ( ) & MEMINITDONE ) {
bfin_write_DMC0_CTL ( bfin_read_DMC0_CTL ( ) & ~ SRREQ ) ;
SSYNC ( ) ;
while ( bfin_read_DMC0_STAT ( ) & SRACK )
continue ;
}
# else /* __ADSPBF60x__ */
vr_ctl = bfin_read_VR_CTL ( ) ;
serial_putc ( ' b ' ) ;
@ -433,7 +629,7 @@ program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs)
# elif defined(SICA_IWR0)
bfin_write_SICA_IWR0 ( 1 ) ;
bfin_write_SICA_IWR1 ( 0 ) ;
# else
# elif defined(SIC_IWR)
bfin_write_SIC_IWR ( 1 ) ;
# endif
@ -482,13 +678,15 @@ program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs)
# elif defined(SICA_IWR0)
bfin_write_SICA_IWR0 ( - 1 ) ;
bfin_write_SICA_IWR1 ( - 1 ) ;
# else
# elif defined(SIC_IWR)
bfin_write_SIC_IWR ( - 1 ) ;
# endif
serial_putc ( ' n ' ) ;
}
# endif /* __ADSPBF60x__ */
serial_putc ( ' o ' ) ;
return vr_ctl ;
@ -505,16 +703,25 @@ update_serial_clocks(ADI_BOOT_DATA *bs, uint sdivB, uint divB, uint vcoB)
* for dividing which means we ' d generate a libgcc reference .
*/
if ( CONFIG_BFIN_BOOT_MODE = = BFIN_BOOT_UART ) {
serial_putc ( ' b ' ) ;
unsigned int sdivR , vcoR ;
sdivR = bfin_read_PLL_DIV ( ) & 0xf ;
vcoR = ( bfin_read_PLL_CTL ( ) > > 9 ) & 0x3f ;
int dividend = sdivB * divB * vcoR ;
int divisor = vcoB * sdivR ;
unsigned int quotient ;
serial_putc ( ' b ' ) ;
# ifdef __ADSPBF60x__
sdivR = bfin_read_CGU_DIV ( ) ;
sdivR = ( ( sdivR > > 8 ) & 0x1f ) * ( ( sdivR > > 5 ) & 0x7 ) ;
vcoR = ( bfin_read_CGU_CTL ( ) > > 8 ) & 0x7f ;
# else
sdivR = bfin_read_PLL_DIV ( ) & 0xf ;
vcoR = ( bfin_read_PLL_CTL ( ) > > 9 ) & 0x3f ;
# endif
for ( quotient = 0 ; dividend > 0 ; + + quotient )
dividend - = divisor ;
serial_early_put_div ( UART_DLL , quotient - ANOMALY_05000230 ) ;
serial_early_put_div ( quotient - ANOMALY_05000230 ) ;
serial_putc ( ' c ' ) ;
}
@ -531,6 +738,84 @@ program_memory_controller(ADI_BOOT_DATA *bs, bool put_into_srfs)
serial_putc ( ' b ' ) ;
# ifdef __ADSPBF60x__
int dlldatacycle ;
int dll_ctl ;
int i = 0 ;
if ( CONFIG_BFIN_GET_DCLK_M = = 125 )
i = 0 ;
else if ( CONFIG_BFIN_GET_DCLK_M = = 133 )
i = 1 ;
else if ( CONFIG_BFIN_GET_DCLK_M = = 150 )
i = 2 ;
else if ( CONFIG_BFIN_GET_DCLK_M = = 166 )
i = 3 ;
else if ( CONFIG_BFIN_GET_DCLK_M = = 200 )
i = 4 ;
else if ( CONFIG_BFIN_GET_DCLK_M = = 225 )
i = 5 ;
else if ( CONFIG_BFIN_GET_DCLK_M = = 250 )
i = 6 ;
#if 0
for ( i = 0 ; i < ARRAY_SIZE ( ddr_config_table ) ; i + + )
if ( CONFIG_BFIN_GET_DCLK_M = = ddr_config_table [ i ] . ddr_clk )
break ;
# endif
# ifndef CONFIG_DMC_DDRCFG
bfin_write_DMC0_CFG ( ddr_config_table [ i ] . dmc_ddrcfg ) ;
# else
bfin_write_DMC0_CFG ( CONFIG_DMC_DDRCFG ) ;
# endif
# ifndef CONFIG_DMC_DDRTR0
bfin_write_DMC0_TR0 ( ddr_config_table [ i ] . dmc_ddrtr0 ) ;
# else
bfin_write_DMC0_TR0 ( CONFIG_DMC_DDRTR0 ) ;
# endif
# ifndef CONFIG_DMC_DDRTR1
bfin_write_DMC0_TR1 ( ddr_config_table [ i ] . dmc_ddrtr1 ) ;
# else
bfin_write_DMC0_TR1 ( CONFIG_DMC_DDRTR1 ) ;
# endif
# ifndef CONFIG_DMC_DDRTR2
bfin_write_DMC0_TR2 ( ddr_config_table [ i ] . dmc_ddrtr2 ) ;
# else
bfin_write_DMC0_TR2 ( CONFIG_DMC_DDRTR2 ) ;
# endif
# ifndef CONFIG_DMC_DDRMR
bfin_write_DMC0_MR ( ddr_config_table [ i ] . dmc_ddrmr ) ;
# else
bfin_write_DMC0_MR ( CONFIG_DMC_DDRMR ) ;
# endif
# ifndef CONFIG_DMC_DDREMR1
bfin_write_DMC0_EMR1 ( ddr_config_table [ i ] . dmc_ddrmr1 ) ;
# else
bfin_write_DMC0_EMR1 ( CONFIG_DMC_DDREMR1 ) ;
# endif
# ifndef CONFIG_DMC_DDRCTL
bfin_write_DMC0_CTL ( ddr_config_table [ i ] . dmc_ddrctl ) ;
# else
bfin_write_DMC0_CTL ( CONFIG_DMC_DDRCTL ) ;
# endif
SSYNC ( ) ;
while ( ! ( bfin_read_DMC0_STAT ( ) & MEMINITDONE ) )
continue ;
dlldatacycle = ( bfin_read_DMC0_STAT ( ) & PHYRDPHASE ) > >
PHYRDPHASE_OFFSET ;
dll_ctl = bfin_read_DMC0_DLLCTL ( ) ;
dll_ctl & = 0x0ff ;
bfin_write_DMC0_DLLCTL ( dll_ctl | ( dlldatacycle < < DATACYC_OFFSET ) ) ;
SSYNC ( ) ;
while ( ! ( bfin_read_DMC0_STAT ( ) & DLLCALDONE ) )
continue ;
serial_putc ( ' ! ' ) ;
# else /* __ADSPBF60x__ */
/* Program the external memory controller before we come out of
* self - refresh . This only works with our SDRAM controller .
*/
@ -583,6 +868,7 @@ program_memory_controller(ADI_BOOT_DATA *bs, bool put_into_srfs)
# endif
# endif
# endif /* __ADSPBF60x__ */
serial_putc ( ' e ' ) ;
}
@ -606,7 +892,8 @@ check_hibernation(ADI_BOOT_DATA *bs, u16 vr_ctl, bool put_into_srfs)
*/
if ( ANOMALY_05000307 | | vr_ctl & 0x8000 ) {
uint32_t * hibernate_magic = 0 ;
__builtin_bfin_ssync ( ) ; /* make sure memory controller is done */
SSYNC ( ) ;
if ( hibernate_magic [ 0 ] = = 0xDEADBEEF ) {
serial_putc ( ' c ' ) ;
bfin_write_EVT15 ( hibernate_magic [ 1 ] ) ;