| /* Copyright (C) 2003 Analog Devices, Inc. All Rights Reserved. |
| * |
| * This file is subject to the terms and conditions of the GNU General Public |
| * License. |
| * |
| * Blackfin BF533/2.6 support : LG Soft India |
| */ |
| |
| |
| /* Include an exception handler to invoke the CPLB manager |
| */ |
| |
| #include <asm-blackfin/linkage.h> |
| #include <asm/cplb.h> |
| #include <asm/entry.h> |
| |
| |
| .text |
| |
| .globl _cplb_hdr; |
| .type _cplb_hdr, STT_FUNC; |
| .extern _cplb_mgr; |
| .type _cplb_mgr, STT_FUNC; |
| .extern __unknown_exception_occurred; |
| .type __unknown_exception_occurred, STT_FUNC; |
| .extern __cplb_miss_all_locked; |
| .type __cplb_miss_all_locked, STT_FUNC; |
| .extern __cplb_miss_without_replacement; |
| .type __cplb_miss_without_replacement, STT_FUNC; |
| .extern __cplb_protection_violation; |
| .type __cplb_protection_violation, STT_FUNC; |
| .extern panic_pv; |
| |
| .align 2; |
| |
| ENTRY(_cplb_hdr) |
| SSYNC; |
| [--SP] = ( R7:0, P5:0 ); |
| [--SP] = ASTAT; |
| [--SP] = SEQSTAT; |
| [--SP] = I0; |
| [--SP] = I1; |
| [--SP] = I2; |
| [--SP] = I3; |
| [--SP] = LT0; |
| [--SP] = LB0; |
| [--SP] = LC0; |
| [--SP] = LT1; |
| [--SP] = LB1; |
| [--SP] = LC1; |
| R2 = SEQSTAT; |
| |
| /*Mask the contents of SEQSTAT and leave only EXCAUSE in R2*/ |
| R2 <<= 26; |
| R2 >>= 26; |
| |
| R1 = 0x23; /* Data access CPLB protection violation */ |
| CC = R2 == R1; |
| IF !CC JUMP not_data_write; |
| R0 = 2; /* is a write to data space*/ |
| JUMP is_icplb_miss; |
| |
| not_data_write: |
| R1 = 0x2C; /* CPLB miss on an instruction fetch */ |
| CC = R2 == R1; |
| R0 = 0; /* is_data_miss == False*/ |
| IF CC JUMP is_icplb_miss; |
| |
| R1 = 0x26; |
| CC = R2 == R1; |
| IF !CC JUMP unknown; |
| |
| R0 = 1; /* is_data_miss == True*/ |
| |
| is_icplb_miss: |
| |
| #if ( defined (CONFIG_BLKFIN_CACHE) || defined (CONFIG_BLKFIN_DCACHE)) |
| #if ( defined (CONFIG_BLKFIN_CACHE) && !defined (CONFIG_BLKFIN_DCACHE)) |
| R1 = CPLB_ENABLE_ICACHE; |
| #endif |
| #if ( !defined (CONFIG_BLKFIN_CACHE) && defined (CONFIG_BLKFIN_DCACHE)) |
| R1 = CPLB_ENABLE_DCACHE; |
| #endif |
| #if ( defined (CONFIG_BLKFIN_CACHE) && defined (CONFIG_BLKFIN_DCACHE)) |
| R1 = CPLB_ENABLE_DCACHE | CPLB_ENABLE_ICACHE; |
| #endif |
| #else |
| R1 = 0; |
| #endif |
| |
| [--SP] = RETS; |
| CALL _cplb_mgr; |
| RETS = [SP++]; |
| CC = R0 == 0; |
| IF !CC JUMP not_replaced; |
| LC1 = [SP++]; |
| LB1 = [SP++]; |
| LT1 = [SP++]; |
| LC0 = [SP++]; |
| LB0 = [SP++]; |
| LT0 = [SP++]; |
| I3 = [SP++]; |
| I2 = [SP++]; |
| I1 = [SP++]; |
| I0 = [SP++]; |
| SEQSTAT = [SP++]; |
| ASTAT = [SP++]; |
| ( R7:0, P5:0 ) = [SP++]; |
| RTS; |
| |
| unknown: |
| [--SP] = RETS; |
| CALL __unknown_exception_occurred; |
| RETS = [SP++]; |
| JUMP unknown; |
| not_replaced: |
| CC = R0 == CPLB_NO_UNLOCKED; |
| IF !CC JUMP next_check; |
| [--SP] = RETS; |
| CALL __cplb_miss_all_locked; |
| RETS = [SP++]; |
| next_check: |
| CC = R0 == CPLB_NO_ADDR_MATCH; |
| IF !CC JUMP next_check2; |
| [--SP] = RETS; |
| CALL __cplb_miss_without_replacement; |
| RETS = [SP++]; |
| JUMP not_replaced; |
| next_check2: |
| CC = R0 == CPLB_PROT_VIOL; |
| IF !CC JUMP strange_return_from_cplb_mgr; |
| [--SP] = RETS; |
| CALL __cplb_protection_violation; |
| RETS = [SP++]; |
| JUMP not_replaced; |
| strange_return_from_cplb_mgr: |
| IDLE; |
| CSYNC; |
| JUMP strange_return_from_cplb_mgr; |
| |
| /************************************ |
| * Diagnostic exception handlers |
| */ |
| |
| __cplb_miss_all_locked: |
| sp += -12; |
| R0 = CPLB_NO_UNLOCKED; |
| call panic_bfin; |
| SP += 12; |
| RTS; |
| |
| __cplb_miss_without_replacement: |
| sp += -12; |
| R0 = CPLB_NO_ADDR_MATCH; |
| call panic_bfin; |
| SP += 12; |
| RTS; |
| |
| __cplb_protection_violation: |
| sp += -12; |
| R0 = CPLB_PROT_VIOL; |
| call panic_bfin; |
| SP += 12; |
| RTS; |
| |
| __unknown_exception_occurred: |
| |
| /* This function is invoked by the default exception |
| * handler, if it does not recognise the kind of |
| * exception that has occurred. In other words, the |
| * default handler only handles some of the system's |
| * exception types, and it does not expect any others |
| * to occur. If your application is going to be using |
| * other kinds of exceptions, you must replace the |
| * default handler with your own, that handles all the |
| * exceptions you will use. |
| * |
| * Since there's nothing we can do, we just loop here |
| * at what we hope is a suitably informative label. |
| */ |
| |
| IDLE; |
| do_not_know_what_to_do: |
| CSYNC; |
| JUMP __unknown_exception_occurred; |
| |
| RTS; |
| .__unknown_exception_occurred.end: |
| .global __unknown_exception_occurred; |
| .type __unknown_exception_occurred, STT_FUNC; |
| |
| panic_bfin: |
| RTS; |
| |