diff options
-rw-r--r-- | drivers/tty/serial/8250/8250_omap.c | 82 |
1 files changed, 73 insertions, 9 deletions
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 9289999cb7c6..dce1a23706e8 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c | |||
@@ -562,12 +562,36 @@ static irqreturn_t omap_wake_irq(int irq, void *dev_id) | |||
562 | return IRQ_NONE; | 562 | return IRQ_NONE; |
563 | } | 563 | } |
564 | 564 | ||
565 | #ifdef CONFIG_SERIAL_8250_DMA | ||
566 | static int omap_8250_dma_handle_irq(struct uart_port *port); | ||
567 | #endif | ||
568 | |||
569 | static irqreturn_t omap8250_irq(int irq, void *dev_id) | ||
570 | { | ||
571 | struct uart_port *port = dev_id; | ||
572 | struct uart_8250_port *up = up_to_u8250p(port); | ||
573 | unsigned int iir; | ||
574 | int ret; | ||
575 | |||
576 | #ifdef CONFIG_SERIAL_8250_DMA | ||
577 | if (up->dma) { | ||
578 | ret = omap_8250_dma_handle_irq(port); | ||
579 | return IRQ_RETVAL(ret); | ||
580 | } | ||
581 | #endif | ||
582 | |||
583 | serial8250_rpm_get(up); | ||
584 | iir = serial_port_in(port, UART_IIR); | ||
585 | ret = serial8250_handle_irq(port, iir); | ||
586 | serial8250_rpm_put(up); | ||
587 | |||
588 | return IRQ_RETVAL(ret); | ||
589 | } | ||
590 | |||
565 | static int omap_8250_startup(struct uart_port *port) | 591 | static int omap_8250_startup(struct uart_port *port) |
566 | { | 592 | { |
567 | struct uart_8250_port *up = | 593 | struct uart_8250_port *up = up_to_u8250p(port); |
568 | container_of(port, struct uart_8250_port, port); | ||
569 | struct omap8250_priv *priv = port->private_data; | 594 | struct omap8250_priv *priv = port->private_data; |
570 | |||
571 | int ret; | 595 | int ret; |
572 | 596 | ||
573 | if (priv->wakeirq) { | 597 | if (priv->wakeirq) { |
@@ -580,10 +604,31 @@ static int omap_8250_startup(struct uart_port *port) | |||
580 | 604 | ||
581 | pm_runtime_get_sync(port->dev); | 605 | pm_runtime_get_sync(port->dev); |
582 | 606 | ||
583 | ret = serial8250_do_startup(port); | 607 | up->mcr = 0; |
584 | if (ret) | 608 | serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); |
609 | |||
610 | serial_out(up, UART_LCR, UART_LCR_WLEN8); | ||
611 | |||
612 | up->lsr_saved_flags = 0; | ||
613 | up->msr_saved_flags = 0; | ||
614 | |||
615 | if (up->dma) { | ||
616 | ret = serial8250_request_dma(up); | ||
617 | if (ret) { | ||
618 | dev_warn_ratelimited(port->dev, | ||
619 | "failed to request DMA\n"); | ||
620 | up->dma = NULL; | ||
621 | } | ||
622 | } | ||
623 | |||
624 | ret = request_irq(port->irq, omap8250_irq, IRQF_SHARED, | ||
625 | dev_name(port->dev), port); | ||
626 | if (ret < 0) | ||
585 | goto err; | 627 | goto err; |
586 | 628 | ||
629 | up->ier = UART_IER_RLSI | UART_IER_RDI; | ||
630 | serial_out(up, UART_IER, up->ier); | ||
631 | |||
587 | #ifdef CONFIG_PM | 632 | #ifdef CONFIG_PM |
588 | up->capabilities |= UART_CAP_RPM; | 633 | up->capabilities |= UART_CAP_RPM; |
589 | #endif | 634 | #endif |
@@ -610,8 +655,7 @@ err: | |||
610 | 655 | ||
611 | static void omap_8250_shutdown(struct uart_port *port) | 656 | static void omap_8250_shutdown(struct uart_port *port) |
612 | { | 657 | { |
613 | struct uart_8250_port *up = | 658 | struct uart_8250_port *up = up_to_u8250p(port); |
614 | container_of(port, struct uart_8250_port, port); | ||
615 | struct omap8250_priv *priv = port->private_data; | 659 | struct omap8250_priv *priv = port->private_data; |
616 | 660 | ||
617 | flush_work(&priv->qos_work); | 661 | flush_work(&priv->qos_work); |
@@ -621,11 +665,24 @@ static void omap_8250_shutdown(struct uart_port *port) | |||
621 | pm_runtime_get_sync(port->dev); | 665 | pm_runtime_get_sync(port->dev); |
622 | 666 | ||
623 | serial_out(up, UART_OMAP_WER, 0); | 667 | serial_out(up, UART_OMAP_WER, 0); |
624 | serial8250_do_shutdown(port); | 668 | |
669 | up->ier = 0; | ||
670 | serial_out(up, UART_IER, 0); | ||
671 | |||
672 | if (up->dma) | ||
673 | serial8250_release_dma(up); | ||
674 | |||
675 | /* | ||
676 | * Disable break condition and FIFOs | ||
677 | */ | ||
678 | if (up->lcr & UART_LCR_SBC) | ||
679 | serial_out(up, UART_LCR, up->lcr & ~UART_LCR_SBC); | ||
680 | serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); | ||
625 | 681 | ||
626 | pm_runtime_mark_last_busy(port->dev); | 682 | pm_runtime_mark_last_busy(port->dev); |
627 | pm_runtime_put_autosuspend(port->dev); | 683 | pm_runtime_put_autosuspend(port->dev); |
628 | 684 | ||
685 | free_irq(port->irq, port); | ||
629 | if (priv->wakeirq) | 686 | if (priv->wakeirq) |
630 | free_irq(priv->wakeirq, port); | 687 | free_irq(priv->wakeirq, port); |
631 | } | 688 | } |
@@ -974,6 +1031,13 @@ static inline int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir) | |||
974 | } | 1031 | } |
975 | #endif | 1032 | #endif |
976 | 1033 | ||
1034 | static int omap8250_no_handle_irq(struct uart_port *port) | ||
1035 | { | ||
1036 | /* IRQ has not been requested but handling irq? */ | ||
1037 | WARN_ONCE(1, "Unexpected irq handling before port startup\n"); | ||
1038 | return 0; | ||
1039 | } | ||
1040 | |||
977 | static int omap8250_probe(struct platform_device *pdev) | 1041 | static int omap8250_probe(struct platform_device *pdev) |
978 | { | 1042 | { |
979 | struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1043 | struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -1075,6 +1139,7 @@ static int omap8250_probe(struct platform_device *pdev) | |||
1075 | pm_runtime_get_sync(&pdev->dev); | 1139 | pm_runtime_get_sync(&pdev->dev); |
1076 | 1140 | ||
1077 | omap_serial_fill_features_erratas(&up, priv); | 1141 | omap_serial_fill_features_erratas(&up, priv); |
1142 | up.port.handle_irq = omap8250_no_handle_irq; | ||
1078 | #ifdef CONFIG_SERIAL_8250_DMA | 1143 | #ifdef CONFIG_SERIAL_8250_DMA |
1079 | if (pdev->dev.of_node) { | 1144 | if (pdev->dev.of_node) { |
1080 | /* | 1145 | /* |
@@ -1088,7 +1153,6 @@ static int omap8250_probe(struct platform_device *pdev) | |||
1088 | ret = of_property_count_strings(pdev->dev.of_node, "dma-names"); | 1153 | ret = of_property_count_strings(pdev->dev.of_node, "dma-names"); |
1089 | if (ret == 2) { | 1154 | if (ret == 2) { |
1090 | up.dma = &priv->omap8250_dma; | 1155 | up.dma = &priv->omap8250_dma; |
1091 | up.port.handle_irq = omap_8250_dma_handle_irq; | ||
1092 | priv->omap8250_dma.fn = the_no_dma_filter_fn; | 1156 | priv->omap8250_dma.fn = the_no_dma_filter_fn; |
1093 | priv->omap8250_dma.tx_dma = omap_8250_tx_dma; | 1157 | priv->omap8250_dma.tx_dma = omap_8250_tx_dma; |
1094 | priv->omap8250_dma.rx_dma = omap_8250_rx_dma; | 1158 | priv->omap8250_dma.rx_dma = omap_8250_rx_dma; |