From f940260a980a1ad7570dfd7a4b73c6ad2207f738 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 27 Oct 2008 18:17:41 +0800 Subject: Blackfin arch: unify duplicated bss init code Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/head.S | 66 ++++++++++++---------------------------- 1 file changed, 19 insertions(+), 47 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index f123a62..42ee2b1 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S @@ -195,6 +195,19 @@ ENDPROC(__start) # define WDOG_CTL WDOGA_CTL #endif +ENTRY(__init_clear_bss) + r2 = r2 - r1; + cc = r2 == 0; + if cc jump .L_bss_done; + r2 >>= 2; + p1 = r1; + p2 = r2; + lsetup (1f, 1f) lc0 = p2; +1: [p1++] = r0; +.L_bss_done: + rts; +ENDPROC(__init_clear_bss) + ENTRY(_real_start) /* Enable nested interrupts */ [--sp] = reti; @@ -206,75 +219,34 @@ ENTRY(_real_start) w[p0] = r0; ssync; + r0 = 0 (x); + /* Zero out all of the fun bss regions */ #if L1_DATA_A_LENGTH > 0 r1.l = __sbss_l1; r1.h = __sbss_l1; r2.l = __ebss_l1; r2.h = __ebss_l1; - r0 = 0 (z); - r2 = r2 - r1; - cc = r2 == 0; - if cc jump .L_a_l1_done; - r2 >>= 2; - p1 = r1; - p2 = r2; - lsetup (.L_clear_a_l1, .L_clear_a_l1 ) lc0 = p2; -.L_clear_a_l1: - [p1++] = r0; -.L_a_l1_done: + call __init_clear_bss #endif - #if L1_DATA_B_LENGTH > 0 r1.l = __sbss_b_l1; r1.h = __sbss_b_l1; r2.l = __ebss_b_l1; r2.h = __ebss_b_l1; - r0 = 0 (z); - r2 = r2 - r1; - cc = r2 == 0; - if cc jump .L_b_l1_done; - r2 >>= 2; - p1 = r1; - p2 = r2; - lsetup (.L_clear_b_l1, .L_clear_b_l1 ) lc0 = p2; -.L_clear_b_l1: - [p1++] = r0; -.L_b_l1_done: + call __init_clear_bss #endif - #if L2_LENGTH > 0 r1.l = __sbss_l2; r1.h = __sbss_l2; r2.l = __ebss_l2; r2.h = __ebss_l2; - r0 = 0 (z); - r2 = r2 - r1; - cc = r2 == 0; - if cc jump .L_l2_done; - r2 >>= 2; - p1 = r1; - p2 = r2; - lsetup (.L_clear_l2, .L_clear_l2 ) lc0 = p2; -.L_clear_l2: - [p1++] = r0; -.L_l2_done: + call __init_clear_bss #endif - - /* Zero out the bss region - * Note: this will fail if bss is 0 bytes ... - */ - r0 = 0 (z); r1.l = ___bss_start; r1.h = ___bss_start; r2.l = ___bss_stop; r2.h = ___bss_stop; - r2 = r2 - r1; - r2 >>= 2; - p1 = r1; - p2 = r2; - lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2; -.L_clear_bss: - [p1++] = r0; + call __init_clear_bss /* In case there is a NULL pointer reference, * zero out region before stext -- cgit v1.1 From dc26aec25d1a4e2690df166dbe843344728994ce Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: BF538/9 Linux kernel Support Add supporing for Blackfin BF538 and BF539 processors. Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/dpmc_modes.S | 3 ++- arch/blackfin/mach-common/ints-priority.c | 20 ++++++++++++++------ arch/blackfin/mach-common/pm.c | 3 ++- 3 files changed, 18 insertions(+), 8 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S index ad5431e..21f6160 100644 --- a/arch/blackfin/mach-common/dpmc_modes.S +++ b/arch/blackfin/mach-common/dpmc_modes.S @@ -247,7 +247,8 @@ ENTRY(_unset_dram_srfs) ENDPROC(_unset_dram_srfs) ENTRY(_set_sic_iwr) -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || \ + defined(CONFIG_BF538) || defined(CONFIG_BF539) P0.H = hi(SIC_IWR0); P0.L = lo(SIC_IWR0); P1.H = hi(SIC_IWR1); diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 34e8a72..67700e6 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -103,12 +103,13 @@ static void __init search_IAR(void) for (irqn = 0; irqn < NR_PERI_INTS; irqn++) { int iar_shift = (irqn & 7) * 4; if (ivg == (0xf & -#ifndef CONFIG_BF52x +#if defined(CONFIG_BF52x) || defined(CONFIG_BF538) || defined(CONFIG_BF539) bfin_read32((unsigned long *)SIC_IAR0 + - (irqn >> 3)) >> iar_shift)) { + ((irqn % 32) >> 3) + ((irqn / 32) * + ((SIC_IAR4 - SIC_IAR0) / 4))) >> iar_shift)) { #else bfin_read32((unsigned long *)SIC_IAR0 + - ((irqn%32) >> 3) + ((irqn / 32) * 16)) >> iar_shift)) { + (irqn >> 3)) >> iar_shift)) { #endif ivg_table[irq_pos].irqno = IVG7 + irqn; ivg_table[irq_pos].isrflag = 1 << (irqn % 32); @@ -537,6 +538,10 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq, irq = IRQ_PH0; break; # endif +#elif defined(CONFIG_BF538) || defined(CONFIG_BF539) + case IRQ_PORTF_INTA: + irq = IRQ_PF0; + break; #elif defined(CONFIG_BF52x) case IRQ_PORTF_INTA: irq = IRQ_PF0; @@ -984,7 +989,7 @@ int __init init_arch_irq(void) int irq; unsigned long ilat = 0; /* Disable all the peripheral intrs - page 4-29 HW Ref manual */ -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || defined(BF538_FAMILY) bfin_write_SIC_IMASK0(SIC_UNMASK_ALL); bfin_write_SIC_IMASK1(SIC_UNMASK_ALL); # ifdef CONFIG_BF54x @@ -1037,7 +1042,10 @@ int __init init_arch_irq(void) case IRQ_PROG0_INTA: case IRQ_PROG1_INTA: case IRQ_PROG2_INTA: +#elif defined(CONFIG_BF538) || defined(CONFIG_BF539) + case IRQ_PORTF_INTA: #endif + set_irq_chained_handler(irq, bfin_demux_gpio_irq); break; @@ -1085,7 +1093,7 @@ int __init init_arch_irq(void) IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || defined(BF538_FAMILY) bfin_write_SIC_IWR0(IWR_DISABLE_ALL); #if defined(CONFIG_BF52x) /* BF52x system reset does not properly reset SIC_IWR1 which @@ -1117,7 +1125,7 @@ void do_irq(int vec, struct pt_regs *fp) } else { struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst; struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop; -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || defined(BF538_FAMILY) unsigned long sic_status[3]; sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0(); diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index e28c6af..f774d8a 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -82,7 +82,8 @@ void bfin_pm_suspend_standby_enter(void) bfin_pm_standby_restore(); -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || \ + defined(CONFIG_BF538) || defined(CONFIG_BF539) bfin_write_SIC_IWR0(IWR_DISABLE_ALL); #if defined(CONFIG_BF52x) /* BF52x system reset does not properly reset SIC_IWR1 which -- cgit v1.1 From fe8015ce2588e3ffe65284a2883703355804276e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 28 Oct 2008 11:07:15 +0800 Subject: Blackfin arch: move EXPORT_SYMBOL to the place where it is actually defined - kernel_thread - irq_flags - checksum Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/ints-priority.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 67700e6..5ae507f 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -65,6 +65,7 @@ * cannot actually mask out in hardware. */ unsigned long irq_flags = 0x1f; +EXPORT_SYMBOL(irq_flags); /* The number of spurious interrupts */ atomic_t num_spurious; -- cgit v1.1 From 6ad2b84cf014d91a9dffa3f8edb008430fbdb445 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 28 Oct 2008 11:03:09 +0800 Subject: Blackfin arch: add an option to allow people to stick exception stack into L1 scratch allow people to stick exception stack into L1 scratch and make sure it gets placed into .bss sections rather than .data Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/entry.S | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index bde6dc4..ad40498 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -1539,14 +1539,23 @@ ENTRY(_sys_call_table) .endr END(_sys_call_table) -_exception_stack: - .rept 1024 - .long 0; - .endr -_exception_stack_top: - #if ANOMALY_05000261 /* Used by the assembly entry point to work around an anomaly. */ _last_cplb_fault_retx: .long 0; #endif + +#ifdef CONFIG_EXCEPTION_L1_SCRATCH +/* .section .l1.bss.scratch */ +.set _exception_stack_top, L1_SCRATCH_START + L1_SCRATCH_LENGTH +#else +#ifdef CONFIG_SYSCALL_TAB_L1 +.section .l1.bss +#else +.bss +#endif +_exception_stack: +.size _exception_stack, 1024 * 4 +.set _exception_stack_top, _exception_stack + 1024 * 4 +.size _exception_stack_top, 0 +#endif -- cgit v1.1 From efe065a1b39974ff2bbb9aa693400f3de4ba5a6a Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Tue, 28 Oct 2008 14:00:52 +0800 Subject: Blackfin arch: fix bug - kernel with SMP patch can not bootup The original code defined _exception_stack but not alloc space for the exception stack. In exception, this area is over written by exception stack. Common kernel luckly boot up, but SMP kernel stuck. Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/entry.S | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index ad40498..c6ae844 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -1555,7 +1555,8 @@ _last_cplb_fault_retx: .bss #endif _exception_stack: -.size _exception_stack, 1024 * 4 -.set _exception_stack_top, _exception_stack + 1024 * 4 -.size _exception_stack_top, 0 + .rept 1024 + .long 0 + .endr +_exception_stack_top: #endif -- cgit v1.1 From 2f6f4bcdd611cb968b800f7569c4383727856668 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Tue, 18 Nov 2008 17:48:21 +0800 Subject: Blackfin arch: add support for Blackfin latest processor family BF51x Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/dpmc_modes.S | 2 +- arch/blackfin/mach-common/ints-priority.c | 20 ++++++++++++-------- arch/blackfin/mach-common/pm.c | 4 ++-- 3 files changed, 15 insertions(+), 11 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S index 21f6160..4da50bc 100644 --- a/arch/blackfin/mach-common/dpmc_modes.S +++ b/arch/blackfin/mach-common/dpmc_modes.S @@ -248,7 +248,7 @@ ENDPROC(_unset_dram_srfs) ENTRY(_set_sic_iwr) #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || \ - defined(CONFIG_BF538) || defined(CONFIG_BF539) + defined(CONFIG_BF538) || defined(CONFIG_BF539) || defined(CONFIG_BF51x) P0.H = hi(SIC_IWR0); P0.L = lo(SIC_IWR0); P1.H = hi(SIC_IWR1); diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 5ae507f..c32fa69 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -104,7 +104,8 @@ static void __init search_IAR(void) for (irqn = 0; irqn < NR_PERI_INTS; irqn++) { int iar_shift = (irqn & 7) * 4; if (ivg == (0xf & -#if defined(CONFIG_BF52x) || defined(CONFIG_BF538) || defined(CONFIG_BF539) +#if defined(CONFIG_BF52x) || defined(CONFIG_BF538) \ + || defined(CONFIG_BF539) || defined(CONFIG_BF51x) bfin_read32((unsigned long *)SIC_IAR0 + ((irqn % 32) >> 3) + ((irqn / 32) * ((SIC_IAR4 - SIC_IAR0) / 4))) >> iar_shift)) { @@ -543,7 +544,7 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq, case IRQ_PORTF_INTA: irq = IRQ_PF0; break; -#elif defined(CONFIG_BF52x) +#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) case IRQ_PORTF_INTA: irq = IRQ_PF0; break; @@ -990,7 +991,8 @@ int __init init_arch_irq(void) int irq; unsigned long ilat = 0; /* Disable all the peripheral intrs - page 4-29 HW Ref manual */ -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || defined(BF538_FAMILY) +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \ + || defined(BF538_FAMILY) || defined(CONFIG_BF51x) bfin_write_SIC_IMASK0(SIC_UNMASK_ALL); bfin_write_SIC_IMASK1(SIC_UNMASK_ALL); # ifdef CONFIG_BF54x @@ -1035,7 +1037,7 @@ int __init init_arch_irq(void) case IRQ_PINT1: case IRQ_PINT2: case IRQ_PINT3: -#elif defined(CONFIG_BF52x) +#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) case IRQ_PORTF_INTA: case IRQ_PORTG_INTA: case IRQ_PORTH_INTA: @@ -1094,10 +1096,11 @@ int __init init_arch_irq(void) IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || defined(BF538_FAMILY) +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \ + || defined(BF538_FAMILY) || defined(CONFIG_BF51x) bfin_write_SIC_IWR0(IWR_DISABLE_ALL); -#if defined(CONFIG_BF52x) - /* BF52x system reset does not properly reset SIC_IWR1 which +#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x) + /* BF52x/BF51x system reset does not properly reset SIC_IWR1 which * will screw up the bootrom as it relies on MDMA0/1 waking it * up from IDLE instructions. See this report for more info: * http://blackfin.uclinux.org/gf/tracker/4323 @@ -1126,7 +1129,8 @@ void do_irq(int vec, struct pt_regs *fp) } else { struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst; struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop; -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || defined(BF538_FAMILY) +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \ + || defined(BF538_FAMILY) || defined(CONFIG_BF51x) unsigned long sic_status[3]; sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0(); diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index f774d8a..ee33a8a 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -83,9 +83,9 @@ void bfin_pm_suspend_standby_enter(void) bfin_pm_standby_restore(); #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || \ - defined(CONFIG_BF538) || defined(CONFIG_BF539) + defined(CONFIG_BF538) || defined(CONFIG_BF539) || defined(CONFIG_BF51x) bfin_write_SIC_IWR0(IWR_DISABLE_ALL); -#if defined(CONFIG_BF52x) +#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x) /* BF52x system reset does not properly reset SIC_IWR1 which * will screw up the bootrom as it relies on MDMA0/1 waking it * up from IDLE instructions. See this report for more info: -- cgit v1.1 From 2cf851137b55cd0c49fd9e005cd01ac4761c005e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 28 Oct 2008 16:34:42 +0800 Subject: Blackfin arch: only add IFLUSH nop padding when anomaly 443 is enabled Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/cache.S | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S index a028e94..3c98dac 100644 --- a/arch/blackfin/mach-common/cache.S +++ b/arch/blackfin/mach-common/cache.S @@ -49,13 +49,17 @@ .ifnb \optflushins \optflushins [P0]; .endif +#if ANOMALY_05000443 .ifb \optnopins 2: .endif \flushins [P0++]; .ifnb \optnopins -2: \optnopins; +2: \optnopins; .endif +#else +2: \flushins [P0++]; +#endif RTS; .endm -- cgit v1.1 From c2414bd0b19e22632835cbd2686cf4103038cf3a Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: use sti to set the mask rather than banging on imask Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/head.S | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index 42ee2b1..29cd019 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S @@ -170,12 +170,8 @@ ENTRY(__start) [p0] = p1; csync; - p0.l = lo(IMASK); - p0.h = hi(IMASK); - p1.l = IMASK_IVG15; - p1.h = 0x0; - [p0] = p1; - csync; + r0 = EVT_IVG15 (z); + sti r0; raise 15; p0.l = .LWAIT_HERE; -- cgit v1.1 From 9f20cf2527fdbd5ee942ac87acff253d391b162f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: do not bother initializing the first 4k our kernel should be sane now, and we want to catch NULL bugs, not ignore them Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/head.S | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index 29cd019..c1dcaeb 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S @@ -244,18 +244,6 @@ ENTRY(_real_start) r2.h = ___bss_stop; call __init_clear_bss - /* In case there is a NULL pointer reference, - * zero out region before stext - */ - p1 = r0; - r2.l = __stext; - r2.h = __stext; - r2 >>= 2; - p2 = r2; - lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2; -.L_clear_zero: - [p1++] = r0; - /* Pass the u-boot arguments to the global value command line */ R0 = R7; call _cmdline_init; -- cgit v1.1 From 397861cd8046549957a04d34a0b97b267cbb9589 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: fix bug - gpio_bank() macros messed up bank number caculating with positioning a gpio The whole story: Before BF51x merged, all the MAX_BLACKFIN_GPIOS are integral multiple of GPIO_BANKSIZE (= 16). But BF51x provides MAX_BLACKFIN_GPIOS = 40 which includes 3 banks and the 3rd bank has only 8 GPIO pins. Therefore, gpio_bank() macros is correct when you try to find a GPIO in which bank (GPIO_35 is in bank 2). But on BF51x gpio_bank(MAX_BLACKFIN_GPIOS) only gives out 2 banks instead of 3 banks for some static array initialization. This patch add a new macros gpio_bank_n() and GPIO_BANK_NUM to do bank number caculating and remain the gpio_bank() macros for positioning a gpio in which bank. Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/ints-priority.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index c32fa69..5b374ff 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -377,8 +377,8 @@ static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle) #if !defined(CONFIG_BF54x) -static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; -static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)]; +static unsigned short gpio_enabled[GPIO_BANK_NUM]; +static unsigned short gpio_edge_triggered[GPIO_BANK_NUM]; extern void bfin_gpio_irq_prepare(unsigned gpio); @@ -620,7 +620,7 @@ static unsigned char irq2pint_lut[NR_PINTS]; static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS]; static unsigned int gpio_both_edge_triggered[NR_PINT_SYS_IRQS]; -static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; +static unsigned short gpio_enabled[GPIO_BANK_NUM]; struct pin_int_t { -- cgit v1.1 From c6db04a78ac21e13aa1be17da73732355d07b2ba Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: remove useless SSYNC() in irq priority code - remove SSYNC() left over from irq init split - do not force SSYNC() when masking/unmasking IRQs in the SIC as any order enforced by the hardware should already be enforced by software Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/ints-priority.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 5b374ff..25ad25e 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -167,7 +167,6 @@ static void bfin_internal_mask_irq(unsigned int irq) bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) & ~(1 << mask_bit)); #endif - SSYNC(); } static void bfin_internal_unmask_irq(unsigned int irq) @@ -182,7 +181,6 @@ static void bfin_internal_unmask_irq(unsigned int irq) bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) | (1 << mask_bit)); #endif - SSYNC(); } #ifdef CONFIG_PM @@ -960,8 +958,6 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq, void __init init_exception_vectors(void) { - SSYNC(); - /* cannot program in software: * evt0 - emulation (jtag) * evt1 - reset -- cgit v1.1 From 8d0223744f531168d4ae87f33354d12a50402779 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: Cleanup and unify Blackfin IRQ and GPIO IRQ handling - Remove SSYNC() - Use irq_to_gpio where applicable - Remove gpio_edge_triggered bitfield, check irq_desc fields instead. - Remove gpio_both_edge_triggeredb bitfield, check irq_desc fields instead. - Use BITMAP and bitops on gpio_enabled - Preferably use 32-bit - Looking at the disassembly this indeed saves quite a few instructions. Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/ints-priority.c | 191 +++++++++++------------------- 1 file changed, 66 insertions(+), 125 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 25ad25e..d45d0c5 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -1,9 +1,6 @@ /* * File: arch/blackfin/mach-common/ints-priority.c - * Based on: - * Author: * - * Created: ? * Description: Set up the interrupt priorities * * Modified: @@ -186,7 +183,7 @@ static void bfin_internal_unmask_irq(unsigned int irq) #ifdef CONFIG_PM int bfin_internal_set_wake(unsigned int irq, unsigned int state) { - unsigned bank, bit, wakeup = 0; + u32 bank, bit, wakeup = 0; unsigned long flags; bank = SIC_SYSIRQ(irq) / 32; bit = SIC_SYSIRQ(irq) % 32; @@ -293,8 +290,6 @@ static void bfin_demux_error_irq(unsigned int int_err_irq, { int irq = 0; - SSYNC(); - #if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) if (bfin_read_EMAC_SYSTAT() & EMAC_ERR_MASK) irq = IRQ_MAC_ERROR; @@ -373,56 +368,47 @@ static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle) desc->handle_irq = handle; } -#if !defined(CONFIG_BF54x) - -static unsigned short gpio_enabled[GPIO_BANK_NUM]; -static unsigned short gpio_edge_triggered[GPIO_BANK_NUM]; - +static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS); extern void bfin_gpio_irq_prepare(unsigned gpio); +#if !defined(CONFIG_BF54x) + static void bfin_gpio_ack_irq(unsigned int irq) { - u16 gpionr = irq - IRQ_PF0; - - if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) { - set_gpio_data(gpionr, 0); - SSYNC(); - } + /* AFAIK ack_irq in case mask_ack is provided + * get's only called for edge sense irqs + */ + set_gpio_data(irq_to_gpio(irq), 0); } static void bfin_gpio_mask_ack_irq(unsigned int irq) { - u16 gpionr = irq - IRQ_PF0; + struct irq_desc *desc = irq_desc + irq; + u32 gpionr = irq_to_gpio(irq); - if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) { + if (desc->handle_irq == handle_edge_irq) set_gpio_data(gpionr, 0); - SSYNC(); - } set_gpio_maska(gpionr, 0); - SSYNC(); } static void bfin_gpio_mask_irq(unsigned int irq) { - set_gpio_maska(irq - IRQ_PF0, 0); - SSYNC(); + set_gpio_maska(irq_to_gpio(irq), 0); } static void bfin_gpio_unmask_irq(unsigned int irq) { - set_gpio_maska(irq - IRQ_PF0, 1); - SSYNC(); + set_gpio_maska(irq_to_gpio(irq), 1); } static unsigned int bfin_gpio_irq_startup(unsigned int irq) { - u16 gpionr = irq - IRQ_PF0; + u32 gpionr = irq_to_gpio(irq); - if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) + if (__test_and_set_bit(gpionr, gpio_enabled)) bfin_gpio_irq_prepare(gpionr); - gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); bfin_gpio_unmask_irq(irq); return 0; @@ -431,28 +417,28 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq) static void bfin_gpio_irq_shutdown(unsigned int irq) { bfin_gpio_mask_irq(irq); - gpio_enabled[gpio_bank(irq - IRQ_PF0)] &= ~gpio_bit(irq - IRQ_PF0); + __clear_bit(irq_to_gpio(irq), gpio_enabled); } static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) { - u16 gpionr = irq - IRQ_PF0; + u32 gpionr = irq_to_gpio(irq); if (type == IRQ_TYPE_PROBE) { /* only probe unenabled GPIO interrupt lines */ - if (gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)) + if (__test_bit(gpionr, gpio_enabled)) return 0; type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; } if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { - if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) + + if (__test_and_set_bit(gpionr, gpio_enabled)) bfin_gpio_irq_prepare(gpionr); - gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); } else { - gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); + __clear_bit(gpionr, gpio_enabled); return 0; } @@ -473,17 +459,13 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { set_gpio_edge(gpionr, 1); set_gpio_inen(gpionr, 1); - gpio_edge_triggered[gpio_bank(gpionr)] |= gpio_bit(gpionr); set_gpio_data(gpionr, 0); } else { set_gpio_edge(gpionr, 0); - gpio_edge_triggered[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); set_gpio_inen(gpionr, 1); } - SSYNC(); - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) bfin_set_irq_handler(irq, handle_edge_irq); else @@ -506,22 +488,6 @@ int bfin_gpio_set_wake(unsigned int irq, unsigned int state) } #endif -static struct irq_chip bfin_gpio_irqchip = { - .name = "GPIO", - .ack = bfin_gpio_ack_irq, - .mask = bfin_gpio_mask_irq, - .mask_ack = bfin_gpio_mask_ack_irq, - .unmask = bfin_gpio_unmask_irq, - .disable = bfin_gpio_mask_irq, - .enable = bfin_gpio_unmask_irq, - .set_type = bfin_gpio_irq_type, - .startup = bfin_gpio_irq_startup, - .shutdown = bfin_gpio_irq_shutdown, -#ifdef CONFIG_PM - .set_wake = bfin_gpio_set_wake, -#endif -}; - static void bfin_demux_gpio_irq(unsigned int inta_irq, struct irq_desc *desc) { @@ -572,9 +538,7 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq, for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { irq += i; - mask = get_gpiop_data(i) & - (gpio_enabled[gpio_bank(i)] & - get_gpiop_maska(i)); + mask = get_gpiop_data(i) & get_gpiop_maska(i); while (mask) { if (mask & 1) { @@ -587,9 +551,7 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq, } } else { gpio = irq_to_gpio(irq); - mask = get_gpiop_data(gpio) & - (gpio_enabled[gpio_bank(gpio)] & - get_gpiop_maska(gpio)); + mask = get_gpiop_data(gpio) & get_gpiop_maska(gpio); do { if (mask & 1) { @@ -617,10 +579,6 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq, static unsigned char irq2pint_lut[NR_PINTS]; static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS]; -static unsigned int gpio_both_edge_triggered[NR_PINT_SYS_IRQS]; -static unsigned short gpio_enabled[GPIO_BANK_NUM]; - - struct pin_int_t { unsigned int mask_set; unsigned int mask_clear; @@ -641,12 +599,9 @@ static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = { (struct pin_int_t *)PINT3_MASK_SET, }; -extern void bfin_gpio_irq_prepare(unsigned gpio); - -inline unsigned short get_irq_base(u8 bank, u8 bmap) +inline unsigned int get_irq_base(u32 bank, u8 bmap) { - - u16 irq_base; + unsigned int irq_base; if (bank < 2) { /*PA-PB */ irq_base = IRQ_PA0 + bmap * 16; @@ -655,7 +610,6 @@ inline unsigned short get_irq_base(u8 bank, u8 bmap) } return irq_base; - } /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */ @@ -682,20 +636,18 @@ void init_pint_lut(void) pint2irq_lut[bit_pos] = irq_base - SYS_IRQS; irq2pint_lut[irq_base - SYS_IRQS] = bit_pos; - } - } - } static void bfin_gpio_ack_irq(unsigned int irq) { - u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + struct irq_desc *desc = irq_desc + irq; + u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; u32 pintbit = PINT_BIT(pint_val); - u8 bank = PINT_2_BANK(pint_val); + u32 bank = PINT_2_BANK(pint_val); - if (unlikely(gpio_both_edge_triggered[bank] & pintbit)) { + if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { if (pint[bank]->invert_set & pintbit) pint[bank]->invert_clear = pintbit; else @@ -703,16 +655,16 @@ static void bfin_gpio_ack_irq(unsigned int irq) } pint[bank]->request = pintbit; - SSYNC(); } static void bfin_gpio_mask_ack_irq(unsigned int irq) { - u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + struct irq_desc *desc = irq_desc + irq; + u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; u32 pintbit = PINT_BIT(pint_val); - u8 bank = PINT_2_BANK(pint_val); + u32 bank = PINT_2_BANK(pint_val); - if (unlikely(gpio_both_edge_triggered[bank] & pintbit)) { + if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { if (pint[bank]->invert_set & pintbit) pint[bank]->invert_clear = pintbit; else @@ -721,32 +673,29 @@ static void bfin_gpio_mask_ack_irq(unsigned int irq) pint[bank]->request = pintbit; pint[bank]->mask_clear = pintbit; - SSYNC(); } static void bfin_gpio_mask_irq(unsigned int irq) { - u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val); - SSYNC(); } static void bfin_gpio_unmask_irq(unsigned int irq) { - u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; u32 pintbit = PINT_BIT(pint_val); - u8 bank = PINT_2_BANK(pint_val); + u32 bank = PINT_2_BANK(pint_val); pint[bank]->request = pintbit; pint[bank]->mask_set = pintbit; - SSYNC(); } static unsigned int bfin_gpio_irq_startup(unsigned int irq) { - u16 gpionr = irq_to_gpio(irq); - u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + u32 gpionr = irq_to_gpio(irq); + u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; if (pint_val == IRQ_NOT_AVAIL) { printk(KERN_ERR @@ -755,10 +704,9 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq) return -ENODEV; } - if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) + if (__test_and_set_bit(gpionr, gpio_enabled)) bfin_gpio_irq_prepare(gpionr); - gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); bfin_gpio_unmask_irq(irq); return 0; @@ -766,38 +714,37 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq) static void bfin_gpio_irq_shutdown(unsigned int irq) { - u16 gpionr = irq_to_gpio(irq); + u32 gpionr = irq_to_gpio(irq); bfin_gpio_mask_irq(irq); - gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); + __clear_bit(gpionr, gpio_enabled); } static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) { - u16 gpionr = irq_to_gpio(irq); - u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + u32 gpionr = irq_to_gpio(irq); + u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; u32 pintbit = PINT_BIT(pint_val); - u8 bank = PINT_2_BANK(pint_val); + u32 bank = PINT_2_BANK(pint_val); if (pint_val == IRQ_NOT_AVAIL) return -ENODEV; if (type == IRQ_TYPE_PROBE) { /* only probe unenabled GPIO interrupt lines */ - if (gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)) + if (__test_bit(gpionr, gpio_enabled)) return 0; type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; } if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { - if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) + if (__test_and_set_bit(gpionr, gpio_enabled)) bfin_gpio_irq_prepare(gpionr); - gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); } else { - gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); + __clear_bit(gpionr, gpio_enabled); return 0; } @@ -808,15 +755,10 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { - - gpio_both_edge_triggered[bank] |= pintbit; - if (gpio_get_value(gpionr)) pint[bank]->invert_set = pintbit; else pint[bank]->invert_clear = pintbit; - } else { - gpio_both_edge_triggered[bank] &= ~pintbit; } if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { @@ -827,8 +769,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) bfin_set_irq_handler(irq, handle_level_irq); } - SSYNC(); - return 0; } @@ -839,7 +779,7 @@ u32 pint_wakeup_masks[NR_PINT_SYS_IRQS]; int bfin_gpio_set_wake(unsigned int irq, unsigned int state) { u32 pint_irq; - u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; u32 bank = PINT_2_BANK(pint_val); u32 pintbit = PINT_BIT(pint_val); @@ -900,26 +840,10 @@ void bfin_pm_restore(void) } #endif -static struct irq_chip bfin_gpio_irqchip = { - .name = "GPIO", - .ack = bfin_gpio_ack_irq, - .mask = bfin_gpio_mask_irq, - .mask_ack = bfin_gpio_mask_ack_irq, - .unmask = bfin_gpio_unmask_irq, - .disable = bfin_gpio_mask_irq, - .enable = bfin_gpio_unmask_irq, - .set_type = bfin_gpio_irq_type, - .startup = bfin_gpio_irq_startup, - .shutdown = bfin_gpio_irq_shutdown, -#ifdef CONFIG_PM - .set_wake = bfin_gpio_set_wake, -#endif -}; - static void bfin_demux_gpio_irq(unsigned int inta_irq, struct irq_desc *desc) { - u8 bank, pint_val; + u32 bank, pint_val; u32 request, irq; switch (inta_irq) { @@ -956,6 +880,22 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq, } #endif +static struct irq_chip bfin_gpio_irqchip = { + .name = "GPIO", + .ack = bfin_gpio_ack_irq, + .mask = bfin_gpio_mask_irq, + .mask_ack = bfin_gpio_mask_ack_irq, + .unmask = bfin_gpio_unmask_irq, + .disable = bfin_gpio_mask_irq, + .enable = bfin_gpio_unmask_irq, + .set_type = bfin_gpio_irq_type, + .startup = bfin_gpio_irq_startup, + .shutdown = bfin_gpio_irq_shutdown, +#ifdef CONFIG_PM + .set_wake = bfin_gpio_set_wake, +#endif +}; + void __init init_exception_vectors(void) { /* cannot program in software: @@ -982,6 +922,7 @@ void __init init_exception_vectors(void) * This function should be called during kernel startup to initialize * the BFin IRQ handling routines. */ + int __init init_arch_irq(void) { int irq; -- cgit v1.1 From 6b3087c64a92a36ae20d33479b4df6d7afc910d4 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Wed, 7 Jan 2009 23:14:39 +0800 Subject: Blackfin arch: SMP supporting patchset: Blackfin header files and machine common code Blackfin dual core BF561 processor can support SMP like features. https://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:smp-like In this patch, we provide SMP extend to Blackfin header files and machine common code Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/Makefile | 1 + arch/blackfin/mach-common/cache.S | 36 +++ arch/blackfin/mach-common/entry.S | 92 +++--- arch/blackfin/mach-common/head.S | 29 +- arch/blackfin/mach-common/ints-priority.c | 41 ++- arch/blackfin/mach-common/smp.c | 476 ++++++++++++++++++++++++++++++ 6 files changed, 605 insertions(+), 70 deletions(-) create mode 100644 arch/blackfin/mach-common/smp.c (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile index e6ed57c..9388b4a 100644 --- a/arch/blackfin/mach-common/Makefile +++ b/arch/blackfin/mach-common/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_BFIN_ICACHE_LOCK) += lock.o obj-$(CONFIG_PM) += pm.o dpmc_modes.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o +obj-$(CONFIG_SMP) += smp.o diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S index 3c98dac..1187512 100644 --- a/arch/blackfin/mach-common/cache.S +++ b/arch/blackfin/mach-common/cache.S @@ -97,3 +97,39 @@ ENTRY(_blackfin_dflush_page) P1 = 1 << (PAGE_SHIFT - L1_CACHE_SHIFT); jump .Ldfr; ENDPROC(_blackfin_dflush_page) + +/* Invalidate the Entire Data cache by + * clearing DMC[1:0] bits + */ +ENTRY(_blackfin_invalidate_entire_dcache) + [--SP] = ( R7:5); + + P0.L = LO(DMEM_CONTROL); + P0.H = HI(DMEM_CONTROL); + R7 = [P0]; + R5 = R7; /* Save DMEM_CNTR */ + + /* Clear the DMC[1:0] bits, All valid bits in the data + * cache are set to the invalid state + */ + BITCLR(R7,DMC0_P); + BITCLR(R7,DMC1_P); + CLI R6; + SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ + .align 8; + [P0] = R7; + SSYNC; + STI R6; + + /* Configures the data cache again */ + + CLI R6; + SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ + .align 8; + [P0] = R5; + SSYNC; + STI R6; + + ( R7:5) = [SP++]; + RTS; +ENDPROC(_blackfin_invalidate_entire_dcache) diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index c6ae844..5531f49 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -75,11 +76,11 @@ ENTRY(_ex_workaround_261) * handle it. */ P4 = R7; /* Store EXCAUSE */ - p5.l = _last_cplb_fault_retx; - p5.h = _last_cplb_fault_retx; - r7 = [p5]; + + GET_PDA(p5, r7); + r7 = [p5 + PDA_LFRETX]; r6 = retx; - [p5] = r6; + [p5 + PDA_LFRETX] = r6; cc = r6 == r7; if !cc jump _bfin_return_from_exception; /* fall through */ @@ -324,7 +325,9 @@ ENTRY(_ex_trap_c) [p4] = p5; csync; + GET_PDA(p5, r6); #ifndef CONFIG_DEBUG_DOUBLEFAULT + /* * Save these registers, as they are only valid in exception context * (where we are now - as soon as we defer to IRQ5, they can change) @@ -335,29 +338,25 @@ ENTRY(_ex_trap_c) p4.l = lo(DCPLB_FAULT_ADDR); p4.h = hi(DCPLB_FAULT_ADDR); r7 = [p4]; - p5.h = _saved_dcplb_fault_addr; - p5.l = _saved_dcplb_fault_addr; - [p5] = r7; + [p5 + PDA_DCPLB] = r7; - r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)]; - p5.h = _saved_icplb_fault_addr; - p5.l = _saved_icplb_fault_addr; - [p5] = r7; + p4.l = lo(ICPLB_FAULT_ADDR); + p4.h = hi(ICPLB_FAULT_ADDR); + r6 = [p4]; + [p5 + PDA_ICPLB] = r6; r6 = retx; - p4.l = _saved_retx; - p4.h = _saved_retx; - [p4] = r6; + [p5 + PDA_RETX] = r6; #endif r6 = SYSCFG; - [p4 + 4] = r6; + [p5 + PDA_SYSCFG] = r6; BITCLR(r6, 0); SYSCFG = r6; /* Disable all interrupts, but make sure level 5 is enabled so * we can switch to that level. Save the old mask. */ cli r6; - [p4 + 8] = r6; + [p5 + PDA_EXIMASK] = r6; p4.l = lo(SAFE_USER_INSTRUCTION); p4.h = hi(SAFE_USER_INSTRUCTION); @@ -424,17 +423,16 @@ ENDPROC(_double_fault) ENTRY(_exception_to_level5) SAVE_ALL_SYS - p4.l = _saved_retx; - p4.h = _saved_retx; - r6 = [p4]; + GET_PDA(p4, r7); /* Fetch current PDA */ + r6 = [p4 + PDA_RETX]; [sp + PT_PC] = r6; - r6 = [p4 + 4]; + r6 = [p4 + PDA_SYSCFG]; [sp + PT_SYSCFG] = r6; /* Restore interrupt mask. We haven't pushed RETI, so this * doesn't enable interrupts until we return from this handler. */ - r6 = [p4 + 8]; + r6 = [p4 + PDA_EXIMASK]; sti r6; /* Restore the hardware error vector. */ @@ -478,8 +476,8 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ * scratch register (for want of a better option). */ EX_SCRATCH_REG = sp; - sp.l = _exception_stack_top; - sp.h = _exception_stack_top; + GET_PDA_SAFE(sp); + sp = [sp + PDA_EXSTACK] /* Try to deal with syscalls quickly. */ [--sp] = ASTAT; [--sp] = (R7:6,P5:4); @@ -501,27 +499,22 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ * but they are not very interesting, so don't save them */ + GET_PDA(p5, r7); p4.l = lo(DCPLB_FAULT_ADDR); p4.h = hi(DCPLB_FAULT_ADDR); r7 = [p4]; - p5.h = _saved_dcplb_fault_addr; - p5.l = _saved_dcplb_fault_addr; - [p5] = r7; + [p5 + PDA_DCPLB] = r7; - r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)]; - p5.h = _saved_icplb_fault_addr; - p5.l = _saved_icplb_fault_addr; - [p5] = r7; + p4.l = lo(ICPLB_FAULT_ADDR); + p4.h = hi(ICPLB_FAULT_ADDR); + r7 = [p4]; + [p5 + PDA_ICPLB] = r7; - p4.l = _saved_retx; - p4.h = _saved_retx; r6 = retx; - [p4] = r6; + [p5 + PDA_RETX] = r6; r7 = SEQSTAT; /* reason code is in bit 5:0 */ - p4.l = _saved_seqstat; - p4.h = _saved_seqstat; - [p4] = r7; + [p5 + PDA_SEQSTAT] = r7; #else r7 = SEQSTAT; /* reason code is in bit 5:0 */ #endif @@ -546,11 +539,11 @@ ENTRY(_kernel_execve) p0 = sp; r3 = SIZEOF_PTREGS / 4; r4 = 0(x); -0: +.Lclear_regs: [p0++] = r4; r3 += -1; cc = r3 == 0; - if !cc jump 0b (bp); + if !cc jump .Lclear_regs (bp); p0 = sp; sp += -16; @@ -558,7 +551,7 @@ ENTRY(_kernel_execve) call _do_execve; SP += 16; cc = r0 == 0; - if ! cc jump 1f; + if ! cc jump .Lexecve_failed; /* Success. Copy our temporary pt_regs to the top of the kernel * stack and do a normal exception return. */ @@ -574,12 +567,12 @@ ENTRY(_kernel_execve) p0 = fp; r4 = [p0--]; r3 = SIZEOF_PTREGS / 4; -0: +.Lcopy_regs: r4 = [p0--]; [p1--] = r4; r3 += -1; cc = r3 == 0; - if ! cc jump 0b (bp); + if ! cc jump .Lcopy_regs (bp); r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z); p1 = r0; @@ -591,7 +584,7 @@ ENTRY(_kernel_execve) RESTORE_CONTEXT; rti; -1: +.Lexecve_failed: unlink; rts; ENDPROC(_kernel_execve) @@ -925,9 +918,14 @@ _schedule_and_signal_from_int: p1 = rets; [sp + PT_RESERVED] = p1; +#ifdef CONFIG_SMP + GET_PDA(p0, r0); /* Fetch current PDA (can't migrate to other CPU here) */ + r0 = [p0 + PDA_IRQFLAGS]; +#else p0.l = _irq_flags; p0.h = _irq_flags; r0 = [p0]; +#endif sti r0; r0 = sp; @@ -1539,12 +1537,6 @@ ENTRY(_sys_call_table) .endr END(_sys_call_table) -#if ANOMALY_05000261 -/* Used by the assembly entry point to work around an anomaly. */ -_last_cplb_fault_retx: - .long 0; -#endif - #ifdef CONFIG_EXCEPTION_L1_SCRATCH /* .section .l1.bss.scratch */ .set _exception_stack_top, L1_SCRATCH_START + L1_SCRATCH_LENGTH @@ -1554,8 +1546,8 @@ _last_cplb_fault_retx: #else .bss #endif -_exception_stack: - .rept 1024 +ENTRY(_exception_stack) + .rept 1024 * NR_CPUS .long 0 .endr _exception_stack_top: diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index c1dcaeb..a621ae4 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S @@ -13,6 +13,7 @@ #include #include #include +#include __INIT @@ -111,33 +112,26 @@ ENTRY(__start) * This happens here, since L1 gets clobbered * below */ - p0.l = _saved_retx; - p0.h = _saved_retx; + GET_PDA(p0, r0); + r7 = [p0 + PDA_RETX]; p1.l = _init_saved_retx; p1.h = _init_saved_retx; - r0 = [p0]; - [p1] = r0; + [p1] = r7; - p0.l = _saved_dcplb_fault_addr; - p0.h = _saved_dcplb_fault_addr; + r7 = [p0 + PDA_DCPLB]; p1.l = _init_saved_dcplb_fault_addr; p1.h = _init_saved_dcplb_fault_addr; - r0 = [p0]; - [p1] = r0; + [p1] = r7; - p0.l = _saved_icplb_fault_addr; - p0.h = _saved_icplb_fault_addr; + r7 = [p0 + PDA_ICPLB]; p1.l = _init_saved_icplb_fault_addr; p1.h = _init_saved_icplb_fault_addr; - r0 = [p0]; - [p1] = r0; + [p1] = r7; - p0.l = _saved_seqstat; - p0.h = _saved_seqstat; + r7 = [p0 + PDA_SEQSTAT]; p1.l = _init_saved_seqstat; p1.h = _init_saved_seqstat; - r0 = [p0]; - [p1] = r0; + [p1] = r7; #endif /* Initialize stack pointer */ @@ -255,6 +249,9 @@ ENTRY(_real_start) sp = sp + p1; usp = sp; fp = sp; + sp += -12; + call _init_pda + sp += 12; jump.l _start_kernel; ENDPROC(_real_start) diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index d45d0c5..eb8dfcf 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -55,6 +55,7 @@ * - */ +#ifndef CONFIG_SMP /* Initialize this to an actual value to force it into the .data * section so that we know it is properly initialized at entry into * the kernel but before bss is initialized to zero (which is where @@ -63,6 +64,7 @@ */ unsigned long irq_flags = 0x1f; EXPORT_SYMBOL(irq_flags); +#endif /* The number of spurious interrupts */ atomic_t num_spurious; @@ -163,6 +165,10 @@ static void bfin_internal_mask_irq(unsigned int irq) mask_bit = SIC_SYSIRQ(irq) % 32; bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) & ~(1 << mask_bit)); +#ifdef CONFIG_SMP + bfin_write_SICB_IMASK(mask_bank, bfin_read_SICB_IMASK(mask_bank) & + ~(1 << mask_bit)); +#endif #endif } @@ -177,6 +183,10 @@ static void bfin_internal_unmask_irq(unsigned int irq) mask_bit = SIC_SYSIRQ(irq) % 32; bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) | (1 << mask_bit)); +#ifdef CONFIG_SMP + bfin_write_SICB_IMASK(mask_bank, bfin_read_SICB_IMASK(mask_bank) | + (1 << mask_bit)); +#endif #endif } @@ -896,7 +906,7 @@ static struct irq_chip bfin_gpio_irqchip = { #endif }; -void __init init_exception_vectors(void) +void __cpuinit init_exception_vectors(void) { /* cannot program in software: * evt0 - emulation (jtag) @@ -935,6 +945,10 @@ int __init init_arch_irq(void) # ifdef CONFIG_BF54x bfin_write_SIC_IMASK2(SIC_UNMASK_ALL); # endif +# ifdef CONFIG_SMP + bfin_write_SICB_IMASK0(SIC_UNMASK_ALL); + bfin_write_SICB_IMASK1(SIC_UNMASK_ALL); +# endif #else bfin_write_SIC_IMASK(SIC_UNMASK_ALL); #endif @@ -995,6 +1009,17 @@ int __init init_arch_irq(void) break; #endif +#ifdef CONFIG_TICK_SOURCE_SYSTMR0 + case IRQ_TIMER0: + set_irq_handler(irq, handle_percpu_irq); + break; +#endif +#ifdef CONFIG_SMP + case IRQ_SUPPLE_0: + case IRQ_SUPPLE_1: + set_irq_handler(irq, handle_percpu_irq); + break; +#endif default: set_irq_handler(irq, handle_simple_irq); break; @@ -1029,7 +1054,7 @@ int __init init_arch_irq(void) search_IAR(); /* Enable interrupts IVG7-15 */ - irq_flags = irq_flags | IMASK_IVG15 | + irq_flags |= IMASK_IVG15 | IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; @@ -1070,8 +1095,16 @@ void do_irq(int vec, struct pt_regs *fp) || defined(BF538_FAMILY) || defined(CONFIG_BF51x) unsigned long sic_status[3]; - sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0(); - sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1(); + if (smp_processor_id()) { +#ifdef CONFIG_SMP + /* This will be optimized out in UP mode. */ + sic_status[0] = bfin_read_SICB_ISR0() & bfin_read_SICB_IMASK0(); + sic_status[1] = bfin_read_SICB_ISR1() & bfin_read_SICB_IMASK1(); +#endif + } else { + sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0(); + sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1(); + } #ifdef CONFIG_BF54x sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2(); #endif diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c new file mode 100644 index 0000000..7aeeced --- /dev/null +++ b/arch/blackfin/mach-common/smp.c @@ -0,0 +1,476 @@ +/* + * File: arch/blackfin/kernel/smp.c + * Author: Philippe Gerum + * IPI management based on arch/arm/kernel/smp.c. + * + * Copyright 2007 Analog Devices Inc. + * + * 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 the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct corelock_slot corelock __attribute__ ((__section__(".l2.bss"))); + +void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb, + *init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb, + *init_saved_dcplb_fault_addr_coreb; + +cpumask_t cpu_possible_map; +EXPORT_SYMBOL(cpu_possible_map); + +cpumask_t cpu_online_map; +EXPORT_SYMBOL(cpu_online_map); + +#define BFIN_IPI_RESCHEDULE 0 +#define BFIN_IPI_CALL_FUNC 1 +#define BFIN_IPI_CPU_STOP 2 + +struct blackfin_flush_data { + unsigned long start; + unsigned long end; +}; + +void *secondary_stack; + + +struct smp_call_struct { + void (*func)(void *info); + void *info; + int wait; + cpumask_t pending; + cpumask_t waitmask; +}; + +static struct blackfin_flush_data smp_flush_data; + +static DEFINE_SPINLOCK(stop_lock); + +struct ipi_message { + struct list_head list; + unsigned long type; + struct smp_call_struct call_struct; +}; + +struct ipi_message_queue { + struct list_head head; + spinlock_t lock; + unsigned long count; +}; + +static DEFINE_PER_CPU(struct ipi_message_queue, ipi_msg_queue); + +static void ipi_cpu_stop(unsigned int cpu) +{ + spin_lock(&stop_lock); + printk(KERN_CRIT "CPU%u: stopping\n", cpu); + dump_stack(); + spin_unlock(&stop_lock); + + cpu_clear(cpu, cpu_online_map); + + local_irq_disable(); + + while (1) + SSYNC(); +} + +static void ipi_flush_icache(void *info) +{ + struct blackfin_flush_data *fdata = info; + + /* Invalidate the memory holding the bounds of the flushed region. */ + blackfin_dcache_invalidate_range((unsigned long)fdata, + (unsigned long)fdata + sizeof(*fdata)); + + blackfin_icache_flush_range(fdata->start, fdata->end); +} + +static void ipi_call_function(unsigned int cpu, struct ipi_message *msg) +{ + int wait; + void (*func)(void *info); + void *info; + func = msg->call_struct.func; + info = msg->call_struct.info; + wait = msg->call_struct.wait; + cpu_clear(cpu, msg->call_struct.pending); + func(info); + if (wait) + cpu_clear(cpu, msg->call_struct.waitmask); + else + kfree(msg); +} + +static irqreturn_t ipi_handler(int irq, void *dev_instance) +{ + struct ipi_message *msg, *mg; + struct ipi_message_queue *msg_queue; + unsigned int cpu = smp_processor_id(); + + platform_clear_ipi(cpu); + + msg_queue = &__get_cpu_var(ipi_msg_queue); + msg_queue->count++; + + spin_lock(&msg_queue->lock); + list_for_each_entry_safe(msg, mg, &msg_queue->head, list) { + list_del(&msg->list); + switch (msg->type) { + case BFIN_IPI_RESCHEDULE: + /* That's the easiest one; leave it to + * return_from_int. */ + kfree(msg); + break; + case BFIN_IPI_CALL_FUNC: + ipi_call_function(cpu, msg); + break; + case BFIN_IPI_CPU_STOP: + ipi_cpu_stop(cpu); + kfree(msg); + break; + default: + printk(KERN_CRIT "CPU%u: Unknown IPI message \ + 0x%lx\n", cpu, msg->type); + kfree(msg); + break; + } + } + spin_unlock(&msg_queue->lock); + return IRQ_HANDLED; +} + +static void ipi_queue_init(void) +{ + unsigned int cpu; + struct ipi_message_queue *msg_queue; + for_each_possible_cpu(cpu) { + msg_queue = &per_cpu(ipi_msg_queue, cpu); + INIT_LIST_HEAD(&msg_queue->head); + spin_lock_init(&msg_queue->lock); + msg_queue->count = 0; + } +} + +int smp_call_function(void (*func)(void *info), void *info, int wait) +{ + unsigned int cpu; + cpumask_t callmap; + unsigned long flags; + struct ipi_message_queue *msg_queue; + struct ipi_message *msg; + + callmap = cpu_online_map; + cpu_clear(smp_processor_id(), callmap); + if (cpus_empty(callmap)) + return 0; + + msg = kmalloc(sizeof(*msg), GFP_ATOMIC); + INIT_LIST_HEAD(&msg->list); + msg->call_struct.func = func; + msg->call_struct.info = info; + msg->call_struct.wait = wait; + msg->call_struct.pending = callmap; + msg->call_struct.waitmask = callmap; + msg->type = BFIN_IPI_CALL_FUNC; + + for_each_cpu_mask(cpu, callmap) { + msg_queue = &per_cpu(ipi_msg_queue, cpu); + spin_lock_irqsave(&msg_queue->lock, flags); + list_add(&msg->list, &msg_queue->head); + spin_unlock_irqrestore(&msg_queue->lock, flags); + platform_send_ipi_cpu(cpu); + } + if (wait) { + while (!cpus_empty(msg->call_struct.waitmask)) + blackfin_dcache_invalidate_range( + (unsigned long)(&msg->call_struct.waitmask), + (unsigned long)(&msg->call_struct.waitmask)); + kfree(msg); + } + return 0; +} +EXPORT_SYMBOL_GPL(smp_call_function); + +int smp_call_function_single(int cpuid, void (*func) (void *info), void *info, + int wait) +{ + unsigned int cpu = cpuid; + cpumask_t callmap; + unsigned long flags; + struct ipi_message_queue *msg_queue; + struct ipi_message *msg; + + if (cpu_is_offline(cpu)) + return 0; + cpus_clear(callmap); + cpu_set(cpu, callmap); + + msg = kmalloc(sizeof(*msg), GFP_ATOMIC); + INIT_LIST_HEAD(&msg->list); + msg->call_struct.func = func; + msg->call_struct.info = info; + msg->call_struct.wait = wait; + msg->call_struct.pending = callmap; + msg->call_struct.waitmask = callmap; + msg->type = BFIN_IPI_CALL_FUNC; + + msg_queue = &per_cpu(ipi_msg_queue, cpu); + spin_lock_irqsave(&msg_queue->lock, flags); + list_add(&msg->list, &msg_queue->head); + spin_unlock_irqrestore(&msg_queue->lock, flags); + platform_send_ipi_cpu(cpu); + + if (wait) { + while (!cpus_empty(msg->call_struct.waitmask)) + blackfin_dcache_invalidate_range( + (unsigned long)(&msg->call_struct.waitmask), + (unsigned long)(&msg->call_struct.waitmask)); + kfree(msg); + } + return 0; +} +EXPORT_SYMBOL_GPL(smp_call_function_single); + +void smp_send_reschedule(int cpu) +{ + unsigned long flags; + struct ipi_message_queue *msg_queue; + struct ipi_message *msg; + + if (cpu_is_offline(cpu)) + return; + + msg = kmalloc(sizeof(*msg), GFP_ATOMIC); + memset(msg, 0, sizeof(msg)); + INIT_LIST_HEAD(&msg->list); + msg->type = BFIN_IPI_RESCHEDULE; + + msg_queue = &per_cpu(ipi_msg_queue, cpu); + spin_lock_irqsave(&msg_queue->lock, flags); + list_add(&msg->list, &msg_queue->head); + spin_unlock_irqrestore(&msg_queue->lock, flags); + platform_send_ipi_cpu(cpu); + + return; +} + +void smp_send_stop(void) +{ + unsigned int cpu; + cpumask_t callmap; + unsigned long flags; + struct ipi_message_queue *msg_queue; + struct ipi_message *msg; + + callmap = cpu_online_map; + cpu_clear(smp_processor_id(), callmap); + if (cpus_empty(callmap)) + return; + + msg = kmalloc(sizeof(*msg), GFP_ATOMIC); + memset(msg, 0, sizeof(msg)); + INIT_LIST_HEAD(&msg->list); + msg->type = BFIN_IPI_CPU_STOP; + + for_each_cpu_mask(cpu, callmap) { + msg_queue = &per_cpu(ipi_msg_queue, cpu); + spin_lock_irqsave(&msg_queue->lock, flags); + list_add(&msg->list, &msg_queue->head); + spin_unlock_irqrestore(&msg_queue->lock, flags); + platform_send_ipi_cpu(cpu); + } + return; +} + +int __cpuinit __cpu_up(unsigned int cpu) +{ + struct task_struct *idle; + int ret; + + idle = fork_idle(cpu); + if (IS_ERR(idle)) { + printk(KERN_ERR "CPU%u: fork() failed\n", cpu); + return PTR_ERR(idle); + } + + secondary_stack = task_stack_page(idle) + THREAD_SIZE; + smp_wmb(); + + ret = platform_boot_secondary(cpu, idle); + + if (ret) { + cpu_clear(cpu, cpu_present_map); + printk(KERN_CRIT "CPU%u: processor failed to boot (%d)\n", cpu, ret); + free_task(idle); + } else + cpu_set(cpu, cpu_online_map); + + secondary_stack = NULL; + + return ret; +} + +static void __cpuinit setup_secondary(unsigned int cpu) +{ +#ifndef CONFIG_TICK_SOURCE_SYSTMR0 + struct irq_desc *timer_desc; +#endif + unsigned long ilat; + + bfin_write_IMASK(0); + CSYNC(); + ilat = bfin_read_ILAT(); + CSYNC(); + bfin_write_ILAT(ilat); + CSYNC(); + + /* Reserve the PDA space for the secondary CPU. */ + reserve_pda(); + + /* Enable interrupt levels IVG7-15. IARs have been already + * programmed by the boot CPU. */ + irq_flags |= IMASK_IVG15 | + IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | + IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; + +#ifdef CONFIG_TICK_SOURCE_SYSTMR0 + /* Power down the core timer, just to play safe. */ + bfin_write_TCNTL(0); + + /* system timer0 has been setup by CoreA. */ +#else + timer_desc = irq_desc + IRQ_CORETMR; + setup_core_timer(); + timer_desc->chip->enable(IRQ_CORETMR); +#endif +} + +void __cpuinit secondary_start_kernel(void) +{ + unsigned int cpu = smp_processor_id(); + struct mm_struct *mm = &init_mm; + + if (_bfin_swrst & SWRST_DBL_FAULT_B) { + printk(KERN_EMERG "CoreB Recovering from DOUBLE FAULT event\n"); +#ifdef CONFIG_DEBUG_DOUBLEFAULT + printk(KERN_EMERG " While handling exception (EXCAUSE = 0x%x) at %pF\n", + (int)init_saved_seqstat_coreb & SEQSTAT_EXCAUSE, init_saved_retx_coreb); + printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n", init_saved_dcplb_fault_addr_coreb); + printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n", init_saved_icplb_fault_addr_coreb); +#endif + printk(KERN_NOTICE " The instruction at %pF caused a double exception\n", + init_retx_coreb); + } + + /* + * We want the D-cache to be enabled early, in case the atomic + * support code emulates cache coherence (see + * __ARCH_SYNC_CORE_DCACHE). + */ + init_exception_vectors(); + + bfin_setup_caches(cpu); + + local_irq_disable(); + + /* Attach the new idle task to the global mm. */ + atomic_inc(&mm->mm_users); + atomic_inc(&mm->mm_count); + current->active_mm = mm; + BUG_ON(current->mm); /* Can't be, but better be safe than sorry. */ + + preempt_disable(); + + setup_secondary(cpu); + + local_irq_enable(); + + platform_secondary_init(cpu); + + cpu_idle(); +} + +void __init smp_prepare_boot_cpu(void) +{ +} + +void __init smp_prepare_cpus(unsigned int max_cpus) +{ + platform_prepare_cpus(max_cpus); + ipi_queue_init(); + platform_request_ipi(&ipi_handler); +} + +void __init smp_cpus_done(unsigned int max_cpus) +{ + unsigned long bogosum = 0; + unsigned int cpu; + + for_each_online_cpu(cpu) + bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy; + + printk(KERN_INFO "SMP: Total of %d processors activated " + "(%lu.%02lu BogoMIPS).\n", + num_online_cpus(), + bogosum / (500000/HZ), + (bogosum / (5000/HZ)) % 100); +} + +void smp_icache_flush_range_others(unsigned long start, unsigned long end) +{ + smp_flush_data.start = start; + smp_flush_data.end = end; + + if (smp_call_function(&ipi_flush_icache, &smp_flush_data, 1)) + printk(KERN_WARNING "SMP: failed to run I-cache flush request on other CPUs\n"); +} +EXPORT_SYMBOL_GPL(smp_icache_flush_range_others); + +#ifdef __ARCH_SYNC_CORE_DCACHE +unsigned long barrier_mask __attribute__ ((__section__(".l2.bss"))); + +void resync_core_dcache(void) +{ + unsigned int cpu = get_cpu(); + blackfin_invalidate_entire_dcache(); + ++per_cpu(cpu_data, cpu).dcache_invld_count; + put_cpu(); +} +EXPORT_SYMBOL(resync_core_dcache); +#endif -- cgit v1.1 From 3c1fbd5184f9c3c52c0a392fae0efb0b0d99a079 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: rewrite blackfin_invalidate_entire_dcache function rewrite blackfin_invalidate_entire_dcache() in C for easier management, better optimization, and so we take all SSYNC anomalies into account Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/Makefile | 2 +- arch/blackfin/mach-common/cache-c.c | 24 ++++++++++++++++++++++++ arch/blackfin/mach-common/cache.S | 36 ------------------------------------ 3 files changed, 25 insertions(+), 37 deletions(-) create mode 100644 arch/blackfin/mach-common/cache-c.c (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile index 9388b4a..38911c6 100644 --- a/arch/blackfin/mach-common/Makefile +++ b/arch/blackfin/mach-common/Makefile @@ -3,7 +3,7 @@ # obj-y := \ - cache.o entry.o head.o \ + cache.o cache-c.o entry.o head.o \ interrupt.o irqpanic.o arch_checks.o ints-priority.o obj-$(CONFIG_BFIN_ICACHE_LOCK) += lock.o diff --git a/arch/blackfin/mach-common/cache-c.c b/arch/blackfin/mach-common/cache-c.c new file mode 100644 index 0000000..e6ab1f8 --- /dev/null +++ b/arch/blackfin/mach-common/cache-c.c @@ -0,0 +1,24 @@ +/* + * Blackfin cache control code (simpler control-style functions) + * + * Copyright 2004-2008 Analog Devices Inc. + * + * Enter bugs at http://blackfin.uclinux.org/ + * + * Licensed under the GPL-2 or later. + */ + +#include + +/* Invalidate the Entire Data cache by + * clearing DMC[1:0] bits + */ +void blackfin_invalidate_entire_dcache(void) +{ + u32 dmem = bfin_read_DMEM_CONTROL(); + SSYNC(); + bfin_write_DMEM_CONTROL(dmem & ~0xc); + SSYNC(); + bfin_write_DMEM_CONTROL(dmem); + SSYNC(); +} diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S index 1187512..3c98dac 100644 --- a/arch/blackfin/mach-common/cache.S +++ b/arch/blackfin/mach-common/cache.S @@ -97,39 +97,3 @@ ENTRY(_blackfin_dflush_page) P1 = 1 << (PAGE_SHIFT - L1_CACHE_SHIFT); jump .Ldfr; ENDPROC(_blackfin_dflush_page) - -/* Invalidate the Entire Data cache by - * clearing DMC[1:0] bits - */ -ENTRY(_blackfin_invalidate_entire_dcache) - [--SP] = ( R7:5); - - P0.L = LO(DMEM_CONTROL); - P0.H = HI(DMEM_CONTROL); - R7 = [P0]; - R5 = R7; /* Save DMEM_CNTR */ - - /* Clear the DMC[1:0] bits, All valid bits in the data - * cache are set to the invalid state - */ - BITCLR(R7,DMC0_P); - BITCLR(R7,DMC1_P); - CLI R6; - SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ - .align 8; - [P0] = R7; - SSYNC; - STI R6; - - /* Configures the data cache again */ - - CLI R6; - SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ - .align 8; - [P0] = R5; - SSYNC; - STI R6; - - ( R7:5) = [SP++]; - RTS; -ENDPROC(_blackfin_invalidate_entire_dcache) -- cgit v1.1 From 7beb7439acea38ecd0abbbdc72f85732dd59658c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: move SIC_SYSIRQ() to the one file that actually uses it Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/ints-priority.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index eb8dfcf..2efddce 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -42,6 +42,8 @@ #include #include +#define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1)) + #ifdef BF537_FAMILY # define BF537_GENERIC_ERROR_INT_DEMUX #else -- cgit v1.1 From 400597842452c02916a61a51f3154dd032c2d569 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: rename irq_flags to bfin_irq_flags rename irq_flags to bfin_irq_flags to avoid namespace collision with common code Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/entry.S | 4 ++-- arch/blackfin/mach-common/ints-priority.c | 16 ++++++++-------- arch/blackfin/mach-common/smp.c | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 5531f49..e22c0a5 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -922,8 +922,8 @@ _schedule_and_signal_from_int: GET_PDA(p0, r0); /* Fetch current PDA (can't migrate to other CPU here) */ r0 = [p0 + PDA_IRQFLAGS]; #else - p0.l = _irq_flags; - p0.h = _irq_flags; + p0.l = _bfin_irq_flags; + p0.h = _bfin_irq_flags; r0 = [p0]; #endif sti r0; diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 2efddce..5a7c1c1 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -64,8 +64,8 @@ * it would live otherwise). The 0x1f magic represents the IRQs we * cannot actually mask out in hardware. */ -unsigned long irq_flags = 0x1f; -EXPORT_SYMBOL(irq_flags); +unsigned long bfin_irq_flags = 0x1f; +EXPORT_SYMBOL(bfin_irq_flags); #endif /* The number of spurious interrupts */ @@ -134,21 +134,21 @@ static void bfin_ack_noop(unsigned int irq) static void bfin_core_mask_irq(unsigned int irq) { - irq_flags &= ~(1 << irq); + bfin_irq_flags &= ~(1 << irq); if (!irqs_disabled()) local_irq_enable(); } static void bfin_core_unmask_irq(unsigned int irq) { - irq_flags |= 1 << irq; + bfin_irq_flags |= 1 << irq; /* * If interrupts are enabled, IMASK must contain the same value - * as irq_flags. Make sure that invariant holds. If interrupts + * as bfin_irq_flags. Make sure that invariant holds. If interrupts * are currently disabled we need not do anything; one of the * callers will take care of setting IMASK to the proper value * when reenabling interrupts. - * local_irq_enable just does "STI irq_flags", so it's exactly + * local_irq_enable just does "STI bfin_irq_flags", so it's exactly * what we need. */ if (!irqs_disabled()) @@ -1048,7 +1048,7 @@ int __init init_arch_irq(void) CSYNC(); printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n"); - /* IMASK=xxx is equivalent to STI xx or irq_flags=xx, + /* IMASK=xxx is equivalent to STI xx or bfin_irq_flags=xx, * local_irq_enable() */ program_IAR(); @@ -1056,7 +1056,7 @@ int __init init_arch_irq(void) search_IAR(); /* Enable interrupts IVG7-15 */ - irq_flags |= IMASK_IVG15 | + bfin_irq_flags |= IMASK_IVG15 | IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 7aeeced..66c47a7 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -365,7 +365,7 @@ static void __cpuinit setup_secondary(unsigned int cpu) /* Enable interrupt levels IVG7-15. IARs have been already * programmed by the boot CPU. */ - irq_flags |= IMASK_IVG15 | + bfin_irq_flags |= IMASK_IVG15 | IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; -- cgit v1.1 From 33c8691f45459a41864562ae8d1ec12b4503f200 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: fix building with CONFIG_DEBUG_DOUBLEFAULT arch/blackfin/mach-common/entry.S:465: Error: pcrel too far BFD_RELOC_BFIN_10 Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/entry.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index e22c0a5..0efd5f5 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -370,9 +370,10 @@ ENTRY(_ex_trap_c) ENDPROC(_ex_trap_c) /* We just realized we got an exception, while we were processing a different - * exception. This is a unrecoverable event, so crash + * exception. This is a unrecoverable event, so crash. + * Note: this cannot be ENTRY() as we jump here with "if cc jump" ... */ -ENTRY(_double_fault) +_double_fault: /* Turn caches & protection off, to ensure we don't get any more * double exceptions */ -- cgit v1.1 From 9b78442fadc1d0319f77437c811fe53398822602 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: rename cache_lock() to bfin_cache_lock() rename cache_lock() to bfin_cache_lock() to avoid namespace collision with common code Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/lock.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/lock.S b/arch/blackfin/mach-common/lock.S index 9daf012..6c5f5f0 100644 --- a/arch/blackfin/mach-common/lock.S +++ b/arch/blackfin/mach-common/lock.S @@ -160,7 +160,7 @@ ENDPROC(_cache_grab_lock) * R0 - Which way to be locked */ -ENTRY(_cache_lock) +ENTRY(_bfin_cache_lock) [--SP]=( R7:0,P5:0 ); @@ -184,7 +184,7 @@ ENTRY(_cache_lock) ( R7:0,P5:0 ) = [SP++]; RTS; -ENDPROC(_cache_lock) +ENDPROC(_bfin_cache_lock) /* Invalidate the Entire Instruction cache by * disabling IMC bit -- cgit v1.1 From b7e11293a4340dc20674144f7e83883a7a40049e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: fix bug - reboot fails on BF527 add ANOMALY_05000435 to handle SIC_IWR1 workaround for rebooting Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/ints-priority.c | 5 ++++- arch/blackfin/mach-common/pm.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 5a7c1c1..f7e35e7 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -1069,7 +1069,10 @@ int __init init_arch_irq(void) * up from IDLE instructions. See this report for more info: * http://blackfin.uclinux.org/gf/tracker/4323 */ - bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11)); + if (ANOMALY_05000435) + bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11)); + else + bfin_write_SIC_IWR1(IWR_DISABLE_ALL); #else bfin_write_SIC_IWR1(IWR_DISABLE_ALL); #endif diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index ee33a8a..96600b8 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -91,7 +91,10 @@ void bfin_pm_suspend_standby_enter(void) * up from IDLE instructions. See this report for more info: * http://blackfin.uclinux.org/gf/tracker/4323 */ - bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11)); + if (ANOMALY_05000435) + bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11)); + else + bfin_write_SIC_IWR1(IWR_DISABLE_ALL); #else bfin_write_SIC_IWR1(IWR_DISABLE_ALL); #endif -- cgit v1.1 From 30af6d490427b49af5beca5824e22b00e468c951 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Tue, 18 Nov 2008 17:48:21 +0800 Subject: Blackfin arch: Add code to free gpio when shutdown irq Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/ints-priority.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index f7e35e7..efa27cb 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -428,8 +428,11 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq) static void bfin_gpio_irq_shutdown(unsigned int irq) { + u32 gpionr = irq_to_gpio(irq); + bfin_gpio_mask_irq(irq); - __clear_bit(irq_to_gpio(irq), gpio_enabled); + __clear_bit(gpionr, gpio_enabled); + bfin_gpio_free(gpionr); } static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) @@ -730,6 +733,7 @@ static void bfin_gpio_irq_shutdown(unsigned int irq) bfin_gpio_mask_irq(irq); __clear_bit(gpionr, gpio_enabled); + bfin_gpio_free(gpionr); } static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) -- cgit v1.1 From 8eb3e3bfd5544c4549a52e3cfc3df2be0b224dbd Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Tue, 18 Nov 2008 17:48:22 +0800 Subject: Blackfin arch: Request the gpio resource when making it as an irq pin, avoiding override it. Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/ints-priority.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index efa27cb..a0bfca9 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -437,8 +437,15 @@ static void bfin_gpio_irq_shutdown(unsigned int irq) static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) { + int ret; + char buf[16]; u32 gpionr = irq_to_gpio(irq); + snprintf(buf, 16, "gpio-irq%d", irq); + ret = bfin_gpio_request(gpionr, buf); + if (ret) + return ret; + if (type == IRQ_TYPE_PROBE) { /* only probe unenabled GPIO interrupt lines */ if (__test_bit(gpionr, gpio_enabled)) @@ -738,7 +745,8 @@ static void bfin_gpio_irq_shutdown(unsigned int irq) static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) { - + int ret; + char buf[16]; u32 gpionr = irq_to_gpio(irq); u32 pint_val = irq2pint_lut[irq - SYS_IRQS]; u32 pintbit = PINT_BIT(pint_val); @@ -747,6 +755,11 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) if (pint_val == IRQ_NOT_AVAIL) return -ENODEV; + snprintf(buf, 16, "gpio-irq%d", irq); + ret = bfin_gpio_request(gpionr, buf); + if (ret) + return ret; + if (type == IRQ_TYPE_PROBE) { /* only probe unenabled GPIO interrupt lines */ if (__test_bit(gpionr, gpio_enabled)) -- cgit v1.1 From 9570ff4af6920c5992eb91141d71fc94127d864b Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Wed, 7 Jan 2009 23:14:38 +0800 Subject: Blackfin arch: Allow a gpio pin be requested both as gpio and irq. [Mike Frysinger : - use KERN_NOTICE when using gpios as both irq and non rather than KERN_ERR - embedded newlines in printk() does not fly] Signed-off-by: Graf Yang Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/ints-priority.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index a0bfca9..7c1db77 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -432,7 +432,7 @@ static void bfin_gpio_irq_shutdown(unsigned int irq) bfin_gpio_mask_irq(irq); __clear_bit(gpionr, gpio_enabled); - bfin_gpio_free(gpionr); + bfin_gpio_irq_free(gpionr); } static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) @@ -441,11 +441,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) char buf[16]; u32 gpionr = irq_to_gpio(irq); - snprintf(buf, 16, "gpio-irq%d", irq); - ret = bfin_gpio_request(gpionr, buf); - if (ret) - return ret; - if (type == IRQ_TYPE_PROBE) { /* only probe unenabled GPIO interrupt lines */ if (__test_bit(gpionr, gpio_enabled)) @@ -456,6 +451,11 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { + snprintf(buf, 16, "gpio-irq%d", irq); + ret = bfin_gpio_irq_request(gpionr, buf); + if (ret) + return ret; + if (__test_and_set_bit(gpionr, gpio_enabled)) bfin_gpio_irq_prepare(gpionr); @@ -740,7 +740,7 @@ static void bfin_gpio_irq_shutdown(unsigned int irq) bfin_gpio_mask_irq(irq); __clear_bit(gpionr, gpio_enabled); - bfin_gpio_free(gpionr); + bfin_gpio_irq_free(gpionr); } static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) @@ -755,11 +755,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) if (pint_val == IRQ_NOT_AVAIL) return -ENODEV; - snprintf(buf, 16, "gpio-irq%d", irq); - ret = bfin_gpio_request(gpionr, buf); - if (ret) - return ret; - if (type == IRQ_TYPE_PROBE) { /* only probe unenabled GPIO interrupt lines */ if (__test_bit(gpionr, gpio_enabled)) @@ -769,6 +764,12 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { + + snprintf(buf, 16, "gpio-irq%d", irq); + ret = bfin_gpio_irq_request(gpionr, buf); + if (ret) + return ret; + if (__test_and_set_bit(gpionr, gpio_enabled)) bfin_gpio_irq_prepare(gpionr); -- cgit v1.1 From 73feb5c09dcf0d64beb67aa5e1f79e11a388e0ff Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 7 Jan 2009 23:14:39 +0800 Subject: Blackfin arch: fix bugs and unify BFIN_KERNEL_CLOCK option - remove duplicated code and headers - add option allowing arbitrary SDRAM/DDR Timing parameters. - mark automatically calculated timings as EXPERIMENTAL - fix comment header block Related to BUGs: - kernel boot up fails with CONFIG_BFIN_KERNEL_CLOCK item on. - kernel does not boot if re-program clocks [ Mike Frysinger - fix comment header - mark do_sync static - document the DMA shutdown - simplify SIC_IWR handling - fix ANOMALY_05000265 handling to work as intended ] Signed-off-by: Michael Hennerich Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/Makefile | 1 + arch/blackfin/mach-common/clocks-init.c | 93 +++++++++++++++++++++++++++++++++ arch/blackfin/mach-common/head.S | 2 +- 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 arch/blackfin/mach-common/clocks-init.c (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile index 38911c6..1f3228e 100644 --- a/arch/blackfin/mach-common/Makefile +++ b/arch/blackfin/mach-common/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_PM) += pm.o dpmc_modes.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_BFIN_KERNEL_CLOCK) += clocks-init.o diff --git a/arch/blackfin/mach-common/clocks-init.c b/arch/blackfin/mach-common/clocks-init.c new file mode 100644 index 0000000..39a94b3 --- /dev/null +++ b/arch/blackfin/mach-common/clocks-init.c @@ -0,0 +1,93 @@ +/* + * arch/blackfin/mach-common/clocks-init.c - reprogram clocks / memory + * + * Copyright 2004-2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include + +#include +#include +#include + +#define PLL_CTL_VAL \ + (((CONFIG_VCO_MULT & 63) << 9) | CLKIN_HALF | \ + (PLL_BYPASS << 8) | (ANOMALY_05000265 ? 0x8000 : 0)) + +__attribute__((l1_text)) +static void do_sync(void) +{ + __builtin_bfin_ssync(); +} + +__attribute__((l1_text)) +void init_clocks(void) +{ + /* Kill any active DMAs as they may trigger external memory accesses + * in the middle of reprogramming things, and that'll screw us up. + * For example, any automatic DMAs left by U-Boot for splash screens. + */ + size_t i; + for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; ++i) { + struct dma_register *dma = dma_io_base_addr[i]; + dma->cfg = 0; + } + + do_sync(); + +#ifdef SIC_IWR0 + bfin_write_SIC_IWR0(IWR_ENABLE(0)); +# ifdef SIC_IWR1 + /* BF52x system reset does not properly reset SIC_IWR1 which + * will screw up the bootrom as it relies on MDMA0/1 waking it + * up from IDLE instructions. See this report for more info: + * http://blackfin.uclinux.org/gf/tracker/4323 + */ + if (ANOMALY_05000435) + bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11)); + else + bfin_write_SIC_IWR1(IWR_DISABLE_ALL); +# endif +# ifdef SIC_IWR2 + bfin_write_SIC_IWR2(IWR_DISABLE_ALL); +# endif +#else + bfin_write_SIC_IWR(IWR_ENABLE(0)); +#endif + do_sync(); +#ifdef EBIU_SDGCTL + bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() | SRFS); + do_sync(); +#endif + +#ifdef CLKBUFOE + bfin_write16(VR_CTL, bfin_read_VR_CTL() | CLKBUFOE); + do_sync(); + __asm__ __volatile__("IDLE;"); +#endif + bfin_write_PLL_LOCKCNT(0x300); + do_sync(); + bfin_write16(PLL_CTL, PLL_CTL_VAL); + __asm__ __volatile__("IDLE;"); + bfin_write_PLL_DIV(CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV); +#ifdef EBIU_SDGCTL + bfin_write_EBIU_SDRRC(mem_SDRRC); + bfin_write_EBIU_SDGCTL(mem_SDGCTL); +#else + bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() & ~(SRREQ)); + do_sync(); + bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | 0x1); + bfin_write_EBIU_DDRCTL0(mem_DDRCTL0); + bfin_write_EBIU_DDRCTL1(mem_DDRCTL1); + bfin_write_EBIU_DDRCTL2(mem_DDRCTL2); +#ifdef CONFIG_MEM_EBIU_DDRQUE + bfin_write_EBIU_DDRQUE(CONFIG_MEM_EBIU_DDRQUE); +#endif +#endif + do_sync(); + bfin_read16(0); +} diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index a621ae4..e1e42c0 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S @@ -147,7 +147,7 @@ ENTRY(__start) /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */ call _bfin_relocate_l1_mem; #ifdef CONFIG_BFIN_KERNEL_CLOCK - call _start_dma_code; + call _init_clocks; #endif /* This section keeps the processor in supervisor mode -- cgit v1.1 From f994607a2e118aedf1116a58ecd16126dbb83d28 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Wed, 7 Jan 2009 23:14:39 +0800 Subject: Blackfin arch: get oprofile work for user space Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/interrupt.S | 12 +++++++----- arch/blackfin/mach-common/irqpanic.c | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index 4a2ec7a..2604b53 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -152,6 +152,12 @@ ENTRY(_evt_ivhw) 1: #endif + # We are going to dump something out, so make sure we print IPEND properly + p2.l = lo(IPEND); + p2.h = hi(IPEND); + r0 = [p2]; + [sp + PT_IPEND] = r0; + #ifdef CONFIG_HARDWARE_PM r7 = [sp + PT_SEQSTAT]; r7 = r7 >>> 0xe; @@ -161,11 +167,6 @@ ENTRY(_evt_ivhw) cc = r7 == r5; if cc jump .Lcall_do_ovf; /* deal with performance counter overflow */ #endif - # We are going to dump something out, so make sure we print IPEND properly - p2.l = lo(IPEND); - p2.h = hi(IPEND); - r0 = [p2]; - [sp + PT_IPEND] = r0; /* set the EXCAUSE to HWERR for trap_c */ r0 = [sp + PT_SEQSTAT]; @@ -196,6 +197,7 @@ ENTRY(_evt_ivhw) #ifdef CONFIG_HARDWARE_PM .Lcall_do_ovf: + R0 = SP; SP += -12; call _pm_overflow; SP += 12; diff --git a/arch/blackfin/mach-common/irqpanic.c b/arch/blackfin/mach-common/irqpanic.c index 606ded9..7b69413 100644 --- a/arch/blackfin/mach-common/irqpanic.c +++ b/arch/blackfin/mach-common/irqpanic.c @@ -139,8 +139,8 @@ asmlinkage void irq_panic(int reason, struct pt_regs *regs) /* * call the handler of Performance overflow */ -asmlinkage void pm_overflow(int irq, struct pt_regs *regs) +asmlinkage void pm_overflow(struct pt_regs *regs) { - pm_overflow_handler(irq, regs); + pm_overflow_handler(regs); } #endif -- cgit v1.1 From 211daf9d7252288ad88ab6b97268a8d828e6b696 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 7 Jan 2009 23:14:39 +0800 Subject: Blackfin arch: rename MAX_BLACKFIN_DMA_CHANNEL to MAX_DMA_CHANNELS to match everyone else Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/clocks-init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/clocks-init.c b/arch/blackfin/mach-common/clocks-init.c index 39a94b3..5d182ab 100644 --- a/arch/blackfin/mach-common/clocks-init.c +++ b/arch/blackfin/mach-common/clocks-init.c @@ -32,7 +32,7 @@ void init_clocks(void) * For example, any automatic DMAs left by U-Boot for splash screens. */ size_t i; - for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; ++i) { + for (i = 0; i < MAX_DMA_CHANNELS; ++i) { struct dma_register *dma = dma_io_base_addr[i]; dma->cfg = 0; } -- cgit v1.1 From bc39ac66808a49d64e6add3e01d3b0fdeaa49d22 Mon Sep 17 00:00:00 2001 From: Nick Andrew Date: Wed, 7 Jan 2009 23:14:39 +0800 Subject: Blackfin arch: Fix incorrect use of loose in cpufreq.c It should be 'lose', not 'loose'. Signed-off-by: Nick Andrew Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c index dda5443..56f68d8 100644 --- a/arch/blackfin/mach-common/cpufreq.c +++ b/arch/blackfin/mach-common/cpufreq.c @@ -112,7 +112,7 @@ static int bfin_target(struct cpufreq_policy *policy, bfin_write_TSCALE(tscale); cycles = get_cycles(); SSYNC(); - cycles += 10; /* ~10 cycles we loose after get_cycles() */ + cycles += 10; /* ~10 cycles we lose after get_cycles() */ __bfin_cycles_off += (cycles << __bfin_cycles_mod) - (cycles << index); __bfin_cycles_mod = index; local_irq_restore(flags); -- cgit v1.1 From dbdf20db537a5369c65330f878ad4905020a8bfa Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Wed, 7 Jan 2009 23:14:38 +0800 Subject: Blackfin arch: Faster C implementation of no-MPU CPLB handler This is a mixture ofcMichael McTernan's patch and the existing cplb-mpu code. We ditch the old cplb-nompu implementation, which is a good example of why a good algorithm in a HLL is preferrable to a bad algorithm written in assembly. Rather than try to construct a table of all posible CPLBs and search it, we just create a (smaller) table of memory regions and their attributes. Some of the data structures are now unified for both the mpu and nompu cases. A lot of needless complexity in cplbinit.c is removed. Further optimizations: * compile cplbmgr.c with a lot of -ffixed-reg options, and omit saving these registers on the stack when entering a CPLB exception. * lose cli/nop/nop/sti sequences for some workarounds - these don't * make sense in an exception context Additional code unification should be possible after this. [Mike Frysinger : - convert CPP if statements to C if statements - remove redundant statements - use a do...while loop rather than a for loop to get slightly better optimization and to avoid gcc "may be used uninitialized" warnings ... we know that the [id]cplb_nr_bounds variables will never be 0, so this is OK - the no-mpu code was the last user of MAX_MEM_SIZE and with that rewritten, we can punt it - add some BUG_ON() checks to make sure we dont overflow the small cplb_bounds array - add i/d cplb entries for the bootrom because there is functions/data in there we want to access - we do not need a NULL trailing entry as any time we access the bounds arrays, we use the nr_bounds variable ] Signed-off-by: Michael McTernan Signed-off-by: Mike Frysinger Signed-off-by: Bernd Schmidt Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/entry.S | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 0efd5f5..fae7746 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -112,24 +112,21 @@ ENTRY(_ex_dcplb_viol) ENTRY(_ex_dcplb_miss) ENTRY(_ex_icplb_miss) (R7:6,P5:4) = [sp++]; - ASTAT = [sp++]; - SAVE_ALL_SYS -#ifdef CONFIG_MPU + /* We leave the previously pushed ASTAT on the stack. */ + SAVE_CONTEXT_CPLB + /* We must load R1 here, _before_ DEBUG_HWTRACE_SAVE, since that * will change the stack pointer. */ R0 = SEQSTAT; R1 = SP; -#endif + DEBUG_HWTRACE_SAVE(p5, r7) -#ifdef CONFIG_MPU + sp += -12; call _cplb_hdr; sp += 12; CC = R0 == 0; IF !CC JUMP _handle_bad_cplb; -#else - call __cplb_hdr; -#endif #ifdef CONFIG_DEBUG_DOUBLEFAULT /* While we were processing this, did we double fault? */ @@ -143,7 +140,8 @@ ENTRY(_ex_icplb_miss) #endif DEBUG_HWTRACE_RESTORE(p5, r7) - RESTORE_ALL_SYS + RESTORE_CONTEXT_CPLB + ASTAT = [SP++]; SP = EX_SCRATCH_REG; rtx; ENDPROC(_ex_icplb_miss) @@ -298,9 +296,8 @@ ENTRY(_handle_bad_cplb) * the stack to get ready so, we can fall through - we * need to make a CPLB exception look like a normal exception */ - - RESTORE_ALL_SYS - [--sp] = ASTAT; + RESTORE_CONTEXT_CPLB + /* ASTAT is still on the stack, where it is needed. */ [--sp] = (R7:6,P5:4); ENTRY(_ex_replaceable) -- cgit v1.1 From 6a01f230339321292cf065551f8cf55361052461 Mon Sep 17 00:00:00 2001 From: Yi Li Date: Wed, 7 Jan 2009 23:14:39 +0800 Subject: Blackfin arch: merge adeos blackfin part to arch/blackfin/ [Mike Frysinger : - handle bf531/bf532/bf534/bf536 variants in ipipe.h - cleanup IPIPE logic for bfin_set_irq_handler() - cleanup ipipe asm code a bit and add missing ENDPROC() - simplify IPIPE code in trap_c - unify some of the IPIPE code and fix style - simplify DO_IRQ_L1 handling with ipipe code - revert IRQ_SW_INT# addition from ipipe merge - remove duplicate get_{c,s}clk() prototypes ] Signed-off-by: Yi Li Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/cpufreq.c | 4 +- arch/blackfin/mach-common/interrupt.S | 60 ++++++++ arch/blackfin/mach-common/ints-priority.c | 235 +++++++++++++++++++++++++++--- arch/blackfin/mach-common/pm.c | 10 +- arch/blackfin/mach-common/smp.c | 4 +- 5 files changed, 281 insertions(+), 32 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c index 56f68d8..72e1660 100644 --- a/arch/blackfin/mach-common/cpufreq.c +++ b/arch/blackfin/mach-common/cpufreq.c @@ -104,7 +104,7 @@ static int bfin_target(struct cpufreq_policy *policy, cclk_hz, target_freq, freqs.old); cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - local_irq_save(flags); + local_irq_save_hw(flags); plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel; tscale = dpm_state_table[index].tscale; bfin_write_PLL_DIV(plldiv); @@ -115,7 +115,7 @@ static int bfin_target(struct cpufreq_policy *policy, cycles += 10; /* ~10 cycles we lose after get_cycles() */ __bfin_cycles_off += (cycles << __bfin_cycles_mod) - (cycles << index); __bfin_cycles_mod = index; - local_irq_restore(flags); + local_irq_restore_hw(flags); /* TODO: just test case for cycles clock source, remove later */ pr_debug("cpufreq: done\n"); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index 2604b53..c1bdd1e 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -129,8 +129,15 @@ __common_int_entry: #endif r1 = sp; SP += -12; +#ifdef CONFIG_IPIPE + call ___ipipe_grab_irq + SP += 12; + cc = r0 == 0; + if cc jump .Lcommon_restore_context; +#else /* CONFIG_IPIPE */ call _do_irq; SP += 12; +#endif /* CONFIG_IPIPE */ call _return_from_int; .Lcommon_restore_context: RESTORE_CONTEXT @@ -247,3 +254,56 @@ ENTRY(_evt_system_call) call _system_call; jump .Lcommon_restore_context; ENDPROC(_evt_system_call) + +#ifdef CONFIG_IPIPE +ENTRY(___ipipe_call_irqtail) + r0.l = 1f; + r0.h = 1f; + reti = r0; + rti; +1: + [--sp] = rets; + [--sp] = ( r7:4, p5:3 ); + p0.l = ___ipipe_irq_tail_hook; + p0.h = ___ipipe_irq_tail_hook; + p0 = [p0]; + sp += -12; + call (p0); + sp += 12; + ( r7:4, p5:3 ) = [sp++]; + rets = [sp++]; + + [--sp] = reti; + reti = [sp++]; /* IRQs are off. */ + r0.h = 3f; + r0.l = 3f; + p0.l = lo(EVT14); + p0.h = hi(EVT14); + [p0] = r0; + csync; + r0 = 0x401f; + sti r0; + raise 14; + [--sp] = reti; /* IRQs on. */ +2: + jump 2b; /* Likely paranoid. */ +3: + sp += 4; /* Discard saved RETI */ + r0.h = _evt14_softirq; + r0.l = _evt14_softirq; + p0.l = lo(EVT14); + p0.h = hi(EVT14); + [p0] = r0; + csync; + p0.l = _bfin_irq_flags; + p0.h = _bfin_irq_flags; + r0 = [p0]; + sti r0; +#if 0 /* FIXME: this actually raises scheduling latencies */ + /* Reenable interrupts */ + [--sp] = reti; + r0 = [sp++]; +#endif + rts; +ENDPROC(___ipipe_call_irqtail) +#endif /* CONFIG_IPIPE */ diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 7c1db77..1bba603 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -34,6 +34,9 @@ #include #include #include +#ifdef CONFIG_IPIPE +#include +#endif #ifdef CONFIG_KGDB #include #endif @@ -135,8 +138,8 @@ static void bfin_ack_noop(unsigned int irq) static void bfin_core_mask_irq(unsigned int irq) { bfin_irq_flags &= ~(1 << irq); - if (!irqs_disabled()) - local_irq_enable(); + if (!irqs_disabled_hw()) + local_irq_enable_hw(); } static void bfin_core_unmask_irq(unsigned int irq) @@ -151,8 +154,8 @@ static void bfin_core_unmask_irq(unsigned int irq) * local_irq_enable just does "STI bfin_irq_flags", so it's exactly * what we need. */ - if (!irqs_disabled()) - local_irq_enable(); + if (!irqs_disabled_hw()) + local_irq_enable_hw(); return; } @@ -235,7 +238,7 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state) break; } - local_irq_save(flags); + local_irq_save_hw(flags); if (state) { bfin_sic_iwr[bank] |= (1 << bit); @@ -246,7 +249,7 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state) vr_wakeup &= ~wakeup; } - local_irq_restore(flags); + local_irq_restore_hw(flags); return 0; } @@ -272,6 +275,19 @@ static struct irq_chip bfin_internal_irqchip = { #endif }; +static void bfin_handle_irq(unsigned irq) +{ +#ifdef CONFIG_IPIPE + struct pt_regs regs; /* Contents not used. */ + ipipe_trace_irq_entry(irq); + __ipipe_handle_irq(irq, ®s); + ipipe_trace_irq_exit(irq); +#else /* !CONFIG_IPIPE */ + struct irq_desc *desc = irq_desc + irq; + desc->handle_irq(irq, desc); +#endif /* !CONFIG_IPIPE */ +} + #ifdef BF537_GENERIC_ERROR_INT_DEMUX static int error_int_mask; @@ -325,10 +341,9 @@ static void bfin_demux_error_irq(unsigned int int_err_irq, irq = IRQ_UART1_ERROR; if (irq) { - if (error_int_mask & (1L << (irq - IRQ_PPI_ERROR))) { - struct irq_desc *desc = irq_desc + irq; - desc->handle_irq(irq, desc); - } else { + if (error_int_mask & (1L << (irq - IRQ_PPI_ERROR))) + bfin_handle_irq(irq); + else { switch (irq) { case IRQ_PPI_ERROR: @@ -374,10 +389,14 @@ static void bfin_demux_error_irq(unsigned int int_err_irq, static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle) { +#ifdef CONFIG_IPIPE + _set_irq_handler(irq, handle_edge_irq); +#else struct irq_desc *desc = irq_desc + irq; /* May not call generic set_irq_handler() due to spinlock recursion. */ desc->handle_irq = handle; +#endif } static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS); @@ -563,10 +582,8 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq, mask = get_gpiop_data(i) & get_gpiop_maska(i); while (mask) { - if (mask & 1) { - desc = irq_desc + irq; - desc->handle_irq(irq, desc); - } + if (mask & 1) + bfin_handle_irq(irq); irq++; mask >>= 1; } @@ -576,10 +593,8 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq, mask = get_gpiop_data(gpio) & get_gpiop_maska(gpio); do { - if (mask & 1) { - desc = irq_desc + irq; - desc->handle_irq(irq, desc); - } + if (mask & 1) + bfin_handle_irq(irq); irq++; mask >>= 1; } while (mask); @@ -900,8 +915,7 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq, while (request) { if (request & 1) { irq = pint2irq_lut[pint_val] + SYS_IRQS; - desc = irq_desc + irq; - desc->handle_irq(irq, desc); + bfin_handle_irq(irq); } pint_val++; request >>= 1; @@ -1025,11 +1039,10 @@ int __init init_arch_irq(void) break; #ifdef BF537_GENERIC_ERROR_INT_DEMUX case IRQ_GENERIC_ERROR: - set_irq_handler(irq, bfin_demux_error_irq); - + set_irq_chained_handler(irq, bfin_demux_error_irq); break; #endif -#ifdef CONFIG_TICK_SOURCE_SYSTMR0 +#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE) case IRQ_TIMER0: set_irq_handler(irq, handle_percpu_irq); break; @@ -1041,7 +1054,17 @@ int __init init_arch_irq(void) break; #endif default: +#ifdef CONFIG_IPIPE + /* + * We want internal interrupt sources to be masked, because + * ISRs may trigger interrupts recursively (e.g. DMA), but + * interrupts are _not_ masked at CPU level. So let's handle + * them as level interrupts. + */ + set_irq_handler(irq, handle_level_irq); +#else /* !CONFIG_IPIPE */ set_irq_handler(irq, handle_simple_irq); +#endif /* !CONFIG_IPIPE */ break; } } @@ -1101,6 +1124,14 @@ int __init init_arch_irq(void) bfin_write_SIC_IWR(IWR_DISABLE_ALL); #endif +#ifdef CONFIG_IPIPE + for (irq = 0; irq < NR_IRQS; irq++) { + struct irq_desc *desc = irq_desc + irq; + desc->ic_prio = __ipipe_get_irq_priority(irq); + desc->thr_prio = __ipipe_get_irqthread_priority(irq); + } +#endif /* CONFIG_IPIPE */ + return 0; } @@ -1156,3 +1187,161 @@ void do_irq(int vec, struct pt_regs *fp) } asm_do_IRQ(vec, fp); } + +#ifdef CONFIG_IPIPE + +int __ipipe_get_irq_priority(unsigned irq) +{ + int ient, prio; + + if (irq <= IRQ_CORETMR) + return irq; + + for (ient = 0; ient < NR_PERI_INTS; ient++) { + struct ivgx *ivg = ivg_table + ient; + if (ivg->irqno == irq) { + for (prio = 0; prio <= IVG13-IVG7; prio++) { + if (ivg7_13[prio].ifirst <= ivg && + ivg7_13[prio].istop > ivg) + return IVG7 + prio; + } + } + } + + return IVG15; +} + +int __ipipe_get_irqthread_priority(unsigned irq) +{ + int ient, prio; + int demux_irq; + + /* The returned priority value is rescaled to [0..IVG13+1] + * with 0 being the lowest effective priority level. */ + + if (irq <= IRQ_CORETMR) + return IVG13 - irq + 1; + + /* GPIO IRQs are given the priority of the demux + * interrupt. */ + if (IS_GPIOIRQ(irq)) { +#if defined(CONFIG_BF54x) + u32 bank = PINT_2_BANK(irq2pint_lut[irq - SYS_IRQS]); + demux_irq = (bank == 0 ? IRQ_PINT0 : + bank == 1 ? IRQ_PINT1 : + bank == 2 ? IRQ_PINT2 : + IRQ_PINT3); +#elif defined(CONFIG_BF561) + demux_irq = (irq >= IRQ_PF32 ? IRQ_PROG2_INTA : + irq >= IRQ_PF16 ? IRQ_PROG1_INTA : + IRQ_PROG0_INTA); +#elif defined(CONFIG_BF52x) + demux_irq = (irq >= IRQ_PH0 ? IRQ_PORTH_INTA : + irq >= IRQ_PG0 ? IRQ_PORTG_INTA : + IRQ_PORTF_INTA); +#else + demux_irq = irq; +#endif + return IVG13 - PRIO_GPIODEMUX(demux_irq) + 1; + } + + /* The GPIO demux interrupt is given a lower priority + * than the GPIO IRQs, so that its threaded handler + * unmasks the interrupt line after the decoded IRQs + * have been processed. */ + prio = PRIO_GPIODEMUX(irq); + /* demux irq? */ + if (prio != -1) + return IVG13 - prio; + + for (ient = 0; ient < NR_PERI_INTS; ient++) { + struct ivgx *ivg = ivg_table + ient; + if (ivg->irqno == irq) { + for (prio = 0; prio <= IVG13-IVG7; prio++) { + if (ivg7_13[prio].ifirst <= ivg && + ivg7_13[prio].istop > ivg) + return IVG7 - prio; + } + } + } + + return 0; +} + +/* Hw interrupts are disabled on entry (check SAVE_CONTEXT). */ +#ifdef CONFIG_DO_IRQ_L1 +__attribute__((l1_text)) +#endif +asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) +{ + struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop; + struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst; + int irq; + + if (likely(vec == EVT_IVTMR_P)) { + irq = IRQ_CORETMR; + goto handle_irq; + } + + SSYNC(); + +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) + { + unsigned long sic_status[3]; + + sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0(); + sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1(); +#ifdef CONFIG_BF54x + sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2(); +#endif + for (;; ivg++) { + if (ivg >= ivg_stop) { + atomic_inc(&num_spurious); + return 0; + } + if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag) + break; + } + } +#else + { + unsigned long sic_status; + + sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR(); + + for (;; ivg++) { + if (ivg >= ivg_stop) { + atomic_inc(&num_spurious); + return 0; + } else if (sic_status & ivg->isrflag) + break; + } + } +#endif + + irq = ivg->irqno; + + if (irq == IRQ_SYSTMR) { + bfin_write_TIMER_STATUS(1); /* Latch TIMIL0 */ + /* This is basically what we need from the register frame. */ + __raw_get_cpu_var(__ipipe_tick_regs).ipend = regs->ipend; + __raw_get_cpu_var(__ipipe_tick_regs).pc = regs->pc; + if (!ipipe_root_domain_p) + __raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10; + else + __raw_get_cpu_var(__ipipe_tick_regs).ipend &= ~0x10; + } + +handle_irq: + + ipipe_trace_irq_entry(irq); + __ipipe_handle_irq(irq, regs); + ipipe_trace_irq_exit(irq); + + if (ipipe_root_domain_p) + return !test_bit(IPIPE_STALL_FLAG, &ipipe_root_cpudom_var(status)); + + return 0; +} + +#endif /* CONFIG_IPIPE */ diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index 96600b8..d3d70fd 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -71,7 +71,7 @@ void bfin_pm_suspend_standby_enter(void) gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE); #endif - local_irq_save(flags); + local_irq_save_hw(flags); bfin_pm_standby_setup(); #ifdef CONFIG_PM_BFIN_SLEEP_DEEPER @@ -105,7 +105,7 @@ void bfin_pm_suspend_standby_enter(void) bfin_write_SIC_IWR(IWR_DISABLE_ALL); #endif - local_irq_restore(flags); + local_irq_restore_hw(flags); } int bf53x_suspend_l1_mem(unsigned char *memptr) @@ -249,12 +249,12 @@ int bfin_pm_suspend_mem_enter(void) wakeup |= GPWE; #endif - local_irq_save(flags); + local_irq_save_hw(flags); ret = blackfin_dma_suspend(); if (ret) { - local_irq_restore(flags); + local_irq_restore_hw(flags); kfree(memptr); return ret; } @@ -275,7 +275,7 @@ int bfin_pm_suspend_mem_enter(void) bfin_gpio_pm_hibernate_restore(); blackfin_dma_resume(); - local_irq_restore(flags); + local_irq_restore_hw(flags); kfree(memptr); return 0; diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 66c47a7..77c9928 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -348,7 +348,7 @@ int __cpuinit __cpu_up(unsigned int cpu) static void __cpuinit setup_secondary(unsigned int cpu) { -#ifndef CONFIG_TICK_SOURCE_SYSTMR0 +#if !(defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)) struct irq_desc *timer_desc; #endif unsigned long ilat; @@ -369,7 +369,7 @@ static void __cpuinit setup_secondary(unsigned int cpu) IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; -#ifdef CONFIG_TICK_SOURCE_SYSTMR0 +#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE) /* Power down the core timer, just to play safe. */ bfin_write_TCNTL(0); -- cgit v1.1 From 172e65e778ad500da26d59965750966e1ac7be51 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Wed, 7 Jan 2009 23:14:39 +0800 Subject: Blackfin arch: remove hardware PM code, oprofile not use it Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/interrupt.S | 22 ---------------------- arch/blackfin/mach-common/irqpanic.c | 12 ------------ 2 files changed, 34 deletions(-) (limited to 'arch/blackfin/mach-common') diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index c1bdd1e..473df0f 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -165,16 +165,6 @@ ENTRY(_evt_ivhw) r0 = [p2]; [sp + PT_IPEND] = r0; -#ifdef CONFIG_HARDWARE_PM - r7 = [sp + PT_SEQSTAT]; - r7 = r7 >>> 0xe; - r6 = 0x1F; - r7 = r7 & r6; - r5 = 0x12; - cc = r7 == r5; - if cc jump .Lcall_do_ovf; /* deal with performance counter overflow */ -#endif - /* set the EXCAUSE to HWERR for trap_c */ r0 = [sp + PT_SEQSTAT]; R1.L = LO(VEC_HWERR); @@ -200,18 +190,6 @@ ENTRY(_evt_ivhw) .Lcommon_restore_all_sys: RESTORE_ALL_SYS rti; - -#ifdef CONFIG_HARDWARE_PM -.Lcall_do_ovf: - - R0 = SP; - SP += -12; - call _pm_overflow; - SP += 12; - - jump .Lcommon_restore_all_sys; -#endif - ENDPROC(_evt_ivhw) /* Interrupt routine for evt2 (NMI). diff --git a/arch/blackfin/mach-common/irqpanic.c b/arch/blackfin/mach-common/irqpanic.c index 7b69413..05004df 100644 --- a/arch/blackfin/mach-common/irqpanic.c +++ b/arch/blackfin/mach-common/irqpanic.c @@ -33,8 +33,6 @@ #include #include -#include "../oprofile/op_blackfin.h" - #ifdef CONFIG_DEBUG_ICACHE_CHECK #define L1_ICACHE_START 0xffa10000 #define L1_ICACHE_END 0xffa13fff @@ -134,13 +132,3 @@ asmlinkage void irq_panic(int reason, struct pt_regs *regs) #endif } - -#ifdef CONFIG_HARDWARE_PM -/* - * call the handler of Performance overflow - */ -asmlinkage void pm_overflow(struct pt_regs *regs) -{ - pm_overflow_handler(regs); -} -#endif -- cgit v1.1