aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/sccnxp.c
diff options
context:
space:
mode:
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 418b495e3233..caccbe8fc1be 100644
--- a/drivers/tty/serial/sccnxp.c
+++ b/drivers/tty/serial/sccnxp.c
@@ -23,8 +23,9 @@
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/tty.h> 24#include <linux/tty.h>
25#include <linux/tty_flip.h> 25#include <linux/tty_flip.h>
26#include <linux/spinlock.h>
26#include <linux/platform_device.h> 27#include <linux/platform_device.h>
27#include <linux/platform_data/sccnxp.h> 28#include <linux/platform_data/serial-sccnxp.h>
28 29
29#define SCCNXP_NAME "uart-sccnxp" 30#define SCCNXP_NAME "uart-sccnxp"
30#define SCCNXP_MAJOR 204 31#define SCCNXP_MAJOR 204
@@ -106,6 +107,7 @@ enum {
106struct sccnxp_port { 107struct sccnxp_port {
107 struct uart_driver uart; 108 struct uart_driver uart;
108 struct uart_port port[SCCNXP_MAX_UARTS]; 109 struct uart_port port[SCCNXP_MAX_UARTS];
110 bool opened[SCCNXP_MAX_UARTS];
109 111
110 const char *name; 112 const char *name;
111 int irq; 113 int irq;
@@ -122,7 +124,10 @@ struct sccnxp_port {
122 struct console console; 124 struct console console;
123#endif 125#endif
124 126
125 struct mutex sccnxp_mutex; 127 spinlock_t lock;
128
129 bool poll;
130 struct timer_list timer;
126 131
127 struct sccnxp_pdata pdata; 132 struct sccnxp_pdata pdata;
128}; 133};
@@ -174,14 +179,12 @@ static int sccnxp_update_best_err(int a, int b, int *besterr)
174 return 1; 179 return 1;
175} 180}
176 181
177struct baud_table { 182static const struct {
178 u8 csr; 183 u8 csr;
179 u8 acr; 184 u8 acr;
180 u8 mr0; 185 u8 mr0;
181 int baud; 186 int baud;
182}; 187} baud_std[] = {
183
184const struct baud_table baud_std[] = {
185 { 0, ACR_BAUD0, MR0_BAUD_NORMAL, 50, }, 188 { 0, ACR_BAUD0, MR0_BAUD_NORMAL, 50, },
186 { 0, ACR_BAUD1, MR0_BAUD_NORMAL, 75, }, 189 { 0, ACR_BAUD1, MR0_BAUD_NORMAL, 75, },
187 { 1, ACR_BAUD0, MR0_BAUD_NORMAL, 110, }, 190 { 1, ACR_BAUD0, MR0_BAUD_NORMAL, 110, },
@@ -285,10 +288,6 @@ static void sccnxp_handle_rx(struct uart_port *port)
285{ 288{
286 u8 sr; 289 u8 sr;
287 unsigned int ch, flag; 290 unsigned int ch, flag;
288 struct tty_struct *tty = tty_port_tty_get(&port->state->port);
289
290 if (!tty)
291 return;
292 291
293 for (;;) { 292 for (;;) {
294 sr = sccnxp_port_read(port, SCCNXP_SR_REG); 293 sr = sccnxp_port_read(port, SCCNXP_SR_REG);
@@ -304,14 +303,19 @@ static void sccnxp_handle_rx(struct uart_port *port)
304 if (unlikely(sr)) { 303 if (unlikely(sr)) {
305 if (sr & SR_BRK) { 304 if (sr & SR_BRK) {
306 port->icount.brk++; 305 port->icount.brk++;
306 sccnxp_port_write(port, SCCNXP_CR_REG,
307 CR_CMD_BREAK_RESET);
307 if (uart_handle_break(port)) 308 if (uart_handle_break(port))
308 continue; 309 continue;
309 } else if (sr & SR_PE) 310 } else if (sr & SR_PE)
310 port->icount.parity++; 311 port->icount.parity++;
311 else if (sr & SR_FE) 312 else if (sr & SR_FE)
312 port->icount.frame++; 313 port->icount.frame++;
313 else if (sr & SR_OVR) 314 else if (sr & SR_OVR) {
314 port->icount.overrun++; 315 port->icount.overrun++;
316 sccnxp_port_write(port, SCCNXP_CR_REG,
317 CR_CMD_STATUS_RESET);
318 }
315 319
316 sr &= port->read_status_mask; 320 sr &= port->read_status_mask;
317 if (sr & SR_BRK) 321 if (sr & SR_BRK)
@@ -333,9 +337,7 @@ static void sccnxp_handle_rx(struct uart_port *port)
333 uart_insert_char(port, sr, SR_OVR, ch, flag); 337 uart_insert_char(port, sr, SR_OVR, ch, flag);
334 } 338 }
335 339
336 tty_flip_buffer_push(tty); 340 tty_flip_buffer_push(&port->state->port);
337
338 tty_kref_put(tty);
339} 341}
340 342
341static void sccnxp_handle_tx(struct uart_port *port) 343static void sccnxp_handle_tx(struct uart_port *port)
@@ -377,31 +379,48 @@ static void sccnxp_handle_tx(struct uart_port *port)
377 uart_write_wakeup(port); 379 uart_write_wakeup(port);
378} 380}
379 381
380static irqreturn_t sccnxp_ist(int irq, void *dev_id) 382static void sccnxp_handle_events(struct sccnxp_port *s)
381{ 383{
382 int i; 384 int i;
383 u8 isr; 385 u8 isr;
384 struct sccnxp_port *s = (struct sccnxp_port *)dev_id;
385
386 mutex_lock(&s->sccnxp_mutex);
387 386
388 for (;;) { 387 do {
389 isr = sccnxp_read(&s->port[0], SCCNXP_ISR_REG); 388 isr = sccnxp_read(&s->port[0], SCCNXP_ISR_REG);
390 isr &= s->imr; 389 isr &= s->imr;
391 if (!isr) 390 if (!isr)
392 break; 391 break;
393 392
394 dev_dbg(s->port[0].dev, "IRQ status: 0x%02x\n", isr);
395
396 for (i = 0; i < s->uart.nr; i++) { 393 for (i = 0; i < s->uart.nr; i++) {
397 if (isr & ISR_RXRDY(i)) 394 if (s->opened[i] && (isr & ISR_RXRDY(i)))
398 sccnxp_handle_rx(&s->port[i]); 395 sccnxp_handle_rx(&s->port[i]);
399 if (isr & ISR_TXRDY(i)) 396 if (s->opened[i] && (isr & ISR_TXRDY(i)))
400 sccnxp_handle_tx(&s->port[i]); 397 sccnxp_handle_tx(&s->port[i]);
401 } 398 }
402 } 399 } while (1);
400}
401
402static void sccnxp_timer(unsigned long data)
403{
404 struct sccnxp_port *s = (struct sccnxp_port *)data;
405 unsigned long flags;
403 406
404 mutex_unlock(&s->sccnxp_mutex); 407 spin_lock_irqsave(&s->lock, flags);
408 sccnxp_handle_events(s);
409 spin_unlock_irqrestore(&s->lock, flags);
410
411 if (!timer_pending(&s->timer))
412 mod_timer(&s->timer, jiffies +
413 usecs_to_jiffies(s->pdata.poll_time_us));
414}
415
416static irqreturn_t sccnxp_ist(int irq, void *dev_id)
417{
418 struct sccnxp_port *s = (struct sccnxp_port *)dev_id;
419 unsigned long flags;
420
421 spin_lock_irqsave(&s->lock, flags);
422 sccnxp_handle_events(s);
423 spin_unlock_irqrestore(&s->lock, flags);
405 424
406 return IRQ_HANDLED; 425 return IRQ_HANDLED;
407} 426}
@@ -409,8 +428,9 @@ static irqreturn_t sccnxp_ist(int irq, void *dev_id)
409static void sccnxp_start_tx(struct uart_port *port) 428static void sccnxp_start_tx(struct uart_port *port)
410{ 429{
411 struct sccnxp_port *s = dev_get_drvdata(port->dev); 430 struct sccnxp_port *s = dev_get_drvdata(port->dev);
431 unsigned long flags;
412 432
413 mutex_lock(&s->sccnxp_mutex); 433 spin_lock_irqsave(&s->lock, flags);
414 434
415 /* Set direction to output */ 435 /* Set direction to output */
416 if (s->flags & SCCNXP_HAVE_IO) 436 if (s->flags & SCCNXP_HAVE_IO)
@@ -418,7 +438,7 @@ static void sccnxp_start_tx(struct uart_port *port)
418 438
419 sccnxp_enable_irq(port, IMR_TXRDY); 439 sccnxp_enable_irq(port, IMR_TXRDY);
420 440
421 mutex_unlock(&s->sccnxp_mutex); 441 spin_unlock_irqrestore(&s->lock, flags);
422} 442}
423 443
424static void sccnxp_stop_tx(struct uart_port *port) 444static void sccnxp_stop_tx(struct uart_port *port)
@@ -429,20 +449,22 @@ static void sccnxp_stop_tx(struct uart_port *port)
429static void sccnxp_stop_rx(struct uart_port *port) 449static void sccnxp_stop_rx(struct uart_port *port)
430{ 450{
431 struct sccnxp_port *s = dev_get_drvdata(port->dev); 451 struct sccnxp_port *s = dev_get_drvdata(port->dev);
452 unsigned long flags;
432 453
433 mutex_lock(&s->sccnxp_mutex); 454 spin_lock_irqsave(&s->lock, flags);
434 sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE); 455 sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE);
435 mutex_unlock(&s->sccnxp_mutex); 456 spin_unlock_irqrestore(&s->lock, flags);
436} 457}
437 458
438static unsigned int sccnxp_tx_empty(struct uart_port *port) 459static unsigned int sccnxp_tx_empty(struct uart_port *port)
439{ 460{
440 u8 val; 461 u8 val;
462 unsigned long flags;
441 struct sccnxp_port *s = dev_get_drvdata(port->dev); 463 struct sccnxp_port *s = dev_get_drvdata(port->dev);
442 464
443 mutex_lock(&s->sccnxp_mutex); 465 spin_lock_irqsave(&s->lock, flags);
444 val = sccnxp_port_read(port, SCCNXP_SR_REG); 466 val = sccnxp_port_read(port, SCCNXP_SR_REG);
445 mutex_unlock(&s->sccnxp_mutex); 467 spin_unlock_irqrestore(&s->lock, flags);
446 468
447 return (val & SR_TXEMT) ? TIOCSER_TEMT : 0; 469 return (val & SR_TXEMT) ? TIOCSER_TEMT : 0;
448} 470}
@@ -455,28 +477,30 @@ static void sccnxp_enable_ms(struct uart_port *port)
455static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl) 477static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl)
456{ 478{
457 struct sccnxp_port *s = dev_get_drvdata(port->dev); 479 struct sccnxp_port *s = dev_get_drvdata(port->dev);
480 unsigned long flags;
458 481
459 if (!(s->flags & SCCNXP_HAVE_IO)) 482 if (!(s->flags & SCCNXP_HAVE_IO))
460 return; 483 return;
461 484
462 mutex_lock(&s->sccnxp_mutex); 485 spin_lock_irqsave(&s->lock, flags);
463 486
464 sccnxp_set_bit(port, DTR_OP, mctrl & TIOCM_DTR); 487 sccnxp_set_bit(port, DTR_OP, mctrl & TIOCM_DTR);
465 sccnxp_set_bit(port, RTS_OP, mctrl & TIOCM_RTS); 488 sccnxp_set_bit(port, RTS_OP, mctrl & TIOCM_RTS);
466 489
467 mutex_unlock(&s->sccnxp_mutex); 490 spin_unlock_irqrestore(&s->lock, flags);
468} 491}
469 492
470static unsigned int sccnxp_get_mctrl(struct uart_port *port) 493static unsigned int sccnxp_get_mctrl(struct uart_port *port)
471{ 494{
472 u8 bitmask, ipr; 495 u8 bitmask, ipr;
496 unsigned long flags;
473 struct sccnxp_port *s = dev_get_drvdata(port->dev); 497 struct sccnxp_port *s = dev_get_drvdata(port->dev);
474 unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR; 498 unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
475 499
476 if (!(s->flags & SCCNXP_HAVE_IO)) 500 if (!(s->flags & SCCNXP_HAVE_IO))
477 return mctrl; 501 return mctrl;
478 502
479 mutex_lock(&s->sccnxp_mutex); 503 spin_lock_irqsave(&s->lock, flags);
480 504
481 ipr = ~sccnxp_read(port, SCCNXP_IPCR_REG); 505 ipr = ~sccnxp_read(port, SCCNXP_IPCR_REG);
482 506
@@ -505,7 +529,7 @@ static unsigned int sccnxp_get_mctrl(struct uart_port *port)
505 mctrl |= (ipr & bitmask) ? TIOCM_RNG : 0; 529 mctrl |= (ipr & bitmask) ? TIOCM_RNG : 0;
506 } 530 }
507 531
508 mutex_unlock(&s->sccnxp_mutex); 532 spin_unlock_irqrestore(&s->lock, flags);
509 533
510 return mctrl; 534 return mctrl;
511} 535}
@@ -513,21 +537,23 @@ static unsigned int sccnxp_get_mctrl(struct uart_port *port)
513static void sccnxp_break_ctl(struct uart_port *port, int break_state) 537static void sccnxp_break_ctl(struct uart_port *port, int break_state)
514{ 538{
515 struct sccnxp_port *s = dev_get_drvdata(port->dev); 539 struct sccnxp_port *s = dev_get_drvdata(port->dev);
540 unsigned long flags;
516 541
517 mutex_lock(&s->sccnxp_mutex); 542 spin_lock_irqsave(&s->lock, flags);
518 sccnxp_port_write(port, SCCNXP_CR_REG, break_state ? 543 sccnxp_port_write(port, SCCNXP_CR_REG, break_state ?
519 CR_CMD_START_BREAK : CR_CMD_STOP_BREAK); 544 CR_CMD_START_BREAK : CR_CMD_STOP_BREAK);
520 mutex_unlock(&s->sccnxp_mutex); 545 spin_unlock_irqrestore(&s->lock, flags);
521} 546}
522 547
523static void sccnxp_set_termios(struct uart_port *port, 548static void sccnxp_set_termios(struct uart_port *port,
524 struct ktermios *termios, struct ktermios *old) 549 struct ktermios *termios, struct ktermios *old)
525{ 550{
526 struct sccnxp_port *s = dev_get_drvdata(port->dev); 551 struct sccnxp_port *s = dev_get_drvdata(port->dev);
552 unsigned long flags;
527 u8 mr1, mr2; 553 u8 mr1, mr2;
528 int baud; 554 int baud;
529 555
530 mutex_lock(&s->sccnxp_mutex); 556 spin_lock_irqsave(&s->lock, flags);
531 557
532 /* Mask termios capabilities we don't support */ 558 /* Mask termios capabilities we don't support */
533 termios->c_cflag &= ~CMSPAR; 559 termios->c_cflag &= ~CMSPAR;
@@ -594,20 +620,22 @@ static void sccnxp_set_termios(struct uart_port *port,
594 /* Update timeout according to new baud rate */ 620 /* Update timeout according to new baud rate */
595 uart_update_timeout(port, termios->c_cflag, baud); 621 uart_update_timeout(port, termios->c_cflag, baud);
596 622
623 /* Report actual baudrate back to core */
597 if (tty_termios_baud_rate(termios)) 624 if (tty_termios_baud_rate(termios))
598 tty_termios_encode_baud_rate(termios, baud, baud); 625 tty_termios_encode_baud_rate(termios, baud, baud);
599 626
600 /* Enable RX & TX */ 627 /* Enable RX & TX */
601 sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE); 628 sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE);
602 629
603 mutex_unlock(&s->sccnxp_mutex); 630 spin_unlock_irqrestore(&s->lock, flags);
604} 631}
605 632
606static int sccnxp_startup(struct uart_port *port) 633static int sccnxp_startup(struct uart_port *port)
607{ 634{
608 struct sccnxp_port *s = dev_get_drvdata(port->dev); 635 struct sccnxp_port *s = dev_get_drvdata(port->dev);
636 unsigned long flags;
609 637
610 mutex_lock(&s->sccnxp_mutex); 638 spin_lock_irqsave(&s->lock, flags);
611 639
612 if (s->flags & SCCNXP_HAVE_IO) { 640 if (s->flags & SCCNXP_HAVE_IO) {
613 /* Outputs are controlled manually */ 641 /* Outputs are controlled manually */
@@ -626,7 +654,9 @@ static int sccnxp_startup(struct uart_port *port)
626 /* Enable RX interrupt */ 654 /* Enable RX interrupt */
627 sccnxp_enable_irq(port, IMR_RXRDY); 655 sccnxp_enable_irq(port, IMR_RXRDY);
628 656
629 mutex_unlock(&s->sccnxp_mutex); 657 s->opened[port->line] = 1;
658
659 spin_unlock_irqrestore(&s->lock, flags);
630 660
631 return 0; 661 return 0;
632} 662}
@@ -634,8 +664,11 @@ static int sccnxp_startup(struct uart_port *port)
634static void sccnxp_shutdown(struct uart_port *port) 664static void sccnxp_shutdown(struct uart_port *port)
635{ 665{
636 struct sccnxp_port *s = dev_get_drvdata(port->dev); 666 struct sccnxp_port *s = dev_get_drvdata(port->dev);
667 unsigned long flags;
637 668
638 mutex_lock(&s->sccnxp_mutex); 669 spin_lock_irqsave(&s->lock, flags);
670
671 s->opened[port->line] = 0;
639 672
640 /* Disable interrupts */ 673 /* Disable interrupts */
641 sccnxp_disable_irq(port, IMR_TXRDY | IMR_RXRDY); 674 sccnxp_disable_irq(port, IMR_TXRDY | IMR_RXRDY);
@@ -647,7 +680,7 @@ static void sccnxp_shutdown(struct uart_port *port)
647 if (s->flags & SCCNXP_HAVE_IO) 680 if (s->flags & SCCNXP_HAVE_IO)
648 sccnxp_set_bit(port, DIR_OP, 0); 681 sccnxp_set_bit(port, DIR_OP, 0);
649 682
650 mutex_unlock(&s->sccnxp_mutex); 683 spin_unlock_irqrestore(&s->lock, flags);
651} 684}
652 685
653static const char *sccnxp_type(struct uart_port *port) 686static const char *sccnxp_type(struct uart_port *port)
@@ -721,10 +754,11 @@ static void sccnxp_console_write(struct console *co, const char *c, unsigned n)
721{ 754{
722 struct sccnxp_port *s = (struct sccnxp_port *)co->data; 755 struct sccnxp_port *s = (struct sccnxp_port *)co->data;
723 struct uart_port *port = &s->port[co->index]; 756 struct uart_port *port = &s->port[co->index];
757 unsigned long flags;
724 758
725 mutex_lock(&s->sccnxp_mutex); 759 spin_lock_irqsave(&s->lock, flags);
726 uart_console_write(port, c, n, sccnxp_console_putchar); 760 uart_console_write(port, c, n, sccnxp_console_putchar);
727 mutex_unlock(&s->sccnxp_mutex); 761 spin_unlock_irqrestore(&s->lock, flags);
728} 762}
729 763
730static int sccnxp_console_setup(struct console *co, char *options) 764static int sccnxp_console_setup(struct console *co, char *options)
@@ -763,7 +797,7 @@ static int sccnxp_probe(struct platform_device *pdev)
763 } 797 }
764 platform_set_drvdata(pdev, s); 798 platform_set_drvdata(pdev, s);
765 799
766 mutex_init(&s->sccnxp_mutex); 800 spin_lock_init(&s->lock);
767 801
768 /* Individual chip settings */ 802 /* Individual chip settings */
769 switch (chiptype) { 803 switch (chiptype) {
@@ -860,11 +894,19 @@ static int sccnxp_probe(struct platform_device *pdev)
860 } else 894 } else
861 memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata)); 895 memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata));
862 896
863 s->irq = platform_get_irq(pdev, 0); 897 if (s->pdata.poll_time_us) {
864 if (s->irq <= 0) { 898 dev_info(&pdev->dev, "Using poll mode, resolution %u usecs\n",
865 dev_err(&pdev->dev, "Missing irq resource data\n"); 899 s->pdata.poll_time_us);
866 ret = -ENXIO; 900 s->poll = 1;
867 goto err_out; 901 }
902
903 if (!s->poll) {
904 s->irq = platform_get_irq(pdev, 0);
905 if (s->irq < 0) {
906 dev_err(&pdev->dev, "Missing irq resource data\n");
907 ret = -ENXIO;
908 goto err_out;
909 }
868 } 910 }
869 911
870 /* Check input frequency */ 912 /* 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]);