summaryrefslogtreecommitdiff
path: root/jtag_uart.c
diff options
context:
space:
mode:
Diffstat (limited to 'jtag_uart.c')
-rw-r--r--jtag_uart.c167
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(&regs[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 */