diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-10 13:23:43 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-10 13:25:27 -0500 |
commit | 5a22e30def8b9539576ff047adb14455ca559f07 (patch) | |
tree | e1e76efd73b28e7ae8124383c263fcf92bcc11e0 /drivers | |
parent | 19e00f2f1d5273dbc52eab0ebc315cae3aa44b2a (diff) | |
parent | 418a936e84e8f346da322c2e839992aa9df108d4 (diff) |
Merge tag 'tty-3.3-rc3' tty-next
This is needed to handle the 8250 file merge mess properly for future
patches.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
28 files changed, 1033 insertions, 220 deletions
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index e44933d58790..94948be5d366 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c | |||
@@ -1015,14 +1015,11 @@ capinc_tty_install(struct tty_driver *driver, struct tty_struct *tty) | |||
1015 | { | 1015 | { |
1016 | int idx = tty->index; | 1016 | int idx = tty->index; |
1017 | struct capiminor *mp = capiminor_get(idx); | 1017 | struct capiminor *mp = capiminor_get(idx); |
1018 | int ret = tty_init_termios(tty); | 1018 | int ret = tty_standard_install(driver, tty); |
1019 | 1019 | ||
1020 | if (ret == 0) { | 1020 | if (ret == 0) |
1021 | tty_driver_kref_get(driver); | ||
1022 | tty->count++; | ||
1023 | tty->driver_data = mp; | 1021 | tty->driver_data = mp; |
1024 | driver->ttys[idx] = tty; | 1022 | else |
1025 | } else | ||
1026 | capiminor_put(mp); | 1023 | capiminor_put(mp); |
1027 | return ret; | 1024 | return ret; |
1028 | } | 1025 | } |
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c index 0b56e3f43573..471ff4c85cd8 100644 --- a/drivers/misc/pti.c +++ b/drivers/misc/pti.c | |||
@@ -481,13 +481,9 @@ static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty) | |||
481 | { | 481 | { |
482 | int idx = tty->index; | 482 | int idx = tty->index; |
483 | struct pti_tty *pti_tty_data; | 483 | struct pti_tty *pti_tty_data; |
484 | int ret = tty_init_termios(tty); | 484 | int ret = tty_standard_install(driver, tty); |
485 | 485 | ||
486 | if (ret == 0) { | 486 | if (ret == 0) { |
487 | tty_driver_kref_get(driver); | ||
488 | tty->count++; | ||
489 | driver->ttys[idx] = tty; | ||
490 | |||
491 | pti_tty_data = kmalloc(sizeof(struct pti_tty), GFP_KERNEL); | 487 | pti_tty_data = kmalloc(sizeof(struct pti_tty), GFP_KERNEL); |
492 | if (pti_tty_data == NULL) | 488 | if (pti_tty_data == NULL) |
493 | return -ENOMEM; | 489 | return -ENOMEM; |
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index 2c151e18c9e8..bd4a67cdac3f 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c | |||
@@ -750,15 +750,12 @@ static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty) | |||
750 | { | 750 | { |
751 | int idx = tty->index; | 751 | int idx = tty->index; |
752 | struct sdio_uart_port *port = sdio_uart_port_get(idx); | 752 | struct sdio_uart_port *port = sdio_uart_port_get(idx); |
753 | int ret = tty_init_termios(tty); | 753 | int ret = tty_standard_install(driver, tty); |
754 | 754 | ||
755 | if (ret == 0) { | 755 | if (ret == 0) |
756 | tty_driver_kref_get(driver); | ||
757 | tty->count++; | ||
758 | /* This is the ref sdio_uart_port get provided */ | 756 | /* This is the ref sdio_uart_port get provided */ |
759 | tty->driver_data = port; | 757 | tty->driver_data = port; |
760 | driver->ttys[idx] = tty; | 758 | else |
761 | } else | ||
762 | sdio_uart_port_put(port); | 759 | sdio_uart_port_put(port); |
763 | return ret; | 760 | return ret; |
764 | } | 761 | } |
diff --git a/drivers/tty/hvc/hvc_beat.c b/drivers/tty/hvc/hvc_beat.c index 5fe4631e2a61..1560d235449e 100644 --- a/drivers/tty/hvc/hvc_beat.c +++ b/drivers/tty/hvc/hvc_beat.c | |||
@@ -113,7 +113,7 @@ static int __init hvc_beat_init(void) | |||
113 | if (!firmware_has_feature(FW_FEATURE_BEAT)) | 113 | if (!firmware_has_feature(FW_FEATURE_BEAT)) |
114 | return -ENODEV; | 114 | return -ENODEV; |
115 | 115 | ||
116 | hp = hvc_alloc(0, NO_IRQ, &hvc_beat_get_put_ops, 16); | 116 | hp = hvc_alloc(0, 0, &hvc_beat_get_put_ops, 16); |
117 | if (IS_ERR(hp)) | 117 | if (IS_ERR(hp)) |
118 | return PTR_ERR(hp); | 118 | return PTR_ERR(hp); |
119 | hvc_beat_dev = hp; | 119 | hvc_beat_dev = hp; |
diff --git a/drivers/tty/hvc/hvc_rtas.c b/drivers/tty/hvc/hvc_rtas.c index 61c4a61558d9..0069bb86ba49 100644 --- a/drivers/tty/hvc/hvc_rtas.c +++ b/drivers/tty/hvc/hvc_rtas.c | |||
@@ -94,7 +94,7 @@ static int __init hvc_rtas_init(void) | |||
94 | 94 | ||
95 | /* Allocate an hvc_struct for the console device we instantiated | 95 | /* Allocate an hvc_struct for the console device we instantiated |
96 | * earlier. Save off hp so that we can return it on exit */ | 96 | * earlier. Save off hp so that we can return it on exit */ |
97 | hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops, 16); | 97 | hp = hvc_alloc(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops, 16); |
98 | if (IS_ERR(hp)) | 98 | if (IS_ERR(hp)) |
99 | return PTR_ERR(hp); | 99 | return PTR_ERR(hp); |
100 | 100 | ||
diff --git a/drivers/tty/hvc/hvc_udbg.c b/drivers/tty/hvc/hvc_udbg.c index b0957e61a7be..4c9b13e7748c 100644 --- a/drivers/tty/hvc/hvc_udbg.c +++ b/drivers/tty/hvc/hvc_udbg.c | |||
@@ -69,7 +69,7 @@ static int __init hvc_udbg_init(void) | |||
69 | 69 | ||
70 | BUG_ON(hvc_udbg_dev); | 70 | BUG_ON(hvc_udbg_dev); |
71 | 71 | ||
72 | hp = hvc_alloc(0, NO_IRQ, &hvc_udbg_ops, 16); | 72 | hp = hvc_alloc(0, 0, &hvc_udbg_ops, 16); |
73 | if (IS_ERR(hp)) | 73 | if (IS_ERR(hp)) |
74 | return PTR_ERR(hp); | 74 | return PTR_ERR(hp); |
75 | 75 | ||
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index 52fdf60bdbe2..a1b0a75c3eae 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c | |||
@@ -176,7 +176,7 @@ static int __init xen_hvc_init(void) | |||
176 | xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn); | 176 | xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn); |
177 | } | 177 | } |
178 | if (xencons_irq < 0) | 178 | if (xencons_irq < 0) |
179 | xencons_irq = 0; /* NO_IRQ */ | 179 | xencons_irq = 0; |
180 | else | 180 | else |
181 | irq_set_noprobe(xencons_irq); | 181 | irq_set_noprobe(xencons_irq); |
182 | 182 | ||
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index b9040bec36bd..df7e7a0a5e6c 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c | |||
@@ -1203,7 +1203,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) | |||
1203 | { | 1203 | { |
1204 | struct hvcs_struct *hvcsd; | 1204 | struct hvcs_struct *hvcsd; |
1205 | unsigned long flags; | 1205 | unsigned long flags; |
1206 | int irq = NO_IRQ; | 1206 | int irq; |
1207 | 1207 | ||
1208 | /* | 1208 | /* |
1209 | * Is someone trying to close the file associated with this device after | 1209 | * Is someone trying to close the file associated with this device after |
@@ -1264,7 +1264,7 @@ static void hvcs_hangup(struct tty_struct * tty) | |||
1264 | struct hvcs_struct *hvcsd = tty->driver_data; | 1264 | struct hvcs_struct *hvcsd = tty->driver_data; |
1265 | unsigned long flags; | 1265 | unsigned long flags; |
1266 | int temp_open_count; | 1266 | int temp_open_count; |
1267 | int irq = NO_IRQ; | 1267 | int irq; |
1268 | 1268 | ||
1269 | spin_lock_irqsave(&hvcsd->lock, flags); | 1269 | spin_lock_irqsave(&hvcsd->lock, flags); |
1270 | /* Preserve this so that we know how many kref refs to put */ | 1270 | /* Preserve this so that we know how many kref refs to put */ |
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c index cdfa3e02d627..1b5f28bd7930 100644 --- a/drivers/tty/hvc/hvsi.c +++ b/drivers/tty/hvc/hvsi.c | |||
@@ -1237,7 +1237,7 @@ static int __init hvsi_console_init(void) | |||
1237 | hp->state = HVSI_CLOSED; | 1237 | hp->state = HVSI_CLOSED; |
1238 | hp->vtermno = *vtermno; | 1238 | hp->vtermno = *vtermno; |
1239 | hp->virq = irq_create_mapping(NULL, irq[0]); | 1239 | hp->virq = irq_create_mapping(NULL, irq[0]); |
1240 | if (hp->virq == NO_IRQ) { | 1240 | if (hp->virq == 0) { |
1241 | printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n", | 1241 | printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n", |
1242 | __func__, irq[0]); | 1242 | __func__, irq[0]); |
1243 | continue; | 1243 | continue; |
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index fd347ff34d07..580da78b2d86 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c | |||
@@ -1602,13 +1602,9 @@ static int ntty_install(struct tty_driver *driver, struct tty_struct *tty) | |||
1602 | int ret; | 1602 | int ret; |
1603 | if (!port || !dc || dc->state != NOZOMI_STATE_READY) | 1603 | if (!port || !dc || dc->state != NOZOMI_STATE_READY) |
1604 | return -ENODEV; | 1604 | return -ENODEV; |
1605 | ret = tty_init_termios(tty); | 1605 | ret = tty_standard_install(driver, tty); |
1606 | if (ret == 0) { | 1606 | if (ret == 0) |
1607 | tty_driver_kref_get(driver); | ||
1608 | tty->count++; | ||
1609 | tty->driver_data = port; | 1607 | tty->driver_data = port; |
1610 | driver->ttys[tty->index] = tty; | ||
1611 | } | ||
1612 | return ret; | 1608 | return ret; |
1613 | } | 1609 | } |
1614 | 1610 | ||
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index d8653ab6f498..39afd045f8ef 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/major.h> | 21 | #include <linux/major.h> |
22 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/sysctl.h> | ||
25 | #include <linux/device.h> | 24 | #include <linux/device.h> |
26 | #include <linux/uaccess.h> | 25 | #include <linux/uaccess.h> |
27 | #include <linux/bitops.h> | 26 | #include <linux/bitops.h> |
@@ -55,11 +54,8 @@ static void pty_close(struct tty_struct *tty, struct file *filp) | |||
55 | wake_up_interruptible(&tty->link->write_wait); | 54 | wake_up_interruptible(&tty->link->write_wait); |
56 | if (tty->driver->subtype == PTY_TYPE_MASTER) { | 55 | if (tty->driver->subtype == PTY_TYPE_MASTER) { |
57 | set_bit(TTY_OTHER_CLOSED, &tty->flags); | 56 | set_bit(TTY_OTHER_CLOSED, &tty->flags); |
58 | #ifdef CONFIG_UNIX98_PTYS | ||
59 | if (tty->driver == ptm_driver) | ||
60 | devpts_pty_kill(tty->link); | ||
61 | #endif | ||
62 | tty_unlock(); | 57 | tty_unlock(); |
58 | devpts_pty_kill(tty->link); | ||
63 | tty_vhangup(tty->link); | 59 | tty_vhangup(tty->link); |
64 | tty_lock(); | 60 | tty_lock(); |
65 | } | 61 | } |
@@ -439,55 +435,9 @@ static inline void legacy_pty_init(void) { } | |||
439 | 435 | ||
440 | /* Unix98 devices */ | 436 | /* Unix98 devices */ |
441 | #ifdef CONFIG_UNIX98_PTYS | 437 | #ifdef CONFIG_UNIX98_PTYS |
442 | /* | ||
443 | * sysctl support for setting limits on the number of Unix98 ptys allocated. | ||
444 | * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. | ||
445 | */ | ||
446 | int pty_limit = NR_UNIX98_PTY_DEFAULT; | ||
447 | static int pty_limit_min; | ||
448 | static int pty_limit_max = NR_UNIX98_PTY_MAX; | ||
449 | static int pty_count; | ||
450 | 438 | ||
451 | static struct cdev ptmx_cdev; | 439 | static struct cdev ptmx_cdev; |
452 | 440 | ||
453 | static struct ctl_table pty_table[] = { | ||
454 | { | ||
455 | .procname = "max", | ||
456 | .maxlen = sizeof(int), | ||
457 | .mode = 0644, | ||
458 | .data = &pty_limit, | ||
459 | .proc_handler = proc_dointvec_minmax, | ||
460 | .extra1 = &pty_limit_min, | ||
461 | .extra2 = &pty_limit_max, | ||
462 | }, { | ||
463 | .procname = "nr", | ||
464 | .maxlen = sizeof(int), | ||
465 | .mode = 0444, | ||
466 | .data = &pty_count, | ||
467 | .proc_handler = proc_dointvec, | ||
468 | }, | ||
469 | {} | ||
470 | }; | ||
471 | |||
472 | static struct ctl_table pty_kern_table[] = { | ||
473 | { | ||
474 | .procname = "pty", | ||
475 | .mode = 0555, | ||
476 | .child = pty_table, | ||
477 | }, | ||
478 | {} | ||
479 | }; | ||
480 | |||
481 | static struct ctl_table pty_root_table[] = { | ||
482 | { | ||
483 | .procname = "kernel", | ||
484 | .mode = 0555, | ||
485 | .child = pty_kern_table, | ||
486 | }, | ||
487 | {} | ||
488 | }; | ||
489 | |||
490 | |||
491 | static int pty_unix98_ioctl(struct tty_struct *tty, | 441 | static int pty_unix98_ioctl(struct tty_struct *tty, |
492 | unsigned int cmd, unsigned long arg) | 442 | unsigned int cmd, unsigned long arg) |
493 | { | 443 | { |
@@ -515,10 +465,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty, | |||
515 | static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver, | 465 | static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver, |
516 | struct inode *ptm_inode, int idx) | 466 | struct inode *ptm_inode, int idx) |
517 | { | 467 | { |
518 | struct tty_struct *tty = devpts_get_tty(ptm_inode, idx); | 468 | /* Master must be open via /dev/ptmx */ |
519 | if (tty) | 469 | return ERR_PTR(-EIO); |
520 | tty = tty->link; | ||
521 | return tty; | ||
522 | } | 470 | } |
523 | 471 | ||
524 | /** | 472 | /** |
@@ -589,7 +537,6 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) | |||
589 | */ | 537 | */ |
590 | tty_driver_kref_get(driver); | 538 | tty_driver_kref_get(driver); |
591 | tty->count++; | 539 | tty->count++; |
592 | pty_count++; | ||
593 | return 0; | 540 | return 0; |
594 | err_free_mem: | 541 | err_free_mem: |
595 | deinitialize_tty_struct(o_tty); | 542 | deinitialize_tty_struct(o_tty); |
@@ -603,7 +550,6 @@ err_free_tty: | |||
603 | 550 | ||
604 | static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) | 551 | static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) |
605 | { | 552 | { |
606 | pty_count--; | ||
607 | } | 553 | } |
608 | 554 | ||
609 | static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) | 555 | static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) |
@@ -667,9 +613,7 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
667 | return retval; | 613 | return retval; |
668 | 614 | ||
669 | /* find a device that is not in use. */ | 615 | /* find a device that is not in use. */ |
670 | tty_lock(); | ||
671 | index = devpts_new_index(inode); | 616 | index = devpts_new_index(inode); |
672 | tty_unlock(); | ||
673 | if (index < 0) { | 617 | if (index < 0) { |
674 | retval = index; | 618 | retval = index; |
675 | goto err_file; | 619 | goto err_file; |
@@ -677,7 +621,7 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
677 | 621 | ||
678 | mutex_lock(&tty_mutex); | 622 | mutex_lock(&tty_mutex); |
679 | tty_lock(); | 623 | tty_lock(); |
680 | tty = tty_init_dev(ptm_driver, index, 1); | 624 | tty = tty_init_dev(ptm_driver, index); |
681 | mutex_unlock(&tty_mutex); | 625 | mutex_unlock(&tty_mutex); |
682 | 626 | ||
683 | if (IS_ERR(tty)) { | 627 | if (IS_ERR(tty)) { |
@@ -704,8 +648,8 @@ err_release: | |||
704 | tty_release(inode, filp); | 648 | tty_release(inode, filp); |
705 | return retval; | 649 | return retval; |
706 | out: | 650 | out: |
707 | devpts_kill_index(inode, index); | ||
708 | tty_unlock(); | 651 | tty_unlock(); |
652 | devpts_kill_index(inode, index); | ||
709 | err_file: | 653 | err_file: |
710 | tty_free_file(filp); | 654 | tty_free_file(filp); |
711 | return retval; | 655 | return retval; |
@@ -762,8 +706,6 @@ static void __init unix98_pty_init(void) | |||
762 | if (tty_register_driver(pts_driver)) | 706 | if (tty_register_driver(pts_driver)) |
763 | panic("Couldn't register Unix98 pts driver"); | 707 | panic("Couldn't register Unix98 pts driver"); |
764 | 708 | ||
765 | register_sysctl_table(pty_root_table); | ||
766 | |||
767 | /* Now create the /dev/ptmx special device */ | 709 | /* Now create the /dev/ptmx special device */ |
768 | tty_default_fops(&ptmx_fops); | 710 | tty_default_fops(&ptmx_fops); |
769 | ptmx_fops.open = ptmx_open; | 711 | ptmx_fops.open = ptmx_open; |
diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c index 1b37626e8f13..f899996b4363 100644 --- a/drivers/tty/serial/21285.c +++ b/drivers/tty/serial/21285.c | |||
@@ -331,7 +331,7 @@ static int serial21285_verify_port(struct uart_port *port, struct serial_struct | |||
331 | int ret = 0; | 331 | int ret = 0; |
332 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285) | 332 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285) |
333 | ret = -EINVAL; | 333 | ret = -EINVAL; |
334 | if (ser->irq != NO_IRQ) | 334 | if (ser->irq <= 0) |
335 | ret = -EINVAL; | 335 | ret = -EINVAL; |
336 | if (ser->baud_base != port->uartclk / 16) | 336 | if (ser->baud_base != port->uartclk / 16) |
337 | ret = -EINVAL; | 337 | ret = -EINVAL; |
@@ -360,7 +360,7 @@ static struct uart_ops serial21285_ops = { | |||
360 | static struct uart_port serial21285_port = { | 360 | static struct uart_port serial21285_port = { |
361 | .mapbase = 0x42000160, | 361 | .mapbase = 0x42000160, |
362 | .iotype = UPIO_MEM, | 362 | .iotype = UPIO_MEM, |
363 | .irq = NO_IRQ, | 363 | .irq = 0, |
364 | .fifosize = 16, | 364 | .fifosize = 16, |
365 | .ops = &serial21285_ops, | 365 | .ops = &serial21285_ops, |
366 | .flags = UPF_BOOT_AUTOCONF, | 366 | .flags = UPF_BOOT_AUTOCONF, |
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 9b7336fcfbb3..b423d0f962a2 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c | |||
@@ -86,13 +86,6 @@ static unsigned int skip_txen_test; /* force skip of txen test at init time */ | |||
86 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) | 86 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) |
87 | 87 | ||
88 | 88 | ||
89 | /* | ||
90 | * We default to IRQ0 for the "no irq" hack. Some | ||
91 | * machine types want others as well - they're free | ||
92 | * to redefine this in their header file. | ||
93 | */ | ||
94 | #define is_real_interrupt(irq) ((irq) != 0) | ||
95 | |||
96 | #ifdef CONFIG_SERIAL_8250_DETECT_IRQ | 89 | #ifdef CONFIG_SERIAL_8250_DETECT_IRQ |
97 | #define CONFIG_SERIAL_DETECT_IRQ 1 | 90 | #define CONFIG_SERIAL_DETECT_IRQ 1 |
98 | #endif | 91 | #endif |
@@ -1750,7 +1743,7 @@ static void serial8250_backup_timeout(unsigned long data) | |||
1750 | * Must disable interrupts or else we risk racing with the interrupt | 1743 | * Must disable interrupts or else we risk racing with the interrupt |
1751 | * based handler. | 1744 | * based handler. |
1752 | */ | 1745 | */ |
1753 | if (is_real_interrupt(up->port.irq)) { | 1746 | if (up->port.irq) { |
1754 | ier = serial_in(up, UART_IER); | 1747 | ier = serial_in(up, UART_IER); |
1755 | serial_out(up, UART_IER, 0); | 1748 | serial_out(up, UART_IER, 0); |
1756 | } | 1749 | } |
@@ -1775,7 +1768,7 @@ static void serial8250_backup_timeout(unsigned long data) | |||
1775 | if (!(iir & UART_IIR_NO_INT)) | 1768 | if (!(iir & UART_IIR_NO_INT)) |
1776 | serial8250_tx_chars(up); | 1769 | serial8250_tx_chars(up); |
1777 | 1770 | ||
1778 | if (is_real_interrupt(up->port.irq)) | 1771 | if (up->port.irq) |
1779 | serial_out(up, UART_IER, ier); | 1772 | serial_out(up, UART_IER, ier); |
1780 | 1773 | ||
1781 | spin_unlock_irqrestore(&up->port.lock, flags); | 1774 | spin_unlock_irqrestore(&up->port.lock, flags); |
@@ -2028,7 +2021,7 @@ static int serial8250_startup(struct uart_port *port) | |||
2028 | serial_outp(up, UART_LCR, 0); | 2021 | serial_outp(up, UART_LCR, 0); |
2029 | } | 2022 | } |
2030 | 2023 | ||
2031 | if (is_real_interrupt(up->port.irq)) { | 2024 | if (up->port.irq) { |
2032 | unsigned char iir1; | 2025 | unsigned char iir1; |
2033 | /* | 2026 | /* |
2034 | * Test for UARTs that do not reassert THRE when the | 2027 | * Test for UARTs that do not reassert THRE when the |
@@ -2083,7 +2076,7 @@ static int serial8250_startup(struct uart_port *port) | |||
2083 | * hardware interrupt, we use a timer-based system. The original | 2076 | * hardware interrupt, we use a timer-based system. The original |
2084 | * driver used to do this with IRQ0. | 2077 | * driver used to do this with IRQ0. |
2085 | */ | 2078 | */ |
2086 | if (!is_real_interrupt(up->port.irq)) { | 2079 | if (!up->port.irq) { |
2087 | up->timer.data = (unsigned long)up; | 2080 | up->timer.data = (unsigned long)up; |
2088 | mod_timer(&up->timer, jiffies + uart_poll_timeout(port)); | 2081 | mod_timer(&up->timer, jiffies + uart_poll_timeout(port)); |
2089 | } else { | 2082 | } else { |
@@ -2099,13 +2092,13 @@ static int serial8250_startup(struct uart_port *port) | |||
2099 | 2092 | ||
2100 | spin_lock_irqsave(&up->port.lock, flags); | 2093 | spin_lock_irqsave(&up->port.lock, flags); |
2101 | if (up->port.flags & UPF_FOURPORT) { | 2094 | if (up->port.flags & UPF_FOURPORT) { |
2102 | if (!is_real_interrupt(up->port.irq)) | 2095 | if (!up->port.irq) |
2103 | up->port.mctrl |= TIOCM_OUT1; | 2096 | up->port.mctrl |= TIOCM_OUT1; |
2104 | } else | 2097 | } else |
2105 | /* | 2098 | /* |
2106 | * Most PC uarts need OUT2 raised to enable interrupts. | 2099 | * Most PC uarts need OUT2 raised to enable interrupts. |
2107 | */ | 2100 | */ |
2108 | if (is_real_interrupt(up->port.irq)) | 2101 | if (up->port.irq) |
2109 | up->port.mctrl |= TIOCM_OUT2; | 2102 | up->port.mctrl |= TIOCM_OUT2; |
2110 | 2103 | ||
2111 | serial8250_set_mctrl(&up->port, up->port.mctrl); | 2104 | serial8250_set_mctrl(&up->port, up->port.mctrl); |
@@ -2223,7 +2216,7 @@ static void serial8250_shutdown(struct uart_port *port) | |||
2223 | 2216 | ||
2224 | del_timer_sync(&up->timer); | 2217 | del_timer_sync(&up->timer); |
2225 | up->timer.function = serial8250_timeout; | 2218 | up->timer.function = serial8250_timeout; |
2226 | if (is_real_interrupt(up->port.irq)) | 2219 | if (up->port.irq) |
2227 | serial_unlink_irq_chain(up); | 2220 | serial_unlink_irq_chain(up); |
2228 | } | 2221 | } |
2229 | 2222 | ||
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 2de99248dfae..76e7764488e6 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig | |||
@@ -1347,4 +1347,17 @@ config SERIAL_AR933X_NR_UARTS | |||
1347 | Set this to the number of serial ports you want the driver | 1347 | Set this to the number of serial ports you want the driver |
1348 | to support. | 1348 | to support. |
1349 | 1349 | ||
1350 | config SERIAL_EFM32_UART | ||
1351 | tristate "EFM32 UART/USART port." | ||
1352 | depends on ARCH_EFM32 | ||
1353 | select SERIAL_CORE | ||
1354 | help | ||
1355 | This driver support the USART and UART ports on | ||
1356 | Energy Micro's efm32 SoCs. | ||
1357 | |||
1358 | config SERIAL_EFM32_UART_CONSOLE | ||
1359 | bool "EFM32 UART/USART console support" | ||
1360 | depends on SERIAL_EFM32_UART=y | ||
1361 | select SERIAL_CORE_CONSOLE | ||
1362 | |||
1350 | endmenu | 1363 | endmenu |
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index fef32e10c851..7257c5d898ae 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile | |||
@@ -61,12 +61,12 @@ obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o | |||
61 | obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o | 61 | obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o |
62 | obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o | 62 | obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o |
63 | obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o | 63 | obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o |
64 | obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o | ||
64 | obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o | 65 | obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o |
65 | obj-$(CONFIG_SERIAL_QE) += ucc_uart.o | 66 | obj-$(CONFIG_SERIAL_QE) += ucc_uart.o |
66 | obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o | 67 | obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o |
67 | obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o | 68 | obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o |
68 | obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o | 69 | obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o |
69 | obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o | ||
70 | obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o | 70 | obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o |
71 | obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o | 71 | obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o |
72 | obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o | 72 | obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o |
@@ -78,3 +78,4 @@ obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o | |||
78 | obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o | 78 | obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o |
79 | obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o | 79 | obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o |
80 | obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o | 80 | obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o |
81 | obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o | ||
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 1d04c5037f25..e7903751e058 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c | |||
@@ -377,6 +377,26 @@ static int altera_uart_verify_port(struct uart_port *port, | |||
377 | return 0; | 377 | return 0; |
378 | } | 378 | } |
379 | 379 | ||
380 | #ifdef CONFIG_CONSOLE_POLL | ||
381 | static int altera_uart_poll_get_char(struct uart_port *port) | ||
382 | { | ||
383 | while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & | ||
384 | ALTERA_UART_STATUS_RRDY_MSK)) | ||
385 | cpu_relax(); | ||
386 | |||
387 | return altera_uart_readl(port, ALTERA_UART_RXDATA_REG); | ||
388 | } | ||
389 | |||
390 | static void altera_uart_poll_put_char(struct uart_port *port, unsigned char c) | ||
391 | { | ||
392 | while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & | ||
393 | ALTERA_UART_STATUS_TRDY_MSK)) | ||
394 | cpu_relax(); | ||
395 | |||
396 | altera_uart_writel(port, c, ALTERA_UART_TXDATA_REG); | ||
397 | } | ||
398 | #endif | ||
399 | |||
380 | /* | 400 | /* |
381 | * Define the basic serial functions we support. | 401 | * Define the basic serial functions we support. |
382 | */ | 402 | */ |
@@ -397,35 +417,16 @@ static struct uart_ops altera_uart_ops = { | |||
397 | .release_port = altera_uart_release_port, | 417 | .release_port = altera_uart_release_port, |
398 | .config_port = altera_uart_config_port, | 418 | .config_port = altera_uart_config_port, |
399 | .verify_port = altera_uart_verify_port, | 419 | .verify_port = altera_uart_verify_port, |
420 | #ifdef CONFIG_CONSOLE_POLL | ||
421 | .poll_get_char = altera_uart_poll_get_char, | ||
422 | .poll_put_char = altera_uart_poll_put_char, | ||
423 | #endif | ||
400 | }; | 424 | }; |
401 | 425 | ||
402 | static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS]; | 426 | static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS]; |
403 | 427 | ||
404 | #if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) | 428 | #if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) |
405 | 429 | ||
406 | int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp) | ||
407 | { | ||
408 | struct uart_port *port; | ||
409 | int i; | ||
410 | |||
411 | for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) { | ||
412 | port = &altera_uart_ports[i].port; | ||
413 | |||
414 | port->line = i; | ||
415 | port->type = PORT_ALTERA_UART; | ||
416 | port->mapbase = platp[i].mapbase; | ||
417 | port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE); | ||
418 | port->iotype = SERIAL_IO_MEM; | ||
419 | port->irq = platp[i].irq; | ||
420 | port->uartclk = platp[i].uartclk; | ||
421 | port->flags = UPF_BOOT_AUTOCONF; | ||
422 | port->ops = &altera_uart_ops; | ||
423 | port->private_data = platp; | ||
424 | } | ||
425 | |||
426 | return 0; | ||
427 | } | ||
428 | |||
429 | static void altera_uart_console_putc(struct uart_port *port, const char c) | 430 | static void altera_uart_console_putc(struct uart_port *port, const char c) |
430 | { | 431 | { |
431 | while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & | 432 | while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & |
diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c new file mode 100644 index 000000000000..615e46470491 --- /dev/null +++ b/drivers/tty/serial/efm32-uart.c | |||
@@ -0,0 +1,830 @@ | |||
1 | #if defined(CONFIG_SERIAL_EFM32_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | ||
2 | #define SUPPORT_SYSRQ | ||
3 | #endif | ||
4 | |||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/module.h> | ||
7 | #include <linux/io.h> | ||
8 | #include <linux/platform_device.h> | ||
9 | #include <linux/console.h> | ||
10 | #include <linux/sysrq.h> | ||
11 | #include <linux/serial_core.h> | ||
12 | #include <linux/tty_flip.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/clk.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/of_device.h> | ||
17 | |||
18 | #include <linux/platform_data/efm32-uart.h> | ||
19 | |||
20 | #define DRIVER_NAME "efm32-uart" | ||
21 | #define DEV_NAME "ttyefm" | ||
22 | |||
23 | #define UARTn_CTRL 0x00 | ||
24 | #define UARTn_CTRL_SYNC 0x0001 | ||
25 | #define UARTn_CTRL_TXBIL 0x1000 | ||
26 | |||
27 | #define UARTn_FRAME 0x04 | ||
28 | #define UARTn_FRAME_DATABITS__MASK 0x000f | ||
29 | #define UARTn_FRAME_DATABITS(n) ((n) - 3) | ||
30 | #define UARTn_FRAME_PARITY_NONE 0x0000 | ||
31 | #define UARTn_FRAME_PARITY_EVEN 0x0200 | ||
32 | #define UARTn_FRAME_PARITY_ODD 0x0300 | ||
33 | #define UARTn_FRAME_STOPBITS_HALF 0x0000 | ||
34 | #define UARTn_FRAME_STOPBITS_ONE 0x1000 | ||
35 | #define UARTn_FRAME_STOPBITS_TWO 0x3000 | ||
36 | |||
37 | #define UARTn_CMD 0x0c | ||
38 | #define UARTn_CMD_RXEN 0x0001 | ||
39 | #define UARTn_CMD_RXDIS 0x0002 | ||
40 | #define UARTn_CMD_TXEN 0x0004 | ||
41 | #define UARTn_CMD_TXDIS 0x0008 | ||
42 | |||
43 | #define UARTn_STATUS 0x10 | ||
44 | #define UARTn_STATUS_TXENS 0x0002 | ||
45 | #define UARTn_STATUS_TXC 0x0020 | ||
46 | #define UARTn_STATUS_TXBL 0x0040 | ||
47 | #define UARTn_STATUS_RXDATAV 0x0080 | ||
48 | |||
49 | #define UARTn_CLKDIV 0x14 | ||
50 | |||
51 | #define UARTn_RXDATAX 0x18 | ||
52 | #define UARTn_RXDATAX_RXDATA__MASK 0x01ff | ||
53 | #define UARTn_RXDATAX_PERR 0x4000 | ||
54 | #define UARTn_RXDATAX_FERR 0x8000 | ||
55 | /* | ||
56 | * This is a software only flag used for ignore_status_mask and | ||
57 | * read_status_mask! It's used for breaks that the hardware doesn't report | ||
58 | * explicitly. | ||
59 | */ | ||
60 | #define SW_UARTn_RXDATAX_BERR 0x2000 | ||
61 | |||
62 | #define UARTn_TXDATA 0x34 | ||
63 | |||
64 | #define UARTn_IF 0x40 | ||
65 | #define UARTn_IF_TXC 0x0001 | ||
66 | #define UARTn_IF_TXBL 0x0002 | ||
67 | #define UARTn_IF_RXDATAV 0x0004 | ||
68 | #define UARTn_IF_RXOF 0x0010 | ||
69 | |||
70 | #define UARTn_IFS 0x44 | ||
71 | #define UARTn_IFC 0x48 | ||
72 | #define UARTn_IEN 0x4c | ||
73 | |||
74 | #define UARTn_ROUTE 0x54 | ||
75 | #define UARTn_ROUTE_LOCATION__MASK 0x0700 | ||
76 | #define UARTn_ROUTE_LOCATION(n) (((n) << 8) & UARTn_ROUTE_LOCATION__MASK) | ||
77 | #define UARTn_ROUTE_RXPEN 0x0001 | ||
78 | #define UARTn_ROUTE_TXPEN 0x0002 | ||
79 | |||
80 | struct efm32_uart_port { | ||
81 | struct uart_port port; | ||
82 | unsigned int txirq; | ||
83 | struct clk *clk; | ||
84 | }; | ||
85 | #define to_efm_port(_port) container_of(_port, struct efm32_uart_port, port) | ||
86 | #define efm_debug(efm_port, format, arg...) \ | ||
87 | dev_dbg(efm_port->port.dev, format, ##arg) | ||
88 | |||
89 | static void efm32_uart_write32(struct efm32_uart_port *efm_port, | ||
90 | u32 value, unsigned offset) | ||
91 | { | ||
92 | writel_relaxed(value, efm_port->port.membase + offset); | ||
93 | } | ||
94 | |||
95 | static u32 efm32_uart_read32(struct efm32_uart_port *efm_port, | ||
96 | unsigned offset) | ||
97 | { | ||
98 | return readl_relaxed(efm_port->port.membase + offset); | ||
99 | } | ||
100 | |||
101 | static unsigned int efm32_uart_tx_empty(struct uart_port *port) | ||
102 | { | ||
103 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
104 | u32 status = efm32_uart_read32(efm_port, UARTn_STATUS); | ||
105 | |||
106 | if (status & UARTn_STATUS_TXC) | ||
107 | return TIOCSER_TEMT; | ||
108 | else | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static void efm32_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
113 | { | ||
114 | /* sorry, neither handshaking lines nor loop functionallity */ | ||
115 | } | ||
116 | |||
117 | static unsigned int efm32_uart_get_mctrl(struct uart_port *port) | ||
118 | { | ||
119 | /* sorry, no handshaking lines available */ | ||
120 | return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR; | ||
121 | } | ||
122 | |||
123 | static void efm32_uart_stop_tx(struct uart_port *port) | ||
124 | { | ||
125 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
126 | u32 ien = efm32_uart_read32(efm_port, UARTn_IEN); | ||
127 | |||
128 | efm32_uart_write32(efm_port, UARTn_CMD_TXDIS, UARTn_CMD); | ||
129 | ien &= ~(UARTn_IF_TXC | UARTn_IF_TXBL); | ||
130 | efm32_uart_write32(efm_port, ien, UARTn_IEN); | ||
131 | } | ||
132 | |||
133 | static void efm32_uart_tx_chars(struct efm32_uart_port *efm_port) | ||
134 | { | ||
135 | struct uart_port *port = &efm_port->port; | ||
136 | struct circ_buf *xmit = &port->state->xmit; | ||
137 | |||
138 | while (efm32_uart_read32(efm_port, UARTn_STATUS) & | ||
139 | UARTn_STATUS_TXBL) { | ||
140 | if (port->x_char) { | ||
141 | port->icount.tx++; | ||
142 | efm32_uart_write32(efm_port, port->x_char, | ||
143 | UARTn_TXDATA); | ||
144 | port->x_char = 0; | ||
145 | continue; | ||
146 | } | ||
147 | if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) { | ||
148 | port->icount.tx++; | ||
149 | efm32_uart_write32(efm_port, xmit->buf[xmit->tail], | ||
150 | UARTn_TXDATA); | ||
151 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
152 | } else | ||
153 | break; | ||
154 | } | ||
155 | |||
156 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
157 | uart_write_wakeup(port); | ||
158 | |||
159 | if (!port->x_char && uart_circ_empty(xmit) && | ||
160 | efm32_uart_read32(efm_port, UARTn_STATUS) & | ||
161 | UARTn_STATUS_TXC) | ||
162 | efm32_uart_stop_tx(port); | ||
163 | } | ||
164 | |||
165 | static void efm32_uart_start_tx(struct uart_port *port) | ||
166 | { | ||
167 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
168 | u32 ien; | ||
169 | |||
170 | efm32_uart_write32(efm_port, | ||
171 | UARTn_IF_TXBL | UARTn_IF_TXC, UARTn_IFC); | ||
172 | ien = efm32_uart_read32(efm_port, UARTn_IEN); | ||
173 | efm32_uart_write32(efm_port, | ||
174 | ien | UARTn_IF_TXBL | UARTn_IF_TXC, UARTn_IEN); | ||
175 | efm32_uart_write32(efm_port, UARTn_CMD_TXEN, UARTn_CMD); | ||
176 | |||
177 | efm32_uart_tx_chars(efm_port); | ||
178 | } | ||
179 | |||
180 | static void efm32_uart_stop_rx(struct uart_port *port) | ||
181 | { | ||
182 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
183 | |||
184 | efm32_uart_write32(efm_port, UARTn_CMD_RXDIS, UARTn_CMD); | ||
185 | } | ||
186 | |||
187 | static void efm32_uart_enable_ms(struct uart_port *port) | ||
188 | { | ||
189 | /* no handshake lines, no modem status interrupts */ | ||
190 | } | ||
191 | |||
192 | static void efm32_uart_break_ctl(struct uart_port *port, int ctl) | ||
193 | { | ||
194 | /* not possible without fiddling with gpios */ | ||
195 | } | ||
196 | |||
197 | static void efm32_uart_rx_chars(struct efm32_uart_port *efm_port, | ||
198 | struct tty_struct *tty) | ||
199 | { | ||
200 | struct uart_port *port = &efm_port->port; | ||
201 | |||
202 | while (efm32_uart_read32(efm_port, UARTn_STATUS) & | ||
203 | UARTn_STATUS_RXDATAV) { | ||
204 | u32 rxdata = efm32_uart_read32(efm_port, UARTn_RXDATAX); | ||
205 | int flag = 0; | ||
206 | |||
207 | /* | ||
208 | * This is a reserved bit and I only saw it read as 0. But to be | ||
209 | * sure not to be confused too much by new devices adhere to the | ||
210 | * warning in the reference manual that reserverd bits might | ||
211 | * read as 1 in the future. | ||
212 | */ | ||
213 | rxdata &= ~SW_UARTn_RXDATAX_BERR; | ||
214 | |||
215 | port->icount.rx++; | ||
216 | |||
217 | if ((rxdata & UARTn_RXDATAX_FERR) && | ||
218 | !(rxdata & UARTn_RXDATAX_RXDATA__MASK)) { | ||
219 | rxdata |= SW_UARTn_RXDATAX_BERR; | ||
220 | port->icount.brk++; | ||
221 | if (uart_handle_break(port)) | ||
222 | continue; | ||
223 | } else if (rxdata & UARTn_RXDATAX_PERR) | ||
224 | port->icount.parity++; | ||
225 | else if (rxdata & UARTn_RXDATAX_FERR) | ||
226 | port->icount.frame++; | ||
227 | |||
228 | rxdata &= port->read_status_mask; | ||
229 | |||
230 | if (rxdata & SW_UARTn_RXDATAX_BERR) | ||
231 | flag = TTY_BREAK; | ||
232 | else if (rxdata & UARTn_RXDATAX_PERR) | ||
233 | flag = TTY_PARITY; | ||
234 | else if (rxdata & UARTn_RXDATAX_FERR) | ||
235 | flag = TTY_FRAME; | ||
236 | else if (uart_handle_sysrq_char(port, | ||
237 | rxdata & UARTn_RXDATAX_RXDATA__MASK)) | ||
238 | continue; | ||
239 | |||
240 | if (tty && (rxdata & port->ignore_status_mask) == 0) | ||
241 | tty_insert_flip_char(tty, | ||
242 | rxdata & UARTn_RXDATAX_RXDATA__MASK, flag); | ||
243 | } | ||
244 | } | ||
245 | |||
246 | static irqreturn_t efm32_uart_rxirq(int irq, void *data) | ||
247 | { | ||
248 | struct efm32_uart_port *efm_port = data; | ||
249 | u32 irqflag = efm32_uart_read32(efm_port, UARTn_IF); | ||
250 | int handled = IRQ_NONE; | ||
251 | struct uart_port *port = &efm_port->port; | ||
252 | struct tty_struct *tty; | ||
253 | |||
254 | spin_lock(&port->lock); | ||
255 | |||
256 | tty = tty_kref_get(port->state->port.tty); | ||
257 | |||
258 | if (irqflag & UARTn_IF_RXDATAV) { | ||
259 | efm32_uart_write32(efm_port, UARTn_IF_RXDATAV, UARTn_IFC); | ||
260 | efm32_uart_rx_chars(efm_port, tty); | ||
261 | |||
262 | handled = IRQ_HANDLED; | ||
263 | } | ||
264 | |||
265 | if (irqflag & UARTn_IF_RXOF) { | ||
266 | efm32_uart_write32(efm_port, UARTn_IF_RXOF, UARTn_IFC); | ||
267 | port->icount.overrun++; | ||
268 | if (tty) | ||
269 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
270 | |||
271 | handled = IRQ_HANDLED; | ||
272 | } | ||
273 | |||
274 | if (tty) { | ||
275 | tty_flip_buffer_push(tty); | ||
276 | tty_kref_put(tty); | ||
277 | } | ||
278 | |||
279 | spin_unlock(&port->lock); | ||
280 | |||
281 | return handled; | ||
282 | } | ||
283 | |||
284 | static irqreturn_t efm32_uart_txirq(int irq, void *data) | ||
285 | { | ||
286 | struct efm32_uart_port *efm_port = data; | ||
287 | u32 irqflag = efm32_uart_read32(efm_port, UARTn_IF); | ||
288 | |||
289 | /* TXBL doesn't need to be cleared */ | ||
290 | if (irqflag & UARTn_IF_TXC) | ||
291 | efm32_uart_write32(efm_port, UARTn_IF_TXC, UARTn_IFC); | ||
292 | |||
293 | if (irqflag & (UARTn_IF_TXC | UARTn_IF_TXBL)) { | ||
294 | efm32_uart_tx_chars(efm_port); | ||
295 | return IRQ_HANDLED; | ||
296 | } else | ||
297 | return IRQ_NONE; | ||
298 | } | ||
299 | |||
300 | static int efm32_uart_startup(struct uart_port *port) | ||
301 | { | ||
302 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
303 | u32 location = 0; | ||
304 | struct efm32_uart_pdata *pdata = dev_get_platdata(port->dev); | ||
305 | int ret; | ||
306 | |||
307 | if (pdata) | ||
308 | location = UARTn_ROUTE_LOCATION(pdata->location); | ||
309 | |||
310 | ret = clk_enable(efm_port->clk); | ||
311 | if (ret) { | ||
312 | efm_debug(efm_port, "failed to enable clk\n"); | ||
313 | goto err_clk_enable; | ||
314 | } | ||
315 | port->uartclk = clk_get_rate(efm_port->clk); | ||
316 | |||
317 | /* Enable pins at configured location */ | ||
318 | efm32_uart_write32(efm_port, location | UARTn_ROUTE_RXPEN | UARTn_ROUTE_TXPEN, | ||
319 | UARTn_ROUTE); | ||
320 | |||
321 | ret = request_irq(port->irq, efm32_uart_rxirq, 0, | ||
322 | DRIVER_NAME, efm_port); | ||
323 | if (ret) { | ||
324 | efm_debug(efm_port, "failed to register rxirq\n"); | ||
325 | goto err_request_irq_rx; | ||
326 | } | ||
327 | |||
328 | /* disable all irqs */ | ||
329 | efm32_uart_write32(efm_port, 0, UARTn_IEN); | ||
330 | |||
331 | ret = request_irq(efm_port->txirq, efm32_uart_txirq, 0, | ||
332 | DRIVER_NAME, efm_port); | ||
333 | if (ret) { | ||
334 | efm_debug(efm_port, "failed to register txirq\n"); | ||
335 | free_irq(port->irq, efm_port); | ||
336 | err_request_irq_rx: | ||
337 | |||
338 | clk_disable(efm_port->clk); | ||
339 | } else { | ||
340 | efm32_uart_write32(efm_port, | ||
341 | UARTn_IF_RXDATAV | UARTn_IF_RXOF, UARTn_IEN); | ||
342 | efm32_uart_write32(efm_port, UARTn_CMD_RXEN, UARTn_CMD); | ||
343 | } | ||
344 | |||
345 | err_clk_enable: | ||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static void efm32_uart_shutdown(struct uart_port *port) | ||
350 | { | ||
351 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
352 | |||
353 | efm32_uart_write32(efm_port, 0, UARTn_IEN); | ||
354 | free_irq(port->irq, efm_port); | ||
355 | |||
356 | clk_disable(efm_port->clk); | ||
357 | } | ||
358 | |||
359 | static void efm32_uart_set_termios(struct uart_port *port, | ||
360 | struct ktermios *new, struct ktermios *old) | ||
361 | { | ||
362 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
363 | unsigned long flags; | ||
364 | unsigned baud; | ||
365 | u32 clkdiv; | ||
366 | u32 frame = 0; | ||
367 | |||
368 | /* no modem control lines */ | ||
369 | new->c_cflag &= ~(CRTSCTS | CMSPAR); | ||
370 | |||
371 | baud = uart_get_baud_rate(port, new, old, | ||
372 | DIV_ROUND_CLOSEST(port->uartclk, 16 * 8192), | ||
373 | DIV_ROUND_CLOSEST(port->uartclk, 16)); | ||
374 | |||
375 | switch (new->c_cflag & CSIZE) { | ||
376 | case CS5: | ||
377 | frame |= UARTn_FRAME_DATABITS(5); | ||
378 | break; | ||
379 | case CS6: | ||
380 | frame |= UARTn_FRAME_DATABITS(6); | ||
381 | break; | ||
382 | case CS7: | ||
383 | frame |= UARTn_FRAME_DATABITS(7); | ||
384 | break; | ||
385 | case CS8: | ||
386 | frame |= UARTn_FRAME_DATABITS(8); | ||
387 | break; | ||
388 | } | ||
389 | |||
390 | if (new->c_cflag & CSTOPB) | ||
391 | /* the receiver only verifies the first stop bit */ | ||
392 | frame |= UARTn_FRAME_STOPBITS_TWO; | ||
393 | else | ||
394 | frame |= UARTn_FRAME_STOPBITS_ONE; | ||
395 | |||
396 | if (new->c_cflag & PARENB) { | ||
397 | if (new->c_cflag & PARODD) | ||
398 | frame |= UARTn_FRAME_PARITY_ODD; | ||
399 | else | ||
400 | frame |= UARTn_FRAME_PARITY_EVEN; | ||
401 | } else | ||
402 | frame |= UARTn_FRAME_PARITY_NONE; | ||
403 | |||
404 | /* | ||
405 | * the 6 lowest bits of CLKDIV are dc, bit 6 has value 0.25. | ||
406 | * port->uartclk <= 14e6, so 4 * port->uartclk doesn't overflow. | ||
407 | */ | ||
408 | clkdiv = (DIV_ROUND_CLOSEST(4 * port->uartclk, 16 * baud) - 4) << 6; | ||
409 | |||
410 | spin_lock_irqsave(&port->lock, flags); | ||
411 | |||
412 | efm32_uart_write32(efm_port, | ||
413 | UARTn_CMD_TXDIS | UARTn_CMD_RXDIS, UARTn_CMD); | ||
414 | |||
415 | port->read_status_mask = UARTn_RXDATAX_RXDATA__MASK; | ||
416 | if (new->c_iflag & INPCK) | ||
417 | port->read_status_mask |= | ||
418 | UARTn_RXDATAX_FERR | UARTn_RXDATAX_PERR; | ||
419 | if (new->c_iflag & (BRKINT | PARMRK)) | ||
420 | port->read_status_mask |= SW_UARTn_RXDATAX_BERR; | ||
421 | |||
422 | port->ignore_status_mask = 0; | ||
423 | if (new->c_iflag & IGNPAR) | ||
424 | port->ignore_status_mask |= | ||
425 | UARTn_RXDATAX_FERR | UARTn_RXDATAX_PERR; | ||
426 | if (new->c_iflag & IGNBRK) | ||
427 | port->ignore_status_mask |= SW_UARTn_RXDATAX_BERR; | ||
428 | |||
429 | uart_update_timeout(port, new->c_cflag, baud); | ||
430 | |||
431 | efm32_uart_write32(efm_port, UARTn_CTRL_TXBIL, UARTn_CTRL); | ||
432 | efm32_uart_write32(efm_port, frame, UARTn_FRAME); | ||
433 | efm32_uart_write32(efm_port, clkdiv, UARTn_CLKDIV); | ||
434 | |||
435 | efm32_uart_write32(efm_port, UARTn_CMD_TXEN | UARTn_CMD_RXEN, | ||
436 | UARTn_CMD); | ||
437 | |||
438 | spin_unlock_irqrestore(&port->lock, flags); | ||
439 | } | ||
440 | |||
441 | static const char *efm32_uart_type(struct uart_port *port) | ||
442 | { | ||
443 | return port->type == PORT_EFMUART ? "efm32-uart" : NULL; | ||
444 | } | ||
445 | |||
446 | static void efm32_uart_release_port(struct uart_port *port) | ||
447 | { | ||
448 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
449 | |||
450 | clk_unprepare(efm_port->clk); | ||
451 | clk_put(efm_port->clk); | ||
452 | iounmap(port->membase); | ||
453 | } | ||
454 | |||
455 | static int efm32_uart_request_port(struct uart_port *port) | ||
456 | { | ||
457 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
458 | int ret; | ||
459 | |||
460 | port->membase = ioremap(port->mapbase, 60); | ||
461 | if (!efm_port->port.membase) { | ||
462 | ret = -ENOMEM; | ||
463 | efm_debug(efm_port, "failed to remap\n"); | ||
464 | goto err_ioremap; | ||
465 | } | ||
466 | |||
467 | efm_port->clk = clk_get(port->dev, NULL); | ||
468 | if (IS_ERR(efm_port->clk)) { | ||
469 | ret = PTR_ERR(efm_port->clk); | ||
470 | efm_debug(efm_port, "failed to get clock\n"); | ||
471 | goto err_clk_get; | ||
472 | } | ||
473 | |||
474 | ret = clk_prepare(efm_port->clk); | ||
475 | if (ret) { | ||
476 | clk_put(efm_port->clk); | ||
477 | err_clk_get: | ||
478 | |||
479 | iounmap(port->membase); | ||
480 | err_ioremap: | ||
481 | return ret; | ||
482 | } | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | static void efm32_uart_config_port(struct uart_port *port, int type) | ||
487 | { | ||
488 | if (type & UART_CONFIG_TYPE && | ||
489 | !efm32_uart_request_port(port)) | ||
490 | port->type = PORT_EFMUART; | ||
491 | } | ||
492 | |||
493 | static int efm32_uart_verify_port(struct uart_port *port, | ||
494 | struct serial_struct *serinfo) | ||
495 | { | ||
496 | int ret = 0; | ||
497 | |||
498 | if (serinfo->type != PORT_UNKNOWN && serinfo->type != PORT_EFMUART) | ||
499 | ret = -EINVAL; | ||
500 | |||
501 | return ret; | ||
502 | } | ||
503 | |||
504 | static struct uart_ops efm32_uart_pops = { | ||
505 | .tx_empty = efm32_uart_tx_empty, | ||
506 | .set_mctrl = efm32_uart_set_mctrl, | ||
507 | .get_mctrl = efm32_uart_get_mctrl, | ||
508 | .stop_tx = efm32_uart_stop_tx, | ||
509 | .start_tx = efm32_uart_start_tx, | ||
510 | .stop_rx = efm32_uart_stop_rx, | ||
511 | .enable_ms = efm32_uart_enable_ms, | ||
512 | .break_ctl = efm32_uart_break_ctl, | ||
513 | .startup = efm32_uart_startup, | ||
514 | .shutdown = efm32_uart_shutdown, | ||
515 | .set_termios = efm32_uart_set_termios, | ||
516 | .type = efm32_uart_type, | ||
517 | .release_port = efm32_uart_release_port, | ||
518 | .request_port = efm32_uart_request_port, | ||
519 | .config_port = efm32_uart_config_port, | ||
520 | .verify_port = efm32_uart_verify_port, | ||
521 | }; | ||
522 | |||
523 | static struct efm32_uart_port *efm32_uart_ports[5]; | ||
524 | |||
525 | #ifdef CONFIG_SERIAL_EFM32_UART_CONSOLE | ||
526 | static void efm32_uart_console_putchar(struct uart_port *port, int ch) | ||
527 | { | ||
528 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
529 | unsigned int timeout = 0x400; | ||
530 | u32 status; | ||
531 | |||
532 | while (1) { | ||
533 | status = efm32_uart_read32(efm_port, UARTn_STATUS); | ||
534 | |||
535 | if (status & UARTn_STATUS_TXBL) | ||
536 | break; | ||
537 | if (!timeout--) | ||
538 | return; | ||
539 | } | ||
540 | efm32_uart_write32(efm_port, ch, UARTn_TXDATA); | ||
541 | } | ||
542 | |||
543 | static void efm32_uart_console_write(struct console *co, const char *s, | ||
544 | unsigned int count) | ||
545 | { | ||
546 | struct efm32_uart_port *efm_port = efm32_uart_ports[co->index]; | ||
547 | u32 status = efm32_uart_read32(efm_port, UARTn_STATUS); | ||
548 | unsigned int timeout = 0x400; | ||
549 | |||
550 | if (!(status & UARTn_STATUS_TXENS)) | ||
551 | efm32_uart_write32(efm_port, UARTn_CMD_TXEN, UARTn_CMD); | ||
552 | |||
553 | uart_console_write(&efm_port->port, s, count, | ||
554 | efm32_uart_console_putchar); | ||
555 | |||
556 | /* Wait for the transmitter to become empty */ | ||
557 | while (1) { | ||
558 | u32 status = efm32_uart_read32(efm_port, UARTn_STATUS); | ||
559 | if (status & UARTn_STATUS_TXC) | ||
560 | break; | ||
561 | if (!timeout--) | ||
562 | break; | ||
563 | } | ||
564 | |||
565 | if (!(status & UARTn_STATUS_TXENS)) | ||
566 | efm32_uart_write32(efm_port, UARTn_CMD_TXDIS, UARTn_CMD); | ||
567 | } | ||
568 | |||
569 | static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port, | ||
570 | int *baud, int *parity, int *bits) | ||
571 | { | ||
572 | u32 ctrl = efm32_uart_read32(efm_port, UARTn_CTRL); | ||
573 | u32 route, clkdiv, frame; | ||
574 | |||
575 | if (ctrl & UARTn_CTRL_SYNC) | ||
576 | /* not operating in async mode */ | ||
577 | return; | ||
578 | |||
579 | route = efm32_uart_read32(efm_port, UARTn_ROUTE); | ||
580 | if (!(route & UARTn_ROUTE_TXPEN)) | ||
581 | /* tx pin not routed */ | ||
582 | return; | ||
583 | |||
584 | clkdiv = efm32_uart_read32(efm_port, UARTn_CLKDIV); | ||
585 | |||
586 | *baud = DIV_ROUND_CLOSEST(4 * efm_port->port.uartclk, | ||
587 | 16 * (4 + (clkdiv >> 6))); | ||
588 | |||
589 | frame = efm32_uart_read32(efm_port, UARTn_FRAME); | ||
590 | if (frame & UARTn_FRAME_PARITY_ODD) | ||
591 | *parity = 'o'; | ||
592 | else if (frame & UARTn_FRAME_PARITY_EVEN) | ||
593 | *parity = 'e'; | ||
594 | else | ||
595 | *parity = 'n'; | ||
596 | |||
597 | *bits = (frame & UARTn_FRAME_DATABITS__MASK) - | ||
598 | UARTn_FRAME_DATABITS(4) + 4; | ||
599 | |||
600 | efm_debug(efm_port, "get_opts: options=%d%c%d\n", | ||
601 | *baud, *parity, *bits); | ||
602 | } | ||
603 | |||
604 | static int efm32_uart_console_setup(struct console *co, char *options) | ||
605 | { | ||
606 | struct efm32_uart_port *efm_port; | ||
607 | int baud = 115200; | ||
608 | int bits = 8; | ||
609 | int parity = 'n'; | ||
610 | int flow = 'n'; | ||
611 | int ret; | ||
612 | |||
613 | if (co->index < 0 || co->index >= ARRAY_SIZE(efm32_uart_ports)) { | ||
614 | unsigned i; | ||
615 | for (i = 0; i < ARRAY_SIZE(efm32_uart_ports); ++i) { | ||
616 | if (efm32_uart_ports[i]) { | ||
617 | pr_warn("efm32-console: fall back to console index %u (from %hhi)\n", | ||
618 | i, co->index); | ||
619 | co->index = i; | ||
620 | break; | ||
621 | } | ||
622 | } | ||
623 | } | ||
624 | |||
625 | efm_port = efm32_uart_ports[co->index]; | ||
626 | if (!efm_port) { | ||
627 | pr_warn("efm32-console: No port at %d\n", co->index); | ||
628 | return -ENODEV; | ||
629 | } | ||
630 | |||
631 | ret = clk_prepare(efm_port->clk); | ||
632 | if (ret) { | ||
633 | dev_warn(efm_port->port.dev, | ||
634 | "console: clk_prepare failed: %d\n", ret); | ||
635 | return ret; | ||
636 | } | ||
637 | |||
638 | efm_port->port.uartclk = clk_get_rate(efm_port->clk); | ||
639 | |||
640 | if (options) | ||
641 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
642 | else | ||
643 | efm32_uart_console_get_options(efm_port, | ||
644 | &baud, &parity, &bits); | ||
645 | |||
646 | return uart_set_options(&efm_port->port, co, baud, parity, bits, flow); | ||
647 | } | ||
648 | |||
649 | static struct uart_driver efm32_uart_reg; | ||
650 | |||
651 | static struct console efm32_uart_console = { | ||
652 | .name = DEV_NAME, | ||
653 | .write = efm32_uart_console_write, | ||
654 | .device = uart_console_device, | ||
655 | .setup = efm32_uart_console_setup, | ||
656 | .flags = CON_PRINTBUFFER, | ||
657 | .index = -1, | ||
658 | .data = &efm32_uart_reg, | ||
659 | }; | ||
660 | |||
661 | #else | ||
662 | #define efm32_uart_console (*(struct console *)NULL) | ||
663 | #endif /* ifdef CONFIG_SERIAL_EFM32_UART_CONSOLE / else */ | ||
664 | |||
665 | static struct uart_driver efm32_uart_reg = { | ||
666 | .owner = THIS_MODULE, | ||
667 | .driver_name = DRIVER_NAME, | ||
668 | .dev_name = DEV_NAME, | ||
669 | .nr = ARRAY_SIZE(efm32_uart_ports), | ||
670 | .cons = &efm32_uart_console, | ||
671 | }; | ||
672 | |||
673 | static int efm32_uart_probe_dt(struct platform_device *pdev, | ||
674 | struct efm32_uart_port *efm_port) | ||
675 | { | ||
676 | struct device_node *np = pdev->dev.of_node; | ||
677 | int ret; | ||
678 | |||
679 | if (!np) | ||
680 | return 1; | ||
681 | |||
682 | ret = of_alias_get_id(np, "serial"); | ||
683 | if (ret < 0) { | ||
684 | dev_err(&pdev->dev, "failed to get alias id: %d\n", ret); | ||
685 | return ret; | ||
686 | } else { | ||
687 | efm_port->port.line = ret; | ||
688 | return 0; | ||
689 | } | ||
690 | |||
691 | } | ||
692 | |||
693 | static int __devinit efm32_uart_probe(struct platform_device *pdev) | ||
694 | { | ||
695 | struct efm32_uart_port *efm_port; | ||
696 | struct resource *res; | ||
697 | int ret; | ||
698 | |||
699 | efm_port = kzalloc(sizeof(*efm_port), GFP_KERNEL); | ||
700 | if (!efm_port) { | ||
701 | dev_dbg(&pdev->dev, "failed to allocate private data\n"); | ||
702 | return -ENOMEM; | ||
703 | } | ||
704 | |||
705 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
706 | if (!res) { | ||
707 | ret = -ENODEV; | ||
708 | dev_dbg(&pdev->dev, "failed to determine base address\n"); | ||
709 | goto err_get_base; | ||
710 | } | ||
711 | |||
712 | if (resource_size(res) < 60) { | ||
713 | ret = -EINVAL; | ||
714 | dev_dbg(&pdev->dev, "memory resource too small\n"); | ||
715 | goto err_too_small; | ||
716 | } | ||
717 | |||
718 | ret = platform_get_irq(pdev, 0); | ||
719 | if (ret <= 0) { | ||
720 | dev_dbg(&pdev->dev, "failed to get rx irq\n"); | ||
721 | goto err_get_rxirq; | ||
722 | } | ||
723 | |||
724 | efm_port->port.irq = ret; | ||
725 | |||
726 | ret = platform_get_irq(pdev, 1); | ||
727 | if (ret <= 0) | ||
728 | ret = efm_port->port.irq + 1; | ||
729 | |||
730 | efm_port->txirq = ret; | ||
731 | |||
732 | efm_port->port.dev = &pdev->dev; | ||
733 | efm_port->port.mapbase = res->start; | ||
734 | efm_port->port.type = PORT_EFMUART; | ||
735 | efm_port->port.iotype = UPIO_MEM32; | ||
736 | efm_port->port.fifosize = 2; | ||
737 | efm_port->port.ops = &efm32_uart_pops; | ||
738 | efm_port->port.flags = UPF_BOOT_AUTOCONF; | ||
739 | |||
740 | ret = efm32_uart_probe_dt(pdev, efm_port); | ||
741 | if (ret > 0) | ||
742 | /* not created by device tree */ | ||
743 | efm_port->port.line = pdev->id; | ||
744 | |||
745 | if (efm_port->port.line >= 0 && | ||
746 | efm_port->port.line < ARRAY_SIZE(efm32_uart_ports)) | ||
747 | efm32_uart_ports[efm_port->port.line] = efm_port; | ||
748 | |||
749 | ret = uart_add_one_port(&efm32_uart_reg, &efm_port->port); | ||
750 | if (ret) { | ||
751 | dev_dbg(&pdev->dev, "failed to add port: %d\n", ret); | ||
752 | |||
753 | if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_uart_ports)) | ||
754 | efm32_uart_ports[pdev->id] = NULL; | ||
755 | err_get_rxirq: | ||
756 | err_too_small: | ||
757 | err_get_base: | ||
758 | kfree(efm_port); | ||
759 | } else { | ||
760 | platform_set_drvdata(pdev, efm_port); | ||
761 | dev_dbg(&pdev->dev, "\\o/\n"); | ||
762 | } | ||
763 | |||
764 | return ret; | ||
765 | } | ||
766 | |||
767 | static int __devexit efm32_uart_remove(struct platform_device *pdev) | ||
768 | { | ||
769 | struct efm32_uart_port *efm_port = platform_get_drvdata(pdev); | ||
770 | |||
771 | platform_set_drvdata(pdev, NULL); | ||
772 | |||
773 | uart_remove_one_port(&efm32_uart_reg, &efm_port->port); | ||
774 | |||
775 | if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_uart_ports)) | ||
776 | efm32_uart_ports[pdev->id] = NULL; | ||
777 | |||
778 | kfree(efm_port); | ||
779 | |||
780 | return 0; | ||
781 | } | ||
782 | |||
783 | static struct of_device_id efm32_uart_dt_ids[] = { | ||
784 | { | ||
785 | .compatible = "efm32,uart", | ||
786 | }, { | ||
787 | /* sentinel */ | ||
788 | } | ||
789 | }; | ||
790 | MODULE_DEVICE_TABLE(of, efm32_uart_dt_ids); | ||
791 | |||
792 | static struct platform_driver efm32_uart_driver = { | ||
793 | .probe = efm32_uart_probe, | ||
794 | .remove = __devexit_p(efm32_uart_remove), | ||
795 | |||
796 | .driver = { | ||
797 | .name = DRIVER_NAME, | ||
798 | .owner = THIS_MODULE, | ||
799 | .of_match_table = efm32_uart_dt_ids, | ||
800 | }, | ||
801 | }; | ||
802 | |||
803 | static int __init efm32_uart_init(void) | ||
804 | { | ||
805 | int ret; | ||
806 | |||
807 | ret = uart_register_driver(&efm32_uart_reg); | ||
808 | if (ret) | ||
809 | return ret; | ||
810 | |||
811 | ret = platform_driver_register(&efm32_uart_driver); | ||
812 | if (ret) | ||
813 | uart_unregister_driver(&efm32_uart_reg); | ||
814 | |||
815 | pr_info("EFM32 UART/USART driver\n"); | ||
816 | |||
817 | return ret; | ||
818 | } | ||
819 | module_init(efm32_uart_init); | ||
820 | |||
821 | static void __exit efm32_uart_exit(void) | ||
822 | { | ||
823 | platform_driver_unregister(&efm32_uart_driver); | ||
824 | uart_unregister_driver(&efm32_uart_reg); | ||
825 | } | ||
826 | |||
827 | MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"); | ||
828 | MODULE_DESCRIPTION("EFM32 UART/USART driver"); | ||
829 | MODULE_LICENSE("GPL v2"); | ||
830 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 94a6792bf97b..e465dda63edf 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c | |||
@@ -70,13 +70,6 @@ | |||
70 | 70 | ||
71 | #define PASS_LIMIT 256 | 71 | #define PASS_LIMIT 256 |
72 | 72 | ||
73 | /* | ||
74 | * We default to IRQ0 for the "no irq" hack. Some | ||
75 | * machine types want others as well - they're free | ||
76 | * to redefine this in their header file. | ||
77 | */ | ||
78 | #define is_real_interrupt(irq) ((irq) != 0) | ||
79 | |||
80 | #define BASE_BAUD 115200 | 73 | #define BASE_BAUD 115200 |
81 | 74 | ||
82 | /* Standard COM flags */ | 75 | /* Standard COM flags */ |
@@ -640,7 +633,7 @@ static int m32r_sio_startup(struct uart_port *port) | |||
640 | * hardware interrupt, we use a timer-based system. The original | 633 | * hardware interrupt, we use a timer-based system. The original |
641 | * driver used to do this with IRQ0. | 634 | * driver used to do this with IRQ0. |
642 | */ | 635 | */ |
643 | if (!is_real_interrupt(up->port.irq)) { | 636 | if (!up->port.irq) { |
644 | unsigned int timeout = up->port.timeout; | 637 | unsigned int timeout = up->port.timeout; |
645 | 638 | ||
646 | timeout = timeout > 6 ? (timeout / 2 - 2) : 1; | 639 | timeout = timeout > 6 ? (timeout / 2 - 2) : 1; |
@@ -687,7 +680,7 @@ static void m32r_sio_shutdown(struct uart_port *port) | |||
687 | 680 | ||
688 | sio_init(); | 681 | sio_init(); |
689 | 682 | ||
690 | if (!is_real_interrupt(up->port.irq)) | 683 | if (!up->port.irq) |
691 | del_timer_sync(&up->timer); | 684 | del_timer_sync(&up->timer); |
692 | else | 685 | else |
693 | serial_unlink_irq_chain(up); | 686 | serial_unlink_irq_chain(up); |
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index 1093a88a1fe3..e9a770d77a6e 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c | |||
@@ -507,7 +507,7 @@ static int __init mpc512x_psc_fifoc_init(void) | |||
507 | 507 | ||
508 | psc_fifoc_irq = irq_of_parse_and_map(np, 0); | 508 | psc_fifoc_irq = irq_of_parse_and_map(np, 0); |
509 | of_node_put(np); | 509 | of_node_put(np); |
510 | if (psc_fifoc_irq == NO_IRQ) { | 510 | if (psc_fifoc_irq == 0) { |
511 | pr_err("%s: Can't get FIFOC irq\n", __func__); | 511 | pr_err("%s: Can't get FIFOC irq\n", __func__); |
512 | iounmap(psc_fifoc); | 512 | iounmap(psc_fifoc); |
513 | return -ENODEV; | 513 | return -ENODEV; |
@@ -1354,7 +1354,7 @@ static int __devinit mpc52xx_uart_of_probe(struct platform_device *op) | |||
1354 | } | 1354 | } |
1355 | 1355 | ||
1356 | psc_ops->get_irq(port, op->dev.of_node); | 1356 | psc_ops->get_irq(port, op->dev.of_node); |
1357 | if (port->irq == NO_IRQ) { | 1357 | if (port->irq == 0) { |
1358 | dev_dbg(&op->dev, "Could not get irq\n"); | 1358 | dev_dbg(&op->dev, "Could not get irq\n"); |
1359 | return -EINVAL; | 1359 | return -EINVAL; |
1360 | } | 1360 | } |
diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c index 06f6aefd5ba6..c61d950e07c1 100644 --- a/drivers/tty/serial/mux.c +++ b/drivers/tty/serial/mux.c | |||
@@ -499,7 +499,7 @@ static int __init mux_probe(struct parisc_device *dev) | |||
499 | port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET); | 499 | port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET); |
500 | port->iotype = UPIO_MEM; | 500 | port->iotype = UPIO_MEM; |
501 | port->type = PORT_MUX; | 501 | port->type = PORT_MUX; |
502 | port->irq = NO_IRQ; | 502 | port->irq = 0; |
503 | port->uartclk = 0; | 503 | port->uartclk = 0; |
504 | port->fifosize = MUX_FIFO_SIZE; | 504 | port->fifosize = MUX_FIFO_SIZE; |
505 | port->ops = &mux_pops; | 505 | port->ops = &mux_pops; |
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 17ae65762d1a..aa4d07b4a9d5 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/nmi.h> | 29 | #include <linux/nmi.h> |
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | 31 | ||
32 | #include <linux/debugfs.h> | ||
32 | #include <linux/dmaengine.h> | 33 | #include <linux/dmaengine.h> |
33 | #include <linux/pch_dma.h> | 34 | #include <linux/pch_dma.h> |
34 | 35 | ||
@@ -144,6 +145,8 @@ enum { | |||
144 | #define PCH_UART_DLL 0x00 | 145 | #define PCH_UART_DLL 0x00 |
145 | #define PCH_UART_DLM 0x01 | 146 | #define PCH_UART_DLM 0x01 |
146 | 147 | ||
148 | #define PCH_UART_BRCSR 0x0E | ||
149 | |||
147 | #define PCH_UART_IID_RLS (PCH_UART_IIR_REI) | 150 | #define PCH_UART_IID_RLS (PCH_UART_IIR_REI) |
148 | #define PCH_UART_IID_RDR (PCH_UART_IIR_RRI) | 151 | #define PCH_UART_IID_RDR (PCH_UART_IIR_RRI) |
149 | #define PCH_UART_IID_RDR_TO (PCH_UART_IIR_RRI | PCH_UART_IIR_TOI) | 152 | #define PCH_UART_IID_RDR_TO (PCH_UART_IIR_RRI | PCH_UART_IIR_TOI) |
@@ -243,6 +246,8 @@ struct eg20t_port { | |||
243 | int tx_dma_use; | 246 | int tx_dma_use; |
244 | void *rx_buf_virt; | 247 | void *rx_buf_virt; |
245 | dma_addr_t rx_buf_dma; | 248 | dma_addr_t rx_buf_dma; |
249 | |||
250 | struct dentry *debugfs; | ||
246 | }; | 251 | }; |
247 | 252 | ||
248 | /** | 253 | /** |
@@ -292,23 +297,73 @@ static const int trigger_level_64[4] = { 1, 16, 32, 56 }; | |||
292 | static const int trigger_level_16[4] = { 1, 4, 8, 14 }; | 297 | static const int trigger_level_16[4] = { 1, 4, 8, 14 }; |
293 | static const int trigger_level_1[4] = { 1, 1, 1, 1 }; | 298 | static const int trigger_level_1[4] = { 1, 1, 1, 1 }; |
294 | 299 | ||
295 | static void pch_uart_hal_request(struct pci_dev *pdev, int fifosize, | 300 | #ifdef CONFIG_DEBUG_FS |
296 | int base_baud) | ||
297 | { | ||
298 | struct eg20t_port *priv = pci_get_drvdata(pdev); | ||
299 | 301 | ||
300 | priv->trigger_level = 1; | 302 | #define PCH_REGS_BUFSIZE 1024 |
301 | priv->fcr = 0; | 303 | static int pch_show_regs_open(struct inode *inode, struct file *file) |
304 | { | ||
305 | file->private_data = inode->i_private; | ||
306 | return 0; | ||
302 | } | 307 | } |
303 | 308 | ||
304 | static unsigned int get_msr(struct eg20t_port *priv, void __iomem *base) | 309 | static ssize_t port_show_regs(struct file *file, char __user *user_buf, |
310 | size_t count, loff_t *ppos) | ||
305 | { | 311 | { |
306 | unsigned int msr = ioread8(base + UART_MSR); | 312 | struct eg20t_port *priv = file->private_data; |
307 | priv->dmsr |= msr & PCH_UART_MSR_DELTA; | 313 | char *buf; |
314 | u32 len = 0; | ||
315 | ssize_t ret; | ||
316 | unsigned char lcr; | ||
317 | |||
318 | buf = kzalloc(PCH_REGS_BUFSIZE, GFP_KERNEL); | ||
319 | if (!buf) | ||
320 | return 0; | ||
321 | |||
322 | len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, | ||
323 | "PCH EG20T port[%d] regs:\n", priv->port.line); | ||
324 | |||
325 | len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, | ||
326 | "=================================\n"); | ||
327 | len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, | ||
328 | "IER: \t0x%02x\n", ioread8(priv->membase + UART_IER)); | ||
329 | len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, | ||
330 | "IIR: \t0x%02x\n", ioread8(priv->membase + UART_IIR)); | ||
331 | len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, | ||
332 | "LCR: \t0x%02x\n", ioread8(priv->membase + UART_LCR)); | ||
333 | len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, | ||
334 | "MCR: \t0x%02x\n", ioread8(priv->membase + UART_MCR)); | ||
335 | len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, | ||
336 | "LSR: \t0x%02x\n", ioread8(priv->membase + UART_LSR)); | ||
337 | len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, | ||
338 | "MSR: \t0x%02x\n", ioread8(priv->membase + UART_MSR)); | ||
339 | len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, | ||
340 | "BRCSR: \t0x%02x\n", | ||
341 | ioread8(priv->membase + PCH_UART_BRCSR)); | ||
308 | 342 | ||
309 | return msr; | 343 | lcr = ioread8(priv->membase + UART_LCR); |
344 | iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR); | ||
345 | len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, | ||
346 | "DLL: \t0x%02x\n", ioread8(priv->membase + UART_DLL)); | ||
347 | len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, | ||
348 | "DLM: \t0x%02x\n", ioread8(priv->membase + UART_DLM)); | ||
349 | iowrite8(lcr, priv->membase + UART_LCR); | ||
350 | |||
351 | if (len > PCH_REGS_BUFSIZE) | ||
352 | len = PCH_REGS_BUFSIZE; | ||
353 | |||
354 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
355 | kfree(buf); | ||
356 | return ret; | ||
310 | } | 357 | } |
311 | 358 | ||
359 | static const struct file_operations port_regs_ops = { | ||
360 | .owner = THIS_MODULE, | ||
361 | .open = pch_show_regs_open, | ||
362 | .read = port_show_regs, | ||
363 | .llseek = default_llseek, | ||
364 | }; | ||
365 | #endif /* CONFIG_DEBUG_FS */ | ||
366 | |||
312 | static void pch_uart_hal_enable_interrupt(struct eg20t_port *priv, | 367 | static void pch_uart_hal_enable_interrupt(struct eg20t_port *priv, |
313 | unsigned int flag) | 368 | unsigned int flag) |
314 | { | 369 | { |
@@ -442,8 +497,9 @@ static int pch_uart_hal_set_fifo(struct eg20t_port *priv, | |||
442 | 497 | ||
443 | static u8 pch_uart_hal_get_modem(struct eg20t_port *priv) | 498 | static u8 pch_uart_hal_get_modem(struct eg20t_port *priv) |
444 | { | 499 | { |
445 | priv->dmsr = 0; | 500 | unsigned int msr = ioread8(priv->membase + UART_MSR); |
446 | return get_msr(priv, priv->membase); | 501 | priv->dmsr = msr & PCH_UART_MSR_DELTA; |
502 | return (u8)msr; | ||
447 | } | 503 | } |
448 | 504 | ||
449 | static void pch_uart_hal_write(struct eg20t_port *priv, | 505 | static void pch_uart_hal_write(struct eg20t_port *priv, |
@@ -524,7 +580,7 @@ static int push_rx(struct eg20t_port *priv, const unsigned char *buf, | |||
524 | 580 | ||
525 | static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf) | 581 | static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf) |
526 | { | 582 | { |
527 | int ret; | 583 | int ret = 0; |
528 | struct uart_port *port = &priv->port; | 584 | struct uart_port *port = &priv->port; |
529 | 585 | ||
530 | if (port->x_char) { | 586 | if (port->x_char) { |
@@ -533,8 +589,6 @@ static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf) | |||
533 | buf[0] = port->x_char; | 589 | buf[0] = port->x_char; |
534 | port->x_char = 0; | 590 | port->x_char = 0; |
535 | ret = 1; | 591 | ret = 1; |
536 | } else { | ||
537 | ret = 0; | ||
538 | } | 592 | } |
539 | 593 | ||
540 | return ret; | 594 | return ret; |
@@ -1032,14 +1086,12 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) | |||
1032 | static unsigned int pch_uart_tx_empty(struct uart_port *port) | 1086 | static unsigned int pch_uart_tx_empty(struct uart_port *port) |
1033 | { | 1087 | { |
1034 | struct eg20t_port *priv; | 1088 | struct eg20t_port *priv; |
1035 | int ret; | 1089 | |
1036 | priv = container_of(port, struct eg20t_port, port); | 1090 | priv = container_of(port, struct eg20t_port, port); |
1037 | if (priv->tx_empty) | 1091 | if (priv->tx_empty) |
1038 | ret = TIOCSER_TEMT; | 1092 | return TIOCSER_TEMT; |
1039 | else | 1093 | else |
1040 | ret = 0; | 1094 | return 0; |
1041 | |||
1042 | return ret; | ||
1043 | } | 1095 | } |
1044 | 1096 | ||
1045 | /* Returns the current state of modem control inputs. */ | 1097 | /* Returns the current state of modem control inputs. */ |
@@ -1273,9 +1325,8 @@ static void pch_uart_set_termios(struct uart_port *port, | |||
1273 | else | 1325 | else |
1274 | parity = PCH_UART_HAL_PARITY_EVEN; | 1326 | parity = PCH_UART_HAL_PARITY_EVEN; |
1275 | 1327 | ||
1276 | } else { | 1328 | } else |
1277 | parity = PCH_UART_HAL_PARITY_NONE; | 1329 | parity = PCH_UART_HAL_PARITY_NONE; |
1278 | } | ||
1279 | 1330 | ||
1280 | /* Only UART0 has auto hardware flow function */ | 1331 | /* Only UART0 has auto hardware flow function */ |
1281 | if ((termios->c_cflag & CRTSCTS) && (priv->fifo_size == 256)) | 1332 | if ((termios->c_cflag & CRTSCTS) && (priv->fifo_size == 256)) |
@@ -1447,7 +1498,6 @@ static void | |||
1447 | pch_console_write(struct console *co, const char *s, unsigned int count) | 1498 | pch_console_write(struct console *co, const char *s, unsigned int count) |
1448 | { | 1499 | { |
1449 | struct eg20t_port *priv; | 1500 | struct eg20t_port *priv; |
1450 | |||
1451 | unsigned long flags; | 1501 | unsigned long flags; |
1452 | u8 ier; | 1502 | u8 ier; |
1453 | int locked = 1; | 1503 | int locked = 1; |
@@ -1554,6 +1604,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, | |||
1554 | int port_type; | 1604 | int port_type; |
1555 | struct pch_uart_driver_data *board; | 1605 | struct pch_uart_driver_data *board; |
1556 | const char *board_name; | 1606 | const char *board_name; |
1607 | char name[32]; /* for debugfs file name */ | ||
1557 | 1608 | ||
1558 | board = &drv_dat[id->driver_data]; | 1609 | board = &drv_dat[id->driver_data]; |
1559 | port_type = board->port_type; | 1610 | port_type = board->port_type; |
@@ -1614,7 +1665,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, | |||
1614 | spin_lock_init(&priv->port.lock); | 1665 | spin_lock_init(&priv->port.lock); |
1615 | 1666 | ||
1616 | pci_set_drvdata(pdev, priv); | 1667 | pci_set_drvdata(pdev, priv); |
1617 | pch_uart_hal_request(pdev, fifosize, base_baud); | 1668 | priv->trigger_level = 1; |
1669 | priv->fcr = 0; | ||
1618 | 1670 | ||
1619 | #ifdef CONFIG_SERIAL_PCH_UART_CONSOLE | 1671 | #ifdef CONFIG_SERIAL_PCH_UART_CONSOLE |
1620 | pch_uart_ports[board->line_no] = priv; | 1672 | pch_uart_ports[board->line_no] = priv; |
@@ -1623,6 +1675,12 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, | |||
1623 | if (ret < 0) | 1675 | if (ret < 0) |
1624 | goto init_port_hal_free; | 1676 | goto init_port_hal_free; |
1625 | 1677 | ||
1678 | #ifdef CONFIG_DEBUG_FS | ||
1679 | snprintf(name, sizeof(name), "uart%d_regs", board->line_no); | ||
1680 | priv->debugfs = debugfs_create_file(name, S_IFREG | S_IRUGO, | ||
1681 | NULL, priv, &port_regs_ops); | ||
1682 | #endif | ||
1683 | |||
1626 | return priv; | 1684 | return priv; |
1627 | 1685 | ||
1628 | init_port_hal_free: | 1686 | init_port_hal_free: |
@@ -1639,6 +1697,11 @@ init_port_alloc_err: | |||
1639 | 1697 | ||
1640 | static void pch_uart_exit_port(struct eg20t_port *priv) | 1698 | static void pch_uart_exit_port(struct eg20t_port *priv) |
1641 | { | 1699 | { |
1700 | |||
1701 | #ifdef CONFIG_DEBUG_FS | ||
1702 | if (priv->debugfs) | ||
1703 | debugfs_remove(priv->debugfs); | ||
1704 | #endif | ||
1642 | uart_remove_one_port(&pch_uart_driver, &priv->port); | 1705 | uart_remove_one_port(&pch_uart_driver, &priv->port); |
1643 | pci_set_drvdata(priv->pdev, NULL); | 1706 | pci_set_drvdata(priv->pdev, NULL); |
1644 | free_page((unsigned long)priv->rxbuf.buf); | 1707 | free_page((unsigned long)priv->rxbuf.buf); |
@@ -1646,9 +1709,7 @@ static void pch_uart_exit_port(struct eg20t_port *priv) | |||
1646 | 1709 | ||
1647 | static void pch_uart_pci_remove(struct pci_dev *pdev) | 1710 | static void pch_uart_pci_remove(struct pci_dev *pdev) |
1648 | { | 1711 | { |
1649 | struct eg20t_port *priv; | 1712 | struct eg20t_port *priv = pci_get_drvdata(pdev); |
1650 | |||
1651 | priv = (struct eg20t_port *)pci_get_drvdata(pdev); | ||
1652 | 1713 | ||
1653 | pci_disable_msi(pdev); | 1714 | pci_disable_msi(pdev); |
1654 | 1715 | ||
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index e9c2dfe471a2..08ebe901bb59 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c | |||
@@ -1506,7 +1506,7 @@ no_dma: | |||
1506 | * fixed up interrupt info, but we use the device-tree directly | 1506 | * fixed up interrupt info, but we use the device-tree directly |
1507 | * here due to early probing so we need the fixup too. | 1507 | * here due to early probing so we need the fixup too. |
1508 | */ | 1508 | */ |
1509 | if (uap->port.irq == NO_IRQ && | 1509 | if (uap->port.irq == 0 && |
1510 | np->parent && np->parent->parent && | 1510 | np->parent && np->parent->parent && |
1511 | of_device_is_compatible(np->parent->parent, "gatwick")) { | 1511 | of_device_is_compatible(np->parent->parent, "gatwick")) { |
1512 | /* IRQs on gatwick are offset by 64 */ | 1512 | /* IRQs on gatwick are offset by 64 */ |
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index 8e916e76b7b5..5a47d1b196d8 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c | |||
@@ -1397,7 +1397,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) | |||
1397 | #endif | 1397 | #endif |
1398 | } | 1398 | } |
1399 | 1399 | ||
1400 | static int zilog_irq = -1; | 1400 | static int zilog_irq; |
1401 | 1401 | ||
1402 | static int __devinit zs_probe(struct platform_device *op) | 1402 | static int __devinit zs_probe(struct platform_device *op) |
1403 | { | 1403 | { |
@@ -1425,7 +1425,7 @@ static int __devinit zs_probe(struct platform_device *op) | |||
1425 | 1425 | ||
1426 | rp = sunzilog_chip_regs[inst]; | 1426 | rp = sunzilog_chip_regs[inst]; |
1427 | 1427 | ||
1428 | if (zilog_irq == -1) | 1428 | if (!zilog_irq) |
1429 | zilog_irq = op->archdata.irqs[0]; | 1429 | zilog_irq = op->archdata.irqs[0]; |
1430 | 1430 | ||
1431 | up = &sunzilog_port_table[inst * 2]; | 1431 | up = &sunzilog_port_table[inst * 2]; |
@@ -1580,7 +1580,7 @@ static int __init sunzilog_init(void) | |||
1580 | if (err) | 1580 | if (err) |
1581 | goto out_unregister_uart; | 1581 | goto out_unregister_uart; |
1582 | 1582 | ||
1583 | if (zilog_irq != -1) { | 1583 | if (!zilog_irq) { |
1584 | struct uart_sunzilog_port *up = sunzilog_irq_chain; | 1584 | struct uart_sunzilog_port *up = sunzilog_irq_chain; |
1585 | err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, | 1585 | err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, |
1586 | "zs", sunzilog_irq_chain); | 1586 | "zs", sunzilog_irq_chain); |
@@ -1621,7 +1621,7 @@ static void __exit sunzilog_exit(void) | |||
1621 | { | 1621 | { |
1622 | platform_driver_unregister(&zs_driver); | 1622 | platform_driver_unregister(&zs_driver); |
1623 | 1623 | ||
1624 | if (zilog_irq != -1) { | 1624 | if (!zilog_irq) { |
1625 | struct uart_sunzilog_port *up = sunzilog_irq_chain; | 1625 | struct uart_sunzilog_port *up = sunzilog_irq_chain; |
1626 | 1626 | ||
1627 | /* Disable Interrupts */ | 1627 | /* Disable Interrupts */ |
@@ -1637,7 +1637,7 @@ static void __exit sunzilog_exit(void) | |||
1637 | } | 1637 | } |
1638 | 1638 | ||
1639 | free_irq(zilog_irq, sunzilog_irq_chain); | 1639 | free_irq(zilog_irq, sunzilog_irq_chain); |
1640 | zilog_irq = -1; | 1640 | zilog_irq = 0; |
1641 | } | 1641 | } |
1642 | 1642 | ||
1643 | if (sunzilog_reg.nr) { | 1643 | if (sunzilog_reg.nr) { |
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index 2ebe606a2db1..f99b0c965f85 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c | |||
@@ -1360,7 +1360,7 @@ static int ucc_uart_probe(struct platform_device *ofdev) | |||
1360 | } | 1360 | } |
1361 | 1361 | ||
1362 | qe_port->port.irq = irq_of_parse_and_map(np, 0); | 1362 | qe_port->port.irq = irq_of_parse_and_map(np, 0); |
1363 | if (qe_port->port.irq == NO_IRQ) { | 1363 | if (qe_port->port.irq == 0) { |
1364 | dev_err(&ofdev->dev, "could not map IRQ for UCC%u\n", | 1364 | dev_err(&ofdev->dev, "could not map IRQ for UCC%u\n", |
1365 | qe_port->ucc_num + 1); | 1365 | qe_port->ucc_num + 1); |
1366 | ret = -EINVAL; | 1366 | ret = -EINVAL; |
diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c index 83148e79ca13..cf0d9485ec08 100644 --- a/drivers/tty/serial/vr41xx_siu.c +++ b/drivers/tty/serial/vr41xx_siu.c | |||
@@ -61,7 +61,7 @@ | |||
61 | static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = { | 61 | static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = { |
62 | [0 ... SIU_PORTS_MAX-1] = { | 62 | [0 ... SIU_PORTS_MAX-1] = { |
63 | .lock = __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock), | 63 | .lock = __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock), |
64 | .irq = -1, | 64 | .irq = 0, |
65 | }, | 65 | }, |
66 | }; | 66 | }; |
67 | 67 | ||
@@ -171,7 +171,7 @@ static inline unsigned int siu_check_type(struct uart_port *port) | |||
171 | { | 171 | { |
172 | if (port->line == 0) | 172 | if (port->line == 0) |
173 | return PORT_VR41XX_SIU; | 173 | return PORT_VR41XX_SIU; |
174 | if (port->line == 1 && port->irq != -1) | 174 | if (port->line == 1 && port->irq) |
175 | return PORT_VR41XX_DSIU; | 175 | return PORT_VR41XX_DSIU; |
176 | 176 | ||
177 | return PORT_UNKNOWN; | 177 | return PORT_UNKNOWN; |
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 7867b7c4538e..8db9125133b8 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c | |||
@@ -322,11 +322,16 @@ static void send_sig_all(int sig) | |||
322 | { | 322 | { |
323 | struct task_struct *p; | 323 | struct task_struct *p; |
324 | 324 | ||
325 | read_lock(&tasklist_lock); | ||
325 | for_each_process(p) { | 326 | for_each_process(p) { |
326 | if (p->mm && !is_global_init(p)) | 327 | if (p->flags & PF_KTHREAD) |
327 | /* Not swapper, init nor kernel thread */ | 328 | continue; |
328 | force_sig(sig, p); | 329 | if (is_global_init(p)) |
330 | continue; | ||
331 | |||
332 | force_sig(sig, p); | ||
329 | } | 333 | } |
334 | read_unlock(&tasklist_lock); | ||
330 | } | 335 | } |
331 | 336 | ||
332 | static void sysrq_handle_term(int key) | 337 | static void sysrq_handle_term(int key) |
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index e41b9bbc107d..ea7ebe22a16c 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -1271,6 +1271,19 @@ int tty_init_termios(struct tty_struct *tty) | |||
1271 | } | 1271 | } |
1272 | EXPORT_SYMBOL_GPL(tty_init_termios); | 1272 | EXPORT_SYMBOL_GPL(tty_init_termios); |
1273 | 1273 | ||
1274 | int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty) | ||
1275 | { | ||
1276 | int ret = tty_init_termios(tty); | ||
1277 | if (ret) | ||
1278 | return ret; | ||
1279 | |||
1280 | tty_driver_kref_get(driver); | ||
1281 | tty->count++; | ||
1282 | driver->ttys[tty->index] = tty; | ||
1283 | return 0; | ||
1284 | } | ||
1285 | EXPORT_SYMBOL_GPL(tty_standard_install); | ||
1286 | |||
1274 | /** | 1287 | /** |
1275 | * tty_driver_install_tty() - install a tty entry in the driver | 1288 | * tty_driver_install_tty() - install a tty entry in the driver |
1276 | * @driver: the driver for the tty | 1289 | * @driver: the driver for the tty |
@@ -1286,21 +1299,8 @@ EXPORT_SYMBOL_GPL(tty_init_termios); | |||
1286 | static int tty_driver_install_tty(struct tty_driver *driver, | 1299 | static int tty_driver_install_tty(struct tty_driver *driver, |
1287 | struct tty_struct *tty) | 1300 | struct tty_struct *tty) |
1288 | { | 1301 | { |
1289 | int idx = tty->index; | 1302 | return driver->ops->install ? driver->ops->install(driver, tty) : |
1290 | int ret; | 1303 | tty_standard_install(driver, tty); |
1291 | |||
1292 | if (driver->ops->install) { | ||
1293 | ret = driver->ops->install(driver, tty); | ||
1294 | return ret; | ||
1295 | } | ||
1296 | |||
1297 | if (tty_init_termios(tty) == 0) { | ||
1298 | tty_driver_kref_get(driver); | ||
1299 | tty->count++; | ||
1300 | driver->ttys[idx] = tty; | ||
1301 | return 0; | ||
1302 | } | ||
1303 | return -ENOMEM; | ||
1304 | } | 1304 | } |
1305 | 1305 | ||
1306 | /** | 1306 | /** |
@@ -1365,7 +1365,6 @@ static int tty_reopen(struct tty_struct *tty) | |||
1365 | * @driver: tty driver we are opening a device on | 1365 | * @driver: tty driver we are opening a device on |
1366 | * @idx: device index | 1366 | * @idx: device index |
1367 | * @ret_tty: returned tty structure | 1367 | * @ret_tty: returned tty structure |
1368 | * @first_ok: ok to open a new device (used by ptmx) | ||
1369 | * | 1368 | * |
1370 | * Prepare a tty device. This may not be a "new" clean device but | 1369 | * Prepare a tty device. This may not be a "new" clean device but |
1371 | * could also be an active device. The pty drivers require special | 1370 | * could also be an active device. The pty drivers require special |
@@ -1385,18 +1384,11 @@ static int tty_reopen(struct tty_struct *tty) | |||
1385 | * relaxed for the (most common) case of reopening a tty. | 1384 | * relaxed for the (most common) case of reopening a tty. |
1386 | */ | 1385 | */ |
1387 | 1386 | ||
1388 | struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | 1387 | struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) |
1389 | int first_ok) | ||
1390 | { | 1388 | { |
1391 | struct tty_struct *tty; | 1389 | struct tty_struct *tty; |
1392 | int retval; | 1390 | int retval; |
1393 | 1391 | ||
1394 | /* Check if pty master is being opened multiple times */ | ||
1395 | if (driver->subtype == PTY_TYPE_MASTER && | ||
1396 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { | ||
1397 | return ERR_PTR(-EIO); | ||
1398 | } | ||
1399 | |||
1400 | /* | 1392 | /* |
1401 | * First time open is complex, especially for PTY devices. | 1393 | * First time open is complex, especially for PTY devices. |
1402 | * This code guarantees that either everything succeeds and the | 1394 | * This code guarantees that either everything succeeds and the |
@@ -1797,11 +1789,11 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1797 | * the slots and preserving the termios structure. | 1789 | * the slots and preserving the termios structure. |
1798 | */ | 1790 | */ |
1799 | release_tty(tty, idx); | 1791 | release_tty(tty, idx); |
1792 | tty_unlock(); | ||
1800 | 1793 | ||
1801 | /* Make this pty number available for reallocation */ | 1794 | /* Make this pty number available for reallocation */ |
1802 | if (devpts) | 1795 | if (devpts) |
1803 | devpts_kill_index(inode, idx); | 1796 | devpts_kill_index(inode, idx); |
1804 | tty_unlock(); | ||
1805 | return 0; | 1797 | return 0; |
1806 | } | 1798 | } |
1807 | 1799 | ||
@@ -1950,7 +1942,7 @@ retry_open: | |||
1950 | if (retval) | 1942 | if (retval) |
1951 | tty = ERR_PTR(retval); | 1943 | tty = ERR_PTR(retval); |
1952 | } else | 1944 | } else |
1953 | tty = tty_init_dev(driver, index, 0); | 1945 | tty = tty_init_dev(driver, index); |
1954 | 1946 | ||
1955 | mutex_unlock(&tty_mutex); | 1947 | mutex_unlock(&tty_mutex); |
1956 | if (driver) | 1948 | if (driver) |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 611b206591cb..1e30cc92719c 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -214,15 +214,14 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) | |||
214 | if (!try_module_get(serial->type->driver.owner)) | 214 | if (!try_module_get(serial->type->driver.owner)) |
215 | goto error_module_get; | 215 | goto error_module_get; |
216 | 216 | ||
217 | /* perform the standard setup */ | ||
218 | retval = tty_init_termios(tty); | ||
219 | if (retval) | ||
220 | goto error_init_termios; | ||
221 | |||
222 | retval = usb_autopm_get_interface(serial->interface); | 217 | retval = usb_autopm_get_interface(serial->interface); |
223 | if (retval) | 218 | if (retval) |
224 | goto error_get_interface; | 219 | goto error_get_interface; |
225 | 220 | ||
221 | retval = tty_standard_install(driver, tty); | ||
222 | if (retval) | ||
223 | goto error_init_termios; | ||
224 | |||
226 | mutex_unlock(&serial->disc_mutex); | 225 | mutex_unlock(&serial->disc_mutex); |
227 | 226 | ||
228 | /* allow the driver to update the settings */ | 227 | /* allow the driver to update the settings */ |
@@ -231,14 +230,11 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) | |||
231 | 230 | ||
232 | tty->driver_data = port; | 231 | tty->driver_data = port; |
233 | 232 | ||
234 | /* Final install (we use the default method) */ | ||
235 | tty_driver_kref_get(driver); | ||
236 | tty->count++; | ||
237 | driver->ttys[idx] = tty; | ||
238 | return retval; | 233 | return retval; |
239 | 234 | ||
240 | error_get_interface: | ||
241 | error_init_termios: | 235 | error_init_termios: |
236 | usb_autopm_put_interface(serial->interface); | ||
237 | error_get_interface: | ||
242 | module_put(serial->type->driver.owner); | 238 | module_put(serial->type->driver.owner); |
243 | error_module_get: | 239 | error_module_get: |
244 | error_no_port: | 240 | error_no_port: |