Commit c720ddc1 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Linus Torvalds

[PATCH] Fix pmac_zilog as console

pmac_zilog wasn't properly updating port->timeout, thus broke with serial
console.  I'm not sure if that timeout thing was added recently or not,
since the driver used to work fine.  This patch fixes that, and adds some
proper SYSRQ support.  By default, BREAK is used for sysrq, though some
Apple zilog's seem to have non-working BREAK detection logic, thus the
driver has a #define option you can manually enable when debugging to do
SYSRQ with ctrl-O instead (like pSeries virtual consoles).
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent bf4a5a18
......@@ -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 <laforge@gnumonks.org>
* - 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,6 +40,7 @@
#undef DEBUG
#undef DEBUG_HARD
#undef USE_CTRL_O_SYSRQ
#include <linux/config.h>
#include <linux/module.h>
......@@ -54,6 +59,7 @@
#include <linux/adb.h>
#include <linux/pmu.h>
#include <linux/bitops.h>
#include <linux/sysrq.h>
#include <asm/sections.h>
#include <asm/io.h>
#include <asm/irq.h>
......@@ -64,6 +70,10 @@
#include <asm/macio.h>
#include <asm/semaphore.h>
#if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/serial.h>
#include <linux/serial_core.h>
......@@ -259,8 +269,27 @@ 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;
}
#ifdef CONFIG_MAGIC_SYSRQ
#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, regs);
spin_lock(&uap->port.lock);
if (swallow)
goto next_char;
}
#endif /* CONFIG_MAGIC_SYSRQ */
/* A real serial line, record the character and status. */
if (drop)
......@@ -276,11 +305,9 @@ 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++;
else if (r1 & CRC_ERR)
......@@ -295,10 +322,6 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
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;
}
if (uap->port.ignore_status_mask == 0xff ||
(r1 & uap->port.ignore_status_mask) == 0) {
......@@ -364,6 +387,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;
}
......@@ -872,8 +898,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;
......@@ -1308,6 +1334,8 @@ 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");
}
......
......@@ -47,6 +47,7 @@ struct uart_pmac_port {
#define PMACZILOG_FLAG_IS_OPEN 0x00002000
#define PMACZILOG_FLAG_IS_IRQ_ON 0x00004000
#define PMACZILOG_FLAG_IS_EXTCLK 0x00008000
#define PMACZILOG_FLAG_BREAK 0x00010000
unsigned char parity_mask;
unsigned char prev_status;
......
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