2005-04-17 02:20:36 +04:00
/*
* Processor capabilities determination functions .
*
* Copyright ( C ) xxxx the Anonymous
2006-01-29 21:42:08 +03:00
* Copyright ( C ) 1994 - 2006 Ralf Baechle
2005-05-05 20:45:59 +04:00
* Copyright ( C ) 2003 , 2004 Maciej W . Rozycki
* Copyright ( C ) 2001 , 2004 MIPS Inc .
2005-04-17 02:20:36 +04: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 .
*/
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/ptrace.h>
2009-06-19 17:05:26 +04:00
# include <linux/smp.h>
2005-04-17 02:20:36 +04:00
# include <linux/stddef.h>
2009-11-16 20:32:59 +03:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
2007-02-18 22:07:31 +03:00
# include <asm/bugs.h>
2005-04-17 02:20:36 +04:00
# include <asm/cpu.h>
# include <asm/fpu.h>
# include <asm/mipsregs.h>
# include <asm/system.h>
2008-09-23 11:07:16 +04:00
# include <asm/watch.h>
2009-07-10 12:51:27 +04:00
# include <asm/spram.h>
2010-10-14 22:32:33 +04:00
# include <asm/uaccess.h>
2005-04-17 02:20:36 +04:00
/*
* Not all of the MIPS CPUs have the " wait " instruction available . Moreover ,
* the implementation of the " wait " feature differs between CPU families . This
* points to the function that implements CPU specific wait .
* The wait instruction stops the pipeline and reduces the power consumption of
* the CPU very much .
*/
2009-09-17 04:25:07 +04:00
void ( * cpu_wait ) ( void ) ;
2009-11-16 20:32:59 +03:00
EXPORT_SYMBOL ( cpu_wait ) ;
2005-04-17 02:20:36 +04:00
static void r3081_wait ( void )
{
unsigned long cfg = read_c0_conf ( ) ;
write_c0_conf ( cfg | R30XX_CONF_HALT ) ;
}
static void r39xx_wait ( void )
{
2006-06-07 20:09:01 +04:00
local_irq_disable ( ) ;
if ( ! need_resched ( ) )
write_c0_conf ( read_c0_conf ( ) | TX39_CONF_HALT ) ;
local_irq_enable ( ) ;
2005-04-17 02:20:36 +04:00
}
2007-11-11 20:05:18 +03:00
extern void r4k_wait ( void ) ;
2006-06-07 20:09:01 +04:00
/*
* This variant is preferable as it allows testing need_resched and going to
* sleep depending on the outcome atomically . Unfortunately the " It is
* implementation - dependent whether the pipeline restarts when a non - enabled
* interrupt is requested " restriction in the MIPS32/MIPS64 architecture makes
* using this version a gamble .
*/
2008-09-09 23:48:52 +04:00
void r4k_wait_irqoff ( void )
2006-06-07 20:09:01 +04:00
{
local_irq_disable ( ) ;
if ( ! need_resched ( ) )
2008-09-09 23:48:52 +04:00
__asm__ ( " .set push \n "
" .set mips3 \n "
2006-06-07 20:09:01 +04:00
" wait \n "
2008-09-09 23:48:52 +04:00
" .set pop \n " ) ;
2006-06-07 20:09:01 +04:00
local_irq_enable ( ) ;
2008-09-09 23:48:52 +04:00
__asm__ ( " .globl __pastwait \n "
" __pastwait: \n " ) ;
2005-04-17 02:20:36 +04:00
}
2007-07-17 21:49:48 +04:00
/*
* The RM7000 variant has to handle erratum 38. The workaround is to not
* have any pending stores when the WAIT instruction is executed .
*/
static void rm7k_wait_irqoff ( void )
{
local_irq_disable ( ) ;
if ( ! need_resched ( ) )
__asm__ (
" .set push \n "
" .set mips3 \n "
" .set noat \n "
" mfc0 $1, $12 \n "
" sync \n "
" mtc0 $1, $12 # stalls until W stage \n "
" wait \n "
" mtc0 $1, $12 # stalls until W stage \n "
" .set pop \n " ) ;
local_irq_enable ( ) ;
}
2009-08-22 20:09:27 +04:00
/*
* The Au1xxx wait is available only if using 32 khz counter or
* external timer source , but specifically not CP0 Counter .
* alchemy / common / time . c may override cpu_wait !
*/
2005-04-07 04:42:10 +04:00
static void au1k_wait ( void )
2005-04-17 02:20:36 +04:00
{
2006-06-07 20:09:01 +04:00
__asm__ ( " .set mips3 \n "
" cache 0x14, 0(%0) \n "
" cache 0x14, 32(%0) \n "
" sync \n "
" nop \n "
" wait \n "
" nop \n "
" nop \n "
" nop \n "
" nop \n "
" .set mips0 \n "
2005-05-25 17:32:49 +04:00
: : " r " ( au1k_wait ) ) ;
2005-04-17 02:20:36 +04:00
}
2009-09-17 04:25:07 +04:00
static int __initdata nowait ;
2005-07-13 23:22:45 +04:00
2007-02-17 19:02:14 +03:00
static int __init wait_disable ( char * s )
2005-07-13 23:22:45 +04:00
{
nowait = 1 ;
return 1 ;
}
__setup ( " nowait " , wait_disable ) ;
2010-05-03 01:43:52 +04:00
static int __cpuinitdata mips_fpu_disabled ;
static int __init fpu_disable ( char * s )
{
cpu_data [ 0 ] . options & = ~ MIPS_CPU_FPU ;
mips_fpu_disabled = 1 ;
return 1 ;
}
__setup ( " nofpu " , fpu_disable ) ;
int __cpuinitdata mips_dsp_disabled ;
static int __init dsp_disable ( char * s )
{
cpu_data [ 0 ] . ases & = ~ MIPS_ASE_DSP ;
mips_dsp_disabled = 1 ;
return 1 ;
}
__setup ( " nodsp " , dsp_disable ) ;
2007-11-11 20:05:18 +03:00
void __init check_wait ( void )
2005-04-17 02:20:36 +04:00
{
struct cpuinfo_mips * c = & current_cpu_data ;
2005-07-13 23:22:45 +04:00
if ( nowait ) {
2006-11-30 04:14:44 +03:00
printk ( " Wait instruction disabled. \n " ) ;
2005-07-13 23:22:45 +04:00
return ;
}
2005-04-17 02:20:36 +04:00
switch ( c - > cputype ) {
case CPU_R3081 :
case CPU_R3081E :
cpu_wait = r3081_wait ;
break ;
case CPU_TX3927 :
cpu_wait = r39xx_wait ;
break ;
case CPU_R4200 :
/* case CPU_R4300: */
case CPU_R4600 :
case CPU_R4640 :
case CPU_R4650 :
case CPU_R4700 :
case CPU_R5000 :
2009-03-03 12:05:51 +03:00
case CPU_R5500 :
2005-04-17 02:20:36 +04:00
case CPU_NEVADA :
case CPU_4KC :
case CPU_4KEC :
case CPU_4KSC :
case CPU_5KC :
case CPU_25KF :
2007-06-21 03:22:34 +04:00
case CPU_PR4450 :
2010-10-17 01:22:30 +04:00
case CPU_BMIPS3300 :
case CPU_BMIPS4350 :
case CPU_BMIPS4380 :
case CPU_BMIPS5000 :
2008-12-12 02:33:26 +03:00
case CPU_CAVIUM_OCTEON :
2010-02-11 02:12:48 +03:00
case CPU_CAVIUM_OCTEON_PLUS :
2010-10-08 03:03:45 +04:00
case CPU_CAVIUM_OCTEON2 :
2010-07-17 15:07:51 +04:00
case CPU_JZRISC :
2007-06-21 03:22:34 +04:00
cpu_wait = r4k_wait ;
break ;
2007-07-17 21:49:48 +04:00
case CPU_RM7000 :
cpu_wait = rm7k_wait_irqoff ;
break ;
2007-06-21 03:22:34 +04:00
case CPU_24K :
2005-07-12 20:12:05 +04:00
case CPU_34K :
2008-04-28 20:14:26 +04:00
case CPU_1004K :
2007-06-21 03:22:34 +04:00
cpu_wait = r4k_wait ;
if ( read_c0_config7 ( ) & MIPS_CONF7_WII )
cpu_wait = r4k_wait_irqoff ;
break ;
2006-05-02 17:08:46 +04:00
case CPU_74K :
2005-04-17 02:20:36 +04:00
cpu_wait = r4k_wait ;
2007-06-21 03:22:34 +04:00
if ( ( c - > processor_id & 0xff ) > = PRID_REV_ENCODE_332 ( 2 , 1 , 0 ) )
cpu_wait = r4k_wait_irqoff ;
2005-04-17 02:20:36 +04:00
break ;
2007-06-21 03:22:34 +04:00
2006-06-07 20:09:01 +04:00
case CPU_TX49XX :
cpu_wait = r4k_wait_irqoff ;
break ;
2009-03-25 19:49:28 +03:00
case CPU_ALCHEMY :
2008-12-21 11:26:23 +03:00
cpu_wait = au1k_wait ;
2005-04-17 02:20:36 +04:00
break ;
2007-06-12 16:04:09 +04:00
case CPU_20KC :
/*
* WAIT on Rev1 .0 has E1 , E2 , E3 and E16 .
* WAIT on Rev2 .0 and Rev3 .0 has E16 .
* Rev3 .1 WAIT is nop , why bother
*/
if ( ( c - > processor_id & 0xff ) < = 0x64 )
break ;
2007-09-14 22:08:43 +04:00
/*
* Another rev is incremeting c0_count at a reduced clock
* rate while in WAIT mode . So we basically have the choice
* between using the cp0 timer as clocksource or avoiding
* the WAIT instruction . Until more details are known ,
* disable the use of WAIT for 20 Kc entirely .
cpu_wait = r4k_wait ;
*/
2007-06-12 16:04:09 +04:00
break ;
2006-06-02 14:48:11 +04:00
case CPU_RM9000 :
2006-11-30 04:14:44 +03:00
if ( ( c - > processor_id & 0x00ff ) > = 0x40 )
2006-06-02 14:48:11 +04:00
cpu_wait = r4k_wait ;
break ;
2005-04-17 02:20:36 +04:00
default :
break ;
}
}
2007-06-15 01:55:31 +04:00
static inline void check_errata ( void )
{
struct cpuinfo_mips * c = & current_cpu_data ;
switch ( c - > cputype ) {
case CPU_34K :
/*
* Erratum " RPS May Cause Incorrect Instruction Execution "
* This code only handles VPE0 , any SMP / SMTC / RTOS code
* making use of VPE1 will be responsable for that VPE .
*/
if ( ( c - > processor_id & PRID_REV_MASK ) < = PRID_REV_34K_V1_0_2 )
write_c0_config7 ( read_c0_config7 ( ) | MIPS_CONF7_RPS ) ;
break ;
default :
break ;
}
}
2005-04-17 02:20:36 +04:00
void __init check_bugs32 ( void )
{
2007-06-15 01:55:31 +04:00
check_errata ( ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Probe whether cpu has config register by trying to play with
* alternate cache bit and see whether it matters .
* It ' s used by cpu_probe to distinguish between R3000A and R3081 .
*/
static inline int cpu_has_confreg ( void )
{
# ifdef CONFIG_CPU_R3000
extern unsigned long r3k_cache_size ( unsigned long ) ;
unsigned long size1 , size2 ;
unsigned long cfg = read_c0_conf ( ) ;
size1 = r3k_cache_size ( ST0_ISC ) ;
write_c0_conf ( cfg ^ R30XX_CONF_AC ) ;
size2 = r3k_cache_size ( ST0_ISC ) ;
write_c0_conf ( cfg ) ;
return size1 ! = size2 ;
# else
return 0 ;
# endif
}
2011-04-18 22:37:55 +04:00
static inline void set_elf_platform ( int cpu , const char * plat )
{
if ( cpu = = 0 )
__elf_platform = plat ;
}
2005-04-17 02:20:36 +04:00
/*
* Get the FPU Implementation / Revision .
*/
static inline unsigned long cpu_get_fpu_id ( void )
{
unsigned long tmp , fpu_id ;
tmp = read_c0_status ( ) ;
__enable_fpu ( ) ;
fpu_id = read_32bit_cp1_register ( CP1_REVISION ) ;
write_c0_status ( tmp ) ;
return fpu_id ;
}
/*
* Check the CPU has an FPU the official way .
*/
static inline int __cpu_has_fpu ( void )
{
return ( ( cpu_get_fpu_id ( ) & 0xff00 ) ! = FPIR_IMP_NONE ) ;
}
2010-02-02 19:52:20 +03:00
static inline void cpu_probe_vmbits ( struct cpuinfo_mips * c )
{
# ifdef __NEED_VMBITS_PROBE
2010-02-08 23:27:00 +03:00
write_c0_entryhi ( 0x3fffffffffffe000ULL ) ;
2010-02-02 19:52:20 +03:00
back_to_back_c0_hazard ( ) ;
2010-02-08 23:27:00 +03:00
c - > vmbits = fls64 ( read_c0_entryhi ( ) & 0x3fffffffffffe000ULL ) ;
2010-02-02 19:52:20 +03:00
# endif
}
2005-10-01 16:06:32 +04:00
# define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
2005-04-17 02:20:36 +04:00
| MIPS_CPU_COUNTER )
2008-10-30 16:38:45 +03:00
static inline void cpu_probe_legacy ( struct cpuinfo_mips * c , unsigned int cpu )
2005-04-17 02:20:36 +04:00
{
switch ( c - > processor_id & 0xff00 ) {
case PRID_IMP_R2000 :
c - > cputype = CPU_R2000 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R2000 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_I ;
2005-10-01 16:06:32 +04:00
c - > options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
MIPS_CPU_NOFPUEX ;
2005-04-17 02:20:36 +04:00
if ( __cpu_has_fpu ( ) )
c - > options | = MIPS_CPU_FPU ;
c - > tlbsize = 64 ;
break ;
case PRID_IMP_R3000 :
2008-10-30 16:38:45 +03:00
if ( ( c - > processor_id & 0xff ) = = PRID_REV_R3000A ) {
if ( cpu_has_confreg ( ) ) {
2005-04-17 02:20:36 +04:00
c - > cputype = CPU_R3081E ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R3081 " ;
} else {
2005-04-17 02:20:36 +04:00
c - > cputype = CPU_R3000A ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R3000A " ;
}
break ;
} else {
2005-04-17 02:20:36 +04:00
c - > cputype = CPU_R3000 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R3000 " ;
}
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_I ;
2005-10-01 16:06:32 +04:00
c - > options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
MIPS_CPU_NOFPUEX ;
2005-04-17 02:20:36 +04:00
if ( __cpu_has_fpu ( ) )
c - > options | = MIPS_CPU_FPU ;
c - > tlbsize = 64 ;
break ;
case PRID_IMP_R4000 :
if ( read_c0_config ( ) & CONF_SC ) {
2008-10-30 16:38:45 +03:00
if ( ( c - > processor_id & 0xff ) > = PRID_REV_R4400 ) {
2005-04-17 02:20:36 +04:00
c - > cputype = CPU_R4400PC ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R4400PC " ;
} else {
2005-04-17 02:20:36 +04:00
c - > cputype = CPU_R4000PC ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R4000PC " ;
}
2005-04-17 02:20:36 +04:00
} else {
2008-10-30 16:38:45 +03:00
if ( ( c - > processor_id & 0xff ) > = PRID_REV_R4400 ) {
2005-04-17 02:20:36 +04:00
c - > cputype = CPU_R4400SC ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R4400SC " ;
} else {
2005-04-17 02:20:36 +04:00
c - > cputype = CPU_R4000SC ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R4000SC " ;
}
2005-04-17 02:20:36 +04:00
}
c - > isa_level = MIPS_CPU_ISA_III ;
c - > options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_WATCH | MIPS_CPU_VCE |
MIPS_CPU_LLSC ;
c - > tlbsize = 48 ;
break ;
case PRID_IMP_VR41XX :
switch ( c - > processor_id & 0xf0 ) {
case PRID_REV_VR4111 :
c - > cputype = CPU_VR4111 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " NEC VR4111 " ;
2005-04-17 02:20:36 +04:00
break ;
case PRID_REV_VR4121 :
c - > cputype = CPU_VR4121 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " NEC VR4121 " ;
2005-04-17 02:20:36 +04:00
break ;
case PRID_REV_VR4122 :
2008-10-30 16:38:45 +03:00
if ( ( c - > processor_id & 0xf ) < 0x3 ) {
2005-04-17 02:20:36 +04:00
c - > cputype = CPU_VR4122 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " NEC VR4122 " ;
} else {
2005-04-17 02:20:36 +04:00
c - > cputype = CPU_VR4181A ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " NEC VR4181A " ;
}
2005-04-17 02:20:36 +04:00
break ;
case PRID_REV_VR4130 :
2008-10-30 16:38:45 +03:00
if ( ( c - > processor_id & 0xf ) < 0x4 ) {
2005-04-17 02:20:36 +04:00
c - > cputype = CPU_VR4131 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " NEC VR4131 " ;
} else {
2005-04-17 02:20:36 +04:00
c - > cputype = CPU_VR4133 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " NEC VR4133 " ;
}
2005-04-17 02:20:36 +04:00
break ;
default :
printk ( KERN_INFO " Unexpected CPU of NEC VR4100 series \n " ) ;
c - > cputype = CPU_VR41XX ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " NEC Vr41xx " ;
2005-04-17 02:20:36 +04:00
break ;
}
c - > isa_level = MIPS_CPU_ISA_III ;
c - > options = R4K_OPTS ;
c - > tlbsize = 32 ;
break ;
case PRID_IMP_R4300 :
c - > cputype = CPU_R4300 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R4300 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_III ;
c - > options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC ;
c - > tlbsize = 32 ;
break ;
case PRID_IMP_R4600 :
c - > cputype = CPU_R4600 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R4600 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_III ;
2005-07-28 01:48:12 +04:00
c - > options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC ;
2005-04-17 02:20:36 +04:00
c - > tlbsize = 48 ;
break ;
#if 0
case PRID_IMP_R4650 :
/*
* This processor doesn ' t have an MMU , so it ' s not
* " real easy " to run Linux on it . It is left purely
* for documentation . Commented out because it shares
* it ' s c0_prid id number with the TX3900 .
*/
2006-03-11 11:18:41 +03:00
c - > cputype = CPU_R4650 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R4650 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_III ;
c - > options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC ;
c - > tlbsize = 48 ;
break ;
# endif
case PRID_IMP_TX39 :
c - > isa_level = MIPS_CPU_ISA_I ;
2005-10-01 16:06:32 +04:00
c - > options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE ;
2005-04-17 02:20:36 +04:00
if ( ( c - > processor_id & 0xf0 ) = = ( PRID_REV_TX3927 & 0xf0 ) ) {
c - > cputype = CPU_TX3927 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " TX3927 " ;
2005-04-17 02:20:36 +04:00
c - > tlbsize = 64 ;
} else {
switch ( c - > processor_id & 0xff ) {
case PRID_REV_TX3912 :
c - > cputype = CPU_TX3912 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " TX3912 " ;
2005-04-17 02:20:36 +04:00
c - > tlbsize = 32 ;
break ;
case PRID_REV_TX3922 :
c - > cputype = CPU_TX3922 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " TX3922 " ;
2005-04-17 02:20:36 +04:00
c - > tlbsize = 64 ;
break ;
}
}
break ;
case PRID_IMP_R4700 :
c - > cputype = CPU_R4700 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R4700 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_III ;
c - > options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC ;
c - > tlbsize = 48 ;
break ;
case PRID_IMP_TX49 :
c - > cputype = CPU_TX49XX ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R49XX " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_III ;
c - > options = R4K_OPTS | MIPS_CPU_LLSC ;
if ( ! ( c - > processor_id & 0x08 ) )
c - > options | = MIPS_CPU_FPU | MIPS_CPU_32FPR ;
c - > tlbsize = 48 ;
break ;
case PRID_IMP_R5000 :
c - > cputype = CPU_R5000 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R5000 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_IV ;
c - > options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC ;
c - > tlbsize = 48 ;
break ;
case PRID_IMP_R5432 :
c - > cputype = CPU_R5432 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R5432 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_IV ;
c - > options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_WATCH | MIPS_CPU_LLSC ;
c - > tlbsize = 48 ;
break ;
case PRID_IMP_R5500 :
c - > cputype = CPU_R5500 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R5500 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_IV ;
c - > options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_WATCH | MIPS_CPU_LLSC ;
c - > tlbsize = 48 ;
break ;
case PRID_IMP_NEVADA :
c - > cputype = CPU_NEVADA ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " Nevada " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_IV ;
c - > options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_DIVEC | MIPS_CPU_LLSC ;
c - > tlbsize = 48 ;
break ;
case PRID_IMP_R6000 :
c - > cputype = CPU_R6000 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R6000 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_II ;
c - > options = MIPS_CPU_TLB | MIPS_CPU_FPU |
MIPS_CPU_LLSC ;
c - > tlbsize = 32 ;
break ;
case PRID_IMP_R6000A :
c - > cputype = CPU_R6000A ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R6000A " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_II ;
c - > options = MIPS_CPU_TLB | MIPS_CPU_FPU |
MIPS_CPU_LLSC ;
c - > tlbsize = 32 ;
break ;
case PRID_IMP_RM7000 :
c - > cputype = CPU_RM7000 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " RM7000 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_IV ;
c - > options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC ;
/*
* Undocumented RM7000 : Bit 29 in the info register of
* the RM7000 v2 .0 indicates if the TLB has 48 or 64
* entries .
*
* 29 1 = > 64 entry JTLB
* 0 = > 48 entry JTLB
*/
c - > tlbsize = ( read_c0_info ( ) & ( 1 < < 29 ) ) ? 64 : 48 ;
break ;
case PRID_IMP_RM9000 :
c - > cputype = CPU_RM9000 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " RM9000 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_IV ;
c - > options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC ;
/*
* Bit 29 in the info register of the RM9000
* indicates if the TLB has 48 or 64 entries .
*
* 29 1 = > 64 entry JTLB
* 0 = > 48 entry JTLB
*/
c - > tlbsize = ( read_c0_info ( ) & ( 1 < < 29 ) ) ? 64 : 48 ;
break ;
case PRID_IMP_R8000 :
c - > cputype = CPU_R8000 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " RM8000 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_IV ;
c - > options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC ;
c - > tlbsize = 384 ; /* has weird TLB: 3-way x 128 */
break ;
case PRID_IMP_R10000 :
c - > cputype = CPU_R10000 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R10000 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_IV ;
2005-11-22 20:53:59 +03:00
c - > options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
2005-04-17 02:20:36 +04:00
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
MIPS_CPU_LLSC ;
c - > tlbsize = 64 ;
break ;
case PRID_IMP_R12000 :
c - > cputype = CPU_R12000 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R12000 " ;
2005-04-17 02:20:36 +04:00
c - > isa_level = MIPS_CPU_ISA_IV ;
2005-11-22 20:53:59 +03:00
c - > options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
2005-04-17 02:20:36 +04:00
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
MIPS_CPU_LLSC ;
c - > tlbsize = 64 ;
break ;
2006-05-17 06:23:59 +04:00
case PRID_IMP_R14000 :
c - > cputype = CPU_R14000 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " R14000 " ;
2006-05-17 06:23:59 +04:00
c - > isa_level = MIPS_CPU_ISA_IV ;
c - > options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
MIPS_CPU_LLSC ;
c - > tlbsize = 64 ;
break ;
2007-06-06 10:52:43 +04:00
case PRID_IMP_LOONGSON2 :
c - > cputype = CPU_LOONGSON2 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " ICT Loongson-2 " ;
2011-04-16 22:29:29 +04:00
switch ( c - > processor_id & PRID_REV_MASK ) {
case PRID_REV_LOONGSON2E :
set_elf_platform ( cpu , " loongson2e " ) ;
break ;
case PRID_REV_LOONGSON2F :
set_elf_platform ( cpu , " loongson2f " ) ;
break ;
}
2007-06-06 10:52:43 +04:00
c - > isa_level = MIPS_CPU_ISA_III ;
c - > options = R4K_OPTS |
MIPS_CPU_FPU | MIPS_CPU_LLSC |
MIPS_CPU_32FPR ;
c - > tlbsize = 64 ;
break ;
2005-04-17 02:20:36 +04:00
}
}
2008-03-08 12:56:28 +03:00
static char unknown_isa [ ] __cpuinitdata = KERN_ERR \
2005-12-08 17:04:24 +03:00
" Unsupported ISA type, c0.config0: %d. " ;
2005-05-05 20:45:59 +04:00
static inline unsigned int decode_config0 ( struct cpuinfo_mips * c )
2005-04-17 02:20:36 +04:00
{
2005-05-05 20:45:59 +04:00
unsigned int config0 ;
int isa ;
2005-04-17 02:20:36 +04:00
2005-05-05 20:45:59 +04:00
config0 = read_c0_config ( ) ;
if ( ( ( config0 & MIPS_CONF_MT ) > > 7 ) = = 1 )
2005-10-01 16:06:32 +04:00
c - > options | = MIPS_CPU_TLB ;
2005-05-05 20:45:59 +04:00
isa = ( config0 & MIPS_CONF_AT ) > > 13 ;
switch ( isa ) {
case 0 :
2006-07-03 16:30:01 +04:00
switch ( ( config0 & MIPS_CONF_AR ) > > 10 ) {
2005-12-08 17:04:24 +03:00
case 0 :
c - > isa_level = MIPS_CPU_ISA_M32R1 ;
break ;
case 1 :
c - > isa_level = MIPS_CPU_ISA_M32R2 ;
break ;
default :
goto unknown ;
}
2005-05-05 20:45:59 +04:00
break ;
case 2 :
2006-07-03 16:30:01 +04:00
switch ( ( config0 & MIPS_CONF_AR ) > > 10 ) {
2005-12-08 17:04:24 +03:00
case 0 :
c - > isa_level = MIPS_CPU_ISA_M64R1 ;
break ;
case 1 :
c - > isa_level = MIPS_CPU_ISA_M64R2 ;
break ;
default :
goto unknown ;
}
2005-05-05 20:45:59 +04:00
break ;
default :
2005-12-08 17:04:24 +03:00
goto unknown ;
2005-05-05 20:45:59 +04:00
}
return config0 & MIPS_CONF_M ;
2005-12-08 17:04:24 +03:00
unknown :
panic ( unknown_isa , config0 ) ;
2005-05-05 20:45:59 +04:00
}
static inline unsigned int decode_config1 ( struct cpuinfo_mips * c )
{
unsigned int config1 ;
2005-04-17 02:20:36 +04:00
config1 = read_c0_config1 ( ) ;
2005-05-05 20:45:59 +04:00
if ( config1 & MIPS_CONF1_MD )
c - > ases | = MIPS_ASE_MDMX ;
if ( config1 & MIPS_CONF1_WR )
2005-04-17 02:20:36 +04:00
c - > options | = MIPS_CPU_WATCH ;
2005-05-05 20:45:59 +04:00
if ( config1 & MIPS_CONF1_CA )
c - > ases | = MIPS_ASE_MIPS16 ;
if ( config1 & MIPS_CONF1_EP )
2005-04-17 02:20:36 +04:00
c - > options | = MIPS_CPU_EJTAG ;
2005-05-05 20:45:59 +04:00
if ( config1 & MIPS_CONF1_FP ) {
2005-04-17 02:20:36 +04:00
c - > options | = MIPS_CPU_FPU ;
c - > options | = MIPS_CPU_32FPR ;
}
2005-05-05 20:45:59 +04:00
if ( cpu_has_tlb )
c - > tlbsize = ( ( config1 & MIPS_CONF1_TLBS ) > > 25 ) + 1 ;
return config1 & MIPS_CONF_M ;
}
static inline unsigned int decode_config2 ( struct cpuinfo_mips * c )
{
unsigned int config2 ;
config2 = read_c0_config2 ( ) ;
if ( config2 & MIPS_CONF2_SL )
c - > scache . flags & = ~ MIPS_CACHE_NOT_PRESENT ;
return config2 & MIPS_CONF_M ;
}
static inline unsigned int decode_config3 ( struct cpuinfo_mips * c )
{
unsigned int config3 ;
config3 = read_c0_config3 ( ) ;
if ( config3 & MIPS_CONF3_SM )
c - > ases | = MIPS_ASE_SMARTMIPS ;
2005-05-31 15:49:19 +04:00
if ( config3 & MIPS_CONF3_DSP )
c - > ases | = MIPS_ASE_DSP ;
2005-07-14 11:34:18 +04:00
if ( config3 & MIPS_CONF3_VINT )
c - > options | = MIPS_CPU_VINT ;
if ( config3 & MIPS_CONF3_VEIC )
c - > options | = MIPS_CPU_VEIC ;
if ( config3 & MIPS_CONF3_MT )
2007-02-05 03:10:11 +03:00
c - > ases | = MIPS_ASE_MIPSMT ;
2007-07-10 20:33:02 +04:00
if ( config3 & MIPS_CONF3_ULRI )
c - > options | = MIPS_CPU_ULRI ;
2005-05-05 20:45:59 +04:00
return config3 & MIPS_CONF_M ;
}
2010-01-23 01:41:15 +03:00
static inline unsigned int decode_config4 ( struct cpuinfo_mips * c )
{
unsigned int config4 ;
config4 = read_c0_config4 ( ) ;
if ( ( config4 & MIPS_CONF4_MMUEXTDEF ) = = MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT
& & cpu_has_tlb )
c - > tlbsize + = ( config4 & MIPS_CONF4_MMUSIZEEXT ) * 0x40 ;
2010-12-22 01:19:09 +03:00
c - > kscratch_mask = ( config4 > > 16 ) & 0xff ;
2010-01-23 01:41:15 +03:00
return config4 & MIPS_CONF_M ;
}
2008-03-08 12:56:28 +03:00
static void __cpuinit decode_configs ( struct cpuinfo_mips * c )
2005-05-05 20:45:59 +04:00
{
2008-10-29 15:33:34 +03:00
int ok ;
2005-05-05 20:45:59 +04:00
/* MIPS32 or MIPS64 compliant CPU. */
2005-10-01 16:06:32 +04:00
c - > options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER |
MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK ;
2005-05-05 20:45:59 +04:00
2005-04-17 02:20:36 +04:00
c - > scache . flags = MIPS_CACHE_NOT_PRESENT ;
2008-10-29 15:33:34 +03:00
ok = decode_config0 ( c ) ; /* Read Config registers. */
BUG_ON ( ! ok ) ; /* Arch spec violation! */
if ( ok )
ok = decode_config1 ( c ) ;
if ( ok )
ok = decode_config2 ( c ) ;
if ( ok )
ok = decode_config3 ( c ) ;
2010-01-23 01:41:15 +03:00
if ( ok )
ok = decode_config4 ( c ) ;
2008-10-29 15:33:34 +03:00
mips_probe_watch_registers ( c ) ;
2010-07-27 01:29:37 +04:00
if ( cpu_has_mips_r2 )
c - > core = read_c0_ebase ( ) & 0x3ff ;
2005-04-17 02:20:36 +04:00
}
2008-10-30 16:38:45 +03:00
static inline void cpu_probe_mips ( struct cpuinfo_mips * c , unsigned int cpu )
2005-04-17 02:20:36 +04:00
{
2005-05-05 20:45:59 +04:00
decode_configs ( c ) ;
2005-04-17 02:20:36 +04:00
switch ( c - > processor_id & 0xff00 ) {
case PRID_IMP_4KC :
c - > cputype = CPU_4KC ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " MIPS 4Kc " ;
2005-04-17 02:20:36 +04:00
break ;
case PRID_IMP_4KEC :
2005-04-09 00:36:05 +04:00
case PRID_IMP_4KECR2 :
c - > cputype = CPU_4KEC ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " MIPS 4KEc " ;
2005-04-09 00:36:05 +04:00
break ;
2005-04-17 02:20:36 +04:00
case PRID_IMP_4KSC :
2005-10-04 18:01:26 +04:00
case PRID_IMP_4KSD :
2005-04-17 02:20:36 +04:00
c - > cputype = CPU_4KSC ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " MIPS 4KSc " ;
2005-04-17 02:20:36 +04:00
break ;
case PRID_IMP_5KC :
c - > cputype = CPU_5KC ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " MIPS 5Kc " ;
2005-04-17 02:20:36 +04:00
break ;
case PRID_IMP_20KC :
c - > cputype = CPU_20KC ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " MIPS 20Kc " ;
2005-04-17 02:20:36 +04:00
break ;
case PRID_IMP_24K :
2005-05-31 15:49:19 +04:00
case PRID_IMP_24KE :
2005-04-17 02:20:36 +04:00
c - > cputype = CPU_24K ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " MIPS 24Kc " ;
2005-04-17 02:20:36 +04:00
break ;
case PRID_IMP_25KF :
c - > cputype = CPU_25KF ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " MIPS 25Kc " ;
2005-04-17 02:20:36 +04:00
break ;
2005-07-12 20:12:05 +04:00
case PRID_IMP_34K :
c - > cputype = CPU_34K ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " MIPS 34Kc " ;
2005-07-12 20:12:05 +04:00
break ;
2006-05-02 17:08:46 +04:00
case PRID_IMP_74K :
c - > cputype = CPU_74K ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " MIPS 74Kc " ;
2006-05-02 17:08:46 +04:00
break ;
2008-04-28 20:14:26 +04:00
case PRID_IMP_1004K :
c - > cputype = CPU_1004K ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " MIPS 1004Kc " ;
2008-04-28 20:14:26 +04:00
break ;
2005-04-17 02:20:36 +04:00
}
2007-09-13 15:32:02 +04:00
spram_config ( ) ;
2005-04-17 02:20:36 +04:00
}
2008-10-30 16:38:45 +03:00
static inline void cpu_probe_alchemy ( struct cpuinfo_mips * c , unsigned int cpu )
2005-04-17 02:20:36 +04:00
{
2005-05-05 20:45:59 +04:00
decode_configs ( c ) ;
2005-04-17 02:20:36 +04:00
switch ( c - > processor_id & 0xff00 ) {
case PRID_IMP_AU1_REV1 :
case PRID_IMP_AU1_REV2 :
2009-03-25 19:49:28 +03:00
c - > cputype = CPU_ALCHEMY ;
2005-04-17 02:20:36 +04:00
switch ( ( c - > processor_id > > 24 ) & 0xff ) {
case 0 :
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " Au1000 " ;
2005-04-17 02:20:36 +04:00
break ;
case 1 :
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " Au1500 " ;
2005-04-17 02:20:36 +04:00
break ;
case 2 :
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " Au1100 " ;
2005-04-17 02:20:36 +04:00
break ;
case 3 :
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " Au1550 " ;
2005-04-17 02:20:36 +04:00
break ;
2005-03-01 09:33:16 +03:00
case 4 :
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " Au1200 " ;
2009-03-25 19:49:28 +03:00
if ( ( c - > processor_id & 0xff ) = = 2 )
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " Au1250 " ;
2007-12-06 11:07:55 +03:00
break ;
case 5 :
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " Au1210 " ;
2005-03-01 09:33:16 +03:00
break ;
2005-04-17 02:20:36 +04:00
default :
2009-03-25 19:49:28 +03:00
__cpu_name [ cpu ] = " Au1xxx " ;
2005-04-17 02:20:36 +04:00
break ;
}
break ;
}
}
2008-10-30 16:38:45 +03:00
static inline void cpu_probe_sibyte ( struct cpuinfo_mips * c , unsigned int cpu )
2005-04-17 02:20:36 +04:00
{
2005-05-05 20:45:59 +04:00
decode_configs ( c ) ;
2005-10-01 16:06:32 +04:00
2005-04-17 02:20:36 +04:00
switch ( c - > processor_id & 0xff00 ) {
case PRID_IMP_SB1 :
c - > cputype = CPU_SB1 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " SiByte SB1 " ;
2005-04-17 02:20:36 +04:00
/* FPU in pass1 is known to have issues. */
2006-05-29 03:02:12 +04:00
if ( ( c - > processor_id & 0xff ) < 0x02 )
2006-01-29 21:42:08 +03:00
c - > options & = ~ ( MIPS_CPU_FPU | MIPS_CPU_32FPR ) ;
2005-04-17 02:20:36 +04:00
break ;
2005-10-20 10:56:20 +04:00
case PRID_IMP_SB1A :
c - > cputype = CPU_SB1A ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " SiByte SB1A " ;
2005-10-20 10:56:20 +04:00
break ;
2005-04-17 02:20:36 +04:00
}
}
2008-10-30 16:38:45 +03:00
static inline void cpu_probe_sandcraft ( struct cpuinfo_mips * c , unsigned int cpu )
2005-04-17 02:20:36 +04:00
{
2005-05-05 20:45:59 +04:00
decode_configs ( c ) ;
2005-04-17 02:20:36 +04:00
switch ( c - > processor_id & 0xff00 ) {
case PRID_IMP_SR71000 :
c - > cputype = CPU_SR71000 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " Sandcraft SR71000 " ;
2005-04-17 02:20:36 +04:00
c - > scache . ways = 8 ;
c - > tlbsize = 64 ;
break ;
}
}
2008-10-30 16:38:45 +03:00
static inline void cpu_probe_nxp ( struct cpuinfo_mips * c , unsigned int cpu )
2005-07-14 21:47:57 +04:00
{
decode_configs ( c ) ;
switch ( c - > processor_id & 0xff00 ) {
case PRID_IMP_PR4450 :
c - > cputype = CPU_PR4450 ;
2008-10-30 16:38:45 +03:00
__cpu_name [ cpu ] = " Philips PR4450 " ;
2005-12-08 16:00:20 +03:00
c - > isa_level = MIPS_CPU_ISA_M32R1 ;
2005-07-14 21:47:57 +04:00
break ;
}
}
2008-10-30 16:38:45 +03:00
static inline void cpu_probe_broadcom ( struct cpuinfo_mips * c , unsigned int cpu )
2007-09-25 17:40:12 +04:00
{
decode_configs ( c ) ;
switch ( c - > processor_id & 0xff00 ) {
2010-11-23 21:26:45 +03:00
case PRID_IMP_BMIPS32_REV4 :
case PRID_IMP_BMIPS32_REV8 :
2010-10-17 01:22:30 +04:00
c - > cputype = CPU_BMIPS32 ;
__cpu_name [ cpu ] = " Broadcom BMIPS32 " ;
2011-04-16 22:29:28 +04:00
set_elf_platform ( cpu , " bmips32 " ) ;
2010-10-17 01:22:30 +04:00
break ;
case PRID_IMP_BMIPS3300 :
case PRID_IMP_BMIPS3300_ALT :
case PRID_IMP_BMIPS3300_BUG :
c - > cputype = CPU_BMIPS3300 ;
__cpu_name [ cpu ] = " Broadcom BMIPS3300 " ;
2011-04-16 22:29:28 +04:00
set_elf_platform ( cpu , " bmips3300 " ) ;
2010-10-17 01:22:30 +04:00
break ;
case PRID_IMP_BMIPS43XX : {
int rev = c - > processor_id & 0xff ;
if ( rev > = PRID_REV_BMIPS4380_LO & &
rev < = PRID_REV_BMIPS4380_HI ) {
c - > cputype = CPU_BMIPS4380 ;
__cpu_name [ cpu ] = " Broadcom BMIPS4380 " ;
2011-04-16 22:29:28 +04:00
set_elf_platform ( cpu , " bmips4380 " ) ;
2010-10-17 01:22:30 +04:00
} else {
c - > cputype = CPU_BMIPS4350 ;
__cpu_name [ cpu ] = " Broadcom BMIPS4350 " ;
2011-04-16 22:29:28 +04:00
set_elf_platform ( cpu , " bmips4350 " ) ;
2010-10-17 01:22:30 +04:00
}
2009-08-18 16:23:37 +04:00
break ;
2010-10-17 01:22:30 +04:00
}
case PRID_IMP_BMIPS5000 :
c - > cputype = CPU_BMIPS5000 ;
__cpu_name [ cpu ] = " Broadcom BMIPS5000 " ;
2011-04-16 22:29:28 +04:00
set_elf_platform ( cpu , " bmips5000 " ) ;
2010-10-17 01:22:30 +04:00
c - > options | = MIPS_CPU_ULRI ;
2009-08-18 16:23:37 +04:00
break ;
2007-09-25 17:40:12 +04:00
}
}
2008-12-12 02:33:26 +03:00
static inline void cpu_probe_cavium ( struct cpuinfo_mips * c , unsigned int cpu )
{
decode_configs ( c ) ;
switch ( c - > processor_id & 0xff00 ) {
case PRID_IMP_CAVIUM_CN38XX :
case PRID_IMP_CAVIUM_CN31XX :
case PRID_IMP_CAVIUM_CN30XX :
2010-02-11 02:12:48 +03:00
c - > cputype = CPU_CAVIUM_OCTEON ;
__cpu_name [ cpu ] = " Cavium Octeon " ;
goto platform ;
2008-12-12 02:33:26 +03:00
case PRID_IMP_CAVIUM_CN58XX :
case PRID_IMP_CAVIUM_CN56XX :
case PRID_IMP_CAVIUM_CN50XX :
case PRID_IMP_CAVIUM_CN52XX :
2010-02-11 02:12:48 +03:00
c - > cputype = CPU_CAVIUM_OCTEON_PLUS ;
__cpu_name [ cpu ] = " Cavium Octeon+ " ;
platform :
2011-04-18 22:37:55 +04:00
set_elf_platform ( cpu , " octeon " ) ;
2008-12-12 02:33:26 +03:00
break ;
2010-10-08 03:03:45 +04:00
case PRID_IMP_CAVIUM_CN63XX :
c - > cputype = CPU_CAVIUM_OCTEON2 ;
__cpu_name [ cpu ] = " Cavium Octeon II " ;
2011-04-18 22:37:55 +04:00
set_elf_platform ( cpu , " octeon2 " ) ;
2010-10-08 03:03:45 +04:00
break ;
2008-12-12 02:33:26 +03:00
default :
printk ( KERN_INFO " Unknown Octeon chip! \n " ) ;
c - > cputype = CPU_UNKNOWN ;
break ;
}
}
2010-07-17 15:07:51 +04:00
static inline void cpu_probe_ingenic ( struct cpuinfo_mips * c , unsigned int cpu )
{
decode_configs ( c ) ;
/* JZRISC does not implement the CP0 counter. */
c - > options & = ~ MIPS_CPU_COUNTER ;
switch ( c - > processor_id & 0xff00 ) {
case PRID_IMP_JZRISC :
c - > cputype = CPU_JZRISC ;
__cpu_name [ cpu ] = " Ingenic JZRISC " ;
break ;
default :
panic ( " Unknown Ingenic Processor ID! " ) ;
break ;
}
}
2011-05-11 10:34:58 +04:00
static inline void cpu_probe_netlogic ( struct cpuinfo_mips * c , int cpu )
{
decode_configs ( c ) ;
c - > options = ( MIPS_CPU_TLB |
MIPS_CPU_4KEX |
MIPS_CPU_COUNTER |
MIPS_CPU_DIVEC |
MIPS_CPU_WATCH |
MIPS_CPU_EJTAG |
MIPS_CPU_LLSC ) ;
switch ( c - > processor_id & 0xff00 ) {
case PRID_IMP_NETLOGIC_XLR732 :
case PRID_IMP_NETLOGIC_XLR716 :
case PRID_IMP_NETLOGIC_XLR532 :
case PRID_IMP_NETLOGIC_XLR308 :
case PRID_IMP_NETLOGIC_XLR532C :
case PRID_IMP_NETLOGIC_XLR516C :
case PRID_IMP_NETLOGIC_XLR508C :
case PRID_IMP_NETLOGIC_XLR308C :
c - > cputype = CPU_XLR ;
__cpu_name [ cpu ] = " Netlogic XLR " ;
break ;
case PRID_IMP_NETLOGIC_XLS608 :
case PRID_IMP_NETLOGIC_XLS408 :
case PRID_IMP_NETLOGIC_XLS404 :
case PRID_IMP_NETLOGIC_XLS208 :
case PRID_IMP_NETLOGIC_XLS204 :
case PRID_IMP_NETLOGIC_XLS108 :
case PRID_IMP_NETLOGIC_XLS104 :
case PRID_IMP_NETLOGIC_XLS616B :
case PRID_IMP_NETLOGIC_XLS608B :
case PRID_IMP_NETLOGIC_XLS416B :
case PRID_IMP_NETLOGIC_XLS412B :
case PRID_IMP_NETLOGIC_XLS408B :
case PRID_IMP_NETLOGIC_XLS404B :
c - > cputype = CPU_XLR ;
__cpu_name [ cpu ] = " Netlogic XLS " ;
break ;
default :
printk ( KERN_INFO " Unknown Netlogic chip id [%02x]! \n " ,
c - > processor_id ) ;
c - > cputype = CPU_XLR ;
break ;
}
c - > isa_level = MIPS_CPU_ISA_M64R1 ;
c - > tlbsize = ( ( read_c0_config1 ( ) > > 25 ) & 0x3f ) + 1 ;
}
2010-10-14 22:32:33 +04:00
# ifdef CONFIG_64BIT
/* For use by uaccess.h */
u64 __ua_limit ;
EXPORT_SYMBOL ( __ua_limit ) ;
# endif
2007-10-12 02:46:17 +04:00
const char * __cpu_name [ NR_CPUS ] ;
2010-01-29 03:52:12 +03:00
const char * __elf_platform ;
2007-10-12 02:46:17 +04:00
2008-03-08 12:56:28 +03:00
__cpuinit void cpu_probe ( void )
2005-04-17 02:20:36 +04:00
{
struct cpuinfo_mips * c = & current_cpu_data ;
2007-10-12 02:46:17 +04:00
unsigned int cpu = smp_processor_id ( ) ;
2005-04-17 02:20:36 +04:00
c - > processor_id = PRID_IMP_UNKNOWN ;
c - > fpu_id = FPIR_IMP_NONE ;
c - > cputype = CPU_UNKNOWN ;
c - > processor_id = read_c0_prid ( ) ;
switch ( c - > processor_id & 0xff0000 ) {
case PRID_COMP_LEGACY :
2008-10-30 16:38:45 +03:00
cpu_probe_legacy ( c , cpu ) ;
2005-04-17 02:20:36 +04:00
break ;
case PRID_COMP_MIPS :
2008-10-30 16:38:45 +03:00
cpu_probe_mips ( c , cpu ) ;
2005-04-17 02:20:36 +04:00
break ;
case PRID_COMP_ALCHEMY :
2008-10-30 16:38:45 +03:00
cpu_probe_alchemy ( c , cpu ) ;
2005-04-17 02:20:36 +04:00
break ;
case PRID_COMP_SIBYTE :
2008-10-30 16:38:45 +03:00
cpu_probe_sibyte ( c , cpu ) ;
2005-04-17 02:20:36 +04:00
break ;
2007-09-25 17:40:12 +04:00
case PRID_COMP_BROADCOM :
2008-10-30 16:38:45 +03:00
cpu_probe_broadcom ( c , cpu ) ;
2007-09-25 17:40:12 +04:00
break ;
2005-04-17 02:20:36 +04:00
case PRID_COMP_SANDCRAFT :
2008-10-30 16:38:45 +03:00
cpu_probe_sandcraft ( c , cpu ) ;
2005-04-17 02:20:36 +04:00
break ;
2008-03-06 12:07:18 +03:00
case PRID_COMP_NXP :
2008-10-30 16:38:45 +03:00
cpu_probe_nxp ( c , cpu ) ;
2006-03-11 11:18:41 +03:00
break ;
2008-12-12 02:33:26 +03:00
case PRID_COMP_CAVIUM :
cpu_probe_cavium ( c , cpu ) ;
break ;
2010-07-17 15:07:51 +04:00
case PRID_COMP_INGENIC :
cpu_probe_ingenic ( c , cpu ) ;
break ;
2011-05-11 10:34:58 +04:00
case PRID_COMP_NETLOGIC :
cpu_probe_netlogic ( c , cpu ) ;
break ;
2005-04-17 02:20:36 +04:00
}
2007-10-08 18:11:51 +04:00
2008-10-30 16:38:45 +03:00
BUG_ON ( ! __cpu_name [ cpu ] ) ;
BUG_ON ( c - > cputype = = CPU_UNKNOWN ) ;
2007-10-08 18:11:51 +04:00
/*
* Platform code can force the cpu type to optimize code
* generation . In that case be sure the cpu type is correctly
* manually setup otherwise it could trigger some nasty bugs .
*/
BUG_ON ( current_cpu_type ( ) ! = c - > cputype ) ;
2010-05-03 01:43:52 +04:00
if ( mips_fpu_disabled )
c - > options & = ~ MIPS_CPU_FPU ;
if ( mips_dsp_disabled )
c - > ases & = ~ MIPS_ASE_DSP ;
2005-05-05 20:45:59 +04:00
if ( c - > options & MIPS_CPU_FPU ) {
2005-04-17 02:20:36 +04:00
c - > fpu_id = cpu_get_fpu_id ( ) ;
2005-05-05 20:45:59 +04:00
2005-12-08 16:00:20 +03:00
if ( c - > isa_level = = MIPS_CPU_ISA_M32R1 | |
2005-12-08 17:04:24 +03:00
c - > isa_level = = MIPS_CPU_ISA_M32R2 | |
c - > isa_level = = MIPS_CPU_ISA_M64R1 | |
c - > isa_level = = MIPS_CPU_ISA_M64R2 ) {
2005-05-05 20:45:59 +04:00
if ( c - > fpu_id & MIPS_FPIR_3D )
c - > ases | = MIPS_ASE_MIPS3D ;
}
}
2007-10-12 02:46:17 +04:00
2007-11-08 21:02:29 +03:00
if ( cpu_has_mips_r2 )
c - > srsets = ( ( read_c0_srsctl ( ) > > 26 ) & 0x0f ) + 1 ;
else
c - > srsets = 1 ;
2010-02-02 19:52:20 +03:00
cpu_probe_vmbits ( c ) ;
2010-10-14 22:32:33 +04:00
# ifdef CONFIG_64BIT
if ( cpu = = 0 )
__ua_limit = ~ ( ( 1ull < < cpu_vmbits ) - 1 ) ;
# endif
2005-04-17 02:20:36 +04:00
}
2008-03-08 12:56:28 +03:00
__cpuinit void cpu_report ( void )
2005-04-17 02:20:36 +04:00
{
struct cpuinfo_mips * c = & current_cpu_data ;
2007-10-12 02:46:17 +04:00
printk ( KERN_INFO " CPU revision is: %08x (%s) \n " ,
c - > processor_id , cpu_name_string ( ) ) ;
2005-04-17 02:20:36 +04:00
if ( c - > options & MIPS_CPU_FPU )
2007-10-12 02:46:17 +04:00
printk ( KERN_INFO " FPU revision is: %08x \n " , c - > fpu_id ) ;
2005-04-17 02:20:36 +04:00
}