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