aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/jsm
diff options
context:
space:
mode:
authorKonrad Zapalowicz <bergo.torino@gmail.com>2014-11-06 18:05:32 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-11-06 18:17:34 -0500
commit95db1ccb15ae3703f751891ce1ee8f7734c21c96 (patch)
treed3fc5bf6136857fa9baecfa24ed189ab9542d08f /drivers/tty/serial/jsm
parentc904375d4b15122c225c1073fd7a56bd541b0ce5 (diff)
drivers: serial: jsm: Add the Classic board implementation
This commit adds the Digi Classic board implementation to the staging/jsm driver. The code here is taken from the staging/dgnc driver and modified to match the serial/jsm state. This work is mostly based on the changes that has been done to the code handling the Digi Neo cards with the inspiration coming from the diff between staging/dgnc and serial/jsm as well as the LKML history for the jsm_neo.c The code compiles now and has no sparse and checkpatch errors or warnings. Signed-off-by: Konrad Zapalowicz <bergo.torino@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/jsm')
-rw-r--r--drivers/tty/serial/jsm/Makefile2
-rw-r--r--drivers/tty/serial/jsm/jsm.h3
-rw-r--r--drivers/tty/serial/jsm/jsm_cls.c990
3 files changed, 993 insertions, 2 deletions
diff --git a/drivers/tty/serial/jsm/Makefile b/drivers/tty/serial/jsm/Makefile
index e46b6e0f8b18..705d1ff6fdeb 100644
--- a/drivers/tty/serial/jsm/Makefile
+++ b/drivers/tty/serial/jsm/Makefile
@@ -4,5 +4,5 @@
4 4
5obj-$(CONFIG_SERIAL_JSM) += jsm.o 5obj-$(CONFIG_SERIAL_JSM) += jsm.o
6 6
7jsm-objs := jsm_driver.o jsm_neo.o jsm_tty.o 7jsm-objs := jsm_driver.o jsm_neo.o jsm_tty.o jsm_cls.o
8 8
diff --git a/drivers/tty/serial/jsm/jsm.h b/drivers/tty/serial/jsm/jsm.h
index 9861639d838f..309428273571 100644
--- a/drivers/tty/serial/jsm/jsm.h
+++ b/drivers/tty/serial/jsm/jsm.h
@@ -189,7 +189,7 @@ struct jsm_board
189#define CH_LOOPBACK 0x2000 /* Channel is in lookback mode */ 189#define CH_LOOPBACK 0x2000 /* Channel is in lookback mode */
190#define CH_BAUD0 0x08000 /* Used for checking B0 transitions */ 190#define CH_BAUD0 0x08000 /* Used for checking B0 transitions */
191 191
192/* Our Read/Error/Write queue sizes */ 192/* Our Read/Error queue sizes */
193#define RQUEUEMASK 0x1FFF /* 8 K - 1 */ 193#define RQUEUEMASK 0x1FFF /* 8 K - 1 */
194#define EQUEUEMASK 0x1FFF /* 8 K - 1 */ 194#define EQUEUEMASK 0x1FFF /* 8 K - 1 */
195#define RQUEUESIZE (RQUEUEMASK + 1) 195#define RQUEUESIZE (RQUEUEMASK + 1)
@@ -431,6 +431,7 @@ struct neo_uart_struct {
431 */ 431 */
432extern struct uart_driver jsm_uart_driver; 432extern struct uart_driver jsm_uart_driver;
433extern struct board_ops jsm_neo_ops; 433extern struct board_ops jsm_neo_ops;
434extern struct board_ops jsm_cls_ops;
434extern int jsm_debug; 435extern int jsm_debug;
435 436
436/************************************************************************* 437/*************************************************************************
diff --git a/drivers/tty/serial/jsm/jsm_cls.c b/drivers/tty/serial/jsm/jsm_cls.c
new file mode 100644
index 000000000000..b3a508d5608c
--- /dev/null
+++ b/drivers/tty/serial/jsm/jsm_cls.c
@@ -0,0 +1,990 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *
20 * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
21 *
22 * This is shared code between Digi's CVS archive and the
23 * Linux Kernel sources.
24 * Changing the source just for reformatting needlessly breaks
25 * our CVS diff history.
26 *
27 * Send any bug fixes/changes to: Eng.Linux at digi dot com.
28 * Thank you.
29 *
30 */
31
32#include <linux/delay.h> /* For udelay */
33#include <linux/io.h> /* For read[bwl]/write[bwl] */
34#include <linux/serial.h> /* For struct async_serial */
35#include <linux/serial_reg.h> /* For the various UART offsets */
36#include <linux/pci.h>
37#include <linux/tty.h>
38
39#include "jsm.h" /* Driver main header file */
40
41static struct {
42 unsigned int rate;
43 unsigned int cflag;
44} baud_rates[] = {
45 { 921600, B921600 },
46 { 460800, B460800 },
47 { 230400, B230400 },
48 { 115200, B115200 },
49 { 57600, B57600 },
50 { 38400, B38400 },
51 { 19200, B19200 },
52 { 9600, B9600 },
53 { 4800, B4800 },
54 { 2400, B2400 },
55 { 1200, B1200 },
56 { 600, B600 },
57 { 300, B300 },
58 { 200, B200 },
59 { 150, B150 },
60 { 134, B134 },
61 { 110, B110 },
62 { 75, B75 },
63 { 50, B50 },
64};
65
66static void cls_set_cts_flow_control(struct jsm_channel *ch)
67{
68 u8 lcrb = readb(&ch->ch_cls_uart->lcr);
69 u8 ier = readb(&ch->ch_cls_uart->ier);
70 u8 isr_fcr = 0;
71
72 /*
73 * The Enhanced Register Set may only be accessed when
74 * the Line Control Register is set to 0xBFh.
75 */
76 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
77
78 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
79
80 /* Turn on CTS flow control, turn off IXON flow control */
81 isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_CTSDSR);
82 isr_fcr &= ~(UART_EXAR654_EFR_IXON);
83
84 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
85
86 /* Write old LCR value back out, which turns enhanced access off */
87 writeb(lcrb, &ch->ch_cls_uart->lcr);
88
89 /*
90 * Enable interrupts for CTS flow, turn off interrupts for
91 * received XOFF chars
92 */
93 ier |= (UART_EXAR654_IER_CTSDSR);
94 ier &= ~(UART_EXAR654_IER_XOFF);
95 writeb(ier, &ch->ch_cls_uart->ier);
96
97 /* Set the usual FIFO values */
98 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
99
100 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_56 |
101 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
102 &ch->ch_cls_uart->isr_fcr);
103
104 ch->ch_t_tlevel = 16;
105}
106
107static void cls_set_ixon_flow_control(struct jsm_channel *ch)
108{
109 u8 lcrb = readb(&ch->ch_cls_uart->lcr);
110 u8 ier = readb(&ch->ch_cls_uart->ier);
111 u8 isr_fcr = 0;
112
113 /*
114 * The Enhanced Register Set may only be accessed when
115 * the Line Control Register is set to 0xBFh.
116 */
117 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
118
119 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
120
121 /* Turn on IXON flow control, turn off CTS flow control */
122 isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_IXON);
123 isr_fcr &= ~(UART_EXAR654_EFR_CTSDSR);
124
125 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
126
127 /* Now set our current start/stop chars while in enhanced mode */
128 writeb(ch->ch_startc, &ch->ch_cls_uart->mcr);
129 writeb(0, &ch->ch_cls_uart->lsr);
130 writeb(ch->ch_stopc, &ch->ch_cls_uart->msr);
131 writeb(0, &ch->ch_cls_uart->spr);
132
133 /* Write old LCR value back out, which turns enhanced access off */
134 writeb(lcrb, &ch->ch_cls_uart->lcr);
135
136 /*
137 * Disable interrupts for CTS flow, turn on interrupts for
138 * received XOFF chars
139 */
140 ier &= ~(UART_EXAR654_IER_CTSDSR);
141 ier |= (UART_EXAR654_IER_XOFF);
142 writeb(ier, &ch->ch_cls_uart->ier);
143
144 /* Set the usual FIFO values */
145 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
146
147 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
148 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
149 &ch->ch_cls_uart->isr_fcr);
150}
151
152static void cls_set_no_output_flow_control(struct jsm_channel *ch)
153{
154 u8 lcrb = readb(&ch->ch_cls_uart->lcr);
155 u8 ier = readb(&ch->ch_cls_uart->ier);
156 u8 isr_fcr = 0;
157
158 /*
159 * The Enhanced Register Set may only be accessed when
160 * the Line Control Register is set to 0xBFh.
161 */
162 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
163
164 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
165
166 /* Turn off IXON flow control, turn off CTS flow control */
167 isr_fcr |= (UART_EXAR654_EFR_ECB);
168 isr_fcr &= ~(UART_EXAR654_EFR_CTSDSR | UART_EXAR654_EFR_IXON);
169
170 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
171
172 /* Write old LCR value back out, which turns enhanced access off */
173 writeb(lcrb, &ch->ch_cls_uart->lcr);
174
175 /*
176 * Disable interrupts for CTS flow, turn off interrupts for
177 * received XOFF chars
178 */
179 ier &= ~(UART_EXAR654_IER_CTSDSR);
180 ier &= ~(UART_EXAR654_IER_XOFF);
181 writeb(ier, &ch->ch_cls_uart->ier);
182
183 /* Set the usual FIFO values */
184 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
185
186 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
187 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
188 &ch->ch_cls_uart->isr_fcr);
189
190 ch->ch_r_watermark = 0;
191 ch->ch_t_tlevel = 16;
192 ch->ch_r_tlevel = 16;
193}
194
195static void cls_set_rts_flow_control(struct jsm_channel *ch)
196{
197 u8 lcrb = readb(&ch->ch_cls_uart->lcr);
198 u8 ier = readb(&ch->ch_cls_uart->ier);
199 u8 isr_fcr = 0;
200
201 /*
202 * The Enhanced Register Set may only be accessed when
203 * the Line Control Register is set to 0xBFh.
204 */
205 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
206
207 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
208
209 /* Turn on RTS flow control, turn off IXOFF flow control */
210 isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_RTSDTR);
211 isr_fcr &= ~(UART_EXAR654_EFR_IXOFF);
212
213 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
214
215 /* Write old LCR value back out, which turns enhanced access off */
216 writeb(lcrb, &ch->ch_cls_uart->lcr);
217
218 /* Enable interrupts for RTS flow */
219 ier |= (UART_EXAR654_IER_RTSDTR);
220 writeb(ier, &ch->ch_cls_uart->ier);
221
222 /* Set the usual FIFO values */
223 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
224
225 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_56 |
226 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
227 &ch->ch_cls_uart->isr_fcr);
228
229 ch->ch_r_watermark = 4;
230 ch->ch_r_tlevel = 8;
231}
232
233static void cls_set_ixoff_flow_control(struct jsm_channel *ch)
234{
235 u8 lcrb = readb(&ch->ch_cls_uart->lcr);
236 u8 ier = readb(&ch->ch_cls_uart->ier);
237 u8 isr_fcr = 0;
238
239 /*
240 * The Enhanced Register Set may only be accessed when
241 * the Line Control Register is set to 0xBFh.
242 */
243 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
244
245 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
246
247 /* Turn on IXOFF flow control, turn off RTS flow control */
248 isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_IXOFF);
249 isr_fcr &= ~(UART_EXAR654_EFR_RTSDTR);
250
251 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
252
253 /* Now set our current start/stop chars while in enhanced mode */
254 writeb(ch->ch_startc, &ch->ch_cls_uart->mcr);
255 writeb(0, &ch->ch_cls_uart->lsr);
256 writeb(ch->ch_stopc, &ch->ch_cls_uart->msr);
257 writeb(0, &ch->ch_cls_uart->spr);
258
259 /* Write old LCR value back out, which turns enhanced access off */
260 writeb(lcrb, &ch->ch_cls_uart->lcr);
261
262 /* Disable interrupts for RTS flow */
263 ier &= ~(UART_EXAR654_IER_RTSDTR);
264 writeb(ier, &ch->ch_cls_uart->ier);
265
266 /* Set the usual FIFO values */
267 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
268
269 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
270 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
271 &ch->ch_cls_uart->isr_fcr);
272}
273
274static void cls_set_no_input_flow_control(struct jsm_channel *ch)
275{
276 u8 lcrb = readb(&ch->ch_cls_uart->lcr);
277 u8 ier = readb(&ch->ch_cls_uart->ier);
278 u8 isr_fcr = 0;
279
280 /*
281 * The Enhanced Register Set may only be accessed when
282 * the Line Control Register is set to 0xBFh.
283 */
284 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
285
286 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
287
288 /* Turn off IXOFF flow control, turn off RTS flow control */
289 isr_fcr |= (UART_EXAR654_EFR_ECB);
290 isr_fcr &= ~(UART_EXAR654_EFR_RTSDTR | UART_EXAR654_EFR_IXOFF);
291
292 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
293
294 /* Write old LCR value back out, which turns enhanced access off */
295 writeb(lcrb, &ch->ch_cls_uart->lcr);
296
297 /* Disable interrupts for RTS flow */
298 ier &= ~(UART_EXAR654_IER_RTSDTR);
299 writeb(ier, &ch->ch_cls_uart->ier);
300
301 /* Set the usual FIFO values */
302 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
303
304 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
305 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
306 &ch->ch_cls_uart->isr_fcr);
307
308 ch->ch_t_tlevel = 16;
309 ch->ch_r_tlevel = 16;
310}
311
312/*
313 * cls_clear_break.
314 * Determines whether its time to shut off break condition.
315 *
316 * No locks are assumed to be held when calling this function.
317 * channel lock is held and released in this function.
318 */
319static void cls_clear_break(struct jsm_channel *ch, int force)
320{
321 unsigned long lock_flags;
322
323 spin_lock_irqsave(&ch->ch_lock, lock_flags);
324
325 /* Turn break off, and unset some variables */
326 if (ch->ch_flags & CH_BREAK_SENDING) {
327 u8 temp = readb(&ch->ch_cls_uart->lcr);
328
329 writeb((temp & ~UART_LCR_SBC), &ch->ch_cls_uart->lcr);
330
331 ch->ch_flags &= ~(CH_BREAK_SENDING);
332 jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,
333 "clear break Finishing UART_LCR_SBC! finished: %lx\n",
334 jiffies);
335 }
336 spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
337}
338
339static void cls_disable_receiver(struct jsm_channel *ch)
340{
341 u8 tmp = readb(&ch->ch_cls_uart->ier);
342
343 tmp &= ~(UART_IER_RDI);
344 writeb(tmp, &ch->ch_cls_uart->ier);
345}
346
347static void cls_enable_receiver(struct jsm_channel *ch)
348{
349 u8 tmp = readb(&ch->ch_cls_uart->ier);
350
351 tmp |= (UART_IER_RDI);
352 writeb(tmp, &ch->ch_cls_uart->ier);
353}
354
355/* Make the UART raise any of the output signals we want up */
356static void cls_assert_modem_signals(struct jsm_channel *ch)
357{
358 if (!ch)
359 return;
360
361 writeb(ch->ch_mostat, &ch->ch_cls_uart->mcr);
362}
363
364static void cls_copy_data_from_uart_to_queue(struct jsm_channel *ch)
365{
366 int qleft = 0;
367 u8 linestatus = 0;
368 u8 error_mask = 0;
369 u16 head;
370 u16 tail;
371 unsigned long flags;
372
373 if (!ch)
374 return;
375
376 spin_lock_irqsave(&ch->ch_lock, flags);
377
378 /* cache head and tail of queue */
379 head = ch->ch_r_head & RQUEUEMASK;
380 tail = ch->ch_r_tail & RQUEUEMASK;
381
382 /* Get our cached LSR */
383 linestatus = ch->ch_cached_lsr;
384 ch->ch_cached_lsr = 0;
385
386 /* Store how much space we have left in the queue */
387 qleft = tail - head - 1;
388 if (qleft < 0)
389 qleft += RQUEUEMASK + 1;
390
391 /*
392 * Create a mask to determine whether we should
393 * insert the character (if any) into our queue.
394 */
395 if (ch->ch_c_iflag & IGNBRK)
396 error_mask |= UART_LSR_BI;
397
398 while (1) {
399 /*
400 * Grab the linestatus register, we need to
401 * check to see if there is any data to read
402 */
403 linestatus = readb(&ch->ch_cls_uart->lsr);
404
405 /* Break out if there is no data to fetch */
406 if (!(linestatus & UART_LSR_DR))
407 break;
408
409 /*
410 * Discard character if we are ignoring the error mask
411 * which in this case is the break signal.
412 */
413 if (linestatus & error_mask) {
414 u8 discard;
415
416 linestatus = 0;
417 discard = readb(&ch->ch_cls_uart->txrx);
418 continue;
419 }
420
421 /*
422 * If our queue is full, we have no choice but to drop some
423 * data. The assumption is that HWFLOW or SWFLOW should have
424 * stopped things way way before we got to this point.
425 *
426 * I decided that I wanted to ditch the oldest data first,
427 * I hope thats okay with everyone? Yes? Good.
428 */
429 while (qleft < 1) {
430 tail = (tail + 1) & RQUEUEMASK;
431 ch->ch_r_tail = tail;
432 ch->ch_err_overrun++;
433 qleft++;
434 }
435
436 ch->ch_equeue[head] = linestatus & (UART_LSR_BI | UART_LSR_PE
437 | UART_LSR_FE);
438 ch->ch_rqueue[head] = readb(&ch->ch_cls_uart->txrx);
439
440 qleft--;
441
442 if (ch->ch_equeue[head] & UART_LSR_PE)
443 ch->ch_err_parity++;
444 if (ch->ch_equeue[head] & UART_LSR_BI)
445 ch->ch_err_break++;
446 if (ch->ch_equeue[head] & UART_LSR_FE)
447 ch->ch_err_frame++;
448
449 /* Add to, and flip head if needed */
450 head = (head + 1) & RQUEUEMASK;
451 ch->ch_rxcount++;
452 }
453
454 /*
455 * Write new final heads to channel structure.
456 */
457 ch->ch_r_head = head & RQUEUEMASK;
458 ch->ch_e_head = head & EQUEUEMASK;
459
460 spin_unlock_irqrestore(&ch->ch_lock, flags);
461}
462
463static void cls_copy_data_from_queue_to_uart(struct jsm_channel *ch)
464{
465 u16 tail;
466 int n;
467 int qlen;
468 u32 len_written = 0;
469 struct circ_buf *circ;
470
471 if (!ch)
472 return;
473
474 circ = &ch->uart_port.state->xmit;
475
476 /* No data to write to the UART */
477 if (uart_circ_empty(circ))
478 return;
479
480 /* If port is "stopped", don't send any data to the UART */
481 if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_BREAK_SENDING))
482 return;
483
484 /* We have to do it this way, because of the EXAR TXFIFO count bug. */
485 if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM)))
486 return;
487
488 n = 32;
489
490 /* cache tail of queue */
491 tail = circ->tail & (UART_XMIT_SIZE - 1);
492 qlen = uart_circ_chars_pending(circ);
493
494 /* Find minimum of the FIFO space, versus queue length */
495 n = min(n, qlen);
496
497 while (n > 0) {
498 writeb(circ->buf[tail], &ch->ch_cls_uart->txrx);
499 tail = (tail + 1) & (UART_XMIT_SIZE - 1);
500 n--;
501 ch->ch_txcount++;
502 len_written++;
503 }
504
505 /* Update the final tail */
506 circ->tail = tail & (UART_XMIT_SIZE - 1);
507
508 if (len_written > ch->ch_t_tlevel)
509 ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
510
511 if (uart_circ_empty(circ))
512 uart_write_wakeup(&ch->uart_port);
513}
514
515static void cls_parse_modem(struct jsm_channel *ch, u8 signals)
516{
517 u8 msignals = signals;
518
519 jsm_dbg(MSIGS, &ch->ch_bd->pci_dev,
520 "neo_parse_modem: port: %d msignals: %x\n",
521 ch->ch_portnum, msignals);
522
523 /*
524 * Scrub off lower bits.
525 * They signify delta's, which I don't care about
526 * Keep DDCD and DDSR though
527 */
528 msignals &= 0xf8;
529
530 if (msignals & UART_MSR_DDCD)
531 uart_handle_dcd_change(&ch->uart_port, msignals & UART_MSR_DCD);
532 if (msignals & UART_MSR_DDSR)
533 uart_handle_dcd_change(&ch->uart_port, msignals & UART_MSR_CTS);
534
535 if (msignals & UART_MSR_DCD)
536 ch->ch_mistat |= UART_MSR_DCD;
537 else
538 ch->ch_mistat &= ~UART_MSR_DCD;
539
540 if (msignals & UART_MSR_DSR)
541 ch->ch_mistat |= UART_MSR_DSR;
542 else
543 ch->ch_mistat &= ~UART_MSR_DSR;
544
545 if (msignals & UART_MSR_RI)
546 ch->ch_mistat |= UART_MSR_RI;
547 else
548 ch->ch_mistat &= ~UART_MSR_RI;
549
550 if (msignals & UART_MSR_CTS)
551 ch->ch_mistat |= UART_MSR_CTS;
552 else
553 ch->ch_mistat &= ~UART_MSR_CTS;
554
555 jsm_dbg(MSIGS, &ch->ch_bd->pci_dev,
556 "Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
557 ch->ch_portnum,
558 !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR),
559 !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS),
560 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_CTS),
561 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DSR),
562 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_RI),
563 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DCD));
564}
565
566/* Parse the ISR register for the specific port */
567static inline void cls_parse_isr(struct jsm_board *brd, uint port)
568{
569 struct jsm_channel *ch;
570 u8 isr = 0;
571 unsigned long flags;
572
573 /*
574 * No need to verify board pointer, it was already
575 * verified in the interrupt routine.
576 */
577
578 if (port > brd->nasync)
579 return;
580
581 ch = brd->channels[port];
582 if (!ch)
583 return;
584
585 /* Here we try to figure out what caused the interrupt to happen */
586 while (1) {
587 isr = readb(&ch->ch_cls_uart->isr_fcr);
588
589 /* Bail if no pending interrupt on port */
590 if (isr & UART_IIR_NO_INT)
591 break;
592
593 /* Receive Interrupt pending */
594 if (isr & (UART_IIR_RDI | UART_IIR_RDI_TIMEOUT)) {
595 /* Read data from uart -> queue */
596 cls_copy_data_from_uart_to_queue(ch);
597 jsm_check_queue_flow_control(ch);
598 }
599
600 /* Transmit Hold register empty pending */
601 if (isr & UART_IIR_THRI) {
602 /* Transfer data (if any) from Write Queue -> UART. */
603 spin_lock_irqsave(&ch->ch_lock, flags);
604 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
605 spin_unlock_irqrestore(&ch->ch_lock, flags);
606 cls_copy_data_from_queue_to_uart(ch);
607 }
608
609 /*
610 * CTS/RTS change of state:
611 * Don't need to do anything, the cls_parse_modem
612 * below will grab the updated modem signals.
613 */
614
615 /* Parse any modem signal changes */
616 cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr));
617 }
618}
619
620/* Channel lock MUST be held before calling this function! */
621static void cls_flush_uart_write(struct jsm_channel *ch)
622{
623 u8 tmp = 0;
624 u8 i = 0;
625
626 if (!ch)
627 return;
628
629 writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT),
630 &ch->ch_cls_uart->isr_fcr);
631
632 for (i = 0; i < 10; i++) {
633 /* Check to see if the UART feels it completely flushed FIFO */
634 tmp = readb(&ch->ch_cls_uart->isr_fcr);
635 if (tmp & UART_FCR_CLEAR_XMIT) {
636 jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,
637 "Still flushing TX UART... i: %d\n", i);
638 udelay(10);
639 } else
640 break;
641 }
642
643 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
644}
645
646/* Channel lock MUST be held before calling this function! */
647static void cls_flush_uart_read(struct jsm_channel *ch)
648{
649 if (!ch)
650 return;
651
652 /*
653 * For complete POSIX compatibility, we should be purging the
654 * read FIFO in the UART here.
655 *
656 * However, clearing the read FIFO (UART_FCR_CLEAR_RCVR) also
657 * incorrectly flushes write data as well as just basically trashing the
658 * FIFO.
659 *
660 * Presumably, this is a bug in this UART.
661 */
662
663 udelay(10);
664}
665
666static void cls_send_start_character(struct jsm_channel *ch)
667{
668 if (!ch)
669 return;
670
671 if (ch->ch_startc != __DISABLED_CHAR) {
672 ch->ch_xon_sends++;
673 writeb(ch->ch_startc, &ch->ch_cls_uart->txrx);
674 }
675}
676
677static void cls_send_stop_character(struct jsm_channel *ch)
678{
679 if (!ch)
680 return;
681
682 if (ch->ch_stopc != __DISABLED_CHAR) {
683 ch->ch_xoff_sends++;
684 writeb(ch->ch_stopc, &ch->ch_cls_uart->txrx);
685 }
686}
687
688/*
689 * cls_param()
690 * Send any/all changes to the line to the UART.
691 */
692static void cls_param(struct jsm_channel *ch)
693{
694 u8 lcr = 0;
695 u8 uart_lcr = 0;
696 u8 ier = 0;
697 u32 baud = 9600;
698 int quot = 0;
699 struct jsm_board *bd;
700 int i;
701 unsigned int cflag;
702
703 bd = ch->ch_bd;
704 if (!bd)
705 return;
706
707 /*
708 * If baud rate is zero, flush queues, and set mval to drop DTR.
709 */
710 if ((ch->ch_c_cflag & (CBAUD)) == 0) {
711 ch->ch_r_head = 0;
712 ch->ch_r_tail = 0;
713 ch->ch_e_head = 0;
714 ch->ch_e_tail = 0;
715
716 cls_flush_uart_write(ch);
717 cls_flush_uart_read(ch);
718
719 /* The baudrate is B0 so all modem lines are to be dropped. */
720 ch->ch_flags |= (CH_BAUD0);
721 ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);
722 cls_assert_modem_signals(ch);
723 return;
724 }
725
726 cflag = C_BAUD(ch->uart_port.state->port.tty);
727 baud = 9600;
728 for (i = 0; i < ARRAY_SIZE(baud_rates); i++) {
729 if (baud_rates[i].cflag == cflag) {
730 baud = baud_rates[i].rate;
731 break;
732 }
733 }
734
735 if (ch->ch_flags & CH_BAUD0)
736 ch->ch_flags &= ~(CH_BAUD0);
737
738 if (ch->ch_c_cflag & PARENB)
739 lcr |= UART_LCR_PARITY;
740
741 if (!(ch->ch_c_cflag & PARODD))
742 lcr |= UART_LCR_EPAR;
743
744 /*
745 * Not all platforms support mark/space parity,
746 * so this will hide behind an ifdef.
747 */
748#ifdef CMSPAR
749 if (ch->ch_c_cflag & CMSPAR)
750 lcr |= UART_LCR_SPAR;
751#endif
752
753 if (ch->ch_c_cflag & CSTOPB)
754 lcr |= UART_LCR_STOP;
755
756 switch (ch->ch_c_cflag & CSIZE) {
757 case CS5:
758 lcr |= UART_LCR_WLEN5;
759 break;
760 case CS6:
761 lcr |= UART_LCR_WLEN6;
762 break;
763 case CS7:
764 lcr |= UART_LCR_WLEN7;
765 break;
766 case CS8:
767 default:
768 lcr |= UART_LCR_WLEN8;
769 break;
770 }
771
772 ier = readb(&ch->ch_cls_uart->ier);
773 uart_lcr = readb(&ch->ch_cls_uart->lcr);
774
775 if (baud == 0)
776 baud = 9600;
777
778 quot = ch->ch_bd->bd_dividend / baud;
779
780 if (quot != 0) {
781 writeb(UART_LCR_DLAB, &ch->ch_cls_uart->lcr);
782 writeb((quot & 0xff), &ch->ch_cls_uart->txrx);
783 writeb((quot >> 8), &ch->ch_cls_uart->ier);
784 writeb(lcr, &ch->ch_cls_uart->lcr);
785 }
786
787 if (uart_lcr != lcr)
788 writeb(lcr, &ch->ch_cls_uart->lcr);
789
790 if (ch->ch_c_cflag & CREAD)
791 ier |= (UART_IER_RDI | UART_IER_RLSI);
792
793 ier |= (UART_IER_THRI | UART_IER_MSI);
794
795 writeb(ier, &ch->ch_cls_uart->ier);
796
797 if (ch->ch_c_cflag & CRTSCTS)
798 cls_set_cts_flow_control(ch);
799 else if (ch->ch_c_iflag & IXON) {
800 /*
801 * If start/stop is set to disable,
802 * then we should disable flow control.
803 */
804 if ((ch->ch_startc == __DISABLED_CHAR) ||
805 (ch->ch_stopc == __DISABLED_CHAR))
806 cls_set_no_output_flow_control(ch);
807 else
808 cls_set_ixon_flow_control(ch);
809 } else
810 cls_set_no_output_flow_control(ch);
811
812 if (ch->ch_c_cflag & CRTSCTS)
813 cls_set_rts_flow_control(ch);
814 else if (ch->ch_c_iflag & IXOFF) {
815 /*
816 * If start/stop is set to disable,
817 * then we should disable flow control.
818 */
819 if ((ch->ch_startc == __DISABLED_CHAR) ||
820 (ch->ch_stopc == __DISABLED_CHAR))
821 cls_set_no_input_flow_control(ch);
822 else
823 cls_set_ixoff_flow_control(ch);
824 } else
825 cls_set_no_input_flow_control(ch);
826
827 cls_assert_modem_signals(ch);
828
829 /* get current status of the modem signals now */
830 cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr));
831}
832
833/*
834 * cls_intr()
835 *
836 * Classic specific interrupt handler.
837 */
838static irqreturn_t cls_intr(int irq, void *voidbrd)
839{
840 struct jsm_board *brd = voidbrd;
841 unsigned long lock_flags;
842 unsigned char uart_poll;
843 uint i = 0;
844
845 /* Lock out the slow poller from running on this board. */
846 spin_lock_irqsave(&brd->bd_intr_lock, lock_flags);
847
848 /*
849 * Check the board's global interrupt offset to see if we
850 * acctually do have an interrupt pending on us.
851 */
852 uart_poll = readb(brd->re_map_membase + UART_CLASSIC_POLL_ADDR_OFFSET);
853
854 jsm_dbg(INTR, &brd->pci_dev, "%s:%d uart_poll: %x\n",
855 __FILE__, __LINE__, uart_poll);
856
857 if (!uart_poll) {
858 jsm_dbg(INTR, &brd->pci_dev,
859 "Kernel interrupted to me, but no pending interrupts...\n");
860 spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
861 return IRQ_NONE;
862 }
863
864 /* At this point, we have at least SOMETHING to service, dig further. */
865
866 /* Parse each port to find out what caused the interrupt */
867 for (i = 0; i < brd->nasync; i++)
868 cls_parse_isr(brd, i);
869
870 spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
871
872 return IRQ_HANDLED;
873}
874
875/* Inits UART */
876static void cls_uart_init(struct jsm_channel *ch)
877{
878 unsigned char lcrb = readb(&ch->ch_cls_uart->lcr);
879 unsigned char isr_fcr = 0;
880
881 writeb(0, &ch->ch_cls_uart->ier);
882
883 /*
884 * The Enhanced Register Set may only be accessed when
885 * the Line Control Register is set to 0xBFh.
886 */
887 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
888
889 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
890
891 /* Turn on Enhanced/Extended controls */
892 isr_fcr |= (UART_EXAR654_EFR_ECB);
893
894 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
895
896 /* Write old LCR value back out, which turns enhanced access off */
897 writeb(lcrb, &ch->ch_cls_uart->lcr);
898
899 /* Clear out UART and FIFO */
900 readb(&ch->ch_cls_uart->txrx);
901
902 writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT),
903 &ch->ch_cls_uart->isr_fcr);
904 udelay(10);
905
906 ch->ch_flags |= (CH_FIFO_ENABLED | CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
907
908 readb(&ch->ch_cls_uart->lsr);
909 readb(&ch->ch_cls_uart->msr);
910}
911
912/*
913 * Turns off UART.
914 */
915static void cls_uart_off(struct jsm_channel *ch)
916{
917 /* Stop all interrupts from accurring. */
918 writeb(0, &ch->ch_cls_uart->ier);
919}
920
921/*
922 * cls_get_uarts_bytes_left.
923 * Returns 0 is nothing left in the FIFO, returns 1 otherwise.
924 *
925 * The channel lock MUST be held by the calling function.
926 */
927static u32 cls_get_uart_bytes_left(struct jsm_channel *ch)
928{
929 u8 left = 0;
930 u8 lsr = readb(&ch->ch_cls_uart->lsr);
931
932 /* Determine whether the Transmitter is empty or not */
933 if (!(lsr & UART_LSR_TEMT))
934 left = 1;
935 else {
936 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
937 left = 0;
938 }
939
940 return left;
941}
942
943/*
944 * cls_send_break.
945 * Starts sending a break thru the UART.
946 *
947 * The channel lock MUST be held by the calling function.
948 */
949static void cls_send_break(struct jsm_channel *ch)
950{
951 /* Tell the UART to start sending the break */
952 if (!(ch->ch_flags & CH_BREAK_SENDING)) {
953 u8 temp = readb(&ch->ch_cls_uart->lcr);
954
955 writeb((temp | UART_LCR_SBC), &ch->ch_cls_uart->lcr);
956 ch->ch_flags |= (CH_BREAK_SENDING);
957 }
958}
959
960/*
961 * cls_send_immediate_char.
962 * Sends a specific character as soon as possible to the UART,
963 * jumping over any bytes that might be in the write queue.
964 *
965 * The channel lock MUST be held by the calling function.
966 */
967static void cls_send_immediate_char(struct jsm_channel *ch, unsigned char c)
968{
969 writeb(c, &ch->ch_cls_uart->txrx);
970}
971
972struct board_ops jsm_cls_ops = {
973 .intr = cls_intr,
974 .uart_init = cls_uart_init,
975 .uart_off = cls_uart_off,
976 .param = cls_param,
977 .assert_modem_signals = cls_assert_modem_signals,
978 .flush_uart_write = cls_flush_uart_write,
979 .flush_uart_read = cls_flush_uart_read,
980 .disable_receiver = cls_disable_receiver,
981 .enable_receiver = cls_enable_receiver,
982 .send_break = cls_send_break,
983 .clear_break = cls_clear_break,
984 .send_start_character = cls_send_start_character,
985 .send_stop_character = cls_send_stop_character,
986 .copy_data_from_queue_to_uart = cls_copy_data_from_queue_to_uart,
987 .get_uart_bytes_left = cls_get_uart_bytes_left,
988 .send_immediate_char = cls_send_immediate_char
989};
990