aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2007-04-22 07:30:41 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-04-22 07:30:41 -0400
commited519dede3d705e1c0012acd5b8de4074aa30fa4 (patch)
tree4de79fbb96d8fcbdc84aaf7a1b823b3a628a2a47 /drivers/serial
parent1b0646a033c370d6c7f5390f2cb452cc1884bb5b (diff)
[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 <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/amba-pl010.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index ea49aafd66bf..1a9a24b82636 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -48,6 +48,7 @@
48#include <linux/serial.h> 48#include <linux/serial.h>
49#include <linux/amba/bus.h> 49#include <linux/amba/bus.h>
50#include <linux/amba/serial.h> 50#include <linux/amba/serial.h>
51#include <linux/clk.h>
51 52
52#include <asm/io.h> 53#include <asm/io.h>
53 54
@@ -70,6 +71,7 @@
70 */ 71 */
71struct uart_amba_port { 72struct uart_amba_port {
72 struct uart_port port; 73 struct uart_port port;
74 struct clk *clk;
73 struct amba_device *dev; 75 struct amba_device *dev;
74 struct amba_pl010_data *data; 76 struct amba_pl010_data *data;
75 unsigned int old_status; 77 unsigned int old_status;
@@ -313,11 +315,20 @@ static int pl010_startup(struct uart_port *port)
313 int retval; 315 int retval;
314 316
315 /* 317 /*
318 * Try to enable the clock producer.
319 */
320 retval = clk_enable(uap->clk);
321 if (retval)
322 goto out;
323
324 uap->port.uartclk = clk_get_rate(uap->clk);
325
326 /*
316 * Allocate the IRQ 327 * Allocate the IRQ
317 */ 328 */
318 retval = request_irq(uap->port.irq, pl010_int, 0, "uart-pl010", uap); 329 retval = request_irq(uap->port.irq, pl010_int, 0, "uart-pl010", uap);
319 if (retval) 330 if (retval)
320 return retval; 331 goto clk_dis;
321 332
322 /* 333 /*
323 * initialise the old status of the modem signals 334 * initialise the old status of the modem signals
@@ -331,6 +342,11 @@ static int pl010_startup(struct uart_port *port)
331 uap->port.membase + UART010_CR); 342 uap->port.membase + UART010_CR);
332 343
333 return 0; 344 return 0;
345
346 clk_dis:
347 clk_disable(uap->clk);
348 out:
349 return retval;
334} 350}
335 351
336static void pl010_shutdown(struct uart_port *port) 352static void pl010_shutdown(struct uart_port *port)
@@ -351,6 +367,11 @@ static void pl010_shutdown(struct uart_port *port)
351 writel(readb(uap->port.membase + UART010_LCRH) & 367 writel(readb(uap->port.membase + UART010_LCRH) &
352 ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN), 368 ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN),
353 uap->port.membase + UART010_LCRH); 369 uap->port.membase + UART010_LCRH);
370
371 /*
372 * Shut down the clock producer
373 */
374 clk_disable(uap->clk);
354} 375}
355 376
356static void 377static void
@@ -540,6 +561,8 @@ pl010_console_write(struct console *co, const char *s, unsigned int count)
540 struct uart_amba_port *uap = amba_ports[co->index]; 561 struct uart_amba_port *uap = amba_ports[co->index];
541 unsigned int status, old_cr; 562 unsigned int status, old_cr;
542 563
564 clk_enable(uap->clk);
565
543 /* 566 /*
544 * First save the CR then disable the interrupts 567 * First save the CR then disable the interrupts
545 */ 568 */
@@ -557,6 +580,8 @@ pl010_console_write(struct console *co, const char *s, unsigned int count)
557 barrier(); 580 barrier();
558 } while (status & UART01x_FR_BUSY); 581 } while (status & UART01x_FR_BUSY);
559 writel(old_cr, uap->port.membase + UART010_CR); 582 writel(old_cr, uap->port.membase + UART010_CR);
583
584 clk_disable(uap->clk);
560} 585}
561 586
562static void __init 587static void __init
@@ -605,6 +630,8 @@ static int __init pl010_console_setup(struct console *co, char *options)
605 if (!uap) 630 if (!uap)
606 return -ENODEV; 631 return -ENODEV;
607 632
633 uap->port.uartclk = clk_get_rate(uap->clk);
634
608 if (options) 635 if (options)
609 uart_parse_options(options, &baud, &parity, &bits, &flow); 636 uart_parse_options(options, &baud, &parity, &bits, &flow);
610 else 637 else
@@ -666,12 +693,17 @@ static int pl010_probe(struct amba_device *dev, void *id)
666 goto free; 693 goto free;
667 } 694 }
668 695
696 uap->clk = clk_get(&dev->dev, "UARTCLK");
697 if (IS_ERR(uap->clk)) {
698 ret = PTR_ERR(uap->clk);
699 goto unmap;
700 }
701
669 uap->port.dev = &dev->dev; 702 uap->port.dev = &dev->dev;
670 uap->port.mapbase = dev->res.start; 703 uap->port.mapbase = dev->res.start;
671 uap->port.membase = base; 704 uap->port.membase = base;
672 uap->port.iotype = UPIO_MEM; 705 uap->port.iotype = UPIO_MEM;
673 uap->port.irq = dev->irq[0]; 706 uap->port.irq = dev->irq[0];
674 uap->port.uartclk = 14745600;
675 uap->port.fifosize = 16; 707 uap->port.fifosize = 16;
676 uap->port.ops = &amba_pl010_pops; 708 uap->port.ops = &amba_pl010_pops;
677 uap->port.flags = UPF_BOOT_AUTOCONF; 709 uap->port.flags = UPF_BOOT_AUTOCONF;
@@ -686,6 +718,8 @@ static int pl010_probe(struct amba_device *dev, void *id)
686 if (ret) { 718 if (ret) {
687 amba_set_drvdata(dev, NULL); 719 amba_set_drvdata(dev, NULL);
688 amba_ports[i] = NULL; 720 amba_ports[i] = NULL;
721 clk_put(uap->clk);
722 unmap:
689 iounmap(base); 723 iounmap(base);
690 free: 724 free:
691 kfree(uap); 725 kfree(uap);
@@ -708,6 +742,7 @@ static int pl010_remove(struct amba_device *dev)
708 amba_ports[i] = NULL; 742 amba_ports[i] = NULL;
709 743
710 iounmap(uap->port.membase); 744 iounmap(uap->port.membase);
745 clk_put(uap->clk);
711 kfree(uap); 746 kfree(uap);
712 return 0; 747 return 0;
713} 748}