Lines Matching +full:delta +full:- +full:sigma

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Support code for Analog Devices Sigma-Delta ADCs
6 * Author: Lars-Peter Clausen <lars@metafoo.de>
31 #include <linux/iio/buffer-dmaengine.h>
47 * ad_sd_set_comm() - Set communications register
49 * @sigma_delta: The sigma delta device
56 sigma_delta->comm = comm & AD_SD_COMM_CHAN_MASK; in ad_sd_set_comm()
61 * ad_sd_write_reg() - Write a register
63 * @sigma_delta: The sigma delta device
65 * @size: Size of the register (0-3)
73 u8 *data = sigma_delta->tx_buf; in ad_sd_write_reg()
77 .cs_change = sigma_delta->keep_cs_asserted, in ad_sd_write_reg()
82 data[0] = (reg << sigma_delta->info->addr_shift) | sigma_delta->comm; in ad_sd_write_reg()
97 return -EINVAL; in ad_sd_write_reg()
103 if (sigma_delta->bus_locked) in ad_sd_write_reg()
104 ret = spi_sync_locked(sigma_delta->spi, &m); in ad_sd_write_reg()
106 ret = spi_sync(sigma_delta->spi, &m); in ad_sd_write_reg()
115 data[0] = reg << sigma_delta->info->addr_shift; in ad_sd_set_read_reg_addr()
116 data[0] |= sigma_delta->info->read_mask; in ad_sd_set_read_reg_addr()
117 data[0] |= sigma_delta->comm; in ad_sd_set_read_reg_addr()
123 u8 *data = sigma_delta->tx_buf; in ad_sd_read_reg_raw()
132 .cs_change = sigma_delta->keep_cs_asserted, in ad_sd_read_reg_raw()
139 if (sigma_delta->info->has_registers) { in ad_sd_read_reg_raw()
145 if (sigma_delta->bus_locked) in ad_sd_read_reg_raw()
146 ret = spi_sync_locked(sigma_delta->spi, &m); in ad_sd_read_reg_raw()
148 ret = spi_sync(sigma_delta->spi, &m); in ad_sd_read_reg_raw()
154 * ad_sd_read_reg() - Read a register
156 * @sigma_delta: The sigma delta device
158 * @size: Size of the register (1-4)
168 ret = ad_sd_read_reg_raw(sigma_delta, reg, size, sigma_delta->rx_buf); in ad_sd_read_reg()
174 *val = get_unaligned_be32(sigma_delta->rx_buf); in ad_sd_read_reg()
177 *val = get_unaligned_be24(sigma_delta->rx_buf); in ad_sd_read_reg()
180 *val = get_unaligned_be16(sigma_delta->rx_buf); in ad_sd_read_reg()
183 *val = sigma_delta->rx_buf[0]; in ad_sd_read_reg()
186 ret = -EINVAL; in ad_sd_read_reg()
196 * ad_sd_reset() - Reset the serial interface
198 * @sigma_delta: The sigma delta device
204 unsigned int reset_length = sigma_delta->info->num_resetclks; in ad_sd_reset()
212 return -ENOMEM; in ad_sd_reset()
215 ret = spi_write(sigma_delta->spi, buf, size); in ad_sd_reset()
224 guard(spinlock_irqsave)(&sigma_delta->irq_lock); in ad_sd_disable_irq()
227 if (sigma_delta->irq_dis) in ad_sd_disable_irq()
230 sigma_delta->irq_dis = true; in ad_sd_disable_irq()
231 disable_irq_nosync(sigma_delta->irq_line); in ad_sd_disable_irq()
237 guard(spinlock_irqsave)(&sigma_delta->irq_lock); in ad_sd_enable_irq()
239 sigma_delta->irq_dis = false; in ad_sd_enable_irq()
240 enable_irq(sigma_delta->irq_line); in ad_sd_enable_irq()
245 /* Called with `sigma_delta->bus_locked == true` only. */
249 unsigned int data_read_len = BITS_TO_BYTES(sigma_delta->info->num_resetclks); in ad_sigma_delta_clear_pending_event()
265 if (sigma_delta->rdy_gpiod) { in ad_sigma_delta_clear_pending_event()
266 pending_event = gpiod_get_value(sigma_delta->rdy_gpiod); in ad_sigma_delta_clear_pending_event()
293 return -ENOMEM; in ad_sigma_delta_clear_pending_event()
296 if (sigma_delta->info->has_registers) { in ad_sigma_delta_clear_pending_event()
297 unsigned int data_reg = sigma_delta->info->data_reg ?: AD_SD_REG_DATA; in ad_sigma_delta_clear_pending_event()
307 * `data_read_len - 1` bytes are less than $num_resetclks ones. in ad_sigma_delta_clear_pending_event()
311 memset(data + 2, 0xff, data_read_len - 1); in ad_sigma_delta_clear_pending_event()
314 ret = spi_sync_locked(sigma_delta->spi, &m); in ad_sigma_delta_clear_pending_event()
331 spi_bus_lock(sigma_delta->spi->controller); in ad_sd_calibrate()
332 sigma_delta->bus_locked = true; in ad_sd_calibrate()
333 sigma_delta->keep_cs_asserted = true; in ad_sd_calibrate()
334 reinit_completion(&sigma_delta->completion); in ad_sd_calibrate()
345 time_left = wait_for_completion_timeout(&sigma_delta->completion, 2 * HZ); in ad_sd_calibrate()
348 ret = -EIO; in ad_sd_calibrate()
353 sigma_delta->keep_cs_asserted = false; in ad_sd_calibrate()
356 sigma_delta->bus_locked = false; in ad_sd_calibrate()
357 spi_bus_unlock(sigma_delta->spi->controller); in ad_sd_calibrate()
364 * ad_sd_calibrate_all() - Performs channel calibration
365 * @sigma_delta: The sigma delta device
388 * ad_sigma_delta_single_conversion() - Performs a single data conversion
404 return -EBUSY; in ad_sigma_delta_single_conversion()
406 ret = ad_sigma_delta_set_channel(sigma_delta, chan->address); in ad_sigma_delta_single_conversion()
410 spi_bus_lock(sigma_delta->spi->controller); in ad_sigma_delta_single_conversion()
411 sigma_delta->bus_locked = true; in ad_sigma_delta_single_conversion()
412 sigma_delta->keep_cs_asserted = true; in ad_sigma_delta_single_conversion()
413 reinit_completion(&sigma_delta->completion); in ad_sigma_delta_single_conversion()
423 &sigma_delta->completion, HZ); in ad_sigma_delta_single_conversion()
426 ret = -EIO; in ad_sigma_delta_single_conversion()
430 if (sigma_delta->info->data_reg != 0) in ad_sigma_delta_single_conversion()
431 data_reg = sigma_delta->info->data_reg; in ad_sigma_delta_single_conversion()
436 BITS_TO_BYTES(chan->scan_type.realbits + chan->scan_type.shift), in ad_sigma_delta_single_conversion()
443 ad_sigma_delta_disable_one(sigma_delta, chan->address); in ad_sigma_delta_single_conversion()
446 sigma_delta->keep_cs_asserted = false; in ad_sigma_delta_single_conversion()
447 sigma_delta->bus_locked = false; in ad_sigma_delta_single_conversion()
448 spi_bus_unlock(sigma_delta->spi->controller); in ad_sigma_delta_single_conversion()
455 sample = raw_sample >> chan->scan_type.shift; in ad_sigma_delta_single_conversion()
456 sample &= (1 << chan->scan_type.realbits) - 1; in ad_sigma_delta_single_conversion()
470 const struct iio_scan_type *scan_type = &indio_dev->channels[0].scan_type; in ad_sd_buffer_postenable()
471 struct spi_transfer *xfer = sigma_delta->sample_xfer; in ad_sd_buffer_postenable()
476 if (sigma_delta->num_slots == 1) { in ad_sd_buffer_postenable()
477 channel = find_first_bit(indio_dev->active_scan_mask, in ad_sd_buffer_postenable()
480 indio_dev->channels[channel].address); in ad_sd_buffer_postenable()
487 * For sigma-delta sequencer drivers with multiple slots, an update_scan_mode in ad_sd_buffer_postenable()
492 sigma_delta->slots[slot] = indio_dev->channels[i].address; in ad_sd_buffer_postenable()
497 sigma_delta->active_slots = slot; in ad_sd_buffer_postenable()
498 sigma_delta->current_slot = 0; in ad_sd_buffer_postenable()
502 xfer[1].bits_per_word = scan_type->realbits; in ad_sd_buffer_postenable()
503 xfer[1].len = spi_bpw_to_bytes(scan_type->realbits); in ad_sd_buffer_postenable()
507 if (sigma_delta->active_slots > 1) { in ad_sd_buffer_postenable()
514 ALIGN(slot * BITS_TO_BYTES(scan_type->storagebits), in ad_sd_buffer_postenable()
517 samples_buf = devm_krealloc(&sigma_delta->spi->dev, in ad_sd_buffer_postenable()
518 sigma_delta->samples_buf, in ad_sd_buffer_postenable()
521 return -ENOMEM; in ad_sd_buffer_postenable()
523 sigma_delta->samples_buf = samples_buf; in ad_sd_buffer_postenable()
524 scan_size = BITS_TO_BYTES(scan_type->realbits + scan_type->shift); in ad_sd_buffer_postenable()
525 /* For 24-bit data, there is an extra byte of padding. */ in ad_sd_buffer_postenable()
526 xfer[1].rx_buf = &sigma_delta->rx_buf[scan_size == 3 ? 1 : 0]; in ad_sd_buffer_postenable()
527 xfer[1].len = scan_size + (sigma_delta->status_appended ? 1 : 0); in ad_sd_buffer_postenable()
531 if (sigma_delta->info->has_registers) { in ad_sd_buffer_postenable()
532 xfer[0].tx_buf = &sigma_delta->sample_addr; in ad_sd_buffer_postenable()
536 sigma_delta->info->data_reg ?: AD_SD_REG_DATA, in ad_sd_buffer_postenable()
537 &sigma_delta->sample_addr); in ad_sd_buffer_postenable()
538 spi_message_init_with_transfers(&sigma_delta->sample_msg, xfer, 2); in ad_sd_buffer_postenable()
540 spi_message_init_with_transfers(&sigma_delta->sample_msg, in ad_sd_buffer_postenable()
544 sigma_delta->sample_msg.offload = sigma_delta->offload; in ad_sd_buffer_postenable()
546 ret = spi_optimize_message(sigma_delta->spi, &sigma_delta->sample_msg); in ad_sd_buffer_postenable()
550 spi_bus_lock(sigma_delta->spi->controller); in ad_sd_buffer_postenable()
551 sigma_delta->bus_locked = true; in ad_sd_buffer_postenable()
552 sigma_delta->keep_cs_asserted = true; in ad_sd_buffer_postenable()
567 ret = spi_offload_trigger_enable(sigma_delta->offload, in ad_sd_buffer_postenable()
568 sigma_delta->offload_trigger, in ad_sd_buffer_postenable()
579 spi_bus_unlock(sigma_delta->spi->controller); in ad_sd_buffer_postenable()
580 spi_unoptimize_message(&sigma_delta->sample_msg); in ad_sd_buffer_postenable()
590 spi_offload_trigger_disable(sigma_delta->offload, in ad_sd_buffer_predisable()
591 sigma_delta->offload_trigger); in ad_sd_buffer_predisable()
593 reinit_completion(&sigma_delta->completion); in ad_sd_buffer_predisable()
594 wait_for_completion_timeout(&sigma_delta->completion, HZ); in ad_sd_buffer_predisable()
599 sigma_delta->keep_cs_asserted = false; in ad_sd_buffer_predisable()
602 if (sigma_delta->status_appended) in ad_sd_buffer_predisable()
606 sigma_delta->bus_locked = false; in ad_sd_buffer_predisable()
607 spi_bus_unlock(sigma_delta->spi->controller); in ad_sd_buffer_predisable()
608 spi_unoptimize_message(&sigma_delta->sample_msg); in ad_sd_buffer_predisable()
616 struct iio_dev *indio_dev = pf->indio_dev; in ad_sd_trigger_handler()
617 const struct iio_scan_type *scan_type = &indio_dev->channels[0].scan_type; in ad_sd_trigger_handler()
619 u8 *data = sigma_delta->rx_buf; in ad_sd_trigger_handler()
626 reg_size = BITS_TO_BYTES(scan_type->realbits + scan_type->shift); in ad_sd_trigger_handler()
627 /* For 24-bit data, there is an extra byte of padding. */ in ad_sd_trigger_handler()
630 ret = spi_sync_locked(sigma_delta->spi, &sigma_delta->sample_msg); in ad_sd_trigger_handler()
638 if (sigma_delta->active_slots == 1) { in ad_sd_trigger_handler()
639 iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp); in ad_sd_trigger_handler()
643 if (sigma_delta->status_appended) { in ad_sd_trigger_handler()
646 converted_channel = data[status_pos] & sigma_delta->info->status_ch_mask; in ad_sd_trigger_handler()
647 if (converted_channel != sigma_delta->slots[sigma_delta->current_slot]) { in ad_sd_trigger_handler()
653 sigma_delta->current_slot = 0; in ad_sd_trigger_handler()
658 sample_size = BITS_TO_BYTES(scan_type->storagebits); in ad_sd_trigger_handler()
659 sample_pos = sample_size * sigma_delta->current_slot; in ad_sd_trigger_handler()
660 memcpy(&sigma_delta->samples_buf[sample_pos], data, sample_size); in ad_sd_trigger_handler()
661 sigma_delta->current_slot++; in ad_sd_trigger_handler()
663 if (sigma_delta->current_slot == sigma_delta->active_slots) { in ad_sd_trigger_handler()
664 sigma_delta->current_slot = 0; in ad_sd_trigger_handler()
665 iio_push_to_buffers_with_timestamp(indio_dev, sigma_delta->samples_buf, in ad_sd_trigger_handler()
666 pf->timestamp); in ad_sd_trigger_handler()
670 iio_trigger_notify_done(indio_dev->trig); in ad_sd_trigger_handler()
680 return bitmap_weight(mask, iio_get_masklength(indio_dev)) <= sigma_delta->num_slots; in ad_sd_validate_scan_mask()
700 * off-limits as reading that would trigger another irq event. in ad_sd_data_rdy_trig_poll()
709 if ((!sigma_delta->rdy_gpiod || gpiod_get_value(sigma_delta->rdy_gpiod)) && in ad_sd_data_rdy_trig_poll()
711 complete(&sigma_delta->completion); in ad_sd_data_rdy_trig_poll()
712 if (sigma_delta->trig) in ad_sd_data_rdy_trig_poll()
713 iio_trigger_poll(sigma_delta->trig); in ad_sd_data_rdy_trig_poll()
722 * ad_sd_validate_trigger() - validate_trigger callback for ad_sigma_delta devices
727 * device, -EINVAL otherwise.
733 if (sigma_delta->trig != trig) in ad_sd_validate_trigger()
734 return -EINVAL; in ad_sd_validate_trigger()
743 unsigned long irq_flags = irq_get_trigger_type(sigma_delta->irq_line); in devm_ad_sd_probe_trigger()
746 init_completion(&sigma_delta->completion); in devm_ad_sd_probe_trigger()
748 sigma_delta->irq_dis = true; in devm_ad_sd_probe_trigger()
751 irq_set_status_flags(sigma_delta->irq_line, IRQ_DISABLE_UNLAZY); in devm_ad_sd_probe_trigger()
755 irq_flags = sigma_delta->info->irq_flags; in devm_ad_sd_probe_trigger()
757 ret = devm_request_irq(dev, sigma_delta->irq_line, in devm_ad_sd_probe_trigger()
760 indio_dev->name, in devm_ad_sd_probe_trigger()
766 sigma_delta->offload_trigger = in devm_ad_sd_probe_trigger()
767 devm_spi_offload_trigger_get(dev, sigma_delta->offload, in devm_ad_sd_probe_trigger()
769 if (IS_ERR(sigma_delta->offload_trigger)) in devm_ad_sd_probe_trigger()
770 return dev_err_probe(dev, PTR_ERR(sigma_delta->offload_trigger), in devm_ad_sd_probe_trigger()
773 if (dev != &sigma_delta->spi->dev) in devm_ad_sd_probe_trigger()
774 return dev_err_probe(dev, -EFAULT, in devm_ad_sd_probe_trigger()
776 dev_name(dev), dev_name(&sigma_delta->spi->dev)); in devm_ad_sd_probe_trigger()
778 sigma_delta->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", in devm_ad_sd_probe_trigger()
779 indio_dev->name, iio_device_id(indio_dev)); in devm_ad_sd_probe_trigger()
780 if (!sigma_delta->trig) in devm_ad_sd_probe_trigger()
781 return -ENOMEM; in devm_ad_sd_probe_trigger()
783 iio_trigger_set_drvdata(sigma_delta->trig, sigma_delta); in devm_ad_sd_probe_trigger()
785 ret = devm_iio_trigger_register(dev, sigma_delta->trig); in devm_ad_sd_probe_trigger()
790 indio_dev->trig = iio_trigger_get(sigma_delta->trig); in devm_ad_sd_probe_trigger()
797 * devm_ad_sd_setup_buffer_and_trigger() - Device-managed buffer & trigger setup
798 * @dev: Device object to which to bind the life-time of the resources attached
806 sigma_delta->slots = devm_kcalloc(dev, sigma_delta->num_slots, in devm_ad_sd_setup_buffer_and_trigger()
807 sizeof(*sigma_delta->slots), GFP_KERNEL); in devm_ad_sd_setup_buffer_and_trigger()
808 if (!sigma_delta->slots) in devm_ad_sd_setup_buffer_and_trigger()
809 return -ENOMEM; in devm_ad_sd_setup_buffer_and_trigger()
815 sigma_delta->offload); in devm_ad_sd_setup_buffer_and_trigger()
825 indio_dev->setup_ops = &ad_sd_buffer_setup_ops; in devm_ad_sd_setup_buffer_and_trigger()
840 * ad_sd_init() - Initializes a ad_sigma_delta struct
842 * @indio_dev: The IIO device which the Sigma Delta device is used for
852 sigma_delta->spi = spi; in ad_sd_init()
853 sigma_delta->info = info; in ad_sd_init()
856 if (!info->num_slots) in ad_sd_init()
857 sigma_delta->num_slots = 1; in ad_sd_init()
859 sigma_delta->num_slots = info->num_slots; in ad_sd_init()
861 if (sigma_delta->num_slots > 1) { in ad_sd_init()
862 if (!indio_dev->info->update_scan_mode) { in ad_sd_init()
863 dev_err(&spi->dev, "iio_dev lacks update_scan_mode().\n"); in ad_sd_init()
864 return -EINVAL; in ad_sd_init()
867 if (!info->disable_all) { in ad_sd_init()
868 dev_err(&spi->dev, "ad_sigma_delta_info lacks disable_all().\n"); in ad_sd_init()
869 return -EINVAL; in ad_sd_init()
873 spin_lock_init(&sigma_delta->irq_lock); in ad_sd_init()
875 if (info->has_named_irqs) { in ad_sd_init()
876 sigma_delta->irq_line = fwnode_irq_get_byname(dev_fwnode(&spi->dev), in ad_sd_init()
878 if (sigma_delta->irq_line < 0) in ad_sd_init()
879 return dev_err_probe(&spi->dev, sigma_delta->irq_line, in ad_sd_init()
882 sigma_delta->irq_line = spi->irq; in ad_sd_init()
885 sigma_delta->rdy_gpiod = devm_gpiod_get_optional(&spi->dev, "rdy", GPIOD_IN); in ad_sd_init()
886 if (IS_ERR(sigma_delta->rdy_gpiod)) in ad_sd_init()
887 return dev_err_probe(&spi->dev, PTR_ERR(sigma_delta->rdy_gpiod), in ad_sd_init()
890 if (sigma_delta->rdy_gpiod && !sigma_delta->irq_line) { in ad_sd_init()
891 sigma_delta->irq_line = gpiod_to_irq(sigma_delta->rdy_gpiod); in ad_sd_init()
892 if (sigma_delta->irq_line < 0) in ad_sd_init()
893 return sigma_delta->irq_line; in ad_sd_init()
896 if (info->supports_spi_offload) { in ad_sd_init()
903 sigma_delta->offload = devm_spi_offload_get(&spi->dev, spi, in ad_sd_init()
905 ret = PTR_ERR_OR_ZERO(sigma_delta->offload); in ad_sd_init()
906 if (ret && ret != -ENODEV) in ad_sd_init()
907 return dev_err_probe(&spi->dev, ret, "Failed to get SPI offload\n"); in ad_sd_init()
916 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
917 MODULE_DESCRIPTION("Analog Devices Sigma-Delta ADCs");