]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/tty/serial/21285.c
kgdb: remove #include <linux/serial_8250.h> from kgdb.h
[karo-tx-linux.git] / drivers / tty / serial / 21285.c
1 /*
2  * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
3  *
4  * Based on drivers/char/serial.c
5  */
6 #include <linux/module.h>
7 #include <linux/tty.h>
8 #include <linux/ioport.h>
9 #include <linux/init.h>
10 #include <linux/console.h>
11 #include <linux/device.h>
12 #include <linux/tty_flip.h>
13 #include <linux/serial_core.h>
14 #include <linux/serial.h>
15 #include <linux/io.h>
16
17 #include <asm/irq.h>
18 #include <asm/mach-types.h>
19 #include <asm/system_info.h>
20 #include <asm/hardware/dec21285.h>
21 #include <mach/hardware.h>
22
23 #define BAUD_BASE               (mem_fclk_21285/64)
24
25 #define SERIAL_21285_NAME       "ttyFB"
26 #define SERIAL_21285_MAJOR      204
27 #define SERIAL_21285_MINOR      4
28
29 #define RXSTAT_DUMMY_READ       0x80000000
30 #define RXSTAT_FRAME            (1 << 0)
31 #define RXSTAT_PARITY           (1 << 1)
32 #define RXSTAT_OVERRUN          (1 << 2)
33 #define RXSTAT_ANYERR           (RXSTAT_FRAME|RXSTAT_PARITY|RXSTAT_OVERRUN)
34
35 #define H_UBRLCR_BREAK          (1 << 0)
36 #define H_UBRLCR_PARENB         (1 << 1)
37 #define H_UBRLCR_PAREVN         (1 << 2)
38 #define H_UBRLCR_STOPB          (1 << 3)
39 #define H_UBRLCR_FIFO           (1 << 4)
40
41 static const char serial21285_name[] = "Footbridge UART";
42
43 #define tx_enabled(port)        ((port)->unused[0])
44 #define rx_enabled(port)        ((port)->unused[1])
45
46 /*
47  * The documented expression for selecting the divisor is:
48  *  BAUD_BASE / baud - 1
49  * However, typically BAUD_BASE is not divisible by baud, so
50  * we want to select the divisor that gives us the minimum
51  * error.  Therefore, we want:
52  *  int(BAUD_BASE / baud - 0.5) ->
53  *  int(BAUD_BASE / baud - (baud >> 1) / baud) ->
54  *  int((BAUD_BASE - (baud >> 1)) / baud)
55  */
56
57 static void serial21285_stop_tx(struct uart_port *port)
58 {
59         if (tx_enabled(port)) {
60                 disable_irq_nosync(IRQ_CONTX);
61                 tx_enabled(port) = 0;
62         }
63 }
64
65 static void serial21285_start_tx(struct uart_port *port)
66 {
67         if (!tx_enabled(port)) {
68                 enable_irq(IRQ_CONTX);
69                 tx_enabled(port) = 1;
70         }
71 }
72
73 static void serial21285_stop_rx(struct uart_port *port)
74 {
75         if (rx_enabled(port)) {
76                 disable_irq_nosync(IRQ_CONRX);
77                 rx_enabled(port) = 0;
78         }
79 }
80
81 static void serial21285_enable_ms(struct uart_port *port)
82 {
83 }
84
85 static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
86 {
87         struct uart_port *port = dev_id;
88         unsigned int status, ch, flag, rxs, max_count = 256;
89
90         status = *CSR_UARTFLG;
91         while (!(status & 0x10) && max_count--) {
92                 ch = *CSR_UARTDR;
93                 flag = TTY_NORMAL;
94                 port->icount.rx++;
95
96                 rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ;
97                 if (unlikely(rxs & RXSTAT_ANYERR)) {
98                         if (rxs & RXSTAT_PARITY)
99                                 port->icount.parity++;
100                         else if (rxs & RXSTAT_FRAME)
101                                 port->icount.frame++;
102                         if (rxs & RXSTAT_OVERRUN)
103                                 port->icount.overrun++;
104
105                         rxs &= port->read_status_mask;
106
107                         if (rxs & RXSTAT_PARITY)
108                                 flag = TTY_PARITY;
109                         else if (rxs & RXSTAT_FRAME)
110                                 flag = TTY_FRAME;
111                 }
112
113                 uart_insert_char(port, rxs, RXSTAT_OVERRUN, ch, flag);
114
115                 status = *CSR_UARTFLG;
116         }
117         tty_flip_buffer_push(&port->state->port);
118
119         return IRQ_HANDLED;
120 }
121
122 static irqreturn_t serial21285_tx_chars(int irq, void *dev_id)
123 {
124         struct uart_port *port = dev_id;
125         struct circ_buf *xmit = &port->state->xmit;
126         int count = 256;
127
128         if (port->x_char) {
129                 *CSR_UARTDR = port->x_char;
130                 port->icount.tx++;
131                 port->x_char = 0;
132                 goto out;
133         }
134         if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
135                 serial21285_stop_tx(port);
136                 goto out;
137         }
138
139         do {
140                 *CSR_UARTDR = xmit->buf[xmit->tail];
141                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
142                 port->icount.tx++;
143                 if (uart_circ_empty(xmit))
144                         break;
145         } while (--count > 0 && !(*CSR_UARTFLG & 0x20));
146
147         if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
148                 uart_write_wakeup(port);
149
150         if (uart_circ_empty(xmit))
151                 serial21285_stop_tx(port);
152
153  out:
154         return IRQ_HANDLED;
155 }
156
157 static unsigned int serial21285_tx_empty(struct uart_port *port)
158 {
159         return (*CSR_UARTFLG & 8) ? 0 : TIOCSER_TEMT;
160 }
161
162 /* no modem control lines */
163 static unsigned int serial21285_get_mctrl(struct uart_port *port)
164 {
165         return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
166 }
167
168 static void serial21285_set_mctrl(struct uart_port *port, unsigned int mctrl)
169 {
170 }
171
172 static void serial21285_break_ctl(struct uart_port *port, int break_state)
173 {
174         unsigned long flags;
175         unsigned int h_lcr;
176
177         spin_lock_irqsave(&port->lock, flags);
178         h_lcr = *CSR_H_UBRLCR;
179         if (break_state)
180                 h_lcr |= H_UBRLCR_BREAK;
181         else
182                 h_lcr &= ~H_UBRLCR_BREAK;
183         *CSR_H_UBRLCR = h_lcr;
184         spin_unlock_irqrestore(&port->lock, flags);
185 }
186
187 static int serial21285_startup(struct uart_port *port)
188 {
189         int ret;
190
191         tx_enabled(port) = 1;
192         rx_enabled(port) = 1;
193
194         ret = request_irq(IRQ_CONRX, serial21285_rx_chars, 0,
195                           serial21285_name, port);
196         if (ret == 0) {
197                 ret = request_irq(IRQ_CONTX, serial21285_tx_chars, 0,
198                                   serial21285_name, port);
199                 if (ret)
200                         free_irq(IRQ_CONRX, port);
201         }
202
203         return ret;
204 }
205
206 static void serial21285_shutdown(struct uart_port *port)
207 {
208         free_irq(IRQ_CONTX, port);
209         free_irq(IRQ_CONRX, port);
210 }
211
212 static void
213 serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
214                         struct ktermios *old)
215 {
216         unsigned long flags;
217         unsigned int baud, quot, h_lcr, b;
218
219         /*
220          * We don't support modem control lines.
221          */
222         termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
223         termios->c_cflag |= CLOCAL;
224
225         /*
226          * We don't support BREAK character recognition.
227          */
228         termios->c_iflag &= ~(IGNBRK | BRKINT);
229
230         /*
231          * Ask the core to calculate the divisor for us.
232          */
233         baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
234         quot = uart_get_divisor(port, baud);
235         b = port->uartclk / (16 * quot);
236         tty_termios_encode_baud_rate(termios, b, b);
237
238         switch (termios->c_cflag & CSIZE) {
239         case CS5:
240                 h_lcr = 0x00;
241                 break;
242         case CS6:
243                 h_lcr = 0x20;
244                 break;
245         case CS7:
246                 h_lcr = 0x40;
247                 break;
248         default: /* CS8 */
249                 h_lcr = 0x60;
250                 break;
251         }
252
253         if (termios->c_cflag & CSTOPB)
254                 h_lcr |= H_UBRLCR_STOPB;
255         if (termios->c_cflag & PARENB) {
256                 h_lcr |= H_UBRLCR_PARENB;
257                 if (!(termios->c_cflag & PARODD))
258                         h_lcr |= H_UBRLCR_PAREVN;
259         }
260
261         if (port->fifosize)
262                 h_lcr |= H_UBRLCR_FIFO;
263
264         spin_lock_irqsave(&port->lock, flags);
265
266         /*
267          * Update the per-port timeout.
268          */
269         uart_update_timeout(port, termios->c_cflag, baud);
270
271         /*
272          * Which character status flags are we interested in?
273          */
274         port->read_status_mask = RXSTAT_OVERRUN;
275         if (termios->c_iflag & INPCK)
276                 port->read_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
277
278         /*
279          * Which character status flags should we ignore?
280          */
281         port->ignore_status_mask = 0;
282         if (termios->c_iflag & IGNPAR)
283                 port->ignore_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
284         if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
285                 port->ignore_status_mask |= RXSTAT_OVERRUN;
286
287         /*
288          * Ignore all characters if CREAD is not set.
289          */
290         if ((termios->c_cflag & CREAD) == 0)
291                 port->ignore_status_mask |= RXSTAT_DUMMY_READ;
292
293         quot -= 1;
294
295         *CSR_UARTCON = 0;
296         *CSR_L_UBRLCR = quot & 0xff;
297         *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
298         *CSR_H_UBRLCR = h_lcr;
299         *CSR_UARTCON = 1;
300
301         spin_unlock_irqrestore(&port->lock, flags);
302 }
303
304 static const char *serial21285_type(struct uart_port *port)
305 {
306         return port->type == PORT_21285 ? "DC21285" : NULL;
307 }
308
309 static void serial21285_release_port(struct uart_port *port)
310 {
311         release_mem_region(port->mapbase, 32);
312 }
313
314 static int serial21285_request_port(struct uart_port *port)
315 {
316         return request_mem_region(port->mapbase, 32, serial21285_name)
317                          != NULL ? 0 : -EBUSY;
318 }
319
320 static void serial21285_config_port(struct uart_port *port, int flags)
321 {
322         if (flags & UART_CONFIG_TYPE && serial21285_request_port(port) == 0)
323                 port->type = PORT_21285;
324 }
325
326 /*
327  * verify the new serial_struct (for TIOCSSERIAL).
328  */
329 static int serial21285_verify_port(struct uart_port *port, struct serial_struct *ser)
330 {
331         int ret = 0;
332         if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285)
333                 ret = -EINVAL;
334         if (ser->irq <= 0)
335                 ret = -EINVAL;
336         if (ser->baud_base != port->uartclk / 16)
337                 ret = -EINVAL;
338         return ret;
339 }
340
341 static struct uart_ops serial21285_ops = {
342         .tx_empty       = serial21285_tx_empty,
343         .get_mctrl      = serial21285_get_mctrl,
344         .set_mctrl      = serial21285_set_mctrl,
345         .stop_tx        = serial21285_stop_tx,
346         .start_tx       = serial21285_start_tx,
347         .stop_rx        = serial21285_stop_rx,
348         .enable_ms      = serial21285_enable_ms,
349         .break_ctl      = serial21285_break_ctl,
350         .startup        = serial21285_startup,
351         .shutdown       = serial21285_shutdown,
352         .set_termios    = serial21285_set_termios,
353         .type           = serial21285_type,
354         .release_port   = serial21285_release_port,
355         .request_port   = serial21285_request_port,
356         .config_port    = serial21285_config_port,
357         .verify_port    = serial21285_verify_port,
358 };
359
360 static struct uart_port serial21285_port = {
361         .mapbase        = 0x42000160,
362         .iotype         = UPIO_MEM,
363         .irq            = 0,
364         .fifosize       = 16,
365         .ops            = &serial21285_ops,
366         .flags          = UPF_BOOT_AUTOCONF,
367 };
368
369 static void serial21285_setup_ports(void)
370 {
371         serial21285_port.uartclk = mem_fclk_21285 / 4;
372 }
373
374 #ifdef CONFIG_SERIAL_21285_CONSOLE
375 static void serial21285_console_putchar(struct uart_port *port, int ch)
376 {
377         while (*CSR_UARTFLG & 0x20)
378                 barrier();
379         *CSR_UARTDR = ch;
380 }
381
382 static void
383 serial21285_console_write(struct console *co, const char *s,
384                           unsigned int count)
385 {
386         uart_console_write(&serial21285_port, s, count, serial21285_console_putchar);
387 }
388
389 static void __init
390 serial21285_get_options(struct uart_port *port, int *baud,
391                         int *parity, int *bits)
392 {
393         if (*CSR_UARTCON == 1) {
394                 unsigned int tmp;
395
396                 tmp = *CSR_H_UBRLCR;
397                 switch (tmp & 0x60) {
398                 case 0x00:
399                         *bits = 5;
400                         break;
401                 case 0x20:
402                         *bits = 6;
403                         break;
404                 case 0x40:
405                         *bits = 7;
406                         break;
407                 default:
408                 case 0x60:
409                         *bits = 8;
410                         break;
411                 }
412
413                 if (tmp & H_UBRLCR_PARENB) {
414                         *parity = 'o';
415                         if (tmp & H_UBRLCR_PAREVN)
416                                 *parity = 'e';
417                 }
418
419                 tmp = *CSR_L_UBRLCR | (*CSR_M_UBRLCR << 8);
420
421                 *baud = port->uartclk / (16 * (tmp + 1));
422         }
423 }
424
425 static int __init serial21285_console_setup(struct console *co, char *options)
426 {
427         struct uart_port *port = &serial21285_port;
428         int baud = 9600;
429         int bits = 8;
430         int parity = 'n';
431         int flow = 'n';
432
433         if (machine_is_personal_server())
434                 baud = 57600;
435
436         /*
437          * Check whether an invalid uart number has been specified, and
438          * if so, search for the first available port that does have
439          * console support.
440          */
441         if (options)
442                 uart_parse_options(options, &baud, &parity, &bits, &flow);
443         else
444                 serial21285_get_options(port, &baud, &parity, &bits);
445
446         return uart_set_options(port, co, baud, parity, bits, flow);
447 }
448
449 static struct uart_driver serial21285_reg;
450
451 static struct console serial21285_console =
452 {
453         .name           = SERIAL_21285_NAME,
454         .write          = serial21285_console_write,
455         .device         = uart_console_device,
456         .setup          = serial21285_console_setup,
457         .flags          = CON_PRINTBUFFER,
458         .index          = -1,
459         .data           = &serial21285_reg,
460 };
461
462 static int __init rs285_console_init(void)
463 {
464         serial21285_setup_ports();
465         register_console(&serial21285_console);
466         return 0;
467 }
468 console_initcall(rs285_console_init);
469
470 #define SERIAL_21285_CONSOLE    &serial21285_console
471 #else
472 #define SERIAL_21285_CONSOLE    NULL
473 #endif
474
475 static struct uart_driver serial21285_reg = {
476         .owner                  = THIS_MODULE,
477         .driver_name            = "ttyFB",
478         .dev_name               = "ttyFB",
479         .major                  = SERIAL_21285_MAJOR,
480         .minor                  = SERIAL_21285_MINOR,
481         .nr                     = 1,
482         .cons                   = SERIAL_21285_CONSOLE,
483 };
484
485 static int __init serial21285_init(void)
486 {
487         int ret;
488
489         printk(KERN_INFO "Serial: 21285 driver\n");
490
491         serial21285_setup_ports();
492
493         ret = uart_register_driver(&serial21285_reg);
494         if (ret == 0)
495                 uart_add_one_port(&serial21285_reg, &serial21285_port);
496
497         return ret;
498 }
499
500 static void __exit serial21285_exit(void)
501 {
502         uart_remove_one_port(&serial21285_reg, &serial21285_port);
503         uart_unregister_driver(&serial21285_reg);
504 }
505
506 module_init(serial21285_init);
507 module_exit(serial21285_exit);
508
509 MODULE_LICENSE("GPL");
510 MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver");
511 MODULE_ALIAS_CHARDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);