fast spi driver development

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

I'm writing a driver for the TI ADS127x family of ADCs. The ads127x is a 24 bit samples, 4/8 channels, ADC, which can be clocked, using SPI, with up to 25 MHz. For what I've seen, I've followed a common approach within the IIO ADC drivers, but I can't get it to work at high frequencies.

I'm using the triggered buffers interface, with a RDY interrupt pin. The problem I have is with timings. When the ADC sends the data ready signal, my handler is called approximately 7µs later. This handler then calls spi_read to get 24 bytes (8 3 bytes samples) and the kernel takes a lot of time to read the SPI bus, actually, to *start* reading.

I would really appreciate some guidance on how to deal with this issue.
I can gladly send the code if someone wish to comment on it, I'm planning to free it once it's working anyway.

Below I've copied part of the code, which I think could be useful now.
The first function is passed to devm_request_irq, and the second one to iio_triggered_buffer_setup.


irqreturn_t ti_ads1x7x_interrupt(int irq, void *dev_id)
{
        struct iio_dev *indio_dev = dev_id;
        struct ti_ads1x7x_state *st = iio_priv(indio_dev);

        if (iio_buffer_enabled(indio_dev)) {
                iio_trigger_poll(st->trig);
        } else {
                complete(&st->completion);
        }

        return IRQ_HANDLED;
};


irqreturn_t ti_ads127x_trigger_handler(int irq, void *p)
{
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct ti_ads1x7x_state *st = iio_priv(indio_dev);
        int ret;
        int i;
        u8 b[24];

        ret = spi_read(st->spi, b, sizeof b);
        for_each_set_bit(i,
                         indio_dev->active_scan_mask,
                         indio_dev->masklength) {
st->data.samples[i] = (b[3 * i] << 16) | (b[3 * i + 1] << 8) | (b[3 * i + 2] << 0);
                if (ret)
                        goto ads127x_error_notify_done;
        }

        iio_push_to_buffers_with_timestamp(indio_dev,
                                           &st->data,
                                           pf->timestamp);

ads127x_error_notify_done:
        iio_trigger_notify_done(indio_dev->trig);
        return IRQ_HANDLED;
}

Thank you!



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux