aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2006-03-20 15:00:09 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-03-20 15:00:09 -0500
commitd358788f3f30113e49882187d794832905e42592 (patch)
tree8c796ee4bf719dad4d3947c03cef2f3fd6cb5940
parent7705a8792b0fc82fd7d4dd923724606bbfd9fb20 (diff)
[SERIAL] kernel console should send CRLF not LFCR
Glen Turner reported that writing LFCR rather than the more traditional CRLF causes issues with some terminals. Since this aflicts many serial drivers, extract the common code to a library function (uart_console_write) and arrange for each driver to supply a "putchar" function. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--drivers/serial/21285.c19
-rw-r--r--drivers/serial/8250.c26
-rw-r--r--drivers/serial/8250_early.c9
-rw-r--r--drivers/serial/amba-pl010.c24
-rw-r--r--drivers/serial/amba-pl011.c20
-rw-r--r--drivers/serial/at91_serial.c24
-rw-r--r--drivers/serial/au1x00_uart.c26
-rw-r--r--drivers/serial/clps711x.c24
-rw-r--r--drivers/serial/dz.c12
-rw-r--r--drivers/serial/imx.c26
-rw-r--r--drivers/serial/ip22zilog.c11
-rw-r--r--drivers/serial/m32r_sio.c26
-rw-r--r--drivers/serial/mpc52xx_uart.c11
-rw-r--r--drivers/serial/pmac_zilog.c23
-rw-r--r--drivers/serial/pxa.c26
-rw-r--r--drivers/serial/s3c2410.c26
-rw-r--r--drivers/serial/sa1100.c26
-rw-r--r--drivers/serial/serial_core.c21
-rw-r--r--drivers/serial/serial_lh7a40x.c17
-rw-r--r--drivers/serial/serial_txx9.c26
-rw-r--r--drivers/serial/sunsab.c10
-rw-r--r--drivers/serial/sunsu.c26
-rw-r--r--drivers/serial/sunzilog.c13
-rw-r--r--drivers/serial/vr41xx_siu.c16
-rw-r--r--include/linux/serial_core.h3
25 files changed, 190 insertions, 301 deletions
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index 8c5c276c5577..7572665a8855 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -375,23 +375,18 @@ static void serial21285_setup_ports(void)
375} 375}
376 376
377#ifdef CONFIG_SERIAL_21285_CONSOLE 377#ifdef CONFIG_SERIAL_21285_CONSOLE
378static void serial21285_console_putchar(struct uart_port *port, int ch)
379{
380 while (*CSR_UARTFLG & 0x20)
381 barrier();
382 *CSR_UARTDR = ch;
383}
378 384
379static void 385static void
380serial21285_console_write(struct console *co, const char *s, 386serial21285_console_write(struct console *co, const char *s,
381 unsigned int count) 387 unsigned int count)
382{ 388{
383 int i; 389 uart_console_write(&serial21285_port, s, count, serial21285_console_putchar);
384
385 for (i = 0; i < count; i++) {
386 while (*CSR_UARTFLG & 0x20)
387 barrier();
388 *CSR_UARTDR = s[i];
389 if (s[i] == '\n') {
390 while (*CSR_UARTFLG & 0x20)
391 barrier();
392 *CSR_UARTDR = '\r';
393 }
394 }
395} 390}
396 391
397static void __init 392static void __init
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 7aca22c9976d..5996d3cd0ed8 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2182,6 +2182,14 @@ static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
2182 } 2182 }
2183} 2183}
2184 2184
2185static void serial8250_console_putchar(struct uart_port *port, int ch)
2186{
2187 struct uart_8250_port *up = (struct uart_8250_port *)port;
2188
2189 wait_for_xmitr(up, UART_LSR_THRE);
2190 serial_out(up, UART_TX, ch);
2191}
2192
2185/* 2193/*
2186 * Print a string to the serial port trying not to disturb 2194 * Print a string to the serial port trying not to disturb
2187 * any possible real use of the port... 2195 * any possible real use of the port...
@@ -2193,7 +2201,6 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
2193{ 2201{
2194 struct uart_8250_port *up = &serial8250_ports[co->index]; 2202 struct uart_8250_port *up = &serial8250_ports[co->index];
2195 unsigned int ier; 2203 unsigned int ier;
2196 int i;
2197 2204
2198 touch_nmi_watchdog(); 2205 touch_nmi_watchdog();
2199 2206
@@ -2207,22 +2214,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
2207 else 2214 else
2208 serial_out(up, UART_IER, 0); 2215 serial_out(up, UART_IER, 0);
2209 2216
2210 /* 2217 uart_console_write(&up->port, s, count, serial8250_console_putchar);
2211 * Now, do each character
2212 */
2213 for (i = 0; i < count; i++, s++) {
2214 wait_for_xmitr(up, UART_LSR_THRE);
2215
2216 /*
2217 * Send the character out.
2218 * If a LF, also do CR...
2219 */
2220 serial_out(up, UART_TX, *s);
2221 if (*s == 10) {
2222 wait_for_xmitr(up, UART_LSR_THRE);
2223 serial_out(up, UART_TX, 13);
2224 }
2225 }
2226 2218
2227 /* 2219 /*
2228 * Finally, wait for transmitter to become empty 2220 * Finally, wait for transmitter to become empty
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
index 59ba5d993b4b..7e511199b4c5 100644
--- a/drivers/serial/8250_early.c
+++ b/drivers/serial/8250_early.c
@@ -74,7 +74,7 @@ static void __init wait_for_xmitr(struct uart_port *port)
74 } 74 }
75} 75}
76 76
77static void __init putc(struct uart_port *port, unsigned char c) 77static void __init putc(struct uart_port *port, int c)
78{ 78{
79 wait_for_xmitr(port); 79 wait_for_xmitr(port);
80 serial_out(port, UART_TX, c); 80 serial_out(port, UART_TX, c);
@@ -89,12 +89,7 @@ static void __init early_uart_write(struct console *console, const char *s, unsi
89 ier = serial_in(port, UART_IER); 89 ier = serial_in(port, UART_IER);
90 serial_out(port, UART_IER, 0); 90 serial_out(port, UART_IER, 0);
91 91
92 while (*s && count-- > 0) { 92 uart_console_write(port, s, count, putc);
93 putc(port, *s);
94 if (*s == '\n')
95 putc(port, '\r');
96 s++;
97 }
98 93
99 /* Wait for transmitter to become empty and restore the IER */ 94 /* Wait for transmitter to become empty and restore the IER */
100 wait_for_xmitr(port); 95 wait_for_xmitr(port);
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 321a3b3a5728..e04d5e82d9ae 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -591,12 +591,18 @@ static struct uart_amba_port amba_ports[UART_NR] = {
591 591
592#ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE 592#ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE
593 593
594static void pl010_console_putchar(struct uart_port *port, int ch)
595{
596 while (!UART_TX_READY(UART_GET_FR(port)))
597 barrier();
598 UART_PUT_CHAR(port, ch);
599}
600
594static void 601static void
595pl010_console_write(struct console *co, const char *s, unsigned int count) 602pl010_console_write(struct console *co, const char *s, unsigned int count)
596{ 603{
597 struct uart_port *port = &amba_ports[co->index].port; 604 struct uart_port *port = &amba_ports[co->index].port;
598 unsigned int status, old_cr; 605 unsigned int status, old_cr;
599 int i;
600 606
601 /* 607 /*
602 * First save the CR then disable the interrupts 608 * First save the CR then disable the interrupts
@@ -604,21 +610,7 @@ pl010_console_write(struct console *co, const char *s, unsigned int count)
604 old_cr = UART_GET_CR(port); 610 old_cr = UART_GET_CR(port);
605 UART_PUT_CR(port, UART01x_CR_UARTEN); 611 UART_PUT_CR(port, UART01x_CR_UARTEN);
606 612
607 /* 613 uart_console_write(port, s, count, pl010_console_putchar);
608 * Now, do each character
609 */
610 for (i = 0; i < count; i++) {
611 do {
612 status = UART_GET_FR(port);
613 } while (!UART_TX_READY(status));
614 UART_PUT_CHAR(port, s[i]);
615 if (s[i] == '\n') {
616 do {
617 status = UART_GET_FR(port);
618 } while (!UART_TX_READY(status));
619 UART_PUT_CHAR(port, '\r');
620 }
621 }
622 614
623 /* 615 /*
624 * Finally, wait for transmitter to become empty 616 * Finally, wait for transmitter to become empty
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 034a029e356e..3d966cfc9a38 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -587,14 +587,12 @@ static struct uart_amba_port *amba_ports[UART_NR];
587 587
588#ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE 588#ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE
589 589
590static inline void 590static void pl011_console_putchar(struct uart_port *port, int ch)
591pl011_console_write_char(struct uart_amba_port *uap, char ch)
592{ 591{
593 unsigned int status; 592 struct uart_amba_port *uap = (struct uart_amba_port *)port;
594 593
595 do { 594 while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
596 status = readw(uap->port.membase + UART01x_FR); 595 barrier();
597 } while (status & UART01x_FR_TXFF);
598 writew(ch, uap->port.membase + UART01x_DR); 596 writew(ch, uap->port.membase + UART01x_DR);
599} 597}
600 598
@@ -603,7 +601,6 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
603{ 601{
604 struct uart_amba_port *uap = amba_ports[co->index]; 602 struct uart_amba_port *uap = amba_ports[co->index];
605 unsigned int status, old_cr, new_cr; 603 unsigned int status, old_cr, new_cr;
606 int i;
607 604
608 clk_enable(uap->clk); 605 clk_enable(uap->clk);
609 606
@@ -615,14 +612,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
615 new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE; 612 new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
616 writew(new_cr, uap->port.membase + UART011_CR); 613 writew(new_cr, uap->port.membase + UART011_CR);
617 614
618 /* 615 uart_console_write(&uap->port, s, count, pl011_console_putchar);
619 * Now, do each character
620 */
621 for (i = 0; i < count; i++) {
622 pl011_console_write_char(uap, s[i]);
623 if (s[i] == '\n')
624 pl011_console_write_char(uap, '\r');
625 }
626 616
627 /* 617 /*
628 * Finally, wait for transmitter to become empty 618 * Finally, wait for transmitter to become empty
diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c
index 2113feb75c39..6547fe0cef96 100644
--- a/drivers/serial/at91_serial.c
+++ b/drivers/serial/at91_serial.c
@@ -711,6 +711,12 @@ void __init at91_register_uart(int idx, int port)
711} 711}
712 712
713#ifdef CONFIG_SERIAL_AT91_CONSOLE 713#ifdef CONFIG_SERIAL_AT91_CONSOLE
714static void at91_console_putchar(struct uart_port *port, int ch)
715{
716 while (!(UART_GET_CSR(port) & AT91_US_TXRDY))
717 barrier();
718 UART_PUT_CHAR(port, ch);
719}
714 720
715/* 721/*
716 * Interrupts are disabled on entering 722 * Interrupts are disabled on entering
@@ -718,7 +724,7 @@ void __init at91_register_uart(int idx, int port)
718static void at91_console_write(struct console *co, const char *s, u_int count) 724static void at91_console_write(struct console *co, const char *s, u_int count)
719{ 725{
720 struct uart_port *port = at91_ports + co->index; 726 struct uart_port *port = at91_ports + co->index;
721 unsigned int status, i, imr; 727 unsigned int status, imr;
722 728
723 /* 729 /*
724 * First, save IMR and then disable interrupts 730 * First, save IMR and then disable interrupts
@@ -726,21 +732,7 @@ static void at91_console_write(struct console *co, const char *s, u_int count)
726 imr = UART_GET_IMR(port); /* get interrupt mask */ 732 imr = UART_GET_IMR(port); /* get interrupt mask */
727 UART_PUT_IDR(port, AT91_US_RXRDY | AT91_US_TXRDY); 733 UART_PUT_IDR(port, AT91_US_RXRDY | AT91_US_TXRDY);
728 734
729 /* 735 uart_console_write(port, s, count, at91_console_putchar);
730 * Now, do each character
731 */
732 for (i = 0; i < count; i++) {
733 do {
734 status = UART_GET_CSR(port);
735 } while (!(status & AT91_US_TXRDY));
736 UART_PUT_CHAR(port, s[i]);
737 if (s[i] == '\n') {
738 do {
739 status = UART_GET_CSR(port);
740 } while (!(status & AT91_US_TXRDY));
741 UART_PUT_CHAR(port, '\r');
742 }
743 }
744 736
745 /* 737 /*
746 * Finally, wait for transmitter to become empty 738 * Finally, wait for transmitter to become empty
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
index 344022fe53ef..29f94bbb79be 100644
--- a/drivers/serial/au1x00_uart.c
+++ b/drivers/serial/au1x00_uart.c
@@ -1121,6 +1121,14 @@ static inline void wait_for_xmitr(struct uart_8250_port *up)
1121 } 1121 }
1122} 1122}
1123 1123
1124static void au1x00_console_putchar(struct uart_port *port, int ch)
1125{
1126 struct uart_8250_port *up = (struct uart_8250_port *)port;
1127
1128 wait_for_xmitr(up);
1129 serial_out(up, UART_TX, ch);
1130}
1131
1124/* 1132/*
1125 * Print a string to the serial port trying not to disturb 1133 * Print a string to the serial port trying not to disturb
1126 * any possible real use of the port... 1134 * any possible real use of the port...
@@ -1132,7 +1140,6 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
1132{ 1140{
1133 struct uart_8250_port *up = &serial8250_ports[co->index]; 1141 struct uart_8250_port *up = &serial8250_ports[co->index];
1134 unsigned int ier; 1142 unsigned int ier;
1135 int i;
1136 1143
1137 /* 1144 /*
1138 * First save the UER then disable the interrupts 1145 * First save the UER then disable the interrupts
@@ -1140,22 +1147,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
1140 ier = serial_in(up, UART_IER); 1147 ier = serial_in(up, UART_IER);
1141 serial_out(up, UART_IER, 0); 1148 serial_out(up, UART_IER, 0);
1142 1149
1143 /* 1150 uart_console_write(&up->port, s, count, au1x00_console_putchar);
1144 * Now, do each character
1145 */
1146 for (i = 0; i < count; i++, s++) {
1147 wait_for_xmitr(up);
1148
1149 /*
1150 * Send the character out.
1151 * If a LF, also do CR...
1152 */
1153 serial_out(up, UART_TX, *s);
1154 if (*s == 10) {
1155 wait_for_xmitr(up);
1156 serial_out(up, UART_TX, 13);
1157 }
1158 }
1159 1151
1160 /* 1152 /*
1161 * Finally, wait for transmitter to become empty 1153 * Finally, wait for transmitter to become empty
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index ce7b2e4ecd17..2691112c84ad 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -424,6 +424,13 @@ static struct uart_port clps711x_ports[UART_NR] = {
424}; 424};
425 425
426#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE 426#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
427static void clps711xuart_console_putchar(struct uart_port *port, int ch)
428{
429 while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF)
430 barrier();
431 clps_writel(ch, UARTDR(port));
432}
433
427/* 434/*
428 * Print a string to the serial port trying not to disturb 435 * Print a string to the serial port trying not to disturb
429 * any possible real use of the port... 436 * any possible real use of the port...
@@ -438,7 +445,6 @@ clps711xuart_console_write(struct console *co, const char *s,
438{ 445{
439 struct uart_port *port = clps711x_ports + co->index; 446 struct uart_port *port = clps711x_ports + co->index;
440 unsigned int status, syscon; 447 unsigned int status, syscon;
441 int i;
442 448
443 /* 449 /*
444 * Ensure that the port is enabled. 450 * Ensure that the port is enabled.
@@ -446,21 +452,7 @@ clps711xuart_console_write(struct console *co, const char *s,
446 syscon = clps_readl(SYSCON(port)); 452 syscon = clps_readl(SYSCON(port));
447 clps_writel(syscon | SYSCON_UARTEN, SYSCON(port)); 453 clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
448 454
449 /* 455 uart_console_write(port, s, count, clps711xuart_console_putchar);
450 * Now, do each character
451 */
452 for (i = 0; i < count; i++) {
453 do {
454 status = clps_readl(SYSFLG(port));
455 } while (status & SYSFLG_UTXFF);
456 clps_writel(s[i], UARTDR(port));
457 if (s[i] == '\n') {
458 do {
459 status = clps_readl(SYSFLG(port));
460 } while (status & SYSFLG_UTXFF);
461 clps_writel('\r', UARTDR(port));
462 }
463 }
464 456
465 /* 457 /*
466 * Finally, wait for transmitter to become empty 458 * Finally, wait for transmitter to become empty
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index ba5541de673b..bf71bad5c34f 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -674,11 +674,12 @@ static void dz_reset(struct dz_port *dport)
674} 674}
675 675
676#ifdef CONFIG_SERIAL_DZ_CONSOLE 676#ifdef CONFIG_SERIAL_DZ_CONSOLE
677static void dz_console_put_char(struct dz_port *dport, unsigned char ch) 677static void dz_console_putchar(struct uart_port *port, int ch)
678{ 678{
679 struct dz_port *dport = (struct dz_port *)uport;
679 unsigned long flags; 680 unsigned long flags;
680 int loops = 2500; 681 int loops = 2500;
681 unsigned short tmp = ch; 682 unsigned short tmp = (unsigned char)ch;
682 /* this code sends stuff out to serial device - spinning its 683 /* this code sends stuff out to serial device - spinning its
683 wheels and waiting. */ 684 wheels and waiting. */
684 685
@@ -694,6 +695,7 @@ static void dz_console_put_char(struct dz_port *dport, unsigned char ch)
694 695
695 spin_unlock_irqrestore(&dport->port.lock, flags); 696 spin_unlock_irqrestore(&dport->port.lock, flags);
696} 697}
698
697/* 699/*
698 * ------------------------------------------------------------------- 700 * -------------------------------------------------------------------
699 * dz_console_print () 701 * dz_console_print ()
@@ -710,11 +712,7 @@ static void dz_console_print(struct console *cons,
710#ifdef DEBUG_DZ 712#ifdef DEBUG_DZ
711 prom_printf((char *) str); 713 prom_printf((char *) str);
712#endif 714#endif
713 while (count--) { 715 uart_console_write(&dport->port, str, count, dz_console_putchar);
714 if (*str == '\n')
715 dz_console_put_char(dport, '\r');
716 dz_console_put_char(dport, *str++);
717 }
718} 716}
719 717
720static int __init dz_console_setup(struct console *co, char *options) 718static int __init dz_console_setup(struct console *co, char *options)
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 4d53fb5ca87b..c3b7a6673e9c 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -743,6 +743,13 @@ static void __init imx_init_ports(void)
743} 743}
744 744
745#ifdef CONFIG_SERIAL_IMX_CONSOLE 745#ifdef CONFIG_SERIAL_IMX_CONSOLE
746static void imx_console_putchar(struct uart_port *port, int ch)
747{
748 struct imx_port *sport = (struct imx_port *)port;
749 while ((UTS((u32)sport->port.membase) & UTS_TXFULL))
750 barrier();
751 URTX0((u32)sport->port.membase) = ch;
752}
746 753
747/* 754/*
748 * Interrupts are disabled on entering 755 * Interrupts are disabled on entering
@@ -751,7 +758,7 @@ static void
751imx_console_write(struct console *co, const char *s, unsigned int count) 758imx_console_write(struct console *co, const char *s, unsigned int count)
752{ 759{
753 struct imx_port *sport = &imx_ports[co->index]; 760 struct imx_port *sport = &imx_ports[co->index];
754 unsigned int old_ucr1, old_ucr2, i; 761 unsigned int old_ucr1, old_ucr2;
755 762
756 /* 763 /*
757 * First, save UCR1/2 and then disable interrupts 764 * First, save UCR1/2 and then disable interrupts
@@ -764,22 +771,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
764 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); 771 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
765 UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN; 772 UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN;
766 773
767 /* 774 uart_console_write(&sport->port, s, count, imx_console_putchar);
768 * Now, do each character
769 */
770 for (i = 0; i < count; i++) {
771
772 while ((UTS((u32)sport->port.membase) & UTS_TXFULL))
773 barrier();
774
775 URTX0((u32)sport->port.membase) = s[i];
776
777 if (s[i] == '\n') {
778 while ((UTS((u32)sport->port.membase) & UTS_TXFULL))
779 barrier();
780 URTX0((u32)sport->port.membase) = '\r';
781 }
782 }
783 775
784 /* 776 /*
785 * Finally, wait for transmitter to become empty 777 * Finally, wait for transmitter to become empty
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index 193722d680cf..651772474ac1 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -967,8 +967,9 @@ static struct zilog_layout * __init get_zs(int chip)
967#define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ 967#define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */
968 968
969#ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE 969#ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE
970static void ip22zilog_put_char(struct zilog_channel *channel, unsigned char ch) 970static void ip22zilog_put_char(struct uart_port *port, int ch)
971{ 971{
972 struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
972 int loops = ZS_PUT_CHAR_MAX_DELAY; 973 int loops = ZS_PUT_CHAR_MAX_DELAY;
973 974
974 /* This is a timed polling loop so do not switch the explicit 975 /* This is a timed polling loop so do not switch the explicit
@@ -992,16 +993,10 @@ static void
992ip22zilog_console_write(struct console *con, const char *s, unsigned int count) 993ip22zilog_console_write(struct console *con, const char *s, unsigned int count)
993{ 994{
994 struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index]; 995 struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index];
995 struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
996 unsigned long flags; 996 unsigned long flags;
997 int i;
998 997
999 spin_lock_irqsave(&up->port.lock, flags); 998 spin_lock_irqsave(&up->port.lock, flags);
1000 for (i = 0; i < count; i++, s++) { 999 uart_console_write(&up->port, s, count, ip22zilog_put_char);
1001 ip22zilog_put_char(channel, *s);
1002 if (*s == 10)
1003 ip22zilog_put_char(channel, 13);
1004 }
1005 udelay(2); 1000 udelay(2);
1006 spin_unlock_irqrestore(&up->port.lock, flags); 1001 spin_unlock_irqrestore(&up->port.lock, flags);
1007} 1002}
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index 242a04104393..876bc5e027bb 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -1039,6 +1039,14 @@ static inline void wait_for_xmitr(struct uart_sio_port *up)
1039 } 1039 }
1040} 1040}
1041 1041
1042static void m32r_sio_console_putchar(struct uart_port *port, int ch)
1043{
1044 struct uart_sio_port *up = (struct uart_sio_port *)port;
1045
1046 wait_for_xmitr(up);
1047 sio_out(up, SIOTXB, ch);
1048}
1049
1042/* 1050/*
1043 * Print a string to the serial port trying not to disturb 1051 * Print a string to the serial port trying not to disturb
1044 * any possible real use of the port... 1052 * any possible real use of the port...
@@ -1058,23 +1066,7 @@ static void m32r_sio_console_write(struct console *co, const char *s,
1058 ier = sio_in(up, SIOTRCR); 1066 ier = sio_in(up, SIOTRCR);
1059 sio_out(up, SIOTRCR, 0); 1067 sio_out(up, SIOTRCR, 0);
1060 1068
1061 /* 1069 uart_console_write(&up->port, s, count, m32r_sio_console_putchar);
1062 * Now, do each character
1063 */
1064 for (i = 0; i < count; i++, s++) {
1065 wait_for_xmitr(up);
1066
1067 /*
1068 * Send the character out.
1069 * If a LF, also do CR...
1070 */
1071 sio_out(up, SIOTXB, *s);
1072
1073 if (*s == 10) {
1074 wait_for_xmitr(up);
1075 sio_out(up, SIOTXB, 13);
1076 }
1077 }
1078 1070
1079 /* 1071 /*
1080 * Finally, wait for transmitter to become empty 1072 * Finally, wait for transmitter to become empty
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 61dd17d7bace..928e6cf12dca 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -603,15 +603,14 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
603 udelay(1); 603 udelay(1);
604 604
605 /* Write all the chars */ 605 /* Write all the chars */
606 for ( i=0 ; i<count ; i++ ) { 606 for (i = 0; i < count; i++, s++) {
607
608 /* Send the char */
609 out_8(&psc->mpc52xx_psc_buffer_8, *s);
610
611 /* Line return handling */ 607 /* Line return handling */
612 if ( *s++ == '\n' ) 608 if (*s == '\n')
613 out_8(&psc->mpc52xx_psc_buffer_8, '\r'); 609 out_8(&psc->mpc52xx_psc_buffer_8, '\r');
614 610
611 /* Send the char */
612 out_8(&psc->mpc52xx_psc_buffer_8, *s);
613
615 /* Wait the TX buffer to be empty */ 614 /* Wait the TX buffer to be empty */
616 j = 20000; /* Maximum wait */ 615 j = 20000; /* Maximum wait */
617 while (!(in_be16(&psc->mpc52xx_psc_status) & 616 while (!(in_be16(&psc->mpc52xx_psc_status) &
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index 9b7ed58cb53b..513ff8597707 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -1916,6 +1916,16 @@ static void __exit exit_pmz(void)
1916 1916
1917#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE 1917#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
1918 1918
1919static void pmz_console_putchar(struct uart_port *port, int ch)
1920{
1921 struct uart_pmac_port *uap = (struct uart_pmac_port *)port;
1922
1923 /* Wait for the transmit buffer to empty. */
1924 while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0)
1925 udelay(5);
1926 write_zsdata(uap, ch);
1927}
1928
1919/* 1929/*
1920 * Print a string to the serial port trying not to disturb 1930 * Print a string to the serial port trying not to disturb
1921 * any possible real use of the port... 1931 * any possible real use of the port...
@@ -1924,7 +1934,6 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c
1924{ 1934{
1925 struct uart_pmac_port *uap = &pmz_ports[con->index]; 1935 struct uart_pmac_port *uap = &pmz_ports[con->index];
1926 unsigned long flags; 1936 unsigned long flags;
1927 int i;
1928 1937
1929 if (ZS_IS_ASLEEP(uap)) 1938 if (ZS_IS_ASLEEP(uap))
1930 return; 1939 return;
@@ -1934,17 +1943,7 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c
1934 write_zsreg(uap, R1, uap->curregs[1] & ~TxINT_ENAB); 1943 write_zsreg(uap, R1, uap->curregs[1] & ~TxINT_ENAB);
1935 write_zsreg(uap, R5, uap->curregs[5] | TxENABLE | RTS | DTR); 1944 write_zsreg(uap, R5, uap->curregs[5] | TxENABLE | RTS | DTR);
1936 1945
1937 for (i = 0; i < count; i++) { 1946 uart_console_write(&uap->port, s, count, pmz_console_putchar);
1938 /* Wait for the transmit buffer to empty. */
1939 while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0)
1940 udelay(5);
1941 write_zsdata(uap, s[i]);
1942 if (s[i] == 10) {
1943 while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0)
1944 udelay(5);
1945 write_zsdata(uap, R13);
1946 }
1947 }
1948 1947
1949 /* Restore the values in the registers. */ 1948 /* Restore the values in the registers. */
1950 write_zsreg(uap, R1, uap->curregs[1]); 1949 write_zsreg(uap, R1, uap->curregs[1]);
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index 10535f00301f..77d4568ccc3a 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -619,6 +619,14 @@ static inline void wait_for_xmitr(struct uart_pxa_port *up)
619 } 619 }
620} 620}
621 621
622static void serial_pxa_console_putchar(struct uart_port *port, int ch)
623{
624 struct uart_pxa_port *up = (struct uart_pxa_port *)port;
625
626 wait_for_xmitr(up);
627 serial_out(up, UART_TX, ch);
628}
629
622/* 630/*
623 * Print a string to the serial port trying not to disturb 631 * Print a string to the serial port trying not to disturb
624 * any possible real use of the port... 632 * any possible real use of the port...
@@ -630,7 +638,6 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
630{ 638{
631 struct uart_pxa_port *up = &serial_pxa_ports[co->index]; 639 struct uart_pxa_port *up = &serial_pxa_ports[co->index];
632 unsigned int ier; 640 unsigned int ier;
633 int i;
634 641
635 /* 642 /*
636 * First save the IER then disable the interrupts 643 * First save the IER then disable the interrupts
@@ -638,22 +645,7 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
638 ier = serial_in(up, UART_IER); 645 ier = serial_in(up, UART_IER);
639 serial_out(up, UART_IER, UART_IER_UUE); 646 serial_out(up, UART_IER, UART_IER_UUE);
640 647
641 /* 648 uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
642 * Now, do each character
643 */
644 for (i = 0; i < count; i++, s++) {
645 wait_for_xmitr(up);
646
647 /*
648 * Send the character out.
649 * If a LF, also do CR...
650 */
651 serial_out(up, UART_TX, *s);
652 if (*s == 10) {
653 wait_for_xmitr(up);
654 serial_out(up, UART_TX, 13);
655 }
656 }
657 649
658 /* 650 /*
659 * Finally, wait for transmitter to become empty 651 * Finally, wait for transmitter to become empty
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 7410e093a6b9..e4d701239702 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -1584,25 +1584,19 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
1584} 1584}
1585 1585
1586static void 1586static void
1587s3c24xx_serial_console_write(struct console *co, const char *s, 1587s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
1588 unsigned int count)
1589{ 1588{
1590 int i;
1591 unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); 1589 unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
1590 while (!s3c24xx_serial_console_txrdy(port, ufcon))
1591 barrier();
1592 wr_regb(cons_uart, S3C2410_UTXH, ch);
1593}
1592 1594
1593 for (i = 0; i < count; i++) { 1595static void
1594 while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon)) 1596s3c24xx_serial_console_write(struct console *co, const char *s,
1595 barrier(); 1597 unsigned int count)
1596 1598{
1597 wr_regb(cons_uart, S3C2410_UTXH, s[i]); 1599 uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
1598
1599 if (s[i] == '\n') {
1600 while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon))
1601 barrier();
1602
1603 wr_regb(cons_uart, S3C2410_UTXH, '\r');
1604 }
1605 }
1606} 1600}
1607 1601
1608static void __init 1602static void __init
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 2c00b8625852..c2d9068b491d 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -689,6 +689,14 @@ void __init sa1100_register_uart(int idx, int port)
689 689
690 690
691#ifdef CONFIG_SERIAL_SA1100_CONSOLE 691#ifdef CONFIG_SERIAL_SA1100_CONSOLE
692static void sa1100_console_putchar(struct uart_port *port, int ch)
693{
694 struct sa1100_port *sport = (struct sa1100_port *)port;
695
696 while (!(UART_GET_UTSR1(sport) & UTSR1_TNF))
697 barrier();
698 UART_PUT_CHAR(sport, ch);
699}
692 700
693/* 701/*
694 * Interrupts are disabled on entering 702 * Interrupts are disabled on entering
@@ -697,7 +705,7 @@ static void
697sa1100_console_write(struct console *co, const char *s, unsigned int count) 705sa1100_console_write(struct console *co, const char *s, unsigned int count)
698{ 706{
699 struct sa1100_port *sport = &sa1100_ports[co->index]; 707 struct sa1100_port *sport = &sa1100_ports[co->index];
700 unsigned int old_utcr3, status, i; 708 unsigned int old_utcr3, status;
701 709
702 /* 710 /*
703 * First, save UTCR3 and then disable interrupts 711 * First, save UTCR3 and then disable interrupts
@@ -706,21 +714,7 @@ sa1100_console_write(struct console *co, const char *s, unsigned int count)
706 UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) | 714 UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) |
707 UTCR3_TXE); 715 UTCR3_TXE);
708 716
709 /* 717 uart_console_write(&sport->port, s, count, sa1100_console_putchar);
710 * Now, do each character
711 */
712 for (i = 0; i < count; i++) {
713 do {
714 status = UART_GET_UTSR1(sport);
715 } while (!(status & UTSR1_TNF));
716 UART_PUT_CHAR(sport, s[i]);
717 if (s[i] == '\n') {
718 do {
719 status = UART_GET_UTSR1(sport);
720 } while (!(status & UTSR1_TNF));
721 UART_PUT_CHAR(sport, '\r');
722 }
723 }
724 718
725 /* 719 /*
726 * Finally, wait for transmitter to become empty 720 * Finally, wait for transmitter to become empty
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index cc1faa31d124..fcd7744c4253 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1755,6 +1755,27 @@ static int uart_read_proc(char *page, char **start, off_t off,
1755 1755
1756#ifdef CONFIG_SERIAL_CORE_CONSOLE 1756#ifdef CONFIG_SERIAL_CORE_CONSOLE
1757/* 1757/*
1758 * uart_console_write - write a console message to a serial port
1759 * @port: the port to write the message
1760 * @s: array of characters
1761 * @count: number of characters in string to write
1762 * @write: function to write character to port
1763 */
1764void uart_console_write(struct uart_port *port, const char *s,
1765 unsigned int count,
1766 void (*putchar)(struct uart_port *, int))
1767{
1768 unsigned int i;
1769
1770 for (i = 0; i < count; i++, s++) {
1771 if (*s == '\n')
1772 putchar(port, '\r');
1773 putchar(port, *s);
1774 }
1775}
1776EXPORT_SYMBOL_GPL(uart_console_write);
1777
1778/*
1758 * Check whether an invalid uart number has been specified, and 1779 * Check whether an invalid uart number has been specified, and
1759 * if so, search for the first available port that does have 1780 * if so, search for the first available port that does have
1760 * console support. 1781 * console support.
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index 04186eaae227..aa521b8e0d4e 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -543,6 +543,12 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
543#else 543#else
544# define LH7A40X_CONSOLE &lh7a40x_console 544# define LH7A40X_CONSOLE &lh7a40x_console
545 545
546static void lh7a40xuart_console_putchar(struct uart_port *port, int ch)
547{
548 while (UR(port, UART_R_STATUS) & nTxRdy)
549 ;
550 UR(port, UART_R_DATA) = ch;
551}
546 552
547static void lh7a40xuart_console_write (struct console* co, 553static void lh7a40xuart_console_write (struct console* co,
548 const char* s, 554 const char* s,
@@ -556,16 +562,7 @@ static void lh7a40xuart_console_write (struct console* co,
556 UR (port, UART_R_INTEN) = 0; /* Disable all interrupts */ 562 UR (port, UART_R_INTEN) = 0; /* Disable all interrupts */
557 BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */ 563 BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */
558 564
559 for (; count-- > 0; ++s) { 565 uart_console_write(port, s, count, lh7a40xuart_console_putchar);
560 while (UR (port, UART_R_STATUS) & nTxRdy)
561 ;
562 UR (port, UART_R_DATA) = *s;
563 if (*s == '\n') {
564 while ((UR (port, UART_R_STATUS) & TxBusy))
565 ;
566 UR (port, UART_R_DATA) = '\r';
567 }
568 }
569 566
570 /* Wait until all characters are sent */ 567 /* Wait until all characters are sent */
571 while (UR (port, UART_R_STATUS) & TxBusy) 568 while (UR (port, UART_R_STATUS) & TxBusy)
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index ee98a867bc6d..1a259cee1a98 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -854,6 +854,14 @@ static inline void wait_for_xmitr(struct uart_txx9_port *up)
854 } 854 }
855} 855}
856 856
857static void serial_txx9_console_putchar(struct uart_port *port, int ch)
858{
859 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
860
861 wait_for_xmitr(up);
862 sio_out(up, TXX9_SITFIFO, ch);
863}
864
857/* 865/*
858 * Print a string to the serial port trying not to disturb 866 * Print a string to the serial port trying not to disturb
859 * any possible real use of the port... 867 * any possible real use of the port...
@@ -865,7 +873,6 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count)
865{ 873{
866 struct uart_txx9_port *up = &serial_txx9_ports[co->index]; 874 struct uart_txx9_port *up = &serial_txx9_ports[co->index];
867 unsigned int ier, flcr; 875 unsigned int ier, flcr;
868 int i;
869 876
870 /* 877 /*
871 * First save the UER then disable the interrupts 878 * First save the UER then disable the interrupts
@@ -879,22 +886,7 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count)
879 if (!(up->port.flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES)) 886 if (!(up->port.flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES))
880 sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES); 887 sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES);
881 888
882 /* 889 uart_console_write(&up->port, s, count, serial_txx9_console_putchar);
883 * Now, do each character
884 */
885 for (i = 0; i < count; i++, s++) {
886 wait_for_xmitr(up);
887
888 /*
889 * Send the character out.
890 * If a LF, also do CR...
891 */
892 sio_out(up, TXX9_SITFIFO, *s);
893 if (*s == 10) {
894 wait_for_xmitr(up);
895 sio_out(up, TXX9_SITFIFO, 13);
896 }
897 }
898 890
899 /* 891 /*
900 * Finally, wait for transmitter to become empty 892 * Finally, wait for transmitter to become empty
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 85664228a0b6..be95eabd0394 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -861,8 +861,9 @@ static int num_channels;
861 861
862#ifdef CONFIG_SERIAL_SUNSAB_CONSOLE 862#ifdef CONFIG_SERIAL_SUNSAB_CONSOLE
863 863
864static __inline__ void sunsab_console_putchar(struct uart_sunsab_port *up, char c) 864static void sunsab_console_putchar(struct uart_port *port, int c)
865{ 865{
866 struct uart_sunsab_port *up = (struct uart_sunsab_port *)port;
866 unsigned long flags; 867 unsigned long flags;
867 868
868 spin_lock_irqsave(&up->port.lock, flags); 869 spin_lock_irqsave(&up->port.lock, flags);
@@ -876,13 +877,8 @@ static __inline__ void sunsab_console_putchar(struct uart_sunsab_port *up, char
876static void sunsab_console_write(struct console *con, const char *s, unsigned n) 877static void sunsab_console_write(struct console *con, const char *s, unsigned n)
877{ 878{
878 struct uart_sunsab_port *up = &sunsab_ports[con->index]; 879 struct uart_sunsab_port *up = &sunsab_ports[con->index];
879 int i;
880 880
881 for (i = 0; i < n; i++) { 881 uart_console_write(&up->port, s, n, sunsab_console_putchar);
882 if (*s == '\n')
883 sunsab_console_putchar(up, '\r');
884 sunsab_console_putchar(up, *s++);
885 }
886 sunsab_tec_wait(up); 882 sunsab_tec_wait(up);
887} 883}
888 884
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 4e453fa966ae..9ca1d8b9364b 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1376,6 +1376,14 @@ static __inline__ void wait_for_xmitr(struct uart_sunsu_port *up)
1376 } 1376 }
1377} 1377}
1378 1378
1379static void sunsu_console_putchar(struct uart_port *port, int ch)
1380{
1381 struct uart_sunsu_port *up = (struct uart_sunsu_port *)port;
1382
1383 wait_for_xmitr(up);
1384 serial_out(up, UART_TX, ch);
1385}
1386
1379/* 1387/*
1380 * Print a string to the serial port trying not to disturb 1388 * Print a string to the serial port trying not to disturb
1381 * any possible real use of the port... 1389 * any possible real use of the port...
@@ -1385,7 +1393,6 @@ static void sunsu_console_write(struct console *co, const char *s,
1385{ 1393{
1386 struct uart_sunsu_port *up = &sunsu_ports[co->index]; 1394 struct uart_sunsu_port *up = &sunsu_ports[co->index];
1387 unsigned int ier; 1395 unsigned int ier;
1388 int i;
1389 1396
1390 /* 1397 /*
1391 * First save the UER then disable the interrupts 1398 * First save the UER then disable the interrupts
@@ -1393,22 +1400,7 @@ static void sunsu_console_write(struct console *co, const char *s,
1393 ier = serial_in(up, UART_IER); 1400 ier = serial_in(up, UART_IER);
1394 serial_out(up, UART_IER, 0); 1401 serial_out(up, UART_IER, 0);
1395 1402
1396 /* 1403 uart_console_write(&up->port, s, count, sunsu_console_putchar);
1397 * Now, do each character
1398 */
1399 for (i = 0; i < count; i++, s++) {
1400 wait_for_xmitr(up);
1401
1402 /*
1403 * Send the character out.
1404 * If a LF, also do CR...
1405 */
1406 serial_out(up, UART_TX, *s);
1407 if (*s == 10) {
1408 wait_for_xmitr(up);
1409 serial_out(up, UART_TX, 13);
1410 }
1411 }
1412 1404
1413 /* 1405 /*
1414 * Finally, wait for transmitter to become empty 1406 * Finally, wait for transmitter to become empty
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 5cc4d4c2935c..b0c46b9a5930 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1252,8 +1252,9 @@ static struct zilog_layout __iomem * __init get_zs(int chip, int node)
1252 1252
1253#define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ 1253#define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */
1254 1254
1255static void sunzilog_put_char(struct zilog_channel __iomem *channel, unsigned char ch) 1255static void sunzilog_putchar(struct uart_port *port, int ch)
1256{ 1256{
1257 struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
1257 int loops = ZS_PUT_CHAR_MAX_DELAY; 1258 int loops = ZS_PUT_CHAR_MAX_DELAY;
1258 1259
1259 /* This is a timed polling loop so do not switch the explicit 1260 /* This is a timed polling loop so do not switch the explicit
@@ -1284,7 +1285,7 @@ static int sunzilog_serio_write(struct serio *serio, unsigned char ch)
1284 1285
1285 spin_lock_irqsave(&sunzilog_serio_lock, flags); 1286 spin_lock_irqsave(&sunzilog_serio_lock, flags);
1286 1287
1287 sunzilog_put_char(ZILOG_CHANNEL_FROM_PORT(&up->port), ch); 1288 sunzilog_putchar(&up->port, ch);
1288 1289
1289 spin_unlock_irqrestore(&sunzilog_serio_lock, flags); 1290 spin_unlock_irqrestore(&sunzilog_serio_lock, flags);
1290 1291
@@ -1325,16 +1326,10 @@ static void
1325sunzilog_console_write(struct console *con, const char *s, unsigned int count) 1326sunzilog_console_write(struct console *con, const char *s, unsigned int count)
1326{ 1327{
1327 struct uart_sunzilog_port *up = &sunzilog_port_table[con->index]; 1328 struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];
1328 struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
1329 unsigned long flags; 1329 unsigned long flags;
1330 int i;
1331 1330
1332 spin_lock_irqsave(&up->port.lock, flags); 1331 spin_lock_irqsave(&up->port.lock, flags);
1333 for (i = 0; i < count; i++, s++) { 1332 uart_console_write(&up->port, s, count, sunzilog_putchar);
1334 sunzilog_put_char(channel, *s);
1335 if (*s == 10)
1336 sunzilog_put_char(channel, 13);
1337 }
1338 udelay(2); 1333 udelay(2);
1339 spin_unlock_irqrestore(&up->port.lock, flags); 1334 spin_unlock_irqrestore(&up->port.lock, flags);
1340} 1335}
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index d61494d185cd..3f88b8e81937 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -821,25 +821,23 @@ static void wait_for_xmitr(struct uart_port *port)
821 } 821 }
822} 822}
823 823
824static void siu_console_putchar(struct uart_port *port, int ch)
825{
826 wait_for_xmitr(port);
827 siu_write(port, UART_TX, ch);
828}
829
824static void siu_console_write(struct console *con, const char *s, unsigned count) 830static void siu_console_write(struct console *con, const char *s, unsigned count)
825{ 831{
826 struct uart_port *port; 832 struct uart_port *port;
827 uint8_t ier; 833 uint8_t ier;
828 unsigned i;
829 834
830 port = &siu_uart_ports[con->index]; 835 port = &siu_uart_ports[con->index];
831 836
832 ier = siu_read(port, UART_IER); 837 ier = siu_read(port, UART_IER);
833 siu_write(port, UART_IER, 0); 838 siu_write(port, UART_IER, 0);
834 839
835 for (i = 0; i < count && *s != '\0'; i++, s++) { 840 uart_console_write(port, s, count, siu_console_putchar);
836 wait_for_xmitr(port);
837 siu_write(port, UART_TX, *s);
838 if (*s == '\n') {
839 wait_for_xmitr(port);
840 siu_write(port, UART_TX, '\r');
841 }
842 }
843 841
844 wait_for_xmitr(port); 842 wait_for_xmitr(port);
845 siu_write(port, UART_IER, ier); 843 siu_write(port, UART_IER, ier);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 4041122dabfc..f7434e5086f5 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -366,6 +366,9 @@ void uart_parse_options(char *options, int *baud, int *parity, int *bits,
366int uart_set_options(struct uart_port *port, struct console *co, int baud, 366int uart_set_options(struct uart_port *port, struct console *co, int baud,
367 int parity, int bits, int flow); 367 int parity, int bits, int flow);
368struct tty_driver *uart_console_device(struct console *co, int *index); 368struct tty_driver *uart_console_device(struct console *co, int *index);
369void uart_console_write(struct uart_port *port, const char *s,
370 unsigned int count,
371 void (*putchar)(struct uart_port *, int));
369 372
370/* 373/*
371 * Port/driver registration/removal 374 * Port/driver registration/removal