update serial driver from rk2818

This commit is contained in:
luowei 2011-04-14 20:48:29 +08:00
parent 635ff65497
commit 53cb481d93
2 changed files with 112 additions and 38 deletions

View File

@ -49,7 +49,19 @@
#define UART_UCV 0x00F8 /* [0x3330_372a] UART Component Version */
#define UART_CTR 0x00FC /* [0x4457_0110] Component Type Register */
#define UART_FCR_FIFO_ENABLE (1<<0)
//#define UART_FCR 0x08
#define UART_FCR_FIFO_ENABLE (1<<0)
#define UART_FCR_CLEAR_RCVR (1<<1) /* Clear the RCVR FIFO */
#define UART_FCR_CLEAR_XMIT (1<<2) /* Clear the XMIT FIFO */
#define UART_FCR_DMA_SELECT (1<<3) /* For DMA applications */
#define UART_FCR_R_TRIG_00 0x00
#define UART_FCR_R_TRIG_01 0x40
#define UART_FCR_R_TRIG_10 0x80
#define UART_FCR_R_TRIG_11 0xc0
#define UART_FCR_T_TRIG_00 0x00
#define UART_FCR_T_TRIG_01 0x10
#define UART_FCR_T_TRIG_10 0x20
#define UART_FCR_T_TRIG_11 0x30
//#define UART_LCR 0x0c
#define LCR_DLA_EN (1<<7)

View File

