Blackfin Sports UART Driver fixing
cover Blackfin Sports UART Driver fixing
Hi Alan and Andrew,
This patches changeset is for Blackfin SPORT UART driver fixing and updates. If you think it is OK, I'd like to merge it from Blackfin git tree.
Thanks
-Bryan
PATCH 1/3 Blackfin SPORTS UART Driver: converting BFIN->BLACKFIN
From: Mike Frysinger <[email protected]>
--- drivers/serial/Kconfig | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/serial/Kconfig +1 -1
@@ -1357,7 +1357,7 @@ config SERIAL_SC26XX_CONSOLE config SERIAL_BFIN_SPORT tristate "Blackfin SPORT emulate UART (EXPERIMENTAL)" - depends on BFIN && EXPERIMENTAL + depends on BLACKFIN && EXPERIMENTAL select SERIAL_CORE help Enble support SPORT emulate UART on Blackfin series.
Signature · 1 line
1.5.5
PATCH 2/3 Blackfin Sports UART Driver: fix bug - the bug caused by sport overrun, use timer to flip the tty buffer in order to return from rx ISR quickly
In reply to Bryan WuFrom: Cliff Cai <[email protected]>
--- drivers/serial/bfin_sport_uart.c | 32 +++++++++++++++++++++++++------- 1 files changed, 25 insertions(+), 7 deletions(-)
drivers/serial/bfin_sport_uart.c +25 -7
@@ -88,7 +88,8 @@ unsigned short bfin_uart_pin_req_sport1[] =struct sport_uart_port {struct uart_port port;char *name; - +struct timer_list rx_timer; +int once;int tx_irq;int rx_irq;int err_irq;
@@ -115,9 +116,10 @@ static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)SPORT_PUT_TX (up, value); } -static inline unsigned int rx_one_byte (struct sport_uart_port *up) +static inline unsigned char rx_one_byte (struct sport_uart_port *up) { -unsigned int value, extract; +unsigned int value; +unsigned char extract; value =SPORT_GET_RX32 (up);pr_debug ("%s value:%x\n" , __FUNCTION__, value);
@@ -171,11 +173,20 @@ static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate)return 0 ; } +static void rx_push (unsigned long data) +{ +struct sport_uart_port *up = (struct sport_uart_port *)data; +struct tty_struct *tty = up->port.info->tty; +tty_flip_buffer_push (tty); +add_timer (&up->rx_timer); +} + +static irqreturn_t sport_uart_rx_irq (int irq,void *dev_id) {struct sport_uart_port *up = dev_id;struct tty_struct *tty = up->port.info->tty; -unsigned int ch; +unsigned char ch; do { ch = rx_one_byte(up);
@@ -186,8 +197,10 @@ static irqreturn_t sport_uart_rx_irq(int irq, void *dev_id)else tty_insert_flip_char (tty, ch,TTY_NORMAL ); }while (SPORT_GET_STAT (up) &RXNE ); -tty_flip_buffer_push (tty); - +if (up->once ==0 ) { +add_timer (&up->rx_timer); + up->once =1 ; + }return IRQ_HANDLED ; }
@@ -253,7 +266,10 @@ static int sport_startup(struct uart_port *port)printk (KERN_ERR "Unable to request interrupt %s\n" , buffer); goto fail2; } - +init_timer (&up->rx_timer); + up->rx_timer.data = (unsigned long )up; + up->rx_timer.expires = jiffies +5 ; + up->rx_timer.function = (void *)rx_push;if (port->line) {if (peripheral_request_list (bfin_uart_pin_req_sport1,DRV_NAME )) goto fail3;
@@ -380,6 +396,8 @@ static void sport_stop_rx(struct uart_port *port) {struct sport_uart_port *up = (struct sport_uart_port *)port; +del_timer (&up->rx_timer); + up->once =0 ;pr_debug ("%s enter\n" , __FUNCTION__);/* Disable sport to stop rx */ SPORT_PUT_RCR1 (up, (SPORT_GET_RCR1 (up) & ~RSPEN ));
Signature · 1 line
1.5.5
Re: [PATCH 2/3] Blackfin Sports UART Driver: fix bug - the bug caused by sport overrun, use timer to flip the tty buffer in order to return from rx ISR quickly
Can you explain what the timer is for ? If you are trying to push the tty processing out of the interrupt handler then surely schedule_work would be sufficient. Also if you don't have tty->low_latency set the tty layer will already do the actual processing work each timer event not in the IRQ.
RE: [PATCH 2/3] Blackfin Sports UART Driver: fix bug - the bug caused by sport overrun, use timer to flip the tty buffer in order to return from rx ISR quickly
I will check it later.
Thanks a lot!
Cliff Cai
-----Original Message-----
From: Alan Cox [mailto:[email protected]]
Sent: Monday, May 12, 2008 5:49 PM
To: Bryan Wu
Cc: [email protected]; [email protected]; Cliff Cai; Bryan Wu
Subject: Re: [PATCH 2/3] Blackfin Sports UART Driver: fix bug - the bug caused by sport overrun, use timer to flip the tty buffer in order to return from rx ISR quickly
Can you explain what the timer is for ? If you are trying to push the tty processing out of the interrupt handler then surely schedule_work would be sufficient. Also if you don't have tty->low_latency set the tty layer will already do the actual processing work each timer event not in the IRQ.
PATCH 3/3 Blackfin SPORT UART Driver: rewrite assembly with better constraints (and proper clobber lists) so gcc can do a better job
In reply to Bryan WuFrom: Mike Frysinger <[email protected]>
--- drivers/serial/bfin_sport_uart.c | 54 ++++++++++++++++++++----------------- 1 files changed, 29 insertions(+), 25 deletions(-)
drivers/serial/bfin_sport_uart.c +29 -25
@@ -102,15 +102,16 @@ static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value) {pr_debug ("%s value:%x\n" , __FUNCTION__, value);/* Place a Start and Stop bit */ - __asm__volatile ( -"R2 = b#01111111100;\n\t" -"R3 = b#10000000001;\n\t" -"%0 <<= 2;\n\t" -"%0 = %0 & R2;\n\t" -"%0 = %0 | R3;\n\t" - :"=r" (value) - :"0" (value) - :"R2" ,"R3" ); + __asm__ __volatile__ ( +"R2 = b#01111111100;" +"R3 = b#10000000001;" +"%0 <<= 2;" +"%0 = %0 & R2;" +"%0 = %0 | R3;" + :"=d" (value) + : + :"ASTAT" ,"R2" ,"R3" + );pr_debug ("%s value:%x\n" , __FUNCTION__, value);SPORT_PUT_TX (up, value);
@@ -120,27 +121,30 @@ static inline unsigned char rx_one_byte(struct sport_uart_port *up) {unsigned int value;unsigned char extract; +u32 tmp_mask1, tmp_mask2, tmp_shift, tmp; value =SPORT_GET_RX32 (up);pr_debug ("%s value:%x\n" , __FUNCTION__, value);/* Extract 8 bits data */ - __asm__volatile ( -"R5 = 0;\n\t" -"P0 = 8;\n\t" -"R1 = 0x1801(Z);\n\t" -"R3 = 0x0300(Z);\n\t" -"R4 = 0;\n\t" -"LSETUP(loop_s, loop_e) LC0 = P0;\nloop_s:\t" -"R2 = extract(%1, R1.L)(Z);\n\t" -"R2 <<= R4;\n\t" -"R5 = R5 | R2;\n\t" -"R1 = R1 - R3;\nloop_e:\t" -"R4 += 1;\n\t" -"%0 = R5;\n\t" - :"=r" (extract) - :"r" (value) - :"P0" ,"R1" ,"R2" ,"R3" ,"R4" ,"R5" ); + __asm__ __volatile__ ( +"%0 = 0;" +"%[mask1] = 0x1801(Z);" +"%[mask2] = 0x0300(Z);" +"%[shift] = 0;" +"LSETUP(.Lloop_s, .Lloop_e) LC0 = %[lc];" +".Lloop_s:" +"%[tmp] = extract(%[val], %[mask1].L)(Z);" +"%[tmp] <<= %[shift];" +"%0 = %0 | %[tmp];" +"%[mask1] = %[mask1] - %[mask2];" +".Lloop_e:" +"%[shift] += 1;" + :"=d" (extract), [shift]"=d" (tmp_shift), [tmp]"=d" (tmp), + [mask1]"=d" (tmp_mask1), [mask2]"=d" (tmp_mask2) + : [val]"d" (value), [lc]"a" (8 ) + :"ASTAT" ,"LB0" ,"LC0" ,"LT0" + );pr_debug (" extract:%x\n" , extract);return extract;
Signature · 1 line
1.5.5