Merge tag 'u-boot-amlogic-20181207' of git://git.denx.de/u-boot-amlogic
[platform/kernel/u-boot.git] / arch / riscv / lib / interrupts.c
index 075db8b..3aff006 100644 (file)
@@ -1,11 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 2016-17 Microsemi Corporation.
  * Padmarao Begari, Microsemi Corporation <padmarao.begari@microsemi.com>
  *
  * Copyright (C) 2017 Andes Technology Corporation
  * Rick Chen, Andes Technology Corporation <rick@andestech.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
@@ -13,7 +12,7 @@
 #include <asm/system.h>
 #include <asm/encoding.h>
 
-static void _exit_trap(int code, uint epc, struct pt_regs *regs);
+static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs);
 
 int interrupt_init(void)
 {
@@ -35,17 +34,30 @@ int disable_interrupts(void)
        return 0;
 }
 
-uint handle_trap(uint mcause, uint epc, struct pt_regs *regs)
+ulong handle_trap(ulong cause, ulong epc, struct pt_regs *regs)
 {
-       uint is_int;
+       ulong is_irq, irq;
+
+       is_irq = (cause & MCAUSE_INT);
+       irq = (cause & ~MCAUSE_INT);
 
-       is_int = (mcause & MCAUSE_INT);
-       if ((is_int) && ((mcause & MCAUSE_CAUSE)  == IRQ_M_EXT))
-               external_interrupt(0);  /* handle_m_ext_interrupt */
-       else if ((is_int) && ((mcause & MCAUSE_CAUSE)  == IRQ_M_TIMER))
-               timer_interrupt(0);     /* handle_m_timer_interrupt */
-       else
-               _exit_trap(mcause, epc, regs);
+       if (is_irq) {
+               switch (irq) {
+               case IRQ_M_EXT:
+               case IRQ_S_EXT:
+                       external_interrupt(0);  /* handle external interrupt */
+                       break;
+               case IRQ_M_TIMER:
+               case IRQ_S_TIMER:
+                       timer_interrupt(0);     /* handle timer interrupt */
+                       break;
+               default:
+                       _exit_trap(cause, epc, regs);
+                       break;
+               };
+       } else {
+               _exit_trap(cause, epc, regs);
+       }
 
        return epc;
 }
@@ -61,16 +73,33 @@ __attribute__((weak)) void timer_interrupt(struct pt_regs *regs)
 {
 }
 
-static void _exit_trap(int code, uint epc, struct pt_regs *regs)
+static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs)
 {
-       static const char *exception_code[] = {
+       static const char * const exception_code[] = {
                "Instruction address misaligned",
                "Instruction access fault",
                "Illegal instruction",
                "Breakpoint",
-               "Load address misaligned"
+               "Load address misaligned",
+               "Load access fault",
+               "Store/AMO address misaligned",
+               "Store/AMO access fault",
+               "Environment call from U-mode",
+               "Environment call from S-mode",
+               "Reserved",
+               "Environment call from M-mode",
+               "Instruction page fault",
+               "Load page fault",
+               "Reserved",
+               "Store/AMO page fault",
        };
 
-       printf("exception code: %d , %s , epc %08x , ra %08lx\n",
-               code, exception_code[code], epc, regs->ra);
+       if (code < ARRAY_SIZE(exception_code)) {
+               printf("exception code: %ld , %s , epc %lx , ra %lx\n",
+                      code, exception_code[code], epc, regs->ra);
+       } else {
+               printf("Reserved\n");
+       }
+
+       hang();
 }