diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-03 12:13:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-03 12:13:29 -0400 |
commit | 6f3a28f7d1f0a65a78443c273b6e8ec01becf301 (patch) | |
tree | ea57276725b31ba115f44cb5267a7d85b133e6fb /drivers/serial | |
parent | 6ebfc0e20b409f13e62bbb84ce70102b49945cfd (diff) | |
parent | 75fde2eddcfcd1dcc87a72dc6cd3c859420b6148 (diff) |
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-serial
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-serial: (21 commits)
[SERIAL] add PNP IDs for FPI based touchscreens
[SERIAL] Magic SysRq SAK does nothing on serial consoles
[SERIAL] tickle NMI watchdog on serial output.
[SERIAL] Fix oops when removing suspended serial port
[SERIAL] Fix resume handling bug
[SERIAL] Remove wrong asm/serial.h inclusions
[SERIAL] CONFIG_PM=n slim: drivers/serial/8250_pci.c
[SERIAL] OMAP1510 serial fix for 115200 baud
[SERIAL] returning proper error from serial core driver
[SERIAL] Make uart_line_info() correctly tell MMIO from I/O port
[SERIAL] suspend/resume handlers don't have level arg anymore
[SERIAL] 8250 resourse management fixes
[SERIAL] serial_cs: Add quirk for brainboxes 2-port RS232 card
[SERIAL] serial_cs: handle Nokia multi->single port bodge via config quirk
[SERIAL] serial_cs: add configuration quirk
[SERIAL] serial_cs: Convert Oxford 950 / Possio GCC wakeup quirk
[SERIAL] serial_cs: convert IBM post-init handling to a quirk
[SERIAL] serial_cs: allow wildcarded quirks
[SERIAL] serial_cs: convert multi-port table to quirk table
[SERIAL] serial_cs: Use clean up multiport card detection
...
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/8250.c | 35 | ||||
-rw-r--r-- | drivers/serial/8250_pci.c | 4 | ||||
-rw-r--r-- | drivers/serial/8250_pnp.c | 13 | ||||
-rw-r--r-- | drivers/serial/m32r_sio.c | 5 | ||||
-rw-r--r-- | drivers/serial/serial_core.c | 18 | ||||
-rw-r--r-- | drivers/serial/serial_cs.c | 292 | ||||
-rw-r--r-- | drivers/serial/serial_txx9.c | 2 |
7 files changed, 268 insertions, 101 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 10c2daab99ac..cc2a205d4230 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -1896,6 +1896,17 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, | |||
1896 | serial_outp(up, UART_EFR, efr); | 1896 | serial_outp(up, UART_EFR, efr); |
1897 | } | 1897 | } |
1898 | 1898 | ||
1899 | #ifdef CONFIG_ARCH_OMAP15XX | ||
1900 | /* Workaround to enable 115200 baud on OMAP1510 internal ports */ | ||
1901 | if (cpu_is_omap1510() && is_omap_port((unsigned int)up->port.membase)) { | ||
1902 | if (baud == 115200) { | ||
1903 | quot = 1; | ||
1904 | serial_out(up, UART_OMAP_OSC_12M_SEL, 1); | ||
1905 | } else | ||
1906 | serial_out(up, UART_OMAP_OSC_12M_SEL, 0); | ||
1907 | } | ||
1908 | #endif | ||
1909 | |||
1899 | if (up->capabilities & UART_NATSEMI) { | 1910 | if (up->capabilities & UART_NATSEMI) { |
1900 | /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */ | 1911 | /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */ |
1901 | serial_outp(up, UART_LCR, 0xe0); | 1912 | serial_outp(up, UART_LCR, 0xe0); |
@@ -1949,6 +1960,8 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) | |||
1949 | case UPIO_AU: | 1960 | case UPIO_AU: |
1950 | size = 0x100000; | 1961 | size = 0x100000; |
1951 | /* fall thru */ | 1962 | /* fall thru */ |
1963 | case UPIO_TSI: | ||
1964 | case UPIO_MEM32: | ||
1952 | case UPIO_MEM: | 1965 | case UPIO_MEM: |
1953 | if (!up->port.mapbase) | 1966 | if (!up->port.mapbase) |
1954 | break; | 1967 | break; |
@@ -1984,6 +1997,8 @@ static void serial8250_release_std_resource(struct uart_8250_port *up) | |||
1984 | case UPIO_AU: | 1997 | case UPIO_AU: |
1985 | size = 0x100000; | 1998 | size = 0x100000; |
1986 | /* fall thru */ | 1999 | /* fall thru */ |
2000 | case UPIO_TSI: | ||
2001 | case UPIO_MEM32: | ||
1987 | case UPIO_MEM: | 2002 | case UPIO_MEM: |
1988 | if (!up->port.mapbase) | 2003 | if (!up->port.mapbase) |
1989 | break; | 2004 | break; |
@@ -2007,17 +2022,15 @@ static int serial8250_request_rsa_resource(struct uart_8250_port *up) | |||
2007 | { | 2022 | { |
2008 | unsigned long start = UART_RSA_BASE << up->port.regshift; | 2023 | unsigned long start = UART_RSA_BASE << up->port.regshift; |
2009 | unsigned int size = 8 << up->port.regshift; | 2024 | unsigned int size = 8 << up->port.regshift; |
2010 | int ret = 0; | 2025 | int ret = -EINVAL; |
2011 | 2026 | ||
2012 | switch (up->port.iotype) { | 2027 | switch (up->port.iotype) { |
2013 | case UPIO_MEM: | ||
2014 | ret = -EINVAL; | ||
2015 | break; | ||
2016 | |||
2017 | case UPIO_HUB6: | 2028 | case UPIO_HUB6: |
2018 | case UPIO_PORT: | 2029 | case UPIO_PORT: |
2019 | start += up->port.iobase; | 2030 | start += up->port.iobase; |
2020 | if (!request_region(start, size, "serial-rsa")) | 2031 | if (request_region(start, size, "serial-rsa")) |
2032 | ret = 0; | ||
2033 | else | ||
2021 | ret = -EBUSY; | 2034 | ret = -EBUSY; |
2022 | break; | 2035 | break; |
2023 | } | 2036 | } |
@@ -2031,9 +2044,6 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up) | |||
2031 | unsigned int size = 8 << up->port.regshift; | 2044 | unsigned int size = 8 << up->port.regshift; |
2032 | 2045 | ||
2033 | switch (up->port.iotype) { | 2046 | switch (up->port.iotype) { |
2034 | case UPIO_MEM: | ||
2035 | break; | ||
2036 | |||
2037 | case UPIO_HUB6: | 2047 | case UPIO_HUB6: |
2038 | case UPIO_PORT: | 2048 | case UPIO_PORT: |
2039 | release_region(up->port.iobase + offset, size); | 2049 | release_region(up->port.iobase + offset, size); |
@@ -2222,9 +2232,10 @@ static inline void wait_for_xmitr(struct uart_8250_port *up, int bits) | |||
2222 | /* Wait up to 1s for flow control if necessary */ | 2232 | /* Wait up to 1s for flow control if necessary */ |
2223 | if (up->port.flags & UPF_CONS_FLOW) { | 2233 | if (up->port.flags & UPF_CONS_FLOW) { |
2224 | tmout = 1000000; | 2234 | tmout = 1000000; |
2225 | while (--tmout && | 2235 | while (!(serial_in(up, UART_MSR) & UART_MSR_CTS) && --tmout) { |
2226 | ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0)) | ||
2227 | udelay(1); | 2236 | udelay(1); |
2237 | touch_nmi_watchdog(); | ||
2238 | } | ||
2228 | } | 2239 | } |
2229 | } | 2240 | } |
2230 | 2241 | ||
@@ -2397,7 +2408,6 @@ int __init early_serial_setup(struct uart_port *port) | |||
2397 | /** | 2408 | /** |
2398 | * serial8250_suspend_port - suspend one serial port | 2409 | * serial8250_suspend_port - suspend one serial port |
2399 | * @line: serial line number | 2410 | * @line: serial line number |
2400 | * @level: the level of port suspension, as per uart_suspend_port | ||
2401 | * | 2411 | * |
2402 | * Suspend one serial port. | 2412 | * Suspend one serial port. |
2403 | */ | 2413 | */ |
@@ -2409,7 +2419,6 @@ void serial8250_suspend_port(int line) | |||
2409 | /** | 2419 | /** |
2410 | * serial8250_resume_port - resume one serial port | 2420 | * serial8250_resume_port - resume one serial port |
2411 | * @line: serial line number | 2421 | * @line: serial line number |
2412 | * @level: the level of port resumption, as per uart_resume_port | ||
2413 | * | 2422 | * |
2414 | * Resume one serial port. | 2423 | * Resume one serial port. |
2415 | */ | 2424 | */ |
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 851e4839d6d9..4d0ff8f4a01b 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c | |||
@@ -1789,6 +1789,7 @@ static void __devexit pciserial_remove_one(struct pci_dev *dev) | |||
1789 | pci_disable_device(dev); | 1789 | pci_disable_device(dev); |
1790 | } | 1790 | } |
1791 | 1791 | ||
1792 | #ifdef CONFIG_PM | ||
1792 | static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state) | 1793 | static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state) |
1793 | { | 1794 | { |
1794 | struct serial_private *priv = pci_get_drvdata(dev); | 1795 | struct serial_private *priv = pci_get_drvdata(dev); |
@@ -1818,6 +1819,7 @@ static int pciserial_resume_one(struct pci_dev *dev) | |||
1818 | } | 1819 | } |
1819 | return 0; | 1820 | return 0; |
1820 | } | 1821 | } |
1822 | #endif | ||
1821 | 1823 | ||
1822 | static struct pci_device_id serial_pci_tbl[] = { | 1824 | static struct pci_device_id serial_pci_tbl[] = { |
1823 | { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, | 1825 | { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, |
@@ -2375,8 +2377,10 @@ static struct pci_driver serial_pci_driver = { | |||
2375 | .name = "serial", | 2377 | .name = "serial", |
2376 | .probe = pciserial_init_one, | 2378 | .probe = pciserial_init_one, |
2377 | .remove = __devexit_p(pciserial_remove_one), | 2379 | .remove = __devexit_p(pciserial_remove_one), |
2380 | #ifdef CONFIG_PM | ||
2378 | .suspend = pciserial_suspend_one, | 2381 | .suspend = pciserial_suspend_one, |
2379 | .resume = pciserial_resume_one, | 2382 | .resume = pciserial_resume_one, |
2383 | #endif | ||
2380 | .id_table = serial_pci_tbl, | 2384 | .id_table = serial_pci_tbl, |
2381 | }; | 2385 | }; |
2382 | 2386 | ||
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 632f62d6ec7e..71d907c8288b 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c | |||
@@ -327,6 +327,19 @@ static const struct pnp_device_id pnp_dev_table[] = { | |||
327 | { "WACF004", 0 }, | 327 | { "WACF004", 0 }, |
328 | { "WACF005", 0 }, | 328 | { "WACF005", 0 }, |
329 | { "WACF006", 0 }, | 329 | { "WACF006", 0 }, |
330 | /* Compaq touchscreen */ | ||
331 | { "FPI2002", 0 }, | ||
332 | /* Fujitsu Stylistic touchscreens */ | ||
333 | { "FUJ02B2", 0 }, | ||
334 | { "FUJ02B3", 0 }, | ||
335 | /* Fujitsu Stylistic LT touchscreens */ | ||
336 | { "FUJ02B4", 0 }, | ||
337 | /* Passive Fujitsu Stylistic touchscreens */ | ||
338 | { "FUJ02B6", 0 }, | ||
339 | { "FUJ02B7", 0 }, | ||
340 | { "FUJ02B8", 0 }, | ||
341 | { "FUJ02B9", 0 }, | ||
342 | { "FUJ02BC", 0 }, | ||
330 | /* Rockwell's (PORALiNK) 33600 INT PNP */ | 343 | /* Rockwell's (PORALiNK) 33600 INT PNP */ |
331 | { "WCI0003", 0 }, | 344 | { "WCI0003", 0 }, |
332 | /* Unkown PnP modems */ | 345 | /* Unkown PnP modems */ |
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index e7fe4bb46eca..28c9ce6f0bdc 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c | |||
@@ -76,7 +76,7 @@ | |||
76 | */ | 76 | */ |
77 | #define is_real_interrupt(irq) ((irq) != 0) | 77 | #define is_real_interrupt(irq) ((irq) != 0) |
78 | 78 | ||
79 | #include <asm/serial.h> | 79 | #define BASE_BAUD 115200 |
80 | 80 | ||
81 | /* Standard COM flags */ | 81 | /* Standard COM flags */ |
82 | #define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) | 82 | #define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) |
@@ -86,7 +86,6 @@ | |||
86 | * standard enumeration mechanism. Platforms that can find all | 86 | * standard enumeration mechanism. Platforms that can find all |
87 | * serial ports via mechanisms like ACPI or PCI need not supply it. | 87 | * serial ports via mechanisms like ACPI or PCI need not supply it. |
88 | */ | 88 | */ |
89 | #undef SERIAL_PORT_DFNS | ||
90 | #if defined(CONFIG_PLAT_USRV) | 89 | #if defined(CONFIG_PLAT_USRV) |
91 | 90 | ||
92 | #define SERIAL_PORT_DFNS \ | 91 | #define SERIAL_PORT_DFNS \ |
@@ -109,7 +108,7 @@ | |||
109 | #endif /* !CONFIG_PLAT_USRV */ | 108 | #endif /* !CONFIG_PLAT_USRV */ |
110 | 109 | ||
111 | static struct old_serial_port old_serial_port[] = { | 110 | static struct old_serial_port old_serial_port[] = { |
112 | SERIAL_PORT_DFNS /* defined in asm/serial.h */ | 111 | SERIAL_PORT_DFNS |
113 | }; | 112 | }; |
114 | 113 | ||
115 | #define UART_NR ARRAY_SIZE(old_serial_port) | 114 | #define UART_NR ARRAY_SIZE(old_serial_port) |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index de5e8930a6fd..c67b05e9a451 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -792,6 +792,7 @@ static int uart_set_info(struct uart_state *state, | |||
792 | * We failed anyway. | 792 | * We failed anyway. |
793 | */ | 793 | */ |
794 | retval = -EBUSY; | 794 | retval = -EBUSY; |
795 | goto exit; // Added to return the correct error -Ram Gupta | ||
795 | } | 796 | } |
796 | } | 797 | } |
797 | 798 | ||
@@ -1662,16 +1663,16 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i) | |||
1662 | struct uart_port *port = state->port; | 1663 | struct uart_port *port = state->port; |
1663 | char stat_buf[32]; | 1664 | char stat_buf[32]; |
1664 | unsigned int status; | 1665 | unsigned int status; |
1665 | int ret; | 1666 | int mmio, ret; |
1666 | 1667 | ||
1667 | if (!port) | 1668 | if (!port) |
1668 | return 0; | 1669 | return 0; |
1669 | 1670 | ||
1671 | mmio = port->iotype >= UPIO_MEM; | ||
1670 | ret = sprintf(buf, "%d: uart:%s %s%08lX irq:%d", | 1672 | ret = sprintf(buf, "%d: uart:%s %s%08lX irq:%d", |
1671 | port->line, uart_type(port), | 1673 | port->line, uart_type(port), |
1672 | port->iotype == UPIO_MEM ? "mmio:0x" : "port:", | 1674 | mmio ? "mmio:0x" : "port:", |
1673 | port->iotype == UPIO_MEM ? port->mapbase : | 1675 | mmio ? port->mapbase : (unsigned long) port->iobase, |
1674 | (unsigned long) port->iobase, | ||
1675 | port->irq); | 1676 | port->irq); |
1676 | 1677 | ||
1677 | if (port->type == PORT_UNKNOWN) { | 1678 | if (port->type == PORT_UNKNOWN) { |
@@ -1939,6 +1940,9 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) | |||
1939 | if (state->info && state->info->flags & UIF_INITIALIZED) { | 1940 | if (state->info && state->info->flags & UIF_INITIALIZED) { |
1940 | const struct uart_ops *ops = port->ops; | 1941 | const struct uart_ops *ops = port->ops; |
1941 | 1942 | ||
1943 | state->info->flags = (state->info->flags & ~UIF_INITIALIZED) | ||
1944 | | UIF_SUSPENDED; | ||
1945 | |||
1942 | spin_lock_irq(&port->lock); | 1946 | spin_lock_irq(&port->lock); |
1943 | ops->stop_tx(port); | 1947 | ops->stop_tx(port); |
1944 | ops->set_mctrl(port, 0); | 1948 | ops->set_mctrl(port, 0); |
@@ -2005,7 +2009,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
2005 | console_start(port->cons); | 2009 | console_start(port->cons); |
2006 | } | 2010 | } |
2007 | 2011 | ||
2008 | if (state->info && state->info->flags & UIF_INITIALIZED) { | 2012 | if (state->info && state->info->flags & UIF_SUSPENDED) { |
2009 | const struct uart_ops *ops = port->ops; | 2013 | const struct uart_ops *ops = port->ops; |
2010 | int ret; | 2014 | int ret; |
2011 | 2015 | ||
@@ -2017,15 +2021,17 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
2017 | ops->set_mctrl(port, port->mctrl); | 2021 | ops->set_mctrl(port, port->mctrl); |
2018 | ops->start_tx(port); | 2022 | ops->start_tx(port); |
2019 | spin_unlock_irq(&port->lock); | 2023 | spin_unlock_irq(&port->lock); |
2024 | state->info->flags |= UIF_INITIALIZED; | ||
2020 | } else { | 2025 | } else { |
2021 | /* | 2026 | /* |
2022 | * Failed to resume - maybe hardware went away? | 2027 | * Failed to resume - maybe hardware went away? |
2023 | * Clear the "initialized" flag so we won't try | 2028 | * Clear the "initialized" flag so we won't try |
2024 | * to call the low level drivers shutdown method. | 2029 | * to call the low level drivers shutdown method. |
2025 | */ | 2030 | */ |
2026 | state->info->flags &= ~UIF_INITIALIZED; | ||
2027 | uart_shutdown(state); | 2031 | uart_shutdown(state); |
2028 | } | 2032 | } |
2033 | |||
2034 | state->info->flags &= ~UIF_SUSPENDED; | ||
2029 | } | 2035 | } |
2030 | 2036 | ||
2031 | mutex_unlock(&state->mutex); | 2037 | mutex_unlock(&state->mutex); |
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index cbf260bc225d..00f9ffd69489 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
@@ -80,23 +80,16 @@ module_param(buggy_uart, int, 0444); | |||
80 | 80 | ||
81 | /* Table of multi-port card ID's */ | 81 | /* Table of multi-port card ID's */ |
82 | 82 | ||
83 | struct multi_id { | 83 | struct serial_quirk { |
84 | u_short manfid; | 84 | unsigned int manfid; |
85 | u_short prodid; | 85 | unsigned int prodid; |
86 | int multi; /* 1 = multifunction, > 1 = # ports */ | 86 | int multi; /* 1 = multifunction, > 1 = # ports */ |
87 | void (*config)(struct pcmcia_device *); | ||
88 | void (*setup)(struct pcmcia_device *, struct uart_port *); | ||
89 | void (*wakeup)(struct pcmcia_device *); | ||
90 | int (*post)(struct pcmcia_device *); | ||
87 | }; | 91 | }; |
88 | 92 | ||
89 | static const struct multi_id multi_id[] = { | ||
90 | { MANFID_OMEGA, PRODID_OMEGA_QSP_100, 4 }, | ||
91 | { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 }, | ||
92 | { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 }, | ||
93 | { MANFID_QUATECH, PRODID_QUATECH_QUAD_RS232, 4 }, | ||
94 | { MANFID_SOCKET, PRODID_SOCKET_DUAL_RS232, 2 }, | ||
95 | { MANFID_INTEL, PRODID_INTEL_DUAL_RS232, 2 }, | ||
96 | { MANFID_NATINST, PRODID_NATINST_QUAD_RS232, 4 } | ||
97 | }; | ||
98 | #define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id)) | ||
99 | |||
100 | struct serial_info { | 93 | struct serial_info { |
101 | struct pcmcia_device *p_dev; | 94 | struct pcmcia_device *p_dev; |
102 | int ndev; | 95 | int ndev; |
@@ -107,6 +100,7 @@ struct serial_info { | |||
107 | int c950ctrl; | 100 | int c950ctrl; |
108 | dev_node_t node[4]; | 101 | dev_node_t node[4]; |
109 | int line[4]; | 102 | int line[4]; |
103 | const struct serial_quirk *quirk; | ||
110 | }; | 104 | }; |
111 | 105 | ||
112 | struct serial_cfg_mem { | 106 | struct serial_cfg_mem { |
@@ -115,37 +109,165 @@ struct serial_cfg_mem { | |||
115 | u_char buf[256]; | 109 | u_char buf[256]; |
116 | }; | 110 | }; |
117 | 111 | ||
112 | /* | ||
113 | * vers_1 5.0, "Brain Boxes", "2-Port RS232 card", "r6" | ||
114 | * manfid 0x0160, 0x0104 | ||
115 | * This card appears to have a 14.7456MHz clock. | ||
116 | */ | ||
117 | static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port) | ||
118 | { | ||
119 | port->uartclk = 14745600; | ||
120 | } | ||
118 | 121 | ||
119 | static int serial_config(struct pcmcia_device * link); | 122 | static int quirk_post_ibm(struct pcmcia_device *link) |
123 | { | ||
124 | conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; | ||
125 | int last_ret, last_fn; | ||
120 | 126 | ||
127 | last_ret = pcmcia_access_configuration_register(link, ®); | ||
128 | if (last_ret) { | ||
129 | last_fn = AccessConfigurationRegister; | ||
130 | goto cs_failed; | ||
131 | } | ||
132 | reg.Action = CS_WRITE; | ||
133 | reg.Value = reg.Value | 1; | ||
134 | last_ret = pcmcia_access_configuration_register(link, ®); | ||
135 | if (last_ret) { | ||
136 | last_fn = AccessConfigurationRegister; | ||
137 | goto cs_failed; | ||
138 | } | ||
139 | return 0; | ||
121 | 140 | ||
122 | static void wakeup_card(struct serial_info *info) | 141 | cs_failed: |
142 | cs_error(link, last_fn, last_ret); | ||
143 | return -ENODEV; | ||
144 | } | ||
145 | |||
146 | /* | ||
147 | * Nokia cards are not really multiport cards. Shouldn't this | ||
148 | * be handled by setting the quirk entry .multi = 0 | 1 ? | ||
149 | */ | ||
150 | static void quirk_config_nokia(struct pcmcia_device *link) | ||
123 | { | 151 | { |
124 | int ctrl = info->c950ctrl; | 152 | struct serial_info *info = link->priv; |
125 | 153 | ||
126 | if (info->manfid == MANFID_OXSEMI) { | 154 | if (info->multi > 1) |
127 | outb(12, ctrl + 1); | 155 | info->multi = 1; |
128 | } else if (info->manfid == MANFID_POSSIO && info->prodid == PRODID_POSSIO_GCC) { | 156 | } |
129 | /* request_region? oxsemi branch does no request_region too... */ | 157 | |
130 | /* This sequence is needed to properly initialize MC45 attached to OXCF950. | 158 | static void quirk_wakeup_oxsemi(struct pcmcia_device *link) |
131 | * I tried decreasing these msleep()s, but it worked properly (survived | 159 | { |
132 | * 1000 stop/start operations) with these timeouts (or bigger). */ | 160 | struct serial_info *info = link->priv; |
133 | outb(0xA, ctrl + 1); | 161 | |
134 | msleep(100); | 162 | outb(12, info->c950ctrl + 1); |
135 | outb(0xE, ctrl + 1); | 163 | } |
136 | msleep(300); | 164 | |
137 | outb(0xC, ctrl + 1); | 165 | /* request_region? oxsemi branch does no request_region too... */ |
138 | msleep(100); | 166 | /* |
139 | outb(0xE, ctrl + 1); | 167 | * This sequence is needed to properly initialize MC45 attached to OXCF950. |
140 | msleep(200); | 168 | * I tried decreasing these msleep()s, but it worked properly (survived |
141 | outb(0xF, ctrl + 1); | 169 | * 1000 stop/start operations) with these timeouts (or bigger). |
142 | msleep(100); | 170 | */ |
143 | outb(0xE, ctrl + 1); | 171 | static void quirk_wakeup_possio_gcc(struct pcmcia_device *link) |
144 | msleep(100); | 172 | { |
145 | outb(0xC, ctrl + 1); | 173 | struct serial_info *info = link->priv; |
174 | unsigned int ctrl = info->c950ctrl; | ||
175 | |||
176 | outb(0xA, ctrl + 1); | ||
177 | msleep(100); | ||
178 | outb(0xE, ctrl + 1); | ||
179 | msleep(300); | ||
180 | outb(0xC, ctrl + 1); | ||
181 | msleep(100); | ||
182 | outb(0xE, ctrl + 1); | ||
183 | msleep(200); | ||
184 | outb(0xF, ctrl + 1); | ||
185 | msleep(100); | ||
186 | outb(0xE, ctrl + 1); | ||
187 | msleep(100); | ||
188 | outb(0xC, ctrl + 1); | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * Socket Dual IO: this enables irq's for second port | ||
193 | */ | ||
194 | static void quirk_config_socket(struct pcmcia_device *link) | ||
195 | { | ||
196 | struct serial_info *info = link->priv; | ||
197 | |||
198 | if (info->multi) { | ||
199 | link->conf.Present |= PRESENT_EXT_STATUS; | ||
200 | link->conf.ExtStatus = ESR_REQ_ATTN_ENA; | ||
146 | } | 201 | } |
147 | } | 202 | } |
148 | 203 | ||
204 | static const struct serial_quirk quirks[] = { | ||
205 | { | ||
206 | .manfid = 0x0160, | ||
207 | .prodid = 0x0104, | ||
208 | .multi = -1, | ||
209 | .setup = quirk_setup_brainboxes_0104, | ||
210 | }, { | ||
211 | .manfid = MANFID_IBM, | ||
212 | .prodid = ~0, | ||
213 | .multi = -1, | ||
214 | .post = quirk_post_ibm, | ||
215 | }, { | ||
216 | .manfid = MANFID_INTEL, | ||
217 | .prodid = PRODID_INTEL_DUAL_RS232, | ||
218 | .multi = 2, | ||
219 | }, { | ||
220 | .manfid = MANFID_NATINST, | ||
221 | .prodid = PRODID_NATINST_QUAD_RS232, | ||
222 | .multi = 4, | ||
223 | }, { | ||
224 | .manfid = MANFID_NOKIA, | ||
225 | .prodid = ~0, | ||
226 | .multi = -1, | ||
227 | .config = quirk_config_nokia, | ||
228 | }, { | ||
229 | .manfid = MANFID_OMEGA, | ||
230 | .prodid = PRODID_OMEGA_QSP_100, | ||
231 | .multi = 4, | ||
232 | }, { | ||
233 | .manfid = MANFID_OXSEMI, | ||
234 | .prodid = ~0, | ||
235 | .multi = -1, | ||
236 | .wakeup = quirk_wakeup_oxsemi, | ||
237 | }, { | ||
238 | .manfid = MANFID_POSSIO, | ||
239 | .prodid = PRODID_POSSIO_GCC, | ||
240 | .multi = -1, | ||
241 | .wakeup = quirk_wakeup_possio_gcc, | ||
242 | }, { | ||
243 | .manfid = MANFID_QUATECH, | ||
244 | .prodid = PRODID_QUATECH_DUAL_RS232, | ||
245 | .multi = 2, | ||
246 | }, { | ||
247 | .manfid = MANFID_QUATECH, | ||
248 | .prodid = PRODID_QUATECH_DUAL_RS232_D1, | ||
249 | .multi = 2, | ||
250 | }, { | ||
251 | .manfid = MANFID_QUATECH, | ||
252 | .prodid = PRODID_QUATECH_QUAD_RS232, | ||
253 | .multi = 4, | ||
254 | }, { | ||
255 | .manfid = MANFID_SOCKET, | ||
256 | .prodid = PRODID_SOCKET_DUAL_RS232, | ||
257 | .multi = 2, | ||
258 | .config = quirk_config_socket, | ||
259 | }, { | ||
260 | .manfid = MANFID_SOCKET, | ||
261 | .prodid = ~0, | ||
262 | .multi = -1, | ||
263 | .config = quirk_config_socket, | ||
264 | } | ||
265 | }; | ||
266 | |||
267 | |||
268 | static int serial_config(struct pcmcia_device * link); | ||
269 | |||
270 | |||
149 | /*====================================================================== | 271 | /*====================================================================== |
150 | 272 | ||
151 | After a card is removed, serial_remove() will unregister | 273 | After a card is removed, serial_remove() will unregister |
@@ -185,14 +307,14 @@ static int serial_suspend(struct pcmcia_device *link) | |||
185 | 307 | ||
186 | static int serial_resume(struct pcmcia_device *link) | 308 | static int serial_resume(struct pcmcia_device *link) |
187 | { | 309 | { |
188 | if (pcmcia_dev_present(link)) { | 310 | struct serial_info *info = link->priv; |
189 | struct serial_info *info = link->priv; | 311 | int i; |
190 | int i; | ||
191 | 312 | ||
192 | for (i = 0; i < info->ndev; i++) | 313 | for (i = 0; i < info->ndev; i++) |
193 | serial8250_resume_port(info->line[i]); | 314 | serial8250_resume_port(info->line[i]); |
194 | wakeup_card(info); | 315 | |
195 | } | 316 | if (info->quirk && info->quirk->wakeup) |
317 | info->quirk->wakeup(link); | ||
196 | 318 | ||
197 | return 0; | 319 | return 0; |
198 | } | 320 | } |
@@ -278,6 +400,10 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, | |||
278 | port.dev = &handle_to_dev(handle); | 400 | port.dev = &handle_to_dev(handle); |
279 | if (buggy_uart) | 401 | if (buggy_uart) |
280 | port.flags |= UPF_BUGGY_UART; | 402 | port.flags |= UPF_BUGGY_UART; |
403 | |||
404 | if (info->quirk && info->quirk->setup) | ||
405 | info->quirk->setup(handle, &port); | ||
406 | |||
281 | line = serial8250_register_port(&port); | 407 | line = serial8250_register_port(&port); |
282 | if (line < 0) { | 408 | if (line < 0) { |
283 | printk(KERN_NOTICE "serial_cs: serial8250_register_port() at " | 409 | printk(KERN_NOTICE "serial_cs: serial8250_register_port() at " |
@@ -433,6 +559,13 @@ next_entry: | |||
433 | } | 559 | } |
434 | if (info->multi && (info->manfid == MANFID_3COM)) | 560 | if (info->multi && (info->manfid == MANFID_3COM)) |
435 | link->conf.ConfigIndex &= ~(0x08); | 561 | link->conf.ConfigIndex &= ~(0x08); |
562 | |||
563 | /* | ||
564 | * Apply any configuration quirks. | ||
565 | */ | ||
566 | if (info->quirk && info->quirk->config) | ||
567 | info->quirk->config(link); | ||
568 | |||
436 | i = pcmcia_request_configuration(link, &link->conf); | 569 | i = pcmcia_request_configuration(link, &link->conf); |
437 | if (i != CS_SUCCESS) { | 570 | if (i != CS_SUCCESS) { |
438 | cs_error(link, RequestConfiguration, i); | 571 | cs_error(link, RequestConfiguration, i); |
@@ -521,11 +654,13 @@ static int multi_config(struct pcmcia_device * link) | |||
521 | cs_error(link, RequestIRQ, i); | 654 | cs_error(link, RequestIRQ, i); |
522 | link->irq.AssignedIRQ = 0; | 655 | link->irq.AssignedIRQ = 0; |
523 | } | 656 | } |
524 | /* Socket Dual IO: this enables irq's for second port */ | 657 | |
525 | if (info->multi && (info->manfid == MANFID_SOCKET)) { | 658 | /* |
526 | link->conf.Present |= PRESENT_EXT_STATUS; | 659 | * Apply any configuration quirks. |
527 | link->conf.ExtStatus = ESR_REQ_ATTN_ENA; | 660 | */ |
528 | } | 661 | if (info->quirk && info->quirk->config) |
662 | info->quirk->config(link); | ||
663 | |||
529 | i = pcmcia_request_configuration(link, &link->conf); | 664 | i = pcmcia_request_configuration(link, &link->conf); |
530 | if (i != CS_SUCCESS) { | 665 | if (i != CS_SUCCESS) { |
531 | cs_error(link, RequestConfiguration, i); | 666 | cs_error(link, RequestConfiguration, i); |
@@ -550,17 +685,19 @@ static int multi_config(struct pcmcia_device * link) | |||
550 | link->irq.AssignedIRQ); | 685 | link->irq.AssignedIRQ); |
551 | } | 686 | } |
552 | info->c950ctrl = base2; | 687 | info->c950ctrl = base2; |
553 | wakeup_card(info); | 688 | |
689 | /* | ||
690 | * FIXME: We really should wake up the port prior to | ||
691 | * handing it over to the serial layer. | ||
692 | */ | ||
693 | if (info->quirk && info->quirk->wakeup) | ||
694 | info->quirk->wakeup(link); | ||
695 | |||
554 | rc = 0; | 696 | rc = 0; |
555 | goto free_cfg_mem; | 697 | goto free_cfg_mem; |
556 | } | 698 | } |
557 | 699 | ||
558 | setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); | 700 | setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); |
559 | /* The Nokia cards are not really multiport cards */ | ||
560 | if (info->manfid == MANFID_NOKIA) { | ||
561 | rc = 0; | ||
562 | goto free_cfg_mem; | ||
563 | } | ||
564 | for (i = 0; i < info->multi - 1; i++) | 701 | for (i = 0; i < info->multi - 1; i++) |
565 | setup_serial(link, info, base2 + (8 * i), | 702 | setup_serial(link, info, base2 + (8 * i), |
566 | link->irq.AssignedIRQ); | 703 | link->irq.AssignedIRQ); |
@@ -622,13 +759,16 @@ static int serial_config(struct pcmcia_device * link) | |||
622 | tuple->DesiredTuple = CISTPL_MANFID; | 759 | tuple->DesiredTuple = CISTPL_MANFID; |
623 | if (first_tuple(link, tuple, parse) == CS_SUCCESS) { | 760 | if (first_tuple(link, tuple, parse) == CS_SUCCESS) { |
624 | info->manfid = parse->manfid.manf; | 761 | info->manfid = parse->manfid.manf; |
625 | info->prodid = le16_to_cpu(buf[1]); | 762 | info->prodid = parse->manfid.card; |
626 | for (i = 0; i < MULTI_COUNT; i++) | 763 | |
627 | if ((info->manfid == multi_id[i].manfid) && | 764 | for (i = 0; i < ARRAY_SIZE(quirks); i++) |
628 | (parse->manfid.card == multi_id[i].prodid)) | 765 | if ((quirks[i].manfid == ~0 || |
766 | quirks[i].manfid == info->manfid) && | ||
767 | (quirks[i].prodid == ~0 || | ||
768 | quirks[i].prodid == info->prodid)) { | ||
769 | info->quirk = &quirks[i]; | ||
629 | break; | 770 | break; |
630 | if (i < MULTI_COUNT) | 771 | } |
631 | info->multi = multi_id[i].multi; | ||
632 | } | 772 | } |
633 | 773 | ||
634 | /* Another check for dual-serial cards: look for either serial or | 774 | /* Another check for dual-serial cards: look for either serial or |
@@ -648,6 +788,12 @@ static int serial_config(struct pcmcia_device * link) | |||
648 | } | 788 | } |
649 | } | 789 | } |
650 | 790 | ||
791 | /* | ||
792 | * Apply any multi-port quirk. | ||
793 | */ | ||
794 | if (info->quirk && info->quirk->multi != -1) | ||
795 | info->multi = info->quirk->multi; | ||
796 | |||
651 | if (info->multi > 1) | 797 | if (info->multi > 1) |
652 | multi_config(link); | 798 | multi_config(link); |
653 | else | 799 | else |
@@ -656,21 +802,13 @@ static int serial_config(struct pcmcia_device * link) | |||
656 | if (info->ndev == 0) | 802 | if (info->ndev == 0) |
657 | goto failed; | 803 | goto failed; |
658 | 804 | ||
659 | if (info->manfid == MANFID_IBM) { | 805 | /* |
660 | conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; | 806 | * Apply any post-init quirk. FIXME: This should really happen |
661 | last_ret = pcmcia_access_configuration_register(link, ®); | 807 | * before we register the port, since it might already be in use. |
662 | if (last_ret) { | 808 | */ |
663 | last_fn = AccessConfigurationRegister; | 809 | if (info->quirk && info->quirk->post) |
664 | goto cs_failed; | 810 | if (info->quirk->post(link)) |
665 | } | 811 | goto failed; |
666 | reg.Action = CS_WRITE; | ||
667 | reg.Value = reg.Value | 1; | ||
668 | last_ret = pcmcia_access_configuration_register(link, ®); | ||
669 | if (last_ret) { | ||
670 | last_fn = AccessConfigurationRegister; | ||
671 | goto cs_failed; | ||
672 | } | ||
673 | } | ||
674 | 812 | ||
675 | link->dev_node = &info->node[0]; | 813 | link->dev_node = &info->node[0]; |
676 | kfree(cfg_mem); | 814 | kfree(cfg_mem); |
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index b361669f85a1..ebd8d2bb17fd 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c | |||
@@ -990,7 +990,6 @@ int __init early_serial_txx9_setup(struct uart_port *port) | |||
990 | /** | 990 | /** |
991 | * serial_txx9_suspend_port - suspend one serial port | 991 | * serial_txx9_suspend_port - suspend one serial port |
992 | * @line: serial line number | 992 | * @line: serial line number |
993 | * @level: the level of port suspension, as per uart_suspend_port | ||
994 | * | 993 | * |
995 | * Suspend one serial port. | 994 | * Suspend one serial port. |
996 | */ | 995 | */ |
@@ -1002,7 +1001,6 @@ static void serial_txx9_suspend_port(int line) | |||
1002 | /** | 1001 | /** |
1003 | * serial_txx9_resume_port - resume one serial port | 1002 | * serial_txx9_resume_port - resume one serial port |
1004 | * @line: serial line number | 1003 | * @line: serial line number |
1005 | * @level: the level of port resumption, as per uart_resume_port | ||
1006 | * | 1004 | * |
1007 | * Resume one serial port. | 1005 | * Resume one serial port. |
1008 | */ | 1006 | */ |