All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
To: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jiri Slaby <jslaby@suse.com>,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-serial@vger.kernel.org
Subject: Re: [PATCH v4 3/3] serial: 8250_dw: add fractional divisor support
Date: Wed, 11 Jul 2018 14:41:25 +0800	[thread overview]
Message-ID: <20180711144125.7d4e6a73@xhacker.debian> (raw)
In-Reply-To: <8c5b6bbbde12b0836e1f833c86b805a817596654.camel@linux.intel.com>

Hi Andy,

On Tue, 10 Jul 2018 19:19:21 +0300 Andy Shevchenko wrote:

> On Tue, 2018-07-10 at 11:15 +0800, Jisheng Zhang wrote:
> > For Synopsys DesignWare 8250 uart which version >= 4.00a, there's a
> > valid divisor latch fraction register. The fractional divisor width is
> > 4bits ~ 6bits.
> > 
> > Now the preparation is done, it's easy to add the feature support.
> > This patch firstly tries to get the fractional divisor width during
> > probe, then setups dw specific get_divisor() and set_divisor() hook.  
> 
> Thanks for an update, my comments below.
> 
> > +/*
> > + * divisor = div(I) + div(F)
> > + * "I" means integer, "F" means fractional
> > + * quot = div(I) = clk / (16 * baud)
> > + * frac = div(F) * 2^dlf_size
> > + *
> > + * let rem = clk % (16 * baud)
> > + * we have: div(F) * (16 * baud) = rem
> > + * so frac = 2^dlf_size * rem / (16 * baud) = (rem << dlf_size) / (16
> > * baud)
> > + */
> > +static unsigned int dw8250_get_divisor(struct uart_port *p,
> > +				       unsigned int baud,
> > +				       unsigned int *frac)
> > +{  
> 
> unsigned int base_baud = baud * 16;

Good point. will send a new version.

> 
> > +	unsigned int quot, rem;
> > +	struct dw8250_data *d = p->private_data;
> > +
> > +	quot = p->uartclk / (16 * baud);
> > +	rem = p->uartclk % (16 * baud);
> > +	*frac = DIV_ROUND_CLOSEST(rem << d->dlf_size, 16 * baud);
> > +  
> 
> While it looks indeed better, I would rather like to have a confirmation
> it's working as designed.
> 
> For example, when I did some calculus, I cooked a preliminary check in
> Python (easy and fast to prototype), for example:
> https://gist.github.com/andy-shev/06b084488b3629898121 in Python, or
> commit 9df461eca18f ("spi: pxa2xx: replace ugly table by approximation")
> in the kernel.
> 
> Or another one here https://gist.github.com/andy-shev/8b2a73aeca2874f4cc
> 89 and commits c1a67b48f6a5 ("serial: 8250_pci: replace switch-case by
> formula for Intel MID"), 21947ba654a6 ("serial: 8250_pci: replace
> switch-case by formula")

My python coding skill is limited. So I wrote a simple c program to
do the check for common clks and baudrate combination. All passed. I
paste the code here:


#include <stdio.h>
#include <assert.h>
#include <math.h>

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

#define DIV_ROUND_CLOSEST(x, divisor)(			\
{							\
	typeof(x) __x = x;				\
	typeof(divisor) __d = divisor;			\
	(((typeof(x))-1) > 0 ||				\
	 ((typeof(divisor))-1) > 0 ||			\
	 (((__x) > 0) == ((__d) > 0))) ?		\
		(((__x) + ((__d) / 2)) / (__d)) :	\
		(((__x) - ((__d) / 2)) / (__d));	\
}							\
)

static unsigned int baud[] = {9600, 19200, 38400, 57600, 115200, 230400,
				460800, 921600, 1843200, 3250000, 4454400,
				576000, 1152000, 500000, 1000000, 1500000,
				2000000, 2500000, 3000000, 3500000, 4000000};

static unsigned int clk[] = {25000000, 50000000, 100000000, 133000000, 200000000};

static void check(int baud, int clk, int dlf_size)
{
	unsigned int rem, frac, quot;
	unsigned int base_baud = baud * 16;
	float div, divf;

	quot = clk / base_baud;
	rem = clk % base_baud;
	frac = DIV_ROUND_CLOSEST(rem << dlf_size, base_baud);

	div = (float)clk / base_baud;
	divf = div - (int)div;
	divf *= (1 << dlf_size);

	assert(quot == (int)div);
	assert(frac == (int)round(divf));
	printf("checked %d %d %d %d %d\n", baud, clk, dlf_size, quot, frac);
}

int main()
{
	int i, j, k;

	for (i = 0; i < ARRAY_SIZE(baud); i++) {
		for (j = 0; j < ARRAY_SIZE(clk); j++) {
			for (k = 4; k <= 6; k++) {
				check(baud[i], clk[j], k);
			}
		}
	}

	return 0;
}

WARNING: multiple messages have this Message-ID (diff)
From: Jisheng.Zhang@synaptics.com (Jisheng Zhang)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v4 3/3] serial: 8250_dw: add fractional divisor support
Date: Wed, 11 Jul 2018 14:41:25 +0800	[thread overview]
Message-ID: <20180711144125.7d4e6a73@xhacker.debian> (raw)
In-Reply-To: <8c5b6bbbde12b0836e1f833c86b805a817596654.camel@linux.intel.com>

