Commit 9dfd7048 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk/linux-2.6-serial

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 2fb99976 25f34d0f
...@@ -450,9 +450,11 @@ static void disable_rsa(struct uart_8250_port *up) ...@@ -450,9 +450,11 @@ static void disable_rsa(struct uart_8250_port *up)
*/ */
static int size_fifo(struct uart_8250_port *up) static int size_fifo(struct uart_8250_port *up)
{ {
unsigned char old_fcr, old_mcr, old_dll, old_dlm; unsigned char old_fcr, old_mcr, old_dll, old_dlm, old_lcr;
int count; int count;
old_lcr = serial_inp(up, UART_LCR);
serial_outp(up, UART_LCR, 0);
old_fcr = serial_inp(up, UART_FCR); old_fcr = serial_inp(up, UART_FCR);
old_mcr = serial_inp(up, UART_MCR); old_mcr = serial_inp(up, UART_MCR);
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
...@@ -475,10 +477,39 @@ static int size_fifo(struct uart_8250_port *up) ...@@ -475,10 +477,39 @@ static int size_fifo(struct uart_8250_port *up)
serial_outp(up, UART_LCR, UART_LCR_DLAB); serial_outp(up, UART_LCR, UART_LCR_DLAB);
serial_outp(up, UART_DLL, old_dll); serial_outp(up, UART_DLL, old_dll);
serial_outp(up, UART_DLM, old_dlm); serial_outp(up, UART_DLM, old_dlm);
serial_outp(up, UART_LCR, old_lcr);
return count; return count;
} }
/*
* Read UART ID using the divisor method - set DLL and DLM to zero
* and the revision will be in DLL and device type in DLM. We
* preserve the device state across this.
*/
static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
{
unsigned char old_dll, old_dlm, old_lcr;
unsigned int id;
old_lcr = serial_inp(p, UART_LCR);
serial_outp(p, UART_LCR, UART_LCR_DLAB);
old_dll = serial_inp(p, UART_DLL);
old_dlm = serial_inp(p, UART_DLM);
serial_outp(p, UART_DLL, 0);
serial_outp(p, UART_DLM, 0);
id = serial_inp(p, UART_DLL) | serial_inp(p, UART_DLM) << 8;
serial_outp(p, UART_DLL, old_dll);
serial_outp(p, UART_DLM, old_dlm);
serial_outp(p, UART_LCR, old_lcr);
return id;
}
/* /*
* This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's. * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
* When this function is called we know it is at least a StarTech * When this function is called we know it is at least a StarTech
...@@ -491,7 +522,7 @@ static int size_fifo(struct uart_8250_port *up) ...@@ -491,7 +522,7 @@ static int size_fifo(struct uart_8250_port *up)
*/ */
static void autoconfig_has_efr(struct uart_8250_port *up) static void autoconfig_has_efr(struct uart_8250_port *up)
{ {
unsigned char id1, id2, id3, rev, saved_dll, saved_dlm; unsigned int id1, id2, id3, rev;
/* /*
* Everything with an EFR has SLEEP * Everything with an EFR has SLEEP
...@@ -541,21 +572,13 @@ static void autoconfig_has_efr(struct uart_8250_port *up) ...@@ -541,21 +572,13 @@ static void autoconfig_has_efr(struct uart_8250_port *up)
* 0x12 - XR16C2850. * 0x12 - XR16C2850.
* 0x14 - XR16C854. * 0x14 - XR16C854.
*/ */
serial_outp(up, UART_LCR, UART_LCR_DLAB); id1 = autoconfig_read_divisor_id(up);
saved_dll = serial_inp(up, UART_DLL); DEBUG_AUTOCONF("850id=%04x ", id1);
saved_dlm = serial_inp(up, UART_DLM);
serial_outp(up, UART_DLL, 0); id2 = id1 >> 8;
serial_outp(up, UART_DLM, 0); if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
id2 = serial_inp(up, UART_DLL); if (id2 == 0x10)
id1 = serial_inp(up, UART_DLM); up->rev = id1 & 255;
serial_outp(up, UART_DLL, saved_dll);
serial_outp(up, UART_DLM, saved_dlm);
DEBUG_AUTOCONF("850id=%02x:%02x ", id1, id2);
if (id1 == 0x10 || id1 == 0x12 || id1 == 0x14) {
if (id1 == 0x10)
up->rev = id2;
up->port.type = PORT_16850; up->port.type = PORT_16850;
return; return;
} }
...@@ -597,6 +620,19 @@ static void autoconfig_8250(struct uart_8250_port *up) ...@@ -597,6 +620,19 @@ static void autoconfig_8250(struct uart_8250_port *up)
up->port.type = PORT_16450; up->port.type = PORT_16450;
} }
static int broken_efr(struct uart_8250_port *up)
{
/*
* Exar ST16C2550 "A2" devices incorrectly detect as
* having an EFR, and report an ID of 0x0201. See
* http://www.exar.com/info.php?pdf=dan180_oct2004.pdf
*/
if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
return 1;
return 0;
}
/* /*
* We know that the chip has FIFOs. Does it have an EFR? The * We know that the chip has FIFOs. Does it have an EFR? The
* EFR is located in the same register position as the IIR and * EFR is located in the same register position as the IIR and
...@@ -633,7 +669,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) ...@@ -633,7 +669,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
* (other ST16C650V2 UARTs, TI16C752A, etc) * (other ST16C650V2 UARTs, TI16C752A, etc)
*/ */
serial_outp(up, UART_LCR, 0xBF); serial_outp(up, UART_LCR, 0xBF);
if (serial_in(up, UART_EFR) == 0) { if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
DEBUG_AUTOCONF("EFRv2 "); DEBUG_AUTOCONF("EFRv2 ");
autoconfig_has_efr(up); autoconfig_has_efr(up);
return; return;
......
...@@ -2211,6 +2211,13 @@ static struct pci_device_id serial_pci_tbl[] = { ...@@ -2211,6 +2211,13 @@ static struct pci_device_id serial_pci_tbl[] = {
0, 0,
0, pbn_exar_XR17C158 }, 0, pbn_exar_XR17C158 },
/*
* Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
*/
{ PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_1_115200 },
/* /*
* These entries match devices with class COMMUNICATION_SERIAL, * These entries match devices with class COMMUNICATION_SERIAL,
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
...@@ -2241,7 +2248,7 @@ static struct pci_driver serial_pci_driver = { ...@@ -2241,7 +2248,7 @@ static struct pci_driver serial_pci_driver = {
static int __init serial8250_pci_init(void) static int __init serial8250_pci_init(void)
{ {
return pci_module_init(&serial_pci_driver); return pci_register_driver(&serial_pci_driver);
} }
static void __exit serial8250_pci_exit(void) static void __exit serial8250_pci_exit(void)
......
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
serial-8250-y := serial-8250-y :=
serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o
serial-8250-$(CONFIG_PNP) += 8250_pnp.o
serial-8250-$(CONFIG_GSC) += 8250_gsc.o serial-8250-$(CONFIG_GSC) += 8250_gsc.o
serial-8250-$(CONFIG_PCI) += 8250_pci.o serial-8250-$(CONFIG_PCI) += 8250_pci.o
serial-8250-$(CONFIG_PNP) += 8250_pnp.o
serial-8250-$(CONFIG_HP300) += 8250_hp300.o serial-8250-$(CONFIG_HP300) += 8250_hp300.o
obj-$(CONFIG_SERIAL_CORE) += serial_core.o obj-$(CONFIG_SERIAL_CORE) += serial_core.o
......
...@@ -1972,6 +1972,9 @@ ...@@ -1972,6 +1972,9 @@
#define PCI_DEVICE_ID_BCM4401 0x4401 #define PCI_DEVICE_ID_BCM4401 0x4401
#define PCI_DEVICE_ID_BCM4401B0 0x4402 #define PCI_DEVICE_ID_BCM4401B0 0x4402
#define PCI_VENDOR_ID_TOPIC 0x151f
#define PCI_DEVICE_ID_TOPIC_TP560 0x0000
#define PCI_VENDOR_ID_ENE 0x1524 #define PCI_VENDOR_ID_ENE 0x1524
#define PCI_DEVICE_ID_ENE_1211 0x1211 #define PCI_DEVICE_ID_ENE_1211 0x1211
#define PCI_DEVICE_ID_ENE_1225 0x1225 #define PCI_DEVICE_ID_ENE_1225 0x1225
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment