2009-03-27 14:25:24 +01:00
/*
* Copyright ( C ) 2007 - 2009 Michal Simek < monstr @ monstr . eu >
* Copyright ( C ) 2007 - 2009 PetaLogix
* Copyright ( C ) 2006 Atmark Techno , Inc .
*
* 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 .
*/
# include <linux/init.h>
2013-12-18 17:18:48 +01:00
# include <linux/clk-provider.h>
2013-08-27 11:13:29 +02:00
# include <linux/clocksource.h>
2009-03-27 14:25:24 +01:00
# include <linux/string.h>
# include <linux/seq_file.h>
# include <linux/cpu.h>
# include <linux/initrd.h>
# include <linux/console.h>
# include <linux/debugfs.h>
2013-09-07 14:05:10 -05:00
# include <linux/of_fdt.h>
2009-03-27 14:25:24 +01:00
# include <asm/setup.h>
# include <asm/sections.h>
# include <asm/page.h>
# include <linux/io.h>
# include <linux/bug.h>
# include <linux/param.h>
2010-01-18 15:27:11 +01:00
# include <linux/pci.h>
2009-03-27 14:25:24 +01:00
# include <linux/cache.h>
2010-01-14 11:21:02 +01:00
# include <linux/of_platform.h>
# include <linux/dma-mapping.h>
2009-03-27 14:25:24 +01:00
# include <asm/cacheflush.h>
# include <asm/entry.h>
# include <asm/cpuinfo.h>
# include <asm/prom.h>
# include <asm/pgtable.h>
DEFINE_PER_CPU ( unsigned int , KSP ) ; /* Saved kernel stack pointer */
DEFINE_PER_CPU ( unsigned int , KM ) ; /* Kernel/user mode */
DEFINE_PER_CPU ( unsigned int , ENTRY_SP ) ; /* Saved SP on kernel entry */
DEFINE_PER_CPU ( unsigned int , R11_SAVE ) ; /* Temp variable for entry */
DEFINE_PER_CPU ( unsigned int , CURRENT_SAVE ) ; /* Saved current pointer */
unsigned int boot_cpuid ;
2012-08-16 15:53:35 +02:00
/*
* Placed cmd_line to . data section because can be initialized from
* ASM code . Default position is BSS section which is cleared
* in machine_early_init ( ) .
*/
char cmd_line [ COMMAND_LINE_SIZE ] __attribute__ ( ( section ( " .data " ) ) ) ;
2009-03-27 14:25:24 +01:00
void __init setup_arch ( char * * cmdline_p )
{
2013-08-26 10:19:07 -05:00
* cmdline_p = boot_command_line ;
2009-03-27 14:25:24 +01:00
console_verbose ( ) ;
unflatten_device_tree ( ) ;
setup_cpuinfo ( ) ;
2009-12-10 11:43:57 +01:00
microblaze_cache_init ( ) ;
2009-03-27 14:25:24 +01:00
setup_memory ( ) ;
2011-04-04 15:45:06 +02:00
# ifdef CONFIG_EARLY_PRINTK
/* remap early console to virtual address */
remap_early_printk ( ) ;
# endif
2010-01-18 15:27:11 +01:00
xilinx_pci_init ( ) ;
2009-03-27 14:25:24 +01:00
# ifdef CONFIG_VT
# if defined(CONFIG_XILINX_CONSOLE)
conswitchp = & xil_con ;
# elif defined(CONFIG_DUMMY_CONSOLE)
conswitchp = & dummy_con ;
# endif
# endif
}
# ifdef CONFIG_MTD_UCLINUX
/* Handle both romfs and cramfs types, without generating unnecessary
code ( ie no point checking for CRAMFS if it ' s not even enabled ) */
inline unsigned get_romfs_len ( unsigned * addr )
{
# ifdef CONFIG_ROMFS_FS
if ( memcmp ( & addr [ 0 ] , " -rom1fs- " , 8 ) = = 0 ) /* romfs */
return be32_to_cpu ( addr [ 2 ] ) ;
# endif
# ifdef CONFIG_CRAMFS
if ( addr [ 0 ] = = le32_to_cpu ( 0x28cd3d45 ) ) /* cramfs */
return le32_to_cpu ( addr [ 1 ] ) ;
# endif
return 0 ;
}
# endif /* CONFIG_MTD_UCLINUX_EBSS */
2010-02-08 16:41:38 +01:00
unsigned long kernel_tlb ;
2009-03-27 14:25:24 +01:00
void __init machine_early_init ( const char * cmdline , unsigned int ram ,
2010-02-08 16:41:38 +01:00
unsigned int fdt , unsigned int msr , unsigned int tlb0 ,
unsigned int tlb1 )
2009-03-27 14:25:24 +01:00
{
2010-11-08 12:37:40 +01:00
unsigned long * src , * dst ;
unsigned int offset = 0 ;
2009-03-27 14:25:24 +01:00
2009-05-19 14:33:47 +02:00
/* If CONFIG_MTD_UCLINUX is defined, assume ROMFS is at the
* end of kernel . There are two position which we want to check .
* The first is __init_end and the second __bss_start .
*/
# ifdef CONFIG_MTD_UCLINUX
int romfs_size ;
unsigned int romfs_base ;
char * old_klimit = klimit ;
romfs_base = ( ram ? ram : ( unsigned int ) & __init_end ) ;
romfs_size = PAGE_ALIGN ( get_romfs_len ( ( unsigned * ) romfs_base ) ) ;
if ( ! romfs_size ) {
romfs_base = ( unsigned int ) & __bss_start ;
romfs_size = PAGE_ALIGN ( get_romfs_len ( ( unsigned * ) romfs_base ) ) ;
}
/* Move ROMFS out of BSS before clearing it */
if ( romfs_size > 0 ) {
2012-05-31 22:39:21 +02:00
memmove ( & __bss_stop , ( int * ) romfs_base , romfs_size ) ;
2009-05-19 14:33:47 +02:00
klimit + = romfs_size ;
}
# endif
2009-03-27 14:25:24 +01:00
/* clearing bss section */
memset ( __bss_start , 0 , __bss_stop - __bss_start ) ;
memset ( _ssbss , 0 , _esbss - _ssbss ) ;
2009-12-10 12:07:02 +01:00
lockdep_init ( ) ;
2009-03-27 14:25:24 +01:00
/* initialize device tree for usage in early_printk */
2013-11-12 20:42:18 +01:00
early_init_devtree ( _fdt_start ) ;
2009-03-27 14:25:24 +01:00
# ifdef CONFIG_EARLY_PRINTK
setup_early_printk ( NULL ) ;
# endif
2010-02-08 16:41:38 +01:00
/* setup kernel_tlb after BSS cleaning
* Maybe worth to move to asm code */
kernel_tlb = tlb0 + tlb1 ;
/* printk("TLB1 0x%08x, TLB0 0x%08x, tlb 0x%x\n", tlb0,
tlb1 , kernel_tlb ) ; */
2012-12-27 10:40:38 +01:00
pr_info ( " Ramdisk addr 0x%08x, " , ram ) ;
2009-06-22 10:28:40 +02:00
if ( fdt )
2012-12-27 10:40:38 +01:00
pr_info ( " FDT at 0x%08x \n " , fdt ) ;
2009-06-22 10:28:40 +02:00
else
2013-11-12 20:42:18 +01:00
pr_info ( " Compiled-in FDT at %p \n " , _fdt_start ) ;
2009-03-27 14:25:24 +01:00
# ifdef CONFIG_MTD_UCLINUX
2012-12-27 10:40:38 +01:00
pr_info ( " Found romfs @ 0x%08x (0x%08x) \n " ,
2009-05-19 14:33:47 +02:00
romfs_base , romfs_size ) ;
2012-12-27 10:40:38 +01:00
pr_info ( " #### klimit %p #### \n " , old_klimit ) ;
2009-05-19 14:33:47 +02:00
BUG_ON ( romfs_size < 0 ) ; /* What else can we do? */
2012-12-27 10:40:38 +01:00
pr_info ( " Moved 0x%08x bytes from 0x%08x to 0x%08x \n " ,
2012-05-31 22:39:21 +02:00
romfs_size , romfs_base , ( unsigned ) & __bss_stop ) ;
2009-05-19 14:33:47 +02:00
2012-12-27 10:40:38 +01:00
pr_info ( " New klimit: 0x%08x \n " , ( unsigned ) klimit ) ;
2009-03-27 14:25:24 +01:00
# endif
2009-07-30 14:31:23 +02:00
# if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
2012-12-27 10:40:38 +01:00
if ( msr ) {
pr_info ( " !!!Your kernel has setup MSR instruction but " ) ;
pr_cont ( " CPU don't have it %x \n " , msr ) ;
}
2009-07-30 14:31:23 +02:00
# else
2012-12-27 10:40:38 +01:00
if ( ! msr ) {
pr_info ( " !!!Your kernel not setup MSR instruction but " ) ;
2013-11-19 14:27:33 +01:00
pr_cont ( " CPU have it %x \n " , msr ) ;
2012-12-27 10:40:38 +01:00
}
2009-07-30 14:31:23 +02:00
# endif
2010-11-08 12:37:40 +01:00
/* Do not copy reset vectors. offset = 0x2 means skip the first
* two instructions . dst is pointer to MB vectors which are placed
* in block ram . If you want to copy reset vector setup offset to 0x0 */
# if !CONFIG_MANUAL_RESET_VECTOR
offset = 0x2 ;
# endif
dst = ( unsigned long * ) ( offset * sizeof ( u32 ) ) ;
for ( src = __ivt_start + offset ; src < __ivt_end ; src + + , dst + + )
2009-03-27 14:25:24 +01:00
* dst = * src ;
/* Initialize global data */
per_cpu ( KM , 0 ) = 0x1 ; /* We start in kernel mode */
per_cpu ( CURRENT_SAVE , 0 ) = ( unsigned long ) current ;
}
2013-08-27 11:13:29 +02:00
void __init time_init ( void )
{
2013-12-18 17:18:48 +01:00
of_clk_init ( NULL ) ;
setup_cpuinfo_clk ( ) ;
2013-08-27 11:13:29 +02:00
clocksource_of_init ( ) ;
}
2009-03-27 14:25:24 +01:00
# ifdef CONFIG_DEBUG_FS
struct dentry * of_debugfs_root ;
static int microblaze_debugfs_init ( void )
{
of_debugfs_root = debugfs_create_dir ( " microblaze " , NULL ) ;
return of_debugfs_root = = NULL ;
}
arch_initcall ( microblaze_debugfs_init ) ;
2010-02-08 16:41:38 +01:00
2012-03-28 10:31:36 +02:00
# ifdef CONFIG_MMU
2010-02-08 16:41:38 +01:00
static int __init debugfs_tlb ( void )
{
struct dentry * d ;
if ( ! of_debugfs_root )
return - ENODEV ;
d = debugfs_create_u32 ( " tlb_skip " , S_IRUGO , of_debugfs_root , & tlb_skip ) ;
if ( ! d )
return - ENOMEM ;
2013-02-01 15:11:21 +01:00
return 0 ;
2010-02-08 16:41:38 +01:00
}
device_initcall ( debugfs_tlb ) ;
2012-03-28 10:31:36 +02:00
# endif
2009-03-27 14:25:24 +01:00
# endif
2010-01-14 11:21:02 +01:00
static int dflt_bus_notify ( struct notifier_block * nb ,
unsigned long action , void * data )
{
struct device * dev = data ;
/* We are only intereted in device addition */
if ( action ! = BUS_NOTIFY_ADD_DEVICE )
return 0 ;
set_dma_ops ( dev , & dma_direct_ops ) ;
return NOTIFY_DONE ;
}
static struct notifier_block dflt_plat_bus_notifier = {
. notifier_call = dflt_bus_notify ,
. priority = INT_MAX ,
} ;
static int __init setup_bus_notifier ( void )
{
bus_register_notifier ( & platform_bus_type , & dflt_plat_bus_notifier ) ;
return 0 ;
}
2012-01-10 12:15:58 +01:00
2012-01-30 10:53:08 +01:00
arch_initcall ( setup_bus_notifier ) ;