aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/serial_txx9.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial/serial_txx9.c')
-rw-r--r--drivers/serial/serial_txx9.c103
1 files changed, 50 insertions, 53 deletions
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index ee98a867bc6d..b848b7d94412 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -33,6 +33,10 @@
33 * 1.02 Cleanup. (import 8250.c changes) 33 * 1.02 Cleanup. (import 8250.c changes)
34 * 1.03 Fix low-latency mode. (import 8250.c changes) 34 * 1.03 Fix low-latency mode. (import 8250.c changes)
35 * 1.04 Remove usage of deprecated functions, cleanup. 35 * 1.04 Remove usage of deprecated functions, cleanup.
36 * 1.05 More strict check in verify_port. Cleanup.
37 * 1.06 Do not insert a char caused previous overrun.
38 * Fix some spin_locks.
39 * Do not call uart_add_one_port for absent ports.
36 */ 40 */
37#include <linux/config.h> 41#include <linux/config.h>
38 42
@@ -57,7 +61,7 @@
57#include <asm/io.h> 61#include <asm/io.h>
58#include <asm/irq.h> 62#include <asm/irq.h>
59 63
60static char *serial_version = "1.04"; 64static char *serial_version = "1.06";
61static char *serial_name = "TX39/49 Serial driver"; 65static char *serial_name = "TX39/49 Serial driver";
62 66
63#define PASS_LIMIT 256 67#define PASS_LIMIT 256
@@ -94,6 +98,8 @@ static char *serial_name = "TX39/49 Serial driver";
94#define UART_NR 4 98#define UART_NR 4
95#endif 99#endif
96 100
101#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
102
97struct uart_txx9_port { 103struct uart_txx9_port {
98 struct uart_port port; 104 struct uart_port port;
99 105
@@ -210,7 +216,7 @@ static inline unsigned int sio_in(struct uart_txx9_port *up, int offset)
210{ 216{
211 switch (up->port.iotype) { 217 switch (up->port.iotype) {
212 default: 218 default:
213 return *(volatile u32 *)(up->port.membase + offset); 219 return __raw_readl(up->port.membase + offset);
214 case UPIO_PORT: 220 case UPIO_PORT:
215 return inl(up->port.iobase + offset); 221 return inl(up->port.iobase + offset);
216 } 222 }
@@ -221,7 +227,7 @@ sio_out(struct uart_txx9_port *up, int offset, int value)
221{ 227{
222 switch (up->port.iotype) { 228 switch (up->port.iotype) {
223 default: 229 default:
224 *(volatile u32 *)(up->port.membase + offset) = value; 230 __raw_writel(value, up->port.membase + offset);
225 break; 231 break;
226 case UPIO_PORT: 232 case UPIO_PORT:
227 outl(value, up->port.iobase + offset); 233 outl(value, up->port.iobase + offset);
@@ -259,34 +265,19 @@ sio_quot_set(struct uart_txx9_port *up, int quot)
259static void serial_txx9_stop_tx(struct uart_port *port) 265static void serial_txx9_stop_tx(struct uart_port *port)
260{ 266{
261 struct uart_txx9_port *up = (struct uart_txx9_port *)port; 267 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
262 unsigned long flags;
263
264 spin_lock_irqsave(&up->port.lock, flags);
265 sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_TIE); 268 sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
266 spin_unlock_irqrestore(&up->port.lock, flags);
267} 269}
268 270
269static void serial_txx9_start_tx(struct uart_port *port) 271static void serial_txx9_start_tx(struct uart_port *port)
270{ 272{
271 struct uart_txx9_port *up = (struct uart_txx9_port *)port; 273 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
272 unsigned long flags;
273
274 spin_lock_irqsave(&up->port.lock, flags);
275 sio_set(up, TXX9_SIDICR, TXX9_SIDICR_TIE); 274 sio_set(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
276 spin_unlock_irqrestore(&up->port.lock, flags);
277} 275}
278 276
279static void serial_txx9_stop_rx(struct uart_port *port) 277static void serial_txx9_stop_rx(struct uart_port *port)
280{ 278{
281 struct uart_txx9_port *up = (struct uart_txx9_port *)port; 279 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
282 unsigned long flags;
283
284 spin_lock_irqsave(&up->port.lock, flags);
285 up->port.read_status_mask &= ~TXX9_SIDISR_RDIS; 280 up->port.read_status_mask &= ~TXX9_SIDISR_RDIS;
286#if 0
287 sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_RIE);
288#endif
289 spin_unlock_irqrestore(&up->port.lock, flags);
290} 281}
291 282
292static void serial_txx9_enable_ms(struct uart_port *port) 283static void serial_txx9_enable_ms(struct uart_port *port)
@@ -302,12 +293,16 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
302 unsigned int disr = *status; 293 unsigned int disr = *status;
303 int max_count = 256; 294 int max_count = 256;
304 char flag; 295 char flag;
296 unsigned int next_ignore_status_mask;
305 297
306 do { 298 do {
307 ch = sio_in(up, TXX9_SIRFIFO); 299 ch = sio_in(up, TXX9_SIRFIFO);
308 flag = TTY_NORMAL; 300 flag = TTY_NORMAL;
309 up->port.icount.rx++; 301 up->port.icount.rx++;
310 302
303 /* mask out RFDN_MASK bit added by previous overrun */
304 next_ignore_status_mask =
305 up->port.ignore_status_mask & ~TXX9_SIDISR_RFDN_MASK;
311 if (unlikely(disr & (TXX9_SIDISR_UBRK | TXX9_SIDISR_UPER | 306 if (unlikely(disr & (TXX9_SIDISR_UBRK | TXX9_SIDISR_UPER |
312 TXX9_SIDISR_UFER | TXX9_SIDISR_UOER))) { 307 TXX9_SIDISR_UFER | TXX9_SIDISR_UOER))) {
313 /* 308 /*
@@ -328,8 +323,17 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
328 up->port.icount.parity++; 323 up->port.icount.parity++;
329 else if (disr & TXX9_SIDISR_UFER) 324 else if (disr & TXX9_SIDISR_UFER)
330 up->port.icount.frame++; 325 up->port.icount.frame++;
331 if (disr & TXX9_SIDISR_UOER) 326 if (disr & TXX9_SIDISR_UOER) {
332 up->port.icount.overrun++; 327 up->port.icount.overrun++;
328 /*
329 * The receiver read buffer still hold
330 * a char which caused overrun.
331 * Ignore next char by adding RFDN_MASK
332 * to ignore_status_mask temporarily.
333 */
334 next_ignore_status_mask |=
335 TXX9_SIDISR_RFDN_MASK;
336 }
333 337
334 /* 338 /*
335 * Mask off conditions which should be ingored. 339 * Mask off conditions which should be ingored.
@@ -349,6 +353,7 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
349 uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag); 353 uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag);
350 354
351 ignore_char: 355 ignore_char:
356 up->port.ignore_status_mask = next_ignore_status_mask;
352 disr = sio_in(up, TXX9_SIDISR); 357 disr = sio_in(up, TXX9_SIDISR);
353 } while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0)); 358 } while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
354 spin_unlock(&up->port.lock); 359 spin_unlock(&up->port.lock);
@@ -450,14 +455,11 @@ static unsigned int serial_txx9_get_mctrl(struct uart_port *port)
450static void serial_txx9_set_mctrl(struct uart_port *port, unsigned int mctrl) 455static void serial_txx9_set_mctrl(struct uart_port *port, unsigned int mctrl)
451{ 456{
452 struct uart_txx9_port *up = (struct uart_txx9_port *)port; 457 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
453 unsigned long flags;
454 458
455 spin_lock_irqsave(&up->port.lock, flags);
456 if (mctrl & TIOCM_RTS) 459 if (mctrl & TIOCM_RTS)
457 sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC); 460 sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
458 else 461 else
459 sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC); 462 sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
460 spin_unlock_irqrestore(&up->port.lock, flags);
461} 463}
462 464
463static void serial_txx9_break_ctl(struct uart_port *port, int break_state) 465static void serial_txx9_break_ctl(struct uart_port *port, int break_state)
@@ -784,8 +786,14 @@ static void serial_txx9_config_port(struct uart_port *port, int uflags)
784static int 786static int
785serial_txx9_verify_port(struct uart_port *port, struct serial_struct *ser) 787serial_txx9_verify_port(struct uart_port *port, struct serial_struct *ser)
786{ 788{
787 if (ser->irq < 0 || 789 unsigned long new_port = ser->port;
788 ser->baud_base < 9600 || ser->type != PORT_TXX9) 790 if (HIGH_BITS_OFFSET)
791 new_port += (unsigned long)ser->port_high << HIGH_BITS_OFFSET;
792 if (ser->type != port->type ||
793 ser->irq != port->irq ||
794 ser->io_type != port->iotype ||
795 new_port != port->iobase ||
796 (unsigned long)ser->iomem_base != port->mapbase)
789 return -EINVAL; 797 return -EINVAL;
790 return 0; 798 return 0;
791} 799}
@@ -827,7 +835,8 @@ static void __init serial_txx9_register_ports(struct uart_driver *drv)
827 835
828 up->port.line = i; 836 up->port.line = i;
829 up->port.ops = &serial_txx9_pops; 837 up->port.ops = &serial_txx9_pops;
830 uart_add_one_port(drv, &up->port); 838 if (up->port.iobase || up->port.mapbase)
839 uart_add_one_port(drv, &up->port);
831 } 840 }
832} 841}
833 842
@@ -854,6 +863,14 @@ static inline void wait_for_xmitr(struct uart_txx9_port *up)
854 } 863 }
855} 864}
856 865
866static void serial_txx9_console_putchar(struct uart_port *port, int ch)
867{
868 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
869
870 wait_for_xmitr(up);
871 sio_out(up, TXX9_SITFIFO, ch);
872}
873
857/* 874/*
858 * Print a string to the serial port trying not to disturb 875 * Print a string to the serial port trying not to disturb
859 * any possible real use of the port... 876 * any possible real use of the port...
@@ -865,7 +882,6 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count)
865{ 882{
866 struct uart_txx9_port *up = &serial_txx9_ports[co->index]; 883 struct uart_txx9_port *up = &serial_txx9_ports[co->index];
867 unsigned int ier, flcr; 884 unsigned int ier, flcr;
868 int i;
869 885
870 /* 886 /*
871 * First save the UER then disable the interrupts 887 * First save the UER then disable the interrupts
@@ -879,22 +895,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)) 895 if (!(up->port.flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES))
880 sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES); 896 sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES);
881 897
882 /* 898 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 899
899 /* 900 /*
900 * Finally, wait for transmitter to become empty 901 * Finally, wait for transmitter to become empty
@@ -927,11 +928,6 @@ static int serial_txx9_console_setup(struct console *co, char *options)
927 return -ENODEV; 928 return -ENODEV;
928 929
929 /* 930 /*
930 * Temporary fix.
931 */
932 spin_lock_init(&port->lock);
933
934 /*
935 * Disable UART interrupts, set DTR and RTS high 931 * Disable UART interrupts, set DTR and RTS high
936 * and set speed. 932 * and set speed.
937 */ 933 */
@@ -1041,11 +1037,10 @@ static int __devinit serial_txx9_register_port(struct uart_port *port)
1041 mutex_lock(&serial_txx9_mutex); 1037 mutex_lock(&serial_txx9_mutex);
1042 for (i = 0; i < UART_NR; i++) { 1038 for (i = 0; i < UART_NR; i++) {
1043 uart = &serial_txx9_ports[i]; 1039 uart = &serial_txx9_ports[i];
1044 if (uart->port.type == PORT_UNKNOWN) 1040 if (!(uart->port.iobase || uart->port.mapbase))
1045 break; 1041 break;
1046 } 1042 }
1047 if (i < UART_NR) { 1043 if (i < UART_NR) {
1048 uart_remove_one_port(&serial_txx9_reg, &uart->port);
1049 uart->port.iobase = port->iobase; 1044 uart->port.iobase = port->iobase;
1050 uart->port.membase = port->membase; 1045 uart->port.membase = port->membase;
1051 uart->port.irq = port->irq; 1046 uart->port.irq = port->irq;
@@ -1080,9 +1075,8 @@ static void __devexit serial_txx9_unregister_port(int line)
1080 uart->port.type = PORT_UNKNOWN; 1075 uart->port.type = PORT_UNKNOWN;
1081 uart->port.iobase = 0; 1076 uart->port.iobase = 0;
1082 uart->port.mapbase = 0; 1077 uart->port.mapbase = 0;
1083 uart->port.membase = 0; 1078 uart->port.membase = NULL;
1084 uart->port.dev = NULL; 1079 uart->port.dev = NULL;
1085 uart_add_one_port(&serial_txx9_reg, &uart->port);
1086 mutex_unlock(&serial_txx9_mutex); 1080 mutex_unlock(&serial_txx9_mutex);
1087} 1081}
1088 1082
@@ -1198,8 +1192,11 @@ static void __exit serial_txx9_exit(void)
1198#ifdef ENABLE_SERIAL_TXX9_PCI 1192#ifdef ENABLE_SERIAL_TXX9_PCI
1199 pci_unregister_driver(&serial_txx9_pci_driver); 1193 pci_unregister_driver(&serial_txx9_pci_driver);
1200#endif 1194#endif
1201 for (i = 0; i < UART_NR; i++) 1195 for (i = 0; i < UART_NR; i++) {
1202 uart_remove_one_port(&serial_txx9_reg, &serial_txx9_ports[i].port); 1196 struct uart_txx9_port *up = &serial_txx9_ports[i];
1197 if (up->port.iobase || up->port.mapbase)
1198 uart_remove_one_port(&serial_txx9_reg, &up->port);
1199 }
1203 1200
1204 uart_unregister_driver(&serial_txx9_reg); 1201 uart_unregister_driver(&serial_txx9_reg);
1205} 1202}