Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: adc: ad_sigma_delta: Add sequencer support

Some sigma-delta chips support sampling of multiple
channels in continuous mode.

When the operating with more than one channel enabled,
the channel sequencer cycles through the enabled channels
in sequential order, from first channel to the last one.
If a channel is disabled, it is skipped by the sequencer.

If more than one channel is used in continuous mode,
instruct the device to append the status to the SPI transfer
(1 extra byte) every time we receive a sample.
All sigma-delta chips possessing a sampling sequencer have
this ability. Inside the status register there will be
the number of the converted channel. In this way, even
if the CPU won't keep up with the sampling rate, it won't
send to userspace wrong channel samples.

When multiple channels are enabled in continuous mode,
the device needs to perform a measurement on all slots
before we can push to userspace the sample.

If, during sequencing and data reading, a channel measurement
is lost, a desync occurred. In this case, ad_sigma_delta drops
the incomplete sample and waits for the device to send the
measurement on the first active slot.

Co-developed-by: Alexandru Tachici <alexandru.tachici@analog.com>
Signed-off-by: Alexandru Tachici <alexandru.tachici@analog.com>
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Link: https://lore.kernel.org/r/20220322105029.86389-5-alexandru.tachici@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Lars-Peter Clausen and committed by
Jonathan Cameron
8bea9af8 fe7d929a

