2005-04-16 15:20:36 -07:00
/*
* Common code for the boards based on Freescale MPC52xx embedded CPU .
*
*
* Maintainer : Sylvain Munaut < tnt @ 246 tNt . com >
*
* Support for other bootloaders than UBoot by Dale Farnsworth
* < dfarnsworth @ mvista . com >
*
* Copyright ( C ) 2004 Sylvain Munaut < tnt @ 246 tNt . com >
* Copyright ( C ) 2003 Montavista Software , Inc
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed " as is " without any warranty of any
* kind , whether express or implied .
*/
# include <asm/io.h>
# include <asm/time.h>
# include <asm/mpc52xx.h>
# include <asm/mpc52xx_psc.h>
# include <asm/pgtable.h>
# include <asm/ppcboot.h>
2006-03-26 13:38:09 +02:00
# include <syslib/mpc52xx_pci.h>
2005-04-16 15:20:36 -07:00
extern bd_t __res ;
static int core_mult [ ] = { /* CPU Frequency multiplier, taken */
0 , 0 , 0 , 10 , 20 , 20 , 25 , 45 , /* from the datasheet used to compute */
30 , 55 , 40 , 50 , 0 , 60 , 35 , 0 , /* CPU frequency from XLB freq and */
30 , 25 , 65 , 10 , 70 , 20 , 75 , 45 , /* external jumper config */
0 , 55 , 40 , 50 , 80 , 60 , 35 , 0
} ;
void
mpc52xx_restart ( char * cmd )
{
struct mpc52xx_gpt __iomem * gpt0 = MPC52xx_VA ( MPC52xx_GPTx_OFFSET ( 0 ) ) ;
local_irq_disable ( ) ;
/* Turn on the watchdog and wait for it to expire. It effectively
does a reset */
out_be32 ( & gpt0 - > count , 0x000000ff ) ;
out_be32 ( & gpt0 - > mode , 0x00009004 ) ;
while ( 1 ) ;
}
void
mpc52xx_halt ( void )
{
local_irq_disable ( ) ;
while ( 1 ) ;
}
void
mpc52xx_power_off ( void )
{
/* By default we don't have any way of shut down.
If a specific board wants to , it can set the power down
code to any hardware implementation dependent code */
mpc52xx_halt ( ) ;
}
void __init
mpc52xx_set_bat ( void )
{
/* Set BAT 2 to map the 0xf0000000 area */
/* This mapping is used during mpc52xx_progress,
* mpc52xx_find_end_of_memory , and UARTs / GPIO access for debug
*/
mb ( ) ;
mtspr ( SPRN_DBAT2U , 0xf0001ffe ) ;
mtspr ( SPRN_DBAT2L , 0xf000002a ) ;
mb ( ) ;
}
void __init
mpc52xx_map_io ( void )
{
2006-01-06 00:11:34 -08:00
/* Here we map the MBAR and the whole upper zone. MBAR is only
64 k but we can ' t map only 64 k with BATs . Map the whole
0xf0000000 range is ok and helps eventual lpb devices placed there */
2005-04-16 15:20:36 -07:00
io_block_mapping (
2006-01-06 00:11:34 -08:00
MPC52xx_MBAR_VIRT , MPC52xx_MBAR , 0x10000000 , _PAGE_IO ) ;
2005-04-16 15:20:36 -07:00
}
# ifdef CONFIG_SERIAL_TEXT_DEBUG
# ifndef MPC52xx_PF_CONSOLE_PORT
# error "mpc52xx PSC for console not selected"
# endif
static void
mpc52xx_psc_putc ( struct mpc52xx_psc __iomem * psc , unsigned char c )
{
while ( ! ( in_be16 ( & psc - > mpc52xx_psc_status ) &
MPC52xx_PSC_SR_TXRDY ) ) ;
out_8 ( & psc - > mpc52xx_psc_buffer_8 , c ) ;
}
void
mpc52xx_progress ( char * s , unsigned short hex )
{
char c ;
struct mpc52xx_psc __iomem * psc ;
psc = MPC52xx_VA ( MPC52xx_PSCx_OFFSET ( MPC52xx_PF_CONSOLE_PORT ) ) ;
while ( ( c = * s + + ) ! = 0 ) {
if ( c = = ' \n ' )
mpc52xx_psc_putc ( psc , ' \r ' ) ;
mpc52xx_psc_putc ( psc , c ) ;
}
mpc52xx_psc_putc ( psc , ' \r ' ) ;
mpc52xx_psc_putc ( psc , ' \n ' ) ;
}
# endif /* CONFIG_SERIAL_TEXT_DEBUG */
unsigned long __init
mpc52xx_find_end_of_memory ( void )
{
u32 ramsize = __res . bi_memsize ;
/*
* if bootloader passed a memsize , just use it
* else get size from sdram config registers
*/
if ( ramsize = = 0 ) {
struct mpc52xx_mmap_ctl __iomem * mmap_ctl ;
u32 sdram_config_0 , sdram_config_1 ;
/* Temp BAT2 mapping active when this is called ! */
mmap_ctl = MPC52xx_VA ( MPC52xx_MMAP_CTL_OFFSET ) ;
sdram_config_0 = in_be32 ( & mmap_ctl - > sdram0 ) ;
sdram_config_1 = in_be32 ( & mmap_ctl - > sdram1 ) ;
if ( ( sdram_config_0 & 0x1f ) > = 0x13 )
ramsize = 1 < < ( ( sdram_config_0 & 0xf ) + 17 ) ;
if ( ( ( sdram_config_1 & 0x1f ) > = 0x13 ) & &
( ( sdram_config_1 & 0xfff00000 ) = = ramsize ) )
ramsize + = 1 < < ( ( sdram_config_1 & 0xf ) + 17 ) ;
}
return ramsize ;
}
void __init
mpc52xx_calibrate_decr ( void )
{
int current_time , previous_time ;
int tbl_start , tbl_end ;
unsigned int xlbfreq , cpufreq , ipbfreq , pcifreq , divisor ;
xlbfreq = __res . bi_busfreq ;
/* if bootloader didn't pass bus frequencies, calculate them */
if ( xlbfreq = = 0 ) {
/* Get RTC & Clock manager modules */
struct mpc52xx_rtc __iomem * rtc ;
struct mpc52xx_cdm __iomem * cdm ;
rtc = ioremap ( MPC52xx_PA ( MPC52xx_RTC_OFFSET ) , MPC52xx_RTC_SIZE ) ;
cdm = ioremap ( MPC52xx_PA ( MPC52xx_CDM_OFFSET ) , MPC52xx_CDM_SIZE ) ;
if ( ( rtc = = NULL ) | | ( cdm = = NULL ) )
panic ( " Can't ioremap RTC/CDM while computing bus freq " ) ;
/* Count bus clock during 1/64 sec */
out_be32 ( & rtc - > dividers , 0x8f1f0000 ) ; /* Set RTC 64x faster */
previous_time = in_be32 ( & rtc - > time ) ;
while ( ( current_time = in_be32 ( & rtc - > time ) ) = = previous_time ) ;
tbl_start = get_tbl ( ) ;
previous_time = current_time ;
while ( ( current_time = in_be32 ( & rtc - > time ) ) = = previous_time ) ;
tbl_end = get_tbl ( ) ;
out_be32 ( & rtc - > dividers , 0xffff0000 ) ; /* Restore RTC */
/* Compute all frequency from that & CDM settings */
xlbfreq = ( tbl_end - tbl_start ) < < 8 ;
cpufreq = ( xlbfreq * core_mult [ in_be32 ( & cdm - > rstcfg ) & 0x1f ] ) / 10 ;
ipbfreq = ( in_8 ( & cdm - > ipb_clk_sel ) & 1 ) ?
xlbfreq / 2 : xlbfreq ;
switch ( in_8 ( & cdm - > pci_clk_sel ) & 3 ) {
case 0 :
pcifreq = ipbfreq ;
break ;
case 1 :
pcifreq = ipbfreq / 2 ;
break ;
default :
pcifreq = xlbfreq / 4 ;
break ;
}
__res . bi_busfreq = xlbfreq ;
__res . bi_intfreq = cpufreq ;
__res . bi_ipbfreq = ipbfreq ;
__res . bi_pcifreq = pcifreq ;
/* Release mapping */
iounmap ( rtc ) ;
iounmap ( cdm ) ;
}
divisor = 4 ;
tb_ticks_per_jiffy = xlbfreq / HZ / divisor ;
tb_to_us = mulhwu_scale_factor ( xlbfreq / divisor , 1000000 ) ;
}
2006-03-26 13:38:09 +02:00
void __init
mpc52xx_setup_cpu ( void )
{
struct mpc52xx_cdm __iomem * cdm ;
struct mpc52xx_xlb __iomem * xlb ;
/* Map zones */
cdm = ioremap ( MPC52xx_PA ( MPC52xx_CDM_OFFSET ) , MPC52xx_CDM_SIZE ) ;
xlb = ioremap ( MPC52xx_PA ( MPC52xx_XLB_OFFSET ) , MPC52xx_XLB_SIZE ) ;
if ( ! cdm | | ! xlb ) {
printk ( KERN_ERR __FILE__ " : "
" Error while mapping CDM/XLB during "
" mpc52xx_setup_cpu \n " ) ;
goto unmap_regs ;
}
/* Use internal 48 Mhz */
out_8 ( & cdm - > ext_48mhz_en , 0x00 ) ;
out_8 ( & cdm - > fd_enable , 0x01 ) ;
if ( in_be32 ( & cdm - > rstcfg ) & 0x40 ) /* Assumes 33Mhz clock */
out_be16 ( & cdm - > fd_counters , 0x0001 ) ;
else
out_be16 ( & cdm - > fd_counters , 0x5555 ) ;
/* Configure the XLB Arbiter priorities */
out_be32 ( & xlb - > master_pri_enable , 0xff ) ;
out_be32 ( & xlb - > master_priority , 0x11111111 ) ;
/* Enable ram snooping for 1GB window */
out_be32 ( & xlb - > config , in_be32 ( & xlb - > config ) | MPC52xx_XLB_CFG_SNOOP ) ;
out_be32 ( & xlb - > snoop_window , MPC52xx_PCI_TARGET_MEM | 0x1d ) ;
/* Disable XLB pipelining */
/* (cfr errate 292. We could do this only just before ATA PIO
transaction and re - enable it after . . . ) */
out_be32 ( & xlb - > config , in_be32 ( & xlb - > config ) | MPC52xx_XLB_CFG_PLDIS ) ;
/* Unmap reg zone */
unmap_regs :
if ( cdm ) iounmap ( cdm ) ;
if ( xlb ) iounmap ( xlb ) ;
}
2005-04-16 15:20:36 -07:00
int mpc52xx_match_psc_function ( int psc_idx , const char * func )
{
struct mpc52xx_psc_func * cf = mpc52xx_psc_functions ;
while ( ( cf - > id ! = - 1 ) & & ( cf - > func ! = NULL ) ) {
if ( ( cf - > id = = psc_idx ) & & ! strcmp ( cf - > func , func ) )
return 1 ;
cf + + ;
}
return 0 ;
}