serial: sirf: only use lookup table to set baudrate when ioclk=150MHz
authorBarry Song <Baohua.Song@csr.com>
Wed, 16 Jan 2013 06:49:27 +0000 (14:49 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 18 Jan 2013 01:18:55 +0000 (17:18 -0800)
The fast lookup table to set baudrate is only right when ioclk
is 150MHz. for most platforms, ioclk is 150MHz, but some boards
might set ioclk to other frequency.

so re-calc the clk_div_reg when ioclk is not 150MHz. this patch
also gets clk in probe and puts it in remove.

Signed-off-by: Barry Song <Baohua.Song@csr.com>
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/sirfsoc_uart.c
drivers/tty/serial/sirfsoc_uart.h

index 8f3d6c091accb32266c94573da0d0d8096efa47c..6bbfe9934a4d7ba70b99e3ed6d7cc94e35de9cfd 100644 (file)
@@ -357,7 +357,6 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
                                       struct ktermios *old)
 {
        struct sirfsoc_uart_port *sirfport = to_sirfport(port);
-       unsigned long   ioclk_rate;
        unsigned long   config_reg = 0;
        unsigned long   baud_rate;
        unsigned long   setted_baud;
@@ -369,7 +368,6 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
        int             threshold_div;
        int             temp;
 
-       ioclk_rate = 150000000;
        switch (termios->c_cflag & CSIZE) {
        default:
        case CS8:
@@ -425,14 +423,17 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
                        sirfsoc_uart_disable_ms(port);
        }
 
-       /* common rate: fast calculation */
-       for (ic = 0; ic < SIRF_BAUD_RATE_SUPPORT_NR; ic++)
-               if (baud_rate == baudrate_to_regv[ic].baud_rate)
-                       clk_div_reg = baudrate_to_regv[ic].reg_val;
+       if (port->uartclk == 150000000) {
+               /* common rate: fast calculation */
+               for (ic = 0; ic < SIRF_BAUD_RATE_SUPPORT_NR; ic++)
+                       if (baud_rate == baudrate_to_regv[ic].baud_rate)
+                               clk_div_reg = baudrate_to_regv[ic].reg_val;
+       }
+
        setted_baud = baud_rate;
        /* arbitary rate setting */
        if (unlikely(clk_div_reg == 0))
-               clk_div_reg = sirfsoc_calc_sample_div(baud_rate, ioclk_rate,
+               clk_div_reg = sirfsoc_calc_sample_div(baud_rate, port->uartclk,
                                                                &setted_baud);
        wr_regl(port, SIRFUART_DIVISOR, clk_div_reg);
 
@@ -691,6 +692,14 @@ int sirfsoc_uart_probe(struct platform_device *pdev)
                        goto err;
        }
 
+       sirfport->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(sirfport->clk)) {
+               ret = PTR_ERR(sirfport->clk);
+               goto clk_err;
+       }
+       clk_prepare_enable(sirfport->clk);
+       port->uartclk = clk_get_rate(sirfport->clk);
+
        port->ops = &sirfsoc_uart_ops;
        spin_lock_init(&port->lock);
 
@@ -704,6 +713,9 @@ int sirfsoc_uart_probe(struct platform_device *pdev)
        return 0;
 
 port_err:
+       clk_disable_unprepare(sirfport->clk);
+       clk_put(sirfport->clk);
+clk_err:
        platform_set_drvdata(pdev, NULL);
        if (sirfport->hw_flow_ctrl)
                pinctrl_put(sirfport->p);
@@ -718,6 +730,8 @@ static int sirfsoc_uart_remove(struct platform_device *pdev)
        platform_set_drvdata(pdev, NULL);
        if (sirfport->hw_flow_ctrl)
                pinctrl_put(sirfport->p);
+       clk_disable_unprepare(sirfport->clk);
+       clk_put(sirfport->clk);
        uart_remove_one_port(&sirfsoc_uart_drv, port);
        return 0;
 }
index 6431640c3163a62011356575aac2112522c5dc44..85328ba0c4e3fc7245cd5c6d45321cd06254c963 100644 (file)
@@ -163,6 +163,7 @@ struct sirfsoc_uart_port {
 
        struct uart_port                port;
        struct pinctrl                  *p;
+       struct clk                      *clk;
 };
 
 /* Hardware Flow Control */