···11+/*22+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>33+ *44+ * This program is free software; you can redistribute it and/or modify55+ * it under the terms of the GNU General Public License as published by66+ * the Free Software Foundation; either version 2 of the License, or77+ * (at your option) any later version.88+ *99+ * This program is distributed in the hope that it will be useful,1010+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1111+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212+ * GNU General Public License for more details.1313+ *1414+ * You should have received a copy of the GNU General Public License1515+ * along with this program. If not, see <http://www.gnu.org/licenses/>.1616+ *1717+ */1818+1919+#ifndef _ASM_NIOS2_SETUP_H2020+#define _ASM_NIOS2_SETUP_H2121+2222+#include <asm-generic/setup.h>2323+2424+#ifndef __ASSEMBLY__2525+#ifdef __KERNEL__2626+2727+extern char exception_handler_hook[];2828+extern char fast_handler[];2929+extern char fast_handler_end[];3030+3131+extern void pagetable_init(void);3232+3333+extern void setup_early_printk(void);3434+3535+#endif/* __KERNEL__ */3636+#endif /* __ASSEMBLY__ */3737+3838+#endif /* _ASM_NIOS2_SETUP_H */
+175
arch/nios2/kernel/head.S
···11+/*22+ * Copyright (C) 2009 Wind River Systems Inc33+ * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com44+ * Copyright (C) 2004 Microtronix Datacom Ltd55+ * Copyright (C) 2001 Vic Phillips, Microtronix Datacom Ltd.66+ *77+ * Based on head.S for Altera's Excalibur development board with nios processor88+ *99+ * Based on the following from the Excalibur sdk distribution:1010+ * NA_MemoryMap.s, NR_JumpToStart.s, NR_Setup.s, NR_CWPManager.s1111+ *1212+ * This file is subject to the terms and conditions of the GNU General Public1313+ * License. See the file "COPYING" in the main directory of this archive1414+ * for more details.1515+ */1616+1717+#include <linux/init.h>1818+#include <linux/linkage.h>1919+#include <asm/thread_info.h>2020+#include <asm/processor.h>2121+#include <asm/cache.h>2222+#include <asm/page.h>2323+#include <asm/asm-offsets.h>2424+#include <asm/asm-macros.h>2525+2626+/*2727+ * ZERO_PAGE is a special page that is used for zero-initialized2828+ * data and COW.2929+ */3030+.data3131+.global empty_zero_page3232+.align 123333+empty_zero_page:3434+ .space PAGE_SIZE3535+3636+/*3737+ * This global variable is used as an extension to the nios'3838+ * STATUS register to emulate a user/supervisor mode.3939+ */4040+ .data4141+ .align 24242+ .set noat4343+4444+ .global _current_thread4545+_current_thread:4646+ .long 04747+/*4848+ * Input(s): passed from u-boot4949+ * r4 - Optional pointer to a board information structure.5050+ * r5 - Optional pointer to the physical starting address of the init RAM5151+ * disk.5252+ * r6 - Optional pointer to the physical ending address of the init RAM5353+ * disk.5454+ * r7 - Optional pointer to the physical starting address of any kernel5555+ * command-line parameters.5656+ */5757+5858+/*5959+ * First executable code - detected and jumped to by the ROM bootstrap6060+ * if the code resides in flash (looks for "Nios" at offset 0x0c from6161+ * the potential executable image).6262+ */6363+ __HEAD6464+ENTRY(_start)6565+ wrctl status, r0 /* Disable interrupts */6666+6767+ /* Initialize all cache lines within the instruction cache */6868+ movia r1, NIOS2_ICACHE_SIZE6969+ movui r2, NIOS2_ICACHE_LINE_SIZE7070+7171+icache_init:7272+ initi r17373+ sub r1, r1, r27474+ bgt r1, r0, icache_init7575+ br 1f7676+7777+ /*7878+ * This is the default location for the exception handler. Code in jump7979+ * to our handler8080+ */8181+ENTRY(exception_handler_hook)8282+ movia r24, inthandler8383+ jmp r248484+8585+ENTRY(fast_handler)8686+ nextpc et8787+helper:8888+ stw r3, r3save - helper(et)8989+9090+ rdctl r3 , pteaddr9191+ srli r3, r3, 129292+ slli r3, r3, 29393+ movia et, pgd_current9494+9595+ ldw et, 0(et)9696+ add r3, et, r39797+ ldw et, 0(r3)9898+9999+ rdctl r3, pteaddr100100+ andi r3, r3, 0xfff101101+ add et, r3, et102102+ ldw et, 0(et)103103+ wrctl tlbacc, et104104+ nextpc et105105+helper2:106106+ ldw r3, r3save - helper2(et)107107+ subi ea, ea, 4108108+ eret109109+r3save:110110+ .word 0x0111111+ENTRY(fast_handler_end)112112+113113+1:114114+ /*115115+ * After the instruction cache is initialized, the data cache must116116+ * also be initialized.117117+ */118118+ movia r1, NIOS2_DCACHE_SIZE119119+ movui r2, NIOS2_DCACHE_LINE_SIZE120120+121121+dcache_init:122122+ initd 0(r1)123123+ sub r1, r1, r2124124+ bgt r1, r0, dcache_init125125+126126+ nextpc r1 /* Find out where we are */127127+chkadr:128128+ movia r2, chkadr129129+ beq r1, r2,finish_move /* We are running in RAM done */130130+ addi r1, r1,(_start - chkadr) /* Source */131131+ movia r2, _start /* Destination */132132+ movia r3, __bss_start /* End of copy */133133+134134+loop_move: /* r1: src, r2: dest, r3: last dest */135135+ ldw r8, 0(r1) /* load a word from [r1] */136136+ stw r8, 0(r2) /* store a word to dest [r2] */137137+ flushd 0(r2) /* Flush cache for safety */138138+ addi r1, r1, 4 /* inc the src addr */139139+ addi r2, r2, 4 /* inc the dest addr */140140+ blt r2, r3, loop_move141141+142142+ movia r1, finish_move /* VMA(_start)->l1 */143143+ jmp r1 /* jmp to _start */144144+145145+finish_move:146146+147147+ /* Mask off all possible interrupts */148148+ wrctl ienable, r0149149+150150+ /* Clear .bss */151151+ movia r2, __bss_start152152+ movia r1, __bss_stop153153+1:154154+ stb r0, 0(r2)155155+ addi r2, r2, 1156156+ bne r1, r2, 1b157157+158158+ movia r1, init_thread_union /* set stack at top of the task union */159159+ addi sp, r1, THREAD_SIZE160160+ movia r2, _current_thread /* Remember current thread */161161+ stw r1, 0(r2)162162+163163+ movia r1, nios2_boot_init /* save args r4-r7 passed from u-boot */164164+ callr r1165165+166166+ movia r1, start_kernel /* call start_kernel as a subroutine */167167+ callr r1168168+169169+ /* If we return from start_kernel, break to the oci debugger and170170+ * buggered we are.171171+ */172172+ break173173+174174+ /* End of startup code */175175+.set at
+218
arch/nios2/kernel/setup.c
···11+/*22+ * Nios2-specific parts of system setup33+ *44+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>55+ * Copyright (C) 2004 Microtronix Datacom Ltd.66+ * Copyright (C) 2001 Vic Phillips <vic@microtronix.com>77+ *88+ * This file is subject to the terms and conditions of the GNU General Public99+ * License. See the file "COPYING" in the main directory of this archive1010+ * for more details.1111+ */1212+1313+#include <linux/export.h>1414+#include <linux/kernel.h>1515+#include <linux/mm.h>1616+#include <linux/sched.h>1717+#include <linux/console.h>1818+#include <linux/bootmem.h>1919+#include <linux/initrd.h>2020+#include <linux/of_fdt.h>2121+2222+#include <asm/mmu_context.h>2323+#include <asm/sections.h>2424+#include <asm/setup.h>2525+#include <asm/cpuinfo.h>2626+2727+unsigned long memory_start;2828+EXPORT_SYMBOL(memory_start);2929+3030+unsigned long memory_end;3131+EXPORT_SYMBOL(memory_end);3232+3333+unsigned long memory_size;3434+3535+static struct pt_regs fake_regs = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,3636+ 0, 0, 0, 0, 0, 0,3737+ 0};3838+3939+/* Copy a short hook instruction sequence to the exception address */4040+static inline void copy_exception_handler(unsigned int addr)4141+{4242+ unsigned int start = (unsigned int) exception_handler_hook;4343+ volatile unsigned int tmp = 0;4444+4545+ if (start == addr) {4646+ /* The CPU exception address already points to the handler. */4747+ return;4848+ }4949+5050+ __asm__ __volatile__ (5151+ "ldw %2,0(%0)\n"5252+ "stw %2,0(%1)\n"5353+ "ldw %2,4(%0)\n"5454+ "stw %2,4(%1)\n"5555+ "ldw %2,8(%0)\n"5656+ "stw %2,8(%1)\n"5757+ "flushd 0(%1)\n"5858+ "flushd 4(%1)\n"5959+ "flushd 8(%1)\n"6060+ "flushi %1\n"6161+ "addi %1,%1,4\n"6262+ "flushi %1\n"6363+ "addi %1,%1,4\n"6464+ "flushi %1\n"6565+ "flushp\n"6666+ : /* no output registers */6767+ : "r" (start), "r" (addr), "r" (tmp)6868+ : "memory"6969+ );7070+}7171+7272+/* Copy the fast TLB miss handler */7373+static inline void copy_fast_tlb_miss_handler(unsigned int addr)7474+{7575+ unsigned int start = (unsigned int) fast_handler;7676+ unsigned int end = (unsigned int) fast_handler_end;7777+ volatile unsigned int tmp = 0;7878+7979+ __asm__ __volatile__ (8080+ "1:\n"8181+ " ldw %3,0(%0)\n"8282+ " stw %3,0(%1)\n"8383+ " flushd 0(%1)\n"8484+ " flushi %1\n"8585+ " flushp\n"8686+ " addi %0,%0,4\n"8787+ " addi %1,%1,4\n"8888+ " bne %0,%2,1b\n"8989+ : /* no output registers */9090+ : "r" (start), "r" (addr), "r" (end), "r" (tmp)9191+ : "memory"9292+ );9393+}9494+9595+/*9696+ * save args passed from u-boot, called from head.S9797+ *9898+ * @r4: NIOS magic9999+ * @r5: initrd start100100+ * @r6: initrd end or fdt101101+ * @r7: kernel command line102102+ */103103+asmlinkage void __init nios2_boot_init(unsigned r4, unsigned r5, unsigned r6,104104+ unsigned r7)105105+{106106+ unsigned dtb_passed = 0;107107+ char cmdline_passed[COMMAND_LINE_SIZE] = { 0, };108108+109109+#if defined(CONFIG_NIOS2_PASS_CMDLINE)110110+ if (r4 == 0x534f494e) { /* r4 is magic NIOS */111111+#if defined(CONFIG_BLK_DEV_INITRD)112112+ if (r5) { /* initramfs */113113+ initrd_start = r5;114114+ initrd_end = r6;115115+ }116116+#endif /* CONFIG_BLK_DEV_INITRD */117117+ dtb_passed = r6;118118+119119+ if (r7)120120+ strncpy(cmdline_passed, (char *)r7, COMMAND_LINE_SIZE);121121+ }122122+#endif123123+124124+ early_init_devtree((void *)dtb_passed);125125+126126+#ifndef CONFIG_CMDLINE_FORCE127127+ if (cmdline_passed[0])128128+ strncpy(boot_command_line, cmdline_passed, COMMAND_LINE_SIZE);129129+#ifdef CONFIG_NIOS2_CMDLINE_IGNORE_DTB130130+ else131131+ strncpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);132132+#endif133133+#endif134134+}135135+136136+void __init setup_arch(char **cmdline_p)137137+{138138+ int bootmap_size;139139+140140+ console_verbose();141141+142142+ memory_start = PAGE_ALIGN((unsigned long)__pa(_end));143143+ memory_end = (unsigned long) CONFIG_NIOS2_MEM_BASE + memory_size;144144+145145+ init_mm.start_code = (unsigned long) _stext;146146+ init_mm.end_code = (unsigned long) _etext;147147+ init_mm.end_data = (unsigned long) _edata;148148+ init_mm.brk = (unsigned long) _end;149149+ init_task.thread.kregs = &fake_regs;150150+151151+ /* Keep a copy of command line */152152+ *cmdline_p = boot_command_line;153153+154154+ min_low_pfn = PFN_UP(memory_start);155155+ max_low_pfn = PFN_DOWN(memory_end);156156+ max_mapnr = max_low_pfn;157157+158158+ /*159159+ * give all the memory to the bootmap allocator, tell it to put the160160+ * boot mem_map at the start of memory161161+ */162162+ pr_debug("init_bootmem_node(?,%#lx, %#x, %#lx)\n",163163+ min_low_pfn, PFN_DOWN(PHYS_OFFSET), max_low_pfn);164164+ bootmap_size = init_bootmem_node(NODE_DATA(0),165165+ min_low_pfn, PFN_DOWN(PHYS_OFFSET),166166+ max_low_pfn);167167+168168+ /*169169+ * free the usable memory, we have to make sure we do not free170170+ * the bootmem bitmap so we then reserve it after freeing it :-)171171+ */172172+ pr_debug("free_bootmem(%#lx, %#lx)\n",173173+ memory_start, memory_end - memory_start);174174+ free_bootmem(memory_start, memory_end - memory_start);175175+176176+ /*177177+ * Reserve the bootmem bitmap itself as well. We do this in two178178+ * steps (first step was init_bootmem()) because this catches179179+ * the (very unlikely) case of us accidentally initializing the180180+ * bootmem allocator with an invalid RAM area.181181+ *182182+ * Arguments are start, size183183+ */184184+ pr_debug("reserve_bootmem(%#lx, %#x)\n", memory_start, bootmap_size);185185+ reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);186186+187187+#ifdef CONFIG_BLK_DEV_INITRD188188+ if (initrd_start) {189189+ reserve_bootmem(virt_to_phys((void *)initrd_start),190190+ initrd_end - initrd_start, BOOTMEM_DEFAULT);191191+ }192192+#endif /* CONFIG_BLK_DEV_INITRD */193193+194194+ unflatten_and_copy_device_tree();195195+196196+ setup_cpuinfo();197197+198198+ copy_exception_handler(cpuinfo.exception_addr);199199+200200+ mmu_init();201201+202202+ copy_fast_tlb_miss_handler(cpuinfo.fast_tlb_miss_exc_addr);203203+204204+ /*205205+ * Initialize MMU context handling here because data from cpuinfo is206206+ * needed for this.207207+ */208208+ mmu_context_init();209209+210210+ /*211211+ * get kmalloc into gear212212+ */213213+ paging_init();214214+215215+#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)216216+ conswitchp = &dummy_con;217217+#endif218218+}