diff options
author | Geert Uytterhoeven <geert+renesas@glider.be> | 2016-01-04 14:45:21 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-02-07 07:54:55 +0100 |
commit | 69eee8e9c876eb412282a3b45d998e989d3a8e93 (patch) | |
tree | c4cbb03d3b6716e4b8a0049a3c467c464cdb7f43 /drivers/tty/serial/sh-sci.c | |
parent | serial: sh-sci: Use premultiplier to handle half sampling rate (diff) | |
download | linux-69eee8e9c876eb412282a3b45d998e989d3a8e93.tar.xz linux-69eee8e9c876eb412282a3b45d998e989d3a8e93.zip |
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: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/sh-sci.c')
-rw-r--r-- | drivers/tty/serial/sh-sci.c | 66 |
1 files changed, 27 insertions, 39 deletions
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 70f005f37de0..dbf488b9ae27 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -84,6 +84,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; @@ -93,7 +105,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 */ @@ -1904,21 +1916,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; @@ -1939,21 +1943,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); @@ -1979,19 +1975,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 @@ -2008,7 +1997,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)); @@ -2102,8 +2091,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; @@ -2535,37 +2523,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; } @@ -2574,7 +2562,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); |