drivers/iio/adc/ad7606_par.c

Source file repositories/reference/linux-study-clean/drivers/iio/adc/ad7606_par.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/ad7606_par.c
Extension
.c
Size
7747 bytes
Lines
266
Domain
Driver Families
Bucket
drivers/iio
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

if (!gpiod_get_value(st->gpio_frstdata)) {
			ad7606_reset(st);
			return -EIO;
		}
		_buf++;
		num--;
	}
	insw((unsigned long)st->base_address, _buf, num);
	return 0;
}

static const struct ad7606_bus_ops ad7606_par16_bops = {
	.read_block = ad7606_par16_read_block,
};

static int ad7606_par8_read_block(struct device *dev,
				  int count, void *buf)
{
	struct iio_dev *indio_dev = dev_get_drvdata(dev);
	struct ad7606_state *st = iio_priv(indio_dev);
	/*
	 * On the parallel interface, the frstdata signal is set to high while
	 * and after reading the sample of the first channel and low for all
	 * other channels.  This can be used to check that the incoming data is
	 * correctly aligned.  During normal operation the data should never
	 * become unaligned, but some glitch or electrostatic discharge might
	 * cause an extra read or clock cycle.  Monitoring the frstdata signal
	 * allows to recover from such failure situations.
	 */
	int num = count;
	u16 *_buf = buf;

	if (st->gpio_frstdata) {
		insb((unsigned long)st->base_address, _buf, 2);
		if (!gpiod_get_value(st->gpio_frstdata)) {
			ad7606_reset(st);
			return -EIO;
		}
		_buf++;
		num--;
	}
	insb((unsigned long)st->base_address, _buf, num * 2);

	return 0;
}

static const struct ad7606_bus_ops ad7606_par8_bops = {
	.read_block = ad7606_par8_read_block,
};

static int ad7606_par_probe(struct platform_device *pdev)
{
	const struct ad7606_chip_info *chip_info;
	const struct platform_device_id *id;
	struct resource *res;
	void __iomem *addr;
	resource_size_t remap_size;
	int irq;

	/*
	 * If a firmware node is available (ACPI or DT), platform_device_id is null
	 * and we must use get_match_data.
	 */
	if (dev_fwnode(&pdev->dev)) {
		chip_info = device_get_match_data(&pdev->dev);
		if (device_property_present(&pdev->dev, "io-backends"))
			/*
			 * If a backend is available ,call the core probe with backend
			 * bops, otherwise use the former bops.
			 */
			return ad7606_probe(&pdev->dev, 0, NULL,
					    chip_info,
					    &ad7606_bi_bops);
	} else {
		id = platform_get_device_id(pdev);
		chip_info = (const struct ad7606_chip_info *)id->driver_data;
	}

	irq = platform_get_irq(pdev, 0);
	if (irq < 0)
		return irq;

	addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
	if (IS_ERR(addr))
		return PTR_ERR(addr);

	remap_size = resource_size(res);

	return ad7606_probe(&pdev->dev, irq, addr, chip_info,
			    remap_size > 1 ? &ad7606_par16_bops :

Annotation

Implementation Notes