aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-01-09 18:09:30 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-09 18:09:30 -0500
commit3995f4c5327595b51482bdac8c189736262eb6e0 (patch)
treeef768d0ecf243a2376bfc646b847964313146d3e /drivers/serial
parent05814450070f13b671fc9dbf89477677aa0258cb (diff)
parentfe38ea5623d262afc0b92ea47b8a7d8c988521d2 (diff)
Merge master.kernel.org:/home/rmk/linux-2.6-arm
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/Kconfig23
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/uart00.c782
3 files changed, 0 insertions, 806 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 3fd5b999fdac..1bae26a8a503 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -369,29 +369,6 @@ config SERIAL_21285_CONSOLE
369 your boot loader (lilo or loadlin) about how to pass options to the 369 your boot loader (lilo or loadlin) about how to pass options to the
370 kernel at boot time.) 370 kernel at boot time.)
371 371
372config SERIAL_UART00
373 bool "Excalibur serial port (uart00) support"
374 depends on ARM && ARCH_CAMELOT
375 select SERIAL_CORE
376 help
377 Say Y here if you want to use the hard logic uart on Excalibur. This
378 driver also supports soft logic implementations of this uart core.
379
380config SERIAL_UART00_CONSOLE
381 bool "Support for console on Excalibur serial port"
382 depends on SERIAL_UART00
383 select SERIAL_CORE_CONSOLE
384 help
385 Say Y here if you want to support a serial console on an Excalibur
386 hard logic uart or uart00 IP core.
387
388 Even if you say Y here, the currently visible virtual console
389 (/dev/tty0) will still be used as the system console by default, but
390 you can alter that using a kernel command line option such as
391 "console=ttyS1". (Try "man bootparam" or see the documentation of
392 your boot loader (lilo or loadlin) about how to pass options to the
393 kernel at boot time.)
394
395config SERIAL_MPSC 372config SERIAL_MPSC
396 bool "Marvell MPSC serial port support" 373 bool "Marvell MPSC serial port support"
397 depends on PPC32 && MV64X60 374 depends on PPC32 && MV64X60
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index d7c7c7180e33..137148bba4fa 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -29,7 +29,6 @@ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
29obj-$(CONFIG_SERIAL_PXA) += pxa.o 29obj-$(CONFIG_SERIAL_PXA) += pxa.o
30obj-$(CONFIG_SERIAL_SA1100) += sa1100.o 30obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
31obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o 31obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
32obj-$(CONFIG_SERIAL_UART00) += uart00.o
33obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o 32obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
34obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o 33obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
35obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o 34obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
diff --git a/drivers/serial/uart00.c b/drivers/serial/uart00.c
deleted file mode 100644
index 47b504ff38b2..000000000000
--- a/drivers/serial/uart00.c
+++ /dev/null
@@ -1,782 +0,0 @@
1/*
2 * linux/drivers/serial/uart00.c
3 *
4 * Driver for UART00 serial ports
5 *
6 * Based on drivers/char/serial_amba.c, by ARM Limited &
7 * Deep Blue Solutions Ltd.
8 * Copyright 2001 Altera Corporation
9 *
10 * Update for 2.6.4 by Dirk Behme <dirk.behme@de.bosch.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * $Id: uart00.c,v 1.35 2002/07/28 10:03:28 rmk Exp $
27 *
28 */
29#include <linux/config.h>
30
31#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
32#define SUPPORT_SYSRQ
33#endif
34
35#include <linux/module.h>
36#include <linux/ioport.h>
37#include <linux/init.h>
38#include <linux/console.h>
39#include <linux/sysrq.h>
40#include <linux/tty.h>
41#include <linux/tty_flip.h>
42#include <linux/serial_core.h>
43#include <linux/serial.h>
44
45#include <asm/io.h>
46#include <asm/irq.h>
47#include <asm/sizes.h>
48
49#include <asm/arch/excalibur.h>
50#define UART00_TYPE (volatile unsigned int*)
51#include <asm/arch/uart00.h>
52#include <asm/arch/int_ctrl00.h>
53
54#define UART_NR 2
55
56#define SERIAL_UART00_NAME "ttyUA"
57#define SERIAL_UART00_MAJOR 204
58#define SERIAL_UART00_MINOR 16 /* Temporary - will change in future */
59#define SERIAL_UART00_NR UART_NR
60#define UART_PORT_SIZE 0x50
61
62#define UART00_ISR_PASS_LIMIT 256
63
64/*
65 * Access macros for the UART00 UARTs
66 */
67#define UART_GET_INT_STATUS(p) inl(UART_ISR((p)->membase))
68#define UART_PUT_IES(p, c) outl(c,UART_IES((p)->membase))
69#define UART_GET_IES(p) inl(UART_IES((p)->membase))
70#define UART_PUT_IEC(p, c) outl(c,UART_IEC((p)->membase))
71#define UART_GET_IEC(p) inl(UART_IEC((p)->membase))
72#define UART_PUT_CHAR(p, c) outl(c,UART_TD((p)->membase))
73#define UART_GET_CHAR(p) inl(UART_RD((p)->membase))
74#define UART_GET_RSR(p) inl(UART_RSR((p)->membase))
75#define UART_GET_RDS(p) inl(UART_RDS((p)->membase))
76#define UART_GET_MSR(p) inl(UART_MSR((p)->membase))
77#define UART_GET_MCR(p) inl(UART_MCR((p)->membase))
78#define UART_PUT_MCR(p, c) outl(c,UART_MCR((p)->membase))
79#define UART_GET_MC(p) inl(UART_MC((p)->membase))
80#define UART_PUT_MC(p, c) outl(c,UART_MC((p)->membase))
81#define UART_GET_TSR(p) inl(UART_TSR((p)->membase))
82#define UART_GET_DIV_HI(p) inl(UART_DIV_HI((p)->membase))
83#define UART_PUT_DIV_HI(p,c) outl(c,UART_DIV_HI((p)->membase))
84#define UART_GET_DIV_LO(p) inl(UART_DIV_LO((p)->membase))
85#define UART_PUT_DIV_LO(p,c) outl(c,UART_DIV_LO((p)->membase))
86#define UART_RX_DATA(s) ((s) & UART_RSR_RX_LEVEL_MSK)
87#define UART_TX_READY(s) (((s) & UART_TSR_TX_LEVEL_MSK) < 15)
88//#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART00_UARTFR_TMSK) == 0)
89
90static void uart00_stop_tx(struct uart_port *port)
91{
92 UART_PUT_IEC(port, UART_IEC_TIE_MSK);
93}
94
95static void uart00_stop_rx(struct uart_port *port)
96{
97 UART_PUT_IEC(port, UART_IEC_RE_MSK);
98}
99
100static void uart00_enable_ms(struct uart_port *port)
101{
102 UART_PUT_IES(port, UART_IES_ME_MSK);
103}
104
105static void
106uart00_rx_chars(struct uart_port *port, struct pt_regs *regs)
107{
108 struct tty_struct *tty = port->info->tty;
109 unsigned int status, ch, rds, flg, ignored = 0;
110
111 status = UART_GET_RSR(port);
112 while (UART_RX_DATA(status)) {
113 /*
114 * We need to read rds before reading the
115 * character from the fifo
116 */
117 rds = UART_GET_RDS(port);
118 ch = UART_GET_CHAR(port);
119 port->icount.rx++;
120
121 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
122 goto ignore_char;
123
124 flg = TTY_NORMAL;
125
126 /*
127 * Note that the error handling code is
128 * out of the main execution path
129 */
130 if (rds & (UART_RDS_BI_MSK |UART_RDS_FE_MSK|
131 UART_RDS_PE_MSK |UART_RDS_PE_MSK))
132 goto handle_error;
133 if (uart_handle_sysrq_char(port, ch, regs))
134 goto ignore_char;
135
136 error_return:
137 tty_insert_flip_char(tty, ch, flg);
138
139 ignore_char:
140 status = UART_GET_RSR(port);
141 }
142 out:
143 tty_flip_buffer_push(tty);
144 return;
145
146 handle_error:
147 if (rds & UART_RDS_BI_MSK) {
148 status &= ~(UART_RDS_FE_MSK | UART_RDS_PE_MSK);
149 port->icount.brk++;
150 if (uart_handle_break(port))
151 goto ignore_char;
152 } else if (rds & UART_RDS_PE_MSK)
153 port->icount.parity++;
154 else if (rds & UART_RDS_FE_MSK)
155 port->icount.frame++;
156 if (rds & UART_RDS_OE_MSK)
157 port->icount.overrun++;
158
159 if (rds & port->ignore_status_mask) {
160 if (++ignored > 100)
161 goto out;
162 goto ignore_char;
163 }
164 rds &= port->read_status_mask;
165
166 if (rds & UART_RDS_BI_MSK)
167 flg = TTY_BREAK;
168 else if (rds & UART_RDS_PE_MSK)
169 flg = TTY_PARITY;
170 else if (rds & UART_RDS_FE_MSK)
171 flg = TTY_FRAME;
172
173 if (rds & UART_RDS_OE_MSK) {
174 /*
175 * CHECK: does overrun affect the current character?
176 * ASSUMPTION: it does not.
177 */
178 tty_insert_flip_char(tty, ch, flg);
179 ch = 0;
180 flg = TTY_OVERRUN;
181 }
182#ifdef SUPPORT_SYSRQ
183 port->sysrq = 0;
184#endif
185 goto error_return;
186}
187
188static void uart00_tx_chars(struct uart_port *port)
189{
190 struct circ_buf *xmit = &port->info->xmit;
191 int count;
192
193 if (port->x_char) {
194 while ((UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK) == 15)
195 barrier();
196 UART_PUT_CHAR(port, port->x_char);
197 port->icount.tx++;
198 port->x_char = 0;
199 return;
200 }
201 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
202 uart00_stop_tx(port);
203 return;
204 }
205
206 count = port->fifosize >> 1;
207 do {
208 while ((UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK) == 15)
209 barrier();
210 UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
211 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
212 port->icount.tx++;
213 if (uart_circ_empty(xmit))
214 break;
215 } while (--count > 0);
216
217 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
218 uart_write_wakeup(port);
219
220 if (uart_circ_empty(xmit))
221 uart00_stop_tx(port);
222}
223
224static void uart00_start_tx(struct uart_port *port)
225{
226 UART_PUT_IES(port, UART_IES_TIE_MSK);
227 uart00_tx_chars(port);
228}
229
230static void uart00_modem_status(struct uart_port *port)
231{
232 unsigned int status;
233
234 status = UART_GET_MSR(port);
235
236 if (!(status & (UART_MSR_DCTS_MSK | UART_MSR_DDSR_MSK |
237 UART_MSR_TERI_MSK | UART_MSR_DDCD_MSK)))
238 return;
239
240 if (status & UART_MSR_DDCD_MSK)
241 uart_handle_dcd_change(port, status & UART_MSR_DCD_MSK);
242
243 if (status & UART_MSR_DDSR_MSK)
244 port->icount.dsr++;
245
246 if (status & UART_MSR_DCTS_MSK)
247 uart_handle_cts_change(port, status & UART_MSR_CTS_MSK);
248
249 wake_up_interruptible(&port->info->delta_msr_wait);
250}
251
252static irqreturn_t uart00_int(int irq, void *dev_id, struct pt_regs *regs)
253{
254 struct uart_port *port = dev_id;
255 unsigned int status, pass_counter = 0;
256
257 status = UART_GET_INT_STATUS(port);
258 do {
259 if (status & UART_ISR_RI_MSK)
260 uart00_rx_chars(port, regs);
261 if (status & UART_ISR_MI_MSK)
262 uart00_modem_status(port);
263 if (status & (UART_ISR_TI_MSK | UART_ISR_TII_MSK))
264 uart00_tx_chars(port);
265 if (pass_counter++ > UART00_ISR_PASS_LIMIT)
266 break;
267
268 status = UART_GET_INT_STATUS(port);
269 } while (status);
270
271 return IRQ_HANDLED;
272}
273
274static unsigned int uart00_tx_empty(struct uart_port *port)
275{
276 return UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK? 0 : TIOCSER_TEMT;
277}
278
279static unsigned int uart00_get_mctrl(struct uart_port *port)
280{
281 unsigned int result = 0;
282 unsigned int status;
283
284 status = UART_GET_MSR(port);
285 if (status & UART_MSR_DCD_MSK)
286 result |= TIOCM_CAR;
287 if (status & UART_MSR_DSR_MSK)
288 result |= TIOCM_DSR;
289 if (status & UART_MSR_CTS_MSK)
290 result |= TIOCM_CTS;
291 if (status & UART_MSR_RI_MSK)
292 result |= TIOCM_RI;
293
294 return result;
295}
296
297static void uart00_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
298{
299}
300
301static void uart00_break_ctl(struct uart_port *port, int break_state)
302{
303 unsigned long flags;
304 unsigned int mcr;
305
306 spin_lock_irqsave(&port->lock, flags);
307 mcr = UART_GET_MCR(port);
308 if (break_state == -1)
309 mcr |= UART_MCR_BR_MSK;
310 else
311 mcr &= ~UART_MCR_BR_MSK;
312 UART_PUT_MCR(port, mcr);
313 spin_unlock_irqrestore(&port->lock, flags);
314}
315
316static void
317uart00_set_termios(struct uart_port *port, struct termios *termios,
318 struct termios *old)
319{
320 unsigned int uart_mc, old_ies, baud, quot;
321 unsigned long flags;
322
323 /*
324 * We don't support CREAD (yet)
325 */
326 termios->c_cflag |= CREAD;
327
328 /*
329 * Ask the core to calculate the divisor for us.
330 */
331 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
332 quot = uart_get_divisor(port, baud);
333
334 /* byte size and parity */
335 switch (termios->c_cflag & CSIZE) {
336 case CS5:
337 uart_mc = UART_MC_CLS_CHARLEN_5;
338 break;
339 case CS6:
340 uart_mc = UART_MC_CLS_CHARLEN_6;
341 break;
342 case CS7:
343 uart_mc = UART_MC_CLS_CHARLEN_7;
344 break;
345 default: // CS8
346 uart_mc = UART_MC_CLS_CHARLEN_8;
347 break;
348 }
349 if (termios->c_cflag & CSTOPB)
350 uart_mc|= UART_MC_ST_TWO;
351 if (termios->c_cflag & PARENB) {
352 uart_mc |= UART_MC_PE_MSK;
353 if (!(termios->c_cflag & PARODD))
354 uart_mc |= UART_MC_EP_MSK;
355 }
356
357 spin_lock_irqsave(&port->lock, flags);
358
359 /*
360 * Update the per-port timeout.
361 */
362 uart_update_timeout(port, termios->c_cflag, baud);
363
364 port->read_status_mask = UART_RDS_OE_MSK;
365 if (termios->c_iflag & INPCK)
366 port->read_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
367 if (termios->c_iflag & (BRKINT | PARMRK))
368 port->read_status_mask |= UART_RDS_BI_MSK;
369
370 /*
371 * Characters to ignore
372 */
373 port->ignore_status_mask = 0;
374 if (termios->c_iflag & IGNPAR)
375 port->ignore_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
376 if (termios->c_iflag & IGNBRK) {
377 port->ignore_status_mask |= UART_RDS_BI_MSK;
378 /*
379 * If we're ignoring parity and break indicators,
380 * ignore overruns to (for real raw support).
381 */
382 if (termios->c_iflag & IGNPAR)
383 port->ignore_status_mask |= UART_RDS_OE_MSK;
384 }
385
386 /* first, disable everything */
387 old_ies = UART_GET_IES(port);
388
389 if (UART_ENABLE_MS(port, termios->c_cflag))
390 old_ies |= UART_IES_ME_MSK;
391
392 /* Set baud rate */
393 UART_PUT_DIV_LO(port, (quot & 0xff));
394 UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
395
396 UART_PUT_MC(port, uart_mc);
397 UART_PUT_IES(port, old_ies);
398
399 spin_unlock_irqrestore(&port->lock, flags);
400}
401
402static int uart00_startup(struct uart_port *port)
403{
404 int result;
405
406 /*
407 * Allocate the IRQ
408 */
409 result = request_irq(port->irq, uart00_int, 0, "uart00", port);
410 if (result) {
411 printk(KERN_ERR "Request of irq %d failed\n", port->irq);
412 return result;
413 }
414
415 /*
416 * Finally, enable interrupts. Use the TII interrupt to minimise
417 * the number of interrupts generated. If higher performance is
418 * needed, consider using the TI interrupt with a suitable FIFO
419 * threshold
420 */
421 UART_PUT_IES(port, UART_IES_RE_MSK | UART_IES_TIE_MSK);
422
423 return 0;
424}
425
426static void uart00_shutdown(struct uart_port *port)
427{
428 /*
429 * disable all interrupts, disable the port
430 */
431 UART_PUT_IEC(port, 0xff);
432
433 /* disable break condition and fifos */
434 UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK);
435
436 /*
437 * Free the interrupt
438 */
439 free_irq(port->irq, port);
440}
441
442static const char *uart00_type(struct uart_port *port)
443{
444 return port->type == PORT_UART00 ? "Altera UART00" : NULL;
445}
446
447/*
448 * Release the memory region(s) being used by 'port'
449 */
450static void uart00_release_port(struct uart_port *port)
451{
452 release_mem_region(port->mapbase, UART_PORT_SIZE);
453
454#ifdef CONFIG_ARCH_CAMELOT
455 if (port->membase != (void*)IO_ADDRESS(EXC_UART00_BASE)) {
456 iounmap(port->membase);
457 }
458#endif
459}
460
461/*
462 * Request the memory region(s) being used by 'port'
463 */
464static int uart00_request_port(struct uart_port *port)
465{
466 return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_uart00")
467 != NULL ? 0 : -EBUSY;
468}
469
470/*
471 * Configure/autoconfigure the port.
472 */
473static void uart00_config_port(struct uart_port *port, int flags)
474{
475
476 /*
477 * Map the io memory if this is a soft uart
478 */
479 if (!port->membase)
480 port->membase = ioremap_nocache(port->mapbase,SZ_4K);
481
482 if (!port->membase)
483 printk(KERN_ERR "serial00: cannot map io memory\n");
484 else
485 port->type = PORT_UART00;
486
487}
488
489/*
490 * verify the new serial_struct (for TIOCSSERIAL).
491 */
492static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser)
493{
494 int ret = 0;
495 if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
496 ret = -EINVAL;
497 if (ser->irq < 0 || ser->irq >= NR_IRQS)
498 ret = -EINVAL;
499 if (ser->baud_base < 9600)
500 ret = -EINVAL;
501 return ret;
502}
503
504static struct uart_ops uart00_pops = {
505 .tx_empty = uart00_tx_empty,
506 .set_mctrl = uart00_set_mctrl_null,
507 .get_mctrl = uart00_get_mctrl,
508 .stop_tx = uart00_stop_tx,
509 .start_tx = uart00_start_tx,
510 .stop_rx = uart00_stop_rx,
511 .enable_ms = uart00_enable_ms,
512 .break_ctl = uart00_break_ctl,
513 .startup = uart00_startup,
514 .shutdown = uart00_shutdown,
515 .set_termios = uart00_set_termios,
516 .type = uart00_type,
517 .release_port = uart00_release_port,
518 .request_port = uart00_request_port,
519 .config_port = uart00_config_port,
520 .verify_port = uart00_verify_port,
521};
522
523
524#ifdef CONFIG_ARCH_CAMELOT
525static struct uart_port epxa10db_port = {
526 .membase = (void*)IO_ADDRESS(EXC_UART00_BASE),
527 .mapbase = EXC_UART00_BASE,
528 .iotype = SERIAL_IO_MEM,
529 .irq = IRQ_UART,
530 .uartclk = EXC_AHB2_CLK_FREQUENCY,
531 .fifosize = 16,
532 .ops = &uart00_pops,
533 .flags = ASYNC_BOOT_AUTOCONF,
534};
535#endif
536
537
538#ifdef CONFIG_SERIAL_UART00_CONSOLE
539static void uart00_console_write(struct console *co, const char *s, unsigned count)
540{
541#ifdef CONFIG_ARCH_CAMELOT
542 struct uart_port *port = &epxa10db_port;
543 unsigned int status, old_ies;
544 int i;
545
546 /*
547 * First save the CR then disable the interrupts
548 */
549 old_ies = UART_GET_IES(port);
550 UART_PUT_IEC(port,0xff);
551
552 /*
553 * Now, do each character
554 */
555 for (i = 0; i < count; i++) {
556 do {
557 status = UART_GET_TSR(port);
558 } while (!UART_TX_READY(status));
559 UART_PUT_CHAR(port, s[i]);
560 if (s[i] == '\n') {
561 do {
562 status = UART_GET_TSR(port);
563 } while (!UART_TX_READY(status));
564 UART_PUT_CHAR(port, '\r');
565 }
566 }
567
568 /*
569 * Finally, wait for transmitter to become empty
570 * and restore the IES
571 */
572 do {
573 status = UART_GET_TSR(port);
574 } while (status & UART_TSR_TX_LEVEL_MSK);
575 UART_PUT_IES(port, old_ies);
576#endif
577}
578
579static void __init
580uart00_console_get_options(struct uart_port *port, int *baud,
581 int *parity, int *bits)
582{
583 unsigned int uart_mc, quot;
584
585 uart_mc = UART_GET_MC(port);
586
587 *parity = 'n';
588 if (uart_mc & UART_MC_PE_MSK) {
589 if (uart_mc & UART_MC_EP_MSK)
590 *parity = 'e';
591 else
592 *parity = 'o';
593 }
594
595 switch (uart_mc & UART_MC_CLS_MSK) {
596 case UART_MC_CLS_CHARLEN_5:
597 *bits = 5;
598 break;
599 case UART_MC_CLS_CHARLEN_6:
600 *bits = 6;
601 break;
602 case UART_MC_CLS_CHARLEN_7:
603 *bits = 7;
604 break;
605 case UART_MC_CLS_CHARLEN_8:
606 *bits = 8;
607 break;
608 }
609 quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
610 *baud = port->uartclk / (16 *quot );
611}
612
613static int __init uart00_console_setup(struct console *co, char *options)
614{
615 struct uart_port *port;
616 int baud = 115200;
617 int bits = 8;
618 int parity = 'n';
619 int flow = 'n';
620
621#ifdef CONFIG_ARCH_CAMELOT
622 port = &epxa10db_port; ;
623#else
624 return -ENODEV;
625#endif
626 if (options)
627 uart_parse_options(options, &baud, &parity, &bits, &flow);
628 else
629 uart00_console_get_options(port, &baud, &parity, &bits);
630
631 return uart_set_options(port, co, baud, parity, bits, flow);
632}
633
634extern struct uart_driver uart00_reg;
635static struct console uart00_console = {
636 .name = SERIAL_UART00_NAME,
637 .write = uart00_console_write,
638 .device = uart_console_device,
639 .setup = uart00_console_setup,
640 .flags = CON_PRINTBUFFER,
641 .index = 0,
642 .data = &uart00_reg,
643};
644
645static int __init uart00_console_init(void)
646{
647 register_console(&uart00_console);
648 return 0;
649}
650console_initcall(uart00_console_init);
651
652#define UART00_CONSOLE &uart00_console
653#else
654#define UART00_CONSOLE NULL
655#endif
656
657static struct uart_driver uart00_reg = {
658 .owner = NULL,
659 .driver_name = SERIAL_UART00_NAME,
660 .dev_name = SERIAL_UART00_NAME,
661 .major = SERIAL_UART00_MAJOR,
662 .minor = SERIAL_UART00_MINOR,
663 .nr = UART_NR,
664 .cons = UART00_CONSOLE,
665};
666
667struct dev_port_entry{
668 unsigned int base_addr;
669 struct uart_port *port;
670};
671
672#ifdef CONFIG_PLD_HOTSWAP
673
674static struct dev_port_entry dev_port_map[UART_NR];
675
676/*
677 * Keep a mapping of dev_info addresses -> port lines to use when
678 * removing ports dev==NULL indicates unused entry
679 */
680
681struct uart00_ps_data{
682 unsigned int clk;
683 unsigned int fifosize;
684};
685
686int uart00_add_device(struct pldhs_dev_info* dev_info, void* dev_ps_data)
687{
688 struct uart00_ps_data* dev_ps=dev_ps_data;
689 struct uart_port * port;
690 int i,result;
691
692 i=0;
693 while(dev_port_map[i].port)
694 i++;
695
696 if(i==UART_NR){
697 printk(KERN_WARNING "uart00: Maximum number of ports reached\n");
698 return 0;
699 }
700
701 port=kmalloc(sizeof(struct uart_port),GFP_KERNEL);
702 if(!port)
703 return -ENOMEM;
704
705 printk("clk=%d fifo=%d\n",dev_ps->clk,dev_ps->fifosize);
706 port->membase=0;
707 port->mapbase=dev_info->base_addr;
708 port->iotype=SERIAL_IO_MEM;
709 port->irq=dev_info->irq;
710 port->uartclk=dev_ps->clk;
711 port->fifosize=dev_ps->fifosize;
712 port->ops=&uart00_pops;
713 port->line=i;
714 port->flags=ASYNC_BOOT_AUTOCONF;
715
716 result=uart_add_one_port(&uart00_reg, port);
717 if(result){
718 printk("uart_add_one_port returned %d\n",result);
719 return result;
720 }
721 dev_port_map[i].base_addr=dev_info->base_addr;
722 dev_port_map[i].port=port;
723 printk("uart00: added device at %x as ttyUA%d\n",dev_port_map[i].base_addr,i);
724 return 0;
725
726}
727
728int uart00_remove_devices(void)
729{
730 int i,result;
731
732
733 result=0;
734 for(i=1;i<UART_NR;i++){
735 if(dev_port_map[i].base_addr){
736 result=uart_remove_one_port(&uart00_reg, dev_port_map[i].port);
737 if(result)
738 return result;
739
740 /* port removed sucessfully, so now tidy up */
741 kfree(dev_port_map[i].port);
742 dev_port_map[i].base_addr=0;
743 dev_port_map[i].port=NULL;
744 }
745 }
746 return 0;
747
748}
749
750struct pld_hotswap_ops uart00_pldhs_ops={
751 .name = "uart00",
752 .add_device = uart00_add_device,
753 .remove_devices = uart00_remove_devices,
754};
755
756#endif
757
758static int __init uart00_init(void)
759{
760 int result;
761
762 printk(KERN_INFO "Serial: UART00 driver $Revision: 1.35 $\n");
763
764 printk(KERN_WARNING "serial_uart00:Using temporary major/minor pairs"
765 " - these WILL change in the future\n");
766
767 result = uart_register_driver(&uart00_reg);
768 if (result)
769 return result;
770#ifdef CONFIG_ARCH_CAMELOT
771 result = uart_add_one_port(&uart00_reg,&epxa10db_port);
772#endif
773 if (result)
774 uart_unregister_driver(&uart00_reg);
775
776#ifdef CONFIG_PLD_HOTSWAP
777 pldhs_register_driver(&uart00_pldhs_ops);
778#endif
779 return result;
780}
781
782__initcall(uart00_init);