diff options
Diffstat (limited to 'drivers/serial/bfin_5xx.c')
-rw-r--r-- | drivers/serial/bfin_5xx.c | 222 |
1 files changed, 151 insertions, 71 deletions
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 66c92bc36f3d..6f475b609864 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
@@ -86,10 +86,8 @@ static void bfin_serial_stop_tx(struct uart_port *port) | |||
86 | { | 86 | { |
87 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | 87 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; |
88 | 88 | ||
89 | #ifdef CONFIG_BF54x | ||
90 | while (!(UART_GET_LSR(uart) & TEMT)) | 89 | while (!(UART_GET_LSR(uart) & TEMT)) |
91 | continue; | 90 | continue; |
92 | #endif | ||
93 | 91 | ||
94 | #ifdef CONFIG_SERIAL_BFIN_DMA | 92 | #ifdef CONFIG_SERIAL_BFIN_DMA |
95 | disable_dma(uart->tx_dma_channel); | 93 | disable_dma(uart->tx_dma_channel); |
@@ -128,8 +126,8 @@ static void bfin_serial_start_tx(struct uart_port *port) | |||
128 | ier = UART_GET_IER(uart); | 126 | ier = UART_GET_IER(uart); |
129 | ier |= ETBEI; | 127 | ier |= ETBEI; |
130 | UART_PUT_IER(uart, ier); | 128 | UART_PUT_IER(uart, ier); |
131 | bfin_serial_tx_chars(uart); | ||
132 | #endif | 129 | #endif |
130 | bfin_serial_tx_chars(uart); | ||
133 | #endif | 131 | #endif |
134 | } | 132 | } |
135 | 133 | ||
@@ -139,18 +137,21 @@ static void bfin_serial_start_tx(struct uart_port *port) | |||
139 | static void bfin_serial_stop_rx(struct uart_port *port) | 137 | static void bfin_serial_stop_rx(struct uart_port *port) |
140 | { | 138 | { |
141 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | 139 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; |
140 | #ifdef CONFIG_KGDB_UART | ||
141 | if (uart->port.line != CONFIG_KGDB_UART_PORT) { | ||
142 | #endif | ||
142 | #ifdef CONFIG_BF54x | 143 | #ifdef CONFIG_BF54x |
143 | UART_CLEAR_IER(uart, ERBFI); | 144 | UART_CLEAR_IER(uart, ERBFI); |
144 | #else | 145 | #else |
145 | unsigned short ier; | 146 | unsigned short ier; |
146 | 147 | ||
147 | ier = UART_GET_IER(uart); | 148 | ier = UART_GET_IER(uart); |
148 | #ifdef CONFIG_KGDB_UART | ||
149 | if (uart->port.line != CONFIG_KGDB_UART_PORT) | ||
150 | #endif | ||
151 | ier &= ~ERBFI; | 149 | ier &= ~ERBFI; |
152 | UART_PUT_IER(uart, ier); | 150 | UART_PUT_IER(uart, ier); |
153 | #endif | 151 | #endif |
152 | #ifdef CONFIG_KGDB_UART | ||
153 | } | ||
154 | #endif | ||
154 | } | 155 | } |
155 | 156 | ||
156 | /* | 157 | /* |
@@ -173,12 +174,15 @@ void kgdb_put_debug_char(int chr) | |||
173 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | 174 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; |
174 | 175 | ||
175 | while (!(UART_GET_LSR(uart) & THRE)) { | 176 | while (!(UART_GET_LSR(uart) & THRE)) { |
176 | __builtin_bfin_ssync(); | 177 | SSYNC(); |
177 | } | 178 | } |
179 | |||
180 | #ifndef CONFIG_BF54x | ||
178 | UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB)); | 181 | UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB)); |
179 | __builtin_bfin_ssync(); | 182 | SSYNC(); |
183 | #endif | ||
180 | UART_PUT_CHAR(uart, (unsigned char)chr); | 184 | UART_PUT_CHAR(uart, (unsigned char)chr); |
181 | __builtin_bfin_ssync(); | 185 | SSYNC(); |
182 | } | 186 | } |
183 | 187 | ||
184 | int kgdb_get_debug_char(void) | 188 | int kgdb_get_debug_char(void) |
@@ -192,12 +196,14 @@ int kgdb_get_debug_char(void) | |||
192 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | 196 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; |
193 | 197 | ||
194 | while(!(UART_GET_LSR(uart) & DR)) { | 198 | while(!(UART_GET_LSR(uart) & DR)) { |
195 | __builtin_bfin_ssync(); | 199 | SSYNC(); |
196 | } | 200 | } |
201 | #ifndef CONFIG_BF54x | ||
197 | UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB)); | 202 | UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB)); |
198 | __builtin_bfin_ssync(); | 203 | SSYNC(); |
204 | #endif | ||
199 | chr = UART_GET_CHAR(uart); | 205 | chr = UART_GET_CHAR(uart); |
200 | __builtin_bfin_ssync(); | 206 | SSYNC(); |
201 | 207 | ||
202 | return chr; | 208 | return chr; |
203 | } | 209 | } |
@@ -225,12 +231,10 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | |||
225 | { | 231 | { |
226 | struct tty_struct *tty = uart->port.info->tty; | 232 | struct tty_struct *tty = uart->port.info->tty; |
227 | unsigned int status, ch, flg; | 233 | unsigned int status, ch, flg; |
234 | static int in_break = 0; | ||
228 | #ifdef CONFIG_KGDB_UART | 235 | #ifdef CONFIG_KGDB_UART |
229 | struct pt_regs *regs = get_irq_regs(); | 236 | struct pt_regs *regs = get_irq_regs(); |
230 | #endif | 237 | #endif |
231 | #ifdef BF533_FAMILY | ||
232 | static int in_break = 0; | ||
233 | #endif | ||
234 | 238 | ||
235 | status = UART_GET_LSR(uart); | 239 | status = UART_GET_LSR(uart); |
236 | ch = UART_GET_CHAR(uart); | 240 | ch = UART_GET_CHAR(uart); |
@@ -256,29 +260,30 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | |||
256 | } | 260 | } |
257 | } | 261 | } |
258 | #endif | 262 | #endif |
259 | 263 | ||
260 | #ifdef BF533_FAMILY | 264 | if (ANOMALY_05000230) { |
261 | /* The BF533 family of processors have a nice misbehavior where | 265 | /* The BF533 family of processors have a nice misbehavior where |
262 | * they continuously generate characters for a "single" break. | 266 | * they continuously generate characters for a "single" break. |
263 | * We have to basically ignore this flood until the "next" valid | 267 | * We have to basically ignore this flood until the "next" valid |
264 | * character comes across. All other Blackfin families operate | 268 | * character comes across. All other Blackfin families operate |
265 | * properly though. | 269 | * properly though. |
266 | */ | 270 | * Note: While Anomaly 05000230 does not directly address this, |
267 | if (in_break) { | 271 | * the changes that went in for it also fixed this issue. |
268 | if (ch != 0) { | 272 | */ |
269 | in_break = 0; | 273 | if (in_break) { |
270 | ch = UART_GET_CHAR(uart); | 274 | if (ch != 0) { |
271 | if (bfin_revid() < 5) | 275 | in_break = 0; |
276 | ch = UART_GET_CHAR(uart); | ||
277 | if (bfin_revid() < 5) | ||
278 | return; | ||
279 | } else | ||
272 | return; | 280 | return; |
273 | } else | 281 | } |
274 | return; | ||
275 | } | 282 | } |
276 | #endif | ||
277 | 283 | ||
278 | if (status & BI) { | 284 | if (status & BI) { |
279 | #ifdef BF533_FAMILY | 285 | if (ANOMALY_05000230) |
280 | in_break = 1; | 286 | in_break = 1; |
281 | #endif | ||
282 | uart->port.icount.brk++; | 287 | uart->port.icount.brk++; |
283 | if (uart_handle_break(&uart->port)) | 288 | if (uart_handle_break(&uart->port)) |
284 | goto ignore_char; | 289 | goto ignore_char; |
@@ -697,17 +702,19 @@ static int bfin_serial_startup(struct uart_port *port) | |||
697 | uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; | 702 | uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; |
698 | add_timer(&(uart->rx_dma_timer)); | 703 | add_timer(&(uart->rx_dma_timer)); |
699 | #else | 704 | #else |
705 | if (request_irq(uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED, | ||
706 | "BFIN_UART_RX", uart)) { | ||
700 | # ifdef CONFIG_KGDB_UART | 707 | # ifdef CONFIG_KGDB_UART |
701 | if (uart->port.line != CONFIG_KGDB_UART_PORT && request_irq | 708 | if (uart->port.line != CONFIG_KGDB_UART_PORT) { |
702 | # else | ||
703 | if (request_irq | ||
704 | # endif | 709 | # endif |
705 | (uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED, | ||
706 | "BFIN_UART_RX", uart)) { | ||
707 | printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); | 710 | printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); |
708 | return -EBUSY; | 711 | return -EBUSY; |
712 | # ifdef CONFIG_KGDB_UART | ||
713 | } | ||
714 | # endif | ||
709 | } | 715 | } |
710 | 716 | ||
717 | |||
711 | if (request_irq | 718 | if (request_irq |
712 | (uart->port.irq+1, bfin_serial_tx_int, IRQF_DISABLED, | 719 | (uart->port.irq+1, bfin_serial_tx_int, IRQF_DISABLED, |
713 | "BFIN_UART_TX", uart)) { | 720 | "BFIN_UART_TX", uart)) { |
@@ -962,30 +969,6 @@ static void __init bfin_serial_init_ports(void) | |||
962 | } | 969 | } |
963 | 970 | ||
964 | #ifdef CONFIG_SERIAL_BFIN_CONSOLE | 971 | #ifdef CONFIG_SERIAL_BFIN_CONSOLE |
965 | static void bfin_serial_console_putchar(struct uart_port *port, int ch) | ||
966 | { | ||
967 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | ||
968 | while (!(UART_GET_LSR(uart) & THRE)) | ||
969 | barrier(); | ||
970 | UART_PUT_CHAR(uart, ch); | ||
971 | SSYNC(); | ||
972 | } | ||
973 | |||
974 | /* | ||
975 | * Interrupts are disabled on entering | ||
976 | */ | ||
977 | static void | ||
978 | bfin_serial_console_write(struct console *co, const char *s, unsigned int count) | ||
979 | { | ||
980 | struct bfin_serial_port *uart = &bfin_serial_ports[co->index]; | ||
981 | int flags = 0; | ||
982 | |||
983 | spin_lock_irqsave(&uart->port.lock, flags); | ||
984 | uart_console_write(&uart->port, s, count, bfin_serial_console_putchar); | ||
985 | spin_unlock_irqrestore(&uart->port.lock, flags); | ||
986 | |||
987 | } | ||
988 | |||
989 | /* | 972 | /* |
990 | * If the port was already initialised (eg, by a boot loader), | 973 | * If the port was already initialised (eg, by a boot loader), |
991 | * try to determine the current setup. | 974 | * try to determine the current setup. |
@@ -1038,19 +1021,25 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud, | |||
1038 | } | 1021 | } |
1039 | pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __FUNCTION__, *baud, *parity, *bits); | 1022 | pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __FUNCTION__, *baud, *parity, *bits); |
1040 | } | 1023 | } |
1024 | #endif | ||
1025 | |||
1026 | #if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK) | ||
1027 | static struct uart_driver bfin_serial_reg; | ||
1041 | 1028 | ||
1042 | static int __init | 1029 | static int __init |
1043 | bfin_serial_console_setup(struct console *co, char *options) | 1030 | bfin_serial_console_setup(struct console *co, char *options) |
1044 | { | 1031 | { |
1045 | struct bfin_serial_port *uart; | 1032 | struct bfin_serial_port *uart; |
1033 | # ifdef CONFIG_SERIAL_BFIN_CONSOLE | ||
1046 | int baud = 57600; | 1034 | int baud = 57600; |
1047 | int bits = 8; | 1035 | int bits = 8; |
1048 | int parity = 'n'; | 1036 | int parity = 'n'; |
1049 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | 1037 | # ifdef CONFIG_SERIAL_BFIN_CTSRTS |
1050 | int flow = 'r'; | 1038 | int flow = 'r'; |
1051 | #else | 1039 | # else |
1052 | int flow = 'n'; | 1040 | int flow = 'n'; |
1053 | #endif | 1041 | # endif |
1042 | # endif | ||
1054 | 1043 | ||
1055 | /* | 1044 | /* |
1056 | * Check whether an invalid uart number has been specified, and | 1045 | * Check whether an invalid uart number has been specified, and |
@@ -1061,15 +1050,45 @@ bfin_serial_console_setup(struct console *co, char *options) | |||
1061 | co->index = 0; | 1050 | co->index = 0; |
1062 | uart = &bfin_serial_ports[co->index]; | 1051 | uart = &bfin_serial_ports[co->index]; |
1063 | 1052 | ||
1053 | # ifdef CONFIG_SERIAL_BFIN_CONSOLE | ||
1064 | if (options) | 1054 | if (options) |
1065 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 1055 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
1066 | else | 1056 | else |
1067 | bfin_serial_console_get_options(uart, &baud, &parity, &bits); | 1057 | bfin_serial_console_get_options(uart, &baud, &parity, &bits); |
1068 | 1058 | ||
1069 | return uart_set_options(&uart->port, co, baud, parity, bits, flow); | 1059 | return uart_set_options(&uart->port, co, baud, parity, bits, flow); |
1060 | # else | ||
1061 | return 0; | ||
1062 | # endif | ||
1063 | } | ||
1064 | #endif /* defined (CONFIG_SERIAL_BFIN_CONSOLE) || | ||
1065 | defined (CONFIG_EARLY_PRINTK) */ | ||
1066 | |||
1067 | #ifdef CONFIG_SERIAL_BFIN_CONSOLE | ||
1068 | static void bfin_serial_console_putchar(struct uart_port *port, int ch) | ||
1069 | { | ||
1070 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | ||
1071 | while (!(UART_GET_LSR(uart) & THRE)) | ||
1072 | barrier(); | ||
1073 | UART_PUT_CHAR(uart, ch); | ||
1074 | SSYNC(); | ||
1075 | } | ||
1076 | |||
1077 | /* | ||
1078 | * Interrupts are disabled on entering | ||
1079 | */ | ||
1080 | static void | ||
1081 | bfin_serial_console_write(struct console *co, const char *s, unsigned int count) | ||
1082 | { | ||
1083 | struct bfin_serial_port *uart = &bfin_serial_ports[co->index]; | ||
1084 | int flags = 0; | ||
1085 | |||
1086 | spin_lock_irqsave(&uart->port.lock, flags); | ||
1087 | uart_console_write(&uart->port, s, count, bfin_serial_console_putchar); | ||
1088 | spin_unlock_irqrestore(&uart->port.lock, flags); | ||
1089 | |||
1070 | } | 1090 | } |
1071 | 1091 | ||
1072 | static struct uart_driver bfin_serial_reg; | ||
1073 | static struct console bfin_serial_console = { | 1092 | static struct console bfin_serial_console = { |
1074 | .name = BFIN_SERIAL_NAME, | 1093 | .name = BFIN_SERIAL_NAME, |
1075 | .write = bfin_serial_console_write, | 1094 | .write = bfin_serial_console_write, |
@@ -1095,7 +1114,64 @@ console_initcall(bfin_serial_rs_console_init); | |||
1095 | #define BFIN_SERIAL_CONSOLE &bfin_serial_console | 1114 | #define BFIN_SERIAL_CONSOLE &bfin_serial_console |
1096 | #else | 1115 | #else |
1097 | #define BFIN_SERIAL_CONSOLE NULL | 1116 | #define BFIN_SERIAL_CONSOLE NULL |
1098 | #endif | 1117 | #endif /* CONFIG_SERIAL_BFIN_CONSOLE */ |
1118 | |||
1119 | |||
1120 | #ifdef CONFIG_EARLY_PRINTK | ||
1121 | static __init void early_serial_putc(struct uart_port *port, int ch) | ||
1122 | { | ||
1123 | unsigned timeout = 0xffff; | ||
1124 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | ||
1125 | |||
1126 | while ((!(UART_GET_LSR(uart) & THRE)) && --timeout) | ||
1127 | cpu_relax(); | ||
1128 | UART_PUT_CHAR(uart, ch); | ||
1129 | } | ||
1130 | |||
1131 | static __init void early_serial_write(struct console *con, const char *s, | ||
1132 | unsigned int n) | ||
1133 | { | ||
1134 | struct bfin_serial_port *uart = &bfin_serial_ports[con->index]; | ||
1135 | unsigned int i; | ||
1136 | |||
1137 | for (i = 0; i < n; i++, s++) { | ||
1138 | if (*s == '\n') | ||
1139 | early_serial_putc(&uart->port, '\r'); | ||
1140 | early_serial_putc(&uart->port, *s); | ||
1141 | } | ||
1142 | } | ||
1143 | |||
1144 | static struct __init console bfin_early_serial_console = { | ||
1145 | .name = "early_BFuart", | ||
1146 | .write = early_serial_write, | ||
1147 | .device = uart_console_device, | ||
1148 | .flags = CON_PRINTBUFFER, | ||
1149 | .setup = bfin_serial_console_setup, | ||
1150 | .index = -1, | ||
1151 | .data = &bfin_serial_reg, | ||
1152 | }; | ||
1153 | |||
1154 | struct console __init *bfin_earlyserial_init(unsigned int port, | ||
1155 | unsigned int cflag) | ||
1156 | { | ||
1157 | struct bfin_serial_port *uart; | ||
1158 | struct ktermios t; | ||
1159 | |||
1160 | if (port == -1 || port >= nr_ports) | ||
1161 | port = 0; | ||
1162 | bfin_serial_init_ports(); | ||
1163 | bfin_early_serial_console.index = port; | ||
1164 | uart = &bfin_serial_ports[port]; | ||
1165 | t.c_cflag = cflag; | ||
1166 | t.c_iflag = 0; | ||
1167 | t.c_oflag = 0; | ||
1168 | t.c_lflag = ICANON; | ||
1169 | t.c_line = port; | ||
1170 | bfin_serial_set_termios(&uart->port, &t, &t); | ||
1171 | return &bfin_early_serial_console; | ||
1172 | } | ||
1173 | |||
1174 | #endif /* CONFIG_SERIAL_BFIN_CONSOLE */ | ||
1099 | 1175 | ||
1100 | static struct uart_driver bfin_serial_reg = { | 1176 | static struct uart_driver bfin_serial_reg = { |
1101 | .owner = THIS_MODULE, | 1177 | .owner = THIS_MODULE, |
@@ -1182,7 +1258,7 @@ static int __init bfin_serial_init(void) | |||
1182 | int ret; | 1258 | int ret; |
1183 | #ifdef CONFIG_KGDB_UART | 1259 | #ifdef CONFIG_KGDB_UART |
1184 | struct bfin_serial_port *uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | 1260 | struct bfin_serial_port *uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; |
1185 | struct termios t; | 1261 | struct ktermios t; |
1186 | #endif | 1262 | #endif |
1187 | 1263 | ||
1188 | pr_info("Serial: Blackfin serial driver\n"); | 1264 | pr_info("Serial: Blackfin serial driver\n"); |
@@ -1199,11 +1275,15 @@ static int __init bfin_serial_init(void) | |||
1199 | } | 1275 | } |
1200 | #ifdef CONFIG_KGDB_UART | 1276 | #ifdef CONFIG_KGDB_UART |
1201 | if (uart->port.cons->index != CONFIG_KGDB_UART_PORT) { | 1277 | if (uart->port.cons->index != CONFIG_KGDB_UART_PORT) { |
1202 | request_irq(uart->port.irq, bfin_serial_int, | 1278 | request_irq(uart->port.irq, bfin_serial_rx_int, |
1203 | IRQF_DISABLED, "BFIN_UART_RX", uart); | 1279 | IRQF_DISABLED, "BFIN_UART_RX", uart); |
1204 | pr_info("Request irq for kgdb uart port\n"); | 1280 | pr_info("Request irq for kgdb uart port\n"); |
1281 | #ifdef CONFIG_BF54x | ||
1282 | UART_SET_IER(uart, ERBFI); | ||
1283 | #else | ||
1205 | UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI); | 1284 | UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI); |
1206 | __builtin_bfin_ssync(); | 1285 | #endif |
1286 | SSYNC(); | ||
1207 | t.c_cflag = CS8|B57600; | 1287 | t.c_cflag = CS8|B57600; |
1208 | t.c_iflag = 0; | 1288 | t.c_iflag = 0; |
1209 | t.c_oflag = 0; | 1289 | t.c_oflag = 0; |