Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | /* * Copyright (c) 2016 Jean-Paul Etienne <fractalclone@gmail.com> * * SPDX-License-Identifier: Apache-2.0 */ #include <kernel_structs.h> #include <offsets.h> #include <toolchain.h> #include <sections.h> #include <soc.h> /* exports */ GTEXT(__soc_save_context) GTEXT(__soc_restore_context) GTEXT(__soc_is_irq) GTEXT(__soc_handle_irq) GTEXT(__soc_irq_unlock) /* Use ABI name of registers for the sake of simplicity */ /* * Pulpino core has hardware loops registers that need to be saved * prior to handling an interrupt/exception. * * NOTE: Stack space allocation is not needed here, as already allocated at * architecture level with __NANO_ESF_SIZEOF value (including space for the * pulpino-specific registers) */ SECTION_FUNC(exception.other, __soc_save_context) /* Save hardware loop registers to stack */ csrr t0, PULP_LPSTART0 csrr t1, PULP_LPEND0 csrr t2, PULP_LPCOUNT0 sw t0, __NANO_ESF_lpstart0_OFFSET(sp) sw t1, __NANO_ESF_lpend0_OFFSET(sp) sw t2, __NANO_ESF_lpcount0_OFFSET(sp) csrr t0, PULP_LPSTART1 csrr t1, PULP_LPEND1 csrr t2, PULP_LPCOUNT1 sw t0, __NANO_ESF_lpstart1_OFFSET(sp) sw t1, __NANO_ESF_lpend1_OFFSET(sp) sw t2, __NANO_ESF_lpcount1_OFFSET(sp) /* Return */ jalr x0, ra SECTION_FUNC(exception.other, __soc_restore_context) /* Restore hardloop registers from stack */ lw t0, __NANO_ESF_lpstart0_OFFSET(sp) lw t1, __NANO_ESF_lpend0_OFFSET(sp) lw t2, __NANO_ESF_lpcount0_OFFSET(sp) csrw PULP_LPSTART0, t0 csrw PULP_LPEND0, t1 csrw PULP_LPCOUNT0, t2 lw t0, __NANO_ESF_lpstart1_OFFSET(sp) lw t1, __NANO_ESF_lpend1_OFFSET(sp) lw t2, __NANO_ESF_lpcount1_OFFSET(sp) csrw PULP_LPSTART1, t0 csrw PULP_LPEND1, t1 csrw PULP_LPCOUNT1, t2 /* Return */ jalr x0, ra /* * SOC-specific function to handle pending IRQ number generating the interrupt. * * The pulpino core has: * 1) an ICP register, which is used to clear the pending * IRQ number upon an interrupt. * 2) an ECP register, which is used to clear the pending IRQ number * that has woken up the CPU from sleep state. * * Exception number is given as parameter via register a0. */ SECTION_FUNC(exception.other, __soc_handle_irq) /* Clear exception number from the Interrupt pending register */ li t1, PULP_ICP_ADDR li t2, 1 sll t3, t2, a0 sw t3, 0x00(t1) /* Clear exception number from the Event pending register */ li t1, PULP_ECP_ADDR sw t3, 0x00(t1) /* Return */ jalr x0, ra /* * SOC-specific function to determine if the exception is the result of a * an interrupt or an exception * return 1 (interrupt) or 0 (exception) */ SECTION_FUNC(exception.other, __soc_is_irq) /* Get exception number from the mcause CSR register. */ csrr t0, mcause andi t0, t0, SOC_MCAUSE_EXP_MASK /* if IRQ number < PULP_MIN_IRQ, not interrupt */ li t1, PULP_MIN_IRQ addi a0, x0, 0 blt t0, t1, not_interrupt addi a0, a0, 1 not_interrupt: /* return */ jalr x0, ra |