unsigned char prev_status;
#ifdef CONFIG_SERIO
- struct serio serio;
+ struct serio *serio;
int serio_open;
#endif
};
-#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel *)((PORT)->membase))
+#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel __iomem *)((PORT)->membase))
#define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT))
#define ZS_IS_KEYB(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_KEYB)
* The port lock must be held and local IRQs must be disabled
* when {read,write}_zsreg is invoked.
*/
-static unsigned char read_zsreg(struct zilog_channel *channel,
+static unsigned char read_zsreg(struct zilog_channel __iomem *channel,
unsigned char reg)
{
unsigned char retval;
return retval;
}
-static void write_zsreg(struct zilog_channel *channel,
+static void write_zsreg(struct zilog_channel __iomem *channel,
unsigned char reg, unsigned char value)
{
sbus_writeb(reg, &channel->control);
ZSDELAY();
}
-static void sunzilog_clear_fifo(struct zilog_channel *channel)
+static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel)
{
int i;
/* This function must only be called when the TX is not busy. The UART
* port lock must be held and local interrupts disabled.
*/
-static void __load_zsregs(struct zilog_channel *channel, unsigned char *regs)
+static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs)
{
int i;
* The UART port lock must be held and local interrupts disabled.
*/
static void sunzilog_maybe_update_regs(struct uart_sunzilog_port *up,
- struct zilog_channel *channel)
+ struct zilog_channel __iomem *channel)
{
if (!ZS_REGS_HELD(up)) {
if (ZS_TX_ACTIVE(up)) {
/* Stop-A is handled by drivers/char/keyboard.c now. */
#ifdef CONFIG_SERIO
if (up->serio_open)
- serio_interrupt(&up->serio, ch, 0, regs);
+ serio_interrupt(up->serio, ch, 0, regs);
#endif
} else if (ZS_IS_MOUSE(up)) {
int ret = suncore_mouse_baud_detection(ch, is_break);
case 0:
#ifdef CONFIG_SERIO
if (up->serio_open)
- serio_interrupt(&up->serio, ch, 0, regs);
+ serio_interrupt(up->serio, ch, 0, regs);
#endif
break;
};
static struct tty_struct *
sunzilog_receive_chars(struct uart_sunzilog_port *up,
- struct zilog_channel *channel,
+ struct zilog_channel __iomem *channel,
struct pt_regs *regs)
{
struct tty_struct *tty;
- unsigned char ch, r1;
+ unsigned char ch, r1, flag;
tty = NULL;
if (up->port.info != NULL && /* Unopened serial console */
continue;
}
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- tty->flip.work.func((void *)tty);
- /*
- * The 8250 bails out of the loop here,
- * but we need to read everything, or die.
- */
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- continue;
- }
-
/* A real serial line, record the character and status. */
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
up->port.icount.rx++;
if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
if (r1 & BRK_ABRT) {
up->port.icount.overrun++;
r1 &= up->port.read_status_mask;
if (r1 & BRK_ABRT)
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
else if (r1 & PAR_ERR)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (r1 & CRC_ERR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
continue;
if (up->port.ignore_status_mask == 0xff ||
(r1 & up->port.ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((r1 & Rx_OVR) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, ch, flag);
}
+ if (r1 & Rx_OVR)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
return tty;
}
static void sunzilog_status_handle(struct uart_sunzilog_port *up,
- struct zilog_channel *channel,
+ struct zilog_channel __iomem *channel,
struct pt_regs *regs)
{
unsigned char status;
}
static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
- struct zilog_channel *channel)
+ struct zilog_channel __iomem *channel)
{
struct circ_buf *xmit;
if (up->port.info == NULL)
goto ack_tx_int;
xmit = &up->port.info->xmit;
- if (uart_circ_empty(xmit)) {
- uart_write_wakeup(&up->port);
+ if (uart_circ_empty(xmit))
goto ack_tx_int;
- }
+
if (uart_tx_stopped(&up->port))
goto ack_tx_int;
struct uart_sunzilog_port *up = dev_id;
while (up) {
- struct zilog_channel *channel
+ struct zilog_channel __iomem *channel
= ZILOG_CHANNEL_FROM_PORT(&up->port);
struct tty_struct *tty;
unsigned char r3;
*/
static __inline__ unsigned char sunzilog_read_channel_status(struct uart_port *port)
{
- struct zilog_channel *channel;
- unsigned long flags;
+ struct zilog_channel __iomem *channel;
unsigned char status;
- spin_lock_irqsave(&port->lock, flags);
-
channel = ZILOG_CHANNEL_FROM_PORT(port);
status = sbus_readb(&channel->control);
ZSDELAY();
- spin_unlock_irqrestore(&port->lock, flags);
-
return status;
}
/* The port lock is not held. */
static unsigned int sunzilog_tx_empty(struct uart_port *port)
{
+ unsigned long flags;
unsigned char status;
unsigned int ret;
+ spin_lock_irqsave(&port->lock, flags);
+
status = sunzilog_read_channel_status(port);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
if (status & Tx_BUF_EMP)
ret = TIOCSER_TEMT;
else
return ret;
}
-/* The port lock is not held. */
+/* The port lock is held and interrupts are disabled. */
static unsigned int sunzilog_get_mctrl(struct uart_port *port)
{
unsigned char status;
static void sunzilog_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
- struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
+ struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
unsigned char set_bits, clear_bits;
set_bits = clear_bits = 0;
}
/* The port lock is held and interrupts are disabled. */
-static void sunzilog_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void sunzilog_stop_tx(struct uart_port *port)
{
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
}
/* The port lock is held and interrupts are disabled. */
-static void sunzilog_start_tx(struct uart_port *port, unsigned int tty_start)
+static void sunzilog_start_tx(struct uart_port *port)
{
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
- struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
+ struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
unsigned char status;
up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
static void sunzilog_stop_rx(struct uart_port *port)
{
struct uart_sunzilog_port *up = UART_ZILOG(port);
- struct zilog_channel *channel;
+ struct zilog_channel __iomem *channel;
if (ZS_IS_CONS(up))
return;
static void sunzilog_enable_ms(struct uart_port *port)
{
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
- struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
+ struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
unsigned char new_reg;
new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE);
static void sunzilog_break_ctl(struct uart_port *port, int break_state)
{
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
- struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
+ struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
unsigned char set_bits, clear_bits, new_reg;
unsigned long flags;
static void __sunzilog_startup(struct uart_sunzilog_port *up)
{
- struct zilog_channel *channel;
+ struct zilog_channel __iomem *channel;
channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
up->prev_status = sbus_readb(&channel->control);
static void sunzilog_shutdown(struct uart_port *port)
{
struct uart_sunzilog_port *up = UART_ZILOG(port);
- struct zilog_channel *channel;
+ struct zilog_channel __iomem *channel;
unsigned long flags;
if (ZS_IS_CONS(up))
sunzilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port));
+ uart_update_timeout(port, termios->c_cflag, baud);
+
spin_unlock_irqrestore(&up->port.lock, flags);
}
};
static struct uart_sunzilog_port *sunzilog_port_table;
-static struct zilog_layout **sunzilog_chip_regs;
+static struct zilog_layout __iomem **sunzilog_chip_regs;
static struct uart_sunzilog_port *sunzilog_irq_chain;
static int zilog_irq = -1;
static void __init sunzilog_alloc_tables(void)
{
- sunzilog_port_table = (struct uart_sunzilog_port *)
+ sunzilog_port_table =
alloc_one_table(NUM_CHANNELS * sizeof(struct uart_sunzilog_port));
- sunzilog_chip_regs = (struct zilog_layout **)
- alloc_one_table(NUM_SUNZILOG * sizeof(struct zilog_layout *));
+ sunzilog_chip_regs =
+ alloc_one_table(NUM_SUNZILOG * sizeof(struct zilog_layout __iomem *));
if (sunzilog_port_table == NULL || sunzilog_chip_regs == NULL) {
prom_printf("SunZilog: Cannot allocate tables.\n");
/* We used to attempt to use the address property of the Zilog device node
* but that totally is not necessary on sparc64.
*/
-static struct zilog_layout * __init get_zs_sun4u(int chip, int zsnode)
+static struct zilog_layout __iomem * __init get_zs_sun4u(int chip, int zsnode)
{
- unsigned long mapped_addr;
+ void __iomem *mapped_addr;
unsigned int sun4u_ino;
struct sbus_bus *sbus = NULL;
struct sbus_dev *sdev = NULL;
apply_fhc_ranges(central_bus->child,
&zsregs[0], 1);
apply_central_ranges(central_bus, &zsregs[0], 1);
- mapped_addr =
- (((u64)zsregs[0].which_io)<<32UL) |
- ((u64)zsregs[0].phys_addr);
+ mapped_addr = (void __iomem *)
+ ((((u64)zsregs[0].which_io)<<32UL) |
+ ((u64)zsregs[0].phys_addr));
}
if (zilog_irq == -1) {
}
}
- return (struct zilog_layout *) mapped_addr;
+ return (struct zilog_layout __iomem *) mapped_addr;
}
#else /* CONFIG_SPARC64 */
* XXX The sun4d case is utterly screwed: it tries to re-walk the tree
* (for the 3rd time) in order to find bootbus and cpu. Streamline it.
*/
-static struct zilog_layout * __init get_zs_sun4cmd(int chip, int node)
+static struct zilog_layout __iomem * __init get_zs_sun4cmd(int chip, int node)
{
struct linux_prom_irqs irq_info[2];
- unsigned long mapped_addr = 0;
+ void __iomem *mapped_addr = NULL;
int zsnode, cpunode, bbnode;
struct linux_prom_registers zsreg[4];
struct resource res;
prom_halt();
}
- return (struct zilog_layout *) mapped_addr;
+ return (struct zilog_layout __iomem *) mapped_addr;
}
#endif /* !(CONFIG_SPARC64) */
/* Get the address of the registers for SunZilog instance CHIP. */
-static struct zilog_layout * __init get_zs(int chip, int node)
+static struct zilog_layout __iomem * __init get_zs(int chip, int node)
{
if (chip < 0 || chip >= NUM_SUNZILOG) {
prom_printf("SunZilog: Illegal chip number %d in get_zs.\n", chip);
zilog_irq = 12;
res.end = (res.start + (8 - 1));
res.flags = IORESOURCE_IO;
- return (struct zilog_layout *) sbus_ioremap(&res, 0, 8, "SunZilog");
+ return sbus_ioremap(&res, 0, 8, "SunZilog");
}
return get_zs_sun4cmd(chip, node);
#define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */
-static void sunzilog_put_char(struct zilog_channel *channel, unsigned char ch)
+static void sunzilog_put_char(struct zilog_channel __iomem *channel, unsigned char ch)
{
int loops = ZS_PUT_CHAR_MAX_DELAY;
#ifdef CONFIG_SERIO
-static spinlock_t sunzilog_serio_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(sunzilog_serio_lock);
static int sunzilog_serio_write(struct serio *serio, unsigned char ch)
{
- struct uart_sunzilog_port *up = serio->driver;
+ struct uart_sunzilog_port *up = serio->port_data;
unsigned long flags;
spin_lock_irqsave(&sunzilog_serio_lock, flags);
static int sunzilog_serio_open(struct serio *serio)
{
- struct uart_sunzilog_port *up = serio->driver;
+ struct uart_sunzilog_port *up = serio->port_data;
unsigned long flags;
int ret;
static void sunzilog_serio_close(struct serio *serio)
{
- struct uart_sunzilog_port *up = serio->driver;
+ struct uart_sunzilog_port *up = serio->port_data;
unsigned long flags;
spin_lock_irqsave(&sunzilog_serio_lock, flags);
static void __init sunzilog_prepare(void)
{
struct uart_sunzilog_port *up;
- struct zilog_layout *rp;
+ struct zilog_layout __iomem *rp;
int channel, chip;
/*
for (chip = 0; chip < NUM_SUNZILOG; chip++) {
rp = sunzilog_chip_regs[chip];
- up[(chip * 2) + 0].port.membase = (char *) &rp->channelA;
- up[(chip * 2) + 1].port.membase = (char *) &rp->channelB;
+ up[(chip * 2) + 0].port.membase = (void __iomem *)&rp->channelA;
+ up[(chip * 2) + 1].port.membase = (void __iomem *)&rp->channelB;
/* Channel A */
- up[(chip * 2) + 0].port.iotype = SERIAL_IO_MEM;
+ up[(chip * 2) + 0].port.iotype = UPIO_MEM;
up[(chip * 2) + 0].port.irq = zilog_irq;
up[(chip * 2) + 0].port.uartclk = ZS_CLOCK;
up[(chip * 2) + 0].port.fifosize = 1;
up[(chip * 2) + 0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
/* Channel B */
- up[(chip * 2) + 1].port.iotype = SERIAL_IO_MEM;
+ up[(chip * 2) + 1].port.iotype = UPIO_MEM;
up[(chip * 2) + 1].port.irq = zilog_irq;
up[(chip * 2) + 1].port.uartclk = ZS_CLOCK;
up[(chip * 2) + 1].port.fifosize = 1;
up->curregs[R15] = BRKIE;
brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
sunzilog_convert_to_zs(up, up->cflag, 0, brg);
+ sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
+ __sunzilog_startup(up);
+}
#ifdef CONFIG_SERIO
- memset(&up->serio, 0, sizeof(up->serio));
+static void __init sunzilog_register_serio(struct uart_sunzilog_port *up, int channel)
+{
+ struct serio *serio;
- up->serio.driver = up;
+ up->serio = serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+ if (serio) {
+ memset(serio, 0, sizeof(*serio));
- up->serio.type = SERIO_RS232;
- if (channel == KEYBOARD_LINE) {
- up->serio.type |= SERIO_SUNKBD;
- up->serio.name = "zskbd";
- } else {
- up->serio.type |= (SERIO_SUN | (1 << 16));
- up->serio.name = "zsms";
- }
- up->serio.phys = (channel == KEYBOARD_LINE ?
- "zs/serio0" : "zs/serio1");
+ serio->port_data = up;
- up->serio.write = sunzilog_serio_write;
- up->serio.open = sunzilog_serio_open;
- up->serio.close = sunzilog_serio_close;
+ serio->id.type = SERIO_RS232;
+ if (channel == KEYBOARD_LINE) {
+ serio->id.proto = SERIO_SUNKBD;
+ strlcpy(serio->name, "zskbd", sizeof(serio->name));
+ } else {
+ serio->id.proto = SERIO_SUN;
+ serio->id.extra = 1;
+ strlcpy(serio->name, "zsms", sizeof(serio->name));
+ }
+ strlcpy(serio->phys,
+ (channel == KEYBOARD_LINE ? "zs/serio0" : "zs/serio1"),
+ sizeof(serio->phys));
- serio_register_port(&up->serio);
-#endif
+ serio->write = sunzilog_serio_write;
+ serio->open = sunzilog_serio_open;
+ serio->close = sunzilog_serio_close;
- sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
- __sunzilog_startup(up);
+ serio_register_port(serio);
+ } else {
+ printk(KERN_WARNING "zs%d: not enough memory for serio port\n",
+ channel);
+ }
}
+#endif
static void __init sunzilog_init_hw(void)
{
for (i = 0; i < NUM_CHANNELS; i++) {
struct uart_sunzilog_port *up = &sunzilog_port_table[i];
- struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+ struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
unsigned long flags;
int baud, brg;
}
spin_unlock_irqrestore(&up->port.lock, flags);
+
+#ifdef CONFIG_SERIO
+ if (i == KEYBOARD_LINE || i == MOUSE_LINE)
+ sunzilog_register_serio(up, i);
+#endif
}
}
-static struct zilog_layout * __init get_zs(int chip, int node);
+static struct zilog_layout __iomem * __init get_zs(int chip, int node);
static void __init sunzilog_scan_probe(struct zs_probe_scan *t, int node)
{
ret = uart_register_driver(&sunzilog_reg);
if (ret == 0) {
+ sunzilog_console_init();
for (i = 0; i < NUM_CHANNELS; i++) {
struct uart_sunzilog_port *up = &sunzilog_port_table[i];
sunzilog_alloc_tables();
sunzilog_ports_init();
- sunzilog_console_init();
return 0;
}
for (i = 0; i < NUM_CHANNELS; i++) {
struct uart_sunzilog_port *up = &sunzilog_port_table[i];
- if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up))
- continue;
-
- uart_remove_one_port(&sunzilog_reg, &up->port);
+ if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
+#ifdef CONFIG_SERIO
+ if (up->serio) {
+ serio_unregister_port(up->serio);
+ up->serio = NULL;
+ }
+#endif
+ } else
+ uart_remove_one_port(&sunzilog_reg, &up->port);
}
uart_unregister_driver(&sunzilog_reg);