[kernel] refresh 2.6.32 patches
[openwrt.git] / target / linux / xburst / patches-2.6.32 / 103-serial.patch
1 From 5b3f9de4171368d9a99fa4c8b8b1bcc8505fb3c6 Mon Sep 17 00:00:00 2001
2 From: Lars-Peter Clausen <lars@metafoo.de>
3 Date: Mon, 11 Jan 2010 04:29:44 +0100
4 Subject: [PATCH] /opt/Projects/openwrt/target/linux/xburst/patches-2.6.31/103-serial.patch
5
6 ---
7 drivers/serial/8250.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++-
8 1 files changed, 103 insertions(+), 1 deletions(-)
9
10 --- a/drivers/serial/8250.c
11 +++ b/drivers/serial/8250.c
12 @@ -199,7 +199,7 @@ static const struct serial8250_config ua
13 [PORT_16550A] = {
14 .name = "16550A",
15 .fifo_size = 16,
16 - .tx_loadsz = 16,
17 + .tx_loadsz = 8,
18 .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
19 .flags = UART_CAP_FIFO,
20 },
21 @@ -406,6 +406,10 @@ static unsigned int mem_serial_in(struct
22 static void mem_serial_out(struct uart_port *p, int offset, int value)
23 {
24 offset = map_8250_out_reg(p, offset) << p->regshift;
25 +#if defined(CONFIG_JZSOC)
26 + if (offset == (UART_FCR << p->regshift))
27 + value |= 0x10; /* set FCR.UUE */
28 +#endif
29 writeb(value, p->membase + offset);
30 }
31
32 @@ -2214,6 +2218,83 @@ static void serial8250_shutdown(struct u
33 serial_unlink_irq_chain(up);
34 }
35
36 +#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
37 +static unsigned short quot1[3] = {0}; /* quot[0]:baud_div, quot[1]:umr, quot[2]:uacr */
38 +static unsigned short * serial8250_get_divisor(struct uart_port *port, unsigned int baud)
39 +{
40 + int err, sum, i, j;
41 + int a[12], b[12];
42 + unsigned short div, umr, uacr;
43 + unsigned short umr_best, div_best, uacr_best;
44 + long long t0, t1, t2, t3;
45 +
46 + sum = 0;
47 + umr_best = div_best = uacr_best = 0;
48 + div = 1;
49 +
50 + if ((port->uartclk % (16 * baud)) == 0) {
51 + quot1[0] = port->uartclk / (16 * baud);
52 + quot1[1] = 16;
53 + quot1[2] = 0;
54 + return quot1;
55 + }
56 +
57 + while (1) {
58 + umr = port->uartclk / (baud * div);
59 + if (umr > 32) {
60 + div++;
61 + continue;
62 + }
63 + if (umr < 4) {
64 + break;
65 + }
66 + for (i = 0; i < 12; i++) {
67 + a[i] = umr;
68 + b[i] = 0;
69 + sum = 0;
70 + for (j = 0; j <= i; j++) {
71 + sum += a[j];
72 + }
73 +
74 + /* the precision could be 1/2^(36) due to the value of t0 */
75 + t0 = 0x1000000000LL;
76 + t1 = (i + 1) * t0;
77 + t2 = (sum * div) * t0;
78 + t3 = div * t0;
79 + do_div(t1, baud);
80 + do_div(t2, port->uartclk);
81 + do_div(t3, (2 * port->uartclk));
82 + err = t1 - t2 - t3;
83 +
84 + if (err > 0) {
85 + a[i] += 1;
86 + b[i] = 1;
87 + }
88 + }
89 +
90 + uacr = 0;
91 + for (i = 0; i < 12; i++) {
92 + if (b[i] == 1) {
93 + uacr |= 1 << i;
94 + }
95 + }
96 +
97 + /* the best value of umr should be near 16, and the value of uacr should better be smaller */
98 + if (abs(umr - 16) < abs(umr_best - 16) || (abs(umr - 16) == abs(umr_best - 16) && uacr_best > uacr)) {
99 + div_best = div;
100 + umr_best = umr;
101 + uacr_best = uacr;
102 + }
103 + div++;
104 + }
105 +
106 + quot1[0] = div_best;
107 + quot1[1] = umr_best;
108 + quot1[2] = uacr_best;
109 +
110 + return quot1;
111 +}
112 +#else
113 static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
114 {
115 unsigned int quot;
116 @@ -2233,6 +2314,7 @@ static unsigned int serial8250_get_divis
117
118 return quot;
119 }
120 +#endif
121
122 static void
123 serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
124 @@ -2242,6 +2324,9 @@ serial8250_set_termios(struct uart_port
125 unsigned char cval, fcr = 0;
126 unsigned long flags;
127 unsigned int baud, quot;
128 +#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
129 + unsigned short *quot1;
130 +#endif
131
132 switch (termios->c_cflag & CSIZE) {
133 case CS5:
134 @@ -2276,7 +2361,12 @@ serial8250_set_termios(struct uart_port
135 baud = uart_get_baud_rate(port, termios, old,
136 port->uartclk / 16 / 0xffff,
137 port->uartclk / 16);
138 +#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
139 + quot1 = serial8250_get_divisor(port, baud);
140 + quot = quot1[0]; /* not usefull, just let gcc happy */
141 +#else
142 quot = serial8250_get_divisor(port, baud);
143 +#endif
144
145 /*
146 * Oxford Semi 952 rev B workaround
147 @@ -2354,6 +2444,10 @@ serial8250_set_termios(struct uart_port
148 if (up->capabilities & UART_CAP_UUE)
149 up->ier |= UART_IER_UUE | UART_IER_RTOIE;
150
151 +#ifdef CONFIG_JZSOC
152 + up->ier |= UART_IER_RTOIE; /* Set this flag, or very slow */
153 +#endif
154 +
155 serial_out(up, UART_IER, up->ier);
156
157 if (up->capabilities & UART_CAP_EFR) {
158 @@ -2388,7 +2482,15 @@ serial8250_set_termios(struct uart_port
159 serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
160 }
161
162 +#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
163 +#define UART_UMR 9
164 +#define UART_UACR 10
165 + serial_dl_write(up, quot1[0]);
166 + serial_outp(up, UART_UMR, quot1[1]);
167 + serial_outp(up, UART_UACR, quot1[2]);
168 +#else
169 serial_dl_write(up, quot);
170 +#endif
171
172 /*
173 * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
This page took 0.060002 seconds and 5 git commands to generate.