18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  linux/arch/arm/kernel/iwmmxt.S
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  XScale iWMMXt (Concan) context switching and handling
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci *  Initial code:
88c2ecf20Sopenharmony_ci *  Copyright (c) 2003, Intel Corporation
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci *  Full lazy switching support, optimizations and more, by Nicolas Pitre
118c2ecf20Sopenharmony_ci*   Copyright (c) 2003-2004, MontaVista Software, Inc.
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/linkage.h>
158c2ecf20Sopenharmony_ci#include <asm/ptrace.h>
168c2ecf20Sopenharmony_ci#include <asm/thread_info.h>
178c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h>
188c2ecf20Sopenharmony_ci#include <asm/assembler.h>
198c2ecf20Sopenharmony_ci#include "iwmmxt.h"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#if defined(CONFIG_CPU_PJ4) || defined(CONFIG_CPU_PJ4B)
228c2ecf20Sopenharmony_ci#define PJ4(code...)		code
238c2ecf20Sopenharmony_ci#define XSC(code...)
248c2ecf20Sopenharmony_ci#elif defined(CONFIG_CPU_MOHAWK) || \
258c2ecf20Sopenharmony_ci	defined(CONFIG_CPU_XSC3) || \
268c2ecf20Sopenharmony_ci	defined(CONFIG_CPU_XSCALE)
278c2ecf20Sopenharmony_ci#define PJ4(code...)
288c2ecf20Sopenharmony_ci#define XSC(code...)		code
298c2ecf20Sopenharmony_ci#else
308c2ecf20Sopenharmony_ci#error "Unsupported iWMMXt architecture"
318c2ecf20Sopenharmony_ci#endif
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#define MMX_WR0		 	(0x00)
348c2ecf20Sopenharmony_ci#define MMX_WR1		 	(0x08)
358c2ecf20Sopenharmony_ci#define MMX_WR2		 	(0x10)
368c2ecf20Sopenharmony_ci#define MMX_WR3			(0x18)
378c2ecf20Sopenharmony_ci#define MMX_WR4		 	(0x20)
388c2ecf20Sopenharmony_ci#define MMX_WR5		 	(0x28)
398c2ecf20Sopenharmony_ci#define MMX_WR6		 	(0x30)
408c2ecf20Sopenharmony_ci#define MMX_WR7		 	(0x38)
418c2ecf20Sopenharmony_ci#define MMX_WR8		 	(0x40)
428c2ecf20Sopenharmony_ci#define MMX_WR9		 	(0x48)
438c2ecf20Sopenharmony_ci#define MMX_WR10		(0x50)
448c2ecf20Sopenharmony_ci#define MMX_WR11		(0x58)
458c2ecf20Sopenharmony_ci#define MMX_WR12		(0x60)
468c2ecf20Sopenharmony_ci#define MMX_WR13		(0x68)
478c2ecf20Sopenharmony_ci#define MMX_WR14		(0x70)
488c2ecf20Sopenharmony_ci#define MMX_WR15		(0x78)
498c2ecf20Sopenharmony_ci#define MMX_WCSSF		(0x80)
508c2ecf20Sopenharmony_ci#define MMX_WCASF		(0x84)
518c2ecf20Sopenharmony_ci#define MMX_WCGR0		(0x88)
528c2ecf20Sopenharmony_ci#define MMX_WCGR1		(0x8C)
538c2ecf20Sopenharmony_ci#define MMX_WCGR2		(0x90)
548c2ecf20Sopenharmony_ci#define MMX_WCGR3		(0x94)
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#define MMX_SIZE		(0x98)
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	.text
598c2ecf20Sopenharmony_ci	.arm
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/*
628c2ecf20Sopenharmony_ci * Lazy switching of Concan coprocessor context
638c2ecf20Sopenharmony_ci *
648c2ecf20Sopenharmony_ci * r10 = struct thread_info pointer
658c2ecf20Sopenharmony_ci * r9  = ret_from_exception
668c2ecf20Sopenharmony_ci * lr  = undefined instr exit
678c2ecf20Sopenharmony_ci *
688c2ecf20Sopenharmony_ci * called from prefetch exception handler with interrupts enabled
698c2ecf20Sopenharmony_ci */
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ciENTRY(iwmmxt_task_enable)
728c2ecf20Sopenharmony_ci	inc_preempt_count r10, r3
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	XSC(mrc	p15, 0, r2, c15, c1, 0)
758c2ecf20Sopenharmony_ci	PJ4(mrc p15, 0, r2, c1, c0, 2)
768c2ecf20Sopenharmony_ci	@ CP0 and CP1 accessible?
778c2ecf20Sopenharmony_ci	XSC(tst	r2, #0x3)
788c2ecf20Sopenharmony_ci	PJ4(tst	r2, #0xf)
798c2ecf20Sopenharmony_ci	bne	4f				@ if so no business here
808c2ecf20Sopenharmony_ci	@ enable access to CP0 and CP1
818c2ecf20Sopenharmony_ci	XSC(orr	r2, r2, #0x3)
828c2ecf20Sopenharmony_ci	XSC(mcr	p15, 0, r2, c15, c1, 0)
838c2ecf20Sopenharmony_ci	PJ4(orr	r2, r2, #0xf)
848c2ecf20Sopenharmony_ci	PJ4(mcr	p15, 0, r2, c1, c0, 2)
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	ldr	r3, =concan_owner
878c2ecf20Sopenharmony_ci	add	r0, r10, #TI_IWMMXT_STATE	@ get task Concan save area
888c2ecf20Sopenharmony_ci	ldr	r2, [sp, #60]			@ current task pc value
898c2ecf20Sopenharmony_ci	ldr	r1, [r3]			@ get current Concan owner
908c2ecf20Sopenharmony_ci	str	r0, [r3]			@ this task now owns Concan regs
918c2ecf20Sopenharmony_ci	sub	r2, r2, #4			@ adjust pc back
928c2ecf20Sopenharmony_ci	str	r2, [sp, #60]
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	mrc	p15, 0, r2, c2, c0, 0
958c2ecf20Sopenharmony_ci	mov	r2, r2				@ cpwait
968c2ecf20Sopenharmony_ci	bl	concan_save
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci#ifdef CONFIG_PREEMPT_COUNT
998c2ecf20Sopenharmony_ci	get_thread_info r10
1008c2ecf20Sopenharmony_ci#endif
1018c2ecf20Sopenharmony_ci4:	dec_preempt_count r10, r3
1028c2ecf20Sopenharmony_ci	ret	r9				@ normal exit from exception
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ciconcan_save:
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	teq	r1, #0				@ test for last ownership
1078c2ecf20Sopenharmony_ci	beq	concan_load			@ no owner, skip save
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	tmrc	r2, wCon
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	@ CUP? wCx
1128c2ecf20Sopenharmony_ci	tst	r2, #0x1
1138c2ecf20Sopenharmony_ci	beq 	1f
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ciconcan_dump:
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	wstrw	wCSSF, r1, MMX_WCSSF
1188c2ecf20Sopenharmony_ci	wstrw	wCASF, r1, MMX_WCASF
1198c2ecf20Sopenharmony_ci	wstrw	wCGR0, r1, MMX_WCGR0
1208c2ecf20Sopenharmony_ci	wstrw	wCGR1, r1, MMX_WCGR1
1218c2ecf20Sopenharmony_ci	wstrw	wCGR2, r1, MMX_WCGR2
1228c2ecf20Sopenharmony_ci	wstrw	wCGR3, r1, MMX_WCGR3
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci1:	@ MUP? wRn
1258c2ecf20Sopenharmony_ci	tst	r2, #0x2
1268c2ecf20Sopenharmony_ci	beq	2f
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	wstrd	wR0,  r1, MMX_WR0
1298c2ecf20Sopenharmony_ci	wstrd	wR1,  r1, MMX_WR1
1308c2ecf20Sopenharmony_ci	wstrd	wR2,  r1, MMX_WR2
1318c2ecf20Sopenharmony_ci	wstrd	wR3,  r1, MMX_WR3
1328c2ecf20Sopenharmony_ci	wstrd	wR4,  r1, MMX_WR4
1338c2ecf20Sopenharmony_ci	wstrd	wR5,  r1, MMX_WR5
1348c2ecf20Sopenharmony_ci	wstrd	wR6,  r1, MMX_WR6
1358c2ecf20Sopenharmony_ci	wstrd	wR7,  r1, MMX_WR7
1368c2ecf20Sopenharmony_ci	wstrd	wR8,  r1, MMX_WR8
1378c2ecf20Sopenharmony_ci	wstrd	wR9,  r1, MMX_WR9
1388c2ecf20Sopenharmony_ci	wstrd	wR10, r1, MMX_WR10
1398c2ecf20Sopenharmony_ci	wstrd	wR11, r1, MMX_WR11
1408c2ecf20Sopenharmony_ci	wstrd	wR12, r1, MMX_WR12
1418c2ecf20Sopenharmony_ci	wstrd	wR13, r1, MMX_WR13
1428c2ecf20Sopenharmony_ci	wstrd	wR14, r1, MMX_WR14
1438c2ecf20Sopenharmony_ci	wstrd	wR15, r1, MMX_WR15
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci2:	teq	r0, #0				@ anything to load?
1468c2ecf20Sopenharmony_ci	reteq	lr				@ if not, return
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ciconcan_load:
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	@ Load wRn
1518c2ecf20Sopenharmony_ci	wldrd	wR0,  r0, MMX_WR0
1528c2ecf20Sopenharmony_ci	wldrd	wR1,  r0, MMX_WR1
1538c2ecf20Sopenharmony_ci	wldrd	wR2,  r0, MMX_WR2
1548c2ecf20Sopenharmony_ci	wldrd	wR3,  r0, MMX_WR3
1558c2ecf20Sopenharmony_ci	wldrd	wR4,  r0, MMX_WR4
1568c2ecf20Sopenharmony_ci	wldrd	wR5,  r0, MMX_WR5
1578c2ecf20Sopenharmony_ci	wldrd	wR6,  r0, MMX_WR6
1588c2ecf20Sopenharmony_ci	wldrd	wR7,  r0, MMX_WR7
1598c2ecf20Sopenharmony_ci	wldrd	wR8,  r0, MMX_WR8
1608c2ecf20Sopenharmony_ci	wldrd	wR9,  r0, MMX_WR9
1618c2ecf20Sopenharmony_ci	wldrd	wR10, r0, MMX_WR10
1628c2ecf20Sopenharmony_ci	wldrd	wR11, r0, MMX_WR11
1638c2ecf20Sopenharmony_ci	wldrd	wR12, r0, MMX_WR12
1648c2ecf20Sopenharmony_ci	wldrd	wR13, r0, MMX_WR13
1658c2ecf20Sopenharmony_ci	wldrd	wR14, r0, MMX_WR14
1668c2ecf20Sopenharmony_ci	wldrd	wR15, r0, MMX_WR15
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	@ Load wCx
1698c2ecf20Sopenharmony_ci	wldrw	wCSSF, r0, MMX_WCSSF
1708c2ecf20Sopenharmony_ci	wldrw	wCASF, r0, MMX_WCASF
1718c2ecf20Sopenharmony_ci	wldrw	wCGR0, r0, MMX_WCGR0
1728c2ecf20Sopenharmony_ci	wldrw	wCGR1, r0, MMX_WCGR1
1738c2ecf20Sopenharmony_ci	wldrw	wCGR2, r0, MMX_WCGR2
1748c2ecf20Sopenharmony_ci	wldrw	wCGR3, r0, MMX_WCGR3
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	@ clear CUP/MUP (only if r1 != 0)
1778c2ecf20Sopenharmony_ci	teq	r1, #0
1788c2ecf20Sopenharmony_ci	mov 	r2, #0
1798c2ecf20Sopenharmony_ci	reteq	lr
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	tmcr	wCon, r2
1828c2ecf20Sopenharmony_ci	ret	lr
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ciENDPROC(iwmmxt_task_enable)
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci/*
1878c2ecf20Sopenharmony_ci * Back up Concan regs to save area and disable access to them
1888c2ecf20Sopenharmony_ci * (mainly for gdb or sleep mode usage)
1898c2ecf20Sopenharmony_ci *
1908c2ecf20Sopenharmony_ci * r0 = struct thread_info pointer of target task or NULL for any
1918c2ecf20Sopenharmony_ci */
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ciENTRY(iwmmxt_task_disable)
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	stmfd	sp!, {r4, lr}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	mrs	ip, cpsr
1988c2ecf20Sopenharmony_ci	orr	r2, ip, #PSR_I_BIT		@ disable interrupts
1998c2ecf20Sopenharmony_ci	msr	cpsr_c, r2
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	ldr	r3, =concan_owner
2028c2ecf20Sopenharmony_ci	add	r2, r0, #TI_IWMMXT_STATE	@ get task Concan save area
2038c2ecf20Sopenharmony_ci	ldr	r1, [r3]			@ get current Concan owner
2048c2ecf20Sopenharmony_ci	teq	r1, #0				@ any current owner?
2058c2ecf20Sopenharmony_ci	beq	1f				@ no: quit
2068c2ecf20Sopenharmony_ci	teq	r0, #0				@ any owner?
2078c2ecf20Sopenharmony_ci	teqne	r1, r2				@ or specified one?
2088c2ecf20Sopenharmony_ci	bne	1f				@ no: quit
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	@ enable access to CP0 and CP1
2118c2ecf20Sopenharmony_ci	XSC(mrc	p15, 0, r4, c15, c1, 0)
2128c2ecf20Sopenharmony_ci	XSC(orr	r4, r4, #0x3)
2138c2ecf20Sopenharmony_ci	XSC(mcr	p15, 0, r4, c15, c1, 0)
2148c2ecf20Sopenharmony_ci	PJ4(mrc p15, 0, r4, c1, c0, 2)
2158c2ecf20Sopenharmony_ci	PJ4(orr	r4, r4, #0xf)
2168c2ecf20Sopenharmony_ci	PJ4(mcr	p15, 0, r4, c1, c0, 2)
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	mov	r0, #0				@ nothing to load
2198c2ecf20Sopenharmony_ci	str	r0, [r3]			@ no more current owner
2208c2ecf20Sopenharmony_ci	mrc	p15, 0, r2, c2, c0, 0
2218c2ecf20Sopenharmony_ci	mov	r2, r2				@ cpwait
2228c2ecf20Sopenharmony_ci	bl	concan_save
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	@ disable access to CP0 and CP1
2258c2ecf20Sopenharmony_ci	XSC(bic	r4, r4, #0x3)
2268c2ecf20Sopenharmony_ci	XSC(mcr	p15, 0, r4, c15, c1, 0)
2278c2ecf20Sopenharmony_ci	PJ4(bic	r4, r4, #0xf)
2288c2ecf20Sopenharmony_ci	PJ4(mcr	p15, 0, r4, c1, c0, 2)
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	mrc	p15, 0, r2, c2, c0, 0
2318c2ecf20Sopenharmony_ci	mov	r2, r2				@ cpwait
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci1:	msr	cpsr_c, ip			@ restore interrupt mode
2348c2ecf20Sopenharmony_ci	ldmfd	sp!, {r4, pc}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ciENDPROC(iwmmxt_task_disable)
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci/*
2398c2ecf20Sopenharmony_ci * Copy Concan state to given memory address
2408c2ecf20Sopenharmony_ci *
2418c2ecf20Sopenharmony_ci * r0 = struct thread_info pointer of target task
2428c2ecf20Sopenharmony_ci * r1 = memory address where to store Concan state
2438c2ecf20Sopenharmony_ci *
2448c2ecf20Sopenharmony_ci * this is called mainly in the creation of signal stack frames
2458c2ecf20Sopenharmony_ci */
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ciENTRY(iwmmxt_task_copy)
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	mrs	ip, cpsr
2508c2ecf20Sopenharmony_ci	orr	r2, ip, #PSR_I_BIT		@ disable interrupts
2518c2ecf20Sopenharmony_ci	msr	cpsr_c, r2
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	ldr	r3, =concan_owner
2548c2ecf20Sopenharmony_ci	add	r2, r0, #TI_IWMMXT_STATE	@ get task Concan save area
2558c2ecf20Sopenharmony_ci	ldr	r3, [r3]			@ get current Concan owner
2568c2ecf20Sopenharmony_ci	teq	r2, r3				@ does this task own it...
2578c2ecf20Sopenharmony_ci	beq	1f
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	@ current Concan values are in the task save area
2608c2ecf20Sopenharmony_ci	msr	cpsr_c, ip			@ restore interrupt mode
2618c2ecf20Sopenharmony_ci	mov	r0, r1
2628c2ecf20Sopenharmony_ci	mov	r1, r2
2638c2ecf20Sopenharmony_ci	mov	r2, #MMX_SIZE
2648c2ecf20Sopenharmony_ci	b	memcpy
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci1:	@ this task owns Concan regs -- grab a copy from there
2678c2ecf20Sopenharmony_ci	mov	r0, #0				@ nothing to load
2688c2ecf20Sopenharmony_ci	mov	r2, #3				@ save all regs
2698c2ecf20Sopenharmony_ci	mov	r3, lr				@ preserve return address
2708c2ecf20Sopenharmony_ci	bl	concan_dump
2718c2ecf20Sopenharmony_ci	msr	cpsr_c, ip			@ restore interrupt mode
2728c2ecf20Sopenharmony_ci	ret	r3
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ciENDPROC(iwmmxt_task_copy)
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci/*
2778c2ecf20Sopenharmony_ci * Restore Concan state from given memory address
2788c2ecf20Sopenharmony_ci *
2798c2ecf20Sopenharmony_ci * r0 = struct thread_info pointer of target task
2808c2ecf20Sopenharmony_ci * r1 = memory address where to get Concan state from
2818c2ecf20Sopenharmony_ci *
2828c2ecf20Sopenharmony_ci * this is used to restore Concan state when unwinding a signal stack frame
2838c2ecf20Sopenharmony_ci */
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ciENTRY(iwmmxt_task_restore)
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	mrs	ip, cpsr
2888c2ecf20Sopenharmony_ci	orr	r2, ip, #PSR_I_BIT		@ disable interrupts
2898c2ecf20Sopenharmony_ci	msr	cpsr_c, r2
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	ldr	r3, =concan_owner
2928c2ecf20Sopenharmony_ci	add	r2, r0, #TI_IWMMXT_STATE	@ get task Concan save area
2938c2ecf20Sopenharmony_ci	ldr	r3, [r3]			@ get current Concan owner
2948c2ecf20Sopenharmony_ci	bic	r2, r2, #0x7			@ 64-bit alignment
2958c2ecf20Sopenharmony_ci	teq	r2, r3				@ does this task own it...
2968c2ecf20Sopenharmony_ci	beq	1f
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	@ this task doesn't own Concan regs -- use its save area
2998c2ecf20Sopenharmony_ci	msr	cpsr_c, ip			@ restore interrupt mode
3008c2ecf20Sopenharmony_ci	mov	r0, r2
3018c2ecf20Sopenharmony_ci	mov	r2, #MMX_SIZE
3028c2ecf20Sopenharmony_ci	b	memcpy
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci1:	@ this task owns Concan regs -- load them directly
3058c2ecf20Sopenharmony_ci	mov	r0, r1
3068c2ecf20Sopenharmony_ci	mov	r1, #0				@ don't clear CUP/MUP
3078c2ecf20Sopenharmony_ci	mov	r3, lr				@ preserve return address
3088c2ecf20Sopenharmony_ci	bl	concan_load
3098c2ecf20Sopenharmony_ci	msr	cpsr_c, ip			@ restore interrupt mode
3108c2ecf20Sopenharmony_ci	ret	r3
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ciENDPROC(iwmmxt_task_restore)
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci/*
3158c2ecf20Sopenharmony_ci * Concan handling on task switch
3168c2ecf20Sopenharmony_ci *
3178c2ecf20Sopenharmony_ci * r0 = next thread_info pointer
3188c2ecf20Sopenharmony_ci *
3198c2ecf20Sopenharmony_ci * Called only from the iwmmxt notifier with task preemption disabled.
3208c2ecf20Sopenharmony_ci */
3218c2ecf20Sopenharmony_ciENTRY(iwmmxt_task_switch)
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	XSC(mrc	p15, 0, r1, c15, c1, 0)
3248c2ecf20Sopenharmony_ci	PJ4(mrc	p15, 0, r1, c1, c0, 2)
3258c2ecf20Sopenharmony_ci	@ CP0 and CP1 accessible?
3268c2ecf20Sopenharmony_ci	XSC(tst	r1, #0x3)
3278c2ecf20Sopenharmony_ci	PJ4(tst	r1, #0xf)
3288c2ecf20Sopenharmony_ci	bne	1f				@ yes: block them for next task
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	ldr	r2, =concan_owner
3318c2ecf20Sopenharmony_ci	add	r3, r0, #TI_IWMMXT_STATE	@ get next task Concan save area
3328c2ecf20Sopenharmony_ci	ldr	r2, [r2]			@ get current Concan owner
3338c2ecf20Sopenharmony_ci	teq	r2, r3				@ next task owns it?
3348c2ecf20Sopenharmony_ci	retne	lr				@ no: leave Concan disabled
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci1:	@ flip Concan access
3378c2ecf20Sopenharmony_ci	XSC(eor	r1, r1, #0x3)
3388c2ecf20Sopenharmony_ci	XSC(mcr	p15, 0, r1, c15, c1, 0)
3398c2ecf20Sopenharmony_ci	PJ4(eor r1, r1, #0xf)
3408c2ecf20Sopenharmony_ci	PJ4(mcr	p15, 0, r1, c1, c0, 2)
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	mrc	p15, 0, r1, c2, c0, 0
3438c2ecf20Sopenharmony_ci	sub	pc, lr, r1, lsr #32		@ cpwait and return
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ciENDPROC(iwmmxt_task_switch)
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci/*
3488c2ecf20Sopenharmony_ci * Remove Concan ownership of given task
3498c2ecf20Sopenharmony_ci *
3508c2ecf20Sopenharmony_ci * r0 = struct thread_info pointer
3518c2ecf20Sopenharmony_ci */
3528c2ecf20Sopenharmony_ciENTRY(iwmmxt_task_release)
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	mrs	r2, cpsr
3558c2ecf20Sopenharmony_ci	orr	ip, r2, #PSR_I_BIT		@ disable interrupts
3568c2ecf20Sopenharmony_ci	msr	cpsr_c, ip
3578c2ecf20Sopenharmony_ci	ldr	r3, =concan_owner
3588c2ecf20Sopenharmony_ci	add	r0, r0, #TI_IWMMXT_STATE	@ get task Concan save area
3598c2ecf20Sopenharmony_ci	ldr	r1, [r3]			@ get current Concan owner
3608c2ecf20Sopenharmony_ci	eors	r0, r0, r1			@ if equal...
3618c2ecf20Sopenharmony_ci	streq	r0, [r3]			@ then clear ownership
3628c2ecf20Sopenharmony_ci	msr	cpsr_c, r2			@ restore interrupts
3638c2ecf20Sopenharmony_ci	ret	lr
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ciENDPROC(iwmmxt_task_release)
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	.data
3688c2ecf20Sopenharmony_ci	.align	2
3698c2ecf20Sopenharmony_ciconcan_owner:
3708c2ecf20Sopenharmony_ci	.word	0
3718c2ecf20Sopenharmony_ci
372