2006-10-03 13:14:04 +09:00
/*
2006-12-25 10:19:56 +09:00
* arch / sh / kernel / setup . c
2005-04-16 15:20:36 -07:00
*
* This file handles the architecture - dependent parts of initialization
2006-12-25 10:19:56 +09:00
*
* Copyright ( C ) 1999 Niibe Yutaka
2010-05-10 15:39:05 +09:00
* Copyright ( C ) 2002 - 2010 Paul Mundt
2005-04-16 15:20:36 -07:00
*/
2006-07-10 04:44:13 -07:00
# include <linux/screen_info.h>
2005-04-16 15:20:36 -07:00
# include <linux/ioport.h>
# include <linux/init.h>
# include <linux/initrd.h>
# include <linux/bootmem.h>
# include <linux/console.h>
# include <linux/root_dev.h>
# include <linux/utsname.h>
2007-03-28 16:38:13 +09:00
# include <linux/nodemask.h>
2005-04-16 15:20:36 -07:00
# include <linux/cpu.h>
2006-03-27 01:16:04 -08:00
# include <linux/pfn.h>
2006-10-03 13:14:04 +09:00
# include <linux/fs.h>
2007-03-28 16:38:13 +09:00
# include <linux/mm.h>
2007-04-27 11:25:57 +09:00
# include <linux/kexec.h>
2007-07-20 16:59:49 +09:00
# include <linux/module.h>
2007-09-21 18:39:49 +09:00
# include <linux/smp.h>
2008-03-07 17:19:58 +09:00
# include <linux/err.h>
2008-07-30 10:29:39 +10:00
# include <linux/crash_dump.h>
2008-09-04 18:53:58 +09:00
# include <linux/mmzone.h>
2008-09-08 20:47:42 +09:00
# include <linux/clk.h>
# include <linux/delay.h>
2009-04-15 10:50:21 +00:00
# include <linux/platform_device.h>
2010-07-12 14:36:09 +10:00
# include <linux/memblock.h>
2005-04-16 15:20:36 -07:00
# include <asm/uaccess.h>
# include <asm/io.h>
2007-05-14 12:50:43 +09:00
# include <asm/page.h>
2007-12-10 15:50:28 +09:00
# include <asm/elf.h>
2005-04-16 15:20:36 -07:00
# include <asm/sections.h>
# include <asm/irq.h>
# include <asm/setup.h>
2006-02-01 03:06:02 -08:00
# include <asm/clock.h>
2010-04-26 18:35:44 +09:00
# include <asm/smp.h>
2007-03-28 16:38:13 +09:00
# include <asm/mmu_context.h>
2010-05-10 15:39:05 +09:00
# include <asm/mmzone.h>
2010-10-27 14:24:34 +09:00
# include <asm/sparsemem.h>
2005-04-16 15:20:36 -07:00
/*
* Initialize loops_per_jiffy as 10000000 ( 1000 MIPS ) .
* This value will be used at the very early stage of serial setup .
* The bigger value means no problem .
*/
2007-09-21 18:01:40 +09:00
struct sh_cpuinfo cpu_data [ NR_CPUS ] __read_mostly = {
[ 0 ] = {
. type = CPU_SH_NONE ,
2009-08-15 10:48:13 +09:00
. family = CPU_FAMILY_UNKNOWN ,
2007-09-21 18:01:40 +09:00
. loops_per_jiffy = 10000000 ,
2010-10-26 14:44:58 +09:00
. phys_bits = MAX_PHYSMEM_BITS ,
2007-09-21 18:01:40 +09:00
} ,
} ;
EXPORT_SYMBOL ( cpu_data ) ;
2007-05-15 15:19:34 +09:00
/*
* The machine vector . First entry in . machvec . init , or clobbered by
* sh_mv = on the command line , prior to . machvec . init teardown .
*/
2007-05-15 15:38:30 +09:00
struct sh_machine_vector sh_mv = { . mv_name = " generic " , } ;
2008-04-25 16:01:38 +09:00
EXPORT_SYMBOL ( sh_mv ) ;
2007-05-15 15:19:34 +09:00
2006-09-27 18:17:31 +09:00
# ifdef CONFIG_VT
2005-04-16 15:20:36 -07:00
struct screen_info screen_info ;
2006-09-27 18:17:31 +09:00
# endif
2005-04-16 15:20:36 -07:00
extern int root_mountflags ;
2005-11-07 00:58:24 -08:00
# define RAMDISK_IMAGE_START_MASK 0x07FF
2005-04-16 15:20:36 -07:00
# define RAMDISK_PROMPT_FLAG 0x8000
2005-11-07 00:58:24 -08:00
# define RAMDISK_LOAD_FLAG 0x4000
2005-04-16 15:20:36 -07:00
2007-02-12 00:54:19 -08:00
static char __initdata command_line [ COMMAND_LINE_SIZE ] = { 0 , } ;
2005-04-16 15:20:36 -07:00
2007-10-30 17:32:08 +09:00
static struct resource code_resource = {
. name = " Kernel code " ,
. flags = IORESOURCE_BUSY | IORESOURCE_MEM ,
} ;
static struct resource data_resource = {
. name = " Kernel data " ,
. flags = IORESOURCE_BUSY | IORESOURCE_MEM ,
} ;
2005-04-16 15:20:36 -07:00
2008-04-23 20:50:27 +09:00
static struct resource bss_resource = {
. name = " Kernel bss " ,
. flags = IORESOURCE_BUSY | IORESOURCE_MEM ,
} ;
2007-07-20 16:59:49 +09:00
unsigned long memory_start ;
EXPORT_SYMBOL ( memory_start ) ;
2007-10-30 17:18:08 +09:00
unsigned long memory_end = 0 ;
2007-07-20 16:59:49 +09:00
EXPORT_SYMBOL ( memory_end ) ;
2010-05-10 20:17:25 +09:00
unsigned long memory_limit = 0 ;
2005-04-16 15:20:36 -07:00
2008-04-23 20:56:44 +09:00
static struct resource mem_resources [ MAX_NUMNODES ] ;
2007-12-10 15:50:28 +09:00
int l1i_cache_shape , l1d_cache_shape , l2_cache_shape ;
2007-05-14 15:59:09 +09:00
static int __init early_parse_mem ( char * p )
2005-04-16 15:20:36 -07:00
{
2010-05-10 20:17:25 +09:00
if ( ! p )
return 1 ;
2005-04-16 15:20:36 -07:00
2010-05-10 20:17:25 +09:00
memory_limit = PAGE_ALIGN ( memparse ( p , & p ) ) ;
2007-11-26 21:16:09 +09:00
2010-05-10 20:17:25 +09:00
pr_notice ( " Memory limited to %ldMB \n " , memory_limit > > 20 ) ;
2006-09-27 18:17:31 +09:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2007-05-14 15:59:09 +09:00
early_param ( " mem " , early_parse_mem ) ;
2005-04-16 15:20:36 -07:00
2010-05-11 13:32:19 +09:00
void __init check_for_initrd ( void )
2010-05-06 15:09:45 +09:00
{
# ifdef CONFIG_BLK_DEV_INITRD
unsigned long start , end ;
/*
* Check for the rare cases where boot loaders adhere to the boot
* ABI .
*/
if ( ! LOADER_TYPE | | ! INITRD_START | | ! INITRD_SIZE )
goto disable ;
start = INITRD_START + __MEMORY_START ;
end = start + INITRD_SIZE ;
if ( unlikely ( end < = start ) )
goto disable ;
if ( unlikely ( start & ~ PAGE_MASK ) ) {
pr_err ( " initrd must be page aligned \n " ) ;
goto disable ;
}
2010-10-05 08:16:08 +00:00
if ( unlikely ( start < __MEMORY_START ) ) {
pr_err ( " initrd start (%08lx) < __MEMORY_START(%x) \n " ,
start , __MEMORY_START ) ;
2010-05-06 15:09:45 +09:00
goto disable ;
}
2010-07-12 14:36:09 +10:00
if ( unlikely ( end > memblock_end_of_DRAM ( ) ) ) {
2010-05-06 15:09:45 +09:00
pr_err ( " initrd extends beyond end of memory "
" (0x%08lx > 0x%08lx) \n disabling initrd \n " ,
2010-07-12 14:36:09 +10:00
end , ( unsigned long ) memblock_end_of_DRAM ( ) ) ;
2010-05-06 15:09:45 +09:00
goto disable ;
}
/*
* If we got this far inspite of the boot loader ' s best efforts
* to the contrary , assume we actually have a valid initrd and
* fix up the root dev .
*/
ROOT_DEV = Root_RAM0 ;
/*
* Address sanitization
*/
2010-10-05 08:16:08 +00:00
initrd_start = ( unsigned long ) __va ( start ) ;
2010-05-06 15:09:45 +09:00
initrd_end = initrd_start + INITRD_SIZE ;
2010-07-12 14:36:09 +10:00
memblock_reserve ( __pa ( initrd_start ) , INITRD_SIZE ) ;
2010-05-06 15:09:45 +09:00
return ;
disable :
pr_info ( " initrd disabled \n " ) ;
initrd_start = initrd_end = 0 ;
# endif
}
2008-09-08 20:47:42 +09:00
void __cpuinit calibrate_delay ( void )
{
struct clk * clk = clk_get ( NULL , " cpu_clk " ) ;
if ( IS_ERR ( clk ) )
panic ( " Need a sane CPU clock definition! " ) ;
loops_per_jiffy = ( clk_get_rate ( clk ) > > 1 ) / HZ ;
printk ( KERN_INFO " Calibrating delay loop (skipped)... "
" %lu.%02lu BogoMIPS PRESET (lpj=%lu) \n " ,
loops_per_jiffy / ( 500000 / HZ ) ,
( loops_per_jiffy / ( 5000 / HZ ) ) % 100 ,
loops_per_jiffy ) ;
}
2008-04-23 20:56:44 +09:00
void __init __add_active_range ( unsigned int nid , unsigned long start_pfn ,
unsigned long end_pfn )
{
struct resource * res = & mem_resources [ nid ] ;
2010-05-11 13:52:50 +09:00
unsigned long start , end ;
2008-04-23 20:56:44 +09:00
WARN_ON ( res - > name ) ; /* max one active range per node for now */
2010-05-11 13:52:50 +09:00
start = start_pfn < < PAGE_SHIFT ;
end = end_pfn < < PAGE_SHIFT ;
2008-04-23 20:56:44 +09:00
res - > name = " System RAM " ;
2010-05-11 13:52:50 +09:00
res - > start = start ;
res - > end = end - 1 ;
2008-04-23 20:56:44 +09:00
res - > flags = IORESOURCE_MEM | IORESOURCE_BUSY ;
2010-05-11 13:52:50 +09:00
2008-04-23 20:56:44 +09:00
if ( request_resource ( & iomem_resource , res ) ) {
pr_err ( " unable to request memory_resource 0x%lx 0x%lx \n " ,
start_pfn , end_pfn ) ;
return ;
}
/*
* We don ' t know which RAM region contains kernel data ,
* so we try it repeatedly and let the resource manager
* test it .
*/
request_resource ( res , & code_resource ) ;
request_resource ( res , & data_resource ) ;
request_resource ( res , & bss_resource ) ;
2005-04-16 15:20:36 -07:00
/*
2010-05-11 13:52:50 +09:00
* Also make sure that there is a PMB mapping that covers this
* range before we attempt to activate it , to avoid reset by MMU .
* We can hit this path with NUMA or memory hot - add .
2005-04-16 15:20:36 -07:00
*/
2010-05-11 13:52:50 +09:00
pmb_bolt_mapping ( ( unsigned long ) __va ( start ) , start , end - start ,
PAGE_KERNEL ) ;
2009-07-03 16:16:54 +09:00
2008-04-23 20:56:44 +09:00
add_active_range ( nid , start_pfn , end_pfn ) ;
2007-03-28 16:38:13 +09:00
}
2010-05-10 15:39:05 +09:00
void __init __weak plat_early_device_setup ( void )
2009-04-15 10:50:21 +00:00
{
}
2007-03-28 16:38:13 +09:00
void __init setup_arch ( char * * cmdline_p )
{
enable_mmu ( ) ;
ROOT_DEV = old_decode_dev ( ORIG_ROOT_DEV ) ;
2008-05-13 17:40:17 +09:00
printk ( KERN_NOTICE " Boot params: \n "
" ... MOUNT_ROOT_RDONLY - %08lx \n "
" ... RAMDISK_FLAGS - %08lx \n "
" ... ORIG_ROOT_DEV - %08lx \n "
" ... LOADER_TYPE - %08lx \n "
" ... INITRD_START - %08lx \n "
" ... INITRD_SIZE - %08lx \n " ,
MOUNT_ROOT_RDONLY , RAMDISK_FLAGS ,
ORIG_ROOT_DEV , LOADER_TYPE ,
INITRD_START , INITRD_SIZE ) ;
2007-03-28 16:38:13 +09:00
# ifdef CONFIG_BLK_DEV_RAM
rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK ;
rd_prompt = ( ( RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG ) ! = 0 ) ;
rd_doload = ( ( RAMDISK_FLAGS & RAMDISK_LOAD_FLAG ) ! = 0 ) ;
# endif
if ( ! MOUNT_ROOT_RDONLY )
root_mountflags & = ~ MS_RDONLY ;
init_mm . start_code = ( unsigned long ) _text ;
init_mm . end_code = ( unsigned long ) _etext ;
init_mm . end_data = ( unsigned long ) _edata ;
init_mm . brk = ( unsigned long ) _end ;
code_resource . start = virt_to_phys ( _text ) ;
code_resource . end = virt_to_phys ( _etext ) - 1 ;
data_resource . start = virt_to_phys ( _etext ) ;
data_resource . end = virt_to_phys ( _edata ) - 1 ;
2008-04-23 20:50:27 +09:00
bss_resource . start = virt_to_phys ( __bss_start ) ;
bss_resource . end = virt_to_phys ( _ebss ) - 1 ;
2007-03-28 16:38:13 +09:00
2009-08-24 16:25:38 +09:00
# ifdef CONFIG_CMDLINE_OVERWRITE
2007-05-14 17:48:00 +09:00
strlcpy ( command_line , CONFIG_CMDLINE , sizeof ( command_line ) ) ;
# else
strlcpy ( command_line , COMMAND_LINE , sizeof ( command_line ) ) ;
2009-08-24 16:25:38 +09:00
# ifdef CONFIG_CMDLINE_EXTEND
strlcat ( command_line , " " , sizeof ( command_line ) ) ;
strlcat ( command_line , CONFIG_CMDLINE , sizeof ( command_line ) ) ;
# endif
2007-05-14 17:48:00 +09:00
# endif
2007-05-14 15:59:09 +09:00
2007-05-14 17:48:00 +09:00
/* Save unparsed command line copy for /proc/cmdline */
memcpy ( boot_command_line , command_line , COMMAND_LINE_SIZE ) ;
2007-05-14 15:59:09 +09:00
* cmdline_p = command_line ;
2007-03-28 16:38:13 +09:00
parse_early_param ( ) ;
2009-04-15 10:50:21 +00:00
plat_early_device_setup ( ) ;
2007-05-14 15:59:09 +09:00
sh_mv_setup ( ) ;
2007-03-28 16:38:13 +09:00
2010-05-11 13:32:19 +09:00
/* Let earlyprintk output early console messages */
early_platform_driver_probe ( " earlyprintk " , 1 , 1 ) ;
2007-05-23 17:48:36 +09:00
2010-05-11 13:32:19 +09:00
paging_init ( ) ;
2005-04-16 15:20:36 -07:00
# ifdef CONFIG_DUMMY_CONSOLE
conswitchp = & dummy_con ;
# endif
/* Perform the machine specific initialisation */
2006-09-27 18:17:31 +09:00
if ( likely ( sh_mv . mv_setup ) )
sh_mv . mv_setup ( cmdline_p ) ;
2005-04-16 15:20:36 -07:00
2007-09-21 18:39:49 +09:00
plat_smp_setup ( ) ;
2007-05-23 17:48:36 +09:00
}
2005-04-16 15:20:36 -07:00
2009-05-28 11:51:51 +00:00
/* processor boot mode configuration */
int generic_mode_pins ( void )
{
pr_warning ( " generic_mode_pins(): missing mode pin configuration \n " ) ;
return 0 ;
}
int test_mode_pin ( int pin )
{
2009-06-02 09:22:02 +00:00
return sh_mv . mv_mode_pins ( ) & pin ;
2009-05-28 11:51:51 +00:00
}