18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * OpenRISC setup.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Linux architectural port borrowing liberally from similar works of 68c2ecf20Sopenharmony_ci * others. All original copyrights apply as per the original source 78c2ecf20Sopenharmony_ci * declaration. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Modifications for the OpenRISC architecture: 108c2ecf20Sopenharmony_ci * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 118c2ecf20Sopenharmony_ci * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * This file handles the architecture-dependent parts of initialization 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/errno.h> 178c2ecf20Sopenharmony_ci#include <linux/sched.h> 188c2ecf20Sopenharmony_ci#include <linux/kernel.h> 198c2ecf20Sopenharmony_ci#include <linux/mm.h> 208c2ecf20Sopenharmony_ci#include <linux/stddef.h> 218c2ecf20Sopenharmony_ci#include <linux/unistd.h> 228c2ecf20Sopenharmony_ci#include <linux/ptrace.h> 238c2ecf20Sopenharmony_ci#include <linux/slab.h> 248c2ecf20Sopenharmony_ci#include <linux/tty.h> 258c2ecf20Sopenharmony_ci#include <linux/ioport.h> 268c2ecf20Sopenharmony_ci#include <linux/delay.h> 278c2ecf20Sopenharmony_ci#include <linux/console.h> 288c2ecf20Sopenharmony_ci#include <linux/init.h> 298c2ecf20Sopenharmony_ci#include <linux/memblock.h> 308c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 318c2ecf20Sopenharmony_ci#include <linux/serial.h> 328c2ecf20Sopenharmony_ci#include <linux/initrd.h> 338c2ecf20Sopenharmony_ci#include <linux/of_fdt.h> 348c2ecf20Sopenharmony_ci#include <linux/of.h> 358c2ecf20Sopenharmony_ci#include <linux/device.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include <asm/sections.h> 388c2ecf20Sopenharmony_ci#include <asm/types.h> 398c2ecf20Sopenharmony_ci#include <asm/setup.h> 408c2ecf20Sopenharmony_ci#include <asm/io.h> 418c2ecf20Sopenharmony_ci#include <asm/cpuinfo.h> 428c2ecf20Sopenharmony_ci#include <asm/delay.h> 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#include "vmlinux.h" 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic void __init setup_memory(void) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci unsigned long ram_start_pfn; 498c2ecf20Sopenharmony_ci unsigned long ram_end_pfn; 508c2ecf20Sopenharmony_ci phys_addr_t memory_start, memory_end; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci memory_end = memory_start = 0; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* Find main memory where is the kernel, we assume its the only one */ 558c2ecf20Sopenharmony_ci memory_start = memblock_start_of_DRAM(); 568c2ecf20Sopenharmony_ci memory_end = memblock_end_of_DRAM(); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci if (!memory_end) { 598c2ecf20Sopenharmony_ci panic("No memory!"); 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci ram_start_pfn = PFN_UP(memory_start); 638c2ecf20Sopenharmony_ci ram_end_pfn = PFN_DOWN(memblock_end_of_DRAM()); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci /* setup bootmem globals (we use no_bootmem, but mm still depends on this) */ 668c2ecf20Sopenharmony_ci min_low_pfn = ram_start_pfn; 678c2ecf20Sopenharmony_ci max_low_pfn = ram_end_pfn; 688c2ecf20Sopenharmony_ci max_pfn = ram_end_pfn; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci /* 718c2ecf20Sopenharmony_ci * initialize the boot-time allocator (with low memory only). 728c2ecf20Sopenharmony_ci * 738c2ecf20Sopenharmony_ci * This makes the memory from the end of the kernel to the end of 748c2ecf20Sopenharmony_ci * RAM usable. 758c2ecf20Sopenharmony_ci */ 768c2ecf20Sopenharmony_ci memblock_reserve(__pa(_stext), _end - _stext); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_INITRD 798c2ecf20Sopenharmony_ci /* Then reserve the initrd, if any */ 808c2ecf20Sopenharmony_ci if (initrd_start && (initrd_end > initrd_start)) { 818c2ecf20Sopenharmony_ci unsigned long aligned_start = ALIGN_DOWN(initrd_start, PAGE_SIZE); 828c2ecf20Sopenharmony_ci unsigned long aligned_end = ALIGN(initrd_end, PAGE_SIZE); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci memblock_reserve(__pa(aligned_start), aligned_end - aligned_start); 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci#endif /* CONFIG_BLK_DEV_INITRD */ 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci early_init_fdt_reserve_self(); 898c2ecf20Sopenharmony_ci early_init_fdt_scan_reserved_mem(); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci memblock_dump_all(); 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cistruct cpuinfo_or1k cpuinfo_or1k[NR_CPUS]; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic void print_cpuinfo(void) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci unsigned long upr = mfspr(SPR_UPR); 998c2ecf20Sopenharmony_ci unsigned long vr = mfspr(SPR_VR); 1008c2ecf20Sopenharmony_ci unsigned int version; 1018c2ecf20Sopenharmony_ci unsigned int revision; 1028c2ecf20Sopenharmony_ci struct cpuinfo_or1k *cpuinfo = &cpuinfo_or1k[smp_processor_id()]; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci version = (vr & SPR_VR_VER) >> 24; 1058c2ecf20Sopenharmony_ci revision = (vr & SPR_VR_REV); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci printk(KERN_INFO "CPU: OpenRISC-%x (revision %d) @%d MHz\n", 1088c2ecf20Sopenharmony_ci version, revision, cpuinfo->clock_frequency / 1000000); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (!(upr & SPR_UPR_UP)) { 1118c2ecf20Sopenharmony_ci printk(KERN_INFO 1128c2ecf20Sopenharmony_ci "-- no UPR register... unable to detect configuration\n"); 1138c2ecf20Sopenharmony_ci return; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci if (upr & SPR_UPR_DCP) 1178c2ecf20Sopenharmony_ci printk(KERN_INFO 1188c2ecf20Sopenharmony_ci "-- dcache: %4d bytes total, %2d bytes/line, %d way(s)\n", 1198c2ecf20Sopenharmony_ci cpuinfo->dcache_size, cpuinfo->dcache_block_size, 1208c2ecf20Sopenharmony_ci cpuinfo->dcache_ways); 1218c2ecf20Sopenharmony_ci else 1228c2ecf20Sopenharmony_ci printk(KERN_INFO "-- dcache disabled\n"); 1238c2ecf20Sopenharmony_ci if (upr & SPR_UPR_ICP) 1248c2ecf20Sopenharmony_ci printk(KERN_INFO 1258c2ecf20Sopenharmony_ci "-- icache: %4d bytes total, %2d bytes/line, %d way(s)\n", 1268c2ecf20Sopenharmony_ci cpuinfo->icache_size, cpuinfo->icache_block_size, 1278c2ecf20Sopenharmony_ci cpuinfo->icache_ways); 1288c2ecf20Sopenharmony_ci else 1298c2ecf20Sopenharmony_ci printk(KERN_INFO "-- icache disabled\n"); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (upr & SPR_UPR_DMP) 1328c2ecf20Sopenharmony_ci printk(KERN_INFO "-- dmmu: %4d entries, %lu way(s)\n", 1338c2ecf20Sopenharmony_ci 1 << ((mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTS) >> 2), 1348c2ecf20Sopenharmony_ci 1 + (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTW)); 1358c2ecf20Sopenharmony_ci if (upr & SPR_UPR_IMP) 1368c2ecf20Sopenharmony_ci printk(KERN_INFO "-- immu: %4d entries, %lu way(s)\n", 1378c2ecf20Sopenharmony_ci 1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> 2), 1388c2ecf20Sopenharmony_ci 1 + (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTW)); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci printk(KERN_INFO "-- additional features:\n"); 1418c2ecf20Sopenharmony_ci if (upr & SPR_UPR_DUP) 1428c2ecf20Sopenharmony_ci printk(KERN_INFO "-- debug unit\n"); 1438c2ecf20Sopenharmony_ci if (upr & SPR_UPR_PCUP) 1448c2ecf20Sopenharmony_ci printk(KERN_INFO "-- performance counters\n"); 1458c2ecf20Sopenharmony_ci if (upr & SPR_UPR_PMP) 1468c2ecf20Sopenharmony_ci printk(KERN_INFO "-- power management\n"); 1478c2ecf20Sopenharmony_ci if (upr & SPR_UPR_PICP) 1488c2ecf20Sopenharmony_ci printk(KERN_INFO "-- PIC\n"); 1498c2ecf20Sopenharmony_ci if (upr & SPR_UPR_TTP) 1508c2ecf20Sopenharmony_ci printk(KERN_INFO "-- timer\n"); 1518c2ecf20Sopenharmony_ci if (upr & SPR_UPR_CUP) 1528c2ecf20Sopenharmony_ci printk(KERN_INFO "-- custom unit(s)\n"); 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic struct device_node *setup_find_cpu_node(int cpu) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci u32 hwid; 1588c2ecf20Sopenharmony_ci struct device_node *cpun; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci for_each_of_cpu_node(cpun) { 1618c2ecf20Sopenharmony_ci if (of_property_read_u32(cpun, "reg", &hwid)) 1628c2ecf20Sopenharmony_ci continue; 1638c2ecf20Sopenharmony_ci if (hwid == cpu) 1648c2ecf20Sopenharmony_ci return cpun; 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci return NULL; 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_civoid __init setup_cpuinfo(void) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci struct device_node *cpu; 1738c2ecf20Sopenharmony_ci unsigned long iccfgr, dccfgr; 1748c2ecf20Sopenharmony_ci unsigned long cache_set_size; 1758c2ecf20Sopenharmony_ci int cpu_id = smp_processor_id(); 1768c2ecf20Sopenharmony_ci struct cpuinfo_or1k *cpuinfo = &cpuinfo_or1k[cpu_id]; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci cpu = setup_find_cpu_node(cpu_id); 1798c2ecf20Sopenharmony_ci if (!cpu) 1808c2ecf20Sopenharmony_ci panic("Couldn't find CPU%d in device tree...\n", cpu_id); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci iccfgr = mfspr(SPR_ICCFGR); 1838c2ecf20Sopenharmony_ci cpuinfo->icache_ways = 1 << (iccfgr & SPR_ICCFGR_NCW); 1848c2ecf20Sopenharmony_ci cache_set_size = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3); 1858c2ecf20Sopenharmony_ci cpuinfo->icache_block_size = 16 << ((iccfgr & SPR_ICCFGR_CBS) >> 7); 1868c2ecf20Sopenharmony_ci cpuinfo->icache_size = 1878c2ecf20Sopenharmony_ci cache_set_size * cpuinfo->icache_ways * cpuinfo->icache_block_size; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci dccfgr = mfspr(SPR_DCCFGR); 1908c2ecf20Sopenharmony_ci cpuinfo->dcache_ways = 1 << (dccfgr & SPR_DCCFGR_NCW); 1918c2ecf20Sopenharmony_ci cache_set_size = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3); 1928c2ecf20Sopenharmony_ci cpuinfo->dcache_block_size = 16 << ((dccfgr & SPR_DCCFGR_CBS) >> 7); 1938c2ecf20Sopenharmony_ci cpuinfo->dcache_size = 1948c2ecf20Sopenharmony_ci cache_set_size * cpuinfo->dcache_ways * cpuinfo->dcache_block_size; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci if (of_property_read_u32(cpu, "clock-frequency", 1978c2ecf20Sopenharmony_ci &cpuinfo->clock_frequency)) { 1988c2ecf20Sopenharmony_ci printk(KERN_WARNING 1998c2ecf20Sopenharmony_ci "Device tree missing CPU 'clock-frequency' parameter." 2008c2ecf20Sopenharmony_ci "Assuming frequency 25MHZ" 2018c2ecf20Sopenharmony_ci "This is probably not what you want."); 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci cpuinfo->coreid = mfspr(SPR_COREID); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci of_node_put(cpu); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci print_cpuinfo(); 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci/** 2128c2ecf20Sopenharmony_ci * or32_early_setup 2138c2ecf20Sopenharmony_ci * 2148c2ecf20Sopenharmony_ci * Handles the pointer to the device tree that this kernel is to use 2158c2ecf20Sopenharmony_ci * for establishing the available platform devices. 2168c2ecf20Sopenharmony_ci * 2178c2ecf20Sopenharmony_ci * Falls back on built-in device tree in case null pointer is passed. 2188c2ecf20Sopenharmony_ci */ 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_civoid __init or32_early_setup(void *fdt) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci if (fdt) 2238c2ecf20Sopenharmony_ci pr_info("FDT at %p\n", fdt); 2248c2ecf20Sopenharmony_ci else { 2258c2ecf20Sopenharmony_ci fdt = __dtb_start; 2268c2ecf20Sopenharmony_ci pr_info("Compiled-in FDT at %p\n", fdt); 2278c2ecf20Sopenharmony_ci } 2288c2ecf20Sopenharmony_ci early_init_devtree(fdt); 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_cistatic inline unsigned long extract_value_bits(unsigned long reg, 2328c2ecf20Sopenharmony_ci short bit_nr, short width) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci return (reg >> bit_nr) & (0 << width); 2358c2ecf20Sopenharmony_ci} 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistatic inline unsigned long extract_value(unsigned long reg, unsigned long mask) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci while (!(mask & 0x1)) { 2408c2ecf20Sopenharmony_ci reg = reg >> 1; 2418c2ecf20Sopenharmony_ci mask = mask >> 1; 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci return mask & reg; 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_civoid __init detect_unit_config(unsigned long upr, unsigned long mask, 2478c2ecf20Sopenharmony_ci char *text, void (*func) (void)) 2488c2ecf20Sopenharmony_ci{ 2498c2ecf20Sopenharmony_ci if (text != NULL) 2508c2ecf20Sopenharmony_ci printk("%s", text); 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci if (upr & mask) { 2538c2ecf20Sopenharmony_ci if (func != NULL) 2548c2ecf20Sopenharmony_ci func(); 2558c2ecf20Sopenharmony_ci else 2568c2ecf20Sopenharmony_ci printk("present\n"); 2578c2ecf20Sopenharmony_ci } else 2588c2ecf20Sopenharmony_ci printk("not present\n"); 2598c2ecf20Sopenharmony_ci} 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci/* 2628c2ecf20Sopenharmony_ci * calibrate_delay 2638c2ecf20Sopenharmony_ci * 2648c2ecf20Sopenharmony_ci * Lightweight calibrate_delay implementation that calculates loops_per_jiffy 2658c2ecf20Sopenharmony_ci * from the clock frequency passed in via the device tree 2668c2ecf20Sopenharmony_ci * 2678c2ecf20Sopenharmony_ci */ 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_civoid calibrate_delay(void) 2708c2ecf20Sopenharmony_ci{ 2718c2ecf20Sopenharmony_ci const int *val; 2728c2ecf20Sopenharmony_ci struct device_node *cpu = setup_find_cpu_node(smp_processor_id()); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci val = of_get_property(cpu, "clock-frequency", NULL); 2758c2ecf20Sopenharmony_ci if (!val) 2768c2ecf20Sopenharmony_ci panic("no cpu 'clock-frequency' parameter in device tree"); 2778c2ecf20Sopenharmony_ci loops_per_jiffy = *val / HZ; 2788c2ecf20Sopenharmony_ci pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n", 2798c2ecf20Sopenharmony_ci loops_per_jiffy / (500000 / HZ), 2808c2ecf20Sopenharmony_ci (loops_per_jiffy / (5000 / HZ)) % 100, loops_per_jiffy); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci of_node_put(cpu); 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_civoid __init setup_arch(char **cmdline_p) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci unflatten_and_copy_device_tree(); 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci setup_cpuinfo(); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 2928c2ecf20Sopenharmony_ci smp_init_cpus(); 2938c2ecf20Sopenharmony_ci#endif 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci /* process 1's initial memory region is the kernel code/data */ 2968c2ecf20Sopenharmony_ci init_mm.start_code = (unsigned long)_stext; 2978c2ecf20Sopenharmony_ci init_mm.end_code = (unsigned long)_etext; 2988c2ecf20Sopenharmony_ci init_mm.end_data = (unsigned long)_edata; 2998c2ecf20Sopenharmony_ci init_mm.brk = (unsigned long)_end; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_INITRD 3028c2ecf20Sopenharmony_ci if (initrd_start == initrd_end) { 3038c2ecf20Sopenharmony_ci printk(KERN_INFO "Initial ramdisk not found\n"); 3048c2ecf20Sopenharmony_ci initrd_start = 0; 3058c2ecf20Sopenharmony_ci initrd_end = 0; 3068c2ecf20Sopenharmony_ci } else { 3078c2ecf20Sopenharmony_ci printk(KERN_INFO "Initial ramdisk at: 0x%p (%lu bytes)\n", 3088c2ecf20Sopenharmony_ci (void *)(initrd_start), initrd_end - initrd_start); 3098c2ecf20Sopenharmony_ci initrd_below_start_ok = 1; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci#endif 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci /* setup memblock allocator */ 3148c2ecf20Sopenharmony_ci setup_memory(); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci /* paging_init() sets up the MMU and marks all pages as reserved */ 3178c2ecf20Sopenharmony_ci paging_init(); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci *cmdline_p = boot_command_line; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci printk(KERN_INFO "OpenRISC Linux -- http://openrisc.io\n"); 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistatic int show_cpuinfo(struct seq_file *m, void *v) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci unsigned int vr, cpucfgr; 3278c2ecf20Sopenharmony_ci unsigned int avr; 3288c2ecf20Sopenharmony_ci unsigned int version; 3298c2ecf20Sopenharmony_ci struct cpuinfo_or1k *cpuinfo = v; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci vr = mfspr(SPR_VR); 3328c2ecf20Sopenharmony_ci cpucfgr = mfspr(SPR_CPUCFGR); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 3358c2ecf20Sopenharmony_ci seq_printf(m, "processor\t\t: %d\n", cpuinfo->coreid); 3368c2ecf20Sopenharmony_ci#endif 3378c2ecf20Sopenharmony_ci if (vr & SPR_VR_UVRP) { 3388c2ecf20Sopenharmony_ci vr = mfspr(SPR_VR2); 3398c2ecf20Sopenharmony_ci version = vr & SPR_VR2_VER; 3408c2ecf20Sopenharmony_ci avr = mfspr(SPR_AVR); 3418c2ecf20Sopenharmony_ci seq_printf(m, "cpu architecture\t: " 3428c2ecf20Sopenharmony_ci "OpenRISC 1000 (%d.%d-rev%d)\n", 3438c2ecf20Sopenharmony_ci (avr >> 24) & 0xff, 3448c2ecf20Sopenharmony_ci (avr >> 16) & 0xff, 3458c2ecf20Sopenharmony_ci (avr >> 8) & 0xff); 3468c2ecf20Sopenharmony_ci seq_printf(m, "cpu implementation id\t: 0x%x\n", 3478c2ecf20Sopenharmony_ci (vr & SPR_VR2_CPUID) >> 24); 3488c2ecf20Sopenharmony_ci seq_printf(m, "cpu version\t\t: 0x%x\n", version); 3498c2ecf20Sopenharmony_ci } else { 3508c2ecf20Sopenharmony_ci version = (vr & SPR_VR_VER) >> 24; 3518c2ecf20Sopenharmony_ci seq_printf(m, "cpu\t\t\t: OpenRISC-%x\n", version); 3528c2ecf20Sopenharmony_ci seq_printf(m, "revision\t\t: %d\n", vr & SPR_VR_REV); 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci seq_printf(m, "frequency\t\t: %ld\n", loops_per_jiffy * HZ); 3558c2ecf20Sopenharmony_ci seq_printf(m, "dcache size\t\t: %d bytes\n", cpuinfo->dcache_size); 3568c2ecf20Sopenharmony_ci seq_printf(m, "dcache block size\t: %d bytes\n", 3578c2ecf20Sopenharmony_ci cpuinfo->dcache_block_size); 3588c2ecf20Sopenharmony_ci seq_printf(m, "dcache ways\t\t: %d\n", cpuinfo->dcache_ways); 3598c2ecf20Sopenharmony_ci seq_printf(m, "icache size\t\t: %d bytes\n", cpuinfo->icache_size); 3608c2ecf20Sopenharmony_ci seq_printf(m, "icache block size\t: %d bytes\n", 3618c2ecf20Sopenharmony_ci cpuinfo->icache_block_size); 3628c2ecf20Sopenharmony_ci seq_printf(m, "icache ways\t\t: %d\n", cpuinfo->icache_ways); 3638c2ecf20Sopenharmony_ci seq_printf(m, "immu\t\t\t: %d entries, %lu ways\n", 3648c2ecf20Sopenharmony_ci 1 << ((mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTS) >> 2), 3658c2ecf20Sopenharmony_ci 1 + (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTW)); 3668c2ecf20Sopenharmony_ci seq_printf(m, "dmmu\t\t\t: %d entries, %lu ways\n", 3678c2ecf20Sopenharmony_ci 1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> 2), 3688c2ecf20Sopenharmony_ci 1 + (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTW)); 3698c2ecf20Sopenharmony_ci seq_printf(m, "bogomips\t\t: %lu.%02lu\n", 3708c2ecf20Sopenharmony_ci (loops_per_jiffy * HZ) / 500000, 3718c2ecf20Sopenharmony_ci ((loops_per_jiffy * HZ) / 5000) % 100); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci seq_puts(m, "features\t\t: "); 3748c2ecf20Sopenharmony_ci seq_printf(m, "%s ", cpucfgr & SPR_CPUCFGR_OB32S ? "orbis32" : ""); 3758c2ecf20Sopenharmony_ci seq_printf(m, "%s ", cpucfgr & SPR_CPUCFGR_OB64S ? "orbis64" : ""); 3768c2ecf20Sopenharmony_ci seq_printf(m, "%s ", cpucfgr & SPR_CPUCFGR_OF32S ? "orfpx32" : ""); 3778c2ecf20Sopenharmony_ci seq_printf(m, "%s ", cpucfgr & SPR_CPUCFGR_OF64S ? "orfpx64" : ""); 3788c2ecf20Sopenharmony_ci seq_printf(m, "%s ", cpucfgr & SPR_CPUCFGR_OV64S ? "orvdx64" : ""); 3798c2ecf20Sopenharmony_ci seq_puts(m, "\n"); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci seq_puts(m, "\n"); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci return 0; 3848c2ecf20Sopenharmony_ci} 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_cistatic void *c_start(struct seq_file *m, loff_t *pos) 3878c2ecf20Sopenharmony_ci{ 3888c2ecf20Sopenharmony_ci *pos = cpumask_next(*pos - 1, cpu_online_mask); 3898c2ecf20Sopenharmony_ci if ((*pos) < nr_cpu_ids) 3908c2ecf20Sopenharmony_ci return &cpuinfo_or1k[*pos]; 3918c2ecf20Sopenharmony_ci return NULL; 3928c2ecf20Sopenharmony_ci} 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_cistatic void *c_next(struct seq_file *m, void *v, loff_t *pos) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci (*pos)++; 3978c2ecf20Sopenharmony_ci return c_start(m, pos); 3988c2ecf20Sopenharmony_ci} 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_cistatic void c_stop(struct seq_file *m, void *v) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci} 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ciconst struct seq_operations cpuinfo_op = { 4058c2ecf20Sopenharmony_ci .start = c_start, 4068c2ecf20Sopenharmony_ci .next = c_next, 4078c2ecf20Sopenharmony_ci .stop = c_stop, 4088c2ecf20Sopenharmony_ci .show = show_cpuinfo, 4098c2ecf20Sopenharmony_ci}; 410