From: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
To: Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Jiri Slaby <jslaby@suse.com>
Cc: linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 3/3] serial: 8250_dw: add fractional divisor support
Date: Wed, 4 Jul 2018 17:03:10 +0800 [thread overview]
Message-ID: <20180704170310.56772d77@xhacker.debian> (raw)
In-Reply-To: <20180704165908.4bb8b090@xhacker.debian>
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 checks the component version during probe, if
version >= 4.00a, then calculates the fractional divisor width, then
setups dw specific get_divisor() and set_divisor() hook.
Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
---
drivers/tty/serial/8250/8250_dw.c | 53 +++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index aff04f1de3a5..b9630f633388 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -31,9 +31,12 @@
/* Offsets for the DesignWare specific registers */
#define DW_UART_USR 0x1f /* UART Status Register */
+#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */
#define DW_UART_CPR 0xf4 /* Component Parameter Register */
#define DW_UART_UCV 0xf8 /* UART Component Version */
+#define DW_FRAC_MIN_VERS 0x3430302A
+
/* Component Parameter Register bits */
#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0)
#define DW_UART_CPR_AFCE_MODE (1 << 4)
@@ -65,6 +68,7 @@ struct dw8250_data {
unsigned int skip_autocfg:1;
unsigned int uart_16550_compatible:1;
+ unsigned int dlf_size:3;
};
static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
@@ -351,6 +355,33 @@ static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
return param == chan->device->dev->parent;
}
+/*
+ * For version >= 4.00a, the dw uarts have a valid divisor latch fraction
+ * register. Calculate divisor with extra 4bits ~ 6bits fractional portion.
+ */
+static unsigned int dw8250_get_divisor(struct uart_port *p,
+ unsigned int baud,
+ unsigned int *frac)
+{
+ unsigned int quot;
+ struct dw8250_data *d = p->private_data;
+
+ quot = DIV_ROUND_CLOSEST(p->uartclk << (d->dlf_size - 4), baud);
+ *frac = quot & (~0U >> (32 - d->dlf_size));
+
+ return quot >> d->dlf_size;
+}
+
+static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
+ unsigned int quot, unsigned int quot_frac)
+{
+ struct uart_8250_port *up = up_to_u8250p(p);
+
+ serial_port_out(p, DW_UART_DLF >> p->regshift, quot_frac);
+ serial_port_out(p, UART_LCR, up->lcr | UART_LCR_DLAB);
+ serial_dl_write(up, quot);
+}
+
static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
{
if (p->dev->of_node) {
@@ -414,6 +445,28 @@ static void dw8250_setup_port(struct uart_port *p)
dev_dbg(p->dev, "Designware UART version %c.%c%c\n",
(reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
+ /*
+ * For version >= 4.00a, the dw uarts have a valid divisor latch
+ * fraction register. Calculate the fractional divisor width.
+ */
+ if (reg >= DW_FRAC_MIN_VERS) {
+ struct dw8250_data *d = p->private_data;
+
+ if (p->iotype == UPIO_MEM32BE) {
+ iowrite32be(~0U, p->membase + DW_UART_DLF);
+ reg = ioread32be(p->membase + DW_UART_DLF);
+ } else {
+ writel(~0U, p->membase + DW_UART_DLF);
+ reg = readl(p->membase + DW_UART_DLF);
+ }
+ d->dlf_size = fls(reg);
+
+ if (d->dlf_size) {
+ p->get_divisor = dw8250_get_divisor;
+ p->set_divisor = dw8250_set_divisor;
+ }
+ }
+
if (p->iotype == UPIO_MEM32BE)
reg = ioread32be(p->membase + DW_UART_CPR);
else
--
2.18.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 v2 3/3] serial: 8250_dw: add fractional divisor support
Date: Wed, 4 Jul 2018 17:03:10 +0800 [thread overview]
Message-ID: <20180704170310.56772d77@xhacker.debian> (raw)
In-Reply-To: <20180704165908.4bb8b090@xhacker.debian>
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 checks the component version during probe, if
version >= 4.00a, then calculates the fractional divisor width, then
setups dw specific get_divisor() and set_divisor() hook.
Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
---
drivers/tty/serial/8250/8250_dw.c | 53 +++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index aff04f1de3a5..b9630f633388 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -31,9 +31,12 @@
/* Offsets for the DesignWare specific registers */
#define DW_UART_USR 0x1f /* UART Status Register */
+#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */
#define DW_UART_CPR 0xf4 /* Component Parameter Register */
#define DW_UART_UCV 0xf8 /* UART Component Version */
+#define DW_FRAC_MIN_VERS 0x3430302A
+
/* Component Parameter Register bits */
#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0)
#define DW_UART_CPR_AFCE_MODE (1 << 4)
@@ -65,6 +68,7 @@ struct dw8250_data {
unsigned int skip_autocfg:1;
unsigned int uart_16550_compatible:1;
+ unsigned int dlf_size:3;
};
static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
@@ -351,6 +355,33 @@ static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
return param == chan->device->dev->parent;
}
+/*
+ * For version >= 4.00a, the dw uarts have a valid divisor latch fraction
+ * register. Calculate divisor with extra 4bits ~ 6bits fractional portion.
+ */
+static unsigned int dw8250_get_divisor(struct uart_port *p,
+ unsigned int baud,
+ unsigned int *frac)
+{
+ unsigned int quot;
+ struct dw8250_data *d = p->private_data;
+
+ quot = DIV_ROUND_CLOSEST(p->uartclk << (d->dlf_size - 4), baud);
+ *frac = quot & (~0U >> (32 - d->dlf_size));
+
+ return quot >> d->dlf_size;
+}
+
+static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
+ unsigned int quot, unsigned int quot_frac)
+{
+ struct uart_8250_port *up = up_to_u8250p(p);
+
+ serial_port_out(p, DW_UART_DLF >> p->regshift, quot_frac);
+ serial_port_out(p, UART_LCR, up->lcr | UART_LCR_DLAB);
+ serial_dl_write(up, quot);
+}
+
static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
{
if (p->dev->of_node) {
@@ -414,6 +445,28 @@ static void dw8250_setup_port(struct uart_port *p)
dev_dbg(p->dev, "Designware UART version %c.%c%c\n",
(reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
+ /*
+ * For version >= 4.00a, the dw uarts have a valid divisor latch
+ * fraction register. Calculate the fractional divisor width.
+ */
+ if (reg >= DW_FRAC_MIN_VERS) {
+ struct dw8250_data *d = p->private_data;
+
+ if (p->iotype == UPIO_MEM32BE) {
+ iowrite32be(~0U, p->membase + DW_UART_DLF);
+ reg = ioread32be(p->membase + DW_UART_DLF);
+ } else {
+ writel(~0U, p->membase + DW_UART_DLF);
+ reg = readl(p->membase + DW_UART_DLF);
+ }
+ d->dlf_size = fls(reg);
+
+ if (d->dlf_size) {
+ p->get_divisor = dw8250_get_divisor;
+ p->set_divisor = dw8250_set_divisor;
+ }
+ }
+
if (p->iotype == UPIO_MEM32BE)
reg = ioread32be(p->membase + DW_UART_CPR);
else
--
2.18.0
next prev parent reply other threads:[~2018-07-04 9:03 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-04 8:59 [PATCH v2 0/3] serial: 8250_dw: add fractional divisor support Jisheng Zhang
2018-07-04 8:59 ` Jisheng Zhang
2018-07-04 9:00 ` [PATCH v2 1/3] serial: 8250: let serial8250_get_divisor() get uart_port * as param Jisheng Zhang
2018-07-04 9:00 ` Jisheng Zhang
2018-07-04 10:00 ` Andy Shevchenko
2018-07-04 10:00 ` Andy Shevchenko
2018-07-04 9:02 ` [PATCH v2 2/3] serial: 8250: introduce get_divisor() and set_divisor() hook Jisheng Zhang
2018-07-04 9:02 ` Jisheng Zhang
2018-07-04 10:00 ` Andy Shevchenko
2018-07-04 10:00 ` Andy Shevchenko
2018-07-04 9:03 ` Jisheng Zhang [this message]
2018-07-04 9:03 ` [PATCH v2 3/3] serial: 8250_dw: add fractional divisor support Jisheng Zhang
2018-07-04 16:08 ` Andy Shevchenko
2018-07-04 16:08 ` Andy Shevchenko
2018-07-04 16:08 ` Andy Shevchenko
2018-07-05 6:39 ` Jisheng Zhang
2018-07-05 6:39 ` Jisheng Zhang
2018-07-05 6:54 ` Jisheng Zhang
2018-07-05 6:54 ` Jisheng Zhang
2018-07-06 17:39 ` Andy Shevchenko
2018-07-06 17:39 ` Andy Shevchenko
2018-07-06 17:37 ` Andy Shevchenko
2018-07-06 17:37 ` Andy Shevchenko
2018-07-09 6:04 ` Jisheng Zhang
2018-07-09 6:04 ` Jisheng Zhang
2018-07-09 6:04 ` Jisheng Zhang
2018-07-09 6:15 ` Andy Shevchenko
2018-07-09 6:15 ` 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=20180704170310.56772d77@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.