drivers/tty/serial/8250/8250_port.c
Source file repositories/reference/linux-study-clean/drivers/tty/serial/8250/8250_port.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/tty/serial/8250/8250_port.c- Extension
.c- Size
- 91781 bytes
- Lines
- 3445
- Domain
- Driver Families
- Bucket
- drivers/tty
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/moduleparam.hlinux/ioport.hlinux/init.hlinux/irq.hlinux/console.hlinux/gpio/consumer.hlinux/lockdep.hlinux/sysrq.hlinux/delay.hlinux/platform_device.hlinux/tty.hlinux/ratelimit.hlinux/tty_flip.hlinux/serial.hlinux/serial_8250.hlinux/nmi.hlinux/mutex.hlinux/slab.hlinux/uaccess.hlinux/pm_runtime.hlinux/ktime.hasm/io.hasm/irq.h8250.h
Detected Declarations
function default_serial_dl_readfunction default_serial_dl_writefunction hub6_serial_infunction hub6_serial_outfunction mem_serial_infunction mem_serial_outfunction mem16_serial_outfunction mem16_serial_infunction mem32_serial_outfunction mem32_serial_infunction mem32be_serial_outfunction mem32be_serial_infunction io_serial_infunction io_serial_outfunction no_serial_infunction no_serial_outfunction set_io_from_upiofunction serial_port_out_syncfunction serial8250_clear_fifosfunction serial8250_clear_and_reinit_fifosfunction serial8250_rpm_getfunction serial8250_rpm_putfunction serial8250_em485_initfunction serial8250_em485_destroyfunction serial8250_em485_configfunction enable_runtime_pm_txfunction serial8250_rpm_put_txfunction serial8250_set_sleepfunction serial8250_clear_interruptsfunction serial8250_clear_IERfunction size_fifofunction autoconfig_read_divisor_idfunction autoconfig_has_efrfunction registerfunction broken_efrfunction autoconfig_16550afunction rs_initfunction autoconfig_irqfunction serial8250_stop_rxfunction serial8250_em485_stop_txfunction serial8250_em485_handle_stop_txfunction start_hrtimer_msfunction __stop_tx_rs485function rs485_stop_txfunction __stop_txfunction __stop_tx_rs485function serial8250_stop_txfunction __start_tx
Annotated Snippet
if (serial_in(up, UART_EFR) != 0) {
up->port.type = PORT_16650;
up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
} else {
serial_out(up, UART_LCR, 0);
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
UART_FCR7_64BYTE);
status1 = serial_in(up, UART_IIR) & UART_IIR_FIFO_ENABLED_16750;
serial_out(up, UART_FCR, 0);
serial_out(up, UART_LCR, 0);
if (status1 == UART_IIR_FIFO_ENABLED_16750)
up->port.type = PORT_16550A_FSL64;
}
serial_out(up, UART_EFR, 0);
return;
}
/*
* Maybe it requires 0xbf to be written to the LCR.
* (other ST16C650V2 UARTs, TI16C752A, etc)
*/
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
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_out(up, UART_LCR, 0);
status1 = serial8250_in_MCR(up);
serial_out(up, UART_LCR, 0xE0);
status2 = serial_in(up, 0x02); /* EXCR1 */
if (!((status2 ^ status1) & UART_MCR_LOOP)) {
serial_out(up, UART_LCR, 0);
serial8250_out_MCR(up, status1 ^ UART_MCR_LOOP);
serial_out(up, UART_LCR, 0xE0);
status2 = serial_in(up, 0x02); /* EXCR1 */
serial_out(up, UART_LCR, 0);
serial8250_out_MCR(up, status1);
if ((status2 ^ status1) & UART_MCR_LOOP) {
unsigned short quot;
serial_out(up, UART_LCR, 0xE0);
quot = serial_dl_read(up);
quot <<= 3;
if (ns16550a_goto_highspeed(up))
serial_dl_write(up, quot);
serial_out(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_out(up, UART_LCR, 0);
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
status1 = serial_in(up, UART_IIR) & UART_IIR_FIFO_ENABLED_16750;
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
status2 = serial_in(up, UART_IIR) & UART_IIR_FIFO_ENABLED_16750;
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_out(up, UART_LCR, 0);
if (status1 == UART_IIR_FIFO_ENABLED_16550A &&
status2 == UART_IIR_FIFO_ENABLED_16750) {
up->port.type = PORT_16750;
up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
Annotation
- Immediate include surface: `linux/module.h`, `linux/moduleparam.h`, `linux/ioport.h`, `linux/init.h`, `linux/irq.h`, `linux/console.h`, `linux/gpio/consumer.h`, `linux/lockdep.h`.
- Detected declarations: `function default_serial_dl_read`, `function default_serial_dl_write`, `function hub6_serial_in`, `function hub6_serial_out`, `function mem_serial_in`, `function mem_serial_out`, `function mem16_serial_out`, `function mem16_serial_in`, `function mem32_serial_out`, `function mem32_serial_in`.
- Atlas domain: Driver Families / drivers/tty.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.