drivers/fsi/fsi-core.c

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

File Facts

System
Linux kernel
Corpus path
drivers/fsi/fsi-core.c
Extension
.c
Size
34963 bytes
Lines
1501
Domain
Driver Families
Bucket
drivers/fsi
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 fsi_bus_match(struct device *dev, const struct device_driver *drv)
{
	struct fsi_device *fsi_dev = to_fsi_dev(dev);
	const struct fsi_driver *fsi_drv = to_fsi_drv(drv);
	const struct fsi_device_id *id;

	if (!fsi_drv->id_table)
		return 0;

	for (id = fsi_drv->id_table; id->engine_type; id++) {
		if (id->engine_type != fsi_dev->engine_type)
			continue;
		if (id->version == FSI_VERSION_ANY ||
		    id->version == fsi_dev->version) {
			if (drv->of_match_table) {
				if (of_driver_match_device(dev, drv))
					return 1;
			} else {
				return 1;
			}
		}
	}

	return 0;
}

static int fsi_probe(struct device *dev)
{
	struct fsi_device *fsidev = to_fsi_dev(dev);
	struct fsi_driver *fsidrv = to_fsi_drv(dev->driver);

	if (fsidrv->probe)
		return fsidrv->probe(fsidev);
	else
		return 0;
}

static void fsi_remove(struct device *dev)
{
	struct fsi_device *fsidev = to_fsi_dev(dev);
	struct fsi_driver *fsidrv = to_fsi_drv(dev->driver);

	if (fsidrv->remove)
		fsidrv->remove(fsidev);
}

static const struct bus_type fsi_bus_type = {
	.name = "fsi",
	.match = fsi_bus_match,
	.probe = fsi_probe,
	.remove = fsi_remove,
};

/*
 * fsi_device_read() / fsi_device_write() / fsi_device_peek()
 *
 * FSI endpoint-device support
 *
 * Read / write / peek accessors for a client
 *
 * Parameters:
 * dev:  Structure passed to FSI client device drivers on probe().
 * addr: FSI address of given device.  Client should pass in its base address
 *       plus desired offset to access its register space.
 * val:  For read/peek this is the value read at the specified address. For
 *       write this is value to write to the specified address.
 *       The data in val must be FSI bus endian (big endian).
 * size: Size in bytes of the operation.  Sizes supported are 1, 2 and 4 bytes.
 *       Addresses must be aligned on size boundaries or an error will result.
 */
int fsi_device_read(struct fsi_device *dev, uint32_t addr, void *val,
		size_t size)
{
	if (addr > dev->size || size > dev->size || addr > dev->size - size)
		return -EINVAL;

	return fsi_slave_read(dev->slave, dev->addr + addr, val, size);
}
EXPORT_SYMBOL_GPL(fsi_device_read);

int fsi_device_write(struct fsi_device *dev, uint32_t addr, const void *val,
		size_t size)
{
	if (addr > dev->size || size > dev->size || addr > dev->size - size)
		return -EINVAL;

	return fsi_slave_write(dev->slave, dev->addr + addr, val, size);
}
EXPORT_SYMBOL_GPL(fsi_device_write);

Annotation

Implementation Notes