2007-09-25 15:40:12 +02:00
/*
* Copyright ( C ) 2004 Florian Schirmer < jolt @ tuxbox . org >
2007-09-25 15:41:24 +02:00
* Copyright ( C ) 2007 Aurelien Jarno < aurelien @ aurel32 . net >
2007-09-25 15:40:12 +02:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation ; either version 2 of the License , or ( at your
* option ) any later version .
*
* THIS SOFTWARE IS PROVIDED ` ` AS IS ' ' AND ANY EXPRESS OR IMPLIED
* WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF
* USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/init.h>
2007-09-25 15:41:24 +02:00
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/spinlock.h>
2012-10-03 11:34:16 +00:00
# include <linux/smp.h>
2007-09-25 15:40:12 +02:00
# include <asm/bootinfo.h>
2007-09-25 15:41:24 +02:00
# include <asm/fw/cfe/cfe_api.h>
# include <asm/fw/cfe/cfe_error.h>
static int cfe_cons_handle ;
2007-09-25 15:40:12 +02:00
const char * get_system_type ( void )
{
return " Broadcom BCM47XX " ;
}
2007-09-25 15:41:24 +02:00
void prom_putchar ( char c )
{
while ( cfe_write ( cfe_cons_handle , & c , 1 ) = = 0 )
;
}
static __init void prom_init_cfe ( void )
{
uint32_t cfe_ept ;
uint32_t cfe_handle ;
uint32_t cfe_eptseal ;
int argc = fw_arg0 ;
char * * envp = ( char * * ) fw_arg2 ;
int * prom_vec = ( int * ) fw_arg3 ;
/*
* Check if a loader was used ; if NOT , the 4 arguments are
* what CFE gives us ( handle , 0 , EPT and EPTSEAL )
*/
if ( argc < 0 ) {
cfe_handle = ( uint32_t ) argc ;
cfe_ept = ( uint32_t ) envp ;
cfe_eptseal = ( uint32_t ) prom_vec ;
} else {
if ( ( int ) prom_vec < 0 ) {
/*
* Old loader ; all it gives us is the handle ,
* so use the " known " entrypoint and assume
* the seal .
*/
cfe_handle = ( uint32_t ) prom_vec ;
cfe_ept = 0xBFC00500 ;
cfe_eptseal = CFE_EPTSEAL ;
} else {
/*
* Newer loaders bundle the handle / ept / eptseal
* Note : prom_vec is in the loader ' s useg
* which is still alive in the TLB .
*/
cfe_handle = prom_vec [ 0 ] ;
cfe_ept = prom_vec [ 2 ] ;
cfe_eptseal = prom_vec [ 3 ] ;
}
}
if ( cfe_eptseal ! = CFE_EPTSEAL ) {
/* too early for panic to do any good */
printk ( KERN_ERR " CFE's entrypoint seal doesn't match. " ) ;
while ( 1 ) ;
}
cfe_init ( cfe_handle , cfe_ept ) ;
}
static __init void prom_init_console ( void )
{
/* Initialize CFE console */
cfe_cons_handle = cfe_getstdhandle ( CFE_STDHANDLE_CONSOLE ) ;
}
static __init void prom_init_cmdline ( void )
{
2009-10-13 23:43:24 +03:00
static char buf [ COMMAND_LINE_SIZE ] __initdata ;
2007-09-25 15:41:24 +02:00
/* Get the kernel command line from CFE */
2009-10-13 23:43:24 +03:00
if ( cfe_getenv ( " LINUX_CMDLINE " , buf , COMMAND_LINE_SIZE ) > = 0 ) {
buf [ COMMAND_LINE_SIZE - 1 ] = 0 ;
2007-09-25 15:41:24 +02:00
strcpy ( arcs_cmdline , buf ) ;
}
/* Force a console handover by adding a console= argument if needed,
* as CFE is not available anymore later in the boot process . */
if ( ( strstr ( arcs_cmdline , " console= " ) ) = = NULL ) {
/* Try to read the default serial port used by CFE */
2009-10-13 23:43:24 +03:00
if ( ( cfe_getenv ( " BOOT_CONSOLE " , buf , COMMAND_LINE_SIZE ) < 0 )
2007-09-25 15:41:24 +02:00
| | ( strncmp ( " uart " , buf , 4 ) ) )
/* Default to uart0 */
strcpy ( buf , " uart0 " ) ;
/* Compute the new command line */
2009-10-13 23:43:24 +03:00
snprintf ( arcs_cmdline , COMMAND_LINE_SIZE , " %s console=ttyS%c,115200 " ,
2007-09-25 15:41:24 +02:00
arcs_cmdline , buf [ 4 ] ) ;
}
}
static __init void prom_init_mem ( void )
2007-09-25 15:40:12 +02:00
{
unsigned long mem ;
2010-07-27 22:12:43 +02:00
unsigned long max ;
2012-10-03 11:34:16 +00:00
struct cpuinfo_mips * c = & current_cpu_data ;
2007-09-25 15:40:12 +02:00
2007-09-25 15:41:24 +02:00
/* Figure out memory size by finding aliases.
*
* We should theoretically use the mapping from CFE using cfe_enummem ( ) .
* However as the BCM47XX is mostly used on low - memory systems , we
* want to reuse the memory used by CFE ( around 4 MB ) . That means cfe_ *
* functions stop to work at some point during the boot , we should only
* call them at the beginning of the boot .
2010-07-27 22:12:43 +02:00
*
* BCM47XX uses 128 MB for addressing the ram , if the system contains
* less that that amount of ram it remaps the ram more often into the
* available space .
* Accessing memory after 128 MB will cause an exception .
* max contains the biggest possible address supported by the platform .
* If the method wants to try something above we assume 128 MB ram .
2007-09-25 15:41:24 +02:00
*/
2010-07-27 22:12:43 +02:00
max = ( ( unsigned long ) ( prom_init ) | ( ( 128 < < 20 ) - 1 ) ) ;
2007-09-25 15:40:12 +02:00
for ( mem = ( 1 < < 20 ) ; mem < ( 128 < < 20 ) ; mem + = ( 1 < < 20 ) ) {
2010-07-27 22:12:43 +02:00
if ( ( ( unsigned long ) ( prom_init ) + mem ) > max ) {
mem = ( 128 < < 20 ) ;
printk ( KERN_DEBUG " assume 128MB RAM \n " ) ;
break ;
}
2007-09-25 15:40:12 +02:00
if ( * ( unsigned long * ) ( ( unsigned long ) ( prom_init ) + mem ) = =
* ( unsigned long * ) ( prom_init ) )
break ;
}
2012-10-03 11:34:16 +00:00
/* Ignoring the last page when ddr size is 128M. Cached
* accesses to last page is causing the processor to prefetch
* using address above 128 M stepping out of the ddr address
* space .
*/
if ( c - > cputype = = CPU_74K & & ( mem = = ( 128 < < 20 ) ) )
mem - = 0x1000 ;
2007-09-25 15:40:12 +02:00
add_memory_region ( 0 , mem , BOOT_MEM_RAM ) ;
}
2007-09-25 15:41:24 +02:00
void __init prom_init ( void )
{
prom_init_cfe ( ) ;
prom_init_console ( ) ;
prom_init_cmdline ( ) ;
prom_init_mem ( ) ;
}
2007-09-25 15:40:12 +02:00
void __init prom_free_prom_memory ( void )
{
}