Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+27 −39
Original line number Diff line number Diff line
@@ -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);