**
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/delay.h> /* for udelay */
#include <linux/device.h>
#include <asm/io.h>
+#include <asm/irq.h>
#include <asm/parisc-device.h>
#ifdef CONFIG_MAGIC_SYSRQ
#define MUX_BREAK(status) ((status & 0xF000) == 0x2000)
#define MUX_NR 256
-static unsigned int port_cnt = 0;
+static unsigned int port_cnt __read_mostly;
static struct uart_port mux_ports[MUX_NR];
static struct uart_driver mux_driver = {
static struct timer_list mux_timer;
-#define UART_PUT_CHAR(p, c) __raw_writel((c), (unsigned long)(p)->membase + IO_DATA_REG_OFFSET)
-#define UART_GET_FIFO_CNT(p) __raw_readl((unsigned long)(p)->membase + IO_DCOUNT_REG_OFFSET)
+#define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET)
+#define UART_GET_FIFO_CNT(p) __raw_readl((p)->membase + IO_DCOUNT_REG_OFFSET)
#define GET_MUX_PORTS(iodc_data) ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8
/**
*/
static unsigned int mux_tx_empty(struct uart_port *port)
{
- unsigned int cnt = __raw_readl((unsigned long)port->membase
- + IO_DCOUNT_REG_OFFSET);
-
- return cnt ? 0 : TIOCSER_TEMT;
+ return UART_GET_FIFO_CNT(port) ? 0 : TIOCSER_TEMT;
}
/**
/**
* mux_stop_tx - Stop transmitting characters.
* @port: Ptr to the uart_port.
- * @tty_stop: tty layer issue this command?
*
* The Serial MUX does not support this function.
*/
-static void mux_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void mux_stop_tx(struct uart_port *port)
{
}
/**
* mux_start_tx - Start transmitting characters.
* @port: Ptr to the uart_port.
- * @tty_start: tty layer issue this command?
*
* The Serial Mux does not support this function.
*/
-static void mux_start_tx(struct uart_port *port, unsigned int tty_start)
+static void mux_start_tx(struct uart_port *port)
{
}
}
if(uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- mux_stop_tx(port, 0);
+ mux_stop_tx(port);
return;
}
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- mux_stop_tx(port, 0);
+ mux_stop_tx(port);
}
/**
__u32 start_count = port->icount.rx;
while(1) {
- data = __raw_readl((unsigned long)port->membase
- + IO_DATA_REG_OFFSET);
+ data = __raw_readl(port->membase + IO_DATA_REG_OFFSET);
if (MUX_STATUS(data))
continue;
if (MUX_EOFIFO(data))
break;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- continue;
-
- *tty->flip.char_buf_ptr = data & 0xffu;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
port->icount.rx++;
if (MUX_BREAK(data)) {
continue;
}
- if (uart_handle_sysrq_char(port, data & 0xffu, NULL))
+ if (uart_handle_sysrq_char(port, data & 0xffu))
continue;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, data & 0xFF, TTY_NORMAL);
}
if (start_count != port->icount.rx) {
* The Serial Mux does not support this function.
*/
static void
-mux_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+mux_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
}
.write = mux_console_write,
.device = mux_console_device,
.setup = mux_console_setup,
- .flags = CON_BOOT|CON_PRINTBUFFER|CON_ENABLED,
+ .flags = CON_ENABLED | CON_PRINTBUFFER,
.index = 0,
};
unsigned long bytecnt;
struct uart_port *port;
- status = pdc_iodc_read(&bytecnt, dev->hpa, 0, iodc_data, 32);
+ status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32);
if(status != PDC_OK) {
printk(KERN_ERR "Serial mux: Unable to read IODC.\n");
return 1;
for(i = 0; i < ports; ++i, ++port_cnt) {
port = &mux_ports[port_cnt];
port->iobase = 0;
- port->mapbase = dev->hpa + MUX_OFFSET + (i * MUX_LINE_OFFSET);
- port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET);
- port->iotype = SERIAL_IO_MEM;
+ port->mapbase = dev->hpa.start + MUX_OFFSET +
+ (i * MUX_LINE_OFFSET);
+ port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET);
+ port->iotype = UPIO_MEM;
port->type = PORT_MUX;
- port->irq = SERIAL_IRQ_NONE;
+ port->irq = NO_IRQ;
port->uartclk = 0;
port->fifosize = MUX_FIFO_SIZE;
port->ops = &mux_pops;
port->flags = UPF_BOOT_AUTOCONF;
port->line = port_cnt;
+
+ /* The port->timeout needs to match what is present in
+ * uart_wait_until_sent in serial_core.c. Otherwise
+ * the time spent in msleep_interruptable will be very
+ * long, causing the appearance of a console hang.
+ */
+ port->timeout = HZ / 50;
+ spin_lock_init(&port->lock);
status = uart_add_one_port(&mux_driver, port);
BUG_ON(status);
}
MODULE_DEVICE_TABLE(parisc, mux_tbl);
static struct parisc_driver serial_mux_driver = {
- .name = "Serial MUX",
+ .name = "serial_mux",
.id_table = mux_tbl,
.probe = mux_probe,
};
for (i = 0; i < port_cnt; i++) {
uart_remove_one_port(&mux_driver, &mux_ports[i]);
+ if (mux_ports[i].membase)
+ iounmap(mux_ports[i].membase);
}
uart_unregister_driver(&mux_driver);