Skip to content

Commit

Permalink
atmel_serial: keep clock off when it's not needed
Browse files Browse the repository at this point in the history
The atmel_serial driver is mismanaging its clock by leaving it on at all
times ...  the whole point of clock management is to leave it off unless
it's actively needed, which conserves power!!

Although the kernel doesn't actually hang without my fix, it does
discard quite a lot of early console output.

The result still looks correct:

          usart        users= 1 on   35000000 Hz, for atmel_usart.0
          usart        users= 0 off  35000000 Hz, for atmel_usart.2

when using ttyS0 as serial console.

[haavard.skinnemoen@atmel.com: Make sure clock is enabled early for console]
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
David Brownell authored and Linus Torvalds committed Nov 6, 2008
1 parent b225d44 commit 06a7f05
Showing 1 changed file with 14 additions and 3 deletions.
17 changes: 14 additions & 3 deletions drivers/serial/atmel_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -1258,6 +1258,8 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
atmel_port->clk = clk_get(&pdev->dev, "usart");
clk_enable(atmel_port->clk);
port->uartclk = clk_get_rate(atmel_port->clk);
clk_disable(atmel_port->clk);
/* only enable clock when USART is in use */
}

atmel_port->use_dma_rx = data->use_dma_rx;
Expand Down Expand Up @@ -1379,6 +1381,8 @@ static int __init atmel_console_setup(struct console *co, char *options)
return -ENODEV;
}

clk_enable(atmel_ports[co->index].clk);

UART_PUT_IDR(port, -1);
UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
Expand All @@ -1403,7 +1407,7 @@ static struct console atmel_console = {
.data = &atmel_uart,
};

#define ATMEL_CONSOLE_DEVICE &atmel_console
#define ATMEL_CONSOLE_DEVICE (&atmel_console)

/*
* Early console initialization (before VM subsystem initialized).
Expand Down Expand Up @@ -1534,6 +1538,15 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
if (ret)
goto err_add_port;

if (atmel_is_console_port(&port->uart)
&& ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) {
/*
* The serial core enabled the clock for us, so undo
* the clk_enable() in atmel_console_setup()
*/
clk_disable(port->clk);
}

device_init_wakeup(&pdev->dev, 1);
platform_set_drvdata(pdev, port);

Expand All @@ -1544,7 +1557,6 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
port->rx_ring.buf = NULL;
err_alloc_ring:
if (!atmel_is_console_port(&port->uart)) {
clk_disable(port->clk);
clk_put(port->clk);
port->clk = NULL;
}
Expand All @@ -1568,7 +1580,6 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev)

/* "port" is allocated statically, so we shouldn't free it */

clk_disable(atmel_port->clk);
clk_put(atmel_port->clk);

return ret;
Expand Down

0 comments on commit 06a7f05

Please sign in to comment.