All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] serial: sh-sci: Add support for SCIFA/SCIFB variable sampling rates
@ 2016-01-04 13:45 ` Geert Uytterhoeven
  0 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2016-01-04 13:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: Simon Horman, Magnus Damm, Yoshinori Sato, linux-serial,
	linux-sh, Geert Uytterhoeven

	Hi Greg, Jiri,

This patch series adds support for variable sampling rates on the SCIFA
and SCIFB variants.

Currently the driver uses a fixed sampling rate divider (usually 16 or 32),
except on HSCIF (full range of 8 to 32).  Supporting all available
sampling rates on SCIFA and SCIFB increases the range and accuracy of
supported baud rates.

E.g. on r8a7791/koelsch:
  - Supports now 134, 150, and standard 500000-4000000 bps,
  - Perfect match for 134, 150, 500000, 1000000, 2000000, and 4000000
    bps,
  - Accuracy has increased for most standard bps values.

Tested on:
  - r8a7791/koelsch (Fully tested on SCIFA and SCIFB),
  - r8a7740/armadillo (Fully tested on SCIFA and SCIFB),
  - sh73a0/kzm9g (Fully tested on SCIFA only, no easy access to SCIFB),
  - r8a73a4/ape6evm (SCIFA/FTDI console at 460800 bps, no easy access to
    SCIFB).

This series depends on my scif-clk-sck-brg-for-v4.5 pull request.

Thanks for your comments!

Geert Uytterhoeven (5):
  serial: sh-sci: Add more Serial Mode Register documentation
  serial: sh-sci: Preserve SCIFA/SCIFB bit rate config for serial
    console
  serial: sh-sci: Use premultiplier to handle half sampling rate
  serial: sh-sci: Use a bitmask to indicate supported sampling rates
  serial: sh-sci: Add support for SCIFA/SCIFB variable sampling rates

 drivers/tty/serial/sh-sci.c | 106 ++++++++++++++++++++++++++------------------
 drivers/tty/serial/sh-sci.h |  15 +++++++
 2 files changed, 77 insertions(+), 44 deletions(-)

-- 
1.9.1

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 0/5] serial: sh-sci: Add support for SCIFA/SCIFB variable sampling rates
@ 2016-01-04 13:45 ` Geert Uytterhoeven
  0 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2016-01-04 13:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: Simon Horman, Magnus Damm, Yoshinori Sato, linux-serial,
	linux-sh, Geert Uytterhoeven

	Hi Greg, Jiri,

This patch series adds support for variable sampling rates on the SCIFA
and SCIFB variants.

Currently the driver uses a fixed sampling rate divider (usually 16 or 32),
except on HSCIF (full range of 8 to 32).  Supporting all available
sampling rates on SCIFA and SCIFB increases the range and accuracy of
supported baud rates.

E.g. on r8a7791/koelsch:
  - Supports now 134, 150, and standard 500000-4000000 bps,
  - Perfect match for 134, 150, 500000, 1000000, 2000000, and 4000000
    bps,
  - Accuracy has increased for most standard bps values.

Tested on:
  - r8a7791/koelsch (Fully tested on SCIFA and SCIFB),
  - r8a7740/armadillo (Fully tested on SCIFA and SCIFB),
  - sh73a0/kzm9g (Fully tested on SCIFA only, no easy access to SCIFB),
  - r8a73a4/ape6evm (SCIFA/FTDI console at 460800 bps, no easy access to
    SCIFB).

This series depends on my scif-clk-sck-brg-for-v4.5 pull request.

Thanks for your comments!

Geert Uytterhoeven (5):
  serial: sh-sci: Add more Serial Mode Register documentation
  serial: sh-sci: Preserve SCIFA/SCIFB bit rate config for serial
    console
  serial: sh-sci: Use premultiplier to handle half sampling rate
  serial: sh-sci: Use a bitmask to indicate supported sampling rates
  serial: sh-sci: Add support for SCIFA/SCIFB variable sampling rates

 drivers/tty/serial/sh-sci.c | 106 ++++++++++++++++++++++++++------------------
 drivers/tty/serial/sh-sci.h |  15 +++++++
 2 files changed, 77 insertions(+), 44 deletions(-)

