1ec9f9101SMichal Simek /* 2ec9f9101SMichal Simek * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> 3ec9f9101SMichal Simek * Copyright (C) 2007-2009 PetaLogix 4ec9f9101SMichal Simek * Copyright (C) 2006 Atmark Techno, Inc. 5ec9f9101SMichal Simek * 6ec9f9101SMichal Simek * This file is subject to the terms and conditions of the GNU General Public 7ec9f9101SMichal Simek * License. See the file "COPYING" in the main directory of this archive 8ec9f9101SMichal Simek * for more details. 9ec9f9101SMichal Simek */ 10ec9f9101SMichal Simek 11ec9f9101SMichal Simek #include <linux/init.h> 12c1120542SMichal Simek #include <linux/clk-provider.h> 134bcd943eSMichal Simek #include <linux/clocksource.h> 14ec9f9101SMichal Simek #include <linux/string.h> 15ec9f9101SMichal Simek #include <linux/seq_file.h> 16ec9f9101SMichal Simek #include <linux/cpu.h> 17ec9f9101SMichal Simek #include <linux/initrd.h> 18ec9f9101SMichal Simek #include <linux/console.h> 19ec9f9101SMichal Simek #include <linux/debugfs.h> 205c9f303eSRob Herring #include <linux/of_fdt.h> 21ec9f9101SMichal Simek 22ec9f9101SMichal Simek #include <asm/setup.h> 23ec9f9101SMichal Simek #include <asm/sections.h> 24ec9f9101SMichal Simek #include <asm/page.h> 25ec9f9101SMichal Simek #include <linux/io.h> 26ec9f9101SMichal Simek #include <linux/bug.h> 27ec9f9101SMichal Simek #include <linux/param.h> 28733cc218SMichal Simek #include <linux/pci.h> 29ec9f9101SMichal Simek #include <linux/cache.h> 3096f0e6fcSRob Herring #include <linux/of.h> 31ccfe27d7SMichal Simek #include <linux/dma-mapping.h> 32ec9f9101SMichal Simek #include <asm/cacheflush.h> 33ec9f9101SMichal Simek #include <asm/entry.h> 34ec9f9101SMichal Simek #include <asm/cpuinfo.h> 35ec9f9101SMichal Simek 36ec9f9101SMichal Simek #include <asm/pgtable.h> 37ec9f9101SMichal Simek 38ec9f9101SMichal Simek DEFINE_PER_CPU(unsigned int, KSP); /* Saved kernel stack pointer */ 39ec9f9101SMichal Simek DEFINE_PER_CPU(unsigned int, KM); /* Kernel/user mode */ 40ec9f9101SMichal Simek DEFINE_PER_CPU(unsigned int, ENTRY_SP); /* Saved SP on kernel entry */ 41ec9f9101SMichal Simek DEFINE_PER_CPU(unsigned int, R11_SAVE); /* Temp variable for entry */ 42ec9f9101SMichal Simek DEFINE_PER_CPU(unsigned int, CURRENT_SAVE); /* Saved current pointer */ 43ec9f9101SMichal Simek 44ec9f9101SMichal Simek unsigned int boot_cpuid; 45fcc1c0ffSMichal Simek /* 46fcc1c0ffSMichal Simek * Placed cmd_line to .data section because can be initialized from 47fcc1c0ffSMichal Simek * ASM code. Default position is BSS section which is cleared 48fcc1c0ffSMichal Simek * in machine_early_init(). 49fcc1c0ffSMichal Simek */ 50fcc1c0ffSMichal Simek char cmd_line[COMMAND_LINE_SIZE] __attribute__ ((section(".data"))); 51ec9f9101SMichal Simek 52ec9f9101SMichal Simek void __init setup_arch(char **cmdline_p) 53ec9f9101SMichal Simek { 54dc0b4335SRob Herring *cmdline_p = boot_command_line; 55ec9f9101SMichal Simek 5696f0e6fcSRob Herring setup_memory(); 5796f0e6fcSRob Herring parse_early_param(); 5896f0e6fcSRob Herring 59ec9f9101SMichal Simek console_verbose(); 60ec9f9101SMichal Simek 61ec9f9101SMichal Simek unflatten_device_tree(); 62ec9f9101SMichal Simek 63ec9f9101SMichal Simek setup_cpuinfo(); 64ec9f9101SMichal Simek 652ee2ff87SMichal Simek microblaze_cache_init(); 66ec9f9101SMichal Simek 67733cc218SMichal Simek xilinx_pci_init(); 68733cc218SMichal Simek 698c770db9SPaul Bolle #if defined(CONFIG_DUMMY_CONSOLE) 70ec9f9101SMichal Simek conswitchp = &dummy_con; 71ec9f9101SMichal Simek #endif 72ec9f9101SMichal Simek } 73ec9f9101SMichal Simek 74ec9f9101SMichal Simek #ifdef CONFIG_MTD_UCLINUX 75ec9f9101SMichal Simek /* Handle both romfs and cramfs types, without generating unnecessary 76ec9f9101SMichal Simek code (ie no point checking for CRAMFS if it's not even enabled) */ 77ec9f9101SMichal Simek inline unsigned get_romfs_len(unsigned *addr) 78ec9f9101SMichal Simek { 79ec9f9101SMichal Simek #ifdef CONFIG_ROMFS_FS 80ec9f9101SMichal Simek if (memcmp(&addr[0], "-rom1fs-", 8) == 0) /* romfs */ 81ec9f9101SMichal Simek return be32_to_cpu(addr[2]); 82ec9f9101SMichal Simek #endif 83ec9f9101SMichal Simek 84ec9f9101SMichal Simek #ifdef CONFIG_CRAMFS 85ec9f9101SMichal Simek if (addr[0] == le32_to_cpu(0x28cd3d45)) /* cramfs */ 86ec9f9101SMichal Simek return le32_to_cpu(addr[1]); 87ec9f9101SMichal Simek #endif 88ec9f9101SMichal Simek return 0; 89ec9f9101SMichal Simek } 90ec9f9101SMichal Simek #endif /* CONFIG_MTD_UCLINUX_EBSS */ 91ec9f9101SMichal Simek 9295b0f9eaSMichal Simek unsigned long kernel_tlb; 9395b0f9eaSMichal Simek 94ec9f9101SMichal Simek void __init machine_early_init(const char *cmdline, unsigned int ram, 9595b0f9eaSMichal Simek unsigned int fdt, unsigned int msr, unsigned int tlb0, 9695b0f9eaSMichal Simek unsigned int tlb1) 97ec9f9101SMichal Simek { 980b9b0200SMichal Simek unsigned long *src, *dst; 990b9b0200SMichal Simek unsigned int offset = 0; 100ec9f9101SMichal Simek 101cda1fd5aSMichal Simek /* If CONFIG_MTD_UCLINUX is defined, assume ROMFS is at the 102cda1fd5aSMichal Simek * end of kernel. There are two position which we want to check. 103cda1fd5aSMichal Simek * The first is __init_end and the second __bss_start. 104cda1fd5aSMichal Simek */ 105cda1fd5aSMichal Simek #ifdef CONFIG_MTD_UCLINUX 106cda1fd5aSMichal Simek int romfs_size; 107cda1fd5aSMichal Simek unsigned int romfs_base; 108cda1fd5aSMichal Simek char *old_klimit = klimit; 109cda1fd5aSMichal Simek 110cda1fd5aSMichal Simek romfs_base = (ram ? ram : (unsigned int)&__init_end); 111cda1fd5aSMichal Simek romfs_size = PAGE_ALIGN(get_romfs_len((unsigned *)romfs_base)); 112cda1fd5aSMichal Simek if (!romfs_size) { 113cda1fd5aSMichal Simek romfs_base = (unsigned int)&__bss_start; 114cda1fd5aSMichal Simek romfs_size = PAGE_ALIGN(get_romfs_len((unsigned *)romfs_base)); 115cda1fd5aSMichal Simek } 116cda1fd5aSMichal Simek 117cda1fd5aSMichal Simek /* Move ROMFS out of BSS before clearing it */ 118cda1fd5aSMichal Simek if (romfs_size > 0) { 119363737d6SGeert Uytterhoeven memmove(&__bss_stop, (int *)romfs_base, romfs_size); 120cda1fd5aSMichal Simek klimit += romfs_size; 121cda1fd5aSMichal Simek } 122cda1fd5aSMichal Simek #endif 123cda1fd5aSMichal Simek 124ec9f9101SMichal Simek /* clearing bss section */ 125ec9f9101SMichal Simek memset(__bss_start, 0, __bss_stop-__bss_start); 126ec9f9101SMichal Simek memset(_ssbss, 0, _esbss-_ssbss); 127ec9f9101SMichal Simek 128ec9f9101SMichal Simek /* initialize device tree for usage in early_printk */ 1297746c99fSGeert Uytterhoeven early_init_devtree(_fdt_start); 130ec9f9101SMichal Simek 13195b0f9eaSMichal Simek /* setup kernel_tlb after BSS cleaning 13295b0f9eaSMichal Simek * Maybe worth to move to asm code */ 13395b0f9eaSMichal Simek kernel_tlb = tlb0 + tlb1; 13495b0f9eaSMichal Simek /* printk("TLB1 0x%08x, TLB0 0x%08x, tlb 0x%x\n", tlb0, 13595b0f9eaSMichal Simek tlb1, kernel_tlb); */ 13695b0f9eaSMichal Simek 1376bd55f0bSMichal Simek pr_info("Ramdisk addr 0x%08x, ", ram); 138909964ecSJohn Williams if (fdt) 1396bd55f0bSMichal Simek pr_info("FDT at 0x%08x\n", fdt); 14074510f2aSMichal Simek else 1417746c99fSGeert Uytterhoeven pr_info("Compiled-in FDT at %p\n", _fdt_start); 142ec9f9101SMichal Simek 143ec9f9101SMichal Simek #ifdef CONFIG_MTD_UCLINUX 1446bd55f0bSMichal Simek pr_info("Found romfs @ 0x%08x (0x%08x)\n", 145cda1fd5aSMichal Simek romfs_base, romfs_size); 1466bd55f0bSMichal Simek pr_info("#### klimit %p ####\n", old_klimit); 147cda1fd5aSMichal Simek BUG_ON(romfs_size < 0); /* What else can we do? */ 148ec9f9101SMichal Simek 1496bd55f0bSMichal Simek pr_info("Moved 0x%08x bytes from 0x%08x to 0x%08x\n", 150363737d6SGeert Uytterhoeven romfs_size, romfs_base, (unsigned)&__bss_stop); 151ec9f9101SMichal Simek 1526bd55f0bSMichal Simek pr_info("New klimit: 0x%08x\n", (unsigned)klimit); 153ec9f9101SMichal Simek #endif 154ec9f9101SMichal Simek 1552622434eSMichal Simek #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 1566bd55f0bSMichal Simek if (msr) { 1576bd55f0bSMichal Simek pr_info("!!!Your kernel has setup MSR instruction but "); 1586bd55f0bSMichal Simek pr_cont("CPU don't have it %x\n", msr); 1596bd55f0bSMichal Simek } 1602622434eSMichal Simek #else 1616bd55f0bSMichal Simek if (!msr) { 1626bd55f0bSMichal Simek pr_info("!!!Your kernel not setup MSR instruction but "); 163eae38104SMichal Simek pr_cont("CPU have it %x\n", msr); 1646bd55f0bSMichal Simek } 1652622434eSMichal Simek #endif 1662622434eSMichal Simek 1670b9b0200SMichal Simek /* Do not copy reset vectors. offset = 0x2 means skip the first 1680b9b0200SMichal Simek * two instructions. dst is pointer to MB vectors which are placed 1690b9b0200SMichal Simek * in block ram. If you want to copy reset vector setup offset to 0x0 */ 1700b9b0200SMichal Simek #if !CONFIG_MANUAL_RESET_VECTOR 1710b9b0200SMichal Simek offset = 0x2; 1720b9b0200SMichal Simek #endif 1730b9b0200SMichal Simek dst = (unsigned long *) (offset * sizeof(u32)); 1740b9b0200SMichal Simek for (src = __ivt_start + offset; src < __ivt_end; src++, dst++) 175ec9f9101SMichal Simek *dst = *src; 176ec9f9101SMichal Simek 177ec9f9101SMichal Simek /* Initialize global data */ 178ec9f9101SMichal Simek per_cpu(KM, 0) = 0x1; /* We start in kernel mode */ 179ec9f9101SMichal Simek per_cpu(CURRENT_SAVE, 0) = (unsigned long)current; 180ec9f9101SMichal Simek } 181ec9f9101SMichal Simek 1824bcd943eSMichal Simek void __init time_init(void) 1834bcd943eSMichal Simek { 184c1120542SMichal Simek of_clk_init(NULL); 185c1120542SMichal Simek setup_cpuinfo_clk(); 186ba5d08c0SDaniel Lezcano timer_probe(); 1874bcd943eSMichal Simek } 1884bcd943eSMichal Simek 189ec9f9101SMichal Simek #ifdef CONFIG_DEBUG_FS 190ec9f9101SMichal Simek struct dentry *of_debugfs_root; 191ec9f9101SMichal Simek 192ec9f9101SMichal Simek static int microblaze_debugfs_init(void) 193ec9f9101SMichal Simek { 194ec9f9101SMichal Simek of_debugfs_root = debugfs_create_dir("microblaze", NULL); 195226a893bSGreg Kroah-Hartman return 0; 196ec9f9101SMichal Simek } 197ec9f9101SMichal Simek arch_initcall(microblaze_debugfs_init); 198e02db0aaSMichal Simek 199a28d73caSMichal Simek # ifdef CONFIG_MMU 200e02db0aaSMichal Simek static int __init debugfs_tlb(void) 201e02db0aaSMichal Simek { 202226a893bSGreg Kroah-Hartman debugfs_create_u32("tlb_skip", S_IRUGO, of_debugfs_root, &tlb_skip); 2035b3084b5SMichal Simek return 0; 204e02db0aaSMichal Simek } 205e02db0aaSMichal Simek device_initcall(debugfs_tlb); 206ec9f9101SMichal Simek # endif 207a28d73caSMichal Simek #endif 208