diff options
Diffstat (limited to 'drivers/tty/serial/sh-sci.c')
-rw-r--r-- | drivers/tty/serial/sh-sci.c | 197 |
1 files changed, 120 insertions, 77 deletions
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 8e55e0a2733a..d0a56235c50e 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c | |||
@@ -62,12 +62,6 @@ struct sci_port { | |||
62 | /* Platform configuration */ | 62 | /* Platform configuration */ |
63 | struct plat_sci_port *cfg; | 63 | struct plat_sci_port *cfg; |
64 | 64 | ||
65 | /* Port enable callback */ | ||
66 | void (*enable)(struct uart_port *port); | ||
67 | |||
68 | /* Port disable callback */ | ||
69 | void (*disable)(struct uart_port *port); | ||
70 | |||
71 | /* Break timer */ | 65 | /* Break timer */ |
72 | struct timer_list break_timer; | 66 | struct timer_list break_timer; |
73 | int break_flag; | 67 | int break_flag; |
@@ -77,6 +71,8 @@ struct sci_port { | |||
77 | /* Function clock */ | 71 | /* Function clock */ |
78 | struct clk *fclk; | 72 | struct clk *fclk; |
79 | 73 | ||
74 | char *irqstr[SCIx_NR_IRQS]; | ||
75 | |||
80 | struct dma_chan *chan_tx; | 76 | struct dma_chan *chan_tx; |
81 | struct dma_chan *chan_rx; | 77 | struct dma_chan *chan_rx; |
82 | 78 | ||
@@ -366,6 +362,29 @@ static int sci_probe_regmap(struct plat_sci_port *cfg) | |||
366 | return 0; | 362 | return 0; |
367 | } | 363 | } |
368 | 364 | ||
365 | static void sci_port_enable(struct sci_port *sci_port) | ||
366 | { | ||
367 | if (!sci_port->port.dev) | ||
368 | return; | ||
369 | |||
370 | pm_runtime_get_sync(sci_port->port.dev); | ||
371 | |||
372 | clk_enable(sci_port->iclk); | ||
373 | sci_port->port.uartclk = clk_get_rate(sci_port->iclk); | ||
374 | clk_enable(sci_port->fclk); | ||
375 | } | ||
376 | |||
377 | static void sci_port_disable(struct sci_port *sci_port) | ||
378 | { | ||
379 | if (!sci_port->port.dev) | ||
380 | return; | ||
381 | |||
382 | clk_disable(sci_port->fclk); | ||
383 | clk_disable(sci_port->iclk); | ||
384 | |||
385 | pm_runtime_put_sync(sci_port->port.dev); | ||
386 | } | ||
387 | |||
369 | #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE) | 388 | #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE) |
370 | 389 | ||
371 | #ifdef CONFIG_CONSOLE_POLL | 390 | #ifdef CONFIG_CONSOLE_POLL |
@@ -651,8 +670,7 @@ static void sci_break_timer(unsigned long data) | |||
651 | { | 670 | { |
652 | struct sci_port *port = (struct sci_port *)data; | 671 | struct sci_port *port = (struct sci_port *)data; |
653 | 672 | ||
654 | if (port->enable) | 673 | sci_port_enable(port); |
655 | port->enable(&port->port); | ||
656 | 674 | ||
657 | if (sci_rxd_in(&port->port) == 0) { | 675 | if (sci_rxd_in(&port->port) == 0) { |
658 | port->break_flag = 1; | 676 | port->break_flag = 1; |
@@ -664,8 +682,7 @@ static void sci_break_timer(unsigned long data) | |||
664 | } else | 682 | } else |
665 | port->break_flag = 0; | 683 | port->break_flag = 0; |
666 | 684 | ||
667 | if (port->disable) | 685 | sci_port_disable(port); |
668 | port->disable(&port->port); | ||
669 | } | 686 | } |
670 | 687 | ||
671 | static int sci_handle_errors(struct uart_port *port) | 688 | static int sci_handle_errors(struct uart_port *port) |
@@ -939,74 +956,102 @@ static int sci_notifier(struct notifier_block *self, | |||
939 | return NOTIFY_OK; | 956 | return NOTIFY_OK; |
940 | } | 957 | } |
941 | 958 | ||
942 | static void sci_clk_enable(struct uart_port *port) | 959 | static struct sci_irq_desc { |
943 | { | 960 | const char *desc; |
944 | struct sci_port *sci_port = to_sci_port(port); | 961 | irq_handler_t handler; |
945 | 962 | } sci_irq_desc[] = { | |
946 | pm_runtime_get_sync(port->dev); | 963 | /* |
964 | * Split out handlers, the default case. | ||
965 | */ | ||
966 | [SCIx_ERI_IRQ] = { | ||
967 | .desc = "rx err", | ||
968 | .handler = sci_er_interrupt, | ||
969 | }, | ||
947 | 970 | ||
948 | clk_enable(sci_port->iclk); | 971 | [SCIx_RXI_IRQ] = { |
949 | sci_port->port.uartclk = clk_get_rate(sci_port->iclk); | 972 | .desc = "rx full", |
950 | clk_enable(sci_port->fclk); | 973 | .handler = sci_rx_interrupt, |
951 | } | 974 | }, |
952 | 975 | ||
953 | static void sci_clk_disable(struct uart_port *port) | 976 | [SCIx_TXI_IRQ] = { |
954 | { | 977 | .desc = "tx empty", |
955 | struct sci_port *sci_port = to_sci_port(port); | 978 | .handler = sci_tx_interrupt, |
979 | }, | ||
956 | 980 | ||
957 | clk_disable(sci_port->fclk); | 981 | [SCIx_BRI_IRQ] = { |
958 | clk_disable(sci_port->iclk); | 982 | .desc = "break", |
983 | .handler = sci_br_interrupt, | ||
984 | }, | ||
959 | 985 | ||
960 | pm_runtime_put_sync(port->dev); | 986 | /* |
961 | } | 987 | * Special muxed handler. |
988 | */ | ||
989 | [SCIx_MUX_IRQ] = { | ||
990 | .desc = "mux", | ||
991 | .handler = sci_mpxed_interrupt, | ||
992 | }, | ||
993 | }; | ||
962 | 994 | ||
963 | static int sci_request_irq(struct sci_port *port) | 995 | static int sci_request_irq(struct sci_port *port) |
964 | { | 996 | { |
965 | int i; | 997 | struct uart_port *up = &port->port; |
966 | irqreturn_t (*handlers[4])(int irq, void *ptr) = { | 998 | int i, j, ret = 0; |
967 | sci_er_interrupt, sci_rx_interrupt, sci_tx_interrupt, | 999 | |
968 | sci_br_interrupt, | 1000 | for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) { |
969 | }; | 1001 | struct sci_irq_desc *desc; |
970 | const char *desc[] = { "SCI Receive Error", "SCI Receive Data Full", | 1002 | unsigned int irq; |
971 | "SCI Transmit Data Empty", "SCI Break" }; | 1003 | |
972 | 1004 | if (SCIx_IRQ_IS_MUXED(port)) { | |
973 | if (port->cfg->irqs[0] == port->cfg->irqs[1]) { | 1005 | i = SCIx_MUX_IRQ; |
974 | if (unlikely(!port->cfg->irqs[0])) | 1006 | irq = up->irq; |
975 | return -ENODEV; | 1007 | } else |
976 | 1008 | irq = port->cfg->irqs[i]; | |
977 | if (request_irq(port->cfg->irqs[0], sci_mpxed_interrupt, | 1009 | |
978 | IRQF_DISABLED, "sci", port)) { | 1010 | desc = sci_irq_desc + i; |
979 | dev_err(port->port.dev, "Can't allocate IRQ\n"); | 1011 | port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s", |
980 | return -ENODEV; | 1012 | dev_name(up->dev), desc->desc); |
1013 | if (!port->irqstr[j]) { | ||
1014 | dev_err(up->dev, "Failed to allocate %s IRQ string\n", | ||
1015 | desc->desc); | ||
1016 | goto out_nomem; | ||
981 | } | 1017 | } |
982 | } else { | 1018 | |
983 | for (i = 0; i < ARRAY_SIZE(handlers); i++) { | 1019 | ret = request_irq(irq, desc->handler, up->irqflags, |
984 | if (unlikely(!port->cfg->irqs[i])) | 1020 | port->irqstr[j], port); |
985 | continue; | 1021 | if (unlikely(ret)) { |
986 | 1022 | dev_err(up->dev, "Can't allocate %s IRQ\n", desc->desc); | |
987 | if (request_irq(port->cfg->irqs[i], handlers[i], | 1023 | goto out_noirq; |
988 | IRQF_DISABLED, desc[i], port)) { | ||
989 | dev_err(port->port.dev, "Can't allocate IRQ\n"); | ||
990 | return -ENODEV; | ||
991 | } | ||
992 | } | 1024 | } |
993 | } | 1025 | } |
994 | 1026 | ||
995 | return 0; | 1027 | return 0; |
1028 | |||
1029 | out_noirq: | ||
1030 | while (--i >= 0) | ||
1031 | free_irq(port->cfg->irqs[i], port); | ||
1032 | |||
1033 | out_nomem: | ||
1034 | while (--j >= 0) | ||
1035 | kfree(port->irqstr[j]); | ||
1036 | |||
1037 | return ret; | ||
996 | } | 1038 | } |
997 | 1039 | ||
998 | static void sci_free_irq(struct sci_port *port) | 1040 | static void sci_free_irq(struct sci_port *port) |
999 | { | 1041 | { |
1000 | int i; | 1042 | int i; |
1001 | 1043 | ||
1002 | if (port->cfg->irqs[0] == port->cfg->irqs[1]) | 1044 | /* |
1003 | free_irq(port->cfg->irqs[0], port); | 1045 | * Intentionally in reverse order so we iterate over the muxed |
1004 | else { | 1046 | * IRQ first. |
1005 | for (i = 0; i < ARRAY_SIZE(port->cfg->irqs); i++) { | 1047 | */ |
1006 | if (!port->cfg->irqs[i]) | 1048 | for (i = 0; i < SCIx_NR_IRQS; i++) { |
1007 | continue; | 1049 | free_irq(port->cfg->irqs[i], port); |
1050 | kfree(port->irqstr[i]); | ||
1008 | 1051 | ||
1009 | free_irq(port->cfg->irqs[i], port); | 1052 | if (SCIx_IRQ_IS_MUXED(port)) { |
1053 | /* If there's only one IRQ, we're done. */ | ||
1054 | return; | ||
1010 | } | 1055 | } |
1011 | } | 1056 | } |
1012 | } | 1057 | } |
@@ -1537,8 +1582,7 @@ static int sci_startup(struct uart_port *port) | |||
1537 | 1582 | ||
1538 | dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); | 1583 | dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); |
1539 | 1584 | ||
1540 | if (s->enable) | 1585 | sci_port_enable(s); |
1541 | s->enable(port); | ||
1542 | 1586 | ||
1543 | ret = sci_request_irq(s); | 1587 | ret = sci_request_irq(s); |
1544 | if (unlikely(ret < 0)) | 1588 | if (unlikely(ret < 0)) |
@@ -1564,8 +1608,7 @@ static void sci_shutdown(struct uart_port *port) | |||
1564 | sci_free_dma(port); | 1608 | sci_free_dma(port); |
1565 | sci_free_irq(s); | 1609 | sci_free_irq(s); |
1566 | 1610 | ||
1567 | if (s->disable) | 1611 | sci_port_disable(s); |
1568 | s->disable(port); | ||
1569 | } | 1612 | } |
1570 | 1613 | ||
1571 | static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, | 1614 | static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, |
@@ -1612,8 +1655,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1612 | if (likely(baud && port->uartclk)) | 1655 | if (likely(baud && port->uartclk)) |
1613 | t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud, port->uartclk); | 1656 | t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud, port->uartclk); |
1614 | 1657 | ||
1615 | if (s->enable) | 1658 | sci_port_enable(s); |
1616 | s->enable(port); | ||
1617 | 1659 | ||
1618 | do { | 1660 | do { |
1619 | status = sci_in(port, SCxSR); | 1661 | status = sci_in(port, SCxSR); |
@@ -1683,8 +1725,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1683 | if ((termios->c_cflag & CREAD) != 0) | 1725 | if ((termios->c_cflag & CREAD) != 0) |
1684 | sci_start_rx(port); | 1726 | sci_start_rx(port); |
1685 | 1727 | ||
1686 | if (s->disable) | 1728 | sci_port_disable(s); |
1687 | s->disable(port); | ||
1688 | } | 1729 | } |
1689 | 1730 | ||
1690 | static const char *sci_type(struct uart_port *port) | 1731 | static const char *sci_type(struct uart_port *port) |
@@ -1825,6 +1866,7 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1825 | struct plat_sci_port *p) | 1866 | struct plat_sci_port *p) |
1826 | { | 1867 | { |
1827 | struct uart_port *port = &sci_port->port; | 1868 | struct uart_port *port = &sci_port->port; |
1869 | int ret; | ||
1828 | 1870 | ||
1829 | port->ops = &sci_uart_ops; | 1871 | port->ops = &sci_uart_ops; |
1830 | port->iotype = UPIO_MEM; | 1872 | port->iotype = UPIO_MEM; |
@@ -1845,8 +1887,11 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1845 | break; | 1887 | break; |
1846 | } | 1888 | } |
1847 | 1889 | ||
1848 | if (p->regtype == SCIx_PROBE_REGTYPE) | 1890 | if (p->regtype == SCIx_PROBE_REGTYPE) { |
1849 | BUG_ON(sci_probe_regmap(p) != 0); | 1891 | ret = sci_probe_regmap(p); |
1892 | if (unlikely(!ret)) | ||
1893 | return ret; | ||
1894 | } | ||
1850 | 1895 | ||
1851 | if (dev) { | 1896 | if (dev) { |
1852 | sci_port->iclk = clk_get(&dev->dev, "sci_ick"); | 1897 | sci_port->iclk = clk_get(&dev->dev, "sci_ick"); |
@@ -1866,8 +1911,6 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1866 | if (IS_ERR(sci_port->fclk)) | 1911 | if (IS_ERR(sci_port->fclk)) |
1867 | sci_port->fclk = NULL; | 1912 | sci_port->fclk = NULL; |
1868 | 1913 | ||
1869 | sci_port->enable = sci_clk_enable; | ||
1870 | sci_port->disable = sci_clk_disable; | ||
1871 | port->dev = &dev->dev; | 1914 | port->dev = &dev->dev; |
1872 | 1915 | ||
1873 | pm_runtime_enable(&dev->dev); | 1916 | pm_runtime_enable(&dev->dev); |
@@ -1918,6 +1961,7 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1918 | * For the muxed case there's nothing more to do. | 1961 | * For the muxed case there's nothing more to do. |
1919 | */ | 1962 | */ |
1920 | port->irq = p->irqs[SCIx_RXI_IRQ]; | 1963 | port->irq = p->irqs[SCIx_RXI_IRQ]; |
1964 | port->irqflags = IRQF_DISABLED; | ||
1921 | 1965 | ||
1922 | port->serial_in = sci_serial_in; | 1966 | port->serial_in = sci_serial_in; |
1923 | port->serial_out = sci_serial_out; | 1967 | port->serial_out = sci_serial_out; |
@@ -1946,8 +1990,7 @@ static void serial_console_write(struct console *co, const char *s, | |||
1946 | struct uart_port *port = &sci_port->port; | 1990 | struct uart_port *port = &sci_port->port; |
1947 | unsigned short bits; | 1991 | unsigned short bits; |
1948 | 1992 | ||
1949 | if (sci_port->enable) | 1993 | sci_port_enable(sci_port); |
1950 | sci_port->enable(port); | ||
1951 | 1994 | ||
1952 | uart_console_write(port, s, count, serial_console_putchar); | 1995 | uart_console_write(port, s, count, serial_console_putchar); |
1953 | 1996 | ||
@@ -1956,8 +1999,7 @@ static void serial_console_write(struct console *co, const char *s, | |||
1956 | while ((sci_in(port, SCxSR) & bits) != bits) | 1999 | while ((sci_in(port, SCxSR) & bits) != bits) |
1957 | cpu_relax(); | 2000 | cpu_relax(); |
1958 | 2001 | ||
1959 | if (sci_port->disable) | 2002 | sci_port_disable(sci_port); |
1960 | sci_port->disable(port); | ||
1961 | } | 2003 | } |
1962 | 2004 | ||
1963 | static int __devinit serial_console_setup(struct console *co, char *options) | 2005 | static int __devinit serial_console_setup(struct console *co, char *options) |
@@ -1989,8 +2031,7 @@ static int __devinit serial_console_setup(struct console *co, char *options) | |||
1989 | if (unlikely(ret != 0)) | 2031 | if (unlikely(ret != 0)) |
1990 | return ret; | 2032 | return ret; |
1991 | 2033 | ||
1992 | if (sci_port->enable) | 2034 | sci_port_enable(sci_port); |
1993 | sci_port->enable(port); | ||
1994 | 2035 | ||
1995 | if (options) | 2036 | if (options) |
1996 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 2037 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
@@ -2207,3 +2248,5 @@ module_exit(sci_exit); | |||
2207 | 2248 | ||
2208 | MODULE_LICENSE("GPL"); | 2249 | MODULE_LICENSE("GPL"); |
2209 | MODULE_ALIAS("platform:sh-sci"); | 2250 | MODULE_ALIAS("platform:sh-sci"); |
2251 | MODULE_AUTHOR("Paul Mundt"); | ||
2252 | MODULE_DESCRIPTION("SuperH SCI(F) serial driver"); | ||