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 | ||
