#pragma once @ vim:ft=arm /* This file provides the entry and exit sequences for the syscall handler * specific to the Vectored Interrupt Manager (VIM) and the Software * IRQ (SW_IRQ), as implemented on the TI Sitara family (AM26x). */ #include "vic.h" #include #include #define SW_IRQ_BITMASK (1U << (RT_VIM_SW_IRQ % 32)) #define SW_IRQ_GROUP_OFFSET (RT_VIM_GROUPS_OFFSET + ((RT_VIM_SW_IRQ / 32) * 0x20)) #define SW_IRQ_PRIMSK (1U << RT_VIM_SW_IRQ_PRIORITY) #define PRIMSK_ENABLE_ALL 0xFFFFU // r0-r3 are used for system call arguments, so vic_svc_start must use only r12 and lr. .macro vic_svc_start mov32 r12, RT_VIM mov lr, (PRIMSK_ENABLE_ALL & ~SW_IRQ_PRIMSK) str lr, [r12, RT_VIM_IRQPRIMSK_OFFSET] /* A read-back of IRQPRIMSK and an isb are ordinarily needed when changing * IRQPRIMSK, to ensure that it has taken effect and to take any latched * interrupts before proceeding, but in this case, only the SW_IRQ needs to * be masked, and the SW_IRQ is only triggered by a write to the VIM. * Because the VIM must have device or strongly-ordered semantics, any * SW_IRQ triggered after this point and before vic_svc_finish will be * masked. */ .endm .macro vic_svc_finish // Re-enable priority 15. mov32 r0, RT_VIM mov r1, PRIMSK_ENABLE_ALL str r1, [r0, RT_VIM_IRQPRIMSK_OFFSET] .endm .macro vic_syscall_irq_start /* Clear the SW_IRQ so that a new one can become pending while the current * one executes. The VIM automatically masks all interrupts of the same * priority including SW_IRQ until we store a value into IRQVEC. */ mov32 r0, RT_VIM mov r1, SW_IRQ_BITMASK str r1, [r0, SW_IRQ_GROUP_OFFSET + RT_VIM_GROUP_STS_OFFSET] .endm .macro vic_syscall_irq_finish // Re-evaluate pending interrupts. mov32 r0, RT_VIM str r1, [r0, RT_VIM_IRQVEC_OFFSET] .endm