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
30 * Version 1.4: cpu frequency scaling
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>
43 #ifdef CONFIG_CPU_FREQ
44 #include <linux/notifier.h>
45 #include <linux/cpufreq.h>
50 #include <asm/hardware.h>
52 #if defined(CONFIG_SERIAL_P2001_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
57 /**************************************************************************
59 **************************************************************************/
60 static const char *version
=
61 "p2001_uart.c:v1.4 12/29/2004 Tobias Lorenz (tobias.lorenz@gmx.net)\n";
63 static const char p2001_uart_name
[] = "P2001 uart";
67 #define tx_enabled(port) ((port)->unused[0])
68 #define rx_enabled(port) ((port)->unused[1])
70 extern struct uart_driver p2001_uart_driver
; /* UART Driver */
71 extern struct uart_port p2001_uart_port
; /* UART Port */
72 extern struct uart_ops p2001_uart_ops
; /* UART Operations */
73 extern struct console p2001_console
; /* Console */
75 #define DEFAULT_BAUD 57600
76 static unsigned int baud
; /* Current baudrate */
80 /**************************************************************************
82 **************************************************************************/
84 static struct uart_driver p2001_uart_driver
= {
86 .driver_name
= "serial", /* name of tty/console device */
87 .dev_name
= "ttyS", /* name of tty/console device */
88 #ifdef CONFIG_DEVFS_FS
89 .devfs_name
= "tts/", /* name of tty/console device */
91 .major
= 4, /* major number for the driver */
92 .minor
= 64, /* starting minor number */
93 .nr
= 1, /* maximum number of serial ports this driver supports */
94 #ifdef CONFIG_SERIAL_P2001_UART_CONSOLE
95 .cons
= &p2001_console
,
101 /**************************************************************************
103 **************************************************************************/
105 static struct uart_port p2001_uart_port
= {
106 .membase
= (void*)P2001_UART
, /* read/write[bwl] */
107 .mapbase
= (unsigned int)P2001_UART
, /* for ioremap */
108 .iotype
= UPIO_MEM
, /* io access style */
109 .irq
= IRQ_UART
, /* irq number */
110 .uartclk
= CONFIG_SYSCLK
/8, /* base uart clock */
111 .fifosize
= 32, /* tx fifo size */
112 .ops
= &p2001_uart_ops
,
113 .flags
= UPF_BOOT_AUTOCONF
,
114 .line
= 0, /* port index */
119 /**************************************************************************
120 * UART interrupt routine
121 **************************************************************************/
123 /* uart interrupt send routine */
124 static void p2001_uart_tx_chars(struct uart_port
*port
)
126 struct circ_buf
*xmit
= &port
->info
->xmit
;
130 while ((P2001_UART
->r
.STATUS
& 0x3f) > TX_MIN_BUF
)
132 P2001_UART
->w
.TX
[0] = port
->x_char
;
137 if (uart_circ_empty(xmit
) || uart_tx_stopped(port
)) {
138 tx_enabled(port
) = 0;
142 count
= port
->fifosize
>> 1;
144 while ((P2001_UART
->r
.STATUS
& 0x3f) > TX_MIN_BUF
)
146 P2001_UART
->w
.TX
[0] = xmit
->buf
[xmit
->tail
];
147 xmit
->tail
= (xmit
->tail
+ 1) & (UART_XMIT_SIZE
- 1);
149 if (uart_circ_empty(xmit
))
151 } while (--count
> 0);
153 if (uart_circ_chars_pending(xmit
) < WAKEUP_CHARS
)
154 uart_write_wakeup(port
);
156 if (uart_circ_empty(xmit
))
157 tx_enabled(port
) = 0;
159 P2001_UART
->w
.IRQ_Status
|= (1<<0);
162 /* uart interrupt receive routine */
163 static void p2001_uart_rx_chars(struct uart_port
*port
, struct pt_regs
*regs
)
165 struct tty_struct
*tty
= port
->info
->tty
;
167 unsigned int rxddelta
;
169 unsigned int max_count
= 256;
171 status
= P2001_UART
->r
.IRQ_Status
;
172 rxddelta
= (P2001_UART
->r
.STATUS
>> 6) & 0x3f;
173 while (rxddelta
&& max_count
--) {
174 if (tty
->flip
.count
>= TTY_FLIPBUF_SIZE
) {
175 tty
->flip
.work
.func((void *)tty
);
176 if (tty
->flip
.count
>= TTY_FLIPBUF_SIZE
) {
177 printk(KERN_WARNING
"TTY_DONT_FLIP set\n");
182 rx
= P2001_UART
->r
.RX
[0];
184 *tty
->flip
.char_buf_ptr
= rx
& 0xff;
185 *tty
->flip
.flag_buf_ptr
= TTY_NORMAL
;
189 * Note that the error handling code is
190 * out of the main execution path
192 if (status
& ((1<<7)|(1<<6)|(1<<9))) {
193 if (status
& (1<<7)) { /* RxD_BRK */
195 if (uart_handle_break(port
))
197 } else if (status
& (1<<6)) /* RxD_FIFO_PAR_ERR */
198 port
->icount
.parity
++;
199 if (status
& (1<<9)) /* RxD_LOST */
200 port
->icount
.overrun
++;
202 status
&= port
->read_status_mask
;
204 if (status
& (1<<7)) /* RxD_BRK */
205 *tty
->flip
.flag_buf_ptr
= TTY_BREAK
;
206 else if (status
& (1<<6)) /* RxD_FIFO_PAR_ERR */
207 *tty
->flip
.flag_buf_ptr
= TTY_PARITY
;
211 if (uart_handle_sysrq_char(port
, ch
, regs
))
214 if (rx
&& port
->ignore_status_mask
== 0) {
215 tty
->flip
.flag_buf_ptr
++;
216 tty
->flip
.char_buf_ptr
++;
219 if ((status
& (1<<9)) && /* RxD_LOST */
220 tty
->flip
.count
< TTY_FLIPBUF_SIZE
) {
222 * Overrun is special, since it's reported
223 * immediately, and doesn't affect the current
226 *tty
->flip
.char_buf_ptr
++ = 0;
227 *tty
->flip
.flag_buf_ptr
++ = TTY_OVERRUN
;
231 rxddelta
= (P2001_UART
->r
.STATUS
>> 6) & 0x3f;
233 tty_flip_buffer_push(tty
);
235 P2001_UART
->w
.IRQ_Status
|= (1<<3) | (1<<6) | (1<<7) | (1<<9);
238 /* uart interrupt routine */
239 static irqreturn_t
p2001_uart_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
241 struct uart_port
*port
= dev_id
;
244 spin_lock(&port
->lock
);
246 status
= P2001_UART
->r
.IRQ_Status
;
247 // TXD_SEND | TXD_LAST_DATA
248 if (status
& (1<<0)) // (1<<2)
249 p2001_uart_tx_chars(port
);
250 // RXD_DATA | RxD_FIFO_PAR_ERR | RxD_BRK | RxD_LOST
251 if (status
& ((1<<3) | (1<<6) | (1<<7) | (1<<9)))
252 p2001_uart_rx_chars(port
, regs
);
254 //status &= ~((1<<0) | (1<<2) | (1<<3));
255 //if (status & 0x3ff)
256 // printk(KERN_INFO "p2001_uart_interrupt: status=0x%8.8x\n", status);
258 P2001_UART
->w
.IRQ_Status
&= ~0x3ff;
260 spin_unlock(&port
->lock
);
267 /**************************************************************************
269 **************************************************************************/
271 /* returns if the port transmitter is empty or not. */
272 static unsigned int p2001_uart_ops_tx_empty(struct uart_port
*port
)
274 unsigned int txddelta
= P2001_UART
->r
.STATUS
& 0x3f;
275 return (txddelta
> 0) ? 0 : TIOCSER_TEMT
;
278 /* sets a new value for the MCR UART register. */
279 static void p2001_uart_ops_set_mctrl(struct uart_port
*port
, unsigned int mctrl
)
281 /* no modem control lines */
284 /* gets the current MCR UART register value. */
285 static unsigned int p2001_uart_ops_get_mctrl(struct uart_port
*port
)
287 /* no modem control lines */
288 return TIOCM_CAR
| TIOCM_DSR
| TIOCM_CTS
;
291 /* stops the port from sending data. */
292 static void p2001_uart_ops_stop_tx(struct uart_port
*port
)
294 if (tx_enabled(port
)) {
295 P2001_UART
->w
.IRQ_Status
&= ~((1<<20) | (1<<22)); // TXD_SEND | TXD_LAST_DATA
296 tx_enabled(port
) = 0;
300 /* starts the port sending data. */
301 static void p2001_uart_ops_start_tx(struct uart_port
*port
)
303 if (!tx_enabled(port
)) {
304 P2001_UART
->w
.IRQ_Status
|= (1<<20) | (1<<22); // TXD_SEND | TXD_LAST_DATA
305 tx_enabled(port
) = 1;
307 p2001_uart_tx_chars(port
);
310 /* tells the port to send the XOFF character to the host. */
312 static void p2001_uart_ops_send_xchar(struct uart_port
*port
, char ch
)
314 #warning "p2001_uart_ops_send_xchar is not implemented."
318 /* stops receiving data. */
319 static void p2001_uart_ops_stop_rx(struct uart_port
*port
)
321 if (rx_enabled(port
)) {
322 P2001_UART
->w
.IRQ_Status
&= ~(1<<23); // RXD_DATA
323 rx_enabled(port
) = 0;
327 /* enables the modem status interrupts. */
328 static void p2001_uart_ops_enable_ms(struct uart_port
*port
)
333 /* sends the BREAK value over the port. */
334 static void p2001_uart_ops_break_ctl(struct uart_port
*port
, int ctl
)
336 /* no break signal */
339 /* called once each time the open call happens */
340 static int p2001_uart_ops_startup(struct uart_port
*port
)
344 tx_enabled(port
) = 1;
345 rx_enabled(port
) = 1;
347 ret
= request_irq(port
->irq
, p2001_uart_interrupt
, 0, p2001_uart_name
, port
);
349 P2001_UART
->w
.Clear
= 0;
350 // TXD_SEND | TXD_LAST_DATA
351 P2001_UART
->w
.IRQ_Status
|= (1<<20) | (1<<22);
352 // RXD_DATA | RxD_FIFO_PAR_ERR | RxD_BRK | RxD_LOST
353 P2001_UART
->w
.IRQ_Status
|= (1<<23) | (1<<26) | (1<<27) | (1<<29);
358 /* called when the port is closed */
359 static void p2001_uart_ops_shutdown(struct uart_port
*port
)
361 free_irq(port
->irq
, port
);
364 /* called whenever the port line settings need to be modified */
365 static void p2001_uart_ops_set_termios(struct uart_port
*port
, struct termios
*new, struct termios
*old
)
369 unsigned int prod
, quot
;
372 * Ask the core to calculate the divisor for us.
374 baud
= uart_get_baud_rate(port
, new, old
, 0, port
->uartclk
); // min:0/max:port->uartclk
376 quot
= (port
->uartclk
* prod
)/baud
;
378 /* interrupt level */
379 config
= (12 << 11) | (12 << 17); /* RXDHIGHWATER = 12, TXDLOWWATER = 12 */
382 switch (new->c_cflag
& CSIZE
) {
384 config
|= (5 << 5); /* WORDLENGTH = 5 */
387 config
|= (6 << 5); /* WORDLENGTH = 6 */
390 config
|= (7 << 5); /* WORDLENGTH = 7 */
393 config
|= (8 << 5); /* WORDLENGTH = 8 */
398 if (new->c_cflag
& PARENB
) {
399 if (!(new->c_cflag
& PARODD
))
400 config
|= (1 << 2); /* PARITYMODE = 1 (Even Parity) */
402 config
|= (2 << 2); /* PARITYMODE = 2 (Odd Parity) */
406 if (new->c_cflag
& CSTOPB
)
407 config
|= (1 << 0); /* STOPBITAW = 1 (1 Stopbit) */
409 /* hardware flow control */
410 if (new->c_cflag
& CRTSCTS
) {
411 config
|= (1 << 10); /* USECTS = 1 */
412 P2001_GPIO
->PIN_MUX
|= (1<<5);
414 P2001_GPIO
->PIN_MUX
&= ~(1<<5);
417 spin_lock_irqsave(&port
->lock
, flags
);
420 * Update the per-port timeout.
422 uart_update_timeout(port
, new->c_cflag
, baud
);
424 port
->read_status_mask
= (1<<9); /* RXD_DATA_LOST */
425 if (new->c_iflag
& INPCK
)
426 port
->read_status_mask
|= (1<<6); /* RxD_FIFO_PAR_ERR */
427 if (new->c_iflag
& (BRKINT
| PARMRK
))
428 port
->read_status_mask
|= (1<<7); /* RxD_BRK */
431 * Characters to ignore
433 port
->ignore_status_mask
= 0;
434 if (new->c_iflag
& IGNPAR
)
435 port
->ignore_status_mask
|= (1<<6); /* RxD_FIFO_PAR_ERR */
436 if (new->c_iflag
& IGNBRK
) {
437 port
->ignore_status_mask
|= (1<<7); /* RxD_BRK */
439 * If we're ignoring parity and break indicators,
440 * ignore overruns too (for real raw support).
442 if (new->c_iflag
& IGNPAR
)
443 port
->ignore_status_mask
|= (1<<9); /* RxD_LOST */
447 * Ignore all characters if CREAD is not set.
449 if ((new->c_cflag
& CREAD
) == 0)
450 port
->ignore_status_mask
|= (1<<3); /* RXD_DATA */
453 P2001_UART
->w
.Baudrate
= (quot
<<16)+prod
;
454 P2001_UART
->w
.Config
= config
;
456 spin_unlock_irqrestore(&port
->lock
, flags
);
459 /* power management: power the hardware down */
461 static void p2001_uart_ops_pm(struct uart_port
*port
, unsigned int state
, unsigned int oldstate
)
463 #warning "p2001_uart_ops_pm is not implemented."
467 /* power management: power the hardware up */
469 static int p2001_uart_ops_set_wake(struct uart_port
*port
, unsigned int state
)
471 #warning "p2001_uart_ops_set_wake is not implemented."
476 * Return a string describing the port type
478 static const char *p2001_uart_ops_type(struct uart_port
*port
)
480 return port
->type
== PORT_P2001
? "P2001" : NULL
;
484 * Release IO and memory resources used by
485 * the port. This includes iounmap if necessary.
487 static void p2001_uart_ops_release_port(struct uart_port
*port
)
489 release_mem_region(port
->mapbase
, 0x30);
493 * Request IO and memory resources used by the
494 * port. This includes iomapping the port if
497 static int p2001_uart_ops_request_port(struct uart_port
*port
)
499 return request_mem_region(port
->mapbase
, 0x30, p2001_uart_name
)
500 != NULL
? 0 : -EBUSY
;
504 * Configure/autoconfigure the port.
506 static void p2001_uart_ops_config_port(struct uart_port
*port
, int flags
)
508 if (flags
& UART_CONFIG_TYPE
&& p2001_uart_ops_request_port(port
) == 0)
509 port
->type
= PORT_P2001
;
513 * Verify the new serial_struct (for TIOCSSERIAL).
515 static int p2001_uart_ops_verify_port(struct uart_port
*port
, struct serial_struct
*ser
)
518 if (ser
->type
!= PORT_UNKNOWN
&& ser
->type
!= PORT_P2001
)
520 if (ser
->irq
!= NO_IRQ
)
525 /* device specific ioctl calls */
527 static int p2001_uart_ops_ioctl(struct uart_port
*port
, unsigned int, unsigned long)
529 #warning "p2001_uart_ops_ioctl is not implemented."
534 static struct uart_ops p2001_uart_ops
= {
535 .tx_empty
= p2001_uart_ops_tx_empty
, /* returns if the port transmitter is empty or not. */
536 .set_mctrl
= p2001_uart_ops_set_mctrl
, /* sets a new value for the MCR UART register. */
537 .get_mctrl
= p2001_uart_ops_get_mctrl
, /* gets the current MCR UART register value. */
538 .stop_tx
= p2001_uart_ops_stop_tx
, /* stops the port from sending data. */
539 .start_tx
= p2001_uart_ops_start_tx
, /* starts the port sending data. */
540 // .send_xchar = p2001_uart_ops_send_xchar, /* tells the port to send the XOFF character to the host. */
541 .stop_rx
= p2001_uart_ops_stop_rx
, /* stops receiving data. */
542 .enable_ms
= p2001_uart_ops_enable_ms
, /* enables the modem status interrupts. */
543 .break_ctl
= p2001_uart_ops_break_ctl
, /* sends the BREAK value over the port. */
544 .startup
= p2001_uart_ops_startup
, /* called once each time the open call happens */
545 .shutdown
= p2001_uart_ops_shutdown
, /* called when the port is closed */
546 .set_termios
= p2001_uart_ops_set_termios
, /* called whenever the port line settings need to be modified */
548 .pm
= p2001_uart_ops_pm
, /* power management: power the hardware down */
549 .set_wake
= p2001_uart_ops_set_wake
, /* power management: power the hardware up */
551 .type
= p2001_uart_ops_type
, /* Return a string describing the port type */
552 .release_port
= p2001_uart_ops_release_port
, /* Release the region(s) being used by 'port' */
553 .request_port
= p2001_uart_ops_request_port
, /* Request the region(s) being used by 'port' */
554 .config_port
= p2001_uart_ops_config_port
, /* Configure/autoconfigure the port. */
555 .verify_port
= p2001_uart_ops_verify_port
, /* Verify the new serial_struct (for TIOCSSERIAL). */
556 // .ioctl = p2001_uart_ops_ioctl, /* device specific ioctl calls */
561 /**************************************************************************
562 * CPU frequency scaling
563 **************************************************************************/
565 #ifdef CONFIG_CPU_FREQ
568 * Starts receiving data.
570 static void p2001_uart_ops_start_rx(struct uart_port
*port
)
572 if (!rx_enabled(port
)) {
573 P2001_UART
->w
.IRQ_Status
|= (1<<23); // RXD_DATA
574 rx_enabled(port
) = 1;
579 * Here we define a transistion notifier so that we can update all of our
580 * ports' baud rate when the peripheral clock changes.
582 static int p2001_uart_notifier(struct notifier_block
*self
, unsigned long phase
, void *data
)
584 struct cpufreq_freqs
*cf
= data
;
585 unsigned int prod
, quot
;
586 struct uart_port
*port
= &p2001_uart_port
;
588 if (phase
== CPUFREQ_PRECHANGE
) {
589 /* Stop transceiver */
590 p2001_uart_ops_stop_rx(&p2001_uart_port
);
591 p2001_uart_ops_stop_tx(&p2001_uart_port
);
593 while (!p2001_uart_ops_tx_empty(port
))
597 if ((phase
== CPUFREQ_POSTCHANGE
) ||
598 (phase
== CPUFREQ_RESUMECHANGE
)){
599 /* Set new baud rate */
600 port
->uartclk
= 1000 * cf
->new / 8; // in MHz
602 quot
= (port
->uartclk
* prod
)/baud
;
603 P2001_UART
->w
.Baudrate
= (quot
<<16)+prod
;
605 /* Start transceiver */
606 p2001_uart_ops_start_rx(&p2001_uart_port
);
607 p2001_uart_ops_start_tx(&p2001_uart_port
);
613 static struct notifier_block p2001_uart_nb
= { &p2001_uart_notifier
, NULL
, 0 };
615 #endif /* CONFIG_CPU_FREQ */
619 /**************************************************************************
621 **************************************************************************/
623 #ifdef CONFIG_SERIAL_P2001_UART_CONSOLE
625 /* the function used to print kernel messages */
626 static void p2001_console_write(struct console
*co
, const char *s
, unsigned int count
)
630 for (i
= 0; i
< count
; i
++) {
631 while ((P2001_UART
->r
.STATUS
& 0x3f) > TX_MIN_BUF
)
633 P2001_UART
->w
.TX
[0] = s
[i
];
635 while ((P2001_UART
->r
.STATUS
& 0x3f) > TX_MIN_BUF
)
637 P2001_UART
->w
.TX
[0] = '\r';
642 /* the function is called when the console= command-line argument matches the name for this console structure. */
643 static int __init
p2001_console_setup(struct console
*co
, char *options
)
645 struct uart_port
*port
= &p2001_uart_port
;
652 uart_parse_options(options
, &baud
, &parity
, &bits
, &flow
);
654 return uart_set_options(port
, co
, baud
, parity
, bits
, flow
);
658 static struct console p2001_console
= {
659 .name
= "ttyS", /* the name of the console device is used to parse the console= command line option. */
660 .write
= p2001_console_write
, /* the function used to print kernel messages */
661 // .read = p2001_console_read, /* ??? */
662 .device
= uart_console_device
, /* a function that returns the device number for the underlying tty device that is currently acting as a console */
663 // .unblank = p2001_console_unblank, /* the function, if defined, is used to unblank the screen. */
664 .setup
= p2001_console_setup
, /* the function is called when the console= command-line argument matches the name for this console structure. */
665 .flags
= CON_PRINTBUFFER
, /* various console flags */
666 .index
= -1, /* the number of the device acting as a console in an array of devices. */
668 .data
= &p2001_uart_driver
,
671 static int __init
p2001_console_init(void)
673 register_console(&p2001_console
);
676 console_initcall(p2001_console_init
);
681 /**************************************************************************
683 **************************************************************************/
685 static int __init
p2001_uart_module_init(void)
691 ret
= uart_register_driver(&p2001_uart_driver
);
692 if (ret
!= 0) return ret
;
694 ret
= uart_add_one_port(&p2001_uart_driver
, &p2001_uart_port
);
695 if (ret
!= 0) return ret
;
697 #ifdef CONFIG_CPU_FREQ
698 ret
= cpufreq_register_notifier(&p2001_uart_nb
, CPUFREQ_TRANSITION_NOTIFIER
);
699 printk("p2001_uart: CPU frequency notifier registered\n");
705 static void __exit
p2001_uart_module_exit(void)
707 #ifdef CONFIG_CPU_FREQ
708 cpufreq_unregister_notifier(&p2001_uart_nb
, CPUFREQ_TRANSITION_NOTIFIER
);
709 printk("p2001_uart: CPU frequency notifier unregistered\n");
711 uart_remove_one_port(&p2001_uart_driver
, &p2001_uart_port
);
712 uart_unregister_driver(&p2001_uart_driver
);
715 module_init(p2001_uart_module_init
);
716 module_exit(p2001_uart_module_exit
);
718 MODULE_AUTHOR("Tobias Lorenz");
719 MODULE_DESCRIPTION("P2001 uart driver");
720 MODULE_LICENSE("GPL");