ia64/xen-unstable

changeset 9519:50778f42f2dd

Compute actual baud rate from UART divisor latch contents
when no baud rate is specified. Generalise the divisor
calculation based on external clock rate.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Mar 29 16:02:40 2006 +0100 (2006-03-29)
parents 5715cf117178
children 4c2d101a3228
files xen/drivers/char/ns16550.c
line diff
     1.1 --- a/xen/drivers/char/ns16550.c	Wed Mar 29 15:39:22 2006 +0100
     1.2 +++ b/xen/drivers/char/ns16550.c	Wed Mar 29 16:02:40 2006 +0100
     1.3 @@ -99,6 +99,9 @@ static struct ns16550 {
     1.4  #define PARITY_MARK     (5<<3)
     1.5  #define PARITY_SPACE    (7<<3)
     1.6  
     1.7 +/* Frequency of external clock source. This definition assumes PC platform. */
     1.8 +#define UART_CLOCK_HZ   1843200
     1.9 +
    1.10  static char ns_read_reg(struct ns16550 *uart, int reg)
    1.11  {
    1.12      if ( uart->remapped_io_base == NULL )
    1.13 @@ -171,6 +174,7 @@ static void ns16550_init_preirq(struct s
    1.14  {
    1.15      struct ns16550 *uart = port->uart;
    1.16      unsigned char lcr;
    1.17 +    unsigned int  divisor;
    1.18  
    1.19      /* I/O ports are distinguished by their size (16 bits). */
    1.20      if ( uart->io_base >= 0x10000 )
    1.21 @@ -182,13 +186,22 @@ static void ns16550_init_preirq(struct s
    1.22      ns_write_reg(uart, IER, 0);
    1.23  
    1.24      /* Line control and baud-rate generator. */
    1.25 +    ns_write_reg(uart, LCR, lcr | LCR_DLAB);
    1.26      if ( uart->baud != BAUD_AUTO )
    1.27      {
    1.28 -        ns_write_reg(uart, LCR, lcr | LCR_DLAB);
    1.29 -        ns_write_reg(uart, DLL, 115200/uart->baud); /* baud lo */
    1.30 -        ns_write_reg(uart, DLM, 0);                 /* baud hi */
    1.31 +        /* Baud rate specified: program it into the divisor latch. */
    1.32 +        divisor = UART_CLOCK_HZ / (uart->baud * 16);
    1.33 +        ns_write_reg(uart, DLL, (char)divisor);
    1.34 +        ns_write_reg(uart, DLM, (char)(divisor >> 8));
    1.35      }
    1.36 -    ns_write_reg(uart, LCR, lcr);               /* parity, data, stop */
    1.37 +    else
    1.38 +    {
    1.39 +        /* Baud rate already set: read it out from the divisor latch. */
    1.40 +        divisor  = ns_read_reg(uart, DLL);
    1.41 +        divisor |= ns_read_reg(uart, DLM) << 8;
    1.42 +        uart->baud = UART_CLOCK_HZ / (divisor * 16);
    1.43 +    }
    1.44 +    ns_write_reg(uart, LCR, lcr);
    1.45  
    1.46      /* No flow ctrl: DTR and RTS are both wedged high to keep remote happy. */
    1.47      ns_write_reg(uart, MCR, MCR_DTR | MCR_RTS);