X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fserial%2Fserial_txx9.c;h=ee98a867bc6dabd5604763fb7c0c26518bdb57bf;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=3bdee64d1a997101f12f49f9f7c509c25694cbd8;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 3bdee64d1..ee98a867b 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -33,10 +33,6 @@ * 1.02 Cleanup. (import 8250.c changes) * 1.03 Fix low-latency mode. (import 8250.c changes) * 1.04 Remove usage of deprecated functions, cleanup. - * 1.05 More strict check in verify_port. Cleanup. - * 1.06 Do not insert a char caused previous overrun. - * Fix some spin_locks. - * Do not call uart_add_one_port for absent ports. */ #include @@ -61,7 +57,7 @@ #include #include -static char *serial_version = "1.06"; +static char *serial_version = "1.04"; static char *serial_name = "TX39/49 Serial driver"; #define PASS_LIMIT 256 @@ -98,8 +94,6 @@ static char *serial_name = "TX39/49 Serial driver"; #define UART_NR 4 #endif -#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) - struct uart_txx9_port { struct uart_port port; @@ -216,7 +210,7 @@ static inline unsigned int sio_in(struct uart_txx9_port *up, int offset) { switch (up->port.iotype) { default: - return __raw_readl(up->port.membase + offset); + return *(volatile u32 *)(up->port.membase + offset); case UPIO_PORT: return inl(up->port.iobase + offset); } @@ -227,7 +221,7 @@ sio_out(struct uart_txx9_port *up, int offset, int value) { switch (up->port.iotype) { default: - __raw_writel(value, up->port.membase + offset); + *(volatile u32 *)(up->port.membase + offset) = value; break; case UPIO_PORT: outl(value, up->port.iobase + offset); @@ -265,19 +259,34 @@ sio_quot_set(struct uart_txx9_port *up, int quot) static void serial_txx9_stop_tx(struct uart_port *port) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; + unsigned long flags; + + spin_lock_irqsave(&up->port.lock, flags); sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_TIE); + spin_unlock_irqrestore(&up->port.lock, flags); } static void serial_txx9_start_tx(struct uart_port *port) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; + unsigned long flags; + + spin_lock_irqsave(&up->port.lock, flags); sio_set(up, TXX9_SIDICR, TXX9_SIDICR_TIE); + spin_unlock_irqrestore(&up->port.lock, flags); } static void serial_txx9_stop_rx(struct uart_port *port) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; + unsigned long flags; + + spin_lock_irqsave(&up->port.lock, flags); up->port.read_status_mask &= ~TXX9_SIDISR_RDIS; +#if 0 + sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_RIE); +#endif + spin_unlock_irqrestore(&up->port.lock, flags); } static void serial_txx9_enable_ms(struct uart_port *port) @@ -293,16 +302,12 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r unsigned int disr = *status; int max_count = 256; char flag; - unsigned int next_ignore_status_mask; do { ch = sio_in(up, TXX9_SIRFIFO); flag = TTY_NORMAL; up->port.icount.rx++; - /* mask out RFDN_MASK bit added by previous overrun */ - next_ignore_status_mask = - up->port.ignore_status_mask & ~TXX9_SIDISR_RFDN_MASK; if (unlikely(disr & (TXX9_SIDISR_UBRK | TXX9_SIDISR_UPER | TXX9_SIDISR_UFER | TXX9_SIDISR_UOER))) { /* @@ -323,17 +328,8 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r up->port.icount.parity++; else if (disr & TXX9_SIDISR_UFER) up->port.icount.frame++; - if (disr & TXX9_SIDISR_UOER) { + if (disr & TXX9_SIDISR_UOER) up->port.icount.overrun++; - /* - * The receiver read buffer still hold - * a char which caused overrun. - * Ignore next char by adding RFDN_MASK - * to ignore_status_mask temporarily. - */ - next_ignore_status_mask |= - TXX9_SIDISR_RFDN_MASK; - } /* * Mask off conditions which should be ingored. @@ -353,7 +349,6 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag); ignore_char: - up->port.ignore_status_mask = next_ignore_status_mask; disr = sio_in(up, TXX9_SIDISR); } while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0)); spin_unlock(&up->port.lock); @@ -455,11 +450,14 @@ static unsigned int serial_txx9_get_mctrl(struct uart_port *port) static void serial_txx9_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; + unsigned long flags; + spin_lock_irqsave(&up->port.lock, flags); if (mctrl & TIOCM_RTS) sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC); else sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC); + spin_unlock_irqrestore(&up->port.lock, flags); } static void serial_txx9_break_ctl(struct uart_port *port, int break_state) @@ -483,7 +481,7 @@ static int serial_txx9_startup(struct uart_port *port) /* * Clear the FIFO buffers and disable them. - * (they will be reenabled in set_termios()) + * (they will be reeanbled in set_termios()) */ sio_set(up, TXX9_SIFCR, TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE); @@ -786,14 +784,8 @@ static void serial_txx9_config_port(struct uart_port *port, int uflags) static int serial_txx9_verify_port(struct uart_port *port, struct serial_struct *ser) { - unsigned long new_port = ser->port; - if (HIGH_BITS_OFFSET) - new_port += (unsigned long)ser->port_high << HIGH_BITS_OFFSET; - if (ser->type != port->type || - ser->irq != port->irq || - ser->io_type != port->iotype || - new_port != port->iobase || - (unsigned long)ser->iomem_base != port->mapbase) + if (ser->irq < 0 || + ser->baud_base < 9600 || ser->type != PORT_TXX9) return -EINVAL; return 0; } @@ -835,8 +827,7 @@ static void __init serial_txx9_register_ports(struct uart_driver *drv) up->port.line = i; up->port.ops = &serial_txx9_pops; - if (up->port.iobase || up->port.mapbase) - uart_add_one_port(drv, &up->port); + uart_add_one_port(drv, &up->port); } } @@ -863,14 +854,6 @@ static inline void wait_for_xmitr(struct uart_txx9_port *up) } } -static void serial_txx9_console_putchar(struct uart_port *port, int ch) -{ - struct uart_txx9_port *up = (struct uart_txx9_port *)port; - - wait_for_xmitr(up); - sio_out(up, TXX9_SITFIFO, ch); -} - /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -882,6 +865,7 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count) { struct uart_txx9_port *up = &serial_txx9_ports[co->index]; unsigned int ier, flcr; + int i; /* * First save the UER then disable the interrupts @@ -895,7 +879,22 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count) if (!(up->port.flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES)) sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES); - uart_console_write(&up->port, s, count, serial_txx9_console_putchar); + /* + * Now, do each character + */ + for (i = 0; i < count; i++, s++) { + wait_for_xmitr(up); + + /* + * Send the character out. + * If a LF, also do CR... + */ + sio_out(up, TXX9_SITFIFO, *s); + if (*s == 10) { + wait_for_xmitr(up); + sio_out(up, TXX9_SITFIFO, 13); + } + } /* * Finally, wait for transmitter to become empty @@ -927,6 +926,11 @@ static int serial_txx9_console_setup(struct console *co, char *options) if (!port->ops) return -ENODEV; + /* + * Temporary fix. + */ + spin_lock_init(&port->lock); + /* * Disable UART interrupts, set DTR and RTS high * and set speed. @@ -1037,10 +1041,11 @@ static int __devinit serial_txx9_register_port(struct uart_port *port) mutex_lock(&serial_txx9_mutex); for (i = 0; i < UART_NR; i++) { uart = &serial_txx9_ports[i]; - if (!(uart->port.iobase || uart->port.mapbase)) + if (uart->port.type == PORT_UNKNOWN) break; } if (i < UART_NR) { + uart_remove_one_port(&serial_txx9_reg, &uart->port); uart->port.iobase = port->iobase; uart->port.membase = port->membase; uart->port.irq = port->irq; @@ -1075,8 +1080,9 @@ static void __devexit serial_txx9_unregister_port(int line) uart->port.type = PORT_UNKNOWN; uart->port.iobase = 0; uart->port.mapbase = 0; - uart->port.membase = NULL; + uart->port.membase = 0; uart->port.dev = NULL; + uart_add_one_port(&serial_txx9_reg, &uart->port); mutex_unlock(&serial_txx9_mutex); } @@ -1192,11 +1198,8 @@ static void __exit serial_txx9_exit(void) #ifdef ENABLE_SERIAL_TXX9_PCI pci_unregister_driver(&serial_txx9_pci_driver); #endif - for (i = 0; i < UART_NR; i++) { - struct uart_txx9_port *up = &serial_txx9_ports[i]; - if (up->port.iobase || up->port.mapbase) - uart_remove_one_port(&serial_txx9_reg, &up->port); - } + for (i = 0; i < UART_NR; i++) + uart_remove_one_port(&serial_txx9_reg, &serial_txx9_ports[i].port); uart_unregister_driver(&serial_txx9_reg); }