You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
3.8 KiB
157 lines
3.8 KiB
/* Copyright (C) 2023 BeagleBoard.org Foundation |
|
* Copyright (C) 2023 S Prashanth |
|
* Copyright (C) 2025 Siemens Mobility GmbH |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#define DT_DRV_COMPAT ti_vim |
|
|
|
#include <stdint.h> |
|
|
|
#include <zephyr/arch/arm/irq.h> |
|
#include <zephyr/arch/cpu.h> |
|
#include <zephyr/devicetree.h> |
|
#include <zephyr/drivers/interrupt_controller/intc_vim.h> |
|
#include <zephyr/kernel.h> |
|
#include <zephyr/logging/log.h> |
|
#include "zephyr/sys/__assert.h" |
|
#include <zephyr/sys/util_macro.h> |
|
|
|
LOG_MODULE_REGISTER(vim); |
|
|
|
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) & VIM_INFO_INTERRUPTS_MASK; |
|
|
|
__ASSERT(CONFIG_NUM_IRQS == num_of_irqs, |
|
"Number of configured interrupts (%d) doesn't match reported " |
|
"(%" PRIu32 ") interrupts", |
|
CONFIG_NUM_IRQS, num_of_irqs); |
|
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)); |
|
}
|
|
|