diff options
Diffstat (limited to 'drivers/serial/imx.c')
-rw-r--r-- | drivers/serial/imx.c | 30 |
1 files changed, 10 insertions, 20 deletions
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index cbd4f3224643..0de81f71f884 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/serial_core.h> | 41 | #include <linux/serial_core.h> |
42 | #include <linux/serial.h> | 42 | #include <linux/serial.h> |
43 | #include <linux/clk.h> | 43 | #include <linux/clk.h> |
44 | #include <linux/rational.h> | ||
44 | 45 | ||
45 | #include <asm/io.h> | 46 | #include <asm/io.h> |
46 | #include <asm/irq.h> | 47 | #include <asm/irq.h> |
@@ -670,7 +671,8 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, | |||
670 | unsigned long flags; | 671 | unsigned long flags; |
671 | unsigned int ucr2, old_ucr1, old_txrxen, baud, quot; | 672 | unsigned int ucr2, old_ucr1, old_txrxen, baud, quot; |
672 | unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; | 673 | unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; |
673 | unsigned int div, num, denom, ufcr; | 674 | unsigned int div, ufcr; |
675 | unsigned long num, denom; | ||
674 | 676 | ||
675 | /* | 677 | /* |
676 | * If we don't support modem control lines, don't allow | 678 | * If we don't support modem control lines, don't allow |
@@ -772,32 +774,20 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, | |||
772 | if (!div) | 774 | if (!div) |
773 | div = 1; | 775 | div = 1; |
774 | 776 | ||
775 | num = baud; | 777 | rational_best_approximation(16 * div * baud, sport->port.uartclk, |
776 | denom = port->uartclk / div / 16; | 778 | 1 << 16, 1 << 16, &num, &denom); |
777 | 779 | ||
778 | /* shift num and denom right until they fit into 16 bits */ | 780 | num -= 1; |
779 | while (num > 0x10000 || denom > 0x10000) { | 781 | denom -= 1; |
780 | num >>= 1; | ||
781 | denom >>= 1; | ||
782 | } | ||
783 | if (num > 0) | ||
784 | num -= 1; | ||
785 | if (denom > 0) | ||
786 | denom -= 1; | ||
787 | |||
788 | writel(num, sport->port.membase + UBIR); | ||
789 | writel(denom, sport->port.membase + UBMR); | ||
790 | |||
791 | if (div == 7) | ||
792 | div = 6; /* 6 in RFDIV means divide by 7 */ | ||
793 | else | ||
794 | div = 6 - div; | ||
795 | 782 | ||
796 | ufcr = readl(sport->port.membase + UFCR); | 783 | ufcr = readl(sport->port.membase + UFCR); |
797 | ufcr = (ufcr & (~UFCR_RFDIV)) | | 784 | ufcr = (ufcr & (~UFCR_RFDIV)) | |
798 | (div << 7); | 785 | (div << 7); |
799 | writel(ufcr, sport->port.membase + UFCR); | 786 | writel(ufcr, sport->port.membase + UFCR); |
800 | 787 | ||
788 | writel(num, sport->port.membase + UBIR); | ||
789 | writel(denom, sport->port.membase + UBMR); | ||
790 | |||
801 | #ifdef ONEMS | 791 | #ifdef ONEMS |
802 | writel(sport->port.uartclk / div / 1000, sport->port.membase + ONEMS); | 792 | writel(sport->port.uartclk / div / 1000, sport->port.membase + ONEMS); |
803 | #endif | 793 | #endif |