Root/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
113static void lqasc_tx_chars(struct uart_port *port);
114static struct ltq_uart_port *lqasc_port[MAXPORTS];
115static struct uart_driver lqasc_reg;
116static DEFINE_SPINLOCK(ltq_asc_lock);
117
118struct 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
129static inline struct
130ltq_uart_port *to_ltq_uart_port(struct uart_port *port)
131{
132    return container_of(port, struct ltq_uart_port, port);
133}
134
135static void
136lqasc_stop_tx(struct uart_port *port)
137{
138    return;
139}
140
141static void
142lqasc_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
151static void
152lqasc_stop_rx(struct uart_port *port)
153{
154    ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
155}
156
157static void
158lqasc_enable_ms(struct uart_port *port)
159{
160}
161
162static int
163lqasc_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
223static void
224lqasc_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
254static irqreturn_t
255lqasc_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
266static irqreturn_t
267lqasc_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
279static irqreturn_t
280lqasc_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
291static unsigned int
292lqasc_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
299static unsigned int
300lqasc_get_mctrl(struct uart_port *port)
301{
302    return TIOCM_CTS | TIOCM_CAR | TIOCM_DSR;
303}
304
305static void
306lqasc_set_mctrl(struct uart_port *port, u_int mctrl)
307{
308}
309
310static void
311lqasc_break_ctl(struct uart_port *port, int break_state)
312{
313}
314
315static int
316lqasc_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
369err2:
370    free_irq(ltq_port->rx_irq, port);
371err1:
372    free_irq(ltq_port->tx_irq, port);
373    return retval;
374}
375
376static void
377lqasc_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
393static void
394lqasc_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
493static const char*
494lqasc_type(struct uart_port *port)
495{
496    if (port->type == PORT_LTQ_ASC)
497        return DRVNAME;
498    else
499        return NULL;
500}
501
502static void
503lqasc_release_port(struct uart_port *port)
504{
505    if (port->flags & UPF_IOREMAP) {
506        iounmap(port->membase);
507        port->membase = NULL;
508    }
509}
510
511static int
512lqasc_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
541static void
542lqasc_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
550static int
551lqasc_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
564static 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
583static void
584lqasc_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
599static void
600lqasc_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
620static int __init
621lqasc_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
646static 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
656static int __init
657lqasc_console_init(void)
658{
659    register_console(&lqasc_console);
660    return 0;
661}
662console_initcall(lqasc_console_init);
663
664static 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
674static int __init
675lqasc_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
740static const struct of_device_id ltq_asc_match[] = {
741    { .compatible = DRVNAME },
742    {},
743};
744MODULE_DEVICE_TABLE(of, ltq_asc_match);
745
746static struct platform_driver lqasc_driver = {
747    .driver = {
748        .name = DRVNAME,
749        .owner = THIS_MODULE,
750        .of_match_table = ltq_asc_match,
751    },
752};
753
754int __init
755init_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
770module_init(init_lqasc);
771
772MODULE_DESCRIPTION("Lantiq serial port driver");
773MODULE_LICENSE("GPL");
774

Archive Download this file



interactive