1 /* Copyright (C) 2023 BeagleBoard.org Foundation
2  * Copyright (C) 2023 S Prashanth
3  * Copyright (C) 2025 Siemens Mobility GmbH
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT ti_vim
9 
10 #include <stdint.h>
11 
12 #include <zephyr/arch/arm/irq.h>
13 #include <zephyr/arch/cpu.h>
14 #include <zephyr/devicetree.h>
15 #include <zephyr/drivers/interrupt_controller/intc_vim.h>
16 #include <zephyr/kernel.h>
17 #include <zephyr/logging/log.h>
18 #include "zephyr/sys/__assert.h"
19 #include <zephyr/sys/util_macro.h>
20 
21 LOG_MODULE_REGISTER(vim);
22 
z_vim_irq_get_active(void)23 unsigned int z_vim_irq_get_active(void)
24 {
25 	uint32_t irq_group_num, irq_bit_num;
26 	uint32_t actirq, vec_addr;
27 
28 	/* Reading IRQVEC register, ACTIRQ gets loaded with valid IRQ values */
29 	vec_addr = sys_read32(VIM_IRQVEC);
30 
31 	/* ACTIRQ register should be read only after reading IRQVEC register */
32 	actirq = sys_read32(VIM_ACTIRQ);
33 
34 	/* Check if the irq number is valid, else return invalid irq number.
35 	 * which will be considered as spurious interrupt
36 	 */
37 	if ((actirq & (VIM_ACTIRQ_VALID_MASK)) == 0) {
38 		return CONFIG_NUM_IRQS + 1;
39 	}
40 
41 	irq_group_num = VIM_GET_IRQ_GROUP_NUM(actirq & VIM_PRIIRQ_NUM_MASK);
42 	irq_bit_num = VIM_GET_IRQ_BIT_NUM(actirq & VIM_PRIIRQ_NUM_MASK);
43 
44 	/* Ack the interrupt in IRQSTS register */
45 	sys_write32(BIT(irq_bit_num), VIM_IRQSTS(irq_group_num));
46 
47 	if (irq_group_num > VIM_MAX_GROUP_NUM) {
48 		return (CONFIG_NUM_IRQS + 1);
49 	}
50 
51 	return (actirq & VIM_ACTIRQ_NUM_MASK);
52 }
53 
z_vim_irq_eoi(unsigned int irq)54 void z_vim_irq_eoi(unsigned int irq)
55 {
56 	sys_write32(0, VIM_IRQVEC);
57 }
58 
z_vim_irq_init(void)59 void z_vim_irq_init(void)
60 {
61 	uint32_t num_of_irqs = sys_read32(VIM_INFO) & VIM_INFO_INTERRUPTS_MASK;
62 
63 	__ASSERT(CONFIG_NUM_IRQS == num_of_irqs,
64 		 "Number of configured interrupts (%d) doesn't match reported "
65 		 "(%" PRIu32 ") interrupts",
66 		 CONFIG_NUM_IRQS, num_of_irqs);
67 	LOG_DBG("VIM: Number of IRQs = %u\n", num_of_irqs);
68 }
69 
z_vim_irq_priority_set(unsigned int irq,unsigned int prio,uint32_t flags)70 void z_vim_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
71 {
72 	uint32_t irq_group_num, irq_bit_num, regval;
73 
74 	if (irq > CONFIG_NUM_IRQS || prio > VIM_PRI_INT_MAX ||
75 	    (flags != IRQ_TYPE_EDGE && flags != IRQ_TYPE_LEVEL)) {
76 		LOG_ERR("%s: Invalid argument irq = %u prio = %u flags = %u\n",
77 			__func__, irq, prio, flags);
78 		return;
79 	}
80 
81 	sys_write8(prio, VIM_PRI_INT(irq));
82 
83 	irq_group_num = VIM_GET_IRQ_GROUP_NUM(irq);
84 	irq_bit_num = VIM_GET_IRQ_BIT_NUM(irq);
85 
86 	regval = sys_read32(VIM_INTTYPE(irq_group_num));
87 
88 	if (flags == IRQ_TYPE_EDGE) {
89 		regval |= (BIT(irq_bit_num));
90 	} else {
91 		regval &= ~(BIT(irq_bit_num));
92 	}
93 
94 	sys_write32(regval, VIM_INTTYPE(irq_group_num));
95 }
96 
z_vim_irq_enable(unsigned int irq)97 void z_vim_irq_enable(unsigned int irq)
98 {
99 	uint32_t irq_group_num, irq_bit_num;
100 
101 	if (irq > CONFIG_NUM_IRQS) {
102 		LOG_ERR("%s: Invalid irq number = %u\n", __func__, irq);
103 		return;
104 	}
105 
106 	irq_group_num = VIM_GET_IRQ_GROUP_NUM(irq);
107 	irq_bit_num = VIM_GET_IRQ_BIT_NUM(irq);
108 
109 	sys_write32(BIT(irq_bit_num), VIM_INTR_EN_SET(irq_group_num));
110 }
111 
z_vim_irq_disable(unsigned int irq)112 void z_vim_irq_disable(unsigned int irq)
113 {
114 	uint32_t irq_group_num, irq_bit_num;
115 
116 	if (irq > CONFIG_NUM_IRQS) {
117 		LOG_ERR("%s: Invalid irq number = %u\n", __func__, irq);
118 		return;
119 	}
120 
121 	irq_group_num = VIM_GET_IRQ_GROUP_NUM(irq);
122 	irq_bit_num = VIM_GET_IRQ_BIT_NUM(irq);
123 
124 	sys_write32(BIT(irq_bit_num), VIM_INTR_EN_CLR(irq_group_num));
125 }
126 
z_vim_irq_is_enabled(unsigned int irq)127 int z_vim_irq_is_enabled(unsigned int irq)
128 {
129 	uint32_t irq_group_num, irq_bit_num, regval;
130 
131 	if (irq > CONFIG_NUM_IRQS) {
132 		LOG_ERR("%s: Invalid irq number = %u\n", __func__, irq);
133 		return -EINVAL;
134 	}
135 
136 	irq_group_num = VIM_GET_IRQ_GROUP_NUM(irq);
137 	irq_bit_num = VIM_GET_IRQ_BIT_NUM(irq);
138 
139 	regval = sys_read32(VIM_INTR_EN_SET(irq_group_num));
140 
141 	return !!(regval & (BIT(irq_bit_num)));
142 }
143 
z_vim_arm_enter_irq(int irq)144 void z_vim_arm_enter_irq(int irq)
145 {
146 	uint32_t irq_group_num, irq_bit_num;
147 
148 	if (irq > CONFIG_NUM_IRQS) {
149 		LOG_ERR("%s: Invalid irq number = %u\n", __func__, irq);
150 		return;
151 	}
152 
153 	irq_group_num = VIM_GET_IRQ_GROUP_NUM(irq);
154 	irq_bit_num = VIM_GET_IRQ_BIT_NUM(irq);
155 
156 	sys_write32(BIT(irq_bit_num), VIM_RAW(irq_group_num));
157 }
158