Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d1c645c authored by Marc Gauthier's avatar Marc Gauthier Committed by Chris Zankel
Browse files

xtensa: dispatch medium-priority interrupts



Add support for dispatching medium-priority interrupts, that is,
interrupts of priority levels 2 to EXCM_LEVEL. IRQ handling may be
preempted by higher priority IRQ.

Signed-off-by: default avatarMarc Gauthier <marc@tensilica.com>
Signed-off-by: default avatarMax Filippov <jcmvbkbc@gmail.com>
Signed-off-by: default avatarChris Zankel <chris@zankel.net>
parent d0b73b48
Loading
Loading
Loading
Loading
+3 −3
Original line number Original line Diff line number Diff line
@@ -7,7 +7,7 @@
 * License.  See the file "COPYING" in the main directory of this archive
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 * for more details.
 *
 *
 * Copyright (C) 2001 - 2005 Tensilica Inc.
 * Copyright (C) 2001 - 2008 Tensilica Inc.
 */
 */


#ifndef _XTENSA_ATOMIC_H
#ifndef _XTENSA_ATOMIC_H
@@ -24,11 +24,11 @@


/*
/*
 * This Xtensa implementation assumes that the right mechanism
 * This Xtensa implementation assumes that the right mechanism
 * for exclusion is for locking interrupts to level 1.
 * for exclusion is for locking interrupts to level EXCM_LEVEL.
 *
 *
 * Locking interrupts looks like this:
 * Locking interrupts looks like this:
 *
 *
 *    rsil a15, 1
 *    rsil a15, LOCKLEVEL
 *    <code>
 *    <code>
 *    wsr  a15, PS
 *    wsr  a15, PS
 *    rsync
 *    rsync
+2 −2
Original line number Original line Diff line number Diff line
@@ -5,7 +5,7 @@
 * License.  See the file "COPYING" in the main directory of this archive
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 * for more details.
 *
 *
 * Copyright (C) 2001 - 2005 Tensilica Inc.
 * Copyright (C) 2001 - 2008 Tensilica Inc.
 */
 */


#ifndef _XTENSA_PROCESSOR_H
#ifndef _XTENSA_PROCESSOR_H
@@ -68,7 +68,7 @@
/* LOCKLEVEL defines the interrupt level that masks all
/* LOCKLEVEL defines the interrupt level that masks all
 * general-purpose interrupts.
 * general-purpose interrupts.
 */
 */
#define LOCKLEVEL 1
#define LOCKLEVEL XCHAL_EXCM_LEVEL


/* WSBITS and WBBITS are the width of the WINDOWSTART and WINDOWBASE
/* WSBITS and WBBITS are the width of the WINDOWSTART and WINDOWBASE
 * registers
 * registers
+1 −0
Original line number Original line Diff line number Diff line
@@ -88,6 +88,7 @@
#define PS_UM_BIT		5
#define PS_UM_BIT		5
#define PS_EXCM_BIT		4
#define PS_EXCM_BIT		4
#define PS_INTLEVEL_SHIFT	0
#define PS_INTLEVEL_SHIFT	0
#define PS_INTLEVEL_WIDTH	4
#define PS_INTLEVEL_MASK	0x0000000F
#define PS_INTLEVEL_MASK	0x0000000F


/*  DBREAKCn register fields.  */
/*  DBREAKCn register fields.  */
+4 −4
Original line number Original line Diff line number Diff line
@@ -5,7 +5,7 @@
 * License.  See the file "COPYING" in the main directory of this archive
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 * for more details.
 *
 *
 * Copyright (C) 2001 - 2005 Tensilica Inc.
 * Copyright (C) 2001 - 2008 Tensilica Inc.
 */
 */


#ifndef _XTENSA_TIMEX_H
#ifndef _XTENSA_TIMEX_H
@@ -19,13 +19,13 @@
#define _INTLEVEL(x)	XCHAL_INT ## x ## _LEVEL
#define _INTLEVEL(x)	XCHAL_INT ## x ## _LEVEL
#define INTLEVEL(x)	_INTLEVEL(x)
#define INTLEVEL(x)	_INTLEVEL(x)


