diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 20:07:18 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 20:07:18 -0500 |
commit | 4bcec913d0a98d991c750034a04675443d1f10b5 (patch) | |
tree | ce2e960ba26d50f09b6a7bd864b2b4d3c275e69b /drivers/tty | |
parent | 03c7287dd22c18815964219c9a2e75054cd004df (diff) | |
parent | f878f84373aefda7f041a74b24a83b8b7dec1cf0 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull more powerpc bits from Ben Herrenschmidt:
"Here are a few more powerpc bits for this merge window. The bulk is
made of two pull requests from Scott and Anatolij that I had missed
previously (they arrived while I was away). Since both their branches
are in -next independently, and the content has been around for a
little while, they can still go in.
The rest is mostly bug and regression fixes, a small series of
cleanups to our pseries cpuidle code (including moving it to the right
place), and one new cpuidle bakend for the powernv platform. I also
wired up the new sched_attr syscalls"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (37 commits)
powerpc: Wire up sched_setattr and sched_getattr syscalls
powerpc/hugetlb: Replace __get_cpu_var with get_cpu_var
powerpc: Make sure "cache" directory is removed when offlining cpu
powerpc/mm: Fix mmap errno when MAP_FIXED is set and mapping exceeds the allowed address space
powerpc/powernv/cpuidle: Back-end cpuidle driver for powernv platform.
powerpc/pseries/cpuidle: smt-snooze-delay cleanup.
powerpc/pseries/cpuidle: Remove MAX_IDLE_STATE macro.
powerpc/pseries/cpuidle: Make cpuidle-pseries backend driver a non-module.
powerpc/pseries/cpuidle: Use cpuidle_register() for initialisation.
powerpc/pseries/cpuidle: Move processor_idle.c to drivers/cpuidle.
powerpc: Fix 32-bit frames for signals delivered when transactional
powerpc/iommu: Fix initialisation of DART iommu table
powerpc/numa: Fix decimal permissions
powerpc/mm: Fix compile error of pgtable-ppc64.h
powerpc: Fix hw breakpoints on !HAVE_HW_BREAKPOINT configurations
clk: corenet: Adds the clock binding
powerpc/booke64: Guard e6500 tlb handler with CONFIG_PPC_FSL_BOOK3E
powerpc/512x: dts: add MPC5125 clock specs
powerpc/512x: clk: support MPC5121/5123/5125 SoC variants
powerpc/512x: clk: enforce even SDHC divider values
...
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/mpc52xx_uart.c | 90 |
1 files changed, 79 insertions, 11 deletions
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index ec06505e3ae6..97888f4900ec 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c | |||
@@ -421,6 +421,7 @@ struct psc_fifoc { | |||
421 | 421 | ||
422 | static struct psc_fifoc __iomem *psc_fifoc; | 422 | static struct psc_fifoc __iomem *psc_fifoc; |
423 | static unsigned int psc_fifoc_irq; | 423 | static unsigned int psc_fifoc_irq; |
424 | static struct clk *psc_fifoc_clk; | ||
424 | 425 | ||
425 | static void mpc512x_psc_fifo_init(struct uart_port *port) | 426 | static void mpc512x_psc_fifo_init(struct uart_port *port) |
426 | { | 427 | { |
@@ -568,36 +569,73 @@ static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port, | |||
568 | /* Init PSC FIFO Controller */ | 569 | /* Init PSC FIFO Controller */ |
569 | static int __init mpc512x_psc_fifoc_init(void) | 570 | static int __init mpc512x_psc_fifoc_init(void) |
570 | { | 571 | { |
572 | int err; | ||
571 | struct device_node *np; | 573 | struct device_node *np; |
574 | struct clk *clk; | ||
575 | |||
576 | /* default error code, potentially overwritten by clock calls */ | ||
577 | err = -ENODEV; | ||
572 | 578 | ||
573 | np = of_find_compatible_node(NULL, NULL, | 579 | np = of_find_compatible_node(NULL, NULL, |
574 | "fsl,mpc5121-psc-fifo"); | 580 | "fsl,mpc5121-psc-fifo"); |
575 | if (!np) { | 581 | if (!np) { |
576 | pr_err("%s: Can't find FIFOC node\n", __func__); | 582 | pr_err("%s: Can't find FIFOC node\n", __func__); |
577 | return -ENODEV; | 583 | goto out_err; |
578 | } | 584 | } |
579 | 585 | ||
586 | clk = of_clk_get(np, 0); | ||
587 | if (IS_ERR(clk)) { | ||
588 | /* backwards compat with device trees that lack clock specs */ | ||
589 | clk = clk_get_sys(np->name, "ipg"); | ||
590 | } | ||
591 | if (IS_ERR(clk)) { | ||
592 | pr_err("%s: Can't lookup FIFO clock\n", __func__); | ||
593 | err = PTR_ERR(clk); | ||
594 | goto out_ofnode_put; | ||
595 | } | ||
596 | if (clk_prepare_enable(clk)) { | ||
597 | pr_err("%s: Can't enable FIFO clock\n", __func__); | ||
598 | clk_put(clk); | ||
599 | goto out_ofnode_put; | ||
600 | } | ||
601 | psc_fifoc_clk = clk; | ||
602 | |||
580 | psc_fifoc = of_iomap(np, 0); | 603 | psc_fifoc = of_iomap(np, 0); |
581 | if (!psc_fifoc) { | 604 | if (!psc_fifoc) { |
582 | pr_err("%s: Can't map FIFOC\n", __func__); | 605 | pr_err("%s: Can't map FIFOC\n", __func__); |
583 | of_node_put(np); | 606 | goto out_clk_disable; |
584 | return -ENODEV; | ||
585 | } | 607 | } |
586 | 608 | ||
587 | psc_fifoc_irq = irq_of_parse_and_map(np, 0); | 609 | psc_fifoc_irq = irq_of_parse_and_map(np, 0); |
588 | of_node_put(np); | ||
589 | if (psc_fifoc_irq == 0) { | 610 | if (psc_fifoc_irq == 0) { |
590 | pr_err("%s: Can't get FIFOC irq\n", __func__); | 611 | pr_err("%s: Can't get FIFOC irq\n", __func__); |
591 | iounmap(psc_fifoc); | 612 | goto out_unmap; |
592 | return -ENODEV; | ||
593 | } | 613 | } |
594 | 614 | ||
615 | of_node_put(np); | ||
595 | return 0; | 616 | return 0; |
617 | |||
618 | out_unmap: | ||
619 | iounmap(psc_fifoc); | ||
620 | out_clk_disable: | ||
621 | clk_disable_unprepare(psc_fifoc_clk); | ||
622 | clk_put(psc_fifoc_clk); | ||
623 | out_ofnode_put: | ||
624 | of_node_put(np); | ||
625 | out_err: | ||
626 | return err; | ||
596 | } | 627 | } |
597 | 628 | ||
598 | static void __exit mpc512x_psc_fifoc_uninit(void) | 629 | static void __exit mpc512x_psc_fifoc_uninit(void) |
599 | { | 630 | { |
600 | iounmap(psc_fifoc); | 631 | iounmap(psc_fifoc); |
632 | |||
633 | /* disable the clock, errors are not fatal */ | ||
634 | if (psc_fifoc_clk) { | ||
635 | clk_disable_unprepare(psc_fifoc_clk); | ||
636 | clk_put(psc_fifoc_clk); | ||
637 | psc_fifoc_clk = NULL; | ||
638 | } | ||
601 | } | 639 | } |
602 | 640 | ||
603 | /* 512x specific interrupt handler. The caller holds the port lock */ | 641 | /* 512x specific interrupt handler. The caller holds the port lock */ |
@@ -619,29 +657,55 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port) | |||
619 | } | 657 | } |
620 | 658 | ||
621 | static struct clk *psc_mclk_clk[MPC52xx_PSC_MAXNUM]; | 659 | static struct clk *psc_mclk_clk[MPC52xx_PSC_MAXNUM]; |
660 | static struct clk *psc_ipg_clk[MPC52xx_PSC_MAXNUM]; | ||
622 | 661 | ||
623 | /* called from within the .request_port() callback (allocation) */ | 662 | /* called from within the .request_port() callback (allocation) */ |
624 | static int mpc512x_psc_alloc_clock(struct uart_port *port) | 663 | static int mpc512x_psc_alloc_clock(struct uart_port *port) |
625 | { | 664 | { |
626 | int psc_num; | 665 | int psc_num; |
627 | char clk_name[16]; | ||
628 | struct clk *clk; | 666 | struct clk *clk; |
629 | int err; | 667 | int err; |
630 | 668 | ||
631 | psc_num = (port->mapbase & 0xf00) >> 8; | 669 | psc_num = (port->mapbase & 0xf00) >> 8; |
632 | snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num); | 670 | |
633 | clk = devm_clk_get(port->dev, clk_name); | 671 | clk = devm_clk_get(port->dev, "mclk"); |
634 | if (IS_ERR(clk)) { | 672 | if (IS_ERR(clk)) { |
635 | dev_err(port->dev, "Failed to get MCLK!\n"); | 673 | dev_err(port->dev, "Failed to get MCLK!\n"); |
636 | return PTR_ERR(clk); | 674 | err = PTR_ERR(clk); |
675 | goto out_err; | ||
637 | } | 676 | } |
638 | err = clk_prepare_enable(clk); | 677 | err = clk_prepare_enable(clk); |
639 | if (err) { | 678 | if (err) { |
640 | dev_err(port->dev, "Failed to enable MCLK!\n"); | 679 | dev_err(port->dev, "Failed to enable MCLK!\n"); |
641 | return err; | 680 | goto out_err; |
642 | } | 681 | } |
643 | psc_mclk_clk[psc_num] = clk; | 682 | psc_mclk_clk[psc_num] = clk; |
683 | |||
684 | clk = devm_clk_get(port->dev, "ipg"); | ||
685 | if (IS_ERR(clk)) { | ||
686 | dev_err(port->dev, "Failed to get IPG clock!\n"); | ||
687 | err = PTR_ERR(clk); | ||
688 | goto out_err; | ||
689 | } | ||
690 | err = clk_prepare_enable(clk); | ||
691 | if (err) { | ||
692 | dev_err(port->dev, "Failed to enable IPG clock!\n"); | ||
693 | goto out_err; | ||
694 | } | ||
695 | psc_ipg_clk[psc_num] = clk; | ||
696 | |||
644 | return 0; | 697 | return 0; |
698 | |||
699 | out_err: | ||
700 | if (psc_mclk_clk[psc_num]) { | ||
701 | clk_disable_unprepare(psc_mclk_clk[psc_num]); | ||
702 | psc_mclk_clk[psc_num] = NULL; | ||
703 | } | ||
704 | if (psc_ipg_clk[psc_num]) { | ||
705 | clk_disable_unprepare(psc_ipg_clk[psc_num]); | ||
706 | psc_ipg_clk[psc_num] = NULL; | ||
707 | } | ||
708 | return err; | ||
645 | } | 709 | } |
646 | 710 | ||
647 | /* called from within the .release_port() callback (release) */ | 711 | /* called from within the .release_port() callback (release) */ |
@@ -656,6 +720,10 @@ static void mpc512x_psc_relse_clock(struct uart_port *port) | |||
656 | clk_disable_unprepare(clk); | 720 | clk_disable_unprepare(clk); |
657 | psc_mclk_clk[psc_num] = NULL; | 721 | psc_mclk_clk[psc_num] = NULL; |
658 | } | 722 | } |
723 | if (psc_ipg_clk[psc_num]) { | ||
724 | clk_disable_unprepare(psc_ipg_clk[psc_num]); | ||
725 | psc_ipg_clk[psc_num] = NULL; | ||
726 | } | ||
659 | } | 727 | } |
660 | 728 | ||
661 | /* implementation of the .clock() callback (enable/disable) */ | 729 | /* implementation of the .clock() callback (enable/disable) */ |