diff options
Diffstat (limited to 'drivers/tty/serial/sirfsoc_uart.c')
| -rw-r--r-- | drivers/tty/serial/sirfsoc_uart.c | 288 |
1 files changed, 115 insertions, 173 deletions
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c index 61c1ad03db5..9b4d71cff00 100644 --- a/drivers/tty/serial/sirfsoc_uart.c +++ b/drivers/tty/serial/sirfsoc_uart.c @@ -24,7 +24,6 @@ #include <linux/dmaengine.h> #include <linux/dma-direction.h> #include <linux/dma-mapping.h> -#include <linux/sirfsoc_dma.h> #include <asm/irq.h> #include <asm/mach/irq.h> @@ -173,7 +172,7 @@ static void sirfsoc_uart_stop_tx(struct uart_port *port) struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; - if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) { + if (sirfport->tx_dma_chan) { if (sirfport->tx_dma_state == TX_DMA_RUNNING) { dmaengine_pause(sirfport->tx_dma_chan); sirfport->tx_dma_state = TX_DMA_PAUSE; @@ -288,7 +287,7 @@ static void sirfsoc_uart_start_tx(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; - if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) + if (sirfport->tx_dma_chan) sirfsoc_uart_tx_with_dma(sirfport); else { sirfsoc_uart_pio_tx_chars(sirfport, 1); @@ -310,7 +309,7 @@ static void sirfsoc_uart_stop_rx(struct uart_port *port) struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0); - if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) { + if (sirfport->rx_dma_chan) { if (!sirfport->is_marco) wr_regl(port, ureg->sirfsoc_int_en_reg, rd_regl(port, ureg->sirfsoc_int_en_reg) & @@ -359,9 +358,11 @@ static irqreturn_t sirfsoc_uart_usp_cts_handler(int irq, void *dev_id) { struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)dev_id; struct uart_port *port = &sirfport->port; + spin_lock(&port->lock); if (gpio_is_valid(sirfport->cts_gpio) && sirfport->ms_enabled) uart_handle_cts_change(port, !gpio_get_value(sirfport->cts_gpio)); + spin_unlock(&port->lock); return IRQ_HANDLED; } @@ -429,10 +430,6 @@ sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count) sirfport->rx_io_count += rx_count; port->icount.rx += rx_count; - spin_unlock(&port->lock); - tty_flip_buffer_push(&port->state->port); - spin_lock(&port->lock); - return rx_count; } @@ -466,6 +463,7 @@ static void sirfsoc_uart_tx_dma_complete_callback(void *param) struct circ_buf *xmit = &port->state->xmit; unsigned long flags; + spin_lock_irqsave(&port->lock, flags); xmit->tail = (xmit->tail + sirfport->transfer_size) & (UART_XMIT_SIZE - 1); port->icount.tx += sirfport->transfer_size; @@ -474,10 +472,9 @@ static void sirfsoc_uart_tx_dma_complete_callback(void *param) if (sirfport->tx_dma_addr) dma_unmap_single(port->dev, sirfport->tx_dma_addr, sirfport->transfer_size, DMA_TO_DEVICE); - spin_lock_irqsave(&sirfport->tx_lock, flags); sirfport->tx_dma_state = TX_DMA_IDLE; sirfsoc_uart_tx_with_dma(sirfport); - spin_unlock_irqrestore(&sirfport->tx_lock, flags); + spin_unlock_irqrestore(&port->lock, flags); } static void sirfsoc_uart_insert_rx_buf_to_tty( @@ -490,7 +487,6 @@ static void sirfsoc_uart_insert_rx_buf_to_tty( inserted = tty_insert_flip_string(tport, sirfport->rx_dma_items[sirfport->rx_completed].xmit.buf, count); port->icount.rx += inserted; - tty_flip_buffer_push(tport); } static void sirfsoc_rx_submit_one_dma_desc(struct uart_port *port, int index) @@ -524,12 +520,14 @@ static void sirfsoc_rx_tmo_process_tl(unsigned long param) struct sirfsoc_int_status *uint_st = &sirfport->uart_reg->uart_int_st; unsigned int count; unsigned long flags; + struct dma_tx_state tx_state; - spin_lock_irqsave(&sirfport->rx_lock, flags); - while (sirfport->rx_completed != sirfport->rx_issued) { + 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); - sirfsoc_rx_submit_one_dma_desc(port, sirfport->rx_completed++); + sirfport->rx_completed++; sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT; } count = CIRC_CNT(sirfport->rx_dma_items[sirfport->rx_issued].xmit.head, @@ -541,9 +539,7 @@ static void sirfsoc_rx_tmo_process_tl(unsigned long param) rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | SIRFUART_IO_MODE); sirfsoc_uart_pio_rx_chars(port, 4 - sirfport->rx_io_count); - spin_unlock_irqrestore(&sirfport->rx_lock, flags); if (sirfport->rx_io_count == 4) { - spin_lock_irqsave(&sirfport->rx_lock, flags); sirfport->rx_io_count = 0; wr_regl(port, ureg->sirfsoc_int_st_reg, uint_st->sirfsoc_rx_done); @@ -554,11 +550,8 @@ static void sirfsoc_rx_tmo_process_tl(unsigned long param) else wr_regl(port, SIRFUART_INT_EN_CLR, uint_en->sirfsoc_rx_done_en); - spin_unlock_irqrestore(&sirfport->rx_lock, flags); - sirfsoc_uart_start_next_rx_dma(port); } else { - spin_lock_irqsave(&sirfport->rx_lock, flags); wr_regl(port, ureg->sirfsoc_int_st_reg, uint_st->sirfsoc_rx_done); if (!sirfport->is_marco) @@ -568,8 +561,9 @@ static void sirfsoc_rx_tmo_process_tl(unsigned long param) else wr_regl(port, ureg->sirfsoc_int_en_reg, uint_en->sirfsoc_rx_done_en); - spin_unlock_irqrestore(&sirfport->rx_lock, flags); } + 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) @@ -578,8 +572,6 @@ static void sirfsoc_uart_handle_rx_tmo(struct sirfsoc_uart_port *sirfport) 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; - spin_lock(&sirfport->rx_lock); - dmaengine_tx_status(sirfport->rx_dma_chan, sirfport->rx_dma_items[sirfport->rx_issued].cookie, &tx_state); dmaengine_terminate_all(sirfport->rx_dma_chan); @@ -592,7 +584,6 @@ static void sirfsoc_uart_handle_rx_tmo(struct sirfsoc_uart_port *sirfport) else wr_regl(port, SIRFUART_INT_EN_CLR, uint_en->sirfsoc_rx_timeout_en); - spin_unlock(&sirfport->rx_lock); tasklet_schedule(&sirfport->rx_tmo_process_tasklet); } @@ -656,7 +647,6 @@ static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id) intr_status &= port->read_status_mask; uart_insert_char(port, intr_status, uint_en->sirfsoc_rx_oflow_en, 0, flag); - tty_flip_buffer_push(&state->port); } recv_char: if ((sirfport->uart_reg->uart_type == SIRF_REAL_UART) && @@ -671,7 +661,7 @@ recv_char: uart_handle_cts_change(port, cts_status); wake_up_interruptible(&state->port.delta_msr_wait); } - if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) { + 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) @@ -681,8 +671,11 @@ recv_char: sirfsoc_uart_pio_rx_chars(port, SIRFSOC_UART_IO_RX_MAX_CNT); } + spin_unlock(&port->lock); + tty_flip_buffer_push(&state->port); + spin_lock(&port->lock); if (intr_status & uint_st->sirfsoc_txfifo_empty) { - if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) + if (sirfport->tx_dma_chan) sirfsoc_uart_tx_with_dma(sirfport); else { if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { @@ -699,6 +692,7 @@ recv_char: } } spin_unlock(&port->lock); + return IRQ_HANDLED; } @@ -706,25 +700,37 @@ 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; unsigned long flags; - spin_lock_irqsave(&sirfport->rx_lock, flags); - while (sirfport->rx_completed != sirfport->rx_issued) { + struct dma_tx_state tx_state; + 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); - sirfsoc_rx_submit_one_dma_desc(port, sirfport->rx_completed++); + 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; } - spin_unlock_irqrestore(&sirfport->rx_lock, flags); + 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; - spin_lock(&sirfport->rx_lock); + unsigned long flags; + + spin_lock_irqsave(&sirfport->port.lock, flags); sirfport->rx_issued++; sirfport->rx_issued %= SIRFSOC_RX_LOOP_BUF_CNT; - spin_unlock(&sirfport->rx_lock); tasklet_schedule(&sirfport->rx_dma_complete_tasklet); + spin_unlock_irqrestore(&sirfport->port.lock, flags); } /* submit rx dma task into dmaengine */ @@ -733,18 +739,14 @@ 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; - unsigned long flags; int i; - spin_lock_irqsave(&sirfport->rx_lock, flags); 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); - spin_unlock_irqrestore(&sirfport->rx_lock, flags); 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; - spin_lock_irqsave(&sirfport->rx_lock, flags); if (!sirfport->is_marco) wr_regl(port, ureg->sirfsoc_int_en_reg, rd_regl(port, ureg->sirfsoc_int_en_reg) | @@ -752,7 +754,6 @@ static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port) else wr_regl(port, ureg->sirfsoc_int_en_reg, SIRFUART_RX_DMA_INT_EN(port, uint_en)); - spin_unlock_irqrestore(&sirfport->rx_lock, flags); } static void sirfsoc_uart_start_rx(struct uart_port *port) @@ -765,7 +766,7 @@ static void sirfsoc_uart_start_rx(struct uart_port *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); - if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) + if (sirfport->rx_dma_chan) sirfsoc_uart_start_next_rx_dma(port); else { if (!sirfport->is_marco) @@ -895,7 +896,7 @@ static void sirfsoc_uart_set_termios(struct uart_port *port, if (termios->c_iflag & INPCK) port->read_status_mask |= uint_en->sirfsoc_frm_err_en; } - if (termios->c_iflag & (BRKINT | PARMRK)) + if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) port->read_status_mask |= uint_en->sirfsoc_rxd_brk_en; if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { if (termios->c_iflag & IGNPAR) @@ -1001,11 +1002,11 @@ static void sirfsoc_uart_set_termios(struct uart_port *port, (sample_div_reg & SIRFSOC_USP_ASYNC_DIV2_MASK) << SIRFSOC_USP_ASYNC_DIV2_OFFSET); } - if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) + if (sirfport->tx_dma_chan) wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_DMA_MODE); else wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE); - if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) + if (sirfport->rx_dma_chan) 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); @@ -1026,91 +1027,14 @@ static void sirfsoc_uart_set_termios(struct uart_port *port, spin_unlock_irqrestore(&port->lock, flags); } -static unsigned int sirfsoc_uart_init_tx_dma(struct uart_port *port) +static void sirfsoc_uart_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) { struct sirfsoc_uart_port *sirfport = to_sirfport(port); - dma_cap_mask_t dma_mask; - struct dma_slave_config tx_slv_cfg = { - .dst_maxburst = 2, - }; - - dma_cap_zero(dma_mask); - dma_cap_set(DMA_SLAVE, dma_mask); - sirfport->tx_dma_chan = dma_request_channel(dma_mask, - (dma_filter_fn)sirfsoc_dma_filter_id, - (void *)sirfport->tx_dma_no); - if (!sirfport->tx_dma_chan) { - dev_err(port->dev, "Uart Request Dma Channel Fail %d\n", - sirfport->tx_dma_no); - return -EPROBE_DEFER; - } - dmaengine_slave_config(sirfport->tx_dma_chan, &tx_slv_cfg); - - return 0; -} - -static unsigned int sirfsoc_uart_init_rx_dma(struct uart_port *port) -{ - struct sirfsoc_uart_port *sirfport = to_sirfport(port); - dma_cap_mask_t dma_mask; - int ret; - int i, j; - struct dma_slave_config slv_cfg = { - .src_maxburst = 2, - }; - - dma_cap_zero(dma_mask); - dma_cap_set(DMA_SLAVE, dma_mask); - sirfport->rx_dma_chan = dma_request_channel(dma_mask, - (dma_filter_fn)sirfsoc_dma_filter_id, - (void *)sirfport->rx_dma_no); - if (!sirfport->rx_dma_chan) { - dev_err(port->dev, "Uart Request Dma Channel Fail %d\n", - sirfport->rx_dma_no); - ret = -EPROBE_DEFER; - goto request_err; - } - for (i = 0; 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; - } - dmaengine_slave_config(sirfport->rx_dma_chan, &slv_cfg); - - 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_release_channel(sirfport->rx_dma_chan); -request_err: - return ret; -} - -static void sirfsoc_uart_uninit_tx_dma(struct sirfsoc_uart_port *sirfport) -{ - dmaengine_terminate_all(sirfport->tx_dma_chan); - dma_release_channel(sirfport->tx_dma_chan); -} - -static void sirfsoc_uart_uninit_rx_dma(struct sirfsoc_uart_port *sirfport) -{ - int i; - struct uart_port *port = &sirfport->port; - 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); + if (!state) + clk_prepare_enable(sirfport->clk); + else + clk_disable_unprepare(sirfport->clk); } static int sirfsoc_uart_startup(struct uart_port *port) @@ -1151,18 +1075,12 @@ static int sirfsoc_uart_startup(struct uart_port *port) wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0); wr_regl(port, ureg->sirfsoc_tx_fifo_ctrl, SIRFUART_FIFO_THD(port)); wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port)); - - if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) { - ret = sirfsoc_uart_init_rx_dma(port); - if (ret) - goto init_rx_err; + if (sirfport->rx_dma_chan) wr_regl(port, ureg->sirfsoc_rx_fifo_level_chk, - SIRFUART_RX_FIFO_CHK_SC(port->line, 0x4) | - SIRFUART_RX_FIFO_CHK_LC(port->line, 0xe) | - SIRFUART_RX_FIFO_CHK_HC(port->line, 0x1b)); - } - if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) { - sirfsoc_uart_init_tx_dma(port); + SIRFUART_RX_FIFO_CHK_SC(port->line, 0x4) | + SIRFUART_RX_FIFO_CHK_LC(port->line, 0xe) | + SIRFUART_RX_FIFO_CHK_HC(port->line, 0x1b)); + if (sirfport->tx_dma_chan) { sirfport->tx_dma_state = TX_DMA_IDLE; wr_regl(port, ureg->sirfsoc_tx_fifo_level_chk, SIRFUART_TX_FIFO_CHK_SC(port->line, 0x1b) | @@ -1209,12 +1127,8 @@ static void sirfsoc_uart_shutdown(struct uart_port *port) gpio_set_value(sirfport->rts_gpio, 1); free_irq(gpio_to_irq(sirfport->cts_gpio), sirfport); } - if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) - sirfsoc_uart_uninit_rx_dma(sirfport); - if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) { - sirfsoc_uart_uninit_tx_dma(sirfport); + if (sirfport->tx_dma_chan) sirfport->tx_dma_state = TX_DMA_IDLE; - } } static const char *sirfsoc_uart_type(struct uart_port *port) @@ -1257,6 +1171,7 @@ static struct uart_ops sirfsoc_uart_ops = { .startup = sirfsoc_uart_startup, .shutdown = sirfsoc_uart_shutdown, .set_termios = sirfsoc_uart_set_termios, + .pm = sirfsoc_uart_pm, .type = sirfsoc_uart_type, .release_port = sirfsoc_uart_release_port, .request_port = sirfsoc_uart_request_port, @@ -1289,8 +1204,8 @@ sirfsoc_uart_console_setup(struct console *co, char *options) port->cons = co; /* default console tx/rx transfer using io mode */ - sirfport->rx_dma_no = UNVALID_DMA_CHAN; - sirfport->tx_dma_no = UNVALID_DMA_CHAN; + sirfport->rx_dma_chan = NULL; + sirfport->tx_dma_chan = NULL; return uart_set_options(port, co, baud, parity, bits, flow); } @@ -1302,7 +1217,7 @@ static void sirfsoc_uart_console_putchar(struct uart_port *port, int ch) while (rd_regl(port, ureg->sirfsoc_tx_fifo_status) & ufifo_st->ff_full(port->line)) cpu_relax(); - wr_regb(port, ureg->sirfsoc_tx_fifo_data, ch); + wr_regl(port, ureg->sirfsoc_tx_fifo_data, ch); } static void sirfsoc_uart_console_write(struct console *co, const char *s, @@ -1358,6 +1273,13 @@ 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, + }; + struct dma_slave_config tx_slv_cfg = { + .dst_maxburst = 2, + }; const struct of_device_id *match; match = of_match_node(sirfsoc_uart_ids, pdev->dev.of_node); @@ -1378,27 +1300,10 @@ static int sirfsoc_uart_probe(struct platform_device *pdev) sirfport->hw_flow_ctrl = of_property_read_bool(pdev->dev.of_node, "sirf,uart-has-rtscts"); - if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-uart")) { + if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-uart")) sirfport->uart_reg->uart_type = SIRF_REAL_UART; - if (of_property_read_u32(pdev->dev.of_node, - "sirf,uart-dma-rx-channel", - &sirfport->rx_dma_no)) - sirfport->rx_dma_no = UNVALID_DMA_CHAN; - if (of_property_read_u32(pdev->dev.of_node, - "sirf,uart-dma-tx-channel", - &sirfport->tx_dma_no)) - sirfport->tx_dma_no = UNVALID_DMA_CHAN; - } if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-usp-uart")) { sirfport->uart_reg->uart_type = SIRF_USP_UART; - if (of_property_read_u32(pdev->dev.of_node, - "sirf,usp-dma-rx-channel", - &sirfport->rx_dma_no)) - sirfport->rx_dma_no = UNVALID_DMA_CHAN; - if (of_property_read_u32(pdev->dev.of_node, - "sirf,usp-dma-tx-channel", - &sirfport->tx_dma_no)) - sirfport->tx_dma_no = UNVALID_DMA_CHAN; if (!sirfport->hw_flow_ctrl) goto usp_no_flow_control; if (of_find_property(pdev->dev.of_node, "cts-gpios", NULL)) @@ -1453,8 +1358,6 @@ usp_no_flow_control: ret = -EFAULT; goto err; } - spin_lock_init(&sirfport->rx_lock); - spin_lock_init(&sirfport->tx_lock); tasklet_init(&sirfport->rx_dma_complete_tasklet, sirfsoc_uart_rx_dma_complete_tl, (unsigned long)sirfport); tasklet_init(&sirfport->rx_tmo_process_tasklet, @@ -1479,7 +1382,6 @@ usp_no_flow_control: ret = PTR_ERR(sirfport->clk); goto err; } - clk_prepare_enable(sirfport->clk); port->uartclk = clk_get_rate(sirfport->clk); port->ops = &sirfsoc_uart_ops; @@ -1492,10 +1394,33 @@ usp_no_flow_control: goto port_err; } - return 0; + 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; + } + 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); + 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_release_channel(sirfport->rx_dma_chan); port_err: - clk_disable_unprepare(sirfport->clk); clk_put(sirfport->clk); err: return ret; @@ -1505,38 +1430,55 @@ static int sirfsoc_uart_remove(struct platform_device *pdev) { struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev); struct uart_port *port = &sirfport->port; - clk_disable_unprepare(sirfport->clk); clk_put(sirfport->clk); 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); + } + if (sirfport->tx_dma_chan) { + dmaengine_terminate_all(sirfport->tx_dma_chan); + dma_release_channel(sirfport->tx_dma_chan); + } return 0; } +#ifdef CONFIG_PM_SLEEP static int -sirfsoc_uart_suspend(struct platform_device *pdev, pm_message_t state) +sirfsoc_uart_suspend(struct device *pdev) { - struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev); + struct sirfsoc_uart_port *sirfport = dev_get_drvdata(pdev); struct uart_port *port = &sirfport->port; uart_suspend_port(&sirfsoc_uart_drv, port); return 0; } -static int sirfsoc_uart_resume(struct platform_device *pdev) +static int sirfsoc_uart_resume(struct device *pdev) { - struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev); + struct sirfsoc_uart_port *sirfport = dev_get_drvdata(pdev); struct uart_port *port = &sirfport->port; uart_resume_port(&sirfsoc_uart_drv, port); return 0; } +#endif + +static const struct dev_pm_ops sirfsoc_uart_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(sirfsoc_uart_suspend, sirfsoc_uart_resume) +}; static struct platform_driver sirfsoc_uart_driver = { .probe = sirfsoc_uart_probe, .remove = sirfsoc_uart_remove, - .suspend = sirfsoc_uart_suspend, - .resume = sirfsoc_uart_resume, .driver = { .name = SIRFUART_PORT_NAME, .owner = THIS_MODULE, .of_match_table = sirfsoc_uart_ids, + .pm = &sirfsoc_uart_pm_ops, }, }; |
