On Sat, Sep 24, 2022 at 12:27:18PM +0200, Pali Rohár wrote: > Calculate baud rate value in c_*speed fields to the real values which were > set on hardware. For this operation, add a new set of methods > *_divisor_to_baud() for each chip and use them for calculating the real > baud rate values. > > Each *_divisor_to_baud() method is constructed as an inverse function of > its corresponding *_baud_to_divisor() method. > > Signed-off-by: Pali Rohár <pali@xxxxxxxxxx> > Tested-by: Marek Behún <kabel@xxxxxxxxxx> > Signed-off-by: Marek Behún <kabel@xxxxxxxxxx> > --- > drivers/usb/serial/ftdi_sio.c | 93 +++++++++++++++++++++++++++++++++++ > 1 file changed, 93 insertions(+) > > diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c > index 79b00912c81c..350ed14b014c 100644 > --- a/drivers/usb/serial/ftdi_sio.c > +++ b/drivers/usb/serial/ftdi_sio.c > @@ -1183,6 +1183,34 @@ static u32 ftdi_sio_baud_to_divisor(int baud) > } > } > > +static int ftdi_sdio_divisor_to_baud(u32 divisor) > +{ > + switch (divisor) { > + case ftdi_sio_b300: > + return 300; > + case ftdi_sio_b600: > + return 600; > + case ftdi_sio_b1200: > + return 1200; > + case ftdi_sio_b2400: > + return 2400; > + case ftdi_sio_b4800: > + return 4800; > + case ftdi_sio_b9600: > + return 9600; > + case ftdi_sio_b19200: > + return 19200; > + case ftdi_sio_b38400: > + return 38400; > + case ftdi_sio_b57600: > + return 57600; > + case ftdi_sio_b115200: > + return 115200; > + default: > + return 9600; > + } > +} As I mentioned before, this one should no be needed as the SIO only supports this discrete set of values (or errors out). > + > static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) > { > unsigned short int divisor; > @@ -1205,11 +1233,28 @@ static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) > return divisor; > } > > +static int ftdi_232am_divisor_base_to_baud(unsigned short int divisor, int base) > +{ > + static const unsigned char divfrac_inv[4] = { 0, 4, 2, 1 }; > + unsigned int divisor3; > + > + if (divisor == 0) > + divisor = 1; > + divisor3 = (GENMASK(13, 0) & divisor) << 3; > + divisor3 |= divfrac_inv[(divisor >> 14) & 0x3]; > + return DIV_ROUND_CLOSEST(base, 2 * divisor3); > +} Still no motivation to review these. [...] > @@ -1358,6 +1444,7 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, > } > div_okay = 0; > } > + baud = ftdi_sdio_divisor_to_baud(div_value); > break; > case FT8U232AM: /* 8U232AM chip */ > if (baud >= 183 && baud <= 3000000) { > @@ -1371,6 +1458,7 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, > div_value = ftdi_232am_baud_to_divisor(baud); > div_okay = 0; > } > + baud = ftdi_232am_divisor_to_baud(div_value); > break; > case FT232BM: /* FT232BM chip */ > case FT2232C: /* FT2232C chip */ > @@ -1397,25 +1485,30 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, > div_value = ftdi_232bm_baud_to_divisor(baud); > div_okay = 0; > } > + baud = ftdi_232bm_divisor_to_baud(div_value); > break; > case FT2232H: /* FT2232H chip */ > case FT4232H: /* FT4232H chip */ > case FT232H: /* FT232H chip */ > if ((baud <= 12000000) && (baud >= 1200)) { > div_value = ftdi_2232h_baud_to_divisor(baud); > + baud = ftdi_2232h_divisor_to_baud(div_value); > } else if (baud >= 183 && baud < 1200) { > div_value = ftdi_232bm_baud_to_divisor(baud); > + baud = ftdi_232bm_divisor_to_baud(div_value); > } else { > dev_dbg(dev, "%s - Baud rate too high!\n", __func__); > if (old_baud >= 183 && old_baud < 1200) { > baud = old_baud; > div_value = ftdi_232bm_baud_to_divisor(baud); > + baud = ftdi_232bm_divisor_to_baud(div_value); > } else { > if (old_baud >= 1200 && old_baud <= 12000000) > baud = old_baud; > else > baud = 9600; > div_value = ftdi_2232h_baud_to_divisor(baud); > + baud = ftdi_2232h_divisor_to_baud(div_value); But this must be cleaned up as mentioned earlier in this thread. > } > div_okay = 0; > } Johan