drivers/tty/serial/8250/8250_keba.c

Source file repositories/reference/linux-study-clean/drivers/tty/serial/8250/8250_keba.c

File Facts

System
Linux kernel
Corpus path
drivers/tty/serial/8250/8250_keba.c
Extension
.c
Size
7841 bytes
Lines
292
Domain
Driver Families
Bucket
drivers/tty
Inferred role
Driver Families: implementation source
Status
source 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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct kuart {
	struct keba_uart_auxdev *auxdev;
	void __iomem *base;
	unsigned int line;

	unsigned int flags;
	u8 capability;
	enum kuart_mode mode;
};

static void kuart_set_phy_mode(struct kuart *kuart, enum kuart_mode mode)
{
	iowrite8(mode, kuart->base + KUART_CONTROL);
}

static void kuart_enhanced_mode(struct uart_8250_port *up, bool enable)
{
	u8 lcr, efr;

	/* backup LCR register */
	lcr = serial_in(up, UART_LCR);

	/* enable 650 compatible register set (EFR, ...) */
	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);

	/* enable/disable enhanced mode with indexed control registers */
	efr = serial_in(up, UART_EFR);
	if (enable)
		efr |= UART_EFR_ECB;
	else
		efr &= ~UART_EFR_ECB;
	serial_out(up, UART_EFR, efr);

	/* disable 650 compatible register set, restore LCR */
	serial_out(up, UART_LCR, lcr);
}

static void kuart_dtr_line_config(struct uart_8250_port *up, u8 dtrlc)
{
	u8 acr;

	/* set index register to 0 to access ACR register */
	serial_out(up, KUART_EMODE_ICR_OFFSET, UART_ACR);

	/* set value register to 0x10 writing DTR mode (1,0) */
	acr = serial_in(up, KUART_EMODE_ICR_VALUE);
	acr &= ~UART_ACR_DTRLC_MASK;
	acr |= dtrlc;
	serial_out(up, KUART_EMODE_ICR_VALUE, acr);
}

static int kuart_rs485_config(struct uart_port *port, struct ktermios *termios,
			      struct serial_rs485 *rs485)
{
	struct uart_8250_port *up = up_to_u8250p(port);
	struct kuart *kuart = port->private_data;
	enum kuart_mode mode;
	u8 dtrlc;

	if (rs485->flags & SER_RS485_ENABLED) {
		if (rs485->flags & SER_RS485_MODE_RS422)
			mode = KUART_MODE_RS422;
		else
			mode = KUART_MODE_RS485;
	} else {
		mode = KUART_MODE_RS232;
	}

	if (mode == kuart->mode)
		return 0;

	if (kuart->flags & KUART_USE_CAPABILITY) {
		/* deactivate physical interface, break before make */
		kuart_set_phy_mode(kuart, KUART_MODE_NONE);
	}

	if (mode == KUART_MODE_RS485) {
		/*
		 * Set DTR line configuration of 95x UART to DTR mode (1,0).
		 * In this mode the DTR pin drives the active-low enable pin of
		 * an external RS485 buffer. The DTR pin will be forced low
		 * whenever the transmitter is not empty, otherwise DTR pin is
		 * high.
		 */
		dtrlc = UART_ACR_DTRLC_ENABLE_LOW;
	} else {
		/*
		 * Set DTR line configuration of 95x UART to DTR mode (0,0).
		 * In this mode the DTR pin is compatible with 16C450, 16C550,
		 * 16C650 and 16c670 (i.e. normal).

Annotation

Implementation Notes