ia64/xen-unstable

changeset 18649:50aaffd8f87c

Enable PCI serial devices for console messages

The basic issue is that some PCI serial devices use a non-standard
crystal to control the baud rate divisor. This patch enhances the
`com' parameter to enable you to specify the crystal frequency used by
the serial device. Since this parameter already allows you to specify
I/O address and IRQ this is all that is needed to get a PCI serial
device to work. With this patch the `com' parameter is now defined
as:
comN=BBB[/CCC][,NPS[,III[,IRQ]]]

Where `CCC' is the crystal frequency. Note that if you specify 0 for
`IRQ' Xen will run the serial device in polled mode, obviating the
need for interrupts (an advantage since this is the only way I was
able to get my PCI serial device to work).

As an example, I am using the xen boot command:

kernel /xen.gz com1=3D115200,8n1,0xe880/921600,0
console=3Dcom1

Signed-off-by: Don Dugger <donald.d.dugger@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Oct 17 12:00:25 2008 +0100 (2008-10-17)
parents 6bf61b830153
children 609d0d34450f
files xen/drivers/char/ns16550.c
line diff
     1.1 --- a/xen/drivers/char/ns16550.c	Thu Oct 16 18:45:48 2008 +0100
     1.2 +++ b/xen/drivers/char/ns16550.c	Fri Oct 17 12:00:25 2008 +0100
     1.3 @@ -18,17 +18,19 @@
     1.4  #include <asm/io.h>
     1.5  
     1.6  /*
     1.7 - * Configure serial port with a string <baud>,DPS,<io-base>,<irq>.
     1.8 + * Configure serial port with a string:
     1.9 + *   <baud>[/<clock_hz>][,DPS[,<io-base>[,<irq>]]].
    1.10   * The tail of the string can be omitted if platform defaults are sufficient.
    1.11   * If the baud rate is pre-configured, perhaps by a bootloader, then 'auto'
    1.12 - * can be specified in place of a numeric baud rate.
    1.13 + * can be specified in place of a numeric baud rate. Polled mode is specified
    1.14 + * by requesting irq 0.
    1.15   */
    1.16  static char opt_com1[30] = "", opt_com2[30] = "";
    1.17  string_param("com1", opt_com1);
    1.18  string_param("com2", opt_com2);
    1.19  
    1.20  static struct ns16550 {
    1.21 -    int baud, data_bits, parity, stop_bits, irq;
    1.22 +    int baud, clock_hz, data_bits, parity, stop_bits, irq;
    1.23      unsigned long io_base;   /* I/O port or memory-mapped I/O address. */
    1.24      char *remapped_io_base;  /* Remapped virtual address of mmap I/O.  */ 
    1.25      /* UART with IRQ line: interrupt-driven I/O. */
    1.26 @@ -192,7 +194,7 @@ static void __devinit ns16550_init_preir
    1.27      if ( uart->baud != BAUD_AUTO )
    1.28      {
    1.29          /* Baud rate specified: program it into the divisor latch. */
    1.30 -        divisor = UART_CLOCK_HZ / (uart->baud * 16);
    1.31 +        divisor = uart->clock_hz / (uart->baud << 4);
    1.32          ns_write_reg(uart, DLL, (char)divisor);
    1.33          ns_write_reg(uart, DLM, (char)(divisor >> 8));
    1.34      }
    1.35 @@ -201,7 +203,7 @@ static void __devinit ns16550_init_preir
    1.36          /* Baud rate already set: read it out from the divisor latch. */
    1.37          divisor  = ns_read_reg(uart, DLL);
    1.38          divisor |= ns_read_reg(uart, DLM) << 8;
    1.39 -        uart->baud = UART_CLOCK_HZ / (divisor * 16);
    1.40 +        uart->baud = uart->clock_hz / (divisor << 4);
    1.41      }
    1.42      ns_write_reg(uart, LCR, lcr);
    1.43  
    1.44 @@ -355,6 +357,12 @@ static void __init ns16550_parse_port_co
    1.45      else if ( (baud = simple_strtoul(conf, &conf, 10)) != 0 )
    1.46          uart->baud = baud;
    1.47  
    1.48 +    if ( *conf == '/')
    1.49 +    {
    1.50 +        conf++;
    1.51 +        uart->clock_hz = simple_strtoul(conf, &conf, 0) << 4;
    1.52 +    }
    1.53 +
    1.54      if ( *conf != ',' )
    1.55          goto config_parsed;
    1.56      conf++;
    1.57 @@ -408,6 +416,7 @@ void __init ns16550_init(int index, stru
    1.58      uart->baud      = (defaults->baud ? :
    1.59                         console_has((index == 0) ? "com1" : "com2")
    1.60                         ? BAUD_AUTO : 0);
    1.61 +    uart->clock_hz  = UART_CLOCK_HZ;
    1.62      uart->data_bits = defaults->data_bits;
    1.63      uart->parity    = parse_parity_char(defaults->parity);
    1.64      uart->stop_bits = defaults->stop_bits;