aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mn10300/kernel
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2011-03-18 12:54:32 -0400
committerDavid Howells <dhowells@redhat.com>2011-03-18 12:54:32 -0400
commit52885b32a5f7326d9505ca45969a695bad2459c4 (patch)
treea849c4dfad098fc42a9b5b74dcd23931cc662c00 /arch/mn10300/kernel
parent5141c46c6137f4866eb5f29e25ed0556bcc4c634 (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/kernel')
-rw-r--r--arch/mn10300/kernel/mn10300-serial.c75
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 *);
119static void mn10300_serial_config_port(struct uart_port *, int); 119static void mn10300_serial_config_port(struct uart_port *, int);
120static int mn10300_serial_verify_port(struct uart_port *, 120static int mn10300_serial_verify_port(struct uart_port *,
121 struct serial_struct *); 121 struct serial_struct *);
122#ifdef CONFIG_CONSOLE_POLL
123static void mn10300_serial_poll_put_char(struct uart_port *, unsigned char);
124static int mn10300_serial_poll_get_char(struct uart_port *);
125#endif
122 126
123static const struct uart_ops mn10300_serial_ops = { 127static 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
143static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id); 151static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id);
@@ -1634,3 +1642,70 @@ static int __init mn10300_serial_console_init(void)
1634 1642
1635console_initcall(mn10300_serial_console_init); 1643console_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 */
1650static 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 */
1679static 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 */