diff options
-rw-r--r-- | drivers/tty/serial/pmac_zilog.c | 102 |
1 files changed, 52 insertions, 50 deletions
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index 5acd24a27d08..51941f02e936 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c | |||
@@ -216,6 +216,18 @@ static void pmz_maybe_update_regs(struct uart_pmac_port *uap) | |||
216 | } | 216 | } |
217 | } | 217 | } |
218 | 218 | ||
219 | static void pmz_interrupt_control(struct uart_pmac_port *uap, int enable) | ||
220 | { | ||
221 | if (enable) { | ||
222 | uap->curregs[1] |= INT_ALL_Rx | TxINT_ENAB; | ||
223 | if (!ZS_IS_EXTCLK(uap)) | ||
224 | uap->curregs[1] |= EXT_INT_ENAB; | ||
225 | } else { | ||
226 | uap->curregs[1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); | ||
227 | } | ||
228 | write_zsreg(uap, R1, uap->curregs[1]); | ||
229 | } | ||
230 | |||
219 | static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) | 231 | static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) |
220 | { | 232 | { |
221 | struct tty_struct *tty = NULL; | 233 | struct tty_struct *tty = NULL; |
@@ -339,9 +351,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) | |||
339 | 351 | ||
340 | return tty; | 352 | return tty; |
341 | flood: | 353 | flood: |
342 | uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); | 354 | pmz_interrupt_control(uap, 0); |
343 | write_zsreg(uap, R1, uap->curregs[R1]); | ||
344 | zssync(uap); | ||
345 | pmz_error("pmz: rx irq flood !\n"); | 355 | pmz_error("pmz: rx irq flood !\n"); |
346 | return tty; | 356 | return tty; |
347 | } | 357 | } |
@@ -990,12 +1000,9 @@ static int pmz_startup(struct uart_port *port) | |||
990 | if (ZS_IS_IRDA(uap)) | 1000 | if (ZS_IS_IRDA(uap)) |
991 | pmz_irda_reset(uap); | 1001 | pmz_irda_reset(uap); |
992 | 1002 | ||
993 | /* Enable interrupts emission from the chip */ | 1003 | /* Enable interrupt requests for the channel */ |
994 | spin_lock_irqsave(&port->lock, flags); | 1004 | spin_lock_irqsave(&port->lock, flags); |
995 | uap->curregs[R1] |= INT_ALL_Rx | TxINT_ENAB; | 1005 | pmz_interrupt_control(uap, 1); |
996 | if (!ZS_IS_EXTCLK(uap)) | ||
997 | uap->curregs[R1] |= EXT_INT_ENAB; | ||
998 | write_zsreg(uap, R1, uap->curregs[R1]); | ||
999 | spin_unlock_irqrestore(&port->lock, flags); | 1006 | spin_unlock_irqrestore(&port->lock, flags); |
1000 | 1007 | ||
1001 | pmz_debug("pmz: startup() done.\n"); | 1008 | pmz_debug("pmz: startup() done.\n"); |
@@ -1015,6 +1022,25 @@ static void pmz_shutdown(struct uart_port *port) | |||
1015 | 1022 | ||
1016 | mutex_lock(&pmz_irq_mutex); | 1023 | mutex_lock(&pmz_irq_mutex); |
1017 | 1024 | ||
1025 | spin_lock_irqsave(&port->lock, flags); | ||
1026 | |||
1027 | if (!ZS_IS_ASLEEP(uap)) { | ||
1028 | /* Disable interrupt requests for the channel */ | ||
1029 | pmz_interrupt_control(uap, 0); | ||
1030 | |||
1031 | if (!ZS_IS_CONS(uap)) { | ||
1032 | /* Disable receiver and transmitter */ | ||
1033 | uap->curregs[R3] &= ~RxENABLE; | ||
1034 | uap->curregs[R5] &= ~TxENABLE; | ||
1035 | |||
1036 | /* Disable break assertion */ | ||
1037 | uap->curregs[R5] &= ~SND_BRK; | ||
1038 | pmz_maybe_update_regs(uap); | ||
1039 | } | ||
1040 | } | ||
1041 | |||
1042 | spin_unlock_irqrestore(&port->lock, flags); | ||
1043 | |||
1018 | /* Release interrupt handler */ | 1044 | /* Release interrupt handler */ |
1019 | free_irq(uap->port.irq, uap); | 1045 | free_irq(uap->port.irq, uap); |
1020 | 1046 | ||
@@ -1025,29 +1051,8 @@ static void pmz_shutdown(struct uart_port *port) | |||
1025 | if (!ZS_IS_OPEN(uap->mate)) | 1051 | if (!ZS_IS_OPEN(uap->mate)) |
1026 | pmz_get_port_A(uap)->flags &= ~PMACZILOG_FLAG_IS_IRQ_ON; | 1052 | pmz_get_port_A(uap)->flags &= ~PMACZILOG_FLAG_IS_IRQ_ON; |
1027 | 1053 | ||
1028 | /* Disable interrupts */ | 1054 | if (!ZS_IS_ASLEEP(uap) && !ZS_IS_CONS(uap)) |
1029 | if (!ZS_IS_ASLEEP(uap)) { | 1055 | pmz_set_scc_power(uap, 0); /* Shut the chip down */ |
1030 | uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); | ||
1031 | write_zsreg(uap, R1, uap->curregs[R1]); | ||
1032 | zssync(uap); | ||
1033 | } | ||
1034 | |||
1035 | if (ZS_IS_CONS(uap) || ZS_IS_ASLEEP(uap)) { | ||
1036 | spin_unlock_irqrestore(&port->lock, flags); | ||
1037 | mutex_unlock(&pmz_irq_mutex); | ||
1038 | return; | ||
1039 | } | ||
1040 | |||
1041 | /* Disable receiver and transmitter. */ | ||
1042 | uap->curregs[R3] &= ~RxENABLE; | ||
1043 | uap->curregs[R5] &= ~TxENABLE; | ||
1044 | |||
1045 | /* Disable all interrupts and BRK assertion. */ | ||
1046 | uap->curregs[R5] &= ~SND_BRK; | ||
1047 | pmz_maybe_update_regs(uap); | ||
1048 | |||
1049 | /* Shut the chip down */ | ||
1050 | pmz_set_scc_power(uap, 0); | ||
1051 | 1056 | ||
1052 | spin_unlock_irqrestore(&port->lock, flags); | 1057 | spin_unlock_irqrestore(&port->lock, flags); |
1053 | 1058 | ||
@@ -1352,19 +1357,15 @@ static void pmz_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1352 | spin_lock_irqsave(&port->lock, flags); | 1357 | spin_lock_irqsave(&port->lock, flags); |
1353 | 1358 | ||
1354 | /* Disable IRQs on the port */ | 1359 | /* Disable IRQs on the port */ |
1355 | uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); | 1360 | pmz_interrupt_control(uap, 0); |
1356 | write_zsreg(uap, R1, uap->curregs[R1]); | ||
1357 | 1361 | ||
1358 | /* Setup new port configuration */ | 1362 | /* Setup new port configuration */ |
1359 | __pmz_set_termios(port, termios, old); | 1363 | __pmz_set_termios(port, termios, old); |
1360 | 1364 | ||
1361 | /* Re-enable IRQs on the port */ | 1365 | /* Re-enable IRQs on the port */ |
1362 | if (ZS_IS_OPEN(uap)) { | 1366 | if (ZS_IS_OPEN(uap)) |
1363 | uap->curregs[R1] |= INT_ALL_Rx | TxINT_ENAB; | 1367 | pmz_interrupt_control(uap, 1); |
1364 | if (!ZS_IS_EXTCLK(uap)) | 1368 | |
1365 | uap->curregs[R1] |= EXT_INT_ENAB; | ||
1366 | write_zsreg(uap, R1, uap->curregs[R1]); | ||
1367 | } | ||
1368 | spin_unlock_irqrestore(&port->lock, flags); | 1369 | spin_unlock_irqrestore(&port->lock, flags); |
1369 | } | 1370 | } |
1370 | 1371 | ||
@@ -1671,14 +1672,17 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state) | |||
1671 | spin_lock_irqsave(&uap->port.lock, flags); | 1672 | spin_lock_irqsave(&uap->port.lock, flags); |
1672 | 1673 | ||
1673 | if (ZS_IS_OPEN(uap) || ZS_IS_CONS(uap)) { | 1674 | if (ZS_IS_OPEN(uap) || ZS_IS_CONS(uap)) { |
1674 | /* Disable receiver and transmitter. */ | 1675 | /* Disable interrupt requests for the channel */ |
1676 | pmz_interrupt_control(uap, 0); | ||
1677 | |||
1678 | /* Disable receiver and transmitter */ | ||
1675 | uap->curregs[R3] &= ~RxENABLE; | 1679 | uap->curregs[R3] &= ~RxENABLE; |
1676 | uap->curregs[R5] &= ~TxENABLE; | 1680 | uap->curregs[R5] &= ~TxENABLE; |
1677 | 1681 | ||
1678 | /* Disable all interrupts and BRK assertion. */ | 1682 | /* Disable break assertion */ |
1679 | uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); | ||
1680 | uap->curregs[R5] &= ~SND_BRK; | 1683 | uap->curregs[R5] &= ~SND_BRK; |
1681 | pmz_load_zsregs(uap, uap->curregs); | 1684 | pmz_load_zsregs(uap, uap->curregs); |
1685 | |||
1682 | uap->flags |= PMACZILOG_FLAG_IS_ASLEEP; | 1686 | uap->flags |= PMACZILOG_FLAG_IS_ASLEEP; |
1683 | mb(); | 1687 | mb(); |
1684 | } | 1688 | } |
@@ -1738,14 +1742,6 @@ static int pmz_resume(struct macio_dev *mdev) | |||
1738 | /* Take care of config that may have changed while asleep */ | 1742 | /* Take care of config that may have changed while asleep */ |
1739 | __pmz_set_termios(&uap->port, &uap->termios_cache, NULL); | 1743 | __pmz_set_termios(&uap->port, &uap->termios_cache, NULL); |
1740 | 1744 | ||
1741 | if (ZS_IS_OPEN(uap)) { | ||
1742 | /* Enable interrupts */ | ||
1743 | uap->curregs[R1] |= INT_ALL_Rx | TxINT_ENAB; | ||
1744 | if (!ZS_IS_EXTCLK(uap)) | ||
1745 | uap->curregs[R1] |= EXT_INT_ENAB; | ||
1746 | write_zsreg(uap, R1, uap->curregs[R1]); | ||
1747 | } | ||
1748 | |||
1749 | spin_unlock_irqrestore(&uap->port.lock, flags); | 1745 | spin_unlock_irqrestore(&uap->port.lock, flags); |
1750 | 1746 | ||
1751 | if (ZS_IS_CONS(uap)) | 1747 | if (ZS_IS_CONS(uap)) |
@@ -1757,6 +1753,12 @@ static int pmz_resume(struct macio_dev *mdev) | |||
1757 | enable_irq(uap->port.irq); | 1753 | enable_irq(uap->port.irq); |
1758 | } | 1754 | } |
1759 | 1755 | ||
1756 | if (ZS_IS_OPEN(uap)) { | ||
1757 | spin_lock_irqsave(&uap->port.lock, flags); | ||
1758 | pmz_interrupt_control(uap, 1); | ||
1759 | spin_unlock_irqrestore(&uap->port.lock, flags); | ||
1760 | } | ||
1761 | |||
1760 | bail: | 1762 | bail: |
1761 | mutex_unlock(&state->port.mutex); | 1763 | mutex_unlock(&state->port.mutex); |
1762 | mutex_unlock(&pmz_irq_mutex); | 1764 | mutex_unlock(&pmz_irq_mutex); |