conf/distro/jlime-donkey.conf : Added parted & Dialog to distro_rdepends
[vuplus_openembedded] / packages / linux / linux-openzaurus-2.6.17 / serial-add-support-for-non-standard-xtals-to-16c950-driver.patch
1
2 From: Petr Vandrovec <vandrove@vc.cvut.cz>
3
4 Patch below adds support for using different prescaler than 16 for 16c950
5 chips.  This is needed for using Fujitsu-Siemens Connect2Air compact-flash
6 card, which comes (apparently) with 806kHz clocks, and so you have to
7 program prescaler for division by 7, and DLAB to 1, to get 115200Bd.  
8
9 To get card properly running you also have to add lines below to
10 /etc/pcmcia/serial.opts so kernel knows that base speed is not 115200 but
11 50400 (50400 * 16 = 806400; 806400 / 7 = 115200).  As I've found no code
12 specifying baud_rate in serial_cs, I assume that specifying it in
13 serial.opts is right way to do this type of things.
14
15 Patch also fixes problem that for UPF_MAGIC_MULTIPLIER maximum possible
16 baud rate passed to uart code was uartclk / 16 while correct value for
17 these devices (and for 16c950) is uartclk / 4.
18
19 Patch also fixes problem that for UPF_MAGIC_MULTIPLIER devices with
20 baud_rate 19200 or 9600 spd_cust did not work correctly.  Not that such
21 devices exist, but we should not ignore spd_cust, user probably knows why
22 he asked for spd_cust.
23
24 serial.opts:
25
26 case "$MANFID-$FUNCID-$PRODID_1-$PRODID_2-$PRODID_3-$PRODID_4" in
27 '0279,950b-2-GPRS Modem---')
28     SERIAL_OPTS="baud_base 50400"
29     ;;
30 esac
31
32 Cc: David Woodhouse <dwmw2@infradead.org>
33 Signed-off-by: Andrew Morton <akpm@osdl.org>
34 ---
35
36  drivers/serial/8250.c |   82 +++++++++++++++++++++++++++++++++++++++-----------
37  1 files changed, 64 insertions(+), 18 deletions(-)
38
39 diff -puN drivers/serial/8250.c~serial-add-support-for-non-standard-xtals-to-16c950-driver drivers/serial/8250.c
40 --- devel/drivers/serial/8250.c~serial-add-support-for-non-standard-xtals-to-16c950-driver      2005-09-12 03:34:57.000000000 -0700
41 +++ devel-akpm/drivers/serial/8250.c    2005-09-12 03:34:57.000000000 -0700
42 @@ -1653,24 +1653,58 @@ static void serial8250_shutdown(struct u
43                 serial_unlink_irq_chain(up);
44  }
45  
46 -static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
47 +static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud,
48 +                                          unsigned int *prescaler)
49  {
50 -       unsigned int quot;
51 -
52 -       /*
53 -        * Handle magic divisors for baud rates above baud_base on
54 -        * SMSC SuperIO chips.
55 +        /*
56 +        * Use special handling only if user did not supply its own divider.
57 +        * spd_cust is defined in terms of baud_base, so always use default
58 +        * prescaler when spd_cust is requested.
59          */
60 -       if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
61 -           baud == (port->uartclk/4))
62 -               quot = 0x8001;
63 -       else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
64 -                baud == (port->uartclk/8))
65 -               quot = 0x8002;
66 -       else
67 -               quot = uart_get_divisor(port, baud);
68  
69 -       return quot;
70 +       *prescaler = 16;
71 +        if (baud != 38400 || (port->flags & UPF_SPD_MASK) != UPF_SPD_CUST) {
72 +               unsigned int quot = port->uartclk / baud;
73 +
74 +               /*
75 +                * Handle magic divisors for baud rates above baud_base on
76 +                * SMSC SuperIO chips.
77 +                */
78 +               if (port->flags & UPF_MAGIC_MULTIPLIER) {
79 +                       if (quot == 4) {
80 +                               return 0x8001;
81 +                       } else if (quot == 8) {
82 +                               return 0x8002;
83 +                       }
84 +               }
85 +               if (port->type == PORT_16C950) {
86 +                       /*
87 +                        * This computes TCR value (4 to 16), not CPR value (which can
88 +                        * be between 1.000 and 31.875) - chip I have uses XTAL of
89 +                        * 806400Hz, and so a division by 7 is required to get 115200Bd.
90 +                        * I'm leaving CPR disabled for now, until someone will
91 +                        * hit even more exotic XTAL (it is needed to get 500kbps
92 +                        * or 1000kbps from 18.432MHz XTAL, but I have no device
93 +                        * which would benefit from doing that).
94 +                        *
95 +                        * If we can use divide by 16, use it.  Otherwise look for
96 +                        * better prescaler, from 15 to 4.  If quotient cannot
97 +                        * be divided by any integer value between 4 and 15, use 4.
98 +                        */
99 +                       if (quot & 0x0F) {
100 +                               unsigned int div;
101 +
102 +                               for (div = 15; div > 4; div--) {
103 +                                       if (quot % div == 0) {
104 +                                               break;
105 +                                       }
106 +                               }
107 +                               *prescaler = div;
108 +                               return quot / div;
109 +                       }
110 +               }
111 +       }
112 +       return uart_get_divisor(port, baud);
113  }
114  
115  static void
116 @@ -1680,7 +1714,7 @@ serial8250_set_termios(struct uart_port 
117         struct uart_8250_port *up = (struct uart_8250_port *)port;
118         unsigned char cval, fcr = 0;
119         unsigned long flags;
120 -       unsigned int baud, quot;
121 +       unsigned int baud, quot, prescaler;
122  
123         switch (termios->c_cflag & CSIZE) {
124         case CS5:
125 @@ -1712,8 +1746,13 @@ serial8250_set_termios(struct uart_port 
126         /*
127          * Ask the core to calculate the divisor for us.
128          */
129 -       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
130 -       quot = serial8250_get_divisor(port, baud);
131 +
132 +       if (port->type == PORT_16C950 || (port->flags & UPF_MAGIC_MULTIPLIER)) {
133 +               baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/4);
134 +       } else {
135 +               baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
136 +       }
137 +       quot = serial8250_get_divisor(port, baud, &prescaler);
138  
139         /*
140          * Oxford Semi 952 rev B workaround
141 @@ -1817,6 +1856,13 @@ serial8250_set_termios(struct uart_port 
142         serial_outp(up, UART_DLM, quot >> 8);           /* MS of divisor */
143  
144         /*
145 +        * Program prescaler for 16C950 chips.
146 +        */
147 +       if (up->port.type == PORT_16C950) {
148 +               serial_icr_write(up, UART_TCR, prescaler == 16 ? 0 : prescaler);
149 +       }
150 +
151 +       /*
152          * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
153          * is written without DLAB set, this mode will be disabled.
154          */
155 _