CPM2 SCC/SMC break handling broken
Laurent Pinchart
laurent.pinchart at tbox.biz
Thu Oct 26 18:02:44 EST 2006
Hi everybody,
I need to generate a break on a CPM2 SMC serial port (same issue with SCC
serial ports).
The tcsendbreak() man page states that the function should generate a break
between 250ms and 500ms, but testing showed that the break is one character
long (10 bits in 8N1 mode).
Breaks are handled by the tty layer (drivers/char/tty_io.c), the generic
serial layer (drivers/serial/serial_core.c) and the CPM driver
(drivers/char/cpm_uart/cpm_uart_core.c).
As the tty driver (drivers/serial/serial_core.c) defines a break handler
(break_ctl), the tty layer calls send_break to send the break:
static int send_break(struct tty_struct *tty, unsigned int duration)
{
tty->driver->break_ctl(tty, -1);
if (!signal_pending(current)) {
msleep_interruptible(duration);
}
tty->driver->break_ctl(tty, 0);
if (signal_pending(current))
return -EINTR;
return 0;
}
tty->driver->break_ctl just forwards the call to the CPM driver, which does
static void cpm_uart_break_ctl(struct uart_port *port, int break_state)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
int line = pinfo - cpm_uart_ports;
pr_debug("CPM uart[%d]:break ctrl, break_state: %d\n", port->line,
break_state);
if (break_state)
cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
else
cpm_line_cr_cmd(line, CPM_CR_RESTART_TX);
}
CPM_CR_STOP_TX is documented to generate a break of BRKCR characters. The
BRKCR register is initialized to 1, so only 1 break character is sent, which
won't last between 250ms and 500ms.
cpm_uart_break_ctl() is not told how long the break must last, so it can't
modify BRKCR before sending CPM_CR_STOP_TX. A solution would be to let the
driver handle the break itself instead of having tty_io.c calling
send_break(). To do that, the driver (serial_core.c) must not declare a break
handler. This would obviously break all other serial drivers. Another
solution would be to have a new platform handler for CPM serial ports which
will turn the I/O ports to low-level outputs. This sounds more like a hack to
me though.
Could anyone think of a proper solution which would not disturb the other
drivers too much ?
Laurent Pinchart
More information about the Linuxppc-embedded
mailing list