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
45ENTRY(__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_BLKFIN_CACHE) || defined(CONFIG_BLKFIN_DCACHE)
73# if defined(CONFIG_BLKFIN_CACHE) && !defined(CONFIG_BLKFIN_DCACHE)
74	R1 = CPLB_ENABLE_ICACHE;
75# endif
76# if !defined(CONFIG_BLKFIN_CACHE) && defined(CONFIG_BLKFIN_DCACHE)
77	R1 = CPLB_ENABLE_DCACHE;
78# endif
79# if defined(CONFIG_BLKFIN_CACHE) && defined(CONFIG_BLKFIN_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
130ENDPROC(__cplb_hdr)
131