public inbox for ecos-patches@sourceware.org
 help / color / mirror / Atom feed
From: "Rene Nielsen" <rbn@vitesse.com>
To: <ecos-patches@sourceware.org>
Subject: Fix of Synopsys DesignWare Bug in Serial Driver
Date: Thu, 12 Feb 2009 10:11:00 -0000	[thread overview]
Message-ID: <376637F07F8A9242AD11921B15FA17DC8AF28A@mx-dk.vsc.vitesse.com> (raw)

The following patch circumvents a bug in the Synopsys DesignWare
16550-compatible UART.
The UART would (a.o.) hang if a character is received while the
baud-rate is being reconfigured.
 
Regards,
Rene Schipp von Branitz Nielsen
Vitesse Semiconductors

Index: ser_16x5x.c
===================================================================
RCS file:
/cvs/ecos/ecos/packages/devs/serial/generic/16x5x/current/src/ser_16x5x.
c,v
retrieving revision 1.17
diff -u -r1.17 ser_16x5x.c
--- ser_16x5x.c 29 Jan 2009 17:48:39 -0000      1.17
+++ ser_16x5x.c 12 Feb 2009 10:05:07 -0000
@@ -77,6 +77,10 @@
 #define REG_msr SER_REG(6)    // Modem status register
 #define REG_scr SER_REG(7)    // Scratch register
 
+#if CYGPKG_IO_SERIAL_GENERIC_16X5X_SYNOPSYS_DESIGNWARE
+#define REG_usr SER_REG(0x1F) // UART status register
+#endif
+
 // Transmit control Registers
 #define REG_thr SER_REG(0)    // Transmit holding register
 #define REG_ier SER_REG(1)    // Interrupt enable register
@@ -129,6 +133,9 @@
 #define ISR_Tx        0x02
 #define ISR_Rx        0x04
 #define ISR_LS        0x06
+#if CYGPKG_IO_SERIAL_GENERIC_16X5X_SYNOPSYS_DESIGNWARE
+#define ISR_BUSY      0x07
+#endif
 #define ISR_RxTO      0x0C
 #define ISR_64BFIFO   0x20
 #define ISR_FIFOworks 0x40
@@ -259,10 +266,39 @@
     _lcr = select_word_length[new_config->word_length -
CYGNUM_SERIAL_WORD_LENGTH_5] | 
         select_stop_bits[new_config->stop] |
         select_parity[new_config->parity];
+   
+#if CYGPKG_IO_SERIAL_GENERIC_16X5X_SYNOPSYS_DESIGNWARE
+    while(1) {
+        // Gotta wait until the LCR_DL bit is set.
+        unsigned char _lcr_rd, _usr;
+        HAL_WRITE_UINT8(base+REG_lcr, _lcr | LCR_DL);
+        HAL_READ_UINT8(base+REG_lcr, _lcr_rd);
+        if(_lcr_rd & LCR_DL)
+            break;
+        // Read the USR to clear any busy interrupts
+        HAL_READ_UINT8(base+REG_usr, _usr);
+    }
+#else
     HAL_WRITE_UINT8(base+REG_lcr, _lcr | LCR_DL);
+#endif
+
     HAL_WRITE_UINT8(base+REG_mdl, baud_divisor >> 8);
     HAL_WRITE_UINT8(base+REG_ldl, baud_divisor & 0xFF);
+
+#if CYGPKG_IO_SERIAL_GENERIC_16X5X_SYNOPSYS_DESIGNWARE
+    while(1) {
+        unsigned char _lcr_rd, _usr;
+        HAL_WRITE_UINT8(base+REG_lcr, _lcr);
+        HAL_READ_UINT8(base+REG_lcr, _lcr_rd);
+        if(!(_lcr_rd & LCR_DL))
+            break;
+        // Read the USR to clear any busy interrupts
+        HAL_READ_UINT8(base+REG_usr, _usr);
+    }
+#else
     HAL_WRITE_UINT8(base+REG_lcr, _lcr);
+#endif
+
     if (init) {
 #ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
         unsigned char _fcr_thresh;
@@ -581,6 +617,19 @@
     // Check if we have an interrupt pending - note that the interrupt
     // is pending of the low bit of the isr is *0*, not 1.
     HAL_READ_UINT8(base+REG_isr, _isr);
+
+#if CYGPKG_IO_SERIAL_GENERIC_16X5X_SYNOPSYS_DESIGNWARE
+    if(_isr & ISR_BUSY) {
+        // This must be checked before the loop below, because
+        // the LSBit is set in the ISR_BUSY mask.
+        // Read uart status register to clear this interrupt, which
+        // may occur if writing to the LCR register while the UART is
busy.
+        cyg_uint8 _usr;
+        HAL_READ_UINT8(base+REG_usr, _usr);
+        HAL_READ_UINT8(base+REG_isr, _isr);
+    }
+#endif
+
     while ((_isr & ISR_nIP) == 0) {
         switch (_isr&0xE) {
         case ISR_Rx:


Index: ser_generic_16x5x.cdl
===================================================================
RCS file:
/cvs/ecos/ecos/packages/devs/serial/generic/16x5x/current/cdl/ser_generi
c_16x5x.cdl,v
retrieving revision 1.10
diff -u -r1.10 ser_generic_16x5x.cdl
--- ser_generic_16x5x.cdl       29 Jan 2009 17:48:39 -0000      1.10
+++ ser_generic_16x5x.cdl       12 Feb 2009 10:06:21 -0000
@@ -121,6 +121,19 @@
                Configures the maximum number of bytes written to the
                16x5x UART transmit FIFO when the TX interrupt occurs."
        }
+        
+    cdl_option CYGPKG_IO_SERIAL_GENERIC_16X5X_SYNOPSYS_DESIGNWARE {
+        display       "16x5x UART is from Synopsys"
+        flavor        bool
+        default_value 0
+        description   "
+            In designs using Synopsys's DesignWare APB UART v.3.04a or
+            earlier, or v.3.05a or later with UART_16550_COMPATIBLE set
+            to 'No', the UART's busy-functionality may cause the UART
+            to hang when programming new divisors while receiving a
+            character. Enabling this option fixes this problem."
+    }
+
     }
             
     cdl_component CYGPKG_IO_SERIAL_GENERIC_16X5X_OPTIONS {

             reply	other threads:[~2009-02-12 10:11 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-12 10:11 Rene Nielsen [this message]
2009-02-16 22:32 ` Jonathan Larmour
2009-02-16 22:34   ` Jonathan Larmour
2009-02-17 22:54   ` Rene Nielsen
2009-02-19  1:03     ` Jonathan Larmour

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=376637F07F8A9242AD11921B15FA17DC8AF28A@mx-dk.vsc.vitesse.com \
    --to=rbn@vitesse.com \
    --cc=ecos-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).