diff options
| -rw-r--r-- | drivers/serial/serial_txx9.c | 276 |
1 files changed, 184 insertions, 92 deletions
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index f4440d329310..509ace7e6881 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c | |||
| @@ -38,6 +38,8 @@ | |||
| 38 | * Fix some spin_locks. | 38 | * Fix some spin_locks. |
| 39 | * Do not call uart_add_one_port for absent ports. | 39 | * Do not call uart_add_one_port for absent ports. |
| 40 | * 1.07 Use CONFIG_SERIAL_TXX9_NR_UARTS. Cleanup. | 40 | * 1.07 Use CONFIG_SERIAL_TXX9_NR_UARTS. Cleanup. |
| 41 | * 1.08 Use platform_device. | ||
| 42 | * Fix and cleanup suspend/resume/initialization codes. | ||
| 41 | */ | 43 | */ |
| 42 | 44 | ||
| 43 | #if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | 45 | #if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
| @@ -50,7 +52,7 @@ | |||
| 50 | #include <linux/console.h> | 52 | #include <linux/console.h> |
| 51 | #include <linux/sysrq.h> | 53 | #include <linux/sysrq.h> |
| 52 | #include <linux/delay.h> | 54 | #include <linux/delay.h> |
| 53 | #include <linux/device.h> | 55 | #include <linux/platform_device.h> |
| 54 | #include <linux/pci.h> | 56 | #include <linux/pci.h> |
| 55 | #include <linux/tty.h> | 57 | #include <linux/tty.h> |
| 56 | #include <linux/tty_flip.h> | 58 | #include <linux/tty_flip.h> |
| @@ -60,7 +62,7 @@ | |||
| 60 | 62 | ||
| 61 | #include <asm/io.h> | 63 | #include <asm/io.h> |
| 62 | 64 | ||
| 63 | static char *serial_version = "1.07"; | 65 | static char *serial_version = "1.08"; |
| 64 | static char *serial_name = "TX39/49 Serial driver"; | 66 | static char *serial_name = "TX39/49 Serial driver"; |
| 65 | 67 | ||
| 66 | #define PASS_LIMIT 256 | 68 | #define PASS_LIMIT 256 |
| @@ -94,12 +96,7 @@ static char *serial_name = "TX39/49 Serial driver"; | |||
| 94 | 96 | ||
| 95 | struct uart_txx9_port { | 97 | struct uart_txx9_port { |
| 96 | struct uart_port port; | 98 | struct uart_port port; |
| 97 | 99 | /* No additional info for now */ | |
| 98 | /* | ||
| 99 | * We provide a per-port pm hook. | ||
| 100 | */ | ||
| 101 | void (*pm)(struct uart_port *port, | ||
| 102 | unsigned int state, unsigned int old); | ||
| 103 | }; | 100 | }; |
| 104 | 101 | ||
| 105 | #define TXX9_REGION_SIZE 0x24 | 102 | #define TXX9_REGION_SIZE 0x24 |
| @@ -277,6 +274,31 @@ static void serial_txx9_enable_ms(struct uart_port *port) | |||
| 277 | /* TXX9-SIO can not control DTR... */ | 274 | /* TXX9-SIO can not control DTR... */ |
| 278 | } | 275 | } |
| 279 | 276 | ||
| 277 | static void serial_txx9_initialize(struct uart_port *port) | ||
| 278 | { | ||
| 279 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | ||
| 280 | unsigned int tmout = 10000; | ||
| 281 | |||
| 282 | sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST); | ||
| 283 | /* TX4925 BUG WORKAROUND. Accessing SIOC register | ||
| 284 | * immediately after soft reset causes bus error. */ | ||
| 285 | mmiowb(); | ||
| 286 | udelay(1); | ||
| 287 | while ((sio_in(up, TXX9_SIFCR) & TXX9_SIFCR_SWRST) && --tmout) | ||
| 288 | udelay(1); | ||
| 289 | /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */ | ||
| 290 | sio_set(up, TXX9_SIFCR, | ||
| 291 | TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1); | ||
| 292 | /* initial settings */ | ||
| 293 | sio_out(up, TXX9_SILCR, | ||
| 294 | TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT | | ||
| 295 | ((up->port.flags & UPF_TXX9_USE_SCLK) ? | ||
| 296 | TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG)); | ||
| 297 | sio_quot_set(up, uart_get_divisor(port, 9600)); | ||
| 298 | sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */); | ||
| 299 | sio_out(up, TXX9_SIDICR, 0); | ||
| 300 | } | ||
| 301 | |||
| 280 | static inline void | 302 | static inline void |
| 281 | receive_chars(struct uart_txx9_port *up, unsigned int *status) | 303 | receive_chars(struct uart_txx9_port *up, unsigned int *status) |
| 282 | { | 304 | { |
| @@ -657,9 +679,8 @@ static void | |||
| 657 | serial_txx9_pm(struct uart_port *port, unsigned int state, | 679 | serial_txx9_pm(struct uart_port *port, unsigned int state, |
| 658 | unsigned int oldstate) | 680 | unsigned int oldstate) |
| 659 | { | 681 | { |
| 660 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | 682 | if (state == 0) |
| 661 | if (up->pm) | 683 | serial_txx9_initialize(port); |
| 662 | up->pm(port, state, oldstate); | ||
| 663 | } | 684 | } |
| 664 | 685 | ||
| 665 | static int serial_txx9_request_resource(struct uart_txx9_port *up) | 686 | static int serial_txx9_request_resource(struct uart_txx9_port *up) |
| @@ -732,7 +753,6 @@ static int serial_txx9_request_port(struct uart_port *port) | |||
| 732 | static void serial_txx9_config_port(struct uart_port *port, int uflags) | 753 | static void serial_txx9_config_port(struct uart_port *port, int uflags) |
| 733 | { | 754 | { |
| 734 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | 755 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; |
| 735 | unsigned long flags; | ||
| 736 | int ret; | 756 | int ret; |
| 737 | 757 | ||
| 738 | /* | 758 | /* |
| @@ -749,30 +769,7 @@ static void serial_txx9_config_port(struct uart_port *port, int uflags) | |||
| 749 | if (up->port.line == up->port.cons->index) | 769 | if (up->port.line == up->port.cons->index) |
| 750 | return; | 770 | return; |
| 751 | #endif | 771 | #endif |
| 752 | spin_lock_irqsave(&up->port.lock, flags); | 772 | serial_txx9_initialize(port); |
| 753 | /* | ||
| 754 | * Reset the UART. | ||
| 755 | */ | ||
| 756 | sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST); | ||
| 757 | #ifdef CONFIG_CPU_TX49XX | ||
| 758 | /* TX4925 BUG WORKAROUND. Accessing SIOC register | ||
| 759 | * immediately after soft reset causes bus error. */ | ||
| 760 | iob(); | ||
| 761 | udelay(1); | ||
| 762 | #endif | ||
| 763 | while (sio_in(up, TXX9_SIFCR) & TXX9_SIFCR_SWRST) | ||
| 764 | ; | ||
| 765 | /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */ | ||
| 766 | sio_set(up, TXX9_SIFCR, | ||
| 767 | TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1); | ||
| 768 | /* initial settings */ | ||
| 769 | sio_out(up, TXX9_SILCR, | ||
| 770 | TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT | | ||
| 771 | ((up->port.flags & UPF_TXX9_USE_SCLK) ? | ||
| 772 | TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG)); | ||
| 773 | sio_quot_set(up, uart_get_divisor(port, 9600)); | ||
| 774 | sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */); | ||
| 775 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
| 776 | } | 773 | } |
| 777 | 774 | ||
| 778 | static int | 775 | static int |
| @@ -818,7 +815,8 @@ static struct uart_ops serial_txx9_pops = { | |||
| 818 | 815 | ||
| 819 | static struct uart_txx9_port serial_txx9_ports[UART_NR]; | 816 | static struct uart_txx9_port serial_txx9_ports[UART_NR]; |
| 820 | 817 | ||
| 821 | static void __init serial_txx9_register_ports(struct uart_driver *drv) | 818 | static void __init serial_txx9_register_ports(struct uart_driver *drv, |
| 819 | struct device *dev) | ||
| 822 | { | 820 | { |
| 823 | int i; | 821 | int i; |
| 824 | 822 | ||
| @@ -827,6 +825,7 @@ static void __init serial_txx9_register_ports(struct uart_driver *drv) | |||
| 827 | 825 | ||
| 828 | up->port.line = i; | 826 | up->port.line = i; |
| 829 | up->port.ops = &serial_txx9_pops; | 827 | up->port.ops = &serial_txx9_pops; |
| 828 | up->port.dev = dev; | ||
| 830 | if (up->port.iobase || up->port.mapbase) | 829 | if (up->port.iobase || up->port.mapbase) |
| 831 | uart_add_one_port(drv, &up->port); | 830 | uart_add_one_port(drv, &up->port); |
| 832 | } | 831 | } |
| @@ -898,7 +897,7 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count) | |||
| 898 | sio_out(up, TXX9_SIDICR, ier); | 897 | sio_out(up, TXX9_SIDICR, ier); |
| 899 | } | 898 | } |
| 900 | 899 | ||
| 901 | static int serial_txx9_console_setup(struct console *co, char *options) | 900 | static int __init serial_txx9_console_setup(struct console *co, char *options) |
| 902 | { | 901 | { |
| 903 | struct uart_port *port; | 902 | struct uart_port *port; |
| 904 | struct uart_txx9_port *up; | 903 | struct uart_txx9_port *up; |
| @@ -919,17 +918,7 @@ static int serial_txx9_console_setup(struct console *co, char *options) | |||
| 919 | if (!port->ops) | 918 | if (!port->ops) |
| 920 | return -ENODEV; | 919 | return -ENODEV; |
| 921 | 920 | ||
| 922 | /* | 921 | serial_txx9_initialize(&up->port); |
| 923 | * Disable UART interrupts, set DTR and RTS high | ||
| 924 | * and set speed. | ||
| 925 | */ | ||
| 926 | sio_out(up, TXX9_SIDICR, 0); | ||
| 927 | /* initial settings */ | ||
| 928 | sio_out(up, TXX9_SILCR, | ||
| 929 | TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT | | ||
| 930 | ((port->flags & UPF_TXX9_USE_SCLK) ? | ||
| 931 | TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG)); | ||
| 932 | sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */); | ||
| 933 | 922 | ||
| 934 | if (options) | 923 | if (options) |
| 935 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 924 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
| @@ -981,31 +970,6 @@ int __init early_serial_txx9_setup(struct uart_port *port) | |||
| 981 | return 0; | 970 | return 0; |
| 982 | } | 971 | } |
| 983 | 972 | ||
| 984 | #ifdef ENABLE_SERIAL_TXX9_PCI | ||
| 985 | #ifdef CONFIG_PM | ||
| 986 | /** | ||
| 987 | * serial_txx9_suspend_port - suspend one serial port | ||
| 988 | * @line: serial line number | ||
| 989 | * | ||
| 990 | * Suspend one serial port. | ||
| 991 | */ | ||
| 992 | static void serial_txx9_suspend_port(int line) | ||
| 993 | { | ||
| 994 | uart_suspend_port(&serial_txx9_reg, &serial_txx9_ports[line].port); | ||
| 995 | } | ||
| 996 | |||
| 997 | /** | ||
| 998 | * serial_txx9_resume_port - resume one serial port | ||
| 999 | * @line: serial line number | ||
| 1000 | * | ||
| 1001 | * Resume one serial port. | ||
| 1002 | */ | ||
| 1003 | static void serial_txx9_resume_port(int line) | ||
| 1004 | { | ||
| 1005 | uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port); | ||
| 1006 | } | ||
| 1007 | #endif | ||
| 1008 | |||
| 1009 | static DEFINE_MUTEX(serial_txx9_mutex); | 973 | static DEFINE_MUTEX(serial_txx9_mutex); |
| 1010 | 974 | ||
| 1011 | /** | 975 | /** |
| @@ -1028,8 +992,18 @@ static int __devinit serial_txx9_register_port(struct uart_port *port) | |||
| 1028 | mutex_lock(&serial_txx9_mutex); | 992 | mutex_lock(&serial_txx9_mutex); |
| 1029 | for (i = 0; i < UART_NR; i++) { | 993 | for (i = 0; i < UART_NR; i++) { |
| 1030 | uart = &serial_txx9_ports[i]; | 994 | uart = &serial_txx9_ports[i]; |
| 1031 | if (!(uart->port.iobase || uart->port.mapbase)) | 995 | if (uart_match_port(&uart->port, port)) { |
| 996 | uart_remove_one_port(&serial_txx9_reg, &uart->port); | ||
| 1032 | break; | 997 | break; |
| 998 | } | ||
| 999 | } | ||
| 1000 | if (i == UART_NR) { | ||
| 1001 | /* Find unused port */ | ||
| 1002 | for (i = 0; i < UART_NR; i++) { | ||
| 1003 | uart = &serial_txx9_ports[i]; | ||
| 1004 | if (!(uart->port.iobase || uart->port.mapbase)) | ||
| 1005 | break; | ||
| 1006 | } | ||
| 1033 | } | 1007 | } |
| 1034 | if (i < UART_NR) { | 1008 | if (i < UART_NR) { |
| 1035 | uart->port.iobase = port->iobase; | 1009 | uart->port.iobase = port->iobase; |
| @@ -1072,6 +1046,95 @@ static void __devexit serial_txx9_unregister_port(int line) | |||
| 1072 | } | 1046 | } |
| 1073 | 1047 | ||
| 1074 | /* | 1048 | /* |
| 1049 | * Register a set of serial devices attached to a platform device. | ||
| 1050 | */ | ||
| 1051 | static int __devinit serial_txx9_probe(struct platform_device *dev) | ||
| 1052 | { | ||
| 1053 | struct uart_port *p = dev->dev.platform_data; | ||
| 1054 | struct uart_port port; | ||
| 1055 | int ret, i; | ||
| 1056 | |||
| 1057 | memset(&port, 0, sizeof(struct uart_port)); | ||
| 1058 | for (i = 0; p && p->uartclk != 0; p++, i++) { | ||
| 1059 | port.iobase = p->iobase; | ||
| 1060 | port.membase = p->membase; | ||
| 1061 | port.irq = p->irq; | ||
| 1062 | port.uartclk = p->uartclk; | ||
| 1063 | port.iotype = p->iotype; | ||
| 1064 | port.flags = p->flags; | ||
| 1065 | port.mapbase = p->mapbase; | ||
| 1066 | port.dev = &dev->dev; | ||
| 1067 | ret = serial_txx9_register_port(&port); | ||
| 1068 | if (ret < 0) { | ||
| 1069 | dev_err(&dev->dev, "unable to register port at index %d " | ||
| 1070 | "(IO%x MEM%lx IRQ%d): %d\n", i, | ||
| 1071 | p->iobase, p->mapbase, p->irq, ret); | ||
| 1072 | } | ||
| 1073 | } | ||
| 1074 | return 0; | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | /* | ||
| 1078 | * Remove serial ports registered against a platform device. | ||
| 1079 | */ | ||
| 1080 | static int __devexit serial_txx9_remove(struct platform_device *dev) | ||
| 1081 | { | ||
| 1082 | int i; | ||
| 1083 | |||
| 1084 | for (i = 0; i < UART_NR; i++) { | ||
| 1085 | struct uart_txx9_port *up = &serial_txx9_ports[i]; | ||
| 1086 | |||
| 1087 | if (up->port.dev == &dev->dev) | ||
| 1088 | serial_txx9_unregister_port(i); | ||
| 1089 | } | ||
| 1090 | return 0; | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | #ifdef CONFIG_PM | ||
| 1094 | static int serial_txx9_suspend(struct platform_device *dev, pm_message_t state) | ||
| 1095 | { | ||
| 1096 | int i; | ||
| 1097 | |||
| 1098 | for (i = 0; i < UART_NR; i++) { | ||
| 1099 | struct uart_txx9_port *up = &serial_txx9_ports[i]; | ||
| 1100 | |||
| 1101 | if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) | ||
| 1102 | uart_suspend_port(&serial_txx9_reg, &up->port); | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | return 0; | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | static int serial_txx9_resume(struct platform_device *dev) | ||
| 1109 | { | ||
| 1110 | int i; | ||
| 1111 | |||
| 1112 | for (i = 0; i < UART_NR; i++) { | ||
| 1113 | struct uart_txx9_port *up = &serial_txx9_ports[i]; | ||
| 1114 | |||
| 1115 | if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) | ||
| 1116 | uart_resume_port(&serial_txx9_reg, &up->port); | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | return 0; | ||
| 1120 | } | ||
| 1121 | #endif | ||
| 1122 | |||
| 1123 | static struct platform_driver serial_txx9_plat_driver = { | ||
| 1124 | .probe = serial_txx9_probe, | ||
| 1125 | .remove = __devexit_p(serial_txx9_remove), | ||
| 1126 | #ifdef CONFIG_PM | ||
| 1127 | .suspend = serial_txx9_suspend, | ||
| 1128 | .resume = serial_txx9_resume, | ||
| 1129 | #endif | ||
| 1130 | .driver = { | ||
| 1131 | .name = "serial_txx9", | ||
| 1132 | .owner = THIS_MODULE, | ||
| 1133 | }, | ||
| 1134 | }; | ||
| 1135 | |||
| 1136 | #ifdef ENABLE_SERIAL_TXX9_PCI | ||
| 1137 | /* | ||
| 1075 | * Probe one serial board. Unfortunately, there is no rhyme nor reason | 1138 | * Probe one serial board. Unfortunately, there is no rhyme nor reason |
| 1076 | * to the arrangement of serial ports on a PCI card. | 1139 | * to the arrangement of serial ports on a PCI card. |
| 1077 | */ | 1140 | */ |
| @@ -1097,20 +1160,22 @@ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent) | |||
| 1097 | line = serial_txx9_register_port(&port); | 1160 | line = serial_txx9_register_port(&port); |
| 1098 | if (line < 0) { | 1161 | if (line < 0) { |
| 1099 | printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line); | 1162 | printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line); |
| 1163 | pci_disable_device(dev); | ||
| 1164 | return line; | ||
| 1100 | } | 1165 | } |
| 1101 | pci_set_drvdata(dev, (void *)(long)line); | 1166 | pci_set_drvdata(dev, &serial_txx9_ports[line]); |
| 1102 | 1167 | ||
| 1103 | return 0; | 1168 | return 0; |
| 1104 | } | 1169 | } |
| 1105 | 1170 | ||
| 1106 | static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev) | 1171 | static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev) |
| 1107 | { | 1172 | { |
| 1108 | int line = (int)(long)pci_get_drvdata(dev); | 1173 | struct uart_txx9_port *up = pci_get_drvdata(dev); |
| 1109 | 1174 | ||
| 1110 | pci_set_drvdata(dev, NULL); | 1175 | pci_set_drvdata(dev, NULL); |
| 1111 | 1176 | ||
| 1112 | if (line) { | 1177 | if (up) { |
| 1113 | serial_txx9_unregister_port(line); | 1178 | serial_txx9_unregister_port(up->port.line); |
| 1114 | pci_disable_device(dev); | 1179 | pci_disable_device(dev); |
| 1115 | } | 1180 | } |
| 1116 | } | 1181 | } |
| @@ -1118,10 +1183,10 @@ static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev) | |||
| 1118 | #ifdef CONFIG_PM | 1183 | #ifdef CONFIG_PM |
| 1119 | static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state) | 1184 | static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state) |
| 1120 | { | 1185 | { |
| 1121 | int line = (int)(long)pci_get_drvdata(dev); | 1186 | struct uart_txx9_port *up = pci_get_drvdata(dev); |
| 1122 | 1187 | ||
| 1123 | if (line) | 1188 | if (up) |
| 1124 | serial_txx9_suspend_port(line); | 1189 | uart_suspend_port(&serial_txx9_reg, &up->port); |
| 1125 | pci_save_state(dev); | 1190 | pci_save_state(dev); |
| 1126 | pci_set_power_state(dev, pci_choose_state(dev, state)); | 1191 | pci_set_power_state(dev, pci_choose_state(dev, state)); |
| 1127 | return 0; | 1192 | return 0; |
| @@ -1129,15 +1194,12 @@ static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state) | |||
| 1129 | 1194 | ||
| 1130 | static int pciserial_txx9_resume_one(struct pci_dev *dev) | 1195 | static int pciserial_txx9_resume_one(struct pci_dev *dev) |
| 1131 | { | 1196 | { |
| 1132 | int line = (int)(long)pci_get_drvdata(dev); | 1197 | struct uart_txx9_port *up = pci_get_drvdata(dev); |
| 1133 | 1198 | ||
| 1134 | pci_set_power_state(dev, PCI_D0); | 1199 | pci_set_power_state(dev, PCI_D0); |
| 1135 | pci_restore_state(dev); | 1200 | pci_restore_state(dev); |
| 1136 | 1201 | if (up) | |
| 1137 | if (line) { | 1202 | uart_resume_port(&serial_txx9_reg, &up->port); |
| 1138 | pci_enable_device(dev); | ||
| 1139 | serial_txx9_resume_port(line); | ||
| 1140 | } | ||
| 1141 | return 0; | 1203 | return 0; |
| 1142 | } | 1204 | } |
| 1143 | #endif | 1205 | #endif |
| @@ -1161,6 +1223,8 @@ static struct pci_driver serial_txx9_pci_driver = { | |||
| 1161 | MODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl); | 1223 | MODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl); |
| 1162 | #endif /* ENABLE_SERIAL_TXX9_PCI */ | 1224 | #endif /* ENABLE_SERIAL_TXX9_PCI */ |
| 1163 | 1225 | ||
| 1226 | static struct platform_device *serial_txx9_plat_devs; | ||
| 1227 | |||
| 1164 | static int __init serial_txx9_init(void) | 1228 | static int __init serial_txx9_init(void) |
| 1165 | { | 1229 | { |
| 1166 | int ret; | 1230 | int ret; |
| @@ -1168,13 +1232,39 @@ static int __init serial_txx9_init(void) | |||
| 1168 | printk(KERN_INFO "%s version %s\n", serial_name, serial_version); | 1232 | printk(KERN_INFO "%s version %s\n", serial_name, serial_version); |
| 1169 | 1233 | ||
| 1170 | ret = uart_register_driver(&serial_txx9_reg); | 1234 | ret = uart_register_driver(&serial_txx9_reg); |
| 1171 | if (ret >= 0) { | 1235 | if (ret) |
| 1172 | serial_txx9_register_ports(&serial_txx9_reg); | 1236 | goto out; |
| 1237 | |||
| 1238 | serial_txx9_plat_devs = platform_device_alloc("serial_txx9", -1); | ||
| 1239 | if (!serial_txx9_plat_devs) { | ||
| 1240 | ret = -ENOMEM; | ||
| 1241 | goto unreg_uart_drv; | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | ret = platform_device_add(serial_txx9_plat_devs); | ||
| 1245 | if (ret) | ||
| 1246 | goto put_dev; | ||
| 1247 | |||
| 1248 | serial_txx9_register_ports(&serial_txx9_reg, | ||
| 1249 | &serial_txx9_plat_devs->dev); | ||
| 1250 | |||
| 1251 | ret = platform_driver_register(&serial_txx9_plat_driver); | ||
| 1252 | if (ret) | ||
| 1253 | goto del_dev; | ||
| 1173 | 1254 | ||
| 1174 | #ifdef ENABLE_SERIAL_TXX9_PCI | 1255 | #ifdef ENABLE_SERIAL_TXX9_PCI |
| 1175 | ret = pci_register_driver(&serial_txx9_pci_driver); | 1256 | ret = pci_register_driver(&serial_txx9_pci_driver); |
| 1176 | #endif | 1257 | #endif |
| 1177 | } | 1258 | if (ret == 0) |
| 1259 | goto out; | ||
| 1260 | |||
| 1261 | del_dev: | ||
| 1262 | platform_device_del(serial_txx9_plat_devs); | ||
| 1263 | put_dev: | ||
| 1264 | platform_device_put(serial_txx9_plat_devs); | ||
| 1265 | unreg_uart_drv: | ||
| 1266 | uart_unregister_driver(&serial_txx9_reg); | ||
| 1267 | out: | ||
| 1178 | return ret; | 1268 | return ret; |
| 1179 | } | 1269 | } |
| 1180 | 1270 | ||
| @@ -1185,6 +1275,8 @@ static void __exit serial_txx9_exit(void) | |||
| 1185 | #ifdef ENABLE_SERIAL_TXX9_PCI | 1275 | #ifdef ENABLE_SERIAL_TXX9_PCI |
| 1186 | pci_unregister_driver(&serial_txx9_pci_driver); | 1276 | pci_unregister_driver(&serial_txx9_pci_driver); |
| 1187 | #endif | 1277 | #endif |
| 1278 | platform_driver_unregister(&serial_txx9_plat_driver); | ||
| 1279 | platform_device_unregister(serial_txx9_plat_devs); | ||
| 1188 | for (i = 0; i < UART_NR; i++) { | 1280 | for (i = 0; i < UART_NR; i++) { |
| 1189 | struct uart_txx9_port *up = &serial_txx9_ports[i]; | 1281 | struct uart_txx9_port *up = &serial_txx9_ports[i]; |
| 1190 | if (up->port.iobase || up->port.mapbase) | 1282 | if (up->port.iobase || up->port.mapbase) |
