diff options
-rw-r--r-- | arch/arm/mach-ep93xx/clock.c | 5 | ||||
-rw-r--r-- | 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 f174d1a3b11c..9d7515c36bff 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c | |||
@@ -27,6 +27,10 @@ struct clk { | |||
27 | u32 enable_mask; | 27 | u32 enable_mask; |
28 | }; | 28 | }; |
29 | 29 | ||
30 | static struct clk clk_uart = { | ||
31 | .name = "UARTCLK", | ||
32 | .rate = 14745600, | ||
33 | }; | ||
30 | static struct clk clk_pll1 = { | 34 | static struct clk clk_pll1 = { |
31 | .name = "pll1", | 35 | .name = "pll1", |
32 | }; | 36 | }; |
@@ -50,6 +54,7 @@ static struct clk clk_usb_host = { | |||
50 | 54 | ||
51 | 55 | ||
52 | static struct clk *clocks[] = { | 56 | static struct clk *clocks[] = { |
57 | &clk_uart, | ||
53 | &clk_pll1, | 58 | &clk_pll1, |
54 | &clk_f, | 59 | &clk_f, |
55 | &clk_h, | 60 | &clk_h, |
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 | */ |
71 | struct uart_amba_port { | 72 | struct 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 | ||
336 | static void pl010_shutdown(struct uart_port *port) | 352 | static 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 | ||
356 | static void | 377 | static 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 | ||
562 | static void __init | 587 | static 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 | } |