diff options
| author | Tony Luck <tony.luck@intel.com> | 2005-05-17 18:53:14 -0400 |
|---|---|---|
| committer | Tony Luck <tony.luck@intel.com> | 2005-05-17 18:53:14 -0400 |
| commit | 325a479c4c110db278ef3361460a48c4093252cc (patch) | |
| tree | bcfbf4d0647d9442045639a5c19da59d55190e81 /drivers/serial/imx.c | |
| parent | ebcc80c1b6629a445f7471cc1ddb48faf8a84e70 (diff) | |
| parent | 7f9eaedf894dbaa08c157832e9a6c9c03ffed1ed (diff) | |
Merge with temp tree to get David's gdb inferior calls patch
Diffstat (limited to 'drivers/serial/imx.c')
| -rw-r--r-- | drivers/serial/imx.c | 68 |
1 files changed, 60 insertions, 8 deletions
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index c682c6308cde..01a8726a3f97 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
| @@ -321,18 +321,39 @@ static void imx_break_ctl(struct uart_port *port, int break_state) | |||
| 321 | #define TXTL 2 /* reset default */ | 321 | #define TXTL 2 /* reset default */ |
| 322 | #define RXTL 1 /* reset default */ | 322 | #define RXTL 1 /* reset default */ |
| 323 | 323 | ||
| 324 | static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) | ||
| 325 | { | ||
| 326 | unsigned int val; | ||
| 327 | unsigned int ufcr_rfdiv; | ||
| 328 | |||
| 329 | /* set receiver / transmitter trigger level. | ||
| 330 | * RFDIV is set such way to satisfy requested uartclk value | ||
| 331 | */ | ||
| 332 | val = TXTL<<10 | RXTL; | ||
| 333 | ufcr_rfdiv = (imx_get_perclk1() + sport->port.uartclk / 2) / sport->port.uartclk; | ||
| 334 | |||
| 335 | if(!ufcr_rfdiv) | ||
| 336 | ufcr_rfdiv = 1; | ||
| 337 | |||
| 338 | if(ufcr_rfdiv >= 7) | ||
| 339 | ufcr_rfdiv = 6; | ||
| 340 | else | ||
| 341 | ufcr_rfdiv = 6 - ufcr_rfdiv; | ||
| 342 | |||
| 343 | val |= UFCR_RFDIV & (ufcr_rfdiv << 7); | ||
| 344 | |||
| 345 | UFCR((u32)sport->port.membase) = val; | ||
| 346 | |||
| 347 | return 0; | ||
| 348 | } | ||
| 349 | |||
| 324 | static int imx_startup(struct uart_port *port) | 350 | static int imx_startup(struct uart_port *port) |
| 325 | { | 351 | { |
| 326 | struct imx_port *sport = (struct imx_port *)port; | 352 | struct imx_port *sport = (struct imx_port *)port; |
| 327 | int retval; | 353 | int retval; |
| 328 | unsigned int val; | ||
| 329 | unsigned long flags; | 354 | unsigned long flags; |
| 330 | 355 | ||
| 331 | /* set receiver / transmitter trigger level. We assume | 356 | imx_setup_ufcr(sport, 0); |
| 332 | * that RFDIV has been set by the arch setup or by the bootloader. | ||
| 333 | */ | ||
| 334 | val = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) | TXTL<<10 | RXTL; | ||
| 335 | UFCR((u32)sport->port.membase) = val; | ||
| 336 | 357 | ||
| 337 | /* disable the DREN bit (Data Ready interrupt enable) before | 358 | /* disable the DREN bit (Data Ready interrupt enable) before |
| 338 | * requesting IRQs | 359 | * requesting IRQs |
| @@ -737,9 +758,12 @@ static void __init | |||
| 737 | imx_console_get_options(struct imx_port *sport, int *baud, | 758 | imx_console_get_options(struct imx_port *sport, int *baud, |
| 738 | int *parity, int *bits) | 759 | int *parity, int *bits) |
| 739 | { | 760 | { |
| 761 | |||
| 740 | if ( UCR1((u32)sport->port.membase) | UCR1_UARTEN ) { | 762 | if ( UCR1((u32)sport->port.membase) | UCR1_UARTEN ) { |
| 741 | /* ok, the port was enabled */ | 763 | /* ok, the port was enabled */ |
| 742 | unsigned int ucr2, ubir,ubmr, uartclk; | 764 | unsigned int ucr2, ubir,ubmr, uartclk; |
| 765 | unsigned int baud_raw; | ||
| 766 | unsigned int ucfr_rfdiv; | ||
| 743 | 767 | ||
| 744 | ucr2 = UCR2((u32)sport->port.membase); | 768 | ucr2 = UCR2((u32)sport->port.membase); |
| 745 | 769 | ||
| @@ -758,9 +782,35 @@ imx_console_get_options(struct imx_port *sport, int *baud, | |||
| 758 | 782 | ||
| 759 | ubir = UBIR((u32)sport->port.membase) & 0xffff; | 783 | ubir = UBIR((u32)sport->port.membase) & 0xffff; |
| 760 | ubmr = UBMR((u32)sport->port.membase) & 0xffff; | 784 | ubmr = UBMR((u32)sport->port.membase) & 0xffff; |
| 761 | uartclk = sport->port.uartclk; | ||
| 762 | 785 | ||
| 763 | *baud = ((uartclk/16) * (ubir + 1)) / (ubmr + 1); | 786 | |
| 787 | ucfr_rfdiv = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) >> 7; | ||
| 788 | if (ucfr_rfdiv == 6) | ||
| 789 | ucfr_rfdiv = 7; | ||
| 790 | else | ||
| 791 | ucfr_rfdiv = 6 - ucfr_rfdiv; | ||
| 792 | |||
| 793 | uartclk = imx_get_perclk1(); | ||
| 794 | uartclk /= ucfr_rfdiv; | ||
| 795 | |||
| 796 | { /* | ||
| 797 | * The next code provides exact computation of | ||
| 798 | * baud_raw = round(((uartclk/16) * (ubir + 1)) / (ubmr + 1)) | ||
| 799 | * without need of float support or long long division, | ||
| 800 | * which would be required to prevent 32bit arithmetic overflow | ||
| 801 | */ | ||
| 802 | unsigned int mul = ubir + 1; | ||
| 803 | unsigned int div = 16 * (ubmr + 1); | ||
| 804 | unsigned int rem = uartclk % div; | ||
| 805 | |||
| 806 | baud_raw = (uartclk / div) * mul; | ||
| 807 | baud_raw += (rem * mul + div / 2) / div; | ||
| 808 | *baud = (baud_raw + 50) / 100 * 100; | ||
| 809 | } | ||
| 810 | |||
| 811 | if(*baud != baud_raw) | ||
| 812 | printk(KERN_INFO "Serial: Console IMX rounded baud rate from %d to %d\n", | ||
| 813 | baud_raw, *baud); | ||
| 764 | } | 814 | } |
| 765 | } | 815 | } |
| 766 | 816 | ||
| @@ -787,6 +837,8 @@ imx_console_setup(struct console *co, char *options) | |||
| 787 | else | 837 | else |
| 788 | imx_console_get_options(sport, &baud, &parity, &bits); | 838 | imx_console_get_options(sport, &baud, &parity, &bits); |
| 789 | 839 | ||
| 840 | imx_setup_ufcr(sport, 0); | ||
| 841 | |||
| 790 | return uart_set_options(&sport->port, co, baud, parity, bits, flow); | 842 | return uart_set_options(&sport->port, co, baud, parity, bits, flow); |
| 791 | } | 843 | } |
| 792 | 844 | ||
