FreeNOS
BroadcomInterrupt.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 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 "BroadcomInterrupt.h"
20 
21 #define INTERRUPT_BASE_ADDR 0xB000
22 #define INTERRUPT_BASICPEND (INTERRUPT_BASE_ADDR+0x200)
23 #define INTERRUPT_IRQPEND1 (INTERRUPT_BASE_ADDR+0x204)
24 #define INTERRUPT_IRQPEND2 (INTERRUPT_BASE_ADDR+0x208)
25 #define INTERRUPT_FIQCONTROL (INTERRUPT_BASE_ADDR+0x20C)
26 #define INTERRUPT_ENABLEIRQ1 (INTERRUPT_BASE_ADDR+0x210)
27 #define INTERRUPT_ENABLEIRQ2 (INTERRUPT_BASE_ADDR+0x214)
28 #define INTERRUPT_ENABLEBASICIRQ (INTERRUPT_BASE_ADDR+0x218)
29 #define INTERRUPT_DISABLEIRQ1 (INTERRUPT_BASE_ADDR+0x21C)
30 #define INTERRUPT_DISABLEIRQ2 (INTERRUPT_BASE_ADDR+0x220)
31 #define INTERRUPT_DISABLEBASICIRQ (INTERRUPT_BASE_ADDR+0x224)
32  #define IRQSYSTIMERC1 1
33  #define IRQSYSTIMERC3 3
34  #define IRQAUX 29
35  #define IRQUART 57
36 
38 {
39  // disable all IRQ sources first, just to be "safe"
40  m_io.write(INTERRUPT_DISABLEIRQ1, 0xFFFFFFFF);
41  m_io.write(INTERRUPT_DISABLEIRQ2, 0xFFFFFFFF);
42 }
43 
45 {
46  // enable the respective interrupt
47  if(vector < 32)
48  {
49  // only 1 bits are recognized when writing to the (en/dis)able regs.
50  // using |= here could be problematic since it would likely be
51  // implemented as multiple instructions: at least a read, an or,
52  // and a write. if we interrupted _after_ the read instruction or
53  // the or instruction, and disabled certain bits in the IRQ
54  // routine, the |= would write back the old state of the enable
55  // bits. This would effectively be re-enabling interrupts that we
56  // wanted disabled.
57  m_io.write(INTERRUPT_ENABLEIRQ1, (1<<vector));
58  }
59  else
60  {
61  m_io.write(INTERRUPT_ENABLEIRQ2, (1<<(vector-32)));
62  }
63  return Success;
64 }
65 
67 {
68  // disable IRQs for this device before NULL-ing the vector. otherwise,
69  // we might interrupt with a NULL_VECT in the handler's address.
70  // because the interrupt wasn't ACKed because we never went to the
71  // handler routine, the device will continue to assert its IRQ line,
72  // which will put us in a never-ending IRQ loop.
73  if(vector < 32)
74  {
75  m_io.write(INTERRUPT_DISABLEIRQ1, (1<<vector));
76  }
77  else
78  {
79  m_io.write(INTERRUPT_DISABLEIRQ2, (1<<(vector-32)));
80  }
81  return Success;
82 }
83 
85 {
86  return Success;
87 }
88 
90 {
91  for (Size i = 0; i < 64; i++)
92  {
93  if (isTriggered(i))
94  {
95  irq = i;
96  return Success;
97  }
98  }
99 
100  return NotFound;
101 }
102 
104 {
105  u32 basic = m_io.read(INTERRUPT_BASICPEND);
106 
107  switch (vector)
108  {
109  case 9: return (basic & (1 << 11));
110  }
111  u32 pend1 = m_io.read(INTERRUPT_IRQPEND1);
112  u32 pend2 = m_io.read(INTERRUPT_IRQPEND2);
113 
114  if (vector < 32)
115  return (pend1 & (1 << vector));
116  else
117  return (pend2 & (1 << (vector-32)));
118 }
IntController
Interrupt controller interface.
Definition: IntController.h:35
BroadcomInterrupt::nextPending
virtual Result nextPending(uint &irq)
Retrieve the next pending interrupt (IRQ).
Definition: BroadcomInterrupt.cpp:89
ARMIO::write
void write(u32 reg, u32 data)
write to memory mapped I/O register
Definition: ARMIO.h:46
INTERRUPT_DISABLEIRQ1
#define INTERRUPT_DISABLEIRQ1
Definition: BroadcomInterrupt.cpp:29
INTERRUPT_DISABLEIRQ2
#define INTERRUPT_DISABLEIRQ2
Definition: BroadcomInterrupt.cpp:30
IntController::Success
@ Success
Definition: IntController.h:44
Log.h
IntController::NotFound
@ NotFound
Definition: IntController.h:48
uint
unsigned int uint
Unsigned integer number.
Definition: Types.h:44
BroadcomInterrupt::m_io
ARMIO m_io
I/O instance.
Definition: BroadcomInterrupt.h:94
BroadcomInterrupt::clear
virtual Result clear(uint vector)
Clear an IRQ vector.
Definition: BroadcomInterrupt.cpp:84
INTERRUPT_ENABLEIRQ1
#define INTERRUPT_ENABLEIRQ1
Definition: BroadcomInterrupt.cpp:26
BroadcomInterrupt::isTriggered
virtual bool isTriggered(uint vector)
Check if an IRQ vector is set.
Definition: BroadcomInterrupt.cpp:103
BroadcomInterrupt::BroadcomInterrupt
BroadcomInterrupt()
Constructor.
Definition: BroadcomInterrupt.cpp:37
u32
unsigned int u32
Unsigned 32-bit number.
Definition: Types.h:53
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
ARMIO::read
u32 read(u32 reg) const
read from memory mapped I/O register
Definition: ARMIO.h:62
INTERRUPT_BASICPEND
#define INTERRUPT_BASICPEND
Definition: BroadcomInterrupt.cpp:22
BroadcomInterrupt.h
INTERRUPT_IRQPEND1
#define INTERRUPT_IRQPEND1
Definition: BroadcomInterrupt.cpp:23
INTERRUPT_ENABLEIRQ2
#define INTERRUPT_ENABLEIRQ2
Definition: BroadcomInterrupt.cpp:27
BroadcomInterrupt::disable
virtual Result disable(uint vector)
Disable an IRQ vector.
Definition: BroadcomInterrupt.cpp:66
BroadcomInterrupt::enable
virtual Result enable(uint vector)
Enable an IRQ vector.
Definition: BroadcomInterrupt.cpp:44
INTERRUPT_IRQPEND2
#define INTERRUPT_IRQPEND2
Definition: BroadcomInterrupt.cpp:24
IntController::Result
Result
Result codes.
Definition: IntController.h:42