aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-common
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/mach-common')
-rw-r--r--arch/blackfin/mach-common/Makefile1
-rw-r--r--arch/blackfin/mach-common/dpmc_modes.S50
-rw-r--r--arch/blackfin/mach-common/entry.S113
-rw-r--r--arch/blackfin/mach-common/interrupt.S17
-rw-r--r--arch/blackfin/mach-common/ints-priority.c11
-rw-r--r--arch/blackfin/mach-common/irqpanic.c106
6 files changed, 135 insertions, 163 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/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 af1bffa21dc1..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)
@@ -1631,6 +1737,7 @@ ENTRY(_sys_call_table)
.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 eaece5f84e42..da7e3c63746b 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -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");
-}