Skip to content

Commit ee8661e

Browse files
author
Tavish Naruka
committed
intc: add vim_tms570 interrupt controller driver
This driver is not compatible with the existing intc_vim.c. Signed-off-by: Tavish Naruka <[email protected]>
1 parent 208d31d commit ee8661e

File tree

10 files changed

+249
-6
lines changed

10 files changed

+249
-6
lines changed

drivers/interrupt_controller/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ zephyr_library_sources_ifdef(CONFIG_NXP_S32_WKPU intc_wkpu_nxp_s32.c)
4242
zephyr_library_sources_ifdef(CONFIG_XMC4XXX_INTC intc_xmc4xxx.c)
4343
zephyr_library_sources_ifdef(CONFIG_NXP_PINT intc_nxp_pint.c)
4444
zephyr_library_sources_ifdef(CONFIG_RENESAS_RZ_EXT_IRQ intc_renesas_rz_ext_irq.c)
45+
zephyr_library_sources_ifdef(CONFIG_TMS570_VIM intc_tms570_vim.c)
4546
zephyr_library_sources_ifdef(CONFIG_NXP_IRQSTEER intc_nxp_irqsteer.c)
4647
zephyr_library_sources_ifdef(CONFIG_INTC_MTK_ADSP intc_mtk_adsp.c)
4748
zephyr_library_sources_ifdef(CONFIG_WCH_PFIC intc_wch_pfic.c)

drivers/interrupt_controller/Kconfig

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

105105
source "drivers/interrupt_controller/Kconfig.renesas_rz"
106106

107+
source "drivers/interrupt_controller/Kconfig.tms570_vim"
108+
107109
source "drivers/interrupt_controller/Kconfig.nxp_irqsteer"
108110

109111
source "drivers/interrupt_controller/Kconfig.mtk_adsp"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright (C) 2025 ispace, inc.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
if CPU_CORTEX_R5
6+
7+
config TMS570_VIM
8+
bool "TI Vectored Interrupt Manager (TMS570)"
9+
default y
10+
depends on DT_HAS_TI_TMS570_VIM_ENABLED
11+
help
12+
The TI Vectored Interrupt Manager provides hardware assistance for prioritizing
13+
and aggregating the interrupt sources for TI herules ARM Cortex-R4/R5 processor cores.
14+
15+
endif # CPU_CORTEX_R5
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
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+
spent a long time debugging a ESM2.25 NMI fault which is
139+
"CCM-R5F VIM compare error". Could not find cause but this
140+
seems to have made it stop.
141+
*/
142+
memset((void *)DRV_VIMRAM_REG, 0, DRV_VIMRAM_REG_SIZE);
143+
144+
#if defined(CONFIG_RUNTIME_NMI)
145+
z_arm_nmi_set_handler(tms570_nmi_handler);
146+
#endif
147+
148+
/* enable interrupt */
149+
arch_irq_unlock(0);
150+
}

dts/arm/ti/tms570.dtsi

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,24 @@
7272
reg = <0xffff1c00 0x400>;
7373
status = "okay";
7474
};
75+
76+
vim: interrupt-controller@fffffe00 {
77+
compatible = "ti,tms570-vim";
78+
reg = <0xfffffe00 0x00000100>, /* VIM control */
79+
<0xfffffd00 0x00000100>, /* ECC related */
80+
<0xfff82000 128>; /* VIM_RAM */
81+
status = "okay";
82+
interrupt-controller;
83+
#interrupt-cells = <2>;
84+
#address-cells = <1>;
85+
};
7586

7687
sci1: uart@fff7e400 {
7788
compatible = "ti,tms570-uart";
7889
reg = <0xfff7e400 256>;
7990
status = "disabled";
8091
};
81-
92+
8293
sci3: uart@fff7e500 {
8394
compatible = "ti,tms570-uart";
8495
reg = <0xfff7e500 256>;
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/tms570lc43x/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ config SOC_TI_TMS570LC43X
1313
select PLATFORM_SPECIFIC_INIT
1414
select PLATFORM_SPECIFIC_PRE_STACK_INIT
1515
# select CPU_HAS_FPU
16-
# select ARM_CUSTOM_INTERRUPT_CONTROLLER
16+
select ARM_CUSTOM_INTERRUPT_CONTROLLER
1717
imply XIP
1818

1919
if SOC_TI_TMS570LC43X

soc/ti/hercules/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 16000000
2136

soc/ti/hercules/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)