drivers/tty/serial/serial_base_bus.c

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

File Facts

System
Linux kernel
Corpus path
drivers/tty/serial/serial_base_bus.c
Extension
.c
Size
6560 bytes
Lines
292
Domain
Driver Families
Bucket
drivers/tty
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static int serial_base_match(struct device *dev, const struct device_driver *drv)
{
	if (dev->type == &serial_ctrl_type &&
	    str_has_prefix(drv->name, serial_ctrl_type.name))
		return 1;

	if (dev->type == &serial_port_type &&
	    str_has_prefix(drv->name, serial_port_type.name))
		return 1;

	return 0;
}

static const struct bus_type serial_base_bus_type = {
	.name = "serial-base",
	.match = serial_base_match,
};

int serial_base_driver_register(struct device_driver *driver)
{
	driver->bus = &serial_base_bus_type;

	return driver_register(driver);
}

void serial_base_driver_unregister(struct device_driver *driver)
{
	driver_unregister(driver);
}

/* On failure the caller must put device @dev with put_device() */
static int serial_base_device_init(struct uart_port *port,
				   struct device *dev,
				   struct device *parent_dev,
				   const struct device_type *type,
				   void (*release)(struct device *dev),
				   unsigned int ctrl_id,
				   unsigned int port_id)
{
	device_initialize(dev);
	dev->type = type;
	dev->parent = parent_dev;
	dev->bus = &serial_base_bus_type;
	dev->release = release;
	dev_set_of_node_reused(dev);

	device_set_node(dev, fwnode_handle_get(dev_fwnode(parent_dev)));

	if (!serial_base_initialized) {
		dev_dbg(port->dev, "uart_add_one_port() called before arch_initcall()?\n");
		return -EPROBE_DEFER;
	}

	if (type == &serial_ctrl_type)
		return dev_set_name(dev, "%s:%d", dev_name(port->dev), ctrl_id);

	if (type == &serial_port_type)
		return dev_set_name(dev, "%s:%d.%d", dev_name(port->dev),
				    ctrl_id, port_id);

	return -EINVAL;
}

static void serial_base_ctrl_release(struct device *dev)
{
	struct serial_ctrl_device *ctrl_dev = to_serial_base_ctrl_device(dev);

	fwnode_handle_put(dev_fwnode(dev));
	kfree(ctrl_dev);
}

void serial_base_ctrl_device_remove(struct serial_ctrl_device *ctrl_dev)
{
	if (!ctrl_dev)
		return;

	device_del(&ctrl_dev->dev);
	put_device(&ctrl_dev->dev);
}

struct serial_ctrl_device *serial_base_ctrl_add(struct uart_port *port,
						struct device *parent)
{
	struct serial_ctrl_device *ctrl_dev;
	int err;

	ctrl_dev = kzalloc_obj(*ctrl_dev);
	if (!ctrl_dev)
		return ERR_PTR(-ENOMEM);

Annotation

Implementation Notes