diff options
-rw-r--r-- | drivers/tty/serial/sirfsoc_uart.c | 341 | ||||
-rw-r--r-- | drivers/tty/serial/sirfsoc_uart.h | 20 |
2 files changed, 135 insertions, 226 deletions
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c index 6b1c92c1c27f..b6116413ca0d 100644 --- a/drivers/tty/serial/sirfsoc_uart.c +++ b/drivers/tty/serial/sirfsoc_uart.c @@ -36,8 +36,6 @@ sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count); static struct uart_driver sirfsoc_uart_drv; static void sirfsoc_uart_tx_dma_complete_callback(void *param); -static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port); -static void sirfsoc_uart_rx_dma_complete_callback(void *param); static const struct sirfsoc_baudrate_to_regv baudrate_to_regv[] = { {4000000, 2359296}, {3500000, 1310721}, @@ -465,144 +463,6 @@ static void sirfsoc_uart_tx_dma_complete_callback(void *param) spin_unlock_irqrestore(&port->lock, flags); } -static void sirfsoc_uart_insert_rx_buf_to_tty( - struct sirfsoc_uart_port *sirfport, int count) -{ - struct uart_port *port = &sirfport->port; - struct tty_port *tport = &port->state->port; - int inserted; - - inserted = tty_insert_flip_string(tport, - sirfport->rx_dma_items[sirfport->rx_completed].xmit.buf, count); - port->icount.rx += inserted; -} - -static void sirfsoc_rx_submit_one_dma_desc(struct uart_port *port, int index) -{ - struct sirfsoc_uart_port *sirfport = to_sirfport(port); - - sirfport->rx_dma_items[index].xmit.tail = - sirfport->rx_dma_items[index].xmit.head = 0; - sirfport->rx_dma_items[index].desc = - dmaengine_prep_slave_single(sirfport->rx_dma_chan, - sirfport->rx_dma_items[index].dma_addr, SIRFSOC_RX_DMA_BUF_SIZE, - DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); - if (IS_ERR_OR_NULL(sirfport->rx_dma_items[index].desc)) { - dev_err(port->dev, "DMA slave single fail\n"); - return; - } - sirfport->rx_dma_items[index].desc->callback = - sirfsoc_uart_rx_dma_complete_callback; - sirfport->rx_dma_items[index].desc->callback_param = sirfport; - sirfport->rx_dma_items[index].cookie = - dmaengine_submit(sirfport->rx_dma_items[index].desc); - dma_async_issue_pending(sirfport->rx_dma_chan); -} - -static void sirfsoc_rx_tmo_process_tl(unsigned long param) -{ - struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param; - struct uart_port *port = &sirfport->port; - struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; - struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; - struct sirfsoc_int_status *uint_st = &sirfport->uart_reg->uart_int_st; - unsigned int count; - struct dma_tx_state tx_state; - unsigned long flags; - int i = 0; - - spin_lock_irqsave(&port->lock, flags); - while (DMA_COMPLETE == dmaengine_tx_status(sirfport->rx_dma_chan, - sirfport->rx_dma_items[sirfport->rx_completed].cookie, - &tx_state)) { - sirfsoc_uart_insert_rx_buf_to_tty(sirfport, - SIRFSOC_RX_DMA_BUF_SIZE); - sirfport->rx_completed++; - sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT; - i++; - if (i > SIRFSOC_RX_LOOP_BUF_CNT) - break; - } - count = CIRC_CNT(sirfport->rx_dma_items[sirfport->rx_issued].xmit.head, - sirfport->rx_dma_items[sirfport->rx_issued].xmit.tail, - SIRFSOC_RX_DMA_BUF_SIZE); - if (count > 0) - sirfsoc_uart_insert_rx_buf_to_tty(sirfport, count); - wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, - rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | - SIRFUART_IO_MODE); - sirfsoc_uart_pio_rx_chars(port, 4 - sirfport->rx_io_count); - if (sirfport->rx_io_count == 4) { - sirfport->rx_io_count = 0; - wr_regl(port, ureg->sirfsoc_int_st_reg, - uint_st->sirfsoc_rx_done); - if (!sirfport->is_atlas7) - wr_regl(port, ureg->sirfsoc_int_en_reg, - rd_regl(port, ureg->sirfsoc_int_en_reg) & - ~(uint_en->sirfsoc_rx_done_en)); - else - wr_regl(port, ureg->sirfsoc_int_en_clr_reg, - uint_en->sirfsoc_rx_done_en); - sirfsoc_uart_start_next_rx_dma(port); - } else { - wr_regl(port, ureg->sirfsoc_int_st_reg, - uint_st->sirfsoc_rx_done); - if (!sirfport->is_atlas7) - wr_regl(port, ureg->sirfsoc_int_en_reg, - rd_regl(port, ureg->sirfsoc_int_en_reg) | - (uint_en->sirfsoc_rx_done_en)); - else - wr_regl(port, ureg->sirfsoc_int_en_reg, - uint_en->sirfsoc_rx_done_en); - } - spin_unlock_irqrestore(&port->lock, flags); - tty_flip_buffer_push(&port->state->port); -} - -static void sirfsoc_uart_handle_rx_tmo(struct sirfsoc_uart_port *sirfport) -{ - struct uart_port *port = &sirfport->port; - struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; - struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; - struct dma_tx_state tx_state; - dmaengine_tx_status(sirfport->rx_dma_chan, - sirfport->rx_dma_items[sirfport->rx_issued].cookie, &tx_state); - dmaengine_terminate_all(sirfport->rx_dma_chan); - sirfport->rx_dma_items[sirfport->rx_issued].xmit.head = - SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue; - if (!sirfport->is_atlas7) - wr_regl(port, ureg->sirfsoc_int_en_reg, - rd_regl(port, ureg->sirfsoc_int_en_reg) & - ~(uint_en->sirfsoc_rx_timeout_en)); - else - wr_regl(port, ureg->sirfsoc_int_en_clr_reg, - uint_en->sirfsoc_rx_timeout_en); - tasklet_schedule(&sirfport->rx_tmo_process_tasklet); -} - -static void sirfsoc_uart_handle_rx_done(struct sirfsoc_uart_port *sirfport) -{ - struct uart_port *port = &sirfport->port; - struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; - struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; - struct sirfsoc_int_status *uint_st = &sirfport->uart_reg->uart_int_st; - - sirfsoc_uart_pio_rx_chars(port, 4 - sirfport->rx_io_count); - if (sirfport->rx_io_count == 4) { - sirfport->rx_io_count = 0; - if (!sirfport->is_atlas7) - wr_regl(port, ureg->sirfsoc_int_en_reg, - rd_regl(port, ureg->sirfsoc_int_en_reg) & - ~(uint_en->sirfsoc_rx_done_en)); - else - wr_regl(port, ureg->sirfsoc_int_en_clr_reg, - uint_en->sirfsoc_rx_done_en); - wr_regl(port, ureg->sirfsoc_int_st_reg, - uint_st->sirfsoc_rx_timeout); - sirfsoc_uart_start_next_rx_dma(port); - } -} - static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id) { unsigned long intr_status; @@ -659,12 +519,8 @@ recv_char: uart_handle_cts_change(port, cts_status); wake_up_interruptible(&state->port.delta_msr_wait); } - if (sirfport->rx_dma_chan) { - if (intr_status & uint_st->sirfsoc_rx_timeout) - sirfsoc_uart_handle_rx_tmo(sirfport); - if (intr_status & uint_st->sirfsoc_rx_done) - sirfsoc_uart_handle_rx_done(sirfport); - } else if (intr_status & SIRFUART_RX_IO_INT_ST(uint_st)) { + if (!sirfport->rx_dma_chan && + (intr_status & SIRFUART_RX_IO_INT_ST(uint_st))) { /* * chip will trigger continuous RX_TIMEOUT interrupt * in RXFIFO empty and not trigger if RXFIFO recevice @@ -734,47 +590,8 @@ recv_char: return IRQ_HANDLED; } -static void sirfsoc_uart_rx_dma_complete_tl(unsigned long param) -{ - struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param; - struct uart_port *port = &sirfport->port; - struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; - struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; - struct dma_tx_state tx_state; - unsigned long flags; - int i = 0; - - spin_lock_irqsave(&port->lock, flags); - while (DMA_COMPLETE == dmaengine_tx_status(sirfport->rx_dma_chan, - sirfport->rx_dma_items[sirfport->rx_completed].cookie, - &tx_state)) { - sirfsoc_uart_insert_rx_buf_to_tty(sirfport, - SIRFSOC_RX_DMA_BUF_SIZE); - if (rd_regl(port, ureg->sirfsoc_int_en_reg) & - uint_en->sirfsoc_rx_timeout_en) - sirfsoc_rx_submit_one_dma_desc(port, - sirfport->rx_completed++); - else - sirfport->rx_completed++; - sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT; - i++; - if (i > SIRFSOC_RX_LOOP_BUF_CNT) - break; - } - spin_unlock_irqrestore(&port->lock, flags); - tty_flip_buffer_push(&port->state->port); -} - static void sirfsoc_uart_rx_dma_complete_callback(void *param) { - struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param; - unsigned long flags; - - spin_lock_irqsave(&sirfport->port.lock, flags); - sirfport->rx_issued++; - sirfport->rx_issued %= SIRFSOC_RX_LOOP_BUF_CNT; - tasklet_schedule(&sirfport->rx_dma_complete_tasklet); - spin_unlock_irqrestore(&sirfport->port.lock, flags); } /* submit rx dma task into dmaengine */ @@ -783,14 +600,27 @@ static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port) struct sirfsoc_uart_port *sirfport = to_sirfport(port); struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; - int i; sirfport->rx_io_count = 0; wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) & ~SIRFUART_IO_MODE); - for (i = 0; i < SIRFSOC_RX_LOOP_BUF_CNT; i++) - sirfsoc_rx_submit_one_dma_desc(port, i); - sirfport->rx_completed = sirfport->rx_issued = 0; + sirfport->rx_dma_items.xmit.tail = + sirfport->rx_dma_items.xmit.head = 0; + sirfport->rx_dma_items.desc = + dmaengine_prep_dma_cyclic(sirfport->rx_dma_chan, + sirfport->rx_dma_items.dma_addr, SIRFSOC_RX_DMA_BUF_SIZE, + SIRFSOC_RX_DMA_BUF_SIZE / 2, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); + if (IS_ERR_OR_NULL(sirfport->rx_dma_items.desc)) { + dev_err(port->dev, "DMA slave single fail\n"); + return; + } + sirfport->rx_dma_items.desc->callback = + sirfsoc_uart_rx_dma_complete_callback; + sirfport->rx_dma_items.desc->callback_param = sirfport; + sirfport->rx_dma_items.cookie = + dmaengine_submit(sirfport->rx_dma_items.desc); + dma_async_issue_pending(sirfport->rx_dma_chan); if (!sirfport->is_atlas7) wr_regl(port, ureg->sirfsoc_int_en_reg, rd_regl(port, ureg->sirfsoc_int_en_reg) | @@ -1059,6 +889,7 @@ static void sirfsoc_uart_set_termios(struct uart_port *port, wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_DMA_MODE); else wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_IO_MODE); + sirfport->rx_period_time = 20000000; /* Reset Rx/Tx FIFO Threshold level for proper baudrate */ if (set_baud < 1000000) threshold_div = 1; @@ -1110,6 +941,9 @@ static int sirfsoc_uart_startup(struct uart_port *port) wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | SIRFUART_IO_MODE); + wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, + rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) & + ~SIRFUART_RX_DMA_FLUSH); wr_regl(port, ureg->sirfsoc_tx_dma_io_len, 0); wr_regl(port, ureg->sirfsoc_rx_dma_io_len, 0); wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_RX_EN | SIRFUART_TX_EN); @@ -1147,8 +981,16 @@ static int sirfsoc_uart_startup(struct uart_port *port) goto init_rx_err; } } - enable_irq(port->irq); + if (sirfport->rx_dma_chan && !sirfport->is_hrt_enabled) { + sirfport->is_hrt_enabled = true; + sirfport->rx_period_time = 20000000; + sirfport->rx_dma_items.xmit.tail = + sirfport->rx_dma_items.xmit.head = 0; + hrtimer_start(&sirfport->hrt, + ns_to_ktime(sirfport->rx_period_time), + HRTIMER_MODE_REL); + } return 0; init_rx_err: @@ -1176,6 +1018,13 @@ static void sirfsoc_uart_shutdown(struct uart_port *port) } if (sirfport->tx_dma_chan) sirfport->tx_dma_state = TX_DMA_IDLE; + if (sirfport->rx_dma_chan && sirfport->is_hrt_enabled) { + while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) & + SIRFUART_RX_FIFO_MASK) > 0) + ; + sirfport->is_hrt_enabled = false; + hrtimer_cancel(&sirfport->hrt); + } } static const char *sirfsoc_uart_type(struct uart_port *port) @@ -1310,6 +1159,70 @@ static struct uart_driver sirfsoc_uart_drv = { #endif }; +static enum hrtimer_restart + sirfsoc_uart_rx_dma_hrtimer_callback(struct hrtimer *hrt) +{ + struct sirfsoc_uart_port *sirfport; + struct uart_port *port; + int count, inserted; + struct dma_tx_state tx_state; + struct tty_struct *tty; + struct sirfsoc_register *ureg; + struct circ_buf *xmit; + + sirfport = container_of(hrt, struct sirfsoc_uart_port, hrt); + port = &sirfport->port; + inserted = 0; + tty = port->state->port.tty; + ureg = &sirfport->uart_reg->uart_reg; + xmit = &sirfport->rx_dma_items.xmit; + dmaengine_tx_status(sirfport->rx_dma_chan, + sirfport->rx_dma_items.cookie, &tx_state); + xmit->head = SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue; + count = CIRC_CNT_TO_END(xmit->head, xmit->tail, + SIRFSOC_RX_DMA_BUF_SIZE); + while (count > 0) { + inserted = tty_insert_flip_string(tty->port, + (const unsigned char *)&xmit->buf[xmit->tail], count); + if (!inserted) + goto next_hrt; + port->icount.rx += inserted; + xmit->tail = (xmit->tail + inserted) & + (SIRFSOC_RX_DMA_BUF_SIZE - 1); + count = CIRC_CNT_TO_END(xmit->head, xmit->tail, + SIRFSOC_RX_DMA_BUF_SIZE); + tty_flip_buffer_push(tty->port); + } + /* + * if RX DMA buffer data have all push into tty buffer, and there is + * only little data(less than a dma transfer unit) left in rxfifo, + * fetch it out in pio mode and switch back to dma immediately + */ + if (!inserted && !count && + ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) & + SIRFUART_RX_FIFO_MASK) > 0)) { + /* switch to pio mode */ + wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, + rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | + SIRFUART_IO_MODE); + while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) & + SIRFUART_RX_FIFO_MASK) > 0) { + if (sirfsoc_uart_pio_rx_chars(port, 16) > 0) + tty_flip_buffer_push(tty->port); + } + wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET); + wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0); + wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START); + /* switch back to dma mode */ + wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, + rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) & + ~SIRFUART_IO_MODE); + } +next_hrt: + hrtimer_forward_now(hrt, ns_to_ktime(sirfport->rx_period_time)); + return HRTIMER_RESTART; +} + static struct of_device_id sirfsoc_uart_ids[] = { { .compatible = "sirf,prima2-uart", .data = &sirfsoc_uart,}, { .compatible = "sirf,atlas7-uart", .data = &sirfsoc_uart}, @@ -1325,7 +1238,6 @@ static int sirfsoc_uart_probe(struct platform_device *pdev) struct uart_port *port; struct resource *res; int ret; - int i, j; struct dma_slave_config slv_cfg = { .src_maxburst = 2, }; @@ -1413,12 +1325,9 @@ usp_no_flow_control: ret = -EFAULT; goto err; } - tasklet_init(&sirfport->rx_dma_complete_tasklet, - sirfsoc_uart_rx_dma_complete_tl, (unsigned long)sirfport); - tasklet_init(&sirfport->rx_tmo_process_tasklet, - sirfsoc_rx_tmo_process_tl, (unsigned long)sirfport); port->mapbase = res->start; - port->membase = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + port->membase = devm_ioremap(&pdev->dev, + res->start, resource_size(res)); if (!port->membase) { dev_err(&pdev->dev, "Cannot remap resource.\n"); ret = -ENOMEM; @@ -1450,30 +1359,32 @@ usp_no_flow_control: } sirfport->rx_dma_chan = dma_request_slave_channel(port->dev, "rx"); - for (i = 0; sirfport->rx_dma_chan && i < SIRFSOC_RX_LOOP_BUF_CNT; i++) { - sirfport->rx_dma_items[i].xmit.buf = - dma_alloc_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE, - &sirfport->rx_dma_items[i].dma_addr, GFP_KERNEL); - if (!sirfport->rx_dma_items[i].xmit.buf) { - dev_err(port->dev, "Uart alloc bufa failed\n"); - ret = -ENOMEM; - goto alloc_coherent_err; - } - sirfport->rx_dma_items[i].xmit.head = - sirfport->rx_dma_items[i].xmit.tail = 0; + sirfport->rx_dma_items.xmit.buf = + dma_alloc_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE, + &sirfport->rx_dma_items.dma_addr, GFP_KERNEL); + if (!sirfport->rx_dma_items.xmit.buf) { + dev_err(port->dev, "Uart alloc bufa failed\n"); + ret = -ENOMEM; + goto alloc_coherent_err; } + sirfport->rx_dma_items.xmit.head = + sirfport->rx_dma_items.xmit.tail = 0; if (sirfport->rx_dma_chan) dmaengine_slave_config(sirfport->rx_dma_chan, &slv_cfg); sirfport->tx_dma_chan = dma_request_slave_channel(port->dev, "tx"); if (sirfport->tx_dma_chan) dmaengine_slave_config(sirfport->tx_dma_chan, &tx_slv_cfg); + if (sirfport->rx_dma_chan) { + hrtimer_init(&sirfport->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + sirfport->hrt.function = sirfsoc_uart_rx_dma_hrtimer_callback; + sirfport->is_hrt_enabled = false; + } return 0; alloc_coherent_err: - for (j = 0; j < i; j++) - dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE, - sirfport->rx_dma_items[j].xmit.buf, - sirfport->rx_dma_items[j].dma_addr); + dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE, + sirfport->rx_dma_items.xmit.buf, + sirfport->rx_dma_items.dma_addr); dma_release_channel(sirfport->rx_dma_chan); err: return ret; @@ -1485,13 +1396,11 @@ static int sirfsoc_uart_remove(struct platform_device *pdev) struct uart_port *port = &sirfport->port; uart_remove_one_port(&sirfsoc_uart_drv, port); if (sirfport->rx_dma_chan) { - int i; dmaengine_terminate_all(sirfport->rx_dma_chan); dma_release_channel(sirfport->rx_dma_chan); - for (i = 0; i < SIRFSOC_RX_LOOP_BUF_CNT; i++) - dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE, - sirfport->rx_dma_items[i].xmit.buf, - sirfport->rx_dma_items[i].dma_addr); + dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE, + sirfport->rx_dma_items.xmit.buf, + sirfport->rx_dma_items.dma_addr); } if (sirfport->tx_dma_chan) { dmaengine_terminate_all(sirfport->tx_dma_chan); diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h index 644f86529571..eb162b012eec 100644 --- a/drivers/tty/serial/sirfsoc_uart.h +++ b/drivers/tty/serial/sirfsoc_uart.h @@ -7,6 +7,7 @@ */ #include <linux/bitops.h> #include <linux/log2.h> +#include <linux/hrtimer.h> struct sirfsoc_uart_param { const char *uart_name; const char *port_name; @@ -293,6 +294,7 @@ struct sirfsoc_uart_register sirfsoc_uart = { #define SIRFUART_IO_MODE BIT(0) #define SIRFUART_DMA_MODE 0x0 +#define SIRFUART_RX_DMA_FLUSH 0x4 /* Baud Rate Calculation */ #define SIRF_USP_MIN_SAMPLE_DIV 0x1 @@ -353,8 +355,7 @@ struct sirfsoc_uart_register sirfsoc_uart = { uint_st->sirfsoc_rx_timeout) #define SIRFUART_CTS_INT_ST(uint_st) (uint_st->sirfsoc_cts) #define SIRFUART_RX_DMA_INT_EN(uint_en, uart_type) \ - (uint_en->sirfsoc_rx_timeout_en |\ - uint_en->sirfsoc_frm_err_en |\ + (uint_en->sirfsoc_frm_err_en |\ uint_en->sirfsoc_rx_oflow_en |\ uint_en->sirfsoc_rxd_brk_en |\ ((uart_type != SIRF_REAL_UART) ? \ @@ -369,7 +370,7 @@ struct sirfsoc_uart_register sirfsoc_uart = { #define SIRFSOC_PORT_TYPE 0xa5 /* Uart Common Use Macro*/ -#define SIRFSOC_RX_DMA_BUF_SIZE 256 +#define SIRFSOC_RX_DMA_BUF_SIZE (1024 * 32) #define BYTES_TO_ALIGN(dma_addr) ((unsigned long)(dma_addr) & 0x3) /* Uart Fifo Level Chk */ #define SIRFUART_TX_FIFO_SC_OFFSET 0 @@ -385,8 +386,8 @@ struct sirfsoc_uart_register sirfsoc_uart = { #define SIRFUART_RX_FIFO_CHK_SC SIRFUART_TX_FIFO_CHK_SC #define SIRFUART_RX_FIFO_CHK_LC SIRFUART_TX_FIFO_CHK_LC #define SIRFUART_RX_FIFO_CHK_HC SIRFUART_TX_FIFO_CHK_HC +#define SIRFUART_RX_FIFO_MASK 0x7f /* Indicate how many buffers used */ -#define SIRFSOC_RX_LOOP_BUF_CNT 2 /* For Fast Baud Rate Calculation */ struct sirfsoc_baudrate_to_regv { @@ -400,7 +401,7 @@ enum sirfsoc_tx_state { TX_DMA_PAUSE, }; -struct sirfsoc_loop_buffer { +struct sirfsoc_rx_buffer { struct circ_buf xmit; dma_cookie_t cookie; struct dma_async_tx_descriptor *desc; @@ -420,17 +421,16 @@ struct sirfsoc_uart_port { struct dma_chan *tx_dma_chan; dma_addr_t tx_dma_addr; struct dma_async_tx_descriptor *tx_dma_desc; - struct tasklet_struct rx_dma_complete_tasklet; - struct tasklet_struct rx_tmo_process_tasklet; unsigned int rx_io_count; unsigned long transfer_size; enum sirfsoc_tx_state tx_dma_state; unsigned int cts_gpio; unsigned int rts_gpio; - struct sirfsoc_loop_buffer rx_dma_items[SIRFSOC_RX_LOOP_BUF_CNT]; - int rx_completed; - int rx_issued; + struct sirfsoc_rx_buffer rx_dma_items; + struct hrtimer hrt; + bool is_hrt_enabled; + unsigned long rx_period_time; }; /* Register Access Control */ |