diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-09-05 02:43:30 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-09-05 02:43:30 -0400 |
commit | 91c2beb56b3ab5cf91fe04ddaeb69b90a22b5d36 (patch) | |
tree | 86dbad225295d8a63048da48728381614c10e1a2 /drivers/tty | |
parent | 83c93e2bdfe33694032cc6d74e956755dd62e551 (diff) | |
parent | f2110cb961200e5c382e9d0878ded015109b5dd6 (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.c | 98 |
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 | ||
619 | static int mpc512x_psc_clock(struct uart_port *port, int enable) | 621 | static struct clk *psc_mclk_clk[MPC52xx_PSC_MAXNUM]; |
622 | |||
623 | /* called from within the .request_port() callback (allocation) */ | ||
624 | static 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) */ | ||
648 | static 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) */ | ||
662 | static 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 | ||
646 | static void mpc512x_psc_get_irq(struct uart_port *port, struct device_node *np) | 690 | static 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) | |||
1166 | static void | 1214 | static void |
1167 | mpc52xx_uart_release_port(struct uart_port *port) | 1215 | mpc52xx_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 | |||
1255 | out_mapregion: | ||
1256 | release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc)); | ||
1257 | out_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 | ||