FreeNOS
ARMGenericInterrupt.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2019 Niek Linnenbank
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <Log.h>
19#include "ARMGenericInterrupt.h"
20
22 Address distRegisterBase,
23 Address cpuRegisterBase)
25{
26 // Set I/O register bases
27 m_dist.setBase(distRegisterBase);
28 m_cpu.setBase(cpuRegisterBase);
29
30 // Read number of interrupt lines available
32 NOTICE(m_numIrqs << " IRQ lines");
33}
34
36{
37 if (performReset)
38 {
39 // Set all interrupts in group 0 and disable all interrupts
40 for (uint i = 0; i < numRegisters(1); i++)
41 {
42 m_dist.write(GICD_GROUPR + (i * 4), 0);
43 m_dist.write(GICD_ICENABLER + (i * 4), ~0);
44 }
45
46 // Set interrupt configuration to level triggered (2-bits)
47 for (uint i = 0; i < (m_numIrqs / 2); i++)
48 {
49 m_dist.write(GICD_ICFGR + (i * 4), 0);
50 }
51
52 // Set interrupt priority
53 for (uint i = 0; i < (m_numIrqs / 4); i++)
54 {
55 m_dist.write(GICD_IPRIORITYR + (i * 4), 0xA0A0A0A0);
56 }
57
58 // All interrupts are assigned to core0.
59 // Ignore the first 32 PPIs, which are local and banked per core.
60 for (uint i = 8; i < (m_numIrqs / 4); i++)
61 {
62 m_dist.write(GICD_ITARGETSR + (i * 4),
63 (1 << 0) | (1 << 8) | (1 << 16) | (1 << 24));
64 }
65
66 // Enable all groups
68 }
69
70 // Set minimum priority level and enable all groups
71 m_cpu.write(GICC_PMR, 0xF0);
73
74 return Success;
75}
76
78 const uint irq)
79{
80 m_dist.write(GICD_SGIR, ((1 << targetCoreId) << 16) | irq);
81 return Success;
82}
83
85{
86 if (!isSoftwareInterrupt(irq))
87 {
88 m_dist.set(GICD_ISENABLER + (4 * (irq / 32)), (1 << (irq % 32)));
89 }
90 return Success;
91}
92
94{
95 if (!isSoftwareInterrupt(irq))
96 {
97 m_dist.set(GICD_ICENABLER + (4 * (irq / 32)), (1 << (irq % 32)));
98 }
99 return Success;
100}
101
103{
104 if (isSoftwareInterrupt(irq))
105 {
106 // Clear all pending bits for SGIs, regardless of which core is the sender
108 }
109
110 // The saved IAR contains target CPU bits for SGIs
113 return Success;
114}
115
117{
119
121
122 // Is this a spurious (unexpected) interrupt?
123 if (irq == 1023)
124 {
125 return NotFound;
126 }
127 else
128 return Success;
129}
130
132{
133 // Unused
134 return false;
135}
136
138{
139 if (m_numIrqs % 32)
140 return ((m_numIrqs * bits) / 32) + 1;
141 else
142 return (m_numIrqs * bits) / 32;
143}
144
146{
147 return irq < NumberOfSoftwareInterrupts;
148}
Size m_numIrqs
Number of interrupts supported.
virtual bool isTriggered(uint irq)
Check if an IRQ vector is set.
ARMIO m_cpu
ARM Generic Interrupt Controller CPU Interface.
virtual Result enable(uint irq)
Enable hardware interrupt (IRQ).
virtual Result nextPending(uint &irq)
Retrieve the next pending interrupt (IRQ).
Result initialize(bool performReset=true)
Initialize the controller.
Size numRegisters(Size bits) const
Calculate the number of 32-bit registers needed to represent given number of bits per IRQ.
bool isSoftwareInterrupt(const uint irq) const
Check if the given IRQ is an SGI.
virtual Result disable(uint irq)
Disable hardware interrupt (IRQ).
static const Size NumberOfSoftwareInterrupts
Total number of software generated interrupts (SGI)
ARMIO m_dist
ARM Generic Interrupt Controller Distributor Interface.
virtual Result send(const uint targetCoreId, const uint irq)
Raise a software generated interrupt (SGI).
ARMGenericInterrupt(Address distRegisterBase, Address cpuRegisterBase)
Constructor.
virtual Result clear(uint irq)
Clear hardware interrupt (IRQ).
u32 m_savedIrqAck
Saved value of the Interrupt-Acknowledge register.
void set(Address addr, u32 data)
Set bits in memory mapped register.
Definition ARMIO.h:109
void write(u32 reg, u32 data)
write to memory mapped I/O register
Definition ARMIO.h:46
u32 read(u32 reg) const
read from memory mapped I/O register
Definition ARMIO.h:62
void setBase(const Address base)
Set memory I/O base offset.
Definition IO.cpp:33
Interrupt controller interface.
Result
Result codes.
unsigned long Address
A memory address.
Definition Types.h:131
#define NOTICE(msg)
Output a notice message.
Definition Log.h:75
unsigned int uint
Unsigned integer number.
Definition Types.h:44
unsigned int Size
Any sane size indicator cannot go negative.
Definition Types.h:128