Commit 69eee8e9 authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Greg Kroah-Hartman

serial: sh-sci: Use a bitmask to indicate supported sampling rates

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: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7b5c0c08
...@@ -84,6 +84,18 @@ enum SCI_CLKS { ...@@ -84,6 +84,18 @@ enum SCI_CLKS {
SCI_NUM_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 sci_port {
struct uart_port port; struct uart_port port;
...@@ -93,7 +105,7 @@ struct sci_port { ...@@ -93,7 +105,7 @@ struct sci_port {
unsigned int overrun_mask; unsigned int overrun_mask;
unsigned int error_mask; unsigned int error_mask;
unsigned int error_clear; unsigned int error_clear;
unsigned int sampling_rate; unsigned int sampling_rate_mask;
resource_size_t reg_size; resource_size_t reg_size;
/* Break timer */ /* Break timer */
...@@ -1904,21 +1916,13 @@ static int sci_sck_calc(struct sci_port *s, unsigned int bps, ...@@ -1904,21 +1916,13 @@ static int sci_sck_calc(struct sci_port *s, unsigned int bps,
unsigned int *srr) unsigned int *srr)
{ {
unsigned long freq = s->clk_rates[SCI_SCK]; unsigned long freq = s->clk_rates[SCI_SCK];
unsigned int min_sr, max_sr, sr;
int err, min_err = INT_MAX; int err, min_err = INT_MAX;
unsigned int sr;
if (s->port.type != PORT_HSCIF) if (s->port.type != PORT_HSCIF)
freq *= 2; 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; err = DIV_ROUND_CLOSEST(freq, sr) - bps;
if (abs(err) >= abs(min_err)) if (abs(err) >= abs(min_err))
continue; continue;
...@@ -1939,21 +1943,13 @@ static int sci_brg_calc(struct sci_port *s, unsigned int bps, ...@@ -1939,21 +1943,13 @@ static int sci_brg_calc(struct sci_port *s, unsigned int bps,
unsigned long freq, unsigned int *dlr, unsigned long freq, unsigned int *dlr,
unsigned int *srr) unsigned int *srr)
{ {
unsigned int min_sr, max_sr, sr, dl;
int err, min_err = INT_MAX; int err, min_err = INT_MAX;
unsigned int sr, dl;
if (s->port.type != PORT_HSCIF) if (s->port.type != PORT_HSCIF)
freq *= 2; 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 = DIV_ROUND_CLOSEST(freq, sr * bps);
dl = clamp(dl, 1U, 65535U); dl = clamp(dl, 1U, 65535U);
...@@ -1979,19 +1975,12 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, ...@@ -1979,19 +1975,12 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
unsigned int *brr, unsigned int *srr, unsigned int *brr, unsigned int *srr,
unsigned int *cks) unsigned int *cks)
{ {
unsigned int min_sr, max_sr, sr, br, prediv, scrate, c;
unsigned long freq = s->clk_rates[SCI_FCK]; unsigned long freq = s->clk_rates[SCI_FCK];
unsigned int sr, br, prediv, scrate, c;
int err, min_err = INT_MAX; int err, min_err = INT_MAX;
if (s->port.type != PORT_HSCIF) if (s->port.type != PORT_HSCIF)
freq *= 2; 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 * Find the combination of sample rate and clock select with the
...@@ -2008,7 +1997,7 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, ...@@ -2008,7 +1997,7 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
* (|D - 0.5| / N * (1 + F))| * (|D - 0.5| / N * (1 + F))|
* NOTE: Usually, treat D for 0.5, F is 0 by this calculation. * 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++) { for (c = 0; c <= 3; c++) {
/* integerized formulas from HSCIF documentation */ /* integerized formulas from HSCIF documentation */
prediv = sr * (1 << (2 * c + 1)); prediv = sr * (1 << (2 * c + 1));
...@@ -2102,8 +2091,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -2102,8 +2091,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
for (i = 0; i < SCI_NUM_CLKS; i++) for (i = 0; i < SCI_NUM_CLKS; i++)
max_freq = max(max_freq, s->clk_rates[i]); max_freq = max(max_freq, s->clk_rates[i]);
baud = uart_get_baud_rate(port, termios, old, 0, baud = uart_get_baud_rate(port, termios, old, 0, max_freq / min_sr(s));
max_freq / max(s->sampling_rate, 8U));
if (!baud) if (!baud)
goto done; goto done;
...@@ -2535,37 +2523,37 @@ static int sci_init_single(struct platform_device *dev, ...@@ -2535,37 +2523,37 @@ static int sci_init_single(struct platform_device *dev,
port->fifosize = 256; port->fifosize = 256;
sci_port->overrun_reg = SCxSR; sci_port->overrun_reg = SCxSR;
sci_port->overrun_mask = SCIFA_ORER; sci_port->overrun_mask = SCIFA_ORER;
sci_port->sampling_rate = 16; sci_port->sampling_rate_mask = SCI_SR(16);
break; break;
case PORT_HSCIF: case PORT_HSCIF:
port->fifosize = 128; port->fifosize = 128;
sci_port->overrun_reg = SCLSR; sci_port->overrun_reg = SCLSR;
sci_port->overrun_mask = SCLSR_ORER; sci_port->overrun_mask = SCLSR_ORER;
sci_port->sampling_rate = 0; sci_port->sampling_rate_mask = SCI_SR_RANGE(8, 32);
break; break;
case PORT_SCIFA: case PORT_SCIFA:
port->fifosize = 64; port->fifosize = 64;
sci_port->overrun_reg = SCxSR; sci_port->overrun_reg = SCxSR;
sci_port->overrun_mask = SCIFA_ORER; sci_port->overrun_mask = SCIFA_ORER;
sci_port->sampling_rate = 16; sci_port->sampling_rate_mask = SCI_SR(16);
break; break;
case PORT_SCIF: case PORT_SCIF:
port->fifosize = 16; port->fifosize = 16;
if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) { if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) {
sci_port->overrun_reg = SCxSR; sci_port->overrun_reg = SCxSR;
sci_port->overrun_mask = SCIFA_ORER; sci_port->overrun_mask = SCIFA_ORER;
sci_port->sampling_rate = 16; sci_port->sampling_rate_mask = SCI_SR(16);
} else { } else {
sci_port->overrun_reg = SCLSR; sci_port->overrun_reg = SCLSR;
sci_port->overrun_mask = SCLSR_ORER; sci_port->overrun_mask = SCLSR_ORER;
sci_port->sampling_rate = 32; sci_port->sampling_rate_mask = SCI_SR(32);
} }
break; break;
default: default:
port->fifosize = 1; port->fifosize = 1;
sci_port->overrun_reg = SCxSR; sci_port->overrun_reg = SCxSR;
sci_port->overrun_mask = SCI_ORER; sci_port->overrun_mask = SCI_ORER;
sci_port->sampling_rate = 32; sci_port->sampling_rate_mask = SCI_SR(32);
break; break;
} }
...@@ -2574,7 +2562,7 @@ static int sci_init_single(struct platform_device *dev, ...@@ -2574,7 +2562,7 @@ static int sci_init_single(struct platform_device *dev,
* data override the sampling rate for now. * data override the sampling rate for now.
*/ */
if (p->sampling_rate) if (p->sampling_rate)
sci_port->sampling_rate = p->sampling_rate; sci_port->sampling_rate_mask = SCI_SR(p->sampling_rate);
if (!early) { if (!early) {
ret = sci_init_clocks(sci_port, &dev->dev); ret = sci_init_clocks(sci_port, &dev->dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment