aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorAtsushi Nemoto <anemo@mba.ocn.ne.jp>2007-02-21 12:17:28 -0500
committerRalf Baechle <ralf@linux-mips.org>2007-02-21 19:50:45 -0500
commit0970769aceb9bccf038f5dba72379f68431f94db (patch)
tree238be13350a38d3f50b906b4c619d722b9bc7541 /drivers/serial
parent5ce704f877057e257ecb9f5cdec6c4aa5c0d064c (diff)
[SERIAL] serial_txx9 driver update
* Use platform_device. * Fix and cleanup suspend/resume/initialization codes. Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Acked-by: Alan Cox <alan@redhat.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/serial_txx9.c276
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
63static char *serial_version = "1.07"; 65static char *serial_version = "1.08";
64static char *serial_name = "TX39/49 Serial driver"; 66static 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
95struct uart_txx9_port { 97struct 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
277static 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
280static inline void 302static inline void
281receive_chars(struct uart_txx9_port *up, unsigned int *status) 303receive_chars(struct uart_txx9_port *up, unsigned int *status)
282{ 304{
@@ -657,9 +679,8 @@ static void
657serial_txx9_pm(struct uart_port *port, unsigned int state, 679serial_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
665static int serial_txx9_request_resource(struct uart_txx9_port *up) 686static int serial_txx9_request_resource(struct uart_txx9_port *up)
@@ -732,7 +753,6 @@ static int serial_txx9_request_port(struct uart_port *port)
732static void serial_txx9_config_port(struct uart_port *port, int uflags) 753static 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
778static int 775static int
@@ -818,7 +815,8 @@ static struct uart_ops serial_txx9_pops = {
818 815
819static struct uart_txx9_port serial_txx9_ports[UART_NR]; 816static struct uart_txx9_port serial_txx9_ports[UART_NR];
820 817
821static void __init serial_txx9_register_ports(struct uart_driver *drv) 818static 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
901static int serial_txx9_console_setup(struct console *co, char *options) 900static 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 */
992static 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 */
1003static void serial_txx9_resume_port(int line)
1004{
1005 uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port);
1006}
1007#endif
1008
1009static DEFINE_MUTEX(serial_txx9_mutex); 973static 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 */
1051static 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 */
1080static 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
1094static 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
1108static 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
1123static 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
1106static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev) 1171static 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
1119static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state) 1184static 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
1130static int pciserial_txx9_resume_one(struct pci_dev *dev) 1195static 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 = {
1161MODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl); 1223MODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl);
1162#endif /* ENABLE_SERIAL_TXX9_PCI */ 1224#endif /* ENABLE_SERIAL_TXX9_PCI */
1163 1225
1226static struct platform_device *serial_txx9_plat_devs;
1227
1164static int __init serial_txx9_init(void) 1228static 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)