-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Ley Foon Tan <lftan@altera.com>
- Loading branch information
Ley Foon Tan
committed
Dec 8, 2014
1 parent
4182de9
commit 2612b87
Showing
2 changed files
with
258 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
* | ||
*/ | ||
|
||
#ifndef _ASM_NIOS2_CPUINFO_H | ||
#define _ASM_NIOS2_CPUINFO_H | ||
|
||
#include <linux/types.h> | ||
|
||
struct cpuinfo { | ||
/* Core CPU configuration */ | ||
char cpu_impl[12]; | ||
u32 cpu_clock_freq; | ||
u32 mmu; | ||
u32 has_div; | ||
u32 has_mul; | ||
u32 has_mulx; | ||
|
||
/* CPU caches */ | ||
u32 icache_line_size; | ||
u32 icache_size; | ||
u32 dcache_line_size; | ||
u32 dcache_size; | ||
|
||
/* TLB */ | ||
u32 tlb_pid_num_bits; /* number of bits used for the PID in TLBMISC */ | ||
u32 tlb_num_ways; | ||
u32 tlb_num_ways_log2; | ||
u32 tlb_num_entries; | ||
u32 tlb_num_lines; | ||
u32 tlb_ptr_sz; | ||
|
||
/* Addresses */ | ||
u32 reset_addr; | ||
u32 exception_addr; | ||
u32 fast_tlb_miss_exc_addr; | ||
}; | ||
|
||
extern struct cpuinfo cpuinfo; | ||
|
||
extern void setup_cpuinfo(void); | ||
|
||
#endif /* _ASM_NIOS2_CPUINFO_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
/* | ||
* Copyright (C) 2013 Altera Corporation | ||
* Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> | ||
* | ||
* Based on cpuinfo.c from microblaze | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
* | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/init.h> | ||
#include <linux/delay.h> | ||
#include <linux/seq_file.h> | ||
#include <linux/string.h> | ||
#include <linux/of.h> | ||
#include <asm/cpuinfo.h> | ||
|
||
struct cpuinfo cpuinfo; | ||
|
||
#define err_cpu(x) \ | ||
pr_err("ERROR: Nios II " x " different for kernel and DTS\n") | ||
|
||
static inline u32 fcpu(struct device_node *cpu, const char *n) | ||
{ | ||
u32 val = 0; | ||
|
||
of_property_read_u32(cpu, n, &val); | ||
|
||
return val; | ||
} | ||
|
||
static inline u32 fcpu_has(struct device_node *cpu, const char *n) | ||
{ | ||
return of_get_property(cpu, n, NULL) ? 1 : 0; | ||
} | ||
|
||
void __init setup_cpuinfo(void) | ||
{ | ||
struct device_node *cpu; | ||
const char *str; | ||
int len; | ||
|
||
cpu = of_find_node_by_type(NULL, "cpu"); | ||
if (!cpu) | ||
panic("%s: No CPU found in devicetree!\n", __func__); | ||
|
||
if (!fcpu_has(cpu, "altr,has-initda")) | ||
panic("initda instruction is unimplemented. Please update your " | ||
"hardware system to have more than 4-byte line data " | ||
"cache\n"); | ||
|
||
cpuinfo.cpu_clock_freq = fcpu(cpu, "clock-frequency"); | ||
|
||
str = of_get_property(cpu, "altr,implementation", &len); | ||
if (str) | ||
strlcpy(cpuinfo.cpu_impl, str, sizeof(cpuinfo.cpu_impl)); | ||
else | ||
strcpy(cpuinfo.cpu_impl, "<unknown>"); | ||
|
||
cpuinfo.has_div = fcpu_has(cpu, "altr,has-div"); | ||
cpuinfo.has_mul = fcpu_has(cpu, "altr,has-mul"); | ||
cpuinfo.has_mulx = fcpu_has(cpu, "altr,has-mulx"); | ||
|
||
#ifdef CONFIG_NIOS2_HW_DIV_SUPPORT | ||
if (!cpuinfo.has_div) | ||
err_cpu("DIV"); | ||
#endif | ||
#ifdef CONFIG_NIOS2_HW_MUL_SUPPORT | ||
if (!cpuinfo.has_mul) | ||
err_cpu("MUL"); | ||
#endif | ||
#ifdef CONFIG_NIOS2_HW_MULX_SUPPORT | ||
if (!cpuinfo.has_mulx) | ||
err_cpu("MULX"); | ||
#endif | ||
|
||
cpuinfo.tlb_num_ways = fcpu(cpu, "altr,tlb-num-ways"); | ||
if (!cpuinfo.tlb_num_ways) | ||
panic("altr,tlb-num-ways can't be 0. Please check your hardware " | ||
"system\n"); | ||
cpuinfo.icache_line_size = fcpu(cpu, "icache-line-size"); | ||
cpuinfo.icache_size = fcpu(cpu, "icache-size"); | ||
if (CONFIG_NIOS2_ICACHE_SIZE != cpuinfo.icache_size) | ||
pr_warn("Warning: icache size configuration mismatch " | ||
"(0x%x vs 0x%x) of CONFIG_NIOS2_ICACHE_SIZE vs " | ||
"device tree icache-size\n", | ||
CONFIG_NIOS2_ICACHE_SIZE, cpuinfo.icache_size); | ||
|
||
cpuinfo.dcache_line_size = fcpu(cpu, "dcache-line-size"); | ||
if (CONFIG_NIOS2_DCACHE_LINE_SIZE != cpuinfo.dcache_line_size) | ||
pr_warn("Warning: dcache line size configuration mismatch " | ||
"(0x%x vs 0x%x) of CONFIG_NIOS2_DCACHE_LINE_SIZE vs " | ||
"device tree dcache-line-size\n", | ||
CONFIG_NIOS2_DCACHE_LINE_SIZE, cpuinfo.dcache_line_size); | ||
cpuinfo.dcache_size = fcpu(cpu, "dcache-size"); | ||
if (CONFIG_NIOS2_DCACHE_SIZE != cpuinfo.dcache_size) | ||
pr_warn("Warning: dcache size configuration mismatch " | ||
"(0x%x vs 0x%x) of CONFIG_NIOS2_DCACHE_SIZE vs " | ||
"device tree dcache-size\n", | ||
CONFIG_NIOS2_DCACHE_SIZE, cpuinfo.dcache_size); | ||
|
||
cpuinfo.tlb_pid_num_bits = fcpu(cpu, "altr,pid-num-bits"); | ||
cpuinfo.tlb_num_ways_log2 = ilog2(cpuinfo.tlb_num_ways); | ||
cpuinfo.tlb_num_entries = fcpu(cpu, "altr,tlb-num-entries"); | ||
cpuinfo.tlb_num_lines = cpuinfo.tlb_num_entries / cpuinfo.tlb_num_ways; | ||
cpuinfo.tlb_ptr_sz = fcpu(cpu, "altr,tlb-ptr-sz"); | ||
|
||
cpuinfo.reset_addr = fcpu(cpu, "altr,reset-addr"); | ||
cpuinfo.exception_addr = fcpu(cpu, "altr,exception-addr"); | ||
cpuinfo.fast_tlb_miss_exc_addr = fcpu(cpu, "altr,fast-tlb-miss-addr"); | ||
} | ||
|
||
#ifdef CONFIG_PROC_FS | ||
|
||
/* | ||
* Get CPU information for use by the procfs. | ||
*/ | ||
static int show_cpuinfo(struct seq_file *m, void *v) | ||
{ | ||
int count = 0; | ||
const u32 clockfreq = cpuinfo.cpu_clock_freq; | ||
|
||
count = seq_printf(m, | ||
"CPU:\t\tNios II/%s\n" | ||
"MMU:\t\t%s\n" | ||
"FPU:\t\tnone\n" | ||
"Clocking:\t%u.%02u MHz\n" | ||
"BogoMips:\t%lu.%02lu\n" | ||
"Calibration:\t%lu loops\n", | ||
cpuinfo.cpu_impl, | ||
cpuinfo.mmu ? "present" : "none", | ||
clockfreq / 1000000, (clockfreq / 100000) % 10, | ||
(loops_per_jiffy * HZ) / 500000, | ||
((loops_per_jiffy * HZ) / 5000) % 100, | ||
(loops_per_jiffy * HZ)); | ||
|
||
count += seq_printf(m, | ||
"HW:\n" | ||
" MUL:\t\t%s\n" | ||
" MULX:\t\t%s\n" | ||
" DIV:\t\t%s\n", | ||
cpuinfo.has_mul ? "yes" : "no", | ||
cpuinfo.has_mulx ? "yes" : "no", | ||
cpuinfo.has_div ? "yes" : "no"); | ||
|
||
count += seq_printf(m, | ||
"Icache:\t\t%ukB, line length: %u\n", | ||
cpuinfo.icache_size >> 10, | ||
cpuinfo.icache_line_size); | ||
|
||
count += seq_printf(m, | ||
"Dcache:\t\t%ukB, line length: %u\n", | ||
cpuinfo.dcache_size >> 10, | ||
cpuinfo.dcache_line_size); | ||
|
||
count += seq_printf(m, | ||
"TLB:\t\t%u ways, %u entries, %u PID bits\n", | ||
cpuinfo.tlb_num_ways, | ||
cpuinfo.tlb_num_entries, | ||
cpuinfo.tlb_pid_num_bits); | ||
|
||
return 0; | ||
} | ||
|
||
static void *cpuinfo_start(struct seq_file *m, loff_t *pos) | ||
{ | ||
unsigned long i = *pos; | ||
|
||
return i < num_possible_cpus() ? (void *) (i + 1) : NULL; | ||
} | ||
|
||
static void *cpuinfo_next(struct seq_file *m, void *v, loff_t *pos) | ||
{ | ||
++*pos; | ||
return cpuinfo_start(m, pos); | ||
} | ||
|
||
static void cpuinfo_stop(struct seq_file *m, void *v) | ||
{ | ||
} | ||
|
||
const struct seq_operations cpuinfo_op = { | ||
.start = cpuinfo_start, | ||
.next = cpuinfo_next, | ||
.stop = cpuinfo_stop, | ||
.show = show_cpuinfo | ||
}; | ||
|
||
#endif /* CONFIG_PROC_FS */ |