Skip to content

Commit e95c087

Browse files
author
Tavish Naruka
committed
drivers: intc: add vim_tms570 interrupt controller
Add TI VIM driver specific to the TMS570 chips. This driver/peripheral is not compatible with the existing intc_vim.c for some other TI chips. Signed-off-by: Tavish Naruka <[email protected]>
1 parent 4cca9d8 commit e95c087

File tree

8 files changed

+236
-4
lines changed

8 files changed

+236
-4
lines changed

drivers/interrupt_controller/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ zephyr_library_sources_ifdef(CONFIG_INTC_ESP32 intc_esp32.c)
3333
zephyr_library_sources_ifdef(CONFIG_SWERV_PIC intc_swerv_pic.c)
3434
zephyr_library_sources_ifdef(CONFIG_VEXRISCV_LITEX_IRQ intc_vexriscv_litex.c)
3535
zephyr_library_sources_ifdef(CONFIG_VIM intc_vim.c)
36+
zephyr_library_sources_ifdef(CONFIG_TMS570_VIM intc_tms570_vim.c)
3637
zephyr_library_sources_ifdef(CONFIG_CLIC intc_clic.c)
3738
zephyr_library_sources_ifdef(CONFIG_CLIC intc_clic.S)
3839
zephyr_library_sources_ifdef(CONFIG_NRFX_CLIC intc_nrfx_clic.c)

drivers/interrupt_controller/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ source "drivers/interrupt_controller/Kconfig.nxp_pint"
102102

103103
source "drivers/interrupt_controller/Kconfig.vim"
104104

105+
source "drivers/interrupt_controller/Kconfig.tms570_vim"
106+
105107
source "drivers/interrupt_controller/Kconfig.renesas_rz"
106108

