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 93c53739cfc..efca426a2ed 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 */ | ||
