aboutsummaryrefslogtreecommitdiff
path: root/libgloss/mips/hal/mips_intctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgloss/mips/hal/mips_intctrl.c')
-rw-r--r--libgloss/mips/hal/mips_intctrl.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/libgloss/mips/hal/mips_intctrl.c b/libgloss/mips/hal/mips_intctrl.c
new file mode 100644
index 0000000..a2bd2a1
--- /dev/null
+++ b/libgloss/mips/hal/mips_intctrl.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2017-2018 MIPS Tech, LLC
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <mips/cpu.h>
+#include <mips/hal.h>
+#include <mips/intctrl.h>
+
+#define _mips_intpatch_kscratch1 0x00
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || defined (__mips_micromips)
+# define _mips_intpatch_isroff1 0x06
+# define _mips_intpatch_isroff2 0x0a
+# define _mips_intpatch_isroff3 0x12
+# define _mips_intpatch_isroff4 0x1a
+#else
+# define _mips_intpatch_isroff1 0x04
+# define _mips_intpatch_isroff2 0x08
+# define _mips_intpatch_isroff3 0x10
+# define _mips_intpatch_isroff4 0x1c
+#endif
+
+extern void m32_sync_icache(unsigned kva, size_t n);
+
+void _MIPS_HAL_NOMIPS16
+_mips_intpatch (const reg_t index, uintptr_t handler, bool k1_to_kscratch1)
+{
+ extern void *__isr_vec_space;
+ uint16_t *patch;
+ uint32_t *patch32;
+ uintptr_t isrbase = (uintptr_t) (mips32_getebase() & EBASE_BASE)
+ + 0x200 + (index * ((uintptr_t) &__isr_vec_space));
+ if (k1_to_kscratch1)
+ {
+#ifdef __mips_micromips
+ patch = (uint16_t *) (isrbase + _mips_intpatch_kscratch1);
+ *(patch++) = 0x037f;
+ *(patch) = 0x12fc;
+#else
+ patch32 = (uint32_t *) (isrbase + _mips_intpatch_kscratch1);
+ *patch32 = 0x409bf802;
+#endif
+ }
+#if SZPTR==4
+ handler += (handler & 0x8000) << 1;
+ patch = (uint16_t *) (isrbase + _mips_intpatch_isroff1);
+ *patch = (uint16_t) (handler >> 16); /* %hi */
+ patch = (uint16_t *) (isrbase + _mips_intpatch_isroff2);
+ *patch = (uint16_t) (handler & 0xffff); /* %lo */
+ m32_sync_icache (isrbase, 32);
+#elif SZPTR==8
+ handler += (handler & 0x800080008000) << 1;
+ patch = (uint16_t *) (isrbase + _mips_intpatch_isroff1);
+ *patch = (uint16_t) (handler >> 48); /* %highest */
+ patch = (uint16_t *) (isrbase + _mips_intpatch_isroff2);
+ *patch = (uint16_t) ((handler >> 32) & 0xffff); /* %higher */
+ patch = (uint16_t *) (isrbase + _mips_intpatch_isroff3);
+ *patch = (uint16_t) ((handler >> 16) & 0xffff); /* %hi */
+ patch = (uint16_t *) (isrbase + _mips_intpatch_isroff4);
+ *patch = (uint16_t) (handler & 0xffff); /* %lo */
+ m32_sync_icache (isrbase, 64);
+#else
+# error "Unknown pointer size"
+#endif
+}
+
+/*
+ * Interrupt masking and acknowledging functions - these are weak so they can
+ * be replaced with versions that understand more complex interrupt models.
+ */
+
+reg_t __attribute__ ((weak)) _MIPS_HAL_NOMIPS16
+_mips_intmask (const reg_t index, const reg_t enable)
+{
+ register reg_t enbefore, valbefore = 0, indexedbit;
+
+ /*
+ * Calculate which bit upfront to minimise critical section.
+ * Note that this function supports the MCU ASE, unlike the .h files.
+ */
+ if ((index >= 0) && (index <= 8))
+ /* Traditional/1st MCU ASE interrupt. */
+ indexedbit = SR_IM0 << index;
+ else if (index == 9)
+ /* 2nd MCU ASE interrupt. */
+ indexedbit = SR_IM7 << 2;
+
+ /* Make sure we can safely adjust the mask. */
+ enbefore = _mips_intdisable ();
+
+ /* Make the change. */
+ valbefore = mips32_bcssr (indexedbit, enable ? indexedbit : 0);
+
+ /* Go live again. */
+ _mips_intrestore (enbefore);
+
+ /* Return true if it was enabled, again outside critical section. */
+ return (valbefore & indexedbit) != 0;
+}
+
+reg_t __attribute__ ((weak)) _MIPS_HAL_NOMIPS16
+_mips_intack (const reg_t index)
+{
+ reg_t enbefore, indexedbit;
+ reg_t valbefore = 0;
+
+ /* We only handle software interrupts - bail out otherwise. */
+ if ((index < 0) && (index > 1))
+ return 0;
+
+ /* Calculate which bit upfront to minimise critical section. */
+ indexedbit = CR_IP0 << index;
+
+ /* Make sure we can safely adjust the state. */
+ enbefore = _mips_intdisable ();
+
+ /* Make the change. */
+ valbefore = mips32_bicsr (indexedbit);
+
+ /* Go live again. */
+ _mips_intrestore (enbefore);
+
+ /* Return true if it was enabled, again outside critical section. */
+ return (valbefore & indexedbit) != 0;
+}