1
0
Fork 0

[PATCH] txx9 serial update

Support for the new RBHMA4500 eval board for the TX4938.  General update
from the 8250 ancestor of this driver.  Replace use of deprecated
interfaces.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Acked-by: Russell King <rmk@arm.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
hifive-unleashed-5.1
Ralf Baechle 2005-09-09 13:01:32 -07:00 committed by Linus Torvalds
parent fef266580e
commit f5ee56cc18
1 changed files with 91 additions and 27 deletions

View File

@ -31,6 +31,8 @@
* 1.01 Set fifosize to make tx_empry called properly.
* Use standard uart_get_divisor.
* 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.
*/
#include <linux/config.h>
@ -54,7 +56,7 @@
#include <asm/io.h>
#include <asm/irq.h>
static char *serial_version = "1.02";
static char *serial_version = "1.04";
static char *serial_name = "TX39/49 Serial driver";
#define PASS_LIMIT 256
@ -86,9 +88,9 @@ static char *serial_name = "TX39/49 Serial driver";
*/
#ifdef ENABLE_SERIAL_TXX9_PCI
#define NR_PCI_BOARDS 4
#define UART_NR (2 + NR_PCI_BOARDS)
#define UART_NR (4 + NR_PCI_BOARDS)
#else
#define UART_NR 2
#define UART_NR 4
#endif
struct uart_txx9_port {
@ -304,8 +306,11 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
/* The following is not allowed by the tty layer and
unsafe. It should be fixed ASAP */
if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
if(tty->low_latency)
if (tty->low_latency) {
spin_unlock(&up->port.lock);
tty_flip_buffer_push(tty);
spin_lock(&up->port.lock);
}
/* If this failed then we will throw away the
bytes but must do so to clear interrupts */
}
@ -356,7 +361,9 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
ignore_char:
disr = sio_in(up, TXX9_SIDISR);
} while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
spin_unlock(&up->port.lock);
tty_flip_buffer_push(tty);
spin_lock(&up->port.lock);
*status = disr;
}
@ -667,17 +674,8 @@ serial_txx9_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
struct uart_txx9_port *up = (struct uart_txx9_port *)port;
if (state) {
/* sleep */
if (up->pm)
up->pm(port, state, oldstate);
} else {
/* wake */
if (up->pm)
up->pm(port, state, oldstate);
}
if (up->pm)
up->pm(port, state, oldstate);
}
static int serial_txx9_request_resource(struct uart_txx9_port *up)
@ -979,14 +977,6 @@ static int __init serial_txx9_console_init(void)
}
console_initcall(serial_txx9_console_init);
static int __init serial_txx9_late_console_init(void)
{
if (!(serial_txx9_console.flags & CON_ENABLED))
register_console(&serial_txx9_console);
return 0;
}
late_initcall(serial_txx9_late_console_init);
#define SERIAL_TXX9_CONSOLE &serial_txx9_console
#else
#define SERIAL_TXX9_CONSOLE NULL
@ -1039,6 +1029,73 @@ static void serial_txx9_resume_port(int line)
uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port);
}
static DECLARE_MUTEX(serial_txx9_sem);
/**
* serial_txx9_register_port - register a serial port
* @port: serial port template
*
* Configure the serial port specified by the request.
*
* The port is then probed and if necessary the IRQ is autodetected
* If this fails an error is returned.
*
* On success the port is ready to use and the line number is returned.
*/
static int __devinit serial_txx9_register_port(struct uart_port *port)
{
int i;
struct uart_txx9_port *uart;
int ret = -ENOSPC;
down(&serial_txx9_sem);
for (i = 0; i < UART_NR; i++) {
uart = &serial_txx9_ports[i];
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;
uart->port.uartclk = port->uartclk;
uart->port.iotype = port->iotype;
uart->port.flags = port->flags | UPF_BOOT_AUTOCONF;
uart->port.mapbase = port->mapbase;
if (port->dev)
uart->port.dev = port->dev;
ret = uart_add_one_port(&serial_txx9_reg, &uart->port);
if (ret == 0)
ret = uart->port.line;
}
up(&serial_txx9_sem);
return ret;
}
/**
* serial_txx9_unregister_port - remove a txx9 serial port at runtime
* @line: serial line number
*
* Remove one serial port. This may not be called from interrupt
* context. We hand the port back to the our control.
*/
static void __devexit serial_txx9_unregister_port(int line)
{
struct uart_txx9_port *uart = &serial_txx9_ports[line];
down(&serial_txx9_sem);
uart_remove_one_port(&serial_txx9_reg, &uart->port);
uart->port.flags = 0;
uart->port.type = PORT_UNKNOWN;
uart->port.iobase = 0;
uart->port.mapbase = 0;
uart->port.membase = 0;
uart->port.dev = NULL;
uart_add_one_port(&serial_txx9_reg, &uart->port);
up(&serial_txx9_sem);
}
/*
* Probe one serial board. Unfortunately, there is no rhyme nor reason
* to the arrangement of serial ports on a PCI card.
@ -1056,13 +1113,13 @@ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
memset(&port, 0, sizeof(port));
port.ops = &serial_txx9_pops;
port.flags |= UPF_BOOT_AUTOCONF; /* uart_ops.config_port will be called */
port.flags |= UPF_TXX9_HAVE_CTS_LINE;
port.uartclk = 66670000;
port.irq = dev->irq;
port.iotype = UPIO_PORT;
port.iobase = pci_resource_start(dev, 1);
line = uart_register_port(&serial_txx9_reg, &port);
port.dev = &dev->dev;
line = serial_txx9_register_port(&port);
if (line < 0) {
printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line);
}
@ -1078,7 +1135,7 @@ static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
pci_set_drvdata(dev, NULL);
if (line) {
uart_unregister_port(&serial_txx9_reg, line);
serial_txx9_unregister_port(line);
pci_disable_device(dev);
}
}
@ -1089,6 +1146,8 @@ static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state)
if (line)
serial_txx9_suspend_port(line);
pci_save_state(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
}
@ -1096,8 +1155,13 @@ static int pciserial_txx9_resume_one(struct pci_dev *dev)
{
int line = (int)(long)pci_get_drvdata(dev);
if (line)
pci_set_power_state(dev, PCI_D0);
pci_restore_state(dev);
if (line) {
pci_enable_device(dev);
serial_txx9_resume_port(line);
}
return 0;
}