1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2010-11-13 weety first version
9 */
10
11
12 #include <rtthread.h>
13 #include <rthw.h>
14 #include "dm36x.h"
15
16 #define MAX_HANDLERS 64
17
18 extern rt_atomic_t rt_interrupt_nest;
19
20 struct rt_irq_desc irq_desc[MAX_HANDLERS];
21
22 /* exception and interrupt handler table */
23 rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
24 rt_uint32_t rt_thread_switch_interrupt_flag;
25
26 #define IRQ_BIT(irq) ((irq) & 0x1f)
27
28 #define FIQ_REG0_OFFSET 0x0000
29 #define FIQ_REG1_OFFSET 0x0004
30 #define IRQ_REG0_OFFSET 0x0008
31 #define IRQ_REG1_OFFSET 0x000C
32 #define IRQ_ENT_REG0_OFFSET 0x0018
33 #define IRQ_ENT_REG1_OFFSET 0x001C
34 #define IRQ_INCTL_REG_OFFSET 0x0020
35 #define IRQ_EABASE_REG_OFFSET 0x0024
36 #define IRQ_INTPRI0_REG_OFFSET 0x0030
37 #define IRQ_INTPRI7_REG_OFFSET 0x004C
38
39 /* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
40 static const rt_uint8_t dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = {
41 [IRQ_DM3XX_VPSSINT0] = 2,
42 [IRQ_DM3XX_VPSSINT1] = 6,
43 [IRQ_DM3XX_VPSSINT2] = 6,
44 [IRQ_DM3XX_VPSSINT3] = 6,
45 [IRQ_DM3XX_VPSSINT4] = 6,
46 [IRQ_DM3XX_VPSSINT5] = 6,
47 [IRQ_DM3XX_VPSSINT6] = 6,
48 [IRQ_DM3XX_VPSSINT7] = 7,
49 [IRQ_DM3XX_VPSSINT8] = 6,
50 [IRQ_ASQINT] = 6,
51 [IRQ_DM365_IMXINT0] = 6,
52 [IRQ_DM3XX_IMCOPINT] = 6,
53 [IRQ_USBINT] = 4,
54 [IRQ_DM3XX_RTOINT] = 4,
55 [IRQ_DM3XX_TINT5] = 7,
56 [IRQ_DM3XX_TINT6] = 7,
57 [IRQ_CCINT0] = 5, /* dma */
58 [IRQ_DM3XX_SPINT1_0] = 5, /* dma */
59 [IRQ_DM3XX_SPINT1_1] = 5, /* dma */
60 [IRQ_DM3XX_SPINT2_0] = 5, /* dma */
61 [IRQ_DM365_PSCINT] = 7,
62 [IRQ_DM3XX_SPINT2_1] = 7,
63 [IRQ_DM3XX_TINT7] = 4,
64 [IRQ_DM3XX_SDIOINT0] = 7,
65 [IRQ_DM365_MBXINT] = 7,
66 [IRQ_DM365_MBRINT] = 7,
67 [IRQ_DM3XX_MMCINT0] = 7,
68 [IRQ_DM3XX_MMCINT1] = 7,
69 [IRQ_DM3XX_PWMINT3] = 7,
70 [IRQ_DM365_DDRINT] = 7,
71 [IRQ_DM365_AEMIFINT] = 7,
72 [IRQ_DM3XX_SDIOINT1] = 4,
73 [IRQ_DM365_TINT0] = 2, /* clockevent */
74 [IRQ_DM365_TINT1] = 2, /* clocksource */
75 [IRQ_DM365_TINT2] = 7, /* DSP timer */
76 [IRQ_DM365_TINT3] = 7, /* system tick */
77 [IRQ_PWMINT0] = 7,
78 [IRQ_PWMINT1] = 7,
79 [IRQ_DM365_PWMINT2] = 7,
80 [IRQ_DM365_IICINT] = 3,
81 [IRQ_UARTINT0] = 3,
82 [IRQ_UARTINT1] = 3,
83 [IRQ_DM3XX_SPINT0_0] = 3,
84 [IRQ_DM3XX_SPINT0_1] = 3,
85 [IRQ_DM3XX_GPIO0] = 3,
86 [IRQ_DM3XX_GPIO1] = 7,
87 [IRQ_DM3XX_GPIO2] = 4,
88 [IRQ_DM3XX_GPIO3] = 4,
89 [IRQ_DM3XX_GPIO4] = 7,
90 [IRQ_DM3XX_GPIO5] = 7,
91 [IRQ_DM3XX_GPIO6] = 7,
92 [IRQ_DM3XX_GPIO7] = 7,
93 [IRQ_DM3XX_GPIO8] = 7,
94 [IRQ_DM3XX_GPIO9] = 7,
95 [IRQ_DM365_GPIO10] = 7,
96 [IRQ_DM365_GPIO11] = 7,
97 [IRQ_DM365_GPIO12] = 7,
98 [IRQ_DM365_GPIO13] = 7,
99 [IRQ_DM365_GPIO14] = 7,
100 [IRQ_DM365_GPIO15] = 7,
101 [IRQ_DM365_KEYINT] = 7,
102 [IRQ_DM365_COMMTX] = 7,
103 [IRQ_DM365_COMMRX] = 7,
104 [IRQ_EMUINT] = 7,
105 };
106
davinci_irq_readl(int offset)107 static inline unsigned int davinci_irq_readl(int offset)
108 {
109 return davinci_readl(DAVINCI_ARM_INTC_BASE + offset);
110 }
111
davinci_irq_writel(unsigned long value,int offset)112 static inline void davinci_irq_writel(unsigned long value, int offset)
113 {
114 davinci_writel(value, DAVINCI_ARM_INTC_BASE + offset);
115 }
116
117 /**
118 * @addtogroup DM36X
119 */
120 /*@{*/
121
rt_hw_interrupt_handle(int vector,void * param)122 rt_isr_handler_t rt_hw_interrupt_handle(int vector, void *param)
123 {
124 rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
125 return RT_NULL;
126 }
127
128 /**
129 * This function will initialize hardware interrupt
130 */
rt_hw_interrupt_init(void)131 void rt_hw_interrupt_init(void)
132 {
133 int i;
134 register rt_uint32_t idx;
135 const rt_uint8_t *priority;
136 priority = dm365_default_priorities;
137
138 /* Clear all interrupt requests */
139 davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
140 davinci_irq_writel(~0x0, FIQ_REG1_OFFSET);
141 davinci_irq_writel(~0x0, IRQ_REG0_OFFSET);
142 davinci_irq_writel(~0x0, IRQ_REG1_OFFSET);
143
144 /* Disable all interrupts */
145 davinci_irq_writel(0x0, IRQ_ENT_REG0_OFFSET);
146 davinci_irq_writel(0x0, IRQ_ENT_REG1_OFFSET);
147
148 /* Interrupts disabled immediately, IRQ entry reflects all */
149 davinci_irq_writel(0x0, IRQ_INCTL_REG_OFFSET);
150
151 /* we don't use the hardware vector table, just its entry addresses */
152 davinci_irq_writel(0, IRQ_EABASE_REG_OFFSET);
153
154 /* Clear all interrupt requests */
155 davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
156 davinci_irq_writel(~0x0, FIQ_REG1_OFFSET);
157 davinci_irq_writel(~0x0, IRQ_REG0_OFFSET);
158 davinci_irq_writel(~0x0, IRQ_REG1_OFFSET);
159
160 for (i = IRQ_INTPRI0_REG_OFFSET; i <= IRQ_INTPRI7_REG_OFFSET; i += 4) {
161 unsigned j;
162 rt_uint32_t pri;
163
164 for (j = 0, pri = 0; j < 32; j += 4, priority++)
165 pri |= (*priority & 0x07) << j;
166 davinci_irq_writel(pri, i);
167 }
168
169 /* init exceptions table */
170 for(idx=0; idx < MAX_HANDLERS; idx++)
171 {
172
173 irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
174 irq_desc[idx].param = RT_NULL;
175 #ifdef RT_USING_INTERRUPT_INFO
176 rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default");
177 irq_desc[idx].counter = 0;
178 #endif
179 }
180
181 /* init interrupt nest, and context in thread sp */
182 rt_interrupt_nest = 0;
183 rt_interrupt_from_thread = 0;
184 rt_interrupt_to_thread = 0;
185 rt_thread_switch_interrupt_flag = 0;
186 }
187
188 /**
189 * This function will mask a interrupt.
190 * @param vector the interrupt number
191 */
rt_hw_interrupt_mask(int irq)192 void rt_hw_interrupt_mask(int irq)
193 {
194 unsigned int mask;
195 rt_uint32_t l;
196
197 mask = 1 << IRQ_BIT(irq);
198
199 if (irq > 31) {
200 l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET);
201 l &= ~mask;
202 davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET);
203 } else {
204 l = davinci_irq_readl(IRQ_ENT_REG0_OFFSET);
205 l &= ~mask;
206 davinci_irq_writel(l, IRQ_ENT_REG0_OFFSET);
207 }
208 }
209
210 /**
211 * This function will un-mask a interrupt.
212 * @param vector the interrupt number
213 */
rt_hw_interrupt_umask(int irq)214 void rt_hw_interrupt_umask(int irq)
215 {
216 unsigned int mask;
217 rt_uint32_t l;
218
219 mask = 1 << IRQ_BIT(irq);
220
221 if (irq > 31) {
222 l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET);
223 l |= mask;
224 davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET);
225 } else {
226 l = davinci_irq_readl(IRQ_ENT_REG0_OFFSET);
227 l |= mask;
228 davinci_irq_writel(l, IRQ_ENT_REG0_OFFSET);
229 }
230 }
231
232 /**
233 * This function will install a interrupt service routine to a interrupt.
234 * @param vector the interrupt number
235 * @param handler the interrupt service routine to be installed
236 * @param param the interrupt service function parameter
237 * @param name the interrupt name
238 * @return old handler
239 */
240
rt_hw_interrupt_install(int vector,rt_isr_handler_t handler,void * param,const char * name)241 rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
242 void *param, const char *name)
243 {
244 rt_isr_handler_t old_handler = RT_NULL;
245
246 if(vector < MAX_HANDLERS)
247 {
248 old_handler = irq_desc[vector].handler;
249 if (handler != RT_NULL)
250 {
251 irq_desc[vector].handler = (rt_isr_handler_t)handler;
252 irq_desc[vector].param = param;
253 #ifdef RT_USING_INTERRUPT_INFO
254 rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name);
255 irq_desc[vector].counter = 0;
256 #endif
257 }
258 }
259
260 return old_handler;
261
262 }
263
264 #ifdef RT_USING_FINSH
265 #ifdef RT_USING_INTERRUPT_INFO
list_irq(void)266 void list_irq(void)
267 {
268 int irq;
269
270 rt_kprintf("number\tcount\tname\n");
271 for (irq = 0; irq < MAX_HANDLERS; irq++)
272 {
273 if (rt_strncmp(irq_desc[irq].name, "default", sizeof("default")))
274 {
275 rt_kprintf("%02ld: %10ld %s\n", irq, irq_desc[irq].counter, irq_desc[irq].name);
276 }
277 }
278 }
279
280 #include <finsh.h>
281 FINSH_FUNCTION_EXPORT(list_irq, list system irq);
282
283 #ifdef FINSH_USING_MSH
cmd_list_irq(int argc,char ** argv)284 int cmd_list_irq(int argc, char** argv)
285 {
286 list_irq();
287 return 0;
288 }
289 MSH_CMD_EXPORT_ALIAS(cmd_list_irq, list_irq, list system irq);
290 #endif
291 #endif
292 #endif
293
294 /*@}*/
295