serial: clps711x: Give a chance to perform useful tasks during wait loop
[deliverable/linux.git] / drivers / tty / serial / clps711x.c
CommitLineData
1da177e4 1/*
1da177e4
LT
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.
1da177e4 13 */
1da177e4
LT
14
15#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
16#define SUPPORT_SYSRQ
17#endif
18
19#include <linux/module.h>
1da177e4 20#include <linux/device.h>
a1c25f2b 21#include <linux/console.h>
1da177e4
LT
22#include <linux/serial_core.h>
23#include <linux/serial.h>
c08f0153 24#include <linux/clk.h>
bc000245 25#include <linux/io.h>
a1c25f2b
AS
26#include <linux/tty.h>
27#include <linux/tty_flip.h>
28#include <linux/ioport.h>
bc000245 29#include <linux/of.h>
95113728 30#include <linux/platform_device.h>
bc000245 31#include <linux/regmap.h>
1da177e4 32
bc000245
AS
33#include <linux/mfd/syscon.h>
34#include <linux/mfd/syscon/clps711x.h>
1da177e4 35
bc000245 36#define UART_CLPS711X_DEVNAME "ttyCL"
117d5d42
AS
37#define UART_CLPS711X_NR 2
38#define UART_CLPS711X_MAJOR 204
39#define UART_CLPS711X_MINOR 40
95113728 40
bc000245
AS
41#define UARTDR_OFFSET (0x00)
42#define UBRLCR_OFFSET (0x40)
43
44#define UARTDR_FRMERR (1 << 8)
45#define UARTDR_PARERR (1 << 9)
46#define UARTDR_OVERR (1 << 10)
47
48#define UBRLCR_BAUD_MASK ((1 << 12) - 1)
49#define UBRLCR_BREAK (1 << 12)
50#define UBRLCR_PRTEN (1 << 13)
51#define UBRLCR_EVENPRT (1 << 14)
52#define UBRLCR_XSTOP (1 << 15)
53#define UBRLCR_FIFOEN (1 << 16)
54#define UBRLCR_WRDLEN5 (0 << 17)
55#define UBRLCR_WRDLEN6 (1 << 17)
56#define UBRLCR_WRDLEN7 (2 << 17)
57#define UBRLCR_WRDLEN8 (3 << 17)
58#define UBRLCR_WRDLEN_MASK (3 << 17)
1da177e4 59
117d5d42 60struct clps711x_port {
bc000245
AS
61 struct uart_port port;
62 unsigned int tx_enabled;
63 int rx_irq;
64 struct regmap *syscon;
65 bool use_ms;
66};
67
68static struct uart_driver clps711x_uart = {
69 .owner = THIS_MODULE,
70 .driver_name = UART_CLPS711X_DEVNAME,
71 .dev_name = UART_CLPS711X_DEVNAME,
72 .major = UART_CLPS711X_MAJOR,
73 .minor = UART_CLPS711X_MINOR,
74 .nr = UART_CLPS711X_NR,
117d5d42
AS
75};
76
a1c25f2b 77static void uart_clps711x_stop_tx(struct uart_port *port)
1da177e4 78{
3c7e9eb1
AS
79 struct clps711x_port *s = dev_get_drvdata(port->dev);
80
bc000245
AS
81 if (s->tx_enabled) {
82 disable_irq(port->irq);
83 s->tx_enabled = 0;
1da177e4
LT
84 }
85}
86
a1c25f2b 87static void uart_clps711x_start_tx(struct uart_port *port)
1da177e4 88{
3c7e9eb1
AS
89 struct clps711x_port *s = dev_get_drvdata(port->dev);
90
bc000245
AS
91 if (!s->tx_enabled) {
92 s->tx_enabled = 1;
93 enable_irq(port->irq);
1da177e4
LT
94 }
95}
96
135cc790 97static irqreturn_t uart_clps711x_int_rx(int irq, void *dev_id)
1da177e4
LT
98{
99 struct uart_port *port = dev_id;
bc000245
AS
100 struct clps711x_port *s = dev_get_drvdata(port->dev);
101 unsigned int status, flg;
bc000245 102 u16 ch;
1da177e4 103
f27de95c 104 for (;;) {
093a9e2a
AS
105 u32 sysflg = 0;
106
bc000245
AS
107 regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
108 if (sysflg & SYSFLG_URXFE)
f27de95c 109 break;
1da177e4 110
093a9e2a 111 ch = readw(port->membase + UARTDR_OFFSET);
f27de95c
AS
112 status = ch & (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR);
113 ch &= 0xff;
114
115 port->icount.rx++;
1da177e4
LT
116 flg = TTY_NORMAL;
117
f27de95c
AS
118 if (unlikely(status)) {
119 if (status & UARTDR_PARERR)
2a9604b8 120 port->icount.parity++;
f27de95c 121 else if (status & UARTDR_FRMERR)
2a9604b8 122 port->icount.frame++;
f27de95c 123 else if (status & UARTDR_OVERR)
2a9604b8 124 port->icount.overrun++;
1da177e4 125
f27de95c 126 status &= port->read_status_mask;
1da177e4 127
f27de95c 128 if (status & UARTDR_PARERR)
2a9604b8 129 flg = TTY_PARITY;
f27de95c 130 else if (status & UARTDR_FRMERR)
2a9604b8 131 flg = TTY_FRAME;
f27de95c
AS
132 else if (status & UARTDR_OVERR)
133 flg = TTY_OVERRUN;
2a9604b8 134 }
1da177e4 135
7d12e780 136 if (uart_handle_sysrq_char(port, ch))
f27de95c 137 continue;
1da177e4 138
f27de95c
AS
139 if (status & port->ignore_status_mask)
140 continue;
2a9604b8 141
f27de95c 142 uart_insert_char(port, status, UARTDR_OVERR, ch, flg);
1da177e4 143 }
f27de95c 144
2e124b4a 145 tty_flip_buffer_push(&port->state->port);
f27de95c 146
2a9604b8 147 return IRQ_HANDLED;
1da177e4
LT
148}
149
135cc790 150static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id)
1da177e4
LT
151{
152 struct uart_port *port = dev_id;
3c7e9eb1 153 struct clps711x_port *s = dev_get_drvdata(port->dev);
ebd2c8f6 154 struct circ_buf *xmit = &port->state->xmit;
1da177e4
LT
155
156 if (port->x_char) {
093a9e2a 157 writew(port->x_char, port->membase + UARTDR_OFFSET);
1da177e4
LT
158 port->icount.tx++;
159 port->x_char = 0;
160 return IRQ_HANDLED;
161 }
7a6fbc9a 162
3c7e9eb1 163 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
bc000245
AS
164 if (s->tx_enabled) {
165 disable_irq_nosync(port->irq);
166 s->tx_enabled = 0;
167 }
3c7e9eb1
AS
168 return IRQ_HANDLED;
169 }
1da177e4 170
cf03a884 171 while (!uart_circ_empty(xmit)) {
093a9e2a
AS
172 u32 sysflg = 0;
173
174 writew(xmit->buf[xmit->tail], port->membase + UARTDR_OFFSET);
1da177e4
LT
175 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
176 port->icount.tx++;
bc000245
AS
177
178 regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
179 if (sysflg & SYSFLG_UTXFF)
1da177e4 180 break;
cf03a884 181 }
1da177e4
LT
182
183 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
184 uart_write_wakeup(port);
185
1da177e4
LT
186 return IRQ_HANDLED;
187}
188
a1c25f2b 189static unsigned int uart_clps711x_tx_empty(struct uart_port *port)
1da177e4 190{
bc000245 191 struct clps711x_port *s = dev_get_drvdata(port->dev);
093a9e2a 192 u32 sysflg = 0;
bc000245
AS
193
194 regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
195
196 return (sysflg & SYSFLG_UBUSY) ? 0 : TIOCSER_TEMT;
1da177e4
LT
197}
198
a1c25f2b 199static unsigned int uart_clps711x_get_mctrl(struct uart_port *port)
1da177e4 200{
bc000245
AS
201 struct clps711x_port *s = dev_get_drvdata(port->dev);
202 unsigned int result = 0;
1da177e4 203
bc000245 204 if (s->use_ms) {
093a9e2a
AS
205 u32 sysflg = 0;
206
bc000245
AS
207 regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
208 if (sysflg & SYSFLG1_DCD)
1da177e4 209 result |= TIOCM_CAR;
bc000245 210 if (sysflg & SYSFLG1_DSR)
1da177e4 211 result |= TIOCM_DSR;
bc000245 212 if (sysflg & SYSFLG1_CTS)
1da177e4 213 result |= TIOCM_CTS;
1593daf9
AS
214 } else
215 result = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
1da177e4
LT
216
217 return result;
218}
219
a1c25f2b 220static void uart_clps711x_set_mctrl(struct uart_port *port, unsigned int mctrl)
1da177e4 221{
a1c25f2b 222 /* Do nothing */
1da177e4
LT
223}
224
a1c25f2b 225static void uart_clps711x_break_ctl(struct uart_port *port, int break_state)
1da177e4 226{
1da177e4
LT
227 unsigned int ubrlcr;
228
093a9e2a 229 ubrlcr = readl(port->membase + UBRLCR_OFFSET);
ec335526 230 if (break_state)
1da177e4
LT
231 ubrlcr |= UBRLCR_BREAK;
232 else
233 ubrlcr &= ~UBRLCR_BREAK;
093a9e2a 234 writel(ubrlcr, port->membase + UBRLCR_OFFSET);
1da177e4
LT
235}
236
71b9e8c6
AS
237static void uart_clps711x_set_ldisc(struct uart_port *port, int ld)
238{
239 if (!port->line) {
240 struct clps711x_port *s = dev_get_drvdata(port->dev);
241
242 regmap_update_bits(s->syscon, SYSCON_OFFSET, SYSCON1_SIREN,
243 (ld == N_IRDA) ? SYSCON1_SIREN : 0);
244 }
245}
246
a1c25f2b 247static int uart_clps711x_startup(struct uart_port *port)
1da177e4 248{
3c7e9eb1 249 struct clps711x_port *s = dev_get_drvdata(port->dev);
1da177e4 250
f52ede2a 251 /* Disable break */
093a9e2a
AS
252 writel(readl(port->membase + UBRLCR_OFFSET) & ~UBRLCR_BREAK,
253 port->membase + UBRLCR_OFFSET);
f52ede2a
AS
254
255 /* Enable the port */
bc000245
AS
256 return regmap_update_bits(s->syscon, SYSCON_OFFSET,
257 SYSCON_UARTEN, SYSCON_UARTEN);
1da177e4
LT
258}
259
a1c25f2b 260static void uart_clps711x_shutdown(struct uart_port *port)
1da177e4 261{
bc000245 262 struct clps711x_port *s = dev_get_drvdata(port->dev);
1da177e4 263
f52ede2a 264 /* Disable the port */
bc000245 265 regmap_update_bits(s->syscon, SYSCON_OFFSET, SYSCON_UARTEN, 0);
1da177e4
LT
266}
267
a1c25f2b
AS
268static void uart_clps711x_set_termios(struct uart_port *port,
269 struct ktermios *termios,
270 struct ktermios *old)
1da177e4 271{
bc000245
AS
272 u32 ubrlcr;
273 unsigned int baud, quot;
1da177e4 274
7ae75e94
AS
275 /* Mask termios capabilities we don't support */
276 termios->c_cflag &= ~CMSPAR;
277 termios->c_iflag &= ~(BRKINT | IGNBRK);
1da177e4 278
c08f0153
AS
279 /* Ask the core to calculate the divisor for us */
280 baud = uart_get_baud_rate(port, termios, old, port->uartclk / 4096,
281 port->uartclk / 16);
1da177e4
LT
282 quot = uart_get_divisor(port, baud);
283
284 switch (termios->c_cflag & CSIZE) {
285 case CS5:
286 ubrlcr = UBRLCR_WRDLEN5;
287 break;
288 case CS6:
289 ubrlcr = UBRLCR_WRDLEN6;
290 break;
291 case CS7:
292 ubrlcr = UBRLCR_WRDLEN7;
293 break;
a1c25f2b
AS
294 case CS8:
295 default:
1da177e4
LT
296 ubrlcr = UBRLCR_WRDLEN8;
297 break;
298 }
7ae75e94 299
1da177e4
LT
300 if (termios->c_cflag & CSTOPB)
301 ubrlcr |= UBRLCR_XSTOP;
7ae75e94 302
1da177e4
LT
303 if (termios->c_cflag & PARENB) {
304 ubrlcr |= UBRLCR_PRTEN;
305 if (!(termios->c_cflag & PARODD))
306 ubrlcr |= UBRLCR_EVENPRT;
307 }
cf03a884
AS
308
309 /* Enable FIFO */
310 ubrlcr |= UBRLCR_FIFOEN;
1da177e4 311
7ae75e94 312 /* Set read status mask */
1da177e4
LT
313 port->read_status_mask = UARTDR_OVERR;
314 if (termios->c_iflag & INPCK)
315 port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
316
7ae75e94 317 /* Set status ignore mask */
1da177e4 318 port->ignore_status_mask = 0;
7ae75e94
AS
319 if (!(termios->c_cflag & CREAD))
320 port->ignore_status_mask |= UARTDR_OVERR | UARTDR_PARERR |
321 UARTDR_FRMERR;
1da177e4 322
7ae75e94 323 uart_update_timeout(port, termios->c_cflag, baud);
1da177e4 324
093a9e2a 325 writel(ubrlcr | (quot - 1), port->membase + UBRLCR_OFFSET);
1da177e4
LT
326}
327
a1c25f2b 328static const char *uart_clps711x_type(struct uart_port *port)
1da177e4 329{
a1c25f2b 330 return (port->type == PORT_CLPS711X) ? "CLPS711X" : NULL;
1da177e4
LT
331}
332
a1c25f2b 333static void uart_clps711x_config_port(struct uart_port *port, int flags)
1da177e4
LT
334{
335 if (flags & UART_CONFIG_TYPE)
336 port->type = PORT_CLPS711X;
337}
338
bc000245 339static void uart_clps711x_nop_void(struct uart_port *port)
1da177e4
LT
340{
341}
342
bc000245 343static int uart_clps711x_nop_int(struct uart_port *port)
1da177e4
LT
344{
345 return 0;
346}
347
a1c25f2b
AS
348static const struct uart_ops uart_clps711x_ops = {
349 .tx_empty = uart_clps711x_tx_empty,
350 .set_mctrl = uart_clps711x_set_mctrl,
351 .get_mctrl = uart_clps711x_get_mctrl,
352 .stop_tx = uart_clps711x_stop_tx,
353 .start_tx = uart_clps711x_start_tx,
bc000245
AS
354 .stop_rx = uart_clps711x_nop_void,
355 .enable_ms = uart_clps711x_nop_void,
a1c25f2b 356 .break_ctl = uart_clps711x_break_ctl,
71b9e8c6 357 .set_ldisc = uart_clps711x_set_ldisc,
a1c25f2b
AS
358 .startup = uart_clps711x_startup,
359 .shutdown = uart_clps711x_shutdown,
360 .set_termios = uart_clps711x_set_termios,
361 .type = uart_clps711x_type,
362 .config_port = uart_clps711x_config_port,
bc000245
AS
363 .release_port = uart_clps711x_nop_void,
364 .request_port = uart_clps711x_nop_int,
1da177e4
LT
365};
366
1da177e4 367#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
117d5d42 368static void uart_clps711x_console_putchar(struct uart_port *port, int ch)
d358788f 369{
bc000245 370 struct clps711x_port *s = dev_get_drvdata(port->dev);
bc000245 371
63e3ad32
AS
372 /* Wait for FIFO is not full */
373 while (1) {
374 u32 sysflg = 0;
375
bc000245 376 regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
63e3ad32
AS
377 if (!(sysflg & SYSFLG_UTXFF))
378 break;
379 cond_resched();
380 }
117d5d42 381
093a9e2a 382 writew(ch, port->membase + UARTDR_OFFSET);
d358788f
RK
383}
384
117d5d42
AS
385static void uart_clps711x_console_write(struct console *co, const char *c,
386 unsigned n)
1da177e4 387{
bc000245
AS
388 struct uart_port *port = clps711x_uart.state[co->index].uart_port;
389 struct clps711x_port *s = dev_get_drvdata(port->dev);
1da177e4 390
117d5d42 391 uart_console_write(port, c, n, uart_clps711x_console_putchar);
1da177e4 392
117d5d42 393 /* Wait for transmitter to become empty */
63e3ad32
AS
394 while (1) {
395 u32 sysflg = 0;
396
bc000245 397 regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
63e3ad32
AS
398 if (!(sysflg & SYSFLG_UBUSY))
399 break;
400 cond_resched();
401 }
1da177e4
LT
402}
403
bc000245 404static int uart_clps711x_console_setup(struct console *co, char *options)
1da177e4 405{
bc000245
AS
406 int baud = 38400, bits = 8, parity = 'n', flow = 'n';
407 int ret, index = co->index;
408 struct clps711x_port *s;
409 struct uart_port *port;
bc000245 410 unsigned int quot;
093a9e2a 411 u32 ubrlcr;
1da177e4 412
bc000245
AS
413 if (index < 0 || index >= UART_CLPS711X_NR)
414 return -EINVAL;
1da177e4 415
bc000245
AS
416 port = clps711x_uart.state[index].uart_port;
417 if (!port)
418 return -ENODEV;
1da177e4 419
bc000245 420 s = dev_get_drvdata(port->dev);
1da177e4 421
bc000245 422 if (!options) {
093a9e2a
AS
423 u32 syscon = 0;
424
bc000245
AS
425 regmap_read(s->syscon, SYSCON_OFFSET, &syscon);
426 if (syscon & SYSCON_UARTEN) {
093a9e2a 427 ubrlcr = readl(port->membase + UBRLCR_OFFSET);
1da177e4 428
bc000245
AS
429 if (ubrlcr & UBRLCR_PRTEN) {
430 if (ubrlcr & UBRLCR_EVENPRT)
431 parity = 'e';
432 else
433 parity = 'o';
434 }
1da177e4 435
bc000245
AS
436 if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7)
437 bits = 7;
438
439 quot = ubrlcr & UBRLCR_BAUD_MASK;
440 baud = port->uartclk / (16 * (quot + 1));
441 }
442 } else
1da177e4 443 uart_parse_options(options, &baud, &parity, &bits, &flow);
1da177e4 444
bc000245
AS
445 ret = uart_set_options(port, co, baud, parity, bits, flow);
446 if (ret)
447 return ret;
448
449 return regmap_update_bits(s->syscon, SYSCON_OFFSET,
450 SYSCON_UARTEN, SYSCON_UARTEN);
1da177e4 451}
bc000245
AS
452
453static struct console clps711x_console = {
454 .name = UART_CLPS711X_DEVNAME,
455 .device = uart_console_device,
456 .write = uart_clps711x_console_write,
457 .setup = uart_clps711x_console_setup,
458 .flags = CON_PRINTBUFFER,
459 .index = -1,
460};
1da177e4
LT
461#endif
462
9671f099 463static int uart_clps711x_probe(struct platform_device *pdev)
1da177e4 464{
bc000245
AS
465 struct device_node *np = pdev->dev.of_node;
466 int ret, index = np ? of_alias_get_id(np, "serial") : pdev->id;
117d5d42 467 struct clps711x_port *s;
bc000245
AS
468 struct resource *res;
469 struct clk *uart_clk;
1da177e4 470
bc000245
AS
471 if (index < 0 || index >= UART_CLPS711X_NR)
472 return -EINVAL;
473
474 s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
475 if (!s)
117d5d42 476 return -ENOMEM;
bc000245
AS
477
478 uart_clk = devm_clk_get(&pdev->dev, NULL);
479 if (IS_ERR(uart_clk))
480 return PTR_ERR(uart_clk);
481
482 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
483 s->port.membase = devm_ioremap_resource(&pdev->dev, res);
484 if (IS_ERR(s->port.membase))
485 return PTR_ERR(s->port.membase);
486
487 s->port.irq = platform_get_irq(pdev, 0);
488 if (IS_ERR_VALUE(s->port.irq))
489 return s->port.irq;
490
491 s->rx_irq = platform_get_irq(pdev, 1);
492 if (IS_ERR_VALUE(s->rx_irq))
493 return s->rx_irq;
494
495 if (!np) {
496 char syscon_name[9];
497
498 sprintf(syscon_name, "syscon.%i", index + 1);
499 s->syscon = syscon_regmap_lookup_by_pdevname(syscon_name);
500 if (IS_ERR(s->syscon))
501 return PTR_ERR(s->syscon);
502
503 s->use_ms = !index;
504 } else {
505 s->syscon = syscon_regmap_lookup_by_phandle(np, "syscon");
506 if (IS_ERR(s->syscon))
507 return PTR_ERR(s->syscon);
508
71b9e8c6 509 if (!index)
bc000245 510 s->use_ms = of_property_read_bool(np, "uart-use-ms");
117d5d42 511 }
bc000245
AS
512
513 s->port.line = index;
514 s->port.dev = &pdev->dev;
515 s->port.iotype = UPIO_MEM32;
516 s->port.mapbase = res->start;
517 s->port.type = PORT_CLPS711X;
518 s->port.fifosize = 16;
519 s->port.flags = UPF_SKIP_TEST | UPF_FIXED_TYPE;
520 s->port.uartclk = clk_get_rate(uart_clk);
521 s->port.ops = &uart_clps711x_ops;
522
117d5d42 523 platform_set_drvdata(pdev, s);
1da177e4 524
bc000245
AS
525 ret = uart_add_one_port(&clps711x_uart, &s->port);
526 if (ret)
527 return ret;
c08f0153 528
bc000245
AS
529 /* Disable port */
530 if (!uart_console(&s->port))
531 regmap_update_bits(s->syscon, SYSCON_OFFSET, SYSCON_UARTEN, 0);
532
533 s->tx_enabled = 1;
534
535 ret = devm_request_irq(&pdev->dev, s->port.irq, uart_clps711x_int_tx, 0,
536 dev_name(&pdev->dev), &s->port);
117d5d42 537 if (ret) {
bc000245 538 uart_remove_one_port(&clps711x_uart, &s->port);
43b829b3 539 return ret;
117d5d42 540 }
1da177e4 541
bc000245
AS
542 ret = devm_request_irq(&pdev->dev, s->rx_irq, uart_clps711x_int_rx, 0,
543 dev_name(&pdev->dev), &s->port);
544 if (ret)
545 uart_remove_one_port(&clps711x_uart, &s->port);
1da177e4 546
bc000245 547 return ret;
1da177e4
LT
548}
549
ae8d8a14 550static int uart_clps711x_remove(struct platform_device *pdev)
1da177e4 551{
117d5d42 552 struct clps711x_port *s = platform_get_drvdata(pdev);
95113728 553
bc000245 554 return uart_remove_one_port(&clps711x_uart, &s->port);
1da177e4
LT
555}
556
bc000245
AS
557static const struct of_device_id __maybe_unused clps711x_uart_dt_ids[] = {
558 { .compatible = "cirrus,clps711x-uart", },
559 { }
560};
561MODULE_DEVICE_TABLE(of, clps711x_uart_dt_ids);
562
563static struct platform_driver clps711x_uart_platform = {
95113728 564 .driver = {
bc000245
AS
565 .name = "clps711x-uart",
566 .owner = THIS_MODULE,
567 .of_match_table = of_match_ptr(clps711x_uart_dt_ids),
95113728
AS
568 },
569 .probe = uart_clps711x_probe,
2d47b716 570 .remove = uart_clps711x_remove,
95113728 571};
95113728
AS
572
573static int __init uart_clps711x_init(void)
574{
bc000245
AS
575 int ret;
576
577#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
578 clps711x_uart.cons = &clps711x_console;
579 clps711x_console.data = &clps711x_uart;
580#endif
581
582 ret = uart_register_driver(&clps711x_uart);
583 if (ret)
584 return ret;
585
586 return platform_driver_register(&clps711x_uart_platform);
95113728
AS
587}
588module_init(uart_clps711x_init);
589
590static void __exit uart_clps711x_exit(void)
591{
bc000245
AS
592 platform_driver_unregister(&clps711x_uart_platform);
593 uart_unregister_driver(&clps711x_uart);
95113728
AS
594}
595module_exit(uart_clps711x_exit);
1da177e4
LT
596
597MODULE_AUTHOR("Deep Blue Solutions Ltd");
95113728 598MODULE_DESCRIPTION("CLPS711X serial driver");
1da177e4 599MODULE_LICENSE("GPL");
This page took 0.788541 seconds and 5 git commands to generate.