2 * arch/ubicom32/kernel/processor.c
3 * Ubicom32 architecture processor info implementation.
5 * (C) Copyright 2009, Ubicom, Inc.
7 * This file is part of the Ubicom32 Linux Kernel Port.
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option) any later version.
14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with the Ubicom32 Linux Kernel Port. If not,
21 * see <http://www.gnu.org/licenses/>.
23 * Ubicom32 implementation derived from (with many thanks):
28 #include <linux/module.h>
29 #include <linux/kernel.h>
30 #include <linux/init.h>
31 #include <linux/sched.h>
32 #include <linux/interrupt.h>
33 #include <linux/irq.h>
34 #include <linux/profile.h>
35 #include <linux/clocksource.h>
36 #include <linux/types.h>
37 #include <linux/seq_file.h>
38 #include <linux/delay.h>
39 #include <linux/cpu.h>
40 #include <asm/devtree.h>
41 #include <asm/processor.h>
43 #include <asm/ocm_size.h>
46 struct devtree_node dn;
49 unsigned int frequency;
50 unsigned int ddr_frequency;
51 unsigned int interrupt0;
52 unsigned int interrupt1;
57 unsigned int arch_version;
58 void *os_syscall_begin;
65 * show_processorinfo()
66 * Print the actual processor information.
68 static void show_processorinfo(struct seq_file *m)
70 char *cpu, *mmu, *fpu;
71 unsigned int clockfreq;
79 "move.4 %0, CHIP_ID \n\t"
84 * General Processor Information.
86 seq_printf(m, "Vendor:\t\t%s\n", "Ubicom");
87 seq_printf(m, "CPU:\t\t%s\n", cpu);
88 seq_printf(m, "MMU:\t\t%s\n", mmu);
89 seq_printf(m, "FPU:\t\t%s\n", fpu);
90 seq_printf(m, "Arch:\t\t%hx\n", chipid >> 16);
91 seq_printf(m, "Rev:\t\t%hx\n", (chipid & 0xffff));
94 * Now compute the clock frequency in Mhz.
96 clockfreq = processor_frequency();
97 seq_printf(m, "Clock Freq:\t%u.0 MHz\n",
99 seq_printf(m, "DDR Freq:\t%u.0 MHz\n",
100 pn ? pn->ddr_frequency / 1000000 : 0);
101 seq_printf(m, "BogoMips:\t%lu.%02lu\n",
102 (loops_per_jiffy * HZ) / 500000,
103 ((loops_per_jiffy * HZ) / 5000) % 100);
104 seq_printf(m, "Calibration:\t%lu loops\n", (loops_per_jiffy * HZ));
109 * Get CPU information for use by the procfs.
111 static int show_cpuinfo(struct seq_file *m, void *v)
113 unsigned long n = (unsigned long)v - 1;
115 #if defined(CONFIG_SMP)
116 struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, n);
120 * Print the general processor information on the first
124 show_processorinfo(m);
127 #if defined(CONFIG_SMP)
129 * For each hwthread, print if this hwthread is running Linux
130 * or is an I/O thread.
132 if (cpu_isset(n, cpu_online_map)) {
133 seq_printf(m, "cpu[%02lu]:\tthread id - %lu\n", n, p->tid);
135 seq_printf(m, "cpu[%02lu]:\toff-line\n", n);
142 static void *c_start(struct seq_file *m, loff_t *pos)
144 unsigned long i = *pos;
146 return i < NR_CPUS ? (void *)(i + 1) : NULL;
149 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
152 return c_start(m, pos);
155 static void c_stop(struct seq_file *m, void *v)
159 const struct seq_operations cpuinfo_op = {
163 .show = show_cpuinfo,
168 * Returns the timers available to Linux.
170 unsigned int processor_timers(void)
179 * processor_threads()
180 * Returns the threads available to Linux.
182 unsigned int processor_threads(void)
191 * processor_frequency()
192 * Returns the frequency of the system clock.
194 unsigned int processor_frequency(void)
199 return pn->frequency;
201 EXPORT_SYMBOL(processor_frequency);
204 * processor_interrupts()
205 * Return the interrupts that are setup at boot time.
207 int processor_interrupts(unsigned int *int0, unsigned int *int1)
214 *int0 = pn->interrupt0;
218 *int1 = pn->interrupt1;
225 * Returns the start and end of OCM available to Linux.
227 void processor_ocm(unsigned long *socm, unsigned long *eocm)
229 *socm = (unsigned long)pn->socm;
230 *eocm = (unsigned long)pn->eocm;
235 * Returns the start and end of dram available to Linux.
237 void processor_dram(unsigned long *sdram, unsigned long *edram)
239 *sdram = (unsigned long)pn->sdram;
240 *edram = (unsigned long)pn->edram;
244 * processor_validate_failed()
245 * Returns the dram available to Linux.
247 static noinline void processor_validate_failed(void)
254 * processor_validate()
255 * Validates the procnode against limitations of this link/built.
257 static void processor_validate(void)
259 void *dram_start = (void *)(KERNELSTART);
260 void *dram_end = (void *)(SDRAMSTART + CONFIG_MIN_RAMSIZE);
261 #if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
262 void *ocm_code_start = (void *)(OCMSTART + APP_OCM_CODE_SIZE);
263 void *ocm_data_end = (void *)(OCMEND - APP_OCM_DATA_SIZE);
265 extern void __os_syscall_begin;
266 extern void __os_syscall_end;
267 int proc_node_valid = 1;
270 printk(KERN_ERR "ERROR: processor node not found\n");
275 if (dram_start < pn->sdram || dram_end > pn->edram) {
276 printk(KERN_ERR "ERROR: processor dram mismatch %p-%p "
277 "available but we are expecting %p-%p\n",
278 pn->sdram, pn->edram, dram_start, dram_end);
281 printk(KERN_ERR "processor dram %p-%p, expecting %p-%p\n",
282 pn->sdram, pn->edram, dram_start, dram_end);
284 if (&__os_syscall_begin < pn->os_syscall_begin ||
285 &__os_syscall_end > pn->os_syscall_end) {
286 printk(KERN_ERR "ERROR: processor syscall area mismatch "
287 "%p-%p available but we are expecting %p-%p\n",
288 pn->os_syscall_begin, pn->os_syscall_end,
289 &__os_syscall_begin, &__os_syscall_end);
292 printk(KERN_ERR "processor dram %p-%p, expecting %p-%p\n",
293 pn->sdram, pn->edram, dram_start, dram_end);
295 #if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
296 if (ocm_code_start < pn->socm || ocm_data_end > pn->eocm) {
297 printk(KERN_ERR "ERROR: processor ocm mismatch %p-%p "
298 "available but we are expecting %p-%p\n",
299 pn->socm, pn->eocm, ocm_code_start, ocm_data_end);
302 printk(KERN_INFO "processor ocm %p-%p, expecting %p-%p\n",
303 pn->socm, pn->eocm, ocm_code_start, ocm_data_end);
308 if (UBICOM32_ARCH_VERSION != pn->arch_version) {
309 printk(KERN_ERR "ERROR: processor arch mismatch, kernel"
310 "compiled for %d found %d\n",
311 UBICOM32_ARCH_VERSION, pn->arch_version);
318 processor_validate_failed();
321 void __init processor_init(void)
324 * If we do not have a trap node in the device tree, we leave the fault
325 * handling to the underlying hardware.
327 pn = (struct procnode *)devtree_find_node("processor");
329 processor_validate();
332 * If necessary correct the initial range registers to cover the
333 * complete physical space
335 if (pn->edram > (void *)(SDRAMSTART + CONFIG_MIN_RAMSIZE)) {
336 printk(KERN_INFO "updating range registers for expanded dram\n");
338 " move.4 D_RANGE1_HI, %0 \t\n"
339 " move.4 I_RANGE0_HI, %0 \t\n"
340 #ifdef CONFIG_PROTECT_KERNEL
341 " move.4 D_RANGE2_HI, %0 \t\n"
342 " move.4 I_RANGE2_HI, %0 \t\n"
344 : : "a"((unsigned long)pn->edram - 4)