2 * linux/drivers/char/p2001_uart.c
4 * Driver for P2001 uart port
6 * Copyright (C) 2004 Tobias Lorenz
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Version 1.0: First working version
25 * Version 1.1: Removed all READ_REG/WRITE_REG
26 * Version 1.2: Break handling
27 * Version 1.3: Hardware handshake
28 * Device naming, major/minor nr for setserial
32 #include <linux/config.h>
33 #include <linux/module.h>
34 #include <linux/tty.h>
35 #include <linux/ioport.h>
36 #include <linux/init.h>
37 #include <linux/serial.h>
38 #include <linux/console.h>
39 #include <linux/sysrq.h>
40 #include <linux/device.h>
41 #include <linux/serial_core.h>
45 #include <asm/hardware.h>
47 #if defined(CONFIG_P2001_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
52 /**************************************************************************
54 **************************************************************************/
55 static const char *version
=
56 "p2001_uart.c:v1.3 10/02/2004 Tobias Lorenz (tobias.lorenz@gmx.net)\n";
58 static const char p2001_uart_name
[] = "P2001 uart";
62 #define tx_enabled(port) ((port)->unused[0])
63 #define rx_enabled(port) ((port)->unused[1])
65 extern struct uart_driver p2001_uart_driver
; /* UART Driver */
66 extern struct uart_port p2001_uart_port
; /* UART Port */
67 extern struct uart_ops p2001_uart_ops
; /* UART Operations */
68 extern struct console p2001_console
; /* Console */
72 /**************************************************************************
74 **************************************************************************/
76 static struct uart_driver p2001_uart_driver
= {
78 .driver_name
= "serial", /* name of tty/console device */
79 .dev_name
= "ttyS", /* name of tty/console device */
80 #ifdef CONFIG_DEVFS_FS
81 .devfs_name
= "tts/", /* name of tty/console device */
83 .major
= 4, /* major number for the driver */
84 .minor
= 64, /* starting minor number */
85 .nr
= 1, /* maximum number of serial ports this driver supports */
86 #ifdef CONFIG_P2001_UART_CONSOLE
87 .cons
= &p2001_console
,
93 /**************************************************************************
95 **************************************************************************/
97 static struct uart_port p2001_uart_port
= {
98 .membase
= (void*)P2001_UART
, /* read/write[bwl] */
99 .mapbase
= (unsigned int)P2001_UART
, /* for ioremap */
100 .iotype
= UPIO_MEM
, /* io access style */
101 .irq
= IRQ_UART
, /* irq number */
102 .uartclk
= CONFIG_SYSCLK
/8, /* base uart clock */
103 .fifosize
= 32, /* tx fifo size */
104 .ops
= &p2001_uart_ops
,
105 .flags
= UPF_BOOT_AUTOCONF
,
106 .line
= 0, /* port index */
111 /**************************************************************************
112 * UART interrupt routine
113 **************************************************************************/
115 /* uart interrupt send routine */
116 static void p2001_uart_tx_chars(struct uart_port
*port
)
118 struct circ_buf
*xmit
= &port
->info
->xmit
;
122 while ((P2001_UART
->r
.STATUS
& 0x3f) > TX_MIN_BUF
)
124 P2001_UART
->w
.TX1
= port
->x_char
;
129 if (uart_circ_empty(xmit
) || uart_tx_stopped(port
)) {
130 tx_enabled(port
) = 0;
134 count
= port
->fifosize
>> 1;
136 while ((P2001_UART
->r
.STATUS
& 0x3f) > TX_MIN_BUF
)
138 P2001_UART
->w
.TX1
= xmit
->buf
[xmit
->tail
];
139 xmit
->tail
= (xmit
->tail
+ 1) & (UART_XMIT_SIZE
- 1);
141 if (uart_circ_empty(xmit
))
143 } while (--count
> 0);
145 if (uart_circ_chars_pending(xmit
) < WAKEUP_CHARS
)
146 uart_write_wakeup(port
);
148 if (uart_circ_empty(xmit
))
149 tx_enabled(port
) = 0;
151 P2001_UART
->w
.IRQ_Status
|= (1<<0);
154 /* uart interrupt receive routine */
155 static void p2001_uart_rx_chars(struct uart_port
*port
, struct pt_regs
*regs
)
157 struct tty_struct
*tty
= port
->info
->tty
;
159 unsigned int rxddelta
;
161 unsigned int max_count
= 256;
163 status
= P2001_UART
->r
.IRQ_Status
;
164 rxddelta
= (P2001_UART
->r
.STATUS
>> 6) & 0x3f;
165 while (rxddelta
&& max_count
--) {
166 if (tty
->flip
.count
>= TTY_FLIPBUF_SIZE
) {
167 tty
->flip
.work
.func((void *)tty
);
168 if (tty
->flip
.count
>= TTY_FLIPBUF_SIZE
) {
169 printk(KERN_WARNING
"TTY_DONT_FLIP set\n");
174 rx
= P2001_UART
->r
.RX1
;
176 *tty
->flip
.char_buf_ptr
= rx
& 0xff;
177 *tty
->flip
.flag_buf_ptr
= TTY_NORMAL
;
181 * Note that the error handling code is
182 * out of the main execution path
184 if (status
& ((1<<7)|(1<<6)|(1<<9))) {
185 if (status
& (1<<7)) { /* RxD_BRK */
187 if (uart_handle_break(port
))
189 } else if (status
& (1<<6)) /* RxD_FIFO_PAR_ERR */
190 port
->icount
.parity
++;
191 if (status
& (1<<9)) /* RxD_LOST */
192 port
->icount
.overrun
++;
194 status
&= port
->read_status_mask
;
196 if (status
& (1<<7)) /* RxD_BRK */
197 *tty
->flip
.flag_buf_ptr
= TTY_BREAK
;
198 else if (status
& (1<<6)) /* RxD_FIFO_PAR_ERR */
199 *tty
->flip
.flag_buf_ptr
= TTY_PARITY
;
203 if (uart_handle_sysrq_char(port
, ch
, regs
))
206 if (rx
&& port
->ignore_status_mask
== 0) {
207 tty
->flip
.flag_buf_ptr
++;
208 tty
->flip
.char_buf_ptr
++;
211 if ((status
& (1<<9)) && /* RxD_LOST */
212 tty
->flip
.count
< TTY_FLIPBUF_SIZE
) {
214 * Overrun is special, since it's reported
215 * immediately, and doesn't affect the current
218 *tty
->flip
.char_buf_ptr
++ = 0;
219 *tty
->flip
.flag_buf_ptr
++ = TTY_OVERRUN
;
223 rxddelta
= (P2001_UART
->r
.STATUS
>> 6) & 0x3f;
225 tty_flip_buffer_push(tty
);
227 P2001_UART
->w
.IRQ_Status
|= (1<<3) | (1<<6) | (1<<7) | (1<<9);
230 /* uart interrupt routine */
231 static irqreturn_t
p2001_uart_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
233 struct uart_port
*port
= dev_id
;
236 spin_lock(&port
->lock
);
238 status
= P2001_UART
->r
.IRQ_Status
;
239 // TXD_SEND | TXD_LAST_DATA
240 if (status
& (1<<0)) // (1<<2)
241 p2001_uart_tx_chars(port
);
242 // RXD_DATA | RxD_FIFO_PAR_ERR | RxD_BRK | RxD_LOST
243 if (status
& ((1<<3) | (1<<6) | (1<<7) | (1<<9)))
244 p2001_uart_rx_chars(port
, regs
);
246 //status &= ~((1<<0) | (1<<2) | (1<<3));
247 //if (status & 0x3ff)
248 // printk(KERN_INFO "p2001_uart_interrupt: status=0x%8.8x\n", status);
250 P2001_UART
->w
.IRQ_Status
&= ~0x3ff;
252 spin_unlock(&port
->lock
);
259 /**************************************************************************
261 **************************************************************************/
263 /* returns if the port transmitter is empty or not. */
264 static unsigned int p2001_uart_ops_tx_empty(struct uart_port
*port
)
266 unsigned int txddelta
= P2001_UART
->r
.STATUS
& 0x3f;
267 return (txddelta
> 0) ? 0 : TIOCSER_TEMT
;
270 /* sets a new value for the MCR UART register. */
271 static void p2001_uart_ops_set_mctrl(struct uart_port
*port
, unsigned int mctrl
)
273 /* no modem control lines */
276 /* gets the current MCR UART register value. */
277 static unsigned int p2001_uart_ops_get_mctrl(struct uart_port
*port
)
279 /* no modem control lines */
280 return TIOCM_CAR
| TIOCM_DSR
| TIOCM_CTS
;
283 /* stops the port from sending data. */
284 static void p2001_uart_ops_stop_tx(struct uart_port
*port
, unsigned int tty_stop
)
286 if (tx_enabled(port
)) {
287 P2001_UART
->w
.IRQ_Status
&= ~((1<<20) | (1<<22)); // TXD_SEND | TXD_LAST_DATA
288 tx_enabled(port
) = 0;
292 /* starts the port sending data. */
293 static void p2001_uart_ops_start_tx(struct uart_port
*port
, unsigned int tty_start
)
295 if (!tx_enabled(port
)) {
296 P2001_UART
->w
.IRQ_Status
|= (1<<20) | (1<<22); // TXD_SEND | TXD_LAST_DATA
297 tx_enabled(port
) = 1;
299 p2001_uart_tx_chars(port
);
302 /* tells the port to send the XOFF character to the host. */
304 static void p2001_uart_ops_send_xchar(struct uart_port
*port
, char ch
)
306 #warning "p2001_uart_ops_send_xchar is not implemented."
310 /* stops receiving data. */
311 static void p2001_uart_ops_stop_rx(struct uart_port
*port
)
313 if (rx_enabled(port
)) {
314 P2001_UART
->w
.IRQ_Status
&= ~(1<<23); // RXD_DATA
315 rx_enabled(port
) = 0;
319 /* enables the modem status interrupts. */
320 static void p2001_uart_ops_enable_ms(struct uart_port
*port
)
325 /* sends the BREAK value over the port. */
326 static void p2001_uart_ops_break_ctl(struct uart_port
*port
, int ctl
)
328 /* no break signal */
331 /* called once each time the open call happens */
332 static int p2001_uart_ops_startup(struct uart_port
*port
)
336 tx_enabled(port
) = 1;
337 rx_enabled(port
) = 1;
339 ret
= request_irq(port
->irq
, p2001_uart_interrupt
, 0, p2001_uart_name
, port
);
341 P2001_UART
->w
.Clear
= 0;
342 // TXD_SEND | TXD_LAST_DATA
343 P2001_UART
->w
.IRQ_Status
|= (1<<20) | (1<<22);
344 // RXD_DATA | RxD_FIFO_PAR_ERR | RxD_BRK | RxD_LOST
345 P2001_UART
->w
.IRQ_Status
|= (1<<23) | (1<<26) | (1<<27) | (1<<29);
350 /* called when the port is closed */
351 static void p2001_uart_ops_shutdown(struct uart_port
*port
)
353 free_irq(port
->irq
, port
);
356 /* called whenever the port line settings need to be modified */
357 static void p2001_uart_ops_set_termios(struct uart_port
*port
, struct termios
*new, struct termios
*old
)
361 unsigned int baud
, quot
;
364 * Ask the core to calculate the divisor for us.
366 baud
= uart_get_baud_rate(port
, new, old
, 0, port
->uartclk
); // min:0/max:port->uartclk
367 quot
= (port
->uartclk
* 3)/baud
;
369 /* interrupt level */
370 config
= (12 << 11) | (12 << 17); /* RXDHIGHWATER = 12, TXDLOWWATER = 12 */
373 switch (new->c_cflag
& CSIZE
) {
375 config
|= (5 << 5); /* WORDLENGTH = 5 */
378 config
|= (6 << 5); /* WORDLENGTH = 6 */
381 config
|= (7 << 5); /* WORDLENGTH = 7 */
384 config
|= (8 << 5); /* WORDLENGTH = 8 */
389 if (new->c_cflag
& PARENB
) {
390 if (!(new->c_cflag
& PARODD
))
391 config
|= (1 << 2); /* PARITYMODE = 1 (Even Parity) */
393 config
|= (2 << 2); /* PARITYMODE = 2 (Odd Parity) */
397 if (new->c_cflag
& CSTOPB
)
398 config
|= (1 << 0); /* STOPBITAW = 1 (1 Stopbit) */
400 /* hardware flow control */
401 if (new->c_cflag
& CRTSCTS
) {
402 config
|= (1 << 10); /* USECTS = 1 */
403 P2001_GPIO
->PIN_MUX
|= (1<<5);
405 P2001_GPIO
->PIN_MUX
&= ~(1<<5);
408 spin_lock_irqsave(&port
->lock
, flags
);
411 * Update the per-port timeout.
413 uart_update_timeout(port
, new->c_cflag
, baud
);
415 port
->read_status_mask
= (1<<9); /* RXD_DATA_LOST */
416 if (new->c_iflag
& INPCK
)
417 port
->read_status_mask
|= (1<<6); /* RxD_FIFO_PAR_ERR */
418 if (new->c_iflag
& (BRKINT
| PARMRK
))
419 port
->read_status_mask
|= (1<<7); /* RxD_BRK */
422 * Characters to ignore
424 port
->ignore_status_mask
= 0;
425 if (new->c_iflag
& IGNPAR
)
426 port
->ignore_status_mask
|= (1<<6); /* RxD_FIFO_PAR_ERR */
427 if (new->c_iflag
& IGNBRK
) {
428 port
->ignore_status_mask
|= (1<<7); /* RxD_BRK */
430 * If we're ignoring parity and break indicators,
431 * ignore overruns too (for real raw support).
433 if (new->c_iflag
& IGNPAR
)
434 port
->ignore_status_mask
|= (1<<9); /* RxD_LOST */
438 * Ignore all characters if CREAD is not set.
440 if ((new->c_cflag
& CREAD
) == 0)
441 port
->ignore_status_mask
|= (1<<3); /* RXD_DATA */
444 P2001_UART
->w
.Baudrate
= (quot
<<16)+3;
445 P2001_UART
->w
.Config
= config
;
447 spin_unlock_irqrestore(&port
->lock
, flags
);
450 /* power management: power the hardware down */
452 static void p2001_uart_ops_pm(struct uart_port
*port
, unsigned int state
, unsigned int oldstate
)
454 #warning "p2001_uart_ops_pm is not implemented."
458 /* power management: power the hardware up */
460 static int p2001_uart_ops_set_wake(struct uart_port
*port
, unsigned int state
)
462 #warning "p2001_uart_ops_set_wake is not implemented."
467 * Return a string describing the port type
469 static const char *p2001_uart_ops_type(struct uart_port
*port
)
471 return port
->type
== PORT_P2001
? "P2001" : NULL
;
475 * Release IO and memory resources used by
476 * the port. This includes iounmap if necessary.
478 static void p2001_uart_ops_release_port(struct uart_port
*port
)
480 release_mem_region(port
->mapbase
, 0x30);
484 * Request IO and memory resources used by the
485 * port. This includes iomapping the port if
488 static int p2001_uart_ops_request_port(struct uart_port
*port
)
490 return request_mem_region(port
->mapbase
, 0x30, p2001_uart_name
)
491 != NULL
? 0 : -EBUSY
;
495 * Configure/autoconfigure the port.
497 static void p2001_uart_ops_config_port(struct uart_port
*port
, int flags
)
499 if (flags
& UART_CONFIG_TYPE
&& p2001_uart_ops_request_port(port
) == 0)
500 port
->type
= PORT_P2001
;
504 * Verify the new serial_struct (for TIOCSSERIAL).
506 static int p2001_uart_ops_verify_port(struct uart_port
*port
, struct serial_struct
*ser
)
509 if (ser
->type
!= PORT_UNKNOWN
&& ser
->type
!= PORT_P2001
)
511 if (ser
->irq
!= NO_IRQ
)
516 /* device specific ioctl calls */
518 static int p2001_uart_ops_ioctl(struct uart_port
*port
, unsigned int, unsigned long)
520 #warning "p2001_uart_ops_ioctl is not implemented."
525 static struct uart_ops p2001_uart_ops
= {
526 .tx_empty
= p2001_uart_ops_tx_empty
, /* returns if the port transmitter is empty or not. */
527 .set_mctrl
= p2001_uart_ops_set_mctrl
, /* sets a new value for the MCR UART register. */
528 .get_mctrl
= p2001_uart_ops_get_mctrl
, /* gets the current MCR UART register value. */
529 .stop_tx
= p2001_uart_ops_stop_tx
, /* stops the port from sending data. */
530 .start_tx
= p2001_uart_ops_start_tx
, /* starts the port sending data. */
531 // .send_xchar = p2001_uart_ops_send_xchar, /* tells the port to send the XOFF character to the host. */
532 .stop_rx
= p2001_uart_ops_stop_rx
, /* stops receiving data. */
533 .enable_ms
= p2001_uart_ops_enable_ms
, /* enables the modem status interrupts. */
534 .break_ctl
= p2001_uart_ops_break_ctl
, /* sends the BREAK value over the port. */
535 .startup
= p2001_uart_ops_startup
, /* called once each time the open call happens */
536 .shutdown
= p2001_uart_ops_shutdown
, /* called when the port is closed */
537 .set_termios
= p2001_uart_ops_set_termios
, /* called whenever the port line settings need to be modified */
539 .pm
= p2001_uart_ops_pm
, /* power management: power the hardware down */
540 .set_wake
= p2001_uart_ops_set_wake
, /* power management: power the hardware up */
542 .type
= p2001_uart_ops_type
, /* Return a string describing the port type */
543 .release_port
= p2001_uart_ops_release_port
, /* Release the region(s) being used by 'port' */
544 .request_port
= p2001_uart_ops_request_port
, /* Request the region(s) being used by 'port' */
545 .config_port
= p2001_uart_ops_config_port
, /* Configure/autoconfigure the port. */
546 .verify_port
= p2001_uart_ops_verify_port
, /* Verify the new serial_struct (for TIOCSSERIAL). */
547 // .ioctl = p2001_uart_ops_ioctl, /* device specific ioctl calls */
552 /**************************************************************************
554 **************************************************************************/
556 #ifdef CONFIG_P2001_UART_CONSOLE
558 /* the function used to print kernel messages */
559 static void p2001_console_write(struct console
*co
, const char *s
, unsigned int count
)
563 for (i
= 0; i
< count
; i
++) {
564 while ((P2001_UART
->r
.STATUS
& 0x3f) > TX_MIN_BUF
)
566 P2001_UART
->w
.TX1
= s
[i
];
568 while ((P2001_UART
->r
.STATUS
& 0x3f) > TX_MIN_BUF
)
570 P2001_UART
->w
.TX1
= '\r';
575 /* the function is called when the console= command-line argument matches the name for this console structure. */
576 static int __init
p2001_console_setup(struct console
*co
, char *options
)
578 struct uart_port
*port
= &p2001_uart_port
;
585 uart_parse_options(options
, &baud
, &parity
, &bits
, &flow
);
587 return uart_set_options(port
, co
, baud
, parity
, bits
, flow
);
591 static struct console p2001_console
= {
592 .name
= "ttyS", /* the name of the console device is used to parse the console= command line option. */
593 .write
= p2001_console_write
, /* the function used to print kernel messages */
594 // .read = p2001_console_read, /* ??? */
595 .device
= uart_console_device
, /* a function that returns the device number for the underlying tty device that is currently acting as a console */
596 // .unblank = p2001_console_unblank, /* the function, if defined, is used to unblank the screen. */
597 .setup
= p2001_console_setup
, /* the function is called when the console= command-line argument matches the name for this console structure. */
598 .flags
= CON_PRINTBUFFER
, /* various console flags */
599 .index
= -1, /* the number of the device acting as a console in an array of devices. */
601 .data
= &p2001_uart_driver
,
604 static int __init
p2001_console_init(void)
606 register_console(&p2001_console
);
609 console_initcall(p2001_console_init
);
614 /**************************************************************************
616 **************************************************************************/
618 static int __init
p2001_uart_init(void)
623 ret
= uart_register_driver(&p2001_uart_driver
);
625 uart_add_one_port(&p2001_uart_driver
, &p2001_uart_port
);
630 static void __exit
p2001_uart_exit(void)
632 uart_remove_one_port(&p2001_uart_driver
, &p2001_uart_port
);
633 uart_unregister_driver(&p2001_uart_driver
);
636 module_init(p2001_uart_init
);
637 module_exit(p2001_uart_exit
);
639 MODULE_AUTHOR("Tobias Lorenz");
640 MODULE_DESCRIPTION("P2001 uart driver");
641 MODULE_LICENSE("GPL");