aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r--arch/blackfin/kernel/asm-offsets.c29
-rw-r--r--arch/blackfin/kernel/bfin_ksyms.c34
-rw-r--r--arch/blackfin/kernel/entry.S1
-rw-r--r--arch/blackfin/kernel/irqchip.c24
-rw-r--r--arch/blackfin/kernel/kgdb.c4
-rw-r--r--arch/blackfin/kernel/module.c13
-rw-r--r--arch/blackfin/kernel/process.c23
-rw-r--r--arch/blackfin/kernel/ptrace.c8
-rw-r--r--arch/blackfin/kernel/reboot.c24
-rw-r--r--arch/blackfin/kernel/setup.c163
-rw-r--r--arch/blackfin/kernel/time.c114
-rw-r--r--arch/blackfin/kernel/traps.c56
12 files changed, 340 insertions, 153 deletions
diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c
index 9bb85dd5ccb3..b5df9459d6d5 100644
--- a/arch/blackfin/kernel/asm-offsets.c
+++ b/arch/blackfin/kernel/asm-offsets.c
@@ -56,6 +56,9 @@ int main(void)
56 /* offsets into the thread struct */ 56 /* offsets into the thread struct */
57 DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); 57 DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
58 DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); 58 DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
59 DEFINE(THREAD_SR, offsetof(struct thread_struct, seqstat));
60 DEFINE(PT_SR, offsetof(struct thread_struct, seqstat));
61 DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
59 DEFINE(THREAD_PC, offsetof(struct thread_struct, pc)); 62 DEFINE(THREAD_PC, offsetof(struct thread_struct, pc));
60 DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE); 63 DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE);
61 64
@@ -128,5 +131,31 @@ int main(void)
128 DEFINE(SIGSEGV, SIGSEGV); 131 DEFINE(SIGSEGV, SIGSEGV);
129 DEFINE(SIGTRAP, SIGTRAP); 132 DEFINE(SIGTRAP, SIGTRAP);
130 133
134 /* PDA management (in L1 scratchpad) */
135 DEFINE(PDA_SYSCFG, offsetof(struct blackfin_pda, syscfg));
136#ifdef CONFIG_SMP
137 DEFINE(PDA_IRQFLAGS, offsetof(struct blackfin_pda, imask));
138#endif
139 DEFINE(PDA_IPDT, offsetof(struct blackfin_pda, ipdt));
140 DEFINE(PDA_IPDT_SWAPCOUNT, offsetof(struct blackfin_pda, ipdt_swapcount));
141 DEFINE(PDA_DPDT, offsetof(struct blackfin_pda, dpdt));
142 DEFINE(PDA_DPDT_SWAPCOUNT, offsetof(struct blackfin_pda, dpdt_swapcount));
143 DEFINE(PDA_EXIPTR, offsetof(struct blackfin_pda, ex_iptr));
144 DEFINE(PDA_EXOPTR, offsetof(struct blackfin_pda, ex_optr));
145 DEFINE(PDA_EXBUF, offsetof(struct blackfin_pda, ex_buf));
146 DEFINE(PDA_EXIMASK, offsetof(struct blackfin_pda, ex_imask));
147 DEFINE(PDA_EXSTACK, offsetof(struct blackfin_pda, ex_stack));
148#ifdef ANOMALY_05000261
149 DEFINE(PDA_LFRETX, offsetof(struct blackfin_pda, last_cplb_fault_retx));
150#endif
151 DEFINE(PDA_DCPLB, offsetof(struct blackfin_pda, dcplb_fault_addr));
152 DEFINE(PDA_ICPLB, offsetof(struct blackfin_pda, icplb_fault_addr));
153 DEFINE(PDA_RETX, offsetof(struct blackfin_pda, retx));
154 DEFINE(PDA_SEQSTAT, offsetof(struct blackfin_pda, seqstat));
155#ifdef CONFIG_SMP
156 /* Inter-core lock (in L2 SRAM) */
157 DEFINE(SIZEOF_CORELOCK, sizeof(struct corelock_slot));
158#endif
159
131 return 0; 160 return 0;
132} 161}
diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c
index b66f1d4c8344..763c31531e9e 100644
--- a/arch/blackfin/kernel/bfin_ksyms.c
+++ b/arch/blackfin/kernel/bfin_ksyms.c
@@ -68,3 +68,37 @@ EXPORT_SYMBOL(insw_8);
68EXPORT_SYMBOL(outsl); 68EXPORT_SYMBOL(outsl);
69EXPORT_SYMBOL(insl); 69EXPORT_SYMBOL(insl);
70EXPORT_SYMBOL(insl_16); 70EXPORT_SYMBOL(insl_16);
71
72#ifdef CONFIG_SMP
73EXPORT_SYMBOL(__raw_atomic_update_asm);
74EXPORT_SYMBOL(__raw_atomic_clear_asm);
75EXPORT_SYMBOL(__raw_atomic_set_asm);
76EXPORT_SYMBOL(__raw_atomic_xor_asm);
77EXPORT_SYMBOL(__raw_atomic_test_asm);
78EXPORT_SYMBOL(__raw_xchg_1_asm);
79EXPORT_SYMBOL(__raw_xchg_2_asm);
80EXPORT_SYMBOL(__raw_xchg_4_asm);
81EXPORT_SYMBOL(__raw_cmpxchg_1_asm);
82EXPORT_SYMBOL(__raw_cmpxchg_2_asm);
83EXPORT_SYMBOL(__raw_cmpxchg_4_asm);
84EXPORT_SYMBOL(__raw_spin_is_locked_asm);
85EXPORT_SYMBOL(__raw_spin_lock_asm);
86EXPORT_SYMBOL(__raw_spin_trylock_asm);
87EXPORT_SYMBOL(__raw_spin_unlock_asm);
88EXPORT_SYMBOL(__raw_read_lock_asm);
89EXPORT_SYMBOL(__raw_read_trylock_asm);
90EXPORT_SYMBOL(__raw_read_unlock_asm);
91EXPORT_SYMBOL(__raw_write_lock_asm);
92EXPORT_SYMBOL(__raw_write_trylock_asm);
93EXPORT_SYMBOL(__raw_write_unlock_asm);
94EXPORT_SYMBOL(__raw_bit_set_asm);
95EXPORT_SYMBOL(__raw_bit_clear_asm);
96EXPORT_SYMBOL(__raw_bit_toggle_asm);
97EXPORT_SYMBOL(__raw_bit_test_asm);
98EXPORT_SYMBOL(__raw_bit_test_set_asm);
99EXPORT_SYMBOL(__raw_bit_test_clear_asm);
100EXPORT_SYMBOL(__raw_bit_test_toggle_asm);
101EXPORT_SYMBOL(__raw_uncached_fetch_asm);
102EXPORT_SYMBOL(__raw_smp_mark_barrier_asm);
103EXPORT_SYMBOL(__raw_smp_check_barrier_asm);
104#endif
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S
index faea88ebb2ef..c0c3fe811228 100644
--- a/arch/blackfin/kernel/entry.S
+++ b/arch/blackfin/kernel/entry.S
@@ -30,6 +30,7 @@
30#include <linux/linkage.h> 30#include <linux/linkage.h>
31#include <asm/thread_info.h> 31#include <asm/thread_info.h>
32#include <asm/errno.h> 32#include <asm/errno.h>
33#include <asm/blackfin.h>
33#include <asm/asm-offsets.h> 34#include <asm/asm-offsets.h>
34 35
35#include <asm/context.S> 36#include <asm/context.S>
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c
index 07402f57c9de..9eebb782fd30 100644
--- a/arch/blackfin/kernel/irqchip.c
+++ b/arch/blackfin/kernel/irqchip.c
@@ -36,7 +36,7 @@
36#include <linux/irq.h> 36#include <linux/irq.h>
37#include <asm/trace.h> 37#include <asm/trace.h>
38 38
39static unsigned long irq_err_count; 39static atomic_t irq_err_count;
40static spinlock_t irq_controller_lock; 40static spinlock_t irq_controller_lock;
41 41
42/* 42/*
@@ -48,7 +48,7 @@ void dummy_mask_unmask_irq(unsigned int irq)
48 48
49void ack_bad_irq(unsigned int irq) 49void ack_bad_irq(unsigned int irq)
50{ 50{
51 irq_err_count += 1; 51 atomic_inc(&irq_err_count);
52 printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); 52 printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq);
53} 53}
54EXPORT_SYMBOL(ack_bad_irq); 54EXPORT_SYMBOL(ack_bad_irq);
@@ -72,7 +72,7 @@ static struct irq_desc bad_irq_desc = {
72 72
73int show_interrupts(struct seq_file *p, void *v) 73int show_interrupts(struct seq_file *p, void *v)
74{ 74{
75 int i = *(loff_t *) v; 75 int i = *(loff_t *) v, j;
76 struct irqaction *action; 76 struct irqaction *action;
77 unsigned long flags; 77 unsigned long flags;
78 78
@@ -80,19 +80,20 @@ int show_interrupts(struct seq_file *p, void *v)
80 spin_lock_irqsave(&irq_desc[i].lock, flags); 80 spin_lock_irqsave(&irq_desc[i].lock, flags);
81 action = irq_desc[i].action; 81 action = irq_desc[i].action;
82 if (!action) 82 if (!action)
83 goto unlock; 83 goto skip;
84 84 seq_printf(p, "%3d: ", i);
85 seq_printf(p, "%3d: %10u ", i, kstat_irqs(i)); 85 for_each_online_cpu(j)
86 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
87 seq_printf(p, " %8s", irq_desc[i].chip->name);
86 seq_printf(p, " %s", action->name); 88 seq_printf(p, " %s", action->name);
87 for (action = action->next; action; action = action->next) 89 for (action = action->next; action; action = action->next)
88 seq_printf(p, ", %s", action->name); 90 seq_printf(p, " %s", action->name);
89 91
90 seq_putc(p, '\n'); 92 seq_putc(p, '\n');
91 unlock: 93 skip:
92 spin_unlock_irqrestore(&irq_desc[i].lock, flags); 94 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
93 } else if (i == NR_IRQS) { 95 } else if (i == NR_IRQS)
94 seq_printf(p, "Err: %10lu\n", irq_err_count); 96 seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
95 }
96 return 0; 97 return 0;
97} 98}
98 99
@@ -101,7 +102,6 @@ int show_interrupts(struct seq_file *p, void *v)
101 * come via this function. Instead, they should provide their 102 * come via this function. Instead, they should provide their
102 * own 'handler' 103 * own 'handler'
103 */ 104 */
104
105#ifdef CONFIG_DO_IRQ_L1 105#ifdef CONFIG_DO_IRQ_L1
106__attribute__((l1_text)) 106__attribute__((l1_text))
107#endif 107#endif
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c
index b795a207742c..ab4022131a2a 100644
--- a/arch/blackfin/kernel/kgdb.c
+++ b/arch/blackfin/kernel/kgdb.c
@@ -363,12 +363,12 @@ void kgdb_passive_cpu_callback(void *info)
363 363
364void kgdb_roundup_cpus(unsigned long flags) 364void kgdb_roundup_cpus(unsigned long flags)
365{ 365{
366 smp_call_function(kgdb_passive_cpu_callback, NULL, 0, 0); 366 smp_call_function(kgdb_passive_cpu_callback, NULL, 0);
367} 367}
368 368
369void kgdb_roundup_cpu(int cpu, unsigned long flags) 369void kgdb_roundup_cpu(int cpu, unsigned long flags)
370{ 370{
371 smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0, 0); 371 smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0);
372} 372}
373#endif 373#endif
374 374
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c
index e1bebc80a5bf..2e14cadd4302 100644
--- a/arch/blackfin/kernel/module.c
+++ b/arch/blackfin/kernel/module.c
@@ -343,7 +343,13 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
343 pr_debug("location is %x, value is %x type is %d \n", 343 pr_debug("location is %x, value is %x type is %d \n",
344 (unsigned int) location32, value, 344 (unsigned int) location32, value,
345 ELF32_R_TYPE(rel[i].r_info)); 345 ELF32_R_TYPE(rel[i].r_info));
346 346#ifdef CONFIG_SMP
347 if ((unsigned long)location16 >= COREB_L1_DATA_A_START) {
348 printk(KERN_ERR "module %s: cannot relocate in L1: %u (SMP kernel)",
349 mod->name, ELF32_R_TYPE(rel[i].r_info));
350 return -ENOEXEC;
351 }
352#endif
347 switch (ELF32_R_TYPE(rel[i].r_info)) { 353 switch (ELF32_R_TYPE(rel[i].r_info)) {
348 354
349 case R_pcrel24: 355 case R_pcrel24:
@@ -436,6 +442,7 @@ module_finalize(const Elf_Ehdr * hdr,
436{ 442{
437 unsigned int i, strindex = 0, symindex = 0; 443 unsigned int i, strindex = 0, symindex = 0;
438 char *secstrings; 444 char *secstrings;
445 long err = 0;
439 446
440 secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 447 secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
441 448
@@ -460,8 +467,10 @@ module_finalize(const Elf_Ehdr * hdr,
460 (strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) || 467 (strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) ||
461 ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) && 468 ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
462 (hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) { 469 (hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) {
463 apply_relocate_add((Elf_Shdr *) sechdrs, strtab, 470 err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
464 symindex, i, mod); 471 symindex, i, mod);
472 if (err < 0)
473 return -ENOEXEC;
465 } 474 }
466 } 475 }
467 return 0; 476 return 0;
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 326e3019cd23..4359ea253010 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -171,6 +171,13 @@ asmlinkage int bfin_clone(struct pt_regs *regs)
171 unsigned long clone_flags; 171 unsigned long clone_flags;
172 unsigned long newsp; 172 unsigned long newsp;
173 173
174#ifdef __ARCH_SYNC_CORE_DCACHE
175 if (current->rt.nr_cpus_allowed == num_possible_cpus()) {
176 current->cpus_allowed = cpumask_of_cpu(smp_processor_id());
177 current->rt.nr_cpus_allowed = 1;
178 }
179#endif
180
174 /* syscall2 puts clone_flags in r0 and usp in r1 */ 181 /* syscall2 puts clone_flags in r0 and usp in r1 */
175 clone_flags = regs->r0; 182 clone_flags = regs->r0;
176 newsp = regs->r1; 183 newsp = regs->r1;
@@ -338,22 +345,22 @@ int _access_ok(unsigned long addr, unsigned long size)
338 if (addr >= (unsigned long)__init_begin && 345 if (addr >= (unsigned long)__init_begin &&
339 addr + size <= (unsigned long)__init_end) 346 addr + size <= (unsigned long)__init_end)
340 return 1; 347 return 1;
341 if (addr >= L1_SCRATCH_START 348 if (addr >= get_l1_scratch_start()
342 && addr + size <= L1_SCRATCH_START + L1_SCRATCH_LENGTH) 349 && addr + size <= get_l1_scratch_start() + L1_SCRATCH_LENGTH)
343 return 1; 350 return 1;
344#if L1_CODE_LENGTH != 0 351#if L1_CODE_LENGTH != 0
345 if (addr >= L1_CODE_START + (_etext_l1 - _stext_l1) 352 if (addr >= get_l1_code_start() + (_etext_l1 - _stext_l1)
346 && addr + size <= L1_CODE_START + L1_CODE_LENGTH) 353 && addr + size <= get_l1_code_start() + L1_CODE_LENGTH)
347 return 1; 354 return 1;
348#endif 355#endif
349#if L1_DATA_A_LENGTH != 0 356#if L1_DATA_A_LENGTH != 0
350 if (addr >= L1_DATA_A_START + (_ebss_l1 - _sdata_l1) 357 if (addr >= get_l1_data_a_start() + (_ebss_l1 - _sdata_l1)
351 && addr + size <= L1_DATA_A_START + L1_DATA_A_LENGTH) 358 && addr + size <= get_l1_data_a_start() + L1_DATA_A_LENGTH)
352 return 1; 359 return 1;
353#endif 360#endif
354#if L1_DATA_B_LENGTH != 0 361#if L1_DATA_B_LENGTH != 0
355 if (addr >= L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1) 362 if (addr >= get_l1_data_b_start() + (_ebss_b_l1 - _sdata_b_l1)
356 && addr + size <= L1_DATA_B_START + L1_DATA_B_LENGTH) 363 && addr + size <= get_l1_data_b_start() + L1_DATA_B_LENGTH)
357 return 1; 364 return 1;
358#endif 365#endif
359#if L2_LENGTH != 0 366#if L2_LENGTH != 0
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index 140bf00e9974..4de44f387dd5 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -220,8 +220,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
220 break; 220 break;
221 pr_debug("ptrace: user address is valid\n"); 221 pr_debug("ptrace: user address is valid\n");
222 222
223 if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START 223 if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start()
224 && addr + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) { 224 && addr + sizeof(tmp) <= get_l1_code_start() + L1_CODE_LENGTH) {
225 safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp)); 225 safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp));
226 copied = sizeof(tmp); 226 copied = sizeof(tmp);
227 227
@@ -300,8 +300,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
300 break; 300 break;
301 pr_debug("ptrace: user address is valid\n"); 301 pr_debug("ptrace: user address is valid\n");
302 302
303 if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START 303 if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start()
304 && addr + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) { 304 && addr + sizeof(data) <= get_l1_code_start() + L1_CODE_LENGTH) {
305 safe_dma_memcpy ((void *)(addr), &data, sizeof(data)); 305 safe_dma_memcpy ((void *)(addr), &data, sizeof(data));
306 copied = sizeof(data); 306 copied = sizeof(data);
307 307
diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c
index ae97ca407b0d..eeee8cb43360 100644
--- a/arch/blackfin/kernel/reboot.c
+++ b/arch/blackfin/kernel/reboot.c
@@ -21,7 +21,7 @@
21 * the core reset. 21 * the core reset.
22 */ 22 */
23__attribute__((l1_text)) 23__attribute__((l1_text))
24static void bfin_reset(void) 24static void _bfin_reset(void)
25{ 25{
26 /* Wait for completion of "system" events such as cache line 26 /* Wait for completion of "system" events such as cache line
27 * line fills so that we avoid infinite stalls later on as 27 * line fills so that we avoid infinite stalls later on as
@@ -66,6 +66,18 @@ static void bfin_reset(void)
66 } 66 }
67} 67}
68 68
69static void bfin_reset(void)
70{
71 if (ANOMALY_05000353 || ANOMALY_05000386)
72 _bfin_reset();
73 else
74 /* the bootrom checks to see how it was reset and will
75 * automatically perform a software reset for us when
76 * it starts executing boot
77 */
78 asm("raise 1;");
79}
80
69__attribute__((weak)) 81__attribute__((weak))
70void native_machine_restart(char *cmd) 82void native_machine_restart(char *cmd)
71{ 83{
@@ -75,14 +87,10 @@ void machine_restart(char *cmd)
75{ 87{
76 native_machine_restart(cmd); 88 native_machine_restart(cmd);
77 local_irq_disable(); 89 local_irq_disable();
78 if (ANOMALY_05000353 || ANOMALY_05000386) 90 if (smp_processor_id())
79 bfin_reset(); 91 smp_call_function((void *)bfin_reset, 0, 1);
80 else 92 else
81 /* the bootrom checks to see how it was reset and will 93 bfin_reset();
82 * automatically perform a software reset for us when
83 * it starts executing boot
84 */
85 asm("raise 1;");
86} 94}
87 95
88__attribute__((weak)) 96__attribute__((weak))
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 71a9a8c53cea..c644d234a02e 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -26,11 +26,10 @@
26#include <asm/blackfin.h> 26#include <asm/blackfin.h>
27#include <asm/cplbinit.h> 27#include <asm/cplbinit.h>
28#include <asm/div64.h> 28#include <asm/div64.h>
29#include <asm/cpu.h>
29#include <asm/fixed_code.h> 30#include <asm/fixed_code.h>
30#include <asm/early_printk.h> 31#include <asm/early_printk.h>
31 32
32static DEFINE_PER_CPU(struct cpu, cpu_devices);
33
34u16 _bfin_swrst; 33u16 _bfin_swrst;
35EXPORT_SYMBOL(_bfin_swrst); 34EXPORT_SYMBOL(_bfin_swrst);
36 35
@@ -79,29 +78,76 @@ static struct change_member *change_point[2*BFIN_MEMMAP_MAX] __initdata;
79static struct bfin_memmap_entry *overlap_list[BFIN_MEMMAP_MAX] __initdata; 78static struct bfin_memmap_entry *overlap_list[BFIN_MEMMAP_MAX] __initdata;
80static struct bfin_memmap_entry new_map[BFIN_MEMMAP_MAX] __initdata; 79static struct bfin_memmap_entry new_map[BFIN_MEMMAP_MAX] __initdata;
81 80
82void __init bfin_cache_init(void) 81DEFINE_PER_CPU(struct blackfin_cpudata, cpu_data);
83{ 82
84#if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE) 83#if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE)
85 generate_cplb_tables(); 84void __init generate_cplb_tables(void)
85{
86 unsigned int cpu;
87
88 /* Generate per-CPU I&D CPLB tables */
89 for (cpu = 0; cpu < num_possible_cpus(); ++cpu)
90 generate_cplb_tables_cpu(cpu);
91}
86#endif 92#endif
87 93
94void __cpuinit bfin_setup_caches(unsigned int cpu)
95{
88#ifdef CONFIG_BFIN_ICACHE 96#ifdef CONFIG_BFIN_ICACHE
89 bfin_icache_init(); 97#ifdef CONFIG_MPU
90 printk(KERN_INFO "Instruction Cache Enabled\n"); 98 bfin_icache_init(icplb_tbl[cpu]);
99#else
100 bfin_icache_init(icplb_tables[cpu]);
101#endif
91#endif 102#endif
92 103
93#ifdef CONFIG_BFIN_DCACHE 104#ifdef CONFIG_BFIN_DCACHE
94 bfin_dcache_init(); 105#ifdef CONFIG_MPU
95 printk(KERN_INFO "Data Cache Enabled" 106 bfin_dcache_init(dcplb_tbl[cpu]);
107#else
108 bfin_dcache_init(dcplb_tables[cpu]);
109#endif
110#endif
111
112 /*
113 * In cache coherence emulation mode, we need to have the
114 * D-cache enabled before running any atomic operation which
115 * might invove cache invalidation (i.e. spinlock, rwlock).
116 * So printk's are deferred until then.
117 */
118#ifdef CONFIG_BFIN_ICACHE
119 printk(KERN_INFO "Instruction Cache Enabled for CPU%u\n", cpu);
120#endif
121#ifdef CONFIG_BFIN_DCACHE
122 printk(KERN_INFO "Data Cache Enabled for CPU%u"
96# if defined CONFIG_BFIN_WB 123# if defined CONFIG_BFIN_WB
97 " (write-back)" 124 " (write-back)"
98# elif defined CONFIG_BFIN_WT 125# elif defined CONFIG_BFIN_WT
99 " (write-through)" 126 " (write-through)"
100# endif 127# endif
101 "\n"); 128 "\n", cpu);
102#endif 129#endif
103} 130}
104 131
132void __cpuinit bfin_setup_cpudata(unsigned int cpu)
133{
134 struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, cpu);
135
136 cpudata->idle = current;
137 cpudata->loops_per_jiffy = loops_per_jiffy;
138 cpudata->cclk = get_cclk();
139 cpudata->imemctl = bfin_read_IMEM_CONTROL();
140 cpudata->dmemctl = bfin_read_DMEM_CONTROL();
141}
142
143void __init bfin_cache_init(void)
144{
145#if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE)
146 generate_cplb_tables();
147#endif
148 bfin_setup_caches(0);
149}
150
105void __init bfin_relocate_l1_mem(void) 151void __init bfin_relocate_l1_mem(void)
106{ 152{
107 unsigned long l1_code_length; 153 unsigned long l1_code_length;
@@ -230,7 +276,7 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map)
230 /* record all known change-points (starting and ending addresses), 276 /* record all known change-points (starting and ending addresses),
231 omitting those that are for empty memory regions */ 277 omitting those that are for empty memory regions */
232 chgidx = 0; 278 chgidx = 0;
233 for (i = 0; i < old_nr; i++) { 279 for (i = 0; i < old_nr; i++) {
234 if (map[i].size != 0) { 280 if (map[i].size != 0) {
235 change_point[chgidx]->addr = map[i].addr; 281 change_point[chgidx]->addr = map[i].addr;
236 change_point[chgidx++]->pentry = &map[i]; 282 change_point[chgidx++]->pentry = &map[i];
@@ -238,13 +284,13 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map)
238 change_point[chgidx++]->pentry = &map[i]; 284 change_point[chgidx++]->pentry = &map[i];
239 } 285 }
240 } 286 }
241 chg_nr = chgidx; /* true number of change-points */ 287 chg_nr = chgidx; /* true number of change-points */
242 288
243 /* sort change-point list by memory addresses (low -> high) */ 289 /* sort change-point list by memory addresses (low -> high) */
244 still_changing = 1; 290 still_changing = 1;
245 while (still_changing) { 291 while (still_changing) {
246 still_changing = 0; 292 still_changing = 0;
247 for (i = 1; i < chg_nr; i++) { 293 for (i = 1; i < chg_nr; i++) {
248 /* if <current_addr> > <last_addr>, swap */ 294 /* if <current_addr> > <last_addr>, swap */
249 /* or, if current=<start_addr> & last=<end_addr>, swap */ 295 /* or, if current=<start_addr> & last=<end_addr>, swap */
250 if ((change_point[i]->addr < change_point[i-1]->addr) || 296 if ((change_point[i]->addr < change_point[i-1]->addr) ||
@@ -261,10 +307,10 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map)
261 } 307 }
262 308
263 /* create a new memmap, removing overlaps */ 309 /* create a new memmap, removing overlaps */
264 overlap_entries = 0; /* number of entries in the overlap table */ 310 overlap_entries = 0; /* number of entries in the overlap table */
265 new_entry = 0; /* index for creating new memmap entries */ 311 new_entry = 0; /* index for creating new memmap entries */
266 last_type = 0; /* start with undefined memory type */ 312 last_type = 0; /* start with undefined memory type */
267 last_addr = 0; /* start with 0 as last starting address */ 313 last_addr = 0; /* start with 0 as last starting address */
268 /* loop through change-points, determining affect on the new memmap */ 314 /* loop through change-points, determining affect on the new memmap */
269 for (chgidx = 0; chgidx < chg_nr; chgidx++) { 315 for (chgidx = 0; chgidx < chg_nr; chgidx++) {
270 /* keep track of all overlapping memmap entries */ 316 /* keep track of all overlapping memmap entries */
@@ -286,14 +332,14 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map)
286 if (overlap_list[i]->type > current_type) 332 if (overlap_list[i]->type > current_type)
287 current_type = overlap_list[i]->type; 333 current_type = overlap_list[i]->type;
288 /* continue building up new memmap based on this information */ 334 /* continue building up new memmap based on this information */
289 if (current_type != last_type) { 335 if (current_type != last_type) {
290 if (last_type != 0) { 336 if (last_type != 0) {
291 new_map[new_entry].size = 337 new_map[new_entry].size =
292 change_point[chgidx]->addr - last_addr; 338 change_point[chgidx]->addr - last_addr;
293 /* move forward only if the new size was non-zero */ 339 /* move forward only if the new size was non-zero */
294 if (new_map[new_entry].size != 0) 340 if (new_map[new_entry].size != 0)
295 if (++new_entry >= BFIN_MEMMAP_MAX) 341 if (++new_entry >= BFIN_MEMMAP_MAX)
296 break; /* no more space left for new entries */ 342 break; /* no more space left for new entries */
297 } 343 }
298 if (current_type != 0) { 344 if (current_type != 0) {
299 new_map[new_entry].addr = change_point[chgidx]->addr; 345 new_map[new_entry].addr = change_point[chgidx]->addr;
@@ -303,9 +349,9 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map)
303 last_type = current_type; 349 last_type = current_type;
304 } 350 }
305 } 351 }
306 new_nr = new_entry; /* retain count for new entries */ 352 new_nr = new_entry; /* retain count for new entries */
307 353
308 /* copy new mapping into original location */ 354 /* copy new mapping into original location */
309 memcpy(map, new_map, new_nr*sizeof(struct bfin_memmap_entry)); 355 memcpy(map, new_map, new_nr*sizeof(struct bfin_memmap_entry));
310 *pnr_map = new_nr; 356 *pnr_map = new_nr;
311 357
@@ -361,7 +407,6 @@ static __init int parse_memmap(char *arg)
361 * - "memmap=XXX[KkmM][@][$]XXX[KkmM]" defines a memory region 407 * - "memmap=XXX[KkmM][@][$]XXX[KkmM]" defines a memory region
362 * @ from <start> to <start>+<mem>, type RAM 408 * @ from <start> to <start>+<mem>, type RAM
363 * $ from <start> to <start>+<mem>, type RESERVED 409 * $ from <start> to <start>+<mem>, type RESERVED
364 *
365 */ 410 */
366static __init void parse_cmdline_early(char *cmdline_p) 411static __init void parse_cmdline_early(char *cmdline_p)
367{ 412{
@@ -383,12 +428,10 @@ static __init void parse_cmdline_early(char *cmdline_p)
383 if (*to != ' ') { 428 if (*to != ' ') {
384 if (*to == '$' 429 if (*to == '$'
385 || *(to + 1) == '$') 430 || *(to + 1) == '$')
386 reserved_mem_dcache_on = 431 reserved_mem_dcache_on = 1;
387 1;
388 if (*to == '#' 432 if (*to == '#'
389 || *(to + 1) == '#') 433 || *(to + 1) == '#')
390 reserved_mem_icache_on = 434 reserved_mem_icache_on = 1;
391 1;
392 } 435 }
393 } 436 }
394 } else if (!memcmp(to, "earlyprintk=", 12)) { 437 } else if (!memcmp(to, "earlyprintk=", 12)) {
@@ -417,9 +460,8 @@ static __init void parse_cmdline_early(char *cmdline_p)
417 * [_ramend - DMA_UNCACHED_REGION, 460 * [_ramend - DMA_UNCACHED_REGION,
418 * _ramend]: uncached DMA region 461 * _ramend]: uncached DMA region
419 * [_ramend, physical_mem_end]: memory not managed by kernel 462 * [_ramend, physical_mem_end]: memory not managed by kernel
420 *
421 */ 463 */
422static __init void memory_setup(void) 464static __init void memory_setup(void)
423{ 465{
424#ifdef CONFIG_MTD_UCLINUX 466#ifdef CONFIG_MTD_UCLINUX
425 unsigned long mtd_phys = 0; 467 unsigned long mtd_phys = 0;
@@ -436,7 +478,7 @@ static __init void memory_setup(void)
436 memory_end = _ramend - DMA_UNCACHED_REGION; 478 memory_end = _ramend - DMA_UNCACHED_REGION;
437 479
438#ifdef CONFIG_MPU 480#ifdef CONFIG_MPU
439 /* Round up to multiple of 4MB. */ 481 /* Round up to multiple of 4MB */
440 memory_start = (_ramstart + 0x3fffff) & ~0x3fffff; 482 memory_start = (_ramstart + 0x3fffff) & ~0x3fffff;
441#else 483#else
442 memory_start = PAGE_ALIGN(_ramstart); 484 memory_start = PAGE_ALIGN(_ramstart);
@@ -616,7 +658,7 @@ static __init void setup_bootmem_allocator(void)
616 end_pfn = memory_end >> PAGE_SHIFT; 658 end_pfn = memory_end >> PAGE_SHIFT;
617 659
618 /* 660 /*
619 * give all the memory to the bootmap allocator, tell it to put the 661 * give all the memory to the bootmap allocator, tell it to put the
620 * boot mem_map at the start of memory. 662 * boot mem_map at the start of memory.
621 */ 663 */
622 bootmap_size = init_bootmem_node(NODE_DATA(0), 664 bootmap_size = init_bootmem_node(NODE_DATA(0),
@@ -791,7 +833,11 @@ void __init setup_arch(char **cmdline_p)
791 bfin_write_SWRST(_bfin_swrst | DOUBLE_FAULT); 833 bfin_write_SWRST(_bfin_swrst | DOUBLE_FAULT);
792#endif 834#endif
793 835
836#ifdef CONFIG_SMP
837 if (_bfin_swrst & SWRST_DBL_FAULT_A) {
838#else
794 if (_bfin_swrst & RESET_DOUBLE) { 839 if (_bfin_swrst & RESET_DOUBLE) {
840#endif
795 printk(KERN_EMERG "Recovering from DOUBLE FAULT event\n"); 841 printk(KERN_EMERG "Recovering from DOUBLE FAULT event\n");
796#ifdef CONFIG_DEBUG_DOUBLEFAULT 842#ifdef CONFIG_DEBUG_DOUBLEFAULT
797 /* We assume the crashing kernel, and the current symbol table match */ 843 /* We assume the crashing kernel, and the current symbol table match */
@@ -835,7 +881,7 @@ void __init setup_arch(char **cmdline_p)
835 printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); 881 printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n");
836 882
837 printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n", 883 printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n",
838 cclk / 1000000, sclk / 1000000); 884 cclk / 1000000, sclk / 1000000);
839 885
840 if (ANOMALY_05000273 && (cclk >> 1) <= sclk) 886 if (ANOMALY_05000273 && (cclk >> 1) <= sclk)
841 printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n"); 887 printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n");
@@ -867,18 +913,21 @@ void __init setup_arch(char **cmdline_p)
867 BUG_ON((char *)&safe_user_instruction - (char *)&fixed_code_start 913 BUG_ON((char *)&safe_user_instruction - (char *)&fixed_code_start
868 != SAFE_USER_INSTRUCTION - FIXED_CODE_START); 914 != SAFE_USER_INSTRUCTION - FIXED_CODE_START);
869 915
916#ifdef CONFIG_SMP
917 platform_init_cpus();
918#endif
870 init_exception_vectors(); 919 init_exception_vectors();
871 bfin_cache_init(); 920 bfin_cache_init(); /* Initialize caches for the boot CPU */
872} 921}
873 922
874static int __init topology_init(void) 923static int __init topology_init(void)
875{ 924{
876 int cpu; 925 unsigned int cpu;
926 /* Record CPU-private information for the boot processor. */
927 bfin_setup_cpudata(0);
877 928
878 for_each_possible_cpu(cpu) { 929 for_each_possible_cpu(cpu) {
879 struct cpu *c = &per_cpu(cpu_devices, cpu); 930 register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu);
880
881 register_cpu(c, cpu);
882 } 931 }
883 932
884 return 0; 933 return 0;
@@ -983,15 +1032,15 @@ static int show_cpuinfo(struct seq_file *m, void *v)
983 char *cpu, *mmu, *fpu, *vendor, *cache; 1032 char *cpu, *mmu, *fpu, *vendor, *cache;
984 uint32_t revid; 1033 uint32_t revid;
985 1034
986 u_long cclk = 0, sclk = 0; 1035 u_long sclk = 0;
987 u_int icache_size = BFIN_ICACHESIZE / 1024, dcache_size = 0, dsup_banks = 0; 1036 u_int icache_size = BFIN_ICACHESIZE / 1024, dcache_size = 0, dsup_banks = 0;
1037 struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, *(unsigned int *)v);
988 1038
989 cpu = CPU; 1039 cpu = CPU;
990 mmu = "none"; 1040 mmu = "none";
991 fpu = "none"; 1041 fpu = "none";
992 revid = bfin_revid(); 1042 revid = bfin_revid();
993 1043
994 cclk = get_cclk();
995 sclk = get_sclk(); 1044 sclk = get_sclk();
996 1045
997 switch (bfin_read_CHIPID() & CHIPID_MANUFACTURE) { 1046 switch (bfin_read_CHIPID() & CHIPID_MANUFACTURE) {
@@ -1003,10 +1052,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
1003 break; 1052 break;
1004 } 1053 }
1005 1054
1006 seq_printf(m, "processor\t: %d\n" 1055 seq_printf(m, "processor\t: %d\n" "vendor_id\t: %s\n",
1007 "vendor_id\t: %s\n", 1056 *(unsigned int *)v, vendor);
1008 *(unsigned int *)v,
1009 vendor);
1010 1057
1011 if (CPUID == bfin_cpuid()) 1058 if (CPUID == bfin_cpuid())
1012 seq_printf(m, "cpu family\t: 0x%04x\n", CPUID); 1059 seq_printf(m, "cpu family\t: 0x%04x\n", CPUID);
@@ -1016,7 +1063,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
1016 1063
1017 seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" 1064 seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n"
1018 "stepping\t: %d\n", 1065 "stepping\t: %d\n",
1019 cpu, cclk/1000000, sclk/1000000, 1066 cpu, cpudata->cclk/1000000, sclk/1000000,
1020#ifdef CONFIG_MPU 1067#ifdef CONFIG_MPU
1021 "mpu on", 1068 "mpu on",
1022#else 1069#else
@@ -1025,16 +1072,16 @@ static int show_cpuinfo(struct seq_file *m, void *v)
1025 revid); 1072 revid);
1026 1073
1027 seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n", 1074 seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n",
1028 cclk/1000000, cclk%1000000, 1075 cpudata->cclk/1000000, cpudata->cclk%1000000,
1029 sclk/1000000, sclk%1000000); 1076 sclk/1000000, sclk%1000000);
1030 seq_printf(m, "bogomips\t: %lu.%02lu\n" 1077 seq_printf(m, "bogomips\t: %lu.%02lu\n"
1031 "Calibration\t: %lu loops\n", 1078 "Calibration\t: %lu loops\n",
1032 (loops_per_jiffy * HZ) / 500000, 1079 (cpudata->loops_per_jiffy * HZ) / 500000,
1033 ((loops_per_jiffy * HZ) / 5000) % 100, 1080 ((cpudata->loops_per_jiffy * HZ) / 5000) % 100,
1034 (loops_per_jiffy * HZ)); 1081 (cpudata->loops_per_jiffy * HZ));
1035 1082
1036 /* Check Cache configutation */ 1083 /* Check Cache configutation */
1037 switch (bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) { 1084 switch (cpudata->dmemctl & (1 << DMC0_P | 1 << DMC1_P)) {
1038 case ACACHE_BSRAM: 1085 case ACACHE_BSRAM:
1039 cache = "dbank-A/B\t: cache/sram"; 1086 cache = "dbank-A/B\t: cache/sram";
1040 dcache_size = 16; 1087 dcache_size = 16;
@@ -1058,10 +1105,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
1058 } 1105 }
1059 1106
1060 /* Is it turned on? */ 1107 /* Is it turned on? */
1061 if ((bfin_read_DMEM_CONTROL() & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE)) 1108 if ((cpudata->dmemctl & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE))
1062 dcache_size = 0; 1109 dcache_size = 0;
1063 1110
1064 if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) != (IMC | ENICPLB)) 1111 if ((cpudata->imemctl & (IMC | ENICPLB)) != (IMC | ENICPLB))
1065 icache_size = 0; 1112 icache_size = 0;
1066 1113
1067 seq_printf(m, "cache size\t: %d KB(L1 icache) " 1114 seq_printf(m, "cache size\t: %d KB(L1 icache) "
@@ -1086,8 +1133,13 @@ static int show_cpuinfo(struct seq_file *m, void *v)
1086 "dcache setup\t: %d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n", 1133 "dcache setup\t: %d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n",
1087 dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS, 1134 dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS,
1088 BFIN_DLINES); 1135 BFIN_DLINES);
1136#ifdef __ARCH_SYNC_CORE_DCACHE
1137 seq_printf(m,
1138 "SMP Dcache Flushes\t: %lu\n\n",
1139 per_cpu(cpu_data, *(unsigned int *)v).dcache_invld_count);
1140#endif
1089#ifdef CONFIG_BFIN_ICACHE_LOCK 1141#ifdef CONFIG_BFIN_ICACHE_LOCK
1090 switch ((bfin_read_IMEM_CONTROL() >> 3) & WAYALL_L) { 1142 switch ((cpudata->imemctl >> 3) & WAYALL_L) {
1091 case WAY0_L: 1143 case WAY0_L:
1092 seq_printf(m, "Way0 Locked-Down\n"); 1144 seq_printf(m, "Way0 Locked-Down\n");
1093 break; 1145 break;
@@ -1137,6 +1189,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
1137 seq_printf(m, "No Ways are locked\n"); 1189 seq_printf(m, "No Ways are locked\n");
1138 } 1190 }
1139#endif 1191#endif
1192 if (*(unsigned int *)v != NR_CPUS-1)
1193 return 0;
1194
1195#if L2_LENGTH
1196 seq_printf(m, "L2 SRAM\t\t: %dKB\n", L2_LENGTH/0x400);
1197#endif
1140 seq_printf(m, "board name\t: %s\n", bfin_board_name); 1198 seq_printf(m, "board name\t: %s\n", bfin_board_name);
1141 seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n", 1199 seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n",
1142 physical_mem_end >> 10, (void *)0, (void *)physical_mem_end); 1200 physical_mem_end >> 10, (void *)0, (void *)physical_mem_end);
@@ -1144,6 +1202,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
1144 ((int)memory_end - (int)_stext) >> 10, 1202 ((int)memory_end - (int)_stext) >> 10,
1145 _stext, 1203 _stext,
1146 (void *)memory_end); 1204 (void *)memory_end);
1205 seq_printf(m, "\n");
1147 1206
1148 return 0; 1207 return 0;
1149} 1208}
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index eb2352320454..06de2ce67a9e 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -34,9 +34,11 @@
34#include <linux/interrupt.h> 34#include <linux/interrupt.h>
35#include <linux/time.h> 35#include <linux/time.h>
36#include <linux/irq.h> 36#include <linux/irq.h>
37#include <linux/delay.h>
37 38
38#include <asm/blackfin.h> 39#include <asm/blackfin.h>
39#include <asm/time.h> 40#include <asm/time.h>
41#include <asm/gptimers.h>
40 42
41/* This is an NTP setting */ 43/* This is an NTP setting */
42#define TICK_SIZE (tick_nsec / 1000) 44#define TICK_SIZE (tick_nsec / 1000)
@@ -46,11 +48,14 @@ static unsigned long gettimeoffset(void);
46 48
47static struct irqaction bfin_timer_irq = { 49static struct irqaction bfin_timer_irq = {
48 .name = "BFIN Timer Tick", 50 .name = "BFIN Timer Tick",
51#ifdef CONFIG_IRQ_PER_CPU
52 .flags = IRQF_DISABLED | IRQF_PERCPU,
53#else
49 .flags = IRQF_DISABLED 54 .flags = IRQF_DISABLED
55#endif
50}; 56};
51 57
52static void 58void setup_core_timer(void)
53time_sched_init(irq_handler_t timer_routine)
54{ 59{
55 u32 tcount; 60 u32 tcount;
56 61
@@ -71,12 +76,41 @@ time_sched_init(irq_handler_t timer_routine)
71 CSYNC(); 76 CSYNC();
72 77
73 bfin_write_TCNTL(7); 78 bfin_write_TCNTL(7);
79}
80
81#ifdef CONFIG_TICK_SOURCE_SYSTMR0
82void setup_system_timer0(void)
83{
84 /* Power down the core timer, just to play safe. */
85 bfin_write_TCNTL(0);
86
87 disable_gptimers(TIMER0bit);
88 set_gptimer_status(0, TIMER_STATUS_TRUN0);
89 while (get_gptimer_status(0) & TIMER_STATUS_TRUN0)
90 udelay(10);
91
92 set_gptimer_config(0, 0x59); /* IRQ enable, periodic, PWM_OUT, SCLKed, OUT PAD disabled */
93 set_gptimer_period(TIMER0_id, get_sclk() / HZ);
94 set_gptimer_pwidth(TIMER0_id, 1);
95 SSYNC();
96 enable_gptimers(TIMER0bit);
97}
98#endif
74 99
100static void
101time_sched_init(irqreturn_t(*timer_routine) (int, void *))
102{
103#ifdef CONFIG_TICK_SOURCE_SYSTMR0
104 setup_system_timer0();
105#else
106 setup_core_timer();
107#endif
75 bfin_timer_irq.handler = (irq_handler_t)timer_routine; 108 bfin_timer_irq.handler = (irq_handler_t)timer_routine;
76 /* call setup_irq instead of request_irq because request_irq calls 109#ifdef CONFIG_TICK_SOURCE_SYSTMR0
77 * kmalloc which has not been initialized yet 110 setup_irq(IRQ_TIMER0, &bfin_timer_irq);
78 */ 111#else
79 setup_irq(IRQ_CORETMR, &bfin_timer_irq); 112 setup_irq(IRQ_CORETMR, &bfin_timer_irq);
113#endif
80} 114}
81 115
82/* 116/*
@@ -87,17 +121,23 @@ static unsigned long gettimeoffset(void)
87 unsigned long offset; 121 unsigned long offset;
88 unsigned long clocks_per_jiffy; 122 unsigned long clocks_per_jiffy;
89 123
124#ifdef CONFIG_TICK_SOURCE_SYSTMR0
125 clocks_per_jiffy = bfin_read_TIMER0_PERIOD();
126 offset = bfin_read_TIMER0_COUNTER() / \
127 (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC);
128
129 if ((get_gptimer_status(0) & TIMER_STATUS_TIMIL0) && offset < (100000 / HZ / 2))
130 offset += (USEC_PER_SEC / HZ);
131#else
90 clocks_per_jiffy = bfin_read_TPERIOD(); 132 clocks_per_jiffy = bfin_read_TPERIOD();
91 offset = 133 offset = (clocks_per_jiffy - bfin_read_TCOUNT()) / \
92 (clocks_per_jiffy - 134 (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC);
93 bfin_read_TCOUNT()) / (((clocks_per_jiffy + 1) * HZ) /
94 USEC_PER_SEC);
95 135
96 /* Check if we just wrapped the counters and maybe missed a tick */ 136 /* Check if we just wrapped the counters and maybe missed a tick */
97 if ((bfin_read_ILAT() & (1 << IRQ_CORETMR)) 137 if ((bfin_read_ILAT() & (1 << IRQ_CORETMR))
98 && (offset < (100000 / HZ / 2))) 138 && (offset < (100000 / HZ / 2)))
99 offset += (USEC_PER_SEC / HZ); 139 offset += (USEC_PER_SEC / HZ);
100 140#endif
101 return offset; 141 return offset;
102} 142}
103 143
@@ -120,34 +160,38 @@ irqreturn_t timer_interrupt(int irq, void *dummy)
120 static long last_rtc_update; 160 static long last_rtc_update;
121 161
122 write_seqlock(&xtime_lock); 162 write_seqlock(&xtime_lock);
123 163#ifdef CONFIG_TICK_SOURCE_SYSTMR0
124 do_timer(1); 164 if (get_gptimer_status(0) & TIMER_STATUS_TIMIL0) {
125 165#endif
126 profile_tick(CPU_PROFILING); 166 do_timer(1);
127 167
128 /* 168
129 * If we have an externally synchronized Linux clock, then update 169 /*
130 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be 170 * If we have an externally synchronized Linux clock, then update
131 * called as close as possible to 500 ms before the new second starts. 171 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
132 */ 172 * called as close as possible to 500 ms before the new second starts.
133 173 */
134 if (ntp_synced() && 174
135 xtime.tv_sec > last_rtc_update + 660 && 175 if (ntp_synced() &&
136 (xtime.tv_nsec / NSEC_PER_USEC) >= 176 xtime.tv_sec > last_rtc_update + 660 &&
137 500000 - ((unsigned)TICK_SIZE) / 2 177 (xtime.tv_nsec / NSEC_PER_USEC) >=
138 && (xtime.tv_nsec / NSEC_PER_USEC) <= 178 500000 - ((unsigned)TICK_SIZE) / 2
139 500000 + ((unsigned)TICK_SIZE) / 2) { 179 && (xtime.tv_nsec / NSEC_PER_USEC) <=
140 if (set_rtc_mmss(xtime.tv_sec) == 0) 180 500000 + ((unsigned)TICK_SIZE) / 2) {
141 last_rtc_update = xtime.tv_sec; 181 if (set_rtc_mmss(xtime.tv_sec) == 0)
142 else 182 last_rtc_update = xtime.tv_sec;
143 /* Do it again in 60s. */ 183 else
144 last_rtc_update = xtime.tv_sec - 600; 184 /* Do it again in 60s. */
185 last_rtc_update = xtime.tv_sec - 600;
186 }
187#ifdef CONFIG_TICK_SOURCE_SYSTMR0
188 set_gptimer_status(0, TIMER_STATUS_TIMIL0);
145 } 189 }
190#endif
146 write_sequnlock(&xtime_lock); 191 write_sequnlock(&xtime_lock);
147 192
148#ifndef CONFIG_SMP
149 update_process_times(user_mode(get_irq_regs())); 193 update_process_times(user_mode(get_irq_regs()));
150#endif 194 profile_tick(CPU_PROFILING);
151 195
152 return IRQ_HANDLED; 196 return IRQ_HANDLED;
153} 197}
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index bef025b07443..af7cc43630de 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -75,16 +75,6 @@ void __init trap_init(void)
75 CSYNC(); 75 CSYNC();
76} 76}
77 77
78/*
79 * Used to save the RETX, SEQSTAT, I/D CPLB FAULT ADDR
80 * values across the transition from exception to IRQ5.
81 * We put these in L1, so they are going to be in a valid
82 * location during exception context
83 */
84__attribute__((l1_data))
85unsigned long saved_retx, saved_seqstat,
86 saved_icplb_fault_addr, saved_dcplb_fault_addr;
87
88static void decode_address(char *buf, unsigned long address) 78static void decode_address(char *buf, unsigned long address)
89{ 79{
90#ifdef CONFIG_DEBUG_VERBOSE 80#ifdef CONFIG_DEBUG_VERBOSE
@@ -211,18 +201,18 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
211 printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); 201 printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
212#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT 202#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
213 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { 203 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) {
204 unsigned int cpu = smp_processor_id();
214 char buf[150]; 205 char buf[150];
215 decode_address(buf, saved_retx); 206 decode_address(buf, cpu_pda[cpu].retx);
216 printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n", 207 printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
217 (int)saved_seqstat & SEQSTAT_EXCAUSE, buf); 208 (unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf);
218 decode_address(buf, saved_dcplb_fault_addr); 209 decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
219 printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf); 210 printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf);
220 decode_address(buf, saved_icplb_fault_addr); 211 decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
221 printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf); 212 printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf);
222 213
223 decode_address(buf, fp->retx); 214 decode_address(buf, fp->retx);
224 printk(KERN_NOTICE "The instruction at %s caused a double exception\n", 215 printk(KERN_NOTICE "The instruction at %s caused a double exception\n", buf);
225 buf);
226 } else 216 } else
227#endif 217#endif
228 { 218 {
@@ -240,6 +230,9 @@ asmlinkage void trap_c(struct pt_regs *fp)
240#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON 230#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
241 int j; 231 int j;
242#endif 232#endif
233#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
234 unsigned int cpu = smp_processor_id();
235#endif
243 int sig = 0; 236 int sig = 0;
244 siginfo_t info; 237 siginfo_t info;
245 unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; 238 unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
@@ -417,7 +410,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
417 info.si_code = ILL_CPLB_MULHIT; 410 info.si_code = ILL_CPLB_MULHIT;
418 sig = SIGSEGV; 411 sig = SIGSEGV;
419#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO 412#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
420 if (saved_dcplb_fault_addr < FIXED_CODE_START) 413 if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START)
421 verbose_printk(KERN_NOTICE "NULL pointer access\n"); 414 verbose_printk(KERN_NOTICE "NULL pointer access\n");
422 else 415 else
423#endif 416#endif
@@ -471,7 +464,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
471 info.si_code = ILL_CPLB_MULHIT; 464 info.si_code = ILL_CPLB_MULHIT;
472 sig = SIGSEGV; 465 sig = SIGSEGV;
473#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO 466#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
474 if (saved_icplb_fault_addr < FIXED_CODE_START) 467 if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START)
475 verbose_printk(KERN_NOTICE "Jump to NULL address\n"); 468 verbose_printk(KERN_NOTICE "Jump to NULL address\n");
476 else 469 else
477#endif 470#endif
@@ -960,6 +953,7 @@ void dump_bfin_process(struct pt_regs *fp)
960 else 953 else
961 verbose_printk(KERN_NOTICE "COMM= invalid\n"); 954 verbose_printk(KERN_NOTICE "COMM= invalid\n");
962 955
956 printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu);
963 if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START) 957 if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
964 verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" 958 verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
965 KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n" 959 KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n"
@@ -1053,6 +1047,7 @@ void show_regs(struct pt_regs *fp)
1053 struct irqaction *action; 1047 struct irqaction *action;
1054 unsigned int i; 1048 unsigned int i;
1055 unsigned long flags; 1049 unsigned long flags;
1050 unsigned int cpu = smp_processor_id();
1056 1051
1057 verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); 1052 verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
1058 verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", 1053 verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n",
@@ -1112,9 +1107,9 @@ unlock:
1112 1107
1113 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) && 1108 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) &&
1114 (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) { 1109 (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
1115 decode_address(buf, saved_dcplb_fault_addr); 1110 decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
1116 verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); 1111 verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
1117 decode_address(buf, saved_icplb_fault_addr); 1112 decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
1118 verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); 1113 verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
1119 } 1114 }
1120 1115
@@ -1153,20 +1148,21 @@ unlock:
1153asmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text)); 1148asmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text));
1154#endif 1149#endif
1155 1150
1156asmlinkage int sys_bfin_spinlock(int *spinlock) 1151static DEFINE_SPINLOCK(bfin_spinlock_lock);
1152
1153asmlinkage int sys_bfin_spinlock(int *p)
1157{ 1154{
1158 int ret = 0; 1155 int ret, tmp = 0;
1159 int tmp = 0;
1160 1156
1161 local_irq_disable(); 1157 spin_lock(&bfin_spinlock_lock); /* This would also hold kernel preemption. */
1162 ret = get_user(tmp, spinlock); 1158 ret = get_user(tmp, p);
1163 if (ret == 0) { 1159 if (likely(ret == 0)) {
1164 if (tmp) 1160 if (unlikely(tmp))
1165 ret = 1; 1161 ret = 1;
1166 tmp = 1; 1162 else
1167 put_user(tmp, spinlock); 1163 put_user(1, p);
1168 } 1164 }
1169 local_irq_enable(); 1165 spin_unlock(&bfin_spinlock_lock);
1170 return ret; 1166 return ret;
1171} 1167}
1172 1168