diff options
Diffstat (limited to 'arch/blackfin/mach-common')
-rw-r--r-- | arch/blackfin/mach-common/Makefile | 2 | ||||
-rw-r--r-- | arch/blackfin/mach-common/arch_checks.c | 60 | ||||
-rw-r--r-- | arch/blackfin/mach-common/cache.S | 8 | ||||
-rw-r--r-- | arch/blackfin/mach-common/cacheinit.S | 13 | ||||
-rw-r--r-- | arch/blackfin/mach-common/cplbhdlr.S | 8 | ||||
-rw-r--r-- | arch/blackfin/mach-common/cplbmgr.S | 56 | ||||
-rw-r--r-- | arch/blackfin/mach-common/dpmc.S | 54 | ||||
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 291 | ||||
-rw-r--r-- | arch/blackfin/mach-common/interrupt.S | 56 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority-dc.c | 46 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority-sc.c | 57 | ||||
-rw-r--r-- | arch/blackfin/mach-common/lock.S | 24 | ||||
-rw-r--r-- | arch/blackfin/mach-common/pm.c | 6 |
13 files changed, 457 insertions, 224 deletions
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile index 0279ede7039..4d7733dfd5d 100644 --- a/arch/blackfin/mach-common/Makefile +++ b/arch/blackfin/mach-common/Makefile @@ -4,7 +4,7 @@ obj-y := \ cache.o cacheinit.o cplbhdlr.o cplbmgr.o entry.o \ - interrupt.o lock.o irqpanic.o + interrupt.o lock.o irqpanic.o arch_checks.o obj-$(CONFIG_CPLB_INFO) += cplbinfo.o obj-$(CONFIG_BFIN_SINGLE_CORE) += ints-priority-sc.o diff --git a/arch/blackfin/mach-common/arch_checks.c b/arch/blackfin/mach-common/arch_checks.c new file mode 100644 index 00000000000..2f6ce397780 --- /dev/null +++ b/arch/blackfin/mach-common/arch_checks.c @@ -0,0 +1,60 @@ +/* + * File: arch/blackfin/mach-common/arch_checks.c + * Based on: + * Author: Robin Getz <rgetz@blackfin.uclinux.org> + * + * Created: 25Jul07 + * Description: Do some checking to make sure things are OK + * + * Modified: + * Copyright 2004-2007 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * 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 <asm/mach/anomaly.h> +#include <asm/mach-common/clocks.h> + +#ifdef CONFIG_BFIN_KERNEL_CLOCK + +# if (CONFIG_VCO_HZ > CONFIG_MAX_VCO_HZ) +# error "VCO selected is more than maximum value. Please change the VCO multipler" +# endif + +# if (CONFIG_SCLK_HZ > CONFIG_MAX_SCLK_HZ) +# error "Sclk value selected is more than maximum. Please select a proper value for SCLK multiplier" +# endif + +# if (CONFIG_SCLK_HZ < CONFIG_MIN_SCLK_HZ) +# error "Sclk value selected is less than minimum. Please select a proper value for SCLK multiplier" +# endif + +# if (ANOMALY_05000273) && (CONFIG_SCLK_HZ * 2 > CONFIG_CCLK_HZ) +# error "ANOMALY 05000273, please make sure CCLK is at least 2x SCLK" +# endif + +# if (CONFIG_SCLK_HZ > CONFIG_CCLK_HZ) && (CONFIG_SCLK_HZ != CONFIG_CLKIN_HZ) && (CONFIG_CCLK_HZ != CONFIG_CLKIN_HZ) +# error "Please select sclk less than cclk" +# endif + +#endif /* CONFIG_BFIN_KERNEL_CLOCK */ + +#if (CONFIG_MEM_SIZE % 4) +#error "SDRAM mem size must be multible of 4MB" +#endif + diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S index 7063795eb7c..0521b158820 100644 --- a/arch/blackfin/mach-common/cache.S +++ b/arch/blackfin/mach-common/cache.S @@ -79,8 +79,8 @@ ENTRY(_icache_invalidate) ENTRY(_invalidate_entire_icache) [--SP] = ( R7:5); - P0.L = (IMEM_CONTROL & 0xFFFF); - P0.H = (IMEM_CONTROL >> 16); + P0.L = LO(IMEM_CONTROL); + P0.H = HI(IMEM_CONTROL); R7 = [P0]; /* Clear the IMC bit , All valid bits in the instruction @@ -197,8 +197,8 @@ ENTRY(_invalidate_entire_dcache) ENTRY(_dcache_invalidate) [--SP] = ( R7:6); - P0.L = (DMEM_CONTROL & 0xFFFF); - P0.H = (DMEM_CONTROL >> 16); + P0.L = LO(DMEM_CONTROL); + P0.H = HI(DMEM_CONTROL); R7 = [P0]; /* Clear the DMC[1:0] bits, All valid bits in the data diff --git a/arch/blackfin/mach-common/cacheinit.S b/arch/blackfin/mach-common/cacheinit.S index 9d475623b72..22fada0c1cb 100644 --- a/arch/blackfin/mach-common/cacheinit.S +++ b/arch/blackfin/mach-common/cacheinit.S @@ -38,13 +38,13 @@ .text -#ifdef ANOMALY_05000125 -#if defined(CONFIG_BLKFIN_CACHE) +#if ANOMALY_05000125 +#if defined(CONFIG_BFIN_ICACHE) ENTRY(_bfin_write_IMEM_CONTROL) /* Enable Instruction Cache */ - P0.l = (IMEM_CONTROL & 0xFFFF); - P0.h = (IMEM_CONTROL >> 16); + P0.l = LO(IMEM_CONTROL); + P0.h = HI(IMEM_CONTROL); /* Anomaly 05000125 */ CLI R1; @@ -58,8 +58,11 @@ ENTRY(_bfin_write_IMEM_CONTROL) ENDPROC(_bfin_write_IMEM_CONTROL) #endif -#if defined(CONFIG_BLKFIN_DCACHE) +#if defined(CONFIG_BFIN_DCACHE) ENTRY(_bfin_write_DMEM_CONTROL) + P0.l = LO(DMEM_CONTROL); + P0.h = HI(DMEM_CONTROL); + CLI R1; SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ .align 8; diff --git a/arch/blackfin/mach-common/cplbhdlr.S b/arch/blackfin/mach-common/cplbhdlr.S index 2f3c72c2399..2788532de72 100644 --- a/arch/blackfin/mach-common/cplbhdlr.S +++ b/arch/blackfin/mach-common/cplbhdlr.S @@ -69,14 +69,14 @@ ENTRY(__cplb_hdr) .Lis_icplb_miss: -#if defined(CONFIG_BLKFIN_CACHE) || defined(CONFIG_BLKFIN_DCACHE) -# if defined(CONFIG_BLKFIN_CACHE) && !defined(CONFIG_BLKFIN_DCACHE) +#if defined(CONFIG_BFIN_ICACHE) || defined(CONFIG_BFIN_DCACHE) +# if defined(CONFIG_BFIN_ICACHE) && !defined(CONFIG_BFIN_DCACHE) R1 = CPLB_ENABLE_ICACHE; # endif -# if !defined(CONFIG_BLKFIN_CACHE) && defined(CONFIG_BLKFIN_DCACHE) +# if !defined(CONFIG_BFIN_ICACHE) && defined(CONFIG_BFIN_DCACHE) R1 = CPLB_ENABLE_DCACHE; # endif -# if defined(CONFIG_BLKFIN_CACHE) && defined(CONFIG_BLKFIN_DCACHE) +# if defined(CONFIG_BFIN_ICACHE) && defined(CONFIG_BFIN_DCACHE) R1 = CPLB_ENABLE_DCACHE | CPLB_ENABLE_ICACHE; # endif #else diff --git a/arch/blackfin/mach-common/cplbmgr.S b/arch/blackfin/mach-common/cplbmgr.S index e4b47e09cf1..946703ef48f 100644 --- a/arch/blackfin/mach-common/cplbmgr.S +++ b/arch/blackfin/mach-common/cplbmgr.S @@ -75,15 +75,15 @@ ENTRY(_cplb_mgr) * from the configuration table. */ - P4.L = (ICPLB_FAULT_ADDR & 0xFFFF); - P4.H = (ICPLB_FAULT_ADDR >> 16); + P4.L = LO(ICPLB_FAULT_ADDR); + P4.H = HI(ICPLB_FAULT_ADDR); P1 = 16; P5.L = _page_size_table; P5.H = _page_size_table; - P0.L = (ICPLB_DATA0 & 0xFFFF); - P0.H = (ICPLB_DATA0 >> 16); + P0.L = LO(ICPLB_DATA0); + P0.H = HI(ICPLB_DATA0); R4 = [P4]; /* Get faulting address*/ R6 = 64; /* Advance past the fault address, which*/ R6 = R6 + R4; /* we'll use if we find a match*/ @@ -117,13 +117,13 @@ ENTRY(_cplb_mgr) I0 = R4; /* Fault address we'll search for*/ /* set up pointers */ - P0.L = (ICPLB_DATA0 & 0xFFFF); - P0.H = (ICPLB_DATA0 >> 16); + P0.L = LO(ICPLB_DATA0); + P0.H = HI(ICPLB_DATA0); /* The replacement procedure for ICPLBs */ - P4.L = (IMEM_CONTROL & 0xFFFF); - P4.H = (IMEM_CONTROL >> 16); + P4.L = LO(IMEM_CONTROL); + P4.H = HI(IMEM_CONTROL); /* disable cplbs */ R5 = [P4]; /* Control Register*/ @@ -243,8 +243,8 @@ ENTRY(_cplb_mgr) * last entry of the table. */ - P1.L = (ICPLB_DATA15 & 0xFFFF); /* ICPLB_DATA15 */ - P1.H = (ICPLB_DATA15 >> 16); + P1.L = LO(ICPLB_DATA15); /* ICPLB_DATA15 */ + P1.H = HI(ICPLB_DATA15); [P1] = R2; [P1-0x100] = R4; #ifdef CONFIG_CPLB_INFO @@ -292,10 +292,10 @@ ENTRY(_cplb_mgr) * pending writes associated with the CPLB. */ - P4.L = (DCPLB_STATUS & 0xFFFF); - P4.H = (DCPLB_STATUS >> 16); - P3.L = (DCPLB_DATA0 & 0xFFFF); - P3.H = (DCPLB_DATA0 >> 16); + P4.L = LO(DCPLB_STATUS); + P4.H = HI(DCPLB_STATUS); + P3.L = LO(DCPLB_DATA0); + P3.H = HI(DCPLB_DATA0); R5 = [P4]; /* A protection violation can be caused by more than just writes @@ -355,11 +355,11 @@ ENTRY(_cplb_mgr) * config table, that covers the faulting address. */ - P1.L = (DCPLB_DATA15 & 0xFFFF); - P1.H = (DCPLB_DATA15 >> 16); + P1.L = LO(DCPLB_DATA15); + P1.H = HI(DCPLB_DATA15); - P4.L = (DCPLB_FAULT_ADDR & 0xFFFF); - P4.H = (DCPLB_FAULT_ADDR >> 16); + P4.L = LO(DCPLB_FAULT_ADDR); + P4.H = HI(DCPLB_FAULT_ADDR); R4 = [P4]; I0 = R4; @@ -368,8 +368,8 @@ ENTRY(_cplb_mgr) R6 = R1; /* Save for later*/ /* Turn off CPLBs while we work.*/ - P4.L = (DMEM_CONTROL & 0xFFFF); - P4.H = (DMEM_CONTROL >> 16); + P4.L = LO(DMEM_CONTROL); + P4.H = HI(DMEM_CONTROL); R5 = [P4]; BITCLR(R5,ENDCPLB_P); CLI R0; @@ -384,8 +384,8 @@ ENTRY(_cplb_mgr) * are no good. */ - I1.L = (DCPLB_DATA0 & 0xFFFF); - I1.H = (DCPLB_DATA0 >> 16); + I1.L = LO(DCPLB_DATA0); + I1.H = HI(DCPLB_DATA0); P1 = 2; P2 = 16; I2.L = _dcplb_preference; @@ -405,7 +405,7 @@ ENTRY(_cplb_mgr) P3.L = _page_size_table; /* retrieve end address */ P3.H = _page_size_table; /* retrieve end address */ R3 = 0x1002; /* 16th - position, 2 bits -length */ -#ifdef ANOMALY_05000209 +#if ANOMALY_05000209 nop; /* Anomaly 05000209 */ #endif R7 = EXTRACT(R1,R3.l); @@ -475,8 +475,8 @@ ENTRY(_cplb_mgr) * one space closer to the start. */ - R1.L = (DCPLB_DATA16 & 0xFFFF); /* DCPLB_DATA15 + 4 */ - R1.H = (DCPLB_DATA16 >> 16); + R1.L = LO(DCPLB_DATA16); /* DCPLB_DATA15 + 4 */ + R1.H = HI(DCPLB_DATA16); R0 = P0; /* If the victim happens to be in DCPLB15, @@ -549,8 +549,8 @@ ENTRY(_cplb_mgr) * if necessary. */ - P1.L = (DCPLB_DATA15 & 0xFFFF); - P1.H = (DCPLB_DATA15 >> 16); + P1.L = LO(DCPLB_DATA15); + P1.H = HI(DCPLB_DATA15); /* If the DCPLB has cache bits set, but caching hasn't * been enabled, then we want to mask off the cache-in-L1 @@ -565,7 +565,7 @@ ENTRY(_cplb_mgr) * cost of first-write exceptions to mark the page as dirty. */ -#ifdef CONFIG_BLKFIN_WT +#ifdef CONFIG_BFIN_WT BITSET(R6, 14); /* Set WT*/ #endif diff --git a/arch/blackfin/mach-common/dpmc.S b/arch/blackfin/mach-common/dpmc.S index 97cdcd6a00d..39fbc286110 100644 --- a/arch/blackfin/mach-common/dpmc.S +++ b/arch/blackfin/mach-common/dpmc.S @@ -39,8 +39,8 @@ ENTRY(_unmask_wdog_wakeup_evt) P0.H = hi(SICA_IWR1); P0.L = lo(SICA_IWR1); #else - P0.h = (SIC_IWR >> 16); - P0.l = (SIC_IWR & 0xFFFF); + P0.h = HI(SIC_IWR); + P0.l = LO(SIC_IWR); #endif R7 = [P0]; #if defined(CONFIG_BF561) @@ -60,11 +60,11 @@ ENTRY(_unmask_wdog_wakeup_evt) */ R7 = 0x0000(z); #if defined(CONFIG_BF561) - P0.h = (WDOGA_STAT >> 16); - P0.l = (WDOGA_STAT & 0xFFFF); + P0.h = HI(WDOGA_STAT); + P0.l = LO(WDOGA_STAT); #else - P0.h = (WDOG_STAT >> 16); - P0.l = (WDOG_STAT & 0xFFFF); + P0.h = HI(WDOG_STAT); + P0.l = LO(WDOG_STAT); #endif [P0] = R7; SSYNC; @@ -73,21 +73,21 @@ ENTRY(_unmask_wdog_wakeup_evt) ENTRY(_program_wdog_timer) [--SP] = ( R7:0, P5:0 ); #if defined(CONFIG_BF561) - P0.h = (WDOGA_CNT >> 16); - P0.l = (WDOGA_CNT & 0xFFFF); + P0.h = HI(WDOGA_CNT); + P0.l = LO(WDOGA_CNT); #else - P0.h = (WDOG_CNT >> 16); - P0.l = (WDOG_CNT & 0xFFFF); + P0.h = HI(WDOG_CNT); + P0.l = LO(WDOG_CNT); #endif [P0] = R0; SSYNC; #if defined(CONFIG_BF561) - P0.h = (WDOGA_CTL >> 16); - P0.l = (WDOGA_CTL & 0xFFFF); + P0.h = HI(WDOGA_CTL); + P0.l = LO(WDOGA_CTL); #else - P0.h = (WDOG_CTL >> 16); - P0.l = (WDOG_CTL & 0xFFFF); + P0.h = HI(WDOG_CTL); + P0.l = LO(WDOG_CTL); #endif R7 = W[P0](Z); CC = BITTST(R7,1); @@ -97,11 +97,11 @@ ENTRY(_program_wdog_timer) .LSKIP_WRITE_TO_STAT: #if defined(CONFIG_BF561) - P0.h = (WDOGA_CTL >> 16); - P0.l = (WDOGA_CTL & 0xFFFF); + P0.h = HI(WDOGA_CTL); + P0.l = LO(WDOGA_CTL); #else - P0.h = (WDOG_CTL >> 16); - P0.l = (WDOG_CTL & 0xFFFF); + P0.h = HI(WDOG_CTL); + P0.l = LO(WDOG_CTL); #endif R7 = W[P0](Z); BITCLR(R7,1); /* Enable GP event */ @@ -122,11 +122,11 @@ ENTRY(_clear_wdog_wakeup_evt) [--SP] = ( R7:0, P5:0 ); #if defined(CONFIG_BF561) - P0.h = (WDOGA_CTL >> 16); - P0.l = (WDOGA_CTL & 0xFFFF); + P0.h = HI(WDOGA_CTL); + P0.l = LO(WDOGA_CTL); #else - P0.h = (WDOG_CTL >> 16); - P0.l = (WDOG_CTL & 0xFFFF); + P0.h = HI(WDOG_CTL); + P0.l = LO(WDOG_CTL); #endif R7 = 0x0AD6(Z); W[P0] = R7.L; @@ -149,11 +149,11 @@ ENTRY(_clear_wdog_wakeup_evt) ENTRY(_disable_wdog_timer) [--SP] = ( R7:0, P5:0 ); #if defined(CONFIG_BF561) - P0.h = (WDOGA_CTL >> 16); - P0.l = (WDOGA_CTL & 0xFFFF); + P0.h = HI(WDOGA_CTL); + P0.l = LO(WDOGA_CTL); #else - P0.h = (WDOG_CTL >> 16); - P0.l = (WDOG_CTL & 0xFFFF); + P0.h = HI(WDOG_CTL); + P0.l = LO(WDOG_CTL); #endif R7 = 0xAD6(Z); W[P0] = R7.L; @@ -300,7 +300,7 @@ ENTRY(_sleep_deeper) P0.H = hi(PLL_CTL); P0.L = lo(PLL_CTL); R5 = W[P0](z); - R0.L = (MIN_VC/CONFIG_CLKIN_HZ) << 9; + R0.L = (CONFIG_MIN_VCO_HZ/CONFIG_CLKIN_HZ) << 9; W[P0] = R0.l; SSYNC; diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index d61bba98fb5..e3ad5802868 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -29,21 +29,7 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* - * 25-Dec-2004 - LG Soft India - * 1. Fix in return_from_int, to make sure any pending - * system call in ILAT for this process to get - * executed, otherwise in case context switch happens, - * system call of first process (i.e in ILAT) will be - * carried forward to the switched process. - * 2. Removed Constant references for the following - * a. IPEND - * b. EXCAUSE mask - * c. PAGE Mask - */ - -/* - * NOTE: This code handles signal-recognition, which happens every time +/* NOTE: This code handles signal-recognition, which happens every time * after a timer-interrupt and after each system call. */ @@ -58,6 +44,23 @@ #include <asm/mach-common/context.S> +#if defined(CONFIG_BFIN_SCRATCH_REG_RETN) +# define EX_SCRATCH_REG RETN +#elif defined(CONFIG_BFIN_SCRATCH_REG_RETE) +# define EX_SCRATCH_REG RETE +#else +# define EX_SCRATCH_REG CYCLES +#endif + +#if ANOMALY_05000281 +ENTRY(_safe_speculative_execution) + NOP; + NOP; + NOP; + jump _safe_speculative_execution; +ENDPROC(_safe_speculative_execution) +#endif + #ifdef CONFIG_EXCPT_IRQ_SYSC_L1 .section .l1.text #else @@ -69,7 +72,7 @@ * patch up CPLB misses on the kernel stack. */ ENTRY(_ex_dcplb) -#if defined(ANOMALY_05000261) +#if ANOMALY_05000261 /* * Work around an anomaly: if we see a new DCPLB fault, return * without doing anything. Then, if we get the same fault again, @@ -93,7 +96,7 @@ ENTRY(_ex_icplb) call __cplb_hdr; DEBUG_START_HWTRACE(p5, r7) RESTORE_ALL_SYS - SP = RETN; + SP = EX_SCRATCH_REG; rtx; ENDPROC(_ex_icplb) @@ -102,7 +105,7 @@ ENTRY(_ex_syscall) (R7:6,P5:4) = [sp++]; ASTAT = [sp++]; raise 15; /* invoked by TRAP #0, for sys call */ - sp = retn; + sp = EX_SCRATCH_REG; rtx ENDPROC(_ex_syscall) @@ -135,9 +138,9 @@ ENTRY(_ex_single_step) cc = r6 == r7; if !cc jump _ex_trap_c; -_return_from_exception: +ENTRY(_return_from_exception) DEBUG_START_HWTRACE(p5, r7) -#ifdef ANOMALY_05000257 +#if ANOMALY_05000257 R7=LC0; LC0=R7; R7=LC1; @@ -145,7 +148,7 @@ _return_from_exception: #endif (R7:6,P5:4) = [sp++]; ASTAT = [sp++]; - sp = retn; + sp = EX_SCRATCH_REG; rtx; ENDPROC(_ex_soft_bp) @@ -163,7 +166,17 @@ ENTRY(_handle_bad_cplb) [--sp] = ASTAT; [--sp] = (R7:6, P5:4); +ENTRY(_ex_replaceable) + nop; + ENTRY(_ex_trap_c) + /* Make sure we are not in a double fault */ + p4.l = lo(IPEND); + p4.h = hi(IPEND); + r7 = [p4]; + CC = BITTST (r7, 5); + if CC jump _double_fault; + /* Call C code (trap_c) to handle the exception, which most * likely involves sending a signal to the current process. * To avoid double faults, lower our priority to IRQ5 first. @@ -204,11 +217,57 @@ ENTRY(_ex_trap_c) DEBUG_START_HWTRACE(p5, r7) (R7:6,P5:4) = [sp++]; ASTAT = [sp++]; - SP = RETN; + SP = EX_SCRATCH_REG; raise 5; rtx; 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 + */ +ENTRY(_double_fault) + /* Turn caches & protection off, to ensure we don't get any more + * double exceptions + */ + + P4.L = LO(IMEM_CONTROL); + P4.H = HI(IMEM_CONTROL); + + R5 = [P4]; /* Control Register*/ + BITCLR(R5,ENICPLB_P); + SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ + .align 8; + [P4] = R5; + SSYNC; + + P4.L = LO(DMEM_CONTROL); + P4.H = HI(DMEM_CONTROL); + R5 = [P4]; + BITCLR(R5,ENDCPLB_P); + SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ + .align 8; + [P4] = R5; + SSYNC; + + /* Fix up the stack */ + (R7:6,P5:4) = [sp++]; + ASTAT = [sp++]; + SP = EX_SCRATCH_REG; + + /* We should be out of the exception stack, and back down into + * kernel or user space stack + */ + SAVE_ALL_SYS + + r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ + SP += -12; + call _double_fault_c; + SP += 12; +.L_double_fault_panic: + JUMP .L_double_fault_panic + +ENDPROC(_double_fault) + ENTRY(_exception_to_level5) SAVE_ALL_SYS @@ -279,7 +338,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ * covered by a CPLB. Switch to an exception stack; use RETN as a * scratch register (for want of a better option). */ - retn = sp; + EX_SCRATCH_REG = sp; sp.l = _exception_stack_top; sp.h = _exception_stack_top; /* Try to deal with syscalls quickly. */ @@ -290,8 +349,8 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ r6.l = lo(SEQSTAT_EXCAUSE); r6.h = hi(SEQSTAT_EXCAUSE); r7 = r7 & r6; - p5.h = _extable; - p5.l = _extable; + p5.h = _ex_table; + p5.l = _ex_table; p4 = r7; p5 = p5 + (p4 << 2); p4 = [p5]; @@ -634,9 +693,9 @@ ENTRY(_return_from_int) p1.h = _schedule_and_signal_from_int; [p0] = p1; csync; -#if defined(ANOMALY_05000281) - r0.l = lo(CONFIG_BOOT_LOAD); - r0.h = hi(CONFIG_BOOT_LOAD); +#if ANOMALY_05000281 + r0.l = _safe_speculative_execution; + r0.h = _safe_speculative_execution; reti = r0; #endif r0 = 0x801f (z); @@ -648,9 +707,9 @@ ENTRY(_return_from_int) ENDPROC(_return_from_int) ENTRY(_lower_to_irq14) -#if defined(ANOMALY_05000281) - r0.l = lo(CONFIG_BOOT_LOAD); - r0.h = hi(CONFIG_BOOT_LOAD); +#if ANOMALY_05000281 + r0.l = _safe_speculative_execution; + r0.h = _safe_speculative_execution; reti = r0; #endif r0 = 0x401f; @@ -731,6 +790,114 @@ ENTRY(_init_exception_buff) rts; ENDPROC(_init_exception_buff) +/* We handle this 100% in exception space - to reduce overhead + * Only potiential problem is if the software buffer gets swapped out of the + * CPLB table - then double fault. - so we don't let this happen in other places + */ +#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND +ENTRY(_ex_trace_buff_full) + [--sp] = P3; + [--sp] = P2; + [--sp] = LC0; + [--sp] = LT0; + [--sp] = LB0; + P5.L = _trace_buff_offset; + P5.H = _trace_buff_offset; + P3 = [P5]; /* trace_buff_offset */ + P5.L = lo(TBUFSTAT); + P5.H = hi(TBUFSTAT); + R7 = [P5]; + R7 <<= 1; /* double, since we need to read twice */ + LC0 = R7; + R7 <<= 2; /* need to shift over again, + * to get the number of bytes */ + P5.L = lo(TBUF); + P5.H = hi(TBUF); + R6 = ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN)*1024) - 1; + + P2 = R7; + P3 = P3 + P2; + R7 = P3; + R7 = R7 & R6; + P3 = R7; + P2.L = _trace_buff_offset; + P2.H = _trace_buff_offset; + [P2] = P3; + + P2.L = _software_trace_buff; + P2.H = _software_trace_buff; + + LSETUP (.Lstart, .Lend) LC0; +.Lstart: + R7 = [P5]; /* read TBUF */ + P4 = P3 + P2; + [P4] = R7; + P3 += -4; + R7 = P3; + R7 = R7 & R6; +.Lend: + P3 = R7; + + LB0 = [sp++]; + LT0 = [sp++]; + LC0 = [sp++]; + P2 = [sp++]; + P3 = [sp++]; + jump _return_from_exception; +ENDPROC(_ex_trace_buff_full) + +#if CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN == 4 +.data +#else +.section .l1.data.B +#endif /* CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN */ +ENTRY(_trace_buff_offset) + .long 0; +ALIGN +ENTRY(_software_trace_buff) + .rept ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN)*256); + .long 0 + .endr +#endif /* CONFIG_DEBUG_BFIN_HWTRACE_EXPAND */ + +#if CONFIG_EARLY_PRINTK +.section .init.text +ENTRY(_early_trap) + SAVE_ALL_SYS + trace_buffer_stop(p0,r0); + + /* Turn caches off, to ensure we don't get double exceptions */ + + P4.L = LO(IMEM_CONTROL); + P4.H = HI(IMEM_CONTROL); + + R5 = [P4]; /* Control Register*/ + BITCLR(R5,ENICPLB_P); + CLI R1; + SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ + .align 8; + [P4] = R5; + SSYNC; + + P4.L = LO(DMEM_CONTROL); + P4.H = HI(DMEM_CONTROL); + R5 = [P4]; + BITCLR(R5,ENDCPLB_P); + SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ + .align 8; + [P4] = R5; + SSYNC; + STI R1; + + r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ + r1 = RETX; + + SP += -12; + call _early_trap_c; + SP += 12; +ENDPROC(_early_trap) +#endif /* CONFIG_EARLY_PRINTK */ + /* * Put these in the kernel data section - that should always be covered by * a CPLB. This is needed to ensure we don't get double fault conditions @@ -741,30 +908,33 @@ ENDPROC(_init_exception_buff) #else .data #endif -ALIGN -_extable: +ENTRY(_ex_table) /* entry for each EXCAUSE[5:0] * This table must be in sync with the table in ./kernel/traps.c * EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined */ - .long _ex_syscall; /* 0x00 - User Defined - Linux Syscall */ + .long _ex_syscall /* 0x00 - User Defined - Linux Syscall */ .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */ - .long _ex_trap_c /* 0x02 - User Defined */ + .long _ex_replaceable /* 0x02 - User Defined */ .long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */ - .long _ex_trap_c /* 0x04 - User Defined */ - .long _ex_trap_c /* 0x05 - User Defined */ - .long _ex_trap_c /* 0x06 - User Defined */ - .long _ex_trap_c /* 0x07 - User Defined */ - .long _ex_trap_c /* 0x08 - User Defined */ - .long _ex_trap_c /* 0x09 - User Defined */ - .long _ex_trap_c /* 0x0A - User Defined */ - .long _ex_trap_c /* 0x0B - User Defined */ - .long _ex_trap_c /* 0x0C - User Defined */ - .long _ex_trap_c /* 0x0D - User Defined */ - .long _ex_trap_c /* 0x0E - User Defined */ - .long _ex_trap_c /* 0x0F - User Defined */ + .long _ex_replaceable /* 0x04 - User Defined */ + .long _ex_replaceable /* 0x05 - User Defined */ + .long _ex_replaceable /* 0x06 - User Defined */ + .long _ex_replaceable /* 0x07 - User Defined */ + .long _ex_replaceable /* 0x08 - User Defined */ + .long _ex_replaceable /* 0x09 - User Defined */ + .long _ex_replaceable /* 0x0A - User Defined */ + .long _ex_replaceable /* 0x0B - User Defined */ + .long _ex_replaceable /* 0x0C - User Defined */ + .long _ex_replaceable /* 0x0D - User Defined */ + .long _ex_replaceable /* 0x0E - User Defined */ + .long _ex_replaceable /* 0x0F - User Defined */ .long _ex_single_step /* 0x10 - HW Single step */ +#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND + .long _ex_trace_buff_full /* 0x11 - Trace Buffer Full */ +#else .long _ex_trap_c /* 0x11 - Trace Buffer Full */ +#endif .long _ex_trap_c /* 0x12 - Reserved */ .long _ex_trap_c /* 0x13 - Reserved */ .long _ex_trap_c /* 0x14 - Reserved */ @@ -812,10 +982,10 @@ _extable: .long _ex_trap_c /* 0x3D - Reserved */ .long _ex_trap_c /* 0x3E - Reserved */ .long _ex_trap_c /* 0x3F - Reserved */ +END(_ex_table) -ALIGN ENTRY(_sys_call_table) - .long _sys_ni_syscall /* 0 - old "setup()" system call*/ + .long _sys_restart_syscall /* 0 */ .long _sys_exit .long _sys_fork .long _sys_read @@ -978,13 +1148,13 @@ ENTRY(_sys_call_table) .long _sys_sched_get_priority_min /* 160 */ .long _sys_sched_rr_get_interval .long _sys_nanosleep - .long _sys_ni_syscall /* sys_mremap */ + .long _sys_mremap .long _sys_setresuid /* setresuid16 */ .long _sys_getresuid /* getresuid16 */ /* 165 */ .long _sys_ni_syscall /* for vm86 */ .long _sys_ni_syscall /* old "query_module" */ .long _sys_ni_syscall /* sys_poll */ - .long _sys_ni_syscall /* sys_nfsservctl */ + .long _sys_nfsservctl .long _sys_setresgid /* setresgid16 */ /* 170 */ .long _sys_getresgid /* getresgid16 */ .long _sys_prctl @@ -1040,7 +1210,7 @@ ENTRY(_sys_call_table) .long _sys_ni_syscall /* reserved for TUX */ .long _sys_ni_syscall .long _sys_gettid - .long _sys_ni_syscall /* 225 */ /* sys_readahead */ + .long _sys_readahead /* 225 */ .long _sys_setxattr .long _sys_lsetxattr .long _sys_fsetxattr @@ -1157,6 +1327,21 @@ ENTRY(_sys_call_table) .long _sys_shmctl .long _sys_shmdt /* 340 */ .long _sys_shmget + .long _sys_splice + .long _sys_sync_file_range + .long _sys_tee + .long _sys_vmsplice /* 345 */ + .long _sys_epoll_pwait + .long _sys_utimensat + .long _sys_signalfd + .long _sys_timerfd + .long _sys_eventfd /* 350 */ + .long _sys_pread64 + .long _sys_pwrite64 + .long _sys_fadvise64 + .long _sys_set_robust_list + .long _sys_get_robust_list /* 355 */ + .long _sys_fallocate .rept NR_syscalls-(.-_sys_call_table)/4 .long _sys_ni_syscall .endr @@ -1169,7 +1354,7 @@ _exception_stack: .endr _exception_stack_top: -#if defined(ANOMALY_05000261) +#if ANOMALY_05000261 /* Used by the assembly entry point to work around an anomaly. */ _last_cplb_fault_retx: .long 0; diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index 203e2070916..c6b32fe0f6e 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -46,30 +46,6 @@ .align 4 /* just in case */ -/* - * initial interrupt handlers - */ - -#ifndef CONFIG_KGDB - /* interrupt routine for emulation - 0 */ - /* Currently used only if GDB stub is not in - invalid */ - /* gdb-stub set the evt itself */ - /* save registers for post-mortem only */ -ENTRY(_evt_emulation) - SAVE_ALL_SYS -#ifdef CONFIG_FRAME_POINTER - fp = 0; -#endif - r0 = IRQ_EMU; - r1 = sp; - SP += -12; - call _irq_panic; - SP += 12; - /* - GDB stub fills this in by itself (if defined) */ - rte; -ENDPROC(_evt_emulation) -#endif - /* Common interrupt entry code. First we do CLI, then push * RETI, to keep interrupts disabled, but to allow this state to be changed * by local_bh_enable. @@ -140,7 +116,7 @@ __common_int_entry: fp = 0; #endif -#if defined (ANOMALY_05000283) || defined (ANOMALY_05000315) +#if ANOMALY_05000283 || ANOMALY_05000315 cc = r7 == r7; p5.h = 0xffc0; p5.l = 0x0014; @@ -163,7 +139,7 @@ ENTRY(_evt_ivhw) #ifdef CONFIG_FRAME_POINTER fp = 0; #endif -#ifdef ANOMALY_05000283 +#if ANOMALY_05000283 cc = r7 == r7; p5.h = 0xffc0; p5.l = 0x0014; @@ -201,27 +177,15 @@ ENTRY(_evt_ivhw) jump .Lcommon_restore_context; #endif -/* interrupt routine for evt2 - 2. This is NMI. */ -ENTRY(_evt_evt2) - SAVE_CONTEXT -#ifdef CONFIG_FRAME_POINTER - fp = 0; -#endif -#ifdef ANOMALY_05000283 - cc = r7 == r7; - p5.h = 0xffc0; - p5.l = 0x0014; - if cc jump 1f; - r7.l = W[p5]; -1: -#endif - r0 = IRQ_NMI; - r1 = sp; - SP += -12; - call _asm_do_IRQ; - SP += 12; - RESTORE_CONTEXT +/* Interrupt routine for evt2 (NMI). + * We don't actually use this, so just return. + * For inner circle type details, please see: + * http://docs.blackfin.uclinux.org/doku.php?id=linux:nmi + */ +ENTRY(_evt_nmi) +.weak _evt_nmi rtn; +ENDPROC(_evt_nmi) /* interrupt routine for core timer - 6 */ ENTRY(_evt_timer) diff --git a/arch/blackfin/mach-common/ints-priority-dc.c b/arch/blackfin/mach-common/ints-priority-dc.c index 6b9fd03ce83..2db3546fc87 100644 --- a/arch/blackfin/mach-common/ints-priority-dc.c +++ b/arch/blackfin/mach-common/ints-priority-dc.c @@ -221,7 +221,7 @@ static unsigned int bf561_gpio_irq_startup(unsigned int irq) if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { - ret = gpio_request(gpionr, NULL); + ret = gpio_request(gpionr, "IRQ"); if (ret) return ret; @@ -261,7 +261,7 @@ static int bf561_gpio_irq_type(unsigned int irq, unsigned int type) if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { - ret = gpio_request(gpionr, NULL); + ret = gpio_request(gpionr, "IRQ"); if (ret) return ret; @@ -358,6 +358,30 @@ static void bf561_demux_gpio_irq(unsigned int inta_irq, #endif /* CONFIG_IRQCHIP_DEMUX_GPIO */ +void __init init_exception_vectors(void) +{ + SSYNC(); + + /* cannot program in software: + * evt0 - emulation (jtag) + * evt1 - reset + */ + bfin_write_EVT2(evt_nmi); + bfin_write_EVT3(trap); + bfin_write_EVT5(evt_ivhw); + bfin_write_EVT6(evt_timer); + bfin_write_EVT7(evt_evt7); + bfin_write_EVT8(evt_evt8); + bfin_write_EVT9(evt_evt9); + bfin_write_EVT10(evt_evt10); + bfin_write_EVT11(evt_evt11); + bfin_write_EVT12(evt_evt12); + bfin_write_EVT13(evt_evt13); + bfin_write_EVT14(evt14_softirq); + bfin_write_EVT15(evt_system_call); + CSYNC(); +} + /* * This function should be called during kernel startup to initialize * the BFin IRQ handling routines. @@ -378,24 +402,6 @@ int __init init_arch_irq(void) init_exception_buff(); -#ifndef CONFIG_KGDB - bfin_write_EVT0(evt_emulation); -#endif - bfin_write_EVT2(evt_evt2); - bfin_write_EVT3(trap); - bfin_write_EVT5(evt_ivhw); - bfin_write_EVT6(evt_timer); - bfin_write_EVT7(evt_evt7); - bfin_write_EVT8(evt_evt8); - bfin_write_EVT9(evt_evt9); - bfin_write_EVT10(evt_evt10); - bfin_write_EVT11(evt_evt11); - bfin_write_EVT12(evt_evt12); - bfin_write_EVT13(evt_evt13); - bfin_write_EVT14(evt14_softirq); - bfin_write_EVT15(evt_system_call); - CSYNC(); - for (irq = 0; irq <= SYS_IRQS; irq++) { if (irq <= IRQ_CORETMR) set_irq_chip(irq, &bf561_core_irqchip); diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority-sc.c index 28a878c3577..d3b7672b2b9 100644 --- a/arch/blackfin/mach-common/ints-priority-sc.c +++ b/arch/blackfin/mach-common/ints-priority-sc.c @@ -343,7 +343,7 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq) u16 gpionr = irq - IRQ_PF0; if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { - ret = gpio_request(gpionr, NULL); + ret = gpio_request(gpionr, "IRQ"); if (ret) return ret; } @@ -377,7 +377,7 @@ 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)) { if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { - ret = gpio_request(gpionr, NULL); + ret = gpio_request(gpionr, "IRQ"); if (ret) return ret; } @@ -579,11 +579,15 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq) u16 gpionr = irq - IRQ_PA0; u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; - if (pint_val == IRQ_NOT_AVAIL) + if (pint_val == IRQ_NOT_AVAIL) { + printk(KERN_ERR + "GPIO IRQ %d :Not in PINT Assign table " + "Reconfigure Interrupt to Port Assignemt\n", irq); return -ENODEV; + } if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { - ret = gpio_request(gpionr, NULL); + ret = gpio_request(gpionr, "IRQ"); if (ret) return ret; } @@ -623,7 +627,7 @@ 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)) { if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { - ret = gpio_request(gpionr, NULL); + ret = gpio_request(gpionr, "IRQ"); if (ret) return ret; } @@ -713,6 +717,30 @@ static void bfin_demux_gpio_irq(unsigned int intb_irq, } #endif /* CONFIG_IRQCHIP_DEMUX_GPIO */ +void __init init_exception_vectors(void) +{ + SSYNC(); + + /* cannot program in software: + * evt0 - emulation (jtag) + * evt1 - reset + */ + bfin_write_EVT2(evt_nmi); + bfin_write_EVT3(trap); + bfin_write_EVT5(evt_ivhw); + bfin_write_EVT6(evt_timer); + bfin_write_EVT7(evt_evt7); + bfin_write_EVT8(evt_evt8); + bfin_write_EVT9(evt_evt9); + bfin_write_EVT10(evt_evt10); + bfin_write_EVT11(evt_evt11); + bfin_write_EVT12(evt_evt12); + bfin_write_EVT13(evt_evt13); + bfin_write_EVT14(evt14_softirq); + bfin_write_EVT15(evt_system_call); + CSYNC(); +} + /* * This function should be called during kernel startup to initialize * the BFin IRQ handling routines. @@ -733,29 +761,10 @@ int __init init_arch_irq(void) bfin_write_SIC_IMASK(SIC_UNMASK_ALL); bfin_write_SIC_IWR(IWR_ENABLE_ALL); #endif - SSYNC(); local_irq_disable(); -#ifndef CONFIG_KGDB - bfin_write_EVT0(evt_emulation); -#endif - bfin_write_EVT2(evt_evt2); - bfin_write_EVT3(trap); - bfin_write_EVT5(evt_ivhw); - bfin_write_EVT6(evt_timer); - bfin_write_EVT7(evt_evt7); - bfin_write_EVT8(evt_evt8); - bfin_write_EVT9(evt_evt9); - bfin_write_EVT10(evt_evt10); - bfin_write_EVT11(evt_evt11); - bfin_write_EVT12(evt_evt12); - bfin_write_EVT13(evt_evt13); - bfin_write_EVT14(evt14_softirq); - bfin_write_EVT15(evt_system_call); - CSYNC(); - #if defined(CONFIG_IRQCHIP_DEMUX_GPIO) && defined(CONFIG_BF54x) #ifdef CONFIG_PINTx_REASSIGN pint[0]->assign = CONFIG_PINT0_ASSIGN; diff --git a/arch/blackfin/mach-common/lock.S b/arch/blackfin/mach-common/lock.S index 386ac8dda07..28b87fe9ce3 100644 --- a/arch/blackfin/mach-common/lock.S +++ b/arch/blackfin/mach-common/lock.S @@ -33,7 +33,7 @@ .text -#ifdef CONFIG_BLKFIN_CACHE_LOCK +#ifdef CONFIG_BFIN_ICACHE_LOCK /* When you come here, it is assumed that * R0 - Which way to be locked @@ -43,12 +43,12 @@ ENTRY(_cache_grab_lock) [--SP]=( R7:0,P5:0 ); - P1.H = (IMEM_CONTROL >> 16); - P1.L = (IMEM_CONTROL & 0xFFFF); - P5.H = (ICPLB_ADDR0 >> 16); - P5.L = (ICPLB_ADDR0 & 0xFFFF); - P4.H = (ICPLB_DATA0 >> 16); - P4.L = (ICPLB_DATA0 & 0xFFFF); + P1.H = HI(IMEM_CONTROL); + P1.L = LO(IMEM_CONTROL); + P5.H = HI(ICPLB_ADDR0); + P5.L = LO(ICPLB_ADDR0); + P4.H = HI(ICPLB_DATA0); + P4.L = LO(ICPLB_DATA0); R7 = R0; /* If the code of interest already resides in the cache @@ -167,8 +167,8 @@ ENTRY(_cache_lock) [--SP]=( R7:0,P5:0 ); - P1.H = (IMEM_CONTROL >> 16); - P1.L = (IMEM_CONTROL & 0xFFFF); + P1.H = HI(IMEM_CONTROL); + P1.L = LO(IMEM_CONTROL); /* Disable the Interrupts*/ CLI R3; @@ -189,14 +189,14 @@ ENTRY(_cache_lock) RTS; ENDPROC(_cache_lock) -#endif /* BLKFIN_CACHE_LOCK */ +#endif /* BFIN_ICACHE_LOCK */ /* Return the ILOC bits of IMEM_CONTROL */ ENTRY(_read_iloc) - P1.H = (IMEM_CONTROL >> 16); - P1.L = (IMEM_CONTROL & 0xFFFF); + P1.H = HI(IMEM_CONTROL); + P1.L = LO(IMEM_CONTROL); R1 = 0xF; R0 = [P1]; R0 = R0 >> 3; diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index 1772d8d2c1a..b1030272220 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -158,10 +158,16 @@ static int bfin_pm_finish(suspend_state_t state) return 0; } +static int bfin_pm_valid(suspend_state_t state) +{ + return (state == PM_SUSPEND_STANDBY); +} + struct pm_ops bfin_pm_ops = { .prepare = bfin_pm_prepare, .enter = bfin_pm_enter, .finish = bfin_pm_finish, + .valid = bfin_pm_valid, }; static int __init bfin_pm_init(void) |