diff options
Diffstat (limited to 'drivers/tty/serial/8250')
| -rw-r--r-- | drivers/tty/serial/8250/8250.c | 72 | ||||
| -rw-r--r-- | drivers/tty/serial/8250/8250.h | 9 | ||||
| -rw-r--r-- | drivers/tty/serial/8250/8250_pci.c | 11 | ||||
| -rw-r--r-- | drivers/tty/serial/8250/8250_pnp.c | 31 | ||||
| -rw-r--r-- | drivers/tty/serial/8250/Kconfig | 16 | ||||
| -rw-r--r-- | drivers/tty/serial/8250/Makefile | 5 |
6 files changed, 92 insertions, 52 deletions
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index d4e0b07cb13..3ba4234592b 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -290,6 +290,9 @@ static const struct serial8250_config uart_config[] = { UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, .flags = UART_CAP_FIFO, }, + [PORT_8250_CIR] = { + .name = "CIR port" + } }; /* Uart divisor latch read */ @@ -1037,6 +1040,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) unsigned char save_lcr, save_mcr; struct uart_port *port = &up->port; unsigned long flags; + unsigned int old_capabilities; if (!port->iobase && !port->mapbase && !port->membase) return; @@ -1087,6 +1091,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) /* * We failed; there's nothing here */ + spin_unlock_irqrestore(&port->lock, flags); DEBUG_AUTOCONF("IER test failed (%02x, %02x) ", scratch2, scratch3); goto out; @@ -1110,6 +1115,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) status1 = serial_in(up, UART_MSR) & 0xF0; serial_out(up, UART_MCR, save_mcr); if (status1 != 0x90) { + spin_unlock_irqrestore(&port->lock, flags); DEBUG_AUTOCONF("LOOP test failed (%02x) ", status1); goto out; @@ -1132,8 +1138,6 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); scratch = serial_in(up, UART_IIR) >> 6; - DEBUG_AUTOCONF("iir=%d ", scratch); - switch (scratch) { case 0: autoconfig_8250(up); @@ -1167,19 +1171,13 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) serial_out(up, UART_LCR, save_lcr); - if (up->capabilities != uart_config[port->type].flags) { - printk(KERN_WARNING - "ttyS%d: detected caps %08x should be %08x\n", - serial_index(port), up->capabilities, - uart_config[port->type].flags); - } - port->fifosize = uart_config[up->port.type].fifo_size; + old_capabilities = up->capabilities; up->capabilities = uart_config[port->type].flags; up->tx_loadsz = uart_config[port->type].tx_loadsz; if (port->type == PORT_UNKNOWN) - goto out; + goto out_lock; /* * Reset the UART. @@ -1196,8 +1194,16 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) else serial_out(up, UART_IER, 0); - out: +out_lock: spin_unlock_irqrestore(&port->lock, flags); + if (up->capabilities != old_capabilities) { + printk(KERN_WARNING + "ttyS%d: detected caps %08x should be %08x\n", + serial_index(port), old_capabilities, + up->capabilities); + } +out: + DEBUG_AUTOCONF("iir=%d ", scratch); DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name); } @@ -1897,6 +1903,9 @@ static int serial8250_startup(struct uart_port *port) unsigned char lsr, iir; int retval; + if (port->type == PORT_8250_CIR) + return -ENODEV; + port->fifosize = uart_config[up->port.type].fifo_size; up->tx_loadsz = uart_config[up->port.type].tx_loadsz; up->capabilities = uart_config[up->port.type].flags; @@ -2554,7 +2563,10 @@ static int serial8250_request_port(struct uart_port *port) { struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); - int ret = 0; + int ret; + + if (port->type == PORT_8250_CIR) + return -ENODEV; ret = serial8250_request_std_resource(up); if (ret == 0 && port->type == PORT_RSA) { @@ -2573,6 +2585,9 @@ static void serial8250_config_port(struct uart_port *port, int flags) int probeflags = PROBE_ANY; int ret; + if (port->type == PORT_8250_CIR) + return; + /* * Find the region that we can probe for. This in turn * tells us whether we can probe for the type of port. @@ -2672,6 +2687,9 @@ static void __init serial8250_isa_init_ports(void) return; first = 0; + if (nr_uarts > UART_NR) + nr_uarts = UART_NR; + for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; struct uart_port *port = &up->port; @@ -2681,6 +2699,7 @@ static void __init serial8250_isa_init_ports(void) init_timer(&up->timer); up->timer.function = serial8250_timeout; + up->cur_iotype = 0xFF; /* * ALPHA_KLUDGE_MCR needs to be killed. @@ -2732,13 +2751,9 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; - up->cur_iotype = 0xFF; - } - serial8250_isa_init_ports(); - - for (i = 0; i < nr_uarts; i++) { - struct uart_8250_port *up = &serial8250_ports[i]; + if (up->port.dev) + continue; up->port.dev = dev; @@ -2863,9 +2878,6 @@ static struct console serial8250_console = { static int __init serial8250_console_init(void) { - if (nr_uarts > UART_NR) - nr_uarts = UART_NR; - serial8250_isa_init_ports(); register_console(&serial8250_console); return 0; @@ -3147,8 +3159,9 @@ int serial8250_register_8250_port(struct uart_8250_port *up) mutex_lock(&serial_mutex); uart = serial8250_find_match_or_unused(&up->port); - if (uart) { - uart_remove_one_port(&serial8250_reg, &uart->port); + if (uart && uart->port.type != PORT_8250_CIR) { + if (uart->port.dev) + uart_remove_one_port(&serial8250_reg, &uart->port); uart->port.iobase = up->port.iobase; uart->port.membase = up->port.membase; @@ -3232,8 +3245,7 @@ static int __init serial8250_init(void) { int ret; - if (nr_uarts > UART_NR) - nr_uarts = UART_NR; + serial8250_isa_init_ports(); printk(KERN_INFO "Serial: 8250/16550 driver, " "%d ports, IRQ sharing %sabled\n", nr_uarts, @@ -3248,11 +3260,15 @@ static int __init serial8250_init(void) if (ret) goto out; + ret = serial8250_pnp_init(); + if (ret) + goto unreg_uart_drv; + serial8250_isa_devs = platform_device_alloc("serial8250", PLAT8250_DEV_LEGACY); if (!serial8250_isa_devs) { ret = -ENOMEM; - goto unreg_uart_drv; + goto unreg_pnp; } ret = platform_device_add(serial8250_isa_devs); @@ -3268,6 +3284,8 @@ static int __init serial8250_init(void) platform_device_del(serial8250_isa_devs); put_dev: platform_device_put(serial8250_isa_devs); +unreg_pnp: + serial8250_pnp_exit(); unreg_uart_drv: #ifdef CONFIG_SPARC sunserial_unregister_minors(&serial8250_reg, UART_NR); @@ -3292,6 +3310,8 @@ static void __exit serial8250_exit(void) platform_driver_unregister(&serial8250_isa_driver); platform_device_unregister(isa_dev); + serial8250_pnp_exit(); + #ifdef CONFIG_SPARC sunserial_unregister_minors(&serial8250_reg, UART_NR); #else diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 0c5e908df0b..5a76f9c8d36 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -97,3 +97,12 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value) #else #define ALPHA_KLUDGE_MCR 0 #endif + +#ifdef CONFIG_SERIAL_8250_PNP +int serial8250_pnp_init(void); +void serial8250_pnp_exit(void); +#else +static inline int serial8250_pnp_init(void) { return 0; } +static inline void serial8250_pnp_exit(void) { } +#endif + diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index fdab80a4e06..17b7d26abf4 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1181,6 +1181,8 @@ pci_wch_ch353_setup(struct serial_private *priv, #define PCI_SUBDEVICE_ID_OCTPRO422 0x0208 #define PCI_SUBDEVICE_ID_POCTAL232 0x0308 #define PCI_SUBDEVICE_ID_POCTAL422 0x0408 +#define PCI_SUBDEVICE_ID_SIIG_DUAL_00 0x2500 +#define PCI_SUBDEVICE_ID_SIIG_DUAL_30 0x2530 #define PCI_VENDOR_ID_ADVANTECH 0x13fe #define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66 #define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620 @@ -3286,8 +3288,11 @@ static struct pci_device_id serial_pci_tbl[] = { * For now just used the hex ID 0x950a. */ { PCI_VENDOR_ID_OXSEMI, 0x950a, - PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0, - pbn_b0_2_115200 }, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_00, + 0, 0, pbn_b0_2_115200 }, + { PCI_VENDOR_ID_OXSEMI, 0x950a, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_30, + 0, 0, pbn_b0_2_115200 }, { PCI_VENDOR_ID_OXSEMI, 0x950a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_2_1130000 }, @@ -4309,7 +4314,7 @@ static void serial8250_io_resume(struct pci_dev *dev) pciserial_resume_ports(priv); } -static struct pci_error_handlers serial8250_err_handler = { +static const struct pci_error_handlers serial8250_err_handler = { .error_detected = serial8250_io_error_detected, .slot_reset = serial8250_io_slot_reset, .resume = serial8250_io_resume, diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index fde5aa60d51..f8ee25001dd 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -1,5 +1,5 @@ /* - * Probe module for 8250/16550-type ISAPNP serial ports. + * Probe for 8250/16550-type ISAPNP serial ports. * * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. * @@ -25,7 +25,7 @@ #include "8250.h" #define UNKNOWN_DEV 0x3000 - +#define CIR_PORT 0x0800 static const struct pnp_device_id pnp_dev_table[] = { /* Archtek America Corp. */ @@ -362,6 +362,9 @@ static const struct pnp_device_id pnp_dev_table[] = { { "PNPCXXX", UNKNOWN_DEV }, /* More unknown PnP modems */ { "PNPDXXX", UNKNOWN_DEV }, + /* Winbond CIR port, should not be probed. We should keep track + of it to prevent the legacy serial driver from probing it */ + { "WEC1022", CIR_PORT }, { "", 0 } }; @@ -409,7 +412,7 @@ static int __devinit check_resources(struct pnp_dev *dev) * PnP modems, alternatively we must hardcode all modems in pnp_devices[] * table. */ -static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags) +static int __devinit serial_pnp_guess_board(struct pnp_dev *dev) { if (!(check_name(pnp_dev_name(dev)) || (dev->card && check_name(dev->card->name)))) @@ -428,7 +431,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) int ret, line, flags = dev_id->driver_data; if (flags & UNKNOWN_DEV) { - ret = serial_pnp_guess_board(dev, &flags); + ret = serial_pnp_guess_board(dev); if (ret < 0) return ret; } @@ -436,7 +439,10 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) memset(&uart, 0, sizeof(uart)); if (pnp_irq_valid(dev, 0)) uart.port.irq = pnp_irq(dev, 0); - if (pnp_port_valid(dev, 0)) { + if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) { + uart.port.iobase = pnp_port_start(dev, 2); + uart.port.iotype = UPIO_PORT; + } else if (pnp_port_valid(dev, 0)) { uart.port.iobase = pnp_port_start(dev, 0); uart.port.iotype = UPIO_PORT; } else if (pnp_mem_valid(dev, 0)) { @@ -451,6 +457,10 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n", uart.port.iobase, uart.port.mapbase, uart.port.irq, uart.port.iotype); #endif + if (flags & CIR_PORT) { + uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; + uart.port.type = PORT_8250_CIR; + } uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE) @@ -459,7 +469,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) uart.port.dev = &dev->dev; line = serial8250_register_8250_port(&uart); - if (line < 0) + if (line < 0 || (flags & CIR_PORT)) return -ENODEV; pnp_set_drvdata(dev, (void *)((long)line + 1)); @@ -507,18 +517,13 @@ static struct pnp_driver serial_pnp_driver = { .id_table = pnp_dev_table, }; -static int __init serial8250_pnp_init(void) +int serial8250_pnp_init(void) { return pnp_register_driver(&serial_pnp_driver); } -static void __exit serial8250_pnp_exit(void) +void serial8250_pnp_exit(void) { pnp_unregister_driver(&serial_pnp_driver); } -module_init(serial8250_pnp_init); -module_exit(serial8250_pnp_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Generic 8250/16x50 PnP serial driver"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index a27dd0569bd..f3d283f2e3a 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -33,6 +33,14 @@ config SERIAL_8250 Most people will say Y or M here, so that they can use serial mice, modems and similar devices connecting to the standard serial ports. +config SERIAL_8250_PNP + bool "8250/16550 PNP device support" if EXPERT + depends on SERIAL_8250 && PNP + default y + ---help--- + This builds standard PNP serial support. You may be able to + disable this feature if you only need legacy serial support. + config SERIAL_8250_CONSOLE bool "Console on 8250/16550 and compatible serial port" depends on SERIAL_8250=y @@ -85,14 +93,6 @@ config SERIAL_8250_PCI disable this feature if you only need legacy serial support. Saves about 9K. -config SERIAL_8250_PNP - tristate "8250/16550 PNP device support" if EXPERT - depends on SERIAL_8250 && PNP - default SERIAL_8250 - help - This builds standard PNP serial support. You may be able to - disable this feature if you only need legacy serial support. - config SERIAL_8250_HP300 tristate depends on SERIAL_8250 && HP300 diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index d7533c7d2c1..108fe7fe13e 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -2,8 +2,9 @@ # Makefile for the 8250 serial device drivers. # -obj-$(CONFIG_SERIAL_8250) += 8250.o -obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o +obj-$(CONFIG_SERIAL_8250) += 8250_core.o +8250_core-y := 8250.o +8250_core-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o |