/* * \brief Programmable interrupt controller for core * \author Stefan Kalkowski * \date 2012-10-24 */ /* * Copyright (C) 2012-2013 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ #ifndef _PIC_H_ #define _PIC_H_ /* Genode includes */ #include /* core includes */ #include namespace Genode { /** * Programmable interrupt controller for core */ class Pic; } class Genode::Pic : public Mmio { public: enum { /* * FIXME: dummy ipi value on non-SMP platform, should be removed * when SMP is an aspect of CPUs only compiled where necessary */ IPI = 0, NR_OF_IRQ = 109, }; protected: /** * Software Interrupt Trigger Register */ struct Swint : Register<0xf00, 32> { struct Intid : Bitfield<0,10> { }; }; /** * Interrupt control register */ struct Intctrl : Register<0, 32> { struct Enable : Bitfield<0,1> { }; struct Nsen : Bitfield<16,1> { }; struct Nsen_mask : Bitfield<31,1> { }; }; /** * Priority mask register */ struct Priomask : Register<0xc, 32> { struct Mask : Bitfield<0,8> { }; }; /** * Interrupt security registers */ struct Intsec : Register_array<0x80, 32, NR_OF_IRQ, 1> { struct Nonsecure : Bitfield<0, 1> { }; }; /** * Interrupt set enable registers */ struct Enset : Register_array<0x100, 32, NR_OF_IRQ, 1, true> { struct Set_enable : Bitfield<0, 1> { }; }; /** * Interrupt clear enable registers */ struct Enclear : Register_array<0x180, 32, NR_OF_IRQ, 1, true> { struct Clear_enable : Bitfield<0, 1> { }; }; /** * Interrupt priority level registers */ struct Priority : Register_array<0x400, 32, NR_OF_IRQ, 8> { }; /** * Highest interrupt pending registers */ struct Hipndr : Register_array<0xd80, 32, NR_OF_IRQ, 1, true> { struct Pending : Bitfield<0, 1> { }; }; /** * Initializes security extension if needed */ void _init_security_ext(); public: /** * Constructor */ Pic() : Mmio(Board::IRQ_CONTROLLER_BASE) { for (unsigned i = 0; i < NR_OF_IRQ; i++) { write(1, i); write(1, i); } write(0x1f); Intctrl::access_t v = 0; Intctrl::Enable::set(v, 1); Intctrl::Nsen::set(v, 1); Intctrl::Nsen_mask::set(v, 1); write(v); _init_security_ext(); } /** * Mark interrupt 'i' unsecure */ void unsecure(unsigned const i); /** * Mark interrupt 'i' secure */ void secure(unsigned const i); /** * Receive a pending request number 'i' */ bool take_request(unsigned & i) { for (unsigned j = 0; j < NR_OF_IRQ; j++) { if (!read(j)) { continue; } i = j; return true; } return false; } /** * Validate request number 'i' */ bool valid(unsigned const i) const { return i < NR_OF_IRQ; } /** * Unmask interrupt 'i' */ void unmask(unsigned const i, unsigned) { if (valid(i)) { write(1, i); } } /** * Mask interrupt 'i' */ void mask(unsigned const i) { if (valid(i)) { write(1, i); } } /* * Trigger interrupt 'i' from software if possible */ void trigger(unsigned const i) { write(Swint::Intid::bits(i)); } /************* ** Dummies ** *************/ void trigger_ip_interrupt(unsigned) { } void init_cpu_local() { } void finish_request() { } }; namespace Kernel { class Pic : public Genode::Pic { }; } #endif /* _PIC_H_ */