1/* 2 * linux/arch/unicore32/kernel/setup.c 3 * 4 * Code specific to PKUnity SoC and UniCore ISA 5 * 6 * Copyright (C) 2001-2010 GUAN Xue-tao 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12#include <linux/module.h> 13#include <linux/kernel.h> 14#include <linux/stddef.h> 15#include <linux/ioport.h> 16#include <linux/delay.h> 17#include <linux/utsname.h> 18#include <linux/initrd.h> 19#include <linux/console.h> 20#include <linux/bootmem.h> 21#include <linux/seq_file.h> 22#include <linux/screen_info.h> 23#include <linux/init.h> 24#include <linux/root_dev.h> 25#include <linux/cpu.h> 26#include <linux/interrupt.h> 27#include <linux/smp.h> 28#include <linux/fs.h> 29#include <linux/proc_fs.h> 30#include <linux/memblock.h> 31#include <linux/elf.h> 32#include <linux/io.h> 33 34#include <asm/cputype.h> 35#include <asm/sections.h> 36#include <asm/setup.h> 37#include <asm/cacheflush.h> 38#include <asm/tlbflush.h> 39#include <asm/traps.h> 40#include <asm/memblock.h> 41 42#include "setup.h" 43 44#ifndef MEM_SIZE 45#define MEM_SIZE (16*1024*1024) 46#endif 47 48struct stack { 49 u32 irq[3]; 50 u32 abt[3]; 51 u32 und[3]; 52} ____cacheline_aligned; 53 54static struct stack stacks[NR_CPUS]; 55 56#ifdef CONFIG_VGA_CONSOLE 57struct screen_info screen_info; 58#endif 59 60char elf_platform[ELF_PLATFORM_SIZE]; 61EXPORT_SYMBOL(elf_platform); 62 63static char __initdata cmd_line[COMMAND_LINE_SIZE]; 64 65static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; 66 67/* 68 * Standard memory resources 69 */ 70static struct resource mem_res[] = { 71 { 72 .name = "Kernel code", 73 .start = 0, 74 .end = 0, 75 .flags = IORESOURCE_MEM 76 }, 77 { 78 .name = "Kernel data", 79 .start = 0, 80 .end = 0, 81 .flags = IORESOURCE_MEM 82 } 83}; 84 85#define kernel_code mem_res[0] 86#define kernel_data mem_res[1] 87 88/* 89 * These functions re-use the assembly code in head.S, which 90 * already provide the required functionality. 91 */ 92static void __init setup_processor(void) 93{ 94 printk(KERN_DEFAULT "CPU: UniCore-II [%08x] revision %d, cr=%08lx\n", 95 uc32_cpuid, (int)(uc32_cpuid >> 16) & 15, cr_alignment); 96 97 sprintf(init_utsname()->machine, "puv3"); 98 sprintf(elf_platform, "ucv2"); 99} 100 101/* 102 * cpu_init - initialise one CPU. 103 * 104 * cpu_init sets up the per-CPU stacks. 105 */ 106void cpu_init(void) 107{ 108 unsigned int cpu = smp_processor_id(); 109 struct stack *stk = &stacks[cpu]; 110 111 /* 112 * setup stacks for re-entrant exception handlers 113 */ 114 __asm__ ( 115 "mov.a asr, %1\n\t" 116 "add sp, %0, %2\n\t" 117 "mov.a asr, %3\n\t" 118 "add sp, %0, %4\n\t" 119 "mov.a asr, %5\n\t" 120 "add sp, %0, %6\n\t" 121 "mov.a asr, %7" 122 : 123 : "r" (stk), 124 "r" (PSR_R_BIT | PSR_I_BIT | INTR_MODE), 125 "I" (offsetof(struct stack, irq[0])), 126 "r" (PSR_R_BIT | PSR_I_BIT | ABRT_MODE), 127 "I" (offsetof(struct stack, abt[0])), 128 "r" (PSR_R_BIT | PSR_I_BIT | EXTN_MODE), 129 "I" (offsetof(struct stack, und[0])), 130 "r" (PSR_R_BIT | PSR_I_BIT | PRIV_MODE) 131 : "r30", "cc"); 132} 133 134static int __init uc32_add_memory(unsigned long start, unsigned long size) 135{ 136 struct membank *bank = &meminfo.bank[meminfo.nr_banks]; 137 138 if (meminfo.nr_banks >= NR_BANKS) { 139 printk(KERN_CRIT "NR_BANKS too low, " 140 "ignoring memory at %#lx\n", start); 141 return -EINVAL; 142 } 143 144 /* 145 * Ensure that start/size are aligned to a page boundary. 146 * Size is appropriately rounded down, start is rounded up. 147 */ 148 size -= start & ~PAGE_MASK; 149 150 bank->start = PAGE_ALIGN(start); 151 bank->size = size & PAGE_MASK; 152 153 /* 154 * Check whether this memory region has non-zero size or 155 * invalid node number. 156 */ 157 if (bank->size == 0) 158 return -EINVAL; 159 160 meminfo.nr_banks++; 161 return 0; 162} 163 164/* 165 * Pick out the memory size. We look for mem=size@start, 166 * where start and size are "size[KkMm]" 167 */ 168static int __init early_mem(char *p) 169{ 170 static int usermem __initdata = 1; 171 unsigned long size, start; 172 char *endp; 173 174 /* 175 * If the user specifies memory size, we 176 * blow away any automatically generated 177 * size. 178 */ 179 if (usermem) { 180 usermem = 0; 181 meminfo.nr_banks = 0; 182 } 183 184 start = PHYS_OFFSET; 185 size = memparse(p, &endp); 186 if (*endp == '@') 187 start = memparse(endp + 1, NULL); 188 189 uc32_add_memory(start, size); 190 191 return 0; 192} 193early_param("mem", early_mem); 194 195static void __init 196request_standard_resources(struct meminfo *mi) 197{ 198 struct resource *res; 199 int i; 200 201 kernel_code.start = virt_to_phys(_stext); 202 kernel_code.end = virt_to_phys(_etext - 1); 203 kernel_data.start = virt_to_phys(_sdata); 204 kernel_data.end = virt_to_phys(_end - 1); 205 206 for (i = 0; i < mi->nr_banks; i++) { 207 if (mi->bank[i].size == 0) 208 continue; 209 210 res = alloc_bootmem_low(sizeof(*res)); 211 res->name = "System RAM"; 212 res->start = mi->bank[i].start; 213 res->end = mi->bank[i].start + mi->bank[i].size - 1; 214 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; 215 216 request_resource(&iomem_resource, res); 217 218 if (kernel_code.start >= res->start && 219 kernel_code.end <= res->end) 220 request_resource(res, &kernel_code); 221 if (kernel_data.start >= res->start && 222 kernel_data.end <= res->end) 223 request_resource(res, &kernel_data); 224 } 225} 226 227static void (*init_machine)(void) __initdata; 228 229static int __init customize_machine(void) 230{ 231 /* customizes platform devices, or adds new ones */ 232 if (init_machine) 233 init_machine(); 234 return 0; 235} 236arch_initcall(customize_machine); 237 238void __init setup_arch(char **cmdline_p) 239{ 240 char *from = default_command_line; 241 242 setup_processor(); 243 244 init_mm.start_code = (unsigned long) _stext; 245 init_mm.end_code = (unsigned long) _etext; 246 init_mm.end_data = (unsigned long) _edata; 247 init_mm.brk = (unsigned long) _end; 248 249 /* parse_early_param needs a boot_command_line */ 250 strlcpy(boot_command_line, from, COMMAND_LINE_SIZE); 251 252 /* populate cmd_line too for later use, preserving boot_command_line */ 253 strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); 254 *cmdline_p = cmd_line; 255 256 parse_early_param(); 257 258 uc32_memblock_init(&meminfo); 259 260 paging_init(); 261 request_standard_resources(&meminfo); 262 263 cpu_init(); 264 265 /* 266 * Set up various architecture-specific pointers 267 */ 268 init_machine = puv3_core_init; 269 270#ifdef CONFIG_VT 271#if defined(CONFIG_VGA_CONSOLE) 272 conswitchp = &vga_con; 273#elif defined(CONFIG_DUMMY_CONSOLE) 274 conswitchp = &dummy_con; 275#endif 276#endif 277 early_trap_init(); 278} 279 280static struct cpu cpuinfo_unicore; 281 282static int __init topology_init(void) 283{ 284 int i; 285 286 for_each_possible_cpu(i) 287 register_cpu(&cpuinfo_unicore, i); 288 289 return 0; 290} 291subsys_initcall(topology_init); 292 293#ifdef CONFIG_HAVE_PROC_CPU 294static int __init proc_cpu_init(void) 295{ 296 struct proc_dir_entry *res; 297 298 res = proc_mkdir("cpu", NULL); 299 if (!res) 300 return -ENOMEM; 301 return 0; 302} 303fs_initcall(proc_cpu_init); 304#endif 305 306static int c_show(struct seq_file *m, void *v) 307{ 308 seq_printf(m, "Processor\t: UniCore-II rev %d (%s)\n", 309 (int)(uc32_cpuid >> 16) & 15, elf_platform); 310 311 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", 312 loops_per_jiffy / (500000/HZ), 313 (loops_per_jiffy / (5000/HZ)) % 100); 314 315 /* dump out the processor features */ 316 seq_puts(m, "Features\t: CMOV UC-F64"); 317 318 seq_printf(m, "\nCPU implementer\t: 0x%02x\n", uc32_cpuid >> 24); 319 seq_printf(m, "CPU architecture: 2\n"); 320 seq_printf(m, "CPU revision\t: %d\n", (uc32_cpuid >> 16) & 15); 321 322 seq_printf(m, "Cache type\t: write-back\n" 323 "Cache clean\t: cp0 c5 ops\n" 324 "Cache lockdown\t: not support\n" 325 "Cache format\t: Harvard\n"); 326 327 seq_puts(m, "\n"); 328 329 seq_printf(m, "Hardware\t: PKUnity v3\n"); 330 331 return 0; 332} 333 334static void *c_start(struct seq_file *m, loff_t *pos) 335{ 336 return *pos < 1 ? (void *)1 : NULL; 337} 338 339static void *c_next(struct seq_file *m, void *v, loff_t *pos) 340{ 341 ++*pos; 342 return NULL; 343} 344 345static void c_stop(struct seq_file *m, void *v) 346{ 347} 348 349const struct seq_operations cpuinfo_op = { 350 .start = c_start, 351 .next = c_next, 352 .stop = c_stop, 353 .show = c_show 354}; 355