aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-08-04 00:52:34 -0400
committerPaul Mundt <lethal@linux-sh.org>2010-08-04 00:52:34 -0400
commitbaea90ea14b316e4599f000c713e446908a5aef6 (patch)
tree17eae40f15832b466121d8f962028472c4568a13 /drivers/serial
parent36239c6704b71da7fb8e2a9429e159a84d0c5a3e (diff)
parent3a09b1be53d23df780a0cd0e4087a05e2ca4a00c (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
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/suncore.c4
-rw-r--r--drivers/serial/sunsu.c13
5 files changed, 90 insertions, 20 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/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;