Re: [PATCH v3 7/7] USB: serial: ftdi_sio: Fill c_*speed fields with real baud rate

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux