aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/amba-pl010.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial/amba-pl010.c')
-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}