diff options
Diffstat (limited to 'meta/packages/linux/linux-rp-2.6.17/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch')
-rw-r--r-- | meta/packages/linux/linux-rp-2.6.17/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/meta/packages/linux/linux-rp-2.6.17/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch b/meta/packages/linux/linux-rp-2.6.17/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.17/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch | |||
@@ -0,0 +1,155 @@ | |||
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 | _ | ||