提交 8316d04c 编写于 作者: Q Qipan Li 提交者: Greg Kroah-Hartman

serial: sirf: add DMA support using dmaengine APIs

if we get the valid dma channels from dts, move to use dmaengine to do
rx/tx. because the dma hardware requires dma address and length to be
4bytes aligned, in this driver, we will still use PIO for non-aligned
bytes, and use dma for aligned bytes.

for rx, to keep the dmaengine always active, we use double-buffer, so
we issue two dma_desc at first, and maintain the status of both
1. dma transfer done: update in rx dma finish callback
2. dma buffer is inserted into tty: update in rx dma finish tasklet and
   rx timeout tasklet
so we re-issue the dma_desc only if both 1&2 are finished.

for tx, as we know the actual length for every transfer, we don't need
the above double buffering.
Signed-off-by: NQipan Li <Qipan.Li@csr.com>
Signed-off-by: NBarry Song <Baohua.Song@csr.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 15cdcb12
此差异已折叠。
......@@ -338,6 +338,12 @@ struct sirfsoc_uart_register sirfsoc_uart = {
uint_st->sirfsoc_rxfifo_thd |\
uint_st->sirfsoc_rxfifo_full)
#define SIRFUART_CTS_INT_ST(uint_st) (uint_st->sirfsoc_cts)
#define SIRFUART_RX_DMA_INT_EN(port, uint_en) \
(uint_en->sirfsoc_rx_timeout_en |\
uint_en->sirfsoc_frm_err_en |\
uint_en->sirfsoc_rx_oflow_en |\
uint_en->sirfsoc_rxd_brk_en |\
((port->line > 2) ? 0 : uint_en->sirfsoc_parity_err_en))
/* Generic Definitions */
#define SIRFSOC_UART_NAME "ttySiRF"
#define SIRFSOC_UART_MAJOR 0
......@@ -356,12 +362,52 @@ struct sirfsoc_uart_register sirfsoc_uart = {
#define SIRF_SAMPLE_DIV_MASK 0x3f0000
#define SIRF_BAUD_RATE_SUPPORT_NR 18
/* Uart Common Use Macro*/
#define SIRFSOC_RX_DMA_BUF_SIZE 256
#define BYTES_TO_ALIGN(dma_addr) ((unsigned long)(dma_addr) & 0x3)
#define LOOP_DMA_BUFA_FILL 1
#define LOOP_DMA_BUFB_FILL 2
#define TX_TRAN_PIO 1
#define TX_TRAN_DMA 2
/* Uart Fifo Level Chk */
#define SIRFUART_TX_FIFO_SC_OFFSET 0
#define SIRFUART_TX_FIFO_LC_OFFSET 10
#define SIRFUART_TX_FIFO_HC_OFFSET 20
#define SIRFUART_TX_FIFO_CHK_SC(line, value) ((((line) == 1) ? (value & 0x3) :\
(value & 0x1f)) << SIRFUART_TX_FIFO_SC_OFFSET)
#define SIRFUART_TX_FIFO_CHK_LC(line, value) ((((line) == 1) ? (value & 0x3) :\
(value & 0x1f)) << SIRFUART_TX_FIFO_LC_OFFSET)
#define SIRFUART_TX_FIFO_CHK_HC(line, value) ((((line) == 1) ? (value & 0x3) :\
(value & 0x1f)) << SIRFUART_TX_FIFO_HC_OFFSET)
#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
/* Indicate how many buffers used */
#define SIRFSOC_RX_LOOP_BUF_CNT 2
/* Indicate if DMA channel valid */
#define IS_DMA_CHAN_VALID(x) ((x) != -1)
#define UNVALID_DMA_CHAN -1
/* For Fast Baud Rate Calculation */
struct sirfsoc_baudrate_to_regv {
unsigned int baud_rate;
unsigned int reg_val;
};
enum sirfsoc_tx_state {
TX_DMA_IDLE,
TX_DMA_RUNNING,
TX_DMA_PAUSE,
};
struct sirfsoc_loop_buffer {
struct circ_buf xmit;
dma_cookie_t cookie;
struct dma_async_tx_descriptor *desc;
dma_addr_t dma_addr;
};
struct sirfsoc_uart_port {
bool hw_flow_ctrl;
bool ms_enabled;
......@@ -371,8 +417,25 @@ struct sirfsoc_uart_port {
/* for SiRFmarco, there are SET/CLR for UART_INT_EN */
bool is_marco;
struct sirfsoc_uart_register *uart_reg;
int rx_dma_no;
int tx_dma_no;
struct dma_chan *rx_dma_chan;
struct dma_chan *tx_dma_chan;
dma_addr_t tx_dma_addr;
struct dma_async_tx_descriptor *tx_dma_desc;
spinlock_t rx_lock;
spinlock_t tx_lock;
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;
};
/* Hardware Flow Control */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册