]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/tty/serial/lantiq.c
TTY: switch tty_flip_buffer_push
[karo-tx-linux.git] / drivers / tty / serial / lantiq.c
1 /*
2  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  *
17  * Copyright (C) 2004 Infineon IFAP DC COM CPE
18  * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
19  * Copyright (C) 2007 John Crispin <blogic@openwrt.org>
20  * Copyright (C) 2010 Thomas Langer, <thomas.langer@lantiq.com>
21  */
22
23 #include <linux/slab.h>
24 #include <linux/module.h>
25 #include <linux/ioport.h>
26 #include <linux/init.h>
27 #include <linux/console.h>
28 #include <linux/sysrq.h>
29 #include <linux/device.h>
30 #include <linux/tty.h>
31 #include <linux/tty_flip.h>
32 #include <linux/serial_core.h>
33 #include <linux/serial.h>
34 #include <linux/of_platform.h>
35 #include <linux/of_address.h>
36 #include <linux/of_irq.h>
37 #include <linux/io.h>
38 #include <linux/clk.h>
39 #include <linux/gpio.h>
40
41 #include <lantiq_soc.h>
42
43 #define PORT_LTQ_ASC            111
44 #define MAXPORTS                2
45 #define UART_DUMMY_UER_RX       1
46 #define DRVNAME                 "lantiq,asc"
47 #ifdef __BIG_ENDIAN
48 #define LTQ_ASC_TBUF            (0x0020 + 3)
49 #define LTQ_ASC_RBUF            (0x0024 + 3)
50 #else
51 #define LTQ_ASC_TBUF            0x0020
52 #define LTQ_ASC_RBUF            0x0024
53 #endif
54 #define LTQ_ASC_FSTAT           0x0048
55 #define LTQ_ASC_WHBSTATE        0x0018
56 #define LTQ_ASC_STATE           0x0014
57 #define LTQ_ASC_IRNCR           0x00F8
58 #define LTQ_ASC_CLC             0x0000
59 #define LTQ_ASC_ID              0x0008
60 #define LTQ_ASC_PISEL           0x0004
61 #define LTQ_ASC_TXFCON          0x0044
62 #define LTQ_ASC_RXFCON          0x0040
63 #define LTQ_ASC_CON             0x0010
64 #define LTQ_ASC_BG              0x0050
65 #define LTQ_ASC_IRNREN          0x00F4
66
67 #define ASC_IRNREN_TX           0x1
68 #define ASC_IRNREN_RX           0x2
69 #define ASC_IRNREN_ERR          0x4
70 #define ASC_IRNREN_TX_BUF       0x8
71 #define ASC_IRNCR_TIR           0x1
72 #define ASC_IRNCR_RIR           0x2
73 #define ASC_IRNCR_EIR           0x4
74
75 #define ASCOPT_CSIZE            0x3
76 #define TXFIFO_FL               1
77 #define RXFIFO_FL               1
78 #define ASCCLC_DISS             0x2
79 #define ASCCLC_RMCMASK          0x0000FF00
80 #define ASCCLC_RMCOFFSET        8
81 #define ASCCON_M_8ASYNC         0x0
82 #define ASCCON_M_7ASYNC         0x2
83 #define ASCCON_ODD              0x00000020
84 #define ASCCON_STP              0x00000080
85 #define ASCCON_BRS              0x00000100
86 #define ASCCON_FDE              0x00000200
87 #define ASCCON_R                0x00008000
88 #define ASCCON_FEN              0x00020000
89 #define ASCCON_ROEN             0x00080000
90 #define ASCCON_TOEN             0x00100000
91 #define ASCSTATE_PE             0x00010000
92 #define ASCSTATE_FE             0x00020000
93 #define ASCSTATE_ROE            0x00080000
94 #define ASCSTATE_ANY            (ASCSTATE_ROE|ASCSTATE_PE|ASCSTATE_FE)
95 #define ASCWHBSTATE_CLRREN      0x00000001
96 #define ASCWHBSTATE_SETREN      0x00000002
97 #define ASCWHBSTATE_CLRPE       0x00000004
98 #define ASCWHBSTATE_CLRFE       0x00000008
99 #define ASCWHBSTATE_CLRROE      0x00000020
100 #define ASCTXFCON_TXFEN         0x0001
101 #define ASCTXFCON_TXFFLU        0x0002
102 #define ASCTXFCON_TXFITLMASK    0x3F00
103 #define ASCTXFCON_TXFITLOFF     8
104 #define ASCRXFCON_RXFEN         0x0001
105 #define ASCRXFCON_RXFFLU        0x0002
106 #define ASCRXFCON_RXFITLMASK    0x3F00
107 #define ASCRXFCON_RXFITLOFF     8
108 #define ASCFSTAT_RXFFLMASK      0x003F
109 #define ASCFSTAT_TXFFLMASK      0x3F00
110 #define ASCFSTAT_TXFREEMASK     0x3F000000
111 #define ASCFSTAT_TXFREEOFF      24
112
113 static void lqasc_tx_chars(struct uart_port *port);
114 static struct ltq_uart_port *lqasc_port[MAXPORTS];
115 static struct uart_driver lqasc_reg;
116 static DEFINE_SPINLOCK(ltq_asc_lock);
117
118 struct ltq_uart_port {
119         struct uart_port        port;
120         /* clock used to derive divider */
121         struct clk              *fpiclk;
122         /* clock gating of the ASC core */
123         struct clk              *clk;
124         unsigned int            tx_irq;
125         unsigned int            rx_irq;
126         unsigned int            err_irq;
127 };
128
129 static inline struct
130 ltq_uart_port *to_ltq_uart_port(struct uart_port *port)
131 {
132         return container_of(port, struct ltq_uart_port, port);
133 }
134
135 static void
136 lqasc_stop_tx(struct uart_port *port)
137 {
138         return;
139 }
140
141 static void
142 lqasc_start_tx(struct uart_port *port)
143 {
144         unsigned long flags;
145         spin_lock_irqsave(&ltq_asc_lock, flags);
146         lqasc_tx_chars(port);
147         spin_unlock_irqrestore(&ltq_asc_lock, flags);
148         return;
149 }
150
151 static void
152 lqasc_stop_rx(struct uart_port *port)
153 {
154         ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
155 }
156
157 static void
158 lqasc_enable_ms(struct uart_port *port)
159 {
160 }
161
162 static int
163 lqasc_rx_chars(struct uart_port *port)
164 {
165         struct tty_port *tport = &port->state->port;
166         unsigned int ch = 0, rsr = 0, fifocnt;
167
168         fifocnt = ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
169         while (fifocnt--) {
170                 u8 flag = TTY_NORMAL;
171                 ch = ltq_r8(port->membase + LTQ_ASC_RBUF);
172                 rsr = (ltq_r32(port->membase + LTQ_ASC_STATE)
173                         & ASCSTATE_ANY) | UART_DUMMY_UER_RX;
174                 tty_flip_buffer_push(tport);
175                 port->icount.rx++;
176
177                 /*
178                  * Note that the error handling code is
179                  * out of the main execution path
180                  */
181                 if (rsr & ASCSTATE_ANY) {
182                         if (rsr & ASCSTATE_PE) {
183                                 port->icount.parity++;
184                                 ltq_w32_mask(0, ASCWHBSTATE_CLRPE,
185                                         port->membase + LTQ_ASC_WHBSTATE);
186                         } else if (rsr & ASCSTATE_FE) {
187                                 port->icount.frame++;
188                                 ltq_w32_mask(0, ASCWHBSTATE_CLRFE,
189                                         port->membase + LTQ_ASC_WHBSTATE);
190                         }
191                         if (rsr & ASCSTATE_ROE) {
192                                 port->icount.overrun++;
193                                 ltq_w32_mask(0, ASCWHBSTATE_CLRROE,
194                                         port->membase + LTQ_ASC_WHBSTATE);
195                         }
196
197                         rsr &= port->read_status_mask;
198
199                         if (rsr & ASCSTATE_PE)
200                                 flag = TTY_PARITY;
201                         else if (rsr & ASCSTATE_FE)
202                                 flag = TTY_FRAME;
203                 }
204
205                 if ((rsr & port->ignore_status_mask) == 0)
206                         tty_insert_flip_char(tport, ch, flag);
207
208                 if (rsr & ASCSTATE_ROE)
209                         /*
210                          * Overrun is special, since it's reported
211                          * immediately, and doesn't affect the current
212                          * character
213                          */
214                         tty_insert_flip_char(tport, 0, TTY_OVERRUN);
215         }
216
217         if (ch != 0)
218                 tty_flip_buffer_push(tport);
219
220         return 0;
221 }
222
223 static void
224 lqasc_tx_chars(struct uart_port *port)
225 {
226         struct circ_buf *xmit = &port->state->xmit;
227         if (uart_tx_stopped(port)) {
228                 lqasc_stop_tx(port);
229                 return;
230         }
231
232         while (((ltq_r32(port->membase + LTQ_ASC_FSTAT) &
233                 ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) {
234                 if (port->x_char) {
235                         ltq_w8(port->x_char, port->membase + LTQ_ASC_TBUF);
236                         port->icount.tx++;
237                         port->x_char = 0;
238                         continue;
239                 }
240
241                 if (uart_circ_empty(xmit))
242                         break;
243
244                 ltq_w8(port->state->xmit.buf[port->state->xmit.tail],
245                         port->membase + LTQ_ASC_TBUF);
246                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
247                 port->icount.tx++;
248         }
249
250         if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
251                 uart_write_wakeup(port);
252 }
253
254 static irqreturn_t
255 lqasc_tx_int(int irq, void *_port)
256 {
257         unsigned long flags;
258         struct uart_port *port = (struct uart_port *)_port;
259         spin_lock_irqsave(&ltq_asc_lock, flags);
260         ltq_w32(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
261         spin_unlock_irqrestore(&ltq_asc_lock, flags);
262         lqasc_start_tx(port);
263         return IRQ_HANDLED;
264 }
265
266 static irqreturn_t
267 lqasc_err_int(int irq, void *_port)
268 {
269         unsigned long flags;
270         struct uart_port *port = (struct uart_port *)_port;
271         spin_lock_irqsave(&ltq_asc_lock, flags);
272         /* clear any pending interrupts */
273         ltq_w32_mask(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE |
274                 ASCWHBSTATE_CLRROE, port->membase + LTQ_ASC_WHBSTATE);
275         spin_unlock_irqrestore(&ltq_asc_lock, flags);
276         return IRQ_HANDLED;
277 }
278
279 static irqreturn_t
280 lqasc_rx_int(int irq, void *_port)
281 {
282         unsigned long flags;
283         struct uart_port *port = (struct uart_port *)_port;
284         spin_lock_irqsave(&ltq_asc_lock, flags);
285         ltq_w32(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
286         lqasc_rx_chars(port);
287         spin_unlock_irqrestore(&ltq_asc_lock, flags);
288         return IRQ_HANDLED;
289 }
290
291 static unsigned int
292 lqasc_tx_empty(struct uart_port *port)
293 {
294         int status;
295         status = ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
296         return status ? 0 : TIOCSER_TEMT;
297 }
298
299 static unsigned int
300 lqasc_get_mctrl(struct uart_port *port)
301 {
302         return TIOCM_CTS | TIOCM_CAR | TIOCM_DSR;
303 }
304
305 static void
306 lqasc_set_mctrl(struct uart_port *port, u_int mctrl)
307 {
308 }
309
310 static void
311 lqasc_break_ctl(struct uart_port *port, int break_state)
312 {
313 }
314
315 static int
316 lqasc_startup(struct uart_port *port)
317 {
318         struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
319         int retval;
320
321         if (ltq_port->clk)
322                 clk_enable(ltq_port->clk);
323         port->uartclk = clk_get_rate(ltq_port->fpiclk);
324
325         ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
326                 port->membase + LTQ_ASC_CLC);
327
328         ltq_w32(0, port->membase + LTQ_ASC_PISEL);
329         ltq_w32(
330                 ((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) |
331                 ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU,
332                 port->membase + LTQ_ASC_TXFCON);
333         ltq_w32(
334                 ((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK)
335                 | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU,
336                 port->membase + LTQ_ASC_RXFCON);
337         /* make sure other settings are written to hardware before
338          * setting enable bits
339          */
340         wmb();
341         ltq_w32_mask(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN |
342                 ASCCON_ROEN, port->membase + LTQ_ASC_CON);
343
344         retval = request_irq(ltq_port->tx_irq, lqasc_tx_int,
345                 0, "asc_tx", port);
346         if (retval) {
347                 pr_err("failed to request lqasc_tx_int\n");
348                 return retval;
349         }
350
351         retval = request_irq(ltq_port->rx_irq, lqasc_rx_int,
352                 0, "asc_rx", port);
353         if (retval) {
354                 pr_err("failed to request lqasc_rx_int\n");
355                 goto err1;
356         }
357
358         retval = request_irq(ltq_port->err_irq, lqasc_err_int,
359                 0, "asc_err", port);
360         if (retval) {
361                 pr_err("failed to request lqasc_err_int\n");
362                 goto err2;
363         }
364
365         ltq_w32(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
366                 port->membase + LTQ_ASC_IRNREN);
367         return 0;
368
369 err2:
370         free_irq(ltq_port->rx_irq, port);
371 err1:
372         free_irq(ltq_port->tx_irq, port);
373         return retval;
374 }
375
376 static void
377 lqasc_shutdown(struct uart_port *port)
378 {
379         struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
380         free_irq(ltq_port->tx_irq, port);
381         free_irq(ltq_port->rx_irq, port);
382         free_irq(ltq_port->err_irq, port);
383
384         ltq_w32(0, port->membase + LTQ_ASC_CON);
385         ltq_w32_mask(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU,
386                 port->membase + LTQ_ASC_RXFCON);
387         ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
388                 port->membase + LTQ_ASC_TXFCON);
389         if (ltq_port->clk)
390                 clk_disable(ltq_port->clk);
391 }
392
393 static void
394 lqasc_set_termios(struct uart_port *port,
395         struct ktermios *new, struct ktermios *old)
396 {
397         unsigned int cflag;
398         unsigned int iflag;
399         unsigned int divisor;
400         unsigned int baud;
401         unsigned int con = 0;
402         unsigned long flags;
403
404         cflag = new->c_cflag;
405         iflag = new->c_iflag;
406
407         switch (cflag & CSIZE) {
408         case CS7:
409                 con = ASCCON_M_7ASYNC;
410                 break;
411
412         case CS5:
413         case CS6:
414         default:
415                 new->c_cflag &= ~ CSIZE;
416                 new->c_cflag |= CS8;
417                 con = ASCCON_M_8ASYNC;
418                 break;
419         }
420
421         cflag &= ~CMSPAR; /* Mark/Space parity is not supported */
422
423         if (cflag & CSTOPB)
424                 con |= ASCCON_STP;
425
426         if (cflag & PARENB) {
427                 if (!(cflag & PARODD))
428                         con &= ~ASCCON_ODD;
429                 else
430                         con |= ASCCON_ODD;
431         }
432
433         port->read_status_mask = ASCSTATE_ROE;
434         if (iflag & INPCK)
435                 port->read_status_mask |= ASCSTATE_FE | ASCSTATE_PE;
436
437         port->ignore_status_mask = 0;
438         if (iflag & IGNPAR)
439                 port->ignore_status_mask |= ASCSTATE_FE | ASCSTATE_PE;
440
441         if (iflag & IGNBRK) {
442                 /*
443                  * If we're ignoring parity and break indicators,
444                  * ignore overruns too (for real raw support).
445                  */
446                 if (iflag & IGNPAR)
447                         port->ignore_status_mask |= ASCSTATE_ROE;
448         }
449
450         if ((cflag & CREAD) == 0)
451                 port->ignore_status_mask |= UART_DUMMY_UER_RX;
452
453         /* set error signals  - framing, parity  and overrun, enable receiver */
454         con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN;
455
456         spin_lock_irqsave(&ltq_asc_lock, flags);
457
458         /* set up CON */
459         ltq_w32_mask(0, con, port->membase + LTQ_ASC_CON);
460
461         /* Set baud rate - take a divider of 2 into account */
462         baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
463         divisor = uart_get_divisor(port, baud);
464         divisor = divisor / 2 - 1;
465
466         /* disable the baudrate generator */
467         ltq_w32_mask(ASCCON_R, 0, port->membase + LTQ_ASC_CON);
468
469         /* make sure the fractional divider is off */
470         ltq_w32_mask(ASCCON_FDE, 0, port->membase + LTQ_ASC_CON);
471
472         /* set up to use divisor of 2 */
473         ltq_w32_mask(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON);
474
475         /* now we can write the new baudrate into the register */
476         ltq_w32(divisor, port->membase + LTQ_ASC_BG);
477
478         /* turn the baudrate generator back on */
479         ltq_w32_mask(0, ASCCON_R, port->membase + LTQ_ASC_CON);
480
481         /* enable rx */
482         ltq_w32(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
483
484         spin_unlock_irqrestore(&ltq_asc_lock, flags);
485
486         /* Don't rewrite B0 */
487         if (tty_termios_baud_rate(new))
488                 tty_termios_encode_baud_rate(new, baud, baud);
489
490         uart_update_timeout(port, cflag, baud);
491 }
492
493 static const char*
494 lqasc_type(struct uart_port *port)
495 {
496         if (port->type == PORT_LTQ_ASC)
497                 return DRVNAME;
498         else
499                 return NULL;
500 }
501
502 static void
503 lqasc_release_port(struct uart_port *port)
504 {
505         if (port->flags & UPF_IOREMAP) {
506                 iounmap(port->membase);
507                 port->membase = NULL;
508         }
509 }
510
511 static int
512 lqasc_request_port(struct uart_port *port)
513 {
514         struct platform_device *pdev = to_platform_device(port->dev);
515         struct resource *res;
516         int size;
517
518         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
519         if (!res) {
520                 dev_err(&pdev->dev, "cannot obtain I/O memory region");
521                 return -ENODEV;
522         }
523         size = resource_size(res);
524
525         res = devm_request_mem_region(&pdev->dev, res->start,
526                 size, dev_name(&pdev->dev));
527         if (!res) {
528                 dev_err(&pdev->dev, "cannot request I/O memory region");
529                 return -EBUSY;
530         }
531
532         if (port->flags & UPF_IOREMAP) {
533                 port->membase = devm_ioremap_nocache(&pdev->dev,
534                         port->mapbase, size);
535                 if (port->membase == NULL)
536                         return -ENOMEM;
537         }
538         return 0;
539 }
540
541 static void
542 lqasc_config_port(struct uart_port *port, int flags)
543 {
544         if (flags & UART_CONFIG_TYPE) {
545                 port->type = PORT_LTQ_ASC;
546                 lqasc_request_port(port);
547         }
548 }
549
550 static int
551 lqasc_verify_port(struct uart_port *port,
552         struct serial_struct *ser)
553 {
554         int ret = 0;
555         if (ser->type != PORT_UNKNOWN && ser->type != PORT_LTQ_ASC)
556                 ret = -EINVAL;
557         if (ser->irq < 0 || ser->irq >= NR_IRQS)
558                 ret = -EINVAL;
559         if (ser->baud_base < 9600)
560                 ret = -EINVAL;
561         return ret;
562 }
563
564 static struct uart_ops lqasc_pops = {
565         .tx_empty =     lqasc_tx_empty,
566         .set_mctrl =    lqasc_set_mctrl,
567         .get_mctrl =    lqasc_get_mctrl,
568         .stop_tx =      lqasc_stop_tx,
569         .start_tx =     lqasc_start_tx,
570         .stop_rx =      lqasc_stop_rx,
571         .enable_ms =    lqasc_enable_ms,
572         .break_ctl =    lqasc_break_ctl,
573         .startup =      lqasc_startup,
574         .shutdown =     lqasc_shutdown,
575         .set_termios =  lqasc_set_termios,
576         .type =         lqasc_type,
577         .release_port = lqasc_release_port,
578         .request_port = lqasc_request_port,
579         .config_port =  lqasc_config_port,
580         .verify_port =  lqasc_verify_port,
581 };
582
583 static void
584 lqasc_console_putchar(struct uart_port *port, int ch)
585 {
586         int fifofree;
587
588         if (!port->membase)
589                 return;
590
591         do {
592                 fifofree = (ltq_r32(port->membase + LTQ_ASC_FSTAT)
593                         & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
594         } while (fifofree == 0);
595         ltq_w8(ch, port->membase + LTQ_ASC_TBUF);
596 }
597
598
599 static void
600 lqasc_console_write(struct console *co, const char *s, u_int count)
601 {
602         struct ltq_uart_port *ltq_port;
603         struct uart_port *port;
604         unsigned long flags;
605
606         if (co->index >= MAXPORTS)
607                 return;
608
609         ltq_port = lqasc_port[co->index];
610         if (!ltq_port)
611                 return;
612
613         port = &ltq_port->port;
614
615         spin_lock_irqsave(&ltq_asc_lock, flags);
616         uart_console_write(port, s, count, lqasc_console_putchar);
617         spin_unlock_irqrestore(&ltq_asc_lock, flags);
618 }
619
620 static int __init
621 lqasc_console_setup(struct console *co, char *options)
622 {
623         struct ltq_uart_port *ltq_port;
624         struct uart_port *port;
625         int baud = 115200;
626         int bits = 8;
627         int parity = 'n';
628         int flow = 'n';
629
630         if (co->index >= MAXPORTS)
631                 return -ENODEV;
632
633         ltq_port = lqasc_port[co->index];
634         if (!ltq_port)
635                 return -ENODEV;
636
637         port = &ltq_port->port;
638
639         port->uartclk = clk_get_rate(ltq_port->fpiclk);
640
641         if (options)
642                 uart_parse_options(options, &baud, &parity, &bits, &flow);
643         return uart_set_options(port, co, baud, parity, bits, flow);
644 }
645
646 static struct console lqasc_console = {
647         .name =         "ttyLTQ",
648         .write =        lqasc_console_write,
649         .device =       uart_console_device,
650         .setup =        lqasc_console_setup,
651         .flags =        CON_PRINTBUFFER,
652         .index =        -1,
653         .data =         &lqasc_reg,
654 };
655
656 static int __init
657 lqasc_console_init(void)
658 {
659         register_console(&lqasc_console);
660         return 0;
661 }
662 console_initcall(lqasc_console_init);
663
664 static struct uart_driver lqasc_reg = {
665         .owner =        THIS_MODULE,
666         .driver_name =  DRVNAME,
667         .dev_name =     "ttyLTQ",
668         .major =        0,
669         .minor =        0,
670         .nr =           MAXPORTS,
671         .cons =         &lqasc_console,
672 };
673
674 static int __init
675 lqasc_probe(struct platform_device *pdev)
676 {
677         struct device_node *node = pdev->dev.of_node;
678         struct ltq_uart_port *ltq_port;
679         struct uart_port *port;
680         struct resource *mmres, irqres[3];
681         int line = 0;
682         int ret;
683
684         mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
685         ret = of_irq_to_resource_table(node, irqres, 3);
686         if (!mmres || (ret != 3)) {
687                 dev_err(&pdev->dev,
688                         "failed to get memory/irq for serial port\n");
689                 return -ENODEV;
690         }
691
692         /* check if this is the console port */
693         if (mmres->start != CPHYSADDR(LTQ_EARLY_ASC))
694                 line = 1;
695
696         if (lqasc_port[line]) {
697                 dev_err(&pdev->dev, "port %d already allocated\n", line);
698                 return -EBUSY;
699         }
700
701         ltq_port = devm_kzalloc(&pdev->dev, sizeof(struct ltq_uart_port),
702                         GFP_KERNEL);
703         if (!ltq_port)
704                 return -ENOMEM;
705
706         port = &ltq_port->port;
707
708         port->iotype    = SERIAL_IO_MEM;
709         port->flags     = ASYNC_BOOT_AUTOCONF | UPF_IOREMAP;
710         port->ops       = &lqasc_pops;
711         port->fifosize  = 16;
712         port->type      = PORT_LTQ_ASC,
713         port->line      = line;
714         port->dev       = &pdev->dev;
715         /* unused, just to be backward-compatible */
716         port->irq       = irqres[0].start;
717         port->mapbase   = mmres->start;
718
719         ltq_port->fpiclk = clk_get_fpi();
720         if (IS_ERR(ltq_port->fpiclk)) {
721                 pr_err("failed to get fpi clk\n");
722                 return -ENOENT;
723         }
724
725         /* not all asc ports have clock gates, lets ignore the return code */
726         ltq_port->clk = clk_get(&pdev->dev, NULL);
727
728         ltq_port->tx_irq = irqres[0].start;
729         ltq_port->rx_irq = irqres[1].start;
730         ltq_port->err_irq = irqres[2].start;
731
732         lqasc_port[line] = ltq_port;
733         platform_set_drvdata(pdev, ltq_port);
734
735         ret = uart_add_one_port(&lqasc_reg, port);
736
737         return ret;
738 }
739
740 static const struct of_device_id ltq_asc_match[] = {
741         { .compatible = DRVNAME },
742         {},
743 };
744 MODULE_DEVICE_TABLE(of, ltq_asc_match);
745
746 static struct platform_driver lqasc_driver = {
747         .driver         = {
748                 .name   = DRVNAME,
749                 .owner  = THIS_MODULE,
750                 .of_match_table = ltq_asc_match,
751         },
752 };
753
754 int __init
755 init_lqasc(void)
756 {
757         int ret;
758
759         ret = uart_register_driver(&lqasc_reg);
760         if (ret != 0)
761                 return ret;
762
763         ret = platform_driver_probe(&lqasc_driver, lqasc_probe);
764         if (ret != 0)
765                 uart_unregister_driver(&lqasc_reg);
766
767         return ret;
768 }
769
770 module_init(init_lqasc);
771
772 MODULE_DESCRIPTION("Lantiq serial port driver");
773 MODULE_LICENSE("GPL");