-- 
1.9.1

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/5] serial: sh-sci: Add more Serial Mode Register documentation
  2016-01-04 13:45 ` Geert Uytterhoeven
@ 2016-01-04 13:45   ` Geert Uytterhoeven
  -1 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2016-01-04 13:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: Simon Horman, Magnus Damm, Yoshinori Sato, linux-serial,
	linux-sh, Geert Uytterhoeven

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 drivers/tty/serial/sh-sci.c |  2 +-
 drivers/tty/serial/sh-sci.h | 15 +++++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 6571f4d944c26297..a7c062192e2d3130 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -2091,7 +2091,7 @@ static void sci_reset(struct uart_port *port)
 static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 			    struct ktermios *old)
 {
-	unsigned int baud, smr_val = 0, scr_val = 0, i;
+	unsigned int baud, smr_val = SCSMR_ASYNC, scr_val = 0, i;
 	unsigned int brr = 255, cks = 0, srr = 15, dl = 0, sccks = 0;
 	unsigned int brr1 = 255, cks1 = 0, srr1 = 15, dl1 = 0;
 	struct sci_port *s = to_sci_port(port);
diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h
index fb176025042185c4..7a4fa185b93ef307 100644
--- a/drivers/tty/serial/sh-sci.h
+++ b/drivers/tty/serial/sh-sci.h
@@ -35,12 +35,27 @@ enum {
 
 
 /* SCSMR (Serial Mode Register) */
+#define SCSMR_C_A	BIT(7)	/* Communication Mode */
+#define SCSMR_CSYNC	BIT(7)	/*   - Clocked synchronous mode */
+#define SCSMR_ASYNC	0	/*   - Asynchronous mode */
 #define SCSMR_CHR	BIT(6)	/* 7-bit Character Length */
 #define SCSMR_PE	BIT(5)	/* Parity Enable */
 #define SCSMR_ODD	BIT(4)	/* Odd Parity */
 #define SCSMR_STOP	BIT(3)	/* Stop Bit Length */
 #define SCSMR_CKS	0x0003	/* Clock Select */
 
+/* Serial Mode Register, SCIFA/SCIFB only bits */
+#define SCSMR_CKEDG	BIT(12)	/* Transmit/Receive Clock Edge Select */
+#define SCSMR_SRC_MASK	0x0700	/* Sampling Control */
+#define SCSMR_SRC_16	0x0000	/* Sampling rate 1/16 */
+#define SCSMR_SRC_5	0x0100	/* Sampling rate 1/5 */
+#define SCSMR_SRC_7	0x0200	/* Sampling rate 1/7 */
+#define SCSMR_SRC_11	0x0300	/* Sampling rate 1/11 */
+#define SCSMR_SRC_13	0x0400	/* Sampling rate 1/13 */
+#define SCSMR_SRC_17	0x0500	/* Sampling rate 1/17 */
+#define SCSMR_SRC_19	0x0600	/* Sampling rate 1/19 */
+#define SCSMR_SRC_27	0x0700	/* Sampling rate 1/27 */
+
 /* Serial Control Register, SCIFA/SCIFB only bits */
 #define SCSCR_TDRQE	BIT(15)	/* Tx Data Transfer Request Enable */
 #define SCSCR_RDRQE	BIT(14)	/* Rx Data Transfer Request Enable */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 1/5] serial: sh-sci: Add more Serial Mode Register documentation
@ 2016-01-04 13:45   ` Geert Uytterhoeven
  0 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2016-01-04 13:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: Simon Horman, Magnus Damm, Yoshinori Sato, linux-serial,
	linux-sh, Geert Uytterhoeven

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 drivers/tty/serial/sh-sci.c |  2 +-
 drivers/tty/serial/sh-sci.h | 15 +++++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 6571f4d944c26297..a7c062192e2d3130 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -2091,7 +2091,7 @@ static void sci_reset(struct uart_port *port)
 static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 			    struct ktermios *old)
 {
-	unsigned int baud, smr_val = 0, scr_val = 0, i;
+	unsigned int baud, smr_val = SCSMR_ASYNC, scr_val = 0, i;
 	unsigned int brr = 255, cks = 0, srr = 15, dl = 0, sccks = 0;
 	unsigned int brr1 = 255, cks1 = 0, srr1 = 15, dl1 = 0;
 	struct sci_port *s = to_sci_port(port);
diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h
index fb176025042185c4..7a4fa185b93ef307 100644
--- a/drivers/tty/serial/sh-sci.h
+++ b/drivers/tty/serial/sh-sci.h
@@ -35,12 +35,27 @@ enum {
 
 
 /* SCSMR (Serial Mode Register) */
+#define SCSMR_C_A	BIT(7)	/* Communication Mode */
+#define SCSMR_CSYNC	BIT(7)	/*   - Clocked synchronous mode */
+#define SCSMR_ASYNC	0	/*   - Asynchronous mode */
 #define SCSMR_CHR	BIT(6)	/* 7-bit Character Length */
 #define SCSMR_PE	BIT(5)	/* Parity Enable */
 #define SCSMR_ODD	BIT(4)	/* Odd Parity */
 #define SCSMR_STOP	BIT(3)	/* Stop Bit Length */
 #define SCSMR_CKS	0x0003	/* Clock Select */
 
+/* Serial Mode Register, SCIFA/SCIFB only bits */
+#define SCSMR_CKEDG	BIT(12)	/* Transmit/Receive Clock Edge Select */
+#define SCSMR_SRC_MASK	0x0700	/* Sampling Control */
+#define SCSMR_SRC_16	0x0000	/* Sampling rate 1/16 */
+#define SCSMR_SRC_5	0x0100	/* Sampling rate 1/5 */
+#define SCSMR_SRC_7	0x0200	/* Sampling rate 1/7 */
+#define SCSMR_SRC_11	0x0300	/* Sampling rate 1/11 */
+#define SCSMR_SRC_13	0x0400	/* Sampling rate 1/13 */
+#define SCSMR_SRC_17	0x0500	/* Sampling rate 1/17 */
+#define SCSMR_SRC_19	0x0600	/* Sampling rate 1/19 */
+#define SCSMR_SRC_27	0x0700	/* Sampling rate 1/27 */
+
 /* Serial Control Register, SCIFA/SCIFB only bits */
 #define SCSCR_TDRQE	BIT(15)	/* Tx Data Transfer Request Enable */
 #define SCSCR_RDRQE	BIT(14)	/* Rx Data Transfer Request Enable */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/5] serial: sh-sci: Preserve SCIFA/SCIFB bit rate config for serial console
  2016-01-04 13:45 ` Geert Uytterhoeven
@ 2016-01-04 13:45   ` Geert Uytterhoeven
  -1 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2016-01-04 13:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: Simon Horman, Magnus Damm, Yoshinori Sato, linux-serial,
	linux-sh, Geert Uytterhoeven

SCIFA and SCIFB have additional bit rate config bits in the Serial Mode
Register.  Don't touch them when using the port as a serial console, as
we rely on the boot loader to have configured the serial port config.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
I'm not aware of any boot loader setting these bits, but better safe
than sorry.
---
 drivers/tty/serial/sh-sci.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index a7c062192e2d3130..e8d6fa77e11208d4 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -2229,7 +2229,8 @@ done:
 	} else {
 		/* Don't touch the bit rate configuration */
 		scr_val = s->cfg->scscr & (SCSCR_CKE1 | SCSCR_CKE0);
-		smr_val |= serial_port_in(port, SCSMR) & SCSMR_CKS;
+		smr_val |= serial_port_in(port, SCSMR) &
+			   (SCSMR_CKEDG | SCSMR_SRC_MASK | SCSMR_CKS);
 		dev_dbg(port->dev, "SCR 0x%x SMR 0x%x\n", scr_val, smr_val);
 		serial_port_out(port, SCSCR, scr_val);
 		serial_port_out(port, SCSMR, smr_val);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/5] serial: sh-sci: Preserve SCIFA/SCIFB bit rate config for serial console
@ 2016-01-04 13:45   ` Geert Uytterhoeven
  0 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2016-01-04 13:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: Simon Horman, Magnus Damm, Yoshinori Sato, linux-serial,
	linux-sh, Geert Uytterhoeven

SCIFA and SCIFB have additional bit rate config bits in the Serial Mode
Register.  Don't touch them when using the port as a serial console, as
we rely on the boot loader to have configured the serial port config.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
I'm not aware of any boot loader setting these bits, but better safe
than sorry.
---
 drivers/tty/serial/sh-sci.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index a7c062192e2d3130..e8d6fa77e11208d4 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -2229,7 +2229,8 @@ done:
 	} else {
 		/* Don't touch the bit rate configuration */
 		scr_val = s->cfg->scscr & (SCSCR_CKE1 | SCSCR_CKE0);
-		smr_val |= serial_port_in(port, SCSMR) & SCSMR_CKS;
+		smr_val |= serial_port_in(port, SCSMR) &
+			   (SCSMR_CKEDG | SCSMR_SRC_MASK | SCSMR_CKS);
 		dev_dbg(port->dev, "SCR 0x%x SMR 0x%x\n", scr_val, smr_val);
 		serial_port_out(port, SCSCR, scr_val);
 		serial_port_out(port, SCSMR, smr_val);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/5] serial: sh-sci: Use premultiplier to handle half sampling rate
  2016-01-04 13:45 ` Geert Uytterhoeven
@ 2016-01-04 13:45   ` Geert Uytterhoeven
  -1 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2016-01-04 13:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: Simon Horman, Magnus Damm, Yoshinori Sato, linux-serial,
	linux-sh, Geert Uytterhoeven

On SCIx variants different from HSCIF, the bit rate is equal to the
sampling clock rate divided by half the sampling rate. Currently this is
handled by dividing the sampling rate by two, which was OK as it was
always even.

Replace halving the sampling rate by premultiplying the base clock
frequency by 2, to accommodate odd sampling rates on SCIFA/SCIFB later.

Replace the shift value in the BRG divider calculation by a
premultiplication of the base clock frequency too, for consistency.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 drivers/tty/serial/sh-sci.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index e8d6fa77e11208d4..f3c2a89a9550add9 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1934,9 +1934,11 @@ static int sci_sck_calc(struct sci_port *s, unsigned int bps,
 	unsigned int min_sr, max_sr, sr;
 	int err, min_err = INT_MAX;
 
+	if (s->port.type != PORT_HSCIF)
+		freq *= 2;
 	if (s->sampling_rate) {
 		/* SCI(F) has a fixed sampling rate */
-		min_sr = max_sr = s->sampling_rate / 2;
+		min_sr = max_sr = s->sampling_rate;
 	} else {
 		/* HSCIF has a variable 1/(8..32) sampling rate */
 		min_sr = 8;
@@ -1967,9 +1969,11 @@ static int sci_brg_calc(struct sci_port *s, unsigned int bps,
 	unsigned int min_sr, max_sr, sr, dl;
 	int err, min_err = INT_MAX;
 
+	if (s->port.type != PORT_HSCIF)
+		freq *= 2;
 	if (s->sampling_rate) {
 		/* SCIF has a fixed sampling rate */
-		min_sr = max_sr = s->sampling_rate / 2;
+		min_sr = max_sr = s->sampling_rate;
 	} else {
 		/* HSCIF has a variable 1/(8..32) sampling rate */
 		min_sr = 8;
@@ -2002,18 +2006,18 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
 			  unsigned int *brr, unsigned int *srr,
 			  unsigned int *cks)
 {
-	unsigned int min_sr, max_sr, shift, sr, br, prediv, scrate, c;
+	unsigned int min_sr, max_sr, sr, br, prediv, scrate, c;
 	unsigned long freq = s->clk_rates[SCI_FCK];
 	int err, min_err = INT_MAX;
 
+	if (s->port.type != PORT_HSCIF)
+		freq *= 2;
 	if (s->sampling_rate) {
 		min_sr = max_sr = s->sampling_rate;
-		shift = 0;
 	} else {
 		/* HSCIF has a variable sample rate */
 		min_sr = 8;
 		max_sr = 32;
-		shift = 1;
 	}
 
 	/*
@@ -2034,7 +2038,7 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
 	for (sr = max_sr; sr >= min_sr; sr--) {
 		for (c = 0; c <= 3; c++) {
 			/* integerized formulas from HSCIF documentation */
-			prediv = sr * (1 << (2 * c + shift));
+			prediv = sr * (1 << (2 * c + 1));
 
 			/*
 			 * We need to calculate:
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/5] serial: sh-sci: Use premultiplier to handle half sampling rate
@ 2016-01-04 13:45   ` Geert Uytterhoeven
  0 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2016-01-04 13:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: Simon Horman, Magnus Damm, Yoshinori Sato, linux-serial,
	linux-sh, Geert Uytterhoeven

On SCIx variants different from HSCIF, the bit rate is equal to the
sampling clock rate divided by half the sampling rate. Currently this is
handled by dividing the sampling rate by two, which was OK as it was
always even.

Replace halving the sampling rate by premultiplying the base clock
frequency by 2, to accommodate odd sampling rates on SCIFA/SCIFB later.

Replace the shift value in the BRG divider calculation by a
premultiplication of the base clock frequency too, for consistency.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 drivers/tty/serial/sh-sci.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index e8d6fa77e11208d4..f3c2a89a9550add9 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1934,9 +1934,11 @@ static int sci_sck_calc(struct sci_port *s, unsigned int bps,
 	unsigned int min_sr, max_sr, sr;
 	int err, min_err = INT_MAX;
 
+	if (s->port.type != PORT_HSCIF)
+		freq *= 2;
 	if (s->sampling_rate) {
 		/* SCI(F) has a fixed sampling rate */
-		min_sr = max_sr = s->sampling_rate / 2;
+		min_sr = max_sr = s->sampling_rate;
 	} else {
 		/* HSCIF has a variable 1/(8..32) sampling rate */
 		min_sr = 8;
@@ -1967,9 +1969,11 @@ static int sci_brg_calc(struct sci_port *s, unsigned int bps,
 	unsigned int min_sr, max_sr, sr, dl;
 	int err, min_err = INT_MAX;
 
+	if (s->port.type != PORT_HSCIF)
+		freq *= 2;
 	if (s->sampling_rate) {
 		/* SCIF has a fixed sampling rate */
-		min_sr = max_sr = s->sampling_rate / 2;
+		min_sr = max_sr = s->sampling_rate;
 	} else {
 		/* HSCIF has a variable 1/(8..32) sampling rate */
 		min_sr = 8;
@@ -2002,18 +2006,18 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
 			  unsigned int *brr, unsigned int *srr,
 			  unsigned int *cks)
 {
-	unsigned int min_sr, max_sr, shift, sr, br, prediv, scrate, c;
+	unsigned int min_sr, max_sr, sr, br, prediv, scrate, c;
 	unsigned long freq = s->clk_rates[SCI_FCK];
 	int err, min_err = INT_MAX;
 
+	if (s->port.type != PORT_HSCIF)
+		freq *= 2;
 	if (s->sampling_rate) {
 		min_sr = max_sr = s->sampling_rate;
-		shift = 0;
 	} else {
 		/* HSCIF has a variable sample rate */
 		min_sr = 8;
 		max_sr = 32;
-		shift = 1;
 	}
 
 	/*
@@ -2034,7 +2038,7 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
 	for (sr = max_sr; sr >= min_sr; sr--) {
 		for (c = 0; c <= 3; c++) {
 			/* integerized formulas from HSCIF documentation */
-			prediv = sr * (1 << (2 * c + shift));
+			prediv = sr * (1 << (2 * c + 1));
 
 			/*
 			 * We need to calculate:
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/5] serial: sh-sci: Use a bitmask to indicate supported sampling rates
  2016-01-04 13:45 ` Geert Uytterhoeven
@ 2016-01-04 13:45   ` Geert Uytterhoeven
  -1 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2016-01-04 13:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: Simon Horman, Magnus Damm, Yoshinori Sato, linux-serial,
	linux-sh, Geert Uytterhoeven

Replace the single sampling rate and special handling for HSCIF's
variable sampling rates by a bitmask and a custom iterator.
This prepares for the advent of SCIFA/SCIFB's sparse variable sampling
rates.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 drivers/tty/serial/sh-sci.c | 66 +++++++++++++++++++--------------------------
 1 file changed, 27 insertions(+), 39 deletions(-)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index f3c2a89a9550add9..17188fc4b1b32439 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -85,6 +85,18 @@ enum SCI_CLKS {
 	SCI_NUM_CLKS
 };
 
+/* Bit x set means sampling rate x + 1 is supported */
+#define SCI_SR(x)		BIT((x) - 1)
+#define SCI_SR_RANGE(x, y)	GENMASK((y) - 1, (x) - 1)
+
+#define min_sr(_port)		ffs((_port)->sampling_rate_mask)
+#define max_sr(_port)		fls((_port)->sampling_rate_mask)
+
+/* Iterate over all supported sampling rates, from high to low */
+#define for_each_sr(_sr, _port)						\
+	for ((_sr) = max_sr(_port); (_sr) >= min_sr(_port); (_sr)--)	\
+		if ((_port)->sampling_rate_mask & SCI_SR((_sr)))
+
 struct sci_port {
 	struct uart_port	port;
 
@@ -94,7 +106,7 @@ struct sci_port {
 	unsigned int		overrun_mask;
 	unsigned int		error_mask;
 	unsigned int		error_clear;
-	unsigned int		sampling_rate;
+	unsigned int		sampling_rate_mask;
 	resource_size_t		reg_size;
 
 	/* Break timer */
@@ -1931,21 +1943,13 @@ static int sci_sck_calc(struct sci_port *s, unsigned int bps,
 			unsigned int *srr)
 {
 	unsigned long freq = s->clk_rates[SCI_SCK];
-	unsigned int min_sr, max_sr, sr;
 	int err, min_err = INT_MAX;
+	unsigned int sr;
 
 	if (s->port.type != PORT_HSCIF)
 		freq *= 2;
-	if (s->sampling_rate) {
-		/* SCI(F) has a fixed sampling rate */
-		min_sr = max_sr = s->sampling_rate;
-	} else {
-		/* HSCIF has a variable 1/(8..32) sampling rate */
-		min_sr = 8;
-		max_sr = 32;
-	}
 
-	for (sr = max_sr; sr >= min_sr; sr--) {
+	for_each_sr(sr, s) {
 		err = DIV_ROUND_CLOSEST(freq, sr) - bps;
 		if (abs(err) >= abs(min_err))
 			continue;
@@ -1966,21 +1970,13 @@ static int sci_brg_calc(struct sci_port *s, unsigned int bps,
 			unsigned long freq, unsigned int *dlr,
 			unsigned int *srr)
 {
-	unsigned int min_sr, max_sr, sr, dl;
 	int err, min_err = INT_MAX;
+	unsigned int sr, dl;
 
 	if (s->port.type != PORT_HSCIF)
 		freq *= 2;
-	if (s->sampling_rate) {
-		/* SCIF has a fixed sampling rate */
-		min_sr = max_sr = s->sampling_rate;
-	} else {
-		/* HSCIF has a variable 1/(8..32) sampling rate */
-		min_sr = 8;
-		max_sr = 32;
-	}
 
-	for (sr = max_sr; sr >= min_sr; sr--) {
+	for_each_sr(sr, s) {
 		dl = DIV_ROUND_CLOSEST(freq, sr * bps);
 		dl = clamp(dl, 1U, 65535U);
 
@@ -2006,19 +2002,12 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
 			  unsigned int *brr, unsigned int *srr,
 			  unsigned int *cks)
 {
-	unsigned int min_sr, max_sr, sr, br, prediv, scrate, c;
 	unsigned long freq = s->clk_rates[SCI_FCK];
+	unsigned int sr, br, prediv, scrate, c;
 	int err, min_err = INT_MAX;
 
 	if (s->port.type != PORT_HSCIF)
 		freq *= 2;
-	if (s->sampling_rate) {
-		min_sr = max_sr = s->sampling_rate;
-	} else {
-		/* HSCIF has a variable sample rate */
-		min_sr = 8;
-		max_sr = 32;
-	}
 
 	/*
 	 * Find the combination of sample rate and clock select with the
@@ -2035,7 +2024,7 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
 	 *      (|D - 0.5| / N * (1 + F))|
 	 *  NOTE: Usually, treat D for 0.5, F is 0 by this calculation.
 	 */
-	for (sr = max_sr; sr >= min_sr; sr--) {
+	for_each_sr(sr, s) {
 		for (c = 0; c <= 3; c++) {
 			/* integerized formulas from HSCIF documentation */
 			prediv = sr * (1 << (2 * c + 1));
@@ -2129,8 +2118,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 	for (i = 0; i < SCI_NUM_CLKS; i++)
 		max_freq = max(max_freq, s->clk_rates[i]);
 
-	baud = uart_get_baud_rate(port, termios, old, 0,
-				  max_freq / max(s->sampling_rate, 8U));
+	baud = uart_get_baud_rate(port, termios, old, 0, max_freq / min_sr(s));
 	if (!baud)
 		goto done;
 
@@ -2562,37 +2550,37 @@ static int sci_init_single(struct platform_device *dev,
 		port->fifosize = 256;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCIFA_ORER;
-		sci_port->sampling_rate = 16;
+		sci_port->sampling_rate_mask = SCI_SR(16);
 		break;
 	case PORT_HSCIF:
 		port->fifosize = 128;
 		sci_port->overrun_reg = SCLSR;
 		sci_port->overrun_mask = SCLSR_ORER;
-		sci_port->sampling_rate = 0;
+		sci_port->sampling_rate_mask = SCI_SR_RANGE(8, 32);
 		break;
 	case PORT_SCIFA:
 		port->fifosize = 64;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCIFA_ORER;
-		sci_port->sampling_rate = 16;
+		sci_port->sampling_rate_mask = SCI_SR(16);
 		break;
 	case PORT_SCIF:
 		port->fifosize = 16;
 		if (p->regtype = SCIx_SH7705_SCIF_REGTYPE) {
 			sci_port->overrun_reg = SCxSR;
 			sci_port->overrun_mask = SCIFA_ORER;
-			sci_port->sampling_rate = 16;
+			sci_port->sampling_rate_mask = SCI_SR(16);
 		} else {
 			sci_port->overrun_reg = SCLSR;
 			sci_port->overrun_mask = SCLSR_ORER;
-			sci_port->sampling_rate = 32;
+			sci_port->sampling_rate_mask = SCI_SR(32);
 		}
 		break;
 	default:
 		port->fifosize = 1;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCI_ORER;
-		sci_port->sampling_rate = 32;
+		sci_port->sampling_rate_mask = SCI_SR(32);
 		break;
 	}
 
@@ -2601,7 +2589,7 @@ static int sci_init_single(struct platform_device *dev,
 	 * data override the sampling rate for now.
 	 */
 	if (p->sampling_rate)
-		sci_port->sampling_rate = p->sampling_rate;
+		sci_port->sampling_rate_mask = SCI_SR(p->sampling_rate);
 
 	if (!early) {
 		ret = sci_init_clocks(sci_port, &dev->dev);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/5] serial: sh-sci: Use a bitmask to indicate supported sampling rates
@ 2016-01-04 13:45   ` Geert Uytterhoeven
  0 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2016-01-04 13:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: Simon Horman, Magnus Damm, Yoshinori Sato, linux-serial,
	linux-sh, Geert Uytterhoeven

Replace the single sampling rate and special handling for HSCIF's
variable sampling rates by a bitmask and a custom iterator.
This prepares for the advent of SCIFA/SCIFB's sparse variable sampling
rates.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 drivers/tty/serial/sh-sci.c | 66 +++++++++++++++++++--------------------------
 1 file changed, 27 insertions(+), 39 deletions(-)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index f3c2a89a9550add9..17188fc4b1b32439 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -85,6 +85,18 @@ enum SCI_CLKS {
 	SCI_NUM_CLKS
 };
 
+/* Bit x set means sampling rate x + 1 is supported */
+#define SCI_SR(x)		BIT((x) - 1)
+#define SCI_SR_RANGE(x, y)	GENMASK((y) - 1, (x) - 1)
+
+#define min_sr(_port)		ffs((_port)->sampling_rate_mask)
+#define max_sr(_port)		fls((_port)->sampling_rate_mask)
+
+/* Iterate over all supported sampling rates, from high to low */
+#define for_each_sr(_sr, _port)						\
+	for ((_sr) = max_sr(_port); (_sr) >= min_sr(_port); (_sr)--)	\
+		if ((_port)->sampling_rate_mask & SCI_SR((_sr)))
+
 struct sci_port {
 	struct uart_port	port;
 
@@ -94,7 +106,7 @@ struct sci_port {
 	unsigned int		overrun_mask;
 	unsigned int		error_mask;
 	unsigned int		error_clear;
-	unsigned int		sampling_rate;
+	unsigned int		sampling_rate_mask;
 	resource_size_t		reg_size;
 
 	/* Break timer */
@@ -1931,21 +1943,13 @@ static int sci_sck_calc(struct sci_port *s, unsigned int bps,
 			unsigned int *srr)
 {
 	unsigned long freq = s->clk_rates[SCI_SCK];
-	unsigned int min_sr, max_sr, sr;
 	int err, min_err = INT_MAX;
+	unsigned int sr;
 
 	if (s->port.type != PORT_HSCIF)
 		freq *= 2;
-	if (s->sampling_rate) {
-		/* SCI(F) has a fixed sampling rate */
-		min_sr = max_sr = s->sampling_rate;
-	} else {
-		/* HSCIF has a variable 1/(8..32) sampling rate */
-		min_sr = 8;
-		max_sr = 32;
-	}
 
-	for (sr = max_sr; sr >= min_sr; sr--) {
+	for_each_sr(sr, s) {
 		err = DIV_ROUND_CLOSEST(freq, sr) - bps;
 		if (abs(err) >= abs(min_err))
 			continue;
@@ -1966,21 +1970,13 @@ static int sci_brg_calc(struct sci_port *s, unsigned int bps,
 			unsigned long freq, unsigned int *dlr,
 			unsigned int *srr)
 {
-	unsigned int min_sr, max_sr, sr, dl;
 	int err, min_err = INT_MAX;
+	unsigned int sr, dl;
 
 	if (s->port.type != PORT_HSCIF)
 		freq *= 2;
-	if (s->sampling_rate) {
-		/* SCIF has a fixed sampling rate */
-		min_sr = max_sr = s->sampling_rate;
-	} else {
-		/* HSCIF has a variable 1/(8..32) sampling rate */
-		min_sr = 8;
-		max_sr = 32;
-	}
 
-	for (sr = max_sr; sr >= min_sr; sr--) {
+	for_each_sr(sr, s) {
 		dl = DIV_ROUND_CLOSEST(freq, sr * bps);
 		dl = clamp(dl, 1U, 65535U);
 
@@ -2006,19 +2002,12 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
 			  unsigned int *brr, unsigned int *srr,
 			  unsigned int *cks)
 {
-	unsigned int min_sr, max_sr, sr, br, prediv, scrate, c;
 	unsigned long freq = s->clk_rates[SCI_FCK];
+	unsigned int sr, br, prediv, scrate, c;
 	int err, min_err = INT_MAX;
 
 	if (s->port.type != PORT_HSCIF)
 		freq *= 2;
-	if (s->sampling_rate) {
-		min_sr = max_sr = s->sampling_rate;
-	} else {
-		/* HSCIF has a variable sample rate */
-		min_sr = 8;
-		max_sr = 32;
-	}
 
 	/*
 	 * Find the combination of sample rate and clock select with the
@@ -2035,7 +2024,7 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
 	 *      (|D - 0.5| / N * (1 + F))|
 	 *  NOTE: Usually, treat D for 0.5, F is 0 by this calculation.
 	 */
-	for (sr = max_sr; sr >= min_sr; sr--) {
+	for_each_sr(sr, s) {
 		for (c = 0; c <= 3; c++) {
 			/* integerized formulas from HSCIF documentation */
 			prediv = sr * (1 << (2 * c + 1));
@@ -2129,8 +2118,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 	for (i = 0; i < SCI_NUM_CLKS; i++)
 		max_freq = max(max_freq, s->clk_rates[i]);
 
-	baud = uart_get_baud_rate(port, termios, old, 0,
-				  max_freq / max(s->sampling_rate, 8U));
+	baud = uart_get_baud_rate(port, termios, old, 0, max_freq / min_sr(s));
 	if (!baud)
 		goto done;
 
@@ -2562,37 +2550,37 @@ static int sci_init_single(struct platform_device *dev,
 		port->fifosize = 256;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCIFA_ORER;
-		sci_port->sampling_rate = 16;
+		sci_port->sampling_rate_mask = SCI_SR(16);
 		break;
 	case PORT_HSCIF:
 		port->fifosize = 128;
 		sci_port->overrun_reg = SCLSR;
 		sci_port->overrun_mask = SCLSR_ORER;
-		sci_port->sampling_rate = 0;
+		sci_port->sampling_rate_mask = SCI_SR_RANGE(8, 32);
 		break;
 	case PORT_SCIFA:
 		port->fifosize = 64;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCIFA_ORER;
-		sci_port->sampling_rate = 16;
+		sci_port->sampling_rate_mask = SCI_SR(16);
 		break;
 	case PORT_SCIF:
 		port->fifosize = 16;
 		if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) {
 			sci_port->overrun_reg = SCxSR;
 			sci_port->overrun_mask = SCIFA_ORER;
-			sci_port->sampling_rate = 16;
+			sci_port->sampling_rate_mask = SCI_SR(16);
 		} else {
 			sci_port->overrun_reg = SCLSR;
 			sci_port->overrun_mask = SCLSR_ORER;
-			sci_port->sampling_rate = 32;
+			sci_port->sampling_rate_mask = SCI_SR(32);
 		}
 		break;
 	default:
 		port->fifosize = 1;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCI_ORER;
-		sci_port->sampling_rate = 32;
+		sci_port->sampling_rate_mask = SCI_SR(32);
 		break;
 	}
 
@@ -2601,7 +2589,7 @@ static int sci_init_single(struct platform_device *dev,
 	 * data override the sampling rate for now.
 	 */
 	if (p->sampling_rate)
-		sci_port->sampling_rate = p->sampling_rate;
+		sci_port->sampling_rate_mask = SCI_SR(p->sampling_rate);
 
 	if (!early) {
 		ret = sci_init_clocks(sci_port, &dev->dev);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/5] serial: sh-sci: Add support for SCIFA/SCIFB variable sampling rates
  2016-01-04 13:45 ` Geert Uytterhoeven
@ 2016-01-04 13:45   ` Geert Uytterhoeven
  -1 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2016-01-04 13:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: Simon Horman, Magnus Damm, Yoshinori Sato, linux-serial,
	linux-sh, Geert Uytterhoeven

Add support for sparse variable sampling rates on SCIFA and SCIFB.
According to the datasheet, sampling rate 1/5 needs a small quirk to
avoid corrupting the first byte received.

This increases the range and accuracy of supported baud rates.
E.g. on r8a7791/koelsch:
  - Supports now 134, 150, and standard 500000-4000000 bps,
  - Perfect match for 134, 150, 500000, 1000000, 2000000, and 4000000
    bps,
  - Accuracy has increased for most standard bps values.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Tested on:
  - r8a7791/koelsch (Fully tested on SCIFA and SCIFB),
  - r8a7740/armadillo (Fully tested on SCIFA and SCIFB),
  - sh73a0/kzm9g (Fully tested on SCIFA only, no easy access to SCIFB),
  - r8a73a4/ape6evm (SCIFA/FTDI console at 460800 bps, no easy access to
    SCIFB).
---
 drivers/tty/serial/sh-sci.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 17188fc4b1b32439..4f638c480c5b270a 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -89,6 +89,10 @@ enum SCI_CLKS {
 #define SCI_SR(x)		BIT((x) - 1)
 #define SCI_SR_RANGE(x, y)	GENMASK((y) - 1, (x) - 1)
 
+#define SCI_SR_SCIFAB		SCI_SR(5) | SCI_SR(7) | SCI_SR(11) | \
+				SCI_SR(13) | SCI_SR(16) | SCI_SR(17) | \
+				SCI_SR(19) | SCI_SR(27)
+
 #define min_sr(_port)		ffs((_port)->sampling_rate_mask)
 #define max_sr(_port)		fls((_port)->sampling_rate_mask)
 
@@ -2206,6 +2210,17 @@ done:
 	uart_update_timeout(port, termios->c_cflag, baud);
 
 	if (best_clk >= 0) {
+		if (port->type = PORT_SCIFA || port->type = PORT_SCIFB)
+			switch (srr + 1) {
+			case 5:  smr_val |= SCSMR_SRC_5;  break;
+			case 7:  smr_val |= SCSMR_SRC_7;  break;
+			case 11: smr_val |= SCSMR_SRC_11; break;
+			case 13: smr_val |= SCSMR_SRC_13; break;
+			case 16: smr_val |= SCSMR_SRC_16; break;
+			case 17: smr_val |= SCSMR_SRC_17; break;
+			case 19: smr_val |= SCSMR_SRC_19; break;
+			case 27: smr_val |= SCSMR_SRC_27; break;
+			}
 		smr_val |= cks;
 		dev_dbg(port->dev,
 			 "SCR 0x%x SMR 0x%x BRR %u CKS 0x%x DL %u SRR %u\n",
@@ -2254,6 +2269,16 @@ done:
 	scr_val |= s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0);
 	dev_dbg(port->dev, "SCSCR 0x%x\n", scr_val);
 	serial_port_out(port, SCSCR, scr_val);
+	if ((srr + 1 = 5) &&
+	    (port->type = PORT_SCIFA || port->type = PORT_SCIFB)) {
+		/*
+		 * In asynchronous mode, when the sampling rate is 1/5, first
+		 * received data may become invalid on some SCIFA and SCIFB.
+		 * To avoid this problem wait more than 1 serial data time (1
+		 * bit time x serial data number) after setting SCSCR.RE = 1.
+		 */
+		udelay(DIV_ROUND_UP(10 * 1000000, baud));
+	}
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
 	/*
@@ -2550,7 +2575,7 @@ static int sci_init_single(struct platform_device *dev,
 		port->fifosize = 256;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCIFA_ORER;
-		sci_port->sampling_rate_mask = SCI_SR(16);
+		sci_port->sampling_rate_mask = SCI_SR_SCIFAB;
 		break;
 	case PORT_HSCIF:
 		port->fifosize = 128;
@@ -2562,7 +2587,7 @@ static int sci_init_single(struct platform_device *dev,
 		port->fifosize = 64;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCIFA_ORER;
-		sci_port->sampling_rate_mask = SCI_SR(16);
+		sci_port->sampling_rate_mask = SCI_SR_SCIFAB;
 		break;
 	case PORT_SCIF:
 		port->fifosize = 16;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/5] serial: sh-sci: Add support for SCIFA/SCIFB variable sampling rates
@ 2016-01-04 13:45   ` Geert Uytterhoeven
  0 siblings, 0 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 2016-01-04 13:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: Simon Horman, Magnus Damm, Yoshinori Sato, linux-serial,
	linux-sh, Geert Uytterhoeven

Add support for sparse variable sampling rates on SCIFA and SCIFB.
According to the datasheet, sampling rate 1/5 needs a small quirk to
avoid corrupting the first byte received.

This increases the range and accuracy of supported baud rates.
E.g. on r8a7791/koelsch:
  - Supports now 134, 150, and standard 500000-4000000 bps,
  - Perfect match for 134, 150, 500000, 1000000, 2000000, and 4000000
    bps,
  - Accuracy has increased for most standard bps values.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Tested on:
  - r8a7791/koelsch (Fully tested on SCIFA and SCIFB),
  - r8a7740/armadillo (Fully tested on SCIFA and SCIFB),
  - sh73a0/kzm9g (Fully tested on SCIFA only, no easy access to SCIFB),
  - r8a73a4/ape6evm (SCIFA/FTDI console at 460800 bps, no easy access to
    SCIFB).
---
 drivers/tty/serial/sh-sci.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 17188fc4b1b32439..4f638c480c5b270a 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -89,6 +89,10 @@ enum SCI_CLKS {
 #define SCI_SR(x)		BIT((x) - 1)
 #define SCI_SR_RANGE(x, y)	GENMASK((y) - 1, (x) - 1)
 
+#define SCI_SR_SCIFAB		SCI_SR(5) | SCI_SR(7) | SCI_SR(11) | \
+				SCI_SR(13) | SCI_SR(16) | SCI_SR(17) | \
+				SCI_SR(19) | SCI_SR(27)
+
 #define min_sr(_port)		ffs((_port)->sampling_rate_mask)
 #define max_sr(_port)		fls((_port)->sampling_rate_mask)
 
@@ -2206,6 +2210,17 @@ done:
 	uart_update_timeout(port, termios->c_cflag, baud);
 
 	if (best_clk >= 0) {
+		if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
+			switch (srr + 1) {
+			case 5:  smr_val |= SCSMR_SRC_5;  break;
+			case 7:  smr_val |= SCSMR_SRC_7;  break;
+			case 11: smr_val |= SCSMR_SRC_11; break;
+			case 13: smr_val |= SCSMR_SRC_13; break;
+			case 16: smr_val |= SCSMR_SRC_16; break;
+			case 17: smr_val |= SCSMR_SRC_17; break;
+			case 19: smr_val |= SCSMR_SRC_19; break;
+			case 27: smr_val |= SCSMR_SRC_27; break;
+			}
 		smr_val |= cks;
 		dev_dbg(port->dev,
 			 "SCR 0x%x SMR 0x%x BRR %u CKS 0x%x DL %u SRR %u\n",
@@ -2254,6 +2269,16 @@ done:
 	scr_val |= s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0);
 	dev_dbg(port->dev, "SCSCR 0x%x\n", scr_val);
 	serial_port_out(port, SCSCR, scr_val);
+	if ((srr + 1 == 5) &&
+	    (port->type == PORT_SCIFA || port->type == PORT_SCIFB)) {
+		/*
+		 * In asynchronous mode, when the sampling rate is 1/5, first
+		 * received data may become invalid on some SCIFA and SCIFB.
+		 * To avoid this problem wait more than 1 serial data time (1
+		 * bit time x serial data number) after setting SCSCR.RE = 1.
+		 */
+		udelay(DIV_ROUND_UP(10 * 1000000, baud));
+	}
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
 	/*
@@ -2550,7 +2575,7 @@ static int sci_init_single(struct platform_device *dev,
 		port->fifosize = 256;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCIFA_ORER;
-		sci_port->sampling_rate_mask = SCI_SR(16);
+		sci_port->sampling_rate_mask = SCI_SR_SCIFAB;
 		break;
 	case PORT_HSCIF:
 		port->fifosize = 128;
@@ -2562,7 +2587,7 @@ static int sci_init_single(struct platform_device *dev,
 		port->fifosize = 64;
 		sci_port->overrun_reg = SCxSR;
 		sci_port->overrun_mask = SCIFA_ORER;
-		sci_port->sampling_rate_mask = SCI_SR(16);
+		sci_port->sampling_rate_mask = SCI_SR_SCIFAB;
 		break;
 	case PORT_SCIF:
 		port->fifosize = 16;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2016-01-04 13:45 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-04 13:45 [PATCH 0/5] serial: sh-sci: Add support for SCIFA/SCIFB variable sampling rates Geert Uytterhoeven
2016-01-04 13:45 ` Geert Uytterhoeven
2016-01-04 13:45 ` [PATCH 1/5] serial: sh-sci: Add more Serial Mode Register documentation Geert Uytterhoeven
2016-01-04 13:45   ` Geert Uytterhoeven
2016-01-04 13:45 ` [PATCH 2/5] serial: sh-sci: Preserve SCIFA/SCIFB bit rate config for serial console Geert Uytterhoeven
2016-01-04 13:45   ` Geert Uytterhoeven
2016-01-04 13:45 ` [PATCH 3/5] serial: sh-sci: Use premultiplier to handle half sampling rate Geert Uytterhoeven
2016-01-04 13:45   ` Geert Uytterhoeven
2016-01-04 13:45 ` [PATCH 4/5] serial: sh-sci: Use a bitmask to indicate supported sampling rates Geert Uytterhoeven
2016-01-04 13:45   ` Geert Uytterhoeven
2016-01-04 13:45 ` [PATCH 5/5] serial: sh-sci: Add support for SCIFA/SCIFB variable " Geert Uytterhoeven
2016-01-04 13:45   ` Geert Uytterhoeven

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.