Title: [4040] branches/2007R1: backport anomaly rework from trunk
- Revision
- 4040
- Author
- vapier
- Date
- 2007-12-13 13:20:47 -0600 (Thu, 13 Dec 2007)
Log Message
backport anomaly rework from trunk
Diffstat
drivers/serial/bfin_5xx.c | 76 ++++++++++++++++------
include/asm-blackfin/mach-bf533/bfin_serial_5xx.h | 3
include/asm-blackfin/mach-bf561/bfin_serial_5xx.h | 3
3 files changed, 64 insertions(+), 18 deletions(-)
Modified Paths
Diff
Modified: branches/2007R1/drivers/serial/bfin_5xx.c (4039 => 4040)
--- branches/2007R1/drivers/serial/bfin_5xx.c 2007-12-13 03:00:41 UTC (rev 4039)
+++ branches/2007R1/drivers/serial/bfin_5xx.c 2007-12-13 19:20:47 UTC (rev 4040)
@@ -182,6 +182,14 @@
}
#endif
+#if defined(ANOMALY_05000230) && defined(CONFIG_SERIAL_BFIN_PIO)
+# define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold)
+# define UART_SET_ANOMALY_THRESHOLD(uart, v) ((uart)->anomaly_threshold = (v))
+#else
+# define UART_GET_ANOMALY_THRESHOLD(uart) 0
+# define UART_SET_ANOMALY_THRESHOLD(uart, v)
+#endif
+
#ifdef CONFIG_SERIAL_BFIN_PIO
static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
{
@@ -190,8 +198,8 @@
#ifdef CONFIG_KGDB_UART
struct pt_regs *regs = get_irq_regs();
#endif
-#ifdef BF533_FAMILY
- static int in_break = 0;
+#ifdef ANOMALY_05000230
+ static struct timeval anomaly_start = { .tv_sec = 0 };
#endif
status = UART_GET_LSR(uart);
@@ -218,28 +226,58 @@
}
}
#endif
-
-#ifdef BF533_FAMILY
- /* The BF533 family of processors have a nice misbehavior where
- * they continuously generate characters for a "single" break.
+
+#ifdef ANOMALY_05000230
+ /* The BF533 (and BF561) family of processors have a nice anomaly
+ * where they continuously generate characters for a "single" break.
* We have to basically ignore this flood until the "next" valid
- * character comes across. All other Blackfin families operate
- * properly though.
+ * character comes across. Due to the nature of the flood, it is
+ * not possible to reliably catch bytes that are sent too quickly
+ * after this break. So application code talking to the Blackfin
+ * which sends a break signal must allow at least 1.5 character
+ * times after the end of the break for things to stabilize. This
+ * timeout was picked as it must absolutely be larger than 1
+ * character time +/- some percent. So 1.5 sounds good. All other
+ * Blackfin families operate properly. Woo.
+ * Note: While Anomaly 05000230 does not directly address this,
+ * the changes that went in for it also fixed this issue.
+ * That anomaly was fixed in 0.5+ silicon. I like bunnies.
*/
- if (in_break) {
- if (ch != 0) {
- in_break = 0;
- ch = UART_GET_CHAR(uart);
- if (bfin_revid() < 5)
- return;
- } else
- return;
+ if (anomaly_start.tv_sec) {
+ struct timeval curr;
+ suseconds_t usecs;
+
+ if ((~ch & (~ch + 1)) & 0xff)
+ goto known_good_char;
+
+ do_gettimeofday(&curr);
+ if (curr.tv_sec - anomaly_start.tv_sec > 1)
+ goto known_good_char;
+
+ usecs = 0;
+ if (curr.tv_sec != anomaly_start.tv_sec)
+ usecs += USEC_PER_SEC;
+ usecs += curr.tv_usec - anomaly_start.tv_usec;
+
+ if (usecs > UART_GET_ANOMALY_THRESHOLD(uart))
+ goto known_good_char;
+
+ if (ch)
+ anomaly_start.tv_sec = 0;
+ else
+ anomaly_start = curr;
+
+ return;
+
+ known_good_char:
+ anomaly_start.tv_sec = 0;
}
#endif
if (status & BI) {
-#ifdef BF533_FAMILY
- in_break = 1;
+#ifdef ANOMALY_05000230
+ if (bfin_revid() < 5)
+ do_gettimeofday(&anomaly_start);
#endif
uart->port.icount.brk++;
if (uart_handle_break(&uart->port))
@@ -730,6 +768,8 @@
quot = uart_get_divisor(port, baud);
spin_lock_irqsave(&uart->port.lock, flags);
+ UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
+
do {
lsr = UART_GET_LSR(uart);
} while (!(lsr & TEMT));
Modified: branches/2007R1/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h (4039 => 4040)
--- branches/2007R1/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h 2007-12-13 03:00:41 UTC (rev 4039)
+++ branches/2007R1/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h 2007-12-13 19:20:47 UTC (rev 4040)
@@ -56,6 +56,9 @@
struct work_struct tx_dma_workqueue;
#else
struct work_struct cts_workqueue;
+# ifdef ANOMALY_05000230
+ unsigned int anomaly_threshold;
+# endif
#endif
#ifdef CONFIG_SERIAL_BFIN_CTSRTS
int cts_pin;
Modified: branches/2007R1/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h (4039 => 4040)
--- branches/2007R1/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h 2007-12-13 03:00:41 UTC (rev 4039)
+++ branches/2007R1/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h 2007-12-13 19:20:47 UTC (rev 4040)
@@ -56,6 +56,9 @@
struct work_struct tx_dma_workqueue;
#else
struct work_struct cts_workqueue;
+# ifdef ANOMALY_05000230
+ unsigned int anomaly_threshold;
+# endif
#endif
#ifdef CONFIG_SERIAL_BFIN_CTSRTS
int cts_pin;
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
http://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits