drivers/tty/serial/8250/8250_em.c

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

File Facts

System
Linux kernel
Corpus path
drivers/tty/serial/8250/8250_em.c
Extension
.c
Size
5998 bytes
Lines
230
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 serial8250_em_priv {
	int line;
};

static void serial8250_em_serial_out_helper(struct uart_port *p, int offset,
					    int value)
{
	switch (offset) {
	case UART_TX: /* TX @ 0x00 */
		writeb(value, p->membase);
		break;
	case UART_LCR: /* LCR @ 0x10 (+1) */
	case UART_MCR: /* MCR @ 0x14 (+1) */
	case UART_SCR: /* SCR @ 0x20 (+1) */
		writel(value, p->membase + ((offset + 1) << 2));
		break;
	case UART_FCR_EM:
		writel(value, p->membase + (UART_FCR_EM_HW << 2));
		break;
	case UART_IER: /* IER @ 0x04 */
		value &= 0x0f; /* only 4 valid bits - not Xscale */
		fallthrough;
	case UART_DLL_EM: /* DLL @ 0x24 (+9) */
	case UART_DLM_EM: /* DLM @ 0x28 (+9) */
	case UART_HCR0_EM: /* HCR0 @ 0x2c */
		writel(value, p->membase + (offset << 2));
		break;
	}
}

static u32 serial8250_em_serial_in(struct uart_port *p, unsigned int offset)
{
	switch (offset) {
	case UART_RX: /* RX @ 0x00 */
		return readb(p->membase);
	case UART_LCR: /* LCR @ 0x10 (+1) */
	case UART_MCR: /* MCR @ 0x14 (+1) */
	case UART_LSR: /* LSR @ 0x18 (+1) */
	case UART_MSR: /* MSR @ 0x1c (+1) */
	case UART_SCR: /* SCR @ 0x20 (+1) */
		return readl(p->membase + ((offset + 1) << 2));
	case UART_FCR_EM:
		return readl(p->membase + (UART_FCR_EM_HW << 2));
	case UART_IER: /* IER @ 0x04 */
	case UART_IIR: /* IIR @ 0x08 */
	case UART_DLL_EM: /* DLL @ 0x24 (+9) */
	case UART_DLM_EM: /* DLM @ 0x28 (+9) */
	case UART_HCR0_EM: /* HCR0 @ 0x2c */
		return readl(p->membase + (offset << 2));
	}
	return 0;
}

static void serial8250_em_reg_update(struct uart_port *p, int off, int value)
{
	unsigned int ier, fcr, lcr, mcr, hcr0;

	ier = serial8250_em_serial_in(p, UART_IER);
	fcr = serial8250_em_serial_in(p, UART_FCR_EM);
	lcr = serial8250_em_serial_in(p, UART_LCR);
	mcr = serial8250_em_serial_in(p, UART_MCR);
	hcr0 = serial8250_em_serial_in(p, UART_HCR0_EM);

	serial8250_em_serial_out_helper(p, UART_FCR_EM, fcr |
							UART_FCR_CLEAR_RCVR |
							UART_FCR_CLEAR_XMIT);
	serial8250_em_serial_out_helper(p, UART_HCR0_EM, hcr0 |
							 UART_HCR0_EM_SW_RESET);
	serial8250_em_serial_out_helper(p, UART_HCR0_EM, hcr0 &
							 ~UART_HCR0_EM_SW_RESET);

	switch (off) {
	case UART_FCR_EM:
		fcr = value;
		break;
	case UART_LCR:
		lcr = value;
		break;
	case UART_MCR:
		mcr = value;
		break;
	}

	serial8250_em_serial_out_helper(p, UART_IER, ier);
	serial8250_em_serial_out_helper(p, UART_FCR_EM, fcr);
	serial8250_em_serial_out_helper(p, UART_MCR, mcr);
	serial8250_em_serial_out_helper(p, UART_LCR, lcr);
	serial8250_em_serial_out_helper(p, UART_HCR0_EM, hcr0);
}

Annotation

Implementation Notes