diff options
author | David Howells <dhowells@redhat.com> | 2011-03-18 12:54:32 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2011-03-18 12:54:32 -0400 |
commit | 52885b32a5f7326d9505ca45969a695bad2459c4 (patch) | |
tree | a849c4dfad098fc42a9b5b74dcd23931cc662c00 /arch/mn10300 | |
parent | 5141c46c6137f4866eb5f29e25ed0556bcc4c634 (diff) |
MN10300: Allow KGDB to use the MN10300 serial ports
Allow KGDB to use the MN10300 serial ports through the polled I/O interface
provided via the TTY/serial layer and the kgdboc driver. This allows the
kernel to be started with something like:
kgdboc=ttySM0,115200
added to the command line.
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'arch/mn10300')
-rw-r--r-- | arch/mn10300/kernel/mn10300-serial.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index 93c53739cfc9..efca426a2ed4 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c | |||
@@ -119,6 +119,10 @@ static int mn10300_serial_request_port(struct uart_port *); | |||
119 | static void mn10300_serial_config_port(struct uart_port *, int); | 119 | static void mn10300_serial_config_port(struct uart_port *, int); |
120 | static int mn10300_serial_verify_port(struct uart_port *, | 120 | static int mn10300_serial_verify_port(struct uart_port *, |
121 | struct serial_struct *); | 121 | struct serial_struct *); |
122 | #ifdef CONFIG_CONSOLE_POLL | ||
123 | static void mn10300_serial_poll_put_char(struct uart_port *, unsigned char); | ||
124 | static int mn10300_serial_poll_get_char(struct uart_port *); | ||
125 | #endif | ||
122 | 126 | ||
123 | static const struct uart_ops mn10300_serial_ops = { | 127 | static const struct uart_ops mn10300_serial_ops = { |
124 | .tx_empty = mn10300_serial_tx_empty, | 128 | .tx_empty = mn10300_serial_tx_empty, |
@@ -138,6 +142,10 @@ static const struct uart_ops mn10300_serial_ops = { | |||
138 | .request_port = mn10300_serial_request_port, | 142 | .request_port = mn10300_serial_request_port, |
139 | .config_port = mn10300_serial_config_port, | 143 | .config_port = mn10300_serial_config_port, |
140 | .verify_port = mn10300_serial_verify_port, | 144 | .verify_port = mn10300_serial_verify_port, |
145 | #ifdef CONFIG_CONSOLE_POLL | ||
146 | .poll_put_char = mn10300_serial_poll_put_char, | ||
147 | .poll_get_char = mn10300_serial_poll_get_char, | ||
148 | #endif | ||
141 | }; | 149 | }; |
142 | 150 | ||
143 | static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id); | 151 | static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id); |
@@ -1634,3 +1642,70 @@ static int __init mn10300_serial_console_init(void) | |||
1634 | 1642 | ||
1635 | console_initcall(mn10300_serial_console_init); | 1643 | console_initcall(mn10300_serial_console_init); |
1636 | #endif | 1644 | #endif |
1645 | |||
1646 | #ifdef CONFIG_CONSOLE_POLL | ||
1647 | /* | ||
1648 | * Polled character reception for the kernel debugger | ||
1649 | */ | ||
1650 | static int mn10300_serial_poll_get_char(struct uart_port *_port) | ||
1651 | { | ||
1652 | struct mn10300_serial_port *port = | ||
1653 | container_of(_port, struct mn10300_serial_port, uart); | ||
1654 | unsigned ix; | ||
1655 | u8 st, ch; | ||
1656 | |||
1657 | _enter("%s", port->name); | ||
1658 | |||
1659 | do { | ||
1660 | /* pull chars out of the hat */ | ||
1661 | ix = port->rx_outp; | ||
1662 | if (ix == port->rx_inp) | ||
1663 | return NO_POLL_CHAR; | ||
1664 | |||
1665 | ch = port->rx_buffer[ix++]; | ||
1666 | st = port->rx_buffer[ix++]; | ||
1667 | smp_rmb(); | ||
1668 | port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1); | ||
1669 | |||
1670 | } while (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF)); | ||
1671 | |||
1672 | return ch; | ||
1673 | } | ||
1674 | |||
1675 | |||
1676 | /* | ||
1677 | * Polled character transmission for the kernel debugger | ||
1678 | */ | ||
1679 | static void mn10300_serial_poll_put_char(struct uart_port *_port, | ||
1680 | unsigned char ch) | ||
1681 | { | ||
1682 | struct mn10300_serial_port *port = | ||
1683 | container_of(_port, struct mn10300_serial_port, uart); | ||
1684 | u8 intr, tmp; | ||
1685 | |||
1686 | /* wait for the transmitter to finish anything it might be doing (and | ||
1687 | * this includes the virtual DMA handler, so it might take a while) */ | ||
1688 | while (*port->_status & (SC01STR_TBF | SC01STR_TXF)) | ||
1689 | continue; | ||
1690 | |||
1691 | /* disable the Tx ready interrupt */ | ||
1692 | intr = *port->_intr; | ||
1693 | *port->_intr = intr & ~SC01ICR_TI; | ||
1694 | tmp = *port->_intr; | ||
1695 | |||
1696 | if (ch == 0x0a) { | ||
1697 | *(u8 *) port->_txb = 0x0d; | ||
1698 | while (*port->_status & SC01STR_TBF) | ||
1699 | continue; | ||
1700 | } | ||
1701 | |||
1702 | *(u8 *) port->_txb = ch; | ||
1703 | while (*port->_status & SC01STR_TBF) | ||
1704 | continue; | ||
1705 | |||
1706 | /* restore the Tx interrupt flag */ | ||
1707 | *port->_intr = intr; | ||
1708 | tmp = *port->_intr; | ||
1709 | } | ||
1710 | |||
1711 | #endif /* CONFIG_CONSOLE_POLL */ | ||