#include "pmac_zilog.h"
+#if defined(CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_PPC64)
+#define HAS_SCCDBG
+extern int sccdbg;
+#endif
/* Not yet implemented */
#undef HAS_DBDMA
*/
static void pmz_maybe_update_regs(struct uart_pmac_port *up)
{
-#if 1
if (!ZS_REGS_HELD(up)) {
if (ZS_TX_ACTIVE(up)) {
up->flags |= PMACZILOG_FLAG_REGS_HELD;
pmz_load_zsregs(up, up->curregs);
}
}
-#else
- pr_debug("pmz: maybe_update_regs: updating\n");
- pmz_load_zsregs(up, up->curregs);
-#endif
}
static void pmz_receive_chars(struct uart_pmac_port *up, struct pt_regs *regs)
zssync(up);
}
- ch = read_zsreg(up, R0);
-
- /* This funny hack depends upon BRK_ABRT not interfering
- * with the other bits we care about in R1.
- */
- if (ch & BRK_ABRT)
- r1 |= BRK_ABRT;
-
ch = read_zsdata(up);
ch &= up->parity_mask;
+ if (ch == 0 && up->prev_status & BRK_ABRT) {
+ r1 |= BRK_ABRT;
+ printk("rx break\n");
+ }
/* A real serial line, record the character and status. */
*tty->flip.char_buf_ptr = ch;
*tty->flip.flag_buf_ptr = TTY_NORMAL;
up->port.icount.rx++;
- if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
+ if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) {
if (r1 & BRK_ABRT) {
r1 &= ~(PAR_ERR | CRC_ERR);
up->port.icount.brk++;
write_zsreg(up, R0, RES_EXT_INT);
zssync(up);
+#ifdef HAS_SCCDBG
+ if (sccdbg && (status & BRK_ABRT) && !(up->prev_status & BRK_ABRT)) {
+#ifdef CONFIG_XMON
+ extern void xmon(struct pt_regs *);
+ xmon(regs);
+#endif
+ }
+#endif /* HAS_SCCDBG */
+
if (ZS_WANTS_MODEM_STATUS(up)) {
if (status & SYNC_HUNT)
up->port.icount.dsr++;
write_zsreg(up_a, R0, RES_H_IUS);
zssync(up_a);
pr_debug("pmz: irq channel A: %x\n", r3);
- if (r3 & CHARxIP)
- pmz_receive_chars(up_a, regs);
if (r3 & CHAEXT)
pmz_status_handle(up_a, regs);
+ if (r3 & CHARxIP)
+ pmz_receive_chars(up_a, regs);
if (r3 & CHATxIP)
pmz_transmit_chars(up_a);
rc = IRQ_HANDLED;
write_zsreg(up_b, R0, RES_H_IUS);
zssync(up_b);
pr_debug("pmz: irq channel B: %x\n", r3);
- if (r3 & CHBRxIP)
- pmz_receive_chars(up_b, regs);
if (r3 & CHBEXT)
pmz_status_handle(up_b, regs);
+ if (r3 & CHBRxIP)
+ pmz_receive_chars(up_b, regs);
if (r3 & CHBTxIP)
pmz_transmit_chars(up_b);
rc = IRQ_HANDLED;
/*
* Enable modem status change interrupts
- * The port lock is not held.
+ * The port lock is held.
*/
static void pmz_enable_ms(struct uart_port *port)
{
struct uart_pmac_port *up = to_pmz(port);
unsigned char new_reg;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE);
if (new_reg != up->curregs[R15]) {
/* NOTE: Not subject to 'transmitter active' rule. */
write_zsreg(up, R15, up->curregs[R15]);
}
-
- spin_unlock_irqrestore(&port->lock, flags);
}
/*
up->curregs[R9] |= NV | MIE;
up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
- // pmz_maybe_update_regs(up);
+ pmz_maybe_update_regs(up);
return pwr_delay;
}
pmz_convert_to_zs(up, termios->c_cflag, termios->c_iflag, baud);
- if (UART_ENABLE_MS(&up->port, termios->c_cflag))
+ if (UART_ENABLE_MS(&up->port, termios->c_cflag)) {
+ up->curregs[R15] |= DCDIE | SYNCIE | CTSIE;
up->flags |= PMACZILOG_FLAG_MODEM_STATUS;
- else
+ } else {
+ up->curregs[R15] &= ~(DCDIE | SYNCIE | CTSIE);
up->flags &= ~PMACZILOG_FLAG_MODEM_STATUS;
+ }
/* set the irda codec to the right rate */
if (ZS_IS_IRDA(up))
* Unlike sunzilog, we don't need to pre-init the spinlock as we don't
* register our console before uart_add_one_port() is called
*/
-static int __init pmz_setup_port(struct uart_pmac_port *up)
+static int __init pmz_init_port(struct uart_pmac_port *up)
{
struct device_node *np = up->node;
char *conn;
{
struct device_node *np;
- if (up->flags & PMACZILOG_FLAG_RSRC_REQUESTED) {
- release_OF_resource(up->node, 0);
- if (ZS_HAS_DMA(up)) {
- release_OF_resource(up->node, up->node->n_addrs - 2);
- release_OF_resource(up->node, up->node->n_addrs - 1);
- }
- }
iounmap((void *)up->control_reg);
np = up->node;
up->node = NULL;
/*
* Setup the ports for real
*/
- rc = pmz_setup_port(&pmz_ports[count]);
+ rc = pmz_init_port(&pmz_ports[count]);
if (rc == 0)
- rc = pmz_setup_port(&pmz_ports[count+1]);
+ rc = pmz_init_port(&pmz_ports[count+1]);
if (rc != 0) {
of_node_put(node_a);
of_node_put(node_b);
/* Probe ports */
pmz_probe();
+#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
+#endif
/* TODO: Autoprobe console based on OF */
/* pmz_console.index = i; */
register_console(&pmz_console);