diff options
Diffstat (limited to 'jtag_uart.c')
-rw-r--r-- | jtag_uart.c | 169 |
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 +}; + + |