aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-2.6.31/ben-nanonote/103-serial.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-2.6.31/ben-nanonote/103-serial.patch')
-rw-r--r--recipes/linux/linux-2.6.31/ben-nanonote/103-serial.patch164
1 files changed, 164 insertions, 0 deletions
diff --git a/recipes/linux/linux-2.6.31/ben-nanonote/103-serial.patch b/recipes/linux/linux-2.6.31/ben-nanonote/103-serial.patch
new file mode 100644
index 0000000000..d6b4ea8444
--- /dev/null
+++ b/recipes/linux/linux-2.6.31/ben-nanonote/103-serial.patch
@@ -0,0 +1,164 @@
+--- a/drivers/serial/8250.c
++++ b/drivers/serial/8250.c
+@@ -194,7 +194,7 @@ static const struct serial8250_config ua
+ [PORT_16550A] = {
+ .name = "16550A",
+ .fifo_size = 16,
+- .tx_loadsz = 16,
++ .tx_loadsz = 8,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO,
+ },
+@@ -401,6 +401,10 @@ static unsigned int mem_serial_in(struct
+ static void mem_serial_out(struct uart_port *p, int offset, int value)
+ {
+ offset = map_8250_out_reg(p, offset) << p->regshift;
++#if defined(CONFIG_JZSOC)
++ if (offset == (UART_FCR << p->regshift))
++ value |= 0x10; /* set FCR.UUE */
++#endif
+ writeb(value, p->membase + offset);
+ }
+
+@@ -2213,6 +2217,83 @@ static void serial8250_shutdown(struct u
+ serial_unlink_irq_chain(up);
+ }
+
++#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
++static unsigned short quot1[3] = {0}; /* quot[0]:baud_div, quot[1]:umr, quot[2]:uacr */
++static unsigned short * serial8250_get_divisor(struct uart_port *port, unsigned int baud)
++{
++ int err, sum, i, j;
++ int a[12], b[12];
++ unsigned short div, umr, uacr;
++ unsigned short umr_best, div_best, uacr_best;
++ long long t0, t1, t2, t3;
++
++ sum = 0;
++ umr_best = div_best = uacr_best = 0;
++ div = 1;
++
++ if ((port->uartclk % (16 * baud)) == 0) {
++ quot1[0] = port->uartclk / (16 * baud);
++ quot1[1] = 16;
++ quot1[2] = 0;
++ return quot1;
++ }
++
++ while (1) {
++ umr = port->uartclk / (baud * div);
++ if (umr > 32) {
++ div++;
++ continue;
++ }
++ if (umr < 4) {
++ break;
++ }
++ for (i = 0; i < 12; i++) {
++ a[i] = umr;
++ b[i] = 0;
++ sum = 0;
++ for (j = 0; j <= i; j++) {
++ sum += a[j];
++ }
++
++ /* the precision could be 1/2^(36) due to the value of t0 */
++ t0 = 0x1000000000LL;
++ t1 = (i + 1) * t0;
++ t2 = (sum * div) * t0;
++ t3 = div * t0;
++ do_div(t1, baud);
++ do_div(t2, port->uartclk);
++ do_div(t3, (2 * port->uartclk));
++ err = t1 - t2 - t3;
++
++ if (err > 0) {
++ a[i] += 1;
++ b[i] = 1;
++ }
++ }
++
++ uacr = 0;
++ for (i = 0; i < 12; i++) {
++ if (b[i] == 1) {
++ uacr |= 1 << i;
++ }
++ }
++
++ /* the best value of umr should be near 16, and the value of uacr should better be smaller */
++ if (abs(umr - 16) < abs(umr_best - 16) || (abs(umr - 16) == abs(umr_best - 16) && uacr_best > uacr)) {
++ div_best = div;
++ umr_best = umr;
++ uacr_best = uacr;
++ }
++ div++;
++ }
++
++ quot1[0] = div_best;
++ quot1[1] = umr_best;
++ quot1[2] = uacr_best;
++
++ return quot1;
++}
++#else
+ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
+ {
+ unsigned int quot;
+@@ -2232,6 +2313,7 @@ static unsigned int serial8250_get_divis
+
+ return quot;
+ }
++#endif
+
+ static void
+ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
+@@ -2241,6 +2323,9 @@ serial8250_set_termios(struct uart_port
+ unsigned char cval, fcr = 0;
+ unsigned long flags;
+ unsigned int baud, quot;
++#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
++ unsigned short *quot1;
++#endif
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+@@ -2273,7 +2358,12 @@ serial8250_set_termios(struct uart_port
+ * Ask the core to calculate the divisor for us.
+ */
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
++#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
++ quot1 = serial8250_get_divisor(port, baud);
++ quot = quot1[0]; /* not usefull, just let gcc happy */
++#else
+ quot = serial8250_get_divisor(port, baud);
++#endif
+
+ /*
+ * Oxford Semi 952 rev B workaround
+@@ -2351,6 +2441,10 @@ serial8250_set_termios(struct uart_port
+ if (up->capabilities & UART_CAP_UUE)
+ up->ier |= UART_IER_UUE | UART_IER_RTOIE;
+
++#ifdef CONFIG_JZSOC
++ up->ier |= UART_IER_RTOIE; /* Set this flag, or very slow */
++#endif
++
+ serial_out(up, UART_IER, up->ier);
+
+ if (up->capabilities & UART_CAP_EFR) {
+@@ -2385,7 +2479,15 @@ serial8250_set_termios(struct uart_port
+ serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
+ }
+
++#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
++#define UART_UMR 9
++#define UART_UACR 10
++ serial_dl_write(up, quot1[0]);
++ serial_outp(up, UART_UMR, quot1[1]);
++ serial_outp(up, UART_UACR, quot1[2]);
++#else
+ serial_dl_write(up, quot);
++#endif
+
+ /*
+ * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR