| 1 | #include "AT91RM9200_inc.h" |
| 2 | |
| 3 | #define ARM_MODE_USER 0x10 |
| 4 | #define ARM_MODE_FIQ 0x11 |
| 5 | #define ARM_MODE_IRQ 0x12 |
| 6 | #define ARM_MODE_SVC 0x13 |
| 7 | #define ARM_MODE_ABORT 0x17 |
| 8 | #define ARM_MODE_UNDEF 0x1B |
| 9 | #define ARM_MODE_SYS 0x1F |
| 10 | |
| 11 | #define I_BIT 0x80 |
| 12 | #define F_BIT 0x40 |
| 13 | #define T_BIT 0x20 |
| 14 | |
| 15 | |
| 16 | /* ----------------------------------------------------------------------------- |
| 17 | AT91F_ASM_SPI_Handler |
| 18 | --------------------- |
| 19 | Handler called by the AIC |
| 20 | |
| 21 | Save context |
| 22 | Call C handler |
| 23 | Restore context |
| 24 | ----------------------------------------------------------------------------- */ |
| 25 | |
| 26 | .global AT91F_ST_ASM_HANDLER |
| 27 | |
| 28 | AT91F_ST_ASM_HANDLER: |
| 29 | /* Adjust and save LR_irq in IRQ stack */ |
| 30 | sub r14, r14, #4 |
| 31 | stmfd sp!, {r14} |
| 32 | |
| 33 | /* Write in the IVR to support Protect Mode |
| 34 | No effect in Normal Mode |
| 35 | De-assert the NIRQ and clear the source in Protect Mode */ |
| 36 | ldr r14, =AT91C_BASE_AIC |
| 37 | str r14, [r14, #AIC_IVR] |
| 38 | |
| 39 | /* Save SPSR and r0 in IRQ stack */ |
| 40 | mrs r14, SPSR |
| 41 | stmfd sp!, {r0, r14} |
| 42 | |
| 43 | /* Enable Interrupt and Switch in SYS Mode */ |
| 44 | mrs r0, CPSR |
| 45 | bic r0, r0, #I_BIT |
| 46 | orr r0, r0, #ARM_MODE_SYS |
| 47 | msr CPSR_c, r0 |
| 48 | |
| 49 | /* Save scratch/used registers and LR in User Stack */ |
| 50 | stmfd sp!, { r1-r3, r12, r14} |
| 51 | |
| 52 | ldr r1, =AT91F_ST_HANDLER |
| 53 | mov r14, pc |
| 54 | bx r1 |
| 55 | |
| 56 | /* Restore scratch/used registers and LR from User Stack */ |
| 57 | ldmia sp!, { r1-r3, r12, r14} |
| 58 | |
| 59 | /* Disable Interrupt and switch back in IRQ mode */ |
| 60 | mrs r0, CPSR |
| 61 | bic r0, r0, #ARM_MODE_SYS |
| 62 | orr r0, r0, #I_BIT | ARM_MODE_IRQ |
| 63 | msr CPSR_c, r0 |
| 64 | |
| 65 | /* Mark the End of Interrupt on the AIC */ |
| 66 | ldr r0, =AT91C_BASE_AIC |
| 67 | str r0, [r0, #AIC_EOICR] |
| 68 | |
| 69 | /* Restore SPSR_irq and r0 from IRQ stack */ |
| 70 | ldmia sp!, {r0, r14} |
| 71 | msr SPSR_cxsf, r14 |
| 72 | |
| 73 | /* Restore adjusted LR_irq from IRQ stack directly in the PC */ |
| 74 | ldmia sp!, {pc}^ |
| 75 | |
| 76 | |