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 {
next 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).