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