summaryrefslogtreecommitdiff
path: root/jtag_uart.c
diff options
context:
space:
mode:
Diffstat (limited to 'jtag_uart.c')
-rw-r--r--jtag_uart.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/jtag_uart.c b/jtag_uart.c
new file mode 100644
index 0000000..052c42c
--- /dev/null
+++ b/jtag_uart.c
@@ -0,0 +1,169 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "public.h"
+#include "jtag_uart.h"
+
+static struct jtag_uart_priv priv;
+static void uart_init(struct io_device * self)
+{
+ memset(&priv, 0x00, sizeof(struct jtag_uart_priv));
+
+ if (self != NULL){
+ self->priv_data = &priv;
+ priv.regs[JTAG_UART_DATA_REG].addr = JTAG_UART_BASE_ADDR;
+ priv.regs[JTAG_UART_CTRL_REG].addr = JTAG_UART_BASE_ADDR + 4;
+ /* init control register */
+ priv.regs[JTAG_UART_CTRL_REG].value = (JTAG_UART_FIFO_SIZE) << ALTERA_JTAGUART_CONTROL_WSPACE_OFST; /* FIFO is empty */
+ }
+
+ printf("Jtag UART at 0x%08x\n",JTAG_UART_BASE_ADDR);
+}
+
+static int32_t uart_is_belong(uint32_t address)
+{
+ int32_t i = 0;
+
+ for (i=0;i<JTAG_UART_REG_COUNT;i++){
+ if (priv.regs[i].addr == address){
+ return ADDR_IS_DEV;
+ }
+ }
+ return ADDR_IS_NOT_DEV;
+}
+
+static uint32_t uart_read(struct io_device * self, uint32_t addr, uint32_t data_len)
+{
+ if (addr == priv.regs[JTAG_UART_CTRL_REG].addr){
+ return priv.regs[JTAG_UART_CTRL_REG].value;
+ }
+ else if (addr == priv.regs[JTAG_UART_DATA_REG].addr){
+ return priv.regs[JTAG_UART_DATA_REG].value;
+ }
+
+ return 0;
+}
+
+static void write_tx_fifo(uint32_t data)
+{
+ priv.tx_fifo.data = data & 0xFF;
+ priv.tx_fifo.is_write = 1;
+ /* clean WI bit */
+ priv.regs[JTAG_UART_CTRL_REG].value &= (~ALTERA_JTAGUART_CONTROL_WI_MSK);
+ /* clean write space bits */
+ priv.regs[JTAG_UART_CTRL_REG].value &= 0xFFFF;
+}
+
+static void uart_write(struct io_device * self, uint32_t addr, uint32_t data, uint32_t data_len)
+{
+ int32_t i = 0;
+
+ for (i=0;i<JTAG_UART_REG_COUNT;i++){
+ if (priv.regs[i].addr == addr){
+ if (i == JTAG_UART_DATA_REG){
+ priv.regs[i].value = io_write_data(priv.regs[i].value, data, data_len);
+ write_tx_fifo(data);
+ }
+ else if(i == JTAG_UART_CTRL_REG){
+ priv.regs[i].value |= (io_write_data(priv.regs[i].value, data, data_len) & 0x3);
+ /* if change the interrupt enable bits */
+ if (data & 0x03){
+ priv.regs[i].value = priv.regs[i].value & (~ALTERA_JTAGUART_CONTROL_WI_MSK);
+ }
+ }
+ }
+ }
+}
+
+static uint32_t jtag_trans_clk = 500;
+static int32_t jtag_uart_has_irq(struct io_device * self)
+{
+ int32_t ret_val = DEV_NO_IRQ;
+ uint32_t reg_ctrl_val = priv.regs[JTAG_UART_CTRL_REG].value;
+
+ if (jtag_trans_clk > 0){
+ jtag_trans_clk --;
+ return ret_val;
+ }
+ else {
+ jtag_trans_clk = 500;
+ }
+
+ /* handle TX write fifo empty interrupt */
+ if (reg_ctrl_val & ALTERA_JTAGUART_CONTROL_WE_MSK){
+ if ((reg_ctrl_val & ALTERA_JTAGUART_CONTROL_WSPACE_MSK) != 0){
+ ret_val = DEV_HAS_IRQ;
+ }
+ }
+
+#if 0
+ /* handle RX data available interrupt */
+ if (reg_ctrl_val & ALTERA_JTAGUART_CONTROL_RE_MSK){
+ if (reg_ctrl_val & ALTERA_JTAGUART_DATA_RVALID_MSK){
+ ret_val = DEV_HAS_IRQ;
+ priv.regs[JTAG_UART_CTRL_REG].value |= ALTERA_JTAGUART_CONTROL_RI_MSK;
+ }
+ else{
+ priv.regs[JTAG_UART_CTRL_REG].value &= (~ALTERA_JTAGUART_CONTROL_RI_MSK);
+ }
+ }
+#endif
+ return ret_val;
+}
+
+static void jtag_uart_simulate(struct io_device * self)
+{
+ /* if has data to send */
+ if (priv.tx_fifo.is_write){
+ printf("%c", priv.tx_fifo.data);
+ priv.tx_fifo.is_write = 0;
+ /* set available fifo size */
+ priv.regs[JTAG_UART_CTRL_REG].value |= (JTAG_UART_FIFO_SIZE << ALTERA_JTAGUART_CONTROL_WSPACE_OFST);
+ /* if set write interrupt enable */
+ if (priv.regs[JTAG_UART_CTRL_REG].value & ALTERA_JTAGUART_CONTROL_WE_MSK){
+ /* set write interrupt bit */
+ priv.regs[JTAG_UART_CTRL_REG].value |= ALTERA_JTAGUART_CONTROL_WI_MSK;
+ }
+ }
+ else {
+ if (priv.regs[JTAG_UART_CTRL_REG].value & (JTAG_UART_FIFO_SIZE << ALTERA_JTAGUART_CONTROL_WSPACE_OFST)){
+ /* if set write interrupt enable */
+ if (priv.regs[JTAG_UART_CTRL_REG].value & ALTERA_JTAGUART_CONTROL_WE_MSK){
+ /* set write interrupt bit */
+ priv.regs[JTAG_UART_CTRL_REG].value |= ALTERA_JTAGUART_CONTROL_WI_MSK;
+ }
+ }
+ }
+}
+
+struct io_device jtag_uart_io_device = {
+ .name = "Jtag UART Core",
+ .init = uart_init,
+ .is_belong = uart_is_belong,
+ .read_data = uart_read,
+ .write_data = uart_write,
+ .has_irq = jtag_uart_has_irq,
+ .simulate = jtag_uart_simulate,
+ .irq_enable_mask = JTAG_IRQ_MASK
+};
+
+