/* * File: arch/blackfin/mach-common/cplbhdlr.S * Based on: * Author: LG Soft India * * Created: ? * Description: CPLB exception handler * * Modified: * Copyright 2004-2006 Analog Devices Inc. * * Bugs: Enter bugs at http://blackfin.uclinux.org/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see the file COPYING, or write * to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <linux/linkage.h> #include <asm/cplb.h> #include <asm/entry.h> #ifdef CONFIG_EXCPT_IRQ_SYSC_L1 .section .l1.text #else .text #endif .type _cplb_mgr, STT_FUNC; .type _panic_cplb_error, STT_FUNC; .align 2 .global __cplb_hdr; .type __cplb_hdr, STT_FUNC; ENTRY(__cplb_hdr) 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 .Lnot_data_write; R0 = 2; /* is a write to data space*/ JUMP .Lis_icplb_miss; .Lnot_data_write: R1 = 0x2C; /* CPLB miss on an instruction fetch */ CC = R2 == R1; R0 = 0; /* is_data_miss == False*/ IF CC JUMP .Lis_icplb_miss; R1 = 0x26; CC = R2 == R1; IF !CC JUMP .Lunknown; R0 = 1; /* is_data_miss == True*/ .Lis_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 .Lnot_replaced; RTS; /* * Diagnostic exception handlers */ .Lunknown: R0 = CPLB_UNKNOWN_ERR; JUMP .Lcplb_error; .Lnot_replaced: CC = R0 == CPLB_NO_UNLOCKED; IF !CC JUMP .Lnext_check; R0 = CPLB_NO_UNLOCKED; JUMP .Lcplb_error; .Lnext_check: CC = R0 == CPLB_NO_ADDR_MATCH; IF !CC JUMP .Lnext_check2; R0 = CPLB_NO_ADDR_MATCH; JUMP .Lcplb_error; .Lnext_check2: CC = R0 == CPLB_PROT_VIOL; IF !CC JUMP .Lstrange_return_from_cplb_mgr; R0 = CPLB_PROT_VIOL; JUMP .Lcplb_error; .Lstrange_return_from_cplb_mgr: IDLE; CSYNC; JUMP .Lstrange_return_from_cplb_mgr; .Lcplb_error: R1 = sp; SP += -12; call _panic_cplb_error; SP += 12; JUMP _handle_bad_cplb;