Skip to contentSkip to conversation

Blackfin Sports UART Driver fixing

PATCH In review Bryan Wu 3 participants 6 messages May 12, 2008 – May 13, 2008

lore
Share & tools
lore

Bryan Wu

author
#0 lore raw

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

author
#1 lore raw

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
index 36acbcc..c88cd1d 100644
@@ -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
author
#2 lore raw

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 Wu

From: Cliff Cai <[email protected]>

http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=3911

---
 drivers/serial/bfin_sport_uart.c |   32 +++++++++++++++++++++++++-------
 1 files changed, 25 insertions(+), 7 deletions(-)
drivers/serial/bfin_sport_uart.c +25 -7
index aca1240..c31ca6f 100644
@@ -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
#3 lore raw

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.

#4 lore raw

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.

author
#5 lore raw

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 Wu

From: 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
index c31ca6f..786451d 100644
@@ -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