#if INTLEVEL(XCHAL_TIMER0_INTERRUPT) == 1
#if INTLEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL
# define LINUX_TIMER     0
# define LINUX_TIMER     0
# define LINUX_TIMER_INT XCHAL_TIMER0_INTERRUPT
# define LINUX_TIMER_INT XCHAL_TIMER0_INTERRUPT
#elif INTLEVEL(XCHAL_TIMER1_INTERRUPT) == 1
#elif INTLEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL
# define LINUX_TIMER     1
# define LINUX_TIMER     1
# define LINUX_TIMER_INT XCHAL_TIMER1_INTERRUPT
# define LINUX_TIMER_INT XCHAL_TIMER1_INTERRUPT
#elif INTLEVEL(XCHAL_TIMER2_INTERRUPT) == 1
#elif INTLEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL
# define LINUX_TIMER     2
# define LINUX_TIMER     2
# define LINUX_TIMER_INT XCHAL_TIMER2_INTERRUPT
# define LINUX_TIMER_INT XCHAL_TIMER2_INTERRUPT
#else
#else
+44 −11
Original line number Original line Diff line number Diff line
@@ -7,7 +7,7 @@
 * License.  See the file "COPYING" in the main directory of this archive
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 * for more details.
 *
 *
 * Copyright (C) 2004-2007 by Tensilica Inc.
 * Copyright (C) 2004 - 2008 by Tensilica Inc.
 *
 *
 * Chris Zankel <chris@zankel.net>
 * Chris Zankel <chris@zankel.net>
 *
 *
@@ -349,15 +349,16 @@ common_exception:
	 * so we can allow exceptions and interrupts (*) again.
	 * so we can allow exceptions and interrupts (*) again.
	 * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X)
	 * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X)
	 *
	 *
	 * (*) We only allow interrupts if PS.INTLEVEL was not set to 1 before
	 * (*) We only allow interrupts of higher priority than current IRQ
	 *     (interrupts disabled) and if this exception is not an interrupt.
	 */
	 */


	rsr	a3, ps
	rsr	a3, ps
	addi	a0, a0, -4
	addi	a0, a0, -4
	movi	a2, 1
	movi	a2, 1
	extui	a3, a3, 0, 1		# a3 = PS.INTLEVEL[0]
	extui	a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
	moveqz	a3, a2, a0		# a3 = 1 iff interrupt exception
					# a3 = PS.INTLEVEL
	movnez	a2, a3, a3		# a2 = 1: level-1, > 1: high priority
	moveqz	a3, a2, a0		# a3 = IRQ level iff interrupt
	movi	a2, 1 << PS_WOE_BIT
	movi	a2, 1 << PS_WOE_BIT
	or	a3, a3, a2
	or	a3, a3, a2
	rsr	a0, exccause
	rsr	a0, exccause
@@ -641,19 +642,51 @@ common_exception_exit:


	l32i	a0, a1, PT_DEPC
	l32i	a0, a1, PT_DEPC
	l32i	a3, a1, PT_AREG3
	l32i	a3, a1, PT_AREG3
	_bltui	a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f

	wsr	a0, depc
	l32i	a2, a1, PT_AREG2
	l32i	a2, a1, PT_AREG2
	_bgeui	a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
	l32i	a0, a1, PT_AREG0
	l32i	a1, a1, PT_AREG1
	rfde


1:
	/* Restore a0...a3 and return */
	/* Restore a0...a3 and return */


	rsr	a0, ps
	extui	a2, a0, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
	movi	a0, 2f
	slli	a2, a2, 4
	add	a0, a2, a0
	l32i	a2, a1, PT_AREG2
	jx	a0

	.macro	irq_exit_level level
	.align	16
	.if	XCHAL_EXCM_LEVEL >= \level
	l32i	a0, a1, PT_PC
	wsr	a0, epc\level
	l32i	a0, a1, PT_AREG0
	l32i	a0, a1, PT_AREG0
	l32i	a1, a1, PT_AREG1
	l32i	a1, a1, PT_AREG1
	rfe
	rfi	\level
	.endif
	.endm


1:	wsr	a0, depc
	.align	16
2:
	l32i	a0, a1, PT_AREG0
	l32i	a0, a1, PT_AREG0
	l32i	a1, a1, PT_AREG1
	l32i	a1, a1, PT_AREG1
	rfde
	rfe

	.align	16
	/* no rfi for level-1 irq, handled by rfe above*/
	nop

	irq_exit_level 2
	irq_exit_level 3
	irq_exit_level 4
	irq_exit_level 5
	irq_exit_level 6


ENDPROC(kernel_exception)
ENDPROC(kernel_exception)


@@ -753,7 +786,7 @@ ENTRY(unrecoverable_exception)
	wsr	a1, windowbase
	wsr	a1, windowbase
	rsync
	rsync


	movi	a1, (1 << PS_WOE_BIT) | 1
	movi	a1, (1 << PS_WOE_BIT) | LOCKLEVEL
	wsr	a1, ps
	wsr	a1, ps
	rsync
	rsync


@@ -1474,7 +1507,7 @@ ENTRY(_spill_registers)
	l32i	a1, a3, EXC_TABLE_KSTK
	l32i	a1, a3, EXC_TABLE_KSTK
	wsr	a3, excsave1
	wsr	a3, excsave1


	movi	a4, (1 << PS_WOE_BIT) | 1
	movi	a4, (1 << PS_WOE_BIT) | LOCKLEVEL
	wsr	a4, ps
	wsr	a4, ps
	rsync
	rsync


Loading