Bug 210351

Summary: Wrong setting baudrate for FTDI chip FT230X
Product: Drivers Reporter: Vladimir (svv75)
Component: USBAssignee: Default virtual assignee for Drivers/USB (drivers_usb)
Status: NEW ---    
Severity: high    
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: all Subsystem:
Regression: No Bisected commit-id:

Description Vladimir 2020-11-25 05:14:18 UTC
Hello!

I have three chips FT232BL, FT232R and FT230X. I am using them as a VCP on Linux (Ubuntu 18.04). According to Application Note AN_120 from FTDI, the baud rate generators of all these chips have 8 sub-integer prescalers. Divisor = 3000000 / baudrate = n + 0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875. Where n is an integer between 2 and16384.
So, I measured real baud rates, for n = 2 in combination with all possible sub-integer prescalers.
And it turned out that all sub-integer prescalers worked for FT232BL, FT232R chips.

And for the FT230X, only a few prescalers work correctly. The following shows exactly how prescalers behave:
0          - correct
0.125  - correct
0.25     - correct
0.375   - WRONG! (works like 0.125)
0.5        - correct
0.625    - WRONG! (works like 0.5)
0.75      - WRONG! (works like 0.25)
0.875    - WRONG! (works like 0.125)

The same for the other n.

I think it is a driver problem, it initializes the sub-integer prescaler incorrectly. Since under Windows FT230X works fine with all sub-integer prescalers.
Comment 1 Johan Hovold 2021-01-08 10:37:20 UTC
On Wed, Nov 25, 2020 at 05:14:18AM +0000, bugzilla-daemon@bugzilla.kernel.org wrote:
> https://bugzilla.kernel.org/show_bug.cgi?id=210351
> 
>             Bug ID: 210351
>            Summary: Wrong setting baudrate for FTDI chip FT230X
>            Product: Drivers
>            Version: 2.5
>     Kernel Version: all
>           Hardware: All
>                 OS: Linux
>               Tree: Mainline
>             Status: NEW
>           Severity: normal
>           Priority: P1
>          Component: USB
>           Assignee: drivers_usb@kernel-bugs.kernel.org
>           Reporter: svv75@mail.ru
>         Regression: No
> 
> Hello!
> 
> I have three chips FT232BL, FT232R and FT230X. I am using them as a VCP on
> Linux (Ubuntu 18.04). According to Application Note AN_120 from FTDI, the
> baud
> rate generators of all these chips have 8 sub-integer prescalers. Divisor =
> 3000000 / baudrate = n + 0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875.
> Where
> n is an integer between 2 and16384.
> So, I measured real baud rates, for n = 2 in combination with all possible
> sub-integer prescalers.
> And it turned out that all sub-integer prescalers worked for FT232BL, FT232R
> chips.
> 
> And for the FT230X, only a few prescalers work correctly. The following shows
> exactly how prescalers behave:
> 0          - correct
> 0.125  - correct
> 0.25     - correct
> 0.375   - WRONG! (works like 0.125)
> 0.5        - correct
> 0.625    - WRONG! (works like 0.5)
> 0.75      - WRONG! (works like 0.25)
> 0.875    - WRONG! (works like 0.125)
> 
> The same for the other n.
> 
> I think it is a driver problem, it initializes the sub-integer prescaler
> incorrectly. Since under Windows FT230X works fine with all sub-integer
> prescalers.

Thanks for the report.

It sounds like your device behaves like a FT8U232AM, which only supports
0.125, 0.25 or 0.5, then. Are you sure Windows is able to use the
others?

Is the device type being detected correctly? What does the log say when
you plug your device in? Please also post the output of "lsusb -v" for
the device.

Johan
Comment 2 Vladimir 2021-01-08 11:37:13 UTC
Hello, Johan.
 
Unfortunately, I don't have a device at hand right now. But I remember the lsusb output was showing FT-X type. And under Windows, all three chips I mentioned work correctly with all prescalers. I contacted FTDI tech support with this problem. They advised me to have such a patch for ftdi_sio.c and it solved the problem. Here's the patch:

static int change_speed (struct tty_struct * tty, struct usb_serial_port * port)

...

      index_value = get_ftdi_divisor (tty, port);

      value = (u16) index_value;

      index = (u16) (index_value >> 16);

      if ((priv-> chip_type == FT2232C) || (priv-> chip_type == FT2232H) ||

            (priv-> chip_type == FT4232H) || (priv-> chip_type == FT232H)) {

            / * Probably the BM type needs the MSB of the encoded fractional

            * divider also moved like for the chips above. Any infos? * /

            index = (u16) ((index << 8) | priv-> interface);

      }

 

So, the high bit of the factional part is lost on the FT-X chips. To fix it in the kernel try:

 

      if ((priv-> chip_type == FT2232C) || (priv-> chip_type == FT2232H) ||

            (priv-> chip_type == FT4232H) || (priv-> chip_type == FT232H) ||

(priv-> chip_type == FTX)) {

            / * Probably the BM type needs the MSB of the encoded fractional

            * divider also moved like for the chips above. Any infos? * /

            index = (u16) ((index << 8) | priv-> interface);

      }

But I don't know why the most significant bit of the prescaler is masked by something. I have no information about the chip configuration registers. It looks like this is confidential information. But they could provide it to you as the driver developer.

Vladimir
Comment 3 Johan Hovold 2021-01-08 13:30:14 UTC
On Fri, Jan 08, 2021 at 11:37:13AM +0000, bugzilla-daemon@bugzilla.kernel.org wrote:
> Unfortunately, I don't have a device at hand right now. But I remember the
> lsusb output was showing FT-X type. And under Windows, all three chips I
> mentioned work correctly with all prescalers. I contacted FTDI tech support
> with this problem. They advised me to have such a patch for ftdi_sio.c and it
> solved the problem. Here's the patch:

>       if ((priv-> chip_type == FT2232C) || (priv-> chip_type == FT2232H) ||
> 
>             (priv-> chip_type == FT4232H) || (priv-> chip_type == FT232H) ||
> 
> (priv-> chip_type == FTX)) {
> 
>             / * Probably the BM type needs the MSB of the encoded fractional
> 
>             * divider also moved like for the chips above. Any infos? * /
> 
>             index = (u16) ((index << 8) | priv-> interface);
> 
>       }

Ah, that's good to hear. Do you want to submit that as a proper patch
that I can apply, or do you want me to do that?
 
> But I don't know why the most significant bit of the prescaler is masked by
> something. I have no information about the chip configuration registers. It
> looks like this is confidential information. But they could provide it to you
> as the driver developer.

I don't have access to any details about these chips apart from the
public sources either, I'm afraid.

But here it seems the upper bits simply needs to be shifted to make room
for the interface number just like for the H-types (which can have more
than one port).

Johan
Comment 4 Vladimir 2021-01-08 14:23:59 UTC
It's strange. The technical support promised that they would contact the developer. As far as I understand, you are the last developer and maintainer of the driver. I don't even know what to do. In general, this patch solves the problem. And it would be nice if it was officially included in the kernel. Otherwise, after each kernel update, you need to rebuild the module. The worry is that perhaps the same problem exists for some other chips. I've only tested three of them. But since you do not have detailed documentation from the manufacturer, you can simply apply this patch.

Vladimir
Comment 5 Johan Hovold 2021-01-26 14:09:20 UTC
Your reply never made it to the linux-usb list so I didn't see it until
today when I was preparing the patch I just CCed you on.

I'll queue it up for 5.12, but then I think we can backport it to the
stable trees as well.

Thanks again for reporting this.

Johan