]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/sparc/bsp/leon3/pic-sparc-leon3.cpp
update
[l4.git] / kernel / fiasco / src / kern / sparc / bsp / leon3 / pic-sparc-leon3.cpp
1 INTERFACE [sparc && leon3]:
2
3 #include "types.h"
4
5 class Irq_chip_icu;
6
7 EXTENSION class Pic
8 {
9 private:
10   /** Pic interrupt control registers (incomplete) */
11   ///+0x00: Peripheral Interrupt Mask Register
12   static Address per_mask() { return _pic_base; }
13   ///+0x04: Peripheral Priority & HI/LO Select Register1
14   static Address per_prio1() { return _pic_base + 0x04; }
15   ///+0x08: Peripheral Priority & HI/LO Select Register2
16   static Address per_prio2() { return _pic_base + 0x08; }
17   ///+0x0c: Peripheral Priority & HI/LO Select Register3
18   static Address per_prio3() { return _pic_base + 0x0c; }
19   ///+0x10: External Enable & External Types Register
20   static Address ext() { return _pic_base + 0x10; }
21   ///+0x14: Critical Priority & Main Inter. Mask Register
22   static Address main_mask() { return _pic_base + 0x14; }
23   ///+0x18: Main Inter. Priority1
24   static Address main_prio1() { return _pic_base + 0x18; }
25   ///+0x1c: Main Inter. Priority2
26   static Address main_prio2() { return _pic_base + 0x1c; }
27   ///+0x24: PerStat, MainStat, CritStat Encoded Registers
28   static Address stat() { return _pic_base + 0x24; }
29
30
31   /** Interrupt lines (sdma is missing) */
32   enum Pic_lines
33   {
34     IRQ_CRIT = 0x0, ///Critical line
35     IRQ_MAIN = 0x1, ///Main line
36     IRQ_PER  = 0x2, ///Periphal line
37     IRQ_SHIFT = 0x4
38   };
39
40   enum Pic_num_per_line
41   {
42     NUM_CRIT = 4,
43     NUM_MAIN = 17,
44     NUM_PER  = 24,
45   };
46
47   /** Interrupt senses */
48   enum Pic_sense
49   {
50     SENSE_LEVEL_HIGH   = 0,
51     SENSE_EDGE_RISING  = 1,
52     SENSE_EDGE_FALLING = 2,
53     SENSE_LEVEL_LOW    = 3
54   };
55
56   static Address _pic_base;
57
58 public:
59   enum { IRQ_MAX  = (IRQ_PER << IRQ_SHIFT) + NUM_PER};
60   enum { No_irq_pending = ~0U };
61
62   static Irq_chip_icu *main;
63 };
64
65 //------------------------------------------------------------------------------
66 IMPLEMENTATION [sparc && leon3]:
67
68 #include "boot_info.h"
69 #include "io.h"
70 #include "irq.h"
71 #include "irq_chip_generic.h"
72 #include "irq_mgr.h"
73 #include "panic.h"
74 #include "sparc_types.h"
75
76 #include <cassert>
77 #include <cstdio>
78
79 Irq_chip_icu *Pic::main;
80
81 class Chip : public Irq_chip_gen
82 {
83 public:
84   Chip() : Irq_chip_gen(Pic::IRQ_MAX) {}
85   int set_mode(Mword, Mode) { return 0; }
86   bool is_edge_triggered(Mword) const { return false; }
87   void set_cpu(Mword, Cpu_number) {}
88 };
89
90 PUBLIC
91 void
92 Chip::mask(Mword)
93 {
94   assert(cpu_lock.test());
95   //Pic::disable_locked(irq);
96 }
97
98 PUBLIC
99 void
100 Chip::ack(Mword)
101 {
102   assert(cpu_lock.test());
103   //Pic::acknowledge_locked(irq);
104 }
105
106 PUBLIC
107 void
108 Chip::mask_and_ack(Mword)
109 {
110   assert(cpu_lock.test());
111   //Pic::disable_locked(irq());
112   //Pic::acknowledge_locked(irq());
113 }
114
115 PUBLIC
116 void
117 Chip::unmask(Mword)
118 {
119   assert(cpu_lock.test());
120   //Pic::enable_locked(irq());
121 }
122
123 IMPLEMENT FIASCO_INIT
124 void
125 Pic::init()
126 {
127 }
128
129 //------------------------------------------------------------------------------
130 /**
131  * Irq number translations
132  */
133 PUBLIC static inline
134 unsigned
135 Pic::irq_num(unsigned line, unsigned pic_num)
136 { return (line << IRQ_SHIFT) | pic_num; }
137
138
139 PUBLIC static
140 int
141 Pic::get_irq_num(const char *name, const char *type)
142 {
143   (void)name; (void)type;
144   return -1;
145 }
146
147 PRIVATE static inline NEEDS[<cassert>]
148 unsigned
149 Pic::pic_line(unsigned irq_num)
150 {
151   unsigned line = irq_num >> IRQ_SHIFT;
152   assert(line < 3);
153   return line;
154 }
155
156 PRIVATE static inline NEEDS[Pic::pic_line]
157 unsigned
158 Pic::pic_num(unsigned irq_num)
159 {
160   unsigned line = pic_line(irq_num);
161   unsigned num = irq_num & ~(~0U << IRQ_SHIFT);
162
163   switch(line)
164     {
165     case IRQ_CRIT:
166       assert(num < NUM_CRIT);
167       break;
168     case IRQ_MAIN:
169       assert(num < NUM_MAIN);
170       break;
171     default:
172       assert(num < NUM_PER);
173     }
174
175   return num;
176 }
177
178
179 //-------------------------------------------------------------------------------
180 /**
181  * Interface implementation
182  */
183 IMPLEMENT inline
184 void
185 Pic::block_locked (unsigned irq_num)
186 {
187   disable_locked(irq_num);
188 }
189
190 IMPLEMENT inline NEEDS["io.h", Pic::pic_line, Pic::pic_num, Pic::set_stat_msb]
191 void
192 Pic::acknowledge_locked(unsigned irq_num)
193 {
194   unsigned line = pic_line(irq_num);
195   unsigned num  = pic_num(irq_num);
196
197   if((line == IRQ_MAIN && (num >= 1 || num <= 3)) ||
198      (line == IRQ_CRIT && num == 0))
199     Io::set<Unsigned32>(1U << (27 - num), ext());
200
201   set_stat_msb(irq_num);
202 }
203
204 PRIVATE static inline
205 void
206 Pic::dispatch_mask(unsigned irq_num, Address *addr, unsigned *bit_offs)
207 {
208   switch(pic_line(irq_num))
209     {
210     case IRQ_MAIN:
211       *addr = main_mask();
212       *bit_offs = 16;
213       break;
214     case IRQ_PER:
215       *addr = per_mask();
216       *bit_offs = 31;
217       break;
218     default:
219       panic("%s: Cannot handle IRQ %u", __PRETTY_FUNCTION__, irq_num);
220     }
221 }
222
223 PRIVATE static inline
224 void
225 Pic::set_stat_msb(unsigned irq_num)
226 {
227   switch(pic_line(irq_num))
228     {
229     case IRQ_MAIN:
230       Io::set<Unsigned32>(0x00200000, stat());
231       break;
232     case IRQ_PER:
233       Io::set<Unsigned32>(0x20000000, stat());
234       break;
235     default:
236       panic("CRIT not implemented");
237     }
238 }
239
240 IMPLEMENT inline NEEDS[Pic::pic_num, Pic::dispatch_mask]
241 void
242 Pic::disable_locked (unsigned irq_num)
243 {
244   Address addr;
245   unsigned bit_offs;
246   dispatch_mask(irq_num, &addr, &bit_offs);
247   Io::set<Unsigned32>(1U << (bit_offs - pic_num(irq_num)), addr);
248 }
249
250 IMPLEMENT inline NEEDS[Pic::dispatch_mask]
251 void
252 Pic::enable_locked (unsigned irq_num, unsigned /*prio*/)
253 {
254   Address addr;
255   unsigned bit_offs;
256   dispatch_mask(irq_num, &addr, &bit_offs);
257
258   Io::clear<Unsigned32>(1U << (bit_offs - pic_num(irq_num)), addr);
259 }
260
261 PUBLIC static inline NEEDS["panic.h"]
262 unsigned
263 Pic::nr_irqs()
264 { return IRQ_MAX; }
265
266 PRIVATE static inline
267 Unsigned32
268 Pic::pending_per(Unsigned32 state)
269 {
270   Unsigned32 irq = state >> 24 & 0x1f; //5 bit
271
272   if(irq  == 0)
273     panic("No support for bestcomm interrupt, yet\n");
274
275   return irq_num(IRQ_PER, irq);
276 }
277
278 PRIVATE static inline
279 Unsigned32
280 Pic::pending_main(Unsigned32 state)
281 {
282   Unsigned32 irq = state >> 16 & 0x1f;
283
284   //low periphal
285   if(irq == 4)
286     return pending_per(state);
287
288   return irq_num(IRQ_MAIN, irq);
289 }
290
291 PUBLIC static inline NEEDS[Pic::pending_main, Pic::pending_per]
292 Unsigned32
293 Pic::pending()
294 {
295   Unsigned32 irq = No_irq_pending;
296   return irq;
297 }
298
299 /**
300  * disable interrupt lines [0-3]
301  */
302 IMPLEMENT inline
303 Pic::Status
304 Pic::disable_all_save()
305 {
306   Status s;
307   return s;
308 }
309
310 IMPLEMENT inline
311 void
312 Pic::restore_all(Status s)
313 {
314   Io::write<Unsigned32>(s, ext());
315 }
316
317 // ------------------------------------------------------------------------
318 IMPLEMENTATION [debug && sparc && leon3]:
319
320 PUBLIC
321 char const *
322 Chip::chip_type() const
323 { return "HW Mpc52xx IRQ"; }