aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/sccnxp.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 16:41:04 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 16:41:04 -0500
commit21eaab6d19ed43e82ed39c8deb7f192134fb4a0e (patch)
treed995205afdcb7f47462bcd28067dc0c4ab0b7b02 /drivers/tty/serial/sccnxp.c
parent74e1a2a39355b2d3ae8c60c78d8add162c6d7183 (diff)
parent9e17df37d710f8998e9cb10a548304fe33d4a5c2 (diff)
Merge tag 'tty-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial patches from Greg Kroah-Hartman: "Here's the big tty/serial driver patches for 3.9-rc1. More tty port rework and fixes from Jiri here, as well as lots of individual serial driver updates and fixes. All of these have been in the linux-next tree for a while." * tag 'tty-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (140 commits) tty: mxser: improve error handling in mxser_probe() and mxser_module_init() serial: imx: fix uninitialized variable warning serial: tegra: assume CONFIG_OF TTY: do not update atime/mtime on read/write lguest: select CONFIG_TTY to build properly. ARM defconfigs: add missing inclusions of linux/platform_device.h fb/exynos: include platform_device.h ARM: sa1100/assabet: include platform_device.h directly serial: imx: Fix recursive locking bug pps: Fix build breakage from decoupling pps from tty tty: Remove ancient hardpps() pps: Additional cleanups in uart_handle_dcd_change pps: Move timestamp read into PPS code proper pps: Don't crash the machine when exiting will do pps: Fix a use-after free bug when unregistering a source. pps: Use pps_lookup_dev to reduce ldisc coupling pps: Add pps_lookup_dev() function tty: serial: uartlite: Support uartlite on big and little endian systems tty: serial: uartlite: Fix sparse and checkpatch warnings serial/arc-uart: Miscll DT related updates (Grant's review comments) ... Fix up trivial conflicts, mostly just due to the TTY config option clashing with the EXPERIMENTAL removal.
Diffstat (limited to 'drivers/tty/serial/sccnxp.c')
-rw-r--r--drivers/tty/serial/sccnxp.c171
1 files changed, 113 insertions, 58 deletions
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
index e869eab180be..08dbfb88d42c 100644
--- a/drivers/tty/serial/sccnxp.c
+++ b/drivers/tty/serial/sccnxp.c
@@ -24,8 +24,9 @@
24#include <linux/io.h> 24#include <linux/io.h>
25#include <linux/tty.h> 25#include <linux/tty.h>
26#include <linux/tty_flip.h> 26#include <linux/tty_flip.h>
27#include <linux/spinlock.h>
27#include <linux/platform_device.h> 28#include <linux/platform_device.h>
28#include <linux/platform_data/sccnxp.h> 29#include <linux/platform_data/serial-sccnxp.h>
29 30
30#define SCCNXP_NAME "uart-sccnxp" 31#define SCCNXP_NAME "uart-sccnxp"
31#define SCCNXP_MAJOR 204 32#define SCCNXP_MAJOR 204
@@ -107,6 +108,7 @@ enum {
107struct sccnxp_port { 108struct sccnxp_port {
108 struct uart_driver uart; 109 struct uart_driver uart;
109 struct uart_port port[SCCNXP_MAX_UARTS]; 110 struct uart_port port[SCCNXP_MAX_UARTS];
111 bool opened[SCCNXP_MAX_UARTS];
110 112
111 const char *name; 113 const char *name;
112 int irq; 114 int irq;
@@ -123,7 +125,10 @@ struct sccnxp_port {
123 struct console console; 125 struct console console;
124#endif 126#endif
125 127
126 struct mutex sccnxp_mutex; 128 spinlock_t lock;
129
130 bool poll;
131 struct timer_list timer;
127 132
128 struct sccnxp_pdata pdata; 133 struct sccnxp_pdata pdata;
129}; 134};
@@ -175,14 +180,12 @@ static int sccnxp_update_best_err(int a, int b, int *besterr)
175 return 1; 180 return 1;
176} 181}
177 182
178struct baud_table { 183static const struct {
179 u8 csr; 184 u8 csr;
180 u8 acr; 185 u8 acr;
181 u8 mr0; 186 u8 mr0;
182 int baud; 187 int baud;
183}; 188} baud_std[] = {
184
185const struct baud_table baud_std[] = {
186 { 0, ACR_BAUD0, MR0_BAUD_NORMAL, 50, }, 189 { 0, ACR_BAUD0, MR0_BAUD_NORMAL, 50, },
187 { 0, ACR_BAUD1, MR0_BAUD_NORMAL, 75, }, 190 { 0, ACR_BAUD1, MR0_BAUD_NORMAL, 75, },
188 { 1, ACR_BAUD0, MR0_BAUD_NORMAL, 110, }, 191 { 1, ACR_BAUD0, MR0_BAUD_NORMAL, 110, },
@@ -286,10 +289,6 @@ static void sccnxp_handle_rx(struct uart_port *port)
286{ 289{
287 u8 sr; 290 u8 sr;
288 unsigned int ch, flag; 291 unsigned int ch, flag;
289 struct tty_struct *tty = tty_port_tty_get(&port->state->port);
290
291 if (!tty)
292 return;
293 292
294 for (;;) { 293 for (;;) {
295 sr = sccnxp_port_read(port, SCCNXP_SR_REG); 294 sr = sccnxp_port_read(port, SCCNXP_SR_REG);
@@ -305,14 +304,19 @@ static void sccnxp_handle_rx(struct uart_port *port)
305 if (unlikely(sr)) { 304 if (unlikely(sr)) {
306 if (sr & SR_BRK) { 305 if (sr & SR_BRK) {
307 port->icount.brk++; 306 port->icount.brk++;
307 sccnxp_port_write(port, SCCNXP_CR_REG,
308 CR_CMD_BREAK_RESET);
308 if (uart_handle_break(port)) 309 if (uart_handle_break(port))
309 continue; 310 continue;
310 } else if (sr & SR_PE) 311 } else if (sr & SR_PE)
311 port->icount.parity++; 312 port->icount.parity++;
312 else if (sr & SR_FE) 313 else if (sr & SR_FE)
313 port->icount.frame++; 314 port->icount.frame++;
314 else if (sr & SR_OVR) 315 else if (sr & SR_OVR) {
315 port->icount.overrun++; 316 port->icount.overrun++;
317 sccnxp_port_write(port, SCCNXP_CR_REG,
318 CR_CMD_STATUS_RESET);
319 }
316 320
317 sr &= port->read_status_mask; 321 sr &= port->read_status_mask;
318 if (sr & SR_BRK) 322 if (sr & SR_BRK)
@@ -334,9 +338,7 @@ static void sccnxp_handle_rx(struct uart_port *port)
334 uart_insert_char(port, sr, SR_OVR, ch, flag); 338 uart_insert_char(port, sr, SR_OVR, ch, flag);
335 } 339 }
336 340
337 tty_flip_buffer_push(tty); 341 tty_flip_buffer_push(&port->state->port);
338
339 tty_kref_put(tty);
340} 342}
341 343
342static void sccnxp_handle_tx(struct uart_port *port) 344static void sccnxp_handle_tx(struct uart_port *port)
@@ -378,31 +380,48 @@ static void sccnxp_handle_tx(struct uart_port *port)
378 uart_write_wakeup(port); 380 uart_write_wakeup(port);
379} 381}
380 382
381static irqreturn_t sccnxp_ist(int irq, void *dev_id) 383static void sccnxp_handle_events(struct sccnxp_port *s)
382{ 384{
383 int i; 385 int i;
384 u8 isr; 386 u8 isr;
385 struct sccnxp_port *s = (struct sccnxp_port *)dev_id;
386
387 mutex_lock(&s->sccnxp_mutex);
388 387
389 for (;;) { 388 do {
390 isr = sccnxp_read(&s->port[0], SCCNXP_ISR_REG); 389 isr = sccnxp_read(&s->port[0], SCCNXP_ISR_REG);
391 isr &= s->imr; 390 isr &= s->imr;
392 if (!isr) 391 if (!isr)
393 break; 392 break;
394 393
395 dev_dbg(s->port[0].dev, "IRQ status: 0x%02x\n", isr);
396
397 for (i = 0; i < s->uart.nr; i++) { 394 for (i = 0; i < s->uart.nr; i++) {
398 if (isr & ISR_RXRDY(i)) 395 if (s->opened[i] && (isr & ISR_RXRDY(i)))
399 sccnxp_handle_rx(&s->port[i]); 396 sccnxp_handle_rx(&s->port[i]);
400 if (isr & ISR_TXRDY(i)) 397 if (s->opened[i] && (isr & ISR_TXRDY(i)))
401 sccnxp_handle_tx(&s->port[i]); 398 sccnxp_handle_tx(&s->port[i]);
402 } 399 }
403 } 400 } while (1);
401}
402
403static void sccnxp_timer(unsigned long data)
404{
405 struct sccnxp_port *s = (struct sccnxp_port *)data;
406 unsigned long flags;
404 407
405 mutex_unlock(&s->sccnxp_mutex); 408 spin_lock_irqsave(&s->lock, flags);
409 sccnxp_handle_events(s);
410 spin_unlock_irqrestore(&s->lock, flags);
411
412 if (!timer_pending(&s->timer))
413 mod_timer(&s->timer, jiffies +
414 usecs_to_jiffies(s->pdata.poll_time_us));
415}
416
417static irqreturn_t sccnxp_ist(int irq, void *dev_id)
418{
419 struct sccnxp_port *s = (struct sccnxp_port *)dev_id;
420 unsigned long flags;
421
422 spin_lock_irqsave(&s->lock, flags);
423 sccnxp_handle_events(s);
424 spin_unlock_irqrestore(&s->lock, flags);
406 425
407 return IRQ_HANDLED; 426 return IRQ_HANDLED;
408} 427}
@@ -410,8 +429,9 @@ static irqreturn_t sccnxp_ist(int irq, void *dev_id)
410static void sccnxp_start_tx(struct uart_port *port) 429static void sccnxp_start_tx(struct uart_port *port)
411{ 430{
412 struct sccnxp_port *s = dev_get_drvdata(port->dev); 431 struct sccnxp_port *s = dev_get_drvdata(port->dev);
432 unsigned long flags;
413 433
414 mutex_lock(&s->sccnxp_mutex); 434 spin_lock_irqsave(&s->lock, flags);
415 435
416 /* Set direction to output */ 436 /* Set direction to output */
417 if (s->flags & SCCNXP_HAVE_IO) 437 if (s->flags & SCCNXP_HAVE_IO)
@@ -419,7 +439,7 @@ static void sccnxp_start_tx(struct uart_port *port)
419 439
420 sccnxp_enable_irq(port, IMR_TXRDY); 440 sccnxp_enable_irq(port, IMR_TXRDY);
421 441
422 mutex_unlock(&s->sccnxp_mutex); 442 spin_unlock_irqrestore(&s->lock, flags);
423} 443}
424 444
425static void sccnxp_stop_tx(struct uart_port *port) 445static void sccnxp_stop_tx(struct uart_port *port)
@@ -430,20 +450,22 @@ static void sccnxp_stop_tx(struct uart_port *port)
430static void sccnxp_stop_rx(struct uart_port *port) 450static void sccnxp_stop_rx(struct uart_port *port)
431{ 451{
432 struct sccnxp_port *s = dev_get_drvdata(port->dev); 452 struct sccnxp_port *s = dev_get_drvdata(port->dev);
453 unsigned long flags;
433 454
434 mutex_lock(&s->sccnxp_mutex); 455 spin_lock_irqsave(&s->lock, flags);
435 sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE); 456 sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE);
436 mutex_unlock(&s->sccnxp_mutex); 457 spin_unlock_irqrestore(&s->lock, flags);
437} 458}
438 459
439static unsigned int sccnxp_tx_empty(struct uart_port *port) 460static unsigned int sccnxp_tx_empty(struct uart_port *port)
440{ 461{
441 u8 val; 462 u8 val;
463 unsigned long flags;
442 struct sccnxp_port *s = dev_get_drvdata(port->dev); 464 struct sccnxp_port *s = dev_get_drvdata(port->dev);
443 465
444 mutex_lock(&s->sccnxp_mutex); 466 spin_lock_irqsave(&s->lock, flags);
445 val = sccnxp_port_read(port, SCCNXP_SR_REG); 467 val = sccnxp_port_read(port, SCCNXP_SR_REG);
446 mutex_unlock(&s->sccnxp_mutex); 468 spin_unlock_irqrestore(&s->lock, flags);
447 469
448 return (val & SR_TXEMT) ? TIOCSER_TEMT : 0; 470 return (val & SR_TXEMT) ? TIOCSER_TEMT : 0;
449} 471}
@@ -456,28 +478,30 @@ static void sccnxp_enable_ms(struct uart_port *port)
456static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl) 478static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl)
457{ 479{
458 struct sccnxp_port *s = dev_get_drvdata(port->dev); 480 struct sccnxp_port *s = dev_get_drvdata(port->dev);
481 unsigned long flags;
459 482
460 if (!(s->flags & SCCNXP_HAVE_IO)) 483 if (!(s->flags & SCCNXP_HAVE_IO))
461 return; 484 return;
462 485
463 mutex_lock(&s->sccnxp_mutex); 486 spin_lock_irqsave(&s->lock, flags);
464 487
465 sccnxp_set_bit(port, DTR_OP, mctrl & TIOCM_DTR); 488 sccnxp_set_bit(port, DTR_OP, mctrl & TIOCM_DTR);
466 sccnxp_set_bit(port, RTS_OP, mctrl & TIOCM_RTS); 489 sccnxp_set_bit(port, RTS_OP, mctrl & TIOCM_RTS);
467 490
468 mutex_unlock(&s->sccnxp_mutex); 491 spin_unlock_irqrestore(&s->lock, flags);
469} 492}
470 493
471static unsigned int sccnxp_get_mctrl(struct uart_port *port) 494static unsigned int sccnxp_get_mctrl(struct uart_port *port)
472{ 495{
473 u8 bitmask, ipr; 496 u8 bitmask, ipr;
497 unsigned long flags;
474 struct sccnxp_port *s = dev_get_drvdata(port->dev); 498 struct sccnxp_port *s = dev_get_drvdata(port->dev);
475 unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR; 499 unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
476 500
477 if (!(s->flags & SCCNXP_HAVE_IO)) 501 if (!(s->flags & SCCNXP_HAVE_IO))
478 return mctrl; 502 return mctrl;
479 503
480 mutex_lock(&s->sccnxp_mutex); 504 spin_lock_irqsave(&s->lock, flags);
481 505
482 ipr = ~sccnxp_read(port, SCCNXP_IPCR_REG); 506 ipr = ~sccnxp_read(port, SCCNXP_IPCR_REG);
483 507
@@ -506,7 +530,7 @@ static unsigned int sccnxp_get_mctrl(struct uart_port *port)
506 mctrl |= (ipr & bitmask) ? TIOCM_RNG : 0; 530 mctrl |= (ipr & bitmask) ? TIOCM_RNG : 0;
507 } 531 }
508 532
509 mutex_unlock(&s->sccnxp_mutex); 533 spin_unlock_irqrestore(&s->lock, flags);
510 534
511 return mctrl; 535 return mctrl;
512} 536}
@@ -514,21 +538,23 @@ static unsigned int sccnxp_get_mctrl(struct uart_port *port)
514static void sccnxp_break_ctl(struct uart_port *port, int break_state) 538static void sccnxp_break_ctl(struct uart_port *port, int break_state)
515{ 539{
516 struct sccnxp_port *s = dev_get_drvdata(port->dev); 540 struct sccnxp_port *s = dev_get_drvdata(port->dev);
541 unsigned long flags;
517 542
518 mutex_lock(&s->sccnxp_mutex); 543 spin_lock_irqsave(&s->lock, flags);
519 sccnxp_port_write(port, SCCNXP_CR_REG, break_state ? 544 sccnxp_port_write(port, SCCNXP_CR_REG, break_state ?
520 CR_CMD_START_BREAK : CR_CMD_STOP_BREAK); 545 CR_CMD_START_BREAK : CR_CMD_STOP_BREAK);
521 mutex_unlock(&s->sccnxp_mutex); 546 spin_unlock_irqrestore(&s->lock, flags);
522} 547}
523 548
524static void sccnxp_set_termios(struct uart_port *port, 549static void sccnxp_set_termios(struct uart_port *port,
525 struct ktermios *termios, struct ktermios *old) 550 struct ktermios *termios, struct ktermios *old)
526{ 551{
527 struct sccnxp_port *s = dev_get_drvdata(port->dev); 552 struct sccnxp_port *s = dev_get_drvdata(port->dev);
553 unsigned long flags;
528 u8 mr1, mr2; 554 u8 mr1, mr2;
529 int baud; 555 int baud;
530 556
531 mutex_lock(&s->sccnxp_mutex); 557 spin_lock_irqsave(&s->lock, flags);
532 558
533 /* Mask termios capabilities we don't support */ 559 /* Mask termios capabilities we don't support */
534 termios->c_cflag &= ~CMSPAR; 560 termios->c_cflag &= ~CMSPAR;
@@ -595,20 +621,22 @@ static void sccnxp_set_termios(struct uart_port *port,
595 /* Update timeout according to new baud rate */ 621 /* Update timeout according to new baud rate */
596 uart_update_timeout(port, termios->c_cflag, baud); 622 uart_update_timeout(port, termios->c_cflag, baud);
597 623
624 /* Report actual baudrate back to core */
598 if (tty_termios_baud_rate(termios)) 625 if (tty_termios_baud_rate(termios))
599 tty_termios_encode_baud_rate(termios, baud, baud); 626 tty_termios_encode_baud_rate(termios, baud, baud);
600 627
601 /* Enable RX & TX */ 628 /* Enable RX & TX */
602 sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE); 629 sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE);
603 630
604 mutex_unlock(&s->sccnxp_mutex); 631 spin_unlock_irqrestore(&s->lock, flags);
605} 632}
606 633
607static int sccnxp_startup(struct uart_port *port) 634static int sccnxp_startup(struct uart_port *port)
608{ 635{
609 struct sccnxp_port *s = dev_get_drvdata(port->dev); 636 struct sccnxp_port *s = dev_get_drvdata(port->dev);
637 unsigned long flags;
610 638
611 mutex_lock(&s->sccnxp_mutex); 639 spin_lock_irqsave(&s->lock, flags);
612 640
613 if (s->flags & SCCNXP_HAVE_IO) { 641 if (s->flags & SCCNXP_HAVE_IO) {
614 /* Outputs are controlled manually */ 642 /* Outputs are controlled manually */
@@ -627,7 +655,9 @@ static int sccnxp_startup(struct uart_port *port)
627 /* Enable RX interrupt */ 655 /* Enable RX interrupt */
628 sccnxp_enable_irq(port, IMR_RXRDY); 656 sccnxp_enable_irq(port, IMR_RXRDY);
629 657
630 mutex_unlock(&s->sccnxp_mutex); 658 s->opened[port->line] = 1;
659
660 spin_unlock_irqrestore(&s->lock, flags);
631 661
632 return 0; 662 return 0;
633} 663}
@@ -635,8 +665,11 @@ static int sccnxp_startup(struct uart_port *port)
635static void sccnxp_shutdown(struct uart_port *port) 665static void sccnxp_shutdown(struct uart_port *port)
636{ 666{
637 struct sccnxp_port *s = dev_get_drvdata(port->dev); 667 struct sccnxp_port *s = dev_get_drvdata(port->dev);
668 unsigned long flags;
638 669
639 mutex_lock(&s->sccnxp_mutex); 670 spin_lock_irqsave(&s->lock, flags);
671
672 s->opened[port->line] = 0;
640 673
641 /* Disable interrupts */ 674 /* Disable interrupts */
642 sccnxp_disable_irq(port, IMR_TXRDY | IMR_RXRDY); 675 sccnxp_disable_irq(port, IMR_TXRDY | IMR_RXRDY);
@@ -648,7 +681,7 @@ static void sccnxp_shutdown(struct uart_port *port)
648 if (s->flags & SCCNXP_HAVE_IO) 681 if (s->flags & SCCNXP_HAVE_IO)
649 sccnxp_set_bit(port, DIR_OP, 0); 682 sccnxp_set_bit(port, DIR_OP, 0);
650 683
651 mutex_unlock(&s->sccnxp_mutex); 684 spin_unlock_irqrestore(&s->lock, flags);
652} 685}
653 686
654static const char *sccnxp_type(struct uart_port *port) 687static const char *sccnxp_type(struct uart_port *port)
@@ -722,10 +755,11 @@ static void sccnxp_console_write(struct console *co, const char *c, unsigned n)
722{ 755{
723 struct sccnxp_port *s = (struct sccnxp_port *)co->data; 756 struct sccnxp_port *s = (struct sccnxp_port *)co->data;
724 struct uart_port *port = &s->port[co->index]; 757 struct uart_port *port = &s->port[co->index];
758 unsigned long flags;
725 759
726 mutex_lock(&s->sccnxp_mutex); 760 spin_lock_irqsave(&s->lock, flags);
727 uart_console_write(port, c, n, sccnxp_console_putchar); 761 uart_console_write(port, c, n, sccnxp_console_putchar);
728 mutex_unlock(&s->sccnxp_mutex); 762 spin_unlock_irqrestore(&s->lock, flags);
729} 763}
730 764
731static int sccnxp_console_setup(struct console *co, char *options) 765static int sccnxp_console_setup(struct console *co, char *options)
@@ -764,7 +798,7 @@ static int sccnxp_probe(struct platform_device *pdev)
764 } 798 }
765 platform_set_drvdata(pdev, s); 799 platform_set_drvdata(pdev, s);
766 800
767 mutex_init(&s->sccnxp_mutex); 801 spin_lock_init(&s->lock);
768 802
769 /* Individual chip settings */ 803 /* Individual chip settings */
770 switch (chiptype) { 804 switch (chiptype) {
@@ -861,11 +895,19 @@ static int sccnxp_probe(struct platform_device *pdev)
861 } else 895 } else
862 memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata)); 896 memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata));
863 897
864 s->irq = platform_get_irq(pdev, 0); 898 if (s->pdata.poll_time_us) {
865 if (s->irq <= 0) { 899 dev_info(&pdev->dev, "Using poll mode, resolution %u usecs\n",
866 dev_err(&pdev->dev, "Missing irq resource data\n"); 900 s->pdata.poll_time_us);
867 ret = -ENXIO; 901 s->poll = 1;
868 goto err_out; 902 }
903
904 if (!s->poll) {
905 s->irq = platform_get_irq(pdev, 0);
906 if (s->irq < 0) {
907 dev_err(&pdev->dev, "Missing irq resource data\n");
908 ret = -ENXIO;
909 goto err_out;
910 }
869 } 911 }
870 912
871 /* Check input frequency */ 913 /* Check input frequency */
@@ -929,13 +971,23 @@ static int sccnxp_probe(struct platform_device *pdev)
929 if (s->pdata.init) 971 if (s->pdata.init)
930 s->pdata.init(); 972 s->pdata.init();
931 973
932 ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL, sccnxp_ist, 974 if (!s->poll) {
933 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 975 ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL,
934 dev_name(&pdev->dev), s); 976 sccnxp_ist,
935 if (!ret) 977 IRQF_TRIGGER_FALLING |
978 IRQF_ONESHOT,
979 dev_name(&pdev->dev), s);
980 if (!ret)
981 return 0;
982
983 dev_err(&pdev->dev, "Unable to reguest IRQ %i\n", s->irq);
984 } else {
985 init_timer(&s->timer);
986 setup_timer(&s->timer, sccnxp_timer, (unsigned long)s);
987 mod_timer(&s->timer, jiffies +
988 usecs_to_jiffies(s->pdata.poll_time_us));
936 return 0; 989 return 0;
937 990 }
938 dev_err(&pdev->dev, "Unable to reguest IRQ %i\n", s->irq);
939 991
940err_out: 992err_out:
941 platform_set_drvdata(pdev, NULL); 993 platform_set_drvdata(pdev, NULL);
@@ -948,7 +1000,10 @@ static int sccnxp_remove(struct platform_device *pdev)
948 int i; 1000 int i;
949 struct sccnxp_port *s = platform_get_drvdata(pdev); 1001 struct sccnxp_port *s = platform_get_drvdata(pdev);
950 1002
951 devm_free_irq(&pdev->dev, s->irq, s); 1003 if (!s->poll)
1004 devm_free_irq(&pdev->dev, s->irq, s);
1005 else
1006 del_timer_sync(&s->timer);
952 1007
953 for (i = 0; i < s->uart.nr; i++) 1008 for (i = 0; i < s->uart.nr; i++)
954 uart_remove_one_port(&s->uart, &s->port[i]); 1009 uart_remove_one_port(&s->uart, &s->port[i]);