diff options
Diffstat (limited to 'arch/blackfin/mach-common')
-rw-r--r-- | arch/blackfin/mach-common/Makefile | 1 | ||||
-rw-r--r-- | arch/blackfin/mach-common/cpufreq.c | 4 | ||||
-rw-r--r-- | arch/blackfin/mach-common/dpmc_modes.S | 50 | ||||
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 116 | ||||
-rw-r--r-- | arch/blackfin/mach-common/interrupt.S | 17 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority.c | 35 | ||||
-rw-r--r-- | arch/blackfin/mach-common/irqpanic.c | 106 | ||||
-rw-r--r-- | arch/blackfin/mach-common/pm.c | 10 |
8 files changed, 157 insertions, 182 deletions
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile index 814cb483853b..ff299f24aba0 100644 --- a/arch/blackfin/mach-common/Makefile +++ b/arch/blackfin/mach-common/Makefile @@ -11,4 +11,3 @@ 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 -obj-$(CONFIG_DEBUG_ICACHE_CHECK) += irqpanic.o diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c index 4391d03dc845..f4cf11d362e1 100644 --- a/arch/blackfin/mach-common/cpufreq.c +++ b/arch/blackfin/mach-common/cpufreq.c @@ -134,7 +134,7 @@ static int bfin_target(struct cpufreq_policy *poli, cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); if (cpu == CPUFREQ_CPU) { - local_irq_save_hw(flags); + flags = hard_local_irq_save(); plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel; bfin_write_PLL_DIV(plldiv); @@ -155,7 +155,7 @@ static int bfin_target(struct cpufreq_policy *poli, loops_per_jiffy = cpufreq_scale(lpj_ref, lpj_ref_freq, freqs.new); } - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); } /* TODO: just test case for cycles clock source, remove later */ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S index 5969d86836a5..9cfdd49a3127 100644 --- a/arch/blackfin/mach-common/dpmc_modes.S +++ b/arch/blackfin/mach-common/dpmc_modes.S @@ -292,13 +292,7 @@ ENTRY(_do_hibernate) #ifdef SIC_IMASK PM_SYS_PUSH(SIC_IMASK) #endif -#ifdef SICA_IMASK0 - PM_SYS_PUSH(SICA_IMASK0) -#endif -#ifdef SICA_IMASK1 - PM_SYS_PUSH(SICA_IMASK1) -#endif -#ifdef SIC_IAR2 +#ifdef SIC_IAR0 PM_SYS_PUSH(SIC_IAR0) PM_SYS_PUSH(SIC_IAR1) PM_SYS_PUSH(SIC_IAR2) @@ -321,17 +315,6 @@ ENTRY(_do_hibernate) PM_SYS_PUSH(SIC_IAR11) #endif -#ifdef SICA_IAR0 - PM_SYS_PUSH(SICA_IAR0) - PM_SYS_PUSH(SICA_IAR1) - PM_SYS_PUSH(SICA_IAR2) - PM_SYS_PUSH(SICA_IAR3) - PM_SYS_PUSH(SICA_IAR4) - PM_SYS_PUSH(SICA_IAR5) - PM_SYS_PUSH(SICA_IAR6) - PM_SYS_PUSH(SICA_IAR7) -#endif - #ifdef SIC_IWR PM_SYS_PUSH(SIC_IWR) #endif @@ -344,12 +327,6 @@ ENTRY(_do_hibernate) #ifdef SIC_IWR2 PM_SYS_PUSH(SIC_IWR2) #endif -#ifdef SICA_IWR0 - PM_SYS_PUSH(SICA_IWR0) -#endif -#ifdef SICA_IWR1 - PM_SYS_PUSH(SICA_IWR1) -#endif #ifdef PINT0_ASSIGN PM_SYS_PUSH(PINT0_MASK_SET) @@ -750,12 +727,6 @@ ENTRY(_do_hibernate) PM_SYS_POP(PINT0_MASK_SET) #endif -#ifdef SICA_IWR1 - PM_SYS_POP(SICA_IWR1) -#endif -#ifdef SICA_IWR0 - PM_SYS_POP(SICA_IWR0) -#endif #ifdef SIC_IWR2 PM_SYS_POP(SIC_IWR2) #endif @@ -769,17 +740,6 @@ ENTRY(_do_hibernate) PM_SYS_POP(SIC_IWR) #endif -#ifdef SICA_IAR0 - PM_SYS_POP(SICA_IAR7) - PM_SYS_POP(SICA_IAR6) - PM_SYS_POP(SICA_IAR5) - PM_SYS_POP(SICA_IAR4) - PM_SYS_POP(SICA_IAR3) - PM_SYS_POP(SICA_IAR2) - PM_SYS_POP(SICA_IAR1) - PM_SYS_POP(SICA_IAR0) -#endif - #ifdef SIC_IAR8 PM_SYS_POP(SIC_IAR11) PM_SYS_POP(SIC_IAR10) @@ -797,17 +757,11 @@ ENTRY(_do_hibernate) #ifdef SIC_IAR3 PM_SYS_POP(SIC_IAR3) #endif -#ifdef SIC_IAR2 +#ifdef SIC_IAR0 PM_SYS_POP(SIC_IAR2) PM_SYS_POP(SIC_IAR1) PM_SYS_POP(SIC_IAR0) #endif -#ifdef SICA_IMASK1 - PM_SYS_POP(SICA_IMASK1) -#endif -#ifdef SICA_IMASK0 - PM_SYS_POP(SICA_IMASK0) -#endif #ifdef SIC_IMASK PM_SYS_POP(SIC_IMASK) #endif diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index a5847f5d67c7..2ca915ee181f 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -889,6 +889,66 @@ ENTRY(_ret_from_exception) rts; ENDPROC(_ret_from_exception) +#if defined(CONFIG_PREEMPT) + +ENTRY(_up_to_irq14) +#if ANOMALY_05000281 || ANOMALY_05000461 + r0.l = lo(SAFE_USER_INSTRUCTION); + r0.h = hi(SAFE_USER_INSTRUCTION); + reti = r0; +#endif + +#ifdef CONFIG_DEBUG_HWERR + /* enable irq14 & hwerr interrupt, until we transition to _evt_evt14 */ + r0 = (EVT_IVG14 | EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU); +#else + /* Only enable irq14 interrupt, until we transition to _evt_evt14 */ + r0 = (EVT_IVG14 | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU); +#endif + sti r0; + + p0.l = lo(EVT14); + p0.h = hi(EVT14); + p1.l = _evt_up_evt14; + p1.h = _evt_up_evt14; + [p0] = p1; + csync; + + raise 14; +1: + jump 1b; +ENDPROC(_up_to_irq14) + +ENTRY(_evt_up_evt14) +#ifdef CONFIG_DEBUG_HWERR + r0 = (EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU); + sti r0; +#else + cli r0; +#endif +#ifdef CONFIG_TRACE_IRQFLAGS + [--sp] = rets; + sp += -12; + call _trace_hardirqs_off; + sp += 12; + rets = [sp++]; +#endif + [--sp] = RETI; + SP += 4; + + /* restore normal evt14 */ + p0.l = lo(EVT14); + p0.h = hi(EVT14); + p1.l = _evt_evt14; + p1.h = _evt_evt14; + [p0] = p1; + csync; + + rts; +ENDPROC(_evt_up_evt14) + +#endif + #ifdef CONFIG_IPIPE _resume_kernel_from_int: @@ -902,8 +962,54 @@ _resume_kernel_from_int: ( r7:4, p5:3 ) = [sp++]; rets = [sp++]; rts +#elif defined(CONFIG_PREEMPT) + +_resume_kernel_from_int: + /* check preempt_count */ + r7 = sp; + r4.l = lo(ALIGN_PAGE_MASK); + r4.h = hi(ALIGN_PAGE_MASK); + r7 = r7 & r4; + p5 = r7; + r7 = [p5 + TI_PREEMPT]; + cc = r7 == 0x0; + if !cc jump .Lreturn_to_kernel; +.Lneed_schedule: + r7 = [p5 + TI_FLAGS]; + r4.l = lo(_TIF_WORK_MASK); + r4.h = hi(_TIF_WORK_MASK); + r7 = r7 & r4; + cc = BITTST(r7, TIF_NEED_RESCHED); + if !cc jump .Lreturn_to_kernel; + /* + * let schedule done at level 15, otherwise sheduled process will run + * at high level and block low level interrupt + */ + r6 = reti; /* save reti */ + r5.l = .Lkernel_schedule; + r5.h = .Lkernel_schedule; + reti = r5; + rti; +.Lkernel_schedule: + [--sp] = rets; + sp += -12; + pseudo_long_call _preempt_schedule_irq, p4; + sp += 12; + rets = [sp++]; + + [--sp] = rets; + sp += -12; + /* up to irq14 so that reti after restore_all can return to irq15(kernel) */ + pseudo_long_call _up_to_irq14, p4; + sp += 12; + rets = [sp++]; + + reti = r6; /* restore reti so that origin process can return to interrupted point */ + + jump .Lneed_schedule; #else -#define _resume_kernel_from_int 2f + +#define _resume_kernel_from_int .Lreturn_to_kernel #endif ENTRY(_return_from_int) @@ -913,7 +1019,7 @@ ENTRY(_return_from_int) p2.h = hi(ILAT); r0 = [p2]; cc = bittst (r0, EVT_IVG15_P); - if cc jump 2f; + if cc jump .Lreturn_to_kernel; /* if not return to user mode, get out */ p2.l = lo(IPEND); @@ -945,7 +1051,7 @@ ENTRY(_return_from_int) STI r0; raise 15; /* raise evt15 to do signal or reschedule */ rti; -2: +.Lreturn_to_kernel: rts; ENDPROC(_return_from_int) @@ -1628,6 +1734,10 @@ ENTRY(_sys_call_table) .long _sys_rt_tgsigqueueinfo .long _sys_perf_event_open .long _sys_recvmmsg /* 370 */ + .long _sys_fanotify_init + .long _sys_fanotify_mark + .long _sys_prlimit64 + .long _sys_cacheflush .rept NR_syscalls-(.-_sys_call_table)/4 .long _sys_ni_syscall diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index cee62cf4acd4..2df37db3b49b 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -116,7 +116,24 @@ __common_int_entry: cc = r0 == 0; if cc jump .Lcommon_restore_context; #else /* CONFIG_IPIPE */ + +#ifdef CONFIG_PREEMPT + r7 = sp; + r4.l = lo(ALIGN_PAGE_MASK); + r4.h = hi(ALIGN_PAGE_MASK); + r7 = r7 & r4; + p5 = r7; + r7 = [p5 + TI_PREEMPT]; /* get preempt count */ + r7 += 1; /* increment it */ + [p5 + TI_PREEMPT] = r7; +#endif pseudo_long_call _do_irq, p2; + +#ifdef CONFIG_PREEMPT + r7 += -1; + [p5 + TI_PREEMPT] = r7; /* restore preempt count */ +#endif + SP += 12; #endif /* CONFIG_IPIPE */ pseudo_long_call _return_from_int, p2; diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 1c8c4c7245c3..da7e3c63746b 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -132,8 +132,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_hw()) - local_irq_enable_hw(); + if (!hard_irqs_disabled()) + hard_local_irq_enable(); } static void bfin_core_unmask_irq(unsigned int irq) @@ -148,8 +148,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_hw()) - local_irq_enable_hw(); + if (!hard_irqs_disabled()) + hard_local_irq_enable(); return; } @@ -158,12 +158,12 @@ static void bfin_internal_mask_irq(unsigned int irq) unsigned long flags; #ifdef CONFIG_BF53x - local_irq_save_hw(flags); + flags = hard_local_irq_save(); bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() & ~(1 << SIC_SYSIRQ(irq))); #else unsigned mask_bank, mask_bit; - local_irq_save_hw(flags); + flags = hard_local_irq_save(); mask_bank = SIC_SYSIRQ(irq) / 32; mask_bit = SIC_SYSIRQ(irq) % 32; bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) & @@ -173,7 +173,7 @@ static void bfin_internal_mask_irq(unsigned int irq) ~(1 << mask_bit)); #endif #endif - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); } #ifdef CONFIG_SMP @@ -186,12 +186,12 @@ static void bfin_internal_unmask_irq(unsigned int irq) unsigned long flags; #ifdef CONFIG_BF53x - local_irq_save_hw(flags); + flags = hard_local_irq_save(); bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() | (1 << SIC_SYSIRQ(irq))); #else unsigned mask_bank, mask_bit; - local_irq_save_hw(flags); + flags = hard_local_irq_save(); mask_bank = SIC_SYSIRQ(irq) / 32; mask_bit = SIC_SYSIRQ(irq) % 32; #ifdef CONFIG_SMP @@ -207,7 +207,7 @@ static void bfin_internal_unmask_irq(unsigned int irq) (1 << mask_bit)); #endif #endif - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); } #ifdef CONFIG_SMP @@ -264,7 +264,7 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state) break; } - local_irq_save_hw(flags); + flags = hard_local_irq_save(); if (state) { bfin_sic_iwr[bank] |= (1 << bit); @@ -275,7 +275,7 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state) vr_wakeup &= ~wakeup; } - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); return 0; } @@ -511,7 +511,7 @@ static void bfin_demux_mac_status_irq(unsigned int int_err_irq, int i, irq = 0; u32 status = bfin_read_EMAC_SYSTAT(); - for (i = 0; i < (IRQ_MAC_STMDONE - IRQ_MAC_PHYINT); i++) + for (i = 0; i <= (IRQ_MAC_STMDONE - IRQ_MAC_PHYINT); i++) if (status & (1L << i)) { irq = IRQ_MAC_PHYINT + i; break; @@ -529,8 +529,9 @@ static void bfin_demux_mac_status_irq(unsigned int int_err_irq, } else printk(KERN_ERR "%s : %s : LINE %d :\nIRQ ?: MAC ERROR" - " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n", - __func__, __FILE__, __LINE__); + " INTERRUPT ASSERTED BUT NO SOURCE FOUND" + "(EMAC_SYSTAT=0x%X)\n", + __func__, __FILE__, __LINE__, status); } #endif @@ -1298,7 +1299,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(SIC_ISR0) || defined(SICA_ISR0) +#if defined(SIC_ISR0) unsigned long sic_status[3]; if (smp_processor_id()) { @@ -1378,7 +1379,7 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) if (likely(vec == EVT_IVTMR_P)) irq = IRQ_CORETMR; else { -#if defined(SIC_ISR0) || defined(SICA_ISR0) +#if defined(SIC_ISR0) unsigned long sic_status[3]; sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0(); diff --git a/arch/blackfin/mach-common/irqpanic.c b/arch/blackfin/mach-common/irqpanic.c deleted file mode 100644 index c6496249e2bc..000000000000 --- a/arch/blackfin/mach-common/irqpanic.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * panic kernel with dump information - * - * Copyright 2005-2009 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/module.h> -#include <linux/kernel_stat.h> -#include <linux/sched.h> -#include <asm/blackfin.h> - -#define L1_ICACHE_START 0xffa10000 -#define L1_ICACHE_END 0xffa13fff - -/* - * irq_panic - calls panic with string setup - */ -__attribute__ ((l1_text)) -asmlinkage void irq_panic(int reason, struct pt_regs *regs) -{ - unsigned int cmd, tag, ca, cache_hi, cache_lo, *pa; - unsigned short i, j, die; - unsigned int bad[10][6]; - - /* check entire cache for coherency - * Since printk is in cacheable memory, - * don't call it until you have checked everything - */ - - die = 0; - i = 0; - - /* check icache */ - - for (ca = L1_ICACHE_START; ca <= L1_ICACHE_END && i < 10; ca += 32) { - - /* Grab various address bits for the itest_cmd fields */ - cmd = (((ca & 0x3000) << 4) | /* ca[13:12] for SBNK[1:0] */ - ((ca & 0x0c00) << 16) | /* ca[11:10] for WAYSEL[1:0] */ - ((ca & 0x3f8)) | /* ca[09:03] for SET[4:0] and DW[1:0] */ - 0); /* Access Tag, Read access */ - - SSYNC(); - bfin_write_ITEST_COMMAND(cmd); - SSYNC(); - tag = bfin_read_ITEST_DATA0(); - SSYNC(); - - /* if tag is marked as valid, check it */ - if (tag & 1) { - /* The icache is arranged in 4 groups of 64-bits */ - for (j = 0; j < 32; j += 8) { - cmd = ((((ca + j) & 0x3000) << 4) | /* ca[13:12] for SBNK[1:0] */ - (((ca + j) & 0x0c00) << 16) | /* ca[11:10] for WAYSEL[1:0] */ - (((ca + j) & 0x3f8)) | /* ca[09:03] for SET[4:0] and DW[1:0] */ - 4); /* Access Data, Read access */ - - SSYNC(); - bfin_write_ITEST_COMMAND(cmd); - SSYNC(); - - cache_hi = bfin_read_ITEST_DATA1(); - cache_lo = bfin_read_ITEST_DATA0(); - - pa = ((unsigned int *)((tag & 0xffffcc00) | - ((ca + j) & ~(0xffffcc00)))); - - /* - * Debugging this, enable - * - * printk("addr: %08x %08x%08x | %08x%08x\n", - * ((unsigned int *)((tag & 0xffffcc00) | ((ca+j) & ~(0xffffcc00)))), - * cache_hi, cache_lo, *(pa+1), *pa); - */ - - if (cache_hi != *(pa + 1) || cache_lo != *pa) { - /* Since icache is not working, stay out of it, by not printing */ - die = 1; - bad[i][0] = (ca + j); - bad[i][1] = cache_hi; - bad[i][2] = cache_lo; - bad[i][3] = ((tag & 0xffffcc00) | - ((ca + j) & ~(0xffffcc00))); - bad[i][4] = *(pa + 1); - bad[i][5] = *(pa); - i++; - } - } - } - } - if (die) { - printk(KERN_EMERG "icache coherency error\n"); - for (j = 0; j <= i; j++) { - printk(KERN_EMERG - "cache address : %08x cache value : %08x%08x\n", - bad[j][0], bad[j][1], bad[j][2]); - printk(KERN_EMERG - "physical address: %08x SDRAM value : %08x%08x\n", - bad[j][3], bad[j][4], bad[j][5]); - } - panic("icache coherency error"); - } else - printk(KERN_EMERG "icache checked, and OK\n"); -} diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index 09c1fb410748..80884b136a0c 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -25,7 +25,7 @@ void bfin_pm_suspend_standby_enter(void) { unsigned long flags; - local_irq_save_hw(flags); + flags = hard_local_irq_save(); bfin_pm_standby_setup(); #ifdef CONFIG_PM_BFIN_SLEEP_DEEPER @@ -56,7 +56,7 @@ void bfin_pm_suspend_standby_enter(void) bfin_write_SIC_IWR(IWR_DISABLE_ALL); #endif - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); } int bf53x_suspend_l1_mem(unsigned char *memptr) @@ -149,12 +149,12 @@ int bfin_pm_suspend_mem_enter(void) wakeup |= GPWE; #endif - local_irq_save_hw(flags); + flags = hard_local_irq_save(); ret = blackfin_dma_suspend(); if (ret) { - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); kfree(memptr); return ret; } @@ -178,7 +178,7 @@ int bfin_pm_suspend_mem_enter(void) bfin_gpio_pm_hibernate_restore(); blackfin_dma_resume(); - local_irq_restore_hw(flags); + hard_local_irq_restore(flags); kfree(memptr); return 0; |