drivers/tty/serial/8250/8250_dfl.c

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

File Facts

System
Linux kernel
Corpus path
drivers/tty/serial/8250/8250_dfl.c
Extension
.c
Size
3818 bytes
Lines
168
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 dfl_uart {
	int line;
};

static int dfh_get_u64_param_val(struct dfl_device *dfl_dev, int param_id, u64 *pval)
{
	size_t psize;
	u64 *p;

	p = dfh_find_param(dfl_dev, param_id, &psize);
	if (IS_ERR(p))
		return PTR_ERR(p);

	if (psize != sizeof(*pval))
		return -EINVAL;

	*pval = *p;

	return 0;
}

static int dfl_uart_get_params(struct dfl_device *dfl_dev, struct uart_8250_port *uart)
{
	struct device *dev = &dfl_dev->dev;
	u64 fifo_len, clk_freq, reg_layout;
	u32 reg_width;
	int ret;

	ret = dfh_get_u64_param_val(dfl_dev, DFHv1_PARAM_ID_CLK_FRQ, &clk_freq);
	if (ret)
		return dev_err_probe(dev, ret, "missing CLK_FRQ param\n");

	uart->port.uartclk = clk_freq;

	ret = dfh_get_u64_param_val(dfl_dev, DFHv1_PARAM_ID_FIFO_LEN, &fifo_len);
	if (ret)
		return dev_err_probe(dev, ret, "missing FIFO_LEN param\n");

	switch (fifo_len) {
	case 32:
		uart->port.type = PORT_ALTR_16550_F32;
		break;

	case 64:
		uart->port.type = PORT_ALTR_16550_F64;
		break;

	case 128:
		uart->port.type = PORT_ALTR_16550_F128;
		break;

	default:
		return dev_err_probe(dev, -EINVAL, "unsupported FIFO_LEN %llu\n", fifo_len);
	}

	ret = dfh_get_u64_param_val(dfl_dev, DFHv1_PARAM_ID_REG_LAYOUT, &reg_layout);
	if (ret)
		return dev_err_probe(dev, ret, "missing REG_LAYOUT param\n");

	uart->port.regshift = FIELD_GET(DFHv1_PARAM_REG_LAYOUT_SHIFT, reg_layout);
	reg_width = FIELD_GET(DFHv1_PARAM_REG_LAYOUT_WIDTH, reg_layout);
	switch (reg_width) {
	case 4:
		uart->port.iotype = UPIO_MEM32;
		break;

	case 2:
		uart->port.iotype = UPIO_MEM16;
		break;

	default:
		return dev_err_probe(dev, -EINVAL, "unsupported reg-width %u\n", reg_width);

	}

	return 0;
}

static int dfl_uart_probe(struct dfl_device *dfl_dev)
{
	struct device *dev = &dfl_dev->dev;
	struct uart_8250_port uart = { };
	struct dfl_uart *dfluart;
	int ret;

	uart.port.flags = UPF_IOREMAP;
	uart.port.mapbase = dfl_dev->mmio_res.start;
	uart.port.mapsize = resource_size(&dfl_dev->mmio_res);

	ret = dfl_uart_get_params(dfl_dev, &uart);

Annotation

Implementation Notes