CPM2 SCC/SMC break handling broken
Laurent Pinchart
laurent.pinchart at tbox.biz
Tue Oct 31 02:23:51 EST 2006
Hi Ricardo,
> > > > 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).
> > >
> > > [snip]
> > >
> > > > 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.
> > >
> > > [snip]
> > >
> > > > Could anyone think of a proper solution which would not disturb the
> > > > other drivers too much ?
> > >
> > > Well, one could always set the BRKCR parameter to the maximum number of
> > > break characters permitted by it's size, since the break condition will
> > > anyway end as soon as the RESTART TX command is issued as a consequence
> > > of the tty->driver->break_ctl(tty, 0) call. But I did not test this.
> >
> > That's a very good idea, but the documentation is a bit misleading here.
> > I tested the CPM2 behaviour, and found out that the break will last BRKCR
> > characters, even if a RESTART TX command is sent sooner.
> >
> > The user manual states
> >
> > "The SMC sends a programmable number of break characters according to
> > BRKCR and reverts to idle or sends data if a RESTART TRANSMIT is issued
> > before completion."
> >
> > I suppose they meant that, if a RESTART TX command is issued before
> > completion of the break sequence, the SMC will send data at the end of
> > the break sequence. This is at least the behaviour I noticed after trying
> > your idea.
>
> Too bad.... :( One more good idea to the junk bin.
>
> Hmm, just a wild shot you can try, while you're at that: what about setting
> BRKCR to zero and issuing another STOP TRANSMIT, just before the RESTART
> TRANSMIT?
Wow, congratulations. I wouldn't have thought about that.
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;
volatile u16 *brkcr = IS_SMC(pinfo) ? &pinfo->smcup->smc_brkcr
: &pinfo->sccup->scc_brkcr;
pr_debug("CPM uart[%d]:break ctrl, break_state: %d\n", port->line,
break_state);
if (break_state)
{
*brkcr = 32767;
cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
}
else
{
*brkcr = 0;
cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
cpm_line_cr_cmd(line, CPM_CR_RESTART_TX);
}
}
This is a bit hackish though, but it works and doesn't require any API
modification.
Vitaly, could you give me your opinion ?
> Another reasonable shot would be to disable and reenable the transmitter in
> an attempt to stop the break sequence; though I don't know what happens to
> the SMC state machine in this case.
>
> Too wild guesses? Well, maybe someone at Freescale can have a better idea.
> :)
I could try contacting them, but they will probably tell me that I should just
set BRKCR to the number of characters I want to send. I doubt they will care
that the kernel break handling code doesn't allow us to do that easily.
Thanks for your help.
Best regards,
Laurent Pinchart
More information about the Linuxppc-embedded
mailing list