1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * altera_uart.c -- Altera UART driver |
4 | * |
5 | * Based on mcf.c -- Freescale ColdFire UART driver |
6 | * |
7 | * (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com> |
8 | * (C) Copyright 2008, Thomas Chou <thomas@wytron.com.tw> |
9 | * (C) Copyright 2010, Tobias Klauser <tklauser@distanz.ch> |
10 | */ |
11 | |
12 | #include <linux/kernel.h> |
13 | #include <linux/init.h> |
14 | #include <linux/timer.h> |
15 | #include <linux/interrupt.h> |
16 | #include <linux/module.h> |
17 | #include <linux/console.h> |
18 | #include <linux/tty.h> |
19 | #include <linux/tty_flip.h> |
20 | #include <linux/serial.h> |
21 | #include <linux/serial_core.h> |
22 | #include <linux/platform_device.h> |
23 | #include <linux/of.h> |
24 | #include <linux/io.h> |
25 | #include <linux/altera_uart.h> |
26 | |
27 | #define DRV_NAME "altera_uart" |
28 | #define SERIAL_ALTERA_MAJOR 204 |
29 | #define SERIAL_ALTERA_MINOR 213 |
30 | |
31 | /* |
32 | * Altera UART register definitions according to the Nios UART datasheet: |
33 | * http://www.altera.com/literature/ds/ds_nios_uart.pdf |
34 | */ |
35 | |
36 | #define ALTERA_UART_SIZE 32 |
37 | |
38 | #define ALTERA_UART_RXDATA_REG 0 |
39 | #define ALTERA_UART_TXDATA_REG 4 |
40 | #define ALTERA_UART_STATUS_REG 8 |
41 | #define ALTERA_UART_CONTROL_REG 12 |
42 | #define ALTERA_UART_DIVISOR_REG 16 |
43 | #define ALTERA_UART_EOP_REG 20 |
44 | |
45 | #define ALTERA_UART_STATUS_PE_MSK 0x0001 /* parity error */ |
46 | #define ALTERA_UART_STATUS_FE_MSK 0x0002 /* framing error */ |
47 | #define ALTERA_UART_STATUS_BRK_MSK 0x0004 /* break */ |
48 | #define ALTERA_UART_STATUS_ROE_MSK 0x0008 /* RX overrun error */ |
49 | #define ALTERA_UART_STATUS_TOE_MSK 0x0010 /* TX overrun error */ |
50 | #define ALTERA_UART_STATUS_TMT_MSK 0x0020 /* TX shift register state */ |
51 | #define ALTERA_UART_STATUS_TRDY_MSK 0x0040 /* TX ready */ |
52 | #define ALTERA_UART_STATUS_RRDY_MSK 0x0080 /* RX ready */ |
53 | #define ALTERA_UART_STATUS_E_MSK 0x0100 /* exception condition */ |
54 | #define ALTERA_UART_STATUS_DCTS_MSK 0x0400 /* CTS logic-level change */ |
55 | #define ALTERA_UART_STATUS_CTS_MSK 0x0800 /* CTS logic state */ |
56 | #define ALTERA_UART_STATUS_EOP_MSK 0x1000 /* EOP written/read */ |
57 | |
58 | /* Enable interrupt on... */ |
59 | #define ALTERA_UART_CONTROL_PE_MSK 0x0001 /* ...parity error */ |
60 | #define ALTERA_UART_CONTROL_FE_MSK 0x0002 /* ...framing error */ |
61 | #define ALTERA_UART_CONTROL_BRK_MSK 0x0004 /* ...break */ |
62 | #define ALTERA_UART_CONTROL_ROE_MSK 0x0008 /* ...RX overrun */ |
63 | #define ALTERA_UART_CONTROL_TOE_MSK 0x0010 /* ...TX overrun */ |
64 | #define ALTERA_UART_CONTROL_TMT_MSK 0x0020 /* ...TX shift register empty */ |
65 | #define ALTERA_UART_CONTROL_TRDY_MSK 0x0040 /* ...TX ready */ |
66 | #define ALTERA_UART_CONTROL_RRDY_MSK 0x0080 /* ...RX ready */ |
67 | #define ALTERA_UART_CONTROL_E_MSK 0x0100 /* ...exception*/ |
68 | |
69 | #define ALTERA_UART_CONTROL_TRBK_MSK 0x0200 /* TX break */ |
70 | #define ALTERA_UART_CONTROL_DCTS_MSK 0x0400 /* Interrupt on CTS change */ |
71 | #define ALTERA_UART_CONTROL_RTS_MSK 0x0800 /* RTS signal */ |
72 | #define ALTERA_UART_CONTROL_EOP_MSK 0x1000 /* Interrupt on EOP */ |
73 | |
74 | /* |
75 | * Local per-uart structure. |
76 | */ |
77 | struct altera_uart { |
78 | struct uart_port port; |
79 | struct timer_list tmr; |
80 | unsigned int sigs; /* Local copy of line sigs */ |
81 | unsigned short imr; /* Local IMR mirror */ |
82 | }; |
83 | |
84 | static u32 altera_uart_readl(struct uart_port *port, int reg) |
85 | { |
86 | return readl(addr: port->membase + (reg << port->regshift)); |
87 | } |
88 | |
89 | static void altera_uart_writel(struct uart_port *port, u32 dat, int reg) |
90 | { |
91 | writel(val: dat, addr: port->membase + (reg << port->regshift)); |
92 | } |
93 | |
94 | static unsigned int altera_uart_tx_empty(struct uart_port *port) |
95 | { |
96 | return (altera_uart_readl(port, ALTERA_UART_STATUS_REG) & |
97 | ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0; |
98 | } |
99 | |
100 | static unsigned int altera_uart_get_mctrl(struct uart_port *port) |
101 | { |
102 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
103 | unsigned int sigs; |
104 | |
105 | sigs = (altera_uart_readl(port, ALTERA_UART_STATUS_REG) & |
106 | ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0; |
107 | sigs |= (pp->sigs & TIOCM_RTS); |
108 | |
109 | return sigs; |
110 | } |
111 | |
112 | static void altera_uart_update_ctrl_reg(struct altera_uart *pp) |
113 | { |
114 | unsigned short imr = pp->imr; |
115 | |
116 | /* |
117 | * If the device doesn't have an irq, ensure that the irq bits are |
118 | * masked out to keep the irq line inactive. |
119 | */ |
120 | if (!pp->port.irq) |
121 | imr &= ALTERA_UART_CONTROL_TRBK_MSK | ALTERA_UART_CONTROL_RTS_MSK; |
122 | |
123 | altera_uart_writel(port: &pp->port, dat: imr, ALTERA_UART_CONTROL_REG); |
124 | } |
125 | |
126 | static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs) |
127 | { |
128 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
129 | |
130 | pp->sigs = sigs; |
131 | if (sigs & TIOCM_RTS) |
132 | pp->imr |= ALTERA_UART_CONTROL_RTS_MSK; |
133 | else |
134 | pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK; |
135 | altera_uart_update_ctrl_reg(pp); |
136 | } |
137 | |
138 | static void altera_uart_start_tx(struct uart_port *port) |
139 | { |
140 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
141 | |
142 | pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK; |
143 | altera_uart_update_ctrl_reg(pp); |
144 | } |
145 | |
146 | static void altera_uart_stop_tx(struct uart_port *port) |
147 | { |
148 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
149 | |
150 | pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; |
151 | altera_uart_update_ctrl_reg(pp); |
152 | } |
153 | |
154 | static void altera_uart_stop_rx(struct uart_port *port) |
155 | { |
156 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
157 | |
158 | pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK; |
159 | altera_uart_update_ctrl_reg(pp); |
160 | } |
161 | |
162 | static void altera_uart_break_ctl(struct uart_port *port, int break_state) |
163 | { |
164 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
165 | unsigned long flags; |
166 | |
167 | uart_port_lock_irqsave(up: port, flags: &flags); |
168 | if (break_state == -1) |
169 | pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK; |
170 | else |
171 | pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK; |
172 | altera_uart_update_ctrl_reg(pp); |
173 | uart_port_unlock_irqrestore(up: port, flags); |
174 | } |
175 | |
176 | static void altera_uart_set_termios(struct uart_port *port, |
177 | struct ktermios *termios, |
178 | const struct ktermios *old) |
179 | { |
180 | unsigned long flags; |
181 | unsigned int baud, baudclk; |
182 | |
183 | baud = uart_get_baud_rate(port, termios, old, min: 0, max: 4000000); |
184 | baudclk = port->uartclk / baud; |
185 | |
186 | if (old) |
187 | tty_termios_copy_hw(new: termios, old); |
188 | tty_termios_encode_baud_rate(termios, ibaud: baud, obaud: baud); |
189 | |
190 | uart_port_lock_irqsave(up: port, flags: &flags); |
191 | uart_update_timeout(port, cflag: termios->c_cflag, baud); |
192 | altera_uart_writel(port, dat: baudclk, ALTERA_UART_DIVISOR_REG); |
193 | uart_port_unlock_irqrestore(up: port, flags); |
194 | |
195 | /* |
196 | * FIXME: port->read_status_mask and port->ignore_status_mask |
197 | * need to be initialized based on termios settings for |
198 | * INPCK, IGNBRK, IGNPAR, PARMRK, BRKINT |
199 | */ |
200 | } |
201 | |
202 | static void altera_uart_rx_chars(struct uart_port *port) |
203 | { |
204 | unsigned short status; |
205 | u8 ch, flag; |
206 | |
207 | while ((status = altera_uart_readl(port, ALTERA_UART_STATUS_REG)) & |
208 | ALTERA_UART_STATUS_RRDY_MSK) { |
209 | ch = altera_uart_readl(port, ALTERA_UART_RXDATA_REG); |
210 | flag = TTY_NORMAL; |
211 | port->icount.rx++; |
212 | |
213 | if (status & ALTERA_UART_STATUS_E_MSK) { |
214 | altera_uart_writel(port, dat: status, |
215 | ALTERA_UART_STATUS_REG); |
216 | |
217 | if (status & ALTERA_UART_STATUS_BRK_MSK) { |
218 | port->icount.brk++; |
219 | if (uart_handle_break(port)) |
220 | continue; |
221 | } else if (status & ALTERA_UART_STATUS_PE_MSK) { |
222 | port->icount.parity++; |
223 | } else if (status & ALTERA_UART_STATUS_ROE_MSK) { |
224 | port->icount.overrun++; |
225 | } else if (status & ALTERA_UART_STATUS_FE_MSK) { |
226 | port->icount.frame++; |
227 | } |
228 | |
229 | status &= port->read_status_mask; |
230 | |
231 | if (status & ALTERA_UART_STATUS_BRK_MSK) |
232 | flag = TTY_BREAK; |
233 | else if (status & ALTERA_UART_STATUS_PE_MSK) |
234 | flag = TTY_PARITY; |
235 | else if (status & ALTERA_UART_STATUS_FE_MSK) |
236 | flag = TTY_FRAME; |
237 | } |
238 | |
239 | if (uart_handle_sysrq_char(port, ch)) |
240 | continue; |
241 | uart_insert_char(port, status, ALTERA_UART_STATUS_ROE_MSK, ch, |
242 | flag); |
243 | } |
244 | |
245 | tty_flip_buffer_push(port: &port->state->port); |
246 | } |
247 | |
248 | static void altera_uart_tx_chars(struct uart_port *port) |
249 | { |
250 | u8 ch; |
251 | |
252 | uart_port_tx(port, ch, |
253 | altera_uart_readl(port, ALTERA_UART_STATUS_REG) & |
254 | ALTERA_UART_STATUS_TRDY_MSK, |
255 | altera_uart_writel(port, ch, ALTERA_UART_TXDATA_REG)); |
256 | } |
257 | |
258 | static irqreturn_t altera_uart_interrupt(int irq, void *data) |
259 | { |
260 | struct uart_port *port = data; |
261 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
262 | unsigned long flags; |
263 | unsigned int isr; |
264 | |
265 | isr = altera_uart_readl(port, ALTERA_UART_STATUS_REG) & pp->imr; |
266 | |
267 | uart_port_lock_irqsave(up: port, flags: &flags); |
268 | if (isr & ALTERA_UART_STATUS_RRDY_MSK) |
269 | altera_uart_rx_chars(port); |
270 | if (isr & ALTERA_UART_STATUS_TRDY_MSK) |
271 | altera_uart_tx_chars(port); |
272 | uart_port_unlock_irqrestore(up: port, flags); |
273 | |
274 | return IRQ_RETVAL(isr); |
275 | } |
276 | |
277 | static void altera_uart_timer(struct timer_list *t) |
278 | { |
279 | struct altera_uart *pp = from_timer(pp, t, tmr); |
280 | struct uart_port *port = &pp->port; |
281 | |
282 | altera_uart_interrupt(irq: 0, data: port); |
283 | mod_timer(timer: &pp->tmr, expires: jiffies + uart_poll_timeout(port)); |
284 | } |
285 | |
286 | static void altera_uart_config_port(struct uart_port *port, int flags) |
287 | { |
288 | port->type = PORT_ALTERA_UART; |
289 | |
290 | /* Clear mask, so no surprise interrupts. */ |
291 | altera_uart_writel(port, dat: 0, ALTERA_UART_CONTROL_REG); |
292 | /* Clear status register */ |
293 | altera_uart_writel(port, dat: 0, ALTERA_UART_STATUS_REG); |
294 | } |
295 | |
296 | static int altera_uart_startup(struct uart_port *port) |
297 | { |
298 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
299 | unsigned long flags; |
300 | |
301 | if (!port->irq) { |
302 | timer_setup(&pp->tmr, altera_uart_timer, 0); |
303 | mod_timer(timer: &pp->tmr, expires: jiffies + uart_poll_timeout(port)); |
304 | } else { |
305 | int ret; |
306 | |
307 | ret = request_irq(irq: port->irq, handler: altera_uart_interrupt, flags: 0, |
308 | DRV_NAME, dev: port); |
309 | if (ret) { |
310 | pr_err(DRV_NAME ": unable to attach Altera UART %d " |
311 | "interrupt vector=%d\n" , port->line, port->irq); |
312 | return ret; |
313 | } |
314 | } |
315 | |
316 | uart_port_lock_irqsave(up: port, flags: &flags); |
317 | |
318 | /* Enable RX interrupts now */ |
319 | pp->imr = ALTERA_UART_CONTROL_RRDY_MSK; |
320 | altera_uart_update_ctrl_reg(pp); |
321 | |
322 | uart_port_unlock_irqrestore(up: port, flags); |
323 | |
324 | return 0; |
325 | } |
326 | |
327 | static void altera_uart_shutdown(struct uart_port *port) |
328 | { |
329 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
330 | unsigned long flags; |
331 | |
332 | uart_port_lock_irqsave(up: port, flags: &flags); |
333 | |
334 | /* Disable all interrupts now */ |
335 | pp->imr = 0; |
336 | altera_uart_update_ctrl_reg(pp); |
337 | |
338 | uart_port_unlock_irqrestore(up: port, flags); |
339 | |
340 | if (port->irq) |
341 | free_irq(port->irq, port); |
342 | else |
343 | del_timer_sync(timer: &pp->tmr); |
344 | } |
345 | |
346 | static const char *altera_uart_type(struct uart_port *port) |
347 | { |
348 | return (port->type == PORT_ALTERA_UART) ? "Altera UART" : NULL; |
349 | } |
350 | |
351 | static int altera_uart_request_port(struct uart_port *port) |
352 | { |
353 | /* UARTs always present */ |
354 | return 0; |
355 | } |
356 | |
357 | static void altera_uart_release_port(struct uart_port *port) |
358 | { |
359 | /* Nothing to release... */ |
360 | } |
361 | |
362 | static int altera_uart_verify_port(struct uart_port *port, |
363 | struct serial_struct *ser) |
364 | { |
365 | if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_ALTERA_UART)) |
366 | return -EINVAL; |
367 | return 0; |
368 | } |
369 | |
370 | #ifdef CONFIG_CONSOLE_POLL |
371 | static int altera_uart_poll_get_char(struct uart_port *port) |
372 | { |
373 | while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & |
374 | ALTERA_UART_STATUS_RRDY_MSK)) |
375 | cpu_relax(); |
376 | |
377 | return altera_uart_readl(port, ALTERA_UART_RXDATA_REG); |
378 | } |
379 | |
380 | static void altera_uart_poll_put_char(struct uart_port *port, unsigned char c) |
381 | { |
382 | while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & |
383 | ALTERA_UART_STATUS_TRDY_MSK)) |
384 | cpu_relax(); |
385 | |
386 | altera_uart_writel(port, dat: c, ALTERA_UART_TXDATA_REG); |
387 | } |
388 | #endif |
389 | |
390 | /* |
391 | * Define the basic serial functions we support. |
392 | */ |
393 | static const struct uart_ops altera_uart_ops = { |
394 | .tx_empty = altera_uart_tx_empty, |
395 | .get_mctrl = altera_uart_get_mctrl, |
396 | .set_mctrl = altera_uart_set_mctrl, |
397 | .start_tx = altera_uart_start_tx, |
398 | .stop_tx = altera_uart_stop_tx, |
399 | .stop_rx = altera_uart_stop_rx, |
400 | .break_ctl = altera_uart_break_ctl, |
401 | .startup = altera_uart_startup, |
402 | .shutdown = altera_uart_shutdown, |
403 | .set_termios = altera_uart_set_termios, |
404 | .type = altera_uart_type, |
405 | .request_port = altera_uart_request_port, |
406 | .release_port = altera_uart_release_port, |
407 | .config_port = altera_uart_config_port, |
408 | .verify_port = altera_uart_verify_port, |
409 | #ifdef CONFIG_CONSOLE_POLL |
410 | .poll_get_char = altera_uart_poll_get_char, |
411 | .poll_put_char = altera_uart_poll_put_char, |
412 | #endif |
413 | }; |
414 | |
415 | static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS]; |
416 | |
417 | #if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) |
418 | |
419 | static void altera_uart_console_putc(struct uart_port *port, unsigned char c) |
420 | { |
421 | while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & |
422 | ALTERA_UART_STATUS_TRDY_MSK)) |
423 | cpu_relax(); |
424 | |
425 | altera_uart_writel(port, dat: c, ALTERA_UART_TXDATA_REG); |
426 | } |
427 | |
428 | static void altera_uart_console_write(struct console *co, const char *s, |
429 | unsigned int count) |
430 | { |
431 | struct uart_port *port = &(altera_uart_ports + co->index)->port; |
432 | |
433 | uart_console_write(port, s, count, putchar: altera_uart_console_putc); |
434 | } |
435 | |
436 | static int __init altera_uart_console_setup(struct console *co, char *options) |
437 | { |
438 | struct uart_port *port; |
439 | int baud = CONFIG_SERIAL_ALTERA_UART_BAUDRATE; |
440 | int bits = 8; |
441 | int parity = 'n'; |
442 | int flow = 'n'; |
443 | |
444 | if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS) |
445 | return -EINVAL; |
446 | port = &altera_uart_ports[co->index].port; |
447 | if (!port->membase) |
448 | return -ENODEV; |
449 | |
450 | if (options) |
451 | uart_parse_options(options, baud: &baud, parity: &parity, bits: &bits, flow: &flow); |
452 | |
453 | return uart_set_options(port, co, baud, parity, bits, flow); |
454 | } |
455 | |
456 | static struct uart_driver altera_uart_driver; |
457 | |
458 | static struct console altera_uart_console = { |
459 | .name = "ttyAL" , |
460 | .write = altera_uart_console_write, |
461 | .device = uart_console_device, |
462 | .setup = altera_uart_console_setup, |
463 | .flags = CON_PRINTBUFFER, |
464 | .index = -1, |
465 | .data = &altera_uart_driver, |
466 | }; |
467 | |
468 | static int __init altera_uart_console_init(void) |
469 | { |
470 | register_console(&altera_uart_console); |
471 | return 0; |
472 | } |
473 | |
474 | console_initcall(altera_uart_console_init); |
475 | |
476 | #define ALTERA_UART_CONSOLE (&altera_uart_console) |
477 | |
478 | static void altera_uart_earlycon_write(struct console *co, const char *s, |
479 | unsigned int count) |
480 | { |
481 | struct earlycon_device *dev = co->data; |
482 | |
483 | uart_console_write(port: &dev->port, s, count, putchar: altera_uart_console_putc); |
484 | } |
485 | |
486 | static int __init altera_uart_earlycon_setup(struct earlycon_device *dev, |
487 | const char *options) |
488 | { |
489 | struct uart_port *port = &dev->port; |
490 | |
491 | if (!port->membase) |
492 | return -ENODEV; |
493 | |
494 | /* Enable RX interrupts now */ |
495 | altera_uart_writel(port, ALTERA_UART_CONTROL_RRDY_MSK, |
496 | ALTERA_UART_CONTROL_REG); |
497 | |
498 | if (dev->baud) { |
499 | unsigned int baudclk = port->uartclk / dev->baud; |
500 | |
501 | altera_uart_writel(port, dat: baudclk, ALTERA_UART_DIVISOR_REG); |
502 | } |
503 | |
504 | dev->con->write = altera_uart_earlycon_write; |
505 | return 0; |
506 | } |
507 | |
508 | OF_EARLYCON_DECLARE(uart, "altr,uart-1.0" , altera_uart_earlycon_setup); |
509 | |
510 | #else |
511 | |
512 | #define ALTERA_UART_CONSOLE NULL |
513 | |
514 | #endif /* CONFIG_SERIAL_ALTERA_UART_CONSOLE */ |
515 | |
516 | /* |
517 | * Define the altera_uart UART driver structure. |
518 | */ |
519 | static struct uart_driver altera_uart_driver = { |
520 | .owner = THIS_MODULE, |
521 | .driver_name = DRV_NAME, |
522 | .dev_name = "ttyAL" , |
523 | .major = SERIAL_ALTERA_MAJOR, |
524 | .minor = SERIAL_ALTERA_MINOR, |
525 | .nr = CONFIG_SERIAL_ALTERA_UART_MAXPORTS, |
526 | .cons = ALTERA_UART_CONSOLE, |
527 | }; |
528 | |
529 | static int altera_uart_probe(struct platform_device *pdev) |
530 | { |
531 | struct altera_uart_platform_uart *platp = dev_get_platdata(dev: &pdev->dev); |
532 | struct uart_port *port; |
533 | struct resource *res_mem; |
534 | int i = pdev->id; |
535 | int ret; |
536 | |
537 | /* if id is -1 scan for a free id and use that one */ |
538 | if (i == -1) { |
539 | for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++) |
540 | if (altera_uart_ports[i].port.mapbase == 0) |
541 | break; |
542 | } |
543 | |
544 | if (i < 0 || i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS) |
545 | return -EINVAL; |
546 | |
547 | port = &altera_uart_ports[i].port; |
548 | |
549 | res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
550 | if (res_mem) |
551 | port->mapbase = res_mem->start; |
552 | else if (platp) |
553 | port->mapbase = platp->mapbase; |
554 | else |
555 | return -EINVAL; |
556 | |
557 | ret = platform_get_irq_optional(pdev, 0); |
558 | if (ret < 0 && ret != -ENXIO) |
559 | return ret; |
560 | if (ret > 0) |
561 | port->irq = ret; |
562 | else if (platp) |
563 | port->irq = platp->irq; |
564 | |
565 | /* Check platform data first so we can override device node data */ |
566 | if (platp) |
567 | port->uartclk = platp->uartclk; |
568 | else { |
569 | ret = of_property_read_u32(np: pdev->dev.of_node, propname: "clock-frequency" , |
570 | out_value: &port->uartclk); |
571 | if (ret) |
572 | return ret; |
573 | } |
574 | |
575 | port->membase = ioremap(offset: port->mapbase, ALTERA_UART_SIZE); |
576 | if (!port->membase) |
577 | return -ENOMEM; |
578 | |
579 | if (platp) |
580 | port->regshift = platp->bus_shift; |
581 | else |
582 | port->regshift = 0; |
583 | |
584 | port->line = i; |
585 | port->type = PORT_ALTERA_UART; |
586 | port->iotype = SERIAL_IO_MEM; |
587 | port->ops = &altera_uart_ops; |
588 | port->flags = UPF_BOOT_AUTOCONF; |
589 | port->dev = &pdev->dev; |
590 | |
591 | platform_set_drvdata(pdev, data: port); |
592 | |
593 | uart_add_one_port(reg: &altera_uart_driver, port); |
594 | |
595 | return 0; |
596 | } |
597 | |
598 | static int altera_uart_remove(struct platform_device *pdev) |
599 | { |
600 | struct uart_port *port = platform_get_drvdata(pdev); |
601 | |
602 | if (port) { |
603 | uart_remove_one_port(reg: &altera_uart_driver, port); |
604 | port->mapbase = 0; |
605 | iounmap(addr: port->membase); |
606 | } |
607 | |
608 | return 0; |
609 | } |
610 | |
611 | #ifdef CONFIG_OF |
612 | static const struct of_device_id altera_uart_match[] = { |
613 | { .compatible = "ALTR,uart-1.0" , }, |
614 | { .compatible = "altr,uart-1.0" , }, |
615 | {}, |
616 | }; |
617 | MODULE_DEVICE_TABLE(of, altera_uart_match); |
618 | #endif /* CONFIG_OF */ |
619 | |
620 | static struct platform_driver altera_uart_platform_driver = { |
621 | .probe = altera_uart_probe, |
622 | .remove = altera_uart_remove, |
623 | .driver = { |
624 | .name = DRV_NAME, |
625 | .of_match_table = of_match_ptr(altera_uart_match), |
626 | }, |
627 | }; |
628 | |
629 | static int __init altera_uart_init(void) |
630 | { |
631 | int rc; |
632 | |
633 | rc = uart_register_driver(uart: &altera_uart_driver); |
634 | if (rc) |
635 | return rc; |
636 | rc = platform_driver_register(&altera_uart_platform_driver); |
637 | if (rc) |
638 | uart_unregister_driver(uart: &altera_uart_driver); |
639 | return rc; |
640 | } |
641 | |
642 | static void __exit altera_uart_exit(void) |
643 | { |
644 | platform_driver_unregister(&altera_uart_platform_driver); |
645 | uart_unregister_driver(uart: &altera_uart_driver); |
646 | } |
647 | |
648 | module_init(altera_uart_init); |
649 | module_exit(altera_uart_exit); |
650 | |
651 | MODULE_DESCRIPTION("Altera UART driver" ); |
652 | MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>" ); |
653 | MODULE_LICENSE("GPL" ); |
654 | MODULE_ALIAS("platform:" DRV_NAME); |
655 | MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_ALTERA_MAJOR); |
656 | |