Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[firefly-linux-kernel-4.4.55.git] / drivers / tty / serial / clps711x.c
1 /*
2  *  Driver for CLPS711x serial ports
3  *
4  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
5  *
6  *  Copyright 1999 ARM Limited
7  *  Copyright (C) 2000 Deep Blue Solutions Ltd.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
25 #define SUPPORT_SYSRQ
26 #endif
27
28 #include <linux/module.h>
29 #include <linux/ioport.h>
30 #include <linux/init.h>
31 #include <linux/console.h>
32 #include <linux/sysrq.h>
33 #include <linux/spinlock.h>
34 #include <linux/device.h>
35 #include <linux/tty.h>
36 #include <linux/tty_flip.h>
37 #include <linux/serial_core.h>
38 #include <linux/serial.h>
39 #include <linux/io.h>
40
41 #include <mach/hardware.h>
42 #include <asm/irq.h>
43
44 #define UART_NR         2
45
46 #define SERIAL_CLPS711X_MAJOR   204
47 #define SERIAL_CLPS711X_MINOR   40
48 #define SERIAL_CLPS711X_NR      UART_NR
49
50 /*
51  * We use the relevant SYSCON register as a base address for these ports.
52  */
53 #define UBRLCR(port)            ((port)->iobase + UBRLCR1 - SYSCON1)
54 #define UARTDR(port)            ((port)->iobase + UARTDR1 - SYSCON1)
55 #define SYSFLG(port)            ((port)->iobase + SYSFLG1 - SYSCON1)
56 #define SYSCON(port)            ((port)->iobase + SYSCON1 - SYSCON1)
57
58 #define TX_IRQ(port)            ((port)->irq)
59 #define RX_IRQ(port)            ((port)->irq + 1)
60
61 #define UART_ANY_ERR            (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
62
63 #define tx_enabled(port)        ((port)->unused[0])
64
65 static void clps711xuart_stop_tx(struct uart_port *port)
66 {
67         if (tx_enabled(port)) {
68                 disable_irq(TX_IRQ(port));
69                 tx_enabled(port) = 0;
70         }
71 }
72
73 static void clps711xuart_start_tx(struct uart_port *port)
74 {
75         if (!tx_enabled(port)) {
76                 enable_irq(TX_IRQ(port));
77                 tx_enabled(port) = 1;
78         }
79 }
80
81 static void clps711xuart_stop_rx(struct uart_port *port)
82 {
83         disable_irq(RX_IRQ(port));
84 }
85
86 static void clps711xuart_enable_ms(struct uart_port *port)
87 {
88 }
89
90 static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id)
91 {
92         struct uart_port *port = dev_id;
93         struct tty_struct *tty = port->state->port.tty;
94         unsigned int status, ch, flg;
95
96         status = clps_readl(SYSFLG(port));
97         while (!(status & SYSFLG_URXFE)) {
98                 ch = clps_readl(UARTDR(port));
99
100                 port->icount.rx++;
101
102                 flg = TTY_NORMAL;
103
104                 /*
105                  * Note that the error handling code is
106                  * out of the main execution path
107                  */
108                 if (unlikely(ch & UART_ANY_ERR)) {
109                         if (ch & UARTDR_PARERR)
110                                 port->icount.parity++;
111                         else if (ch & UARTDR_FRMERR)
112                                 port->icount.frame++;
113                         if (ch & UARTDR_OVERR)
114                                 port->icount.overrun++;
115
116                         ch &= port->read_status_mask;
117
118                         if (ch & UARTDR_PARERR)
119                                 flg = TTY_PARITY;
120                         else if (ch & UARTDR_FRMERR)
121                                 flg = TTY_FRAME;
122
123 #ifdef SUPPORT_SYSRQ
124                         port->sysrq = 0;
125 #endif
126                 }
127
128                 if (uart_handle_sysrq_char(port, ch))
129                         goto ignore_char;
130
131                 /*
132                  * CHECK: does overrun affect the current character?
133                  * ASSUMPTION: it does not.
134                  */
135                 uart_insert_char(port, ch, UARTDR_OVERR, ch, flg);
136
137         ignore_char:
138                 status = clps_readl(SYSFLG(port));
139         }
140         tty_flip_buffer_push(tty);
141         return IRQ_HANDLED;
142 }
143
144 static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
145 {
146         struct uart_port *port = dev_id;
147         struct circ_buf *xmit = &port->state->xmit;
148         int count;
149
150         if (port->x_char) {
151                 clps_writel(port->x_char, UARTDR(port));
152                 port->icount.tx++;
153                 port->x_char = 0;
154                 return IRQ_HANDLED;
155         }
156
157         if (uart_circ_empty(xmit) || uart_tx_stopped(port))
158                 goto disable_tx_irq;
159
160         count = port->fifosize >> 1;
161         do {
162                 clps_writel(xmit->buf[xmit->tail], UARTDR(port));
163                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
164                 port->icount.tx++;
165                 if (uart_circ_empty(xmit))
166                         break;
167         } while (--count > 0);
168
169         if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
170                 uart_write_wakeup(port);
171
172         if (uart_circ_empty(xmit)) {
173         disable_tx_irq:
174                 disable_irq_nosync(TX_IRQ(port));
175                 tx_enabled(port) = 0;
176         }
177
178         return IRQ_HANDLED;
179 }
180
181 static unsigned int clps711xuart_tx_empty(struct uart_port *port)
182 {
183         unsigned int status = clps_readl(SYSFLG(port));
184         return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
185 }
186
187 static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
188 {
189         unsigned int port_addr;
190         unsigned int result = 0;
191         unsigned int status;
192
193         port_addr = SYSFLG(port);
194         if (port_addr == SYSFLG1) {
195                 status = clps_readl(SYSFLG1);
196                 if (status & SYSFLG1_DCD)
197                         result |= TIOCM_CAR;
198                 if (status & SYSFLG1_DSR)
199                         result |= TIOCM_DSR;
200                 if (status & SYSFLG1_CTS)
201                         result |= TIOCM_CTS;
202         }
203
204         return result;
205 }
206
207 static void
208 clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
209 {
210 }
211
212 static void clps711xuart_break_ctl(struct uart_port *port, int break_state)
213 {
214         unsigned long flags;
215         unsigned int ubrlcr;
216
217         spin_lock_irqsave(&port->lock, flags);
218         ubrlcr = clps_readl(UBRLCR(port));
219         if (break_state == -1)
220                 ubrlcr |= UBRLCR_BREAK;
221         else
222                 ubrlcr &= ~UBRLCR_BREAK;
223         clps_writel(ubrlcr, UBRLCR(port));
224         spin_unlock_irqrestore(&port->lock, flags);
225 }
226
227 static int clps711xuart_startup(struct uart_port *port)
228 {
229         unsigned int syscon;
230         int retval;
231
232         tx_enabled(port) = 1;
233
234         /*
235          * Allocate the IRQs
236          */
237         retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0,
238                              "clps711xuart_tx", port);
239         if (retval)
240                 return retval;
241
242         retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
243                              "clps711xuart_rx", port);
244         if (retval) {
245                 free_irq(TX_IRQ(port), port);
246                 return retval;
247         }
248
249         /*
250          * enable the port
251          */
252         syscon = clps_readl(SYSCON(port));
253         syscon |= SYSCON_UARTEN;
254         clps_writel(syscon, SYSCON(port));
255
256         return 0;
257 }
258
259 static void clps711xuart_shutdown(struct uart_port *port)
260 {
261         unsigned int ubrlcr, syscon;
262
263         /*
264          * Free the interrupt
265          */
266         free_irq(TX_IRQ(port), port);   /* TX interrupt */
267         free_irq(RX_IRQ(port), port);   /* RX interrupt */
268
269         /*
270          * disable the port
271          */
272         syscon = clps_readl(SYSCON(port));
273         syscon &= ~SYSCON_UARTEN;
274         clps_writel(syscon, SYSCON(port));
275
276         /*
277          * disable break condition and fifos
278          */
279         ubrlcr = clps_readl(UBRLCR(port));
280         ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
281         clps_writel(ubrlcr, UBRLCR(port));
282 }
283
284 static void
285 clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
286                          struct ktermios *old)
287 {
288         unsigned int ubrlcr, baud, quot;
289         unsigned long flags;
290
291         /*
292          * We don't implement CREAD.
293          */
294         termios->c_cflag |= CREAD;
295
296         /*
297          * Ask the core to calculate the divisor for us.
298          */
299         baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
300         quot = uart_get_divisor(port, baud);
301
302         switch (termios->c_cflag & CSIZE) {
303         case CS5:
304                 ubrlcr = UBRLCR_WRDLEN5;
305                 break;
306         case CS6:
307                 ubrlcr = UBRLCR_WRDLEN6;
308                 break;
309         case CS7:
310                 ubrlcr = UBRLCR_WRDLEN7;
311                 break;
312         default: // CS8
313                 ubrlcr = UBRLCR_WRDLEN8;
314                 break;
315         }
316         if (termios->c_cflag & CSTOPB)
317                 ubrlcr |= UBRLCR_XSTOP;
318         if (termios->c_cflag & PARENB) {
319                 ubrlcr |= UBRLCR_PRTEN;
320                 if (!(termios->c_cflag & PARODD))
321                         ubrlcr |= UBRLCR_EVENPRT;
322         }
323         if (port->fifosize > 1)
324                 ubrlcr |= UBRLCR_FIFOEN;
325
326         spin_lock_irqsave(&port->lock, flags);
327
328         /*
329          * Update the per-port timeout.
330          */
331         uart_update_timeout(port, termios->c_cflag, baud);
332
333         port->read_status_mask = UARTDR_OVERR;
334         if (termios->c_iflag & INPCK)
335                 port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
336
337         /*
338          * Characters to ignore
339          */
340         port->ignore_status_mask = 0;
341         if (termios->c_iflag & IGNPAR)
342                 port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR;
343         if (termios->c_iflag & IGNBRK) {
344                 /*
345                  * If we're ignoring parity and break indicators,
346                  * ignore overruns to (for real raw support).
347                  */
348                 if (termios->c_iflag & IGNPAR)
349                         port->ignore_status_mask |= UARTDR_OVERR;
350         }
351
352         quot -= 1;
353
354         clps_writel(ubrlcr | quot, UBRLCR(port));
355
356         spin_unlock_irqrestore(&port->lock, flags);
357 }
358
359 static const char *clps711xuart_type(struct uart_port *port)
360 {
361         return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
362 }
363
364 /*
365  * Configure/autoconfigure the port.
366  */
367 static void clps711xuart_config_port(struct uart_port *port, int flags)
368 {
369         if (flags & UART_CONFIG_TYPE)
370                 port->type = PORT_CLPS711X;
371 }
372
373 static void clps711xuart_release_port(struct uart_port *port)
374 {
375 }
376
377 static int clps711xuart_request_port(struct uart_port *port)
378 {
379         return 0;
380 }
381
382 static struct uart_ops clps711x_pops = {
383         .tx_empty       = clps711xuart_tx_empty,
384         .set_mctrl      = clps711xuart_set_mctrl_null,
385         .get_mctrl      = clps711xuart_get_mctrl,
386         .stop_tx        = clps711xuart_stop_tx,
387         .start_tx       = clps711xuart_start_tx,
388         .stop_rx        = clps711xuart_stop_rx,
389         .enable_ms      = clps711xuart_enable_ms,
390         .break_ctl      = clps711xuart_break_ctl,
391         .startup        = clps711xuart_startup,
392         .shutdown       = clps711xuart_shutdown,
393         .set_termios    = clps711xuart_set_termios,
394         .type           = clps711xuart_type,
395         .config_port    = clps711xuart_config_port,
396         .release_port   = clps711xuart_release_port,
397         .request_port   = clps711xuart_request_port,
398 };
399
400 static struct uart_port clps711x_ports[UART_NR] = {
401         {
402                 .iobase         = SYSCON1,
403                 .irq            = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
404                 .uartclk        = 3686400,
405                 .fifosize       = 16,
406                 .ops            = &clps711x_pops,
407                 .line           = 0,
408                 .flags          = UPF_BOOT_AUTOCONF,
409         },
410         {
411                 .iobase         = SYSCON2,
412                 .irq            = IRQ_UTXINT2, /* IRQ_URXINT2 */
413                 .uartclk        = 3686400,
414                 .fifosize       = 16,
415                 .ops            = &clps711x_pops,
416                 .line           = 1,
417                 .flags          = UPF_BOOT_AUTOCONF,
418         }
419 };
420
421 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
422 static void clps711xuart_console_putchar(struct uart_port *port, int ch)
423 {
424         while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF)
425                 barrier();
426         clps_writel(ch, UARTDR(port));
427 }
428
429 /*
430  *      Print a string to the serial port trying not to disturb
431  *      any possible real use of the port...
432  *
433  *      The console_lock must be held when we get here.
434  *
435  *      Note that this is called with interrupts already disabled
436  */
437 static void
438 clps711xuart_console_write(struct console *co, const char *s,
439                            unsigned int count)
440 {
441         struct uart_port *port = clps711x_ports + co->index;
442         unsigned int status, syscon;
443
444         /*
445          *      Ensure that the port is enabled.
446          */
447         syscon = clps_readl(SYSCON(port));
448         clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
449
450         uart_console_write(port, s, count, clps711xuart_console_putchar);
451
452         /*
453          *      Finally, wait for transmitter to become empty
454          *      and restore the uart state.
455          */
456         do {
457                 status = clps_readl(SYSFLG(port));
458         } while (status & SYSFLG_UBUSY);
459
460         clps_writel(syscon, SYSCON(port));
461 }
462
463 static void __init
464 clps711xuart_console_get_options(struct uart_port *port, int *baud,
465                                  int *parity, int *bits)
466 {
467         if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
468                 unsigned int ubrlcr, quot;
469
470                 ubrlcr = clps_readl(UBRLCR(port));
471
472                 *parity = 'n';
473                 if (ubrlcr & UBRLCR_PRTEN) {
474                         if (ubrlcr & UBRLCR_EVENPRT)
475                                 *parity = 'e';
476                         else
477                                 *parity = 'o';
478                 }
479
480                 if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7)
481                         *bits = 7;
482                 else
483                         *bits = 8;
484
485                 quot = ubrlcr & UBRLCR_BAUD_MASK;
486                 *baud = port->uartclk / (16 * (quot + 1));
487         }
488 }
489
490 static int __init clps711xuart_console_setup(struct console *co, char *options)
491 {
492         struct uart_port *port;
493         int baud = 38400;
494         int bits = 8;
495         int parity = 'n';
496         int flow = 'n';
497
498         /*
499          * Check whether an invalid uart number has been specified, and
500          * if so, search for the first available port that does have
501          * console support.
502          */
503         port = uart_get_console(clps711x_ports, UART_NR, co);
504
505         if (options)
506                 uart_parse_options(options, &baud, &parity, &bits, &flow);
507         else
508                 clps711xuart_console_get_options(port, &baud, &parity, &bits);
509
510         return uart_set_options(port, co, baud, parity, bits, flow);
511 }
512
513 static struct uart_driver clps711x_reg;
514 static struct console clps711x_console = {
515         .name           = "ttyCL",
516         .write          = clps711xuart_console_write,
517         .device         = uart_console_device,
518         .setup          = clps711xuart_console_setup,
519         .flags          = CON_PRINTBUFFER,
520         .index          = -1,
521         .data           = &clps711x_reg,
522 };
523
524 static int __init clps711xuart_console_init(void)
525 {
526         register_console(&clps711x_console);
527         return 0;
528 }
529 console_initcall(clps711xuart_console_init);
530
531 #define CLPS711X_CONSOLE        &clps711x_console
532 #else
533 #define CLPS711X_CONSOLE        NULL
534 #endif
535
536 static struct uart_driver clps711x_reg = {
537         .driver_name            = "ttyCL",
538         .dev_name               = "ttyCL",
539         .major                  = SERIAL_CLPS711X_MAJOR,
540         .minor                  = SERIAL_CLPS711X_MINOR,
541         .nr                     = UART_NR,
542
543         .cons                   = CLPS711X_CONSOLE,
544 };
545
546 static int __init clps711xuart_init(void)
547 {
548         int ret, i;
549
550         printk(KERN_INFO "Serial: CLPS711x driver\n");
551
552         ret = uart_register_driver(&clps711x_reg);
553         if (ret)
554                 return ret;
555
556         for (i = 0; i < UART_NR; i++)
557                 uart_add_one_port(&clps711x_reg, &clps711x_ports[i]);
558
559         return 0;
560 }
561
562 static void __exit clps711xuart_exit(void)
563 {
564         int i;
565
566         for (i = 0; i < UART_NR; i++)
567                 uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]);
568
569         uart_unregister_driver(&clps711x_reg);
570 }
571
572 module_init(clps711xuart_init);
573 module_exit(clps711xuart_exit);
574
575 MODULE_AUTHOR("Deep Blue Solutions Ltd");
576 MODULE_DESCRIPTION("CLPS-711x generic serial driver");
577 MODULE_LICENSE("GPL");
578 MODULE_ALIAS_CHARDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR);