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)