]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/tty/serial/sh-sci.c
serial: sh-sci: Convert from clk_get() to devm_clk_get()
[karo-tx-linux.git] / drivers / tty / serial / sh-sci.c
index 960e50a97558cff52a1fb9eb8ed8879a5238991c..b9eb4b525c0a75712b7803b9ea0cb86395c1617c 100644 (file)
@@ -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);
        }
 
@@ -1867,35 +1863,12 @@ 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);
-}
-
-/* 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;
+       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(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% */
@@ -1997,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++)
@@ -2241,6 +2213,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 = devm_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 = 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 = devm_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 = devm_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 +2341,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,9 +2400,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);
 }
 
@@ -2426,7 +2418,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;
 
@@ -2438,9 +2430,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);
 
@@ -2623,7 +2617,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;
 
@@ -2633,7 +2627,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);