diff options
Diffstat (limited to 'src/devices/machine/sa1110.cpp')
-rw-r--r-- | src/devices/machine/sa1110.cpp | 761 |
1 files changed, 680 insertions, 81 deletions
diff --git a/src/devices/machine/sa1110.cpp b/src/devices/machine/sa1110.cpp index eded21499d2..218819f44ad 100644 --- a/src/devices/machine/sa1110.cpp +++ b/src/devices/machine/sa1110.cpp @@ -10,21 +10,26 @@ #include "sa1110.h" #define LOG_UNKNOWN (1 << 1) -#define LOG_UART (1 << 2) -#define LOG_UART_HF (1 << 3) -#define LOG_MCP (1 << 4) -#define LOG_SSP (1 << 5) -#define LOG_OSTIMER (1 << 6) -#define LOG_OSTIMER_HF (1 << 7) -#define LOG_RTC (1 << 8) -#define LOG_POWER (1 << 9) -#define LOG_RESET (1 << 10) -#define LOG_GPIO (1 << 11) -#define LOG_GPIO_HF (1 << 12) -#define LOG_INTC (1 << 13) -#define LOG_ALL (LOG_UNKNOWN | LOG_UART | LOG_MCP | LOG_SSP | LOG_OSTIMER | LOG_RTC | LOG_POWER | LOG_RESET | LOG_GPIO | LOG_INTC) - -#define VERBOSE (0) // (LOG_ALL) +#define LOG_ICP (1 << 2) +#define LOG_UART3 (1 << 3) +#define LOG_UART3_HF (1 << 4) +#define LOG_MCP (1 << 5) +#define LOG_SSP (1 << 6) +#define LOG_OSTIMER (1 << 7) +#define LOG_OSTIMER_HF (1 << 8) +#define LOG_RTC (1 << 9) +#define LOG_RTC_HF (1 << 10) +#define LOG_POWER (1 << 11) +#define LOG_POWER_HF (1 << 12) +#define LOG_RESET (1 << 13) +#define LOG_GPIO (1 << 14) +#define LOG_GPIO_HF (1 << 15) +#define LOG_INTC (1 << 16) +#define LOG_PPC (1 << 17) +#define LOG_DMA (1 << 18) +#define LOG_ALL (LOG_UNKNOWN | LOG_ICP | LOG_UART3 | LOG_MCP | LOG_OSTIMER | LOG_RTC | LOG_POWER | LOG_RESET | LOG_GPIO | LOG_INTC | LOG_PPC | LOG_DMA) + +#define VERBOSE (0) #include "logmacro.h" DEFINE_DEVICE_TYPE(SA1110_PERIPHERALS, sa1110_periphs_device, "sa1110_periphs", "Intel XScale SA1110 Peripherals") @@ -44,6 +49,252 @@ sa1110_periphs_device::sa1110_periphs_device(const machine_config &mconfig, cons /* + Intel SA-1110 ICP - Serial Port 2 + + pg. 264 to 288 Intel StrongARM SA-1110 Microprocessor Developer's Manual + +*/ + +TIMER_CALLBACK_MEMBER(sa1110_periphs_device::icp_rx_callback) +{ +} + +TIMER_CALLBACK_MEMBER(sa1110_periphs_device::icp_tx_callback) +{ +} + +TIMER_CALLBACK_MEMBER(sa1110_periphs_device::hssp_rx_callback) +{ +} + +TIMER_CALLBACK_MEMBER(sa1110_periphs_device::hssp_tx_callback) +{ +} + +void sa1110_periphs_device::icp_uart_set_receiver_enabled(bool enabled) +{ +} + +void sa1110_periphs_device::icp_uart_set_transmitter_enabled(bool enabled) +{ +} + +void sa1110_periphs_device::icp_uart_set_receive_irq_enabled(bool enabled) +{ +} + +void sa1110_periphs_device::icp_uart_set_transmit_irq_enabled(bool enabled) +{ +} + +uint8_t sa1110_periphs_device::icp_uart_read_receive_fifo() +{ + return 0; +} + +void sa1110_periphs_device::icp_uart_write_transmit_fifo(uint8_t data) +{ +} + +uint16_t sa1110_periphs_device::icp_hssp_read_receive_fifo() +{ + return 0; +} + +void sa1110_periphs_device::icp_hssp_write_transmit_fifo(uint8_t data) +{ +} + +void sa1110_periphs_device::icp_uart_set_receiver_idle() +{ +} + +void sa1110_periphs_device::icp_uart_begin_of_break() +{ +} + +void sa1110_periphs_device::icp_uart_end_of_break() +{ +} + + +uint32_t sa1110_periphs_device::icp_r(offs_t offset, uint32_t mem_mask) +{ + switch (offset) + { + case REG_UTCR0: + LOGMASKED(LOG_ICP, "%s: icp_r: UART Control Register 0: %08x & %08x\n", machine().describe_context(), m_icp_regs.uart.utcr[0], mem_mask); + return m_icp_regs.uart.utcr[0]; + case REG_UTCR1: + LOGMASKED(LOG_ICP, "%s: icp_r: UART Control Register 1: %08x & %08x\n", machine().describe_context(), m_icp_regs.uart.utcr[1], mem_mask); + return m_icp_regs.uart.utcr[1]; + case REG_UTCR2: + LOGMASKED(LOG_ICP, "%s: icp_r: UART Control Register 2: %08x & %08x\n", machine().describe_context(), m_icp_regs.uart.utcr[2], mem_mask); + return m_icp_regs.uart.utcr[2]; + case REG_UTCR3: + LOGMASKED(LOG_ICP, "%s: icp_r: UART Control Register 3: %08x & %08x\n", machine().describe_context(), m_icp_regs.uart.utcr[3], mem_mask); + return m_icp_regs.uart.utcr[3]; + case REG_UTCR4: + LOGMASKED(LOG_ICP, "%s: icp_r: UART Control Register 4: %08x & %08x\n", machine().describe_context(), m_icp_regs.utcr4, mem_mask); + return m_icp_regs.utcr4; + case REG_UTDR: + { + const uint8_t data = icp_uart_read_receive_fifo(); + LOGMASKED(LOG_ICP, "%s: icp_r: UART Data Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + return data; + } + case REG_UTSR0: + LOGMASKED(LOG_ICP, "%s: icp_r: UART Status Register 0: %08x & %08x\n", machine().describe_context(), m_icp_regs.uart.utsr0, mem_mask); + return m_icp_regs.uart.utsr0; + case REG_UTSR1: + LOGMASKED(LOG_ICP, "%s: icp_r: UART Status Register 1: %08x & %08x\n", machine().describe_context(), m_icp_regs.uart.utsr1, mem_mask); + return m_icp_regs.uart.utsr1; + case REG_HSCR0: + LOGMASKED(LOG_ICP, "%s: icp_r: HSSP Control Register 0: %08x & %08x\n", machine().describe_context(), m_icp_regs.hssp.hscr0, mem_mask); + return m_icp_regs.hssp.hscr0; + case REG_HSCR1: + LOGMASKED(LOG_ICP, "%s: icp_r: HSSP Control Register 1: %08x & %08x\n", machine().describe_context(), m_icp_regs.hssp.hscr1, mem_mask); + return m_icp_regs.hssp.hscr1; + case REG_HSDR: + { + const uint16_t data = icp_hssp_read_receive_fifo(); + LOGMASKED(LOG_ICP, "%s: icp_r: HSSP Data Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + return data; + } + case REG_HSSR0: + LOGMASKED(LOG_ICP, "%s: icp_r: HSSP Status Register 0: %08x & %08x\n", machine().describe_context(), m_icp_regs.hssp.hssr0, mem_mask); + return m_icp_regs.hssp.hssr0; + case REG_HSSR1: + LOGMASKED(LOG_ICP, "%s: icp_r: HSSP Status Register 1: %08x & %08x\n", machine().describe_context(), m_icp_regs.hssp.hssr1, mem_mask); + return m_icp_regs.hssp.hssr1; + default: + LOGMASKED(LOG_ICP | LOG_UNKNOWN, "%s: icp_r: Unknown address: %08x & %08x\n", machine().describe_context(), ICP_BASE_ADDR | (offset << 2), mem_mask); + return 0; + } +} + +void sa1110_periphs_device::icp_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + switch (offset) + { + case REG_UTCR0: + { + LOGMASKED(LOG_ICP, "%s: icp_w: UART Control Register 0 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_ICP, "%s: Parity Enable: %d\n", machine().describe_context(), BIT(data, 0)); + LOGMASKED(LOG_ICP, "%s: Parity Mode: %s\n", machine().describe_context(), BIT(data, 1) ? "Even" : "Odd"); + LOGMASKED(LOG_ICP, "%s: Stop Bits: %d\n", machine().describe_context(), BIT(data, 2) + 1); + LOGMASKED(LOG_ICP, "%s: Data Size: %d\n", machine().describe_context(), BIT(data, 3) ? 8 : 7); + LOGMASKED(LOG_ICP, "%s: Sample Clock: %s\n", machine().describe_context(), BIT(data, 4) ? "External" : "Internal"); + LOGMASKED(LOG_ICP, "%s: Receive Edge: %s\n", machine().describe_context(), BIT(data, 5) ? "Falling" : "Rising"); + LOGMASKED(LOG_ICP, "%s: Transmit Edge: %s\n", machine().describe_context(), BIT(data, 6) ? "Falling" : "Rising"); + + //stop_bits_t stop_bits = (BIT(data, 2) ? STOP_BITS_2 : STOP_BITS_1); + + //parity_t parity = PARITY_NONE; + //if (BIT(data, 0)) + //{ + // parity = (BIT(data, 1) ? PARITY_EVEN : PARITY_ODD); + //} + + //set_data_frame(1, BIT(data, 3) ? 8 : 7, parity, stop_bits); + //receive_register_reset(); + //transmit_register_reset(); + + COMBINE_DATA(&m_icp_regs.uart.utcr[0]); + break; + } + case REG_UTCR1: + { + LOGMASKED(LOG_ICP, "%s: icp_w: UART Control Register 1 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_ICP, "%s: Baud Rate Divisor MSB: %02x\n", machine().describe_context(), data & 0x0f); + //const uint8_t old = m_uart_regs.utcr[1] & 0x0f; + COMBINE_DATA(&m_icp_regs.uart.utcr[1]); + //if ((m_uart_regs.utcr[1] & 0x0f) != old) + // icp_uart_recalculate_divisor(); + break; + } + case REG_UTCR2: + { + LOGMASKED(LOG_ICP, "%s: icp_w: UART Control Register 2 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_ICP, "%s: Baud Rate Divisor LSB: %02x\n", machine().describe_context(), (uint8_t)data); + //const uint8_t old = m_uart_regs.utcr[2] & 0xff; + COMBINE_DATA(&m_icp_regs.uart.utcr[2]); + //if ((m_uart_regs.utcr[2] & 0xff) != old) + // icp_uart_recalculate_divisor(); + break; + } + case REG_UTCR3: + { + LOGMASKED(LOG_ICP, "%s: icp_w: UART Control Register 3 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_ICP, "%s: Receive Enable: %d\n", machine().describe_context(), BIT(data, 0)); + LOGMASKED(LOG_ICP, "%s: Transmit Enable: %d\n", machine().describe_context(), BIT(data, 1)); + LOGMASKED(LOG_ICP, "%s: Send Break: %d\n", machine().describe_context(), BIT(data, 2)); + LOGMASKED(LOG_ICP, "%s: Receive FIFO IRQ Enable: %d\n", machine().describe_context(), BIT(data, 3)); + LOGMASKED(LOG_ICP, "%s: Transmit FIFO IRQ Enable: %d\n", machine().describe_context(), BIT(data, 4)); + LOGMASKED(LOG_ICP, "%s: Loopback Enable: %d\n", machine().describe_context(), BIT(data, 5)); + const uint32_t old = m_icp_regs.uart.utcr[3]; + COMBINE_DATA(&m_icp_regs.uart.utcr[3]); + const uint32_t changed = old ^ m_icp_regs.uart.utcr[3]; + if (BIT(changed, 0)) + icp_uart_set_receiver_enabled(BIT(data, 0)); + if (BIT(changed, 1)) + icp_uart_set_transmitter_enabled(BIT(data, 1)); + if (BIT(changed, 3)) + icp_uart_set_receive_irq_enabled(BIT(data, 3)); + if (BIT(changed, 4)) + icp_uart_set_transmit_irq_enabled(BIT(data, 4)); + break; + } + case REG_UTCR4: + LOGMASKED(LOG_ICP, "%s: icp_w: UART Control Register 4 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_ICP, "%s: HP-SIR enable: %d\n", machine().describe_context(), BIT(data, UTCR4_HSE_BIT), mem_mask); + LOGMASKED(LOG_ICP, "%s: Low-Power enable: %d\n", machine().describe_context(), BIT(data, UTCR4_LPM_BIT), mem_mask); + COMBINE_DATA(&m_icp_regs.utcr4); + break; + case REG_UTDR: + LOGMASKED(LOG_ICP, "%s: icp_w: UART Data Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + if (data == 0x0d || data == 0x0a || (data >= 0x20 && data < 0x7f)) + { + printf("%c", (char)data); + } + icp_uart_write_transmit_fifo((uint8_t)data); + break; + case REG_UTSR0: + LOGMASKED(LOG_ICP, "%s: icp_w: UART Status Register 0 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_ICP, "%s: Receiver Idle Status: %d\n", machine().describe_context(), BIT(data, 2)); + LOGMASKED(LOG_ICP, "%s: Receiver Begin of Break Status: %d\n", machine().describe_context(), BIT(data, 3)); + LOGMASKED(LOG_ICP, "%s: Receiver End of Break Status: %d\n", machine().describe_context(), BIT(data, 4)); + if (BIT(data, 2)) + icp_uart_set_receiver_idle(); + if (BIT(data, 3)) + icp_uart_begin_of_break(); + if (BIT(data, 4)) + icp_uart_end_of_break(); + break; + case REG_HSCR0: + LOGMASKED(LOG_ICP, "%s: icp_w: HSSP Control Register 0 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + case REG_HSCR1: + LOGMASKED(LOG_ICP, "%s: icp_w: HSSP Control Register 1 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + case REG_HSDR: + LOGMASKED(LOG_ICP, "%s: icp_w: HSSP Data Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + icp_hssp_write_transmit_fifo((uint8_t)data); + break; + case REG_HSSR0: + LOGMASKED(LOG_ICP, "%s: icp_w: HSSP Status Register 0 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + case REG_HSSR1: + LOGMASKED(LOG_ICP, "%s: icp_w: HSSP Status Register 1 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + default: + LOGMASKED(LOG_ICP | LOG_UNKNOWN, "%s: icp_w: Unknown address: %08x = %08x & %08x\n", machine().describe_context(), ICP_BASE_ADDR | (offset << 2), data, mem_mask); + break; + } +} + +/* + Intel SA-1110 Serial Port 3 - UART pg. 289 to 306 Intel StrongARM SA-1110 Microprocessor Developer's Manual @@ -140,9 +391,6 @@ void sa1110_periphs_device::uart_write_receive_fifo(uint16_t data_and_flags) m_uart_regs.rx_fifo_count++; m_uart_regs.rx_fifo_write_idx = (m_uart_regs.rx_fifo_write_idx + 1) % ARRAY_LENGTH(m_uart_regs.rx_fifo); - // update receiver-not-full flag - m_uart_regs.utsr1 |= (1 << UTSR1_RNE_BIT); - // update error flags uart_update_eif_status(); @@ -163,18 +411,20 @@ uint8_t sa1110_periphs_device::uart_read_receive_fifo() m_uart_regs.utsr1 &= ~((1 << UTSR1_PRE_BIT) | (1 << UTSR1_FRE_BIT) | (1 << UTSR1_ROR_BIT)); m_uart_regs.utsr1 |= fifo_bottom_flags << UTSR1_PRE_BIT; } - else - { - m_uart_regs.utsr1 &= ~(1 << UTSR1_RNE_BIT); - } uart_update_eif_status(); } + uart_check_rx_fifo_service(); return data; } void sa1110_periphs_device::uart_check_rx_fifo_service() { - if (m_uart_regs.rx_fifo_count > 4 && BIT(m_uart_regs.utcr[3], UTCR3_RXE_BIT)) + if (m_uart_regs.rx_fifo_count != 0) + m_uart_regs.utsr1 |= (1 << UTSR1_RNE_BIT); + else + m_uart_regs.utsr1 &= ~(1 << UTSR1_RNE_BIT); + + if (m_uart_regs.rx_fifo_count > 4) { m_uart_regs.utsr0 |= (1 << UTSR0_RFS_BIT); if (BIT(m_uart_regs.utcr[3], UTCR3_RIE_BIT)) @@ -208,19 +458,18 @@ void sa1110_periphs_device::uart_write_transmit_fifo(uint8_t data) m_uart_regs.tx_fifo_count++; m_uart_regs.tx_fifo_write_idx = (m_uart_regs.tx_fifo_write_idx + 1) % ARRAY_LENGTH(m_uart_regs.tx_fifo); - // update transmitter-not-full flag - if (m_uart_regs.tx_fifo_count == ARRAY_LENGTH(m_uart_regs.tx_fifo)) - m_uart_regs.utsr1 &= ~(1 << UTSR1_TNF_BIT); - else - m_uart_regs.utsr1 |= (1 << UTSR1_TNF_BIT); - // update FIFO-service interrupt uart_check_tx_fifo_service(); } void sa1110_periphs_device::uart_check_tx_fifo_service() { - if (m_uart_regs.tx_fifo_count <= 4 && BIT(m_uart_regs.utcr[3], UTCR3_TXE_BIT)) + if (m_uart_regs.tx_fifo_count < ARRAY_LENGTH(m_uart_regs.tx_fifo)) + m_uart_regs.utsr1 |= (1 << UTSR1_TNF_BIT); + else + m_uart_regs.utsr1 &= ~(1 << UTSR1_TNF_BIT); + + if (m_uart_regs.tx_fifo_count <= 4) { m_uart_regs.utsr0 |= (1 << UTSR0_TFS_BIT); if (BIT(m_uart_regs.utcr[3], UTCR3_TIE_BIT)) @@ -268,18 +517,18 @@ void sa1110_periphs_device::uart_set_transmitter_enabled(bool enabled) { if (enabled) { - m_uart_regs.utsr0 |= (1 << UTSR0_TFS_BIT); - m_uart3_irqs->in_w<UART3_TFS>(1); + //m_uart_regs.utsr0 |= (1 << UTSR0_TFS_BIT); + //m_uart3_irqs->in_w<UART3_TFS>(1); - m_uart_regs.utsr1 |= (1 << UTSR1_TNF_BIT); + //m_uart_regs.utsr1 |= (1 << UTSR1_TNF_BIT); } else { - m_uart_regs.utsr0 &= ~(1 << UTSR0_TFS_BIT); - m_uart3_irqs->in_w<UART3_TFS>(0); + //m_uart_regs.utsr0 &= ~(1 << UTSR0_TFS_BIT); + //m_uart3_irqs->in_w<UART3_TFS>(0); - m_uart_regs.utsr1 &= ~(1 << UTSR1_TBY_BIT); - m_uart_regs.utsr1 &= ~(1 << UTSR1_TNF_BIT); + //m_uart_regs.utsr1 &= ~(1 << UTSR1_TBY_BIT); + //m_uart_regs.utsr1 &= ~(1 << UTSR1_TNF_BIT); m_uart_regs.tx_fifo_count = 0; m_uart_regs.tx_fifo_read_idx = 0; @@ -287,6 +536,8 @@ void sa1110_periphs_device::uart_set_transmitter_enabled(bool enabled) transmit_register_reset(); } + + uart_check_tx_fifo_service(); } void sa1110_periphs_device::uart_set_receive_irq_enabled(bool enabled) @@ -302,31 +553,31 @@ uint32_t sa1110_periphs_device::uart3_r(offs_t offset, uint32_t mem_mask) switch (offset) { case REG_UTCR0: - LOGMASKED(LOG_UART, "%s: uart3_r: UART Control Register 0: %08x & %08x\n", machine().describe_context(), m_uart_regs.utcr[0], mem_mask); + LOGMASKED(LOG_UART3, "%s: uart3_r: UART Control Register 0: %08x & %08x\n", machine().describe_context(), m_uart_regs.utcr[0], mem_mask); return m_uart_regs.utcr[0]; case REG_UTCR1: - LOGMASKED(LOG_UART, "%s: uart3_r: UART Control Register 1: %08x & %08x\n", machine().describe_context(), m_uart_regs.utcr[1], mem_mask); + LOGMASKED(LOG_UART3, "%s: uart3_r: UART Control Register 1: %08x & %08x\n", machine().describe_context(), m_uart_regs.utcr[1], mem_mask); return m_uart_regs.utcr[1]; case REG_UTCR2: - LOGMASKED(LOG_UART, "%s: uart3_r: UART Control Register 2: %08x & %08x\n", machine().describe_context(), m_uart_regs.utcr[2], mem_mask); + LOGMASKED(LOG_UART3, "%s: uart3_r: UART Control Register 2: %08x & %08x\n", machine().describe_context(), m_uart_regs.utcr[2], mem_mask); return m_uart_regs.utcr[2]; case REG_UTCR3: - LOGMASKED(LOG_UART, "%s: uart3_r: UART Control Register 3: %08x & %08x\n", machine().describe_context(), m_uart_regs.utcr[3], mem_mask); + LOGMASKED(LOG_UART3, "%s: uart3_r: UART Control Register 3: %08x & %08x\n", machine().describe_context(), m_uart_regs.utcr[3], mem_mask); return m_uart_regs.utcr[3]; case REG_UTDR: { const uint8_t data = uart_read_receive_fifo(); - LOGMASKED(LOG_UART, "%s: uart3_r: UART Data Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_UART3, "%s: uart3_r: UART Data Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); return data; } case REG_UTSR0: - LOGMASKED(LOG_UART_HF, "%s: uart3_r: UART Status Register 0: %08x & %08x\n", machine().describe_context(), m_uart_regs.utsr0, mem_mask); + LOGMASKED(LOG_UART3, "%s: uart3_r: UART Status Register 0: %08x & %08x\n", machine().describe_context(), m_uart_regs.utsr0, mem_mask); return m_uart_regs.utsr0; case REG_UTSR1: - LOGMASKED(LOG_UART_HF, "%s: uart3_r: UART Status Register 1: %08x & %08x\n", machine().describe_context(), m_uart_regs.utsr1, mem_mask); + LOGMASKED(LOG_UART3, "%s: uart3_r: UART Status Register 1: %08x & %08x\n", machine().describe_context(), m_uart_regs.utsr1, mem_mask); return m_uart_regs.utsr1; default: - LOGMASKED(LOG_UART | LOG_UNKNOWN, "%s: uart3_r: Unknown address: %08x & %08x\n", machine().describe_context(), UART_BASE_ADDR | (offset << 2), mem_mask); + LOGMASKED(LOG_UART3 | LOG_UNKNOWN, "%s: uart3_r: Unknown address: %08x & %08x\n", machine().describe_context(), UART_BASE_ADDR | (offset << 2), mem_mask); return 0; } } @@ -337,14 +588,14 @@ void sa1110_periphs_device::uart3_w(offs_t offset, uint32_t data, uint32_t mem_m { case REG_UTCR0: { - LOGMASKED(LOG_UART, "%s: uart3_w: UART Control Register 0: %08x & %08x\n", machine().describe_context(), data, mem_mask); - LOGMASKED(LOG_UART, "%s: Parity Enable: %d\n", machine().describe_context(), BIT(data, 0)); - LOGMASKED(LOG_UART, "%s: Parity Mode: %s\n", machine().describe_context(), BIT(data, 1) ? "Even" : "Odd"); - LOGMASKED(LOG_UART, "%s: Stop Bits: %d\n", machine().describe_context(), BIT(data, 2) + 1); - LOGMASKED(LOG_UART, "%s: Data Size: %d\n", machine().describe_context(), BIT(data, 3) ? 8 : 7); - LOGMASKED(LOG_UART, "%s: Sample Clock: %s\n", machine().describe_context(), BIT(data, 4) ? "External" : "Internal"); - LOGMASKED(LOG_UART, "%s: Receive Edge: %s\n", machine().describe_context(), BIT(data, 5) ? "Falling" : "Rising"); - LOGMASKED(LOG_UART, "%s: Transmit Edge: %s\n", machine().describe_context(), BIT(data, 6) ? "Falling" : "Rising"); + LOGMASKED(LOG_UART3, "%s: uart3_w: UART Control Register 0 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_UART3, "%s: Parity Enable: %d\n", machine().describe_context(), BIT(data, 0)); + LOGMASKED(LOG_UART3, "%s: Parity Mode: %s\n", machine().describe_context(), BIT(data, 1) ? "Even" : "Odd"); + LOGMASKED(LOG_UART3, "%s: Stop Bits: %d\n", machine().describe_context(), BIT(data, 2) + 1); + LOGMASKED(LOG_UART3, "%s: Data Size: %d\n", machine().describe_context(), BIT(data, 3) ? 8 : 7); + LOGMASKED(LOG_UART3, "%s: Sample Clock: %s\n", machine().describe_context(), BIT(data, 4) ? "External" : "Internal"); + LOGMASKED(LOG_UART3, "%s: Receive Edge: %s\n", machine().describe_context(), BIT(data, 5) ? "Falling" : "Rising"); + LOGMASKED(LOG_UART3, "%s: Transmit Edge: %s\n", machine().describe_context(), BIT(data, 6) ? "Falling" : "Rising"); stop_bits_t stop_bits = (BIT(data, 2) ? STOP_BITS_2 : STOP_BITS_1); @@ -363,8 +614,8 @@ void sa1110_periphs_device::uart3_w(offs_t offset, uint32_t data, uint32_t mem_m } case REG_UTCR1: { - LOGMASKED(LOG_UART, "%s: uart3_w: UART Control Register 1: %08x & %08x\n", machine().describe_context(), data, mem_mask); - LOGMASKED(LOG_UART, "%s: Baud Rate Divisor MSB: %02x\n", machine().describe_context(), data & 0x0f); + LOGMASKED(LOG_UART3, "%s: uart3_w: UART Control Register 1 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_UART3, "%s: Baud Rate Divisor MSB: %02x\n", machine().describe_context(), data & 0x0f); const uint8_t old = m_uart_regs.utcr[1] & 0x0f; COMBINE_DATA(&m_uart_regs.utcr[1]); if ((m_uart_regs.utcr[1] & 0x0f) != old) @@ -373,8 +624,8 @@ void sa1110_periphs_device::uart3_w(offs_t offset, uint32_t data, uint32_t mem_m } case REG_UTCR2: { - LOGMASKED(LOG_UART, "%s: uart3_w: UART Control Register 2: %08x & %08x\n", machine().describe_context(), data, mem_mask); - LOGMASKED(LOG_UART, "%s: Baud Rate Divisor LSB: %02x\n", machine().describe_context(), (uint8_t)data); + LOGMASKED(LOG_UART3, "%s: uart3_w: UART Control Register 2 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_UART3, "%s: Baud Rate Divisor LSB: %02x\n", machine().describe_context(), (uint8_t)data); const uint8_t old = m_uart_regs.utcr[2] & 0xff; COMBINE_DATA(&m_uart_regs.utcr[2]); if ((m_uart_regs.utcr[2] & 0xff) != old) @@ -383,13 +634,13 @@ void sa1110_periphs_device::uart3_w(offs_t offset, uint32_t data, uint32_t mem_m } case REG_UTCR3: { - LOGMASKED(LOG_UART, "%s: uart3_w: UART Control Register 3: %08x & %08x\n", machine().describe_context(), data, mem_mask); - LOGMASKED(LOG_UART, "%s: Receive Enable: %d\n", machine().describe_context(), BIT(data, 0)); - LOGMASKED(LOG_UART, "%s: Transmit Enable: %d\n", machine().describe_context(), BIT(data, 1)); - LOGMASKED(LOG_UART, "%s: Send Break: %d\n", machine().describe_context(), BIT(data, 2)); - LOGMASKED(LOG_UART, "%s: Receive FIFO IRQ Enable: %d\n", machine().describe_context(), BIT(data, 3)); - LOGMASKED(LOG_UART, "%s: Transmit FIFO IRQ Enable: %d\n", machine().describe_context(), BIT(data, 4)); - LOGMASKED(LOG_UART, "%s: Loopback Enable: %d\n", machine().describe_context(), BIT(data, 5)); + LOGMASKED(LOG_UART3, "%s: uart3_w: UART Control Register 3 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_UART3, "%s: Receive Enable: %d\n", machine().describe_context(), BIT(data, 0)); + LOGMASKED(LOG_UART3, "%s: Transmit Enable: %d\n", machine().describe_context(), BIT(data, 1)); + LOGMASKED(LOG_UART3, "%s: Send Break: %d\n", machine().describe_context(), BIT(data, 2)); + LOGMASKED(LOG_UART3, "%s: Receive FIFO IRQ Enable: %d\n", machine().describe_context(), BIT(data, 3)); + LOGMASKED(LOG_UART3, "%s: Transmit FIFO IRQ Enable: %d\n", machine().describe_context(), BIT(data, 4)); + LOGMASKED(LOG_UART3, "%s: Loopback Enable: %d\n", machine().describe_context(), BIT(data, 5)); const uint32_t old = m_uart_regs.utcr[3]; COMBINE_DATA(&m_uart_regs.utcr[3]); const uint32_t changed = old ^ m_uart_regs.utcr[3]; @@ -404,7 +655,7 @@ void sa1110_periphs_device::uart3_w(offs_t offset, uint32_t data, uint32_t mem_m break; } case REG_UTDR: - LOGMASKED(LOG_UART, "%s: uart3_w: UART Data Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_UART3, "%s: uart3_w: UART Data Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); if (data == 0x0d || data == 0x0a || (data >= 0x20 && data < 0x7f)) { printf("%c", (char)data); @@ -412,10 +663,10 @@ void sa1110_periphs_device::uart3_w(offs_t offset, uint32_t data, uint32_t mem_m uart_write_transmit_fifo((uint8_t)data); break; case REG_UTSR0: - LOGMASKED(LOG_UART, "%s: uart3_w: UART Status Register 0: %08x & %08x\n", machine().describe_context(), data, mem_mask); - LOGMASKED(LOG_UART, "%s: Receiver Idle Status: %d\n", machine().describe_context(), BIT(data, 2)); - LOGMASKED(LOG_UART, "%s: Receiver Begin of Break Status: %d\n", machine().describe_context(), BIT(data, 3)); - LOGMASKED(LOG_UART, "%s: Receiver End of Break Status: %d\n", machine().describe_context(), BIT(data, 4)); + LOGMASKED(LOG_UART3, "%s: uart3_w: UART Status Register 0 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_UART3, "%s: Receiver Idle Status: %d\n", machine().describe_context(), BIT(data, 2)); + LOGMASKED(LOG_UART3, "%s: Receiver Begin of Break Status: %d\n", machine().describe_context(), BIT(data, 3)); + LOGMASKED(LOG_UART3, "%s: Receiver End of Break Status: %d\n", machine().describe_context(), BIT(data, 4)); if (BIT(data, 2)) uart_set_receiver_idle(); if (BIT(data, 3)) @@ -424,7 +675,7 @@ void sa1110_periphs_device::uart3_w(offs_t offset, uint32_t data, uint32_t mem_m uart_end_of_break(); break; default: - LOGMASKED(LOG_UART | LOG_UNKNOWN, "%s: uart3_w: Unknown address: %08x = %08x & %08x\n", machine().describe_context(), UART_BASE_ADDR | (offset << 2), data, mem_mask); + LOGMASKED(LOG_UART3 | LOG_UNKNOWN, "%s: uart3_w: Unknown address: %08x = %08x & %08x\n", machine().describe_context(), UART_BASE_ADDR | (offset << 2), data, mem_mask); break; } } @@ -1198,7 +1449,7 @@ uint32_t sa1110_periphs_device::rtc_r(offs_t offset, uint32_t mem_mask) LOGMASKED(LOG_RTC, "%s: rtc_r: RTC Alarm Register: %08x & %08x\n", machine().describe_context(), m_rtc_regs.rtar, mem_mask); return m_rtc_regs.rtar; case REG_RCNR: - LOGMASKED(LOG_RTC, "%s: rtc_r: RTC Count Register: %08x & %08x\n", machine().describe_context(), m_rtc_regs.rcnr, mem_mask); + LOGMASKED(LOG_RTC_HF, "%s: rtc_r: RTC Count Register: %08x & %08x\n", machine().describe_context(), m_rtc_regs.rcnr, mem_mask); return m_rtc_regs.rcnr; case REG_RTTR: LOGMASKED(LOG_RTC, "%s: rtc_r: RTC Timer Trim Register: %08x & %08x\n", machine().describe_context(), m_rtc_regs.rttr, mem_mask); @@ -1276,7 +1527,7 @@ uint32_t sa1110_periphs_device::power_r(offs_t offset, uint32_t mem_mask) LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Sleep Status Register: %08x & %08x\n", machine().describe_context(), m_power_regs.pssr, mem_mask); return m_power_regs.pssr; case REG_PSPR: - LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Scratch Pad Register: %08x & %08x\n", machine().describe_context(), m_power_regs.pspr, mem_mask); + LOGMASKED(LOG_POWER_HF, "%s: power_r: Power Manager Scratch Pad Register: %08x & %08x\n", machine().describe_context(), m_power_regs.pspr, mem_mask); return m_power_regs.pspr; case REG_PWER: LOGMASKED(LOG_POWER, "%s: power_r: Power Manager Wake-up Enable Register: %08x & %08x\n", machine().describe_context(), m_power_regs.pwer, mem_mask); @@ -1312,7 +1563,7 @@ void sa1110_periphs_device::power_w(offs_t offset, uint32_t data, uint32_t mem_m m_power_regs.pssr &= ~(data & 0x0000001f); break; case REG_PSPR: - LOGMASKED(LOG_POWER, "%s: power_w: Power Manager Scratch Pad Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_POWER_HF, "%s: power_w: Power Manager Scratch Pad Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); COMBINE_DATA(&m_power_regs.pspr); break; case REG_PWER: @@ -1398,6 +1649,7 @@ void sa1110_periphs_device::gpio_in(const uint32_t line, const int state) m_gpio_regs.input_latch &= ~mask; m_gpio_regs.input_latch |= (state << line); + LOGMASKED(LOG_GPIO, "gpio_in: Line %d, state %d\n", line, state); if (old_latch != m_gpio_regs.input_latch && !BIT(m_gpio_regs.gafr, line)) { // TODO: The manual is unclear if edge detection functions on both inputs and outputs. @@ -1414,6 +1666,7 @@ void sa1110_periphs_device::gpio_in(const uint32_t line, const int state) } m_gpio_regs.gplr = (m_gpio_regs.input_latch & ~m_gpio_regs.gafr) | (m_gpio_regs.alt_input_latch & m_gpio_regs.gafr); + LOGMASKED(LOG_GPIO, "gpio_in: New GPLR: %08x\n", m_gpio_regs.gplr); } } @@ -1557,7 +1810,7 @@ void sa1110_periphs_device::gpio_w(offs_t offset, uint32_t data, uint32_t mem_ma const uint32_t old = m_gpio_regs.gedr; m_gpio_regs.gedr &= ~(data & mem_mask); if (old != m_gpio_regs.gedr) - gpio_update_interrupts(old); + gpio_update_interrupts(old ^ m_gpio_regs.gedr); break; } case REG_GAFR: @@ -1566,7 +1819,7 @@ void sa1110_periphs_device::gpio_w(offs_t offset, uint32_t data, uint32_t mem_ma const uint32_t old = m_gpio_regs.gafr; COMBINE_DATA(&m_gpio_regs.gafr); if (old != m_gpio_regs.gafr) - gpio_update_alternate_pins(old); + gpio_update_alternate_pins(old ^ m_gpio_regs.gafr); break; } default: @@ -1649,11 +1902,11 @@ void sa1110_periphs_device::intc_w(offs_t offset, uint32_t data, uint32_t mem_ma switch (offset) { case REG_ICIP: - LOGMASKED(LOG_INTC, "%s: intc_w: (Invalid Write) Interrupt Controller IRQ Pending Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_INTC, "%s: intc_w: (Invalid Write) Interrupt Controller IRQ Pending Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); break; case REG_ICMR: { - LOGMASKED(LOG_INTC, "%s: intc_w: Interrupt Controller Mask Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_INTC, "%s: intc_w: Interrupt Controller Mask Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); const uint32_t old = m_intc_regs.icmr; COMBINE_DATA(&m_intc_regs.icmr); if (old != m_intc_regs.icmr) @@ -1662,7 +1915,7 @@ void sa1110_periphs_device::intc_w(offs_t offset, uint32_t data, uint32_t mem_ma } case REG_ICLR: { - LOGMASKED(LOG_INTC, "%s: intc_w: Interrupt Controller Level Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_INTC, "%s: intc_w: Interrupt Controller Level Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); const uint32_t old = m_intc_regs.iclr; COMBINE_DATA(&m_intc_regs.iclr); if (old != m_intc_regs.iclr) @@ -1670,13 +1923,13 @@ void sa1110_periphs_device::intc_w(offs_t offset, uint32_t data, uint32_t mem_ma break; } case REG_ICFP: - LOGMASKED(LOG_INTC, "%s: intc_w: (Invalid Write) Interrupt Controller FIQ Pending Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_INTC, "%s: intc_w: (Invalid Write) Interrupt Controller FIQ Pending Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); break; case REG_ICPR: - LOGMASKED(LOG_INTC, "%s: intc_w: (Invalid Write) Interrupt Controller Pending Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_INTC, "%s: intc_w: (Invalid Write) Interrupt Controller Pending Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); break; case REG_ICCR: - LOGMASKED(LOG_INTC, "%s: intc_w: Interrupt Controller Control Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_INTC, "%s: intc_w: Interrupt Controller Control Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); m_intc_regs.iccr = BIT(data, 0); break; default: @@ -1685,8 +1938,292 @@ void sa1110_periphs_device::intc_w(offs_t offset, uint32_t data, uint32_t mem_ma } } +/* + + Intel SA-1110 Peripheral Pin Controller + + pg. 347 to 357 Intel StrongARM SA-1110 Microprocessor Developer's Manual + +*/ + +uint32_t sa1110_periphs_device::ppc_r(offs_t offset, uint32_t mem_mask) +{ + switch (offset) + { + case REG_PPDR: + LOGMASKED(LOG_PPC, "%s: ppc_r: PPC Pin Direction Register: %08x & %08x\n", machine().describe_context(), m_ppc_regs.ppdr, mem_mask); + return m_ppc_regs.ppdr; + case REG_PPSR: + LOGMASKED(LOG_PPC, "%s: ppc_r: PPC Pin State Register: %08x & %08x\n", machine().describe_context(), m_ppc_regs.ppsr, mem_mask); + return m_ppc_regs.ppsr; + case REG_PPAR: + LOGMASKED(LOG_PPC, "%s: ppc_r: PPC Pin Assignment Register: %08x & %08x\n", machine().describe_context(), m_ppc_regs.ppar, mem_mask); + return m_ppc_regs.ppar; + case REG_PSDR: + LOGMASKED(LOG_PPC, "%s: ppc_r: PPC Sleep Mode Direction Register: %08x & %08x\n", machine().describe_context(), m_ppc_regs.psdr, mem_mask); + return m_ppc_regs.psdr; + case REG_PPFR: + LOGMASKED(LOG_PPC, "%s: ppc_r: PPC Pin Flag Register: %08x & %08x\n", machine().describe_context(), m_ppc_regs.ppfr, mem_mask); + return m_ppc_regs.ppfr; + default: + LOGMASKED(LOG_PPC | LOG_UNKNOWN, "%s: ppc_r: Unknown address: %08x & %08x\n", machine().describe_context(), PPC_BASE_ADDR | (offset << 2), mem_mask); + return 0; + } +} + +void sa1110_periphs_device::ppc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + switch (offset) + { + case REG_PPDR: + { + LOGMASKED(LOG_PPC, "%s: ppc_w: PPC Pin Direction Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_ppc_regs.ppdr); + //const uint32_t old_ppsr = m_ppc_regs.ppsr; + m_ppc_regs.ppsr = (m_ppc_regs.ppsr_out & m_ppc_regs.ppdr) | (m_ppc_regs.ppsr_in & ~m_ppc_regs.ppdr); + //const uint32_t changed_states = old_ppsr ^ m_ppc_regs.ppsr; + //if (changed_states) + //{ + //} + break; + } + case REG_PPSR: + { + LOGMASKED(LOG_PPC, "%s: ppc_w: PPC Pin State Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + //const uint32_t old_latch = m_ppc_regs.ppsr_out; + COMBINE_DATA(&m_ppc_regs.ppsr_out); + m_ppc_regs.ppsr = (m_ppc_regs.ppsr_out & m_ppc_regs.ppdr) | (m_ppc_regs.ppsr_in & ~m_ppc_regs.ppdr); + //const uint32_t changed_outputs = (old ^ m_ppc_regs.ppsr_out) & m_ppc_regs.ppdr; + //if (changed_outputs) + //{ + // Do stuff + //} + break; + } + case REG_PPAR: + LOGMASKED(LOG_PPC, "%s: ppc_w: PPC Pin Assignment Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_ppc_regs.ppar); + break; + case REG_PSDR: + LOGMASKED(LOG_PPC, "%s: ppc_w: PPC Sleep Mode Direction Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_ppc_regs.psdr); + break; + case REG_PPFR: + LOGMASKED(LOG_PPC, "%s: ppc_w: PPC Pin Flag Register: %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_ppc_regs.ppfr); + break; + default: + LOGMASKED(LOG_PPC | LOG_UNKNOWN, "%s: ppc_w: Unknown address: %08x = %08x & %08x\n", machine().describe_context(), PPC_BASE_ADDR | (offset << 2), data, mem_mask); + break; + } +} + +/* + + Intel SA-1110 Peripheral Pin Controller + + pg. 186 to 194 Intel StrongARM SA-1110 Microprocessor Developer's Manual + +*/ + +void sa1110_periphs_device::dma_set_control_bits(int channel, uint32_t bits) +{ + dma_regs ®s = m_dma_regs[channel]; + const uint32_t old = regs.dsr; + regs.dsr |= bits; + const uint32_t newly_set = ~old & bits; + if (newly_set == 0) + return; + + const uint32_t irq_mask = (1 << DSR_ERROR_BIT) | (1 << DSR_DONEA_BIT) | (1 << DSR_DONEB_BIT); + + if (BIT(newly_set, DSR_RUN_BIT)) + regs.dsr &= ~(1 << DSR_ERROR_BIT); + if (BIT(newly_set, DSR_DONEA_BIT) || BIT(newly_set, DSR_STRTA_BIT)) + regs.dsr &= ~(1 << DSR_DONEA_BIT); + if (BIT(newly_set, DSR_DONEB_BIT) || BIT(newly_set, DSR_STRTB_BIT)) + regs.dsr &= ~(1 << DSR_DONEB_BIT); + + if (regs.ddar == 0x81400580 && BIT(regs.dsr, DSR_RUN_BIT)) + { + const uint32_t buf = BIT(regs.dsr, DSR_BIU_BIT); + const uint32_t count = regs.dbt[buf]; + if (count) + { + const uint32_t start_mask = (buf ? (1 << DSR_STRTB_BIT) : (1 << DSR_STRTA_BIT)); + const uint32_t done_mask = (buf ? (1 << DSR_DONEB_BIT) : (1 << DSR_DONEA_BIT)); + const uint32_t addr = regs.dbs[buf]; + address_space &space = m_maincpu->space(AS_PROGRAM); + if (regs.dsr & start_mask) + { + for (uint32_t i = 0; i < count; i++) + { + const uint8_t value = space.read_byte(addr + i); + if (value == 0x0d || value == 0x0a || (value >= 0x20 && value < 0x7f)) + { + printf("%c", (char)value); + } + } + printf("\n"); + regs.dsr &= ~start_mask; + regs.dsr |= done_mask; + regs.dsr ^= (1 << DSR_BIU_BIT); + } + } + } + + set_irq_line(INT_DMA0 + channel, (BIT(regs.dsr, DSR_IE_BIT) && (regs.dsr & irq_mask)) ? 1 : 0); +} + +void sa1110_periphs_device::dma_clear_control_bits(int channel, uint32_t bits) +{ + dma_regs ®s = m_dma_regs[channel]; + + const uint32_t irq_mask = (1 << DSR_ERROR_BIT) | (1 << DSR_DONEA_BIT) | (1 << DSR_DONEB_BIT); + + regs.dsr &= ~bits; + set_irq_line(INT_DMA0 + channel, (BIT(regs.dsr, DSR_IE_BIT) && (regs.dsr & irq_mask)) ? 1 : 0); +} + +uint32_t sa1110_periphs_device::dma_r(offs_t offset, uint32_t mem_mask) +{ + uint32_t channel = (offset >> 3) & 7; + if (channel < 6) + { + switch (offset & 7) + { + case REG_DDAR: + LOGMASKED(LOG_DMA, "%s: dma_r: DMA%d Device Address Register: %08x & %08x\n", machine().describe_context(), channel, m_dma_regs[channel].ddar, mem_mask); + return m_dma_regs[channel].ddar; + case REG_DSSR: + case REG_DCSR: + case REG_DSR: + LOGMASKED(LOG_DMA, "%s: dma_r: DMA%d Control/Status Register: %08x & %08x\n", machine().describe_context(), channel, m_dma_regs[channel].dsr, mem_mask); + return m_dma_regs[channel].dsr; + case REG_DBSA: + LOGMASKED(LOG_DMA, "%s: dma_r: DMA%d Buffer A Start Address: %08x & %08x\n", machine().describe_context(), channel, m_dma_regs[channel].dbs[0], mem_mask); + return m_dma_regs[channel].dbs[0]; + case REG_DBTA: + LOGMASKED(LOG_DMA, "%s: dma_r: DMA%d Buffer A Transfer Count: %08x & %08x\n", machine().describe_context(), channel, m_dma_regs[channel].dbt[0], mem_mask); + return m_dma_regs[channel].dbt[0]; + case REG_DBSB: + LOGMASKED(LOG_DMA, "%s: dma_r: DMA%d Buffer B Start Address: %08x & %08x\n", machine().describe_context(), channel, m_dma_regs[channel].dbs[1], mem_mask); + return m_dma_regs[channel].dbs[1]; + case REG_DBTB: + LOGMASKED(LOG_DMA, "%s: dma_r: DMA%d Buffer B Transfer Count: %08x & %08x\n", machine().describe_context(), channel, m_dma_regs[channel].dbt[1], mem_mask); + return m_dma_regs[channel].dbt[1]; + default: + LOGMASKED(LOG_DMA | LOG_UNKNOWN, "%s: dma_r: Unknown address: %08x & %08x\n", machine().describe_context(), DMA_BASE_ADDR | (offset << 2), mem_mask); + return 0; + } + } + return 0; +} + +void sa1110_periphs_device::dma_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + uint32_t channel = (offset >> 3) & 7; + if (channel < 6) + { + switch (offset & 7) + { + case REG_DDAR: + LOGMASKED(LOG_DMA, "%s: dma_w: DMA%d Device Address Register = %08x & %08x\n", machine().describe_context(), channel, data, mem_mask); + COMBINE_DATA(&m_dma_regs[channel].ddar); + break; + case REG_DSSR: + LOGMASKED(LOG_DMA, "%s: dma_w: DMA%d Control/Status Register (1S) = %08x & %08x\n", machine().describe_context(), channel, data, mem_mask); + LOGMASKED(LOG_DMA, "%s: Run Set: %d\n", machine().describe_context(), BIT(data, DSR_RUN_BIT)); + LOGMASKED(LOG_DMA, "%s: Interrupt Enable Set: %d\n", machine().describe_context(), BIT(data, DSR_IE_BIT)); + LOGMASKED(LOG_DMA, "%s: Error Set: %d\n", machine().describe_context(), BIT(data, DSR_ERROR_BIT)); + LOGMASKED(LOG_DMA, "%s: Done A Set: %d\n", machine().describe_context(), BIT(data, DSR_DONEA_BIT)); + LOGMASKED(LOG_DMA, "%s: Start A Set: %d\n", machine().describe_context(), BIT(data, DSR_STRTA_BIT)); + LOGMASKED(LOG_DMA, "%s: Done B Set: %d\n", machine().describe_context(), BIT(data, DSR_DONEB_BIT)); + LOGMASKED(LOG_DMA, "%s: Start B Set: %d\n", machine().describe_context(), BIT(data, DSR_STRTB_BIT)); + LOGMASKED(LOG_DMA, "%s: Buffer In Use Set: %d\n", machine().describe_context(), BIT(data, DSR_BIU_BIT)); + dma_set_control_bits(channel, data & mem_mask); + break; + case REG_DCSR: + LOGMASKED(LOG_DMA, "%s: dma_w: DMA%d Control/Status Register (1C) = %08x & %08x\n", machine().describe_context(), channel, data, mem_mask); + LOGMASKED(LOG_DMA, "%s: Run Clear: %d\n", machine().describe_context(), BIT(data, DSR_RUN_BIT)); + LOGMASKED(LOG_DMA, "%s: Interrupt Enable Clear: %d\n", machine().describe_context(), BIT(data, DSR_IE_BIT)); + LOGMASKED(LOG_DMA, "%s: Error Clear: %d\n", machine().describe_context(), BIT(data, DSR_ERROR_BIT)); + LOGMASKED(LOG_DMA, "%s: Done A Clear: %d\n", machine().describe_context(), BIT(data, DSR_DONEA_BIT)); + LOGMASKED(LOG_DMA, "%s: Start A Clear: %d\n", machine().describe_context(), BIT(data, DSR_STRTA_BIT)); + LOGMASKED(LOG_DMA, "%s: Done B Clear: %d\n", machine().describe_context(), BIT(data, DSR_DONEB_BIT)); + LOGMASKED(LOG_DMA, "%s: Start B Clear: %d\n", machine().describe_context(), BIT(data, DSR_STRTB_BIT)); + LOGMASKED(LOG_DMA, "%s: Buffer In Use Clear: %d\n", machine().describe_context(), BIT(data, DSR_BIU_BIT)); + dma_clear_control_bits(channel, data & mem_mask); + break; + case REG_DSR: + LOGMASKED(LOG_DMA, "%s: dma_w: DMA%d Control/Status Register (RO) = %08x & %08x\n", machine().describe_context(), channel, data, mem_mask); + break; + case REG_DBSA: + LOGMASKED(LOG_DMA, "%s: dma_w: DMA%d Buffer A Start Address = %08x & %08x\n", machine().describe_context(), channel, data, mem_mask); + if (!BIT(m_dma_regs[channel].dsr, DSR_STRTA_BIT)) + COMBINE_DATA(&m_dma_regs[channel].dbs[0]); + break; + case REG_DBTA: + LOGMASKED(LOG_DMA, "%s: dma_w: DMA%d Buffer A Transfer Count = %08x & %08x\n", machine().describe_context(), channel, data, mem_mask); + if (!BIT(m_dma_regs[channel].dsr, DSR_STRTA_BIT)) + { + COMBINE_DATA(&m_dma_regs[channel].dbt[0]); + m_dma_regs[channel].dbt[0] &= DBT_MASK; + } + break; + case REG_DBSB: + LOGMASKED(LOG_DMA, "%s: dma_w: DMA%d Buffer B Start Address = %08x & %08x\n", machine().describe_context(), channel, data, mem_mask); + if (!BIT(m_dma_regs[channel].dsr, DSR_STRTB_BIT)) + COMBINE_DATA(&m_dma_regs[channel].dbs[1]); + break; + case REG_DBTB: + LOGMASKED(LOG_DMA, "%s: dma_w: DMA%d Buffer B Transfer Count = %08x & %08x\n", machine().describe_context(), channel, data, mem_mask); + if (!BIT(m_dma_regs[channel].dsr, DSR_STRTB_BIT)) + { + COMBINE_DATA(&m_dma_regs[channel].dbt[1]); + m_dma_regs[channel].dbt[1] &= DBT_MASK; + } + break; + default: + LOGMASKED(LOG_DMA | LOG_UNKNOWN, "%s: dma_w: Unknown address %08x = %08x & %08x\n", machine().describe_context(), DMA_BASE_ADDR | (offset << 2), data, mem_mask); + break; + } + } +} + void sa1110_periphs_device::device_start() { + save_item(NAME(m_icp_regs.uart.utcr)); + save_item(NAME(m_icp_regs.uart.utsr0)); + save_item(NAME(m_icp_regs.uart.utsr1)); + save_item(NAME(m_icp_regs.uart.rx_fifo)); + save_item(NAME(m_icp_regs.uart.rx_fifo_read_idx)); + save_item(NAME(m_icp_regs.uart.rx_fifo_write_idx)); + save_item(NAME(m_icp_regs.uart.rx_fifo_count)); + m_icp_regs.uart_rx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sa1110_periphs_device::icp_rx_callback), this)); + save_item(NAME(m_icp_regs.uart.tx_fifo)); + save_item(NAME(m_icp_regs.uart.tx_fifo_read_idx)); + save_item(NAME(m_icp_regs.uart.tx_fifo_write_idx)); + save_item(NAME(m_icp_regs.uart.tx_fifo_count)); + m_icp_regs.uart_tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sa1110_periphs_device::icp_tx_callback), this)); + save_item(NAME(m_icp_regs.uart.rx_break_interlock)); + + save_item(NAME(m_icp_regs.utcr4)); + save_item(NAME(m_icp_regs.hssp.hscr0)); + save_item(NAME(m_icp_regs.hssp.hscr1)); + save_item(NAME(m_icp_regs.hssp.hssr0)); + save_item(NAME(m_icp_regs.hssp.hssr1)); + save_item(NAME(m_icp_regs.hssp.rx_fifo)); + save_item(NAME(m_icp_regs.hssp.rx_fifo_read_idx)); + save_item(NAME(m_icp_regs.hssp.rx_fifo_write_idx)); + save_item(NAME(m_icp_regs.hssp.rx_fifo_count)); + m_icp_regs.hssp.rx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sa1110_periphs_device::hssp_rx_callback), this)); + save_item(NAME(m_icp_regs.hssp.tx_fifo)); + save_item(NAME(m_icp_regs.hssp.tx_fifo_read_idx)); + save_item(NAME(m_icp_regs.hssp.tx_fifo_write_idx)); + save_item(NAME(m_icp_regs.hssp.tx_fifo_count)); + m_icp_regs.hssp.tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sa1110_periphs_device::hssp_tx_callback), this)); + save_item(NAME(m_uart_regs.utcr)); save_item(NAME(m_uart_regs.utsr0)); save_item(NAME(m_uart_regs.utsr1)); @@ -1783,6 +2320,18 @@ void sa1110_periphs_device::device_start() save_item(NAME(m_intc_regs.icfp)); save_item(NAME(m_intc_regs.icpr)); + save_item(NAME(m_ppc_regs.ppdr)); + save_item(NAME(m_ppc_regs.ppsr)); + save_item(NAME(m_ppc_regs.ppar)); + save_item(NAME(m_ppc_regs.psdr)); + save_item(NAME(m_ppc_regs.ppfr)); + + save_item(STRUCT_MEMBER(m_dma_regs, ddar)); + save_item(STRUCT_MEMBER(m_dma_regs, dsr)); + save_item(STRUCT_MEMBER(m_dma_regs, dbs)); + save_item(STRUCT_MEMBER(m_dma_regs, dbt)); + save_item(NAME(m_dma_active_mask)); + m_gpio_out.resolve_all_safe(); m_ssp_out.resolve_safe(); m_uart3_tx_out.resolve_safe(); @@ -1790,6 +2339,38 @@ void sa1110_periphs_device::device_start() void sa1110_periphs_device::device_reset() { + // init ICP + memset(m_icp_regs.uart.utcr, 0, sizeof(uint32_t) * 4); + m_icp_regs.uart.utsr0 = 0; + m_icp_regs.uart.utsr1 = 0; + memset(m_icp_regs.uart.rx_fifo, 0, sizeof(uint16_t) * 12); + m_icp_regs.uart.rx_fifo_read_idx = 0; + m_icp_regs.uart.rx_fifo_write_idx = 0; + m_icp_regs.uart.rx_fifo_count = 0; + m_icp_regs.uart_rx_timer->adjust(attotime::never); + memset(m_icp_regs.uart.tx_fifo, 0, 8); + m_icp_regs.uart.tx_fifo_read_idx = 0; + m_icp_regs.uart.tx_fifo_write_idx = 0; + m_icp_regs.uart.tx_fifo_count = 0; + m_icp_regs.uart_tx_timer->adjust(attotime::never); + m_icp_regs.uart.rx_break_interlock = false; + + m_icp_regs.utcr4 = 0; + m_icp_regs.hssp.hscr0 = 0; + m_icp_regs.hssp.hscr1 = 0; + m_icp_regs.hssp.hssr0 = 0; + m_icp_regs.hssp.hssr1 = 0; + memset(m_icp_regs.hssp.rx_fifo, 0, sizeof(uint16_t) * 8); + m_icp_regs.hssp.rx_fifo_read_idx = 0; + m_icp_regs.hssp.rx_fifo_write_idx = 0; + m_icp_regs.hssp.rx_fifo_count = 0; + m_icp_regs.hssp.rx_timer->adjust(attotime::never); + memset(m_icp_regs.hssp.tx_fifo, 0, sizeof(uint16_t) * 8); + m_icp_regs.hssp.tx_fifo_read_idx = 0; + m_icp_regs.hssp.tx_fifo_write_idx = 0; + m_icp_regs.hssp.tx_fifo_count = 0; + m_icp_regs.hssp.tx_timer->adjust(attotime::never); + // init UART3 memset(m_uart_regs.utcr, 0, sizeof(uint32_t) * 4); m_uart_regs.utsr0 = 0; @@ -1868,10 +2449,28 @@ void sa1110_periphs_device::device_reset() memset(&m_power_regs, 0, sizeof(m_power_regs)); m_power_regs.posr = 1; // flag oscillator OK + // init PPC regs + m_ppc_regs.ppdr = 0; + m_ppc_regs.ppsr = 0; + m_ppc_regs.ppar = 0; + m_ppc_regs.psdr = 0x003fffff; + m_ppc_regs.ppfr = 0x0007f001; + + // init DMA regs + for (int channel = 0; channel < 6; channel++) + { + m_dma_regs[channel].ddar = 0; + m_dma_regs[channel].dsr = 0; + memset(m_dma_regs[channel].dbs, 0, sizeof(uint32_t) * 2); + memset(m_dma_regs[channel].dbt, 0, sizeof(uint32_t) * 2); + } // bulk-init other registers m_rcsr = 0x00000001; // indicate hardware reset memset(&m_gpio_regs, 0, sizeof(m_gpio_regs)); memset(&m_intc_regs, 0, sizeof(m_intc_regs)); + + uart_check_rx_fifo_service(); + uart_check_tx_fifo_service(); } void sa1110_periphs_device::device_add_mconfig(machine_config &config) |