107109
source "drivers/interrupt_controller/Kconfig.nxp_irqsteer"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright (C) 2025 ispace, inc.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
config TMS570_VIM
6+
bool "TI Vectored Interrupt Manager (TMS570)"
7+
default y
8+
depends on DT_HAS_TI_TMS570_VIM_ENABLED
9+
help
10+
The TI Vectored Interrupt Manager provides hardware assistance for prioritizing
11+
and aggregating the interrupt sources for TI herules ARM Cortex-R4/R5 processor cores.
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
* Copyright (C) 2025 ispace, inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#include <zephyr/irq.h>
7+
#include <zephyr/devicetree.h>
8+
#include <string.h>
9+
10+
#define DT_DRV_COMPAT ti_tms570_vim
11+
12+
#define DRV_CONTROL_REG DT_INST_REG_ADDR_BY_IDX(0, 0)
13+
#define DRV_ECC_REG DT_INST_REG_ADDR_BY_IDX(0, 1)
14+
#define DRV_VIMRAM_REG DT_INST_REG_ADDR_BY_IDX(0, 2)
15+
#define DRV_VIMRAM_REG_SIZE DT_INST_REG_SIZE_BY_IDX(0, 2)
16+
17+
/* control registers */
18+
#define VIM_REG_IRQINDEX (DRV_CONTROL_REG + 0x00)
19+
#define VIM_REG_FIQINDEX (DRV_CONTROL_REG + 0x04)
20+
#define VIM_REG_REQMASKSET_0 (DRV_CONTROL_REG + 0x30) /* 0,1,2,3 in sequence, each is a 4 byte register*/
21+
#define VIM_REG_REQMASKCLR_0 (DRV_CONTROL_REG + 0x40) /* 0,1,2,3 in sequence, each is a 4 byte register*/
22+
23+
/* ECC related registers */
24+
#define VIM_ECC_CTL (DRV_ECC_REG + 0xF0)
25+
26+
#define REQUMASK_IRQ_PER_REG (32u)
27+
28+
static inline void set_reqmask_bit(unsigned int irq, uintptr_t reg_0_addr)
29+
{
30+
sys_write32(1 << (irq % REQUMASK_IRQ_PER_REG),
31+
reg_0_addr + (irq / REQUMASK_IRQ_PER_REG) * sizeof(uint32_t));
32+
}
33+
34+
static inline int get_reqmask_bit(unsigned int irq, uintptr_t reg_0_addr)
35+
{
36+
return sys_read32(reg_0_addr + (irq / REQUMASK_IRQ_PER_REG) * sizeof(uint32_t));
37+
}
38+
39+
/* count of number of times the phantom interrupt happened */
40+
unsigned int nr_phantom_isr;
41+
42+
static void phantom_isr(void)
43+
{
44+
/**
45+
* we don't want this to call the z_spurious_irq because we have seen
46+
* phantom irq happen even though we don't expect it to happen.
47+
*/
48+
nr_phantom_isr++;
49+
}
50+
51+
#if defined(CONFIG_RUNTIME_NMI)
52+
static void tms570_nmi_handler(void)
53+
{
54+
while (1) {
55+
/* forever */
56+
}
57+
}
58+
#endif
59+
60+
/**
61+
* @brief Get active interrupt ID (IRQ only)
62+
*
63+
* @return Returns the ID of an active interrupt
64+
*/
65+
unsigned int z_soc_irq_get_active(void)
66+
{
67+
unsigned int irq_idx;
68+
69+
/* a 0 means phantom ISR, channel 0 starts from index 1 */
70+
irq_idx = sys_read32(VIM_REG_IRQINDEX);
71+
if (irq_idx > 0) {
72+
z_soc_irq_disable(irq_idx - 1);
73+
return irq_idx - 1;
74+
75+
} else {
76+
phantom_isr();
77+
}
78+
79+
return (CONFIG_NUM_IRQS + 1);
80+
}
81+
82+
void z_soc_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
83+
{
84+
/**
85+
* not supported, all IRQ sources generate IRQ, instead of FIQ,
86+
* and with the default priority.
87+
*/
88+
}
89+
90+
void z_soc_irq_enable(unsigned int irq)
91+
{
92+
set_reqmask_bit(irq, VIM_REG_REQMASKSET_0);
93+
}
94+
95+
void z_soc_irq_disable(unsigned int irq)
96+
{
97+
set_reqmask_bit(irq, VIM_REG_REQMASKCLR_0);
98+
}
99+
100+
int z_soc_irq_is_enabled(unsigned int irq)
101+
{
102+
return get_reqmask_bit(irq, VIM_REG_REQMASKSET_0);
103+
}
104+
105+
/**
106+
* @brief Signal end-of-interrupt
107+
*
108+
* @param irq interrupt ID
109+
*/
110+
void z_soc_irq_eoi(unsigned int irq)
111+
{
112+
z_soc_irq_enable(irq);
113+
}
114+
115+
void z_soc_irq_init(void)
116+
{
117+
/**
118+
* ref. SPNA218.pdf
119+
* We are implementing what is referred to as "Legacy ARM7 Interrupts".
120+
* We do not use the VIM_RAM at all.
121+
* Sequence is like this:
122+
* 1. Interrupt request happens
123+
* 2. Exception vector 0x18 (IRQ) or 0x1C (FIQ) is taken
124+
* - in case of IRQ "ldr pc, =_isr_wrapper"
125+
* - in case of FIQ "ldr pc, =z_arm_nmi"
126+
* 3. _isr_wrapper uses z_soc_irq_get_active to get index into
127+
* _sw_isr_table for arg and ISR handler
128+
* 4. run ISR handler
129+
*
130+
* Drivers attach interrupts using IRQ_CONNECT/IRQ_DIRECT_CONNECT like:
131+
* IRQ_CONNECT(irqnum, irqnum, z_irq_spurious, NULL, 0);
132+
*/
133+
134+
/* Errata VIM#28 Workaround: Disable Single Bit error correction */
135+
sys_write32((0xAU << 0U) | (0x5U << 16U), VIM_ECC_CTL);
136+
137+
/**
138+
* We do not use VIM RAM, or need to care about ECC, but if we do not set
139+
* the VIM RAM locations to a _valid_ memory address (memset to 0 doesn't work),
140+
* it keeps generating ESM NMI with ESM group 1 status = 0x80008000.
141+
* Doing the following stops it.
142+
*/
143+
uint32_t *p = (void *) DRV_VIMRAM_REG;
144+
for (int i = 0; i < DRV_VIMRAM_REG_SIZE / 4; i++) {
145+
*(p + i) = (uint32_t) &z_irq_spurious;
146+
}
147+
148+
#if defined(CONFIG_RUNTIME_NMI)
149+
z_arm_nmi_set_handler(tms570_nmi_handler);
150+
#endif
151+
152+
/* enable interrupt */
153+
arch_irq_unlock(0);
154+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copyright (c) 2025 ispace, inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: VIM for TMS570
5+
6+
compatible: "ti,tms570-vim"
7+
8+
include: [interrupt-controller.yaml, base.yaml]
9+
10+
11+
properties:
12+
# NOTE: Register ranges:
13+
# - 0 : VIM control registers
14+
# - 1 : VIM ECC related registers
15+
# - 2 : VIM RAM
16+
reg:
17+
required: true
18+
19+
"#interrupt-cells":
20+
const: 2
21+
22+
interrupt-cells:
23+
- irq
24+
- priority

soc/ti/hercules/ti_tms570lc43x/Kconfig.defconfig

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,33 @@
44
if SOC_TI_TMS570LC43X
55

66
config SYS_CLOCK_EXISTS
7-
default n
7+
default y
88

99
config MULTITHREADING
10+
default y
11+
12+
config DYNAMIC_INTERRUPTS
1013
default n
1114

1215
config GEN_SW_ISR_TABLE
13-
default n
16+
default y
1417

1518
config GEN_ISR_TABLES
19+
default y
20+
21+
config GEN_IRQ_VECTOR_TABLE
1622
default n
1723

18-
# launchpad is 16MHz
24+
config USE_SWITCH
25+
default n
26+
27+
config RUNTIME_NMI
28+
default y
29+
30+
# 10ms OS tick from a 1MHz free-running clock
31+
config SYS_CLOCK_TICKS_PER_SEC
32+
default 100
33+
1934
config SYS_CLOCK_HW_CYCLES_PER_SEC
2035
default 1000000
2136

soc/ti/hercules/ti_tms570lc43x/soc.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,16 @@
1111
#include <stdint.h>
1212
#define __GIC_PRESENT 0
1313

14+
/* these are the default "Interrupt request assignments", see table in datasheet with same name */
15+
#define IRQ_NUM_ESM_HIGH 0 /* cannot be remapped, is NMI (FIQ) */
16+
#define IRQ_RTI_COMPARE_0 2 /* RTI1 compare interrupt 0 */
17+
#define IRQ_RTI_COMPARE_1 3 /* RTI1 compare interrupt 1 */
18+
#define IRQ_RTI_COMPARE_2 4 /* RTI1 compare interrupt 2 */
19+
#define IRQ_RTI_COMPARE_3 5 /* RTI1 compare interrupt 3 */
20+
#define IRQ_RTI_OVERFLOW_0 6 /* RTI1 overflow interrupt 1 */
21+
#define IRQ_RTI_OVERFLOW_1 7 /* RTI1 overflow interrupt 1 */
22+
#define IRQ_RTI_TIME_BASE 8 /* RTI1 time-base */
23+
#define IRQ_GIO_HIGH_LEVEL 9 /* GIO high level interrupt */
24+
#define IRQ_NUM_ESM_LOW 20 /* ESM low level interrupt */
25+
1426
#endif /* __TMS570_SOC_H__ */

subsys/testsuite/include/zephyr/interrupt_util.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,9 @@ static inline void trigger_irq(int irq)
202202
z_mips_enter_irq(irq);
203203
}
204204

205-
#elif defined(CONFIG_CPU_CORTEX_R5) && defined(CONFIG_VIM)
205+
#elif defined(CONFIG_CPU_CORTEX_R5)
206+
207+
#if defined(CONFIG_VIM)
206208

207209
extern void z_vim_arm_enter_irq(int);
208210

@@ -211,6 +213,17 @@ static inline void trigger_irq(int irq)
211213
z_vim_arm_enter_irq(irq);
212214
}
213215

216+
#elif defined(CONFIG_TMS570_VIM)
217+
218+
extern void z_tms570_vim_arm_enter_irq(int);
219+
220+
static inline void trigger_irq(int irq)
221+
{
222+
z_tms570_vim_arm_enter_irq(irq);
223+
}
224+
225+
#endif
226+
214227
#else
215228
/* So far, Nios II does not support this */
216229
#define NO_TRIGGER_FROM_SW

0 commit comments

Comments
 (0)