@ -37,8 +37,8 @@
#include "rk2818_serial.h"
#define DBG_PORT 0
#if 0
#define DBG printk
#if 1
#define DBG(msg...) printk(msg);
#else
#define DBG(...)
#endif
@ -86,7 +86,10 @@ static int rk29_set_baud_rate(struct uart_port *port, unsigned int baud)
*/
static u_int rk29_serial_tx_empty(struct uart_port *port)
{
int timeout = 10000000;
while(!(rk29_uart_read(port,UART_USR)&UART_TRANSMIT_FIFO_EMPTY))
if(timeout-- ==0)
break;
cpu_relax();
if(rk29_uart_read(port,UART_USR)&UART_TRANSMIT_FIFO_EMPTY)
{
@ -257,10 +260,12 @@ static void rk29_rx_chars(struct uart_port *port)
if (uart_handle_break(port))
continue;
}
#if 0
if (uart_handle_sysrq_char(port, ch))
{
continue;
}
#endif
uart_insert_char(port, 0, 0, ch, flag);
if(DBG_PORT == port->line) {
@ -282,12 +287,14 @@ static irqreturn_t rk29_uart_interrupt(int irq, void *dev_id)
struct uart_port *port = dev_id;
unsigned int status, pending;
spin_lock(&port->lock);
status = rk29_uart_read(port,UART_IIR);
pending = status & 0x0f;
if((pending == UART_IIR_RECV_AVAILABLE) || (pending == UART_IIR_CHAR_TIMEOUT))
rk29_rx_chars(port);
if(pending == UART_IIR_THR_EMPTY)
rk29_serial_start_tx(port);
spin_unlock(&port->lock);
return IRQ_HANDLED;
}
@ -298,6 +305,9 @@ static void rk29_serial_shutdown(struct uart_port *port)
{
struct rk29_port *rk29_port = UART_TO_RK29(port);
rk29_uart_write(port,0x00,UART_IER);
rk29_uart_write(port, UART_FCR_FIFO_ENABLE |
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, UART_FCR);
rk29_uart_write(port, 0, UART_FCR);
clk_disable(rk29_port->clk);
free_irq(port->irq, port);
}
@ -309,20 +319,19 @@ static int rk29_serial_startup(struct uart_port *port)
struct rk29_port *rk29_port = UART_TO_RK29(port);
struct tty_struct *tty = port->state->port.tty;
int retval;
DBG("%s\n",__FUNCTION__);
if(2 == port->line)
{
rk29_mux_api_set(GPIO2B1_UART2SOUT_NAME, GPIO2L_UART2_SOUT);
rk29_mux_api_set(GPIO2B0_UART2SIN_NAME, GPIO2L_UART2_SIN);
}
else if(0 == port->line)
{
rk29_mux_api_set(GPIO1B7_UART0SOUT_NAME, GPIO1L_UART0_SOUT);
rk29_mux_api_set(GPIO1B6_UART0SIN_NAME, GPIO1L_UART0_SIN);
}
if(2 == port->line) {
rk29_mux_api_set(GPIO2B1_UART2SOUT_NAME, GPIO2L_UART2_SOUT);
rk29_mux_api_set(GPIO2B0_UART2SIN_NAME, GPIO2L_UART2_SIN);
rk29_mux_api_set(GPIO2A7_UART2RTSN_NAME, GPIO2L_UART2_RTS_N);
rk29_mux_api_set(GPIO2A6_UART2CTSN_NAME, GPIO2L_UART2_CTS_N);
}
else if(0 == port->line) {
rk29_mux_api_set(GPIO1B7_UART0SOUT_NAME, GPIO1L_UART0_SOUT);
rk29_mux_api_set(GPIO1B6_UART0SIN_NAME, GPIO1L_UART0_SIN);
rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_UART0_CTS_N);
}
retval = request_irq(port->irq,rk29_uart_interrupt,IRQF_SHARED,
tty ? tty->name : "rk29_serial",port);
if(retval)
@ -332,9 +341,37 @@ static int rk29_serial_startup(struct uart_port *port)
return retval;
}
clk_enable(rk29_port->clk);
rk29_uart_write(port,0xf1,UART_FCR);
rk29_uart_write(port,0x01,UART_SFE);///enable fifo
rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE,UART_IER); //enable uart recevice IRQ
#if 0
if(port->irq == IRQ_NR_UART0)
rk29_uart_write(port,0xf7,UART_FCR); //enable and clear fifo if busy while starting
else
rk29_uart_write(port,0xf1,UART_FCR); //enable fifo
rk29_uart_write(port,0x01,UART_SFE);
rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE,UART_IER); //enable uart recevice IRQ
#else
//lw modify on 110309
/*
* Clear the FIFO buffers and disable them.
*/
rk29_uart_write(port, UART_FCR_FIFO_ENABLE, UART_FCR);
rk29_uart_write(port, UART_FCR_FIFO_ENABLE |
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, UART_FCR);
rk29_uart_write(port, 0, UART_FCR);
/*
* Clear the interrupt registers.
*/
(void) rk29_uart_read(port, UART_LSR);
(void) rk29_uart_read(port, UART_RBR);
(void) rk29_uart_read(port, UART_IIR);
(void) rk29_uart_read(port, UART_MSR);
/*
* And clear the user registers.
*/
(void) rk29_uart_read(port, UART_USR);
#endif
return 0;
}
@ -347,6 +384,7 @@ static void rk29_serial_set_termios(struct uart_port *port, struct ktermios *ter
unsigned long flags;
unsigned int mode, baud;
unsigned int umcon,fcr;
spin_lock_irqsave(&port->lock, flags);
/* Get current mode register */
mode = rk29_uart_read(port,UART_LCR) & (BREAK_CONTROL_BIT | EVEN_PARITY_SELECT | PARITY_ENABLED
| ONE_HALF_OR_TWO_BIT | UART_DATABIT_MASK);
@ -381,34 +419,58 @@ static void rk29_serial_set_termios(struct uart_port *port, struct ktermios *ter
else
mode |= EVEN_PARITY;
}
spin_lock_irqsave(&port->lock, flags);
int timeout = 10000000;
while(rk29_uart_read(port,UART_USR)&UART_USR_BUSY){
if(timeout-- == 0){
printk("rk29_serial_set_termios uart timeout,irq=%d,ret=0x%x\n",port->irq,rk29_uart_read(port,UART_USR));
break;
}
cpu_relax();
}
rk29_uart_write(port,mode,UART_LCR);
baud = rk29_set_baud_rate(port, baud);
uart_update_timeout(port, termios->c_cflag, baud);
/*
* enable FIFO and interrupt
*/
if(termios->c_cflag & CRTSCTS)
{
/*¿ªÆôuart0Ó²¼þÁ÷¿Ø*/
printk("start CRTSCTS control and baudrate is %d\n",baud);
/*¿ªÆôuart0Ó²¼þÁ÷¿Ø*/
printk("start CRTSCTS control and baudrate is %d,irq=%d\n",baud,port->irq);
if(2 == port->line)
{
rk29_mux_api_set(GPIO2A7_UART2RTSN_NAME, GPIO2L_UART2_RTS_N);
rk29_mux_api_set(GPIO2A6_UART2CTSN_NAME, GPIO2L_UART2_CTS_N);
}
else if(0 == port->line)
{
rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_UART0_CTS_N);
}
umcon=rk29_uart_read(port,UART_MCR);
printk("UART_GET_MCR umcon=0x%x\n",umcon);
umcon |= UART_MCR_AFCEN;
umcon |= UART_MCR_URRTS;
umcon &=~UART_SIR_ENABLE;
rk29_uart_write(port,umcon,UART_MCR);
printk("UART_GET_MCR umcon=0x%x\n",umcon);
fcr=rk29_uart_read(port,UART_FCR);
printk("UART_GET_MCR fcr=0x%x\n",fcr);
fcr |= UART_FCR_FIFO_ENABLE;
rk29_uart_write(port,fcr,UART_FCR);
printk("UART_GET_MCR fcr=0x%x\n",fcr);
}
mode = mode | LCR_DLA_EN;
{
int timeout = 10000000;
while ((rk29_uart_read(port,UART_USR)&UART_USR_BUSY) && timeout--)
cpu_relax();
}
rk29_uart_write(port,mode,UART_LCR);
baud = rk29_set_baud_rate(port, baud);
uart_update_timeout(port, termios->c_cflag, baud);
spin_unlock_irqrestore(&port->lock, flags);
mode = mode | LCR_DLA_EN;
#if 1
//lw modify on 110309
fcr = UART_FCR_FIFO_ENABLE | UART_FCR_R_TRIG_10 | UART_FCR_T_TRIG_10;
rk29_uart_write(port, fcr, UART_FCR);
rk29_uart_write(port,0x01,UART_SFE);
rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE,UART_IER); //enable uart recevice IRQ
printk("%s:fcr=0x%x,irq=%d\n",__FUNCTION__,fcr,port->irq);
#endif
spin_unlock_irqrestore(&port->lock, flags);
}