2005-04-16 15:20:36 -07:00
/*
* Copyright ( C ) 1995 , 1996 , 2001 Ralf Baechle
2005-05-05 16:45:59 +00:00
* Copyright ( C ) 2001 , 2004 MIPS Technologies , Inc .
2013-01-22 12:59:30 +01:00
* Copyright ( C ) 2004 Maciej W . Rozycki
2005-04-16 15:20:36 -07:00
*/
# include <linux/delay.h>
# include <linux/kernel.h>
# include <linux/sched.h>
# include <linux/seq_file.h>
# include <asm/bootinfo.h>
# include <asm/cpu.h>
# include <asm/cpu-features.h>
2013-05-21 16:59:19 +02:00
# include <asm/idle.h>
2005-04-16 15:20:36 -07:00
# include <asm/mipsregs.h>
# include <asm/processor.h>
2013-04-11 05:34:59 +00:00
# include <asm/prom.h>
2005-04-16 15:20:36 -07:00
unsigned int vced_count , vcei_count ;
2013-10-16 17:10:07 +02:00
/*
* * No lock ; only written during early bootup by CPU 0.
* */
static RAW_NOTIFIER_HEAD ( proc_cpuinfo_chain ) ;
int __ref register_proc_cpuinfo_notifier ( struct notifier_block * nb )
{
return raw_notifier_chain_register ( & proc_cpuinfo_chain , nb ) ;
}
int proc_cpuinfo_notifier_call_chain ( unsigned long val , void * v )
{
return raw_notifier_call_chain ( & proc_cpuinfo_chain , val , v ) ;
}
2005-04-16 15:20:36 -07:00
static int show_cpuinfo ( struct seq_file * m , void * v )
{
2013-10-16 17:10:07 +02:00
struct proc_cpuinfo_notifier_args proc_cpuinfo_notifier_args ;
2005-04-16 15:20:36 -07:00
unsigned long n = ( unsigned long ) v - 1 ;
2006-10-08 01:15:02 +02:00
unsigned int version = cpu_data [ n ] . processor_id ;
unsigned int fp_vers = cpu_data [ n ] . fpu_id ;
2005-04-16 15:20:36 -07:00
char fmt [ 64 ] ;
2008-09-23 00:07:16 -07:00
int i ;
2005-04-16 15:20:36 -07:00
# ifdef CONFIG_SMP
2012-03-29 15:38:30 +10:30
if ( ! cpu_online ( n ) )
2005-04-16 15:20:36 -07:00
return 0 ;
# endif
/*
* For the first processor also print the system type
*/
2010-11-23 16:06:25 +01:00
if ( n = = 0 ) {
2005-04-16 15:20:36 -07:00
seq_printf ( m , " system type \t \t : %s \n " , get_system_type ( ) ) ;
2010-11-23 16:06:25 +01:00
if ( mips_get_machine_name ( ) )
seq_printf ( m , " machine \t \t \t : %s \n " ,
mips_get_machine_name ( ) ) ;
}
2005-04-16 15:20:36 -07:00
seq_printf ( m , " processor \t \t : %ld \n " , n ) ;
sprintf ( fmt , " cpu model \t \t : %%s V%%d.%%d%s \n " ,
2012-05-10 23:21:18 -05:00
cpu_data [ n ] . options & MIPS_CPU_FPU ? " FPU V%d.%d " : " " ) ;
2008-10-13 19:36:21 +02:00
seq_printf ( m , fmt , __cpu_name [ n ] ,
2012-05-10 23:21:18 -05:00
( version > > 4 ) & 0x0f , version & 0x0f ,
( fp_vers > > 4 ) & 0x0f , fp_vers & 0x0f ) ;
2009-02-28 09:44:28 +00:00
seq_printf ( m , " BogoMIPS \t \t : %u.%02u \n " ,
2012-05-10 23:21:18 -05:00
cpu_data [ n ] . udelay_val / ( 500000 / HZ ) ,
( cpu_data [ n ] . udelay_val / ( 5000 / HZ ) ) % 100 ) ;
2005-04-16 15:20:36 -07:00
seq_printf ( m , " wait instruction \t : %s \n " , cpu_wait ? " yes " : " no " ) ;
seq_printf ( m , " microsecond timers \t : %s \n " ,
2012-05-10 23:21:18 -05:00
cpu_has_counter ? " yes " : " no " ) ;
2006-10-08 01:15:02 +02:00
seq_printf ( m , " tlb_entries \t \t : %d \n " , cpu_data [ n ] . tlbsize ) ;
2005-04-16 15:20:36 -07:00
seq_printf ( m , " extra interrupt vector \t : %s \n " ,
2012-05-10 23:21:18 -05:00
cpu_has_divec ? " yes " : " no " ) ;
2008-09-23 00:07:16 -07:00
seq_printf ( m , " hardware watchpoint \t : %s " ,
2012-05-10 23:21:18 -05:00
cpu_has_watch ? " yes, " : " no \n " ) ;
2008-09-23 00:07:16 -07:00
if ( cpu_has_watch ) {
seq_printf ( m , " count: %d, address/irw mask: [ " ,
2012-05-10 23:21:18 -05:00
cpu_data [ n ] . watch_reg_count ) ;
2008-09-23 00:07:16 -07:00
for ( i = 0 ; i < cpu_data [ n ] . watch_reg_count ; i + + )
seq_printf ( m , " %s0x%04x " , i ? " , " : " " ,
2012-05-10 23:21:18 -05:00
cpu_data [ n ] . watch_reg_masks [ i ] ) ;
2008-09-23 00:07:16 -07:00
seq_printf ( m , " ] \n " ) ;
}
2013-12-31 01:26:31 +02:00
2014-11-14 10:10:02 +00:00
seq_printf ( m , " isa \t \t \t : " ) ;
2017-07-08 23:24:44 +01:00
if ( cpu_has_mips_1 )
2014-11-14 10:10:02 +00:00
seq_printf ( m , " mips1 " ) ;
2013-12-31 01:26:31 +02:00
if ( cpu_has_mips_2 )
seq_printf ( m , " %s " , " mips2 " ) ;
if ( cpu_has_mips_3 )
seq_printf ( m , " %s " , " mips3 " ) ;
if ( cpu_has_mips_4 )
seq_printf ( m , " %s " , " mips4 " ) ;
if ( cpu_has_mips_5 )
seq_printf ( m , " %s " , " mips5 " ) ;
if ( cpu_has_mips32r1 )
seq_printf ( m , " %s " , " mips32r1 " ) ;
if ( cpu_has_mips32r2 )
seq_printf ( m , " %s " , " mips32r2 " ) ;
2014-11-14 10:10:02 +00:00
if ( cpu_has_mips32r6 )
seq_printf ( m , " %s " , " mips32r6 " ) ;
2013-12-31 01:26:31 +02:00
if ( cpu_has_mips64r1 )
seq_printf ( m , " %s " , " mips64r1 " ) ;
if ( cpu_has_mips64r2 )
seq_printf ( m , " %s " , " mips64r2 " ) ;
2014-11-14 10:10:02 +00:00
if ( cpu_has_mips64r6 )
seq_printf ( m , " %s " , " mips64r6 " ) ;
2013-12-31 01:26:31 +02:00
seq_printf ( m , " \n " ) ;
2012-08-20 16:39:11 +02:00
seq_printf ( m , " ASEs implemented \t : " ) ;
if ( cpu_has_mips16 ) seq_printf ( m , " %s " , " mips16 " ) ;
2017-07-08 16:00:09 +01:00
if ( cpu_has_mips16e2 ) seq_printf ( m , " %s " , " mips16e2 " ) ;
2012-08-20 16:39:11 +02:00
if ( cpu_has_mdmx ) seq_printf ( m , " %s " , " mdmx " ) ;
if ( cpu_has_mips3d ) seq_printf ( m , " %s " , " mips3d " ) ;
if ( cpu_has_smartmips ) seq_printf ( m , " %s " , " smartmips " ) ;
if ( cpu_has_dsp ) seq_printf ( m , " %s " , " dsp " ) ;
if ( cpu_has_dsp2 ) seq_printf ( m , " %s " , " dsp2 " ) ;
2016-03-29 15:50:25 +01:00
if ( cpu_has_dsp3 ) seq_printf ( m , " %s " , " dsp3 " ) ;
2012-08-20 16:39:11 +02:00
if ( cpu_has_mipsmt ) seq_printf ( m , " %s " , " mt " ) ;
2012-12-07 03:51:35 +00:00
if ( cpu_has_mmips ) seq_printf ( m , " %s " , " micromips " ) ;
2013-02-16 23:42:43 +01:00
if ( cpu_has_vz ) seq_printf ( m , " %s " , " vz " ) ;
2014-01-27 15:23:10 +00:00
if ( cpu_has_msa ) seq_printf ( m , " %s " , " msa " ) ;
2014-01-27 15:10:40 +00:00
if ( cpu_has_eva ) seq_printf ( m , " %s " , " eva " ) ;
2014-07-14 12:43:28 +01:00
if ( cpu_has_htw ) seq_printf ( m , " %s " , " htw " ) ;
2015-02-26 18:16:38 -06:00
if ( cpu_has_xpa ) seq_printf ( m , " %s " , " xpa " ) ;
2012-08-20 16:39:11 +02:00
seq_printf ( m , " \n " ) ;
2013-03-25 13:27:11 -05:00
if ( cpu_has_mmips ) {
seq_printf ( m , " micromips kernel \t : %s \n " ,
( read_c0_config3 ( ) & MIPS_CONF3_ISA_OE ) ? " yes " : " no " ) ;
}
2007-11-08 18:02:29 +00:00
seq_printf ( m , " shadow register sets \t : %d \n " ,
2012-05-10 23:21:18 -05:00
cpu_data [ n ] . srsets ) ;
2010-12-21 14:19:09 -08:00
seq_printf ( m , " kscratch registers \t : %d \n " ,
2012-05-10 23:21:18 -05:00
hweight8 ( cpu_data [ n ] . kscratch_mask ) ) ;
2014-06-26 11:41:26 +08:00
seq_printf ( m , " package \t \t \t : %d \n " , cpu_data [ n ] . package ) ;
2007-03-02 20:42:04 +00:00
seq_printf ( m , " core \t \t \t : %d \n " , cpu_data [ n ] . core ) ;
2014-04-03 13:14:05 +02:00
2016-08-04 17:19:38 +01:00
# if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6)
if ( cpu_has_mipsmt )
seq_printf ( m , " VPE \t \t \t : %d \n " , cpu_data [ n ] . vpe_id ) ;
else if ( cpu_has_vp )
seq_printf ( m , " VP \t \t \t : %d \n " , cpu_data [ n ] . vpe_id ) ;
# endif
2005-04-16 15:20:36 -07:00
sprintf ( fmt , " VCE%%c exceptions \t \t : %s \n " ,
2012-05-10 23:21:18 -05:00
cpu_has_vce ? " %u " : " not available " ) ;
2005-04-16 15:20:36 -07:00
seq_printf ( m , fmt , ' D ' , vced_count ) ;
seq_printf ( m , fmt , ' I ' , vcei_count ) ;
2013-10-16 17:10:07 +02:00
proc_cpuinfo_notifier_args . m = m ;
proc_cpuinfo_notifier_args . n = n ;
raw_notifier_call_chain ( & proc_cpuinfo_chain , 0 ,
& proc_cpuinfo_notifier_args ) ;
2006-03-20 02:51:20 +00:00
seq_printf ( m , " \n " ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
static void * c_start ( struct seq_file * m , loff_t * pos )
{
unsigned long i = * pos ;
return i < NR_CPUS ? ( void * ) ( i + 1 ) : NULL ;
}
static void * c_next ( struct seq_file * m , void * v , loff_t * pos )
{
+ + * pos ;
return c_start ( m , pos ) ;
}
static void c_stop ( struct seq_file * m , void * v )
{
}
2008-01-22 20:42:33 +01:00
const struct seq_operations cpuinfo_op = {
2005-04-16 15:20:36 -07:00
. start = c_start ,
. next = c_next ,
. stop = c_stop ,
. show = show_cpuinfo ,
} ;