📄 8250.c
字号:
serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); mode = serial_inp(up, UART_RSA_MSR); result = !(mode & UART_RSA_MSR_FIFO); } if (result) up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16; spin_unlock_irq(&up->port.lock); }}#endif /* CONFIG_SERIAL_8250_RSA *//* * This is a quickie test to see how big the FIFO is. * It doesn't work at all the time, more's the pity. */static int size_fifo(struct uart_8250_port *up){ unsigned char old_fcr, old_mcr, old_lcr; unsigned short old_dl; int count; old_lcr = serial_inp(up, UART_LCR); serial_outp(up, UART_LCR, 0); old_fcr = serial_inp(up, UART_FCR); old_mcr = serial_inp(up, UART_MCR); serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); serial_outp(up, UART_MCR, UART_MCR_LOOP); serial_outp(up, UART_LCR, UART_LCR_DLAB); old_dl = serial_dl_read(up); serial_dl_write(up, 0x0001); serial_outp(up, UART_LCR, 0x03); for (count = 0; count < 256; count++) serial_outp(up, UART_TX, count); mdelay(20);/* FIXME - schedule_timeout */ for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) && (count < 256); count++) serial_inp(up, UART_RX); serial_outp(up, UART_FCR, old_fcr); serial_outp(up, UART_MCR, old_mcr); serial_outp(up, UART_LCR, UART_LCR_DLAB); serial_dl_write(up, old_dl); serial_outp(up, UART_LCR, old_lcr); 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. * When this function is called we know it is at least a StarTech * 16650 V2, but it might be one of several StarTech UARTs, or one of * its clones. (We treat the broken original StarTech 16650 V1 as a * 16550, and why not? Startech doesn't seem to even acknowledge its * existence.) * * What evil have men's minds wrought... */static void autoconfig_has_efr(struct uart_8250_port *up){ unsigned int id1, id2, id3, rev; /* * Everything with an EFR has SLEEP */ up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP; /* * First we check to see if it's an Oxford Semiconductor UART. * * If we have to do this here because some non-National * Semiconductor clone chips lock up if you try writing to the * LSR register (which serial_icr_read does) */ /* * Check for Oxford Semiconductor 16C950. * * EFR [4] must be set else this test fails. * * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca) * claims that it's needed for 952 dual UART's (which are not * recommended for new designs). */ up->acr = 0; serial_out(up, UART_LCR, 0xBF); serial_out(up, UART_EFR, UART_EFR_ECB); serial_out(up, UART_LCR, 0x00); id1 = serial_icr_read(up, UART_ID1); id2 = serial_icr_read(up, UART_ID2); id3 = serial_icr_read(up, UART_ID3); rev = serial_icr_read(up, UART_REV); DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev); if (id1 == 0x16 && id2 == 0xC9 && (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) { up->port.type = PORT_16C950; /* * Enable work around for the Oxford Semiconductor 952 rev B * chip which causes it to seriously miscalculate baud rates * when DLL is 0. */ if (id3 == 0x52 && rev == 0x01) up->bugs |= UART_BUG_QUOT; return; } /* * We check for a XR16C850 by setting DLL and DLM to 0, and then * reading back DLL and DLM. The chip type depends on the DLM * value read back: * 0x10 - XR16C850 and the DLL contains the chip revision. * 0x12 - XR16C2850. * 0x14 - XR16C854. */ id1 = autoconfig_read_divisor_id(up); DEBUG_AUTOCONF("850id=%04x ", id1); id2 = id1 >> 8; if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) { up->port.type = PORT_16850; return; } /* * It wasn't an XR16C850. * * We distinguish between the '654 and the '650 by counting * how many bytes are in the FIFO. I'm using this for now, * since that's the technique that was sent to me in the * serial driver update, but I'm not convinced this works. * I've had problems doing this in the past. -TYT */ if (size_fifo(up) == 64) up->port.type = PORT_16654; else up->port.type = PORT_16650V2;}/* * We detected a chip without a FIFO. Only two fall into * this category - the original 8250 and the 16450. The * 16450 has a scratch register (accessible with LCR=0) */static void autoconfig_8250(struct uart_8250_port *up){ unsigned char scratch, status1, status2; up->port.type = PORT_8250; scratch = serial_in(up, UART_SCR); serial_outp(up, UART_SCR, 0xa5); status1 = serial_in(up, UART_SCR); serial_outp(up, UART_SCR, 0x5a); status2 = serial_in(up, UART_SCR); serial_outp(up, UART_SCR, scratch); if (status1 == 0xa5 && status2 == 0x5a) 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 * EFR is located in the same register position as the IIR and * we know the top two bits of the IIR are currently set. The * EFR should contain zero. Try to read the EFR. */static void autoconfig_16550a(struct uart_8250_port *up){ unsigned char status1, status2; unsigned int iersave; up->port.type = PORT_16550A; up->capabilities |= UART_CAP_FIFO; /* * Check for presence of the EFR when DLAB is set. * Only ST16C650V1 UARTs pass this test. */ serial_outp(up, UART_LCR, UART_LCR_DLAB); if (serial_in(up, UART_EFR) == 0) { serial_outp(up, UART_EFR, 0xA8); if (serial_in(up, UART_EFR) != 0) { DEBUG_AUTOCONF("EFRv1 "); up->port.type = PORT_16650; up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP; } else { DEBUG_AUTOCONF("Motorola 8xxx DUART "); } serial_outp(up, UART_EFR, 0); return; } /* * Maybe it requires 0xbf to be written to the LCR. * (other ST16C650V2 UARTs, TI16C752A, etc) */ serial_outp(up, UART_LCR, 0xBF); if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) { DEBUG_AUTOCONF("EFRv2 "); autoconfig_has_efr(up); return; } /* * Check for a National Semiconductor SuperIO chip. * Attempt to switch to bank 2, read the value of the LOOP bit * from EXCR1. Switch back to bank 0, change it in MCR. Then * switch back to bank 2, read it from EXCR1 again and check * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2 */ serial_outp(up, UART_LCR, 0); status1 = serial_in(up, UART_MCR); serial_outp(up, UART_LCR, 0xE0); status2 = serial_in(up, 0x02); /* EXCR1 */ if (!((status2 ^ status1) & UART_MCR_LOOP)) { serial_outp(up, UART_LCR, 0); serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP); serial_outp(up, UART_LCR, 0xE0); status2 = serial_in(up, 0x02); /* EXCR1 */ serial_outp(up, UART_LCR, 0); serial_outp(up, UART_MCR, status1); if ((status2 ^ status1) & UART_MCR_LOOP) { unsigned short quot; serial_outp(up, UART_LCR, 0xE0); quot = serial_dl_read(up); quot <<= 3; status1 = serial_in(up, 0x04); /* EXCR1 */ status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ serial_outp(up, 0x04, status1); serial_dl_write(up, quot); serial_outp(up, UART_LCR, 0); up->port.uartclk = 921600*16; up->port.type = PORT_NS16550A; up->capabilities |= UART_NATSEMI; return; } } /* * No EFR. Try to detect a TI16750, which only sets bit 5 of * the IIR when 64 byte FIFO mode is enabled when DLAB is set. * Try setting it with and without DLAB set. Cheap clones * set bit 5 without DLAB set. */ serial_outp(up, UART_LCR, 0); serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); status1 = serial_in(up, UART_IIR) >> 5; serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); serial_outp(up, UART_LCR, UART_LCR_DLAB); serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); status2 = serial_in(up, UART_IIR) >> 5; serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); serial_outp(up, UART_LCR, 0); DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2); if (status1 == 6 && status2 == 7) { up->port.type = PORT_16750; up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP; return; } /* * Try writing and reading the UART_IER_UUE bit (b6). * If it works, this is probably one of the Xscale platform's * internal UARTs. * We're going to explicitly set the UUE bit to 0 before * trying to write and read a 1 just to make sure it's not * already a 1 and maybe locked there before we even start start. */ iersave = serial_in(up, UART_IER); serial_outp(up, UART_IER, iersave & ~UART_IER_UUE); if (!(serial_in(up, UART_IER) & UART_IER_UUE)) { /* * OK it's in a known zero state, try writing and reading * without disturbing the current state of the other bits. */ serial_outp(up, UART_IER, iersave | UART_IER_UUE); if (serial_in(up, UART_IER) & UART_IER_UUE) { /* * It's an Xscale. * We'll leave the UART_IER_UUE bit set to 1 (enabled). */ DEBUG_AUTOCONF("Xscale "); up->port.type = PORT_XSCALE; up->capabilities |= UART_CAP_UUE; return; } } else { /* * If we got here we couldn't force the IER_UUE bit to 0. * Log it and continue. */ DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); } serial_outp(up, UART_IER, iersave);}/* * This routine is called by rs_init() to initialize a specific serial * port. It determines what type of UART chip this serial port is * using: 8250, 16450, 16550, 16550A. The important question is * whether or not this UART is a 16550A or not, since this will * determine whether or not we can use its FIFO features or not. */static void autoconfig(struct uart_8250_port *up, unsigned int probeflags){ unsigned char status1, scratch, scratch2, scratch3; unsigned char save_lcr, save_mcr; unsigned long flags; if (!up->port.iobase && !up->port.mapbase && !up->port.membase) return; DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%p): ", up->port.line, up->port.iobase, up->port.membase); /* * We really do need global IRQs disabled here - we're going to * be frobbing the chips IRQ enable register to see if it exists. */ spin_lock_irqsave(&up->port.lock, flags);// save_flags(flags); cli(); up->capabilities = 0; up->bugs = 0; if (!(up->port.flags & UPF_BUGGY_UART)) { /* * Do a simple existence test first; if we fail this, * there's no point trying anything else. * * 0x80 is used as a nonsense port to prevent against * false positives due to ISA bus float. The * assumption is that 0x80 is a non-existent port; * which should be safe since include/asm/io.h also * makes this assumption. * * Note: this is safe as long as MCR bit 4 is clear * and the device is in "PC" mode. */ scratch = serial_inp(up, UART_IER); serial_outp(up, UART_IER, 0);#ifdef __i386__ outb(0xff, 0x080);#endif scratch2 = serial_inp(up, UART_IER); serial_outp(up, UART_IER, 0x0F);#ifdef __i386__ outb(0, 0x080);#endif scratch3 = serial_inp(up, UART_IER); serial_outp(up, UART_IER, scratch); if (scratch2 != 0 || scratch3 != 0x0F) { /* * We failed; there's nothing here */ DEBUG_AUTOCONF("IER test failed (%02x, %02x) ", scratch2, scratch3); goto out; } } save_mcr = serial_in(up, UART_MCR); save_lcr = serial_in(up, UART_LCR); /* * Check to see if a UART is really there. Certain broken * internal modems based on the Rockwell chipset fail this * test, because they apparently don't implement the loopback * test mode. So this test is skipped on the COM 1 through * COM 4 ports. This *should* be safe, since no board * manufacturer would be stupid enough to design a board * that conflicts with COM 1-4 --- we hope! */ if (!(up->port.flags & UPF_SKIP_TEST)) { serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A); status1 = serial_inp(up, UART_MSR) & 0xF0; serial_outp(up, UART_MCR, save_mcr); if (status1 != 0x90) { DEBUG_AUTOCONF("LOOP test failed (%02x) ", status1); goto out; } } /* * We're pretty sure there's a port here. Lets find out what * type of port it is. The IIR top two bits allows us to find * out if it's 8250 or 16450, 16550, 16550A or later. This * determines what we test for next. * * We also initialise the EFR (if any) to zero for later. The * EFR occupies the same register location as the FCR and IIR. */ serial_outp(up, UART_LCR, 0xBF); serial_outp(up, UART_EFR, 0); serial_outp(up, UART_LCR, 0); serial_outp(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); break; case 1: up->port.type = PORT_UNKNOWN; break; case 2: up->port.type = PORT_16550; break; case 3: autoconfig_16550a(up); break; }#ifdef CONFIG_SERIAL_8250_RSA /* * Only probe for RSA ports if we got the region. */ if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) { int i; for (i = 0 ; i < probe_rsa_count; ++i) { if (probe_rsa[i] == up->port.iobase && __enable_rsa(up)) { up->port.type = PORT_RSA; break; } } }#endif#ifdef CONFIG_SERIAL_8250_AU1X00 /* if access method is AU, it is a 16550 with a quirk */ if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU) up->bugs |= UART_BUG_NOMSR;#endif serial_outp(up, UART_LCR, save_lcr); if (up->capabilities != uart_config[up->port.type].flags) { printk(KERN_WARNING "ttyS%d: detected caps %08x should be %08x\n", up->port.line, up->capabilities, uart_config[up->port.type].flags); } up->port.fifosize = uart_config[up->port.type].fifo_size; up->capabilities = uart_config[up->port.type].flags; up->tx_loadsz = uart_config[up->port.type].tx_loadsz; if (up->port.type == PORT_UNKNOWN) goto out; /* * Reset the UART. */#ifdef CONFIG_SERIAL_8250_RSA if (up->port.type == PORT_RSA) serial_outp(up, UART_RSA_FRR, 0);#endif serial_outp(up, UART_MCR, save_mcr); serial8250_clear_fifos(up); (void)serial_in(up, UART_RX); if (up->capabilities & UART_CAP_UUE) serial_outp(up, UART_IER, UART_IER_UUE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -