ppc64: Fix break handling in pmac_zilog driver, fixes for 64 bits kernel

parent 0afc48b4
...@@ -68,6 +68,10 @@ ...@@ -68,6 +68,10 @@
#include "pmac_zilog.h" #include "pmac_zilog.h"
#if defined(CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_PPC64)
#define HAS_SCCDBG
extern int sccdbg;
#endif
/* Not yet implemented */ /* Not yet implemented */
#undef HAS_DBDMA #undef HAS_DBDMA
...@@ -170,7 +174,6 @@ static void pmz_load_zsregs(struct uart_pmac_port *up, u8 *regs) ...@@ -170,7 +174,6 @@ static void pmz_load_zsregs(struct uart_pmac_port *up, u8 *regs)
*/ */
static void pmz_maybe_update_regs(struct uart_pmac_port *up) static void pmz_maybe_update_regs(struct uart_pmac_port *up)
{ {
#if 1
if (!ZS_REGS_HELD(up)) { if (!ZS_REGS_HELD(up)) {
if (ZS_TX_ACTIVE(up)) { if (ZS_TX_ACTIVE(up)) {
up->flags |= PMACZILOG_FLAG_REGS_HELD; up->flags |= PMACZILOG_FLAG_REGS_HELD;
...@@ -179,10 +182,6 @@ static void pmz_maybe_update_regs(struct uart_pmac_port *up) ...@@ -179,10 +182,6 @@ static void pmz_maybe_update_regs(struct uart_pmac_port *up)
pmz_load_zsregs(up, up->curregs); 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) static void pmz_receive_chars(struct uart_pmac_port *up, struct pt_regs *regs)
...@@ -205,22 +204,18 @@ static void pmz_receive_chars(struct uart_pmac_port *up, struct pt_regs *regs) ...@@ -205,22 +204,18 @@ static void pmz_receive_chars(struct uart_pmac_port *up, struct pt_regs *regs)
zssync(up); 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 = read_zsdata(up);
ch &= up->parity_mask; 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. */ /* A real serial line, record the character and status. */
*tty->flip.char_buf_ptr = ch; *tty->flip.char_buf_ptr = ch;
*tty->flip.flag_buf_ptr = TTY_NORMAL; *tty->flip.flag_buf_ptr = TTY_NORMAL;
up->port.icount.rx++; 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) { if (r1 & BRK_ABRT) {
r1 &= ~(PAR_ERR | CRC_ERR); r1 &= ~(PAR_ERR | CRC_ERR);
up->port.icount.brk++; up->port.icount.brk++;
...@@ -274,6 +269,15 @@ static void pmz_status_handle(struct uart_pmac_port *up, struct pt_regs *regs) ...@@ -274,6 +269,15 @@ static void pmz_status_handle(struct uart_pmac_port *up, struct pt_regs *regs)
write_zsreg(up, R0, RES_EXT_INT); write_zsreg(up, R0, RES_EXT_INT);
zssync(up); 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 (ZS_WANTS_MODEM_STATUS(up)) {
if (status & SYNC_HUNT) if (status & SYNC_HUNT)
up->port.icount.dsr++; up->port.icount.dsr++;
...@@ -383,10 +387,10 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -383,10 +387,10 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id, struct pt_regs *regs)
write_zsreg(up_a, R0, RES_H_IUS); write_zsreg(up_a, R0, RES_H_IUS);
zssync(up_a); zssync(up_a);
pr_debug("pmz: irq channel A: %x\n", r3); pr_debug("pmz: irq channel A: %x\n", r3);
if (r3 & CHARxIP)
pmz_receive_chars(up_a, regs);
if (r3 & CHAEXT) if (r3 & CHAEXT)
pmz_status_handle(up_a, regs); pmz_status_handle(up_a, regs);
if (r3 & CHARxIP)
pmz_receive_chars(up_a, regs);
if (r3 & CHATxIP) if (r3 & CHATxIP)
pmz_transmit_chars(up_a); pmz_transmit_chars(up_a);
rc = IRQ_HANDLED; rc = IRQ_HANDLED;
...@@ -398,10 +402,10 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -398,10 +402,10 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id, struct pt_regs *regs)
write_zsreg(up_b, R0, RES_H_IUS); write_zsreg(up_b, R0, RES_H_IUS);
zssync(up_b); zssync(up_b);
pr_debug("pmz: irq channel B: %x\n", r3); pr_debug("pmz: irq channel B: %x\n", r3);
if (r3 & CHBRxIP)
pmz_receive_chars(up_b, regs);
if (r3 & CHBEXT) if (r3 & CHBEXT)
pmz_status_handle(up_b, regs); pmz_status_handle(up_b, regs);
if (r3 & CHBRxIP)
pmz_receive_chars(up_b, regs);
if (r3 & CHBTxIP) if (r3 & CHBTxIP)
pmz_transmit_chars(up_b); pmz_transmit_chars(up_b);
rc = IRQ_HANDLED; rc = IRQ_HANDLED;
...@@ -575,15 +579,12 @@ static void pmz_stop_rx(struct uart_port *port) ...@@ -575,15 +579,12 @@ static void pmz_stop_rx(struct uart_port *port)
/* /*
* Enable modem status change interrupts * 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) static void pmz_enable_ms(struct uart_port *port)
{ {
struct uart_pmac_port *up = to_pmz(port); struct uart_pmac_port *up = to_pmz(port);
unsigned char new_reg; unsigned char new_reg;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE); new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE);
if (new_reg != up->curregs[R15]) { if (new_reg != up->curregs[R15]) {
...@@ -592,8 +593,6 @@ static void pmz_enable_ms(struct uart_port *port) ...@@ -592,8 +593,6 @@ static void pmz_enable_ms(struct uart_port *port)
/* NOTE: Not subject to 'transmitter active' rule. */ /* NOTE: Not subject to 'transmitter active' rule. */
write_zsreg(up, R15, up->curregs[R15]); write_zsreg(up, R15, up->curregs[R15]);
} }
spin_unlock_irqrestore(&port->lock, flags);
} }
/* /*
...@@ -765,7 +764,7 @@ static int __pmz_startup(struct uart_pmac_port *up) ...@@ -765,7 +764,7 @@ static int __pmz_startup(struct uart_pmac_port *up)
up->curregs[R9] |= NV | MIE; up->curregs[R9] |= NV | MIE;
up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
// pmz_maybe_update_regs(up); pmz_maybe_update_regs(up);
return pwr_delay; return pwr_delay;
} }
...@@ -1051,10 +1050,13 @@ pmz_set_termios(struct uart_port *port, struct termios *termios, ...@@ -1051,10 +1050,13 @@ pmz_set_termios(struct uart_port *port, struct termios *termios,
pmz_convert_to_zs(up, termios->c_cflag, termios->c_iflag, baud); 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; up->flags |= PMACZILOG_FLAG_MODEM_STATUS;
else } else {
up->curregs[R15] &= ~(DCDIE | SYNCIE | CTSIE);
up->flags &= ~PMACZILOG_FLAG_MODEM_STATUS; up->flags &= ~PMACZILOG_FLAG_MODEM_STATUS;
}
/* set the irda codec to the right rate */ /* set the irda codec to the right rate */
if (ZS_IS_IRDA(up)) if (ZS_IS_IRDA(up))
...@@ -1120,7 +1122,7 @@ static struct uart_ops pmz_pops = { ...@@ -1120,7 +1122,7 @@ static struct uart_ops pmz_pops = {
* Unlike sunzilog, we don't need to pre-init the spinlock as we don't * 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 * 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; struct device_node *np = up->node;
char *conn; char *conn;
...@@ -1225,13 +1227,6 @@ static void pmz_dispose_port(struct uart_pmac_port *up) ...@@ -1225,13 +1227,6 @@ static void pmz_dispose_port(struct uart_pmac_port *up)
{ {
struct device_node *np; 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); iounmap((void *)up->control_reg);
np = up->node; np = up->node;
up->node = NULL; up->node = NULL;
...@@ -1335,9 +1330,9 @@ static int __init pmz_probe(void) ...@@ -1335,9 +1330,9 @@ static int __init pmz_probe(void)
/* /*
* Setup the ports for real * Setup the ports for real
*/ */
rc = pmz_setup_port(&pmz_ports[count]); rc = pmz_init_port(&pmz_ports[count]);
if (rc == 0) if (rc == 0)
rc = pmz_setup_port(&pmz_ports[count+1]); rc = pmz_init_port(&pmz_ports[count+1]);
if (rc != 0) { if (rc != 0) {
of_node_put(node_a); of_node_put(node_a);
of_node_put(node_b); of_node_put(node_b);
...@@ -1581,6 +1576,8 @@ static int __init pmz_console_init(void) ...@@ -1581,6 +1576,8 @@ static int __init pmz_console_init(void)
/* Probe ports */ /* Probe ports */
pmz_probe(); pmz_probe();
#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
#endif
/* TODO: Autoprobe console based on OF */ /* TODO: Autoprobe console based on OF */
/* pmz_console.index = i; */ /* pmz_console.index = i; */
register_console(&pmz_console); register_console(&pmz_console);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment