drivers/tty/serial/8250/8250_ni.c

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

File Facts

System
Linux kernel
Corpus path
drivers/tty/serial/8250/8250_ni.c
Extension
.c
Size
12296 bytes
Lines
451
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 ni16550_device_info {
	u32 uartclk;
	u8 prescaler;
	u8 flags;
};

struct ni16550_data {
	int line;
	struct clk *clk;
};

static int ni16550_enable_transceivers(struct uart_port *port)
{
	u8 pcr;

	pcr = port->serial_in(port, NI16550_PCR_OFFSET);
	pcr |= NI16550_PCR_TXVR_ENABLE_BIT;
	dev_dbg(port->dev, "enable transceivers: write pcr: 0x%02x\n", pcr);
	port->serial_out(port, NI16550_PCR_OFFSET, pcr);

	return 0;
}

static int ni16550_disable_transceivers(struct uart_port *port)
{
	u8 pcr;

	pcr = serial_port_in(port, NI16550_PCR_OFFSET);
	pcr &= ~NI16550_PCR_TXVR_ENABLE_BIT;
	dev_dbg(port->dev, "disable transceivers: write pcr: 0x%02x\n", pcr);
	serial_port_out(port, NI16550_PCR_OFFSET, pcr);

	return 0;
}

static int ni16550_rs485_config(struct uart_port *port,
				struct ktermios *termios,
				struct serial_rs485 *rs485)
{
	struct uart_8250_port *up = container_of(port, struct uart_8250_port, port);
	u8 pcr;

	pcr = serial_port_in(port, NI16550_PCR_OFFSET);
	pcr &= ~NI16550_PCR_WIRE_MODE_MASK;

	if ((rs485->flags & SER_RS485_MODE_RS422) ||
	    !(rs485->flags & SER_RS485_ENABLED)) {
		/* RS-422 */
		pcr |= NI16550_PCR_RS422;
		up->acr &= ~NI16550_ACR_AUTO_DTR_EN;
	} else {
		/* RS-485 2-wire Auto */
		pcr |= NI16550_PCR_AUTO_RS485;
		up->acr |= NI16550_ACR_AUTO_DTR_EN;
	}

	dev_dbg(port->dev, "config rs485: write pcr: 0x%02x, acr: %02x\n", pcr, up->acr);
	serial_port_out(port, NI16550_PCR_OFFSET, pcr);
	serial_icr_write(up, UART_ACR, up->acr);

	return 0;
}

static bool is_pmr_rs232_mode(struct uart_8250_port *up)
{
	u8 pmr = serial_in(up, NI16550_PMR_OFFSET);
	u8 pmr_mode = pmr & NI16550_PMR_MODE_MASK;
	u8 pmr_cap = pmr & NI16550_PMR_CAP_MASK;

	/*
	 * If the PMR is not implemented, then by default NI UARTs are
	 * connected to RS-485 transceivers
	 */
	if (pmr_cap == NI16550_PMR_NOT_IMPL)
		return false;

	if (pmr_cap == NI16550_PMR_CAP_DUAL)
		/*
		 * If the port is dual-mode capable, then read the mode bit
		 * to know the current mode
		 */
		return pmr_mode == NI16550_PMR_MODE_RS232;
	/*
	 * If it is not dual-mode capable, then decide based on the
	 * capability
	 */
	return pmr_cap == NI16550_PMR_CAP_RS232;
}

static void ni16550_config_prescaler(struct uart_8250_port *up,

Annotation

Implementation Notes