1/* MN10300 Arch-specific initialisation 2 * 3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public Licence 8 * as published by the Free Software Foundation; either version 9 * 2 of the Licence, or (at your option) any later version. 10 */ 11#include <linux/errno.h> 12#include <linux/sched.h> 13#include <linux/kernel.h> 14#include <linux/mm.h> 15#include <linux/stddef.h> 16#include <linux/unistd.h> 17#include <linux/ptrace.h> 18#include <linux/user.h> 19#include <linux/tty.h> 20#include <linux/ioport.h> 21#include <linux/delay.h> 22#include <linux/init.h> 23#include <linux/bootmem.h> 24#include <linux/seq_file.h> 25#include <asm/processor.h> 26#include <linux/console.h> 27#include <asm/uaccess.h> 28#include <asm/system.h> 29#include <asm/setup.h> 30#include <asm/io.h> 31#include <asm/smp.h> 32#include <proc/proc.h> 33#include <asm/busctl-regs.h> 34#include <asm/fpu.h> 35#include <asm/sections.h> 36 37struct mn10300_cpuinfo boot_cpu_data; 38 39/* For PCI or other memory-mapped resources */ 40unsigned long pci_mem_start = 0x18000000; 41 42char redboot_command_line[COMMAND_LINE_SIZE] = 43 "console=ttyS0,115200 root=/dev/mtdblock3 rw"; 44 45char __initdata redboot_platform_name[COMMAND_LINE_SIZE]; 46 47static struct resource code_resource = { 48 .start = 0x100000, 49 .end = 0, 50 .name = "Kernel code", 51}; 52 53static struct resource data_resource = { 54 .start = 0, 55 .end = 0, 56 .name = "Kernel data", 57}; 58 59static unsigned long __initdata phys_memory_base; 60static unsigned long __initdata phys_memory_end; 61static unsigned long __initdata memory_end; 62unsigned long memory_size; 63 64struct thread_info *__current_ti = &init_thread_union.thread_info; 65struct task_struct *__current = &init_task; 66 67#define mn10300_known_cpus 3 68static const char *const mn10300_cputypes[] = { 69 "am33v1", 70 "am33v2", 71 "am34v1", 72 "unknown" 73}; 74 75/* 76 * 77 */ 78static void __init parse_mem_cmdline(char **cmdline_p) 79{ 80 char *from, *to, c; 81 82 /* save unparsed command line copy for /proc/cmdline */ 83 strcpy(boot_command_line, redboot_command_line); 84 85 /* see if there's an explicit memory size option */ 86 from = redboot_command_line; 87 to = redboot_command_line; 88 c = ' '; 89 90 for (;;) { 91 if (c == ' ' && !memcmp(from, "mem=", 4)) { 92 if (to != redboot_command_line) 93 to--; 94 memory_size = memparse(from + 4, &from); 95 } 96 97 c = *(from++); 98 if (!c) 99 break; 100 101 *(to++) = c; 102 } 103 104 *to = '\0'; 105 *cmdline_p = redboot_command_line; 106 107 if (memory_size == 0) 108 panic("Memory size not known\n"); 109 110 memory_end = (unsigned long) CONFIG_KERNEL_RAM_BASE_ADDRESS + 111 memory_size; 112 if (memory_end > phys_memory_end) 113 memory_end = phys_memory_end; 114} 115 116/* 117 * architecture specific setup 118 */ 119void __init setup_arch(char **cmdline_p) 120{ 121 unsigned long bootmap_size; 122 unsigned long kstart_pfn, start_pfn, free_pfn, end_pfn; 123 124 cpu_init(); 125 unit_setup(); 126 parse_mem_cmdline(cmdline_p); 127 128 init_mm.start_code = (unsigned long)&_text; 129 init_mm.end_code = (unsigned long) &_etext; 130 init_mm.end_data = (unsigned long) &_edata; 131 init_mm.brk = (unsigned long) &_end; 132 133 code_resource.start = virt_to_bus(&_text); 134 code_resource.end = virt_to_bus(&_etext)-1; 135 data_resource.start = virt_to_bus(&_etext); 136 data_resource.end = virt_to_bus(&_edata)-1; 137 138 start_pfn = (CONFIG_KERNEL_RAM_BASE_ADDRESS >> PAGE_SHIFT); 139 kstart_pfn = PFN_UP(__pa(&_text)); 140 free_pfn = PFN_UP(__pa(&_end)); 141 end_pfn = PFN_DOWN(__pa(memory_end)); 142 143 bootmap_size = init_bootmem_node(&contig_page_data, 144 free_pfn, 145 start_pfn, 146 end_pfn); 147 148 if (kstart_pfn > start_pfn) 149 free_bootmem(PFN_PHYS(start_pfn), 150 PFN_PHYS(kstart_pfn - start_pfn)); 151 152 free_bootmem(PFN_PHYS(free_pfn), 153 PFN_PHYS(end_pfn - free_pfn)); 154 155 /* If interrupt vector table is in main ram, then we need to 156 reserve the page it is occupying. */ 157 if (CONFIG_INTERRUPT_VECTOR_BASE >= CONFIG_KERNEL_RAM_BASE_ADDRESS && 158 CONFIG_INTERRUPT_VECTOR_BASE < memory_end) 159 reserve_bootmem(CONFIG_INTERRUPT_VECTOR_BASE, PAGE_SIZE, 160 BOOTMEM_DEFAULT); 161 162 reserve_bootmem(PAGE_ALIGN(PFN_PHYS(free_pfn)), bootmap_size, 163 BOOTMEM_DEFAULT); 164 165#ifdef CONFIG_VT 166#if defined(CONFIG_VGA_CONSOLE) 167 conswitchp = &vga_con; 168#elif defined(CONFIG_DUMMY_CONSOLE) 169 conswitchp = &dummy_con; 170#endif 171#endif 172 173 paging_init(); 174} 175 176/* 177 * perform CPU initialisation 178 */ 179void __init cpu_init(void) 180{ 181 unsigned long cpurev = CPUREV, type; 182 unsigned long base, size; 183 184 type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S; 185 if (type > mn10300_known_cpus) 186 type = mn10300_known_cpus; 187 188 printk(KERN_INFO "Matsushita %s, rev %ld\n", 189 mn10300_cputypes[type], 190 (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S); 191 192 /* determine the memory size and base from the memory controller regs */ 193 memory_size = 0; 194 195 base = SDBASE(0); 196 if (base & SDBASE_CE) { 197 size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT; 198 size = ~size + 1; 199 base &= SDBASE_CBA; 200 201 printk(KERN_INFO "SDRAM[0]: %luMb @%08lx\n", size >> 20, base); 202 memory_size += size; 203 phys_memory_base = base; 204 } 205 206 base = SDBASE(1); 207 if (base & SDBASE_CE) { 208 size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT; 209 size = ~size + 1; 210 base &= SDBASE_CBA; 211 212 printk(KERN_INFO "SDRAM[1]: %luMb @%08lx\n", size >> 20, base); 213 memory_size += size; 214 if (phys_memory_base == 0) 215 phys_memory_base = base; 216 } 217 218 phys_memory_end = phys_memory_base + memory_size; 219 220#ifdef CONFIG_FPU 221 fpu_init_state(); 222#endif 223} 224 225/* 226 * Get CPU information for use by the procfs. 227 */ 228static int show_cpuinfo(struct seq_file *m, void *v) 229{ 230 unsigned long cpurev = CPUREV, type, icachesz, dcachesz; 231 232 type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S; 233 if (type > mn10300_known_cpus) 234 type = mn10300_known_cpus; 235 236 icachesz = 237 ((cpurev & CPUREV_ICWAY ) >> CPUREV_ICWAY_S) * 238 ((cpurev & CPUREV_ICSIZE) >> CPUREV_ICSIZE_S) * 239 1024; 240 241 dcachesz = 242 ((cpurev & CPUREV_DCWAY ) >> CPUREV_DCWAY_S) * 243 ((cpurev & CPUREV_DCSIZE) >> CPUREV_DCSIZE_S) * 244 1024; 245 246 seq_printf(m, 247 "processor : 0\n" 248 "vendor_id : Matsushita\n" 249 "cpu core : %s\n" 250 "cpu rev : %lu\n" 251 "model name : " PROCESSOR_MODEL_NAME "\n" 252 "icache size: %lu\n" 253 "dcache size: %lu\n", 254 mn10300_cputypes[type], 255 (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S, 256 icachesz, 257 dcachesz 258 ); 259 260 seq_printf(m, 261 "ioclk speed: %lu.%02luMHz\n" 262 "bogomips : %lu.%02lu\n\n", 263 MN10300_IOCLK / 1000000, 264 (MN10300_IOCLK / 10000) % 100, 265 loops_per_jiffy / (500000 / HZ), 266 (loops_per_jiffy / (5000 / HZ)) % 100 267 ); 268 269 return 0; 270} 271 272static void *c_start(struct seq_file *m, loff_t *pos) 273{ 274 return *pos < NR_CPUS ? cpu_data + *pos : NULL; 275} 276 277static void *c_next(struct seq_file *m, void *v, loff_t *pos) 278{ 279 ++*pos; 280 return c_start(m, pos); 281} 282 283static void c_stop(struct seq_file *m, void *v) 284{ 285} 286 287const struct seq_operations cpuinfo_op = { 288 .start = c_start, 289 .next = c_next, 290 .stop = c_stop, 291 .show = show_cpuinfo, 292}; 293