1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2009-01-05     Bernard      first version
9  */
10 
11 #include <rthw.h>
12 #include <asm/ppc4xx.h>
13 #include <asm/processor.h>
14 
15 /* interrupt nest */
16 extern volatile rt_atomic_t rt_interrupt_nest;
17 
18 /* exception and interrupt handler table */
19 #define MAX_HANDLERS 32
20 struct rt_irq_desc isr_table[MAX_HANDLERS];
21 
22 rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
23 rt_uint32_t rt_thread_switch_interrput_flag;
24 
rt_hw_interrupt_handler(rt_uint32_t vector,void * param)25 rt_isr_handler_t rt_hw_interrupt_handler(rt_uint32_t vector, void* param)
26 {
27     rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
28     return RT_NULL;
29 }
30 
uic_irq_ack(unsigned int vec)31 void uic_irq_ack(unsigned int vec)
32 {
33     mtdcr(uic0sr, UIC_MASK(vec));
34 }
35 
uic_int_handler(unsigned int vec)36 void  uic_int_handler (unsigned int vec)
37 {
38     rt_interrupt_enter();
39 
40     /* Allow external interrupts to the CPU. */
41     if (isr_table [vec].handler != 0)
42     {
43        (*isr_table[vec].handler)(vec, isr_table[vec].param);
44     }
45     uic_irq_ack(vec);
46 
47     rt_interrupt_leave();
48 }
49 
50 /* handler for UIC interrupt */
uic_interrupt(rt_uint32_t uic_base,int vec_base)51 void uic_interrupt(rt_uint32_t uic_base, int vec_base)
52 {
53     int vec;
54     rt_uint32_t uic_msr;
55     rt_uint32_t msr_shift;
56 
57     /*
58      * Read masked interrupt status register to determine interrupt source
59      */
60     uic_msr = get_dcr(uic_base + UIC_MSR);
61     msr_shift = uic_msr;
62     vec = vec_base;
63 
64     while (msr_shift != 0)
65     {
66         if (msr_shift & 0x80000000)
67             uic_int_handler(vec);
68 
69         /*
70          * Shift msr to next position and increment vector
71          */
72         msr_shift <<= 1;
73         vec++;
74     }
75 }
76 
rt_hw_interrupt_install(int vector,rt_isr_handler_t new_handler,void * param,const char * name)77 rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t new_handler,
78     void* param, const char* name)
79 {
80     rt_base_t level;
81     rt_isr_handler_t old_handler;
82 
83     if (((int)vector < 0)  || ((int) vector >= MAX_HANDLERS))
84     {
85         return RT_NULL;   /*  out of range  */
86     }
87 
88     /* install the handler in the system interrupt table  */
89     level = rt_hw_interrupt_disable(); /* lock interrupts to prevent races */
90 
91     old_handler = isr_table[vector].handler;
92     isr_table[vector].handler = new_handler;
93     isr_table[vector].param = param;
94 
95     rt_hw_interrupt_enable(level);
96 }
97 
rt_hw_interrupt_mask(int vector)98 void rt_hw_interrupt_mask(int vector)
99 {
100     mtdcr(uic0er, mfdcr(uic0er) & ~UIC_MASK(vector));
101 }
102 
rt_hw_interrupt_unmask(int vector)103 void rt_hw_interrupt_unmask(int vector)
104 {
105     mtdcr(uic0er, mfdcr(uic0er) | UIC_MASK(vector));
106 }
107 
rt_hw_interrupt_init()108 void rt_hw_interrupt_init()
109 {
110     int vector;
111     rt_uint32_t pit_value;
112 
113     pit_value = RT_TICK_PER_SECOND * (100000000 / RT_CPU_FREQ);
114 
115     /* enable pit */
116     mtspr(SPRN_PIT, pit_value);
117     mtspr(SPRN_TCR, 0x4400000);
118 
119     /* set default interrupt handler */
120     for (vector = 0; vector < MAX_HANDLERS; vector++)
121     {
122         isr_table [vector].handler = (rt_isr_handler_t)rt_hw_interrupt_handler;
123         isr_table [vector].param = RT_NULL;
124     }
125 
126     /* initialize interrupt nest, and context in thread sp */
127     rt_interrupt_nest = 0;
128     rt_interrupt_from_thread = 0;
129     rt_interrupt_to_thread = 0;
130     rt_thread_switch_interrput_flag = 0;
131 }
132 
133 /*@}*/
134