Message ID | 20220712115306.26471-8-kabel@kernel.org |
---|---|
State | New |
Headers | show |
Series | ftdi_sio driver improvements | expand |
On Tue, Jul 12, 2022 at 01:53:06PM +0200, Marek Behún wrote: > From: Pali Rohár <pali@kernel.org> > > 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@kernel.org> > Tested-by: Marek Behún <kabel@kernel.org> > Signed-off-by: Marek Behún <kabel@kernel.org> > --- > drivers/usb/serial/ftdi_sio.c | 83 +++++++++++++++++++++++++++++++++++ > 1 file changed, 83 insertions(+) > > diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c > index 39e8c5d06157..838acce53e69 100644 > --- a/drivers/usb/serial/ftdi_sio.c > +++ b/drivers/usb/serial/ftdi_sio.c > @@ -1167,6 +1167,23 @@ static int 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; > + } > +} This one should not be needed as sio only supports this discrete set of values in the first place. > static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) > { > unsigned short int divisor; > @@ -1189,15 +1206,33 @@ 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) I believe "base" was used as a function name suffix in the inverse function (due to the additional base argument). > +{ > + 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); > +} I don't have the motivation to try to review these inverses right now. Let's get the rest of the series in order first. Johan
On Thu, Aug 18, 2022 at 04:17:38PM +0200, Pali Rohár wrote: > On Sunday 24 July 2022 14:41:19 Johan Hovold wrote: > > On Tue, Jul 12, 2022 at 01:53:06PM +0200, Marek Behún wrote: > > > From: Pali Rohár <pali@kernel.org> > > > > > > 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@kernel.org> > > > Tested-by: Marek Behún <kabel@kernel.org> > > > Signed-off-by: Marek Behún <kabel@kernel.org> > > > --- > > > drivers/usb/serial/ftdi_sio.c | 83 +++++++++++++++++++++++++++++++++++ > > > 1 file changed, 83 insertions(+) > > > static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) > > > { > > > unsigned short int divisor; > > > @@ -1189,15 +1206,33 @@ 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) > > > > I believe "base" was used as a function name suffix in the inverse > > function (due to the additional base argument). > > Yes, in the same way as it used in name of ftdi_232am_baud_base_to_divisor. No, you used "base" as an infix here. Johan
On Tuesday 13 September 2022 17:02:39 Johan Hovold wrote: > On Thu, Aug 18, 2022 at 04:17:38PM +0200, Pali Rohár wrote: > > On Sunday 24 July 2022 14:41:19 Johan Hovold wrote: > > > On Tue, Jul 12, 2022 at 01:53:06PM +0200, Marek Behún wrote: > > > > From: Pali Rohár <pali@kernel.org> > > > > > > > > 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@kernel.org> > > > > Tested-by: Marek Behún <kabel@kernel.org> > > > > Signed-off-by: Marek Behún <kabel@kernel.org> > > > > --- > > > > drivers/usb/serial/ftdi_sio.c | 83 +++++++++++++++++++++++++++++++++++ > > > > 1 file changed, 83 insertions(+) > > > > > static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) > > > > { > > > > unsigned short int divisor; > > > > @@ -1189,15 +1206,33 @@ 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) > > > > > > I believe "base" was used as a function name suffix in the inverse > > > function (due to the additional base argument). > > > > Yes, in the same way as it used in name of ftdi_232am_baud_base_to_divisor. > > No, you used "base" as an infix here. > > Johan Yes, of course, it is "in the middle" because I said I used it in the same way as in ftdi_232am_baud_base_to_divisor. ftdi_232am_baud_base_to_divisor converts input "baud" and input "base" to return "divisor". Hence baud_base_to_divisor. And so ftdi_232am_divisor_base_to_baud converts input "divisor" and input "base" to return value "baud". Hence divisor_base_to_baud. So what is the problem? I still have not caught.
On Tue, Sep 13, 2022 at 05:24:05PM +0200, Pali Rohár wrote: > On Tuesday 13 September 2022 17:02:39 Johan Hovold wrote: > > On Thu, Aug 18, 2022 at 04:17:38PM +0200, Pali Rohár wrote: > > > On Sunday 24 July 2022 14:41:19 Johan Hovold wrote: > > > > > static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) > > > > > { > > > > > unsigned short int divisor; > > > > > @@ -1189,15 +1206,33 @@ 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) > > > > > > > > I believe "base" was used as a function name suffix in the inverse > > > > function (due to the additional base argument). > > > > > > Yes, in the same way as it used in name of ftdi_232am_baud_base_to_divisor. > > > > No, you used "base" as an infix here. > Yes, of course, it is "in the middle" because I said I used it in the > same way as in ftdi_232am_baud_base_to_divisor. > > ftdi_232am_baud_base_to_divisor converts input "baud" and input "base" > to return "divisor". Hence baud_base_to_divisor. > > And so ftdi_232am_divisor_base_to_baud converts input "divisor" and > input "base" to return value "baud". Hence divisor_base_to_baud. > > So what is the problem? I still have not caught. Ok, I should have looked closer at the code before replying. I believe I expected "base" to be used as a suffix in the current code but that doesn't appear to be the case. So you're just following the current style. Johan
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 39e8c5d06157..838acce53e69 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1167,6 +1167,23 @@ static int 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; + } +} + static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) { unsigned short int divisor; @@ -1189,15 +1206,33 @@ 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); +} + static unsigned short int ftdi_232am_baud_to_divisor(int baud) { return ftdi_232am_baud_base_to_divisor(baud, 48000000); } +static int ftdi_232am_divisor_to_baud(unsigned short int divisor) +{ + return ftdi_232am_divisor_base_to_baud(divisor, 48000000); +} + static u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) { static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; u32 divisor; + /* divisor shifted 3 bits to the left */ int divisor3 = DIV_ROUND_CLOSEST(base, 2 * baud); if (divisor3 > GENMASK(16, 0)) @@ -1212,11 +1247,31 @@ static u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) return divisor; } +static int ftdi_232bm_divisor_base_to_baud(u32 divisor, int base) +{ + static const unsigned char divfrac_inv[8] = { 0, 4, 2, 1, 3, 5, 6, 7 }; + u32 divisor3; + + /* Deal with special cases for highest baud rates. */ + if (divisor == 0) + divisor = 1; /* 1.0 */ + else if (divisor == 1) + divisor = 0x4001; /* 1.5 */ + divisor3 = (GENMASK(13, 0) & divisor) << 3; + divisor3 |= divfrac_inv[(divisor >> 14) & 0x7]; + return DIV_ROUND_CLOSEST(base, 2 * divisor3); +} + static u32 ftdi_232bm_baud_to_divisor(int baud) { return ftdi_232bm_baud_base_to_divisor(baud, 48000000); } +static int ftdi_232bm_divisor_to_baud(u32 divisor) +{ + return ftdi_232bm_divisor_base_to_baud(divisor, 48000000); +} + static u32 ftdi_2232h_baud_base_to_divisor(int baud, int base) { static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; @@ -1244,11 +1299,32 @@ static u32 ftdi_2232h_baud_base_to_divisor(int baud, int base) return divisor; } +static int ftdi_2232h_divisor_base_to_baud(u32 divisor, int base) +{ + static const unsigned char divfrac_inv[8] = { 0, 4, 2, 1, 3, 5, 6, 7 }; + u32 divisor3; + + divisor &= GENMASK(16, 0); + /* Deal with special cases for highest baud rates. */ + if (divisor == 0) + divisor = 1; /* 1.0 */ + else if (divisor == 1) + divisor = 0x4001; /* 1.5 */ + divisor3 = (GENMASK(13, 0) & divisor) << 3; + divisor3 |= divfrac_inv[(divisor >> 14) & 0x7]; + return DIV_ROUND_CLOSEST(8 * base, 10 * divisor3); +} + static u32 ftdi_2232h_baud_to_divisor(int baud) { return ftdi_2232h_baud_base_to_divisor(baud, 120000000); } +static int ftdi_2232h_divisor_to_baud(u32 divisor) +{ + return ftdi_2232h_divisor_base_to_baud(divisor, 120000000); +} + #define set_mctrl(port, set) update_mctrl((port), (set), 0) #define clear_mctrl(port, clear) update_mctrl((port), 0, (clear)) @@ -1342,6 +1418,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) { @@ -1352,6 +1429,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 */ @@ -1375,22 +1453,27 @@ 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 { baud = (old_baud >= 1200 && old_baud <= 12000000) ? old_baud : 9600; div_value = ftdi_2232h_baud_to_divisor(baud); + baud = ftdi_2232h_divisor_to_baud(div_value); } div_okay = 0; }