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