drivers/tty/serial/8250/8250_ingenic.c

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

File Facts

System
Linux kernel
Corpus path
drivers/tty/serial/8250/8250_ingenic.c
Extension
.c
Size
9191 bytes
Lines
372
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 ingenic_uart_config {
	int tx_loadsz;
	int fifosize;
};

struct ingenic_uart_data {
	struct clk	*clk_module;
	struct clk	*clk_baud;
	int		line;
};

static const struct of_device_id of_match[];

#define UART_FCR_UME	BIT(4)

#define UART_MCR_MDCE	BIT(7)
#define UART_MCR_FCM	BIT(6)

static struct earlycon_device *early_device;

static uint8_t early_in(struct uart_port *port, int offset)
{
	return readl(port->membase + (offset << 2));
}

static void early_out(struct uart_port *port, int offset, uint8_t value)
{
	writel(value, port->membase + (offset << 2));
}

static void ingenic_early_console_putc(struct uart_port *port, unsigned char c)
{
	u16 lsr;

	do {
		lsr = early_in(port, UART_LSR);
	} while ((lsr & UART_LSR_TEMT) == 0);

	early_out(port, UART_TX, c);
}

static void ingenic_early_console_write(struct console *console,
					      const char *s, unsigned int count)
{
	uart_console_write(&early_device->port, s, count,
			   ingenic_early_console_putc);
}

static void __init ingenic_early_console_setup_clock(struct earlycon_device *dev)
{
	void *fdt = initial_boot_params;
	const __be32 *prop;
	int offset;

	offset = fdt_path_offset(fdt, "/ext");
	if (offset < 0)
		return;

	prop = fdt_getprop(fdt, offset, "clock-frequency", NULL);
	if (!prop)
		return;

	dev->port.uartclk = be32_to_cpup(prop);
}

static int __init ingenic_earlycon_setup_tail(struct earlycon_device *dev,
					      const char *opt)
{
	struct uart_port *port = &dev->port;
	unsigned int divisor;
	int baud = 115200;

	if (!dev->port.membase)
		return -ENODEV;

	if (opt) {
		unsigned int parity, bits, flow; /* unused for now */

		uart_parse_options(opt, &baud, &parity, &bits, &flow);
	}

	if (dev->baud)
		baud = dev->baud;
	divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud);

	early_out(port, UART_IER, 0);
	early_out(port, UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8);
	early_out(port, UART_DLL, 0);
	early_out(port, UART_DLM, 0);
	early_out(port, UART_LCR, UART_LCR_WLEN8);

Annotation

Implementation Notes