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>
This commit is contained in:
Родитель
7b5c0c08f5
Коммит
69eee8e9c8
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче