From a9ec81f4ed5c05dbbc671e5fa39de0540eb0495f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 14 Sep 2015 15:14:23 +0300 Subject: serial: sh-sci: Drop the interface clock As no platform defines an interface clock the SCI driver always falls back to a clock named "peripheral_clk". - On SH platforms that clock is the base clock for the SCI functional clock and has the same frequency, - On ARM platforms that clock doesn't exist, and clk_get() will return the default clock for the device. We can thus make the functional clock mandatory and drop the interface clock. EPROBE_DEFER is handled for clocks that may be referenced from DT (i.e. "fck", and the deprecated "sci_ick"). Cc: devicetree@vger.kernel.org Signed-off-by: Laurent Pinchart Acked-by: Simon Horman [geert: Handle EPROBE_DEFER, reformat description, break long comment line] Signed-off-by: Geert Uytterhoeven Acked-by: Rob Herring Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 64 +++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 23 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 960e50a97558..cc6fa55231ba 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -92,8 +92,6 @@ struct sci_port { struct timer_list break_timer; int break_flag; - /* Interface clock */ - struct clk *iclk; /* Function clock */ struct clk *fclk; @@ -457,9 +455,8 @@ static void sci_port_enable(struct sci_port *sci_port) pm_runtime_get_sync(sci_port->port.dev); - clk_prepare_enable(sci_port->iclk); - sci_port->port.uartclk = clk_get_rate(sci_port->iclk); clk_prepare_enable(sci_port->fclk); + sci_port->port.uartclk = clk_get_rate(sci_port->fclk); } static void sci_port_disable(struct sci_port *sci_port) @@ -476,7 +473,6 @@ static void sci_port_disable(struct sci_port *sci_port) sci_port->break_flag = 0; clk_disable_unprepare(sci_port->fclk); - clk_disable_unprepare(sci_port->iclk); pm_runtime_put_sync(sci_port->port.dev); } @@ -1622,7 +1618,7 @@ 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->iclk); + port->uartclk = clk_get_rate(sci_port->fclk); spin_unlock_irqrestore(&port->lock, flags); } @@ -2241,6 +2237,42 @@ static struct uart_ops sci_uart_ops = { #endif }; +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 = clk_get(dev, "fck"); + if (PTR_ERR(sci_port->fclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (!IS_ERR(sci_port->fclk)) + return 0; + + /* + * But it used to be called "sci_ick", and we need to maintain DT + * backward compatibility. + */ + sci_port->fclk = clk_get(dev, "sci_ick"); + if (PTR_ERR(sci_port->fclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (!IS_ERR(sci_port->fclk)) + return 0; + + /* SH has historically named the clock "sci_fck". */ + sci_port->fclk = clk_get(dev, "sci_fck"); + if (!IS_ERR(sci_port->fclk)) + return 0; + + /* + * 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 = clk_get(dev, "peripheral_clk"); + if (!IS_ERR(sci_port->fclk)) + return 0; + + dev_err(dev, "failed to get functional clock\n"); + return PTR_ERR(sci_port->fclk); +} + static int sci_init_single(struct platform_device *dev, struct sci_port *sci_port, unsigned int index, struct plat_sci_port *p, bool early) @@ -2333,22 +2365,9 @@ static int sci_init_single(struct platform_device *dev, sci_port->sampling_rate = p->sampling_rate; if (!early) { - sci_port->iclk = clk_get(&dev->dev, "sci_ick"); - if (IS_ERR(sci_port->iclk)) { - sci_port->iclk = clk_get(&dev->dev, "peripheral_clk"); - if (IS_ERR(sci_port->iclk)) { - dev_err(&dev->dev, "can't get iclk\n"); - return PTR_ERR(sci_port->iclk); - } - } - - /* - * The function clock is optional, ignore it if we can't - * find it. - */ - sci_port->fclk = clk_get(&dev->dev, "sci_fck"); - if (IS_ERR(sci_port->fclk)) - sci_port->fclk = NULL; + ret = sci_init_clocks(sci_port, &dev->dev); + if (ret < 0) + return ret; port->dev = &dev->dev; @@ -2405,7 +2424,6 @@ static int sci_init_single(struct platform_device *dev, static void sci_cleanup_single(struct sci_port *port) { - clk_put(port->iclk); clk_put(port->fclk); pm_runtime_disable(port->port.dev); -- cgit v1.2.3 From dcafbb47bdfde32b9f3c275aa4b435c120d02f15 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 3 Nov 2015 18:14:10 +0100 Subject: serial: sh-sci: Drop useless check for zero sampling_rate sci_port.sampling_rate is always non-zero, except for HSCIF, which uses sci_baud_calc_hscif() instead of sci_scbrr_calc(). Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index cc6fa55231ba..dfee7a2f51f1 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1863,13 +1863,7 @@ static void sci_shutdown(struct uart_port *port) static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, unsigned long freq) { - if (s->sampling_rate) - return DIV_ROUND_CLOSEST(freq, s->sampling_rate * bps) - 1; - - /* Warn, but use a safe default */ - WARN_ON(1); - - return ((freq + 16 * bps) / (32 * bps) - 1); + return DIV_ROUND_CLOSEST(freq, s->sampling_rate * bps) - 1; } /* calculate frame length from SMR */ -- cgit v1.2.3 From 2095fc76953aeec2a091d321426daca3534fca12 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 12 Nov 2015 13:39:49 +0100 Subject: serial: sh-sci: Grammar s/Get ... for/Get ... from/ Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index dfee7a2f51f1..5ec1a70cd2f4 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2645,7 +2645,7 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) if (!p) return NULL; - /* Get the line number for the aliases node. */ + /* Get the line number from the aliases node. */ id = of_alias_get_id(np, "serial"); if (id < 0) { dev_err(&pdev->dev, "failed to get alias id (%d)\n", id); -- cgit v1.2.3 From 495bb47c5dfe92bedce92fd5f3a3a0258d72ac36 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 10 Dec 2015 16:02:17 +0100 Subject: serial: sh-sci: Use existing local variable in sci_parse_dt() Signed-off-by: Geert Uytterhoeven --- drivers/tty/serial/sh-sci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 5ec1a70cd2f4..36077193f111 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2635,7 +2635,7 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) if (!IS_ENABLED(CONFIG_OF) || !np) return NULL; - match = of_match_node(of_sci_match, pdev->dev.of_node); + match = of_match_node(of_sci_match, np); if (!match) return NULL; -- cgit v1.2.3 From bdcb3826976e60204cce52470c01bb9541e547b3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 13 Nov 2015 09:48:34 +0100 Subject: serial: sh-sci: Drop unused frame_len parameter for sci_baud_calc_hscif() As F is assumed to be zero in the receive margin formula, frame_len is not used. Remove it, together with the sci_baud_calc_frame_len() helper function. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 36077193f111..05ac15336e4f 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1866,26 +1866,9 @@ static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, return DIV_ROUND_CLOSEST(freq, s->sampling_rate * bps) - 1; } -/* calculate frame length from SMR */ -static int sci_baud_calc_frame_len(unsigned int smr_val) -{ - int len = 10; - - if (smr_val & SCSMR_CHR) - len--; - if (smr_val & SCSMR_PE) - len++; - if (smr_val & SCSMR_STOP) - len++; - - return len; -} - - /* calculate sample rate, BRR, and clock select for HSCIF */ -static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, - int *brr, unsigned int *srr, - unsigned int *cks, int frame_len) +static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, + unsigned int *srr, unsigned int *cks) { int sr, c, br, err, recv_margin; int min_err = 1000; /* 100% */ @@ -1987,9 +1970,8 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, baud = uart_get_baud_rate(port, termios, old, 0, max_baud); if (likely(baud && port->uartclk)) { if (s->cfg->type == PORT_HSCIF) { - int frame_len = sci_baud_calc_frame_len(smr_val); sci_baud_calc_hscif(baud, port->uartclk, &t, &srr, - &cks, frame_len); + &cks); } else { t = sci_scbrr_calc(s, baud, port->uartclk); for (cks = 0; t >= 256 && cks <= 3; cks++) -- cgit v1.2.3 From a67969b5fd366d488ffa1defd5256e8c3a87434d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 18 Nov 2015 16:20:44 +0100 Subject: serial: sh-sci: Don't overwrite clock selection in serial_console_write() Blindly writing the default configuration value into the SCSCR register may change the clock selection bits, breaking the serial console if the current driver settings differ from the default settings. Keep the current clock selection bits to prevent this from happening on e.g. r8a7791/koelsch when support for the BRG will be added. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 05ac15336e4f..136ad2f63341 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2420,7 +2420,7 @@ static void serial_console_write(struct console *co, const char *s, { struct sci_port *sci_port = &sci_ports[co->index]; struct uart_port *port = &sci_port->port; - unsigned short bits, ctrl; + unsigned short bits, ctrl, ctrl_temp; unsigned long flags; int locked = 1; @@ -2432,9 +2432,11 @@ static void serial_console_write(struct console *co, const char *s, else spin_lock(&port->lock); - /* first save the SCSCR then disable the interrupts */ + /* first save SCSCR then disable interrupts, keep clock source */ ctrl = serial_port_in(port, SCSCR); - serial_port_out(port, SCSCR, sci_port->cfg->scscr); + ctrl_temp = (sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) | + (ctrl & (SCSCR_CKE1 | SCSCR_CKE0)); + serial_port_out(port, SCSCR, ctrl_temp); uart_console_write(port, s, count, serial_console_putchar); -- cgit v1.2.3 From f4de472ef2ff8937b04d5da9d885c78fcbd4c171 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 26 Oct 2015 09:56:20 +0100 Subject: serial: sh-sci: Convert from clk_get() to devm_clk_get() Transfer clock cleanup handling to the core device management code. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 136ad2f63341..b9eb4b525c0a 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2216,7 +2216,7 @@ 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 = clk_get(dev, "fck"); + 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)) @@ -2226,14 +2226,14 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) * But it used to be called "sci_ick", and we need to maintain DT * backward compatibility. */ - sci_port->fclk = clk_get(dev, "sci_ick"); + 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; /* SH has historically named the clock "sci_fck". */ - sci_port->fclk = clk_get(dev, "sci_fck"); + sci_port->fclk = devm_clk_get(dev, "sci_fck"); if (!IS_ERR(sci_port->fclk)) return 0; @@ -2241,7 +2241,7 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) * 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 = clk_get(dev, "peripheral_clk"); + sci_port->fclk = devm_clk_get(dev, "peripheral_clk"); if (!IS_ERR(sci_port->fclk)) return 0; @@ -2400,8 +2400,6 @@ static int sci_init_single(struct platform_device *dev, static void sci_cleanup_single(struct sci_port *port) { - clk_put(port->fclk); - pm_runtime_disable(port->port.dev); } -- cgit v1.2.3 From 95a2703e36530c09a9416321ec21c062f3e91d01 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 13 Nov 2015 16:56:08 +0100 Subject: serial: sh-sci: Make unsigned values in sci_baud_calc_hscif() unsigned Move the -1 offset of br to the assignment to *brr, so br cannot become negative anymore, and update the clamp() call. Now all unsigned values in sci_baud_calc_hscif() can become unsigned. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index b9eb4b525c0a..77e0a582da44 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1870,7 +1870,8 @@ static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, unsigned int *srr, unsigned int *cks) { - int sr, c, br, err, recv_margin; + unsigned int sr, br, c; + int err, recv_margin; int min_err = 1000; /* 100% */ int recv_max_margin = 0; @@ -1880,9 +1881,9 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, for (c = 0; c <= 3; c++) { /* integerized formulas from HSCIF documentation */ br = DIV_ROUND_CLOSEST(freq, (sr * - (1 << (2 * c + 1)) * bps)) - 1; - br = clamp(br, 0, 255); - err = DIV_ROUND_CLOSEST(freq, ((br + 1) * bps * sr * + (1 << (2 * c + 1)) * bps)); + br = clamp(br, 1U, 256U); + err = DIV_ROUND_CLOSEST(freq, (br * bps * sr * (1 << (2 * c + 1)) / 1000)) - 1000; /* Calc recv margin @@ -1908,7 +1909,7 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, else continue; - *brr = br; + *brr = br - 1; *srr = sr - 1; *cks = c; } -- cgit v1.2.3 From de01e6cd0b100bac088b1d59a7040ebe2af64f1c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 13 Nov 2015 17:04:56 +0100 Subject: serial: sh-sci: Avoid overflow in sci_baud_calc_hscif() If bps >= 1048576, the multiplication of the predivider and "bps" will overflow, and both br and err will contain bogus values. Skip the current and all higher clock select predividers when overflow is detected. Simplify the calculations using intermediates while we're at it. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 77e0a582da44..c490c51d6032 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1870,7 +1870,7 @@ static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, unsigned int *srr, unsigned int *cks) { - unsigned int sr, br, c; + unsigned int sr, br, prediv, scrate, c; int err, recv_margin; int min_err = 1000; /* 100% */ int recv_max_margin = 0; @@ -1880,12 +1880,25 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, for (sr = 8; sr <= 32; sr++) { for (c = 0; c <= 3; c++) { /* integerized formulas from HSCIF documentation */ - br = DIV_ROUND_CLOSEST(freq, (sr * - (1 << (2 * c + 1)) * bps)); + prediv = sr * (1 << (2 * c + 1)); + + /* + * We need to calculate: + * + * br = freq / (prediv * bps) clamped to [1..256] + * err = (freq / (br * prediv * bps / 1000)) - 1000 + * + * Watch out for overflow when calculating the desired + * sampling clock rate! + */ + if (bps > UINT_MAX / prediv) + break; + + scrate = prediv * bps; + br = DIV_ROUND_CLOSEST(freq, scrate); br = clamp(br, 1U, 256U); - err = DIV_ROUND_CLOSEST(freq, (br * bps * sr * - (1 << (2 * c + 1)) / 1000)) - - 1000; + err = DIV_ROUND_CLOSEST(freq, (br * scrate) / 1000) - + 1000; /* Calc recv margin * M: Receive margin (%) * N: Ratio of bit rate to clock (N = sampling rate) -- cgit v1.2.3 From 881a7489f463e59a44417ad89ecb4ea21b2b86cd Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 16 Nov 2015 15:54:47 +0100 Subject: serial: sh-sci: Improve bit rate error calculation for HSCIF The algorithm to find the best parameters for the requested bit rate calculates the relative bit rate error, using "(br * scrate) / 1000". For small "br * scrate", this has two problems: - The quotient may be zero, leading to a division by zero error, - This may introduce a large rounding error. Switch from relative to absolute bit rate error calculation to fix this. The default baud rate generator values can be removed, as there will always be one set of values that gives the smallest absolute error. Print the best set of values when debugging. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index c490c51d6032..306497ee5c32 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1867,12 +1867,13 @@ static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, } /* calculate sample rate, BRR, and clock select for HSCIF */ -static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, +static void sci_baud_calc_hscif(struct sci_port *s, unsigned int bps, + unsigned long freq, int *brr, unsigned int *srr, unsigned int *cks) { unsigned int sr, br, prediv, scrate, c; int err, recv_margin; - int min_err = 1000; /* 100% */ + int min_err = INT_MAX; int recv_max_margin = 0; /* Find the combination of sample rate and clock select with the @@ -1886,7 +1887,7 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, * We need to calculate: * * br = freq / (prediv * bps) clamped to [1..256] - * err = (freq / (br * prediv * bps / 1000)) - 1000 + * err = freq / (br * prediv) - bps * * Watch out for overflow when calculating the desired * sampling clock rate! @@ -1897,8 +1898,7 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, scrate = prediv * bps; br = DIV_ROUND_CLOSEST(freq, scrate); br = clamp(br, 1U, 256U); - err = DIV_ROUND_CLOSEST(freq, (br * scrate) / 1000) - - 1000; + err = DIV_ROUND_CLOSEST(freq, br * prediv) - bps; /* Calc recv margin * M: Receive margin (%) * N: Ratio of bit rate to clock (N = sampling rate) @@ -1928,13 +1928,8 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, int *brr, } } - if (min_err == 1000) { - WARN_ON(1); - /* use defaults */ - *brr = 255; - *srr = 15; - *cks = 0; - } + dev_dbg(s->port.dev, "BRR: %u%+d bps using N %u SR %u cks %u\n", bps, + min_err, *brr, *srr + 1, *cks); } static void sci_reset(struct uart_port *port) @@ -1984,7 +1979,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, baud = uart_get_baud_rate(port, termios, old, 0, max_baud); if (likely(baud && port->uartclk)) { if (s->cfg->type == PORT_HSCIF) { - sci_baud_calc_hscif(baud, port->uartclk, &t, &srr, + sci_baud_calc_hscif(s, baud, port->uartclk, &t, &srr, &cks); } else { t = sci_scbrr_calc(s, baud, port->uartclk); -- cgit v1.2.3 From 6c51332dfc23fc7c2c58244e35d36744db202077 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 16 Nov 2015 16:33:22 +0100 Subject: serial: sh-sci: Avoid calculating the receive margin for HSCIF When assuming D = 0.5 and F = 0, maximizing the receive margin M is equivalent to maximizing the sample rate N. Hence there's no need to calculate the receive margin, as we can obtain the same result by iterating over all possible sample rates in reverse order, and skipping parameter sets that don't provide a lower bit rate error. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 51 +++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 27 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 306497ee5c32..c3a193616484 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1872,13 +1872,24 @@ static void sci_baud_calc_hscif(struct sci_port *s, unsigned int bps, unsigned int *srr, unsigned int *cks) { unsigned int sr, br, prediv, scrate, c; - int err, recv_margin; - int min_err = INT_MAX; - int recv_max_margin = 0; + int err, min_err = INT_MAX; - /* Find the combination of sample rate and clock select with the - smallest deviation from the desired baud rate. */ - for (sr = 8; sr <= 32; sr++) { + /* + * Find the combination of sample rate and clock select with the + * smallest deviation from the desired baud rate. + * Prefer high sample rates to maximise the receive margin. + * + * M: Receive margin (%) + * N: Ratio of bit rate to clock (N = sampling rate) + * D: Clock duty (D = 0 to 1.0) + * L: Frame length (L = 9 to 12) + * F: Absolute value of clock frequency deviation + * + * M = |(0.5 - 1 / 2 * N) - ((L - 0.5) * F) - + * (|D - 0.5| / N * (1 + F))| + * NOTE: Usually, treat D for 0.5, F is 0 by this calculation. + */ + for (sr = 32; sr >= 8; sr--) { for (c = 0; c <= 3; c++) { /* integerized formulas from HSCIF documentation */ prediv = sr * (1 << (2 * c + 1)); @@ -1898,36 +1909,22 @@ static void sci_baud_calc_hscif(struct sci_port *s, unsigned int bps, scrate = prediv * bps; br = DIV_ROUND_CLOSEST(freq, scrate); br = clamp(br, 1U, 256U); + err = DIV_ROUND_CLOSEST(freq, br * prediv) - bps; - /* Calc recv margin - * M: Receive margin (%) - * N: Ratio of bit rate to clock (N = sampling rate) - * D: Clock duty (D = 0 to 1.0) - * L: Frame length (L = 9 to 12) - * F: Absolute value of clock frequency deviation - * - * M = |(0.5 - 1 / 2 * N) - ((L - 0.5) * F) - - * (|D - 0.5| / N * (1 + F))| - * NOTE: Usually, treat D for 0.5, F is 0 by this - * calculation. - */ - recv_margin = abs((500 - - DIV_ROUND_CLOSEST(1000, sr << 1)) / 10); - if (abs(min_err) > abs(err)) { - min_err = err; - recv_max_margin = recv_margin; - } else if ((min_err == err) && - (recv_margin > recv_max_margin)) - recv_max_margin = recv_margin; - else + if (abs(err) >= abs(min_err)) continue; + min_err = err; *brr = br - 1; *srr = sr - 1; *cks = c; + + if (!err) + goto found; } } +found: dev_dbg(s->port.dev, "BRR: %u%+d bps using N %u SR %u cks %u\n", bps, min_err, *brr, *srr + 1, *cks); } -- cgit v1.2.3 From b4a5c459088b724734573a550c9da42a9a19c9d0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 16 Nov 2015 17:22:16 +0100 Subject: serial: sh-sci: Merge sci_scbrr_calc() and sci_baud_calc_hscif() For low bit rates, the for-loop that reduces the divider returned by sci_scbrr_calc() and picks the clock select value may terminate without finding suitable values, leading to out-of-range divider and clock select values. sci_baud_calc_hscif() doesn't suffer from this problem, as it correctly uses clamp(). Since there are only two relevant differences between HSCIF and other variants w.r.t. bit rate configuration (fixed vs. variable sample rate, and an additional factor of two), sci_scbrr_calc() and sci_baud_calc_hscif() can be merged, fixing the issue with out-of-range values. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index c3a193616484..d89d4b7576cf 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1860,20 +1860,24 @@ static void sci_shutdown(struct uart_port *port) sci_free_irq(s); } -static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, - unsigned long freq) +/* 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) { - return DIV_ROUND_CLOSEST(freq, s->sampling_rate * bps) - 1; -} - -/* calculate sample rate, BRR, and clock select for HSCIF */ -static void sci_baud_calc_hscif(struct sci_port *s, unsigned int bps, - unsigned long freq, int *brr, - unsigned int *srr, unsigned int *cks) -{ - unsigned int sr, br, prediv, scrate, c; + unsigned int min_sr, max_sr, shift, sr, br, prediv, scrate, c; int err, min_err = INT_MAX; + if (s->sampling_rate) { + min_sr = max_sr = s->sampling_rate; + shift = 0; + } else { + /* HSCIF has a variable sample rate */ + min_sr = 8; + max_sr = 32; + shift = 1; + } + /* * Find the combination of sample rate and clock select with the * smallest deviation from the desired baud rate. @@ -1889,10 +1893,10 @@ static void sci_baud_calc_hscif(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 = 32; sr >= 8; sr--) { + for (sr = max_sr; sr >= min_sr; sr--) { for (c = 0; c <= 3; c++) { /* integerized formulas from HSCIF documentation */ - prediv = sr * (1 << (2 * c + 1)); + prediv = sr * (1 << (2 * c + shift)); /* * We need to calculate: @@ -1974,16 +1978,8 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, max_baud = port->uartclk ? port->uartclk / 16 : 115200; baud = uart_get_baud_rate(port, termios, old, 0, max_baud); - if (likely(baud && port->uartclk)) { - if (s->cfg->type == PORT_HSCIF) { - sci_baud_calc_hscif(s, baud, port->uartclk, &t, &srr, - &cks); - } else { - t = sci_scbrr_calc(s, baud, port->uartclk); - for (cks = 0; t >= 256 && cks <= 3; cks++) - t >>= 2; - } - } + if (likely(baud && port->uartclk)) + sci_scbrr_calc(s, baud, port->uartclk, &t, &srr, &cks); sci_port_enable(s); -- cgit v1.2.3 From ff8b275f1f0927621cf543c2a6f02761052c360d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 19 Nov 2015 14:35:09 +0100 Subject: serial: sh-sci: Take into account sampling rate for max baud rate The maximum baud rate depends on the sampling rate. HSCIF has a variable sampling rate and sets s->sampling_rate to zero, hence use the minimum sampling rate of 8. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index d89d4b7576cf..5b120757c02a 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1975,7 +1975,10 @@ 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. */ - max_baud = port->uartclk ? port->uartclk / 16 : 115200; + if (port->uartclk) + max_baud = port->uartclk / max(s->sampling_rate, 8U); + else + max_baud = 115200; baud = uart_get_baud_rate(port, termios, old, 0, max_baud); if (likely(baud && port->uartclk)) -- cgit v1.2.3 From b8bbd6b2923279f1c9c74d59638b38a1eace78e8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 12 Nov 2015 13:36:06 +0100 Subject: serial: sh-sci: Add BRG register definitions Add register definitions for the Baud Rate Generator for External Clock (BRG), as found in some SCIF and in HSCIF, including a new regtype for the "SH-4(A)"-derived SCIF variant with BRG. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ drivers/tty/serial/sh-sci.h | 10 ++++++++++ include/linux/serial_sci.h | 1 + 3 files changed, 57 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 5b120757c02a..fb5eac2e3182 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -161,6 +161,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -183,6 +185,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -204,6 +208,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = { 0x30, 16 }, [SCPDR] = { 0x34, 16 }, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -225,6 +231,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = { 0x30, 16 }, [SCPDR] = { 0x34, 16 }, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -247,6 +255,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -268,6 +278,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -289,6 +301,32 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, + }, + + /* + * Common SCIF definitions for ports with a Baud Rate Generator for + * External Clock (BRG). + */ + [SCIx_SH4_SCIF_BRG_REGTYPE] = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x0c, 8 }, + [SCxSR] = { 0x10, 16 }, + [SCxRDR] = { 0x14, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCTFDR] = sci_reg_invalid, + [SCRFDR] = sci_reg_invalid, + [SCSPTR] = { 0x20, 16 }, + [SCLSR] = { 0x24, 16 }, + [HSSRR] = sci_reg_invalid, + [SCPCR] = sci_reg_invalid, + [SCPDR] = sci_reg_invalid, + [SCDL] = { 0x30, 16 }, + [SCCKS] = { 0x34, 16 }, }, /* @@ -310,6 +348,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = { 0x40, 16 }, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = { 0x30, 16 }, + [SCCKS] = { 0x34, 16 }, }, /* @@ -332,6 +372,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -354,6 +396,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, /* @@ -376,6 +420,8 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [HSSRR] = sci_reg_invalid, [SCPCR] = sci_reg_invalid, [SCPDR] = sci_reg_invalid, + [SCDL] = sci_reg_invalid, + [SCCKS] = sci_reg_invalid, }, }; diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h index bf69bbdcc1f9..fb1760250421 100644 --- a/drivers/tty/serial/sh-sci.h +++ b/drivers/tty/serial/sh-sci.h @@ -27,6 +27,8 @@ enum { HSSRR, /* Sampling Rate Register */ SCPCR, /* Serial Port Control Register */ SCPDR, /* Serial Port Data Register */ + SCDL, /* BRG Frequency Division Register */ + SCCKS, /* BRG Clock Select Register */ SCIx_NR_REGS, }; @@ -109,6 +111,14 @@ enum { #define SCPDR_RTSD BIT(4) /* Serial Port RTS Output Pin Data */ #define SCPDR_CTSD BIT(3) /* Serial Port CTS Input Pin Data */ +/* + * BRG Clock Select Register (Some SCIF and HSCIF) + * The Baud Rate Generator for external clock can provide a clock source for + * the sampling clock. It outputs either its frequency divided clock, or the + * (undivided) (H)SCK external clock. + */ +#define SCCKS_CKS BIT(15) /* Select (H)SCK (1) or divided SC_CLK (0) */ +#define SCCKS_XIN BIT(14) /* SC_CLK uses bus clock (1) or SCIF_CLK (0) */ #define SCxSR_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND) #define SCxSR_RDxF(port) (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF) diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index 7c536ac5be05..9f2bfd055742 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -32,6 +32,7 @@ enum { SCIx_SH2_SCIF_FIFODATA_REGTYPE, SCIx_SH3_SCIF_REGTYPE, SCIx_SH4_SCIF_REGTYPE, + SCIx_SH4_SCIF_BRG_REGTYPE, SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, SCIx_SH4_SCIF_FIFODATA_REGTYPE, SCIx_SH7705_SCIF_REGTYPE, -- cgit v1.2.3 From bd2238fb84df6054d966364d07e0414b54ef8e19 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Nov 2015 16:09:23 +0100 Subject: serial: sh-sci: Replace struct sci_port_info by type/regtype encoding Store the encoded port and register types directly in of_device_id.data, instead of using a pointer to a structure. This saves memory and simplifies the source code, especially when adding more compatible entries later. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 40 +++++++++++----------------------------- 1 file changed, 11 insertions(+), 29 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index fb5eac2e3182..13c6abe9d842 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2614,42 +2614,27 @@ static int sci_remove(struct platform_device *dev) return 0; } -struct sci_port_info { - unsigned int type; - unsigned int regtype; -}; + +#define SCI_OF_DATA(type, regtype) (void *)((type) << 16 | (regtype)) +#define SCI_OF_TYPE(data) ((unsigned long)(data) >> 16) +#define SCI_OF_REGTYPE(data) ((unsigned long)(data) & 0xffff) static const struct of_device_id of_sci_match[] = { { .compatible = "renesas,scif", - .data = &(const struct sci_port_info) { - .type = PORT_SCIF, - .regtype = SCIx_SH4_SCIF_REGTYPE, - }, + .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_REGTYPE), }, { .compatible = "renesas,scifa", - .data = &(const struct sci_port_info) { - .type = PORT_SCIFA, - .regtype = SCIx_SCIFA_REGTYPE, - }, + .data = SCI_OF_DATA(PORT_SCIFA, SCIx_SCIFA_REGTYPE), }, { .compatible = "renesas,scifb", - .data = &(const struct sci_port_info) { - .type = PORT_SCIFB, - .regtype = SCIx_SCIFB_REGTYPE, - }, + .data = SCI_OF_DATA(PORT_SCIFB, SCIx_SCIFB_REGTYPE), }, { .compatible = "renesas,hscif", - .data = &(const struct sci_port_info) { - .type = PORT_HSCIF, - .regtype = SCIx_HSCIF_REGTYPE, - }, + .data = SCI_OF_DATA(PORT_HSCIF, SCIx_HSCIF_REGTYPE), }, { .compatible = "renesas,sci", - .data = &(const struct sci_port_info) { - .type = PORT_SCI, - .regtype = SCIx_SCI_REGTYPE, - }, + .data = SCI_OF_DATA(PORT_SCI, SCIx_SCI_REGTYPE), }, { /* Terminator */ }, @@ -2661,7 +2646,6 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) { struct device_node *np = pdev->dev.of_node; const struct of_device_id *match; - const struct sci_port_info *info; struct plat_sci_port *p; int id; @@ -2672,8 +2656,6 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) if (!match) return NULL; - info = match->data; - p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL); if (!p) return NULL; @@ -2688,8 +2670,8 @@ sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) *dev_id = id; p->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; - p->type = info->type; - p->regtype = info->regtype; + p->type = SCI_OF_TYPE(match->data); + p->regtype = SCI_OF_REGTYPE(match->data); p->scscr = SCSCR_RE | SCSCR_TE; return p; -- cgit v1.2.3 From f443ff80d02d74be6c3930e325a6573eb06347ea Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Nov 2015 16:16:54 +0100 Subject: serial: sh-sci: Correct SCIF type on RZ/A1H The "renesas,scif" compatible value is currently used for the SCIF variant in all Renesas SoCs of the R-Car and RZ families. However, the variant used in the RZ family is not the common "SH-4(A)" variant, but the "SH-2(A) with FIFO data count register" variant, as it has the "Serial Extension Mode Register" (SCEMR), just like on sh7203, sh7263, sh7264, and sh7269. Use the (already documented) SoC-specific "renesas,scif-r7s72100" compatible value to differentiate. The "renesas,scif" compatible value can still be used as a common denominator for SCIF variants with the "SH-4(A)" register layout (i.e. ignoring the SCEMR register). Note that currently both variants are treated the same, but this may change if support for the SCEMR register is ever added. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 13c6abe9d842..5b8504bfd42e 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2620,6 +2620,12 @@ static int sci_remove(struct platform_device *dev) #define SCI_OF_REGTYPE(data) ((unsigned long)(data) & 0xffff) static const struct of_device_id of_sci_match[] = { + /* SoC-specific types */ + { + .compatible = "renesas,scif-r7s72100", + .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH2_SCIF_FIFODATA_REGTYPE), + }, + /* Generic types */ { .compatible = "renesas,scif", .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_REGTYPE), -- cgit v1.2.3 From 9ed44bb209d0ece90abb6b4279d8b18e17680476 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Nov 2015 18:57:23 +0100 Subject: serial: sh-sci: Correct SCIF type on R-Car for BRG The "renesas,scif" compatible value is currently used for the SCIF variant in all Renesas SoCs of the R-Car family. However, the variant used in the R-Car family is not the common "SH-4(A)" variant, but a derivative with added "Baud Rate Generator for External Clock" (BRG), which is also present in sh7734. Use the family-specific SCIF compatible values for R-Car Gen1, Gen2, and Gen3 SoCs to differentiate. The "renesas,scif" compatible value can still be used as a common denominator for SCIF variants with the "SH-4(A)" register layout (i.e. ignoring the "Serial Extension Mode Register" (SCEMR) and the new BRG-specific registers). Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 5b8504bfd42e..a202e4e40b8a 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2625,6 +2625,17 @@ static const struct of_device_id of_sci_match[] = { .compatible = "renesas,scif-r7s72100", .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH2_SCIF_FIFODATA_REGTYPE), }, + /* Family-specific types */ + { + .compatible = "renesas,rcar-gen1-scif", + .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE), + }, { + .compatible = "renesas,rcar-gen2-scif", + .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE), + }, { + .compatible = "renesas,rcar-gen3-scif", + .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE), + }, /* Generic types */ { .compatible = "renesas,scif", -- cgit v1.2.3 From f4998e55b8987428aa86de02c934fb6e0988d9a3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 26 Oct 2015 09:58:16 +0100 Subject: serial: sh-sci: Prepare for multiple sampling clock sources Refactor the clock and baud rate parameter code to ease adding support for multiple sampling clock sources. sci_scbrr_calc() now returns the bit rate error, so it can be compared to the bit rate error using other sampling clock sources. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 194 ++++++++++++++++++++++++++++++-------------- 1 file changed, 134 insertions(+), 60 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index a202e4e40b8a..fa3fd876105b 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, prediv, scrate, c; + unsigned long freq = s->clk_rates[SCI_FCK]; int err, min_err = INT_MAX; if (s->sampling_rate) { @@ -1977,6 +1996,7 @@ static void sci_scbrr_calc(struct sci_port *s, unsigned int bps, found: 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) @@ -1998,11 +2018,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; @@ -2021,35 +2044,64 @@ 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; + + /* + * There can be multiple sources for the sampling clock. Find the one + * that gives us the smallest deviation from the desired baud rate. + */ + + /* Divided Functional Clock using 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); @@ -2074,7 +2126,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 /* @@ -2266,38 +2320,58 @@ 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; - /* SH has historically named the clock "sci_fck". */ - sci_port->fclk = devm_clk_get(dev, "sci_fck"); - 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; - /* - * 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)) + goto found; - dev_err(dev, "failed to get functional clock\n"); - return PTR_ERR(sci_port->fclk); + /* SH has historically named the clock "sci_fck". */ + clk = devm_clk_get(dev, "sci_fck"); + 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 %s (%ld)\n", clk_names[i], + PTR_ERR(clk)); + return PTR_ERR(clk); + } + +found: + if (IS_ERR(clk)) + dev_dbg(dev, "failed to get %s (%ld)\n", clk_names[i], + PTR_ERR(clk)); + else + dev_dbg(dev, "clk %s is %pC rate %pCr\n", clk_names[i], + clk, clk); + sci_port->clks[i] = IS_ERR(clk) ? NULL : clk; + } + return 0; } static int sci_init_single(struct platform_device *dev, -- cgit v1.2.3 From 6af27bf299e2d66ade25f278f0c13d51007e9879 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 18 Nov 2015 11:12:26 +0100 Subject: serial: sh-sci: Add support for optional external (H)SCK input Add support for using the SCIx clock pin "(H)SCK" as an external clock input on (H)SCI(F), providing the sampling clock. Note that this feature is not yet supported on the select SCIFA variants that also have it (e.g. sh7723, sh7724, and r8a7740). On (H)SCIF variants with an External Baud Rate Generator (BRG), the BRG Clock Select Register must be configured for the external clock. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 69 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index fa3fd876105b..229162481fd6 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -79,6 +79,7 @@ enum { enum SCI_CLKS { SCI_FCK, /* Functional Clock */ + SCI_SCK, /* Optional External Clock */ SCI_NUM_CLKS }; @@ -1924,6 +1925,39 @@ static void sci_shutdown(struct uart_port *port) sci_free_irq(s); } +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; + + if (s->sampling_rate) { + /* SCI(F) has a fixed sampling rate */ + min_sr = max_sr = s->sampling_rate / 2; + } else { + /* HSCIF has a variable 1/(8..32) sampling rate */ + min_sr = 8; + max_sr = 32; + } + + for (sr = max_sr; sr >= min_sr; sr--) { + err = DIV_ROUND_CLOSEST(freq, sr) - bps; + if (abs(err) >= abs(min_err)) + continue; + + min_err = err; + *srr = sr - 1; + + if (!err) + break; + } + + dev_dbg(s->port.dev, "SCK: %u%+d bps using SR %u\n", bps, min_err, + *srr + 1); + return min_err; +} + /* calculate sample rate, BRR, and clock select */ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, unsigned int *brr, unsigned int *srr, @@ -2019,7 +2053,7 @@ 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 brr = 255, cks = 0, srr = 15, sccks = 0; unsigned int brr1 = 255, cks1 = 0, srr1 = 15; struct sci_port *s = to_sci_port(port); const struct plat_sci_reg *reg; @@ -2062,10 +2096,26 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, * that gives us the smallest deviation from the desired baud rate. */ + /* Optional Undivided External Clock */ + if (s->clk_rates[SCI_SCK] && port->type != PORT_SCIFA && + port->type != PORT_SCIFB) { + err = sci_sck_calc(s, baud, &srr1); + if (abs(err) < abs(min_err)) { + best_clk = SCI_SCK; + scr_val = SCSCR_CKE1; + sccks = SCCKS_CKS; + min_err = err; + srr = srr1; + if (!err) + goto done; + } + } + /* Divided Functional Clock using standard Bit Rate Register */ err = sci_scbrr_calc(s, baud, &brr1, &srr1, &cks1); if (abs(err) < abs(min_err)) { best_clk = SCI_FCK; + scr_val = 0; min_err = err; brr = brr1; srr = srr1; @@ -2079,14 +2129,23 @@ done: sci_port_enable(s); + /* + * Program the optional External Baud Rate Generator (BRG) first. + * It controls the mux to select (H)SCK or frequency divided clock. + */ + if (best_clk >= 0 && sci_getreg(port, SCCKS)->size) + serial_port_out(port, SCCKS, sccks); + sci_reset(port); uart_update_timeout(port, termios->c_cflag, baud); if (best_clk >= 0) { smr_val |= cks; - dev_dbg(port->dev, "SMR 0x%x BRR %u SRR %u\n", smr_val, brr, - srr); + dev_dbg(port->dev, + "SCR 0x%x SMR 0x%x BRR %u CKS 0x%x SRR %u\n", + scr_val, smr_val, brr, sccks, srr); + serial_port_out(port, SCSCR, scr_val); serial_port_out(port, SCSMR, smr_val); serial_port_out(port, SCBRR, brr); if (sci_getreg(port, HSSRR)->size) @@ -2322,10 +2381,14 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) { const char *clk_names[] = { [SCI_FCK] = "fck", + [SCI_SCK] = "sck", }; struct clk *clk; unsigned int i; + if (sci_port->cfg->type == PORT_HSCIF) + clk_names[SCI_SCK] = "hsck"; + for (i = 0; i < SCI_NUM_CLKS; i++) { clk = devm_clk_get(dev, clk_names[i]); if (PTR_ERR(clk) == -EPROBE_DEFER) -- cgit v1.2.3 From 1270f86517f342f455dc146b1b321a18d3a274f9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 18 Nov 2015 11:25:53 +0100 Subject: serial: sh-sci: Add support for optional BRG on (H)SCIF Add support for using the Baud Rate Generator for External Clock (BRG), as found on some SCIF and HSCIF variants, to provide the sampling clock. This can improve baud rate range and accuracy. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 85 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 5 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 229162481fd6..4ff5d0cf8126 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -80,6 +80,8 @@ enum { enum SCI_CLKS { SCI_FCK, /* Functional Clock */ SCI_SCK, /* Optional External Clock */ + SCI_BRG_INT, /* Optional BRG Internal Clock Source */ + SCI_SCIF_CLK, /* Optional BRG External Clock Source */ SCI_NUM_CLKS }; @@ -1958,6 +1960,43 @@ static int sci_sck_calc(struct sci_port *s, unsigned int bps, return min_err; } +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; + + if (s->sampling_rate) { + /* SCIF has a fixed sampling rate */ + min_sr = max_sr = s->sampling_rate / 2; + } else { + /* HSCIF has a variable 1/(8..32) sampling rate */ + min_sr = 8; + max_sr = 32; + } + + for (sr = max_sr; sr >= min_sr; sr--) { + dl = DIV_ROUND_CLOSEST(freq, sr * bps); + dl = clamp(dl, 1U, 65535U); + + err = DIV_ROUND_CLOSEST(freq, sr * dl) - bps; + if (abs(err) >= abs(min_err)) + continue; + + min_err = err; + *dlr = dl; + *srr = sr - 1; + + if (!err) + break; + } + + dev_dbg(s->port.dev, "BRG: %u%+d bps using DL %u SR %u\n", bps, + min_err, *dlr, *srr + 1); + return min_err; +} + /* calculate sample rate, BRR, and clock select */ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, unsigned int *brr, unsigned int *srr, @@ -2053,8 +2092,8 @@ 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, sccks = 0; - unsigned int brr1 = 255, cks1 = 0, srr1 = 15; + unsigned int brr = 255, cks = 0, srr = 15, dl = 0, sccks = 0; + unsigned int brr1 = 255, cks1 = 0, srr1 = 15, dl1 = 0; struct sci_port *s = to_sci_port(port); const struct plat_sci_reg *reg; int min_err = INT_MAX, err; @@ -2111,6 +2150,38 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, } } + /* Optional BRG Frequency Divided External Clock */ + if (s->clk_rates[SCI_SCIF_CLK] && sci_getreg(port, SCDL)->size) { + err = sci_brg_calc(s, baud, s->clk_rates[SCI_SCIF_CLK], &dl1, + &srr1); + if (abs(err) < abs(min_err)) { + best_clk = SCI_SCIF_CLK; + scr_val = SCSCR_CKE1; + sccks = 0; + min_err = err; + dl = dl1; + srr = srr1; + if (!err) + goto done; + } + } + + /* Optional BRG Frequency Divided Internal Clock */ + if (s->clk_rates[SCI_BRG_INT] && sci_getreg(port, SCDL)->size) { + err = sci_brg_calc(s, baud, s->clk_rates[SCI_BRG_INT], &dl1, + &srr1); + if (abs(err) < abs(min_err)) { + best_clk = SCI_BRG_INT; + scr_val = SCSCR_CKE1; + sccks = SCCKS_XIN; + min_err = err; + dl = dl1; + srr = srr1; + if (!min_err) + goto done; + } + } + /* Divided Functional Clock using standard Bit Rate Register */ err = sci_scbrr_calc(s, baud, &brr1, &srr1, &cks1); if (abs(err) < abs(min_err)) { @@ -2133,8 +2204,10 @@ done: * Program the optional External Baud Rate Generator (BRG) first. * It controls the mux to select (H)SCK or frequency divided clock. */ - if (best_clk >= 0 && sci_getreg(port, SCCKS)->size) + if (best_clk >= 0 && sci_getreg(port, SCCKS)->size) { + serial_port_out(port, SCDL, dl); serial_port_out(port, SCCKS, sccks); + } sci_reset(port); @@ -2143,8 +2216,8 @@ done: if (best_clk >= 0) { smr_val |= cks; dev_dbg(port->dev, - "SCR 0x%x SMR 0x%x BRR %u CKS 0x%x SRR %u\n", - scr_val, smr_val, brr, sccks, srr); + "SCR 0x%x SMR 0x%x BRR %u CKS 0x%x DL %u SRR %u\n", + scr_val, smr_val, brr, sccks, dl, srr); serial_port_out(port, SCSCR, scr_val); serial_port_out(port, SCSMR, smr_val); serial_port_out(port, SCBRR, brr); @@ -2382,6 +2455,8 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) const char *clk_names[] = { [SCI_FCK] = "fck", [SCI_SCK] = "sck", + [SCI_BRG_INT] = "brg_int", + [SCI_SCIF_CLK] = "scif_clk", }; struct clk *clk; unsigned int i; -- cgit v1.2.3 From 192d367f218d0cd94aa9b5059992e4aa19ec5b36 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 14 Sep 2015 15:14:36 +0300 Subject: serial: sh-sci: Drop the sci_fck clock fallback All platforms that used to define an sci_fck clock have now switched to the fck name. Remove the fallback code. Signed-off-by: Laurent Pinchart Acked-by: Simon Horman Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 4ff5d0cf8126..6571f4d944c2 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2481,11 +2481,6 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) if (!IS_ERR(clk)) goto found; - /* SH has historically named the clock "sci_fck". */ - clk = devm_clk_get(dev, "sci_fck"); - 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 -- cgit v1.2.3