X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fserial%2Fpmac_zilog.c;h=752ef07516b9d7d6cfa6ec2842334b0a790ab20a;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=d452d4b4014732161a4d372991b0e011aa254e2e;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index d452d4b40..752ef0751 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -29,6 +29,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * 2004-08-06 Harald Welte + * - Enable BREAK interrupt + * - Add support for sysreq + * * TODO: - Add DMA support * - Defer port shutdown to a few seconds after close * - maybe put something right into uap->clk_divisor @@ -36,8 +40,8 @@ #undef DEBUG #undef DEBUG_HARD +#undef USE_CTRL_O_SYSRQ -#include #include #include @@ -53,16 +57,21 @@ #include #include #include +#include +#include +#include #include #include #include #include -#include #include #include #include #include -#include + +#if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif #include #include @@ -86,12 +95,11 @@ MODULE_LICENSE("GPL"); */ static struct uart_pmac_port pmz_ports[MAX_ZS_PORTS]; static int pmz_ports_count; -static DECLARE_MUTEX(pmz_irq_sem); +static DEFINE_MUTEX(pmz_irq_mutex); static struct uart_driver pmz_uart_reg = { .owner = THIS_MODULE, .driver_name = "ttyS", - .devfs_name = "tts/", .dev_name = "ttyS", .major = TTY_MAJOR, }; @@ -196,14 +204,12 @@ static void pmz_maybe_update_regs(struct uart_pmac_port *uap) } } -static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, - struct pt_regs *regs) +static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) { struct tty_struct *tty = NULL; - unsigned char ch, r1, drop, error; + unsigned char ch, r1, drop, error, flag; int loops = 0; - retry: /* The interrupt can be enabled when the port isn't open, typically * that happens when using one port is open and the other closed (stale * interrupt) or when one port is used as a console. @@ -236,20 +242,6 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, error = 0; drop = 0; - if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { - /* Have to drop the lock here */ - pmz_debug("pmz: flip overflow\n"); - spin_unlock(&uap->port.lock); - tty->flip.work.func((void *)tty); - spin_lock(&uap->port.lock); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - drop = 1; - if (ZS_IS_ASLEEP(uap)) - return 0; - if (!ZS_IS_OPEN(uap)) - goto retry; - } - r1 = read_zsreg(uap, R1); ch = read_zsdata(uap); @@ -259,15 +251,33 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, } ch &= uap->parity_mask; - if (ch == 0 && uap->prev_status & BRK_ABRT) - r1 |= BRK_ABRT; + if (ch == 0 && uap->flags & PMACZILOG_FLAG_BREAK) { + uap->flags &= ~PMACZILOG_FLAG_BREAK; + } + +#if defined(CONFIG_MAGIC_SYSRQ) && defined(CONFIG_SERIAL_CORE_CONSOLE) +#ifdef USE_CTRL_O_SYSRQ + /* Handle the SysRq ^O Hack */ + if (ch == '\x0f') { + uap->port.sysrq = jiffies + HZ*5; + goto next_char; + } +#endif /* USE_CTRL_O_SYSRQ */ + if (uap->port.sysrq) { + int swallow; + spin_unlock(&uap->port.lock); + swallow = uart_handle_sysrq_char(&uap->port, ch); + spin_lock(&uap->port.lock); + if (swallow) + goto next_char; + } +#endif /* CONFIG_MAGIC_SYSRQ && CONFIG_SERIAL_CORE_CONSOLE */ /* A real serial line, record the character and status. */ if (drop) goto next_char; - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; + flag = TTY_NORMAL; uap->port.icount.rx++; if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) { @@ -276,10 +286,8 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, pmz_debug("pmz: got break !\n"); r1 &= ~(PAR_ERR | CRC_ERR); uap->port.icount.brk++; - if (uart_handle_break(&uap->port)) { - pmz_debug("pmz: do handle break !\n"); + if (uart_handle_break(&uap->port)) goto next_char; - } } else if (r1 & PAR_ERR) uap->port.icount.parity++; @@ -289,30 +297,19 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, uap->port.icount.overrun++; r1 &= uap->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; - } - if (uart_handle_sysrq_char(&uap->port, ch, regs)) { - pmz_debug("pmz: sysrq swallowed the char\n"); - goto next_char; + flag = TTY_FRAME; } if (uap->port.ignore_status_mask == 0xff || (r1 & uap->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); next_char: /* We can get stuck in an infinite loop getting char 0 when the * line is in a wrong HW state, we break that here. @@ -337,7 +334,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, return tty; } -static void pmz_status_handle(struct uart_pmac_port *uap, struct pt_regs *regs) +static void pmz_status_handle(struct uart_pmac_port *uap) { unsigned char status; @@ -364,6 +361,9 @@ static void pmz_status_handle(struct uart_pmac_port *uap, struct pt_regs *regs) wake_up_interruptible(&uap->port.info->delta_msr_wait); } + if (status & BRK_ABRT) + uap->flags |= PMACZILOG_FLAG_BREAK; + uap->prev_status = status; } @@ -437,7 +437,7 @@ ack_tx_int: } /* Hrm... we register that twice, fixme later.... */ -static irqreturn_t pmz_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t pmz_interrupt(int irq, void *dev_id) { struct uart_pmac_port *uap = dev_id; struct uart_pmac_port *uap_a; @@ -461,9 +461,9 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id, struct pt_regs *regs) write_zsreg(uap_a, R0, RES_H_IUS); zssync(uap_a); if (r3 & CHAEXT) - pmz_status_handle(uap_a, regs); + pmz_status_handle(uap_a); if (r3 & CHARxIP) - tty = pmz_receive_chars(uap_a, regs); + tty = pmz_receive_chars(uap_a); if (r3 & CHATxIP) pmz_transmit_chars(uap_a); rc = IRQ_HANDLED; @@ -481,9 +481,9 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id, struct pt_regs *regs) write_zsreg(uap_b, R0, RES_H_IUS); zssync(uap_b); if (r3 & CHBEXT) - pmz_status_handle(uap_b, regs); + pmz_status_handle(uap_b); if (r3 & CHBRxIP) - tty = pmz_receive_chars(uap_b, regs); + tty = pmz_receive_chars(uap_b); if (r3 & CHBTxIP) pmz_transmit_chars(uap_b); rc = IRQ_HANDLED; @@ -578,7 +578,7 @@ static void pmz_set_mctrl(struct uart_port *port, unsigned int mctrl) /* * Get Modem Control bits (only the input ones, the core will * or that with a cached value of the control ones) - * The port lock is not held. + * The port lock is held and interrupts are disabled. */ static unsigned int pmz_get_mctrl(struct uart_port *port) { @@ -589,7 +589,7 @@ static unsigned int pmz_get_mctrl(struct uart_port *port) if (ZS_IS_ASLEEP(uap) || uap->node == NULL) return 0; - status = pmz_peek_status(to_pmz(port)); + status = read_zsreg(uap, R0); ret = 0; if (status & DCD) @@ -604,11 +604,10 @@ static unsigned int pmz_get_mctrl(struct uart_port *port) /* * Stop TX side. Dealt like sunzilog at next Tx interrupt, - * though for DMA, we will have to do a bit more. What is - * the meaning of the tty_stop bit ? XXX + * though for DMA, we will have to do a bit more. * The port lock is held and interrupts are disabled. */ -static void pmz_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void pmz_stop_tx(struct uart_port *port) { to_pmz(port)->flags |= PMACZILOG_FLAG_TX_STOPPED; } @@ -617,7 +616,7 @@ static void pmz_stop_tx(struct uart_port *port, unsigned int tty_stop) * Kick the Tx side. * The port lock is held and interrupts are disabled. */ -static void pmz_start_tx(struct uart_port *port, unsigned int tty_start) +static void pmz_start_tx(struct uart_port *port) { struct uart_pmac_port *uap = to_pmz(port); unsigned char status; @@ -872,8 +871,8 @@ static int __pmz_startup(struct uart_pmac_port *uap) uap->curregs[R13] = 0; uap->curregs[R14] = BRENAB; - /* Clear handshaking */ - uap->curregs[R15] = 0; + /* Clear handshaking, enable BREAK interrupts */ + uap->curregs[R15] = BRKIE; /* Master interrupt enable */ uap->curregs[R9] |= NV | MIE; @@ -920,7 +919,7 @@ static int pmz_startup(struct uart_port *port) if (uap->node == NULL) return -ENODEV; - down(&pmz_irq_sem); + mutex_lock(&pmz_irq_mutex); uap->flags |= PMACZILOG_FLAG_IS_OPEN; @@ -934,23 +933,22 @@ static int pmz_startup(struct uart_port *port) } pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON; - if (request_irq(uap->port.irq, pmz_interrupt, SA_SHIRQ, "PowerMac Zilog", uap)) { + if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED, "PowerMac Zilog", uap)) { dev_err(&uap->dev->ofdev.dev, "Unable to register zs interrupt handler.\n"); pmz_set_scc_power(uap, 0); - up(&pmz_irq_sem); + mutex_unlock(&pmz_irq_mutex); return -ENXIO; } - up(&pmz_irq_sem); + mutex_unlock(&pmz_irq_mutex); /* Right now, we deal with delay by blocking here, I'll be * smarter later on */ if (pwr_delay != 0) { pmz_debug("pmz: delaying %d ms\n", pwr_delay); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((pwr_delay * HZ)/1000); + msleep(pwr_delay); } /* IrDA reset is done now */ @@ -980,7 +978,7 @@ static void pmz_shutdown(struct uart_port *port) if (uap->node == NULL) return; - down(&pmz_irq_sem); + mutex_lock(&pmz_irq_mutex); /* Release interrupt handler */ free_irq(uap->port.irq, uap); @@ -1001,7 +999,7 @@ static void pmz_shutdown(struct uart_port *port) if (ZS_IS_CONS(uap) || ZS_IS_ASLEEP(uap)) { spin_unlock_irqrestore(&port->lock, flags); - up(&pmz_irq_sem); + mutex_unlock(&pmz_irq_mutex); return; } @@ -1018,7 +1016,7 @@ static void pmz_shutdown(struct uart_port *port) spin_unlock_irqrestore(&port->lock, flags); - up(&pmz_irq_sem); + mutex_unlock(&pmz_irq_mutex); pmz_debug("pmz: shutdown() done.\n"); } @@ -1264,8 +1262,8 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) } -static void __pmz_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pmac_port *uap = to_pmz(port); unsigned long baud; @@ -1275,7 +1273,7 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios, if (ZS_IS_ASLEEP(uap)) return; - memcpy(&uap->termios_cache, termios, sizeof(struct termios)); + memcpy(&uap->termios_cache, termios, sizeof(struct ktermios)); /* XXX Check which revs of machines actually allow 1 and 4Mb speeds * on the IR dongle. Note that the IRTTY driver currently doesn't know @@ -1309,12 +1307,14 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios, /* Load registers to the chip */ pmz_maybe_update_regs(uap); } + uart_update_timeout(port, termios->c_cflag, baud); + pmz_debug("pmz: set_termios() done.\n"); } /* The port lock is not held. */ -static void pmz_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void pmz_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pmac_port *uap = to_pmz(port); unsigned long flags; @@ -1399,45 +1399,51 @@ static struct uart_ops pmz_pops = { static int __init pmz_init_port(struct uart_pmac_port *uap) { struct device_node *np = uap->node; - char *conn; - struct slot_names_prop { + const char *conn; + const struct slot_names_prop { int count; char name[1]; } *slots; int len; + struct resource r_ports, r_rxdma, r_txdma; /* * Request & map chip registers */ - uap->port.mapbase = np->addrs[0].address; + if (of_address_to_resource(np, 0, &r_ports)) + return -ENODEV; + uap->port.mapbase = r_ports.start; uap->port.membase = ioremap(uap->port.mapbase, 0x1000); - uap->control_reg = (volatile u8 *)uap->port.membase; + uap->control_reg = uap->port.membase; uap->data_reg = uap->control_reg + 0x10; /* * Request & map DBDMA registers */ #ifdef HAS_DBDMA - if (np->n_addrs >= 3 && np->n_intrs >= 3) + if (of_address_to_resource(np, 1, &r_txdma) == 0 && + of_address_to_resource(np, 2, &r_rxdma) == 0) uap->flags |= PMACZILOG_FLAG_HAS_DMA; +#else + memset(&r_txdma, 0, sizeof(struct resource)); + memset(&r_rxdma, 0, sizeof(struct resource)); #endif if (ZS_HAS_DMA(uap)) { - uap->tx_dma_regs = (volatile struct dbdma_regs *) - ioremap(np->addrs[np->n_addrs - 2].address, 0x1000); + uap->tx_dma_regs = ioremap(r_txdma.start, 0x100); if (uap->tx_dma_regs == NULL) { uap->flags &= ~PMACZILOG_FLAG_HAS_DMA; goto no_dma; } - uap->rx_dma_regs = (volatile struct dbdma_regs *) - ioremap(np->addrs[np->n_addrs - 1].address, 0x1000); + uap->rx_dma_regs = ioremap(r_rxdma.start, 0x100); if (uap->rx_dma_regs == NULL) { - iounmap((void *)uap->tx_dma_regs); + iounmap(uap->tx_dma_regs); + uap->tx_dma_regs = NULL; uap->flags &= ~PMACZILOG_FLAG_HAS_DMA; goto no_dma; } - uap->tx_dma_irq = np->intrs[1].line; - uap->rx_dma_irq = np->intrs[2].line; + uap->tx_dma_irq = irq_of_parse_and_map(np, 1); + uap->rx_dma_irq = irq_of_parse_and_map(np, 2); } no_dma: @@ -1451,7 +1457,7 @@ no_dma: uap->flags |= PMACZILOG_FLAG_IS_IRDA; uap->port_type = PMAC_SCC_ASYNC; /* 1999 Powerbook G3 has slot-names property instead */ - slots = (struct slot_names_prop *)get_property(np, "slot-names", &len); + slots = get_property(np, "slot-names", &len); if (slots && slots->count > 0) { if (strcmp(slots->name, "IrDA") == 0) uap->flags |= PMACZILOG_FLAG_IS_IRDA; @@ -1463,7 +1469,8 @@ no_dma: if (ZS_IS_INTMODEM(uap)) { struct device_node* i2c_modem = find_devices("i2c-modem"); if (i2c_modem) { - char* mid = get_property(i2c_modem, "modem-id", NULL); + const char* mid = + get_property(i2c_modem, "modem-id", NULL); if (mid) switch(*mid) { case 0x04 : case 0x05 : @@ -1483,8 +1490,8 @@ no_dma: /* * Init remaining bits of "port" structure */ - uap->port.iotype = SERIAL_IO_MEM; - uap->port.irq = np->intrs[0].line; + uap->port.iotype = UPIO_MEM; + uap->port.irq = irq_of_parse_and_map(np, 0); uap->port.uartclk = ZS_CLOCK; uap->port.fifosize = 1; uap->port.ops = &pmz_pops; @@ -1507,16 +1514,19 @@ static void pmz_dispose_port(struct uart_pmac_port *uap) { struct device_node *np; - iounmap((void *)uap->control_reg); np = uap->node; + iounmap(uap->rx_dma_regs); + iounmap(uap->tx_dma_regs); + iounmap(uap->control_reg); uap->node = NULL; of_node_put(np); + memset(uap, 0, sizeof(struct uart_pmac_port)); } /* * Called upon match with an escc node in the devive-tree. */ -static int pmz_attach(struct macio_dev *mdev, const struct of_match *match) +static int pmz_attach(struct macio_dev *mdev, const struct of_device_id *match) { int i; @@ -1561,7 +1571,7 @@ static int pmz_detach(struct macio_dev *mdev) } -static int pmz_suspend(struct macio_dev *mdev, u32 pm_state) +static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state) { struct uart_pmac_port *uap = dev_get_drvdata(&mdev->ofdev.dev); struct uart_state *state; @@ -1572,15 +1582,15 @@ static int pmz_suspend(struct macio_dev *mdev, u32 pm_state) return 0; } - if (pm_state == mdev->ofdev.dev.power_state || pm_state < 2) + if (pm_state.event == mdev->ofdev.dev.power.power_state.event) return 0; pmz_debug("suspend, switching to state %d\n", pm_state); state = pmz_uart_reg.state + uap->port.line; - down(&pmz_irq_sem); - down(&state->sem); + mutex_lock(&pmz_irq_mutex); + mutex_lock(&state->mutex); spin_lock_irqsave(&uap->port.lock, flags); @@ -1611,12 +1621,12 @@ static int pmz_suspend(struct macio_dev *mdev, u32 pm_state) /* Shut the chip down */ pmz_set_scc_power(uap, 0); - up(&state->sem); - up(&pmz_irq_sem); + mutex_unlock(&state->mutex); + mutex_unlock(&pmz_irq_mutex); pmz_debug("suspend, switching complete\n"); - mdev->ofdev.dev.power_state = pm_state; + mdev->ofdev.dev.power.power_state = pm_state; return 0; } @@ -1632,15 +1642,15 @@ static int pmz_resume(struct macio_dev *mdev) if (uap == NULL) return 0; - if (mdev->ofdev.dev.power_state == 0) + if (mdev->ofdev.dev.power.power_state.event == PM_EVENT_ON) return 0; pmz_debug("resume, switching to state 0\n"); state = pmz_uart_reg.state + uap->port.line; - down(&pmz_irq_sem); - down(&state->sem); + mutex_lock(&pmz_irq_mutex); + mutex_lock(&state->mutex); spin_lock_irqsave(&uap->port.lock, flags); if (!ZS_IS_OPEN(uap) && !ZS_IS_CONS(uap)) { @@ -1672,21 +1682,20 @@ static int pmz_resume(struct macio_dev *mdev) } bail: - up(&state->sem); - up(&pmz_irq_sem); + mutex_unlock(&state->mutex); + mutex_unlock(&pmz_irq_mutex); /* Right now, we deal with delay by blocking here, I'll be * smarter later on */ if (pwr_delay != 0) { pmz_debug("pmz: delaying %d ms\n", pwr_delay); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((pwr_delay * HZ)/1000); + msleep(pwr_delay); } pmz_debug("resume, switching complete\n"); - mdev->ofdev.dev.power_state = 0; + mdev->ofdev.dev.power.power_state.event = PM_EVENT_ON; return 0; } @@ -1797,7 +1806,7 @@ static int __init pmz_register(void) * Register this driver with the serial core */ rc = uart_register_driver(&pmz_uart_reg); - if (rc != 0) + if (rc) return rc; /* @@ -1807,26 +1816,32 @@ static int __init pmz_register(void) struct uart_pmac_port *uport = &pmz_ports[i]; /* NULL node may happen on wallstreet */ if (uport->node != NULL) - uart_add_one_port(&pmz_uart_reg, &uport->port); + rc = uart_add_one_port(&pmz_uart_reg, &uport->port); + if (rc) + goto err_out; } return 0; +err_out: + while (i-- > 0) { + struct uart_pmac_port *uport = &pmz_ports[i]; + uart_remove_one_port(&pmz_uart_reg, &uport->port); + } + uart_unregister_driver(&pmz_uart_reg); + return rc; } -static struct of_match pmz_match[] = +static struct of_device_id pmz_match[] = { { .name = "ch-a", - .type = OF_ANY_MATCH, - .compatible = OF_ANY_MATCH }, { .name = "ch-b", - .type = OF_ANY_MATCH, - .compatible = OF_ANY_MATCH }, {}, }; +MODULE_DEVICE_TABLE (of, pmz_match); static struct macio_driver pmz_driver = { @@ -1840,6 +1855,7 @@ static struct macio_driver pmz_driver = static int __init init_pmz(void) { + int rc, i; printk(KERN_INFO "%s\n", version); /* @@ -1861,7 +1877,16 @@ static int __init init_pmz(void) /* * Now we register with the serial layer */ - pmz_register(); + rc = pmz_register(); + if (rc) { + printk(KERN_ERR + "pmac_zilog: Error registering serial device, disabling pmac_zilog.\n" + "pmac_zilog: Did another serial driver already claim the minors?\n"); + /* effectively "pmz_unprobe()" */ + for (i=0; i < pmz_ports_count; i++) + pmz_dispose_port(&pmz_ports[i]); + return rc; + } /* * Then we register the macio driver itself @@ -1889,6 +1914,16 @@ static void __exit exit_pmz(void) #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE +static void pmz_console_putchar(struct uart_port *port, int ch) +{ + struct uart_pmac_port *uap = (struct uart_pmac_port *)port; + + /* Wait for the transmit buffer to empty. */ + while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) + udelay(5); + write_zsdata(uap, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -1897,25 +1932,16 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c { struct uart_pmac_port *uap = &pmz_ports[con->index]; unsigned long flags; - int i; + if (ZS_IS_ASLEEP(uap)) + return; spin_lock_irqsave(&uap->port.lock, flags); /* Turn of interrupts and enable the transmitter. */ write_zsreg(uap, R1, uap->curregs[1] & ~TxINT_ENAB); write_zsreg(uap, R5, uap->curregs[5] | TxENABLE | RTS | DTR); - for (i = 0; i < count; i++) { - /* Wait for the transmit buffer to empty. */ - while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) - udelay(5); - write_zsdata(uap, s[i]); - if (s[i] == 10) { - while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) - udelay(5); - write_zsdata(uap, R13); - } - } + uart_console_write(&uap->port, s, count, pmz_console_putchar); /* Restore the values in the registers. */ write_zsreg(uap, R1, uap->curregs[1]); @@ -1985,8 +2011,6 @@ static int __init pmz_console_init(void) /* Probe ports */ pmz_probe(); -#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE -#endif /* TODO: Autoprobe console based on OF */ /* pmz_console.index = i; */ register_console(&pmz_console);