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:
committed by
Greg Kroah-Hartman
parent
d8782c7452
commit
7d78cbefaa
@ -4,7 +4,15 @@ Required properties:
|
|||||||
- compatible : "snps,dw-apb-uart"
|
- compatible : "snps,dw-apb-uart"
|
||||||
- reg : offset and length of the register set for the device.
|
- reg : offset and length of the register set for the device.
|
||||||
- interrupts : should contain uart interrupt.
|
- 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.
|
- 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:
|
Optional properties:
|
||||||
- reg-shift : quantity to shift the register offsets by. If this property is
|
- reg-shift : quantity to shift the register offsets by. If this property is
|
||||||
@ -23,3 +31,26 @@ Example:
|
|||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
reg-io-width = <4>;
|
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>;
|
||||||
|
};
|
||||||
|
@ -59,6 +59,7 @@ struct dw8250_data {
|
|||||||
int last_mcr;
|
int last_mcr;
|
||||||
int line;
|
int line;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
struct clk *pclk;
|
||||||
struct uart_8250_dma dma;
|
struct uart_8250_dma dma;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -359,12 +360,27 @@ static int dw8250_probe(struct platform_device *pdev)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
data->usr_reg = DW_UART_USR;
|
data->usr_reg = DW_UART_USR;
|
||||||
|
data->clk = devm_clk_get(&pdev->dev, "baudclk");
|
||||||
|
if (IS_ERR(data->clk))
|
||||||
data->clk = devm_clk_get(&pdev->dev, NULL);
|
data->clk = devm_clk_get(&pdev->dev, NULL);
|
||||||
if (!IS_ERR(data->clk)) {
|
if (!IS_ERR(data->clk)) {
|
||||||
clk_prepare_enable(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);
|
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;
|
data->dma.rx_chan_id = -1;
|
||||||
data->dma.tx_chan_id = -1;
|
data->dma.tx_chan_id = -1;
|
||||||
data->dma.rx_param = data;
|
data->dma.rx_param = data;
|
||||||
@ -408,6 +424,9 @@ static int dw8250_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
serial8250_unregister_port(data->line);
|
serial8250_unregister_port(data->line);
|
||||||
|
|
||||||
|
if (!IS_ERR(data->pclk))
|
||||||
|
clk_disable_unprepare(data->pclk);
|
||||||
|
|
||||||
if (!IS_ERR(data->clk))
|
if (!IS_ERR(data->clk))
|
||||||
clk_disable_unprepare(data->clk);
|
clk_disable_unprepare(data->clk);
|
||||||
|
|
||||||
@ -445,6 +464,9 @@ static int dw8250_runtime_suspend(struct device *dev)
|
|||||||
if (!IS_ERR(data->clk))
|
if (!IS_ERR(data->clk))
|
||||||
clk_disable_unprepare(data->clk);
|
clk_disable_unprepare(data->clk);
|
||||||
|
|
||||||
|
if (!IS_ERR(data->pclk))
|
||||||
|
clk_disable_unprepare(data->pclk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,6 +474,9 @@ static int dw8250_runtime_resume(struct device *dev)
|
|||||||
{
|
{
|
||||||
struct dw8250_data *data = dev_get_drvdata(dev);
|
struct dw8250_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (!IS_ERR(data->pclk))
|
||||||
|
clk_prepare_enable(data->pclk);
|
||||||
|
|
||||||
if (!IS_ERR(data->clk))
|
if (!IS_ERR(data->clk))
|
||||||
clk_prepare_enable(data->clk);
|
clk_prepare_enable(data->clk);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user