2006-01-10 13:21:23

by Miika Keskinen

[permalink] [raw]
Subject: serial port, custom divisor

Hi

I read from the Documentation/serial/driver that the custom divisor is
only applied to ports that have baud 38400. I'm asking if there is some
reason why custom divisor should not be used for other speeds too? I do
have a MIPS-SoC that does have 16550A-type uart but it needs custom
divisor, no matter what the speed is. The custom divisor is calculated
as follows:

baud = speed of port
system_frequency is in MHz

cdiv = (system_frequency * 5000) / baud;
if ((cdiv % 16)>7) cdiv += 8;
cdiv /= 16;

What I'm doing is to use early_serial_setup with flags containing
ASYNC_SPD_CUST and cdiv as .custom_divisor. However the serial_core
doesn't apply that divisor unless the speed is 38400 (and for example I
mostly need to run it in 9600). I'm now asking if I've misunderstood
something or does the removal of baud==38400 from serial_core cause
problems with other architectures?

btw. I'm not subscribed to the list so please cc me if replying.

yours,
Miika

--
All bugs added by me :)


2006-01-10 15:16:08

by Stuart MacDonald

[permalink] [raw]
Subject: RE: serial port, custom divisor

From: On Behalf Of Miika Keskinen
> I read from the Documentation/serial/driver that the custom divisor is
> only applied to ports that have baud 38400. I'm asking if
> there is some
> reason why custom divisor should not be used for other speeds
> too? I do

Because it's a hack. The normal method is to specify a baud rate via
the lookup table, say B9600. The table is however a fixed size and has
set entries. At some point it became necessary to be able to specify a
divisor instead, to generate baud rates that are not part of the
normal lookup table. So, to specify that the driver should use a
custom divisor supplied by user space, there's a hack. Set the
appropriate flag, set the lookup table value to B38400 and set the
custom divisor to what you need.

The driver will see that the flag is set, see that the baud rate is
B38400, and use the custom divisor instead of calculating its own. If
you want 9600, you have two options. If it works for you, you can set
B9600. The driver will calculate its own divisor and use that, without
losing the custom information you've supplied. I suppose this is to
make it easy to switch back and forth. Or, you can just alter the
custom divisor to be what you need it to be to generate 9600. The apps
I've written that use the custom divisor, I do that. Switch the flag
on, switch to B38400, and control all my own baud rates via setting
the appropriate custom divisor.

> What I'm doing is to use early_serial_setup with flags containing
> ASYNC_SPD_CUST and cdiv as .custom_divisor. However the serial_core
> doesn't apply that divisor unless the speed is 38400 (and for

Correct. B38400 is simply being used as a flag here, it's not actually
setting 38400.

> example I
> mostly need to run it in 9600). I'm now asking if I've misunderstood

So, set the flag, B38400, and the custom divisor that generates 9600
for you.

> something or does the removal of baud==38400 from serial_core cause
> problems with other architectures?

If you mean, would taking out that code from the driver be a good
idea? Probably not. This is a long standing well understood hack.
Attempts to change it will probably be resisted.

..Stu