summaryrefslogtreecommitdiffstats
path: root/meta/packages/linux/linux-rp-2.6.19+2.6.20-rc4/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/packages/linux/linux-rp-2.6.19+2.6.20-rc4/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch')
-rw-r--r--meta/packages/linux/linux-rp-2.6.19+2.6.20-rc4/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch155
1 files changed, 155 insertions, 0 deletions
diff --git a/meta/packages/linux/linux-rp-2.6.19+2.6.20-rc4/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch b/meta/packages/linux/linux-rp-2.6.19+2.6.20-rc4/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch
new file mode 100644
index 0000000000..18bf4268fc
--- /dev/null
+++ b/meta/packages/linux/linux-rp-2.6.19+2.6.20-rc4/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch
@@ -0,0 +1,155 @@
1
2From: Petr Vandrovec <vandrove@vc.cvut.cz>
3
4Patch below adds support for using different prescaler than 16 for 16c950
5chips. This is needed for using Fujitsu-Siemens Connect2Air compact-flash
6card, which comes (apparently) with 806kHz clocks, and so you have to
7program prescaler for division by 7, and DLAB to 1, to get 115200Bd.
8
9To 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
1150400 (50400 * 16 = 806400; 806400 / 7 = 115200). As I've found no code
12specifying baud_rate in serial_cs, I assume that specifying it in
13serial.opts is right way to do this type of things.
14
15Patch also fixes problem that for UPF_MAGIC_MULTIPLIER maximum possible
16baud rate passed to uart code was uartclk / 16 while correct value for
17these devices (and for 16c950) is uartclk / 4.
18
19Patch also fixes problem that for UPF_MAGIC_MULTIPLIER devices with
20baud_rate 19200 or 9600 spd_cust did not work correctly. Not that such
21devices exist, but we should not ignore spd_cust, user probably knows why
22he asked for spd_cust.
23
24serial.opts:
25
26case "$MANFID-$FUNCID-$PRODID_1-$PRODID_2-$PRODID_3-$PRODID_4" in
27'0279,950b-2-GPRS Modem---')
28 SERIAL_OPTS="baud_base 50400"
29 ;;
30esac
31
32Cc: David Woodhouse <dwmw2@infradead.org>
33Signed-off-by: Andrew Morton <akpm@osdl.org>
34---
35
36 drivers/serial/8250.c | 82 +++++++++++++++++++++++++++++++++++++++-----------
37 1 files changed, 64 insertions(+), 18 deletions(-)
38
39diff -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_