提交 0c0c47bc 编写于 作者: V Vlad Lungu 提交者: Greg Kroah-Hartman

tty: xuartps: Implement BREAK detection, add SYSRQ support

The Cadence UART does not do break detection, even if the
datasheet says it does. This patch adds break detection in
software (tested in 8N1 mode only) and enables SYSRQ,
allowing for Break-g to enter KDB and all the other goodies.
Signed-off-by: NVlad Lungu <vlad.lungu@windriver.com>
Signed-off-by: NSoren Brinkmann <soren.brinkmann@xilinx.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 c03cae17
......@@ -11,13 +11,17 @@
*
*/
#if defined(CONFIG_SERIAL_XILINX_PS_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/platform_device.h>
#include <linux/serial.h>
#include <linux/console.h>
#include <linux/serial_core.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/console.h>
#include <linux/clk.h>
#include <linux/irq.h>
#include <linux/io.h>
......@@ -128,6 +132,9 @@
#define XUARTPS_IXR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt. */
#define XUARTPS_IXR_MASK 0x00001FFF /* Valid bit mask */
/* Goes in read_status_mask for break detection as the HW doesn't do it*/
#define XUARTPS_IXR_BRK 0x80000000
/** Channel Status Register
*
* The channel status register (CSR) is provided to enable the control logic
......@@ -171,6 +178,23 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
*/
isrstatus = xuartps_readl(XUARTPS_ISR_OFFSET);
/*
* There is no hardware break detection, so we interpret framing
* error with all-zeros data as a break sequence. Most of the time,
* there's another non-zero byte at the end of the sequence.
*/
if (isrstatus & XUARTPS_IXR_FRAMING) {
while (!(xuartps_readl(XUARTPS_SR_OFFSET) &
XUARTPS_SR_RXEMPTY)) {
if (!xuartps_readl(XUARTPS_FIFO_OFFSET)) {
port->read_status_mask |= XUARTPS_IXR_BRK;
isrstatus &= ~XUARTPS_IXR_FRAMING;
}
}
xuartps_writel(XUARTPS_IXR_FRAMING, XUARTPS_ISR_OFFSET);
}
/* drop byte with parity error if IGNPAR specified */
if (isrstatus & port->ignore_status_mask & XUARTPS_IXR_PARITY)
isrstatus &= ~(XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT);
......@@ -184,6 +208,30 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
while ((xuartps_readl(XUARTPS_SR_OFFSET) &
XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) {
data = xuartps_readl(XUARTPS_FIFO_OFFSET);
/* Non-NULL byte after BREAK is garbage (99%) */
if (data && (port->read_status_mask &
XUARTPS_IXR_BRK)) {
port->read_status_mask &= ~XUARTPS_IXR_BRK;
port->icount.brk++;
if (uart_handle_break(port))
continue;
}
/*
* uart_handle_sysrq_char() doesn't work if
* spinlocked, for some reason
*/
if (port->sysrq) {
spin_unlock(&port->lock);
if (uart_handle_sysrq_char(port,
(unsigned char)data)) {
spin_lock(&port->lock);
continue;
}
spin_lock(&port->lock);
}
port->icount.rx++;
if (isrstatus & XUARTPS_IXR_PARITY) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册