drivers/usb/common/ulpi.c

Source file repositories/reference/linux-study-clean/drivers/usb/common/ulpi.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/common/ulpi.c
Extension
.c
Size
9620 bytes
Lines
383
Domain
Driver Families
Bucket
drivers/usb
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 ulpi_match(struct device *dev, const struct device_driver *driver)
{
	struct ulpi_driver *drv = to_ulpi_driver(driver);
	struct ulpi *ulpi = to_ulpi_dev(dev);
	const struct ulpi_device_id *id;

	/*
	 * Some ULPI devices don't have a vendor id
	 * or provide an id_table so rely on OF match.
	 */
	if (ulpi->id.vendor == 0 || !drv->id_table)
		return of_driver_match_device(dev, driver);

	for (id = drv->id_table; id->vendor; id++)
		if (id->vendor == ulpi->id.vendor &&
		    id->product == ulpi->id.product)
			return 1;

	return 0;
}

static int ulpi_uevent(const struct device *dev, struct kobj_uevent_env *env)
{
	const struct ulpi *ulpi = to_ulpi_dev(dev);
	int ret;

	ret = of_device_uevent_modalias(dev, env);
	if (ret != -ENODEV)
		return ret;

	if (add_uevent_var(env, "MODALIAS=ulpi:v%04xp%04x",
			   ulpi->id.vendor, ulpi->id.product))
		return -ENOMEM;
	return 0;
}

static int ulpi_probe(struct device *dev)
{
	struct ulpi_driver *drv = to_ulpi_driver(dev->driver);
	int ret;

	ret = of_clk_set_defaults(dev->of_node, false);
	if (ret < 0)
		return ret;

	return drv->probe(to_ulpi_dev(dev));
}

static void ulpi_remove(struct device *dev)
{
	struct ulpi_driver *drv = to_ulpi_driver(dev->driver);

	if (drv->remove)
		drv->remove(to_ulpi_dev(dev));
}

static const struct bus_type ulpi_bus = {
	.name = "ulpi",
	.match = ulpi_match,
	.uevent = ulpi_uevent,
	.probe = ulpi_probe,
	.remove = ulpi_remove,
};

/* -------------------------------------------------------------------------- */

static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
			     char *buf)
{
	int len;
	struct ulpi *ulpi = to_ulpi_dev(dev);

	len = of_device_modalias(dev, buf, PAGE_SIZE);
	if (len != -ENODEV)
		return len;

	return sprintf(buf, "ulpi:v%04xp%04x\n",
		       ulpi->id.vendor, ulpi->id.product);
}
static DEVICE_ATTR_RO(modalias);

static struct attribute *ulpi_dev_attrs[] = {
	&dev_attr_modalias.attr,
	NULL
};

static const struct attribute_group ulpi_dev_attr_group = {
	.attrs = ulpi_dev_attrs,
};

Annotation

Implementation Notes