linux-openzaurus: Add non-standard xtals patch from -mm to 2.6.14-git3;
authorJonathan McDowell <noodles@earth.li>
Tue, 1 Nov 2005 19:54:20 +0000 (19:54 +0000)
committerOpenEmbedded Project <openembedded-devel@lists.openembedded.org>
Tue, 1 Nov 2005 19:54:20 +0000 (19:54 +0000)
required for working Billionton Bluetooth CF support.

packages/linux/linux-openzaurus-2.6.14-git3/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch [new file with mode: 0644]
packages/linux/linux-openzaurus_2.6.14-git3.bb

diff --git a/packages/linux/linux-openzaurus-2.6.14-git3/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch b/packages/linux/linux-openzaurus-2.6.14-git3/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch
new file mode 100644 (file)
index 0000000..18bf426
--- /dev/null
@@ -0,0 +1,155 @@
+
+From: Petr Vandrovec <vandrove@vc.cvut.cz>
+
+Patch below adds support for using different prescaler than 16 for 16c950
+chips.  This is needed for using Fujitsu-Siemens Connect2Air compact-flash
+card, which comes (apparently) with 806kHz clocks, and so you have to
+program prescaler for division by 7, and DLAB to 1, to get 115200Bd.  
+
+To get card properly running you also have to add lines below to
+/etc/pcmcia/serial.opts so kernel knows that base speed is not 115200 but
+50400 (50400 * 16 = 806400; 806400 / 7 = 115200).  As I've found no code
+specifying baud_rate in serial_cs, I assume that specifying it in
+serial.opts is right way to do this type of things.
+
+Patch also fixes problem that for UPF_MAGIC_MULTIPLIER maximum possible
+baud rate passed to uart code was uartclk / 16 while correct value for
+these devices (and for 16c950) is uartclk / 4.
+
+Patch also fixes problem that for UPF_MAGIC_MULTIPLIER devices with
+baud_rate 19200 or 9600 spd_cust did not work correctly.  Not that such
+devices exist, but we should not ignore spd_cust, user probably knows why
+he asked for spd_cust.
+
+serial.opts:
+
+case "$MANFID-$FUNCID-$PRODID_1-$PRODID_2-$PRODID_3-$PRODID_4" in
+'0279,950b-2-GPRS Modem---')
+    SERIAL_OPTS="baud_base 50400"
+    ;;
+esac
+
+Cc: David Woodhouse <dwmw2@infradead.org>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+---
+
+ drivers/serial/8250.c |   82 +++++++++++++++++++++++++++++++++++++++-----------
+ 1 files changed, 64 insertions(+), 18 deletions(-)
+
+diff -puN drivers/serial/8250.c~serial-add-support-for-non-standard-xtals-to-16c950-driver drivers/serial/8250.c
+--- devel/drivers/serial/8250.c~serial-add-support-for-non-standard-xtals-to-16c950-driver     2005-09-12 03:34:57.000000000 -0700
++++ devel-akpm/drivers/serial/8250.c   2005-09-12 03:34:57.000000000 -0700
+@@ -1653,24 +1653,58 @@ static void serial8250_shutdown(struct u
+               serial_unlink_irq_chain(up);
+ }
+-static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
++static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud,
++                                         unsigned int *prescaler)
+ {
+-      unsigned int quot;
+-
+-      /*
+-       * Handle magic divisors for baud rates above baud_base on
+-       * SMSC SuperIO chips.
++        /*
++       * Use special handling only if user did not supply its own divider.
++       * spd_cust is defined in terms of baud_base, so always use default
++       * prescaler when spd_cust is requested.
+        */
+-      if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+-          baud == (port->uartclk/4))
+-              quot = 0x8001;
+-      else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+-               baud == (port->uartclk/8))
+-              quot = 0x8002;
+-      else
+-              quot = uart_get_divisor(port, baud);
+-      return quot;
++      *prescaler = 16;
++        if (baud != 38400 || (port->flags & UPF_SPD_MASK) != UPF_SPD_CUST) {
++              unsigned int quot = port->uartclk / baud;
++
++              /*
++               * Handle magic divisors for baud rates above baud_base on
++               * SMSC SuperIO chips.
++               */
++              if (port->flags & UPF_MAGIC_MULTIPLIER) {
++                      if (quot == 4) {
++                              return 0x8001;
++                      } else if (quot == 8) {
++                              return 0x8002;
++                      }
++              }
++              if (port->type == PORT_16C950) {
++                      /*
++                       * This computes TCR value (4 to 16), not CPR value (which can
++                       * be between 1.000 and 31.875) - chip I have uses XTAL of
++                       * 806400Hz, and so a division by 7 is required to get 115200Bd.
++                       * I'm leaving CPR disabled for now, until someone will
++                       * hit even more exotic XTAL (it is needed to get 500kbps
++                       * or 1000kbps from 18.432MHz XTAL, but I have no device
++                       * which would benefit from doing that).
++                       *
++                       * If we can use divide by 16, use it.  Otherwise look for
++                       * better prescaler, from 15 to 4.  If quotient cannot
++                       * be divided by any integer value between 4 and 15, use 4.
++                       */
++                      if (quot & 0x0F) {
++                              unsigned int div;
++
++                              for (div = 15; div > 4; div--) {
++                                      if (quot % div == 0) {
++                                              break;
++                                      }
++                              }
++                              *prescaler = div;
++                              return quot / div;
++                      }
++              }
++      }
++      return uart_get_divisor(port, baud);
+ }
+ static void
+@@ -1680,7 +1714,7 @@ serial8250_set_termios(struct uart_port 
+       struct uart_8250_port *up = (struct uart_8250_port *)port;
+       unsigned char cval, fcr = 0;
+       unsigned long flags;
+-      unsigned int baud, quot;
++      unsigned int baud, quot, prescaler;
+       switch (termios->c_cflag & CSIZE) {
+       case CS5:
+@@ -1712,8 +1746,13 @@ serial8250_set_termios(struct uart_port 
+       /*
+        * Ask the core to calculate the divisor for us.
+        */
+-      baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
+-      quot = serial8250_get_divisor(port, baud);
++
++      if (port->type == PORT_16C950 || (port->flags & UPF_MAGIC_MULTIPLIER)) {
++              baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/4);
++      } else {
++              baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
++      }
++      quot = serial8250_get_divisor(port, baud, &prescaler);
+       /*
+        * Oxford Semi 952 rev B workaround
+@@ -1817,6 +1856,13 @@ serial8250_set_termios(struct uart_port 
+       serial_outp(up, UART_DLM, quot >> 8);           /* MS of divisor */
+       /*
++       * Program prescaler for 16C950 chips.
++       */
++      if (up->port.type == PORT_16C950) {
++              serial_icr_write(up, UART_TCR, prescaler == 16 ? 0 : prescaler);
++      }
++
++      /*
+        * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
+        * is written without DLAB set, this mode will be disabled.
+        */
+_
index 653d549..3e75a82 100644 (file)
@@ -68,6 +68,7 @@ SRC_URI = "ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.14.tar.gz \
            file://pxa-serial-hack.patch;patch=1 \
            ${RPSRC}/jl1/pxa-linking-bug.patch;patch=1 \
            file://dtl1_cs-add-socket-revE.patch;patch=1 \
+          file://serial-add-support-for-non-standard-xtals-to-16c950-driver.patch;patch=1 \
            file://connectplus-remove-ide-HACK.patch;patch=1 \
            file://defconfig-c7x0 \
            file://defconfig-ipaq-pxa270 \