Skip to content

Commit

Permalink
serial: sirf: add a new uart type support
Browse files Browse the repository at this point in the history
in CSR A7DA SoC, uart6 located at BT module and it need multiple clock
sources, so for "sirf,marco-bt-uart" compatible uarts, drivers take 3
clock sources and enable them.

this patch also replaces clk_get by devm_clk_get function and fix DT
binding document in which we missed to fix when we added marco platform
in commit 909102d "serial: sirf: add support for Marco chip".

Signed-off-by: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Qipan Li authored and Greg Kroah-Hartman committed Nov 26, 2014
1 parent e620e54 commit 52bec4e
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 8 deletions.
16 changes: 15 additions & 1 deletion Documentation/devicetree/bindings/serial/sirf-uart.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
* CSR SiRFprimaII/atlasVI Universal Synchronous Asynchronous Receiver/Transmitter *

Required properties:
- compatible : Should be "sirf,prima2-uart" or "sirf, prima2-usp-uart"
- compatible : Should be "sirf,prima2-uart", "sirf, prima2-usp-uart",
"sirf,marco-uart" or "sirf,marco-bt-uart" which means
uart located in BT module and used for BT.
- reg : Offset and length of the register set for the device
- interrupts : Should contain uart interrupt
- fifosize : Should define hardware rx/tx fifo size
Expand Down Expand Up @@ -31,3 +33,15 @@ usp@b0090000 {
rts-gpios = <&gpio 15 0>;
cts-gpios = <&gpio 46 0>;
};

for uart use in BT module,
uart6: uart@11000000 {
cell-index = <6>;
compatible = "sirf,marco-bt-uart", "sirf,marco-uart";
reg = <0x11000000 0x1000>;
interrupts = <0 100 0>;
clocks = <&clks 138>, <&clks 140>, <&clks 141>;
clock-names = "uart", "general", "noc";
fifosize = <128>;
status = "disabled";
}
34 changes: 27 additions & 7 deletions drivers/tty/serial/sirfsoc_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -1032,10 +1032,19 @@ static void sirfsoc_uart_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
if (!state)
if (!state) {
if (sirfport->is_bt_uart) {
clk_prepare_enable(sirfport->clk_noc);
clk_prepare_enable(sirfport->clk_general);
}
clk_prepare_enable(sirfport->clk);
else
} else {
clk_disable_unprepare(sirfport->clk);
if (sirfport->is_bt_uart) {
clk_disable_unprepare(sirfport->clk_general);
clk_disable_unprepare(sirfport->clk_noc);
}
}
}

static int sirfsoc_uart_startup(struct uart_port *port)
Expand Down Expand Up @@ -1378,12 +1387,26 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
}
port->irq = res->start;

sirfport->clk = clk_get(&pdev->dev, NULL);
sirfport->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(sirfport->clk)) {
ret = PTR_ERR(sirfport->clk);
goto err;
}
port->uartclk = clk_get_rate(sirfport->clk);
if (of_device_is_compatible(pdev->dev.of_node, "sirf,marco-bt-uart")) {
sirfport->clk_general = devm_clk_get(&pdev->dev, "general");
if (IS_ERR(sirfport->clk_general)) {
ret = PTR_ERR(sirfport->clk_general);
goto err;
}
sirfport->clk_noc = devm_clk_get(&pdev->dev, "noc");
if (IS_ERR(sirfport->clk_noc)) {
ret = PTR_ERR(sirfport->clk_noc);
goto err;
}
sirfport->is_bt_uart = true;
} else
sirfport->is_bt_uart = false;

port->ops = &sirfsoc_uart_ops;
spin_lock_init(&port->lock);
Expand All @@ -1392,7 +1415,7 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
ret = uart_add_one_port(&sirfsoc_uart_drv, port);
if (ret != 0) {
dev_err(&pdev->dev, "Cannot add UART port(%d).\n", pdev->id);
goto port_err;
goto err;
}

sirfport->rx_dma_chan = dma_request_slave_channel(port->dev, "rx");
Expand Down Expand Up @@ -1421,8 +1444,6 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
sirfport->rx_dma_items[j].xmit.buf,
sirfport->rx_dma_items[j].dma_addr);
dma_release_channel(sirfport->rx_dma_chan);
port_err:
clk_put(sirfport->clk);
err:
return ret;
}
Expand All @@ -1431,7 +1452,6 @@ static int sirfsoc_uart_remove(struct platform_device *pdev)
{
struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev);
struct uart_port *port = &sirfport->port;
clk_put(sirfport->clk);
uart_remove_one_port(&sirfsoc_uart_drv, port);
if (sirfport->rx_dma_chan) {
int i;
Expand Down
4 changes: 4 additions & 0 deletions drivers/tty/serial/sirfsoc_uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,10 @@ struct sirfsoc_uart_port {

struct uart_port port;
struct clk *clk;
/* UART6 for BT usage in A7DA platform need multi-clock source */
bool is_bt_uart;
struct clk *clk_general;
struct clk *clk_noc;
/* for SiRFmarco, there are SET/CLR for UART_INT_EN */
bool is_marco;
struct sirfsoc_uart_register *uart_reg;
Expand Down

0 comments on commit 52bec4e

Please sign in to comment.