diff --git a/arch/risc-v/include/bl808/irq.h b/arch/risc-v/include/bl808/irq.h index 60fb0530dbf..0733536a090 100644 --- a/arch/risc-v/include/bl808/irq.h +++ b/arch/risc-v/include/bl808/irq.h @@ -53,6 +53,7 @@ #define BL808_IRQ_UART3 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 4) #define BL808_IRQ_D0_IPC (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 38) +#define BL808_IRQ_M0IC (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 65) /* M0 IRQs ******************************************************************/ diff --git a/arch/risc-v/src/bl808/bl808_irq.c b/arch/risc-v/src/bl808/bl808_irq.c index 9139a7d95ab..343a1094181 100644 --- a/arch/risc-v/src/bl808/bl808_irq.c +++ b/arch/risc-v/src/bl808/bl808_irq.c @@ -36,6 +36,55 @@ #include "riscv_ipi.h" #include "chip.h" +#include "hardware/bl808_m0ic.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: m0ic_interrupt + * + * Description: + * Interrupt handler for M0 interrupt controller. Reads status registers + * to find source, and dispatches the appropriate handler. + * + ****************************************************************************/ + +static int __m0ic_interrupt(int irq, void *context, void *arg) +{ + uint32_t status_0 = getreg32(BL808_M0IC_STATUS(0)); + uint32_t status_1 = getreg32(BL808_M0IC_STATUS(1)); + + /* Check status_0 for interrupt source */ + + int m0_extirq = ffs(status_0) - 1; + if (m0_extirq < 0) + { + /* Source not in status_0. Check status_1 */ + + m0_extirq = ffs(status_1) + 32 - 1; + if (m0_extirq < 32) + { + /* Interrupt goes off on startup without any + * status bits set. When this happens, just return. + */ + + return OK; + } + } + + int irqn = m0_extirq + BL808_IRQ_NUM_BASE + + BL808_M0_IRQ_OFFSET + RISCV_IRQ_SEXT; + + irq_dispatch(irqn, NULL); + + putreg32(status_0, BL808_M0IC_CLEAR(0)); + putreg32(status_1, BL808_M0IC_CLEAR(1)); + + return OK; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -137,6 +186,14 @@ void up_disable_irq(int irq) modifyreg32(BL808_PLIC_ENABLE1 + (4 * (extirq / 32)), 1 << (extirq % 32), 0); } + else if ((BL808_D0_MAX_EXTIRQ + 1) <= extirq + && extirq <= (BL808_M0_MAX_EXTIRQ + + BL808_M0_IRQ_OFFSET)) + { + int m0_extirq = extirq - BL808_M0_IRQ_OFFSET - BL808_IRQ_NUM_BASE; + modifyreg32(BL808_M0IC_MASK(m0_extirq / 32), + 0, 1 << (m0_extirq % 32)); + } else { PANIC(); @@ -179,6 +236,14 @@ void up_enable_irq(int irq) modifyreg32(BL808_PLIC_ENABLE1 + (4 * (extirq / 32)), 0, 1 << (extirq % 32)); } + else if ((BL808_D0_MAX_EXTIRQ + 1) <= extirq + && extirq <= (BL808_M0_MAX_EXTIRQ + + BL808_M0_IRQ_OFFSET)) + { + int m0_extirq = extirq - BL808_M0_IRQ_OFFSET - BL808_IRQ_NUM_BASE; + modifyreg32(BL808_M0IC_MASK(m0_extirq / 32), + 1 << (m0_extirq % 32), 0); + } else { PANIC(); @@ -198,5 +263,27 @@ irqstate_t up_irq_enable(void) oldstat = READ_AND_SET_CSR(CSR_STATUS, STATUS_IE); + /* Enable IRQs from M0IC */ + + /* First, clear interrupts */ + + putreg32(0xffffffff, BL808_M0IC_CLEAR(0)); + putreg32(0xffffffff, BL808_M0IC_CLEAR(1)); + + /* Mask all sources */ + + putreg32(0xffffffff, BL808_M0IC_MASK(0)); + putreg32(0xffffffff, BL808_M0IC_MASK(1)); + + int ret = irq_attach(BL808_IRQ_M0IC, __m0ic_interrupt, NULL); + if (ret == OK) + { + up_enable_irq(BL808_IRQ_M0IC); + } + else + { + PANIC(); + } + return oldstat; } diff --git a/arch/risc-v/src/bl808/hardware/bl808_m0ic.h b/arch/risc-v/src/bl808/hardware/bl808_m0ic.h new file mode 100644 index 00000000000..0276f2c563a --- /dev/null +++ b/arch/risc-v/src/bl808/hardware/bl808_m0ic.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/hardware/bl808_m0ic.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_M0IC_H +#define __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_M0IC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/bl808_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register offsets */ + +#define BL808_M0IC_STATUS_OFFSET(n) (0x00 + 4 * (n)) +#define BL808_M0IC_MASK_OFFSET(n) (0x08 + 4 * (n)) +#define BL808_M0IC_CLEAR_OFFSET(n) (0x10 + 4 * (n)) + +/* Register locations */ + +#define BL808_M0IC_STATUS(n) BL808_M0IC_BASE + BL808_M0IC_STATUS_OFFSET(n) +#define BL808_M0IC_MASK(n) BL808_M0IC_BASE + BL808_M0IC_MASK_OFFSET(n) +#define BL808_M0IC_CLEAR(n) BL808_M0IC_BASE + BL808_M0IC_CLEAR_OFFSET(n) + +#endif /* __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_M0IC_H */ diff --git a/arch/risc-v/src/bl808/hardware/bl808_memorymap.h b/arch/risc-v/src/bl808/hardware/bl808_memorymap.h index b657728b2b5..eb0d0dba14d 100644 --- a/arch/risc-v/src/bl808/hardware/bl808_memorymap.h +++ b/arch/risc-v/src/bl808/hardware/bl808_memorymap.h @@ -28,6 +28,8 @@ /* Register Base Address ****************************************************/ #define BL808_GLB_BASE 0x20000000ul +#define BL808_M0IC_BASE 0x20000050ul + #define BL808_GPIO_BASE 0x200008c4ul #define BL808_UART0_BASE 0x2000a000ul #define BL808_UART1_BASE 0x2000a100ul