summaryrefslogtreecommitdiff
path: root/src/dev/arm/pl011.hh
diff options
context:
space:
mode:
authorAndreas Sandberg <Andreas.Sandberg@ARM.com>2015-03-02 04:00:44 -0500
committerAndreas Sandberg <Andreas.Sandberg@ARM.com>2015-03-02 04:00:44 -0500
commit7be9d4eb673b9d9b45eabfd40a56718569a2a1be (patch)
tree90a4356f817492a686d6931a3068645858fab001 /src/dev/arm/pl011.hh
parentd64b34bef82e6ea8a2438d92224d8d093df47d59 (diff)
downloadgem5-7be9d4eb673b9d9b45eabfd40a56718569a2a1be.tar.xz
dev, arm: Clean up PL011 and rewrite interrupt handling
The ARM PL011 UART model didn't clear and raise interrupts correctly. This changeset rewrites the whole interrupt handling and makes it both simpler and fixes several cases where the correct interrupts weren't raised or cleared. Additionally, it cleans up many other aspects of the code.
Diffstat (limited to 'src/dev/arm/pl011.hh')
-rw-r--r--src/dev/arm/pl011.hh150
1 files changed, 83 insertions, 67 deletions
diff --git a/src/dev/arm/pl011.hh b/src/dev/arm/pl011.hh
index b5c55beab..f2587c08d 100644
--- a/src/dev/arm/pl011.hh
+++ b/src/dev/arm/pl011.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2015 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -38,6 +38,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
+ * Andreas Sandberg
*/
@@ -48,18 +49,73 @@
#ifndef __DEV_ARM_PL011_H__
#define __DEV_ARM_PL011_H__
-#include "base/bitfield.hh"
-#include "base/bitunion.hh"
#include "dev/arm/amba_device.hh"
-#include "dev/io_device.hh"
#include "dev/uart.hh"
-#include "params/Pl011.hh"
class BaseGic;
+struct Pl011Params;
class Pl011 : public Uart, public AmbaDevice
{
- protected:
+ public:
+ Pl011(const Pl011Params *p);
+
+ void serialize(std::ostream &os) M5_ATTR_OVERRIDE;
+ void unserialize(Checkpoint *cp, const std::string &sec) M5_ATTR_OVERRIDE;
+
+ public: // PioDevice
+ Tick read(PacketPtr pkt) M5_ATTR_OVERRIDE;
+ Tick write(PacketPtr pkt) M5_ATTR_OVERRIDE;
+
+ public: // Uart
+ void dataAvailable() M5_ATTR_OVERRIDE;
+
+
+ protected: // Interrupt handling
+ /** Function to generate interrupt */
+ void generateInterrupt();
+
+ /**
+ * Assign new interrupt values and update interrupt signals
+ *
+ * A new interrupt is scheduled signalled if the set of unmasked
+ * interrupts goes empty to non-empty. Conversely, if the set of
+ * unmasked interrupts goes from non-empty to empty, the interrupt
+ * signal is cleared.
+ *
+ * @param ints New <i>raw</i> interrupt status
+ * @param mask New interrupt mask
+ */
+ void setInterrupts(uint16_t ints, uint16_t mask);
+ /**
+ * Convenience function to update the interrupt mask
+ *
+ * @see setInterrupts
+ * @param mask New interrupt mask
+ */
+ void setInterruptMask(uint16_t mask) { setInterrupts(rawInt, mask); }
+ /**
+ * Convenience function to raise a new interrupt
+ *
+ * @see setInterrupts
+ * @param ints Set of interrupts to raise
+ */
+ void raiseInterrupts(uint16_t ints) { setInterrupts(rawInt | ints, imsc); }
+ /**
+ * Convenience function to clear interrupts
+ *
+ * @see setInterrupts
+ * @param ints Set of interrupts to clear
+ */
+ void clearInterrupts(uint16_t ints) { setInterrupts(rawInt & ~ints, imsc); }
+
+ /** Masked interrupt status register */
+ const inline uint16_t maskInt() const { return rawInt & imsc; }
+
+ /** Wrapper to create an event out of the thing */
+ EventWrapper<Pl011, &Pl011::generateInterrupt> intEvent;
+
+ protected: // Registers
static const uint64_t AMBA_ID = ULL(0xb105f00d00341011);
static const int UART_DR = 0x000;
static const int UART_FR = 0x018;
@@ -76,6 +132,18 @@ class Pl011 : public Uart, public AmbaDevice
static const int UART_MIS = 0x040;
static const int UART_ICR = 0x044;
+ static const uint16_t UART_RIINTR = 1 << 0;
+ static const uint16_t UART_CTSINTR = 1 << 1;
+ static const uint16_t UART_CDCINTR = 1 << 2;
+ static const uint16_t UART_DSRINTR = 1 << 3;
+ static const uint16_t UART_RXINTR = 1 << 4;
+ static const uint16_t UART_TXINTR = 1 << 5;
+ static const uint16_t UART_RTINTR = 1 << 6;
+ static const uint16_t UART_FEINTR = 1 << 7;
+ static const uint16_t UART_PEINTR = 1 << 8;
+ static const uint16_t UART_BEINTR = 1 << 9;
+ static const uint16_t UART_OEINTR = 1 << 10;
+
uint16_t control;
/** fractional baud rate divisor. Not used for anything but reporting
@@ -94,76 +162,24 @@ class Pl011 : public Uart, public AmbaDevice
* written value */
uint16_t ifls;
- BitUnion16(INTREG)
- Bitfield<0> rimim;
- Bitfield<1> ctsmim;
- Bitfield<2> dcdmim;
- Bitfield<3> dsrmim;
- Bitfield<4> rxim;
- Bitfield<5> txim;
- Bitfield<6> rtim;
- Bitfield<7> feim;
- Bitfield<8> peim;
- Bitfield<9> beim;
- Bitfield<10> oeim;
- Bitfield<15,11> rsvd;
- EndBitUnion(INTREG)
-
/** interrupt mask register. */
- INTREG imsc;
+ uint16_t imsc;
/** raw interrupt status register */
- INTREG rawInt;
-
- /** Masked interrupt status register */
- INTREG maskInt;
-
- /** Interrupt number to generate */
- int intNum;
+ uint16_t rawInt;
+ protected: // Configuration
/** Gic to use for interrupting */
- BaseGic *gic;
+ BaseGic * const gic;
/** Should the simulation end on an EOT */
- bool endOnEOT;
-
- /** Delay before interrupting */
- Tick intDelay;
-
- /** Function to generate interrupt */
- void generateInterrupt();
-
- /** Wrapper to create an event out of the thing */
- EventWrapper<Pl011, &Pl011::generateInterrupt> intEvent;
+ const bool endOnEOT;
- public:
- typedef Pl011Params Params;
- const Params *
- params() const
- {
- return dynamic_cast<const Params *>(_params);
- }
- Pl011(const Params *p);
-
- virtual Tick read(PacketPtr pkt);
- virtual Tick write(PacketPtr pkt);
-
- /**
- * Inform the uart that there is data available.
- */
- virtual void dataAvailable();
-
-
- /**
- * Return if we have an interrupt pending
- * @return interrupt status
- * @todo fix me when implementation improves
- */
- virtual bool intStatus() { return false; }
-
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
+ /** Interrupt number to generate */
+ const int intNum;
+ /** Delay before interrupting */
+ const Tick intDelay;
};
#endif //__DEV_ARM_PL011_H__