Commit | Line | Data |
---|---|---|
041f031d | 1 | /* |
ce871229 VM |
2 | * MPS2 UART driver |
3 | * | |
041f031d VM |
4 | * Copyright (C) 2015 ARM Limited |
5 | * | |
6 | * Author: Vladimir Murzin <vladimir.murzin@arm.com> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License version 2 as | |
10 | * published by the Free Software Foundation. | |
11 | * | |
12 | * TODO: support for SysRq | |
13 | */ | |
14 | ||
15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
16 | ||
17 | #include <linux/bitops.h> | |
18 | #include <linux/clk.h> | |
19 | #include <linux/console.h> | |
20 | #include <linux/io.h> | |
21 | #include <linux/kernel.h> | |
041f031d VM |
22 | #include <linux/of_device.h> |
23 | #include <linux/of.h> | |
24 | #include <linux/platform_device.h> | |
25 | #include <linux/serial_core.h> | |
26 | #include <linux/tty_flip.h> | |
27 | #include <linux/types.h> | |
28 | ||
29 | #define SERIAL_NAME "ttyMPS" | |
30 | #define DRIVER_NAME "mps2-uart" | |
31 | #define MAKE_NAME(x) (DRIVER_NAME # x) | |
32 | ||
33 | #define UARTn_DATA 0x00 | |
34 | ||
35 | #define UARTn_STATE 0x04 | |
36 | #define UARTn_STATE_TX_FULL BIT(0) | |
37 | #define UARTn_STATE_RX_FULL BIT(1) | |
38 | #define UARTn_STATE_TX_OVERRUN BIT(2) | |
39 | #define UARTn_STATE_RX_OVERRUN BIT(3) | |
40 | ||
41 | #define UARTn_CTRL 0x08 | |
42 | #define UARTn_CTRL_TX_ENABLE BIT(0) | |
43 | #define UARTn_CTRL_RX_ENABLE BIT(1) | |
44 | #define UARTn_CTRL_TX_INT_ENABLE BIT(2) | |
45 | #define UARTn_CTRL_RX_INT_ENABLE BIT(3) | |
46 | #define UARTn_CTRL_TX_OVERRUN_INT_ENABLE BIT(4) | |
47 | #define UARTn_CTRL_RX_OVERRUN_INT_ENABLE BIT(5) | |
48 | ||
49 | #define UARTn_INT 0x0c | |
50 | #define UARTn_INT_TX BIT(0) | |
51 | #define UARTn_INT_RX BIT(1) | |
52 | #define UARTn_INT_TX_OVERRUN BIT(2) | |
53 | #define UARTn_INT_RX_OVERRUN BIT(3) | |
54 | ||
55 | #define UARTn_BAUDDIV 0x10 | |
56 | #define UARTn_BAUDDIV_MASK GENMASK(20, 0) | |
57 | ||
58 | /* | |
59 | * Helpers to make typical enable/disable operations more readable. | |
60 | */ | |
61 | #define UARTn_CTRL_TX_GRP (UARTn_CTRL_TX_ENABLE |\ | |
62 | UARTn_CTRL_TX_INT_ENABLE |\ | |
63 | UARTn_CTRL_TX_OVERRUN_INT_ENABLE) | |
64 | ||
65 | #define UARTn_CTRL_RX_GRP (UARTn_CTRL_RX_ENABLE |\ | |
66 | UARTn_CTRL_RX_INT_ENABLE |\ | |
67 | UARTn_CTRL_RX_OVERRUN_INT_ENABLE) | |
68 | ||
69 | #define MPS2_MAX_PORTS 3 | |
70 | ||
71 | struct mps2_uart_port { | |
72 | struct uart_port port; | |
73 | struct clk *clk; | |
74 | unsigned int tx_irq; | |
75 | unsigned int rx_irq; | |
76 | }; | |
77 | ||
78 | static inline struct mps2_uart_port *to_mps2_port(struct uart_port *port) | |
79 | { | |
80 | return container_of(port, struct mps2_uart_port, port); | |
81 | } | |
82 | ||
83 | static void mps2_uart_write8(struct uart_port *port, u8 val, unsigned int off) | |
84 | { | |
85 | struct mps2_uart_port *mps_port = to_mps2_port(port); | |
86 | ||
87 | writeb(val, mps_port->port.membase + off); | |
88 | } | |
89 | ||
90 | static u8 mps2_uart_read8(struct uart_port *port, unsigned int off) | |
91 | { | |
92 | struct mps2_uart_port *mps_port = to_mps2_port(port); | |
93 | ||
94 | return readb(mps_port->port.membase + off); | |
95 | } | |
96 | ||
97 | static void mps2_uart_write32(struct uart_port *port, u32 val, unsigned int off) | |
98 | { | |
99 | struct mps2_uart_port *mps_port = to_mps2_port(port); | |
100 | ||
101 | writel_relaxed(val, mps_port->port.membase + off); | |
102 | } | |
103 | ||
104 | static unsigned int mps2_uart_tx_empty(struct uart_port *port) | |
105 | { | |
106 | u8 status = mps2_uart_read8(port, UARTn_STATE); | |
107 | ||
108 | return (status & UARTn_STATE_TX_FULL) ? 0 : TIOCSER_TEMT; | |
109 | } | |
110 | ||
111 | static void mps2_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | |
112 | { | |
113 | } | |
114 | ||
115 | static unsigned int mps2_uart_get_mctrl(struct uart_port *port) | |
116 | { | |
117 | return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR; | |
118 | } | |
119 | ||
120 | static void mps2_uart_stop_tx(struct uart_port *port) | |
121 | { | |
122 | u8 control = mps2_uart_read8(port, UARTn_CTRL); | |
123 | ||
124 | control &= ~UARTn_CTRL_TX_INT_ENABLE; | |
125 | ||
126 | mps2_uart_write8(port, control, UARTn_CTRL); | |
127 | } | |
128 | ||
129 | static void mps2_uart_tx_chars(struct uart_port *port) | |
130 | { | |
131 | struct circ_buf *xmit = &port->state->xmit; | |
132 | ||
133 | while (!(mps2_uart_read8(port, UARTn_STATE) & UARTn_STATE_TX_FULL)) { | |
134 | if (port->x_char) { | |
135 | mps2_uart_write8(port, port->x_char, UARTn_DATA); | |
136 | port->x_char = 0; | |
137 | port->icount.tx++; | |
138 | continue; | |
139 | } | |
140 | ||
141 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) | |
142 | break; | |
143 | ||
144 | mps2_uart_write8(port, xmit->buf[xmit->tail], UARTn_DATA); | |
145 | xmit->tail = (xmit->tail + 1) % UART_XMIT_SIZE; | |
146 | port->icount.tx++; | |
147 | } | |
148 | ||
149 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | |
150 | uart_write_wakeup(port); | |
151 | ||
152 | if (uart_circ_empty(xmit)) | |
153 | mps2_uart_stop_tx(port); | |
154 | } | |
155 | ||
156 | static void mps2_uart_start_tx(struct uart_port *port) | |
157 | { | |
158 | u8 control = mps2_uart_read8(port, UARTn_CTRL); | |
159 | ||
160 | control |= UARTn_CTRL_TX_INT_ENABLE; | |
161 | ||
162 | mps2_uart_write8(port, control, UARTn_CTRL); | |
163 | ||
164 | /* | |
165 | * We've just unmasked the TX IRQ and now slow-starting via | |
166 | * polling; if there is enough data to fill up the internal | |
167 | * write buffer in one go, the TX IRQ should assert, at which | |
168 | * point we switch to fully interrupt-driven TX. | |
169 | */ | |
170 | ||
171 | mps2_uart_tx_chars(port); | |
172 | } | |
173 | ||
174 | static void mps2_uart_stop_rx(struct uart_port *port) | |
175 | { | |
176 | u8 control = mps2_uart_read8(port, UARTn_CTRL); | |
177 | ||
178 | control &= ~UARTn_CTRL_RX_GRP; | |
179 | ||
180 | mps2_uart_write8(port, control, UARTn_CTRL); | |
181 | } | |
182 | ||
183 | static void mps2_uart_break_ctl(struct uart_port *port, int ctl) | |
184 | { | |
185 | } | |
186 | ||
187 | static void mps2_uart_rx_chars(struct uart_port *port) | |
188 | { | |
189 | struct tty_port *tport = &port->state->port; | |
190 | ||
191 | while (mps2_uart_read8(port, UARTn_STATE) & UARTn_STATE_RX_FULL) { | |
192 | u8 rxdata = mps2_uart_read8(port, UARTn_DATA); | |
193 | ||
194 | port->icount.rx++; | |
195 | tty_insert_flip_char(&port->state->port, rxdata, TTY_NORMAL); | |
196 | } | |
197 | ||
198 | tty_flip_buffer_push(tport); | |
199 | } | |
200 | ||
201 | static irqreturn_t mps2_uart_rxirq(int irq, void *data) | |
202 | { | |
203 | struct uart_port *port = data; | |
204 | u8 irqflag = mps2_uart_read8(port, UARTn_INT); | |
205 | ||
206 | if (unlikely(!(irqflag & UARTn_INT_RX))) | |
207 | return IRQ_NONE; | |
208 | ||
209 | spin_lock(&port->lock); | |
210 | ||
211 | mps2_uart_write8(port, UARTn_INT_RX, UARTn_INT); | |
212 | mps2_uart_rx_chars(port); | |
213 | ||
214 | spin_unlock(&port->lock); | |
215 | ||
216 | return IRQ_HANDLED; | |
217 | } | |
218 | ||
219 | static irqreturn_t mps2_uart_txirq(int irq, void *data) | |
220 | { | |
221 | struct uart_port *port = data; | |
222 | u8 irqflag = mps2_uart_read8(port, UARTn_INT); | |
223 | ||
224 | if (unlikely(!(irqflag & UARTn_INT_TX))) | |
225 | return IRQ_NONE; | |
226 | ||
227 | spin_lock(&port->lock); | |
228 | ||
229 | mps2_uart_write8(port, UARTn_INT_TX, UARTn_INT); | |
230 | mps2_uart_tx_chars(port); | |
231 | ||
232 | spin_unlock(&port->lock); | |
233 | ||
234 | return IRQ_HANDLED; | |
235 | } | |
236 | ||
237 | static irqreturn_t mps2_uart_oerrirq(int irq, void *data) | |
238 | { | |
239 | irqreturn_t handled = IRQ_NONE; | |
240 | struct uart_port *port = data; | |
241 | u8 irqflag = mps2_uart_read8(port, UARTn_INT); | |
242 | ||
243 | spin_lock(&port->lock); | |
244 | ||
245 | if (irqflag & UARTn_INT_RX_OVERRUN) { | |
246 | struct tty_port *tport = &port->state->port; | |
247 | ||
248 | mps2_uart_write8(port, UARTn_INT_RX_OVERRUN, UARTn_INT); | |
249 | port->icount.overrun++; | |
250 | tty_insert_flip_char(tport, 0, TTY_OVERRUN); | |
251 | tty_flip_buffer_push(tport); | |
252 | handled = IRQ_HANDLED; | |
253 | } | |
254 | ||
255 | /* | |
256 | * It's never been seen in practice and it never *should* happen since | |
257 | * we check if there is enough room in TX buffer before sending data. | |
258 | * So we keep this check in case something suspicious has happened. | |
259 | */ | |
260 | if (irqflag & UARTn_INT_TX_OVERRUN) { | |
261 | mps2_uart_write8(port, UARTn_INT_TX_OVERRUN, UARTn_INT); | |
262 | handled = IRQ_HANDLED; | |
263 | } | |
264 | ||
265 | spin_unlock(&port->lock); | |
266 | ||
267 | return handled; | |
268 | } | |
269 | ||
270 | static int mps2_uart_startup(struct uart_port *port) | |
271 | { | |
272 | struct mps2_uart_port *mps_port = to_mps2_port(port); | |
273 | u8 control = mps2_uart_read8(port, UARTn_CTRL); | |
274 | int ret; | |
275 | ||
276 | control &= ~(UARTn_CTRL_RX_GRP | UARTn_CTRL_TX_GRP); | |
277 | ||
278 | mps2_uart_write8(port, control, UARTn_CTRL); | |
279 | ||
280 | ret = request_irq(mps_port->rx_irq, mps2_uart_rxirq, 0, | |
281 | MAKE_NAME(-rx), mps_port); | |
282 | if (ret) { | |
283 | dev_err(port->dev, "failed to register rxirq (%d)\n", ret); | |
284 | return ret; | |
285 | } | |
286 | ||
287 | ret = request_irq(mps_port->tx_irq, mps2_uart_txirq, 0, | |
288 | MAKE_NAME(-tx), mps_port); | |
289 | if (ret) { | |
290 | dev_err(port->dev, "failed to register txirq (%d)\n", ret); | |
291 | goto err_free_rxirq; | |
292 | } | |
293 | ||
294 | ret = request_irq(port->irq, mps2_uart_oerrirq, IRQF_SHARED, | |
295 | MAKE_NAME(-overrun), mps_port); | |
296 | ||
297 | if (ret) { | |
298 | dev_err(port->dev, "failed to register oerrirq (%d)\n", ret); | |
299 | goto err_free_txirq; | |
300 | } | |
301 | ||
302 | control |= UARTn_CTRL_RX_GRP | UARTn_CTRL_TX_GRP; | |
303 | ||
304 | mps2_uart_write8(port, control, UARTn_CTRL); | |
305 | ||
306 | return 0; | |
307 | ||
308 | err_free_txirq: | |
309 | free_irq(mps_port->tx_irq, mps_port); | |
310 | err_free_rxirq: | |
311 | free_irq(mps_port->rx_irq, mps_port); | |
312 | ||
313 | return ret; | |
314 | } | |
315 | ||
316 | static void mps2_uart_shutdown(struct uart_port *port) | |
317 | { | |
318 | struct mps2_uart_port *mps_port = to_mps2_port(port); | |
319 | u8 control = mps2_uart_read8(port, UARTn_CTRL); | |
320 | ||
321 | control &= ~(UARTn_CTRL_RX_GRP | UARTn_CTRL_TX_GRP); | |
322 | ||
323 | mps2_uart_write8(port, control, UARTn_CTRL); | |
324 | ||
325 | free_irq(mps_port->rx_irq, mps_port); | |
326 | free_irq(mps_port->tx_irq, mps_port); | |
327 | free_irq(port->irq, mps_port); | |
328 | } | |
329 | ||
330 | static void | |
331 | mps2_uart_set_termios(struct uart_port *port, struct ktermios *termios, | |
332 | struct ktermios *old) | |
333 | { | |
334 | unsigned long flags; | |
335 | unsigned int baud, bauddiv; | |
336 | ||
337 | termios->c_cflag &= ~(CRTSCTS | CMSPAR); | |
338 | termios->c_cflag &= ~CSIZE; | |
339 | termios->c_cflag |= CS8; | |
340 | termios->c_cflag &= ~PARENB; | |
341 | termios->c_cflag &= ~CSTOPB; | |
342 | ||
343 | baud = uart_get_baud_rate(port, termios, old, | |
344 | DIV_ROUND_CLOSEST(port->uartclk, UARTn_BAUDDIV_MASK), | |
345 | DIV_ROUND_CLOSEST(port->uartclk, 16)); | |
346 | ||
347 | bauddiv = DIV_ROUND_CLOSEST(port->uartclk, baud); | |
348 | ||
349 | spin_lock_irqsave(&port->lock, flags); | |
350 | ||
351 | uart_update_timeout(port, termios->c_cflag, baud); | |
352 | mps2_uart_write32(port, bauddiv, UARTn_BAUDDIV); | |
353 | ||
354 | spin_unlock_irqrestore(&port->lock, flags); | |
355 | ||
356 | if (tty_termios_baud_rate(termios)) | |
357 | tty_termios_encode_baud_rate(termios, baud, baud); | |
358 | } | |
359 | ||
360 | static const char *mps2_uart_type(struct uart_port *port) | |
361 | { | |
362 | return (port->type == PORT_MPS2UART) ? DRIVER_NAME : NULL; | |
363 | } | |
364 | ||
365 | static void mps2_uart_release_port(struct uart_port *port) | |
366 | { | |
367 | } | |
368 | ||
369 | static int mps2_uart_request_port(struct uart_port *port) | |
370 | { | |
371 | return 0; | |
372 | } | |
373 | ||
374 | static void mps2_uart_config_port(struct uart_port *port, int type) | |
375 | { | |
376 | if (type & UART_CONFIG_TYPE && !mps2_uart_request_port(port)) | |
377 | port->type = PORT_MPS2UART; | |
378 | } | |
379 | ||
380 | static int mps2_uart_verify_port(struct uart_port *port, struct serial_struct *serinfo) | |
381 | { | |
382 | return -EINVAL; | |
383 | } | |
384 | ||
385 | static const struct uart_ops mps2_uart_pops = { | |
386 | .tx_empty = mps2_uart_tx_empty, | |
387 | .set_mctrl = mps2_uart_set_mctrl, | |
388 | .get_mctrl = mps2_uart_get_mctrl, | |
389 | .stop_tx = mps2_uart_stop_tx, | |
390 | .start_tx = mps2_uart_start_tx, | |
391 | .stop_rx = mps2_uart_stop_rx, | |
392 | .break_ctl = mps2_uart_break_ctl, | |
393 | .startup = mps2_uart_startup, | |
394 | .shutdown = mps2_uart_shutdown, | |
395 | .set_termios = mps2_uart_set_termios, | |
396 | .type = mps2_uart_type, | |
397 | .release_port = mps2_uart_release_port, | |
398 | .request_port = mps2_uart_request_port, | |
399 | .config_port = mps2_uart_config_port, | |
400 | .verify_port = mps2_uart_verify_port, | |
401 | }; | |
402 | ||
403 | static struct mps2_uart_port mps2_uart_ports[MPS2_MAX_PORTS]; | |
404 | ||
405 | #ifdef CONFIG_SERIAL_MPS2_UART_CONSOLE | |
406 | static void mps2_uart_console_putchar(struct uart_port *port, int ch) | |
407 | { | |
408 | while (mps2_uart_read8(port, UARTn_STATE) & UARTn_STATE_TX_FULL) | |
409 | cpu_relax(); | |
410 | ||
411 | mps2_uart_write8(port, ch, UARTn_DATA); | |
412 | } | |
413 | ||
414 | static void mps2_uart_console_write(struct console *co, const char *s, unsigned int cnt) | |
415 | { | |
416 | struct uart_port *port = &mps2_uart_ports[co->index].port; | |
417 | ||
418 | uart_console_write(port, s, cnt, mps2_uart_console_putchar); | |
419 | } | |
420 | ||
421 | static int mps2_uart_console_setup(struct console *co, char *options) | |
422 | { | |
423 | struct mps2_uart_port *mps_port; | |
424 | int baud = 9600; | |
425 | int bits = 8; | |
426 | int parity = 'n'; | |
427 | int flow = 'n'; | |
428 | ||
429 | if (co->index < 0 || co->index >= MPS2_MAX_PORTS) | |
430 | return -ENODEV; | |
431 | ||
432 | mps_port = &mps2_uart_ports[co->index]; | |
433 | ||
434 | if (options) | |
435 | uart_parse_options(options, &baud, &parity, &bits, &flow); | |
436 | ||
437 | return uart_set_options(&mps_port->port, co, baud, parity, bits, flow); | |
438 | } | |
439 | ||
440 | static struct uart_driver mps2_uart_driver; | |
441 | ||
442 | static struct console mps2_uart_console = { | |
443 | .name = SERIAL_NAME, | |
444 | .device = uart_console_device, | |
445 | .write = mps2_uart_console_write, | |
446 | .setup = mps2_uart_console_setup, | |
447 | .flags = CON_PRINTBUFFER, | |
448 | .index = -1, | |
449 | .data = &mps2_uart_driver, | |
450 | }; | |
451 | ||
452 | #define MPS2_SERIAL_CONSOLE (&mps2_uart_console) | |
453 | ||
bd8d257f VM |
454 | static void mps2_early_putchar(struct uart_port *port, int ch) |
455 | { | |
456 | while (readb(port->membase + UARTn_STATE) & UARTn_STATE_TX_FULL) | |
457 | cpu_relax(); | |
458 | ||
459 | writeb((unsigned char)ch, port->membase + UARTn_DATA); | |
460 | } | |
461 | ||
462 | static void mps2_early_write(struct console *con, const char *s, unsigned int n) | |
463 | { | |
464 | struct earlycon_device *dev = con->data; | |
465 | ||
466 | uart_console_write(&dev->port, s, n, mps2_early_putchar); | |
467 | } | |
468 | ||
469 | static int __init mps2_early_console_setup(struct earlycon_device *device, | |
470 | const char *opt) | |
471 | { | |
472 | if (!device->port.membase) | |
473 | return -ENODEV; | |
474 | ||
475 | device->con->write = mps2_early_write; | |
476 | ||
477 | return 0; | |
478 | } | |
479 | ||
480 | OF_EARLYCON_DECLARE(mps2, "arm,mps2-uart", mps2_early_console_setup); | |
481 | ||
041f031d VM |
482 | #else |
483 | #define MPS2_SERIAL_CONSOLE NULL | |
484 | #endif | |
485 | ||
486 | static struct uart_driver mps2_uart_driver = { | |
487 | .driver_name = DRIVER_NAME, | |
488 | .dev_name = SERIAL_NAME, | |
489 | .nr = MPS2_MAX_PORTS, | |
490 | .cons = MPS2_SERIAL_CONSOLE, | |
491 | }; | |
492 | ||
493 | static struct mps2_uart_port *mps2_of_get_port(struct platform_device *pdev) | |
494 | { | |
495 | struct device_node *np = pdev->dev.of_node; | |
496 | int id; | |
497 | ||
498 | if (!np) | |
499 | return NULL; | |
500 | ||
501 | id = of_alias_get_id(np, "serial"); | |
502 | if (id < 0) | |
503 | id = 0; | |
504 | ||
505 | if (WARN_ON(id >= MPS2_MAX_PORTS)) | |
506 | return NULL; | |
507 | ||
508 | mps2_uart_ports[id].port.line = id; | |
509 | return &mps2_uart_ports[id]; | |
510 | } | |
511 | ||
512 | static int mps2_init_port(struct mps2_uart_port *mps_port, | |
513 | struct platform_device *pdev) | |
514 | { | |
515 | struct resource *res; | |
516 | int ret; | |
517 | ||
518 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
519 | mps_port->port.membase = devm_ioremap_resource(&pdev->dev, res); | |
520 | if (IS_ERR(mps_port->port.membase)) | |
521 | return PTR_ERR(mps_port->port.membase); | |
522 | ||
523 | mps_port->port.mapbase = res->start; | |
524 | mps_port->port.mapsize = resource_size(res); | |
525 | ||
526 | mps_port->rx_irq = platform_get_irq(pdev, 0); | |
527 | mps_port->tx_irq = platform_get_irq(pdev, 1); | |
528 | mps_port->port.irq = platform_get_irq(pdev, 2); | |
529 | ||
530 | mps_port->port.iotype = UPIO_MEM; | |
531 | mps_port->port.flags = UPF_BOOT_AUTOCONF; | |
532 | mps_port->port.fifosize = 1; | |
533 | mps_port->port.ops = &mps2_uart_pops; | |
534 | mps_port->port.dev = &pdev->dev; | |
535 | ||
536 | mps_port->clk = devm_clk_get(&pdev->dev, NULL); | |
537 | if (IS_ERR(mps_port->clk)) | |
538 | return PTR_ERR(mps_port->clk); | |
539 | ||
540 | ret = clk_prepare_enable(mps_port->clk); | |
541 | if (ret) | |
542 | return ret; | |
543 | ||
544 | mps_port->port.uartclk = clk_get_rate(mps_port->clk); | |
545 | ||
546 | clk_disable_unprepare(mps_port->clk); | |
547 | ||
548 | return ret; | |
549 | } | |
550 | ||
551 | static int mps2_serial_probe(struct platform_device *pdev) | |
552 | { | |
553 | struct mps2_uart_port *mps_port; | |
554 | int ret; | |
555 | ||
556 | mps_port = mps2_of_get_port(pdev); | |
557 | if (!mps_port) | |
558 | return -ENODEV; | |
559 | ||
560 | ret = mps2_init_port(mps_port, pdev); | |
561 | if (ret) | |
562 | return ret; | |
563 | ||
564 | ret = uart_add_one_port(&mps2_uart_driver, &mps_port->port); | |
565 | if (ret) | |
566 | return ret; | |
567 | ||
568 | platform_set_drvdata(pdev, mps_port); | |
569 | ||
570 | return 0; | |
571 | } | |
572 | ||
041f031d VM |
573 | #ifdef CONFIG_OF |
574 | static const struct of_device_id mps2_match[] = { | |
575 | { .compatible = "arm,mps2-uart", }, | |
576 | {}, | |
577 | }; | |
041f031d VM |
578 | #endif |
579 | ||
580 | static struct platform_driver mps2_serial_driver = { | |
581 | .probe = mps2_serial_probe, | |
041f031d VM |
582 | |
583 | .driver = { | |
584 | .name = DRIVER_NAME, | |
585 | .of_match_table = of_match_ptr(mps2_match), | |
ce871229 | 586 | .suppress_bind_attrs = true, |
041f031d VM |
587 | }, |
588 | }; | |
589 | ||
590 | static int __init mps2_uart_init(void) | |
591 | { | |
592 | int ret; | |
593 | ||
594 | ret = uart_register_driver(&mps2_uart_driver); | |
595 | if (ret) | |
596 | return ret; | |
597 | ||
598 | ret = platform_driver_register(&mps2_serial_driver); | |
599 | if (ret) | |
600 | uart_unregister_driver(&mps2_uart_driver); | |
601 | ||
602 | return ret; | |
603 | } | |
ce871229 | 604 | arch_initcall(mps2_uart_init); |