drivers/spi/spidev.c

Source file repositories/reference/linux-study-clean/drivers/spi/spidev.c

File Facts

System
Linux kernel
Corpus path
drivers/spi/spidev.c
Extension
.c
Size
23377 bytes
Lines
900
Domain
Driver Families
Bucket
drivers/spi
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 const struct file_operations spidev_fops = {
	.owner =	THIS_MODULE,
	/* REVISIT switch to aio primitives, so that userspace
	 * gets more complete API coverage.  It'll simplify things
	 * too, except for the locking.
	 */
	.write =	spidev_write,
	.read =		spidev_read,
	.unlocked_ioctl = spidev_ioctl,
	.compat_ioctl = spidev_compat_ioctl,
	.open =		spidev_open,
	.release =	spidev_release,
};

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

/* The main reason to have this class is to make mdev/udev create the
 * /dev/spidevB.C character device nodes exposing our userspace API.
 * It also simplifies memory management.
 */

static const struct class spidev_class = {
	.name = "spidev",
};

/*
 * The spi device ids are expected to match the device names of the
 * spidev_dt_ids array below. Both arrays are kept in the same ordering.
 */
static const struct spi_device_id spidev_spi_ids[] = {
	{ .name = /* abb */ "spi-sensor" },
	{ .name = /* arduino */ "unoq-mcu" },
	{ .name = /* cisco */ "spi-petra" },
	{ .name = /* dh */ "dhcom-board" },
	{ .name = /* elgin */ "jg10309-01" },
	{ .name = /* gocontroll */ "moduline-module-slot"},
	{ .name = /* lineartechnology */ "ltc2488" },
	{ .name = /* lwn */ "bk4" },
	{ .name = /* lwn */ "bk4-spi" },
	{ .name = /* menlo */ "m53cpld" },
	{ .name = /* micron */ "spi-authenta" },
	{ .name = /* rohm */ "bh2228fv" },
	{ .name = /* rohm */ "dh2228fv" },
	{ .name = /* semtech */ "sx1301" },
	{ .name = /* silabs */ "em3581" },
	{ .name = /* silabs */ "si3210" },
	{},
};
MODULE_DEVICE_TABLE(spi, spidev_spi_ids);

/*
 * spidev should never be referenced in DT without a specific compatible string,
 * it is a Linux implementation thing rather than a description of the hardware.
 */
static int spidev_of_check(struct device *dev)
{
	if (device_property_match_string(dev, "compatible", "spidev") < 0)
		return 0;

	dev_err(dev, "spidev listed directly in DT is not supported\n");
	return -EINVAL;
}

static const struct of_device_id spidev_dt_ids[] = {
	{ .compatible = "abb,spi-sensor", .data = &spidev_of_check },
	{ .compatible = "arduino,unoq-mcu", .data = &spidev_of_check },
	{ .compatible = "cisco,spi-petra", .data = &spidev_of_check },
	{ .compatible = "dh,dhcom-board", .data = &spidev_of_check },
	{ .compatible = "elgin,jg10309-01", .data = &spidev_of_check },
	{ .compatible = "gocontroll,moduline-module-slot", .data = &spidev_of_check},
	{ .compatible = "lineartechnology,ltc2488", .data = &spidev_of_check },
	{ .compatible = "lwn,bk4", .data = &spidev_of_check },
	{ .compatible = "lwn,bk4-spi", .data = &spidev_of_check },
	{ .compatible = "menlo,m53cpld", .data = &spidev_of_check },
	{ .compatible = "micron,spi-authenta", .data = &spidev_of_check },
	{ .compatible = "rohm,bh2228fv", .data = &spidev_of_check },
	{ .compatible = "rohm,dh2228fv", .data = &spidev_of_check },
	{ .compatible = "semtech,sx1301", .data = &spidev_of_check },
	{ .compatible = "silabs,em3581", .data = &spidev_of_check },
	{ .compatible = "silabs,si3210", .data = &spidev_of_check },
	{},
};
MODULE_DEVICE_TABLE(of, spidev_dt_ids);

/* Dummy SPI devices not to be used in production systems */
static int spidev_acpi_check(struct device *dev)
{
	dev_warn(dev, "do not use this driver in production systems!\n");
	return 0;
}

Annotation

Implementation Notes