Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | /* Copyright (C) 2023 BeagleBoard.org Foundation
* Copyright (C) 2023 S Prashanth
*
* 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/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_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));
}
|