2006-06-13 15:59:01 +04:00
/*
* Big Endian PROM code for SNI RM machines
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*
* Copyright ( C ) 2005 - 2006 Florian Lohoff ( flo @ rfc822 . org )
* Copyright ( C ) 2005 - 2006 Thomas Bogendoerfer ( tsbogend @ alpha . franken . de )
*/
2007-03-01 14:56:43 +03:00
# define DEBUG
2006-06-13 15:59:01 +04:00
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/string.h>
2006-12-28 20:22:32 +03:00
# include <linux/console.h>
2006-06-13 15:59:01 +04:00
# include <asm/addrspace.h>
# include <asm/sni.h>
# include <asm/mipsprom.h>
2007-07-24 05:49:27 +04:00
# include <asm/mipsregs.h>
2006-06-13 15:59:01 +04:00
# include <asm/bootinfo.h>
/* special SNI prom calls */
/*
* This does not exist in all proms - SINIX compares
* the prom env variable " version " against " 2.0008 "
* or greater . If lesser it tries to probe interesting
* registers
*/
# define PROM_GET_MEMCONF 58
# define PROM_VEC (u64 *)CKSEG1ADDR(0x1fc00000)
# define PROM_ENTRY(x) (PROM_VEC + (x))
static int * ( * __prom_putchar ) ( int ) = ( int * ( * ) ( int ) ) PROM_ENTRY ( PROM_PUTCHAR ) ;
2007-03-01 14:56:43 +03:00
void prom_putchar ( char c )
{
__prom_putchar ( c ) ;
}
2006-06-13 15:59:01 +04:00
static char * ( * __prom_getenv ) ( char * ) = ( char * ( * ) ( char * ) ) PROM_ENTRY ( PROM_GETENV ) ;
static void ( * __prom_get_memconf ) ( void * ) = ( void ( * ) ( void * ) ) PROM_ENTRY ( PROM_GET_MEMCONF ) ;
2007-10-12 02:46:15 +04:00
char * prom_getenv ( char * s )
2006-06-13 15:59:01 +04:00
{
return __prom_getenv ( s ) ;
}
2006-12-29 18:43:59 +03:00
void __init prom_free_prom_memory ( void )
2006-06-13 15:59:01 +04:00
{
}
/*
* / proc / cpuinfo system type
*
*/
static const char * systype = " Unknown " ;
const char * get_system_type ( void )
{
return systype ;
}
# define SNI_IDPROM_BASE 0xbff00000
# define SNI_IDPROM_MEMSIZE (SNI_IDPROM_BASE+0x28) /* Memsize in 16MB quantities */
# define SNI_IDPROM_BRDTYPE (SNI_IDPROM_BASE+0x29) /* Board Type */
# define SNI_IDPROM_CPUTYPE (SNI_IDPROM_BASE+0x30) /* CPU Type */
# define SNI_IDPROM_SIZE 0x1000
# ifdef DEBUG
2007-07-24 05:49:27 +04:00
static void __init sni_idprom_dump ( void )
2006-06-13 15:59:01 +04:00
{
int i ;
2007-03-01 14:56:43 +03:00
pr_debug ( " SNI IDProm dump: \n " ) ;
2006-12-28 20:22:32 +03:00
for ( i = 0 ; i < 256 ; i + + ) {
2006-06-13 15:59:01 +04:00
if ( i % 16 = = 0 )
2007-03-01 14:56:43 +03:00
pr_debug ( " %04x " , i ) ;
2006-06-13 15:59:01 +04:00
2007-03-01 14:56:43 +03:00
printk ( " %02x " , * ( unsigned char * ) ( SNI_IDPROM_BASE + i ) ) ;
2006-06-13 15:59:01 +04:00
2006-12-28 20:22:32 +03:00
if ( i % 16 = = 15 )
2007-03-01 14:56:43 +03:00
printk ( " \n " ) ;
2006-06-13 15:59:01 +04:00
}
}
# endif
2007-07-24 05:49:27 +04:00
static void __init sni_mem_init ( void )
2006-06-13 15:59:01 +04:00
{
int i , memsize ;
struct membank {
u32 size ;
u32 base ;
u32 size2 ;
u32 pad1 ;
u32 pad2 ;
} memconf [ 8 ] ;
/* MemSIZE from prom in 16MByte chunks */
2006-12-28 20:22:32 +03:00
memsize = * ( ( unsigned char * ) SNI_IDPROM_MEMSIZE ) * 16 ;
2006-06-13 15:59:01 +04:00
2007-03-01 14:56:43 +03:00
pr_debug ( " IDProm memsize: %lu MByte \n " , memsize ) ;
2006-06-13 15:59:01 +04:00
/* get memory bank layout from prom */
__prom_get_memconf ( & memconf ) ;
2007-03-01 14:56:43 +03:00
pr_debug ( " prom_get_mem_conf memory configuration: \n " ) ;
2006-12-28 20:22:32 +03:00
for ( i = 0 ; i < 8 & & memconf [ i ] . size ; i + + ) {
if ( sni_brd_type = = SNI_BRD_PCI_TOWER | |
sni_brd_type = = SNI_BRD_PCI_TOWER_CPLUS ) {
if ( memconf [ i ] . base > = 0x20000000 & &
memconf [ i ] . base < 0x30000000 ) {
memconf [ i ] . base - = 0x20000000 ;
}
}
2007-03-01 14:56:43 +03:00
pr_debug ( " Bank%d: %08x @ %08x \n " , i ,
2006-06-13 15:59:01 +04:00
memconf [ i ] . size , memconf [ i ] . base ) ;
add_memory_region ( memconf [ i ] . base , memconf [ i ] . size , BOOT_MEM_RAM ) ;
}
}
2006-12-28 20:22:32 +03:00
static void __init sni_console_setup ( void )
{
char * ctype ;
char * cdev ;
char * baud ;
int port ;
static char options [ 8 ] ;
2007-10-12 02:46:15 +04:00
cdev = prom_getenv ( " console_dev " ) ;
2006-12-28 20:22:32 +03:00
if ( strncmp ( cdev , " tty " , 3 ) = = 0 ) {
2007-10-12 02:46:15 +04:00
ctype = prom_getenv ( " console " ) ;
2006-12-28 20:22:32 +03:00
switch ( * ctype ) {
default :
case ' l ' :
port = 0 ;
baud = prom_getenv ( " lbaud " ) ;
break ;
case ' r ' :
port = 1 ;
baud = prom_getenv ( " rbaud " ) ;
break ;
}
if ( baud )
strcpy ( options , baud ) ;
2007-06-21 01:36:47 +04:00
if ( strncmp ( cdev , " tty552 " , 6 ) = = 0 )
add_preferred_console ( " ttyS " , port , baud ? options : NULL ) ;
else
add_preferred_console ( " ttySC " , port , baud ? options : NULL ) ;
2006-12-28 20:22:32 +03:00
}
}
2006-06-13 15:59:01 +04:00
void __init prom_init ( void )
{
int argc = fw_arg0 ;
char * * argv = ( void * ) fw_arg1 ;
int i ;
2006-12-28 20:22:32 +03:00
int cputype ;
2006-06-13 15:59:01 +04:00
2006-12-28 20:22:32 +03:00
sni_brd_type = * ( unsigned char * ) SNI_IDPROM_BRDTYPE ;
cputype = * ( unsigned char * ) SNI_IDPROM_CPUTYPE ;
switch ( sni_brd_type ) {
case SNI_BRD_TOWER_OASIC :
switch ( cputype ) {
case SNI_CPU_M8030 :
systype = " RM400-330 " ;
break ;
case SNI_CPU_M8031 :
systype = " RM400-430 " ;
break ;
case SNI_CPU_M8037 :
systype = " RM400-530 " ;
break ;
case SNI_CPU_M8034 :
systype = " RM400-730 " ;
break ;
default :
systype = " RM400-xxx " ;
break ;
}
break ;
case SNI_BRD_MINITOWER :
switch ( cputype ) {
case SNI_CPU_M8021 :
case SNI_CPU_M8043 :
systype = " RM400-120 " ;
break ;
case SNI_CPU_M8040 :
systype = " RM400-220 " ;
break ;
case SNI_CPU_M8053 :
systype = " RM400-225 " ;
break ;
case SNI_CPU_M8050 :
systype = " RM400-420 " ;
break ;
default :
systype = " RM400-xxx " ;
break ;
}
break ;
case SNI_BRD_PCI_TOWER :
systype = " RM400-Cxx " ;
break ;
case SNI_BRD_RM200 :
systype = " RM200-xxx " ;
break ;
case SNI_BRD_PCI_MTOWER :
systype = " RM300-Cxx " ;
break ;
case SNI_BRD_PCI_DESKTOP :
switch ( read_c0_prid ( ) & 0xff00 ) {
case PRID_IMP_R4600 :
case PRID_IMP_R4700 :
systype = " RM200-C20 " ;
break ;
case PRID_IMP_R5000 :
systype = " RM200-C40 " ;
break ;
default :
systype = " RM200-Cxx " ;
break ;
}
break ;
case SNI_BRD_PCI_TOWER_CPLUS :
systype = " RM400-Exx " ;
break ;
case SNI_BRD_PCI_MTOWER_CPLUS :
systype = " RM300-Exx " ;
break ;
}
2007-10-12 02:46:15 +04:00
pr_debug ( " Found SNI brdtype %02x name %s \n " , sni_brd_type , systype ) ;
2006-06-13 15:59:01 +04:00
# ifdef DEBUG
sni_idprom_dump ( ) ;
# endif
sni_mem_init ( ) ;
2006-12-28 20:22:32 +03:00
sni_console_setup ( ) ;
2006-06-13 15:59:01 +04:00
/* copy prom cmdline parameters to kernel cmdline */
for ( i = 1 ; i < argc ; i + + ) {
strcat ( arcs_cmdline , argv [ i ] ) ;
if ( i < ( argc - 1 ) )
strcat ( arcs_cmdline , " " ) ;
}
}