Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=ed519dede3d705e1c0012acd5b8de4074aa30fa4
Commit:     ed519dede3d705e1c0012acd5b8de4074aa30fa4
Parent:     1b0646a033c370d6c7f5390f2cb452cc1884bb5b
Author:     Russell King <[EMAIL PROTECTED]>
AuthorDate: Sun Apr 22 12:30:41 2007 +0100
Committer:  Russell King <[EMAIL PROTECTED]>
CommitDate: Sun Apr 22 12:30:41 2007 +0100

    [ARM] Convert AMBA PL010 driver to use the clk infrastructure
    
    Convert the AMBA PL010 serial driver to use the clock infrastructure
    to allow EP93xx platforms to properly gate the clock to the UARTs.
    
    Signed-off-by: Russell King <[EMAIL PROTECTED]>
---
 arch/arm/mach-ep93xx/clock.c |    5 +++++
 drivers/serial/amba-pl010.c  |   39 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
index f174d1a..9d7515c 100644
--- a/arch/arm/mach-ep93xx/clock.c
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -27,6 +27,10 @@ struct clk {
        u32             enable_mask;
 };
 
+static struct clk clk_uart = {
+       .name           = "UARTCLK",
+       .rate           = 14745600,
+};
 static struct clk clk_pll1 = {
        .name           = "pll1",
 };
@@ -50,6 +54,7 @@ static struct clk clk_usb_host = {
 
 
 static struct clk *clocks[] = {
+       &clk_uart,
        &clk_pll1,
        &clk_f,
        &clk_h,
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index ea49aaf..1a9a24b 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -48,6 +48,7 @@
 #include <linux/serial.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/serial.h>
+#include <linux/clk.h>
 
 #include <asm/io.h>
 
@@ -70,6 +71,7 @@
  */
 struct uart_amba_port {
        struct uart_port        port;
+       struct clk              *clk;
        struct amba_device      *dev;
        struct amba_pl010_data  *data;
        unsigned int            old_status;
@@ -313,11 +315,20 @@ static int pl010_startup(struct uart_port *port)
        int retval;
 
        /*
+        * Try to enable the clock producer.
+        */
+       retval = clk_enable(uap->clk);
+       if (retval)
+               goto out;
+
+       uap->port.uartclk = clk_get_rate(uap->clk);
+
+       /*
         * Allocate the IRQ
         */
        retval = request_irq(uap->port.irq, pl010_int, 0, "uart-pl010", uap);
        if (retval)
-               return retval;
+               goto clk_dis;
 
        /*
         * initialise the old status of the modem signals
@@ -331,6 +342,11 @@ static int pl010_startup(struct uart_port *port)
               uap->port.membase + UART010_CR);
 
        return 0;
+
+ clk_dis:
+       clk_disable(uap->clk);
+ out:
+       return retval;
 }
 
 static void pl010_shutdown(struct uart_port *port)
@@ -351,6 +367,11 @@ static void pl010_shutdown(struct uart_port *port)
        writel(readb(uap->port.membase + UART010_LCRH) &
                ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN),
               uap->port.membase + UART010_LCRH);
+
+       /*
+        * Shut down the clock producer
+        */
+       clk_disable(uap->clk);
 }
 
 static void
@@ -540,6 +561,8 @@ pl010_console_write(struct console *co, const char *s, 
unsigned int count)
        struct uart_amba_port *uap = amba_ports[co->index];
        unsigned int status, old_cr;
 
+       clk_enable(uap->clk);
+
        /*
         *      First save the CR then disable the interrupts
         */
@@ -557,6 +580,8 @@ pl010_console_write(struct console *co, const char *s, 
unsigned int count)
                barrier();
        } while (status & UART01x_FR_BUSY);
        writel(old_cr, uap->port.membase + UART010_CR);
+
+       clk_disable(uap->clk);
 }
 
 static void __init
@@ -605,6 +630,8 @@ static int __init pl010_console_setup(struct console *co, 
char *options)
        if (!uap)
                return -ENODEV;
 
+       uap->port.uartclk = clk_get_rate(uap->clk);
+
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
        else
@@ -666,12 +693,17 @@ static int pl010_probe(struct amba_device *dev, void *id)
                goto free;
        }
 
+       uap->clk = clk_get(&dev->dev, "UARTCLK");
+       if (IS_ERR(uap->clk)) {
+               ret = PTR_ERR(uap->clk);
+               goto unmap;
+       }
+
        uap->port.dev = &dev->dev;
        uap->port.mapbase = dev->res.start;
        uap->port.membase = base;
        uap->port.iotype = UPIO_MEM;
        uap->port.irq = dev->irq[0];
-       uap->port.uartclk = 14745600;
        uap->port.fifosize = 16;
        uap->port.ops = &amba_pl010_pops;
        uap->port.flags = UPF_BOOT_AUTOCONF;
@@ -686,6 +718,8 @@ static int pl010_probe(struct amba_device *dev, void *id)
        if (ret) {
                amba_set_drvdata(dev, NULL);
                amba_ports[i] = NULL;
+               clk_put(uap->clk);
+ unmap:
                iounmap(base);
  free:
                kfree(uap);
@@ -708,6 +742,7 @@ static int pl010_remove(struct amba_device *dev)
                        amba_ports[i] = NULL;
 
        iounmap(uap->port.membase);
+       clk_put(uap->clk);
        kfree(uap);
        return 0;
 }
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to