serial: 8250_dw: add ability to handle the peripheral clock
authorHeiko Stübner <heiko@sntech.de>
Mon, 16 Jun 2014 13:25:17 +0000 (15:25 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Jul 2014 22:27:37 +0000 (15:27 -0700)
First try to find the named clock variants then fall back to the already
existing handling of a nameless declared baudclk.

This also adds the missing documentation for this already existing variant.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
drivers/tty/serial/8250/8250_dw.c

index f13f1c5..095ac71 100644 (file)
@@ -4,7 +4,15 @@ Required properties:
 - compatible : "snps,dw-apb-uart"
 - reg : offset and length of the register set for the device.
 - interrupts : should contain uart interrupt.
+
+Clock handling:
+The clock rate of the input clock needs to be supplied by one of
 - clock-frequency : the input clock frequency for the UART.
+- clocks : phandle to the input clock
+
+The supplying peripheral clock can also be handled, needing a second property
+- clock-names: tuple listing input clock names.
+       Required elements: "baudclk", "apb_pclk"
 
 Optional properties:
 - reg-shift : quantity to shift the register offsets by.  If this property is
@@ -23,3 +31,26 @@ Example:
                reg-shift = <2>;
                reg-io-width = <4>;
        };
+
+Example with one clock:
+
+       uart@80230000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x80230000 0x100>;
+               clocks = <&baudclk>;
+               interrupts = <10>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+       };
+
+Example with two clocks:
+
+       uart@80230000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x80230000 0x100>;
+               clocks = <&baudclk>, <&apb_pclk>;
+               clock-names = "baudclk", "apb_pclk";
+               interrupts = <10>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+       };
index a1450ae..c531fa4 100644 (file)
@@ -59,6 +59,7 @@ struct dw8250_data {
        int                     last_mcr;
        int                     line;
        struct clk              *clk;
+       struct clk              *pclk;
        struct uart_8250_dma    dma;
 };
 
@@ -359,10 +360,25 @@ static int dw8250_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        data->usr_reg = DW_UART_USR;
-       data->clk = devm_clk_get(&pdev->dev, NULL);
+       data->clk = devm_clk_get(&pdev->dev, "baudclk");
+       if (IS_ERR(data->clk))
+               data->clk = devm_clk_get(&pdev->dev, NULL);
        if (!IS_ERR(data->clk)) {
-               clk_prepare_enable(data->clk);
-               uart.port.uartclk = clk_get_rate(data->clk);
+               err = clk_prepare_enable(data->clk);
+               if (err)
+                       dev_warn(&pdev->dev, "could not enable optional baudclk: %d\n",
+                                err);
+               else
+                       uart.port.uartclk = clk_get_rate(data->clk);
+       }
+
+       data->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
+       if (!IS_ERR(data->pclk)) {
+               err = clk_prepare_enable(data->pclk);
+               if (err) {
+                       dev_err(&pdev->dev, "could not enable apb_pclk\n");
+                       return err;
+               }
        }
 
        data->dma.rx_chan_id = -1;
@@ -408,6 +424,9 @@ static int dw8250_remove(struct platform_device *pdev)
 
        serial8250_unregister_port(data->line);
 
+       if (!IS_ERR(data->pclk))
+               clk_disable_unprepare(data->pclk);
+
        if (!IS_ERR(data->clk))
                clk_disable_unprepare(data->clk);
 
@@ -445,6 +464,9 @@ static int dw8250_runtime_suspend(struct device *dev)
        if (!IS_ERR(data->clk))
                clk_disable_unprepare(data->clk);
 
+       if (!IS_ERR(data->pclk))
+               clk_disable_unprepare(data->pclk);
+
        return 0;
 }
 
@@ -452,6 +474,9 @@ static int dw8250_runtime_resume(struct device *dev)
 {
        struct dw8250_data *data = dev_get_drvdata(dev);
 
+       if (!IS_ERR(data->pclk))
+               clk_prepare_enable(data->pclk);
+
        if (!IS_ERR(data->clk))
                clk_prepare_enable(data->clk);