1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI |
4 | * |
5 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) |
6 | * Copyright (C) 1998-1999 Pete Zaitcev (zaitcev@yahoo.com) |
7 | * |
8 | * This is mainly a variation of 8250.c, credits go to authors mentioned |
9 | * therein. In fact this driver should be merged into the generic 8250.c |
10 | * infrastructure perhaps using a 8250_sparc.c module. |
11 | * |
12 | * Fixed to use tty_get_baud_rate(). |
13 | * Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12 |
14 | * |
15 | * Converted to new 2.5.x UART layer. |
16 | * David S. Miller (davem@davemloft.net), 2002-Jul-29 |
17 | */ |
18 | |
19 | #include <linux/module.h> |
20 | #include <linux/kernel.h> |
21 | #include <linux/spinlock.h> |
22 | #include <linux/errno.h> |
23 | #include <linux/tty.h> |
24 | #include <linux/tty_flip.h> |
25 | #include <linux/major.h> |
26 | #include <linux/string.h> |
27 | #include <linux/ptrace.h> |
28 | #include <linux/ioport.h> |
29 | #include <linux/circ_buf.h> |
30 | #include <linux/serial.h> |
31 | #include <linux/sysrq.h> |
32 | #include <linux/console.h> |
33 | #include <linux/slab.h> |
34 | #ifdef CONFIG_SERIO |
35 | #include <linux/serio.h> |
36 | #endif |
37 | #include <linux/serial_reg.h> |
38 | #include <linux/init.h> |
39 | #include <linux/delay.h> |
40 | #include <linux/of.h> |
41 | #include <linux/platform_device.h> |
42 | |
43 | #include <linux/io.h> |
44 | #include <asm/irq.h> |
45 | #include <asm/setup.h> |
46 | |
47 | #include <linux/serial_core.h> |
48 | #include <linux/sunserialcore.h> |
49 | |
50 | /* We are on a NS PC87303 clocked with 24.0 MHz, which results |
51 | * in a UART clock of 1.8462 MHz. |
52 | */ |
53 | #define SU_BASE_BAUD (1846200 / 16) |
54 | |
55 | enum su_type { SU_PORT_NONE, SU_PORT_MS, SU_PORT_KBD, SU_PORT_PORT }; |
56 | static char *su_typev[] = { "su(???)" , "su(mouse)" , "su(kbd)" , "su(serial)" }; |
57 | |
58 | struct serial_uart_config { |
59 | char *name; |
60 | int dfl_xmit_fifo_size; |
61 | int flags; |
62 | }; |
63 | |
64 | /* |
65 | * Here we define the default xmit fifo size used for each type of UART. |
66 | */ |
67 | static const struct serial_uart_config uart_config[] = { |
68 | { "unknown" , 1, 0 }, |
69 | { "8250" , 1, 0 }, |
70 | { "16450" , 1, 0 }, |
71 | { "16550" , 1, 0 }, |
72 | { "16550A" , 16, UART_CLEAR_FIFO | UART_USE_FIFO }, |
73 | { "Cirrus" , 1, 0 }, |
74 | { "ST16650" , 1, UART_CLEAR_FIFO | UART_STARTECH }, |
75 | { "ST16650V2" , 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, |
76 | { "TI16750" , 64, UART_CLEAR_FIFO | UART_USE_FIFO }, |
77 | { "Startech" , 1, 0 }, |
78 | { "16C950/954" , 128, UART_CLEAR_FIFO | UART_USE_FIFO }, |
79 | { "ST16654" , 64, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, |
80 | { "XR16850" , 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, |
81 | { "RSA" , 2048, UART_CLEAR_FIFO | UART_USE_FIFO } |
82 | }; |
83 | |
84 | struct uart_sunsu_port { |
85 | struct uart_port port; |
86 | unsigned char acr; |
87 | unsigned char ier; |
88 | unsigned short rev; |
89 | unsigned char lcr; |
90 | unsigned int lsr_break_flag; |
91 | unsigned int cflag; |
92 | |
93 | /* Probing information. */ |
94 | enum su_type su_type; |
95 | unsigned int type_probed; /* XXX Stupid */ |
96 | unsigned long reg_size; |
97 | |
98 | #ifdef CONFIG_SERIO |
99 | struct serio serio; |
100 | int serio_open; |
101 | #endif |
102 | }; |
103 | |
104 | static unsigned int serial_in(struct uart_sunsu_port *up, int offset) |
105 | { |
106 | offset <<= up->port.regshift; |
107 | |
108 | switch (up->port.iotype) { |
109 | case UPIO_HUB6: |
110 | outb(value: up->port.hub6 - 1 + offset, port: up->port.iobase); |
111 | return inb(port: up->port.iobase + 1); |
112 | |
113 | case UPIO_MEM: |
114 | return readb(addr: up->port.membase + offset); |
115 | |
116 | default: |
117 | return inb(port: up->port.iobase + offset); |
118 | } |
119 | } |
120 | |
121 | static void serial_out(struct uart_sunsu_port *up, int offset, int value) |
122 | { |
123 | #ifndef CONFIG_SPARC64 |
124 | /* |
125 | * MrCoffee has weird schematics: IRQ4 & P10(?) pins of SuperIO are |
126 | * connected with a gate then go to SlavIO. When IRQ4 goes tristated |
127 | * gate outputs a logical one. Since we use level triggered interrupts |
128 | * we have lockup and watchdog reset. We cannot mask IRQ because |
129 | * keyboard shares IRQ with us (Word has it as Bob Smelik's design). |
130 | * This problem is similar to what Alpha people suffer, see |
131 | * 8250_alpha.c. |
132 | */ |
133 | if (offset == UART_MCR) |
134 | value |= UART_MCR_OUT2; |
135 | #endif |
136 | offset <<= up->port.regshift; |
137 | |
138 | switch (up->port.iotype) { |
139 | case UPIO_HUB6: |
140 | outb(value: up->port.hub6 - 1 + offset, port: up->port.iobase); |
141 | outb(value, port: up->port.iobase + 1); |
142 | break; |
143 | |
144 | case UPIO_MEM: |
145 | writeb(val: value, addr: up->port.membase + offset); |
146 | break; |
147 | |
148 | default: |
149 | outb(value, port: up->port.iobase + offset); |
150 | } |
151 | } |
152 | |
153 | /* |
154 | * We used to support using pause I/O for certain machines. We |
155 | * haven't supported this for a while, but just in case it's badly |
156 | * needed for certain old 386 machines, I've left these #define's |
157 | * in.... |
158 | */ |
159 | #define serial_inp(up, offset) serial_in(up, offset) |
160 | #define serial_outp(up, offset, value) serial_out(up, offset, value) |
161 | |
162 | |
163 | /* |
164 | * For the 16C950 |
165 | */ |
166 | static void serial_icr_write(struct uart_sunsu_port *up, int offset, int value) |
167 | { |
168 | serial_out(up, UART_SCR, value: offset); |
169 | serial_out(up, UART_ICR, value); |
170 | } |
171 | |
172 | #if 0 /* Unused currently */ |
173 | static unsigned int serial_icr_read(struct uart_sunsu_port *up, int offset) |
174 | { |
175 | unsigned int value; |
176 | |
177 | serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD); |
178 | serial_out(up, UART_SCR, offset); |
179 | value = serial_in(up, UART_ICR); |
180 | serial_icr_write(up, UART_ACR, up->acr); |
181 | |
182 | return value; |
183 | } |
184 | #endif |
185 | |
186 | #ifdef CONFIG_SERIAL_8250_RSA |
187 | /* |
188 | * Attempts to turn on the RSA FIFO. Returns zero on failure. |
189 | * We set the port uart clock rate if we succeed. |
190 | */ |
191 | static int __enable_rsa(struct uart_sunsu_port *up) |
192 | { |
193 | unsigned char mode; |
194 | int result; |
195 | |
196 | mode = serial_inp(up, UART_RSA_MSR); |
197 | result = mode & UART_RSA_MSR_FIFO; |
198 | |
199 | if (!result) { |
200 | serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); |
201 | mode = serial_inp(up, UART_RSA_MSR); |
202 | result = mode & UART_RSA_MSR_FIFO; |
203 | } |
204 | |
205 | if (result) |
206 | up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16; |
207 | |
208 | return result; |
209 | } |
210 | |
211 | static void enable_rsa(struct uart_sunsu_port *up) |
212 | { |
213 | if (up->port.type == PORT_RSA) { |
214 | if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) { |
215 | uart_port_lock_irq(up: &up->port); |
216 | __enable_rsa(up); |
217 | uart_port_unlock_irq(up: &up->port); |
218 | } |
219 | if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) |
220 | serial_outp(up, UART_RSA_FRR, 0); |
221 | } |
222 | } |
223 | |
224 | /* |
225 | * Attempts to turn off the RSA FIFO. Returns zero on failure. |
226 | * It is unknown why interrupts were disabled in here. However, |
227 | * the caller is expected to preserve this behaviour by grabbing |
228 | * the spinlock before calling this function. |
229 | */ |
230 | static void disable_rsa(struct uart_sunsu_port *up) |
231 | { |
232 | unsigned char mode; |
233 | int result; |
234 | |
235 | if (up->port.type == PORT_RSA && |
236 | up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) { |
237 | uart_port_lock_irq(up: &up->port); |
238 | |
239 | mode = serial_inp(up, UART_RSA_MSR); |
240 | result = !(mode & UART_RSA_MSR_FIFO); |
241 | |
242 | if (!result) { |
243 | serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); |
244 | mode = serial_inp(up, UART_RSA_MSR); |
245 | result = !(mode & UART_RSA_MSR_FIFO); |
246 | } |
247 | |
248 | if (result) |
249 | up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16; |
250 | uart_port_unlock_irq(up: &up->port); |
251 | } |
252 | } |
253 | #endif /* CONFIG_SERIAL_8250_RSA */ |
254 | |
255 | static inline void __stop_tx(struct uart_sunsu_port *p) |
256 | { |
257 | if (p->ier & UART_IER_THRI) { |
258 | p->ier &= ~UART_IER_THRI; |
259 | serial_out(up: p, UART_IER, value: p->ier); |
260 | } |
261 | } |
262 | |
263 | static void sunsu_stop_tx(struct uart_port *port) |
264 | { |
265 | struct uart_sunsu_port *up = |
266 | container_of(port, struct uart_sunsu_port, port); |
267 | |
268 | __stop_tx(p: up); |
269 | |
270 | /* |
271 | * We really want to stop the transmitter from sending. |
272 | */ |
273 | if (up->port.type == PORT_16C950) { |
274 | up->acr |= UART_ACR_TXDIS; |
275 | serial_icr_write(up, UART_ACR, value: up->acr); |
276 | } |
277 | } |
278 | |
279 | static void sunsu_start_tx(struct uart_port *port) |
280 | { |
281 | struct uart_sunsu_port *up = |
282 | container_of(port, struct uart_sunsu_port, port); |
283 | |
284 | if (!(up->ier & UART_IER_THRI)) { |
285 | up->ier |= UART_IER_THRI; |
286 | serial_out(up, UART_IER, value: up->ier); |
287 | } |
288 | |
289 | /* |
290 | * Re-enable the transmitter if we disabled it. |
291 | */ |
292 | if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) { |
293 | up->acr &= ~UART_ACR_TXDIS; |
294 | serial_icr_write(up, UART_ACR, value: up->acr); |
295 | } |
296 | } |
297 | |
298 | static void sunsu_stop_rx(struct uart_port *port) |
299 | { |
300 | struct uart_sunsu_port *up = |
301 | container_of(port, struct uart_sunsu_port, port); |
302 | |
303 | up->ier &= ~UART_IER_RLSI; |
304 | up->port.read_status_mask &= ~UART_LSR_DR; |
305 | serial_out(up, UART_IER, value: up->ier); |
306 | } |
307 | |
308 | static void sunsu_enable_ms(struct uart_port *port) |
309 | { |
310 | struct uart_sunsu_port *up = |
311 | container_of(port, struct uart_sunsu_port, port); |
312 | unsigned long flags; |
313 | |
314 | uart_port_lock_irqsave(up: &up->port, flags: &flags); |
315 | up->ier |= UART_IER_MSI; |
316 | serial_out(up, UART_IER, value: up->ier); |
317 | uart_port_unlock_irqrestore(up: &up->port, flags); |
318 | } |
319 | |
320 | static void |
321 | receive_chars(struct uart_sunsu_port *up, unsigned char *status) |
322 | { |
323 | struct tty_port *port = &up->port.state->port; |
324 | unsigned char ch, flag; |
325 | int max_count = 256; |
326 | int saw_console_brk = 0; |
327 | |
328 | do { |
329 | ch = serial_inp(up, UART_RX); |
330 | flag = TTY_NORMAL; |
331 | up->port.icount.rx++; |
332 | |
333 | if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | |
334 | UART_LSR_FE | UART_LSR_OE))) { |
335 | /* |
336 | * For statistics only |
337 | */ |
338 | if (*status & UART_LSR_BI) { |
339 | *status &= ~(UART_LSR_FE | UART_LSR_PE); |
340 | up->port.icount.brk++; |
341 | if (up->port.cons != NULL && |
342 | up->port.line == up->port.cons->index) |
343 | saw_console_brk = 1; |
344 | /* |
345 | * We do the SysRQ and SAK checking |
346 | * here because otherwise the break |
347 | * may get masked by ignore_status_mask |
348 | * or read_status_mask. |
349 | */ |
350 | if (uart_handle_break(port: &up->port)) |
351 | goto ignore_char; |
352 | } else if (*status & UART_LSR_PE) |
353 | up->port.icount.parity++; |
354 | else if (*status & UART_LSR_FE) |
355 | up->port.icount.frame++; |
356 | if (*status & UART_LSR_OE) |
357 | up->port.icount.overrun++; |
358 | |
359 | /* |
360 | * Mask off conditions which should be ingored. |
361 | */ |
362 | *status &= up->port.read_status_mask; |
363 | |
364 | if (up->port.cons != NULL && |
365 | up->port.line == up->port.cons->index) { |
366 | /* Recover the break flag from console xmit */ |
367 | *status |= up->lsr_break_flag; |
368 | up->lsr_break_flag = 0; |
369 | } |
370 | |
371 | if (*status & UART_LSR_BI) { |
372 | flag = TTY_BREAK; |
373 | } else if (*status & UART_LSR_PE) |
374 | flag = TTY_PARITY; |
375 | else if (*status & UART_LSR_FE) |
376 | flag = TTY_FRAME; |
377 | } |
378 | if (uart_handle_sysrq_char(port: &up->port, ch)) |
379 | goto ignore_char; |
380 | if ((*status & up->port.ignore_status_mask) == 0) |
381 | tty_insert_flip_char(port, ch, flag); |
382 | if (*status & UART_LSR_OE) |
383 | /* |
384 | * Overrun is special, since it's reported |
385 | * immediately, and doesn't affect the current |
386 | * character. |
387 | */ |
388 | tty_insert_flip_char(port, ch: 0, TTY_OVERRUN); |
389 | ignore_char: |
390 | *status = serial_inp(up, UART_LSR); |
391 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); |
392 | |
393 | if (saw_console_brk) |
394 | sun_do_break(); |
395 | } |
396 | |
397 | static void transmit_chars(struct uart_sunsu_port *up) |
398 | { |
399 | struct circ_buf *xmit = &up->port.state->xmit; |
400 | int count; |
401 | |
402 | if (up->port.x_char) { |
403 | serial_outp(up, UART_TX, up->port.x_char); |
404 | up->port.icount.tx++; |
405 | up->port.x_char = 0; |
406 | return; |
407 | } |
408 | if (uart_tx_stopped(port: &up->port)) { |
409 | sunsu_stop_tx(port: &up->port); |
410 | return; |
411 | } |
412 | if (uart_circ_empty(xmit)) { |
413 | __stop_tx(p: up); |
414 | return; |
415 | } |
416 | |
417 | count = up->port.fifosize; |
418 | do { |
419 | serial_out(up, UART_TX, value: xmit->buf[xmit->tail]); |
420 | uart_xmit_advance(up: &up->port, chars: 1); |
421 | if (uart_circ_empty(xmit)) |
422 | break; |
423 | } while (--count > 0); |
424 | |
425 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
426 | uart_write_wakeup(port: &up->port); |
427 | |
428 | if (uart_circ_empty(xmit)) |
429 | __stop_tx(p: up); |
430 | } |
431 | |
432 | static void check_modem_status(struct uart_sunsu_port *up) |
433 | { |
434 | int status; |
435 | |
436 | status = serial_in(up, UART_MSR); |
437 | |
438 | if ((status & UART_MSR_ANY_DELTA) == 0) |
439 | return; |
440 | |
441 | if (status & UART_MSR_TERI) |
442 | up->port.icount.rng++; |
443 | if (status & UART_MSR_DDSR) |
444 | up->port.icount.dsr++; |
445 | if (status & UART_MSR_DDCD) |
446 | uart_handle_dcd_change(uport: &up->port, active: status & UART_MSR_DCD); |
447 | if (status & UART_MSR_DCTS) |
448 | uart_handle_cts_change(uport: &up->port, active: status & UART_MSR_CTS); |
449 | |
450 | wake_up_interruptible(&up->port.state->port.delta_msr_wait); |
451 | } |
452 | |
453 | static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id) |
454 | { |
455 | struct uart_sunsu_port *up = dev_id; |
456 | unsigned long flags; |
457 | unsigned char status; |
458 | |
459 | uart_port_lock_irqsave(up: &up->port, flags: &flags); |
460 | |
461 | do { |
462 | status = serial_inp(up, UART_LSR); |
463 | if (status & UART_LSR_DR) |
464 | receive_chars(up, status: &status); |
465 | check_modem_status(up); |
466 | if (status & UART_LSR_THRE) |
467 | transmit_chars(up); |
468 | |
469 | tty_flip_buffer_push(port: &up->port.state->port); |
470 | |
471 | } while (!(serial_in(up, UART_IIR) & UART_IIR_NO_INT)); |
472 | |
473 | uart_port_unlock_irqrestore(up: &up->port, flags); |
474 | |
475 | return IRQ_HANDLED; |
476 | } |
477 | |
478 | /* Separate interrupt handling path for keyboard/mouse ports. */ |
479 | |
480 | static void |
481 | sunsu_change_speed(struct uart_port *port, unsigned int cflag, |
482 | unsigned int iflag, unsigned int quot); |
483 | |
484 | static void sunsu_change_mouse_baud(struct uart_sunsu_port *up) |
485 | { |
486 | unsigned int cur_cflag = up->cflag; |
487 | int quot, new_baud; |
488 | |
489 | up->cflag &= ~CBAUD; |
490 | up->cflag |= suncore_mouse_baud_cflag_next(cur_cflag, &new_baud); |
491 | |
492 | quot = up->port.uartclk / (16 * new_baud); |
493 | |
494 | sunsu_change_speed(port: &up->port, cflag: up->cflag, iflag: 0, quot); |
495 | } |
496 | |
497 | static void receive_kbd_ms_chars(struct uart_sunsu_port *up, int is_break) |
498 | { |
499 | do { |
500 | unsigned char ch = serial_inp(up, UART_RX); |
501 | |
502 | /* Stop-A is handled by drivers/char/keyboard.c now. */ |
503 | if (up->su_type == SU_PORT_KBD) { |
504 | #ifdef CONFIG_SERIO |
505 | serio_interrupt(serio: &up->serio, data: ch, flags: 0); |
506 | #endif |
507 | } else if (up->su_type == SU_PORT_MS) { |
508 | int ret = suncore_mouse_baud_detection(ch, is_break); |
509 | |
510 | switch (ret) { |
511 | case 2: |
512 | sunsu_change_mouse_baud(up); |
513 | fallthrough; |
514 | case 1: |
515 | break; |
516 | |
517 | case 0: |
518 | #ifdef CONFIG_SERIO |
519 | serio_interrupt(serio: &up->serio, data: ch, flags: 0); |
520 | #endif |
521 | break; |
522 | } |
523 | } |
524 | } while (serial_in(up, UART_LSR) & UART_LSR_DR); |
525 | } |
526 | |
527 | static irqreturn_t sunsu_kbd_ms_interrupt(int irq, void *dev_id) |
528 | { |
529 | struct uart_sunsu_port *up = dev_id; |
530 | |
531 | if (!(serial_in(up, UART_IIR) & UART_IIR_NO_INT)) { |
532 | unsigned char status = serial_inp(up, UART_LSR); |
533 | |
534 | if ((status & UART_LSR_DR) || (status & UART_LSR_BI)) |
535 | receive_kbd_ms_chars(up, is_break: (status & UART_LSR_BI) != 0); |
536 | } |
537 | |
538 | return IRQ_HANDLED; |
539 | } |
540 | |
541 | static unsigned int sunsu_tx_empty(struct uart_port *port) |
542 | { |
543 | struct uart_sunsu_port *up = |
544 | container_of(port, struct uart_sunsu_port, port); |
545 | unsigned long flags; |
546 | unsigned int ret; |
547 | |
548 | uart_port_lock_irqsave(up: &up->port, flags: &flags); |
549 | ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; |
550 | uart_port_unlock_irqrestore(up: &up->port, flags); |
551 | |
552 | return ret; |
553 | } |
554 | |
555 | static unsigned int sunsu_get_mctrl(struct uart_port *port) |
556 | { |
557 | struct uart_sunsu_port *up = |
558 | container_of(port, struct uart_sunsu_port, port); |
559 | unsigned char status; |
560 | unsigned int ret; |
561 | |
562 | status = serial_in(up, UART_MSR); |
563 | |
564 | ret = 0; |
565 | if (status & UART_MSR_DCD) |
566 | ret |= TIOCM_CAR; |
567 | if (status & UART_MSR_RI) |
568 | ret |= TIOCM_RNG; |
569 | if (status & UART_MSR_DSR) |
570 | ret |= TIOCM_DSR; |
571 | if (status & UART_MSR_CTS) |
572 | ret |= TIOCM_CTS; |
573 | return ret; |
574 | } |
575 | |
576 | static void sunsu_set_mctrl(struct uart_port *port, unsigned int mctrl) |
577 | { |
578 | struct uart_sunsu_port *up = |
579 | container_of(port, struct uart_sunsu_port, port); |
580 | unsigned char mcr = 0; |
581 | |
582 | if (mctrl & TIOCM_RTS) |
583 | mcr |= UART_MCR_RTS; |
584 | if (mctrl & TIOCM_DTR) |
585 | mcr |= UART_MCR_DTR; |
586 | if (mctrl & TIOCM_OUT1) |
587 | mcr |= UART_MCR_OUT1; |
588 | if (mctrl & TIOCM_OUT2) |
589 | mcr |= UART_MCR_OUT2; |
590 | if (mctrl & TIOCM_LOOP) |
591 | mcr |= UART_MCR_LOOP; |
592 | |
593 | serial_out(up, UART_MCR, value: mcr); |
594 | } |
595 | |
596 | static void sunsu_break_ctl(struct uart_port *port, int break_state) |
597 | { |
598 | struct uart_sunsu_port *up = |
599 | container_of(port, struct uart_sunsu_port, port); |
600 | unsigned long flags; |
601 | |
602 | uart_port_lock_irqsave(up: &up->port, flags: &flags); |
603 | if (break_state == -1) |
604 | up->lcr |= UART_LCR_SBC; |
605 | else |
606 | up->lcr &= ~UART_LCR_SBC; |
607 | serial_out(up, UART_LCR, value: up->lcr); |
608 | uart_port_unlock_irqrestore(up: &up->port, flags); |
609 | } |
610 | |
611 | static int sunsu_startup(struct uart_port *port) |
612 | { |
613 | struct uart_sunsu_port *up = |
614 | container_of(port, struct uart_sunsu_port, port); |
615 | unsigned long flags; |
616 | int retval; |
617 | |
618 | if (up->port.type == PORT_16C950) { |
619 | /* Wake up and initialize UART */ |
620 | up->acr = 0; |
621 | serial_outp(up, UART_LCR, 0xBF); |
622 | serial_outp(up, UART_EFR, UART_EFR_ECB); |
623 | serial_outp(up, UART_IER, 0); |
624 | serial_outp(up, UART_LCR, 0); |
625 | serial_icr_write(up, UART_CSR, value: 0); /* Reset the UART */ |
626 | serial_outp(up, UART_LCR, 0xBF); |
627 | serial_outp(up, UART_EFR, UART_EFR_ECB); |
628 | serial_outp(up, UART_LCR, 0); |
629 | } |
630 | |
631 | #ifdef CONFIG_SERIAL_8250_RSA |
632 | /* |
633 | * If this is an RSA port, see if we can kick it up to the |
634 | * higher speed clock. |
635 | */ |
636 | enable_rsa(up); |
637 | #endif |
638 | |
639 | /* |
640 | * Clear the FIFO buffers and disable them. |
641 | * (they will be reenabled in set_termios()) |
642 | */ |
643 | if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) { |
644 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); |
645 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | |
646 | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); |
647 | serial_outp(up, UART_FCR, 0); |
648 | } |
649 | |
650 | /* |
651 | * Clear the interrupt registers. |
652 | */ |
653 | (void) serial_inp(up, UART_LSR); |
654 | (void) serial_inp(up, UART_RX); |
655 | (void) serial_inp(up, UART_IIR); |
656 | (void) serial_inp(up, UART_MSR); |
657 | |
658 | /* |
659 | * At this point, there's no way the LSR could still be 0xff; |
660 | * if it is, then bail out, because there's likely no UART |
661 | * here. |
662 | */ |
663 | if (!(up->port.flags & UPF_BUGGY_UART) && |
664 | (serial_inp(up, UART_LSR) == 0xff)) { |
665 | printk("ttyS%d: LSR safety check engaged!\n" , up->port.line); |
666 | return -ENODEV; |
667 | } |
668 | |
669 | if (up->su_type != SU_PORT_PORT) { |
670 | retval = request_irq(irq: up->port.irq, handler: sunsu_kbd_ms_interrupt, |
671 | IRQF_SHARED, name: su_typev[up->su_type], dev: up); |
672 | } else { |
673 | retval = request_irq(irq: up->port.irq, handler: sunsu_serial_interrupt, |
674 | IRQF_SHARED, name: su_typev[up->su_type], dev: up); |
675 | } |
676 | if (retval) { |
677 | printk("su: Cannot register IRQ %d\n" , up->port.irq); |
678 | return retval; |
679 | } |
680 | |
681 | /* |
682 | * Now, initialize the UART |
683 | */ |
684 | serial_outp(up, UART_LCR, UART_LCR_WLEN8); |
685 | |
686 | uart_port_lock_irqsave(up: &up->port, flags: &flags); |
687 | |
688 | up->port.mctrl |= TIOCM_OUT2; |
689 | |
690 | sunsu_set_mctrl(port: &up->port, mctrl: up->port.mctrl); |
691 | uart_port_unlock_irqrestore(up: &up->port, flags); |
692 | |
693 | /* |
694 | * Finally, enable interrupts. Note: Modem status interrupts |
695 | * are set via set_termios(), which will be occurring imminently |
696 | * anyway, so we don't enable them here. |
697 | */ |
698 | up->ier = UART_IER_RLSI | UART_IER_RDI; |
699 | serial_outp(up, UART_IER, up->ier); |
700 | |
701 | if (up->port.flags & UPF_FOURPORT) { |
702 | unsigned int icp; |
703 | /* |
704 | * Enable interrupts on the AST Fourport board |
705 | */ |
706 | icp = (up->port.iobase & 0xfe0) | 0x01f; |
707 | outb_p(value: 0x80, port: icp); |
708 | (void) inb_p(port: icp); |
709 | } |
710 | |
711 | /* |
712 | * And clear the interrupt registers again for luck. |
713 | */ |
714 | (void) serial_inp(up, UART_LSR); |
715 | (void) serial_inp(up, UART_RX); |
716 | (void) serial_inp(up, UART_IIR); |
717 | (void) serial_inp(up, UART_MSR); |
718 | |
719 | return 0; |
720 | } |
721 | |
722 | static void sunsu_shutdown(struct uart_port *port) |
723 | { |
724 | struct uart_sunsu_port *up = |
725 | container_of(port, struct uart_sunsu_port, port); |
726 | unsigned long flags; |
727 | |
728 | /* |
729 | * Disable interrupts from this port |
730 | */ |
731 | up->ier = 0; |
732 | serial_outp(up, UART_IER, 0); |
733 | |
734 | uart_port_lock_irqsave(up: &up->port, flags: &flags); |
735 | if (up->port.flags & UPF_FOURPORT) { |
736 | /* reset interrupts on the AST Fourport board */ |
737 | inb(port: (up->port.iobase & 0xfe0) | 0x1f); |
738 | up->port.mctrl |= TIOCM_OUT1; |
739 | } else |
740 | up->port.mctrl &= ~TIOCM_OUT2; |
741 | |
742 | sunsu_set_mctrl(port: &up->port, mctrl: up->port.mctrl); |
743 | uart_port_unlock_irqrestore(up: &up->port, flags); |
744 | |
745 | /* |
746 | * Disable break condition and FIFOs |
747 | */ |
748 | serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC); |
749 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | |
750 | UART_FCR_CLEAR_RCVR | |
751 | UART_FCR_CLEAR_XMIT); |
752 | serial_outp(up, UART_FCR, 0); |
753 | |
754 | #ifdef CONFIG_SERIAL_8250_RSA |
755 | /* |
756 | * Reset the RSA board back to 115kbps compat mode. |
757 | */ |
758 | disable_rsa(up); |
759 | #endif |
760 | |
761 | /* |
762 | * Read data port to reset things. |
763 | */ |
764 | (void) serial_in(up, UART_RX); |
765 | |
766 | free_irq(up->port.irq, up); |
767 | } |
768 | |
769 | static void |
770 | sunsu_change_speed(struct uart_port *port, unsigned int cflag, |
771 | unsigned int iflag, unsigned int quot) |
772 | { |
773 | struct uart_sunsu_port *up = |
774 | container_of(port, struct uart_sunsu_port, port); |
775 | unsigned char cval, fcr = 0; |
776 | unsigned long flags; |
777 | |
778 | switch (cflag & CSIZE) { |
779 | case CS5: |
780 | cval = 0x00; |
781 | break; |
782 | case CS6: |
783 | cval = 0x01; |
784 | break; |
785 | case CS7: |
786 | cval = 0x02; |
787 | break; |
788 | default: |
789 | case CS8: |
790 | cval = 0x03; |
791 | break; |
792 | } |
793 | |
794 | if (cflag & CSTOPB) |
795 | cval |= 0x04; |
796 | if (cflag & PARENB) |
797 | cval |= UART_LCR_PARITY; |
798 | if (!(cflag & PARODD)) |
799 | cval |= UART_LCR_EPAR; |
800 | if (cflag & CMSPAR) |
801 | cval |= UART_LCR_SPAR; |
802 | |
803 | /* |
804 | * Work around a bug in the Oxford Semiconductor 952 rev B |
805 | * chip which causes it to seriously miscalculate baud rates |
806 | * when DLL is 0. |
807 | */ |
808 | if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 && |
809 | up->rev == 0x5201) |
810 | quot ++; |
811 | |
812 | if (uart_config[up->port.type].flags & UART_USE_FIFO) { |
813 | if ((up->port.uartclk / quot) < (2400 * 16)) |
814 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; |
815 | #ifdef CONFIG_SERIAL_8250_RSA |
816 | else if (up->port.type == PORT_RSA) |
817 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14; |
818 | #endif |
819 | else |
820 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; |
821 | } |
822 | if (up->port.type == PORT_16750) |
823 | fcr |= UART_FCR7_64BYTE; |
824 | |
825 | /* |
826 | * Ok, we're now changing the port state. Do it with |
827 | * interrupts disabled. |
828 | */ |
829 | uart_port_lock_irqsave(up: &up->port, flags: &flags); |
830 | |
831 | /* |
832 | * Update the per-port timeout. |
833 | */ |
834 | uart_update_timeout(port, cflag, baud: (port->uartclk / (16 * quot))); |
835 | |
836 | up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; |
837 | if (iflag & INPCK) |
838 | up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; |
839 | if (iflag & (IGNBRK | BRKINT | PARMRK)) |
840 | up->port.read_status_mask |= UART_LSR_BI; |
841 | |
842 | /* |
843 | * Characteres to ignore |
844 | */ |
845 | up->port.ignore_status_mask = 0; |
846 | if (iflag & IGNPAR) |
847 | up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; |
848 | if (iflag & IGNBRK) { |
849 | up->port.ignore_status_mask |= UART_LSR_BI; |
850 | /* |
851 | * If we're ignoring parity and break indicators, |
852 | * ignore overruns too (for real raw support). |
853 | */ |
854 | if (iflag & IGNPAR) |
855 | up->port.ignore_status_mask |= UART_LSR_OE; |
856 | } |
857 | |
858 | /* |
859 | * ignore all characters if CREAD is not set |
860 | */ |
861 | if ((cflag & CREAD) == 0) |
862 | up->port.ignore_status_mask |= UART_LSR_DR; |
863 | |
864 | /* |
865 | * CTS flow control flag and modem status interrupts |
866 | */ |
867 | up->ier &= ~UART_IER_MSI; |
868 | if (UART_ENABLE_MS(&up->port, cflag)) |
869 | up->ier |= UART_IER_MSI; |
870 | |
871 | serial_out(up, UART_IER, value: up->ier); |
872 | |
873 | if (uart_config[up->port.type].flags & UART_STARTECH) { |
874 | serial_outp(up, UART_LCR, 0xBF); |
875 | serial_outp(up, UART_EFR, cflag & CRTSCTS ? UART_EFR_CTS :0); |
876 | } |
877 | serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ |
878 | serial_outp(up, UART_DLL, quot & 0xff); /* LS of divisor */ |
879 | serial_outp(up, UART_DLM, quot >> 8); /* MS of divisor */ |
880 | if (up->port.type == PORT_16750) |
881 | serial_outp(up, UART_FCR, fcr); /* set fcr */ |
882 | serial_outp(up, UART_LCR, cval); /* reset DLAB */ |
883 | up->lcr = cval; /* Save LCR */ |
884 | if (up->port.type != PORT_16750) { |
885 | if (fcr & UART_FCR_ENABLE_FIFO) { |
886 | /* emulated UARTs (Lucent Venus 167x) need two steps */ |
887 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); |
888 | } |
889 | serial_outp(up, UART_FCR, fcr); /* set fcr */ |
890 | } |
891 | |
892 | up->cflag = cflag; |
893 | |
894 | uart_port_unlock_irqrestore(up: &up->port, flags); |
895 | } |
896 | |
897 | static void |
898 | sunsu_set_termios(struct uart_port *port, struct ktermios *termios, |
899 | const struct ktermios *old) |
900 | { |
901 | unsigned int baud, quot; |
902 | |
903 | /* |
904 | * Ask the core to calculate the divisor for us. |
905 | */ |
906 | baud = uart_get_baud_rate(port, termios, old, min: 0, max: port->uartclk/16); |
907 | quot = uart_get_divisor(port, baud); |
908 | |
909 | sunsu_change_speed(port, cflag: termios->c_cflag, iflag: termios->c_iflag, quot); |
910 | } |
911 | |
912 | static void sunsu_release_port(struct uart_port *port) |
913 | { |
914 | } |
915 | |
916 | static int sunsu_request_port(struct uart_port *port) |
917 | { |
918 | return 0; |
919 | } |
920 | |
921 | static void sunsu_config_port(struct uart_port *port, int flags) |
922 | { |
923 | struct uart_sunsu_port *up = |
924 | container_of(port, struct uart_sunsu_port, port); |
925 | |
926 | if (flags & UART_CONFIG_TYPE) { |
927 | /* |
928 | * We are supposed to call autoconfig here, but this requires |
929 | * splitting all the OBP probing crap from the UART probing. |
930 | * We'll do it when we kill sunsu.c altogether. |
931 | */ |
932 | port->type = up->type_probed; /* XXX */ |
933 | } |
934 | } |
935 | |
936 | static int |
937 | sunsu_verify_port(struct uart_port *port, struct serial_struct *ser) |
938 | { |
939 | return -EINVAL; |
940 | } |
941 | |
942 | static const char * |
943 | sunsu_type(struct uart_port *port) |
944 | { |
945 | int type = port->type; |
946 | |
947 | if (type >= ARRAY_SIZE(uart_config)) |
948 | type = 0; |
949 | return uart_config[type].name; |
950 | } |
951 | |
952 | static const struct uart_ops sunsu_pops = { |
953 | .tx_empty = sunsu_tx_empty, |
954 | .set_mctrl = sunsu_set_mctrl, |
955 | .get_mctrl = sunsu_get_mctrl, |
956 | .stop_tx = sunsu_stop_tx, |
957 | .start_tx = sunsu_start_tx, |
958 | .stop_rx = sunsu_stop_rx, |
959 | .enable_ms = sunsu_enable_ms, |
960 | .break_ctl = sunsu_break_ctl, |
961 | .startup = sunsu_startup, |
962 | .shutdown = sunsu_shutdown, |
963 | .set_termios = sunsu_set_termios, |
964 | .type = sunsu_type, |
965 | .release_port = sunsu_release_port, |
966 | .request_port = sunsu_request_port, |
967 | .config_port = sunsu_config_port, |
968 | .verify_port = sunsu_verify_port, |
969 | }; |
970 | |
971 | #define UART_NR 4 |
972 | |
973 | static struct uart_sunsu_port sunsu_ports[UART_NR]; |
974 | static int nr_inst; /* Number of already registered ports */ |
975 | |
976 | #ifdef CONFIG_SERIO |
977 | |
978 | static DEFINE_SPINLOCK(sunsu_serio_lock); |
979 | |
980 | static int sunsu_serio_write(struct serio *serio, unsigned char ch) |
981 | { |
982 | struct uart_sunsu_port *up = serio->port_data; |
983 | unsigned long flags; |
984 | int lsr; |
985 | |
986 | spin_lock_irqsave(&sunsu_serio_lock, flags); |
987 | |
988 | do { |
989 | lsr = serial_in(up, UART_LSR); |
990 | } while (!(lsr & UART_LSR_THRE)); |
991 | |
992 | /* Send the character out. */ |
993 | serial_out(up, UART_TX, value: ch); |
994 | |
995 | spin_unlock_irqrestore(lock: &sunsu_serio_lock, flags); |
996 | |
997 | return 0; |
998 | } |
999 | |
1000 | static int sunsu_serio_open(struct serio *serio) |
1001 | { |
1002 | struct uart_sunsu_port *up = serio->port_data; |
1003 | unsigned long flags; |
1004 | int ret; |
1005 | |
1006 | spin_lock_irqsave(&sunsu_serio_lock, flags); |
1007 | if (!up->serio_open) { |
1008 | up->serio_open = 1; |
1009 | ret = 0; |
1010 | } else |
1011 | ret = -EBUSY; |
1012 | spin_unlock_irqrestore(lock: &sunsu_serio_lock, flags); |
1013 | |
1014 | return ret; |
1015 | } |
1016 | |
1017 | static void sunsu_serio_close(struct serio *serio) |
1018 | { |
1019 | struct uart_sunsu_port *up = serio->port_data; |
1020 | unsigned long flags; |
1021 | |
1022 | spin_lock_irqsave(&sunsu_serio_lock, flags); |
1023 | up->serio_open = 0; |
1024 | spin_unlock_irqrestore(lock: &sunsu_serio_lock, flags); |
1025 | } |
1026 | |
1027 | #endif /* CONFIG_SERIO */ |
1028 | |
1029 | static void sunsu_autoconfig(struct uart_sunsu_port *up) |
1030 | { |
1031 | unsigned char status1, status2, scratch, scratch2, scratch3; |
1032 | unsigned char save_lcr, save_mcr; |
1033 | unsigned long flags; |
1034 | |
1035 | if (up->su_type == SU_PORT_NONE) |
1036 | return; |
1037 | |
1038 | up->type_probed = PORT_UNKNOWN; |
1039 | up->port.iotype = UPIO_MEM; |
1040 | |
1041 | uart_port_lock_irqsave(up: &up->port, flags: &flags); |
1042 | |
1043 | if (!(up->port.flags & UPF_BUGGY_UART)) { |
1044 | /* |
1045 | * Do a simple existence test first; if we fail this, there's |
1046 | * no point trying anything else. |
1047 | * |
1048 | * 0x80 is used as a nonsense port to prevent against false |
1049 | * positives due to ISA bus float. The assumption is that |
1050 | * 0x80 is a non-existent port; which should be safe since |
1051 | * include/asm/io.h also makes this assumption. |
1052 | */ |
1053 | scratch = serial_inp(up, UART_IER); |
1054 | serial_outp(up, UART_IER, 0); |
1055 | #ifdef __i386__ |
1056 | outb(0xff, 0x080); |
1057 | #endif |
1058 | scratch2 = serial_inp(up, UART_IER); |
1059 | serial_outp(up, UART_IER, 0x0f); |
1060 | #ifdef __i386__ |
1061 | outb(0, 0x080); |
1062 | #endif |
1063 | scratch3 = serial_inp(up, UART_IER); |
1064 | serial_outp(up, UART_IER, scratch); |
1065 | if (scratch2 != 0 || scratch3 != 0x0F) |
1066 | goto out; /* We failed; there's nothing here */ |
1067 | } |
1068 | |
1069 | save_mcr = serial_in(up, UART_MCR); |
1070 | save_lcr = serial_in(up, UART_LCR); |
1071 | |
1072 | /* |
1073 | * Check to see if a UART is really there. Certain broken |
1074 | * internal modems based on the Rockwell chipset fail this |
1075 | * test, because they apparently don't implement the loopback |
1076 | * test mode. So this test is skipped on the COM 1 through |
1077 | * COM 4 ports. This *should* be safe, since no board |
1078 | * manufacturer would be stupid enough to design a board |
1079 | * that conflicts with COM 1-4 --- we hope! |
1080 | */ |
1081 | if (!(up->port.flags & UPF_SKIP_TEST)) { |
1082 | serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A); |
1083 | status1 = serial_inp(up, UART_MSR) & 0xF0; |
1084 | serial_outp(up, UART_MCR, save_mcr); |
1085 | if (status1 != 0x90) |
1086 | goto out; /* We failed loopback test */ |
1087 | } |
1088 | serial_outp(up, UART_LCR, 0xBF); /* set up for StarTech test */ |
1089 | serial_outp(up, UART_EFR, 0); /* EFR is the same as FCR */ |
1090 | serial_outp(up, UART_LCR, 0); |
1091 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); |
1092 | scratch = serial_in(up, UART_IIR) >> 6; |
1093 | switch (scratch) { |
1094 | case 0: |
1095 | up->port.type = PORT_16450; |
1096 | break; |
1097 | case 1: |
1098 | up->port.type = PORT_UNKNOWN; |
1099 | break; |
1100 | case 2: |
1101 | up->port.type = PORT_16550; |
1102 | break; |
1103 | case 3: |
1104 | up->port.type = PORT_16550A; |
1105 | break; |
1106 | } |
1107 | if (up->port.type == PORT_16550A) { |
1108 | /* Check for Startech UART's */ |
1109 | serial_outp(up, UART_LCR, UART_LCR_DLAB); |
1110 | if (serial_in(up, UART_EFR) == 0) { |
1111 | up->port.type = PORT_16650; |
1112 | } else { |
1113 | serial_outp(up, UART_LCR, 0xBF); |
1114 | if (serial_in(up, UART_EFR) == 0) |
1115 | up->port.type = PORT_16650V2; |
1116 | } |
1117 | } |
1118 | if (up->port.type == PORT_16550A) { |
1119 | /* Check for TI 16750 */ |
1120 | serial_outp(up, UART_LCR, save_lcr | UART_LCR_DLAB); |
1121 | serial_outp(up, UART_FCR, |
1122 | UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); |
1123 | scratch = serial_in(up, UART_IIR) >> 5; |
1124 | if (scratch == 7) { |
1125 | /* |
1126 | * If this is a 16750, and not a cheap UART |
1127 | * clone, then it should only go into 64 byte |
1128 | * mode if the UART_FCR7_64BYTE bit was set |
1129 | * while UART_LCR_DLAB was latched. |
1130 | */ |
1131 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); |
1132 | serial_outp(up, UART_LCR, 0); |
1133 | serial_outp(up, UART_FCR, |
1134 | UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); |
1135 | scratch = serial_in(up, UART_IIR) >> 5; |
1136 | if (scratch == 6) |
1137 | up->port.type = PORT_16750; |
1138 | } |
1139 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); |
1140 | } |
1141 | serial_outp(up, UART_LCR, save_lcr); |
1142 | if (up->port.type == PORT_16450) { |
1143 | scratch = serial_in(up, UART_SCR); |
1144 | serial_outp(up, UART_SCR, 0xa5); |
1145 | status1 = serial_in(up, UART_SCR); |
1146 | serial_outp(up, UART_SCR, 0x5a); |
1147 | status2 = serial_in(up, UART_SCR); |
1148 | serial_outp(up, UART_SCR, scratch); |
1149 | |
1150 | if ((status1 != 0xa5) || (status2 != 0x5a)) |
1151 | up->port.type = PORT_8250; |
1152 | } |
1153 | |
1154 | up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size; |
1155 | |
1156 | if (up->port.type == PORT_UNKNOWN) |
1157 | goto out; |
1158 | up->type_probed = up->port.type; /* XXX */ |
1159 | |
1160 | /* |
1161 | * Reset the UART. |
1162 | */ |
1163 | #ifdef CONFIG_SERIAL_8250_RSA |
1164 | if (up->port.type == PORT_RSA) |
1165 | serial_outp(up, UART_RSA_FRR, 0); |
1166 | #endif |
1167 | serial_outp(up, UART_MCR, save_mcr); |
1168 | serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO | |
1169 | UART_FCR_CLEAR_RCVR | |
1170 | UART_FCR_CLEAR_XMIT)); |
1171 | serial_outp(up, UART_FCR, 0); |
1172 | (void)serial_in(up, UART_RX); |
1173 | serial_outp(up, UART_IER, 0); |
1174 | |
1175 | out: |
1176 | uart_port_unlock_irqrestore(up: &up->port, flags); |
1177 | } |
1178 | |
1179 | static struct uart_driver sunsu_reg = { |
1180 | .owner = THIS_MODULE, |
1181 | .driver_name = "sunsu" , |
1182 | .dev_name = "ttyS" , |
1183 | .major = TTY_MAJOR, |
1184 | }; |
1185 | |
1186 | static int sunsu_kbd_ms_init(struct uart_sunsu_port *up) |
1187 | { |
1188 | int quot, baud; |
1189 | #ifdef CONFIG_SERIO |
1190 | struct serio *serio; |
1191 | #endif |
1192 | |
1193 | if (up->su_type == SU_PORT_KBD) { |
1194 | up->cflag = B1200 | CS8 | CLOCAL | CREAD; |
1195 | baud = 1200; |
1196 | } else { |
1197 | up->cflag = B4800 | CS8 | CLOCAL | CREAD; |
1198 | baud = 4800; |
1199 | } |
1200 | quot = up->port.uartclk / (16 * baud); |
1201 | |
1202 | sunsu_autoconfig(up); |
1203 | if (up->port.type == PORT_UNKNOWN) |
1204 | return -ENODEV; |
1205 | |
1206 | printk("%pOF: %s port at %llx, irq %u\n" , |
1207 | up->port.dev->of_node, |
1208 | (up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse" , |
1209 | (unsigned long long) up->port.mapbase, |
1210 | up->port.irq); |
1211 | |
1212 | #ifdef CONFIG_SERIO |
1213 | serio = &up->serio; |
1214 | serio->port_data = up; |
1215 | |
1216 | serio->id.type = SERIO_RS232; |
1217 | if (up->su_type == SU_PORT_KBD) { |
1218 | serio->id.proto = SERIO_SUNKBD; |
1219 | strscpy(p: serio->name, q: "sukbd" , size: sizeof(serio->name)); |
1220 | } else { |
1221 | serio->id.proto = SERIO_SUN; |
1222 | serio->id.extra = 1; |
1223 | strscpy(p: serio->name, q: "sums" , size: sizeof(serio->name)); |
1224 | } |
1225 | strscpy(p: serio->phys, |
1226 | q: (!(up->port.line & 1) ? "su/serio0" : "su/serio1" ), |
1227 | size: sizeof(serio->phys)); |
1228 | |
1229 | serio->write = sunsu_serio_write; |
1230 | serio->open = sunsu_serio_open; |
1231 | serio->close = sunsu_serio_close; |
1232 | serio->dev.parent = up->port.dev; |
1233 | |
1234 | serio_register_port(serio); |
1235 | #endif |
1236 | |
1237 | sunsu_change_speed(port: &up->port, cflag: up->cflag, iflag: 0, quot); |
1238 | |
1239 | sunsu_startup(port: &up->port); |
1240 | return 0; |
1241 | } |
1242 | |
1243 | /* |
1244 | * ------------------------------------------------------------ |
1245 | * Serial console driver |
1246 | * ------------------------------------------------------------ |
1247 | */ |
1248 | |
1249 | #ifdef CONFIG_SERIAL_SUNSU_CONSOLE |
1250 | |
1251 | /* |
1252 | * Wait for transmitter & holding register to empty |
1253 | */ |
1254 | static void wait_for_xmitr(struct uart_sunsu_port *up) |
1255 | { |
1256 | unsigned int status, tmout = 10000; |
1257 | |
1258 | /* Wait up to 10ms for the character(s) to be sent. */ |
1259 | do { |
1260 | status = serial_in(up, UART_LSR); |
1261 | |
1262 | if (status & UART_LSR_BI) |
1263 | up->lsr_break_flag = UART_LSR_BI; |
1264 | |
1265 | if (--tmout == 0) |
1266 | break; |
1267 | udelay(1); |
1268 | } while (!uart_lsr_tx_empty(status)); |
1269 | |
1270 | /* Wait up to 1s for flow control if necessary */ |
1271 | if (up->port.flags & UPF_CONS_FLOW) { |
1272 | tmout = 1000000; |
1273 | while (--tmout && |
1274 | ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0)) |
1275 | udelay(1); |
1276 | } |
1277 | } |
1278 | |
1279 | static void sunsu_console_putchar(struct uart_port *port, unsigned char ch) |
1280 | { |
1281 | struct uart_sunsu_port *up = |
1282 | container_of(port, struct uart_sunsu_port, port); |
1283 | |
1284 | wait_for_xmitr(up); |
1285 | serial_out(up, UART_TX, ch); |
1286 | } |
1287 | |
1288 | /* |
1289 | * Print a string to the serial port trying not to disturb |
1290 | * any possible real use of the port... |
1291 | */ |
1292 | static void sunsu_console_write(struct console *co, const char *s, |
1293 | unsigned int count) |
1294 | { |
1295 | struct uart_sunsu_port *up = &sunsu_ports[co->index]; |
1296 | unsigned long flags; |
1297 | unsigned int ier; |
1298 | int locked = 1; |
1299 | |
1300 | if (up->port.sysrq || oops_in_progress) |
1301 | locked = uart_port_trylock_irqsave(&up->port, &flags); |
1302 | else |
1303 | uart_port_lock_irqsave(&up->port, &flags); |
1304 | |
1305 | /* |
1306 | * First save the UER then disable the interrupts |
1307 | */ |
1308 | ier = serial_in(up, UART_IER); |
1309 | serial_out(up, UART_IER, 0); |
1310 | |
1311 | uart_console_write(&up->port, s, count, sunsu_console_putchar); |
1312 | |
1313 | /* |
1314 | * Finally, wait for transmitter to become empty |
1315 | * and restore the IER |
1316 | */ |
1317 | wait_for_xmitr(up); |
1318 | serial_out(up, UART_IER, ier); |
1319 | |
1320 | if (locked) |
1321 | uart_port_unlock_irqrestore(&up->port, flags); |
1322 | } |
1323 | |
1324 | /* |
1325 | * Setup initial baud/bits/parity. We do two things here: |
1326 | * - construct a cflag setting for the first su_open() |
1327 | * - initialize the serial port |
1328 | * Return non-zero if we didn't find a serial port. |
1329 | */ |
1330 | static int __init sunsu_console_setup(struct console *co, char *options) |
1331 | { |
1332 | static struct ktermios dummy; |
1333 | struct ktermios termios; |
1334 | struct uart_port *port; |
1335 | |
1336 | printk("Console: ttyS%d (SU)\n" , |
1337 | (sunsu_reg.minor - 64) + co->index); |
1338 | |
1339 | if (co->index > nr_inst) |
1340 | return -ENODEV; |
1341 | port = &sunsu_ports[co->index].port; |
1342 | |
1343 | /* |
1344 | * Temporary fix. |
1345 | */ |
1346 | spin_lock_init(&port->lock); |
1347 | |
1348 | /* Get firmware console settings. */ |
1349 | sunserial_console_termios(co, port->dev->of_node); |
1350 | |
1351 | memset(&termios, 0, sizeof(struct ktermios)); |
1352 | termios.c_cflag = co->cflag; |
1353 | port->mctrl |= TIOCM_DTR; |
1354 | port->ops->set_termios(port, &termios, &dummy); |
1355 | |
1356 | return 0; |
1357 | } |
1358 | |
1359 | static struct console sunsu_console = { |
1360 | .name = "ttyS" , |
1361 | .write = sunsu_console_write, |
1362 | .device = uart_console_device, |
1363 | .setup = sunsu_console_setup, |
1364 | .flags = CON_PRINTBUFFER, |
1365 | .index = -1, |
1366 | .data = &sunsu_reg, |
1367 | }; |
1368 | |
1369 | /* |
1370 | * Register console. |
1371 | */ |
1372 | |
1373 | static inline struct console *SUNSU_CONSOLE(void) |
1374 | { |
1375 | return &sunsu_console; |
1376 | } |
1377 | #else |
1378 | #define SUNSU_CONSOLE() (NULL) |
1379 | #define sunsu_serial_console_init() do { } while (0) |
1380 | #endif |
1381 | |
1382 | static enum su_type su_get_type(struct device_node *dp) |
1383 | { |
1384 | struct device_node *ap = of_find_node_by_path(path: "/aliases" ); |
1385 | enum su_type rc = SU_PORT_PORT; |
1386 | |
1387 | if (ap) { |
1388 | const char *keyb = of_get_property(node: ap, name: "keyboard" , NULL); |
1389 | const char *ms = of_get_property(node: ap, name: "mouse" , NULL); |
1390 | struct device_node *match; |
1391 | |
1392 | if (keyb) { |
1393 | match = of_find_node_by_path(path: keyb); |
1394 | |
1395 | /* |
1396 | * The pointer is used as an identifier not |
1397 | * as a pointer, we can drop the refcount on |
1398 | * the of__node immediately after getting it. |
1399 | */ |
1400 | of_node_put(node: match); |
1401 | |
1402 | if (dp == match) { |
1403 | rc = SU_PORT_KBD; |
1404 | goto out; |
1405 | } |
1406 | } |
1407 | if (ms) { |
1408 | match = of_find_node_by_path(path: ms); |
1409 | |
1410 | of_node_put(node: match); |
1411 | |
1412 | if (dp == match) { |
1413 | rc = SU_PORT_MS; |
1414 | goto out; |
1415 | } |
1416 | } |
1417 | } |
1418 | |
1419 | out: |
1420 | of_node_put(node: ap); |
1421 | return rc; |
1422 | } |
1423 | |
1424 | static int su_probe(struct platform_device *op) |
1425 | { |
1426 | struct device_node *dp = op->dev.of_node; |
1427 | struct uart_sunsu_port *up; |
1428 | struct resource *rp; |
1429 | enum su_type type; |
1430 | bool ignore_line; |
1431 | int err; |
1432 | |
1433 | type = su_get_type(dp); |
1434 | if (type == SU_PORT_PORT) { |
1435 | if (nr_inst >= UART_NR) |
1436 | return -EINVAL; |
1437 | up = &sunsu_ports[nr_inst]; |
1438 | } else { |
1439 | up = kzalloc(size: sizeof(*up), GFP_KERNEL); |
1440 | if (!up) |
1441 | return -ENOMEM; |
1442 | } |
1443 | |
1444 | up->port.line = nr_inst; |
1445 | |
1446 | spin_lock_init(&up->port.lock); |
1447 | |
1448 | up->su_type = type; |
1449 | |
1450 | rp = &op->resource[0]; |
1451 | up->port.mapbase = rp->start; |
1452 | up->reg_size = resource_size(res: rp); |
1453 | up->port.membase = of_ioremap(rp, 0, up->reg_size, "su" ); |
1454 | if (!up->port.membase) { |
1455 | if (type != SU_PORT_PORT) |
1456 | kfree(objp: up); |
1457 | return -ENOMEM; |
1458 | } |
1459 | |
1460 | up->port.irq = op->archdata.irqs[0]; |
1461 | |
1462 | up->port.dev = &op->dev; |
1463 | |
1464 | up->port.type = PORT_UNKNOWN; |
1465 | up->port.uartclk = (SU_BASE_BAUD * 16); |
1466 | up->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SUNSU_CONSOLE); |
1467 | |
1468 | err = 0; |
1469 | if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) { |
1470 | err = sunsu_kbd_ms_init(up); |
1471 | if (err) { |
1472 | of_iounmap(&op->resource[0], |
1473 | up->port.membase, up->reg_size); |
1474 | kfree(objp: up); |
1475 | return err; |
1476 | } |
1477 | platform_set_drvdata(pdev: op, data: up); |
1478 | |
1479 | nr_inst++; |
1480 | |
1481 | return 0; |
1482 | } |
1483 | |
1484 | up->port.flags |= UPF_BOOT_AUTOCONF; |
1485 | |
1486 | sunsu_autoconfig(up); |
1487 | |
1488 | err = -ENODEV; |
1489 | if (up->port.type == PORT_UNKNOWN) |
1490 | goto out_unmap; |
1491 | |
1492 | up->port.ops = &sunsu_pops; |
1493 | |
1494 | ignore_line = false; |
1495 | if (of_node_name_eq(np: dp, name: "rsc-console" ) || |
1496 | of_node_name_eq(np: dp, name: "lom-console" )) |
1497 | ignore_line = true; |
1498 | |
1499 | sunserial_console_match(SUNSU_CONSOLE(), dp, |
1500 | &sunsu_reg, up->port.line, |
1501 | ignore_line); |
1502 | err = uart_add_one_port(reg: &sunsu_reg, port: &up->port); |
1503 | if (err) |
1504 | goto out_unmap; |
1505 | |
1506 | platform_set_drvdata(pdev: op, data: up); |
1507 | |
1508 | nr_inst++; |
1509 | |
1510 | return 0; |
1511 | |
1512 | out_unmap: |
1513 | of_iounmap(&op->resource[0], up->port.membase, up->reg_size); |
1514 | kfree(objp: up); |
1515 | return err; |
1516 | } |
1517 | |
1518 | static int su_remove(struct platform_device *op) |
1519 | { |
1520 | struct uart_sunsu_port *up = platform_get_drvdata(pdev: op); |
1521 | bool kbdms = false; |
1522 | |
1523 | if (up->su_type == SU_PORT_MS || |
1524 | up->su_type == SU_PORT_KBD) |
1525 | kbdms = true; |
1526 | |
1527 | if (kbdms) { |
1528 | #ifdef CONFIG_SERIO |
1529 | serio_unregister_port(serio: &up->serio); |
1530 | #endif |
1531 | } else if (up->port.type != PORT_UNKNOWN) |
1532 | uart_remove_one_port(reg: &sunsu_reg, port: &up->port); |
1533 | |
1534 | if (up->port.membase) |
1535 | of_iounmap(&op->resource[0], up->port.membase, up->reg_size); |
1536 | |
1537 | if (kbdms) |
1538 | kfree(objp: up); |
1539 | |
1540 | return 0; |
1541 | } |
1542 | |
1543 | static const struct of_device_id su_match[] = { |
1544 | { |
1545 | .name = "su" , |
1546 | }, |
1547 | { |
1548 | .name = "su_pnp" , |
1549 | }, |
1550 | { |
1551 | .name = "serial" , |
1552 | .compatible = "su" , |
1553 | }, |
1554 | { |
1555 | .type = "serial" , |
1556 | .compatible = "su" , |
1557 | }, |
1558 | {}, |
1559 | }; |
1560 | MODULE_DEVICE_TABLE(of, su_match); |
1561 | |
1562 | static struct platform_driver su_driver = { |
1563 | .driver = { |
1564 | .name = "su" , |
1565 | .of_match_table = su_match, |
1566 | }, |
1567 | .probe = su_probe, |
1568 | .remove = su_remove, |
1569 | }; |
1570 | |
1571 | static int __init sunsu_init(void) |
1572 | { |
1573 | struct device_node *dp; |
1574 | int err; |
1575 | int num_uart = 0; |
1576 | |
1577 | for_each_node_by_name(dp, "su" ) { |
1578 | if (su_get_type(dp) == SU_PORT_PORT) |
1579 | num_uart++; |
1580 | } |
1581 | for_each_node_by_name(dp, "su_pnp" ) { |
1582 | if (su_get_type(dp) == SU_PORT_PORT) |
1583 | num_uart++; |
1584 | } |
1585 | for_each_node_by_name(dp, "serial" ) { |
1586 | if (of_device_is_compatible(device: dp, "su" )) { |
1587 | if (su_get_type(dp) == SU_PORT_PORT) |
1588 | num_uart++; |
1589 | } |
1590 | } |
1591 | for_each_node_by_type(dp, "serial" ) { |
1592 | if (of_device_is_compatible(device: dp, "su" )) { |
1593 | if (su_get_type(dp) == SU_PORT_PORT) |
1594 | num_uart++; |
1595 | } |
1596 | } |
1597 | |
1598 | if (num_uart) { |
1599 | err = sunserial_register_minors(&sunsu_reg, num_uart); |
1600 | if (err) |
1601 | return err; |
1602 | } |
1603 | |
1604 | err = platform_driver_register(&su_driver); |
1605 | if (err && num_uart) |
1606 | sunserial_unregister_minors(&sunsu_reg, num_uart); |
1607 | |
1608 | return err; |
1609 | } |
1610 | |
1611 | static void __exit sunsu_exit(void) |
1612 | { |
1613 | platform_driver_unregister(&su_driver); |
1614 | if (sunsu_reg.nr) |
1615 | sunserial_unregister_minors(&sunsu_reg, sunsu_reg.nr); |
1616 | } |
1617 | |
1618 | module_init(sunsu_init); |
1619 | module_exit(sunsu_exit); |
1620 | |
1621 | MODULE_AUTHOR("Eddie C. Dost, Peter Zaitcev, and David S. Miller" ); |
1622 | MODULE_DESCRIPTION("Sun SU serial port driver" ); |
1623 | MODULE_VERSION("2.0" ); |
1624 | MODULE_LICENSE("GPL" ); |
1625 | |