1/* 2 * Port on Texas Instruments TMS320C6x architecture 3 * 4 * Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated 5 * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11#include <linux/dma-mapping.h> 12#include <linux/memblock.h> 13#include <linux/seq_file.h> 14#include <linux/bootmem.h> 15#include <linux/clkdev.h> 16#include <linux/initrd.h> 17#include <linux/kernel.h> 18#include <linux/module.h> 19#include <linux/of_fdt.h> 20#include <linux/string.h> 21#include <linux/errno.h> 22#include <linux/cache.h> 23#include <linux/delay.h> 24#include <linux/sched.h> 25#include <linux/clk.h> 26#include <linux/cpu.h> 27#include <linux/fs.h> 28#include <linux/of.h> 29#include <linux/console.h> 30#include <linux/screen_info.h> 31 32#include <asm/sections.h> 33#include <asm/div64.h> 34#include <asm/setup.h> 35#include <asm/dscr.h> 36#include <asm/clock.h> 37#include <asm/soc.h> 38#include <asm/special_insns.h> 39 40static const char *c6x_soc_name; 41 42struct screen_info screen_info; 43 44int c6x_num_cores; 45EXPORT_SYMBOL_GPL(c6x_num_cores); 46 47unsigned int c6x_silicon_rev; 48EXPORT_SYMBOL_GPL(c6x_silicon_rev); 49 50/* 51 * Device status register. This holds information 52 * about device configuration needed by some drivers. 53 */ 54unsigned int c6x_devstat; 55EXPORT_SYMBOL_GPL(c6x_devstat); 56 57/* 58 * Some SoCs have fuse registers holding a unique MAC 59 * address. This is parsed out of the device tree with 60 * the resulting MAC being held here. 61 */ 62unsigned char c6x_fuse_mac[6]; 63 64unsigned long memory_start; 65unsigned long memory_end; 66EXPORT_SYMBOL(memory_end); 67 68unsigned long ram_start; 69unsigned long ram_end; 70 71/* Uncached memory for DMA consistent use (memdma=) */ 72static unsigned long dma_start __initdata; 73static unsigned long dma_size __initdata; 74 75struct cpuinfo_c6x { 76 const char *cpu_name; 77 const char *cpu_voltage; 78 const char *mmu; 79 const char *fpu; 80 char *cpu_rev; 81 unsigned int core_id; 82 char __cpu_rev[5]; 83}; 84 85static DEFINE_PER_CPU(struct cpuinfo_c6x, cpu_data); 86 87unsigned int ticks_per_ns_scaled; 88EXPORT_SYMBOL(ticks_per_ns_scaled); 89 90unsigned int c6x_core_freq; 91 92static void __init get_cpuinfo(void) 93{ 94 unsigned cpu_id, rev_id, csr; 95 struct clk *coreclk = clk_get_sys(NULL, "core"); 96 unsigned long core_khz; 97 u64 tmp; 98 struct cpuinfo_c6x *p; 99 struct device_node *node, *np; 100 101 p = &per_cpu(cpu_data, smp_processor_id()); 102 103 if (!IS_ERR(coreclk)) 104 c6x_core_freq = clk_get_rate(coreclk); 105 else { 106 printk(KERN_WARNING 107 "Cannot find core clock frequency. Using 700MHz\n"); 108 c6x_core_freq = 700000000; 109 } 110 111 core_khz = c6x_core_freq / 1000; 112 113 tmp = (uint64_t)core_khz << C6X_NDELAY_SCALE; 114 do_div(tmp, 1000000); 115 ticks_per_ns_scaled = tmp; 116 117 csr = get_creg(CSR); 118 cpu_id = csr >> 24; 119 rev_id = (csr >> 16) & 0xff; 120 121 p->mmu = "none"; 122 p->fpu = "none"; 123 p->cpu_voltage = "unknown"; 124 125 switch (cpu_id) { 126 case 0: 127 p->cpu_name = "C67x"; 128 p->fpu = "yes"; 129 break; 130 case 2: 131 p->cpu_name = "C62x"; 132 break; 133 case 8: 134 p->cpu_name = "C64x"; 135 break; 136 case 12: 137 p->cpu_name = "C64x"; 138 break; 139 case 16: 140 p->cpu_name = "C64x+"; 141 p->cpu_voltage = "1.2"; 142 break; 143 case 21: 144 p->cpu_name = "C66X"; 145 p->cpu_voltage = "1.2"; 146 break; 147 default: 148 p->cpu_name = "unknown"; 149 break; 150 } 151 152 if (cpu_id < 16) { 153 switch (rev_id) { 154 case 0x1: 155 if (cpu_id > 8) { 156 p->cpu_rev = "DM640/DM641/DM642/DM643"; 157 p->cpu_voltage = "1.2 - 1.4"; 158 } else { 159 p->cpu_rev = "C6201"; 160 p->cpu_voltage = "2.5"; 161 } 162 break; 163 case 0x2: 164 p->cpu_rev = "C6201B/C6202/C6211"; 165 p->cpu_voltage = "1.8"; 166 break; 167 case 0x3: 168 p->cpu_rev = "C6202B/C6203/C6204/C6205"; 169 p->cpu_voltage = "1.5"; 170 break; 171 case 0x201: 172 p->cpu_rev = "C6701 revision 0 (early CPU)"; 173 p->cpu_voltage = "1.8"; 174 break; 175 case 0x202: 176 p->cpu_rev = "C6701/C6711/C6712"; 177 p->cpu_voltage = "1.8"; 178 break; 179 case 0x801: 180 p->cpu_rev = "C64x"; 181 p->cpu_voltage = "1.5"; 182 break; 183 default: 184 p->cpu_rev = "unknown"; 185 } 186 } else { 187 p->cpu_rev = p->__cpu_rev; 188 snprintf(p->__cpu_rev, sizeof(p->__cpu_rev), "0x%x", cpu_id); 189 } 190 191 p->core_id = get_coreid(); 192 193 node = of_find_node_by_name(NULL, "cpus"); 194 if (node) { 195 for_each_child_of_node(node, np) 196 if (!strcmp("cpu", np->name)) 197 ++c6x_num_cores; 198 of_node_put(node); 199 } 200 201 node = of_find_node_by_name(NULL, "soc"); 202 if (node) { 203 if (of_property_read_string(node, "model", &c6x_soc_name)) 204 c6x_soc_name = "unknown"; 205 of_node_put(node); 206 } else 207 c6x_soc_name = "unknown"; 208 209 printk(KERN_INFO "CPU%d: %s rev %s, %s volts, %uMHz\n", 210 p->core_id, p->cpu_name, p->cpu_rev, 211 p->cpu_voltage, c6x_core_freq / 1000000); 212} 213 214/* 215 * Early parsing of the command line 216 */ 217static u32 mem_size __initdata; 218 219/* "mem=" parsing. */ 220static int __init early_mem(char *p) 221{ 222 if (!p) 223 return -EINVAL; 224 225 mem_size = memparse(p, &p); 226 /* don't remove all of memory when handling "mem={invalid}" */ 227 if (mem_size == 0) 228 return -EINVAL; 229 230 return 0; 231} 232early_param("mem", early_mem); 233 234/* "memdma=<size>[@<address>]" parsing. */ 235static int __init early_memdma(char *p) 236{ 237 if (!p) 238 return -EINVAL; 239 240 dma_size = memparse(p, &p); 241 if (*p == '@') 242 dma_start = memparse(p, &p); 243 244 return 0; 245} 246early_param("memdma", early_memdma); 247 248int __init c6x_add_memory(phys_addr_t start, unsigned long size) 249{ 250 static int ram_found __initdata; 251 252 /* We only handle one bank (the one with PAGE_OFFSET) for now */ 253 if (ram_found) 254 return -EINVAL; 255 256 if (start > PAGE_OFFSET || PAGE_OFFSET >= (start + size)) 257 return 0; 258 259 ram_start = start; 260 ram_end = start + size; 261 262 ram_found = 1; 263 return 0; 264} 265 266/* 267 * Do early machine setup and device tree parsing. This is called very 268 * early on the boot process. 269 */ 270notrace void __init machine_init(unsigned long dt_ptr) 271{ 272 void *dtb = __va(dt_ptr); 273 void *fdt = _fdt_start; 274 275 /* interrupts must be masked */ 276 set_creg(IER, 2); 277 278 /* 279 * Set the Interrupt Service Table (IST) to the beginning of the 280 * vector table. 281 */ 282 set_ist(_vectors_start); 283 284 lockdep_init(); 285 286 /* 287 * dtb is passed in from bootloader. 288 * fdt is linked in blob. 289 */ 290 if (dtb && dtb != fdt) 291 fdt = dtb; 292 293 /* Do some early initialization based on the flat device tree */ 294 early_init_dt_scan(fdt); 295 296 parse_early_param(); 297} 298 299void __init setup_arch(char **cmdline_p) 300{ 301 int bootmap_size; 302 struct memblock_region *reg; 303 304 printk(KERN_INFO "Initializing kernel\n"); 305 306 /* Initialize command line */ 307 *cmdline_p = boot_command_line; 308 309 memory_end = ram_end; 310 memory_end &= ~(PAGE_SIZE - 1); 311 312 if (mem_size && (PAGE_OFFSET + PAGE_ALIGN(mem_size)) < memory_end) 313 memory_end = PAGE_OFFSET + PAGE_ALIGN(mem_size); 314 315 /* add block that this kernel can use */ 316 memblock_add(PAGE_OFFSET, memory_end - PAGE_OFFSET); 317 318 /* reserve kernel text/data/bss */ 319 memblock_reserve(PAGE_OFFSET, 320 PAGE_ALIGN((unsigned long)&_end - PAGE_OFFSET)); 321 322 if (dma_size) { 323 /* align to cacheability granularity */ 324 dma_size = CACHE_REGION_END(dma_size); 325 326 if (!dma_start) 327 dma_start = memory_end - dma_size; 328 329 /* align to cacheability granularity */ 330 dma_start = CACHE_REGION_START(dma_start); 331 332 /* reserve DMA memory taken from kernel memory */ 333 if (memblock_is_region_memory(dma_start, dma_size)) 334 memblock_reserve(dma_start, dma_size); 335 } 336 337 memory_start = PAGE_ALIGN((unsigned int) &_end); 338 339 printk(KERN_INFO "Memory Start=%08lx, Memory End=%08lx\n", 340 memory_start, memory_end); 341 342#ifdef CONFIG_BLK_DEV_INITRD 343 /* 344 * Reserve initrd memory if in kernel memory. 345 */ 346 if (initrd_start < initrd_end) 347 if (memblock_is_region_memory(initrd_start, 348 initrd_end - initrd_start)) 349 memblock_reserve(initrd_start, 350 initrd_end - initrd_start); 351#endif 352 353 init_mm.start_code = (unsigned long) &_stext; 354 init_mm.end_code = (unsigned long) &_etext; 355 init_mm.end_data = memory_start; 356 init_mm.brk = memory_start; 357 358 /* 359 * Give all the memory to the bootmap allocator, tell it to put the 360 * boot mem_map at the start of memory 361 */ 362 bootmap_size = init_bootmem_node(NODE_DATA(0), 363 memory_start >> PAGE_SHIFT, 364 PAGE_OFFSET >> PAGE_SHIFT, 365 memory_end >> PAGE_SHIFT); 366 memblock_reserve(memory_start, bootmap_size); 367 368 unflatten_device_tree(); 369 370 c6x_cache_init(); 371 372 /* Set the whole external memory as non-cacheable */ 373 disable_caching(ram_start, ram_end - 1); 374 375 /* Set caching of external RAM used by Linux */ 376 for_each_memblock(memory, reg) 377 enable_caching(CACHE_REGION_START(reg->base), 378 CACHE_REGION_START(reg->base + reg->size - 1)); 379 380#ifdef CONFIG_BLK_DEV_INITRD 381 /* 382 * Enable caching for initrd which falls outside kernel memory. 383 */ 384 if (initrd_start < initrd_end) { 385 if (!memblock_is_region_memory(initrd_start, 386 initrd_end - initrd_start)) 387 enable_caching(CACHE_REGION_START(initrd_start), 388 CACHE_REGION_START(initrd_end - 1)); 389 } 390#endif 391 392 /* 393 * Disable caching for dma coherent memory taken from kernel memory. 394 */ 395 if (dma_size && memblock_is_region_memory(dma_start, dma_size)) 396 disable_caching(dma_start, 397 CACHE_REGION_START(dma_start + dma_size - 1)); 398 399 /* Initialize the coherent memory allocator */ 400 coherent_mem_init(dma_start, dma_size); 401 402 /* 403 * Free all memory as a starting point. 404 */ 405 free_bootmem(PAGE_OFFSET, memory_end - PAGE_OFFSET); 406 407 /* 408 * Then reserve memory which is already being used. 409 */ 410 for_each_memblock(reserved, reg) { 411 pr_debug("reserved - 0x%08x-0x%08x\n", 412 (u32) reg->base, (u32) reg->size); 413 reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT); 414 } 415 416 max_low_pfn = PFN_DOWN(memory_end); 417 min_low_pfn = PFN_UP(memory_start); 418 max_mapnr = max_low_pfn - min_low_pfn; 419 420 /* Get kmalloc into gear */ 421 paging_init(); 422 423 /* 424 * Probe for Device State Configuration Registers. 425 * We have to do this early in case timer needs to be enabled 426 * through DSCR. 427 */ 428 dscr_probe(); 429 430 /* We do this early for timer and core clock frequency */ 431 c64x_setup_clocks(); 432 433 /* Get CPU info */ 434 get_cpuinfo(); 435 436#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE) 437 conswitchp = &dummy_con; 438#endif 439} 440 441#define cpu_to_ptr(n) ((void *)((long)(n)+1)) 442#define ptr_to_cpu(p) ((long)(p) - 1) 443 444static int show_cpuinfo(struct seq_file *m, void *v) 445{ 446 int n = ptr_to_cpu(v); 447 struct cpuinfo_c6x *p = &per_cpu(cpu_data, n); 448 449 if (n == 0) { 450 seq_printf(m, 451 "soc\t\t: %s\n" 452 "soc revision\t: 0x%x\n" 453 "soc cores\t: %d\n", 454 c6x_soc_name, c6x_silicon_rev, c6x_num_cores); 455 } 456 457 seq_printf(m, 458 "\n" 459 "processor\t: %d\n" 460 "cpu\t\t: %s\n" 461 "core revision\t: %s\n" 462 "core voltage\t: %s\n" 463 "core id\t\t: %d\n" 464 "mmu\t\t: %s\n" 465 "fpu\t\t: %s\n" 466 "cpu MHz\t\t: %u\n" 467 "bogomips\t: %lu.%02lu\n\n", 468 n, 469 p->cpu_name, p->cpu_rev, p->cpu_voltage, 470 p->core_id, p->mmu, p->fpu, 471 (c6x_core_freq + 500000) / 1000000, 472 (loops_per_jiffy/(500000/HZ)), 473 (loops_per_jiffy/(5000/HZ))%100); 474 475 return 0; 476} 477 478static void *c_start(struct seq_file *m, loff_t *pos) 479{ 480 return *pos < nr_cpu_ids ? cpu_to_ptr(*pos) : NULL; 481} 482static void *c_next(struct seq_file *m, void *v, loff_t *pos) 483{ 484 ++*pos; 485 return NULL; 486} 487static void c_stop(struct seq_file *m, void *v) 488{ 489} 490 491const struct seq_operations cpuinfo_op = { 492 c_start, 493 c_stop, 494 c_next, 495 show_cpuinfo 496}; 497 498static struct cpu cpu_devices[NR_CPUS]; 499 500static int __init topology_init(void) 501{ 502 int i; 503 504 for_each_present_cpu(i) 505 register_cpu(&cpu_devices[i], i); 506 507 return 0; 508} 509 510subsys_initcall(topology_init); 511