linux-sh.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Simon Horman <horms@verge.net.au>,
	Magnus Damm <magnus.damm@gmail.com>,
	Yoshinori Sato <ysato@users.sourceforge.jp>,
	linux-serial@vger.kernel.org, linux-sh@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH 18/25] serial: sh-sci: Prepare for multiple clocks and baud rate generators
Date: Thu, 19 Nov 2015 21:04:02 +0000	[thread overview]
Message-ID: <3383903.1R72kZGx62@avalon> (raw)
In-Reply-To: <1447958344-836-19-git-send-email-geert+renesas@glider.be>

Hi Geert,

Thank you for the patch.

On Thursday 19 November 2015 19:38:57 Geert Uytterhoeven wrote:
> Refactor the clock and baud rate parameter code to ease adding support
> for multiple clocks and baud rate generators later.
> sci_scbrr_calc() now returns the bit rate error, so it can be compared
> to the bit rate error for other baud rate generators.
> 
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
>  drivers/tty/serial/sh-sci.c | 176 +++++++++++++++++++++++++++--------------
>  1 file changed, 120 insertions(+), 56 deletions(-)
> 
> diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
> index 726c96d5a511c222..12800e52f41953dc 100644
> --- a/drivers/tty/serial/sh-sci.c
> +++ b/drivers/tty/serial/sh-sci.c
> @@ -2,6 +2,7 @@
>   * SuperH on-chip serial module support.  (SCI with no FIFO / with FIFO)
>   *
>   *  Copyright (C) 2002 - 2011  Paul Mundt
> + *  Copyright (C) 2015 Glider bvba
>   *  Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007).
> *
>   * based off of the old drivers/char/sh-sci.c by:
> @@ -76,6 +77,11 @@ enum {
>  	((port)->irqs[SCIx_ERI_IRQ] &&	\
>  	 ((port)->irqs[SCIx_RXI_IRQ] < 0))
> 
> +enum SCI_CLKS {
> +	SCI_FCK,		/* Functional Clock */
> +	SCI_NUM_CLKS
> +};
> +
>  struct sci_port {
>  	struct uart_port	port;
> 
> @@ -92,8 +98,9 @@ struct sci_port {
>  	struct timer_list	break_timer;
>  	int			break_flag;
> 
> -	/* Function clock */
> -	struct clk		*fclk;
> +	/* Clocks */
> +	struct clk		*clks[SCI_NUM_CLKS];
> +	unsigned long		clk_rates[SCI_NUM_CLKS];
> 
>  	int			irqs[SCIx_NR_IRQS];
>  	char			*irqstr[SCIx_NR_IRQS];
> @@ -496,17 +503,24 @@ static int sci_probe_regmap(struct plat_sci_port *cfg)
> 
>  static void sci_port_enable(struct sci_port *sci_port)
>  {
> +	unsigned int i;
> +
>  	if (!sci_port->port.dev)
>  		return;
> 
>  	pm_runtime_get_sync(sci_port->port.dev);
> 
> -	clk_prepare_enable(sci_port->fclk);
> -	sci_port->port.uartclk = clk_get_rate(sci_port->fclk);
> +	for (i = 0; i < SCI_NUM_CLKS; i++) {
> +		clk_prepare_enable(sci_port->clks[i]);
> +		sci_port->clk_rates[i] = clk_get_rate(sci_port->clks[i]);
> +	}
> +	sci_port->port.uartclk = sci_port->clk_rates[SCI_FCK];
>  }
> 
>  static void sci_port_disable(struct sci_port *sci_port)
>  {
> +	unsigned int i;
> +
>  	if (!sci_port->port.dev)
>  		return;
> 
> @@ -518,7 +532,8 @@ static void sci_port_disable(struct sci_port *sci_port)
>  	del_timer_sync(&sci_port->break_timer);
>  	sci_port->break_flag = 0;
> 
> -	clk_disable_unprepare(sci_port->fclk);
> +	for (i = SCI_NUM_CLKS; i-- > 0; )
> +		clk_disable_unprepare(sci_port->clks[i]);
> 
>  	pm_runtime_put_sync(sci_port->port.dev);
>  }
> @@ -1657,6 +1672,7 @@ static int sci_notifier(struct notifier_block *self,
>  {
>  	struct sci_port *sci_port;
>  	unsigned long flags;
> +	unsigned int i;
> 
>  	sci_port = container_of(self, struct sci_port, freq_transition);
> 
> @@ -1664,7 +1680,9 @@ static int sci_notifier(struct notifier_block *self,
>  		struct uart_port *port = &sci_port->port;
> 
>  		spin_lock_irqsave(&port->lock, flags);
> -		port->uartclk = clk_get_rate(sci_port->fclk);
> +		for (i = 0; i < SCI_NUM_CLKS; i++)
> +			sci_port->clk_rates[i] > +				clk_get_rate(sci_port->clks[i]);
>  		spin_unlock_irqrestore(&port->lock, flags);
>  	}
> 
> @@ -1907,11 +1925,12 @@ static void sci_shutdown(struct uart_port *port)
>  }
> 
>  /* calculate sample rate, BRR, and clock select */
> -static void sci_scbrr_calc(struct sci_port *s, unsigned int bps,
> -			   unsigned long freq, int *brr, unsigned int *srr,
> -			   unsigned int *cks)
> +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, a, b, c;
> +	unsigned long freq = s->clk_rates[SCI_FCK];
>  	int err, min_err = INT_MAX;
> 
>  	if (s->sampling_rate) {
> @@ -1963,6 +1982,7 @@ static void sci_scbrr_calc(struct sci_port *s,
> unsigned int bps,
> 
>  	dev_dbg(s->port.dev, "BRR: %u%+d bps using N %u SR %u cks %u\n", bps,
>  		min_err, *brr, *srr + 1, *cks);
> +	return min_err;
>  }
> 
>  static void sci_reset(struct uart_port *port)
> @@ -1984,11 +2004,14 @@ 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 brr = 255, cks = 0, srr = 15;
> +	unsigned int brr1 = 255, cks1 = 0, srr1 = 15;
>  	struct sci_port *s = to_sci_port(port);
>  	const struct plat_sci_reg *reg;
> -	unsigned int baud, smr_val = 0, max_baud, cks = 0;
> -	int t = -1;
> -	unsigned int srr = 15;
> +	int min_err = INT_MAX, err;
> +	unsigned long max_freq = 0;
> +	int best_clk = -1;
> 
>  	if ((termios->c_cflag & CSIZE) = CS7)
>  		smr_val |= SCSMR_CHR;
> @@ -2007,35 +2030,59 @@ static void sci_set_termios(struct uart_port *port,
> struct ktermios *termios, * that the previous boot loader has enabled
> required clocks and * setup the baud rate generator hardware for us
> already.
>  	 */
> -	if (port->uartclk)
> -		max_baud = port->uartclk / max(s->sampling_rate, 8U);
> -	else
> -		max_baud = 115200;
> +	if (!port->uartclk) {
> +		baud = uart_get_baud_rate(port, termios, old, 0, 115200);
> +		goto done;
> +	}
> 
> -	baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
> -	if (likely(baud && port->uartclk))
> -		sci_scbrr_calc(s, baud, port->uartclk, &t, &srr, &cks);
> +	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));
> +	if (!baud)
> +		goto done;
> +
> +	/* Functional Clock and standard Bit Rate Register */
> +	err = sci_scbrr_calc(s, baud, &brr1, &srr1, &cks1);
> +	if (abs(err) < abs(min_err)) {
> +		best_clk = SCI_FCK;
> +		min_err = err;
> +		brr = brr1;
> +		srr = srr1;
> +		cks = cks1;
> +	}
> +
> +done:
> +	if (best_clk >= 0)
> +		dev_dbg(port->dev, "Using clk %pC for %u%+d bps\n",
> +			s->clks[best_clk], baud, min_err);
> 
>  	sci_port_enable(s);
> 
>  	sci_reset(port);
> 
> -	smr_val |= serial_port_in(port, SCSMR) & SCSMR_CKS;
> -
>  	uart_update_timeout(port, termios->c_cflag, baud);
> 
> -	dev_dbg(port->dev, "%s: SMR %x, cks %x, t %x, SCSCR %x\n",
> -		__func__, smr_val, cks, t, s->cfg->scscr);
> -
> -	if (t >= 0) {
> -		serial_port_out(port, SCSMR, (smr_val & ~SCSMR_CKS) | cks);
> -		serial_port_out(port, SCBRR, t);
> -		reg = sci_getreg(port, HSSRR);
> -		if (reg->size)
> +	if (best_clk >= 0) {
> +		smr_val |= cks;
> +		dev_dbg(port->dev, "SMR 0x%x BRR %u SRR %u\n", smr_val, brr,
> +			srr);
> +		serial_port_out(port, SCSMR, smr_val);
> +		serial_port_out(port, SCBRR, brr);
> +		if (sci_getreg(port, HSSRR)->size)
>  			serial_port_out(port, HSSRR, srr | HSCIF_SRE);
> -		udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
> -	} else
> +
> +		/* Wait one bit interval */
> +		udelay((1000000 + (baud - 1)) / baud);
> +	} 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;
> +		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);
> +	}
> 
>  	sci_init_pins(port, termios->c_cflag);
> 
> @@ -2060,7 +2107,9 @@ static void sci_set_termios(struct uart_port *port,
> struct ktermios *termios, serial_port_out(port, SCFCR, ctrl);
>  	}
> 
> -	serial_port_out(port, SCSCR, s->cfg->scscr);
> +	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);
> 
>  #ifdef CONFIG_SERIAL_SH_SCI_DMA
>  	/*
> @@ -2252,33 +2301,48 @@ static struct uart_ops sci_uart_ops = {
> 
>  static int sci_init_clocks(struct sci_port *sci_port, struct device *dev)
>  {
> -	/* Get the SCI functional clock. It's called "fck" on ARM. */
> -	sci_port->fclk = devm_clk_get(dev, "fck");
> -	if (PTR_ERR(sci_port->fclk) = -EPROBE_DEFER)
> -		return -EPROBE_DEFER;
> -	if (!IS_ERR(sci_port->fclk))
> -		return 0;
> +	const char *clk_names[] = {
> +		[SCI_FCK] = "fck",
> +	};
> +	struct clk *clk;
> +	unsigned int i;
> 
> -	/*
> -	 * But it used to be called "sci_ick", and we need to maintain DT
> -	 * backward compatibility.
> -	 */
> -	sci_port->fclk = devm_clk_get(dev, "sci_ick");
> -	if (PTR_ERR(sci_port->fclk) = -EPROBE_DEFER)
> -		return -EPROBE_DEFER;
> -	if (!IS_ERR(sci_port->fclk))
> -		return 0;
> +	for (i = 0; i < SCI_NUM_CLKS; i++) {
> +		clk = devm_clk_get(dev, clk_names[i]);
> +		if (PTR_ERR(clk) = -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> 
> -	/*
> -	 * Not all SH platforms declare a clock lookup entry for SCI devices,
> -	 * in which case we need to get the global "peripheral_clk" clock.
> -	 */
> -	sci_port->fclk = devm_clk_get(dev, "peripheral_clk");
> -	if (!IS_ERR(sci_port->fclk))
> -		return 0;
> +		if (IS_ERR(clk) && i = SCI_FCK) {
> +			/*
> +			 * "fck" used to be called "sci_ick", and we need to
> +			 * maintain DT backward compatibility.
> +			 */
> +			clk = devm_clk_get(dev, "sci_ick");
> +			if (PTR_ERR(clk) = -EPROBE_DEFER)
> +				return -EPROBE_DEFER;
> +
> +			if (!IS_ERR(clk))
> +				goto found;
> +
> +			/*
> +			 * Not all SH platforms declare a clock lookup entry
> +			 * for SCI devices, in which case we need to get the
> +			 * global "peripheral_clk" clock.
> +			 */
> +			clk = devm_clk_get(dev, "peripheral_clk");
> +			if (!IS_ERR(clk))
> +				goto found;
> +
> +			dev_err(dev, "failed to get functional clock\n");
> +			return PTR_ERR(clk);
> +		}
> 
> -	dev_err(dev, "failed to get functional clock\n");
> -	return PTR_ERR(sci_port->fclk);
> +found:
> +		if (!IS_ERR(clk))
> +			dev_dbg(dev, "clk %u is %pC rate %pCr\n", i, clk, clk);
> +		sci_port->clks[i] = IS_ERR(clk) ? NULL : clk;

Isn't it an issue that we can't tell apart the case where there is no clock 
specified in DT and the case where we can't get the clock due to another error 
?

> +	}
> +	return 0;
>  }
> 
>  static int sci_init_single(struct platform_device *dev,

-- 
Regards,

Laurent Pinchart


  reply	other threads:[~2015-11-19 21:04 UTC|newest]

Thread overview: 72+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-19 18:38 [PATCH 00/25] serial: sh-sci: Add external clock and BRG Support Geert Uytterhoeven
     [not found] ` <1447958344-836-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
2015-11-19 18:38   ` [PATCH 01/25] serial: sh-sci: Update DT binding documentation for external clock input Geert Uytterhoeven
     [not found]     ` <1447958344-836-2-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
2015-11-19 20:19       ` Laurent Pinchart
2015-11-19 20:27         ` Laurent Pinchart
2015-11-19 20:39           ` Geert Uytterhoeven
     [not found]             ` <CAMuHMdUnT2zCnj9QBVgxJaHV2fk5iuc7cxq=fh+fVTv3toOVaQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-11-19 21:17               ` Laurent Pinchart
2015-11-20  8:00                 ` Geert Uytterhoeven
2015-11-19 20:33         ` Geert Uytterhoeven
     [not found]           ` <CAMuHMdX4ToefbBLR6o2AMuzCMoKcYo9XRZOzHJzgtQn552vmNg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-12-21 14:20             ` Geert Uytterhoeven
2015-11-19 18:38   ` [PATCH 02/25] serial: sh-sci: Update DT binding documentation for BRG support Geert Uytterhoeven
2015-11-19 20:26     ` Laurent Pinchart
2015-11-19 20:44       ` Geert Uytterhoeven
     [not found]         ` <CAMuHMdWHbc1kK7MipyZ_M_C6gPyPqvC4H35eZLXQezjbQNK2Jw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-11-19 21:13           ` Laurent Pinchart
2015-11-20  7:58             ` Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 03/25] serial: sh-sci: Drop useless check for zero sampling_rate Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 04/25] serial: sh-sci: Grammar s/Get ... for/Get ... from/ Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 05/25] serial: sh-sci: Drop unused frame_len parameter for sci_baud_calc_hscif() Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 06/25] serial: sh-sci: Don't overwrite clock selection in serial_console_write() Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 07/25] serial: sh-sci: Convert from clk_get() to devm_clk_get() Geert Uytterhoeven
2015-11-19 20:38   ` Laurent Pinchart
2015-12-10 12:30     ` Geert Uytterhoeven
2015-12-13 19:39       ` Laurent Pinchart
2015-12-14 10:34         ` Geert Uytterhoeven
2015-12-14 15:47           ` Laurent Pinchart
2015-11-19 18:38 ` [PATCH 08/25] serial: sh-sci: Make unsigned values in sci_baud_calc_hscif() unsigned Geert Uytterhoeven
2015-11-19 20:36   ` Laurent Pinchart
2015-11-19 20:49     ` Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 09/25] serial: sh-sci: Avoid overflow in sci_baud_calc_hscif() Geert Uytterhoeven
2015-11-19 20:37   ` Laurent Pinchart
2015-11-19 20:50     ` Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 10/25] serial: sh-sci: Improve bit rate error calculation for HSCIF Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 11/25] serial: sh-sci: Avoid calculating the receive margin " Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 12/25] serial: sh-sci: Merge sci_scbrr_calc() and sci_baud_calc_hscif() Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 13/25] serial: sh-sci: Take into account sampling rate for max baud rate Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 14/25] serial: sh-sci: Add BRG register definitions Geert Uytterhoeven
2015-11-19 20:45   ` Laurent Pinchart
2015-11-19 18:38 ` [PATCH 15/25] serial: sh-sci: Replace struct sci_port_info by type/regtype encoding Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 16/25] serial: sh-sci: Correct SCIF type on RZ/A1H Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 17/25] serial: sh-sci: Correct SCIF type on R-Car for BRG Geert Uytterhoeven
2015-11-19 20:55   ` Laurent Pinchart
2015-11-20  7:46     ` Geert Uytterhoeven
2015-11-20 14:52       ` Laurent Pinchart
2015-11-20 15:30         ` Geert Uytterhoeven
2015-11-20 15:33           ` Laurent Pinchart
2015-12-10  9:21             ` Geert Uytterhoeven
2015-12-11  1:12               ` Simon Horman
2015-12-13 19:18               ` Laurent Pinchart
2015-11-19 18:38 ` [PATCH 18/25] serial: sh-sci: Prepare for multiple clocks and baud rate generators Geert Uytterhoeven
2015-11-19 21:04   ` Laurent Pinchart [this message]
2015-11-20  7:52     ` Geert Uytterhoeven
2015-11-20 14:47       ` Laurent Pinchart
2015-11-20 15:17         ` Geert Uytterhoeven
2015-11-20 15:31           ` Laurent Pinchart
2015-11-19 18:38 ` [PATCH 19/25] serial: sh-sci: Add support for optional external (H)SCK input Geert Uytterhoeven
2015-11-19 18:38 ` [PATCH 20/25] serial: sh-sci: Add support for optional BRG on (H)SCIF Geert Uytterhoeven
2015-11-19 18:39 ` [PATCH 21/25] ARM: shmobile: r8a7791 dtsi: Add BRG support for (H)SCIF Geert Uytterhoeven
2015-11-19 18:39 ` [PATCH 22/25] ARM: shmobile: koelsch dts: Enable SCIF_CLK frequency and pins Geert Uytterhoeven
2015-11-19 18:39 ` [PATCH 23/25] arm64: renesas: r8a7795 dtsi: Add BRG support for (H)SCIF Geert Uytterhoeven
2015-11-19 21:07   ` Laurent Pinchart
2015-11-20  8:17     ` Geert Uytterhoeven
2015-11-19 18:39 ` [PATCH 24/25] arm64: renesas: salvator-x dts: Enable SCIF_CLK frequency and pins Geert Uytterhoeven
2015-11-19 18:39 ` [PATCH 25/25] sh: sh7734: Correct SCIF type for BRG Geert Uytterhoeven
2015-11-19 21:08 ` [PATCH 00/25] serial: sh-sci: Add external clock and BRG Support Laurent Pinchart
2015-11-20  8:22   ` Geert Uytterhoeven
2015-11-20  8:58     ` Laurent Pinchart
2015-11-20  9:07       ` Geert Uytterhoeven
2015-11-20 14:50         ` Laurent Pinchart
2015-11-20 15:31           ` Geert Uytterhoeven
2015-11-20  9:09 ` Geert Uytterhoeven
2015-12-13  6:43   ` Greg Kroah-Hartman
2015-12-13  9:09     ` Geert Uytterhoeven
2015-11-24  2:43 ` Simon Horman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3383903.1R72kZGx62@avalon \
    --to=laurent.pinchart@ideasonboard.com \
    --cc=geert+renesas@glider.be \
    --cc=gregkh@linuxfoundation.org \
    --cc=horms@verge.net.au \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=linux-sh@vger.kernel.org \
    --cc=magnus.damm@gmail.com \
    --cc=ysato@users.sourceforge.jp \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).