linux/drivers/staging/iio/meter/ade7758_ring.c
<<
>>
Prefs
   1/*
   2 * ADE7758 Poly Phase Multifunction Energy Metering IC driver
   3 *
   4 * Copyright 2010-2011 Analog Devices Inc.
   5 *
   6 * Licensed under the GPL-2.
   7 */
   8#include <linux/export.h>
   9#include <linux/interrupt.h>
  10#include <linux/kernel.h>
  11#include <linux/spi/spi.h>
  12#include <linux/slab.h>
  13#include <asm/unaligned.h>
  14
  15#include <linux/iio/iio.h>
  16#include <linux/iio/buffer.h>
  17#include <linux/iio/kfifo_buf.h>
  18#include <linux/iio/trigger_consumer.h>
  19#include "ade7758.h"
  20
  21/**
  22 * ade7758_spi_read_burst() - read data registers
  23 * @indio_dev: the IIO device
  24 **/
  25static int ade7758_spi_read_burst(struct iio_dev *indio_dev)
  26{
  27        struct ade7758_state *st = iio_priv(indio_dev);
  28        int ret;
  29
  30        ret = spi_sync(st->us, &st->ring_msg);
  31        if (ret)
  32                dev_err(&st->us->dev, "problem when reading WFORM value\n");
  33
  34        return ret;
  35}
  36
  37static int ade7758_write_waveform_type(struct device *dev, unsigned int type)
  38{
  39        int ret;
  40        u8 reg;
  41
  42        ret = ade7758_spi_read_reg_8(dev, ADE7758_WAVMODE, &reg);
  43        if (ret)
  44                goto out;
  45
  46        reg &= ~0x1F;
  47        reg |= type & 0x1F;
  48
  49        ret = ade7758_spi_write_reg_8(dev, ADE7758_WAVMODE, reg);
  50out:
  51        return ret;
  52}
  53
  54/* Whilst this makes a lot of calls to iio_sw_ring functions - it is too device
  55 * specific to be rolled into the core.
  56 */
  57static irqreturn_t ade7758_trigger_handler(int irq, void *p)
  58{
  59        struct iio_poll_func *pf = p;
  60        struct iio_dev *indio_dev = pf->indio_dev;
  61        struct ade7758_state *st = iio_priv(indio_dev);
  62        s64 dat64[2];
  63        u32 *dat32 = (u32 *)dat64;
  64
  65        if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
  66                if (ade7758_spi_read_burst(indio_dev) >= 0)
  67                        *dat32 = get_unaligned_be32(&st->rx_buf[5]) & 0xFFFFFF;
  68
  69        iio_push_to_buffers_with_timestamp(indio_dev, dat64, pf->timestamp);
  70
  71        iio_trigger_notify_done(indio_dev->trig);
  72
  73        return IRQ_HANDLED;
  74}
  75
  76/**
  77 * ade7758_ring_preenable() setup the parameters of the ring before enabling
  78 *
  79 * The complex nature of the setting of the number of bytes per datum is due
  80 * to this driver currently ensuring that the timestamp is stored at an 8
  81 * byte boundary.
  82 **/
  83static int ade7758_ring_preenable(struct iio_dev *indio_dev)
  84{
  85        unsigned int channel;
  86
  87        if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
  88                return -EINVAL;
  89
  90        channel = find_first_bit(indio_dev->active_scan_mask,
  91                                 indio_dev->masklength);
  92
  93        ade7758_write_waveform_type(&indio_dev->dev,
  94                                    indio_dev->channels[channel].address);
  95
  96        return 0;
  97}
  98
  99static const struct iio_buffer_setup_ops ade7758_ring_setup_ops = {
 100        .preenable = &ade7758_ring_preenable,
 101        .postenable = &iio_triggered_buffer_postenable,
 102        .predisable = &iio_triggered_buffer_predisable,
 103        .validate_scan_mask = &iio_validate_scan_mask_onehot,
 104};
 105
 106void ade7758_unconfigure_ring(struct iio_dev *indio_dev)
 107{
 108        iio_dealloc_pollfunc(indio_dev->pollfunc);
 109        iio_kfifo_free(indio_dev->buffer);
 110}
 111
 112int ade7758_configure_ring(struct iio_dev *indio_dev)
 113{
 114        struct ade7758_state *st = iio_priv(indio_dev);
 115        struct iio_buffer *buffer;
 116        int ret = 0;
 117
 118        buffer = iio_kfifo_allocate();
 119        if (!buffer)
 120                return -ENOMEM;
 121
 122        iio_device_attach_buffer(indio_dev, buffer);
 123
 124        indio_dev->setup_ops = &ade7758_ring_setup_ops;
 125
 126        indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
 127                                                 &ade7758_trigger_handler,
 128                                                 0,
 129                                                 indio_dev,
 130                                                 "ade7759_consumer%d",
 131                                                 indio_dev->id);
 132        if (!indio_dev->pollfunc) {
 133                ret = -ENOMEM;
 134                goto error_iio_kfifo_free;
 135        }
 136
 137        indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
 138
 139        st->tx_buf[0] = ADE7758_READ_REG(ADE7758_RSTATUS);
 140        st->tx_buf[1] = 0;
 141        st->tx_buf[2] = 0;
 142        st->tx_buf[3] = 0;
 143        st->tx_buf[4] = ADE7758_READ_REG(ADE7758_WFORM);
 144        st->tx_buf[5] = 0;
 145        st->tx_buf[6] = 0;
 146        st->tx_buf[7] = 0;
 147
 148        /* build spi ring message */
 149        st->ring_xfer[0].tx_buf = &st->tx_buf[0];
 150        st->ring_xfer[0].len = 1;
 151        st->ring_xfer[0].bits_per_word = 8;
 152        st->ring_xfer[0].delay_usecs = 4;
 153        st->ring_xfer[1].rx_buf = &st->rx_buf[1];
 154        st->ring_xfer[1].len = 3;
 155        st->ring_xfer[1].bits_per_word = 8;
 156        st->ring_xfer[1].cs_change = 1;
 157
 158        st->ring_xfer[2].tx_buf = &st->tx_buf[4];
 159        st->ring_xfer[2].len = 1;
 160        st->ring_xfer[2].bits_per_word = 8;
 161        st->ring_xfer[2].delay_usecs = 1;
 162        st->ring_xfer[3].rx_buf = &st->rx_buf[5];
 163        st->ring_xfer[3].len = 3;
 164        st->ring_xfer[3].bits_per_word = 8;
 165
 166        spi_message_init(&st->ring_msg);
 167        spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg);
 168        spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg);
 169        spi_message_add_tail(&st->ring_xfer[2], &st->ring_msg);
 170        spi_message_add_tail(&st->ring_xfer[3], &st->ring_msg);
 171
 172        return 0;
 173
 174error_iio_kfifo_free:
 175        iio_kfifo_free(indio_dev->buffer);
 176        return ret;
 177}
 178