Skip to content

Commit

Permalink
drivers: interrupt-controller: Add VIM Interrupt Controller support
Browse files Browse the repository at this point in the history
Add VIM (Vectored Interrupt Manager) interrupt controller support

Signed-off-by: Prashanth S <slpp95prashanth@yahoo.com>
  • Loading branch information
slpp95prashanth committed Jul 27, 2023
1 parent d7c00ee commit e953584
Show file tree
Hide file tree
Showing 8 changed files with 597 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/interrupt_controller/CMakeLists.txt
Expand Up @@ -34,6 +34,7 @@ zephyr_library_sources_ifdef(CONFIG_NUCLEI_ECLIC intc_nuclei_eclic.c)
zephyr_library_sources_ifdef(CONFIG_NXP_S32_EIRQ intc_eirq_nxp_s32.c)
zephyr_library_sources_ifdef(CONFIG_XMC4XXX_INTC intc_xmc4xxx.c)
zephyr_library_sources_ifdef(CONFIG_NXP_PINT intc_nxp_pint.c)
zephyr_library_sources_ifdef(CONFIG_VIM intc_vim.c)

if(CONFIG_INTEL_VTD_ICTL)
zephyr_library_include_directories(${ZEPHYR_BASE}/arch/x86/include)
Expand Down
2 changes: 2 additions & 0 deletions drivers/interrupt_controller/Kconfig
Expand Up @@ -100,4 +100,6 @@ source "drivers/interrupt_controller/Kconfig.xmc4xxx"

source "drivers/interrupt_controller/Kconfig.nxp_pint"

source "drivers/interrupt_controller/Kconfig.vim"

endmenu
16 changes: 16 additions & 0 deletions drivers/interrupt_controller/Kconfig.vim
@@ -0,0 +1,16 @@
# Copyright (C) 2023 BeagleBoard.org Foundation
# Copyright (C) 2023 S Prashanth
#
# SPDX-License-Identifier: Apache-2.0

if CPU_CORTEX

config VIM
bool "Vectored Interrupt Manager"
default y
depends on DT_HAS_ARM_VIM_ENABLED
help
The Vectored Interrupt Manager provides hardware assistance for prioritizing
and controlling the many interrupt sources for ARM Cortex-family processors.

endif # CPU_CORTEX
150 changes: 150 additions & 0 deletions drivers/interrupt_controller/intc_vim.c
@@ -0,0 +1,150 @@
/* Copyright (C) 2023 BeagleBoard.org Foundation
* Copyright (C) 2023 S Prashanth
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <stdint.h>

#include <zephyr/kernel.h>
#include <zephyr/arch/cpu.h>
#include <zephyr/devicetree.h>
#include <zephyr/arch/arm/aarch32/irq.h>
#include <zephyr/sys/util_macro.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(vim);

#include <zephyr/drivers/interrupt_controller/intc_vim.h>

unsigned int z_vim_irq_get_active(void)
{
uint32_t irq_group_num, irq_bit_num;
uint32_t actirq, vec_addr;

/* Reading IRQVEC register, ACTIRQ gets loaded with valid IRQ values */
vec_addr = sys_read32(VIM_IRQVEC);

/* ACTIRQ register should be read only after reading IRQVEC register */
actirq = sys_read32(VIM_ACTIRQ);

/* Check if the irq number is valid, else return invalid irq number.
* which will be considered as spurious interrupt
*/
if ((actirq & (VIM_ACTIRQ_VALID_MASK)) == 0) {
return CONFIG_NUM_IRQS + 1;
}

irq_group_num = VIM_GET_IRQ_GROUP_NUM(actirq & VIM_PRIIRQ_NUM_MASK);
irq_bit_num = VIM_GET_IRQ_BIT_NUM(actirq & VIM_PRIIRQ_NUM_MASK);

/* Ack the interrupt in IRQSTS register */
sys_write32(BIT(irq_bit_num), VIM_IRQSTS(irq_group_num));

if (irq_group_num > VIM_MAX_GROUP_NUM) {
return (CONFIG_NUM_IRQS + 1);
}

