aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mn10300/kernel/asm-offsets.c2
-rw-r--r--arch/mn10300/kernel/mn10300-serial-low.S9
-rw-r--r--arch/mn10300/kernel/mn10300-serial.c121
-rw-r--r--arch/mn10300/kernel/mn10300-serial.h6
4 files changed, 90 insertions, 48 deletions
diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c
index 96f24fab7de6..47b3bb0c04ff 100644
--- a/arch/mn10300/kernel/asm-offsets.c
+++ b/arch/mn10300/kernel/asm-offsets.c
@@ -96,7 +96,7 @@ void foo(void)
96 OFFSET(__rx_outp, mn10300_serial_port, rx_outp); 96 OFFSET(__rx_outp, mn10300_serial_port, rx_outp);
97 OFFSET(__uart_state, mn10300_serial_port, uart.state); 97 OFFSET(__uart_state, mn10300_serial_port, uart.state);
98 OFFSET(__tx_xchar, mn10300_serial_port, tx_xchar); 98 OFFSET(__tx_xchar, mn10300_serial_port, tx_xchar);
99 OFFSET(__tx_break, mn10300_serial_port, tx_break); 99 OFFSET(__tx_flags, mn10300_serial_port, tx_flags);
100 OFFSET(__intr_flags, mn10300_serial_port, intr_flags); 100 OFFSET(__intr_flags, mn10300_serial_port, intr_flags);
101 OFFSET(__rx_icr, mn10300_serial_port, rx_icr); 101 OFFSET(__rx_icr, mn10300_serial_port, rx_icr);
102 OFFSET(__tx_icr, mn10300_serial_port, tx_icr); 102 OFFSET(__tx_icr, mn10300_serial_port, tx_icr);
diff --git a/arch/mn10300/kernel/mn10300-serial-low.S b/arch/mn10300/kernel/mn10300-serial-low.S
index dfc1b6f2fa9a..b95e76caf4fa 100644
--- a/arch/mn10300/kernel/mn10300-serial-low.S
+++ b/arch/mn10300/kernel/mn10300-serial-low.S
@@ -118,8 +118,8 @@ ENTRY(mn10300_serial_vdma_tx_handler)
118 movbu d2,(e3) # ACK the interrupt 118 movbu d2,(e3) # ACK the interrupt
119 movhu (e3),d2 # flush 119 movhu (e3),d2 # flush
120 120
121 btst 0x01,(__tx_break,a3) # handle transmit break request 121 btst 0xFF,(__tx_flags,a3) # handle transmit flags
122 bne mnsc_vdma_tx_break 122 bne mnsc_vdma_tx_flags
123 123
124 movbu (SCxSTR,e2),d2 # don't try and transmit a char if the 124 movbu (SCxSTR,e2),d2 # don't try and transmit a char if the
125 # buffer is not empty 125 # buffer is not empty
@@ -171,10 +171,13 @@ mnsc_vdma_tx_empty:
171 bset MNSCx_TX_EMPTY,(__intr_flags,a3) 171 bset MNSCx_TX_EMPTY,(__intr_flags,a3)
172 bra mnsc_vdma_tx_done 172 bra mnsc_vdma_tx_done
173 173
174mnsc_vdma_tx_break: 174mnsc_vdma_tx_flags:
175 btst MNSCx_TX_STOP,(__tx_flags,a3)
176 bne mnsc_vdma_tx_stop
175 movhu (SCxCTR,e2),d2 # turn on break mode 177 movhu (SCxCTR,e2),d2 # turn on break mode
176 or SC01CTR_BKE,d2 178 or SC01CTR_BKE,d2
177 movhu d2,(SCxCTR,e2) 179 movhu d2,(SCxCTR,e2)
180mnsc_vdma_tx_stop:
178 mov +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2 181 mov +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2
179 movhu d2,(e3) # disable transmit interrupts on this 182 movhu d2,(e3) # disable transmit interrupts on this
180 # channel 183 # channel
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c
index cac0f0da9203..587545cb7e4c 100644
--- a/arch/mn10300/kernel/mn10300-serial.c
+++ b/arch/mn10300/kernel/mn10300-serial.c
@@ -444,25 +444,53 @@ struct mn10300_serial_int mn10300_serial_int_tbl[NR_IRQS];
444 444
445static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port) 445static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port)
446{ 446{
447 unsigned long flags; 447 int retries = 100;
448 u16 x; 448 u16 x;
449 449
450 flags = arch_local_cli_save(); 450 /* nothing to do if irq isn't set up */
451 *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); 451 if (!mn10300_serial_int_tbl[port->tx_irq].port)
452 x = *port->tx_icr; 452 return;
453 arch_local_irq_restore(flags); 453
454 port->tx_flags |= MNSCx_TX_STOP;
455 mb();
456
457 /*
458 * Here we wait for the irq to be disabled. Either it already is
459 * disabled or we wait some number of retries for the VDMA handler
460 * to disable it. The retries give the VDMA handler enough time to
461 * run to completion if it was already in progress. If the VDMA IRQ
462 * is enabled but the handler is not yet running when arrive here,
463 * the STOP flag will prevent the handler from conflicting with the
464 * driver code following this loop.
465 */
466 while ((*port->tx_icr & GxICR_ENABLE) && retries-- > 0)
467 ;
468 if (retries <= 0) {
469 *port->tx_icr =
470 NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
471 x = *port->tx_icr;
472 }
454} 473}
455 474
456static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port) 475static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port)
457{ 476{
458 unsigned long flags;
459 u16 x; 477 u16 x;
460 478
461 flags = arch_local_cli_save(); 479 /* nothing to do if irq isn't set up */
480 if (!mn10300_serial_int_tbl[port->tx_irq].port)
481 return;
482
483 /* stop vdma irq if not already stopped */
484 if (!(port->tx_flags & MNSCx_TX_STOP))
485 mn10300_serial_dis_tx_intr(port);
486
487 port->tx_flags &= ~MNSCx_TX_STOP;
488 mb();
489
462 *port->tx_icr = 490 *port->tx_icr =
463 NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) | GxICR_ENABLE; 491 NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) |
492 GxICR_ENABLE | GxICR_REQUEST | GxICR_DETECT;
464 x = *port->tx_icr; 493 x = *port->tx_icr;
465 arch_local_irq_restore(flags);
466} 494}
467 495
468static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port) 496static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port)
@@ -807,8 +835,6 @@ static void mn10300_serial_start_tx(struct uart_port *_port)
807 struct mn10300_serial_port *port = 835 struct mn10300_serial_port *port =
808 container_of(_port, struct mn10300_serial_port, uart); 836 container_of(_port, struct mn10300_serial_port, uart);
809 837
810 u16 x;
811
812 _enter("%s{%lu}", 838 _enter("%s{%lu}",
813 port->name, 839 port->name,
814 CIRC_CNT(&port->uart.state->xmit.head, 840 CIRC_CNT(&port->uart.state->xmit.head,
@@ -816,14 +842,7 @@ static void mn10300_serial_start_tx(struct uart_port *_port)
816 UART_XMIT_SIZE)); 842 UART_XMIT_SIZE));
817 843
818 /* kick the virtual DMA controller */ 844 /* kick the virtual DMA controller */
819 arch_local_cli(); 845 mn10300_serial_en_tx_intr(port);
820 x = *port->tx_icr;
821 x |= GxICR_ENABLE;
822
823 if (*port->_status & SC01STR_TBF)
824 x &= ~(GxICR_REQUEST | GxICR_DETECT);
825 else
826 x |= GxICR_REQUEST | GxICR_DETECT;
827 846
828 _debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx", 847 _debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx",
829 *port->_control, *port->_intr, *port->_status, 848 *port->_control, *port->_intr, *port->_status,
@@ -831,10 +850,6 @@ static void mn10300_serial_start_tx(struct uart_port *_port)
831 (port->div_timer == MNSCx_DIV_TIMER_8BIT) ? 850 (port->div_timer == MNSCx_DIV_TIMER_8BIT) ?
832 *(volatile u8 *)port->_tmxbr : *port->_tmxbr, 851 *(volatile u8 *)port->_tmxbr : *port->_tmxbr,
833 *port->tx_icr); 852 *port->tx_icr);
834
835 *port->tx_icr = x;
836 x = *port->tx_icr;
837 arch_local_sti();
838} 853}
839 854
840/* 855/*
@@ -844,13 +859,17 @@ static void mn10300_serial_send_xchar(struct uart_port *_port, char ch)
844{ 859{
845 struct mn10300_serial_port *port = 860 struct mn10300_serial_port *port =
846 container_of(_port, struct mn10300_serial_port, uart); 861 container_of(_port, struct mn10300_serial_port, uart);
862 unsigned long flags;
847 863
848 _enter("%s,%02x", port->name, ch); 864 _enter("%s,%02x", port->name, ch);
849 865
850 if (likely(port->gdbstub)) { 866 if (likely(port->gdbstub)) {
851 port->tx_xchar = ch; 867 port->tx_xchar = ch;
852 if (ch) 868 if (ch) {
869 spin_lock_irqsave(&port->uart.lock, flags);
853 mn10300_serial_en_tx_intr(port); 870 mn10300_serial_en_tx_intr(port);
871 spin_unlock_irqrestore(&port->uart.lock, flags);
872 }
854 } 873 }
855} 874}
856 875
@@ -911,18 +930,21 @@ static void mn10300_serial_break_ctl(struct uart_port *_port, int ctl)
911{ 930{
912 struct mn10300_serial_port *port = 931 struct mn10300_serial_port *port =
913 container_of(_port, struct mn10300_serial_port, uart); 932 container_of(_port, struct mn10300_serial_port, uart);
933 unsigned long flags;
914 934
915 _enter("%s,%d", port->name, ctl); 935 _enter("%s,%d", port->name, ctl);
916 936
937 spin_lock_irqsave(&port->uart.lock, flags);
917 if (ctl) { 938 if (ctl) {
918 /* tell the virtual DMA handler to assert BREAK */ 939 /* tell the virtual DMA handler to assert BREAK */
919 port->tx_break = 1; 940 port->tx_flags |= MNSCx_TX_BREAK;
920 mn10300_serial_en_tx_intr(port); 941 mn10300_serial_en_tx_intr(port);
921 } else { 942 } else {
922 port->tx_break = 0; 943 port->tx_flags &= ~MNSCx_TX_BREAK;
923 *port->_control &= ~SC01CTR_BKE; 944 *port->_control &= ~SC01CTR_BKE;
924 mn10300_serial_en_tx_intr(port); 945 mn10300_serial_en_tx_intr(port);
925 } 946 }
947 spin_unlock_irqrestore(&port->uart.lock, flags);
926} 948}
927 949
928/* 950/*
@@ -945,6 +967,7 @@ static int mn10300_serial_startup(struct uart_port *_port)
945 return -ENOMEM; 967 return -ENOMEM;
946 968
947 port->rx_inp = port->rx_outp = 0; 969 port->rx_inp = port->rx_outp = 0;
970 port->tx_flags = 0;
948 971
949 /* finally, enable the device */ 972 /* finally, enable the device */
950 *port->_intr = SC01ICR_TI; 973 *port->_intr = SC01ICR_TI;
@@ -994,14 +1017,22 @@ error:
994 */ 1017 */
995static void mn10300_serial_shutdown(struct uart_port *_port) 1018static void mn10300_serial_shutdown(struct uart_port *_port)
996{ 1019{
1020 unsigned long flags;
997 u16 x; 1021 u16 x;
998 struct mn10300_serial_port *port = 1022 struct mn10300_serial_port *port =
999 container_of(_port, struct mn10300_serial_port, uart); 1023 container_of(_port, struct mn10300_serial_port, uart);
1000 1024
1001 _enter("%s", port->name); 1025 _enter("%s", port->name);
1002 1026
1027 spin_lock_irqsave(&_port->lock, flags);
1028 mn10300_serial_dis_tx_intr(port);
1029
1030 *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
1031 x = *port->rx_icr;
1032 port->tx_flags = 0;
1033 spin_unlock_irqrestore(&_port->lock, flags);
1034
1003 /* disable the serial port and its baud rate timer */ 1035 /* disable the serial port and its baud rate timer */
1004 port->tx_break = 0;
1005 *port->_control &= ~(SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE); 1036 *port->_control &= ~(SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE);
1006 *port->_tmxmd = 0; 1037 *port->_tmxmd = 0;
1007 1038
@@ -1016,12 +1047,8 @@ static void mn10300_serial_shutdown(struct uart_port *_port)
1016 free_irq(port->rx_irq, port); 1047 free_irq(port->rx_irq, port);
1017 free_irq(port->tx_irq, port); 1048 free_irq(port->tx_irq, port);
1018 1049
1019 arch_local_cli(); 1050 mn10300_serial_int_tbl[port->tx_irq].port = NULL;
1020 *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL); 1051 mn10300_serial_int_tbl[port->rx_irq].port = NULL;
1021 x = *port->rx_icr;
1022 *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
1023 x = *port->tx_icr;
1024 arch_local_sti();
1025} 1052}
1026 1053
1027/* 1054/*
@@ -1549,17 +1576,24 @@ static void mn10300_serial_console_write(struct console *co,
1549{ 1576{
1550 struct mn10300_serial_port *port; 1577 struct mn10300_serial_port *port;
1551 unsigned i; 1578 unsigned i;
1552 u16 scxctr, txicr, tmp; 1579 u16 scxctr;
1553 u8 tmxmd; 1580 u8 tmxmd;
1581 unsigned long flags;
1582 int locked = 1;
1554 1583
1555 port = mn10300_serial_ports[co->index]; 1584 port = mn10300_serial_ports[co->index];
1556 1585
1586 local_irq_save(flags);
1587 if (port->uart.sysrq) {
1588 /* mn10300_serial_interrupt() already took the lock */
1589 locked = 0;
1590 } else if (oops_in_progress) {
1591 locked = spin_trylock(&port->uart.lock);
1592 } else
1593 spin_lock(&port->uart.lock);
1594
1557 /* firstly hijack the serial port from the "virtual DMA" controller */ 1595 /* firstly hijack the serial port from the "virtual DMA" controller */
1558 arch_local_cli(); 1596 mn10300_serial_dis_tx_intr(port);
1559 txicr = *port->tx_icr;
1560 *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
1561 tmp = *port->tx_icr;
1562 arch_local_sti();
1563 1597
1564 /* the transmitter may be disabled */ 1598 /* the transmitter may be disabled */
1565 scxctr = *port->_control; 1599 scxctr = *port->_control;
@@ -1613,10 +1647,11 @@ static void mn10300_serial_console_write(struct console *co,
1613 if (!(scxctr & SC01CTR_TXE)) 1647 if (!(scxctr & SC01CTR_TXE))
1614 *port->_control = scxctr; 1648 *port->_control = scxctr;
1615 1649
1616 arch_local_cli(); 1650 mn10300_serial_en_tx_intr(port);
1617 *port->tx_icr = txicr; 1651
1618 tmp = *port->tx_icr; 1652 if (locked)
1619 arch_local_sti(); 1653 spin_unlock(&port->uart.lock);
1654 local_irq_restore(flags);
1620} 1655}
1621 1656
1622/* 1657/*
diff --git a/arch/mn10300/kernel/mn10300-serial.h b/arch/mn10300/kernel/mn10300-serial.h
index 6796499bf789..0004e61619a5 100644
--- a/arch/mn10300/kernel/mn10300-serial.h
+++ b/arch/mn10300/kernel/mn10300-serial.h
@@ -29,6 +29,10 @@
29#define MNSCx_TX_SPACE 0x04 29#define MNSCx_TX_SPACE 0x04
30#define MNSCx_TX_EMPTY 0x08 30#define MNSCx_TX_EMPTY 0x08
31 31
32/* tx_flags bits */
33#define MNSCx_TX_BREAK 0x01
34#define MNSCx_TX_STOP 0x02
35
32#ifndef __ASSEMBLY__ 36#ifndef __ASSEMBLY__
33 37
34struct mn10300_serial_port { 38struct mn10300_serial_port {
@@ -36,7 +40,7 @@ struct mn10300_serial_port {
36 unsigned rx_inp; /* pointer to rx input offset */ 40 unsigned rx_inp; /* pointer to rx input offset */
37 unsigned rx_outp; /* pointer to rx output offset */ 41 unsigned rx_outp; /* pointer to rx output offset */
38 u8 tx_xchar; /* high-priority XON/XOFF buffer */ 42 u8 tx_xchar; /* high-priority XON/XOFF buffer */
39 u8 tx_break; /* transmit break request */ 43 u8 tx_flags; /* transmit break/stop request */
40 u8 intr_flags; /* interrupt flags */ 44 u8 intr_flags; /* interrupt flags */
41 volatile u16 *rx_icr; /* Rx interrupt control register */ 45 volatile u16 *rx_icr; /* Rx interrupt control register */
42 volatile u16 *tx_icr; /* Tx interrupt control register */ 46 volatile u16 *tx_icr; /* Tx interrupt control register */