diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/cpm_uart/cpm_uart_core.c | 95 |
1 files changed, 94 insertions, 1 deletions
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 93e407ee08b9..1ff80de177db 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -201,6 +201,10 @@ static void cpm_uart_int_tx(struct uart_port *port) | |||
201 | cpm_uart_tx_pump(port); | 201 | cpm_uart_tx_pump(port); |
202 | } | 202 | } |
203 | 203 | ||
204 | #ifdef CONFIG_CONSOLE_POLL | ||
205 | static int serial_polled; | ||
206 | #endif | ||
207 | |||
204 | /* | 208 | /* |
205 | * Receive characters | 209 | * Receive characters |
206 | */ | 210 | */ |
@@ -222,6 +226,12 @@ static void cpm_uart_int_rx(struct uart_port *port) | |||
222 | */ | 226 | */ |
223 | bdp = pinfo->rx_cur; | 227 | bdp = pinfo->rx_cur; |
224 | for (;;) { | 228 | for (;;) { |
229 | #ifdef CONFIG_CONSOLE_POLL | ||
230 | if (unlikely(serial_polled)) { | ||
231 | serial_polled = 0; | ||
232 | return; | ||
233 | } | ||
234 | #endif | ||
225 | /* get status */ | 235 | /* get status */ |
226 | status = in_be16(&bdp->cbd_sc); | 236 | status = in_be16(&bdp->cbd_sc); |
227 | /* If this one is empty, return happy */ | 237 | /* If this one is empty, return happy */ |
@@ -253,7 +263,12 @@ static void cpm_uart_int_rx(struct uart_port *port) | |||
253 | goto handle_error; | 263 | goto handle_error; |
254 | if (uart_handle_sysrq_char(port, ch)) | 264 | if (uart_handle_sysrq_char(port, ch)) |
255 | continue; | 265 | continue; |
256 | 266 | #ifdef CONFIG_CONSOLE_POLL | |
267 | if (unlikely(serial_polled)) { | ||
268 | serial_polled = 0; | ||
269 | return; | ||
270 | } | ||
271 | #endif | ||
257 | error_return: | 272 | error_return: |
258 | tty_insert_flip_char(tty, ch, flg); | 273 | tty_insert_flip_char(tty, ch, flg); |
259 | 274 | ||
@@ -865,6 +880,80 @@ static void cpm_uart_config_port(struct uart_port *port, int flags) | |||
865 | cpm_uart_request_port(port); | 880 | cpm_uart_request_port(port); |
866 | } | 881 | } |
867 | } | 882 | } |
883 | |||
884 | #ifdef CONFIG_CONSOLE_POLL | ||
885 | /* Serial polling routines for writing and reading from the uart while | ||
886 | * in an interrupt or debug context. | ||
887 | */ | ||
888 | |||
889 | #define GDB_BUF_SIZE 512 /* power of 2, please */ | ||
890 | |||
891 | static char poll_buf[GDB_BUF_SIZE]; | ||
892 | static char *pollp; | ||
893 | static int poll_chars; | ||
894 | |||
895 | static int poll_wait_key(char *obuf, struct uart_cpm_port *pinfo) | ||
896 | { | ||
897 | u_char c, *cp; | ||
898 | volatile cbd_t *bdp; | ||
899 | int i; | ||
900 | |||
901 | /* Get the address of the host memory buffer. | ||
902 | */ | ||
903 | bdp = pinfo->rx_cur; | ||
904 | while (bdp->cbd_sc & BD_SC_EMPTY) | ||
905 | ; | ||
906 | |||
907 | /* If the buffer address is in the CPM DPRAM, don't | ||
908 | * convert it. | ||
909 | */ | ||
910 | cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); | ||
911 | |||
912 | if (obuf) { | ||
913 | i = c = bdp->cbd_datlen; | ||
914 | while (i-- > 0) | ||
915 | *obuf++ = *cp++; | ||
916 | } else | ||
917 | c = *cp; | ||
918 | bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID); | ||
919 | bdp->cbd_sc |= BD_SC_EMPTY; | ||
920 | |||
921 | if (bdp->cbd_sc & BD_SC_WRAP) | ||
922 | bdp = pinfo->rx_bd_base; | ||
923 | else | ||
924 | bdp++; | ||
925 | pinfo->rx_cur = (cbd_t *)bdp; | ||
926 | |||
927 | return (int)c; | ||
928 | } | ||
929 | |||
930 | static int cpm_get_poll_char(struct uart_port *port) | ||
931 | { | ||
932 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; | ||
933 | |||
934 | if (!serial_polled) { | ||
935 | serial_polled = 1; | ||
936 | poll_chars = 0; | ||
937 | } | ||
938 | if (poll_chars <= 0) { | ||
939 | poll_chars = poll_wait_key(poll_buf, pinfo); | ||
940 | pollp = poll_buf; | ||
941 | } | ||
942 | poll_chars--; | ||
943 | return *pollp++; | ||
944 | } | ||
945 | |||
946 | static void cpm_put_poll_char(struct uart_port *port, | ||
947 | unsigned char c) | ||
948 | { | ||
949 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; | ||
950 | static char ch[2]; | ||
951 | |||
952 | ch[0] = (char)c; | ||
953 | cpm_uart_early_write(pinfo->port.line, ch, 1); | ||
954 | } | ||
955 | #endif /* CONFIG_CONSOLE_POLL */ | ||
956 | |||
868 | static struct uart_ops cpm_uart_pops = { | 957 | static struct uart_ops cpm_uart_pops = { |
869 | .tx_empty = cpm_uart_tx_empty, | 958 | .tx_empty = cpm_uart_tx_empty, |
870 | .set_mctrl = cpm_uart_set_mctrl, | 959 | .set_mctrl = cpm_uart_set_mctrl, |
@@ -882,6 +971,10 @@ static struct uart_ops cpm_uart_pops = { | |||
882 | .request_port = cpm_uart_request_port, | 971 | .request_port = cpm_uart_request_port, |
883 | .config_port = cpm_uart_config_port, | 972 | .config_port = cpm_uart_config_port, |
884 | .verify_port = cpm_uart_verify_port, | 973 | .verify_port = cpm_uart_verify_port, |
974 | #ifdef CONFIG_CONSOLE_POLL | ||
975 | .poll_get_char = cpm_get_poll_char, | ||
976 | .poll_put_char = cpm_put_poll_char, | ||
977 | #endif | ||
885 | }; | 978 | }; |
886 | 979 | ||
887 | struct uart_cpm_port cpm_uart_ports[UART_NR]; | 980 | struct uart_cpm_port cpm_uart_ports[UART_NR]; |