+171 -10
+133 -10
drivers/iio/adc/ad_sigma_delta.c
··· 6 6 * Author: Lars-Peter Clausen <lars@metafoo.de> 7 7 */ 8 8 9 + #include <linux/align.h> 9 10 #include <linux/interrupt.h> 10 11 #include <linux/device.h> 11 12 #include <linux/kernel.h> ··· 343 342 static int ad_sd_buffer_postenable(struct iio_dev *indio_dev) 344 343 { 345 344 struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); 345 + unsigned int i, slot, samples_buf_size; 346 346 unsigned int channel; 347 + uint8_t *samples_buf; 347 348 int ret; 348 349 349 - channel = find_first_bit(indio_dev->active_scan_mask, 350 - indio_dev->masklength); 351 - ret = ad_sigma_delta_set_channel(sigma_delta, 352 - indio_dev->channels[channel].address); 353 - if (ret) 354 - return ret; 350 + if (sigma_delta->num_slots == 1) { 351 + channel = find_first_bit(indio_dev->active_scan_mask, 352 + indio_dev->masklength); 353 + ret = ad_sigma_delta_set_channel(sigma_delta, 354 + indio_dev->channels[channel].address); 355 + if (ret) 356 + return ret; 357 + slot = 1; 358 + } else { 359 + /* 360 + * At this point update_scan_mode already enabled the required channels. 361 + * For sigma-delta sequencer drivers with multiple slots, an update_scan_mode 362 + * implementation is mandatory. 363 + */ 364 + slot = 0; 365 + for_each_set_bit(i, indio_dev->active_scan_mask, indio_dev->masklength) { 366 + sigma_delta->slots[slot] = indio_dev->channels[i].address; 367 + slot++; 368 + } 369 + } 370 + 371 + sigma_delta->active_slots = slot; 372 + sigma_delta->current_slot = 0; 373 + 374 + if (sigma_delta->active_slots > 1) { 375 + ret = ad_sigma_delta_append_status(sigma_delta, true); 376 + if (ret) 377 + return ret; 378 + } 379 + 380 + samples_buf_size = ALIGN(slot * indio_dev->channels[0].scan_type.storagebits, 8); 381 + samples_buf_size += sizeof(int64_t); 382 + samples_buf = devm_krealloc(&sigma_delta->spi->dev, sigma_delta->samples_buf, 383 + samples_buf_size, GFP_KERNEL); 384 + if (!samples_buf) 385 + return -ENOMEM; 386 + 387 + sigma_delta->samples_buf = samples_buf; 355 388 356 389 spi_bus_lock(sigma_delta->spi->master); 357 390 sigma_delta->bus_locked = true; ··· 421 386 sigma_delta->keep_cs_asserted = false; 422 387 ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); 423 388 389 + if (sigma_delta->status_appended) 390 + ad_sigma_delta_append_status(sigma_delta, false); 391 + 392 + ad_sigma_delta_disable_all(sigma_delta); 424 393 sigma_delta->bus_locked = false; 425 394 return spi_bus_unlock(sigma_delta->spi->master); 426 395 } ··· 435 396 struct iio_dev *indio_dev = pf->indio_dev; 436 397 struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); 437 398 uint8_t *data = sigma_delta->rx_buf; 399 + unsigned int transfer_size; 400 + unsigned int sample_size; 401 + unsigned int sample_pos; 402 + unsigned int status_pos; 438 403 unsigned int reg_size; 439 404 unsigned int data_reg; 440 405 ··· 451 408 else 452 409 data_reg = AD_SD_REG_DATA; 453 410 411 + /* Status word will be appended to the sample during transfer */ 412 + if (sigma_delta->status_appended) 413 + transfer_size = reg_size + 1; 414 + else 415 + transfer_size = reg_size; 416 + 454 417 switch (reg_size) { 455 418 case 4: 456 419 case 2: 457 420 case 1: 458 - ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size, &data[0]); 421 + status_pos = reg_size; 422 + ad_sd_read_reg_raw(sigma_delta, data_reg, transfer_size, &data[0]); 459 423 break; 460 424 case 3: 425 + /* 426 + * Data array after transfer will look like (if status is appended): 427 + * data[] = { [0][sample][sample][sample][status] } 428 + * Keeping the first byte 0 shifts the status postion by 1 byte to the right. 429 + */ 430 + status_pos = reg_size + 1; 431 + 461 432 /* We store 24 bit samples in a 32 bit word. Keep the upper 462 433 * byte set to zero. */ 463 - ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size, &data[1]); 434 + ad_sd_read_reg_raw(sigma_delta, data_reg, transfer_size, &data[1]); 464 435 break; 465 436 } 466 437 467 - iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp); 438 + /* 439 + * For devices sampling only one channel at 440 + * once, there is no need for sample number tracking. 441 + */ 442 + if (sigma_delta->active_slots == 1) { 443 + iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp); 444 + goto irq_handled; 445 + } 468 446 447 + if (sigma_delta->status_appended) { 448 + u8 converted_channel; 449 + 450 + converted_channel = data[status_pos] & sigma_delta->info->status_ch_mask; 451 + if (converted_channel != sigma_delta->slots[sigma_delta->current_slot]) { 452 + /* 453 + * Desync occurred during continuous sampling of multiple channels. 454 + * Drop this incomplete sample and start from first channel again. 455 + */ 456 + 457 + sigma_delta->current_slot = 0; 458 + goto irq_handled; 459 + } 460 + } 461 + 462 + sample_size = indio_dev->channels[0].scan_type.storagebits / 8; 463 + sample_pos = sample_size * sigma_delta->current_slot; 464 + memcpy(&sigma_delta->samples_buf[sample_pos], data, sample_size); 465 + sigma_delta->current_slot++; 466 + 467 + if (sigma_delta->current_slot == sigma_delta->active_slots) { 468 + sigma_delta->current_slot = 0; 469 + iio_push_to_buffers_with_timestamp(indio_dev, sigma_delta->samples_buf, 470 + pf->timestamp); 471 + } 472 + 473 + irq_handled: 469 474 iio_trigger_notify_done(indio_dev->trig); 470 475 sigma_delta->irq_dis = false; 471 476 enable_irq(sigma_delta->spi->irq); ··· 521 430 return IRQ_HANDLED; 522 431 } 523 432 433 + static bool ad_sd_validate_scan_mask(struct iio_dev *indio_dev, const unsigned long *mask) 434 + { 435 + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); 436 + 437 + return bitmap_weight(mask, indio_dev->masklength) <= sigma_delta->num_slots; 438 + } 439 + 524 440 static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = { 525 441 .postenable = &ad_sd_buffer_postenable, 526 442 .postdisable = &ad_sd_buffer_postdisable, 527 - .validate_scan_mask = &iio_validate_scan_mask_onehot, 443 + .validate_scan_mask = &ad_sd_validate_scan_mask, 528 444 }; 529 445 530 446 static irqreturn_t ad_sd_data_rdy_trig_poll(int irq, void *private) ··· 611 513 */ 612 514 int devm_ad_sd_setup_buffer_and_trigger(struct device *dev, struct iio_dev *indio_dev) 613 515 { 516 + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); 614 517 int ret; 518 + 519 + sigma_delta->slots = devm_kcalloc(dev, sigma_delta->num_slots, 520 + sizeof(*sigma_delta->slots), GFP_KERNEL); 521 + if (!sigma_delta->slots) 522 + return -ENOMEM; 615 523 616 524 ret = devm_iio_triggered_buffer_setup(dev, indio_dev, 617 525 &iio_pollfunc_store_time, ··· 645 541 { 646 542 sigma_delta->spi = spi; 647 543 sigma_delta->info = info; 544 + 545 + /* If the field is unset in ad_sigma_delta_info, asume there can only be 1 slot. */ 546 + if (!info->num_slots) 547 + sigma_delta->num_slots = 1; 548 + else 549 + sigma_delta->num_slots = info->num_slots; 550 + 551 + if (sigma_delta->num_slots > 1) { 552 + if (!indio_dev->info->update_scan_mode) { 553 + dev_err(&spi->dev, "iio_dev lacks update_scan_mode().\n"); 554 + return -EINVAL; 555 + } 556 + 557 + if (!info->disable_all) { 558 + dev_err(&spi->dev, "ad_sigma_delta_info lacks disable_all().\n"); 559 + return -EINVAL; 560 + } 561 + } 562 + 648 563 iio_device_set_drvdata(indio_dev, sigma_delta); 649 564 650 565 return 0;
+38
include/linux/iio/adc/ad_sigma_delta.h
··· 32 32 /** 33 33 * struct ad_sigma_delta_info - Sigma Delta driver specific callbacks and options 34 34 * @set_channel: Will be called to select the current channel, may be NULL. 35 + * @append_status: Will be called to enable status append at the end of the sample, may be NULL. 35 36 * @set_mode: Will be called to select the current mode, may be NULL. 37 + * @disable_all: Will be called to disable all channels, may be NULL. 36 38 * @postprocess_sample: Is called for each sampled data word, can be used to 37 39 * modify or drop the sample data, it, may be NULL. 38 40 * @has_registers: true if the device has writable and readable registers, false 39 41 * if there is just one read-only sample data shift register. 40 42 * @addr_shift: Shift of the register address in the communications register. 41 43 * @read_mask: Mask for the communications register having the read bit set. 44 + * @status_ch_mask: Mask for the channel number stored in status register. 42 45 * @data_reg: Address of the data register, if 0 the default address of 0x3 will 43 46 * be used. 44 47 * @irq_flags: flags for the interrupt used by the triggered buffer 48 + * @num_slots: Number of sequencer slots 45 49 */ 46 50 struct ad_sigma_delta_info { 47 51 int (*set_channel)(struct ad_sigma_delta *, unsigned int channel); 52 + int (*append_status)(struct ad_sigma_delta *, bool append); 48 53 int (*set_mode)(struct ad_sigma_delta *, enum ad_sigma_delta_mode mode); 54 + int (*disable_all)(struct ad_sigma_delta *); 49 55 int (*postprocess_sample)(struct ad_sigma_delta *, unsigned int raw_sample); 50 56 bool has_registers; 51 57 unsigned int addr_shift; 52 58 unsigned int read_mask; 59 + unsigned int status_ch_mask; 53 60 unsigned int data_reg; 54 61 unsigned long irq_flags; 62 + unsigned int num_slots; 55 63 }; 56 64 57 65 /** ··· 84 76 uint8_t comm; 85 77 86 78 const struct ad_sigma_delta_info *info; 79 + unsigned int active_slots; 80 + unsigned int current_slot; 81 + unsigned int num_slots; 82 + bool status_appended; 83 + /* map slots to channels in order to know what to expect from devices */ 84 + unsigned int *slots; 85 + uint8_t *samples_buf; 87 86 88 87 /* 89 88 * DMA (thus cache coherency maintenance) requires the ··· 108 93 { 109 94 if (sd->info->set_channel) 110 95 return sd->info->set_channel(sd, channel); 96 + 97 + return 0; 98 + } 99 + 100 + static inline int ad_sigma_delta_append_status(struct ad_sigma_delta *sd, bool append) 101 + { 102 + int ret; 103 + 104 + if (sd->info->append_status) { 105 + ret = sd->info->append_status(sd, append); 106 + if (ret < 0) 107 + return ret; 108 + 109 + sd->status_appended = append; 110 + } 111 + 112 + return 0; 113 + } 114 + 115 + static inline int ad_sigma_delta_disable_all(struct ad_sigma_delta *sd) 116 + { 117 + if (sd->info->disable_all) 118 + return sd->info->disable_all(sd); 111 119 112 120 return 0; 113 121 }