Root/target/linux/ubicom32/files/drivers/serial/ubi32_serdes.c

1/*
2 * drivers/serial/ubi32_serdes.c
3 * Ubicom32 On-Chip Serial Driver
4 *
5 * (C) Copyright 2009, Ubicom, Inc.
6 *
7 * This file is part of the Ubicom32 Linux Kernel Port.
8 *
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with the Ubicom32 Linux Kernel Port. If not,
21 * see <http://www.gnu.org/licenses/>.
22 *
23 * Ubicom32 implementation derived from (with many thanks):
24 * arch/m68knommu
25 * arch/blackfin
26 * arch/parisc
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/platform_device.h>
34#include <linux/tty.h>
35#include <linux/tty_flip.h>
36#include <linux/serial_core.h>
37
38#include <asm/ip5000.h>
39#include <asm/ubicom32suart.h>
40
41
42#define SERIAL_UBICOM_PIN_RXD (1 << 0)
43#define SERIAL_UBICOM_PIN_TXD (1 << 6)
44#define SERIAL_UBICOM_CTL0 0x8b300000
45#define SERIAL_UBICOM_CTL1 0x00000009
46
47#define SERIAL_UBICOM_DATA_BIT 8 /* Fixed parameter - do not change */
48#define SERIAL_UBICOM_PAR_BIT 0 /* Fixed parameter - do not change */
49#define SERIAL_UBICOM_STOP_BIT 1 /* Fixed parameter - do not change */
50
51/* UART name and device definitions */
52#define UBI32_SERDES_NAME "ttyUS" // XXX
53#define UBI32_SERDES_MAJOR 206 // XXX
54#define UBI32_SERDES_MINOR 64 // XXX
55
56#define PORT_UBI32_SERDES 1234
57#define NR_PORTS 1
58
59struct uart_port ubi32_serdes_ports[NR_PORTS];
60
61struct ubi32_serdes_resource {
62    void *uart_base_addr;
63    int uart_irq;
64    int uart_clock;
65} ubi32_serdes_resource[NR_PORTS] = {
66    /*
67     * Get params from kernel command line (required for early printk)
68     * or from platform resources.
69     */
70    {0, 0, 0}
71};
72
73/*
74 * Can get overridden by 'serdes=' kernel command line.
75 */
76static int ubi32_serdes_default_baud_rate = 115200;
77
78
79#define IO_PORT(port) ((struct ubicom32_io_port *)port->membase)
80#define IO_PORT_INT_STATUS(port) (IO_PORT(port)->int_status)
81#define IO_PORT_INT_MASK(port) (IO_PORT(port)->int_mask)
82#define IO_PORT_INT_CLR(port) (IO_PORT(port)->int_clr)
83
84
85/*
86 * ubi32_serdes_get_char()
87 */
88static u8_t ubi32_serdes_get_char(struct ubicom32_io_port *io_port)
89{
90    /*
91     * Read from hardware (forced 32-bit atomic read).
92     */
93    u32_t data = 0;
94
95    if ( io_port ) {
96        io_port->int_clr = IO_PORTX_INT_SERDES_RXBF;
97        asm volatile (
98            "move.4 %0, %1 \n\t"
99            : "=r" (data)
100            : "m" (*(u32_t *)&(io_port->rx_fifo))
101            );
102    }
103
104    return (u8_t)(data & 0x000000ff);
105}
106
107/*
108 * ubi32_serdes_put_char()
109 */
110static void ubi32_serdes_put_char(struct ubicom32_io_port *io_port, u8_t c)
111{
112    u32_t data = 0x0000fe00 | (c << 1);
113
114    if ( io_port ) {
115        /*
116         * Fixed data format:
117         * [LSB]1 start bit - 8 data bits - no parity - 1 stop bit[MSB]
118         */
119        io_port->int_clr = IO_PORTX_INT_SERDES_TXBE;
120        io_port->ctl2 = data;
121        io_port->int_set = IO_PORTX_INT_SERDES_TXBUF_VALID;
122    }
123}
124
125static void ubi32_serdes_hw_init(struct uart_port *port, int baud)
126{
127    struct ubicom32_io_port *io_port = IO_PORT(port);
128
129    if ( io_port ) {
130        /*
131         * Put port functions 1-4 into reset state.
132         * Function 0 (GPIO) does not need or have a reset bit.
133         *
134         * Select SERDES function for restart below.
135         */
136        io_port->function =
137            IO_FUNC_FUNCTION_RESET(1) | IO_FUNC_FUNCTION_RESET(2) |
138            IO_FUNC_FUNCTION_RESET(3) | IO_FUNC_FUNCTION_RESET(4) |
139            IO_PORTX_FUNC_SERDES;
140
141        /*
142         * Configure SERDES baudrate
143         */
144        if ( baud == 0 ) {
145            baud = ubi32_serdes_default_baud_rate;
146        }
147
148        io_port->ctl0 =
149            SERIAL_UBICOM_CTL0 |
150            ((port->uartclk / (16 * baud)) - 1);
151
152        io_port->ctl1 =
153            SERIAL_UBICOM_CTL1;
154
155        /*
156         * don't interrupt until startup and start_tx
157         */
158        io_port->int_mask = 0;
159
160        /*
161         * Set TXD pin output, RXD input and prevent GPIO
162         * override on the TXD & RXD pins
163         */
164        io_port->gpio_ctl &= ~SERIAL_UBICOM_PIN_RXD;
165        io_port->gpio_ctl |= SERIAL_UBICOM_PIN_TXD;
166        io_port->gpio_mask &= ~(SERIAL_UBICOM_PIN_RXD | SERIAL_UBICOM_PIN_TXD);
167
168        /*
169         * Restart (un-reset) the port's SERDES function.
170         */
171        io_port->function &= ~(IO_FUNC_FUNCTION_RESET(IO_PORTX_FUNC_SERDES));
172    }
173}
174
175#define ULITE_STATUS_RXVALID IO_PORTX_INT_SERDES_RXBF
176#define ULITE_STATUS_OVERRUN 0
177#define ULITE_STATUS_FRAME 0
178#define ULITE_STATUS_PARITY 0
179#define ULITE_STATUS_TXEMPTY IO_PORTX_INT_SERDES_TXBE
180#define ULITE_STATUS_TXFULL 0
181
182static int ubi32_serdes_receive(struct uart_port *port, int stat)
183{
184    struct tty_struct *tty = port->info->port.tty;
185    unsigned char ch = 0;
186    char flag = TTY_NORMAL;
187
188    if ((stat & (ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
189             | ULITE_STATUS_FRAME)) == 0)
190        return 0;
191
192    /* stats */
193    if (stat & ULITE_STATUS_RXVALID) {
194        port->icount.rx++;
195        ch = ubi32_serdes_get_char((struct ubicom32_io_port *)port->membase);
196
197        if (stat & ULITE_STATUS_PARITY)
198            port->icount.parity++;
199    }
200
201    if (stat & ULITE_STATUS_OVERRUN)
202        port->icount.overrun++;
203
204    if (stat & ULITE_STATUS_FRAME)
205        port->icount.frame++;
206
207
208    /* drop byte with parity error if IGNPAR specificed */
209    if (stat & port->ignore_status_mask & ULITE_STATUS_PARITY)
210        stat &= ~ULITE_STATUS_RXVALID;
211
212    stat &= port->read_status_mask;
213
214    if (stat & ULITE_STATUS_PARITY)
215        flag = TTY_PARITY;
216
217    stat &= ~port->ignore_status_mask;
218
219    if (stat & ULITE_STATUS_RXVALID)
220        tty_insert_flip_char(tty, ch, flag);
221
222    if (stat & ULITE_STATUS_FRAME)
223        tty_insert_flip_char(tty, 0, TTY_FRAME);
224
225    if (stat & ULITE_STATUS_OVERRUN)
226        tty_insert_flip_char(tty, 0, TTY_OVERRUN);
227
228    return 1;
229}
230
231/*
232 * interrupts are disabled on entry
233 */
234static void ubi32_serdes_stop_tx(struct uart_port *port)
235{
236    IO_PORT_INT_MASK(port) = IO_PORT_INT_MASK(port) & ~IO_PORTX_INT_SERDES_TXBE;
237}
238
239static int ubi32_serdes_transmit(struct uart_port *port, int stat)
240{
241    struct circ_buf *xmit = &port->info->xmit;
242
243    if (!(stat & IO_PORTX_INT_SERDES_TXBE))
244        return 0;
245
246    if (port->x_char) {
247        ubi32_serdes_put_char(IO_PORT(port), port->x_char);
248        port->x_char = 0;
249        port->icount.tx++;
250        return 1;
251    }
252
253    if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
254        ubi32_serdes_stop_tx(port);
255        return 0;
256    }
257
258    ubi32_serdes_put_char(IO_PORT(port), xmit->buf[xmit->tail]);
259    xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
260    port->icount.tx++;
261
262    /* wake up */
263    if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
264        uart_write_wakeup(port);
265
266    if (uart_circ_empty(xmit))
267        ubi32_serdes_stop_tx(port);
268
269    return 1;
270}
271
272/*
273 * port is locked and interrupts are disabled
274 */
275static void ubi32_serdes_start_tx(struct uart_port *port)
276{
277    IO_PORT_INT_MASK(port) = IO_PORT_INT_MASK(port) | IO_PORTX_INT_SERDES_TXBE;
278    ubi32_serdes_transmit(port, IO_PORT_INT_STATUS(port));
279}
280
281/*
282 * Interrupts are enabled
283 */
284static void ubi32_serdes_stop_rx(struct uart_port *port)
285{
286    /* don't forward any more data (like !CREAD) */
287    port->ignore_status_mask = IO_PORTX_INT_SERDES_RXBF;
288}
289
290/*
291 * Set the modem control timer to fire immediately.
292 */
293static void ubi32_serdes_enable_ms(struct uart_port *port)
294{
295    /* N/A */
296}
297
298static irqreturn_t ubi32_serdes_isr(int irq, void *dev_id)
299{
300    struct uart_port *port = dev_id;
301    int busy;
302
303    spin_lock(&port->lock);
304
305    do {
306        int stat = IO_PORT_INT_STATUS(port);
307        busy = ubi32_serdes_receive(port, stat);
308        busy |= ubi32_serdes_transmit(port, stat);
309    } while (busy);
310
311    tty_flip_buffer_push(port->info->port.tty);
312
313    spin_unlock(&port->lock);
314
315    return IRQ_HANDLED;
316}
317
318/*
319 * Return TIOCSER_TEMT when transmitter is not busy.
320 */
321static unsigned int ubi32_serdes_tx_empty(struct uart_port *port)
322{
323    unsigned long flags;
324    unsigned int ret;
325
326    spin_lock_irqsave(&port->lock, flags);
327    ret = IO_PORT_INT_STATUS(port);
328    spin_unlock_irqrestore(&port->lock, flags);
329
330    return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
331}
332
333static unsigned int ubi32_serdes_get_mctrl(struct uart_port *port)
334{
335    return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
336}
337
338static void ubi32_serdes_set_mctrl(struct uart_port *port, unsigned int mctrl)
339{
340    /* N/A */
341}
342
343/*
344 * Interrupts are always disabled.
345 */
346static void ubi32_serdes_break_ctl(struct uart_port *port, int break_state)
347{
348    /* N/A */
349}
350
351static int ubi32_serdes_startup(struct uart_port *port)
352{
353    if (request_irq(port->irq, ubi32_serdes_isr, IRQF_DISABLED,
354         "UBI32_SERDES", port)) {
355        printk(KERN_NOTICE "Unable to attach port interrupt\n");
356        return -EBUSY;
357    }
358
359    IO_PORT_INT_CLR(port) = IO_PORTX_INT_SERDES_RXBF;
360    IO_PORT_INT_MASK(port) = IO_PORTX_INT_SERDES_RXBF;
361    return 0;
362}
363
364static void ubi32_serdes_shutdown(struct uart_port *port)
365{
366    struct ubi32_serdes_port *uart = (struct ubi32_serdes_port *)port;
367
368    IO_PORT_INT_MASK(port) = 0;
369    free_irq(port->irq, uart);
370}
371
372static void
373ubi32_serdes_set_termios(struct uart_port *port, struct ktermios *termios,
374           struct ktermios *old)
375{
376    unsigned long flags;
377    unsigned int baud;
378
379    spin_lock_irqsave(&port->lock, flags);
380
381    port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
382        | ULITE_STATUS_TXFULL;
383
384    if (termios->c_iflag & INPCK)
385        port->read_status_mask |=
386            ULITE_STATUS_PARITY | ULITE_STATUS_FRAME;
387
388    port->ignore_status_mask = 0;
389    if (termios->c_iflag & IGNPAR)
390        port->ignore_status_mask |= ULITE_STATUS_PARITY
391            | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
392
393    /* ignore all characters if CREAD is not set */
394    if ((termios->c_cflag & CREAD) == 0)
395        port->ignore_status_mask |=
396            ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY
397            | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
398
399    /* update timeout */
400    baud = uart_get_baud_rate(port, termios, old, 0, 460800);
401    uart_update_timeout(port, termios->c_cflag, baud);
402
403    IO_PORT(port)->ctl0 = SERIAL_UBICOM_CTL0 |
404            ((port->uartclk / (16 * baud)) - 1);
405
406    spin_unlock_irqrestore(&port->lock, flags);
407}
408
409static const char *ubi32_serdes_type(struct uart_port *port)
410{
411    return port->type == PORT_UBI32_SERDES ? "UBI32_SERDES" : NULL;
412}
413
414/*
415 * Release the memory region(s) being used by 'port'.
416 */
417static void ubi32_serdes_release_port(struct uart_port *port)
418{
419}
420
421/*
422 * Request the memory region(s) being used by 'port'.
423 */
424static int ubi32_serdes_request_port(struct uart_port *port)
425{
426    return 0;
427}
428
429/*
430 * Configure/autoconfigure the port.
431 */
432static void ubi32_serdes_config_port(struct uart_port *port, int flags)
433{
434    if (flags & UART_CONFIG_TYPE &&
435        ubi32_serdes_request_port(port) == 0)
436        port->type = PORT_UBI32_SERDES;
437}
438
439/*
440 * Verify the new serial_struct (for TIOCSSERIAL).
441 * The only change we allow are to the flags and type, and
442 * even then only between PORT_UBI32_SERDES and PORT_UNKNOWN
443 */
444static int
445ubi32_serdes_verify_port(struct uart_port *port, struct serial_struct *ser)
446{
447    return 0;
448}
449
450static struct uart_ops ubi32_serdes_pops = {
451    .tx_empty = ubi32_serdes_tx_empty,
452    .set_mctrl = ubi32_serdes_set_mctrl,
453    .get_mctrl = ubi32_serdes_get_mctrl,
454    .stop_tx = ubi32_serdes_stop_tx,
455    .start_tx = ubi32_serdes_start_tx,
456    .stop_rx = ubi32_serdes_stop_rx,
457    .enable_ms = ubi32_serdes_enable_ms,
458    .break_ctl = ubi32_serdes_break_ctl,
459    .startup = ubi32_serdes_startup,
460    .shutdown = ubi32_serdes_shutdown,
461    .set_termios = ubi32_serdes_set_termios,
462    .type = ubi32_serdes_type,
463    .release_port = ubi32_serdes_release_port,
464    .request_port = ubi32_serdes_request_port,
465    .config_port = ubi32_serdes_config_port,
466    .verify_port = ubi32_serdes_verify_port,
467};
468
469static void __init ubi32_serdes_init_ports(void)
470{
471    int i;
472
473    for (i = 0; i < NR_PORTS; i++) {
474        ubi32_serdes_ports[i].uartclk = ubi32_serdes_resource[i].uart_clock;
475        ubi32_serdes_ports[i].ops = &ubi32_serdes_pops;
476        ubi32_serdes_ports[i].line = i;
477        ubi32_serdes_ports[i].iotype = UPIO_MEM;
478        ubi32_serdes_ports[i].membase =
479            (void __iomem *)ubi32_serdes_resource[i].uart_base_addr;
480        ubi32_serdes_ports[i].mapbase =
481            (resource_size_t)ubi32_serdes_resource[i].uart_base_addr;
482        ubi32_serdes_ports[i].irq =
483            ubi32_serdes_resource[i].uart_irq;
484        ubi32_serdes_ports[i].flags = UPF_BOOT_AUTOCONF;
485
486        ubi32_serdes_hw_init(&ubi32_serdes_ports[i], 0);
487    }
488
489}
490
491#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
492/*
493 * If the port was already initialised (eg, by a boot loader),
494 * try to determine the current setup.
495 */
496static void __init
497ubi32_serdes_console_get_options(struct uart_port *port, int *baud)
498{
499    u32 round_to = 1200;
500    u32 real_baud;
501
502    /*
503     * We might get called before platform init and with no
504     * kernel command line options, so port might be NULL.
505     */
506    *baud = ubi32_serdes_default_baud_rate;;
507    if ( IO_PORT(port) == 0 )
508        return;
509
510    real_baud = port->uartclk
511        / (16 * ((IO_PORT(port)->ctl0 & ~SERIAL_UBICOM_CTL0) + 1));
512
513    *baud = ((real_baud + round_to - 1) / round_to) * round_to;
514
515    pr_debug("%s:baud = %d, real_baud = %d\n", __FUNCTION__, *baud, real_baud);
516}
517#endif
518
519#if defined(CONFIG_SERIAL_UBI32_SERDES_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
520static struct uart_driver ubi32_serdes_reg;
521
522static int __init
523ubi32_serdes_console_setup(struct console *co, char *options)
524{
525    struct uart_port *port;
526#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
527    int baud = ubi32_serdes_default_baud_rate;
528    int bits = 8;
529    int parity = 'n';
530    int flow = 'n';
531#endif
532
533    /*
534     * Check whether an invalid uart number has been specified, and
535     * if so, search for the first available port that does have
536     * console support.
537     */
538    if (co->index == -1 || co->index >= NR_PORTS)
539        co->index = 0;
540    port = &ubi32_serdes_ports[co->index];
541
542#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
543    if (options) {
544        uart_parse_options(options, &baud, &parity, &bits, &flow);
545        ubi32_serdes_hw_init(port, baud);
546    }
547    else
548        ubi32_serdes_console_get_options(port, &baud);
549
550    return uart_set_options(port, co, baud, parity, bits, flow);
551#else
552    return 0;
553#endif
554}
555#endif /* defined (CONFIG_SERIAL_UBI32_SERDES_CONSOLE) ||
556                 defined (CONFIG_EARLY_PRINTK) */
557
558#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
559static void
560ubi32_serdes_console_putchar(struct uart_port *port, int ch)
561{
562    if ( IO_PORT(port) ) {
563        while (!(IO_PORT_INT_STATUS(port) & IO_PORTX_INT_SERDES_TXBE))
564            barrier();
565        ubi32_serdes_put_char(IO_PORT(port), ch);
566    }
567}
568
569/*
570 * Interrupts are disabled on entering
571 */
572static void
573ubi32_serdes_console_write(struct console *co, const char *s, unsigned int count)
574{
575    struct uart_port *port = &ubi32_serdes_ports[co->index];
576    unsigned long flags = 0;
577
578    spin_lock_irqsave(&port->lock, flags);
579    uart_console_write(port, s, count, ubi32_serdes_console_putchar);
580    spin_unlock_irqrestore(&port->lock, flags);
581
582}
583
584static struct console ubi32_serdes_console = {
585    .name = UBI32_SERDES_NAME,
586    .write = ubi32_serdes_console_write,
587    .device = uart_console_device,
588    .setup = ubi32_serdes_console_setup,
589    .flags = CON_PRINTBUFFER,
590    .index = -1,
591    .data = &ubi32_serdes_reg,
592};
593
594static int __init ubi32_serdes_console_init(void)
595{
596    ubi32_serdes_init_ports();
597    register_console(&ubi32_serdes_console);
598    return 0;
599}
600console_initcall(ubi32_serdes_console_init);
601
602#define UBI32_SERDES_CONSOLE &ubi32_serdes_console
603#else
604#define UBI32_SERDES_CONSOLE NULL
605#endif /* CONFIG_SERIAL_UBI32_SERDES_CONSOLE */
606
607
608#ifdef CONFIG_EARLY_PRINTK
609static __init void ubi32_serdes_early_putc(struct uart_port *port, int ch)
610{
611    unsigned timeout = 0xffff;
612
613    while ((!(IO_PORT_INT_STATUS(port) & IO_PORTX_INT_SERDES_TXBE)) && --timeout)
614        cpu_relax();
615    ubi32_serdes_put_char(IO_PORT(port), ch);
616}
617
618static __init void ubi32_serdes_early_write(struct console *con, const char *s,
619                    unsigned int n)
620{
621    struct uart_port *port = &ubi32_serdes_ports[con->index];
622    unsigned int i;
623
624    for (i = 0; i < n; i++, s++) {
625        if (*s == '\n')
626            ubi32_serdes_early_putc(port, '\r');
627        ubi32_serdes_early_putc(port, *s);
628    }
629}
630
631static struct __init console ubi32_serdes_early_console = {
632    .name = "early_US",
633    .write = ubi32_serdes_early_write,
634    .device = uart_console_device,
635    .flags = CON_PRINTBUFFER,
636    .setup = ubi32_serdes_console_setup,
637    .index = -1,
638    .data = &ubi32_serdes_reg,
639};
640
641/*
642 * XXX Unused in our driver. Need to find out what the termios initialization is good/needed for.
643 */
644struct console __init *ubi32_serdes_early_init(unsigned int port_index,
645                        unsigned int cflag)
646{
647    struct uart_port *uart;
648    struct ktermios t;
649
650    if (port_index == -1 || port_index >= NR_PORTS)
651        port_index = 0;
652    ubi32_serdes_init_ports();
653    ubi32_serdes_early_console.index = port_index;
654    uart = &ubi32_serdes_ports[port_index];
655    t.c_cflag = cflag;
656    t.c_iflag = 0;
657    t.c_oflag = 0;
658    t.c_lflag = ICANON;
659    t.c_line = port_index;
660    ubi32_serdes_set_termios(uart, &t, &t);
661    return &ubi32_serdes_early_console;
662}
663
664#endif /* CONFIG_SERIAL_UBI32_SERDES_CONSOLE */
665
666static struct uart_driver ubi32_serdes_reg = {
667    .owner = THIS_MODULE,
668    .driver_name = "ubi32_serdes",
669    .dev_name = UBI32_SERDES_NAME,
670    .major = UBI32_SERDES_MAJOR,
671    .minor = UBI32_SERDES_MINOR,
672    .nr = NR_PORTS,
673    .cons = UBI32_SERDES_CONSOLE,
674};
675
676static int ubi32_serdes_suspend(struct platform_device *dev, pm_message_t state)
677{
678    struct uart_port *port = platform_get_drvdata(dev);
679
680    if (port)
681        uart_suspend_port(&ubi32_serdes_reg, port);
682
683    return 0;
684}
685
686static int ubi32_serdes_resume(struct platform_device *dev)
687{
688    struct uart_port *port = platform_get_drvdata(dev);
689
690    if (port)
691        uart_resume_port(&ubi32_serdes_reg, port);
692
693    return 0;
694}
695
696static int ubi32_serdes_probe(struct platform_device *dev)
697{
698    struct resource *res = dev->resource;
699    int i;
700
701    for (i = 0; i < dev->num_resources; i++, res++) {
702        if (res->flags & IORESOURCE_MEM) {
703            ubi32_serdes_resource[0].uart_base_addr = (void *) res->start;
704        }
705        else if (res->flags & IORESOURCE_IRQ) {
706            ubi32_serdes_resource[0].uart_irq = res->start;
707        }
708        else if (res->flags & UBICOM32_SUART_IORESOURCE_CLOCK) {
709            ubi32_serdes_resource[0].uart_clock = res->start;
710        }
711    }
712
713    ubi32_serdes_init_ports();
714
715    return 0;
716}
717
718static int ubi32_serdes_remove(struct platform_device *pdev)
719{
720    struct uart_port *port = platform_get_drvdata(pdev);
721
722    platform_set_drvdata(pdev, NULL);
723
724    if (port)
725        uart_remove_one_port(&ubi32_serdes_reg, port);
726
727    return 0;
728}
729
730static struct platform_driver ubi32_serdes_driver = {
731    .remove = ubi32_serdes_remove,
732    .suspend = ubi32_serdes_suspend,
733    .resume = ubi32_serdes_resume,
734    .driver = {
735        .name = "ubicom32suart",
736        .owner = THIS_MODULE,
737    },
738};
739
740
741#ifndef MODULE
742/*
743 * Called at boot time.
744 *
745 * You can specify IO base, IRQ, and clock for the serdes serial port
746 * using kernel command line "serdes=0xiobase,irq,clock". Values
747 * specified will be overwritten by platform device data, if present.
748 */
749static int __init ubi32_serdes_setup(char *str)
750{
751#define N_PARMS (4+1)
752    int ints[N_PARMS];
753    int i;
754
755    str = get_options(str, ARRAY_SIZE(ints), ints);
756
757    for (i = 0; i < N_PARMS; i++) {
758        if (i < ints[0]) {
759            if (i == 0) {
760                ubi32_serdes_resource[0].uart_base_addr = (void *) ints[i+1];
761            }
762            else if (i == 1) {
763                ubi32_serdes_resource[0].uart_irq = ints[i+1];
764            }
765            else if (i == 2) {
766                ubi32_serdes_resource[0].uart_clock = ints[i+1];
767            }
768            else if (i == 3) {
769                ubi32_serdes_default_baud_rate = ints[i+1];
770            }
771        }
772    }
773    return 1;
774}
775
776__setup("serdes=", ubi32_serdes_setup);
777#endif
778
779static int __init ubi32_serdes_init(void)
780{
781    int ret;
782
783    pr_info("Serial: Ubicom32 serdes uart serial driver\n");
784
785    ret = platform_driver_probe(&ubi32_serdes_driver, ubi32_serdes_probe);
786    if (ret != 0) {
787        printk(KERN_INFO "serdes platform_driver_probe() failed: %d\n", ret);
788        return ret;
789    }
790
791    ubi32_serdes_init_ports();
792
793    ret = uart_register_driver(&ubi32_serdes_reg);
794    if ( ret == 0 ) {
795        ret = uart_add_one_port(&ubi32_serdes_reg, &ubi32_serdes_ports[0]);
796        if ( ret != 0 ) {
797            uart_unregister_driver(&ubi32_serdes_reg);
798        }
799    }
800
801    return ret;
802}
803
804static void __exit ubi32_serdes_exit(void)
805{
806    platform_driver_unregister(&ubi32_serdes_driver);
807    uart_unregister_driver(&ubi32_serdes_reg);
808}
809
810module_init(ubi32_serdes_init);
811module_exit(ubi32_serdes_exit);
812
813MODULE_AUTHOR("Rainer Keller <rkeller@ubicom.com>");
814MODULE_DESCRIPTION("Ubicom generic serial port driver");
815MODULE_LICENSE("GPL");
816MODULE_ALIAS_CHARDEV_MAJOR(UBI32_SERDES_MAJOR);
817MODULE_ALIAS("platform:ubi32_serdes");
818

Archive Download this file



interactive