Merge git://git.infradead.org/battery-2.6
[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 ENTRY(__cplb_hdr)
46         R2 = SEQSTAT;
47
48         /* Mask the contents of SEQSTAT and leave only EXCAUSE in R2 */
49         R2 <<= 26;
50         R2 >>= 26;
51
52         R1 = 0x23; /* Data access CPLB protection violation */
53         CC = R2 == R1;
54         IF !CC JUMP .Lnot_data_write;
55         R0 = 2;         /* is a write to data space*/
56         JUMP .Lis_icplb_miss;
57
58 .Lnot_data_write:
59         R1 = 0x2C; /* CPLB miss on an instruction fetch */
60         CC = R2 == R1;
61         R0 = 0;         /* is_data_miss == False*/
62         IF CC JUMP .Lis_icplb_miss;
63
64         R1 = 0x26;
65         CC = R2 == R1;
66         IF !CC JUMP .Lunknown;
67
68         R0 = 1;         /* is_data_miss == True*/
69
70 .Lis_icplb_miss:
71
72 #if defined(CONFIG_BFIN_ICACHE) || defined(CONFIG_BFIN_DCACHE)
73 # if defined(CONFIG_BFIN_ICACHE) && !defined(CONFIG_BFIN_DCACHE)
74         R1 = CPLB_ENABLE_ICACHE;
75 # endif
76 # if !defined(CONFIG_BFIN_ICACHE) && defined(CONFIG_BFIN_DCACHE)
77         R1 = CPLB_ENABLE_DCACHE;
78 # endif
79 # if defined(CONFIG_BFIN_ICACHE) && defined(CONFIG_BFIN_DCACHE)
80         R1 = CPLB_ENABLE_DCACHE | CPLB_ENABLE_ICACHE;
81 # endif
82 #else
83         R1 = 0;
84 #endif
85
86         [--SP] = RETS;
87         CALL _cplb_mgr;
88         RETS = [SP++];
89         CC = R0 == 0;
90         IF !CC JUMP .Lnot_replaced;
91         RTS;
92
93 /*
94  * Diagnostic exception handlers
95  */
96 .Lunknown:
97         R0 = CPLB_UNKNOWN_ERR;
98         JUMP .Lcplb_error;
99
100 .Lnot_replaced:
101         CC = R0 == CPLB_NO_UNLOCKED;
102         IF !CC JUMP .Lnext_check;
103         R0 = CPLB_NO_UNLOCKED;
104         JUMP .Lcplb_error;
105
106 .Lnext_check:
107         CC = R0 == CPLB_NO_ADDR_MATCH;
108         IF !CC JUMP .Lnext_check2;
109         R0 = CPLB_NO_ADDR_MATCH;
110         JUMP .Lcplb_error;
111
112 .Lnext_check2:
113         CC = R0 == CPLB_PROT_VIOL;
114         IF !CC JUMP .Lstrange_return_from_cplb_mgr;
115         R0 = CPLB_PROT_VIOL;
116         JUMP .Lcplb_error;
117
118 .Lstrange_return_from_cplb_mgr:
119         IDLE;
120         CSYNC;
121         JUMP .Lstrange_return_from_cplb_mgr;
122
123 .Lcplb_error:
124         R1 = sp;
125         SP += -12;
126         call _panic_cplb_error;
127         SP += 12;
128         JUMP _handle_bad_cplb;
129
130 ENDPROC(__cplb_hdr)