aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/amba-pl010.c2
-rw-r--r--drivers/serial/amba-pl011.c90
-rw-r--r--drivers/serial/atmel_serial.c1
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c143
-rw-r--r--drivers/serial/serial_cs.c1
-rw-r--r--drivers/serial/suncore.c4
-rw-r--r--drivers/serial/sunsu.c13
7 files changed, 170 insertions, 84 deletions
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index b09a638d051f..50441ffe8e38 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -782,7 +782,7 @@ static int pl010_resume(struct amba_device *dev)
782 return 0; 782 return 0;
783} 783}
784 784
785static struct amba_id pl010_ids[] __initdata = { 785static struct amba_id pl010_ids[] = {
786 { 786 {
787 .id = 0x00041010, 787 .id = 0x00041010,
788 .mask = 0x000fffff, 788 .mask = 0x000fffff,
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index eb4cb480b93e..6ca7a44f29c2 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -69,9 +69,12 @@
69struct uart_amba_port { 69struct uart_amba_port {
70 struct uart_port port; 70 struct uart_port port;
71 struct clk *clk; 71 struct clk *clk;
72 unsigned int im; /* interrupt mask */ 72 unsigned int im; /* interrupt mask */
73 unsigned int old_status; 73 unsigned int old_status;
74 unsigned int ifls; /* vendor-specific */ 74 unsigned int ifls; /* vendor-specific */
75 unsigned int lcrh_tx; /* vendor-specific */
76 unsigned int lcrh_rx; /* vendor-specific */
77 bool oversampling; /* vendor-specific */
75 bool autorts; 78 bool autorts;
76}; 79};
77 80
@@ -79,16 +82,25 @@ struct uart_amba_port {
79struct vendor_data { 82struct vendor_data {
80 unsigned int ifls; 83 unsigned int ifls;
81 unsigned int fifosize; 84 unsigned int fifosize;
85 unsigned int lcrh_tx;
86 unsigned int lcrh_rx;
87 bool oversampling;
82}; 88};
83 89
84static struct vendor_data vendor_arm = { 90static struct vendor_data vendor_arm = {
85 .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, 91 .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
86 .fifosize = 16, 92 .fifosize = 16,
93 .lcrh_tx = UART011_LCRH,
94 .lcrh_rx = UART011_LCRH,
95 .oversampling = false,
87}; 96};
88 97
89static struct vendor_data vendor_st = { 98static struct vendor_data vendor_st = {
90 .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, 99 .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
91 .fifosize = 64, 100 .fifosize = 64,
101 .lcrh_tx = ST_UART011_LCRH_TX,
102 .lcrh_rx = ST_UART011_LCRH_RX,
103 .oversampling = true,
92}; 104};
93 105
94static void pl011_stop_tx(struct uart_port *port) 106static void pl011_stop_tx(struct uart_port *port)
@@ -327,12 +339,12 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)
327 unsigned int lcr_h; 339 unsigned int lcr_h;
328 340
329 spin_lock_irqsave(&uap->port.lock, flags); 341 spin_lock_irqsave(&uap->port.lock, flags);
330 lcr_h = readw(uap->port.membase + UART011_LCRH); 342 lcr_h = readw(uap->port.membase + uap->lcrh_tx);
331 if (break_state == -1) 343 if (break_state == -1)
332 lcr_h |= UART01x_LCRH_BRK; 344 lcr_h |= UART01x_LCRH_BRK;
333 else 345 else
334 lcr_h &= ~UART01x_LCRH_BRK; 346 lcr_h &= ~UART01x_LCRH_BRK;
335 writew(lcr_h, uap->port.membase + UART011_LCRH); 347 writew(lcr_h, uap->port.membase + uap->lcrh_tx);
336 spin_unlock_irqrestore(&uap->port.lock, flags); 348 spin_unlock_irqrestore(&uap->port.lock, flags);
337} 349}
338 350
@@ -393,7 +405,17 @@ static int pl011_startup(struct uart_port *port)
393 writew(cr, uap->port.membase + UART011_CR); 405 writew(cr, uap->port.membase + UART011_CR);
394 writew(0, uap->port.membase + UART011_FBRD); 406 writew(0, uap->port.membase + UART011_FBRD);
395 writew(1, uap->port.membase + UART011_IBRD); 407 writew(1, uap->port.membase + UART011_IBRD);
396 writew(0, uap->port.membase + UART011_LCRH); 408 writew(0, uap->port.membase + uap->lcrh_rx);
409 if (uap->lcrh_tx != uap->lcrh_rx) {
410 int i;
411 /*
412 * Wait 10 PCLKs before writing LCRH_TX register,
413 * to get this delay write read only register 10 times
414 */
415 for (i = 0; i < 10; ++i)
416 writew(0xff, uap->port.membase + UART011_MIS);
417 writew(0, uap->port.membase + uap->lcrh_tx);
418 }
397 writew(0, uap->port.membase + UART01x_DR); 419 writew(0, uap->port.membase + UART01x_DR);
398 while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) 420 while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
399 barrier(); 421 barrier();
@@ -422,10 +444,19 @@ static int pl011_startup(struct uart_port *port)
422 return retval; 444 return retval;
423} 445}
424 446
447static void pl011_shutdown_channel(struct uart_amba_port *uap,
448 unsigned int lcrh)
449{
450 unsigned long val;
451
452 val = readw(uap->port.membase + lcrh);
453 val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
454 writew(val, uap->port.membase + lcrh);
455}
456
425static void pl011_shutdown(struct uart_port *port) 457static void pl011_shutdown(struct uart_port *port)
426{ 458{
427 struct uart_amba_port *uap = (struct uart_amba_port *)port; 459 struct uart_amba_port *uap = (struct uart_amba_port *)port;
428 unsigned long val;
429 460
430 /* 461 /*
431 * disable all interrupts 462 * disable all interrupts
@@ -450,9 +481,9 @@ static void pl011_shutdown(struct uart_port *port)
450 /* 481 /*
451 * disable break condition and fifos 482 * disable break condition and fifos
452 */ 483 */
453 val = readw(uap->port.membase + UART011_LCRH); 484 pl011_shutdown_channel(uap, uap->lcrh_rx);
454 val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN); 485 if (uap->lcrh_rx != uap->lcrh_tx)
455 writew(val, uap->port.membase + UART011_LCRH); 486 pl011_shutdown_channel(uap, uap->lcrh_tx);
456 487
457 /* 488 /*
458 * Shut down the clock producer 489 * Shut down the clock producer
@@ -472,8 +503,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
472 /* 503 /*
473 * Ask the core to calculate the divisor for us. 504 * Ask the core to calculate the divisor for us.
474 */ 505 */
475 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 506 baud = uart_get_baud_rate(port, termios, old, 0,
476 quot = port->uartclk * 4 / baud; 507 port->uartclk/(uap->oversampling ? 8 : 16));
508
509 if (baud > port->uartclk/16)
510 quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud);
511 else
512 quot = DIV_ROUND_CLOSEST(port->uartclk * 4, baud);
477 513
478 switch (termios->c_cflag & CSIZE) { 514 switch (termios->c_cflag & CSIZE) {
479 case CS5: 515 case CS5:
@@ -552,6 +588,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
552 uap->autorts = false; 588 uap->autorts = false;
553 } 589 }
554 590
591 if (uap->oversampling) {
592 if (baud > port->uartclk/16)
593 old_cr |= ST_UART011_CR_OVSFACT;
594 else
595 old_cr &= ~ST_UART011_CR_OVSFACT;
596 }
597
555 /* Set baud rate */ 598 /* Set baud rate */
556 writew(quot & 0x3f, port->membase + UART011_FBRD); 599 writew(quot & 0x3f, port->membase + UART011_FBRD);
557 writew(quot >> 6, port->membase + UART011_IBRD); 600 writew(quot >> 6, port->membase + UART011_IBRD);
@@ -561,7 +604,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
561 * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L 604 * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
562 * ----------^----------^----------^----------^----- 605 * ----------^----------^----------^----------^-----
563 */ 606 */
564 writew(lcr_h, port->membase + UART011_LCRH); 607 writew(lcr_h, port->membase + uap->lcrh_rx);
608 if (uap->lcrh_rx != uap->lcrh_tx) {
609 int i;
610 /*
611 * Wait 10 PCLKs before writing LCRH_TX register,
612 * to get this delay write read only register 10 times
613 */
614 for (i = 0; i < 10; ++i)
615 writew(0xff, uap->port.membase + UART011_MIS);
616 writew(lcr_h, port->membase + uap->lcrh_tx);
617 }
565 writew(old_cr, port->membase + UART011_CR); 618 writew(old_cr, port->membase + UART011_CR);
566 619
567 spin_unlock_irqrestore(&port->lock, flags); 620 spin_unlock_irqrestore(&port->lock, flags);
@@ -688,7 +741,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
688 if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) { 741 if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) {
689 unsigned int lcr_h, ibrd, fbrd; 742 unsigned int lcr_h, ibrd, fbrd;
690 743
691 lcr_h = readw(uap->port.membase + UART011_LCRH); 744 lcr_h = readw(uap->port.membase + uap->lcrh_tx);
692 745
693 *parity = 'n'; 746 *parity = 'n';
694 if (lcr_h & UART01x_LCRH_PEN) { 747 if (lcr_h & UART01x_LCRH_PEN) {
@@ -707,6 +760,12 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
707 fbrd = readw(uap->port.membase + UART011_FBRD); 760 fbrd = readw(uap->port.membase + UART011_FBRD);
708 761
709 *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd); 762 *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
763
764 if (uap->oversampling) {
765 if (readw(uap->port.membase + UART011_CR)
766 & ST_UART011_CR_OVSFACT)
767 *baud *= 2;
768 }
710 } 769 }
711} 770}
712 771
@@ -800,6 +859,9 @@ static int pl011_probe(struct amba_device *dev, struct amba_id *id)
800 } 859 }
801 860
802 uap->ifls = vendor->ifls; 861 uap->ifls = vendor->ifls;
862 uap->lcrh_rx = vendor->lcrh_rx;
863 uap->lcrh_tx = vendor->lcrh_tx;
864 uap->oversampling = vendor->oversampling;
803 uap->port.dev = &dev->dev; 865 uap->port.dev = &dev->dev;
804 uap->port.mapbase = dev->res.start; 866 uap->port.mapbase = dev->res.start;
805 uap->port.membase = base; 867 uap->port.membase = base;
@@ -868,7 +930,7 @@ static int pl011_resume(struct amba_device *dev)
868} 930}
869#endif 931#endif
870 932
871static struct amba_id pl011_ids[] __initdata = { 933static struct amba_id pl011_ids[] = {
872 { 934 {
873 .id = 0x00041011, 935 .id = 0x00041011,
874 .mask = 0x000fffff, 936 .mask = 0x000fffff,
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index eed3c2d8dd1c..a182def7007d 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -41,6 +41,7 @@
41#include <linux/uaccess.h> 41#include <linux/uaccess.h>
42 42
43#include <asm/io.h> 43#include <asm/io.h>
44#include <asm/ioctls.h>
44 45
45#include <asm/mach/serial_at91.h> 46#include <asm/mach/serial_at91.h>
46#include <mach/board.h> 47#include <mach/board.h>
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 9259e849f463..6016179db533 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -930,6 +930,83 @@ static void cpm_uart_config_port(struct uart_port *port, int flags)
930 } 930 }
931} 931}
932 932
933#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_CPM_CONSOLE)
934/*
935 * Write a string to the serial port
936 * Note that this is called with interrupts already disabled
937 */
938static void cpm_uart_early_write(struct uart_cpm_port *pinfo,
939 const char *string, u_int count)
940{
941 unsigned int i;
942 cbd_t __iomem *bdp, *bdbase;
943 unsigned char *cpm_outp_addr;
944
945 /* Get the address of the host memory buffer.
946 */
947 bdp = pinfo->tx_cur;
948 bdbase = pinfo->tx_bd_base;
949
950 /*
951 * Now, do each character. This is not as bad as it looks
952 * since this is a holding FIFO and not a transmitting FIFO.
953 * We could add the complexity of filling the entire transmit
954 * buffer, but we would just wait longer between accesses......
955 */
956 for (i = 0; i < count; i++, string++) {
957 /* Wait for transmitter fifo to empty.
958 * Ready indicates output is ready, and xmt is doing
959 * that, not that it is ready for us to send.
960 */
961 while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
962 ;
963
964 /* Send the character out.
965 * If the buffer address is in the CPM DPRAM, don't
966 * convert it.
967 */
968 cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
969 pinfo);
970 *cpm_outp_addr = *string;
971
972 out_be16(&bdp->cbd_datlen, 1);
973 setbits16(&bdp->cbd_sc, BD_SC_READY);
974
975 if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
976 bdp = bdbase;
977 else
978 bdp++;
979
980 /* if a LF, also do CR... */
981 if (*string == 10) {
982 while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
983 ;
984
985 cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
986 pinfo);
987 *cpm_outp_addr = 13;
988
989 out_be16(&bdp->cbd_datlen, 1);
990 setbits16(&bdp->cbd_sc, BD_SC_READY);
991
992 if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
993 bdp = bdbase;
994 else
995 bdp++;
996 }
997 }
998
999 /*
1000 * Finally, Wait for transmitter & holding register to empty
1001 * and restore the IER
1002 */
1003 while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
1004 ;
1005
1006 pinfo->tx_cur = bdp;
1007}
1008#endif
1009
933#ifdef CONFIG_CONSOLE_POLL 1010#ifdef CONFIG_CONSOLE_POLL
934/* Serial polling routines for writing and reading from the uart while 1011/* Serial polling routines for writing and reading from the uart while
935 * in an interrupt or debug context. 1012 * in an interrupt or debug context.
@@ -999,7 +1076,7 @@ static void cpm_put_poll_char(struct uart_port *port,
999 static char ch[2]; 1076 static char ch[2];
1000 1077
1001 ch[0] = (char)c; 1078 ch[0] = (char)c;
1002 cpm_uart_early_write(pinfo->port.line, ch, 1); 1079 cpm_uart_early_write(pinfo, ch, 1);
1003} 1080}
1004#endif /* CONFIG_CONSOLE_POLL */ 1081#endif /* CONFIG_CONSOLE_POLL */
1005 1082
@@ -1130,9 +1207,6 @@ static void cpm_uart_console_write(struct console *co, const char *s,
1130 u_int count) 1207 u_int count)
1131{ 1208{
1132 struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index]; 1209 struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
1133 unsigned int i;
1134 cbd_t __iomem *bdp, *bdbase;
1135 unsigned char *cp;
1136 unsigned long flags; 1210 unsigned long flags;
1137 int nolock = oops_in_progress; 1211 int nolock = oops_in_progress;
1138 1212
@@ -1142,66 +1216,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
1142 spin_lock_irqsave(&pinfo->port.lock, flags); 1216 spin_lock_irqsave(&pinfo->port.lock, flags);
1143 } 1217 }
1144 1218
1145 /* Get the address of the host memory buffer. 1219 cpm_uart_early_write(pinfo, s, count);
1146 */
1147 bdp = pinfo->tx_cur;
1148 bdbase = pinfo->tx_bd_base;
1149
1150 /*
1151 * Now, do each character. This is not as bad as it looks
1152 * since this is a holding FIFO and not a transmitting FIFO.
1153 * We could add the complexity of filling the entire transmit
1154 * buffer, but we would just wait longer between accesses......
1155 */
1156 for (i = 0; i < count; i++, s++) {
1157 /* Wait for transmitter fifo to empty.
1158 * Ready indicates output is ready, and xmt is doing
1159 * that, not that it is ready for us to send.
1160 */
1161 while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
1162 ;
1163
1164 /* Send the character out.
1165 * If the buffer address is in the CPM DPRAM, don't
1166 * convert it.
1167 */
1168 cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
1169 *cp = *s;
1170
1171 out_be16(&bdp->cbd_datlen, 1);
1172 setbits16(&bdp->cbd_sc, BD_SC_READY);
1173
1174 if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
1175 bdp = bdbase;
1176 else
1177 bdp++;
1178
1179 /* if a LF, also do CR... */
1180 if (*s == 10) {
1181 while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
1182 ;
1183
1184 cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
1185 *cp = 13;
1186
1187 out_be16(&bdp->cbd_datlen, 1);
1188 setbits16(&bdp->cbd_sc, BD_SC_READY);
1189
1190 if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
1191 bdp = bdbase;
1192 else
1193 bdp++;
1194 }
1195 }
1196
1197 /*
1198 * Finally, Wait for transmitter & holding register to empty
1199 * and restore the IER
1200 */
1201 while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
1202 ;
1203
1204 pinfo->tx_cur = bdp;
1205 1220
1206 if (unlikely(nolock)) { 1221 if (unlikely(nolock)) {
1207 local_irq_restore(flags); 1222 local_irq_restore(flags);
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 526307368f8b..ab17c08ddc03 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -821,6 +821,7 @@ static struct pcmcia_device_id serial_ids[] = {
821 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"), 821 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
822 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"), 822 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
823 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"), 823 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
824 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
824 PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"), 825 PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
825 PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"), 826 PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
826 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"), 827 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c
index ed7d958b0a01..544f2e25d0e5 100644
--- a/drivers/serial/suncore.c
+++ b/drivers/serial/suncore.c
@@ -71,7 +71,9 @@ int sunserial_console_match(struct console *con, struct device_node *dp,
71 71
72 con->index = line; 72 con->index = line;
73 drv->cons = con; 73 drv->cons = con;
74 add_preferred_console(con->name, line, NULL); 74
75 if (!console_set_on_cmdline)
76 add_preferred_console(con->name, line, NULL);
75 77
76 return 1; 78 return 1;
77} 79}
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 234459c2f012..ffbf4553f665 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1500,20 +1500,25 @@ out_unmap:
1500static int __devexit su_remove(struct of_device *op) 1500static int __devexit su_remove(struct of_device *op)
1501{ 1501{
1502 struct uart_sunsu_port *up = dev_get_drvdata(&op->dev); 1502 struct uart_sunsu_port *up = dev_get_drvdata(&op->dev);
1503 bool kbdms = false;
1503 1504
1504 if (up->su_type == SU_PORT_MS || 1505 if (up->su_type == SU_PORT_MS ||
1505 up->su_type == SU_PORT_KBD) { 1506 up->su_type == SU_PORT_KBD)
1507 kbdms = true;
1508
1509 if (kbdms) {
1506#ifdef CONFIG_SERIO 1510#ifdef CONFIG_SERIO
1507 serio_unregister_port(&up->serio); 1511 serio_unregister_port(&up->serio);
1508#endif 1512#endif
1509 kfree(up); 1513 } else if (up->port.type != PORT_UNKNOWN)
1510 } else if (up->port.type != PORT_UNKNOWN) {
1511 uart_remove_one_port(&sunsu_reg, &up->port); 1514 uart_remove_one_port(&sunsu_reg, &up->port);
1512 }
1513 1515
1514 if (up->port.membase) 1516 if (up->port.membase)
1515 of_iounmap(&op->resource[0], up->port.membase, up->reg_size); 1517 of_iounmap(&op->resource[0], up->port.membase, up->reg_size);
1516 1518
1519 if (kbdms)
1520 kfree(up);
1521
1517 dev_set_drvdata(&op->dev, NULL); 1522 dev_set_drvdata(&op->dev, NULL);
1518 1523
1519 return 0; 1524 return 0;