4be4c5b826
Timer test assumes that timer 0 IRQ has level 1 and other timers have higher level IRQs. This assumption is not correct and the levels may be arbitrary. Fix that assumption by providing TIMER*_VECTOR macro and using it for vector selection and by making the check for the timer exception cause conditional. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
292 lines
5.9 KiB
ArmAsm
292 lines
5.9 KiB
ArmAsm
#include "macros.inc"
|
|
|
|
#define CCOUNT_SHIFT 4
|
|
#define WAIT_LOOPS 20
|
|
#define level1 kernel
|
|
#define INTERRUPT_LEVEL(n) glue3(XCHAL_INT, n, _LEVEL)
|
|
|
|
.macro make_ccount_delta target, delta
|
|
rsr \delta, ccount
|
|
rsr \target, ccount
|
|
sub \delta, \target, \delta
|
|
slli \delta, \delta, CCOUNT_SHIFT
|
|
add \target, \target, \delta
|
|
.endm
|
|
|
|
test_suite timer
|
|
|
|
#if XCHAL_HAVE_CCOUNT
|
|
|
|
test ccount
|
|
rsr a3, ccount
|
|
rsr a4, ccount
|
|
assert ne, a3, a4
|
|
test_end
|
|
|
|
test ccount_write
|
|
rsr a3, ccount
|
|
rsr a4, ccount
|
|
sub a4, a4, a3
|
|
movi a2, 0x12345678
|
|
wsr a2, ccount
|
|
esync
|
|
rsr a3, ccount
|
|
sub a3, a3, a2
|
|
slli a4, a4, 2
|
|
assert ltu, a3, a4
|
|
test_end
|
|
|
|
#if XCHAL_NUM_TIMERS
|
|
|
|
#if INTERRUPT_LEVEL(XCHAL_TIMER0_INTERRUPT) == 1
|
|
#define TIMER0_VECTOR kernel
|
|
#else
|
|
#define TIMER0_VECTOR glue(level, INTERRUPT_LEVEL(XCHAL_TIMER0_INTERRUPT))
|
|
#endif
|
|
|
|
#if XCHAL_NUM_TIMERS > 1
|
|
#if INTERRUPT_LEVEL(XCHAL_TIMER1_INTERRUPT) == 1
|
|
#define TIMER1_VECTOR kernel
|
|
#else
|
|
#define TIMER1_VECTOR glue(level, INTERRUPT_LEVEL(XCHAL_TIMER1_INTERRUPT))
|
|
#endif
|
|
#endif
|
|
|
|
#if XCHAL_NUM_TIMERS > 2
|
|
#if INTERRUPT_LEVEL(XCHAL_TIMER2_INTERRUPT) == 1
|
|
#define TIMER2_VECTOR kernel
|
|
#else
|
|
#define TIMER2_VECTOR glue(level, INTERRUPT_LEVEL(XCHAL_TIMER2_INTERRUPT))
|
|
#endif
|
|
#endif
|
|
|
|
test ccount_update_deadline
|
|
movi a2, 0
|
|
wsr a2, intenable
|
|
rsr a2, interrupt
|
|
wsr a2, intclear
|
|
movi a2, 0
|
|
#if XCHAL_NUM_TIMERS > 1
|
|
wsr a2, ccompare1
|
|
#endif
|
|
#if XCHAL_NUM_TIMERS > 2
|
|
wsr a2, ccompare2
|
|
#endif
|
|
movi a2, 0x12345678
|
|
wsr a2, ccompare0
|
|
rsr a3, interrupt
|
|
assert eqi, a3, 0
|
|
movi a2, 0x12345677
|
|
wsr a2, ccount
|
|
esync
|
|
nop
|
|
rsr a2, interrupt
|
|
movi a3, 1 << XCHAL_TIMER0_INTERRUPT
|
|
assert eq, a2, a3
|
|
test_end
|
|
|
|
test ccompare
|
|
movi a2, 0
|
|
wsr a2, intenable
|
|
rsr a2, interrupt
|
|
wsr a2, intclear
|
|
movi a2, 0
|
|
#if XCHAL_NUM_TIMERS > 1
|
|
wsr a2, ccompare1
|
|
#endif
|
|
#if XCHAL_NUM_TIMERS > 2
|
|
wsr a2, ccompare2
|
|
#endif
|
|
|
|
make_ccount_delta a2, a15
|
|
wsr a2, ccompare0
|
|
1:
|
|
rsr a3, interrupt
|
|
rsr a4, ccount
|
|
rsr a5, interrupt
|
|
sub a4, a4, a2
|
|
bgez a4, 2f
|
|
assert eqi, a3, 0
|
|
j 1b
|
|
2:
|
|
assert nei, a5, 0
|
|
test_end
|
|
|
|
test ccompare0_interrupt
|
|
set_vector TIMER0_VECTOR, 2f
|
|
movi a2, 0
|
|
wsr a2, intenable
|
|
rsr a2, interrupt
|
|
wsr a2, intclear
|
|
movi a2, 0
|
|
#if XCHAL_NUM_TIMERS > 1
|
|
wsr a2, ccompare1
|
|
#endif
|
|
#if XCHAL_NUM_TIMERS > 2
|
|
wsr a2, ccompare2
|
|
#endif
|
|
|
|
movi a3, WAIT_LOOPS
|
|
make_ccount_delta a2, a15
|
|
wsr a2, ccompare0
|
|
rsync
|
|
rsr a2, interrupt
|
|
assert eqi, a2, 0
|
|
|
|
movi a2, 1 << XCHAL_TIMER0_INTERRUPT
|
|
wsr a2, intenable
|
|
rsil a2, 0
|
|
1:
|
|
addi a3, a3, -1
|
|
bnez a3, 1b
|
|
test_fail
|
|
2:
|
|
#if INTERRUPT_LEVEL(XCHAL_TIMER0_INTERRUPT) == 1
|
|
rsr a2, exccause
|
|
assert eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
|
|
#endif
|
|
test_end
|
|
|
|
#if XCHAL_NUM_TIMERS > 1
|
|
|
|
test ccompare1_interrupt
|
|
set_vector TIMER1_VECTOR, 2f
|
|
movi a2, 0
|
|
wsr a2, intenable
|
|
rsr a2, interrupt
|
|
wsr a2, intclear
|
|
movi a2, 0
|
|
wsr a2, ccompare0
|
|
#if XCHAL_NUM_TIMERS > 2
|
|
wsr a2, ccompare2
|
|
#endif
|
|
|
|
movi a3, WAIT_LOOPS
|
|
make_ccount_delta a2, a15
|
|
wsr a2, ccompare1
|
|
rsync
|
|
rsr a2, interrupt
|
|
assert eqi, a2, 0
|
|
movi a2, 1 << XCHAL_TIMER1_INTERRUPT
|
|
wsr a2, intenable
|
|
rsil a2, INTERRUPT_LEVEL(XCHAL_TIMER1_INTERRUPT) - 1
|
|
1:
|
|
addi a3, a3, -1
|
|
bnez a3, 1b
|
|
test_fail
|
|
2:
|
|
#if INTERRUPT_LEVEL(XCHAL_TIMER1_INTERRUPT) == 1
|
|
rsr a2, exccause
|
|
assert eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
|
|
#endif
|
|
test_end
|
|
|
|
#endif
|
|
#if XCHAL_NUM_TIMERS > 2
|
|
|
|
test ccompare2_interrupt
|
|
set_vector TIMER2_VECTOR, 2f
|
|
movi a2, 0
|
|
wsr a2, intenable
|
|
rsr a2, interrupt
|
|
wsr a2, intclear
|
|
movi a2, 0
|
|
wsr a2, ccompare0
|
|
wsr a2, ccompare1
|
|
|
|
movi a3, WAIT_LOOPS
|
|
make_ccount_delta a2, a15
|
|
wsr a2, ccompare2
|
|
rsync
|
|
rsr a2, interrupt
|
|
assert eqi, a2, 0
|
|
movi a2, 1 << XCHAL_TIMER2_INTERRUPT
|
|
wsr a2, intenable
|
|
rsil a2, INTERRUPT_LEVEL(XCHAL_TIMER2_INTERRUPT) - 1
|
|
1:
|
|
addi a3, a3, -1
|
|
bnez a3, 1b
|
|
test_fail
|
|
2:
|
|
#if INTERRUPT_LEVEL(XCHAL_TIMER2_INTERRUPT) == 1
|
|
rsr a2, exccause
|
|
assert eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
|
|
#endif
|
|
test_end
|
|
|
|
#endif
|
|
|
|
test ccompare_interrupt_masked
|
|
set_vector TIMER0_VECTOR, 2f
|
|
movi a2, 0
|
|
wsr a2, intenable
|
|
rsr a2, interrupt
|
|
wsr a2, intclear
|
|
movi a2, 0
|
|
#if XCHAL_NUM_TIMERS > 2
|
|
wsr a2, ccompare2
|
|
#endif
|
|
|
|
movi a3, WAIT_LOOPS
|
|
make_ccount_delta a2, a15
|
|
#if XCHAL_NUM_TIMERS > 1
|
|
wsr a2, ccompare1
|
|
#endif
|
|
add a2, a2, a15
|
|
wsr a2, ccompare0
|
|
rsync
|
|
rsr a2, interrupt
|
|
assert eqi, a2, 0
|
|
|
|
movi a2, 1 << XCHAL_TIMER0_INTERRUPT
|
|
wsr a2, intenable
|
|
rsil a2, 0
|
|
1:
|
|
addi a3, a3, -1
|
|
bnez a3, 1b
|
|
|
|
test_fail
|
|
2:
|
|
#if INTERRUPT_LEVEL(XCHAL_TIMER0_INTERRUPT) == 1
|
|
rsr a2, exccause
|
|
assert eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
|
|
#endif
|
|
test_end
|
|
|
|
test ccompare_interrupt_masked_waiti
|
|
set_vector TIMER0_VECTOR, 2f
|
|
movi a2, 0
|
|
wsr a2, intenable
|
|
rsr a2, interrupt
|
|
wsr a2, intclear
|
|
movi a2, 0
|
|
#if XCHAL_NUM_TIMERS > 2
|
|
wsr a2, ccompare2
|
|
#endif
|
|
|
|
make_ccount_delta a2, a15
|
|
#if XCHAL_NUM_TIMERS > 1
|
|
wsr a2, ccompare1
|
|
#endif
|
|
add a2, a2, a15
|
|
wsr a2, ccompare0
|
|
rsync
|
|
rsr a2, interrupt
|
|
assert eqi, a2, 0
|
|
|
|
movi a2, 1 << XCHAL_TIMER0_INTERRUPT
|
|
wsr a2, intenable
|
|
waiti 0
|
|
test_fail
|
|
2:
|
|
#if INTERRUPT_LEVEL(XCHAL_TIMER0_INTERRUPT) == 1
|
|
rsr a2, exccause
|
|
assert eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
|
|
#endif
|
|
test_end
|
|
|
|
#endif
|
|
#endif
|
|
|
|
test_suite_end
|