Re: [PATCH v1 1/3] serial: 8250: introduce helper to configure prescaler

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

 



Hi Andy,

On 03/11/2015 04:19 PM, Andy Shevchenko wrote:
> The fractional divider is used to provide different frequencies from one
> source. The following formulas are used to show the relations between Fref,
> Fuart, prescaler, nominator, and denominator values:
> 
> 	Fuart = Fref * m / n
> 	baud = Fuart / (prescaler * DLAB)
> 
> where prescaler value is in range 1..16.
> 
> The helper function returns prescaler, nominator, and denominator values. It
> also sets port UART clock to the corresponding value. Since serial core
> considers base Fuart = baud * 16, the given value of Fuart will be in
> proportion to that:
> 
>     Port UART clock = Fuart * 16 / prescaler
> 
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
> ---
>  drivers/tty/serial/8250/8250.h      |  4 +++
>  drivers/tty/serial/8250/8250_core.c | 54 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 58 insertions(+)
> 
> diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
> index 656ecc6..feed6a3 100644
> --- a/drivers/tty/serial/8250/8250.h
> +++ b/drivers/tty/serial/8250/8250.h
> @@ -198,3 +198,7 @@ static inline int serial8250_request_dma(struct uart_8250_port *p)
>  }
>  static inline void serial8250_release_dma(struct uart_8250_port *p) { }
>  #endif
> +
> +unsigned short serial8250_get_ps(struct uart_port *port, unsigned int baud,
> +				 unsigned int fref, unsigned short width,
> +				 unsigned int *m, unsigned int *n);
> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
> index 7b502c0..09803f5 100644
> --- a/drivers/tty/serial/8250/8250_core.c
> +++ b/drivers/tty/serial/8250/8250_core.c
> @@ -27,6 +27,7 @@
>  #include <linux/console.h>
>  #include <linux/sysrq.h>
>  #include <linux/delay.h>
> +#include <linux/gcd.h>
>  #include <linux/platform_device.h>
>  #include <linux/tty.h>
>  #include <linux/ratelimit.h>
> @@ -2412,6 +2413,59 @@ static void serial8250_shutdown(struct uart_port *port)
>  		serial8250_do_shutdown(port);
>  }
>  
> +/**
> + * serial8250_get_ps - calculates prescaler, nominator, and denominator values
> + * @port:	pointer to struct uart_port object
> + * @baud:	baud rate
> + * @fref:	reference frequency in Hz
> + * @width:	maximum width of @m and @n in bits
> + * @m:		nominator of fractional divider
> + * @n:		denominator of fractional divider
> + *
> + * The fractional divider is used to provide different frequencies from one
> + * source. The following formulas are used to show the relations between Fref,
> + * Fuart, prescaler, nominator, and denominator values:
> + *
> + *	Fuart = Fref * m / n, where m <= n
> + *
> + *	baud = Fuart / (prescaler * DLAB)
> + *
> + * Return:
> + * Prescaler value from 16 to 1, and sets port UART clock to the corresponding
> + * value. Since serial core considers base Fuart = baud * 16, the given value
> + * of Fuart will be in proportion to that:
> + *
> + *	Port UART clock = Fuart * 16 / prescaler
> + */
> +unsigned short serial8250_get_ps(struct uart_port *port, unsigned int baud,
> +				 unsigned int fref, unsigned short width,
> +				 unsigned int *m, unsigned int *n)

I don't think this belongs in the 8250 core; this should be a static helper
function to those 2 Intel parts.

Unless you think this is applicable to any other designs?

Regards,
Peter Hurley


> +{
> +	unsigned int fuart;
> +	unsigned int ps = 16, divisor, denominator;
> +
> +	/* Find prescaler value that satisfies Fuart < Fref */
> +	do {
> +		fuart = baud * ps;
> +	} while ((fuart > fref) && (--ps > 1));
> +
> +	/* Get Fuart closer to Fref */
> +	fuart *= rounddown_pow_of_two(fref / fuart);
> +
> +	/* Get a greatest common divisor */
> +	divisor = gcd(fref, fuart);
> +
> +	denominator = fref / divisor;
> +	while (denominator > BIT(width)) {
> +		divisor <<= 1;
> +		denominator >>= 1;
> +	}
> +	*n = denominator;
> +	*m = fuart / divisor;
> +	port->uartclk = fuart * 16 / ps;
> +	return ps;
> +}
> +
>  /*
>   * XR17V35x UARTs have an extra fractional divisor register (DLD)
>   * Calculate divisor with extra 4-bit fractional portion
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux