]>
Commit | Line | Data |
---|---|---|
f780aa2a WD |
1 | /* |
2 | * (C) Copyright 2000-2002 | |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | * | |
5 | * (C) Copyright 2002 (440 port) | |
6 | * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com | |
7 | * | |
ba56f625 WD |
8 | * (C) Copyright 2003 (440GX port) |
9 | * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com | |
10 | * | |
d865fd09 | 11 | * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX) |
5b218ae1 | 12 | * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@gmail.com |
d865fd09 RR |
13 | * Work supported by Qtechnology (htpp://qtec.com) |
14 | * | |
1a459660 | 15 | * SPDX-License-Identifier: GPL-2.0+ |
f780aa2a WD |
16 | */ |
17 | ||
18 | #include <common.h> | |
19 | #include <watchdog.h> | |
20 | #include <command.h> | |
f780aa2a | 21 | #include <asm/processor.h> |
d865fd09 | 22 | #include <asm/interrupt.h> |
b36df561 | 23 | #include <asm/ppc4xx.h> |
f780aa2a | 24 | #include <ppc_asm.tmpl> |
f780aa2a | 25 | |
d1631fe1 SR |
26 | DECLARE_GLOBAL_DATA_PTR; |
27 | ||
f780aa2a WD |
28 | /* |
29 | * CPM interrupt vector functions. | |
30 | */ | |
31 | struct irq_action { | |
32 | interrupt_handler_t *handler; | |
33 | void *arg; | |
34 | int count; | |
35 | }; | |
d865fd09 | 36 | static struct irq_action irq_vecs[IRQ_MAX]; |
f780aa2a | 37 | |
f780aa2a WD |
38 | #if defined(CONFIG_440) |
39 | ||
40 | /* SPRN changed in 440 */ | |
41 | static __inline__ void set_evpr(unsigned long val) | |
42 | { | |
43 | asm volatile("mtspr 0x03f,%0" : : "r" (val)); | |
44 | } | |
45 | ||
46 | #else /* !defined(CONFIG_440) */ | |
47 | ||
f780aa2a WD |
48 | static __inline__ void set_pit(unsigned long val) |
49 | { | |
50 | asm volatile("mtpit %0" : : "r" (val)); | |
51 | } | |
52 | ||
f780aa2a WD |
53 | static __inline__ void set_evpr(unsigned long val) |
54 | { | |
55 | asm volatile("mtevpr %0" : : "r" (val)); | |
56 | } | |
57 | #endif /* defined(CONFIG_440 */ | |
58 | ||
a8c7c708 | 59 | int interrupt_init_cpu (unsigned *decrementer_count) |
f780aa2a | 60 | { |
f780aa2a WD |
61 | int vec; |
62 | unsigned long val; | |
63 | ||
a8c7c708 WD |
64 | /* decrementer is automatically reloaded */ |
65 | *decrementer_count = 0; | |
d4ca31c4 | 66 | |
f780aa2a WD |
67 | /* |
68 | * Mark all irqs as free | |
69 | */ | |
d865fd09 | 70 | for (vec = 0; vec < IRQ_MAX; vec++) { |
f780aa2a WD |
71 | irq_vecs[vec].handler = NULL; |
72 | irq_vecs[vec].arg = NULL; | |
73 | irq_vecs[vec].count = 0; | |
f780aa2a WD |
74 | } |
75 | ||
76 | #ifdef CONFIG_4xx | |
77 | /* | |
78 | * Init PIT | |
79 | */ | |
80 | #if defined(CONFIG_440) | |
58ea142f | 81 | val = mfspr( SPRN_TCR ); |
f780aa2a | 82 | val &= (~0x04400000); /* clear DIS & ARE */ |
58ea142f MF |
83 | mtspr( SPRN_TCR, val ); |
84 | mtspr( SPRN_DEC, 0 ); /* Prevent exception after TSR clear*/ | |
85 | mtspr( SPRN_DECAR, 0 ); /* clear reload */ | |
86 | mtspr( SPRN_TSR, 0x08000000 ); /* clear DEC status */ | |
68e0236f | 87 | val = gd->bd->bi_intfreq/1000; /* 1 msec */ |
58ea142f MF |
88 | mtspr( SPRN_DECAR, val ); /* Set auto-reload value */ |
89 | mtspr( SPRN_DEC, val ); /* Set inital val */ | |
f780aa2a WD |
90 | #else |
91 | set_pit(gd->bd->bi_intfreq / 1000); | |
92 | #endif | |
93 | #endif /* CONFIG_4xx */ | |
94 | ||
95 | #ifdef CONFIG_ADCIOP | |
96 | /* | |
97 | * Init PIT | |
98 | */ | |
99 | set_pit(66000); | |
100 | #endif | |
101 | ||
102 | /* | |
103 | * Enable PIT | |
104 | */ | |
58ea142f | 105 | val = mfspr(SPRN_TCR); |
f780aa2a | 106 | val |= 0x04400000; |
58ea142f | 107 | mtspr(SPRN_TCR, val); |
f780aa2a WD |
108 | |
109 | /* | |
110 | * Set EVPR to 0 | |
111 | */ | |
112 | set_evpr(0x00000000); | |
113 | ||
d865fd09 | 114 | /* |
60204d06 | 115 | * Call uic or xilinx_irq pic_enable |
d865fd09 RR |
116 | */ |
117 | pic_enable(); | |
f780aa2a WD |
118 | |
119 | return (0); | |
120 | } | |
121 | ||
d865fd09 | 122 | void timer_interrupt_cpu(struct pt_regs *regs) |
ba56f625 | 123 | { |
d865fd09 RR |
124 | /* nothing to do here */ |
125 | return; | |
f780aa2a | 126 | } |
ba56f625 | 127 | |
d865fd09 | 128 | void interrupt_run_handler(int vec) |
ba56f625 | 129 | { |
d865fd09 RR |
130 | irq_vecs[vec].count++; |
131 | ||
132 | if (irq_vecs[vec].handler != NULL) { | |
133 | /* call isr */ | |
134 | (*irq_vecs[vec].handler) (irq_vecs[vec].arg); | |
135 | } else { | |
136 | pic_irq_disable(vec); | |
137 | printf("Masking bogus interrupt vector %d\n", vec); | |
138 | } | |
6c5879f3 | 139 | |
d865fd09 | 140 | pic_irq_ack(vec); |
56e41017 | 141 | return; |
6c5879f3 | 142 | } |
f780aa2a | 143 | |
56e41017 | 144 | void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg) |
f780aa2a | 145 | { |
c157d8e2 | 146 | /* |
56e41017 | 147 | * Print warning when replacing with a different irq vector |
c157d8e2 | 148 | */ |
56e41017 SR |
149 | if ((irq_vecs[vec].handler != NULL) && (irq_vecs[vec].handler != handler)) { |
150 | printf("Interrupt vector %d: handler 0x%x replacing 0x%x\n", | |
151 | vec, (uint) handler, (uint) irq_vecs[vec].handler); | |
f780aa2a | 152 | } |
56e41017 SR |
153 | irq_vecs[vec].handler = handler; |
154 | irq_vecs[vec].arg = arg; | |
155 | ||
d865fd09 RR |
156 | pic_irq_enable(vec); |
157 | return; | |
f780aa2a WD |
158 | } |
159 | ||
d865fd09 | 160 | void irq_free_handler(int vec) |
f780aa2a | 161 | { |
56e41017 SR |
162 | debug("Free interrupt for vector %d ==> %p\n", |
163 | vec, irq_vecs[vec].handler); | |
f780aa2a | 164 | |
d865fd09 | 165 | pic_irq_disable(vec); |
f780aa2a | 166 | |
56e41017 SR |
167 | irq_vecs[vec].handler = NULL; |
168 | irq_vecs[vec].arg = NULL; | |
a8c7c708 | 169 | return; |
f780aa2a WD |
170 | } |
171 | ||
3a1ed1e1 | 172 | #if defined(CONFIG_CMD_IRQ) |
54841ab5 | 173 | int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
f780aa2a WD |
174 | { |
175 | int vec; | |
176 | ||
56e41017 | 177 | printf ("Interrupt-Information:\n"); |
f780aa2a WD |
178 | printf ("Nr Routine Arg Count\n"); |
179 | ||
d865fd09 | 180 | for (vec = 0; vec < IRQ_MAX; vec++) { |
f780aa2a WD |
181 | if (irq_vecs[vec].handler != NULL) { |
182 | printf ("%02d %08lx %08lx %d\n", | |
183 | vec, | |
184 | (ulong)irq_vecs[vec].handler, | |
185 | (ulong)irq_vecs[vec].arg, | |
186 | irq_vecs[vec].count); | |
187 | } | |
188 | } | |
189 | ||
ba56f625 WD |
190 | return 0; |
191 | } | |
3a1ed1e1 | 192 | #endif |