diff options
Diffstat (limited to 'drivers/serial/altera_uart.c')
-rw-r--r-- | drivers/serial/altera_uart.c | 156 |
1 files changed, 106 insertions, 50 deletions
diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c index f8d8a00554da..721216292a50 100644 --- a/drivers/serial/altera_uart.c +++ b/drivers/serial/altera_uart.c | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/timer.h> | ||
18 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
20 | #include <linux/console.h> | 21 | #include <linux/console.h> |
@@ -27,6 +28,8 @@ | |||
27 | #include <linux/altera_uart.h> | 28 | #include <linux/altera_uart.h> |
28 | 29 | ||
29 | #define DRV_NAME "altera_uart" | 30 | #define DRV_NAME "altera_uart" |
31 | #define SERIAL_ALTERA_MAJOR 204 | ||
32 | #define SERIAL_ALTERA_MINOR 213 | ||
30 | 33 | ||
31 | /* | 34 | /* |
32 | * Altera UART register definitions according to the Nios UART datasheet: | 35 | * Altera UART register definitions according to the Nios UART datasheet: |
@@ -76,13 +79,28 @@ | |||
76 | */ | 79 | */ |
77 | struct altera_uart { | 80 | struct altera_uart { |
78 | struct uart_port port; | 81 | struct uart_port port; |
82 | struct timer_list tmr; | ||
79 | unsigned int sigs; /* Local copy of line sigs */ | 83 | unsigned int sigs; /* Local copy of line sigs */ |
80 | unsigned short imr; /* Local IMR mirror */ | 84 | unsigned short imr; /* Local IMR mirror */ |
81 | }; | 85 | }; |
82 | 86 | ||
87 | static u32 altera_uart_readl(struct uart_port *port, int reg) | ||
88 | { | ||
89 | struct altera_uart_platform_uart *platp = port->private_data; | ||
90 | |||
91 | return readl(port->membase + (reg << platp->bus_shift)); | ||
92 | } | ||
93 | |||
94 | static void altera_uart_writel(struct uart_port *port, u32 dat, int reg) | ||
95 | { | ||
96 | struct altera_uart_platform_uart *platp = port->private_data; | ||
97 | |||
98 | writel(dat, port->membase + (reg << platp->bus_shift)); | ||
99 | } | ||
100 | |||
83 | static unsigned int altera_uart_tx_empty(struct uart_port *port) | 101 | static unsigned int altera_uart_tx_empty(struct uart_port *port) |
84 | { | 102 | { |
85 | return (readl(port->membase + ALTERA_UART_STATUS_REG) & | 103 | return (altera_uart_readl(port, ALTERA_UART_STATUS_REG) & |
86 | ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0; | 104 | ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0; |
87 | } | 105 | } |
88 | 106 | ||
@@ -91,8 +109,7 @@ static unsigned int altera_uart_get_mctrl(struct uart_port *port) | |||
91 | struct altera_uart *pp = container_of(port, struct altera_uart, port); | 109 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
92 | unsigned int sigs; | 110 | unsigned int sigs; |
93 | 111 | ||
94 | sigs = | 112 | sigs = (altera_uart_readl(port, ALTERA_UART_STATUS_REG) & |
95 | (readl(port->membase + ALTERA_UART_STATUS_REG) & | ||
96 | ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0; | 113 | ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0; |
97 | sigs |= (pp->sigs & TIOCM_RTS); | 114 | sigs |= (pp->sigs & TIOCM_RTS); |
98 | 115 | ||
@@ -108,7 +125,7 @@ static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs) | |||
108 | pp->imr |= ALTERA_UART_CONTROL_RTS_MSK; | 125 | pp->imr |= ALTERA_UART_CONTROL_RTS_MSK; |
109 | else | 126 | else |
110 | pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK; | 127 | pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK; |
111 | writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); | 128 | altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); |
112 | } | 129 | } |
113 | 130 | ||
114 | static void altera_uart_start_tx(struct uart_port *port) | 131 | static void altera_uart_start_tx(struct uart_port *port) |
@@ -116,7 +133,7 @@ static void altera_uart_start_tx(struct uart_port *port) | |||
116 | struct altera_uart *pp = container_of(port, struct altera_uart, port); | 133 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
117 | 134 | ||
118 | pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK; | 135 | pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK; |
119 | writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); | 136 | altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); |
120 | } | 137 | } |
121 | 138 | ||
122 | static void altera_uart_stop_tx(struct uart_port *port) | 139 | static void altera_uart_stop_tx(struct uart_port *port) |
@@ -124,7 +141,7 @@ static void altera_uart_stop_tx(struct uart_port *port) | |||
124 | struct altera_uart *pp = container_of(port, struct altera_uart, port); | 141 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
125 | 142 | ||
126 | pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; | 143 | pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; |
127 | writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); | 144 | altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); |
128 | } | 145 | } |
129 | 146 | ||
130 | static void altera_uart_stop_rx(struct uart_port *port) | 147 | static void altera_uart_stop_rx(struct uart_port *port) |
@@ -132,7 +149,7 @@ static void altera_uart_stop_rx(struct uart_port *port) | |||
132 | struct altera_uart *pp = container_of(port, struct altera_uart, port); | 149 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
133 | 150 | ||
134 | pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK; | 151 | pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK; |
135 | writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); | 152 | altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); |
136 | } | 153 | } |
137 | 154 | ||
138 | static void altera_uart_break_ctl(struct uart_port *port, int break_state) | 155 | static void altera_uart_break_ctl(struct uart_port *port, int break_state) |
@@ -145,7 +162,7 @@ static void altera_uart_break_ctl(struct uart_port *port, int break_state) | |||
145 | pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK; | 162 | pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK; |
146 | else | 163 | else |
147 | pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK; | 164 | pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK; |
148 | writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); | 165 | altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); |
149 | spin_unlock_irqrestore(&port->lock, flags); | 166 | spin_unlock_irqrestore(&port->lock, flags); |
150 | } | 167 | } |
151 | 168 | ||
@@ -168,7 +185,8 @@ static void altera_uart_set_termios(struct uart_port *port, | |||
168 | tty_termios_encode_baud_rate(termios, baud, baud); | 185 | tty_termios_encode_baud_rate(termios, baud, baud); |
169 | 186 | ||
170 | spin_lock_irqsave(&port->lock, flags); | 187 | spin_lock_irqsave(&port->lock, flags); |
171 | writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG); | 188 | uart_update_timeout(port, termios->c_cflag, baud); |
189 | altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG); | ||
172 | spin_unlock_irqrestore(&port->lock, flags); | 190 | spin_unlock_irqrestore(&port->lock, flags); |
173 | } | 191 | } |
174 | 192 | ||
@@ -178,14 +196,15 @@ static void altera_uart_rx_chars(struct altera_uart *pp) | |||
178 | unsigned char ch, flag; | 196 | unsigned char ch, flag; |
179 | unsigned short status; | 197 | unsigned short status; |
180 | 198 | ||
181 | while ((status = readl(port->membase + ALTERA_UART_STATUS_REG)) & | 199 | while ((status = altera_uart_readl(port, ALTERA_UART_STATUS_REG)) & |
182 | ALTERA_UART_STATUS_RRDY_MSK) { | 200 | ALTERA_UART_STATUS_RRDY_MSK) { |
183 | ch = readl(port->membase + ALTERA_UART_RXDATA_REG); | 201 | ch = altera_uart_readl(port, ALTERA_UART_RXDATA_REG); |
184 | flag = TTY_NORMAL; | 202 | flag = TTY_NORMAL; |
185 | port->icount.rx++; | 203 | port->icount.rx++; |
186 | 204 | ||
187 | if (status & ALTERA_UART_STATUS_E_MSK) { | 205 | if (status & ALTERA_UART_STATUS_E_MSK) { |
188 | writel(status, port->membase + ALTERA_UART_STATUS_REG); | 206 | altera_uart_writel(port, status, |
207 | ALTERA_UART_STATUS_REG); | ||
189 | 208 | ||
190 | if (status & ALTERA_UART_STATUS_BRK_MSK) { | 209 | if (status & ALTERA_UART_STATUS_BRK_MSK) { |
191 | port->icount.brk++; | 210 | port->icount.brk++; |
@@ -225,18 +244,18 @@ static void altera_uart_tx_chars(struct altera_uart *pp) | |||
225 | 244 | ||
226 | if (port->x_char) { | 245 | if (port->x_char) { |
227 | /* Send special char - probably flow control */ | 246 | /* Send special char - probably flow control */ |
228 | writel(port->x_char, port->membase + ALTERA_UART_TXDATA_REG); | 247 | altera_uart_writel(port, port->x_char, ALTERA_UART_TXDATA_REG); |
229 | port->x_char = 0; | 248 | port->x_char = 0; |
230 | port->icount.tx++; | 249 | port->icount.tx++; |
231 | return; | 250 | return; |
232 | } | 251 | } |
233 | 252 | ||
234 | while (readl(port->membase + ALTERA_UART_STATUS_REG) & | 253 | while (altera_uart_readl(port, ALTERA_UART_STATUS_REG) & |
235 | ALTERA_UART_STATUS_TRDY_MSK) { | 254 | ALTERA_UART_STATUS_TRDY_MSK) { |
236 | if (xmit->head == xmit->tail) | 255 | if (xmit->head == xmit->tail) |
237 | break; | 256 | break; |
238 | writel(xmit->buf[xmit->tail], | 257 | altera_uart_writel(port, xmit->buf[xmit->tail], |
239 | port->membase + ALTERA_UART_TXDATA_REG); | 258 | ALTERA_UART_TXDATA_REG); |
240 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 259 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
241 | port->icount.tx++; | 260 | port->icount.tx++; |
242 | } | 261 | } |
@@ -246,7 +265,7 @@ static void altera_uart_tx_chars(struct altera_uart *pp) | |||
246 | 265 | ||
247 | if (xmit->head == xmit->tail) { | 266 | if (xmit->head == xmit->tail) { |
248 | pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; | 267 | pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; |
249 | writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); | 268 | altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); |
250 | } | 269 | } |
251 | } | 270 | } |
252 | 271 | ||
@@ -256,7 +275,7 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data) | |||
256 | struct altera_uart *pp = container_of(port, struct altera_uart, port); | 275 | struct altera_uart *pp = container_of(port, struct altera_uart, port); |
257 | unsigned int isr; | 276 | unsigned int isr; |
258 | 277 | ||
259 | isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr; | 278 | isr = altera_uart_readl(port, ALTERA_UART_STATUS_REG) & pp->imr; |
260 | 279 | ||
261 | spin_lock(&port->lock); | 280 | spin_lock(&port->lock); |
262 | if (isr & ALTERA_UART_STATUS_RRDY_MSK) | 281 | if (isr & ALTERA_UART_STATUS_RRDY_MSK) |
@@ -268,14 +287,23 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data) | |||
268 | return IRQ_RETVAL(isr); | 287 | return IRQ_RETVAL(isr); |
269 | } | 288 | } |
270 | 289 | ||
290 | static void altera_uart_timer(unsigned long data) | ||
291 | { | ||
292 | struct uart_port *port = (void *)data; | ||
293 | struct altera_uart *pp = container_of(port, struct altera_uart, port); | ||
294 | |||
295 | altera_uart_interrupt(0, port); | ||
296 | mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port)); | ||
297 | } | ||
298 | |||
271 | static void altera_uart_config_port(struct uart_port *port, int flags) | 299 | static void altera_uart_config_port(struct uart_port *port, int flags) |
272 | { | 300 | { |
273 | port->type = PORT_ALTERA_UART; | 301 | port->type = PORT_ALTERA_UART; |
274 | 302 | ||
275 | /* Clear mask, so no surprise interrupts. */ | 303 | /* Clear mask, so no surprise interrupts. */ |
276 | writel(0, port->membase + ALTERA_UART_CONTROL_REG); | 304 | altera_uart_writel(port, 0, ALTERA_UART_CONTROL_REG); |
277 | /* Clear status register */ | 305 | /* Clear status register */ |
278 | writel(0, port->membase + ALTERA_UART_STATUS_REG); | 306 | altera_uart_writel(port, 0, ALTERA_UART_STATUS_REG); |
279 | } | 307 | } |
280 | 308 | ||
281 | static int altera_uart_startup(struct uart_port *port) | 309 | static int altera_uart_startup(struct uart_port *port) |
@@ -284,6 +312,12 @@ static int altera_uart_startup(struct uart_port *port) | |||
284 | unsigned long flags; | 312 | unsigned long flags; |
285 | int ret; | 313 | int ret; |
286 | 314 | ||
315 | if (!port->irq) { | ||
316 | setup_timer(&pp->tmr, altera_uart_timer, (unsigned long)port); | ||
317 | mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port)); | ||
318 | return 0; | ||
319 | } | ||
320 | |||
287 | ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED, | 321 | ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED, |
288 | DRV_NAME, port); | 322 | DRV_NAME, port); |
289 | if (ret) { | 323 | if (ret) { |
@@ -316,7 +350,10 @@ static void altera_uart_shutdown(struct uart_port *port) | |||
316 | 350 | ||
317 | spin_unlock_irqrestore(&port->lock, flags); | 351 | spin_unlock_irqrestore(&port->lock, flags); |
318 | 352 | ||
319 | free_irq(port->irq, port); | 353 | if (port->irq) |
354 | free_irq(port->irq, port); | ||
355 | else | ||
356 | del_timer_sync(&pp->tmr); | ||
320 | } | 357 | } |
321 | 358 | ||
322 | static const char *altera_uart_type(struct uart_port *port) | 359 | static const char *altera_uart_type(struct uart_port *port) |
@@ -384,8 +421,9 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp) | |||
384 | port->iotype = SERIAL_IO_MEM; | 421 | port->iotype = SERIAL_IO_MEM; |
385 | port->irq = platp[i].irq; | 422 | port->irq = platp[i].irq; |
386 | port->uartclk = platp[i].uartclk; | 423 | port->uartclk = platp[i].uartclk; |
387 | port->flags = ASYNC_BOOT_AUTOCONF; | 424 | port->flags = UPF_BOOT_AUTOCONF; |
388 | port->ops = &altera_uart_ops; | 425 | port->ops = &altera_uart_ops; |
426 | port->private_data = platp; | ||
389 | } | 427 | } |
390 | 428 | ||
391 | return 0; | 429 | return 0; |
@@ -393,7 +431,7 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp) | |||
393 | 431 | ||
394 | static void altera_uart_console_putc(struct uart_port *port, const char c) | 432 | static void altera_uart_console_putc(struct uart_port *port, const char c) |
395 | { | 433 | { |
396 | while (!(readl(port->membase + ALTERA_UART_STATUS_REG) & | 434 | while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & |
397 | ALTERA_UART_STATUS_TRDY_MSK)) | 435 | ALTERA_UART_STATUS_TRDY_MSK)) |
398 | cpu_relax(); | 436 | cpu_relax(); |
399 | 437 | ||
@@ -423,7 +461,7 @@ static int __init altera_uart_console_setup(struct console *co, char *options) | |||
423 | if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS) | 461 | if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS) |
424 | return -EINVAL; | 462 | return -EINVAL; |
425 | port = &altera_uart_ports[co->index].port; | 463 | port = &altera_uart_ports[co->index].port; |
426 | if (port->membase == 0) | 464 | if (!port->membase) |
427 | return -ENODEV; | 465 | return -ENODEV; |
428 | 466 | ||
429 | if (options) | 467 | if (options) |
@@ -435,7 +473,7 @@ static int __init altera_uart_console_setup(struct console *co, char *options) | |||
435 | static struct uart_driver altera_uart_driver; | 473 | static struct uart_driver altera_uart_driver; |
436 | 474 | ||
437 | static struct console altera_uart_console = { | 475 | static struct console altera_uart_console = { |
438 | .name = "ttyS", | 476 | .name = "ttyAL", |
439 | .write = altera_uart_console_write, | 477 | .write = altera_uart_console_write, |
440 | .device = uart_console_device, | 478 | .device = uart_console_device, |
441 | .setup = altera_uart_console_setup, | 479 | .setup = altera_uart_console_setup, |
@@ -466,9 +504,9 @@ console_initcall(altera_uart_console_init); | |||
466 | static struct uart_driver altera_uart_driver = { | 504 | static struct uart_driver altera_uart_driver = { |
467 | .owner = THIS_MODULE, | 505 | .owner = THIS_MODULE, |
468 | .driver_name = DRV_NAME, | 506 | .driver_name = DRV_NAME, |
469 | .dev_name = "ttyS", | 507 | .dev_name = "ttyAL", |
470 | .major = TTY_MAJOR, | 508 | .major = SERIAL_ALTERA_MAJOR, |
471 | .minor = 64, | 509 | .minor = SERIAL_ALTERA_MINOR, |
472 | .nr = CONFIG_SERIAL_ALTERA_UART_MAXPORTS, | 510 | .nr = CONFIG_SERIAL_ALTERA_UART_MAXPORTS, |
473 | .cons = ALTERA_UART_CONSOLE, | 511 | .cons = ALTERA_UART_CONSOLE, |
474 | }; | 512 | }; |
@@ -477,38 +515,55 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) | |||
477 | { | 515 | { |
478 | struct altera_uart_platform_uart *platp = pdev->dev.platform_data; | 516 | struct altera_uart_platform_uart *platp = pdev->dev.platform_data; |
479 | struct uart_port *port; | 517 | struct uart_port *port; |
480 | int i; | 518 | struct resource *res_mem; |
519 | struct resource *res_irq; | ||
520 | int i = pdev->id; | ||
481 | 521 | ||
482 | for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) { | 522 | /* -1 emphasizes that the platform must have one port, no .N suffix */ |
483 | port = &altera_uart_ports[i].port; | 523 | if (i == -1) |
524 | i = 0; | ||
484 | 525 | ||
485 | port->line = i; | 526 | if (i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS) |
486 | port->type = PORT_ALTERA_UART; | 527 | return -EINVAL; |
487 | port->mapbase = platp[i].mapbase; | ||
488 | port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE); | ||
489 | port->iotype = SERIAL_IO_MEM; | ||
490 | port->irq = platp[i].irq; | ||
491 | port->uartclk = platp[i].uartclk; | ||
492 | port->ops = &altera_uart_ops; | ||
493 | port->flags = ASYNC_BOOT_AUTOCONF; | ||
494 | 528 | ||
495 | uart_add_one_port(&altera_uart_driver, port); | 529 | port = &altera_uart_ports[i].port; |
496 | } | 530 | |
531 | res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
532 | if (res_mem) | ||
533 | port->mapbase = res_mem->start; | ||
534 | else if (platp->mapbase) | ||
535 | port->mapbase = platp->mapbase; | ||
536 | else | ||
537 | return -EINVAL; | ||
538 | |||
539 | res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
540 | if (res_irq) | ||
541 | port->irq = res_irq->start; | ||
542 | else if (platp->irq) | ||
543 | port->irq = platp->irq; | ||
544 | |||
545 | port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE); | ||
546 | if (!port->membase) | ||
547 | return -ENOMEM; | ||
548 | |||
549 | port->line = i; | ||
550 | port->type = PORT_ALTERA_UART; | ||
551 | port->iotype = SERIAL_IO_MEM; | ||
552 | port->uartclk = platp->uartclk; | ||
553 | port->ops = &altera_uart_ops; | ||
554 | port->flags = UPF_BOOT_AUTOCONF; | ||
555 | port->private_data = platp; | ||
556 | |||
557 | uart_add_one_port(&altera_uart_driver, port); | ||
497 | 558 | ||
498 | return 0; | 559 | return 0; |
499 | } | 560 | } |
500 | 561 | ||
501 | static int __devexit altera_uart_remove(struct platform_device *pdev) | 562 | static int __devexit altera_uart_remove(struct platform_device *pdev) |
502 | { | 563 | { |
503 | struct uart_port *port; | 564 | struct uart_port *port = &altera_uart_ports[pdev->id].port; |
504 | int i; | ||
505 | |||
506 | for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++) { | ||
507 | port = &altera_uart_ports[i].port; | ||
508 | if (port) | ||
509 | uart_remove_one_port(&altera_uart_driver, port); | ||
510 | } | ||
511 | 565 | ||
566 | uart_remove_one_port(&altera_uart_driver, port); | ||
512 | return 0; | 567 | return 0; |
513 | } | 568 | } |
514 | 569 | ||
@@ -550,3 +605,4 @@ MODULE_DESCRIPTION("Altera UART driver"); | |||
550 | MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>"); | 605 | MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>"); |
551 | MODULE_LICENSE("GPL"); | 606 | MODULE_LICENSE("GPL"); |
552 | MODULE_ALIAS("platform:" DRV_NAME); | 607 | MODULE_ALIAS("platform:" DRV_NAME); |
608 | MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_ALTERA_MAJOR); | ||