drivers/i2c/busses/i2c-pca-isa.c

Source file repositories/reference/linux-study-clean/drivers/i2c/busses/i2c-pca-isa.c

File Facts

System
Linux kernel
Corpus path
drivers/i2c/busses/i2c-pca-isa.c
Extension
.c
Size
4693 bytes
Lines
202
Domain
Driver Families
Bucket
drivers/i2c
Inferred role
Driver Families: implementation source
Status
source 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 irqreturn_t pca_handler(int this_irq, void *dev_id) {
	wake_up(&pca_wait);
	return IRQ_HANDLED;
}

static struct i2c_algo_pca_data pca_isa_data = {
	/* .data intentionally left NULL, not needed with ISA */
	.write_byte		= pca_isa_writebyte,
	.read_byte		= pca_isa_readbyte,
	.wait_for_completion_cb	= pca_isa_waitforcompletion,
	.reset_chip		= pca_isa_resetchip,
};

static struct i2c_adapter pca_isa_ops = {
	.owner          = THIS_MODULE,
	.algo_data	= &pca_isa_data,
	.name		= "PCA9564/PCA9665 ISA Adapter",
	.timeout	= HZ,
};

static int pca_isa_match(struct device *dev, unsigned int id)
{
	int match = base != 0;

	if (match) {
		if (irq <= -1)
			dev_warn(dev, "Using polling mode (specify irq)\n");
	} else
		dev_err(dev, "Please specify I/O base\n");

	return match;
}

static int pca_isa_probe(struct device *dev, unsigned int id)
{
	init_waitqueue_head(&pca_wait);

	dev_info(dev, "i/o base %#08lx. irq %d\n", base, irq);

#ifdef CONFIG_PPC
	if (check_legacy_ioport(base)) {
		dev_err(dev, "I/O address %#08lx is not available\n", base);
		goto out;
	}
#endif

	if (!request_region(base, IO_SIZE, "i2c-pca-isa")) {
		dev_err(dev, "I/O address %#08lx is in use\n", base);
		goto out;
	}

	if (irq > -1) {
		if (request_irq(irq, pca_handler, 0, "i2c-pca-isa", &pca_isa_ops) < 0) {
			dev_err(dev, "Request irq%d failed\n", irq);
			goto out_region;
		}
	}

	pca_isa_data.i2c_clock = clock;
	if (i2c_pca_add_bus(&pca_isa_ops) < 0) {
		dev_err(dev, "Failed to add i2c bus\n");
		goto out_irq;
	}

	return 0;

 out_irq:
	if (irq > -1)
		free_irq(irq, &pca_isa_ops);
 out_region:
	release_region(base, IO_SIZE);
 out:
	return -ENODEV;
}

static void pca_isa_remove(struct device *dev, unsigned int id)
{
	i2c_del_adapter(&pca_isa_ops);

	if (irq > -1) {
		disable_irq(irq);
		free_irq(irq, &pca_isa_ops);
	}
	release_region(base, IO_SIZE);
}

static struct isa_driver pca_isa_driver = {
	.match		= pca_isa_match,
	.probe		= pca_isa_probe,
	.remove		= pca_isa_remove,

Annotation

Implementation Notes