2005-06-24 09:01:16 +04:00
/*
2006-10-04 01:01:26 +04:00
* arch / xtensa / kernel / setup . c
2005-06-24 09:01:16 +04:00
*
* 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 ) 1995 Linus Torvalds
* Copyright ( C ) 2001 - 2005 Tensilica Inc .
*
* Chris Zankel < chris @ zankel . net >
* Joe Taylor < joe @ tensilica . com , joetylr @ yahoo . com >
* Kevin Chea
* Marc Gauthier < marc @ tensilica . com > < marc @ alumni . uwaterloo . ca >
*/
# include <linux/errno.h>
# include <linux/init.h>
2008-07-24 08:28:13 +04:00
# include <linux/mm.h>
2005-06-24 09:01:16 +04:00
# include <linux/proc_fs.h>
2006-07-10 15:44:13 +04:00
# include <linux/screen_info.h>
2005-06-24 09:01:16 +04:00
# include <linux/bootmem.h>
# include <linux/kernel.h>
2013-10-17 02:42:26 +04:00
# include <linux/percpu.h>
2014-01-29 06:20:46 +04:00
# include <linux/clk-provider.h>
2013-10-17 02:42:26 +04:00
# include <linux/cpu.h>
2012-11-04 00:30:13 +04:00
# include <linux/of_fdt.h>
# include <linux/of_platform.h>
2005-06-24 09:01:16 +04:00
# if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
# include <linux / console.h>
# endif
# ifdef CONFIG_RTC
# include <linux / timex.h>
# endif
# ifdef CONFIG_PROC_FS
# include <linux / seq_file.h>
# endif
# include <asm/bootparam.h>
2013-10-17 02:42:21 +04:00
# include <asm/mmu_context.h>
2005-06-24 09:01:16 +04:00
# include <asm/pgtable.h>
# include <asm/processor.h>
# include <asm/timex.h>
# include <asm/platform.h>
# include <asm/page.h>
# include <asm/setup.h>
2007-06-01 04:47:01 +04:00
# include <asm/param.h>
2012-11-28 11:33:02 +04:00
# include <asm/traps.h>
2013-10-17 02:42:26 +04:00
# include <asm/smp.h>
2014-03-23 03:17:43 +04:00
# include <asm/sysmem.h>
2005-06-24 09:01:16 +04:00
2009-03-10 22:55:49 +03:00
# include <platform/hardware.h>
2005-06-24 09:01:16 +04:00
# if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
struct screen_info screen_info = { 0 , 24 , 0 , 0 , 0 , 80 , 0 , 0 , 0 , 24 , 1 , 16 } ;
# endif
# ifdef CONFIG_BLK_DEV_FD
extern struct fd_ops no_fd_ops ;
struct fd_ops * fd_ops ;
# endif
extern struct rtc_ops no_rtc_ops ;
struct rtc_ops * rtc_ops ;
# ifdef CONFIG_BLK_DEV_INITRD
2013-08-31 02:06:53 +04:00
extern unsigned long initrd_start ;
extern unsigned long initrd_end ;
2005-06-24 09:01:16 +04:00
int initrd_is_mapped = 0 ;
extern int initrd_below_start_ok ;
# endif
2012-11-04 00:30:13 +04:00
# ifdef CONFIG_OF
void * dtb_start = __dtb_start ;
# endif
2005-06-24 09:01:16 +04:00
unsigned char aux_device_present ;
extern unsigned long loops_per_jiffy ;
/* Command line specified as configuration option. */
2007-02-12 11:54:25 +03:00
static char __initdata command_line [ COMMAND_LINE_SIZE ] ;
2005-06-24 09:01:16 +04:00
# ifdef CONFIG_CMDLINE_BOOL
static char default_command_line [ COMMAND_LINE_SIZE ] __initdata = CONFIG_CMDLINE ;
# endif
/*
* Boot parameter parsing .
*
* The Xtensa port uses a list of variable - sized tags to pass data to
* the kernel . The first tag must be a BP_TAG_FIRST tag for the list
* to be recognised . The list is terminated with a zero - sized
* BP_TAG_LAST tag .
*/
typedef struct tagtable {
u32 tag ;
int ( * parse ) ( const bp_tag_t * ) ;
} tagtable_t ;
# define __tagtable(tag, fn) static tagtable_t __tagtable_##fn \
2012-10-15 03:55:37 +04:00
__attribute__ ( ( used , section ( " .taglist " ) ) ) = { tag , fn }
2005-06-24 09:01:16 +04:00
/* parse current tag */
2012-11-04 00:30:13 +04:00
static int __init parse_tag_mem ( const bp_tag_t * tag )
{
2014-03-23 03:17:43 +04:00
struct bp_meminfo * mi = ( struct bp_meminfo * ) ( tag - > data ) ;
2012-11-04 00:30:13 +04:00
if ( mi - > type ! = MEMORY_TYPE_CONVENTIONAL )
return - 1 ;
2014-03-23 03:17:43 +04:00
return add_sysmem_bank ( mi - > start , mi - > end ) ;
2012-11-04 00:30:13 +04:00
}
2005-06-24 09:01:16 +04:00
__tagtable ( BP_TAG_MEMORY , parse_tag_mem ) ;
# ifdef CONFIG_BLK_DEV_INITRD
static int __init parse_tag_initrd ( const bp_tag_t * tag )
{
2014-03-23 03:17:43 +04:00
struct bp_meminfo * mi = ( struct bp_meminfo * ) ( tag - > data ) ;
2013-08-31 02:06:53 +04:00
initrd_start = ( unsigned long ) __va ( mi - > start ) ;
initrd_end = ( unsigned long ) __va ( mi - > end ) ;
2005-06-24 09:01:16 +04:00
return 0 ;
}
__tagtable ( BP_TAG_INITRD , parse_tag_initrd ) ;
2012-11-04 00:30:13 +04:00
# ifdef CONFIG_OF
static int __init parse_tag_fdt ( const bp_tag_t * tag )
{
2013-06-09 04:52:11 +04:00
dtb_start = __va ( tag - > data [ 0 ] ) ;
2012-11-04 00:30:13 +04:00
return 0 ;
}
__tagtable ( BP_TAG_FDT , parse_tag_fdt ) ;
# endif /* CONFIG_OF */
2005-06-24 09:01:16 +04:00
# endif /* CONFIG_BLK_DEV_INITRD */
static int __init parse_tag_cmdline ( const bp_tag_t * tag )
{
2012-11-04 00:30:13 +04:00
strlcpy ( command_line , ( char * ) ( tag - > data ) , COMMAND_LINE_SIZE ) ;
2005-06-24 09:01:16 +04:00
return 0 ;
}
__tagtable ( BP_TAG_COMMAND_LINE , parse_tag_cmdline ) ;
static int __init parse_bootparam ( const bp_tag_t * tag )
{
extern tagtable_t __tagtable_begin , __tagtable_end ;
tagtable_t * t ;
/* Boot parameters must start with a BP_TAG_FIRST tag. */
if ( tag - > id ! = BP_TAG_FIRST ) {
printk ( KERN_WARNING " Invalid boot parameters! \n " ) ;
return 0 ;
}
tag = ( bp_tag_t * ) ( ( unsigned long ) tag + sizeof ( bp_tag_t ) + tag - > size ) ;
/* Parse all tags. */
while ( tag ! = NULL & & tag - > id ! = BP_TAG_LAST ) {
for ( t = & __tagtable_begin ; t < & __tagtable_end ; t + + ) {
if ( tag - > id = = t - > tag ) {
t - > parse ( tag ) ;
break ;
}
}
if ( t = = & __tagtable_end )
printk ( KERN_WARNING " Ignoring tag "
" 0x%08x \n " , tag - > id ) ;
tag = ( bp_tag_t * ) ( ( unsigned long ) ( tag + 1 ) + tag - > size ) ;
}
return 0 ;
}
2012-11-04 00:30:13 +04:00
# ifdef CONFIG_OF
2013-08-28 19:05:10 +04:00
bool __initdata dt_memory_scan = false ;
2012-11-04 00:30:13 +04:00
2015-09-24 23:36:45 +03:00
# if !XCHAL_HAVE_PTP_MMU || XCHAL_HAVE_SPANNING_WAY
2013-12-29 13:03:30 +04:00
unsigned long xtensa_kio_paddr = XCHAL_KIO_DEFAULT_PADDR ;
EXPORT_SYMBOL ( xtensa_kio_paddr ) ;
static int __init xtensa_dt_io_area ( unsigned long node , const char * uname ,
int depth , void * data )
{
const __be32 * ranges ;
2014-04-02 08:49:03 +04:00
int len ;
2013-12-29 13:03:30 +04:00
if ( depth > 1 )
return 0 ;
if ( ! of_flat_dt_is_compatible ( node , " simple-bus " ) )
return 0 ;
ranges = of_get_flat_dt_prop ( node , " ranges " , & len ) ;
if ( ! ranges )
return 1 ;
if ( len = = 0 )
return 1 ;
xtensa_kio_paddr = of_read_ulong ( ranges + 1 , 1 ) ;
/* round down to nearest 256MB boundary */
xtensa_kio_paddr & = 0xf0000000 ;
return 1 ;
}
# else
static int __init xtensa_dt_io_area ( unsigned long node , const char * uname ,
int depth , void * data )
{
return 1 ;
}
# endif
2012-11-04 00:30:13 +04:00
void __init early_init_dt_add_memory_arch ( u64 base , u64 size )
{
2013-08-28 19:05:10 +04:00
if ( ! dt_memory_scan )
return ;
2012-11-04 00:30:13 +04:00
size & = PAGE_MASK ;
2014-03-23 03:17:43 +04:00
add_sysmem_bank ( base , base + size ) ;
2012-11-04 00:30:13 +04:00
}
void * __init early_init_dt_alloc_memory_arch ( u64 size , u64 align )
{
return __alloc_bootmem ( size , align , 0 ) ;
}
void __init early_init_devtree ( void * params )
{
2013-08-28 19:05:10 +04:00
if ( sysmem . nr_banks = = 0 )
dt_memory_scan = true ;
2012-11-04 00:30:13 +04:00
2013-08-28 19:05:10 +04:00
early_init_dt_scan ( params ) ;
2013-12-29 13:03:30 +04:00
of_scan_flat_dt ( xtensa_dt_io_area , NULL ) ;
2012-11-04 00:30:13 +04:00
2013-08-28 19:05:10 +04:00
if ( ! command_line [ 0 ] )
strlcpy ( command_line , boot_command_line , COMMAND_LINE_SIZE ) ;
2012-11-04 00:30:13 +04:00
}
static int __init xtensa_device_probe ( void )
{
2014-01-29 06:20:46 +04:00
of_clk_init ( NULL ) ;
2013-12-23 22:49:57 +04:00
of_platform_populate ( NULL , of_default_bus_match_table , NULL , NULL ) ;
2012-11-04 00:30:13 +04:00
return 0 ;
}
device_initcall ( xtensa_device_probe ) ;
# endif /* CONFIG_OF */
2005-06-24 09:01:16 +04:00
/*
* Initialize architecture . ( Early stage )
*/
void __init init_arch ( bp_tag_t * bp_start )
{
/* Parse boot parameters */
2012-11-29 04:53:51 +04:00
if ( bp_start )
2012-11-04 00:30:13 +04:00
parse_bootparam ( bp_start ) ;
# ifdef CONFIG_OF
early_init_devtree ( dtb_start ) ;
# endif
2005-06-24 09:01:16 +04:00
if ( sysmem . nr_banks = = 0 ) {
2014-03-23 03:17:43 +04:00
add_sysmem_bank ( PLATFORM_DEFAULT_MEM_START ,
PLATFORM_DEFAULT_MEM_START +
PLATFORM_DEFAULT_MEM_SIZE ) ;
2005-06-24 09:01:16 +04:00
}
2012-11-04 00:30:13 +04:00
# ifdef CONFIG_CMDLINE_BOOL
if ( ! command_line [ 0 ] )
strlcpy ( command_line , default_command_line , COMMAND_LINE_SIZE ) ;
# endif
2005-06-24 09:01:16 +04:00
/* Early hook for platforms */
platform_init ( bp_start ) ;
/* Initialize MMU. */
init_mmu ( ) ;
}
/*
* Initialize system . Setup memory and reserve regions .
*/
extern char _end ;
extern char _stext ;
extern char _WindowVectors_text_start ;
extern char _WindowVectors_text_end ;
extern char _DebugInterruptVector_literal_start ;
extern char _DebugInterruptVector_text_end ;
extern char _KernelExceptionVector_literal_start ;
extern char _KernelExceptionVector_text_end ;
extern char _UserExceptionVector_literal_start ;
extern char _UserExceptionVector_text_end ;
extern char _DoubleExceptionVector_literal_start ;
extern char _DoubleExceptionVector_text_end ;
2013-01-05 04:57:17 +04:00
# if XCHAL_EXCM_LEVEL >= 2
extern char _Level2InterruptVector_text_start ;
extern char _Level2InterruptVector_text_end ;
# endif
# if XCHAL_EXCM_LEVEL >= 3
extern char _Level3InterruptVector_text_start ;
extern char _Level3InterruptVector_text_end ;
# endif
# if XCHAL_EXCM_LEVEL >= 4
extern char _Level4InterruptVector_text_start ;
extern char _Level4InterruptVector_text_end ;
# endif
# if XCHAL_EXCM_LEVEL >= 5
extern char _Level5InterruptVector_text_start ;
extern char _Level5InterruptVector_text_end ;
# endif
# if XCHAL_EXCM_LEVEL >= 6
extern char _Level6InterruptVector_text_start ;
extern char _Level6InterruptVector_text_end ;
# endif
2015-10-16 17:01:04 +03:00
# ifdef CONFIG_SMP
extern char _SecondaryResetVector_text_start ;
extern char _SecondaryResetVector_text_end ;
# endif
2005-06-24 09:01:16 +04:00
2012-11-28 11:33:02 +04:00
# ifdef CONFIG_S32C1I_SELFTEST
# if XCHAL_HAVE_S32C1I
static int __initdata rcw_word , rcw_probe_pc , rcw_exc ;
/*
* Basic atomic compare - and - swap , that records PC of S32C1I for probing .
*
* If * v = = cmp , set * v = set . Return previous * v .
*/
static inline int probed_compare_swap ( int * v , int cmp , int set )
{
int tmp ;
__asm__ __volatile__ (
" movi %1, 1f \n "
" s32i %1, %4, 0 \n "
" wsr %2, scompare1 \n "
" 1: s32c1i %0, %3, 0 \n "
: " =a " ( set ) , " =&a " ( tmp )
: " a " ( cmp ) , " a " ( v ) , " a " ( & rcw_probe_pc ) , " 0 " ( set )
: " memory "
) ;
return set ;
}
/* Handle probed exception */
2013-10-17 02:42:20 +04:00
static void __init do_probed_exception ( struct pt_regs * regs ,
unsigned long exccause )
2012-11-28 11:33:02 +04:00
{
if ( regs - > pc = = rcw_probe_pc ) { /* exception on s32c1i ? */
regs - > pc + = 3 ; /* skip the s32c1i instruction */
rcw_exc = exccause ;
} else {
do_unhandled ( regs , exccause ) ;
}
}
/* Simple test of S32C1I (soc bringup assist) */
2013-10-17 02:42:20 +04:00
static int __init check_s32c1i ( void )
2012-11-28 11:33:02 +04:00
{
int n , cause1 , cause2 ;
void * handbus , * handdata , * handaddr ; /* temporarily saved handlers */
rcw_probe_pc = 0 ;
handbus = trap_set_handler ( EXCCAUSE_LOAD_STORE_ERROR ,
do_probed_exception ) ;
handdata = trap_set_handler ( EXCCAUSE_LOAD_STORE_DATA_ERROR ,
do_probed_exception ) ;
handaddr = trap_set_handler ( EXCCAUSE_LOAD_STORE_ADDR_ERROR ,
do_probed_exception ) ;
/* First try an S32C1I that does not store: */
rcw_exc = 0 ;
rcw_word = 1 ;
n = probed_compare_swap ( & rcw_word , 0 , 2 ) ;
cause1 = rcw_exc ;
/* took exception? */
if ( cause1 ! = 0 ) {
/* unclean exception? */
if ( n ! = 2 | | rcw_word ! = 1 )
panic ( " S32C1I exception error " ) ;
} else if ( rcw_word ! = 1 | | n ! = 1 ) {
panic ( " S32C1I compare error " ) ;
}
/* Then an S32C1I that stores: */
rcw_exc = 0 ;
rcw_word = 0x1234567 ;
n = probed_compare_swap ( & rcw_word , 0x1234567 , 0xabcde ) ;
cause2 = rcw_exc ;
if ( cause2 ! = 0 ) {
/* unclean exception? */
if ( n ! = 0xabcde | | rcw_word ! = 0x1234567 )
panic ( " S32C1I exception error (b) " ) ;
} else if ( rcw_word ! = 0xabcde | | n ! = 0x1234567 ) {
panic ( " S32C1I store error " ) ;
}
/* Verify consistency of exceptions: */
if ( cause1 | | cause2 ) {
pr_warn ( " S32C1I took exception %d, %d \n " , cause1 , cause2 ) ;
/* If emulation of S32C1I upon bus error gets implemented,
we can get rid of this panic for single core ( not SMP ) */
panic ( " S32C1I exceptions not currently supported " ) ;
}
if ( cause1 ! = cause2 )
panic ( " inconsistent S32C1I exceptions " ) ;
trap_set_handler ( EXCCAUSE_LOAD_STORE_ERROR , handbus ) ;
trap_set_handler ( EXCCAUSE_LOAD_STORE_DATA_ERROR , handdata ) ;
trap_set_handler ( EXCCAUSE_LOAD_STORE_ADDR_ERROR , handaddr ) ;
2013-10-17 02:42:20 +04:00
return 0 ;
2012-11-28 11:33:02 +04:00
}
# else /* XCHAL_HAVE_S32C1I */
/* This condition should not occur with a commercially deployed processor.
Display reminder for early engr test or demo chips / FPGA bitstreams */
2013-10-17 02:42:20 +04:00
static int __init check_s32c1i ( void )
2012-11-28 11:33:02 +04:00
{
pr_warn ( " Processor configuration lacks atomic compare-and-swap support! \n " ) ;
2013-10-17 02:42:20 +04:00
return 0 ;
2012-11-28 11:33:02 +04:00
}
# endif /* XCHAL_HAVE_S32C1I */
2013-10-17 02:42:20 +04:00
early_initcall ( check_s32c1i ) ;
2012-11-28 11:33:02 +04:00
# endif /* CONFIG_S32C1I_SELFTEST */
2005-06-24 09:01:16 +04:00
void __init setup_arch ( char * * cmdline_p )
{
2012-11-04 00:30:13 +04:00
strlcpy ( boot_command_line , command_line , COMMAND_LINE_SIZE ) ;
2005-06-24 09:01:16 +04:00
* cmdline_p = command_line ;
/* Reserve some memory regions */
# ifdef CONFIG_BLK_DEV_INITRD
if ( initrd_start < initrd_end ) {
initrd_is_mapped = mem_reserve ( __pa ( initrd_start ) ,
2014-03-23 03:24:45 +04:00
__pa ( initrd_end ) , 0 ) = = 0 ;
2005-06-24 09:01:16 +04:00
initrd_below_start_ok = 1 ;
2012-11-29 04:53:51 +04:00
} else {
2005-06-24 09:01:16 +04:00
initrd_start = 0 ;
}
# endif
mem_reserve ( __pa ( & _stext ) , __pa ( & _end ) , 1 ) ;
mem_reserve ( __pa ( & _WindowVectors_text_start ) ,
__pa ( & _WindowVectors_text_end ) , 0 ) ;
mem_reserve ( __pa ( & _DebugInterruptVector_literal_start ) ,
__pa ( & _DebugInterruptVector_text_end ) , 0 ) ;
mem_reserve ( __pa ( & _KernelExceptionVector_literal_start ) ,
__pa ( & _KernelExceptionVector_text_end ) , 0 ) ;
mem_reserve ( __pa ( & _UserExceptionVector_literal_start ) ,
__pa ( & _UserExceptionVector_text_end ) , 0 ) ;
mem_reserve ( __pa ( & _DoubleExceptionVector_literal_start ) ,
__pa ( & _DoubleExceptionVector_text_end ) , 0 ) ;
2013-01-05 04:57:17 +04:00
# if XCHAL_EXCM_LEVEL >= 2
mem_reserve ( __pa ( & _Level2InterruptVector_text_start ) ,
__pa ( & _Level2InterruptVector_text_end ) , 0 ) ;
# endif
# if XCHAL_EXCM_LEVEL >= 3
mem_reserve ( __pa ( & _Level3InterruptVector_text_start ) ,
__pa ( & _Level3InterruptVector_text_end ) , 0 ) ;
# endif
# if XCHAL_EXCM_LEVEL >= 4
mem_reserve ( __pa ( & _Level4InterruptVector_text_start ) ,
__pa ( & _Level4InterruptVector_text_end ) , 0 ) ;
# endif
# if XCHAL_EXCM_LEVEL >= 5
mem_reserve ( __pa ( & _Level5InterruptVector_text_start ) ,
__pa ( & _Level5InterruptVector_text_end ) , 0 ) ;
# endif
# if XCHAL_EXCM_LEVEL >= 6
mem_reserve ( __pa ( & _Level6InterruptVector_text_start ) ,
__pa ( & _Level6InterruptVector_text_end ) , 0 ) ;
# endif
2015-10-16 17:01:04 +03:00
# ifdef CONFIG_SMP
mem_reserve ( __pa ( & _SecondaryResetVector_text_start ) ,
__pa ( & _SecondaryResetVector_text_end ) , 0 ) ;
# endif
2014-03-21 21:04:40 +04:00
parse_early_param ( ) ;
2005-06-24 09:01:16 +04:00
bootmem_init ( ) ;
2013-08-26 20:24:11 +04:00
unflatten_and_copy_device_tree ( ) ;
2005-06-24 09:01:16 +04:00
2012-11-04 00:30:13 +04:00
platform_setup ( cmdline_p ) ;
2005-06-24 09:01:16 +04:00
2013-10-17 02:42:26 +04:00
# ifdef CONFIG_SMP
smp_init_cpus ( ) ;
# endif
2005-06-24 09:01:16 +04:00
paging_init ( ) ;
2009-03-04 18:21:31 +03:00
zones_init ( ) ;
2005-06-24 09:01:16 +04:00
# ifdef CONFIG_VT
# if defined(CONFIG_VGA_CONSOLE)
conswitchp = & vga_con ;
# elif defined(CONFIG_DUMMY_CONSOLE)
conswitchp = & dummy_con ;
# endif
# endif
2005-09-23 08:44:23 +04:00
# ifdef CONFIG_PCI
2005-06-24 09:01:16 +04:00
platform_pcibios_init ( ) ;
# endif
}
2013-10-17 02:42:26 +04:00
static DEFINE_PER_CPU ( struct cpu , cpu_data ) ;
static int __init topology_init ( void )
{
int i ;
for_each_possible_cpu ( i ) {
struct cpu * cpu = & per_cpu ( cpu_data , i ) ;
2013-10-17 02:42:28 +04:00
cpu - > hotpluggable = ! ! i ;
2013-10-17 02:42:26 +04:00
register_cpu ( cpu , i ) ;
}
return 0 ;
}
subsys_initcall ( topology_init ) ;
2005-06-24 09:01:16 +04:00
void machine_restart ( char * cmd )
{
platform_restart ( ) ;
}
void machine_halt ( void )
{
platform_halt ( ) ;
while ( 1 ) ;
}
void machine_power_off ( void )
{
platform_power_off ( ) ;
while ( 1 ) ;
}
# ifdef CONFIG_PROC_FS
/*
* Display some core information through / proc / cpuinfo .
*/
static int
c_show ( struct seq_file * f , void * slot )
{
/* high-level stuff */
2013-10-17 02:42:26 +04:00
seq_printf ( f , " CPU count \t : %u \n "
2015-02-14 01:37:17 +03:00
" CPU list \t : %*pbl \n "
2013-10-17 02:42:26 +04:00
" vendor_id \t : Tensilica \n "
" model \t \t : Xtensa " XCHAL_HW_VERSION_NAME " \n "
" core ID \t \t : " XCHAL_CORE_ID " \n "
" build ID \t : 0x%x \n "
" byte order \t : %s \n "
" cpu MHz \t \t : %lu.%02lu \n "
" bogomips \t : %lu.%02lu \n " ,
num_online_cpus ( ) ,
2015-02-14 01:37:17 +03:00
cpumask_pr_args ( cpu_online_mask ) ,
2013-10-17 02:42:26 +04:00
XCHAL_BUILD_UNIQUE_ID ,
XCHAL_HAVE_BE ? " big " : " little " ,
ccount_freq / 1000000 ,
( ccount_freq / 10000 ) % 100 ,
loops_per_jiffy / ( 500000 / HZ ) ,
( loops_per_jiffy / ( 5000 / HZ ) ) % 100 ) ;
2005-06-24 09:01:16 +04:00
seq_printf ( f , " flags \t \t : "
# if XCHAL_HAVE_NMI
" nmi "
# endif
# if XCHAL_HAVE_DEBUG
" debug "
# if XCHAL_HAVE_OCD
" ocd "
# endif
# endif
# if XCHAL_HAVE_DENSITY
" density "
# endif
# if XCHAL_HAVE_BOOLEANS
" boolean "
# endif
# if XCHAL_HAVE_LOOPS
" loop "
# endif
# if XCHAL_HAVE_NSA
" nsa "
# endif
# if XCHAL_HAVE_MINMAX
" minmax "
# endif
# if XCHAL_HAVE_SEXT
" sext "
# endif
# if XCHAL_HAVE_CLAMPS
" clamps "
# endif
# if XCHAL_HAVE_MAC16
" mac16 "
# endif
# if XCHAL_HAVE_MUL16
" mul16 "
# endif
# if XCHAL_HAVE_MUL32
" mul32 "
# endif
# if XCHAL_HAVE_MUL32_HIGH
" mul32h "
# endif
# if XCHAL_HAVE_FP
" fpu "
2012-11-11 04:44:22 +04:00
# endif
# if XCHAL_HAVE_S32C1I
" s32c1i "
2005-06-24 09:01:16 +04:00
# endif
" \n " ) ;
/* Registers. */
seq_printf ( f , " physical aregs \t : %d \n "
" misc regs \t : %d \n "
" ibreak \t \t : %d \n "
" dbreak \t \t : %d \n " ,
XCHAL_NUM_AREGS ,
XCHAL_NUM_MISC_REGS ,
XCHAL_NUM_IBREAK ,
XCHAL_NUM_DBREAK ) ;
/* Interrupt. */
seq_printf ( f , " num ints \t : %d \n "
" ext ints \t : %d \n "
" int levels \t : %d \n "
" timers \t \t : %d \n "
" debug level \t : %d \n " ,
XCHAL_NUM_INTERRUPTS ,
XCHAL_NUM_EXTINTERRUPTS ,
XCHAL_NUM_INTLEVELS ,
XCHAL_NUM_TIMERS ,
XCHAL_DEBUGLEVEL ) ;
/* Cache */
seq_printf ( f , " icache line size: %d \n "
" icache ways \t : %d \n "
" icache size \t : %d \n "
" icache flags \t : "
# if XCHAL_ICACHE_LINE_LOCKABLE
2012-11-11 01:29:10 +04:00
" lock "
2005-06-24 09:01:16 +04:00
# endif
" \n "
" dcache line size: %d \n "
" dcache ways \t : %d \n "
" dcache size \t : %d \n "
" dcache flags \t : "
# if XCHAL_DCACHE_IS_WRITEBACK
2012-11-11 01:29:10 +04:00
" writeback "
2005-06-24 09:01:16 +04:00
# endif
# if XCHAL_DCACHE_LINE_LOCKABLE
2012-11-11 01:29:10 +04:00
" lock "
2005-06-24 09:01:16 +04:00
# endif
" \n " ,
XCHAL_ICACHE_LINESIZE ,
XCHAL_ICACHE_WAYS ,
XCHAL_ICACHE_SIZE ,
XCHAL_DCACHE_LINESIZE ,
XCHAL_DCACHE_WAYS ,
XCHAL_DCACHE_SIZE ) ;
return 0 ;
}
/*
* We show only CPU # 0 info .
*/
static void *
c_start ( struct seq_file * f , loff_t * pos )
{
2013-10-17 02:42:26 +04:00
return ( * pos = = 0 ) ? ( void * ) 1 : NULL ;
2005-06-24 09:01:16 +04:00
}
static void *
c_next ( struct seq_file * f , void * v , loff_t * pos )
{
return NULL ;
}
static void
c_stop ( struct seq_file * f , void * v )
{
}
2008-02-08 15:21:19 +03:00
const struct seq_operations cpuinfo_op =
2005-06-24 09:01:16 +04:00
{
2013-10-17 02:42:26 +04:00
. start = c_start ,
. next = c_next ,
. stop = c_stop ,
. show = c_show ,
2005-06-24 09:01:16 +04:00
} ;
# endif /* CONFIG_PROC_FS */