]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/arm/bsp/s3c/pic-arm-s3c2410.cpp
a89d122cf268924c6e2a840b30a696ad81edcea0
[l4.git] / kernel / fiasco / src / kern / arm / bsp / s3c / pic-arm-s3c2410.cpp
1 INTERFACE [arm && s3c2410]:
2
3 #include "kmem.h"
4
5 EXTENSION class Pic
6 {
7 public:
8   enum
9   {
10     SRCPND    = Kmem::Pic_map_base + 0x00,
11     INTMODE   = Kmem::Pic_map_base + 0x04,
12     INTMSK    = Kmem::Pic_map_base + 0x08,
13     PRIORITY  = Kmem::Pic_map_base + 0x0c,
14     INTPND    = Kmem::Pic_map_base + 0x10,
15     INTOFFSET = Kmem::Pic_map_base + 0x14,
16     SUBSRCPND = Kmem::Pic_map_base + 0x18,
17     INTSUBMSK = Kmem::Pic_map_base + 0x1c,
18   };
19
20   enum
21   {
22     MAIN_0        = 0,
23     MAIN_EINT4_7  = 4,
24     MAIN_EINT8_23 = 5,
25     MAIN_UART2    = 15,
26     MAIN_LCD      = 16,
27     MAIN_UART1    = 23,
28     MAIN_UART0    = 28,
29     MAIN_ADC      = 31,
30     MAIN_31       = 31,
31
32     SUB_RXD0 = 0,
33     SUB_TXD0 = 1,
34     SUB_ERR0 = 2,
35     SUB_RXD1 = 3,
36     SUB_TXD1 = 4,
37     SUB_ERR1 = 5,
38     SUB_RXD2 = 6,
39     SUB_TXD2 = 7,
40     SUB_ERR2 = 8,
41     SUB_TC   = 9,
42     SUB_ADC  = 10,
43   };
44
45   enum // Interrupts
46   {
47     // EINT4_7
48     EINT4  = 32,
49     EINT7  = 35,
50     // EINT8_23
51     EINT8  = 36,
52     EINT23 = 51,
53     // UART2
54     INT_UART2_ERR = 52,
55     INT_UART2_RXD = 53,
56     INT_UART2_TXD = 54,
57     // LCD
58     INT_LCD_FRSYN = 55,
59     INT_LCD_FICNT = 56,
60     // UART1
61     INT_UART1_ERR = 57,
62     INT_UART1_RXD = 58,
63     INT_UART1_TXD = 59,
64     // UART0
65     INT_UART0_ERR = 60,
66     INT_UART0_RXD = 61,
67     INT_UART0_TXD = 62,
68     // ADC
69     INT_ADC = 63,
70     INT_TC  = 64,
71   };
72 };
73
74 // ---------------------------------------------------------------------
75 IMPLEMENTATION [arm && s3c2410]:
76
77 #include "config.h"
78 #include "io.h"
79 #include "irq_chip_generic.h"
80 #include "irq_mgr.h"
81
82 #include <cstdio>
83
84 class S3c_chip : public Irq_chip_gen
85 {
86 public:
87   S3c_chip() : Irq_chip_gen(32) {}
88   unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; }
89   void set_cpu(Mword, unsigned) {}
90 };
91
92
93 PUBLIC
94 void
95 S3c_chip::mask(Mword irq)
96 {
97   Mword mainirq;
98
99   switch (irq)
100     {
101       case Pic::INT_TC:        Io::set<Mword>(1 << Pic::SUB_TC,   Pic::INTSUBMSK); mainirq = Pic::MAIN_ADC;   break;
102       case Pic::INT_ADC:       Io::set<Mword>(1 << Pic::SUB_ADC,  Pic::INTSUBMSK); mainirq = Pic::MAIN_ADC;   break;
103       case Pic::INT_UART0_RXD: Io::set<Mword>(1 << Pic::SUB_RXD0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break;
104       case Pic::INT_UART0_TXD: Io::set<Mword>(1 << Pic::SUB_TXD0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break;
105       case Pic::INT_UART0_ERR: Io::set<Mword>(1 << Pic::SUB_ERR0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break;
106       case Pic::INT_UART1_RXD: Io::set<Mword>(1 << Pic::SUB_RXD1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break;
107       case Pic::INT_UART1_TXD: Io::set<Mword>(1 << Pic::SUB_TXD1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break;
108       case Pic::INT_UART1_ERR: Io::set<Mword>(1 << Pic::SUB_ERR1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break;
109       case Pic::INT_UART2_RXD: Io::set<Mword>(1 << Pic::SUB_RXD2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break;
110       case Pic::INT_UART2_TXD: Io::set<Mword>(1 << Pic::SUB_TXD2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break;
111       case Pic::INT_UART2_ERR: Io::set<Mword>(1 << Pic::SUB_ERR2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break;
112       default:
113          if (irq > 31)
114            return; // XXX: need to add other cases
115          mainirq = irq;
116     };
117
118   Io::set<Mword>(1 << mainirq, Pic::INTMSK);
119 }
120
121 PUBLIC
122 void
123 S3c_chip::unmask(Mword irq)
124 {
125   int mainirq;
126
127   switch (irq)
128     {
129       case Pic::INT_TC:        Io::clear<Mword>(1 << Pic::SUB_TC,   Pic::INTSUBMSK); mainirq = Pic::MAIN_ADC;   break;
130       case Pic::INT_ADC:       Io::clear<Mword>(1 << Pic::SUB_ADC,  Pic::INTSUBMSK); mainirq = Pic::MAIN_ADC;   break;
131       case Pic::INT_UART0_RXD: Io::clear<Mword>(1 << Pic::SUB_RXD0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break;
132       case Pic::INT_UART0_TXD: Io::clear<Mword>(1 << Pic::SUB_TXD0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break;
133       case Pic::INT_UART0_ERR: Io::clear<Mword>(1 << Pic::SUB_ERR0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break;
134       case Pic::INT_UART1_RXD: Io::clear<Mword>(1 << Pic::SUB_RXD1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break;
135       case Pic::INT_UART1_TXD: Io::clear<Mword>(1 << Pic::SUB_TXD1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break;
136       case Pic::INT_UART1_ERR: Io::clear<Mword>(1 << Pic::SUB_ERR1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break;
137       case Pic::INT_UART2_RXD: Io::clear<Mword>(1 << Pic::SUB_RXD2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break;
138       case Pic::INT_UART2_TXD: Io::clear<Mword>(1 << Pic::SUB_TXD2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break;
139       case Pic::INT_UART2_ERR: Io::clear<Mword>(1 << Pic::SUB_ERR2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break;
140       default:
141          if (irq > 31)
142            return; // XXX: need to add other cases
143          mainirq = irq;
144     };
145
146   Io::clear<Mword>(1 << mainirq, Pic::INTMSK);
147 }
148
149 PUBLIC
150 void
151 S3c_chip::ack(Mword irq)
152 {
153   int mainirq;
154
155   switch (irq)
156     {
157       case Pic::INT_TC:        Io::write<Mword>(1 << Pic::SUB_TC,   Pic::SUBSRCPND); mainirq = Pic::MAIN_ADC;   break;
158       case Pic::INT_ADC:       Io::write<Mword>(1 << Pic::SUB_ADC,  Pic::SUBSRCPND); mainirq = Pic::MAIN_ADC;   break;
159       case Pic::INT_UART0_RXD: Io::write<Mword>(1 << Pic::SUB_RXD0, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART0; break;
160       case Pic::INT_UART0_TXD: Io::write<Mword>(1 << Pic::SUB_TXD0, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART0; break;
161       case Pic::INT_UART0_ERR: Io::write<Mword>(1 << Pic::SUB_ERR0, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART0; break;
162       case Pic::INT_UART1_RXD: Io::write<Mword>(1 << Pic::SUB_RXD1, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART1; break;
163       case Pic::INT_UART1_TXD: Io::write<Mword>(1 << Pic::SUB_TXD1, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART1; break;
164       case Pic::INT_UART1_ERR: Io::write<Mword>(1 << Pic::SUB_ERR1, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART1; break;
165       case Pic::INT_UART2_RXD: Io::write<Mword>(1 << Pic::SUB_RXD2, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART2; break;
166       case Pic::INT_UART2_TXD: Io::write<Mword>(1 << Pic::SUB_TXD2, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART2; break;
167       case Pic::INT_UART2_ERR: Io::write<Mword>(1 << Pic::SUB_ERR2, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART2; break;
168       default:
169          if (irq > 31)
170            return; // XXX: need to add other cases
171         mainirq = irq;
172     };
173
174   Io::write<Mword>(1 << mainirq, Pic::SRCPND); // only 1s are set to 0
175   Io::write<Mword>(1 << mainirq, Pic::INTPND); // clear pending interrupt
176 }
177
178 PUBLIC
179 void
180 S3c_chip::mask_and_ack(Mword irq)
181 {
182   assert(cpu_lock.test());
183   mask(irq);
184   ack(irq);
185 }
186
187
188 static Static_object<Irq_mgr_single_chip<S3c_chip> > mgr;
189
190
191 IMPLEMENT FIASCO_INIT
192 void Pic::init()
193 {
194   Irq_mgr::mgr = mgr.construct();
195
196   Io::write<Mword>(0xffffffff, INTMSK); // all masked
197   Io::write<Mword>(0x7fe, INTSUBMSK);   // all masked
198   Io::write<Mword>(0, INTMODE);         // all IRQs, no FIQs
199   Io::write<Mword>(Io::read<Mword>(SRCPND), SRCPND); // clear source pending
200   Io::write<Mword>(Io::read<Mword>(SUBSRCPND), SUBSRCPND); // clear sub src pnd
201   Io::write<Mword>(Io::read<Mword>(INTPND), INTPND); // clear pending interrupt
202 }
203
204
205 IMPLEMENT inline
206 Pic::Status Pic::disable_all_save()
207 {
208   Status s = 0;
209   return s;
210 }
211
212 IMPLEMENT inline
213 void Pic::restore_all(Status)
214 {}
215
216 PUBLIC static inline NEEDS["io.h"]
217 Unsigned32 Pic::pending()
218 {
219   int mainirq = Io::read<Mword>(INTOFFSET);
220
221   switch (mainirq)
222     {
223     case MAIN_ADC:
224         {
225           int subirq = Io::read<Mword>(SUBSRCPND);
226           if ((1 << SUB_ADC) & subirq)
227             return INT_ADC;
228           else if ((1 << SUB_TC) & subirq)
229             return INT_TC;
230         }
231       break;
232     // more: tbd
233     default:
234       return mainirq;
235     }
236   return 32;
237 }
238
239 extern "C"
240 void irq_handler()
241 {
242   Unsigned32 i = Pic::pending();
243   if (i != 32)
244     mgr->c.handle_irq<S3c_chip>(i, 0);
245 }
246
247 //---------------------------------------------------------------------------
248 IMPLEMENTATION [debug && s3c2410]:
249
250 PUBLIC
251 char const *
252 S3c_chip::chip_type() const
253 { return "HW S3C2410 IRQ"; }
254