diff options
| -rw-r--r-- | drivers/serial/cpm_uart/cpm_uart_core.c | 143 |
1 files changed, 79 insertions, 64 deletions
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 9eb62a256e9a..cd6cf575902e 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
| @@ -930,6 +930,83 @@ static void cpm_uart_config_port(struct uart_port *port, int flags) | |||
| 930 | } | 930 | } |
| 931 | } | 931 | } |
| 932 | 932 | ||
| 933 | #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_CPM_CONSOLE) | ||
| 934 | /* | ||
| 935 | * Write a string to the serial port | ||
| 936 | * Note that this is called with interrupts already disabled | ||
| 937 | */ | ||
| 938 | static void cpm_uart_early_write(struct uart_cpm_port *pinfo, | ||
| 939 | const char *string, u_int count) | ||
| 940 | { | ||
| 941 | unsigned int i; | ||
| 942 | cbd_t __iomem *bdp, *bdbase; | ||
| 943 | unsigned char *cpm_outp_addr; | ||
| 944 | |||
| 945 | /* Get the address of the host memory buffer. | ||
| 946 | */ | ||
| 947 | bdp = pinfo->tx_cur; | ||
| 948 | bdbase = pinfo->tx_bd_base; | ||
| 949 | |||
| 950 | /* | ||
| 951 | * Now, do each character. This is not as bad as it looks | ||
| 952 | * since this is a holding FIFO and not a transmitting FIFO. | ||
| 953 | * We could add the complexity of filling the entire transmit | ||
| 954 | * buffer, but we would just wait longer between accesses...... | ||
| 955 | */ | ||
| 956 | for (i = 0; i < count; i++, string++) { | ||
| 957 | /* Wait for transmitter fifo to empty. | ||
| 958 | * Ready indicates output is ready, and xmt is doing | ||
| 959 | * that, not that it is ready for us to send. | ||
| 960 | */ | ||
| 961 | while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) | ||
| 962 | ; | ||
| 963 | |||
| 964 | /* Send the character out. | ||
| 965 | * If the buffer address is in the CPM DPRAM, don't | ||
| 966 | * convert it. | ||
| 967 | */ | ||
| 968 | cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), | ||
| 969 | pinfo); | ||
| 970 | *cpm_outp_addr = *string; | ||
| 971 | |||
| 972 | out_be16(&bdp->cbd_datlen, 1); | ||
| 973 | setbits16(&bdp->cbd_sc, BD_SC_READY); | ||
| 974 | |||
| 975 | if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) | ||
| 976 | bdp = bdbase; | ||
| 977 | else | ||
| 978 | bdp++; | ||
| 979 | |||
| 980 | /* if a LF, also do CR... */ | ||
| 981 | if (*string == 10) { | ||
| 982 | while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) | ||
| 983 | ; | ||
| 984 | |||
| 985 | cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), | ||
| 986 | pinfo); | ||
| 987 | *cpm_outp_addr = 13; | ||
| 988 | |||
| 989 | out_be16(&bdp->cbd_datlen, 1); | ||
| 990 | setbits16(&bdp->cbd_sc, BD_SC_READY); | ||
| 991 | |||
| 992 | if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) | ||
| 993 | bdp = bdbase; | ||
| 994 | else | ||
| 995 | bdp++; | ||
| 996 | } | ||
| 997 | } | ||
| 998 | |||
| 999 | /* | ||
| 1000 | * Finally, Wait for transmitter & holding register to empty | ||
| 1001 | * and restore the IER | ||
| 1002 | */ | ||
| 1003 | while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) | ||
| 1004 | ; | ||
| 1005 | |||
| 1006 | pinfo->tx_cur = bdp; | ||
| 1007 | } | ||
| 1008 | #endif | ||
| 1009 | |||
| 933 | #ifdef CONFIG_CONSOLE_POLL | 1010 | #ifdef CONFIG_CONSOLE_POLL |
| 934 | /* Serial polling routines for writing and reading from the uart while | 1011 | /* Serial polling routines for writing and reading from the uart while |
| 935 | * in an interrupt or debug context. | 1012 | * in an interrupt or debug context. |
| @@ -999,7 +1076,7 @@ static void cpm_put_poll_char(struct uart_port *port, | |||
| 999 | static char ch[2]; | 1076 | static char ch[2]; |
| 1000 | 1077 | ||
| 1001 | ch[0] = (char)c; | 1078 | ch[0] = (char)c; |
| 1002 | cpm_uart_early_write(pinfo->port.line, ch, 1); | 1079 | cpm_uart_early_write(pinfo, ch, 1); |
| 1003 | } | 1080 | } |
| 1004 | #endif /* CONFIG_CONSOLE_POLL */ | 1081 | #endif /* CONFIG_CONSOLE_POLL */ |
| 1005 | 1082 | ||
| @@ -1130,9 +1207,6 @@ static void cpm_uart_console_write(struct console *co, const char *s, | |||
| 1130 | u_int count) | 1207 | u_int count) |
| 1131 | { | 1208 | { |
| 1132 | struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index]; | 1209 | struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index]; |
| 1133 | unsigned int i; | ||
| 1134 | cbd_t __iomem *bdp, *bdbase; | ||
| 1135 | unsigned char *cp; | ||
| 1136 | unsigned long flags; | 1210 | unsigned long flags; |
| 1137 | int nolock = oops_in_progress; | 1211 | int nolock = oops_in_progress; |
| 1138 | 1212 | ||
| @@ -1142,66 +1216,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, | |||
| 1142 | spin_lock_irqsave(&pinfo->port.lock, flags); | 1216 | spin_lock_irqsave(&pinfo->port.lock, flags); |
| 1143 | } | 1217 | } |
| 1144 | 1218 | ||
| 1145 | /* Get the address of the host memory buffer. | 1219 | cpm_uart_early_write(pinfo, s, count); |
| 1146 | */ | ||
| 1147 | bdp = pinfo->tx_cur; | ||
| 1148 | bdbase = pinfo->tx_bd_base; | ||
| 1149 | |||
| 1150 | /* | ||
| 1151 | * Now, do each character. This is not as bad as it looks | ||
| 1152 | * since this is a holding FIFO and not a transmitting FIFO. | ||
| 1153 | * We could add the complexity of filling the entire transmit | ||
| 1154 | * buffer, but we would just wait longer between accesses...... | ||
| 1155 | */ | ||
| 1156 | for (i = 0; i < count; i++, s++) { | ||
| 1157 | /* Wait for transmitter fifo to empty. | ||
| 1158 | * Ready indicates output is ready, and xmt is doing | ||
| 1159 | * that, not that it is ready for us to send. | ||
| 1160 | */ | ||
| 1161 | while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) | ||
| 1162 | ; | ||
| 1163 | |||
| 1164 | /* Send the character out. | ||
| 1165 | * If the buffer address is in the CPM DPRAM, don't | ||
| 1166 | * convert it. | ||
| 1167 | */ | ||
| 1168 | cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo); | ||
| 1169 | *cp = *s; | ||
| 1170 | |||
| 1171 | out_be16(&bdp->cbd_datlen, 1); | ||
| 1172 | setbits16(&bdp->cbd_sc, BD_SC_READY); | ||
| 1173 | |||
| 1174 | if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) | ||
| 1175 | bdp = bdbase; | ||
| 1176 | else | ||
| 1177 | bdp++; | ||
| 1178 | |||
| 1179 | /* if a LF, also do CR... */ | ||
| 1180 | if (*s == 10) { | ||
| 1181 | while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) | ||
| 1182 | ; | ||
| 1183 | |||
| 1184 | cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo); | ||
| 1185 | *cp = 13; | ||
| 1186 | |||
| 1187 | out_be16(&bdp->cbd_datlen, 1); | ||
| 1188 | setbits16(&bdp->cbd_sc, BD_SC_READY); | ||
| 1189 | |||
| 1190 | if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) | ||
| 1191 | bdp = bdbase; | ||
| 1192 | else | ||
| 1193 | bdp++; | ||
| 1194 | } | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | /* | ||
| 1198 | * Finally, Wait for transmitter & holding register to empty | ||
| 1199 | * and restore the IER | ||
| 1200 | */ | ||
| 1201 | while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) | ||
| 1202 | ; | ||
| 1203 | |||
| 1204 | pinfo->tx_cur = bdp; | ||
| 1205 | 1220 | ||
| 1206 | if (unlikely(nolock)) { | 1221 | if (unlikely(nolock)) { |
| 1207 | local_irq_restore(flags); | 1222 | local_irq_restore(flags); |
