diff options
Diffstat (limited to 'src/devices/machine/vic_pl192.cpp')
-rw-r--r-- | src/devices/machine/vic_pl192.cpp | 347 |
1 files changed, 170 insertions, 177 deletions
diff --git a/src/devices/machine/vic_pl192.cpp b/src/devices/machine/vic_pl192.cpp index bd7c4de4e2c..c2c47549556 100644 --- a/src/devices/machine/vic_pl192.cpp +++ b/src/devices/machine/vic_pl192.cpp @@ -1,12 +1,10 @@ // license:BSD-3-Clause // copyright-holders:Devin Acker, Melissa Goad -// ARM PrimeCell PL910/PL192 VIC emulation +// ARM PrimeCell PL190/PL192 VIC emulation #include "emu.h" -#include "machine/vic_pl192.h" - -#define LOG_GENERAL (1U << 0) +#include "vic_pl192.h" #define VERBOSE (LOG_GENERAL) #include "logmacro.h" @@ -15,31 +13,181 @@ DEFINE_DEVICE_TYPE(PL190_VIC, vic_pl190_device, "vic_pl190", "ARM PL190 VIC") DEFINE_DEVICE_TYPE(UPD800468_VIC, vic_upd800468_device, "vic_upd800468", "NEC uPD800468 VIC") DEFINE_DEVICE_TYPE(PL192_VIC, vic_pl192_device, "vic_pl192", "ARM PL192 VIC") -void vic_pl190_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +vic_pl190_device::vic_pl190_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, type, tag, owner, clock) + , device_memory_interface(mconfig, *this) + , num_vectors(16) + , periph_id{0x92, 0x11, 0x04, 0x00} + , pcell_id{0x0d, 0xf0, 0x05, 0xb1} + , m_irq_sync_timer(nullptr) + , m_mmio_config("mmio", ENDIANNESS_LITTLE, 32, 32, 0) + , m_out_irq_func(*this) + , m_out_fiq_func(*this) +{ +} + +vic_pl190_device::vic_pl190_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : vic_pl190_device(mconfig, PL190_VIC, tag, owner, clock) +{ +} + +vic_upd800468_device::vic_upd800468_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : vic_pl190_device(mconfig, UPD800468_VIC, tag, owner, clock) +{ + num_vectors = 32; +} + +vic_pl192_device::vic_pl192_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : vic_pl190_device(mconfig, PL192_VIC, tag, owner, clock) +{ + num_vectors = 32; +} + +void vic_pl190_device::device_start() +{ + save_item(NAME(raw_intr)); + save_item(NAME(intr_select)); + save_item(NAME(intr_en)); + save_item(NAME(soft_intr)); + save_item(NAME(vectaddr)); + save_item(NAME(defaddress)); + save_item(NAME(vicaddress)); + save_item(NAME(priority_mask)); + save_item(NAME(priority)); + save_item(NAME(protection)); + + m_irq_sync_timer = timer_alloc(FUNC(vic_pl190_device::irq_sync_tick), this); +} + +void vic_pl192_device::device_start() +{ + vic_pl190_device::device_start(); + + save_item(NAME(sw_priority_mask)); + save_item(NAME(daisy_priority)); +} + +void vic_pl190_device::device_reset() +{ + raw_intr = intr_select = intr_en = soft_intr = 0; + defaddress = vicaddress = protection = 0; + + priority_mask = ~0; + priority = ~0; + + for(int i = 0; i < 32; i++) + { + vectaddr[i] = 0; + vectctl[i] = 0; + } +} + +void vic_pl192_device::device_reset() +{ + vic_pl190_device::device_reset(); + + sw_priority_mask = 0xffff; + daisy_priority = 0xf; + + for (int i = 0; i < 32; i++) + { + vectctl[i] = 0xf; + } +} + +device_memory_interface::space_config_vector vic_pl190_device::memory_space_config() const +{ + return space_config_vector{ + std::make_pair(0, &m_mmio_config) + }; +} + +void vic_pl190_device::map(address_map &map) +{ + map(0x000, 0x003).r(FUNC(vic_pl190_device::irq_status_r)); + map(0x004, 0x007).r(FUNC(vic_pl190_device::fiq_status_r)); + map(0x008, 0x00b).r(FUNC(vic_pl190_device::raw_intr_r)); + map(0x00c, 0x00f).rw(FUNC(vic_pl190_device::int_select_r), FUNC(vic_pl190_device::int_select_w)); + map(0x010, 0x013).rw(FUNC(vic_pl190_device::int_enable_r), FUNC(vic_pl190_device::int_enable_w)); + map(0x014, 0x017).w(FUNC(vic_pl190_device::int_en_clear_w)); + map(0x018, 0x01b).rw(FUNC(vic_pl190_device::soft_int_r), FUNC(vic_pl190_device::soft_int_w)); + map(0x01c, 0x01f).w(FUNC(vic_pl190_device::soft_int_clear_w)); + map(0x020, 0x020).rw(FUNC(vic_pl190_device::protection_r), FUNC(vic_pl190_device::protection_w)).umask32(0x000000ff); + map(0x030, 0x033).rw(FUNC(vic_pl190_device::cur_vect_addr_r), FUNC(vic_pl190_device::cur_vect_addr_w)); + map(0x034, 0x037).rw(FUNC(vic_pl190_device::def_vect_addr_r), FUNC(vic_pl190_device::def_vect_addr_w)); + map(0x100, 0x13f).rw(FUNC(vic_pl190_device::vect_addr_r), FUNC(vic_pl190_device::vect_addr_w)); + map(0x200, 0x23f).rw(FUNC(vic_pl190_device::vect_ctl_r), FUNC(vic_pl190_device::vect_ctl_w)); + map(0xfe0, 0xfe0).lr8([this](offs_t offset){ return periph_id[0]; }, "periph_id0").umask32(0x000000ff); + map(0xfe4, 0xfe4).lr8([this](offs_t offset){ return periph_id[1]; }, "periph_id1").umask32(0x000000ff); + map(0xfe8, 0xfe8).lr8([this](offs_t offset){ return periph_id[2]; }, "periph_id2").umask32(0x000000ff); + map(0xfec, 0xfec).lr8([this](offs_t offset){ return periph_id[3]; }, "periph_id3").umask32(0x000000ff); + map(0xff0, 0xff0).lr8([this](offs_t offset){ return pcell_id[0]; }, "pcell_id0").umask32(0x000000ff); + map(0xff4, 0xff4).lr8([this](offs_t offset){ return pcell_id[1]; }, "pcell_id1").umask32(0x000000ff); + map(0xff8, 0xff8).lr8([this](offs_t offset){ return pcell_id[2]; }, "pcell_id2").umask32(0x000000ff); + map(0xffc, 0xffc).lr8([this](offs_t offset){ return pcell_id[3]; }, "pcell_id3").umask32(0x000000ff); +} + +void vic_upd800468_device::map(address_map &map) +{ + vic_pl190_device::map(map); + + map(0x100, 0x17f).rw(FUNC(vic_pl190_device::vect_addr_r), FUNC(vic_pl190_device::vect_addr_w)); + map(0x200, 0x27f).rw(FUNC(vic_pl190_device::vect_ctl_r), FUNC(vic_pl190_device::vect_ctl_w)); + map(0x2c8, 0x2cb).w(FUNC(vic_upd800468_device::int_clear_w)); +} + +void vic_pl192_device::map(address_map &map) +{ + map(0x000, 0x003).r(FUNC(vic_pl190_device::irq_status_r)); + map(0x004, 0x007).r(FUNC(vic_pl190_device::fiq_status_r)); + map(0x008, 0x00b).r(FUNC(vic_pl190_device::raw_intr_r)); + map(0x00c, 0x00f).rw(FUNC(vic_pl190_device::int_select_r), FUNC(vic_pl190_device::int_select_w)); + map(0x010, 0x013).rw(FUNC(vic_pl190_device::int_enable_r), FUNC(vic_pl190_device::int_enable_w)); + map(0x014, 0x017).w(FUNC(vic_pl190_device::int_en_clear_w)); + map(0x018, 0x01b).rw(FUNC(vic_pl190_device::soft_int_r), FUNC(vic_pl190_device::soft_int_w)); + map(0x01c, 0x01f).w(FUNC(vic_pl190_device::soft_int_clear_w)); + map(0x020, 0x020).rw(FUNC(vic_pl190_device::protection_r), FUNC(vic_pl190_device::protection_w)).umask32(0x000000ff); + map(0x024, 0x025).rw(FUNC(vic_pl192_device::sw_priority_r), FUNC(vic_pl192_device::sw_priority_w)).umask32(0x0000ffff); + map(0x028, 0x028).rw(FUNC(vic_pl192_device::daisy_priority_r), FUNC(vic_pl192_device::daisy_priority_w)).umask32(0x000000ff); + map(0x100, 0x17f).rw(FUNC(vic_pl190_device::vect_addr_r), FUNC(vic_pl190_device::vect_addr_w)); + map(0x200, 0x27f).rw(FUNC(vic_pl190_device::vect_ctl_r), FUNC(vic_pl190_device::vect_ctl_w)); + map(0xf00, 0xf03).rw(FUNC(vic_pl190_device::cur_vect_addr_r), FUNC(vic_pl190_device::cur_vect_addr_w)); + map(0xfe0, 0xfe0).lr8([this](offs_t offset) { return periph_id[0]; }, "periph_id0").umask32(0x000000ff); + map(0xfe4, 0xfe4).lr8([this](offs_t offset) { return periph_id[1]; }, "periph_id1").umask32(0x000000ff); + map(0xfe8, 0xfe8).lr8([this](offs_t offset) { return periph_id[2]; }, "periph_id2").umask32(0x000000ff); + map(0xfec, 0xfec).lr8([this](offs_t offset) { return periph_id[3]; }, "periph_id3").umask32(0x000000ff); + map(0xff0, 0xff0).lr8([this](offs_t offset) { return pcell_id[0]; }, "pcell_id0").umask32(0x000000ff); + map(0xff4, 0xff4).lr8([this](offs_t offset) { return pcell_id[1]; }, "pcell_id1").umask32(0x000000ff); + map(0xff8, 0xff8).lr8([this](offs_t offset) { return pcell_id[2]; }, "pcell_id2").umask32(0x000000ff); + map(0xffc, 0xffc).lr8([this](offs_t offset) { return pcell_id[3]; }, "pcell_id3").umask32(0x000000ff); +} + +TIMER_CALLBACK_MEMBER(vic_pl190_device::irq_sync_tick) { u32 intrs = (raw_intr | soft_intr) & intr_en; - if (intrs & intr_select) m_out_fiq_func(1); - else m_out_fiq_func(0); + if (intrs & intr_select) + m_out_fiq_func(1); + else + m_out_fiq_func(0); - if (intrs & ~intr_select & priority_mask) m_out_irq_func(1); - else m_out_irq_func(0); + if (intrs & ~intr_select & priority_mask) + m_out_irq_func(1); + else + m_out_irq_func(0); } void vic_pl190_device::set_irq_line(int irq, int state) { u32 mask = (1 << irq); - if(state) - { + if (state) raw_intr |= mask; - } else - { raw_intr &= ~mask; - } - timer_set(attotime::zero, TIMER_CHECK_IRQ); + + m_irq_sync_timer->adjust(attotime::zero); } u32 vic_pl190_device::irq_status_r() @@ -65,7 +213,7 @@ u32 vic_pl190_device::int_select_r() void vic_pl190_device::int_select_w(u32 data) { intr_select = data; - timer_set(attotime::zero, TIMER_CHECK_IRQ); + m_irq_sync_timer->adjust(attotime::zero); } u32 vic_pl190_device::int_enable_r() @@ -76,13 +224,13 @@ u32 vic_pl190_device::int_enable_r() void vic_pl190_device::int_enable_w(u32 data) { intr_en |= data; - timer_set(attotime::zero, TIMER_CHECK_IRQ); + m_irq_sync_timer->adjust(attotime::zero); } void vic_pl190_device::int_en_clear_w(u32 data) { intr_en &= ~data; - timer_set(attotime::zero, TIMER_CHECK_IRQ); + m_irq_sync_timer->adjust(attotime::zero); } u32 vic_pl190_device::soft_int_r() @@ -93,13 +241,13 @@ u32 vic_pl190_device::soft_int_r() void vic_pl190_device::soft_int_w(u32 data) { soft_intr |= data; - timer_set(attotime::zero, TIMER_CHECK_IRQ); + m_irq_sync_timer->adjust(attotime::zero); } void vic_pl190_device::soft_int_clear_w(u32 data) { soft_intr &= ~data; - timer_set(attotime::zero, TIMER_CHECK_IRQ); + m_irq_sync_timer->adjust(attotime::zero); } u8 vic_pl190_device::protection_r() @@ -124,7 +272,7 @@ void vic_pl190_device::cur_vect_addr_w(u32 data) { priority_mask = ~0; priority = ~0; - timer_set(attotime::zero, TIMER_CHECK_IRQ); + m_irq_sync_timer->adjust(attotime::zero); } u32 vic_pl190_device::def_vect_addr_r() @@ -194,114 +342,12 @@ void vic_pl190_device::update_vector() vicaddress = defaddress; } -void vic_pl190_device::map(address_map &map) -{ - map(0x000, 0x003).r(FUNC(vic_pl190_device::irq_status_r)); - map(0x004, 0x007).r(FUNC(vic_pl190_device::fiq_status_r)); - map(0x008, 0x00b).r(FUNC(vic_pl190_device::raw_intr_r)); - map(0x00c, 0x00f).rw(FUNC(vic_pl190_device::int_select_r), FUNC(vic_pl190_device::int_select_w)); - map(0x010, 0x013).rw(FUNC(vic_pl190_device::int_enable_r), FUNC(vic_pl190_device::int_enable_w)); - map(0x014, 0x017).w(FUNC(vic_pl190_device::int_en_clear_w)); - map(0x018, 0x01b).rw(FUNC(vic_pl190_device::soft_int_r), FUNC(vic_pl190_device::soft_int_w)); - map(0x01c, 0x01f).w(FUNC(vic_pl190_device::soft_int_clear_w)); - map(0x020, 0x020).rw(FUNC(vic_pl190_device::protection_r), FUNC(vic_pl190_device::protection_w)).umask32(0x000000ff); - map(0x030, 0x033).rw(FUNC(vic_pl190_device::cur_vect_addr_r), FUNC(vic_pl190_device::cur_vect_addr_w)); - map(0x034, 0x037).rw(FUNC(vic_pl190_device::def_vect_addr_r), FUNC(vic_pl190_device::def_vect_addr_w)); - map(0x100, 0x13f).rw(FUNC(vic_pl190_device::vect_addr_r), FUNC(vic_pl190_device::vect_addr_w)); - map(0x200, 0x23f).rw(FUNC(vic_pl190_device::vect_ctl_r), FUNC(vic_pl190_device::vect_ctl_w)); - map(0xfe0, 0xfe0).lr8([this](offs_t offset){ return periph_id[0]; }, "periph_id0").umask32(0x000000ff); - map(0xfe4, 0xfe4).lr8([this](offs_t offset){ return periph_id[1]; }, "periph_id1").umask32(0x000000ff); - map(0xfe8, 0xfe8).lr8([this](offs_t offset){ return periph_id[2]; }, "periph_id2").umask32(0x000000ff); - map(0xfec, 0xfec).lr8([this](offs_t offset){ return periph_id[3]; }, "periph_id3").umask32(0x000000ff); - map(0xff0, 0xff0).lr8([this](offs_t offset){ return pcell_id[0]; }, "pcell_id0").umask32(0x000000ff); - map(0xff4, 0xff4).lr8([this](offs_t offset){ return pcell_id[1]; }, "pcell_id1").umask32(0x000000ff); - map(0xff8, 0xff8).lr8([this](offs_t offset){ return pcell_id[2]; }, "pcell_id2").umask32(0x000000ff); - map(0xffc, 0xffc).lr8([this](offs_t offset){ return pcell_id[3]; }, "pcell_id3").umask32(0x000000ff); -} - -device_memory_interface::space_config_vector vic_pl190_device::memory_space_config() const -{ - return space_config_vector{ - std::make_pair(0, &m_mmio_config) - }; -} - -void vic_pl190_device::device_resolve_objects() -{ - // resolve callbacks - m_out_irq_func.resolve_safe(); - m_out_fiq_func.resolve_safe(); -} - -void vic_pl190_device::device_start() -{ - save_item(NAME(raw_intr)); - save_item(NAME(intr_select)); - save_item(NAME(intr_en)); - save_item(NAME(soft_intr)); - save_item(NAME(vectaddr)); - save_item(NAME(defaddress)); - save_item(NAME(vicaddress)); - save_item(NAME(priority_mask)); - save_item(NAME(priority)); - save_item(NAME(protection)); -} - -void vic_pl190_device::device_reset() -{ - raw_intr = intr_select = intr_en = soft_intr = 0; - defaddress = vicaddress = protection = 0; - - priority_mask = ~0; - priority = ~0; - - for(int i = 0; i < 32; i++) - { - vectaddr[i] = 0; - vectctl[i] = 0; - } -} - -vic_pl190_device::vic_pl190_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock) - , device_memory_interface(mconfig, *this) - , num_vectors(16) - , periph_id{0x92, 0x11, 0x04, 0x00} - , pcell_id{0x0d, 0xf0, 0x05, 0xb1} - , m_mmio_config("mmio", ENDIANNESS_LITTLE, 32, 32, 0) - , m_out_irq_func(*this) - , m_out_fiq_func(*this) -{ -} - -vic_pl190_device::vic_pl190_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : vic_pl190_device(mconfig, PL190_VIC, tag, owner, clock) -{ -} - - - - void vic_upd800468_device::int_clear_w(u32 data) { raw_intr &= ~data; - timer_set(attotime::zero, TIMER_CHECK_IRQ); + m_irq_sync_timer->adjust(attotime::zero); } -void vic_upd800468_device::map(address_map &map) -{ - vic_pl190_device::map(map); - - map(0x100, 0x17f).rw(FUNC(vic_pl190_device::vect_addr_r), FUNC(vic_pl190_device::vect_addr_w)); - map(0x200, 0x27f).rw(FUNC(vic_pl190_device::vect_ctl_r), FUNC(vic_pl190_device::vect_ctl_w)); - map(0x2c8, 0x2cb).w(FUNC(vic_upd800468_device::int_clear_w)); -} - -vic_upd800468_device::vic_upd800468_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : vic_pl190_device(mconfig, UPD800468_VIC, tag, owner, clock) -{ - num_vectors = 32; -} @@ -354,56 +400,3 @@ void vic_pl192_device::update_vector() } priority_mask = newmask; } - -void vic_pl192_device::map(address_map &map) -{ - map(0x000, 0x003).r(FUNC(vic_pl190_device::irq_status_r)); - map(0x004, 0x007).r(FUNC(vic_pl190_device::fiq_status_r)); - map(0x008, 0x00b).r(FUNC(vic_pl190_device::raw_intr_r)); - map(0x00c, 0x00f).rw(FUNC(vic_pl190_device::int_select_r), FUNC(vic_pl190_device::int_select_w)); - map(0x010, 0x013).rw(FUNC(vic_pl190_device::int_enable_r), FUNC(vic_pl190_device::int_enable_w)); - map(0x014, 0x017).w(FUNC(vic_pl190_device::int_en_clear_w)); - map(0x018, 0x01b).rw(FUNC(vic_pl190_device::soft_int_r), FUNC(vic_pl190_device::soft_int_w)); - map(0x01c, 0x01f).w(FUNC(vic_pl190_device::soft_int_clear_w)); - map(0x020, 0x020).rw(FUNC(vic_pl190_device::protection_r), FUNC(vic_pl190_device::protection_w)).umask32(0x000000ff); - map(0x024, 0x025).rw(FUNC(vic_pl192_device::sw_priority_r), FUNC(vic_pl192_device::sw_priority_w)).umask32(0x0000ffff); - map(0x028, 0x028).rw(FUNC(vic_pl192_device::daisy_priority_r), FUNC(vic_pl192_device::daisy_priority_w)).umask32(0x000000ff); - map(0x100, 0x17f).rw(FUNC(vic_pl190_device::vect_addr_r), FUNC(vic_pl190_device::vect_addr_w)); - map(0x200, 0x27f).rw(FUNC(vic_pl190_device::vect_ctl_r), FUNC(vic_pl190_device::vect_ctl_w)); - map(0xf00, 0xf03).rw(FUNC(vic_pl190_device::cur_vect_addr_r), FUNC(vic_pl190_device::cur_vect_addr_w)); - map(0xfe0, 0xfe0).lr8([this](offs_t offset) { return periph_id[0]; }, "periph_id0").umask32(0x000000ff); - map(0xfe4, 0xfe4).lr8([this](offs_t offset) { return periph_id[1]; }, "periph_id1").umask32(0x000000ff); - map(0xfe8, 0xfe8).lr8([this](offs_t offset) { return periph_id[2]; }, "periph_id2").umask32(0x000000ff); - map(0xfec, 0xfec).lr8([this](offs_t offset) { return periph_id[3]; }, "periph_id3").umask32(0x000000ff); - map(0xff0, 0xff0).lr8([this](offs_t offset) { return pcell_id[0]; }, "pcell_id0").umask32(0x000000ff); - map(0xff4, 0xff4).lr8([this](offs_t offset) { return pcell_id[1]; }, "pcell_id1").umask32(0x000000ff); - map(0xff8, 0xff8).lr8([this](offs_t offset) { return pcell_id[2]; }, "pcell_id2").umask32(0x000000ff); - map(0xffc, 0xffc).lr8([this](offs_t offset) { return pcell_id[3]; }, "pcell_id3").umask32(0x000000ff); -} - -void vic_pl192_device::device_start() -{ - vic_pl190_device::device_start(); - - save_item(NAME(sw_priority_mask)); - save_item(NAME(daisy_priority)); -} - -void vic_pl192_device::device_reset() -{ - vic_pl190_device::device_start(); - - sw_priority_mask = 0xffff; - daisy_priority = 0xf; - - for (int i = 0; i < 32; i++) - { - vectctl[i] = 0xf; - } -} - -vic_pl192_device::vic_pl192_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : vic_pl190_device(mconfig, PL192_VIC, tag, owner, clock) -{ - num_vectors = 32; -} |