Hi Andy,

On Tue, 10 Jul 2018 19:19:21 +0300 Andy Shevchenko wrote:

> On Tue, 2018-07-10 at 11:15 +0800, Jisheng Zhang wrote:
> > For Synopsys DesignWare 8250 uart which version >= 4.00a, there's a
> > valid divisor latch fraction register. The fractional divisor width is
> > 4bits ~ 6bits.
> > 
> > Now the preparation is done, it's easy to add the feature support.
> > This patch firstly tries to get the fractional divisor width during
> > probe, then setups dw specific get_divisor() and set_divisor() hook.  
> 
> Thanks for an update, my comments below.
> 
> > +/*
> > + * divisor = div(I) + div(F)
> > + * "I" means integer, "F" means fractional
> > + * quot = div(I) = clk / (16 * baud)
> > + * frac = div(F) * 2^dlf_size
> > + *
> > + * let rem = clk % (16 * baud)
> > + * we have: div(F) * (16 * baud) = rem
> > + * so frac = 2^dlf_size * rem / (16 * baud) = (rem << dlf_size) / (16
> > * baud)
> > + */
> > +static unsigned int dw8250_get_divisor(struct uart_port *p,
> > +				       unsigned int baud,
> > +				       unsigned int *frac)
> > +{  
> 
> unsigned int base_baud = baud * 16;

Good point. will send a new version.

> 
> > +	unsigned int quot, rem;
> > +	struct dw8250_data *d = p->private_data;
> > +
> > +	quot = p->uartclk / (16 * baud);
> > +	rem = p->uartclk % (16 * baud);
> > +	*frac = DIV_ROUND_CLOSEST(rem << d->dlf_size, 16 * baud);
> > +  
> 
> While it looks indeed better, I would rather like to have a confirmation
> it's working as designed.
> 
> For example, when I did some calculus, I cooked a preliminary check in
> Python (easy and fast to prototype), for example:
> https://gist.github.com/andy-shev/06b084488b3629898121 in Python, or
> commit 9df461eca18f ("spi: pxa2xx: replace ugly table by approximation")
> in the kernel.
> 
> Or another one here https://gist.github.com/andy-shev/8b2a73aeca2874f4cc
> 89 and commits c1a67b48f6a5 ("serial: 8250_pci: replace switch-case by
> formula for Intel MID"), 21947ba654a6 ("serial: 8250_pci: replace
> switch-case by formula")

My python coding skill is limited. So I wrote a simple c program to
do the check for common clks and baudrate combination. All passed. I
paste the code here:


#include <stdio.h>
#include <assert.h>
#include <math.h>

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

#define DIV_ROUND_CLOSEST(x, divisor)(			\
{							\
	typeof(x) __x = x;				\
	typeof(divisor) __d = divisor;			\
	(((typeof(x))-1) > 0 ||				\
	 ((typeof(divisor))-1) > 0 ||			\
	 (((__x) > 0) == ((__d) > 0))) ?		\
		(((__x) + ((__d) / 2)) / (__d)) :	\
		(((__x) - ((__d) / 2)) / (__d));	\
}							\
)

static unsigned int baud[] = {9600, 19200, 38400, 57600, 115200, 230400,
				460800, 921600, 1843200, 3250000, 4454400,
				576000, 1152000, 500000, 1000000, 1500000,
				2000000, 2500000, 3000000, 3500000, 4000000};

static unsigned int clk[] = {25000000, 50000000, 100000000, 133000000, 200000000};

static void check(int baud, int clk, int dlf_size)
{
	unsigned int rem, frac, quot;
	unsigned int base_baud = baud * 16;
	float div, divf;

	quot = clk / base_baud;
	rem = clk % base_baud;
	frac = DIV_ROUND_CLOSEST(rem << dlf_size, base_baud);

	div = (float)clk / base_baud;
	divf = div - (int)div;
	divf *= (1 << dlf_size);

	assert(quot == (int)div);
	assert(frac == (int)round(divf));
	printf("checked %d %d %d %d %d\n", baud, clk, dlf_size, quot, frac);
}

int main()
{
	int i, j, k;

	for (i = 0; i < ARRAY_SIZE(baud); i++) {
		for (j = 0; j < ARRAY_SIZE(clk); j++) {
			for (k = 4; k <= 6; k++) {
				check(baud[i], clk[j], k);
			}
		}
	}

	return 0;
}

  reply	other threads:[~2018-07-11  6:41 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-10  3:09 [PATCH v4 0/3] serial: 8250_dw: add fractional divisor support Jisheng Zhang
2018-07-10  3:09 ` Jisheng Zhang
2018-07-10  3:09 ` Jisheng Zhang
2018-07-10  3:12 ` [PATCH v4 1/3] serial: 8250: introduce get_divisor() and set_divisor() hook Jisheng Zhang
2018-07-10  3:12   ` Jisheng Zhang
2018-07-10  3:12   ` Jisheng Zhang
2018-07-10  3:13 ` [PATCH v4 2/3] serial: 8250: export serial8250_do_set_divisor() Jisheng Zhang
2018-07-10  3:13   ` Jisheng Zhang
2018-07-10  3:13   ` Jisheng Zhang
2018-07-10 13:56   ` Andy Shevchenko
2018-07-10 13:56     ` Andy Shevchenko
2018-07-10  3:15 ` [PATCH v4 3/3] serial: 8250_dw: add fractional divisor support Jisheng Zhang
2018-07-10  3:15   ` Jisheng Zhang
2018-07-10  3:15   ` Jisheng Zhang
2018-07-10 16:19   ` Andy Shevchenko
2018-07-10 16:19     ` Andy Shevchenko
2018-07-11  6:41     ` Jisheng Zhang [this message]
2018-07-11  6:41       ` Jisheng Zhang
2018-07-11 14:23       ` Andy Shevchenko
2018-07-11 14:23         ` Andy Shevchenko
2018-07-11  7:11   ` [PATCH v5 " Jisheng Zhang
2018-07-11  7:11     ` Jisheng Zhang
2018-07-11  7:11     ` Jisheng Zhang
2018-07-11 11:31     ` Andy Shevchenko
2018-07-11 11:31       ` Andy Shevchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180711144125.7d4e6a73@xhacker.debian \
    --to=jisheng.zhang@synaptics.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jslaby@suse.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.