Root/target/linux/xburst/patches-2.6.32/103-serial.patch

1From 5b3f9de4171368d9a99fa4c8b8b1bcc8505fb3c6 Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Mon, 11 Jan 2010 04:29:44 +0100
4Subject: [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
174

Archive Download this file



interactive