drivers/iio/adc/ad_sigma_delta.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/ad_sigma_delta.c
Extension
.c
Size
25230 bytes
Lines
922
Domain
Driver Families
Bucket
drivers/iio
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

iio_for_each_active_channel(indio_dev, i) {
			sigma_delta->slots[slot] = indio_dev->channels[i].address;
			slot++;
		}
	}

	sigma_delta->active_slots = slot;
	sigma_delta->current_slot = 0;

	if (ad_sigma_delta_has_spi_offload(sigma_delta)) {
		xfer[1].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
		xfer[1].bits_per_word = scan_type->realbits;
		xfer[1].len = spi_bpw_to_bytes(scan_type->realbits);
	} else {
		unsigned int samples_buf_size, scan_size;

		if (sigma_delta->active_slots > 1) {
			ret = ad_sigma_delta_append_status(sigma_delta, true);
			if (ret)
				return ret;
		}

		samples_buf_size =
			ALIGN(slot * BITS_TO_BYTES(scan_type->storagebits),
			      sizeof(s64));
		samples_buf_size += sizeof(s64);
		samples_buf = devm_krealloc(&sigma_delta->spi->dev,
					    sigma_delta->samples_buf,
					    samples_buf_size, GFP_KERNEL);
		if (!samples_buf)
			return -ENOMEM;

		sigma_delta->samples_buf = samples_buf;
		scan_size = BITS_TO_BYTES(scan_type->realbits + scan_type->shift);
		/* For 24-bit data, there is an extra byte of padding. */
		xfer[1].rx_buf = &sigma_delta->rx_buf[scan_size == 3 ? 1 : 0];
		xfer[1].len = scan_size + (sigma_delta->status_appended ? 1 : 0);
	}
	xfer[1].cs_change = 1;

	if (sigma_delta->info->has_registers) {
		xfer[0].tx_buf = &sigma_delta->sample_addr;
		xfer[0].len = 1;

		ad_sd_set_read_reg_addr(sigma_delta,
					sigma_delta->info->data_reg ?: AD_SD_REG_DATA,
					&sigma_delta->sample_addr);
		spi_message_init_with_transfers(&sigma_delta->sample_msg, xfer, 2);
	} else {
		spi_message_init_with_transfers(&sigma_delta->sample_msg,
						&xfer[1], 1);
	}

	sigma_delta->sample_msg.offload = sigma_delta->offload;

	ret = spi_optimize_message(sigma_delta->spi, &sigma_delta->sample_msg);
	if (ret)
		return ret;

	spi_bus_lock(sigma_delta->spi->controller);
	sigma_delta->bus_locked = true;
	sigma_delta->keep_cs_asserted = true;

	ret = ad_sigma_delta_clear_pending_event(sigma_delta);
	if (ret)
		goto err_unlock;

	ret = ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_CONTINUOUS);
	if (ret)
		goto err_unlock;

	if (ad_sigma_delta_has_spi_offload(sigma_delta)) {
		struct spi_offload_trigger_config config = {
			.type = SPI_OFFLOAD_TRIGGER_DATA_READY,
		};

		ret = spi_offload_trigger_enable(sigma_delta->offload,
						 sigma_delta->offload_trigger,
						 &config);
		if (ret)
			goto err_unlock;
	} else {
		ad_sd_enable_irq(sigma_delta);
	}

	return 0;

err_unlock:
	spi_bus_unlock(sigma_delta->spi->controller);
	spi_unoptimize_message(&sigma_delta->sample_msg);

Annotation

Implementation Notes