diff options
Diffstat (limited to 'jtag_uart.c')
-rw-r--r-- | jtag_uart.c | 167 |
1 files changed, 102 insertions, 65 deletions
diff --git a/jtag_uart.c b/jtag_uart.c index ba0bf5f..5f3e9d8 100644 --- a/jtag_uart.c +++ b/jtag_uart.c @@ -9,64 +9,137 @@ * for more details. */ +#include <stdio.h> +#include <stdlib.h> + #include "nios2sim-ng.h" #include "device.h" #include "jtag_uart.h" +#define JTAG_UART_CLK_COUNT_INIT 500 + +#define jtag_uart_printf(fmt, args...) fprintf(stdout, fmt, ##args) + +struct jtag_uart_fifo { + uint8_t data; + bool has_data; +}; + +struct jtag_uart { + struct io_register regs[JTAG_UART_REG_COUNT]; + struct jtag_uart_fifo tx_fifo; + unsigned int clk_count; +}; + +static const uint32_t jtag_uart_valid_mask[JTAG_UART_REG_COUNT] = { + 0xFFFF80FF, /* data */ + 0xFFFF0703, /* control */ +}; + +static const uint32_t jtag_uart_readonly_mask[JTAG_UART_REG_COUNT] = { + 0xFFFF8000, /* data */ + 0xFFFF0300, /* control */ +}; + static int jtag_uart_init(struct device *dev) { + struct jtag_uart *ju; + struct io_register *regs; + unsigned int i; + + ju = malloc(sizeof(struct jtag_uart)); + if (unlikely(ju == NULL)) + return -1; + + /* Initialite registers */ + regs = ju->regs; + for (i = 0; i < JTAG_UART_REG_COUNT; i++) { + io_register_init(®s[i], + JTAG_UART_BASE + REG_TO_OFF(i), + jtag_uart_valid_mask[i], + jtag_uart_readonly_mask[i], + 0); + } + + /* Explicitely initialize control register */ + regs[JTAG_UART_CTRL_REG].value = + (JTAG_UART_FIFO_SIZE << JTAG_UART_CTRL_WSPACE_OFF) + & JTAG_UART_CTRL_WSPACE_MASK; + + ju->clk_count = JTAG_UART_CLK_COUNT_INIT; + dev->priv = ju; + return 0; } static bool jtag_uart_is_dev_addr(struct device *dev, uint32_t addr) { + struct jtag_uart *ju = dev->priv; + unsigned int i; + + for (i = 0; i < JTAG_UART_REG_COUNT; i++) + if (ju->regs[i].addr == addr) + return true; + + return false; +} + +static bool jtag_uart_has_irq(struct device *dev) +{ + struct jtag_uart *ju = dev->priv; + uint32_t ctrl_val; + + ju->clk_count--; + if (ju->clk_count > 0) + return false; + + ctrl_val = ju->regs[JTAG_UART_CTRL_REG].value; + + /* handle write interrupt */ + if (ctrl_val & JTAG_UART_CTRL_WE_MASK) + if ((ctrl_val & JTAG_UART_CTRL_WSPACE_MASK) != 0) + return true; + + /* TODO: Read interrupt */ + return false; } static void jtag_uart_simulate(struct device *dev) { + struct jtag_uart *ju = dev->priv; + struct io_register *regs = ju->regs; + + if (ju->tx_fifo.has_data) { + jtag_uart_printf("%c", ju->tx_fifo.data); + ju->tx_fifo.has_data = false; + /* set available fifo size */ + regs[JTAG_UART_CTRL_REG].value |= + (JTAG_UART_FIFO_SIZE << JTAG_UART_CTRL_WSPACE_OFF) + & JTAG_UART_CTRL_WSPACE_MASK; + + if (regs[JTAG_UART_CTRL_REG].value & JTAG_UART_CTRL_WE_MASK) + regs[JTAG_UART_CTRL_REG].value |= JTAG_UART_CTRL_WI_MASK; + } else { + if ((regs[JTAG_UART_CTRL_REG].value & JTAG_UART_CTRL_WSPACE_MASK) != 0 + && (regs[JTAG_UART_CTRL_REG].value & JTAG_UART_CTRL_WE_MASK)) + regs[JTAG_UART_CTRL_REG].value |= JTAG_UART_CTRL_WI_MASK; + } } struct device jtag_uart_core = { .name = "JTAG UART Core", .base = JTAG_UART_BASE, .size = JTAG_UART_SIZE, + .irq_mask = IRQ_TO_MASK(IRQ_JTAG_UART), .init = jtag_uart_init, .is_dev_addr = jtag_uart_is_dev_addr, + .has_irq = jtag_uart_has_irq, .simulate = jtag_uart_simulate, }; - #if 0 -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){ @@ -110,42 +183,6 @@ static void uart_write(struct io_device * self, uint32_t addr, uint32_t data, ui } } -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 */ |