serial: 8250_dw: add ability to handle the peripheral clock

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>
This commit is contained in:
Heiko Stübner 2014-06-16 15:25:17 +02:00 committed by Greg Kroah-Hartman
parent d8782c7452
commit 7d78cbefaa
2 changed files with 59 additions and 3 deletions

View 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>;
};

View 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);