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