Wolfgang Denk | 6cb142f | 2006-03-12 02:12:27 +0100 | [diff] [blame] | 1 | /* Copyright (C) 2003 Analog Devices, Inc. All Rights Reserved. |
| 2 | * |
| 3 | * This file is subject to the terms and conditions of the GNU General Public |
| 4 | * License. |
| 5 | * |
| 6 | * Blackfin BF533/2.6 support : LG Soft India |
| 7 | */ |
| 8 | |
| 9 | |
| 10 | /* Include an exception handler to invoke the CPLB manager |
| 11 | */ |
| 12 | |
| 13 | #include <asm-blackfin/linkage.h> |
| 14 | #include <asm/cplb.h> |
| 15 | #include <asm/entry.h> |
| 16 | |
| 17 | |
| 18 | .text |
| 19 | |
| 20 | .globl _cplb_hdr; |
| 21 | .type _cplb_hdr, STT_FUNC; |
| 22 | .extern _cplb_mgr; |
| 23 | .type _cplb_mgr, STT_FUNC; |
| 24 | .extern __unknown_exception_occurred; |
| 25 | .type __unknown_exception_occurred, STT_FUNC; |
| 26 | .extern __cplb_miss_all_locked; |
| 27 | .type __cplb_miss_all_locked, STT_FUNC; |
| 28 | .extern __cplb_miss_without_replacement; |
| 29 | .type __cplb_miss_without_replacement, STT_FUNC; |
| 30 | .extern __cplb_protection_violation; |
| 31 | .type __cplb_protection_violation, STT_FUNC; |
| 32 | .extern panic_pv; |
| 33 | |
| 34 | .align 2; |
| 35 | |
| 36 | ENTRY(_cplb_hdr) |
| 37 | SSYNC; |
| 38 | [--SP] = ( R7:0, P5:0 ); |
| 39 | [--SP] = ASTAT; |
| 40 | [--SP] = SEQSTAT; |
| 41 | [--SP] = I0; |
| 42 | [--SP] = I1; |
| 43 | [--SP] = I2; |
| 44 | [--SP] = I3; |
| 45 | [--SP] = LT0; |
| 46 | [--SP] = LB0; |
| 47 | [--SP] = LC0; |
| 48 | [--SP] = LT1; |
| 49 | [--SP] = LB1; |
| 50 | [--SP] = LC1; |
| 51 | R2 = SEQSTAT; |
| 52 | |
| 53 | /*Mask the contents of SEQSTAT and leave only EXCAUSE in R2*/ |
| 54 | R2 <<= 26; |
| 55 | R2 >>= 26; |
| 56 | |
| 57 | R1 = 0x23; /* Data access CPLB protection violation */ |
| 58 | CC = R2 == R1; |
| 59 | IF !CC JUMP not_data_write; |
| 60 | R0 = 2; /* is a write to data space*/ |
| 61 | JUMP is_icplb_miss; |
| 62 | |
| 63 | not_data_write: |
| 64 | R1 = 0x2C; /* CPLB miss on an instruction fetch */ |
| 65 | CC = R2 == R1; |
| 66 | R0 = 0; /* is_data_miss == False*/ |
| 67 | IF CC JUMP is_icplb_miss; |
| 68 | |
| 69 | R1 = 0x26; |
| 70 | CC = R2 == R1; |
| 71 | IF !CC JUMP unknown; |
| 72 | |
| 73 | R0 = 1; /* is_data_miss == True*/ |
| 74 | |
| 75 | is_icplb_miss: |
| 76 | |
| 77 | #if ( defined (CONFIG_BLKFIN_CACHE) || defined (CONFIG_BLKFIN_DCACHE)) |
| 78 | #if ( defined (CONFIG_BLKFIN_CACHE) && !defined (CONFIG_BLKFIN_DCACHE)) |
| 79 | R1 = CPLB_ENABLE_ICACHE; |
| 80 | #endif |
| 81 | #if ( !defined (CONFIG_BLKFIN_CACHE) && defined (CONFIG_BLKFIN_DCACHE)) |
| 82 | R1 = CPLB_ENABLE_DCACHE; |
| 83 | #endif |
| 84 | #if ( defined (CONFIG_BLKFIN_CACHE) && defined (CONFIG_BLKFIN_DCACHE)) |
| 85 | R1 = CPLB_ENABLE_DCACHE | CPLB_ENABLE_ICACHE; |
| 86 | #endif |
| 87 | #else |
| 88 | R1 = 0; |
| 89 | #endif |
| 90 | |
| 91 | [--SP] = RETS; |
| 92 | CALL _cplb_mgr; |
| 93 | RETS = [SP++]; |
| 94 | CC = R0 == 0; |
| 95 | IF !CC JUMP not_replaced; |
| 96 | LC1 = [SP++]; |
| 97 | LB1 = [SP++]; |
| 98 | LT1 = [SP++]; |
| 99 | LC0 = [SP++]; |
| 100 | LB0 = [SP++]; |
| 101 | LT0 = [SP++]; |
| 102 | I3 = [SP++]; |
| 103 | I2 = [SP++]; |
| 104 | I1 = [SP++]; |
| 105 | I0 = [SP++]; |
| 106 | SEQSTAT = [SP++]; |
| 107 | ASTAT = [SP++]; |
| 108 | ( R7:0, P5:0 ) = [SP++]; |
| 109 | RTS; |
| 110 | |
| 111 | unknown: |
| 112 | [--SP] = RETS; |
| 113 | CALL __unknown_exception_occurred; |
| 114 | RETS = [SP++]; |
| 115 | JUMP unknown; |
| 116 | not_replaced: |
| 117 | CC = R0 == CPLB_NO_UNLOCKED; |
| 118 | IF !CC JUMP next_check; |
| 119 | [--SP] = RETS; |
| 120 | CALL __cplb_miss_all_locked; |
| 121 | RETS = [SP++]; |
| 122 | next_check: |
| 123 | CC = R0 == CPLB_NO_ADDR_MATCH; |
| 124 | IF !CC JUMP next_check2; |
| 125 | [--SP] = RETS; |
| 126 | CALL __cplb_miss_without_replacement; |
| 127 | RETS = [SP++]; |
| 128 | JUMP not_replaced; |
| 129 | next_check2: |
| 130 | CC = R0 == CPLB_PROT_VIOL; |
| 131 | IF !CC JUMP strange_return_from_cplb_mgr; |
| 132 | [--SP] = RETS; |
| 133 | CALL __cplb_protection_violation; |
| 134 | RETS = [SP++]; |
| 135 | JUMP not_replaced; |
| 136 | strange_return_from_cplb_mgr: |
| 137 | IDLE; |
| 138 | CSYNC; |
| 139 | JUMP strange_return_from_cplb_mgr; |
| 140 | |
| 141 | /************************************ |
| 142 | * Diagnostic exception handlers |
| 143 | */ |
| 144 | |
| 145 | __cplb_miss_all_locked: |
| 146 | sp += -12; |
| 147 | R0 = CPLB_NO_UNLOCKED; |
| 148 | call panic_bfin; |
| 149 | SP += 12; |
| 150 | RTS; |
| 151 | |
| 152 | __cplb_miss_without_replacement: |
| 153 | sp += -12; |
| 154 | R0 = CPLB_NO_ADDR_MATCH; |
| 155 | call panic_bfin; |
| 156 | SP += 12; |
| 157 | RTS; |
| 158 | |
| 159 | __cplb_protection_violation: |
| 160 | sp += -12; |
| 161 | R0 = CPLB_PROT_VIOL; |
| 162 | call panic_bfin; |
| 163 | SP += 12; |
| 164 | RTS; |
| 165 | |
| 166 | __unknown_exception_occurred: |
| 167 | |
| 168 | /* This function is invoked by the default exception |
| 169 | * handler, if it does not recognise the kind of |
| 170 | * exception that has occurred. In other words, the |
| 171 | * default handler only handles some of the system's |
| 172 | * exception types, and it does not expect any others |
| 173 | * to occur. If your application is going to be using |
| 174 | * other kinds of exceptions, you must replace the |
| 175 | * default handler with your own, that handles all the |
| 176 | * exceptions you will use. |
| 177 | * |
| 178 | * Since there's nothing we can do, we just loop here |
| 179 | * at what we hope is a suitably informative label. |
| 180 | */ |
| 181 | |
| 182 | IDLE; |
| 183 | do_not_know_what_to_do: |
| 184 | CSYNC; |
| 185 | JUMP __unknown_exception_occurred; |
| 186 | |
| 187 | RTS; |
| 188 | .__unknown_exception_occurred.end: |
| 189 | .global __unknown_exception_occurred; |
| 190 | .type __unknown_exception_occurred, STT_FUNC; |
| 191 | |
| 192 | panic_bfin: |
| 193 | RTS; |
| 194 | |