summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/atmel_arm_aic.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/atmel_arm_aic.cpp')
-rw-r--r--src/devices/machine/atmel_arm_aic.cpp93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/devices/machine/atmel_arm_aic.cpp b/src/devices/machine/atmel_arm_aic.cpp
new file mode 100644
index 00000000000..2013e038cb8
--- /dev/null
+++ b/src/devices/machine/atmel_arm_aic.cpp
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+/*
+ ARM AIC (Advanced Interrupt Controller) from Atmel
+ typically integrated into the AM91SAM series of chips
+
+ see http://sam7-ex256.narod.ru/include/HTML/AT91SAM7X256_AIC.html
+ current implementation only handles basics needed for pgm2 (pgm2.cpp)
+ if this peripheral is not available as a standalone chip it could also be moved to
+ the CPU folder alongside the ARM instead
+*/
+
+#include "emu.h"
+#include "atmel_arm_aic.h"
+
+DEFINE_DEVICE_TYPE(ARM_AIC, arm_aic_device, "arm_aic", "ARM Advanced Interrupt Controller")
+
+
+DEVICE_ADDRESS_MAP_START( regs_map, 32, arm_aic_device )
+ AM_RANGE(0x000, 0x07f) AM_READWRITE(aic_smr_r, aic_smr_w) // AIC_SMR[32] (AIC_SMR) Source Mode Register
+ AM_RANGE(0x080, 0x0ff) AM_READWRITE(aic_svr_r, aic_svr_w) // AIC_SVR[32] (AIC_SVR) Source Vector Register
+ AM_RANGE(0x100, 0x103) AM_READ(irq_vector_r) // AIC_IVR IRQ Vector Register
+ AM_RANGE(0x104, 0x107) AM_READ(firq_vector_r) // AIC_FVR FIQ Vector Register
+// 0x108 AIC_ISR Interrupt Status Register
+// 0x10C AIC_IPR Interrupt Pending Register
+// 0x110 AIC_IMR Interrupt Mask Register
+// 0x114 AIC_CISR Core Interrupt Status Register
+ AM_RANGE(0x120, 0x123) AM_WRITE(aic_iecr_w) // 0x120 AIC_IECR Interrupt Enable Command Register
+ AM_RANGE(0x124, 0x127) AM_WRITE(aic_idcr_w) // 0x124 AIC_IDCR Interrupt Disable Command Register
+ AM_RANGE(0x128, 0x12b) AM_WRITE(aic_iccr_w) // 0x128 AIC_ICCR Interrupt Clear Command Register
+// 0x12C AIC_ISCR Interrupt Set Command Register
+ AM_RANGE(0x130, 0x133) AM_WRITE(aic_eoicr_w) // 0x130 AIC_EOICR End of Interrupt Command Register
+// 0x134 AIC_SPU Spurious Vector Register
+// 0x138 AIC_DCR Debug Control Register (Protect)
+// 0x140 AIC_FFER Fast Forcing Enable Register
+// 0x144 AIC_FFDR Fast Forcing Disable Register
+// 0x148 AIC_FFSR Fast Forcing Status Register
+ADDRESS_MAP_END
+
+READ32_MEMBER(arm_aic_device::irq_vector_r)
+{
+ return m_current_irq_vector;
+}
+
+READ32_MEMBER(arm_aic_device::firq_vector_r)
+{
+ return m_current_firq_vector;
+}
+
+void arm_aic_device::device_start()
+{
+ m_irq_out.resolve_safe();
+
+ save_item(NAME(m_irqs_enabled));
+ save_item(NAME(m_current_irq_vector));
+ save_item(NAME(m_current_firq_vector));
+
+ save_item(NAME(m_aic_smr));
+ save_item(NAME(m_aic_svr));
+}
+
+void arm_aic_device::device_reset()
+{
+ m_irqs_enabled = 0;
+ m_current_irq_vector = 0;
+ m_current_firq_vector = 0;
+
+ for(auto & elem : m_aic_smr) { elem = 0; }
+ for(auto & elem : m_aic_svr) { elem = 0; }
+}
+
+void arm_aic_device::set_irq(int identity)
+{
+ for (int i = 0;i < 32;i++)
+ {
+ if (m_aic_smr[i] == identity)
+ {
+ if ((m_irqs_enabled >> i) & 1)
+ {
+ m_current_irq_vector = m_aic_svr[i];
+ m_irq_out(ASSERT_LINE);
+ return;
+ }
+ }
+ }
+}
+
+WRITE32_MEMBER(arm_aic_device::aic_iccr_w)
+{
+ //logerror("%s: aic_iccr_w %08x (Interrupt Clear Command Register)\n", machine().describe_context().c_str(), data);
+ m_irq_out(CLEAR_LINE);
+};