aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-09-05 02:43:30 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-09-05 02:43:30 -0400
commit91c2beb56b3ab5cf91fe04ddaeb69b90a22b5d36 (patch)
tree86dbad225295d8a63048da48728381614c10e1a2 /drivers/tty
parent83c93e2bdfe33694032cc6d74e956755dd62e551 (diff)
parentf2110cb961200e5c382e9d0878ded015109b5dd6 (diff)
Merge remote-tracking branch 'agust/next' into next
From Anatolij: << There are cleanups for some mpc5121 specific drivers and DTS files in preparation to switch mpc5121 clock support to a clock driver based on common clock framework. Additionally Sebastian fixed the mpc52xx PIC driver so that it builds when using older gcc versions. >>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c98
1 files changed, 81 insertions, 17 deletions
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index e1280a20b7a2..5be1df39f9f5 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -107,6 +107,8 @@ struct psc_ops {
107 unsigned int (*set_baudrate)(struct uart_port *port, 107 unsigned int (*set_baudrate)(struct uart_port *port,
108 struct ktermios *new, 108 struct ktermios *new,
109 struct ktermios *old); 109 struct ktermios *old);
110 int (*clock_alloc)(struct uart_port *port);
111 void (*clock_relse)(struct uart_port *port);
110 int (*clock)(struct uart_port *port, int enable); 112 int (*clock)(struct uart_port *port, int enable);
111 int (*fifoc_init)(void); 113 int (*fifoc_init)(void);
112 void (*fifoc_uninit)(void); 114 void (*fifoc_uninit)(void);
@@ -616,31 +618,73 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
616 return IRQ_NONE; 618 return IRQ_NONE;
617} 619}
618 620
619static int mpc512x_psc_clock(struct uart_port *port, int enable) 621static struct clk *psc_mclk_clk[MPC52xx_PSC_MAXNUM];
622
623/* called from within the .request_port() callback (allocation) */
624static int mpc512x_psc_alloc_clock(struct uart_port *port)
620{ 625{
621 struct clk *psc_clk;
622 int psc_num; 626 int psc_num;
623 char clk_name[10]; 627 char clk_name[16];
628 struct clk *clk;
629 int err;
630
631 psc_num = (port->mapbase & 0xf00) >> 8;
632 snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
633 clk = devm_clk_get(port->dev, clk_name);
634 if (IS_ERR(clk)) {
635 dev_err(port->dev, "Failed to get MCLK!\n");
636 return PTR_ERR(clk);
637 }
638 err = clk_prepare_enable(clk);
639 if (err) {
640 dev_err(port->dev, "Failed to enable MCLK!\n");
641 return err;
642 }
643 psc_mclk_clk[psc_num] = clk;
644 return 0;
645}
646
647/* called from within the .release_port() callback (release) */
648static void mpc512x_psc_relse_clock(struct uart_port *port)
649{
650 int psc_num;
651 struct clk *clk;
652
653 psc_num = (port->mapbase & 0xf00) >> 8;
654 clk = psc_mclk_clk[psc_num];
655 if (clk) {
656 clk_disable_unprepare(clk);
657 psc_mclk_clk[psc_num] = NULL;
658 }
659}
660
661/* implementation of the .clock() callback (enable/disable) */
662static int mpc512x_psc_endis_clock(struct uart_port *port, int enable)
663{
664 int psc_num;
665 struct clk *psc_clk;
666 int ret;
624 667
625 if (uart_console(port)) 668 if (uart_console(port))
626 return 0; 669 return 0;
627 670
628 psc_num = (port->mapbase & 0xf00) >> 8; 671 psc_num = (port->mapbase & 0xf00) >> 8;
629 snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num); 672 psc_clk = psc_mclk_clk[psc_num];
630 psc_clk = clk_get(port->dev, clk_name); 673 if (!psc_clk) {
631 if (IS_ERR(psc_clk)) {
632 dev_err(port->dev, "Failed to get PSC clock entry!\n"); 674 dev_err(port->dev, "Failed to get PSC clock entry!\n");
633 return -ENODEV; 675 return -ENODEV;
634 } 676 }
635 677
636 dev_dbg(port->dev, "%s %sable\n", clk_name, enable ? "en" : "dis"); 678 dev_dbg(port->dev, "mclk %sable\n", enable ? "en" : "dis");
637 679 if (enable) {
638 if (enable) 680 ret = clk_enable(psc_clk);
639 clk_enable(psc_clk); 681 if (ret)
640 else 682 dev_err(port->dev, "Failed to enable MCLK!\n");
683 return ret;
684 } else {
641 clk_disable(psc_clk); 685 clk_disable(psc_clk);
642 686 return 0;
643 return 0; 687 }
644} 688}
645 689
646static void mpc512x_psc_get_irq(struct uart_port *port, struct device_node *np) 690static void mpc512x_psc_get_irq(struct uart_port *port, struct device_node *np)
@@ -873,7 +917,9 @@ static struct psc_ops mpc5125_psc_ops = {
873 .cw_disable_ints = mpc5125_psc_cw_disable_ints, 917 .cw_disable_ints = mpc5125_psc_cw_disable_ints,
874 .cw_restore_ints = mpc5125_psc_cw_restore_ints, 918 .cw_restore_ints = mpc5125_psc_cw_restore_ints,
875 .set_baudrate = mpc5125_psc_set_baudrate, 919 .set_baudrate = mpc5125_psc_set_baudrate,
876 .clock = mpc512x_psc_clock, 920 .clock_alloc = mpc512x_psc_alloc_clock,
921 .clock_relse = mpc512x_psc_relse_clock,
922 .clock = mpc512x_psc_endis_clock,
877 .fifoc_init = mpc512x_psc_fifoc_init, 923 .fifoc_init = mpc512x_psc_fifoc_init,
878 .fifoc_uninit = mpc512x_psc_fifoc_uninit, 924 .fifoc_uninit = mpc512x_psc_fifoc_uninit,
879 .get_irq = mpc512x_psc_get_irq, 925 .get_irq = mpc512x_psc_get_irq,
@@ -906,7 +952,9 @@ static struct psc_ops mpc512x_psc_ops = {
906 .cw_disable_ints = mpc512x_psc_cw_disable_ints, 952 .cw_disable_ints = mpc512x_psc_cw_disable_ints,
907 .cw_restore_ints = mpc512x_psc_cw_restore_ints, 953 .cw_restore_ints = mpc512x_psc_cw_restore_ints,
908 .set_baudrate = mpc512x_psc_set_baudrate, 954 .set_baudrate = mpc512x_psc_set_baudrate,
909 .clock = mpc512x_psc_clock, 955 .clock_alloc = mpc512x_psc_alloc_clock,
956 .clock_relse = mpc512x_psc_relse_clock,
957 .clock = mpc512x_psc_endis_clock,
910 .fifoc_init = mpc512x_psc_fifoc_init, 958 .fifoc_init = mpc512x_psc_fifoc_init,
911 .fifoc_uninit = mpc512x_psc_fifoc_uninit, 959 .fifoc_uninit = mpc512x_psc_fifoc_uninit,
912 .get_irq = mpc512x_psc_get_irq, 960 .get_irq = mpc512x_psc_get_irq,
@@ -1166,6 +1214,9 @@ mpc52xx_uart_type(struct uart_port *port)
1166static void 1214static void
1167mpc52xx_uart_release_port(struct uart_port *port) 1215mpc52xx_uart_release_port(struct uart_port *port)
1168{ 1216{
1217 if (psc_ops->clock_relse)
1218 psc_ops->clock_relse(port);
1219
1169 /* remapped by us ? */ 1220 /* remapped by us ? */
1170 if (port->flags & UPF_IOREMAP) { 1221 if (port->flags & UPF_IOREMAP) {
1171 iounmap(port->membase); 1222 iounmap(port->membase);
@@ -1190,11 +1241,24 @@ mpc52xx_uart_request_port(struct uart_port *port)
1190 err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc), 1241 err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
1191 "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY; 1242 "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
1192 1243
1193 if (err && (port->flags & UPF_IOREMAP)) { 1244 if (err)
1245 goto out_membase;
1246
1247 if (psc_ops->clock_alloc) {
1248 err = psc_ops->clock_alloc(port);
1249 if (err)
1250 goto out_mapregion;
1251 }
1252
1253 return 0;
1254
1255out_mapregion:
1256 release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
1257out_membase:
1258 if (port->flags & UPF_IOREMAP) {
1194 iounmap(port->membase); 1259 iounmap(port->membase);
1195 port->membase = NULL; 1260 port->membase = NULL;
1196 } 1261 }
1197
1198 return err; 1262 return err;
1199} 1263}
1200 1264