linux/arch/blackfin/mach-common/lock.S

224 lines
4.2 KiB
ArmAsm

/*
* File: arch/blackfin/mach-common/lock.S
* Based on:
* Author: LG Soft India
*
* Created: ?
* Description: kernel locks
*
* 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/blackfin.h>
.text
/* When you come here, it is assumed that
* R0 - Which way to be locked
*/
ENTRY(_cache_grab_lock)
[--SP]=( R7:0,P5:0 );
P1.H = HI(IMEM_CONTROL);
P1.L = LO(IMEM_CONTROL);
P5.H = HI(ICPLB_ADDR0);
P5.L = LO(ICPLB_ADDR0);
P4.H = HI(ICPLB_DATA0);
P4.L = LO(ICPLB_DATA0);
R7 = R0;
/* If the code of interest already resides in the cache
* invalidate the entire cache itself.
* invalidate_entire_icache;
*/
SP += -12;
[--SP] = RETS;
CALL _invalidate_entire_icache;
RETS = [SP++];
SP += 12;
/* Disable the Interrupts*/
CLI R3;
.LLOCK_WAY:
/* Way0 - 0xFFA133E0
* Way1 - 0xFFA137E0
* Way2 - 0xFFA13BE0 Total Way Size = 4K
* Way3 - 0xFFA13FE0
*/
/* Procedure Ex. -Set the locks for other ways by setting ILOC[3:1]
* Only Way0 of the instruction cache can now be
* replaced by a new code
*/
R5 = R7;
CC = BITTST(R7,0);
IF CC JUMP .LCLEAR1;
R7 = 0;
BITSET(R7,0);
JUMP .LDONE1;
.LCLEAR1:
R7 = 0;
BITCLR(R7,0);
.LDONE1: R4 = R7 << 3;
R7 = [P1];
R7 = R7 | R4;
SSYNC; /* SSYNC required writing to IMEM_CONTROL. */
.align 8;
[P1] = R7;
SSYNC;
R7 = R5;
CC = BITTST(R7,1);
IF CC JUMP .LCLEAR2;
R7 = 0;
BITSET(R7,1);
JUMP .LDONE2;
.LCLEAR2:
R7 = 0;
BITCLR(R7,1);
.LDONE2: R4 = R7 << 3;
R7 = [P1];
R7 = R7 | R4;
SSYNC; /* SSYNC required writing to IMEM_CONTROL. */
.align 8;
[P1] = R7;
SSYNC;
R7 = R5;
CC = BITTST(R7,2);
IF CC JUMP .LCLEAR3;
R7 = 0;
BITSET(R7,2);
JUMP .LDONE3;
.LCLEAR3:
R7 = 0;
BITCLR(R7,2);
.LDONE3: R4 = R7 << 3;
R7 = [P1];
R7 = R7 | R4;
SSYNC; /* SSYNC required writing to IMEM_CONTROL. */
.align 8;
[P1] = R7;
SSYNC;
R7 = R5;
CC = BITTST(R7,3);
IF CC JUMP .LCLEAR4;
R7 = 0;
BITSET(R7,3);
JUMP .LDONE4;
.LCLEAR4:
R7 = 0;
BITCLR(R7,3);
.LDONE4: R4 = R7 << 3;
R7 = [P1];
R7 = R7 | R4;
SSYNC; /* SSYNC required writing to IMEM_CONTROL. */
.align 8;
[P1] = R7;
SSYNC;
STI R3;
( R7:0,P5:0 ) = [SP++];
RTS;
ENDPROC(_cache_grab_lock)
/* After the execution of critical code, the code is now locked into
* the cache way. Now we need to set ILOC.
*
* R0 - Which way to be locked
*/
ENTRY(_cache_lock)
[--SP]=( R7:0,P5:0 );
P1.H = HI(IMEM_CONTROL);
P1.L = LO(IMEM_CONTROL);
/* Disable the Interrupts*/
CLI R3;
R7 = [P1];
R2 = ~(0x78) (X); /* mask out ILOC */
R7 = R7 & R2;
R0 = R0 << 3;
R7 = R0 | R7;
SSYNC; /* SSYNC required writing to IMEM_CONTROL. */
.align 8;
[P1] = R7;
SSYNC;
/* Renable the Interrupts */
STI R3;
( R7:0,P5:0 ) = [SP++];
RTS;
ENDPROC(_cache_lock)
/* Invalidate the Entire Instruction cache by
* disabling IMC bit
*/
ENTRY(_invalidate_entire_icache)
[--SP] = ( R7:5);
P0.L = LO(IMEM_CONTROL);
P0.H = HI(IMEM_CONTROL);
R7 = [P0];
/* Clear the IMC bit , All valid bits in the instruction
* cache are set to the invalid state
*/
BITCLR(R7,IMC_P);
CLI R6;
SSYNC; /* SSYNC required before invalidating cache. */
.align 8;
[P0] = R7;
SSYNC;
STI R6;
/* Configures the instruction cache agian */
R6 = (IMC | ENICPLB);
R7 = R7 | R6;
CLI R6;
SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
.align 8;
[P0] = R7;
SSYNC;
STI R6;
( R7:5) = [SP++];
RTS;
ENDPROC(_invalidate_entire_icache)