drivers/tty/serdev/core.c

Source file repositories/reference/linux-study-clean/drivers/tty/serdev/core.c

File Facts

System
Linux kernel
Corpus path
drivers/tty/serdev/core.c
Extension
.c
Size
22544 bytes
Lines
908
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 serdev_device_match(struct device *dev, const struct device_driver *drv)
{
	if (!is_serdev_device(dev))
		return 0;

	/* TODO: platform matching */
	if (acpi_driver_match_device(dev, drv))
		return 1;

	return of_driver_match_device(dev, drv);
}

/**
 * serdev_device_add() - add a device previously constructed via serdev_device_alloc()
 * @serdev:	serdev_device to be added
 */
int serdev_device_add(struct serdev_device *serdev)
{
	struct serdev_controller *ctrl = serdev->ctrl;
	struct device *parent = serdev->dev.parent;
	int err;

	dev_set_name(&serdev->dev, "%s-%d", dev_name(parent), serdev->nr);

	/* Only a single slave device is currently supported. */
	if (ctrl->serdev) {
		dev_err(&serdev->dev, "controller busy\n");
		return -EBUSY;
	}
	ctrl->serdev = serdev;

	err = device_add(&serdev->dev);
	if (err < 0) {
		dev_err(&serdev->dev, "Failed to add serdev: %d\n", err);
		goto err_clear_serdev;
	}

	dev_dbg(&serdev->dev, "serdev registered successfully\n");

	return 0;

err_clear_serdev:
	ctrl->serdev = NULL;
	return err;
}
EXPORT_SYMBOL_GPL(serdev_device_add);

/**
 * serdev_device_remove(): remove an serdev device
 * @serdev:	serdev_device to be removed
 */
void serdev_device_remove(struct serdev_device *serdev)
{
	struct serdev_controller *ctrl = serdev->ctrl;

	device_unregister(&serdev->dev);
	ctrl->serdev = NULL;
}
EXPORT_SYMBOL_GPL(serdev_device_remove);

int serdev_device_open(struct serdev_device *serdev)
{
	struct serdev_controller *ctrl = serdev->ctrl;
	int ret;

	if (!ctrl || !ctrl->ops->open)
		return -EINVAL;

	ret = ctrl->ops->open(ctrl);
	if (ret)
		return ret;

	ret = pm_runtime_get_sync(&ctrl->dev);
	if (ret < 0) {
		pm_runtime_put_noidle(&ctrl->dev);
		goto err_close;
	}

	return 0;

err_close:
	if (ctrl->ops->close)
		ctrl->ops->close(ctrl);

	return ret;
}
EXPORT_SYMBOL_GPL(serdev_device_open);

void serdev_device_close(struct serdev_device *serdev)
{

Annotation

Implementation Notes