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

parent 0afc48b4
......@@ -68,6 +68,10 @@
#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
......@@ -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)
{
#if 1
if (!ZS_REGS_HELD(up)) {
if (ZS_TX_ACTIVE(up)) {
up->flags |= PMACZILOG_FLAG_REGS_HELD;
......@@ -179,10 +182,6 @@ static void pmz_maybe_update_regs(struct uart_pmac_port *up)
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)
......@@ -205,22 +204,18 @@ 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++;
......@@ -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);
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++;
......@@ -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);
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;
......@@ -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);
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;
......@@ -575,15 +579,12 @@ static void pmz_stop_rx(struct uart_port *port)
/*
* 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]) {
......@@ -592,8 +593,6 @@ static void pmz_enable_ms(struct uart_port *port)
/* NOTE: Not subject to 'transmitter active' rule. */
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)
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;
}
......@@ -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);
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))
......@@ -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
* 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;
......@@ -1225,13 +1227,6 @@ static void pmz_dispose_port(struct uart_pmac_port *up)
{
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;
......@@ -1335,9 +1330,9 @@ static int __init pmz_probe(void)
/*
* 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);
......@@ -1581,6 +1576,8 @@ 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);
......
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