Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
[linux-2.6] / arch / blackfin / mach-common / cplbhdlr.S
1 /*
2  * File:         arch/blackfin/mach-common/cplbhdlr.S
3  * Based on:
4  * Author:       LG Soft India
5  *
6  * Created:      ?
7  * Description:  CPLB exception handler
8  *
9  * Modified:
10  *               Copyright 2004-2006 Analog Devices Inc.
11  *
12  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, see the file COPYING, or write
26  * to the Free Software Foundation, Inc.,
27  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
28  */
29
30 #include <linux/linkage.h>
31 #include <asm/cplb.h>
32 #include <asm/entry.h>
33
34 #ifdef CONFIG_EXCPT_IRQ_SYSC_L1
35 .section .l1.text
36 #else
37 .text
38 #endif
39
40 .type _cplb_mgr, STT_FUNC;
41 .type _panic_cplb_error, STT_FUNC;
42
43 .align 2
44
45 .global __cplb_hdr;
46 .type __cplb_hdr, STT_FUNC;
47 ENTRY(__cplb_hdr)
48         R2 = SEQSTAT;
49
50         /* Mask the contents of SEQSTAT and leave only EXCAUSE in R2 */
51         R2 <<= 26;
52         R2 >>= 26;
53
54         R1 = 0x23; /* Data access CPLB protection violation */
55         CC = R2 == R1;
56         IF !CC JUMP .Lnot_data_write;
57         R0 = 2;         /* is a write to data space*/
58         JUMP .Lis_icplb_miss;
59
60 .Lnot_data_write:
61         R1 = 0x2C; /* CPLB miss on an instruction fetch */
62         CC = R2 == R1;
63         R0 = 0;         /* is_data_miss == False*/
64         IF CC JUMP .Lis_icplb_miss;
65
66         R1 = 0x26;
67         CC = R2 == R1;
68         IF !CC JUMP .Lunknown;
69
70         R0 = 1;         /* is_data_miss == True*/
71
72 .Lis_icplb_miss:
73
74 #if defined(CONFIG_BLKFIN_CACHE) || defined(CONFIG_BLKFIN_DCACHE)
75 # if defined(CONFIG_BLKFIN_CACHE) && !defined(CONFIG_BLKFIN_DCACHE)
76         R1 = CPLB_ENABLE_ICACHE;
77 # endif
78 # if !defined(CONFIG_BLKFIN_CACHE) && defined(CONFIG_BLKFIN_DCACHE)
79         R1 = CPLB_ENABLE_DCACHE;
80 # endif
81 # if defined(CONFIG_BLKFIN_CACHE) && defined(CONFIG_BLKFIN_DCACHE)
82         R1 = CPLB_ENABLE_DCACHE | CPLB_ENABLE_ICACHE;
83 # endif
84 #else
85         R1 = 0;
86 #endif
87
88         [--SP] = RETS;
89         CALL _cplb_mgr;
90         RETS = [SP++];
91         CC = R0 == 0;
92         IF !CC JUMP .Lnot_replaced;
93         RTS;
94
95 /*
96  * Diagnostic exception handlers
97  */
98 .Lunknown:
99         R0 = CPLB_UNKNOWN_ERR;
100         JUMP .Lcplb_error;
101
102 .Lnot_replaced:
103         CC = R0 == CPLB_NO_UNLOCKED;
104         IF !CC JUMP .Lnext_check;
105         R0 = CPLB_NO_UNLOCKED;
106         JUMP .Lcplb_error;
107
108 .Lnext_check:
109         CC = R0 == CPLB_NO_ADDR_MATCH;
110         IF !CC JUMP .Lnext_check2;
111         R0 = CPLB_NO_ADDR_MATCH;
112         JUMP .Lcplb_error;
113
114 .Lnext_check2:
115         CC = R0 == CPLB_PROT_VIOL;
116         IF !CC JUMP .Lstrange_return_from_cplb_mgr;
117         R0 = CPLB_PROT_VIOL;
118         JUMP .Lcplb_error;
119
120 .Lstrange_return_from_cplb_mgr:
121         IDLE;
122         CSYNC;
123         JUMP .Lstrange_return_from_cplb_mgr;
124
125 .Lcplb_error:
126         R1 = sp;
127         SP += -12;
128         call _panic_cplb_error;
129         SP += 12;
130         JUMP _handle_bad_cplb;