diff options
| -rw-r--r-- | drivers/serial/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/serial/imx.c | 30 |
2 files changed, 11 insertions, 20 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 3391ef0d761..641e800ed69 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
| @@ -833,6 +833,7 @@ config SERIAL_IMX | |||
| 833 | bool "IMX serial port support" | 833 | bool "IMX serial port support" |
| 834 | depends on ARM && (ARCH_IMX || ARCH_MXC) | 834 | depends on ARM && (ARCH_IMX || ARCH_MXC) |
| 835 | select SERIAL_CORE | 835 | select SERIAL_CORE |
| 836 | select RATIONAL | ||
| 836 | help | 837 | help |
| 837 | If you have a machine based on a Motorola IMX CPU you | 838 | If you have a machine based on a Motorola IMX CPU you |
| 838 | can enable its onboard serial port by enabling this option. | 839 | can enable its onboard serial port by enabling this option. |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index cbd4f322464..0de81f71f88 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 |
