aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/serial/Kconfig18
-rw-r--r--drivers/tty/serial/Makefile1
-rw-r--r--drivers/tty/serial/sc26xx.c749
3 files changed, 0 insertions, 768 deletions
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index a3817ab8602f..7fbbbadea2dd 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1146,31 +1146,13 @@ config SERIAL_QE
1146 This driver supports the QE serial ports on Freescale embedded 1146 This driver supports the QE serial ports on Freescale embedded
1147 PowerPC that contain a QUICC Engine. 1147 PowerPC that contain a QUICC Engine.
1148 1148
1149config SERIAL_SC26XX
1150 tristate "SC2681/SC2692 serial port support"
1151 depends on SNI_RM
1152 select SERIAL_CORE
1153 help
1154 This is a driver for the onboard serial ports of
1155 older RM400 machines.
1156
1157config SERIAL_SC26XX_CONSOLE
1158 bool "Console on SC2681/SC2692 serial port"
1159 depends on SERIAL_SC26XX=y
1160 select SERIAL_CORE_CONSOLE
1161 help
1162 Support for Console on SC2681/SC2692 serial ports.
1163
1164config SERIAL_SCCNXP 1149config SERIAL_SCCNXP
1165 tristate "SCCNXP serial port support" 1150 tristate "SCCNXP serial port support"
1166 depends on !SERIAL_SC26XX
1167 select SERIAL_CORE 1151 select SERIAL_CORE
1168 default n
1169 help 1152 help
1170 This selects support for an advanced UART from NXP (Philips). 1153 This selects support for an advanced UART from NXP (Philips).
1171 Supported ICs are SCC2681, SCC2691, SCC2692, SC28L91, SC28L92, 1154 Supported ICs are SCC2681, SCC2691, SCC2692, SC28L91, SC28L92,
1172 SC28L202, SCC68681 and SCC68692. 1155 SC28L202, SCC68681 and SCC68692.
1173 Positioned as a replacement for the driver SC26XX.
1174 1156
1175config SERIAL_SCCNXP_CONSOLE 1157config SERIAL_SCCNXP_CONSOLE
1176 bool "Console on SCCNXP serial port" 1158 bool "Console on SCCNXP serial port"
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3068c7722087..3680854fef41 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -47,7 +47,6 @@ obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o
47obj-$(CONFIG_SERIAL_MPSC) += mpsc.o 47obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
48obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o 48obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
49obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o 49obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
50obj-$(CONFIG_SERIAL_SC26XX) += sc26xx.o
51obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o 50obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o
52obj-$(CONFIG_SERIAL_JSM) += jsm/ 51obj-$(CONFIG_SERIAL_JSM) += jsm/
53obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o 52obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
diff --git a/drivers/tty/serial/sc26xx.c b/drivers/tty/serial/sc26xx.c
deleted file mode 100644
index 887b4f770749..000000000000
--- a/drivers/tty/serial/sc26xx.c
+++ /dev/null
@@ -1,749 +0,0 @@
1/*
2 * SC268xx.c: Serial driver for Philiphs SC2681/SC2692 devices.
3 *
4 * Copyright (C) 2006,2007 Thomas Bogendörfer (tsbogend@alpha.franken.de)
5 */
6
7#include <linux/module.h>
8#include <linux/kernel.h>
9#include <linux/errno.h>
10#include <linux/tty.h>
11#include <linux/tty_flip.h>
12#include <linux/major.h>
13#include <linux/circ_buf.h>
14#include <linux/serial.h>
15#include <linux/sysrq.h>
16#include <linux/console.h>
17#include <linux/spinlock.h>
18#include <linux/slab.h>
19#include <linux/delay.h>
20#include <linux/init.h>
21#include <linux/platform_device.h>
22#include <linux/irq.h>
23#include <linux/io.h>
24
25#warning "Please try migrate to use new driver SCCNXP and report the status" \
26 "in the linux-serial mailing list."
27
28#if defined(CONFIG_MAGIC_SYSRQ)
29#define SUPPORT_SYSRQ
30#endif
31
32#include <linux/serial_core.h>
33
34#define SC26XX_MAJOR 204
35#define SC26XX_MINOR_START 205
36#define SC26XX_NR 2
37
38struct uart_sc26xx_port {
39 struct uart_port port[2];
40 u8 dsr_mask[2];
41 u8 cts_mask[2];
42 u8 dcd_mask[2];
43 u8 ri_mask[2];
44 u8 dtr_mask[2];
45 u8 rts_mask[2];
46 u8 imr;
47};
48
49/* register common to both ports */
50#define RD_ISR 0x14
51#define RD_IPR 0x34
52
53#define WR_ACR 0x10
54#define WR_IMR 0x14
55#define WR_OPCR 0x34
56#define WR_OPR_SET 0x38
57#define WR_OPR_CLR 0x3C
58
59/* access common register */
60#define READ_SC(p, r) readb((p)->membase + RD_##r)
61#define WRITE_SC(p, r, v) writeb((v), (p)->membase + WR_##r)
62
63/* register per port */
64#define RD_PORT_MRx 0x00
65#define RD_PORT_SR 0x04
66#define RD_PORT_RHR 0x0c
67
68#define WR_PORT_MRx 0x00
69#define WR_PORT_CSR 0x04
70#define WR_PORT_CR 0x08
71#define WR_PORT_THR 0x0c
72
73/* SR bits */
74#define SR_BREAK (1 << 7)
75#define SR_FRAME (1 << 6)
76#define SR_PARITY (1 << 5)
77#define SR_OVERRUN (1 << 4)
78#define SR_TXRDY (1 << 2)
79#define SR_RXRDY (1 << 0)
80
81#define CR_RES_MR (1 << 4)
82#define CR_RES_RX (2 << 4)
83#define CR_RES_TX (3 << 4)
84#define CR_STRT_BRK (6 << 4)
85#define CR_STOP_BRK (7 << 4)
86#define CR_DIS_TX (1 << 3)
87#define CR_ENA_TX (1 << 2)
88#define CR_DIS_RX (1 << 1)
89#define CR_ENA_RX (1 << 0)
90
91/* ISR bits */
92#define ISR_RXRDYB (1 << 5)
93#define ISR_TXRDYB (1 << 4)
94#define ISR_RXRDYA (1 << 1)
95#define ISR_TXRDYA (1 << 0)
96
97/* IMR bits */
98#define IMR_RXRDY (1 << 1)
99#define IMR_TXRDY (1 << 0)
100
101/* access port register */
102static inline u8 read_sc_port(struct uart_port *p, u8 reg)
103{
104 return readb(p->membase + p->line * 0x20 + reg);
105}
106
107static inline void write_sc_port(struct uart_port *p, u8 reg, u8 val)
108{
109 writeb(val, p->membase + p->line * 0x20 + reg);
110}
111
112#define READ_SC_PORT(p, r) read_sc_port(p, RD_PORT_##r)
113#define WRITE_SC_PORT(p, r, v) write_sc_port(p, WR_PORT_##r, v)
114
115static void sc26xx_enable_irq(struct uart_port *port, int mask)
116{
117 struct uart_sc26xx_port *up;
118 int line = port->line;
119
120 port -= line;
121 up = container_of(port, struct uart_sc26xx_port, port[0]);
122
123 up->imr |= mask << (line * 4);
124 WRITE_SC(port, IMR, up->imr);
125}
126
127static void sc26xx_disable_irq(struct uart_port *port, int mask)
128{
129 struct uart_sc26xx_port *up;
130 int line = port->line;
131
132 port -= line;
133 up = container_of(port, struct uart_sc26xx_port, port[0]);
134
135 up->imr &= ~(mask << (line * 4));
136 WRITE_SC(port, IMR, up->imr);
137}
138
139static bool receive_chars(struct uart_port *port)
140{
141 struct tty_port *tport = NULL;
142 int limit = 10000;
143 unsigned char ch;
144 char flag;
145 u8 status;
146
147 /* FIXME what is this trying to achieve? */
148 if (port->state != NULL) /* Unopened serial console */
149 tport = &port->state->port;
150
151 while (limit-- > 0) {
152 status = READ_SC_PORT(port, SR);
153 if (!(status & SR_RXRDY))
154 break;
155 ch = READ_SC_PORT(port, RHR);
156
157 flag = TTY_NORMAL;
158 port->icount.rx++;
159
160 if (unlikely(status & (SR_BREAK | SR_FRAME |
161 SR_PARITY | SR_OVERRUN))) {
162 if (status & SR_BREAK) {
163 status &= ~(SR_PARITY | SR_FRAME);
164 port->icount.brk++;
165 if (uart_handle_break(port))
166 continue;
167 } else if (status & SR_PARITY)
168 port->icount.parity++;
169 else if (status & SR_FRAME)
170 port->icount.frame++;
171 if (status & SR_OVERRUN)
172 port->icount.overrun++;
173
174 status &= port->read_status_mask;
175 if (status & SR_BREAK)
176 flag = TTY_BREAK;
177 else if (status & SR_PARITY)
178 flag = TTY_PARITY;
179 else if (status & SR_FRAME)
180 flag = TTY_FRAME;
181 }
182
183 if (uart_handle_sysrq_char(port, ch))
184 continue;
185
186 if (status & port->ignore_status_mask)
187 continue;
188
189 tty_insert_flip_char(tport, ch, flag);
190 }
191 return !!tport;
192}
193
194static void transmit_chars(struct uart_port *port)
195{
196 struct circ_buf *xmit;
197
198 if (!port->state)
199 return;
200
201 xmit = &port->state->xmit;
202 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
203 sc26xx_disable_irq(port, IMR_TXRDY);
204 return;
205 }
206 while (!uart_circ_empty(xmit)) {
207 if (!(READ_SC_PORT(port, SR) & SR_TXRDY))
208 break;
209
210 WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]);
211 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
212 port->icount.tx++;
213 }
214 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
215 uart_write_wakeup(port);
216}
217
218static irqreturn_t sc26xx_interrupt(int irq, void *dev_id)
219{
220 struct uart_sc26xx_port *up = dev_id;
221 unsigned long flags;
222 bool push;
223 u8 isr;
224
225 spin_lock_irqsave(&up->port[0].lock, flags);
226
227 push = false;
228 isr = READ_SC(&up->port[0], ISR);
229 if (isr & ISR_TXRDYA)
230 transmit_chars(&up->port[0]);
231 if (isr & ISR_RXRDYA)
232 push = receive_chars(&up->port[0]);
233
234 spin_unlock(&up->port[0].lock);
235
236 if (push)
237 tty_flip_buffer_push(&up->port[0].state->port);
238
239 spin_lock(&up->port[1].lock);
240
241 push = false;
242 if (isr & ISR_TXRDYB)
243 transmit_chars(&up->port[1]);
244 if (isr & ISR_RXRDYB)
245 push = receive_chars(&up->port[1]);
246
247 spin_unlock_irqrestore(&up->port[1].lock, flags);
248
249 if (push)
250 tty_flip_buffer_push(&up->port[1].state->port);
251
252 return IRQ_HANDLED;
253}
254
255/* port->lock is not held. */
256static unsigned int sc26xx_tx_empty(struct uart_port *port)
257{
258 return (READ_SC_PORT(port, SR) & SR_TXRDY) ? TIOCSER_TEMT : 0;
259}
260
261/* port->lock held by caller. */
262static void sc26xx_set_mctrl(struct uart_port *port, unsigned int mctrl)
263{
264 struct uart_sc26xx_port *up;
265 int line = port->line;
266
267 port -= line;
268 up = container_of(port, struct uart_sc26xx_port, port[0]);
269
270 if (up->dtr_mask[line]) {
271 if (mctrl & TIOCM_DTR)
272 WRITE_SC(port, OPR_SET, up->dtr_mask[line]);
273 else
274 WRITE_SC(port, OPR_CLR, up->dtr_mask[line]);
275 }
276 if (up->rts_mask[line]) {
277 if (mctrl & TIOCM_RTS)
278 WRITE_SC(port, OPR_SET, up->rts_mask[line]);
279 else
280 WRITE_SC(port, OPR_CLR, up->rts_mask[line]);
281 }
282}
283
284/* port->lock is held by caller and interrupts are disabled. */
285static unsigned int sc26xx_get_mctrl(struct uart_port *port)
286{
287 struct uart_sc26xx_port *up;
288 int line = port->line;
289 unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
290 u8 ipr;
291
292 port -= line;
293 up = container_of(port, struct uart_sc26xx_port, port[0]);
294 ipr = READ_SC(port, IPR) ^ 0xff;
295
296 if (up->dsr_mask[line]) {
297 mctrl &= ~TIOCM_DSR;
298 mctrl |= ipr & up->dsr_mask[line] ? TIOCM_DSR : 0;
299 }
300 if (up->cts_mask[line]) {
301 mctrl &= ~TIOCM_CTS;
302 mctrl |= ipr & up->cts_mask[line] ? TIOCM_CTS : 0;
303 }
304 if (up->dcd_mask[line]) {
305 mctrl &= ~TIOCM_CAR;
306 mctrl |= ipr & up->dcd_mask[line] ? TIOCM_CAR : 0;
307 }
308 if (up->ri_mask[line]) {
309 mctrl &= ~TIOCM_RNG;
310 mctrl |= ipr & up->ri_mask[line] ? TIOCM_RNG : 0;
311 }
312 return mctrl;
313}
314
315/* port->lock held by caller. */
316static void sc26xx_stop_tx(struct uart_port *port)
317{
318 return;
319}
320
321/* port->lock held by caller. */
322static void sc26xx_start_tx(struct uart_port *port)
323{
324 struct circ_buf *xmit = &port->state->xmit;
325
326 while (!uart_circ_empty(xmit)) {
327 if (!(READ_SC_PORT(port, SR) & SR_TXRDY)) {
328 sc26xx_enable_irq(port, IMR_TXRDY);
329 break;
330 }
331 WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]);
332 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
333 port->icount.tx++;
334 }
335}
336
337/* port->lock held by caller. */
338static void sc26xx_stop_rx(struct uart_port *port)
339{
340}
341
342/* port->lock held by caller. */
343static void sc26xx_enable_ms(struct uart_port *port)
344{
345}
346
347/* port->lock is not held. */
348static void sc26xx_break_ctl(struct uart_port *port, int break_state)
349{
350 if (break_state == -1)
351 WRITE_SC_PORT(port, CR, CR_STRT_BRK);
352 else
353 WRITE_SC_PORT(port, CR, CR_STOP_BRK);
354}
355
356/* port->lock is not held. */
357static int sc26xx_startup(struct uart_port *port)
358{
359 sc26xx_disable_irq(port, IMR_TXRDY | IMR_RXRDY);
360 WRITE_SC(port, OPCR, 0);
361
362 /* reset tx and rx */
363 WRITE_SC_PORT(port, CR, CR_RES_RX);
364 WRITE_SC_PORT(port, CR, CR_RES_TX);
365
366 /* start rx/tx */
367 WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX);
368
369 /* enable irqs */
370 sc26xx_enable_irq(port, IMR_RXRDY);
371 return 0;
372}
373
374/* port->lock is not held. */
375static void sc26xx_shutdown(struct uart_port *port)
376{
377 /* disable interrupst */
378 sc26xx_disable_irq(port, IMR_TXRDY | IMR_RXRDY);
379
380 /* stop tx/rx */
381 WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX);
382}
383
384/* port->lock is not held. */
385static void sc26xx_set_termios(struct uart_port *port, struct ktermios *termios,
386 struct ktermios *old)
387{
388 unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
389 unsigned int quot = uart_get_divisor(port, baud);
390 unsigned int iflag, cflag;
391 unsigned long flags;
392 u8 mr1, mr2, csr;
393
394 spin_lock_irqsave(&port->lock, flags);
395
396 while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc)
397 udelay(2);
398
399 WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX);
400
401 iflag = termios->c_iflag;
402 cflag = termios->c_cflag;
403
404 port->read_status_mask = SR_OVERRUN;
405 if (iflag & INPCK)
406 port->read_status_mask |= SR_PARITY | SR_FRAME;
407 if (iflag & (BRKINT | PARMRK))
408 port->read_status_mask |= SR_BREAK;
409
410 port->ignore_status_mask = 0;
411 if (iflag & IGNBRK)
412 port->ignore_status_mask |= SR_BREAK;
413 if ((cflag & CREAD) == 0)
414 port->ignore_status_mask |= SR_BREAK | SR_FRAME |
415 SR_PARITY | SR_OVERRUN;
416
417 switch (cflag & CSIZE) {
418 case CS5:
419 mr1 = 0x00;
420 break;
421 case CS6:
422 mr1 = 0x01;
423 break;
424 case CS7:
425 mr1 = 0x02;
426 break;
427 default:
428 case CS8:
429 mr1 = 0x03;
430 break;
431 }
432 mr2 = 0x07;
433 if (cflag & CSTOPB)
434 mr2 = 0x0f;
435 if (cflag & PARENB) {
436 if (cflag & PARODD)
437 mr1 |= (1 << 2);
438 } else
439 mr1 |= (2 << 3);
440
441 switch (baud) {
442 case 50:
443 csr = 0x00;
444 break;
445 case 110:
446 csr = 0x11;
447 break;
448 case 134:
449 csr = 0x22;
450 break;
451 case 200:
452 csr = 0x33;
453 break;
454 case 300:
455 csr = 0x44;
456 break;
457 case 600:
458 csr = 0x55;
459 break;
460 case 1200:
461 csr = 0x66;
462 break;
463 case 2400:
464 csr = 0x88;
465 break;
466 case 4800:
467 csr = 0x99;
468 break;
469 default:
470 case 9600:
471 csr = 0xbb;
472 break;
473 case 19200:
474 csr = 0xcc;
475 break;
476 }
477
478 WRITE_SC_PORT(port, CR, CR_RES_MR);
479 WRITE_SC_PORT(port, MRx, mr1);
480 WRITE_SC_PORT(port, MRx, mr2);
481
482 WRITE_SC(port, ACR, 0x80);
483 WRITE_SC_PORT(port, CSR, csr);
484
485 /* reset tx and rx */
486 WRITE_SC_PORT(port, CR, CR_RES_RX);
487 WRITE_SC_PORT(port, CR, CR_RES_TX);
488
489 WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX);
490 while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc)
491 udelay(2);
492
493 /* XXX */
494 uart_update_timeout(port, cflag,
495 (port->uartclk / (16 * quot)));
496
497 spin_unlock_irqrestore(&port->lock, flags);
498}
499
500static const char *sc26xx_type(struct uart_port *port)
501{
502 return "SC26XX";
503}
504
505static void sc26xx_release_port(struct uart_port *port)
506{
507}
508
509static int sc26xx_request_port(struct uart_port *port)
510{
511 return 0;
512}
513
514static void sc26xx_config_port(struct uart_port *port, int flags)
515{
516}
517
518static int sc26xx_verify_port(struct uart_port *port, struct serial_struct *ser)
519{
520 return -EINVAL;
521}
522
523static struct uart_ops sc26xx_ops = {
524 .tx_empty = sc26xx_tx_empty,
525 .set_mctrl = sc26xx_set_mctrl,
526 .get_mctrl = sc26xx_get_mctrl,
527 .stop_tx = sc26xx_stop_tx,
528 .start_tx = sc26xx_start_tx,
529 .stop_rx = sc26xx_stop_rx,
530 .enable_ms = sc26xx_enable_ms,
531 .break_ctl = sc26xx_break_ctl,
532 .startup = sc26xx_startup,
533 .shutdown = sc26xx_shutdown,
534 .set_termios = sc26xx_set_termios,
535 .type = sc26xx_type,
536 .release_port = sc26xx_release_port,
537 .request_port = sc26xx_request_port,
538 .config_port = sc26xx_config_port,
539 .verify_port = sc26xx_verify_port,
540};
541
542static struct uart_port *sc26xx_port;
543
544#ifdef CONFIG_SERIAL_SC26XX_CONSOLE
545static void sc26xx_console_putchar(struct uart_port *port, char c)
546{
547 unsigned long flags;
548 int limit = 1000000;
549
550 spin_lock_irqsave(&port->lock, flags);
551
552 while (limit-- > 0) {
553 if (READ_SC_PORT(port, SR) & SR_TXRDY) {
554 WRITE_SC_PORT(port, THR, c);
555 break;
556 }
557 udelay(2);
558 }
559
560 spin_unlock_irqrestore(&port->lock, flags);
561}
562
563static void sc26xx_console_write(struct console *con, const char *s, unsigned n)
564{
565 struct uart_port *port = sc26xx_port;
566 int i;
567
568 for (i = 0; i < n; i++) {
569 if (*s == '\n')
570 sc26xx_console_putchar(port, '\r');
571 sc26xx_console_putchar(port, *s++);
572 }
573}
574
575static int __init sc26xx_console_setup(struct console *con, char *options)
576{
577 struct uart_port *port = sc26xx_port;
578 int baud = 9600;
579 int bits = 8;
580 int parity = 'n';
581 int flow = 'n';
582
583 if (port->type != PORT_SC26XX)
584 return -1;
585
586 printk(KERN_INFO "Console: ttySC%d (SC26XX)\n", con->index);
587 if (options)
588 uart_parse_options(options, &baud, &parity, &bits, &flow);
589
590 return uart_set_options(port, con, baud, parity, bits, flow);
591}
592
593static struct uart_driver sc26xx_reg;
594static struct console sc26xx_console = {
595 .name = "ttySC",
596 .write = sc26xx_console_write,
597 .device = uart_console_device,
598 .setup = sc26xx_console_setup,
599 .flags = CON_PRINTBUFFER,
600 .index = -1,
601 .data = &sc26xx_reg,
602};
603#define SC26XX_CONSOLE &sc26xx_console
604#else
605#define SC26XX_CONSOLE NULL
606#endif
607
608static struct uart_driver sc26xx_reg = {
609 .owner = THIS_MODULE,
610 .driver_name = "SC26xx",
611 .dev_name = "ttySC",
612 .major = SC26XX_MAJOR,
613 .minor = SC26XX_MINOR_START,
614 .nr = SC26XX_NR,
615 .cons = SC26XX_CONSOLE,
616};
617
618static u8 sc26xx_flags2mask(unsigned int flags, unsigned int bitpos)
619{
620 unsigned int bit = (flags >> bitpos) & 15;
621
622 return bit ? (1 << (bit - 1)) : 0;
623}
624
625static void sc26xx_init_masks(struct uart_sc26xx_port *up,
626 int line, unsigned int data)
627{
628 up->dtr_mask[line] = sc26xx_flags2mask(data, 0);
629 up->rts_mask[line] = sc26xx_flags2mask(data, 4);
630 up->dsr_mask[line] = sc26xx_flags2mask(data, 8);
631 up->cts_mask[line] = sc26xx_flags2mask(data, 12);
632 up->dcd_mask[line] = sc26xx_flags2mask(data, 16);
633 up->ri_mask[line] = sc26xx_flags2mask(data, 20);
634}
635
636static int sc26xx_probe(struct platform_device *dev)
637{
638 struct resource *res;
639 struct uart_sc26xx_port *up;
640 unsigned int *sc26xx_data = dev_get_platdata(&dev->dev);
641 int err;
642
643 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
644 if (!res)
645 return -ENODEV;
646
647 up = kzalloc(sizeof *up, GFP_KERNEL);
648 if (unlikely(!up))
649 return -ENOMEM;
650
651 up->port[0].line = 0;
652 up->port[0].ops = &sc26xx_ops;
653 up->port[0].type = PORT_SC26XX;
654 up->port[0].uartclk = (29491200 / 16); /* arbitrary */
655
656 up->port[0].mapbase = res->start;
657 up->port[0].membase = ioremap_nocache(up->port[0].mapbase, 0x40);
658 up->port[0].iotype = UPIO_MEM;
659 up->port[0].irq = platform_get_irq(dev, 0);
660
661 up->port[0].dev = &dev->dev;
662
663 sc26xx_init_masks(up, 0, sc26xx_data[0]);
664
665 sc26xx_port = &up->port[0];
666
667 up->port[1].line = 1;
668 up->port[1].ops = &sc26xx_ops;
669 up->port[1].type = PORT_SC26XX;
670 up->port[1].uartclk = (29491200 / 16); /* arbitrary */
671
672 up->port[1].mapbase = up->port[0].mapbase;
673 up->port[1].membase = up->port[0].membase;
674 up->port[1].iotype = UPIO_MEM;
675 up->port[1].irq = up->port[0].irq;
676
677 up->port[1].dev = &dev->dev;
678
679 sc26xx_init_masks(up, 1, sc26xx_data[1]);
680
681 err = uart_register_driver(&sc26xx_reg);
682 if (err)
683 goto out_free_port;
684
685 sc26xx_reg.tty_driver->name_base = sc26xx_reg.minor;
686
687 err = uart_add_one_port(&sc26xx_reg, &up->port[0]);
688 if (err)
689 goto out_unregister_driver;
690
691 err = uart_add_one_port(&sc26xx_reg, &up->port[1]);
692 if (err)
693 goto out_remove_port0;
694
695 err = request_irq(up->port[0].irq, sc26xx_interrupt, 0, "sc26xx", up);
696 if (err)
697 goto out_remove_ports;
698
699 platform_set_drvdata(dev, up);
700 return 0;
701
702out_remove_ports:
703 uart_remove_one_port(&sc26xx_reg, &up->port[1]);
704out_remove_port0:
705 uart_remove_one_port(&sc26xx_reg, &up->port[0]);
706
707out_unregister_driver:
708 uart_unregister_driver(&sc26xx_reg);
709
710out_free_port:
711 kfree(up);
712 sc26xx_port = NULL;
713 return err;
714}
715
716
717static int __exit sc26xx_driver_remove(struct platform_device *dev)
718{
719 struct uart_sc26xx_port *up = platform_get_drvdata(dev);
720
721 free_irq(up->port[0].irq, up);
722
723 uart_remove_one_port(&sc26xx_reg, &up->port[0]);
724 uart_remove_one_port(&sc26xx_reg, &up->port[1]);
725
726 uart_unregister_driver(&sc26xx_reg);
727
728 kfree(up);
729 sc26xx_port = NULL;
730
731 return 0;
732}
733
734static struct platform_driver sc26xx_driver = {
735 .probe = sc26xx_probe,
736 .remove = sc26xx_driver_remove,
737 .driver = {
738 .name = "SC26xx",
739 .owner = THIS_MODULE,
740 },
741};
742
743module_platform_driver(sc26xx_driver);
744
745MODULE_AUTHOR("Thomas Bogendörfer");
746MODULE_DESCRIPTION("SC681/SC2692 serial driver");
747MODULE_VERSION("1.0");
748MODULE_LICENSE("GPL");
749MODULE_ALIAS("platform:SC26xx");