serial: clps711x: Convert all static variables to dynamic
[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 #include <linux/platform_device.h>
41
42 #include <mach/hardware.h>
43 #include <asm/irq.h>
44
45 #define UART_CLPS711X_NAME      "uart-clps711x"
46 #define UART_CLPS711X_NR        2
47 #define UART_CLPS711X_MAJOR     204
48 #define UART_CLPS711X_MINOR     40
49
50 #define UBRLCR(port)            ((port)->line ? UBRLCR2 : UBRLCR1)
51 #define UARTDR(port)            ((port)->line ? UARTDR2 : UARTDR1)
52 #define SYSFLG(port)            ((port)->line ? SYSFLG2 : SYSFLG1)
53 #define SYSCON(port)            ((port)->line ? SYSCON2 : SYSCON1)
54 #define TX_IRQ(port)            ((port)->line ? IRQ_UTXINT2 : IRQ_UTXINT1)
55 #define RX_IRQ(port)            ((port)->line ? IRQ_URXINT2 : IRQ_URXINT1)
56
57 #define UART_ANY_ERR            (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
58
59 #define tx_enabled(port)        ((port)->unused[0])
60
61 struct clps711x_port {
62         struct uart_driver      uart;
63         struct uart_port        port[UART_CLPS711X_NR];
64 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
65         struct console          console;
66 #endif
67 };
68
69 static void clps711xuart_stop_tx(struct uart_port *port)
70 {
71         if (tx_enabled(port)) {
72                 disable_irq(TX_IRQ(port));
73                 tx_enabled(port) = 0;
74         }
75 }
76
77 static void clps711xuart_start_tx(struct uart_port *port)
78 {
79         if (!tx_enabled(port)) {
80                 enable_irq(TX_IRQ(port));
81                 tx_enabled(port) = 1;
82         }
83 }
84
85 static void clps711xuart_stop_rx(struct uart_port *port)
86 {
87         disable_irq(RX_IRQ(port));
88 }
89
90 static void clps711xuart_enable_ms(struct uart_port *port)
91 {
92 }
93
94 static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id)
95 {
96         struct uart_port *port = dev_id;
97         struct tty_struct *tty = port->state->port.tty;
98         unsigned int status, ch, flg;
99
100         status = clps_readl(SYSFLG(port));
101         while (!(status & SYSFLG_URXFE)) {
102                 ch = clps_readl(UARTDR(port));
103
104                 port->icount.rx++;
105
106                 flg = TTY_NORMAL;
107
108                 /*
109                  * Note that the error handling code is
110                  * out of the main execution path
111                  */
112                 if (unlikely(ch & UART_ANY_ERR)) {
113                         if (ch & UARTDR_PARERR)
114                                 port->icount.parity++;
115                         else if (ch & UARTDR_FRMERR)
116                                 port->icount.frame++;
117                         if (ch & UARTDR_OVERR)
118                                 port->icount.overrun++;
119
120                         ch &= port->read_status_mask;
121
122                         if (ch & UARTDR_PARERR)
123                                 flg = TTY_PARITY;
124                         else if (ch & UARTDR_FRMERR)
125                                 flg = TTY_FRAME;
126
127 #ifdef SUPPORT_SYSRQ
128                         port->sysrq = 0;
129 #endif
130                 }
131
132                 if (uart_handle_sysrq_char(port, ch))
133                         goto ignore_char;
134
135                 /*
136                  * CHECK: does overrun affect the current character?
137                  * ASSUMPTION: it does not.
138                  */
139                 uart_insert_char(port, ch, UARTDR_OVERR, ch, flg);
140
141         ignore_char:
142                 status = clps_readl(SYSFLG(port));
143         }
144         tty_flip_buffer_push(tty);
145         return IRQ_HANDLED;
146 }
147
148 static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
149 {
150         struct uart_port *port = dev_id;
151         struct circ_buf *xmit = &port->state->xmit;
152         int count;
153
154         if (port->x_char) {
155                 clps_writel(port->x_char, UARTDR(port));
156                 port->icount.tx++;
157                 port->x_char = 0;
158                 return IRQ_HANDLED;
159         }
160
161         if (uart_circ_empty(xmit) || uart_tx_stopped(port))
162                 goto disable_tx_irq;
163
164         count = port->fifosize >> 1;
165         do {
166                 clps_writel(xmit->buf[xmit->tail], UARTDR(port));
167                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
168                 port->icount.tx++;
169                 if (uart_circ_empty(xmit))
170                         break;
171         } while (--count > 0);
172
173         if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
174                 uart_write_wakeup(port);
175
176         if (uart_circ_empty(xmit)) {
177         disable_tx_irq:
178                 disable_irq_nosync(TX_IRQ(port));
179                 tx_enabled(port) = 0;
180         }
181
182         return IRQ_HANDLED;
183 }
184
185 static unsigned int clps711xuart_tx_empty(struct uart_port *port)
186 {
187         unsigned int status = clps_readl(SYSFLG(port));
188         return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
189 }
190
191 static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
192 {
193         unsigned int port_addr;
194         unsigned int result = 0;
195         unsigned int status;
196
197         port_addr = SYSFLG(port);
198         if (port_addr == SYSFLG1) {
199                 status = clps_readl(SYSFLG1);
200                 if (status & SYSFLG1_DCD)
201                         result |= TIOCM_CAR;
202                 if (status & SYSFLG1_DSR)
203                         result |= TIOCM_DSR;
204                 if (status & SYSFLG1_CTS)
205                         result |= TIOCM_CTS;
206         }
207
208         return result;
209 }
210
211 static void
212 clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
213 {
214 }
215
216 static void clps711xuart_break_ctl(struct uart_port *port, int break_state)
217 {
218         unsigned long flags;
219         unsigned int ubrlcr;
220
221         spin_lock_irqsave(&port->lock, flags);
222         ubrlcr = clps_readl(UBRLCR(port));
223         if (break_state == -1)
224                 ubrlcr |= UBRLCR_BREAK;
225         else
226                 ubrlcr &= ~UBRLCR_BREAK;
227         clps_writel(ubrlcr, UBRLCR(port));
228         spin_unlock_irqrestore(&port->lock, flags);
229 }
230
231 static int clps711xuart_startup(struct uart_port *port)
232 {
233         unsigned int syscon;
234         int retval;
235
236         tx_enabled(port) = 1;
237
238         /*
239          * Allocate the IRQs
240          */
241         retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0,
242                              "clps711xuart_tx", port);
243         if (retval)
244                 return retval;
245
246         retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
247                              "clps711xuart_rx", port);
248         if (retval) {
249                 free_irq(TX_IRQ(port), port);
250                 return retval;
251         }
252
253         /*
254          * enable the port
255          */
256         syscon = clps_readl(SYSCON(port));
257         syscon |= SYSCON_UARTEN;
258         clps_writel(syscon, SYSCON(port));
259
260         return 0;
261 }
262
263 static void clps711xuart_shutdown(struct uart_port *port)
264 {
265         unsigned int ubrlcr, syscon;
266
267         /*
268          * Free the interrupt
269          */
270         free_irq(TX_IRQ(port), port);   /* TX interrupt */
271         free_irq(RX_IRQ(port), port);   /* RX interrupt */
272
273         /*
274          * disable the port
275          */
276         syscon = clps_readl(SYSCON(port));
277         syscon &= ~SYSCON_UARTEN;
278         clps_writel(syscon, SYSCON(port));
279
280         /*
281          * disable break condition and fifos
282          */
283         ubrlcr = clps_readl(UBRLCR(port));
284         ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
285         clps_writel(ubrlcr, UBRLCR(port));
286 }
287
288 static void
289 clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
290                          struct ktermios *old)
291 {
292         unsigned int ubrlcr, baud, quot;
293         unsigned long flags;
294
295         /*
296          * We don't implement CREAD.
297          */
298         termios->c_cflag |= CREAD;
299
300         /*
301          * Ask the core to calculate the divisor for us.
302          */
303         baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
304         quot = uart_get_divisor(port, baud);
305
306         switch (termios->c_cflag & CSIZE) {
307         case CS5:
308                 ubrlcr = UBRLCR_WRDLEN5;
309                 break;
310         case CS6:
311                 ubrlcr = UBRLCR_WRDLEN6;
312                 break;
313         case CS7:
314                 ubrlcr = UBRLCR_WRDLEN7;
315                 break;
316         default: // CS8
317                 ubrlcr = UBRLCR_WRDLEN8;
318                 break;
319         }
320         if (termios->c_cflag & CSTOPB)
321                 ubrlcr |= UBRLCR_XSTOP;
322         if (termios->c_cflag & PARENB) {
323                 ubrlcr |= UBRLCR_PRTEN;
324                 if (!(termios->c_cflag & PARODD))
325                         ubrlcr |= UBRLCR_EVENPRT;
326         }
327         if (port->fifosize > 1)
328                 ubrlcr |= UBRLCR_FIFOEN;
329
330         spin_lock_irqsave(&port->lock, flags);
331
332         /*
333          * Update the per-port timeout.
334          */
335         uart_update_timeout(port, termios->c_cflag, baud);
336
337         port->read_status_mask = UARTDR_OVERR;
338         if (termios->c_iflag & INPCK)
339                 port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
340
341         /*
342          * Characters to ignore
343          */
344         port->ignore_status_mask = 0;
345         if (termios->c_iflag & IGNPAR)
346                 port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR;
347         if (termios->c_iflag & IGNBRK) {
348                 /*
349                  * If we're ignoring parity and break indicators,
350                  * ignore overruns to (for real raw support).
351                  */
352                 if (termios->c_iflag & IGNPAR)
353                         port->ignore_status_mask |= UARTDR_OVERR;
354         }
355
356         quot -= 1;
357
358         clps_writel(ubrlcr | quot, UBRLCR(port));
359
360         spin_unlock_irqrestore(&port->lock, flags);
361 }
362
363 static const char *clps711xuart_type(struct uart_port *port)
364 {
365         return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
366 }
367
368 /*
369  * Configure/autoconfigure the port.
370  */
371 static void clps711xuart_config_port(struct uart_port *port, int flags)
372 {
373         if (flags & UART_CONFIG_TYPE)
374                 port->type = PORT_CLPS711X;
375 }
376
377 static void clps711xuart_release_port(struct uart_port *port)
378 {
379 }
380
381 static int clps711xuart_request_port(struct uart_port *port)
382 {
383         return 0;
384 }
385
386 static struct uart_ops uart_clps711x_ops = {
387         .tx_empty       = clps711xuart_tx_empty,
388         .set_mctrl      = clps711xuart_set_mctrl_null,
389         .get_mctrl      = clps711xuart_get_mctrl,
390         .stop_tx        = clps711xuart_stop_tx,
391         .start_tx       = clps711xuart_start_tx,
392         .stop_rx        = clps711xuart_stop_rx,
393         .enable_ms      = clps711xuart_enable_ms,
394         .break_ctl      = clps711xuart_break_ctl,
395         .startup        = clps711xuart_startup,
396         .shutdown       = clps711xuart_shutdown,
397         .set_termios    = clps711xuart_set_termios,
398         .type           = clps711xuart_type,
399         .config_port    = clps711xuart_config_port,
400         .release_port   = clps711xuart_release_port,
401         .request_port   = clps711xuart_request_port,
402 };
403
404 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
405 static void uart_clps711x_console_putchar(struct uart_port *port, int ch)
406 {
407         while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF)
408                 barrier();
409
410         clps_writew(ch, UARTDR(port));
411 }
412
413 static void uart_clps711x_console_write(struct console *co, const char *c,
414                                         unsigned n)
415 {
416         struct clps711x_port *s = (struct clps711x_port *)co->data;
417         struct uart_port *port = &s->port[co->index];
418         u32 syscon;
419
420         /* Ensure that the port is enabled */
421         syscon = clps_readl(SYSCON(port));
422         clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
423
424         uart_console_write(port, c, n, uart_clps711x_console_putchar);
425
426         /* Wait for transmitter to become empty */
427         while (clps_readl(SYSFLG(port)) & SYSFLG_UBUSY)
428                 barrier();
429
430         /* Restore the uart state */
431         clps_writel(syscon, SYSCON(port));
432 }
433
434 static void uart_clps711x_console_get_options(struct uart_port *port,
435                                               int *baud, int *parity,
436                                               int *bits)
437 {
438         if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
439                 unsigned int ubrlcr, quot;
440
441                 ubrlcr = clps_readl(UBRLCR(port));
442
443                 *parity = 'n';
444                 if (ubrlcr & UBRLCR_PRTEN) {
445                         if (ubrlcr & UBRLCR_EVENPRT)
446                                 *parity = 'e';
447                         else
448                                 *parity = 'o';
449                 }
450
451                 if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7)
452                         *bits = 7;
453                 else
454                         *bits = 8;
455
456                 quot = ubrlcr & UBRLCR_BAUD_MASK;
457                 *baud = port->uartclk / (16 * (quot + 1));
458         }
459 }
460
461 static int uart_clps711x_console_setup(struct console *co, char *options)
462 {
463         int baud = 38400, bits = 8, parity = 'n', flow = 'n';
464         struct clps711x_port *s = (struct clps711x_port *)co->data;
465         struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0];
466
467         if (options)
468                 uart_parse_options(options, &baud, &parity, &bits, &flow);
469         else
470                 uart_clps711x_console_get_options(port, &baud, &parity, &bits);
471
472         return uart_set_options(port, co, baud, parity, bits, flow);
473 }
474 #endif
475
476 static int __devinit uart_clps711x_probe(struct platform_device *pdev)
477 {
478         struct clps711x_port *s;
479         int ret, i;
480
481         s = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_port), GFP_KERNEL);
482         if (!s) {
483                 dev_err(&pdev->dev, "Error allocating port structure\n");
484                 return -ENOMEM;
485         }
486         platform_set_drvdata(pdev, s);
487
488         s->uart.owner           = THIS_MODULE;
489         s->uart.dev_name        = "ttyCL";
490         s->uart.major           = UART_CLPS711X_MAJOR;
491         s->uart.minor           = UART_CLPS711X_MINOR;
492         s->uart.nr              = UART_CLPS711X_NR;
493 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
494         s->uart.cons            = &s->console;
495         s->uart.cons->device    = uart_console_device;
496         s->uart.cons->write     = uart_clps711x_console_write;
497         s->uart.cons->setup     = uart_clps711x_console_setup;
498         s->uart.cons->flags     = CON_PRINTBUFFER;
499         s->uart.cons->index     = -1;
500         s->uart.cons->data      = s;
501         strcpy(s->uart.cons->name, "ttyCL");
502 #endif
503         ret = uart_register_driver(&s->uart);
504         if (ret) {
505                 dev_err(&pdev->dev, "Registering UART driver failed\n");
506                 goto err_out;
507         }
508
509         for (i = 0; i < UART_CLPS711X_NR; i++) {
510                 s->port[i].line         = i;
511                 s->port[i].dev          = &pdev->dev;
512                 s->port[i].irq          = TX_IRQ(&s->port[i]);
513                 s->port[i].iobase       = SYSCON(&s->port[i]);
514                 s->port[i].type         = PORT_CLPS711X;
515                 s->port[i].fifosize     = 16;
516                 s->port[i].flags        = UPF_SKIP_TEST | UPF_FIXED_TYPE;
517                 s->port[i].uartclk      = 3686400;
518                 s->port[i].ops          = &uart_clps711x_ops;
519                 WARN_ON(uart_add_one_port(&s->uart, &s->port[i]));
520         }
521
522         return 0;
523
524 err_out:
525         platform_set_drvdata(pdev, NULL);
526
527         return ret;
528 }
529
530 static int __devexit uart_clps711x_remove(struct platform_device *pdev)
531 {
532         struct clps711x_port *s = platform_get_drvdata(pdev);
533         int i;
534
535         for (i = 0; i < UART_CLPS711X_NR; i++)
536                 uart_remove_one_port(&s->uart, &s->port[i]);
537
538         uart_unregister_driver(&s->uart);
539         platform_set_drvdata(pdev, NULL);
540
541         return 0;
542 }
543
544 static struct platform_driver clps711x_uart_driver = {
545         .driver = {
546                 .name   = UART_CLPS711X_NAME,
547                 .owner  = THIS_MODULE,
548         },
549         .probe  = uart_clps711x_probe,
550         .remove = __devexit_p(uart_clps711x_remove),
551 };
552 module_platform_driver(clps711x_uart_driver);
553
554 static struct platform_device clps711x_uart_device = {
555         .name   = UART_CLPS711X_NAME,
556 };
557
558 static int __init uart_clps711x_init(void)
559 {
560         return platform_device_register(&clps711x_uart_device);
561 }
562 module_init(uart_clps711x_init);
563
564 static void __exit uart_clps711x_exit(void)
565 {
566         platform_device_unregister(&clps711x_uart_device);
567 }
568 module_exit(uart_clps711x_exit);
569
570 MODULE_AUTHOR("Deep Blue Solutions Ltd");
571 MODULE_DESCRIPTION("CLPS711X serial driver");
572 MODULE_LICENSE("GPL");