2011-11-17 19:17:04 +04:00
/*
* Drivers for CSR SiRFprimaII onboard UARTs .
*
* Copyright ( c ) 2011 Cambridge Silicon Radio Limited , a CSR plc group company .
*
* Licensed under GPLv2 or later .
*/
# include <linux/bitops.h>
2013-08-12 14:15:35 +04:00
struct sirfsoc_uart_param {
const char * uart_name ;
const char * port_name ;
u32 uart_nr ;
u32 register_uart_nr ;
} ;
struct sirfsoc_register {
/* hardware uart specific */
u32 sirfsoc_line_ctrl ;
u32 sirfsoc_divisor ;
/* uart - usp common */
u32 sirfsoc_tx_rx_en ;
u32 sirfsoc_int_en_reg ;
u32 sirfsoc_int_st_reg ;
u32 sirfsoc_tx_dma_io_ctrl ;
u32 sirfsoc_tx_dma_io_len ;
u32 sirfsoc_tx_fifo_ctrl ;
u32 sirfsoc_tx_fifo_level_chk ;
u32 sirfsoc_tx_fifo_op ;
u32 sirfsoc_tx_fifo_status ;
u32 sirfsoc_tx_fifo_data ;
u32 sirfsoc_rx_dma_io_ctrl ;
u32 sirfsoc_rx_dma_io_len ;
u32 sirfsoc_rx_fifo_ctrl ;
u32 sirfsoc_rx_fifo_level_chk ;
u32 sirfsoc_rx_fifo_op ;
u32 sirfsoc_rx_fifo_status ;
u32 sirfsoc_rx_fifo_data ;
u32 sirfsoc_afc_ctrl ;
u32 sirfsoc_swh_dma_io ;
/* hardware usp specific */
u32 sirfsoc_mode1 ;
u32 sirfsoc_mode2 ;
u32 sirfsoc_tx_frame_ctrl ;
u32 sirfsoc_rx_frame_ctrl ;
u32 sirfsoc_async_param_reg ;
} ;
typedef u32 ( * fifo_full_mask ) ( int line ) ;
typedef u32 ( * fifo_empty_mask ) ( int line ) ;
struct sirfsoc_fifo_status {
fifo_full_mask ff_full ;
fifo_empty_mask ff_empty ;
} ;
struct sirfsoc_int_en {
u32 sirfsoc_rx_done_en ;
u32 sirfsoc_tx_done_en ;
u32 sirfsoc_rx_oflow_en ;
u32 sirfsoc_tx_allout_en ;
u32 sirfsoc_rx_io_dma_en ;
u32 sirfsoc_tx_io_dma_en ;
u32 sirfsoc_rxfifo_full_en ;
u32 sirfsoc_txfifo_empty_en ;
u32 sirfsoc_rxfifo_thd_en ;
u32 sirfsoc_txfifo_thd_en ;
u32 sirfsoc_frm_err_en ;
u32 sirfsoc_rxd_brk_en ;
u32 sirfsoc_rx_timeout_en ;
u32 sirfsoc_parity_err_en ;
u32 sirfsoc_cts_en ;
u32 sirfsoc_rts_en ;
} ;
struct sirfsoc_int_status {
u32 sirfsoc_rx_done ;
u32 sirfsoc_tx_done ;
u32 sirfsoc_rx_oflow ;
u32 sirfsoc_tx_allout ;
u32 sirfsoc_rx_io_dma ;
u32 sirfsoc_tx_io_dma ;
u32 sirfsoc_rxfifo_full ;
u32 sirfsoc_txfifo_empty ;
u32 sirfsoc_rxfifo_thd ;
u32 sirfsoc_txfifo_thd ;
u32 sirfsoc_frm_err ;
u32 sirfsoc_rxd_brk ;
u32 sirfsoc_rx_timeout ;
u32 sirfsoc_parity_err ;
u32 sirfsoc_cts ;
u32 sirfsoc_rts ;
} ;
enum sirfsoc_uart_type {
SIRF_REAL_UART ,
SIRF_USP_UART ,
} ;
struct sirfsoc_uart_register {
struct sirfsoc_register uart_reg ;
struct sirfsoc_int_en uart_int_en ;
struct sirfsoc_int_status uart_int_st ;
struct sirfsoc_fifo_status fifo_status ;
struct sirfsoc_uart_param uart_param ;
enum sirfsoc_uart_type uart_type ;
} ;
2011-11-17 19:17:04 +04:00
2013-08-12 14:15:35 +04:00
u32 usp_ff_full ( int line )
{
return 0x80 ;
}
u32 usp_ff_empty ( int line )
{
return 0x100 ;
}
u32 uart_ff_full ( int line )
{
return ( line = = 1 ) ? ( 0x20 ) : ( 0x80 ) ;
}
u32 uart_ff_empty ( int line )
{
return ( line = = 1 ) ? ( 0x40 ) : ( 0x100 ) ;
}
struct sirfsoc_uart_register sirfsoc_usp = {
. uart_reg = {
. sirfsoc_mode1 = 0x0000 ,
. sirfsoc_mode2 = 0x0004 ,
. sirfsoc_tx_frame_ctrl = 0x0008 ,
. sirfsoc_rx_frame_ctrl = 0x000c ,
. sirfsoc_tx_rx_en = 0x0010 ,
. sirfsoc_int_en_reg = 0x0014 ,
. sirfsoc_int_st_reg = 0x0018 ,
. sirfsoc_async_param_reg = 0x0024 ,
. sirfsoc_tx_dma_io_ctrl = 0x0100 ,
. sirfsoc_tx_dma_io_len = 0x0104 ,
. sirfsoc_tx_fifo_ctrl = 0x0108 ,
. sirfsoc_tx_fifo_level_chk = 0x010c ,
. sirfsoc_tx_fifo_op = 0x0110 ,
. sirfsoc_tx_fifo_status = 0x0114 ,
. sirfsoc_tx_fifo_data = 0x0118 ,
. sirfsoc_rx_dma_io_ctrl = 0x0120 ,
. sirfsoc_rx_dma_io_len = 0x0124 ,
. sirfsoc_rx_fifo_ctrl = 0x0128 ,
. sirfsoc_rx_fifo_level_chk = 0x012c ,
. sirfsoc_rx_fifo_op = 0x0130 ,
. sirfsoc_rx_fifo_status = 0x0134 ,
. sirfsoc_rx_fifo_data = 0x0138 ,
} ,
. uart_int_en = {
. sirfsoc_rx_done_en = BIT ( 0 ) ,
. sirfsoc_tx_done_en = BIT ( 1 ) ,
. sirfsoc_rx_oflow_en = BIT ( 2 ) ,
. sirfsoc_tx_allout_en = BIT ( 3 ) ,
. sirfsoc_rx_io_dma_en = BIT ( 4 ) ,
. sirfsoc_tx_io_dma_en = BIT ( 5 ) ,
. sirfsoc_rxfifo_full_en = BIT ( 6 ) ,
. sirfsoc_txfifo_empty_en = BIT ( 7 ) ,
. sirfsoc_rxfifo_thd_en = BIT ( 8 ) ,
. sirfsoc_txfifo_thd_en = BIT ( 9 ) ,
. sirfsoc_frm_err_en = BIT ( 10 ) ,
. sirfsoc_rx_timeout_en = BIT ( 11 ) ,
. sirfsoc_rxd_brk_en = BIT ( 15 ) ,
} ,
. uart_int_st = {
. sirfsoc_rx_done = BIT ( 0 ) ,
. sirfsoc_tx_done = BIT ( 1 ) ,
. sirfsoc_rx_oflow = BIT ( 2 ) ,
. sirfsoc_tx_allout = BIT ( 3 ) ,
. sirfsoc_rx_io_dma = BIT ( 4 ) ,
. sirfsoc_tx_io_dma = BIT ( 5 ) ,
. sirfsoc_rxfifo_full = BIT ( 6 ) ,
. sirfsoc_txfifo_empty = BIT ( 7 ) ,
. sirfsoc_rxfifo_thd = BIT ( 8 ) ,
. sirfsoc_txfifo_thd = BIT ( 9 ) ,
. sirfsoc_frm_err = BIT ( 10 ) ,
. sirfsoc_rx_timeout = BIT ( 11 ) ,
. sirfsoc_rxd_brk = BIT ( 15 ) ,
} ,
. fifo_status = {
. ff_full = usp_ff_full ,
. ff_empty = usp_ff_empty ,
} ,
. uart_param = {
. uart_name = " ttySiRF " ,
. port_name = " sirfsoc-uart " ,
. uart_nr = 2 ,
. register_uart_nr = 3 ,
} ,
} ;
struct sirfsoc_uart_register sirfsoc_uart = {
. uart_reg = {
. sirfsoc_line_ctrl = 0x0040 ,
. sirfsoc_tx_rx_en = 0x004c ,
. sirfsoc_divisor = 0x0050 ,
. sirfsoc_int_en_reg = 0x0054 ,
. sirfsoc_int_st_reg = 0x0058 ,
. sirfsoc_tx_dma_io_ctrl = 0x0100 ,
. sirfsoc_tx_dma_io_len = 0x0104 ,
. sirfsoc_tx_fifo_ctrl = 0x0108 ,
. sirfsoc_tx_fifo_level_chk = 0x010c ,
. sirfsoc_tx_fifo_op = 0x0110 ,
. sirfsoc_tx_fifo_status = 0x0114 ,
. sirfsoc_tx_fifo_data = 0x0118 ,
. sirfsoc_rx_dma_io_ctrl = 0x0120 ,
. sirfsoc_rx_dma_io_len = 0x0124 ,
. sirfsoc_rx_fifo_ctrl = 0x0128 ,
. sirfsoc_rx_fifo_level_chk = 0x012c ,
. sirfsoc_rx_fifo_op = 0x0130 ,
. sirfsoc_rx_fifo_status = 0x0134 ,
. sirfsoc_rx_fifo_data = 0x0138 ,
. sirfsoc_afc_ctrl = 0x0140 ,
. sirfsoc_swh_dma_io = 0x0148 ,
} ,
. uart_int_en = {
. sirfsoc_rx_done_en = BIT ( 0 ) ,
. sirfsoc_tx_done_en = BIT ( 1 ) ,
. sirfsoc_rx_oflow_en = BIT ( 2 ) ,
. sirfsoc_tx_allout_en = BIT ( 3 ) ,
. sirfsoc_rx_io_dma_en = BIT ( 4 ) ,
. sirfsoc_tx_io_dma_en = BIT ( 5 ) ,
. sirfsoc_rxfifo_full_en = BIT ( 6 ) ,
. sirfsoc_txfifo_empty_en = BIT ( 7 ) ,
. sirfsoc_rxfifo_thd_en = BIT ( 8 ) ,
. sirfsoc_txfifo_thd_en = BIT ( 9 ) ,
. sirfsoc_frm_err_en = BIT ( 10 ) ,
. sirfsoc_rxd_brk_en = BIT ( 11 ) ,
. sirfsoc_rx_timeout_en = BIT ( 12 ) ,
. sirfsoc_parity_err_en = BIT ( 13 ) ,
. sirfsoc_cts_en = BIT ( 14 ) ,
. sirfsoc_rts_en = BIT ( 15 ) ,
} ,
. uart_int_st = {
. sirfsoc_rx_done = BIT ( 0 ) ,
. sirfsoc_tx_done = BIT ( 1 ) ,
. sirfsoc_rx_oflow = BIT ( 2 ) ,
. sirfsoc_tx_allout = BIT ( 3 ) ,
. sirfsoc_rx_io_dma = BIT ( 4 ) ,
. sirfsoc_tx_io_dma = BIT ( 5 ) ,
. sirfsoc_rxfifo_full = BIT ( 6 ) ,
. sirfsoc_txfifo_empty = BIT ( 7 ) ,
. sirfsoc_rxfifo_thd = BIT ( 8 ) ,
. sirfsoc_txfifo_thd = BIT ( 9 ) ,
. sirfsoc_frm_err = BIT ( 10 ) ,
. sirfsoc_rxd_brk = BIT ( 11 ) ,
. sirfsoc_rx_timeout = BIT ( 12 ) ,
. sirfsoc_parity_err = BIT ( 13 ) ,
. sirfsoc_cts = BIT ( 14 ) ,
. sirfsoc_rts = BIT ( 15 ) ,
} ,
. fifo_status = {
. ff_full = uart_ff_full ,
. ff_empty = uart_ff_empty ,
} ,
. uart_param = {
. uart_name = " ttySiRF " ,
. port_name = " sirfsoc_uart " ,
. uart_nr = 3 ,
. register_uart_nr = 0 ,
} ,
} ;
/* uart io ctrl */
2011-11-17 19:17:04 +04:00
# define SIRFUART_DATA_BIT_LEN_MASK 0x3
# define SIRFUART_DATA_BIT_LEN_5 BIT(0)
# define SIRFUART_DATA_BIT_LEN_6 1
# define SIRFUART_DATA_BIT_LEN_7 2
# define SIRFUART_DATA_BIT_LEN_8 3
# define SIRFUART_STOP_BIT_LEN_1 0
# define SIRFUART_STOP_BIT_LEN_2 BIT(2)
# define SIRFUART_PARITY_EN BIT(3)
# define SIRFUART_EVEN_BIT BIT(4)
# define SIRFUART_STICK_BIT_MASK (7 << 3)
# define SIRFUART_STICK_BIT_NONE (0 << 3)
# define SIRFUART_STICK_BIT_EVEN BIT(3)
# define SIRFUART_STICK_BIT_ODD (3 << 3)
# define SIRFUART_STICK_BIT_MARK (5 << 3)
# define SIRFUART_STICK_BIT_SPACE (7 << 3)
# define SIRFUART_SET_BREAK BIT(6)
# define SIRFUART_LOOP_BACK BIT(7)
# define SIRFUART_PARITY_MASK (7 << 3)
# define SIRFUART_DUMMY_READ BIT(16)
2013-08-12 14:15:35 +04:00
# define SIRFUART_AFC_CTRL_RX_THD 0x70
2011-11-17 19:17:04 +04:00
# define SIRFUART_AFC_RX_EN BIT(8)
# define SIRFUART_AFC_TX_EN BIT(9)
2013-08-12 14:15:35 +04:00
# define SIRFUART_AFC_CTS_CTRL BIT(10)
# define SIRFUART_AFC_RTS_CTRL BIT(11)
# define SIRFUART_AFC_CTS_STATUS BIT(12)
# define SIRFUART_AFC_RTS_STATUS BIT(13)
2011-11-17 19:17:04 +04:00
/* UART FIFO Register */
2013-08-12 14:15:35 +04:00
# define SIRFUART_FIFO_STOP 0x0
# define SIRFUART_FIFO_RESET BIT(0)
# define SIRFUART_FIFO_START BIT(1)
# define SIRFUART_RX_EN BIT(0)
# define SIRFUART_TX_EN BIT(1)
# define SIRFUART_IO_MODE BIT(0)
# define SIRFUART_DMA_MODE 0x0
/* Macro Specific*/
# define SIRFUART_INT_EN_CLR 0x0060
/* Baud Rate Calculation */
# define SIRF_MIN_SAMPLE_DIV 0xf
# define SIRF_MAX_SAMPLE_DIV 0x3f
# define SIRF_IOCLK_DIV_MAX 0xffff
# define SIRF_SAMPLE_DIV_SHIFT 16
# define SIRF_IOCLK_DIV_MASK 0xffff
# define SIRF_SAMPLE_DIV_MASK 0x3f0000
# define SIRF_BAUD_RATE_SUPPORT_NR 18
/* USP SPEC */
# define SIRFSOC_USP_ENDIAN_CTRL_LSBF BIT(4)
# define SIRFSOC_USP_EN BIT(5)
2013-08-25 16:18:40 +04:00
# define SIRFSOC_USP_MODE2_RXD_DELAY_OFFSET 0
# define SIRFSOC_USP_MODE2_TXD_DELAY_OFFSET 8
# define SIRFSOC_USP_MODE2_CLK_DIVISOR_MASK 0x3ff
# define SIRFSOC_USP_MODE2_CLK_DIVISOR_OFFSET 21
# define SIRFSOC_USP_TX_DATA_LEN_OFFSET 0
# define SIRFSOC_USP_TX_SYNC_LEN_OFFSET 8
# define SIRFSOC_USP_TX_FRAME_LEN_OFFSET 16
# define SIRFSOC_USP_TX_SHIFTER_LEN_OFFSET 24
# define SIRFSOC_USP_TX_CLK_DIVISOR_OFFSET 30
# define SIRFSOC_USP_RX_DATA_LEN_OFFSET 0
# define SIRFSOC_USP_RX_FRAME_LEN_OFFSET 8
# define SIRFSOC_USP_RX_SHIFTER_LEN_OFFSET 16
# define SIRFSOC_USP_RX_CLK_DIVISOR_OFFSET 24
# define SIRFSOC_USP_ASYNC_DIV2_MASK 0x3f
# define SIRFSOC_USP_ASYNC_DIV2_OFFSET 16
2013-08-12 14:15:35 +04:00
/* USP-UART Common */
# define SIRFSOC_UART_RX_TIMEOUT(br, to) (((br) * (((to) + 999) / 1000)) / 1000)
# define SIRFUART_RECV_TIMEOUT_VALUE(x) \
( ( ( x ) > 0xFFFF ) ? 0xFFFF : ( ( x ) & 0xFFFF ) )
# define SIRFUART_RECV_TIMEOUT(port, x) \
( ( ( port ) - > line > 2 ) ? ( x & 0xFFFF ) : ( ( x ) & 0xFFFF ) < < 16 )
2011-11-17 19:17:04 +04:00
2013-08-12 14:15:35 +04:00
# define SIRFUART_FIFO_THD(port) ((port->line) == 1 ? 16 : 64)
# define SIRFUART_ERR_INT_STAT(port, unit_st) \
( uint_st - > sirfsoc_rx_oflow | \
uint_st - > sirfsoc_frm_err | \
uint_st - > sirfsoc_rxd_brk | \
( ( port - > line > 2 ) ? 0 : uint_st - > sirfsoc_parity_err ) )
# define SIRFUART_RX_IO_INT_EN(port, uint_en) \
( uint_en - > sirfsoc_rx_timeout_en | \
uint_en - > sirfsoc_rxfifo_thd_en | \
uint_en - > sirfsoc_rxfifo_full_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 ) )
# define SIRFUART_RX_IO_INT_ST(uint_st) \
( uint_st - > sirfsoc_rx_timeout | \
uint_st - > sirfsoc_rxfifo_thd | \
uint_st - > sirfsoc_rxfifo_full )
# define SIRFUART_CTS_INT_ST(uint_st) (uint_st->sirfsoc_cts)
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: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-08-19 07:47:53 +04:00
# 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 ) )
2011-11-17 19:17:04 +04:00
/* Generic Definitions */
# define SIRFSOC_UART_NAME "ttySiRF"
# define SIRFSOC_UART_MAJOR 0
# define SIRFSOC_UART_MINOR 0
# define SIRFUART_PORT_NAME "sirfsoc-uart"
# define SIRFUART_MAP_SIZE 0x200
2013-08-25 16:18:41 +04:00
# define SIRFSOC_UART_NR 6
2011-11-17 19:17:04 +04:00
# define SIRFSOC_PORT_TYPE 0xa5
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: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-08-19 07:47:53 +04:00
/* 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
2011-11-17 19:17:04 +04:00
/* For Fast Baud Rate Calculation */
struct sirfsoc_baudrate_to_regv {
unsigned int baud_rate ;
unsigned int reg_val ;
} ;
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: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-08-19 07:47:53 +04:00
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 ;
} ;
2011-11-17 19:17:04 +04:00
struct sirfsoc_uart_port {
2013-08-15 02:52:15 +04:00
bool hw_flow_ctrl ;
bool ms_enabled ;
2011-11-17 19:17:04 +04:00
struct uart_port port ;
2013-01-16 10:49:27 +04:00
struct clk * clk ;
2014-11-11 15:44:58 +03:00
/* UART6 for BT usage in A7DA platform need multi-clock source */
bool is_bt_uart ;
struct clk * clk_general ;
struct clk * clk_noc ;
2013-08-07 09:35:38 +04:00
/* for SiRFmarco, there are SET/CLR for UART_INT_EN */
bool is_marco ;
2013-08-12 14:15:35 +04:00
struct sirfsoc_uart_register * uart_reg ;
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: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-08-19 07:47:53 +04:00
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 ;
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 ;
2013-08-15 02:52:15 +04:00
unsigned int cts_gpio ;
unsigned int rts_gpio ;
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: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-08-19 07:47:53 +04:00
struct sirfsoc_loop_buffer rx_dma_items [ SIRFSOC_RX_LOOP_BUF_CNT ] ;
int rx_completed ;
int rx_issued ;
2011-11-17 19:17:04 +04:00
} ;
/* Register Access Control */
# define portaddr(port, reg) ((port)->membase + (reg))
# define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))
# define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg))
/* UART Port Mask */
# define SIRFUART_FIFOLEVEL_MASK(port) ((port->line == 1) ? (0x1f) : (0x7f))
# define SIRFUART_FIFOFULL_MASK(port) ((port->line == 1) ? (0x20) : (0x80))
# define SIRFUART_FIFOEMPTY_MASK(port) ((port->line == 1) ? (0x40) : (0x100))
/* I/O Mode */
# define SIRFSOC_UART_IO_RX_MAX_CNT 256
2014-07-03 17:26:59 +04:00
# define SIRFSOC_UART_IO_TX_REASONABLE_CNT 256