]> 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   unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; }
86   void set_cpu(Mword, unsigned) {}
87 };
88
89 PUBLIC
90 void
91 Chip::mask(Mword)
92 {
93   assert(cpu_lock.test());
94   //Pic::disable_locked(irq);
95 }
96
97 PUBLIC
98 void
99 Chip::ack(Mword)
100 {
101   assert(cpu_lock.test());
102   //Pic::acknowledge_locked(irq);
103 }
104
105 PUBLIC
106 void
107 Chip::mask_and_ack(Mword)
108 {
109   assert(cpu_lock.test());
110   //Pic::disable_locked(irq());
111   //Pic::acknowledge_locked(irq());
112 }
113
114 PUBLIC
115 void
116 Chip::unmask(Mword)
117 {
118   assert(cpu_lock.test());
119   //Pic::enable_locked(irq());
120 }
121
122 IMPLEMENT FIASCO_INIT
123 void
124 Pic::init()
125 {
126 }
127
128 //------------------------------------------------------------------------------
129 /**
130  * Irq number translations
131  */
132 PUBLIC static inline
133 unsigned
134 Pic::irq_num(unsigned line, unsigned pic_num)
135 { return (line << IRQ_SHIFT) | pic_num; }
136
137
138 PUBLIC static
139 int
140 Pic::get_irq_num(const char *name, const char *type)
141 {
142   (void)name; (void)type;
143   return -1;
144 }
145
146 PRIVATE static inline NEEDS[<cassert>]
147 unsigned
148 Pic::pic_line(unsigned irq_num)
149 {
150   unsigned line = irq_num >> IRQ_SHIFT;
151   assert(line < 3);
152   return line;
153 }
154
155 PRIVATE static inline NEEDS[Pic::pic_line]
156 unsigned
157 Pic::pic_num(unsigned irq_num)
158 {
159   unsigned line = pic_line(irq_num);
160   unsigned num = irq_num & ~(~0U << IRQ_SHIFT);
161
162   switch(line)
163     {
164     case IRQ_CRIT:
165       assert(num < NUM_CRIT);
166       break;
167     case IRQ_MAIN:
168       assert(num < NUM_MAIN);
169       break;
170     default:
171       assert(num < NUM_PER);
172     }
173
174   return num;
175 }
176
177
178 //-------------------------------------------------------------------------------
179 /**
180  * Interface implementation
181  */
182 IMPLEMENT inline
183 void
184 Pic::block_locked (unsigned irq_num)
185 {
186   disable_locked(irq_num);
187 }
188
189 IMPLEMENT inline NEEDS["io.h", Pic::pic_line, Pic::pic_num, Pic::set_stat_msb]
190 void
191 Pic::acknowledge_locked(unsigned irq_num)
192 {
193   unsigned line = pic_line(irq_num);
194   unsigned num  = pic_num(irq_num);
195
196   if((line == IRQ_MAIN && (num >= 1 || num <= 3)) ||
197      (line == IRQ_CRIT && num == 0))
198     Io::set<Unsigned32>(1U << (27 - num), ext());
199
200   set_stat_msb(irq_num);
201 }
202
203 PRIVATE static inline
204 void
205 Pic::dispatch_mask(unsigned irq_num, Address *addr, unsigned *bit_offs)
206 {
207   switch(pic_line(irq_num))
208     {
209     case IRQ_MAIN:
210       *addr = main_mask();
211       *bit_offs = 16;
212       break;
213     case IRQ_PER:
214       *addr = per_mask();
215       *bit_offs = 31;
216       break;
217     default:
218       panic("%s: Cannot handle IRQ %u", __PRETTY_FUNCTION__, irq_num);
219     }
220 }
221
222 PRIVATE static inline
223 void
224 Pic::set_stat_msb(unsigned irq_num)
225 {
226   switch(pic_line(irq_num))
227     {
228     case IRQ_MAIN:
229       Io::set<Unsigned32>(0x00200000, stat());
230       break;
231     case IRQ_PER:
232       Io::set<Unsigned32>(0x20000000, stat());
233       break;
234     default:
235       panic("CRIT not implemented");
236     }
237 }
238
239 IMPLEMENT inline NEEDS[Pic::pic_num, Pic::dispatch_mask]
240 void
241 Pic::disable_locked (unsigned irq_num)
242 {
243   Address addr;
244   unsigned bit_offs;
245   dispatch_mask(irq_num, &addr, &bit_offs);
246   Io::set<Unsigned32>(1U << (bit_offs - pic_num(irq_num)), addr);
247 }
248
249 IMPLEMENT inline NEEDS[Pic::dispatch_mask]
250 void
251 Pic::enable_locked (unsigned irq_num, unsigned /*prio*/)
252 {
253   Address addr;
254   unsigned bit_offs;
255   dispatch_mask(irq_num, &addr, &bit_offs);
256
257   Io::clear<Unsigned32>(1U << (bit_offs - pic_num(irq_num)), addr);
258 }
259
260 PUBLIC static inline NEEDS["panic.h"]
261 unsigned
262 Pic::nr_irqs()
263 { return IRQ_MAX; }
264
265 PRIVATE static inline
266 Unsigned32
267 Pic::pending_per(Unsigned32 state)
268 {
269   Unsigned32 irq = state >> 24 & 0x1f; //5 bit
270
271   if(irq  == 0)
272     panic("No support for bestcomm interrupt, yet\n");
273
274   return irq_num(IRQ_PER, irq);
275 }
276
277 PRIVATE static inline
278 Unsigned32
279 Pic::pending_main(Unsigned32 state)
280 {
281   Unsigned32 irq = state >> 16 & 0x1f;
282
283   //low periphal
284   if(irq == 4)
285     return pending_per(state);
286
287   return irq_num(IRQ_MAIN, irq);
288 }
289
290 PUBLIC static inline NEEDS[Pic::pending_main, Pic::pending_per]
291 Unsigned32
292 Pic::pending()
293 {
294   Unsigned32 irq = No_irq_pending;
295   return irq;
296 }
297
298 /**
299  * disable interrupt lines [0-3]
300  */
301 IMPLEMENT inline
302 Pic::Status
303 Pic::disable_all_save()
304 {
305   Status s;
306   return s;
307 }
308
309 IMPLEMENT inline
310 void
311 Pic::restore_all(Status s)
312 {
313   Io::write<Unsigned32>(s, ext());
314 }
315
316 // ------------------------------------------------------------------------
317 IMPLEMENTATION [debug && sparc && leon3]:
318
319 PUBLIC
320 char const *
321 Chip::chip_type() const
322 { return "HW Mpc52xx IRQ"; }