1 INTERFACE [arm && pic_gic]:
19 DIST_ENABLE_SET = 0x100,
20 DIST_ENABLE_CLEAR = 0x180,
35 CPU_CTRL_USE_FIQ_FOR_SEC = 8,
39 class Gic_pin : public Irq_pin
42 Gic_pin(unsigned gic_idx, unsigned irq)
43 { payload()[0] = (gic_idx << 16) | irq; }
45 unsigned irq() const { return payload()[0] & 0xffff; }
46 Gic *gic() const { return &_gic[payload()[0] >> 16]; }
51 class Gic_cascade_pin : public Gic_pin
54 Gic_cascade_pin(unsigned gic_idx, unsigned irq)
55 : Gic_pin(gic_idx, irq) {}
58 class Gic_cascade_irq : public Irq_base
61 explicit Gic_cascade_irq(Gic *child_gic, Unsigned32 irq_offset)
62 : _child_gic(child_gic), _irq_offset(irq_offset) {}
64 Unsigned32 irq_offset() const { return _irq_offset; }
65 Gic *child_gic() const { return _child_gic; }
68 Unsigned32 _irq_offset;
71 //-------------------------------------------------------------------
72 IMPLEMENTATION [arm && pic_gic]:
79 #include "irq_chip_generic.h"
83 PUBLIC inline NEEDS["io.h"]
86 { return ((Io::read<Mword>(_dist_base + DIST_CTR) & 0x1f) + 1) * 32; }
88 PUBLIC inline NEEDS["io.h"]
91 { return Io::read<Mword>(_dist_base + DIST_CTR) & (1 << 10); }
94 void Gic::softint_cpu(unsigned callmap, unsigned m)
96 Io::write<Mword>((callmap & 0xff) << 16 | m, _dist_base + DIST_SOFTINT);
100 void Gic::softint_bcast(unsigned m)
101 { Io::write<Mword>(1 << 24 | m, _dist_base + DIST_SOFTINT); }
107 Io::write<Mword>(CPU_CTRL_ENABLE, _cpu_base + CPU_CTRL);
108 Io::write<Mword>(0xf0, _cpu_base + CPU_PRIMASK);
113 Gic::init(Address cpu_base, Address dist_base)
115 _cpu_base = cpu_base;
116 _dist_base = dist_base;
118 Io::write<Mword>(0, _dist_base + DIST_CTRL);
120 unsigned num = nr_irqs();
121 printf("Number of IRQs available at this GIC: %d\n", num);
123 unsigned int intmask = 1 << Proc::cpu_id();
124 intmask |= intmask << 8;
125 intmask |= intmask << 16;
127 for (unsigned i = 32; i < num; i += 16)
128 Io::write<Mword>(0, _dist_base + DIST_CONFIG + i * 4 / 16);
129 for (unsigned i = 32; i < num; i += 4)
130 Io::write<Mword>(intmask, _dist_base + DIST_TARGET + i);
131 for (unsigned i = 0; i < num; i += 4)
132 Io::write<Mword>(0xa0a0a0a0, _dist_base + DIST_PRI + i);
133 for (unsigned i = 0; i < num; i += 32)
134 Io::write<Mword>(0xffffffff, _dist_base + DIST_ENABLE_CLEAR + i * 4 / 32);
136 Io::write<Mword>(1, _dist_base + DIST_CTRL);
138 Io::write<Mword>(CPU_CTRL_ENABLE, _cpu_base + CPU_CTRL);
139 Io::write<Mword>(0xf0, _cpu_base + CPU_PRIMASK);
141 //enable_tz_support();
144 PUBLIC inline NEEDS["io.h"]
145 void Gic::disable_locked( unsigned irq )
146 { Io::write<Mword>(1 << (irq % 32), _dist_base + DIST_ENABLE_CLEAR + (irq / 32) * 4); }
148 PUBLIC inline NEEDS["io.h"]
149 void Gic::enable_locked(unsigned irq, unsigned /*prio*/)
150 { Io::write<Mword>(1 << (irq % 32), _dist_base + DIST_ENABLE_SET + (irq / 32) * 4); }
152 PUBLIC inline NEEDS [Gic::enable_locked]
153 void Gic::acknowledge_locked( unsigned irq )
154 { Io::write<Mword>(irq, _cpu_base + CPU_EOI); }
158 Gic_pin::unbind_irq()
162 Irq_chip::hw_chip->free(Irq::self(this), irq());
163 replace<Sw_irq_pin>();
170 assert (cpu_lock.test());
171 gic()->disable_locked(irq());
176 Gic_pin::do_mask_and_ack()
178 assert (cpu_lock.test());
180 gic()->disable_locked(irq());
181 gic()->acknowledge_locked(irq());
188 gic()->acknowledge_locked(irq());
195 Irq::self(this)->Irq::hit();
202 assert (cpu_lock.test());
203 gic()->enable_locked(irq(), 0xa);
208 Gic_pin::do_set_mode(unsigned)
213 Gic_pin::check_debug_irq()
215 return !Vkey::check_(irq());
221 Gic_cascade_irq::self(Irq_pin const *pin)
223 #define MYoffsetof(TYPE, MEMBER) (((size_t) &((TYPE *)10)->MEMBER) - 10)
224 return reinterpret_cast<Gic_cascade_irq*>(reinterpret_cast<Mword>(pin)
225 - MYoffsetof(Gic_cascade_irq, _pin));
232 Gic_cascade_pin::hit()
234 Unsigned32 num = Gic_cascade_irq::self(this)->child_gic()->pending();
238 Irq *i = nonull_static_cast<Irq*>(Irq_chip_gen::lookup(num + Gic_cascade_irq::self(this)->irq_offset()));
241 gic()->acknowledge_locked(irq());
244 //-------------------------------------------------------------------
245 IMPLEMENTATION [arm && !mp && pic_gic]:
249 Gic_pin::set_cpu(unsigned)
252 PUBLIC inline NEEDS["io.h"]
253 Unsigned32 Gic::pending()
254 { return Io::read<Mword>(_cpu_base + CPU_INTACK) & 0x3ff; }
256 //-------------------------------------------------------------------
257 IMPLEMENTATION [arm && mp && pic_gic]:
261 PUBLIC inline NEEDS["io.h"]
262 Unsigned32 Gic::pending()
264 Unsigned32 ack = Io::read<Mword>(_cpu_base + CPU_INTACK);
266 // IPIs/SGIs need to take the whole ack value
267 if ((ack & 0x3ff) < 16)
268 Io::write<Mword>(ack, _cpu_base + CPU_EOI);
273 PUBLIC inline NEEDS["cpu.h"]
275 Gic::set_cpu(unsigned irq, unsigned cpu)
277 Mword reg = _dist_base + DIST_TARGET + (irq & ~3);
278 Mword val = Io::read<Mword>(reg);
280 int shift = (irq % 4) * 8;
281 val = (val & ~(0xf << shift)) | (1 << (Cpu::cpus.cpu(cpu).phys_id() + shift));
283 Io::write<Mword>(val, reg);
288 Gic_pin::set_cpu(unsigned cpu)
290 gic()->set_cpu(irq(), cpu);
293 //-------------------------------------------------------------------
294 IMPLEMENTATION [arm && pic_gic && tz]:
299 Gic::set_irq_nonsecure(unsigned irqnum)
301 Io::set<Mword>(1 << (irqnum % 32),
302 _dist_base + DIST_IRQ_SEC + ((irqnum & ~31) / 8));
306 PUBLIC inline NEEDS[<cstdio>]
308 Gic::enable_tz_support()
311 printf("GIC:Has security extension\n");
313 printf("GIC: Signal secure Interrupts as FIQs!\n");
314 Io::write<Mword>(CPU_CTRL_ENABLE | CPU_CTRL_USE_FIQ_FOR_SEC,
315 _cpu_base + CPU_CTRL);
318 //-------------------------------------------------------------------
319 IMPLEMENTATION [arm && pic_gic && !tz]:
323 Gic::enable_tz_support()
326 //---------------------------------------------------------------------------
327 IMPLEMENTATION [debug]:
331 Gic_pin::pin_type() const
332 { return "HW GIC IRQ"; }