Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * drivers/serial/v850e_uart.c -- Serial I/O using V850E on-chip UART or UARTB
  3  *
  4  *  Copyright (C) 2001,02,03  NEC Electronics Corporation
  5  *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  6  *
  7  * This file is subject to the terms and conditions of the GNU General
  8  * Public License.  See the file COPYING in the main directory of this
  9  * archive for more details.
 10  *
 11  * Written by Miles Bader <miles@gnu.org>
 12  */
 13 
 14 /* This driver supports both the original V850E UART interface (called
 15    merely `UART' in the docs) and the newer `UARTB' interface, which is
 16    roughly a superset of the first one.  The selection is made at
 17    configure time -- if CONFIG_V850E_UARTB is defined, then UARTB is
 18    presumed, otherwise the old UART -- as these are on-CPU UARTS, a system
 19    can never have both.
 20 
 21    The UARTB interface also has a 16-entry FIFO mode, which is not
 22    yet supported by this driver.  */
 23 
 24 #include <linux/kernel.h>
 25 #include <linux/init.h>
 26 #include <linux/module.h>
 27 #include <linux/console.h>
 28 #include <linux/tty.h>
 29 #include <linux/tty_flip.h>
 30 #include <linux/serial.h>
 31 #include <linux/serial_core.h>
 32 
 33 #include <asm/v850e_uart.h>
 34 
 35 /* Initial UART state.  This may be overridden by machine-dependent headers. */
 36 #ifndef V850E_UART_INIT_BAUD
 37 #define V850E_UART_INIT_BAUD    115200
 38 #endif
 39 #ifndef V850E_UART_INIT_CFLAGS
 40 #define V850E_UART_INIT_CFLAGS  (B115200 | CS8 | CREAD)
 41 #endif
 42 
 43 /* A string used for prefixing printed descriptions; since the same UART
 44    macro is actually used on other chips than the V850E.  This must be a
 45    constant string.  */
 46 #ifndef V850E_UART_CHIP_NAME
 47 #define V850E_UART_CHIP_NAME    "V850E"
 48 #endif
 49 
 50 #define V850E_UART_MINOR_BASE   64         /* First tty minor number */
 51 
 52 
 53 /* Low-level UART functions.  */
 54 
 55 /* Configure and turn on uart channel CHAN, using the termios `control
 56    modes' bits in CFLAGS, and a baud-rate of BAUD.  */
 57 void v850e_uart_configure (unsigned chan, unsigned cflags, unsigned baud)
 58 {
 59         int flags;
 60         v850e_uart_speed_t old_speed;
 61         v850e_uart_config_t old_config;
 62         v850e_uart_speed_t new_speed = v850e_uart_calc_speed (baud);
 63         v850e_uart_config_t new_config = v850e_uart_calc_config (cflags);
 64 
 65         /* Disable interrupts while we're twiddling the hardware.  */
 66         local_irq_save (flags);
 67 
 68 #ifdef V850E_UART_PRE_CONFIGURE
 69         V850E_UART_PRE_CONFIGURE (chan, cflags, baud);
 70 #endif
 71 
 72         old_config = V850E_UART_CONFIG (chan);
 73         old_speed = v850e_uart_speed (chan);
 74 
 75         if (! v850e_uart_speed_eq (old_speed, new_speed)) {
 76                 /* The baud rate has changed.  First, disable the UART.  */
 77                 V850E_UART_CONFIG (chan) = V850E_UART_CONFIG_FINI;
 78                 old_config = 0; /* Force the uart to be re-initialized. */
 79 
 80                 /* Reprogram the baud-rate generator.  */
 81                 v850e_uart_set_speed (chan, new_speed);
 82         }
 83 
 84         if (! (old_config & V850E_UART_CONFIG_ENABLED)) {
 85                 /* If we are using the uart for the first time, start by
 86                    enabling it, which must be done before turning on any
 87                    other bits.  */
 88                 V850E_UART_CONFIG (chan) = V850E_UART_CONFIG_INIT;
 89                 /* See the initial state.  */
 90                 old_config = V850E_UART_CONFIG (chan);
 91         }
 92 
 93         if (new_config != old_config) {
 94                 /* Which of the TXE/RXE bits we'll temporarily turn off
 95                    before changing other control bits.  */
 96                 unsigned temp_disable = 0;
 97                 /* Which of the TXE/RXE bits will be enabled.  */
 98                 unsigned enable = 0;
 99                 unsigned changed_bits = new_config ^ old_config;
100 
101                 /* Which of RX/TX will be enabled in the new configuration.  */
102                 if (new_config & V850E_UART_CONFIG_RX_BITS)
103                         enable |= (new_config & V850E_UART_CONFIG_RX_ENABLE);
104                 if (new_config & V850E_UART_CONFIG_TX_BITS)
105                         enable |= (new_config & V850E_UART_CONFIG_TX_ENABLE);
106 
107                 /* Figure out which of RX/TX needs to be disabled; note
108                    that this will only happen if they're not already
109                    disabled.  */
110                 if (changed_bits & V850E_UART_CONFIG_RX_BITS)
111                         temp_disable
112                                 |= (old_config & V850E_UART_CONFIG_RX_ENABLE);
113                 if (changed_bits & V850E_UART_CONFIG_TX_BITS)
114                         temp_disable
115                                 |= (old_config & V850E_UART_CONFIG_TX_ENABLE);
116 
117                 /* We have to turn off RX and/or TX mode before changing
118                    any associated control bits.  */
119                 if (temp_disable)
120                         V850E_UART_CONFIG (chan) = old_config & ~temp_disable;
121 
122                 /* Write the new control bits, while RX/TX are disabled. */ 
123                 if (changed_bits & ~enable)
124                         V850E_UART_CONFIG (chan) = new_config & ~enable;
125 
126                 v850e_uart_config_delay (new_config, new_speed);
127 
128                 /* Write the final version, with enable bits turned on.  */
129                 V850E_UART_CONFIG (chan) = new_config;
130         }
131 
132         local_irq_restore (flags);
133 }
134 
135 
136 /*  Low-level console. */
137 
138 #ifdef CONFIG_V850E_UART_CONSOLE
139 
140 static void v850e_uart_cons_write (struct console *co,
141                                    const char *s, unsigned count)
142 {
143         if (count > 0) {
144                 unsigned chan = co->index;
145                 unsigned irq = V850E_UART_TX_IRQ (chan);
146                 int irq_was_enabled, irq_was_pending, flags;
147 
148                 /* We don't want to get `transmission completed'
149                    interrupts, since we're busy-waiting, so we disable them
150                    while sending (we don't disable interrupts entirely
151                    because sending over a serial line is really slow).  We
152                    save the status of the tx interrupt and restore it when
153                    we're done so that using printk doesn't interfere with
154                    normal serial transmission (other than interleaving the
155                    output, of course!).  This should work correctly even if
156                    this function is interrupted and the interrupt printks
157                    something.  */
158 
159                 /* Disable interrupts while fiddling with tx interrupt.  */
160                 local_irq_save (flags);
161                 /* Get current tx interrupt status.  */
162                 irq_was_enabled = v850e_intc_irq_enabled (irq);
163                 irq_was_pending = v850e_intc_irq_pending (irq);
164                 /* Disable tx interrupt if necessary.  */
165                 if (irq_was_enabled)
166                         v850e_intc_disable_irq (irq);
167                 /* Turn interrupts back on.  */
168                 local_irq_restore (flags);
169 
170                 /* Send characters.  */
171                 while (count > 0) {
172                         int ch = *s++;
173 
174                         if (ch == '\n') {
175                                 /* We don't have the benefit of a tty
176                                    driver, so translate NL into CR LF.  */
177                                 v850e_uart_wait_for_xmit_ok (chan);
178                                 v850e_uart_putc (chan, '\r');
179                         }
180 
181                         v850e_uart_wait_for_xmit_ok (chan);
182                         v850e_uart_putc (chan, ch);
183 
184                         count--;
185                 }
186 
187                 /* Restore saved tx interrupt status.  */
188                 if (irq_was_enabled) {
189                         /* Wait for the last character we sent to be
190                            completely transmitted (as we'll get an
191                            interrupt interrupt at that point).  */
192                         v850e_uart_wait_for_xmit_done (chan);
193                         /* Clear pending interrupts received due
194                            to our transmission, unless there was already
195                            one pending, in which case we want the
196                            handler to be called.  */
197                         if (! irq_was_pending)
198                                 v850e_intc_clear_pending_irq (irq);
199                         /* ... and then turn back on handling.  */
200                         v850e_intc_enable_irq (irq);
201                 }
202         }
203 }
204 
205 extern struct uart_driver v850e_uart_driver;
206 static struct console v850e_uart_cons =
207 {
208     .name       = "ttyS",
209     .write      = v850e_uart_cons_write,
210     .device     = uart_console_device,
211     .flags      = CON_PRINTBUFFER,
212     .cflag      = V850E_UART_INIT_CFLAGS,
213     .index      = -1,
214     .data       = &v850e_uart_driver,
215 };
216 
217 void v850e_uart_cons_init (unsigned chan)
218 {
219         v850e_uart_configure (chan, V850E_UART_INIT_CFLAGS,
220                               V850E_UART_INIT_BAUD);
221         v850e_uart_cons.index = chan;
222         register_console (&v850e_uart_cons);
223         printk ("Console: %s on-chip UART channel %d\n",
224                 V850E_UART_CHIP_NAME, chan);
225 }
226 
227 /* This is what the init code actually calls.  */
228 static int v850e_uart_console_init (void)
229 {
230         v850e_uart_cons_init (V850E_UART_CONSOLE_CHANNEL);
231         return 0;
232 }
233 console_initcall(v850e_uart_console_init);
234 
235 #define V850E_UART_CONSOLE &v850e_uart_cons
236 
237 #else /* !CONFIG_V850E_UART_CONSOLE */
238 #define V850E_UART_CONSOLE 0
239 #endif /* CONFIG_V850E_UART_CONSOLE */
240 
241 /* TX/RX interrupt handlers.  */
242 
243 static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop);
244 
245 void v850e_uart_tx (struct uart_port *port)
246 {
247         struct circ_buf *xmit = &port->info->xmit;
248         int stopped = uart_tx_stopped (port);
249 
250         if (v850e_uart_xmit_ok (port->line)) {
251                 int tx_ch;
252 
253                 if (port->x_char) {
254                         tx_ch = port->x_char;
255                         port->x_char = 0;
256                 } else if (!uart_circ_empty (xmit) && !stopped) {
257                         tx_ch = xmit->buf[xmit->tail];
258                         xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
259                 } else
260                         goto no_xmit;
261 
262                 v850e_uart_putc (port->line, tx_ch);
263                 port->icount.tx++;
264 
265                 if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS)
266                         uart_write_wakeup (port);
267         }
268 
269  no_xmit:
270         if (uart_circ_empty (xmit) || stopped)
271                 v850e_uart_stop_tx (port, stopped);
272 }
273 
274 static irqreturn_t v850e_uart_tx_irq(int irq, void *data, struct pt_regs *regs)
275 {
276         struct uart_port *port = data;
277         v850e_uart_tx (port);
278         return IRQ_HANDLED;
279 }
280 
281 static irqreturn_t v850e_uart_rx_irq(int irq, void *data, struct pt_regs *regs)
282 {
283         struct uart_port *port = data;
284         unsigned ch_stat = TTY_NORMAL;
285         unsigned ch = v850e_uart_getc (port->line);
286         unsigned err = v850e_uart_err (port->line);
287 
288         if (err) {
289                 if (err & V850E_UART_ERR_OVERRUN) {
290                         ch_stat = TTY_OVERRUN;
291                         port->icount.overrun++;
292                 } else if (err & V850E_UART_ERR_FRAME) {
293                         ch_stat = TTY_FRAME;
294                         port->icount.frame++;
295                 } else if (err & V850E_UART_ERR_PARITY) {
296                         ch_stat = TTY_PARITY;
297                         port->icount.parity++;
298                 }
299         }
300 
301         port->icount.rx++;
302 
303         tty_insert_flip_char (port->info->tty, ch, ch_stat);
304         tty_schedule_flip (port->info->tty);
305 
306         return IRQ_HANDLED;
307 }
308 
309 
310 /* Control functions for the serial framework.  */
311 
312 static void v850e_uart_nop (struct uart_port *port) { }
313 static int v850e_uart_success (struct uart_port *port) { return 0; }
314 
315 static unsigned v850e_uart_tx_empty (struct uart_port *port)
316 {
317         return TIOCSER_TEMT;    /* Can't detect.  */
318 }
319 
320 static void v850e_uart_set_mctrl (struct uart_port *port, unsigned mctrl)
321 {
322 #ifdef V850E_UART_SET_RTS
323         V850E_UART_SET_RTS (port->line, (mctrl & TIOCM_RTS));
324 #endif
325 }
326 
327 static unsigned v850e_uart_get_mctrl (struct uart_port *port)
328 {
329         /* We don't support DCD or DSR, so consider them permanently active. */
330         int mctrl = TIOCM_CAR | TIOCM_DSR;
331 
332         /* We may support CTS.  */
333 #ifdef V850E_UART_CTS
334         mctrl |= V850E_UART_CTS(port->line) ? TIOCM_CTS : 0;
335 #else
336         mctrl |= TIOCM_CTS;
337 #endif
338 
339         return mctrl;
340 }
341 
342 static void v850e_uart_start_tx (struct uart_port *port, unsigned tty_start)
343 {
344         v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line));
345         v850e_uart_tx (port);
346         v850e_intc_enable_irq (V850E_UART_TX_IRQ (port->line));
347 }
348 
349 static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop)
350 {
351         v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line));
352 }
353 
354 static void v850e_uart_start_rx (struct uart_port *port)
355 {
356         v850e_intc_enable_irq (V850E_UART_RX_IRQ (port->line));
357 }
358 
359 static void v850e_uart_stop_rx (struct uart_port *port)
360 {
361         v850e_intc_disable_irq (V850E_UART_RX_IRQ (port->line));
362 }
363 
364 static void v850e_uart_break_ctl (struct uart_port *port, int break_ctl)
365 {
366         /* Umm, do this later.  */
367 }
368 
369 static int v850e_uart_startup (struct uart_port *port)
370 {
371         int err;
372 
373         /* Alloc RX irq.  */
374         err = request_irq (V850E_UART_RX_IRQ (port->line), v850e_uart_rx_irq,
375                            SA_INTERRUPT, "v850e_uart", port);
376         if (err)
377                 return err;
378 
379         /* Alloc TX irq.  */
380         err = request_irq (V850E_UART_TX_IRQ (port->line), v850e_uart_tx_irq,
381                            SA_INTERRUPT, "v850e_uart", port);
382         if (err) {
383                 free_irq (V850E_UART_RX_IRQ (port->line), port);
384                 return err;
385         }
386 
387         v850e_uart_start_rx (port);
388 
389         return 0;
390 }
391 
392 static void v850e_uart_shutdown (struct uart_port *port)
393 {
394         /* Disable port interrupts.  */
395         free_irq (V850E_UART_TX_IRQ (port->line), port);
396         free_irq (V850E_UART_RX_IRQ (port->line), port);
397 
398         /* Turn off xmit/recv enable bits.  */
399         V850E_UART_CONFIG (port->line)
400                 &= ~(V850E_UART_CONFIG_TX_ENABLE
401                      | V850E_UART_CONFIG_RX_ENABLE);
402         /* Then reset the channel.  */
403         V850E_UART_CONFIG (port->line) = 0;
404 }
405 
406 static void
407 v850e_uart_set_termios (struct uart_port *port, struct termios *termios,
408                         struct termios *old)
409 {
410         unsigned cflags = termios->c_cflag;
411 
412         /* Restrict flags to legal values.  */
413         if ((cflags & CSIZE) != CS7 && (cflags & CSIZE) != CS8)
414                 /* The new value of CSIZE is invalid, use the old value.  */
415                 cflags = (cflags & ~CSIZE)
416                         | (old ? (old->c_cflag & CSIZE) : CS8);
417 
418         termios->c_cflag = cflags;
419 
420         v850e_uart_configure (port->line, cflags,
421                               uart_get_baud_rate (port, termios, old,
422                                                   v850e_uart_min_baud(),
423                                                   v850e_uart_max_baud()));
424 }
425 
426 static const char *v850e_uart_type (struct uart_port *port)
427 {
428         return port->type == PORT_V850E_UART ? "v850e_uart" : 0;
429 }
430 
431 static void v850e_uart_config_port (struct uart_port *port, int flags)
432 {
433         if (flags & UART_CONFIG_TYPE)
434                 port->type = PORT_V850E_UART;
435 }
436 
437 static int
438 v850e_uart_verify_port (struct uart_port *port, struct serial_struct *ser)
439 {
440         if (ser->type != PORT_UNKNOWN && ser->type != PORT_V850E_UART)
441                 return -EINVAL;
442         if (ser->irq != V850E_UART_TX_IRQ (port->line))
443                 return -EINVAL;
444         return 0;
445 }
446 
447 static struct uart_ops v850e_uart_ops = {
448         .tx_empty       = v850e_uart_tx_empty,
449         .get_mctrl      = v850e_uart_get_mctrl,
450         .set_mctrl      = v850e_uart_set_mctrl,
451         .start_tx       = v850e_uart_start_tx,
452         .stop_tx        = v850e_uart_stop_tx,
453         .stop_rx        = v850e_uart_stop_rx,
454         .enable_ms      = v850e_uart_nop,
455         .break_ctl      = v850e_uart_break_ctl,
456         .startup        = v850e_uart_startup,
457         .shutdown       = v850e_uart_shutdown,
458         .set_termios    = v850e_uart_set_termios,
459         .type           = v850e_uart_type,
460         .release_port   = v850e_uart_nop,
461         .request_port   = v850e_uart_success,
462         .config_port    = v850e_uart_config_port,
463         .verify_port    = v850e_uart_verify_port,
464 };
465 
466 /* Initialization and cleanup.  */
467 
468 static struct uart_driver v850e_uart_driver = {
469         .owner                  = THIS_MODULE,
470         .driver_name            = "v850e_uart",
471         .devfs_name             = "tts/",
472         .dev_name               = "ttyS",
473         .major                  = TTY_MAJOR,
474         .minor                  = V850E_UART_MINOR_BASE,
475         .nr                     = V850E_UART_NUM_CHANNELS,
476         .cons                   = V850E_UART_CONSOLE,
477 };
478 
479 
480 static struct uart_port v850e_uart_ports[V850E_UART_NUM_CHANNELS];
481 
482 static int __init v850e_uart_init (void)
483 {
484         int rval;
485 
486         printk (KERN_INFO "%s on-chip UART\n", V850E_UART_CHIP_NAME);
487 
488         rval = uart_register_driver (&v850e_uart_driver);
489         if (rval == 0) {
490                 unsigned chan;
491 
492                 for (chan = 0; chan < V850E_UART_NUM_CHANNELS; chan++) {
493                         struct uart_port *port = &v850e_uart_ports[chan];
494                         
495                         memset (port, 0, sizeof *port);
496 
497                         port->ops = &v850e_uart_ops;
498                         port->line = chan;
499                         port->iotype = SERIAL_IO_MEM;
500                         port->flags = UPF_BOOT_AUTOCONF;
501 
502                         /* We actually use multiple IRQs, but the serial
503                            framework seems to mainly use this for
504                            informational purposes anyway.  Here we use the TX
505                            irq.  */
506                         port->irq = V850E_UART_TX_IRQ (chan);
507 
508                         /* The serial framework doesn't really use these
509                            membase/mapbase fields for anything useful, but
510                            it requires that they be something non-zero to
511                            consider the port `valid', and also uses them
512                            for informational purposes.  */
513                         port->membase = (void *)V850E_UART_BASE_ADDR (chan);
514                         port->mapbase = V850E_UART_BASE_ADDR (chan);
515 
516                         /* The framework insists on knowing the uart's master
517                            clock freq, though it doesn't seem to do anything
518                            useful for us with it.  We must make it at least
519                            higher than (the maximum baud rate * 16), otherwise
520                            the framework will puke during its internal
521                            calculations, and force the baud rate to be 9600.
522                            To be accurate though, just repeat the calculation
523                            we use when actually setting the speed.  */
524                         port->uartclk = v850e_uart_max_clock() * 16;
525 
526                         uart_add_one_port (&v850e_uart_driver, port);
527                 }
528         }
529 
530         return rval;
531 }
532 
533 static void __exit v850e_uart_exit (void)
534 {
535         unsigned chan;
536 
537         for (chan = 0; chan < V850E_UART_NUM_CHANNELS; chan++)
538                 uart_remove_one_port (&v850e_uart_driver,
539                                       &v850e_uart_ports[chan]);
540 
541         uart_unregister_driver (&v850e_uart_driver);
542 }
543 
544 module_init (v850e_uart_init);
545 module_exit (v850e_uart_exit);
546 
547 MODULE_AUTHOR ("Miles Bader");
548 MODULE_DESCRIPTION ("NEC " V850E_UART_CHIP_NAME " on-chip UART");
549 MODULE_LICENSE ("GPL");
550 
  This page was automatically generated by the LXR engine.