diff options
author | Paul Mundt <lethal@linux-sh.org> | 2010-08-04 00:52:34 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-08-04 00:52:34 -0400 |
commit | baea90ea14b316e4599f000c713e446908a5aef6 (patch) | |
tree | 17eae40f15832b466121d8f962028472c4568a13 /drivers/serial | |
parent | 36239c6704b71da7fb8e2a9429e159a84d0c5a3e (diff) | |
parent | 3a09b1be53d23df780a0cd0e4087a05e2ca4a00c (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.c | 2 | ||||
-rw-r--r-- | drivers/serial/amba-pl011.c | 90 | ||||
-rw-r--r-- | drivers/serial/atmel_serial.c | 1 | ||||
-rw-r--r-- | drivers/serial/suncore.c | 4 | ||||
-rw-r--r-- | drivers/serial/sunsu.c | 13 |
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 | ||
785 | static struct amba_id pl010_ids[] __initdata = { | 785 | static 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 @@ | |||
69 | struct uart_amba_port { | 69 | struct 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 { | |||
79 | struct vendor_data { | 82 | struct 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 | ||
84 | static struct vendor_data vendor_arm = { | 90 | static 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 | ||
89 | static struct vendor_data vendor_st = { | 98 | static 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 | ||
94 | static void pl011_stop_tx(struct uart_port *port) | 106 | static 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 | ||
447 | static 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 | |||
425 | static void pl011_shutdown(struct uart_port *port) | 457 | static 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 | ||
871 | static struct amba_id pl011_ids[] __initdata = { | 933 | static 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: | |||
1500 | static int __devexit su_remove(struct of_device *op) | 1500 | static 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; |