drivers/soundwire/bus_type.c

Source file repositories/reference/linux-study-clean/drivers/soundwire/bus_type.c

File Facts

System
Linux kernel
Corpus path
drivers/soundwire/bus_type.c
Extension
.c
Size
5877 bytes
Lines
247
Domain
Driver Families
Bucket
drivers/soundwire
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 sdw_bus_match(struct device *dev, const struct device_driver *ddrv)
{
	struct sdw_slave *slave;
	const struct sdw_driver *drv;
	int ret = 0;

	if (is_sdw_slave(dev)) {
		slave = dev_to_sdw_dev(dev);
		drv = drv_to_sdw_driver(ddrv);

		ret = !!sdw_get_device_id(slave, drv);
	}
	return ret;
}

int sdw_slave_modalias(const struct sdw_slave *slave, char *buf, size_t size)
{
	/* modalias is sdw:m<mfg_id>p<part_id>v<version>c<class_id> */

	return snprintf(buf, size, "sdw:m%04Xp%04Xv%02Xc%02X\n",
			slave->id.mfg_id, slave->id.part_id,
			slave->id.sdw_version, slave->id.class_id);
}

int sdw_slave_uevent(const struct device *dev, struct kobj_uevent_env *env)
{
	const struct sdw_slave *slave = dev_to_sdw_dev(dev);
	char modalias[32];

	sdw_slave_modalias(slave, modalias, sizeof(modalias));

	if (add_uevent_var(env, "MODALIAS=%s", modalias))
		return -ENOMEM;

	return 0;
}

static int sdw_bus_probe(struct device *dev)
{
	struct sdw_slave *slave = dev_to_sdw_dev(dev);
	struct sdw_driver *drv = drv_to_sdw_driver(dev->driver);
	const struct sdw_device_id *id;
	int ret;

	/*
	 * fw description is mandatory to bind
	 */
	if (!dev->fwnode)
		return -ENODEV;

	if (!IS_ENABLED(CONFIG_ACPI) && !dev->of_node)
		return -ENODEV;

	id = sdw_get_device_id(slave, drv);
	if (!id)
		return -ENODEV;

	/*
	 * attach to power domain but don't turn on (last arg)
	 */
	ret = dev_pm_domain_attach(dev, 0);
	if (ret)
		return ret;

	ret = ida_alloc_max(&slave->bus->slave_ida, SDW_FW_MAX_DEVICES - 1, GFP_KERNEL);
	if (ret < 0) {
		dev_err(dev, "Failed to allocated ID: %d\n", ret);
		return ret;
	}
	slave->index = ret;

	ret = drv->probe(slave, id);
	if (ret) {
		ida_free(&slave->bus->slave_ida, slave->index);
		return ret;
	}

	mutex_lock(&slave->sdw_dev_lock);

	/* device is probed so let's read the properties now */
	if (drv->ops && drv->ops->read_prop)
		drv->ops->read_prop(slave);

	if (slave->prop.use_domain_irq)
		sdw_irq_create_mapping(slave);

	/* init the dynamic sysfs attributes we need */
	ret = sdw_slave_sysfs_dpn_init(slave);
	if (ret < 0)
		dev_warn(dev, "failed to initialise sysfs: %d\n", ret);

Annotation

Implementation Notes