return (actirq & VIM_ACTIRQ_NUM_MASK);
}

void z_vim_irq_eoi(unsigned int irq)
{
sys_write32(0, VIM_IRQVEC);
}

void z_vim_irq_init(void)
{
uint32_t num_of_irqs = sys_read32(VIM_INFO_INTERRUPTS_MASK);

LOG_DBG("VIM: Number of IRQs = %u\n", num_of_irqs);
}

void z_vim_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
{
uint32_t irq_group_num, irq_bit_num, regval;

if (irq > CONFIG_NUM_IRQS || prio > VIM_PRI_INT_MAX ||
(flags != IRQ_TYPE_EDGE && flags != IRQ_TYPE_LEVEL)) {
LOG_ERR("%s: Invalid argument irq = %u prio = %u flags = %u\n",
__func__, irq, prio, flags);
return;
}

sys_write8(prio, VIM_PRI_INT(irq));

irq_group_num = VIM_GET_IRQ_GROUP_NUM(irq);
irq_bit_num = VIM_GET_IRQ_BIT_NUM(irq);

regval = sys_read32(VIM_INTTYPE(irq_group_num));

if (flags == IRQ_TYPE_EDGE) {
regval |= (BIT(irq_bit_num));
} else {
regval &= ~(BIT(irq_bit_num));
}

sys_write32(regval, VIM_INTTYPE(irq_group_num));
}

void z_vim_irq_enable(unsigned int irq)
{
uint32_t irq_group_num, irq_bit_num;

if (irq > CONFIG_NUM_IRQS) {
LOG_ERR("%s: Invalid irq number = %u\n", __func__, irq);
return;
}

irq_group_num = VIM_GET_IRQ_GROUP_NUM(irq);
irq_bit_num = VIM_GET_IRQ_BIT_NUM(irq);

sys_write32(BIT(irq_bit_num), VIM_INTR_EN_SET(irq_group_num));
}

void z_vim_irq_disable(unsigned int irq)
{
uint32_t irq_group_num, irq_bit_num;

if (irq > CONFIG_NUM_IRQS) {
LOG_ERR("%s: Invalid irq number = %u\n", __func__, irq);
return;
}

irq_group_num = VIM_GET_IRQ_GROUP_NUM(irq);
irq_bit_num = VIM_GET_IRQ_BIT_NUM(irq);

sys_write32(BIT(irq_bit_num), VIM_INTR_EN_CLR(irq_group_num));
}

int z_vim_irq_is_enabled(unsigned int irq)
{
uint32_t irq_group_num, irq_bit_num, regval;

if (irq > CONFIG_NUM_IRQS) {
LOG_ERR("%s: Invalid irq number = %u\n", __func__, irq);
return -EINVAL;
}

irq_group_num = VIM_GET_IRQ_GROUP_NUM(irq);
irq_bit_num = VIM_GET_IRQ_BIT_NUM(irq);

regval = sys_read32(VIM_INTR_EN_SET(irq_group_num));

return !!(regval & (BIT(irq_bit_num)));
}

void z_vim_arm_enter_irq(int irq)
{
uint32_t irq_group_num, irq_bit_num;

if (irq > CONFIG_NUM_IRQS) {
LOG_ERR("%s: Invalid irq number = %u\n", __func__, irq);
return;
}

irq_group_num = VIM_GET_IRQ_GROUP_NUM(irq);
irq_bit_num = VIM_GET_IRQ_BIT_NUM(irq);

sys_write32(BIT(irq_bit_num), VIM_RAW(irq_group_num));
}
20 changes: 20 additions & 0 deletions dts/bindings/interrupt-controller/arm,vim.yaml
@@ -0,0 +1,20 @@
# Copyright (C) 2023 BeagleBoard.org Foundation
# Copyright (C) 2023 S Prashanth
#
# SPDX-License-Identifier: Apache-2.0

description: TI Vectored Interrupt Manager

compatible: "arm,vim"

include: base.yaml

properties:
reg:
required: true

interrupt-cells:
- type
- irq
- flags
- priority

0 comments on commit e953584

Please sign in to comment.