diff options
Diffstat (limited to 'drivers/serial')
| -rw-r--r-- | drivers/serial/serial_txx9.c | 118 |
1 files changed, 91 insertions, 27 deletions
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 49afadbe461b..f10c86d60b64 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c | |||
| @@ -31,6 +31,8 @@ | |||
| 31 | * 1.01 Set fifosize to make tx_empry called properly. | 31 | * 1.01 Set fifosize to make tx_empry called properly. |
| 32 | * Use standard uart_get_divisor. | 32 | * Use standard uart_get_divisor. |
| 33 | * 1.02 Cleanup. (import 8250.c changes) | 33 | * 1.02 Cleanup. (import 8250.c changes) |
| 34 | * 1.03 Fix low-latency mode. (import 8250.c changes) | ||
| 35 | * 1.04 Remove usage of deprecated functions, cleanup. | ||
| 34 | */ | 36 | */ |
| 35 | #include <linux/config.h> | 37 | #include <linux/config.h> |
| 36 | 38 | ||
| @@ -54,7 +56,7 @@ | |||
| 54 | #include <asm/io.h> | 56 | #include <asm/io.h> |
| 55 | #include <asm/irq.h> | 57 | #include <asm/irq.h> |
| 56 | 58 | ||
| 57 | static char *serial_version = "1.02"; | 59 | static char *serial_version = "1.04"; |
| 58 | static char *serial_name = "TX39/49 Serial driver"; | 60 | static char *serial_name = "TX39/49 Serial driver"; |
| 59 | 61 | ||
| 60 | #define PASS_LIMIT 256 | 62 | #define PASS_LIMIT 256 |
| @@ -86,9 +88,9 @@ static char *serial_name = "TX39/49 Serial driver"; | |||
| 86 | */ | 88 | */ |
| 87 | #ifdef ENABLE_SERIAL_TXX9_PCI | 89 | #ifdef ENABLE_SERIAL_TXX9_PCI |
| 88 | #define NR_PCI_BOARDS 4 | 90 | #define NR_PCI_BOARDS 4 |
| 89 | #define UART_NR (2 + NR_PCI_BOARDS) | 91 | #define UART_NR (4 + NR_PCI_BOARDS) |
| 90 | #else | 92 | #else |
| 91 | #define UART_NR 2 | 93 | #define UART_NR 4 |
| 92 | #endif | 94 | #endif |
| 93 | 95 | ||
| 94 | struct uart_txx9_port { | 96 | struct uart_txx9_port { |
| @@ -304,8 +306,11 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r | |||
| 304 | /* The following is not allowed by the tty layer and | 306 | /* The following is not allowed by the tty layer and |
| 305 | unsafe. It should be fixed ASAP */ | 307 | unsafe. It should be fixed ASAP */ |
| 306 | if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { | 308 | if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { |
| 307 | if(tty->low_latency) | 309 | if (tty->low_latency) { |
| 310 | spin_unlock(&up->port.lock); | ||
| 308 | tty_flip_buffer_push(tty); | 311 | tty_flip_buffer_push(tty); |
| 312 | spin_lock(&up->port.lock); | ||
| 313 | } | ||
| 309 | /* If this failed then we will throw away the | 314 | /* If this failed then we will throw away the |
| 310 | bytes but must do so to clear interrupts */ | 315 | bytes but must do so to clear interrupts */ |
| 311 | } | 316 | } |
| @@ -356,7 +361,9 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r | |||
| 356 | ignore_char: | 361 | ignore_char: |
| 357 | disr = sio_in(up, TXX9_SIDISR); | 362 | disr = sio_in(up, TXX9_SIDISR); |
| 358 | } while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0)); | 363 | } while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0)); |
| 364 | spin_unlock(&up->port.lock); | ||
| 359 | tty_flip_buffer_push(tty); | 365 | tty_flip_buffer_push(tty); |
| 366 | spin_lock(&up->port.lock); | ||
| 360 | *status = disr; | 367 | *status = disr; |
| 361 | } | 368 | } |
| 362 | 369 | ||
| @@ -667,17 +674,8 @@ serial_txx9_pm(struct uart_port *port, unsigned int state, | |||
| 667 | unsigned int oldstate) | 674 | unsigned int oldstate) |
| 668 | { | 675 | { |
| 669 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | 676 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; |
| 670 | if (state) { | 677 | if (up->pm) |
| 671 | /* sleep */ | 678 | up->pm(port, state, oldstate); |
| 672 | |||
| 673 | if (up->pm) | ||
| 674 | up->pm(port, state, oldstate); | ||
| 675 | } else { | ||
| 676 | /* wake */ | ||
| 677 | |||
| 678 | if (up->pm) | ||
| 679 | up->pm(port, state, oldstate); | ||
| 680 | } | ||
| 681 | } | 679 | } |
| 682 | 680 | ||
| 683 | static int serial_txx9_request_resource(struct uart_txx9_port *up) | 681 | static int serial_txx9_request_resource(struct uart_txx9_port *up) |
| @@ -979,14 +977,6 @@ static int __init serial_txx9_console_init(void) | |||
| 979 | } | 977 | } |
| 980 | console_initcall(serial_txx9_console_init); | 978 | console_initcall(serial_txx9_console_init); |
| 981 | 979 | ||
| 982 | static int __init serial_txx9_late_console_init(void) | ||
| 983 | { | ||
| 984 | if (!(serial_txx9_console.flags & CON_ENABLED)) | ||
| 985 | register_console(&serial_txx9_console); | ||
| 986 | return 0; | ||
| 987 | } | ||
| 988 | late_initcall(serial_txx9_late_console_init); | ||
| 989 | |||
| 990 | #define SERIAL_TXX9_CONSOLE &serial_txx9_console | 980 | #define SERIAL_TXX9_CONSOLE &serial_txx9_console |
| 991 | #else | 981 | #else |
| 992 | #define SERIAL_TXX9_CONSOLE NULL | 982 | #define SERIAL_TXX9_CONSOLE NULL |
| @@ -1039,6 +1029,73 @@ static void serial_txx9_resume_port(int line) | |||
| 1039 | uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port); | 1029 | uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port); |
| 1040 | } | 1030 | } |
| 1041 | 1031 | ||
| 1032 | static DECLARE_MUTEX(serial_txx9_sem); | ||
| 1033 | |||
| 1034 | /** | ||
| 1035 | * serial_txx9_register_port - register a serial port | ||
| 1036 | * @port: serial port template | ||
| 1037 | * | ||
| 1038 | * Configure the serial port specified by the request. | ||
| 1039 | * | ||
| 1040 | * The port is then probed and if necessary the IRQ is autodetected | ||
| 1041 | * If this fails an error is returned. | ||
| 1042 | * | ||
| 1043 | * On success the port is ready to use and the line number is returned. | ||
| 1044 | */ | ||
| 1045 | static int __devinit serial_txx9_register_port(struct uart_port *port) | ||
| 1046 | { | ||
| 1047 | int i; | ||
| 1048 | struct uart_txx9_port *uart; | ||
| 1049 | int ret = -ENOSPC; | ||
| 1050 | |||
| 1051 | down(&serial_txx9_sem); | ||
| 1052 | for (i = 0; i < UART_NR; i++) { | ||
| 1053 | uart = &serial_txx9_ports[i]; | ||
| 1054 | if (uart->port.type == PORT_UNKNOWN) | ||
| 1055 | break; | ||
| 1056 | } | ||
| 1057 | if (i < UART_NR) { | ||
| 1058 | uart_remove_one_port(&serial_txx9_reg, &uart->port); | ||
| 1059 | uart->port.iobase = port->iobase; | ||
| 1060 | uart->port.membase = port->membase; | ||
| 1061 | uart->port.irq = port->irq; | ||
| 1062 | uart->port.uartclk = port->uartclk; | ||
| 1063 | uart->port.iotype = port->iotype; | ||
| 1064 | uart->port.flags = port->flags | UPF_BOOT_AUTOCONF; | ||
| 1065 | uart->port.mapbase = port->mapbase; | ||
| 1066 | if (port->dev) | ||
| 1067 | uart->port.dev = port->dev; | ||
| 1068 | ret = uart_add_one_port(&serial_txx9_reg, &uart->port); | ||
| 1069 | if (ret == 0) | ||
| 1070 | ret = uart->port.line; | ||
| 1071 | } | ||
| 1072 | up(&serial_txx9_sem); | ||
| 1073 | return ret; | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | /** | ||
| 1077 | * serial_txx9_unregister_port - remove a txx9 serial port at runtime | ||
| 1078 | * @line: serial line number | ||
| 1079 | * | ||
| 1080 | * Remove one serial port. This may not be called from interrupt | ||
| 1081 | * context. We hand the port back to the our control. | ||
| 1082 | */ | ||
| 1083 | static void __devexit serial_txx9_unregister_port(int line) | ||
| 1084 | { | ||
| 1085 | struct uart_txx9_port *uart = &serial_txx9_ports[line]; | ||
| 1086 | |||
| 1087 | down(&serial_txx9_sem); | ||
| 1088 | uart_remove_one_port(&serial_txx9_reg, &uart->port); | ||
| 1089 | uart->port.flags = 0; | ||
| 1090 | uart->port.type = PORT_UNKNOWN; | ||
| 1091 | uart->port.iobase = 0; | ||
| 1092 | uart->port.mapbase = 0; | ||
| 1093 | uart->port.membase = 0; | ||
| 1094 | uart->port.dev = NULL; | ||
| 1095 | uart_add_one_port(&serial_txx9_reg, &uart->port); | ||
| 1096 | up(&serial_txx9_sem); | ||
| 1097 | } | ||
| 1098 | |||
| 1042 | /* | 1099 | /* |
| 1043 | * Probe one serial board. Unfortunately, there is no rhyme nor reason | 1100 | * Probe one serial board. Unfortunately, there is no rhyme nor reason |
| 1044 | * to the arrangement of serial ports on a PCI card. | 1101 | * to the arrangement of serial ports on a PCI card. |
| @@ -1056,13 +1113,13 @@ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent) | |||
| 1056 | 1113 | ||
| 1057 | memset(&port, 0, sizeof(port)); | 1114 | memset(&port, 0, sizeof(port)); |
| 1058 | port.ops = &serial_txx9_pops; | 1115 | port.ops = &serial_txx9_pops; |
| 1059 | port.flags |= UPF_BOOT_AUTOCONF; /* uart_ops.config_port will be called */ | ||
| 1060 | port.flags |= UPF_TXX9_HAVE_CTS_LINE; | 1116 | port.flags |= UPF_TXX9_HAVE_CTS_LINE; |
| 1061 | port.uartclk = 66670000; | 1117 | port.uartclk = 66670000; |
| 1062 | port.irq = dev->irq; | 1118 | port.irq = dev->irq; |
| 1063 | port.iotype = UPIO_PORT; | 1119 | port.iotype = UPIO_PORT; |
| 1064 | port.iobase = pci_resource_start(dev, 1); | 1120 | port.iobase = pci_resource_start(dev, 1); |
| 1065 | line = uart_register_port(&serial_txx9_reg, &port); | 1121 | port.dev = &dev->dev; |
| 1122 | line = serial_txx9_register_port(&port); | ||
| 1066 | if (line < 0) { | 1123 | if (line < 0) { |
| 1067 | printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line); | 1124 | printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line); |
| 1068 | } | 1125 | } |
| @@ -1078,7 +1135,7 @@ static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev) | |||
| 1078 | pci_set_drvdata(dev, NULL); | 1135 | pci_set_drvdata(dev, NULL); |
| 1079 | 1136 | ||
| 1080 | if (line) { | 1137 | if (line) { |
| 1081 | uart_unregister_port(&serial_txx9_reg, line); | 1138 | serial_txx9_unregister_port(line); |
| 1082 | pci_disable_device(dev); | 1139 | pci_disable_device(dev); |
| 1083 | } | 1140 | } |
| 1084 | } | 1141 | } |
| @@ -1089,6 +1146,8 @@ static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state) | |||
| 1089 | 1146 | ||
| 1090 | if (line) | 1147 | if (line) |
| 1091 | serial_txx9_suspend_port(line); | 1148 | serial_txx9_suspend_port(line); |
| 1149 | pci_save_state(dev); | ||
| 1150 | pci_set_power_state(dev, pci_choose_state(dev, state)); | ||
| 1092 | return 0; | 1151 | return 0; |
| 1093 | } | 1152 | } |
| 1094 | 1153 | ||
| @@ -1096,8 +1155,13 @@ static int pciserial_txx9_resume_one(struct pci_dev *dev) | |||
| 1096 | { | 1155 | { |
| 1097 | int line = (int)(long)pci_get_drvdata(dev); | 1156 | int line = (int)(long)pci_get_drvdata(dev); |
| 1098 | 1157 | ||
| 1099 | if (line) | 1158 | pci_set_power_state(dev, PCI_D0); |
| 1159 | pci_restore_state(dev); | ||
| 1160 | |||
| 1161 | if (line) { | ||
| 1162 | pci_enable_device(dev); | ||
| 1100 | serial_txx9_resume_port(line); | 1163 | serial_txx9_resume_port(line); |
| 1164 | } | ||
| 1101 | return 0; | 1165 | return 0; |
| 1102 | } | 1166 | } |
| 1103 | 1167 | ||
