Re: [PATCH] iio: impedance-analyzer: New driver for AD5933/4 Impedance Converter, Network Analyzer

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

 



On 07/28/11 16:19, Michael Hennerich wrote:
> On 07/28/2011 04:03 PM, Jonathan Cameron wrote:
>> On 07/28/11 12:32, michael.hennerich@xxxxxxxxxx wrote:
>>> From: Michael Hennerich<michael.hennerich@xxxxxxxxxx>
>>>
>>> The AD5933 is a high precision impedance converter system solution
>>> that combines an on-board frequency generator with a 12-bit, 1 MSPS,
>>> analog-to-digital converter (ADC). The frequency generator allows an
>>> external complex impedance to be excited with a known frequency.
>>>
>>> The response signal from the impedance is sampled by the on-board ADC
>>> and a discrete Fourier transform (DFT) is processed by an on-chip DSP engine.
>>> The DFT algorithm returns a real (R) and imaginary (I) data-word at each
>>> output frequency.
>>>
>> Mostly looks good. Couple of nitpicks / queries in line.  I'm particularly
>> bothered about the SCALE info elements in chan_spec that aren't matched
>> in the read_raw (or a write_raw if relevant).
> in0_real_raw and in0_imag_raw only exist as scan elements.
> They aren't present in indio_dev->channels. I therefore couldn't use
> scale info elements from channel spec.

Ah. I hadn't noticed that (obviously).  Why is this the case?  Does it just
not make sense to read them directly?  If so, set their channel number to -1
and they won't appear.  Hmm.  Perhaps we need to make that test a little
more refined to make this work.  iio_device_add_channel_sysfs drops the channel
immediately if it's number is negative.   Maybe move the magic value into channel2?

That way the only uggliness will come if we have a differential channel that only exists
for scans.  Or use a negative index (rather than just -1).  That's probably the cleanest
option, but will require a few abs() insertions in the code and some testing 
to make sure we got them all.

Something like:

diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index b49db92..aeeb5e6 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -480,7 +480,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
                        = kasprintf(GFP_KERNEL, "%s_%s%d_%s",
                                    iio_direction[chan->output],
                                    iio_chan_type_name_spec_shared[chan->type],
-                                   chan->channel,
+                                   (int)abs(chan->channel),
                                    full_postfix);
 
        if (name_format == NULL) {
@@ -489,7 +489,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
        }
        dev_attr->attr.name = kasprintf(GFP_KERNEL,
                                        name_format,
-                                       chan->channel,
+                                       (int)abs(chan->channel),
                                        chan->channel2);
        if (dev_attr->attr.name == NULL) {
                ret = -ENOMEM;
@@ -585,27 +585,27 @@ static int iio_device_add_channel_sysfs(struct iio_dev *dev_info,
 {
        int ret, i;
 
-       if (chan->channel < 0)
-               return 0;
-       if (chan->processed_val)
-               ret = __iio_add_chan_devattr("input", NULL, chan,
-                                            &iio_read_channel_info,
-                                            NULL,
-                                            0,
-                                            0,
-                                            &dev_info->dev,
-                                            &dev_info->channel_attr_list);
-       else
-               ret = __iio_add_chan_devattr("raw", NULL, chan,
-                                            &iio_read_channel_info,
-                                            (chan->output ?
-                                            &iio_write_channel_info : NULL),
-                                            0,
-                                            0,
-                                            &dev_info->dev,
-                                            &dev_info->channel_attr_list);
-       if (ret)
-               goto error_ret;
+       if (chan->channel >= 0) {
+               if (chan->processed_val)
+                       ret = __iio_add_chan_devattr("input", NULL, chan,
+                                                    &iio_read_channel_info,
+                                                    NULL,
+                                                    0,
+                                                    0,
+                                                    &dev_info->dev,
+                                                    &dev_info->channel_attr_list);
+               else
+                       ret = __iio_add_chan_devattr("raw", NULL, chan,
+                                                    &iio_read_channel_info,
+                                                    (chan->output ?
+                                                     &iio_write_channel_info : NULL),
+                                                    0,
+                                                    0,
+                                                    &dev_info->dev,
+                                                    &dev_info->channel_attr_list);
+               if (ret)
+                       goto error_ret;
+       }
 
        for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) {
                ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2],

> 
>> Jonathan
>>> Signed-off-by: Michael Hennerich<michael.hennerich@xxxxxxxxxx>
>>> ---
>>>   .../sysfs-bus-iio-impedance-analyzer-ad5933        |   30 +
>>>   drivers/staging/iio/Kconfig                        |    1 +
>>>   drivers/staging/iio/Makefile                       |    1 +
>>>   drivers/staging/iio/impedance-analyzer/Kconfig     |   16 +
>>>   drivers/staging/iio/impedance-analyzer/Makefile    |    5 +
>>>   drivers/staging/iio/impedance-analyzer/ad5933.c    |  815 ++++++++++++++++++++
>>>   drivers/staging/iio/impedance-analyzer/ad5933.h    |   28 +
>>>   7 files changed, 896 insertions(+), 0 deletions(-)
>>>   create mode 100644 drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933
>>>   create mode 100644 drivers/staging/iio/impedance-analyzer/Kconfig
>>>   create mode 100644 drivers/staging/iio/impedance-analyzer/Makefile
>>>   create mode 100644 drivers/staging/iio/impedance-analyzer/ad5933.c
>>>   create mode 100644 drivers/staging/iio/impedance-analyzer/ad5933.h
>>>
>>> diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933 b/drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933
>>> new file mode 100644
>>> index 0000000..798029a
>>> --- /dev/null
>>> +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933
>> Maybe keep in mind to move these to a general impedance-analyzer file the
>> moment we get a second one. + we can add these to chan spec masks if we get a few
>> users.
>>
>>> @@ -0,0 +1,30 @@
>>> +What:                /sys/bus/iio/devices/iio:deviceX/outY_freq_start
>>> +KernelVersion:       3.0.1
>>> +Contact:     linux-iio@xxxxxxxxxxxxxxx
>>> +Description:
>>> +             Frequency sweep start frequency in Hz.
>>> +
>>> +What:                /sys/bus/iio/devices/iio:deviceX/outY_freq_increment
>>> +KernelVersion:       3.0.1
>>> +Contact:     linux-iio@xxxxxxxxxxxxxxx
>>> +Description:
>>> +             Frequency increment in Hz (step size) between consecutive
>>> +             frequency points along the sweep.
>>> +
>>> +What:                /sys/bus/iio/devices/iio:deviceX/outY_freq_points
>>> +KernelVersion:       3.0.1
>>> +Contact:     linux-iio@xxxxxxxxxxxxxxx
>>> +Description:
>>> +             Number of frequency points (steps) in the frequency sweep.
>>> +             This value, in conjunction with the outY_freq_start and the
>>> +             outY_freq_increment, determines the frequency sweep range
>>> +             for the sweep operation.
>>> +
>>> +What:                /sys/bus/iio/devices/iio:deviceX/outY_settling_cycles
>>> +KernelVersion:       3.0.1
>>> +Contact:     linux-iio@xxxxxxxxxxxxxxx
>>> +Description:
>>> +             Number of output excitation cycles (settling time cycles)
>>> +             that are allowed to pass through the unknown impedance,
>>> +             after each frequency increment, and before the ADC is triggered
>>> +             to perform a conversion sequence of the response signal.
>>> diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig
>>> index d329635..7526567 100644
>>> --- a/drivers/staging/iio/Kconfig
>>> +++ b/drivers/staging/iio/Kconfig
>>> @@ -62,6 +62,7 @@ source "drivers/staging/iio/addac/Kconfig"
>>>   source "drivers/staging/iio/dac/Kconfig"
>>>   source "drivers/staging/iio/dds/Kconfig"
>>>   source "drivers/staging/iio/gyro/Kconfig"
>>> +source "drivers/staging/iio/impedance-analyzer/Kconfig"
>>>   source "drivers/staging/iio/imu/Kconfig"
>>>   source "drivers/staging/iio/light/Kconfig"
>>>   source "drivers/staging/iio/magnetometer/Kconfig"
>>> diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile
>>> index bb5c95c..eaff649 100644
>>> --- a/drivers/staging/iio/Makefile
>>> +++ b/drivers/staging/iio/Makefile
>>> @@ -16,6 +16,7 @@ obj-y += addac/
>>>   obj-y += dac/
>>>   obj-y += dds/
>>>   obj-y += gyro/
>>> +obj-y += impedance-analyzer/
>>>   obj-y += imu/
>>>   obj-y += light/
>>>   obj-y += magnetometer/
>>> diff --git a/drivers/staging/iio/impedance-analyzer/Kconfig b/drivers/staging/iio/impedance-analyzer/Kconfig
>>> new file mode 100644
>>> index 0000000..9e91a9b
>>> --- /dev/null
>>> +++ b/drivers/staging/iio/impedance-analyzer/Kconfig
>>> @@ -0,0 +1,16 @@
>>> +#
>>> +# Impedance Converter, Network Analyzer drivers
>>> +#
>>> +comment "Network Analyzer, Impedance Converters"
>>> +
>>> +config AD5933
>>> +     tristate "Analog Devices AD5933, AD5934 driver"
>>> +     depends on I2C
>>> +     select IIO_RING_BUFFER
>>> +     select IIO_SW_RING
>>> +     help
>>> +       Say yes here to build support for Analog Devices Impedance Converter,
>>> +       Network Analyzer, AD5933/4, provides direct access via sysfs.
>>> +
>>> +       To compile this driver as a module, choose M here: the
>>> +       module will be called ad5933.
>>> diff --git a/drivers/staging/iio/impedance-analyzer/Makefile b/drivers/staging/iio/impedance-analyzer/Makefile
>>> new file mode 100644
>>> index 0000000..7604d78
>>> --- /dev/null
>>> +++ b/drivers/staging/iio/impedance-analyzer/Makefile
>>> @@ -0,0 +1,5 @@
>>> +#
>>> +# Makefile for Impedance Converter, Network Analyzer drivers
>>> +#
>>> +
>>> +obj-$(CONFIG_AD5933) += ad5933.o
>>> diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
>>> new file mode 100644
>>> index 0000000..d43161b
>>> --- /dev/null
>>> +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
>>> @@ -0,0 +1,815 @@
>>> +/*
>>> + * AD5933 AD5934 Impedance Converter, Network Analyzer
>>> + *
>>> + * Copyright 2011 Analog Devices Inc.
>>> + *
>>> + * Licensed under the GPL-2.
>>> + */
>>> +
>>> +#include<linux/interrupt.h>
>>> +#include<linux/device.h>
>>> +#include<linux/kernel.h>
>>> +#include<linux/sysfs.h>
>>> +#include<linux/i2c.h>
>>> +#include<linux/regulator/consumer.h>
>>> +#include<linux/slab.h>
>>> +#include<linux/types.h>
>>> +#include<linux/err.h>
>>> +#include<linux/delay.h>
>>> +#include<asm/div64.h>
>>> +
>>> +#include "../iio.h"
>>> +#include "../sysfs.h"
>>> +#include "../ring_generic.h"
>>> +#include "../ring_sw.h"
>>> +
>>> +#include "ad5933.h"
>>> +
>>> +/* AD5933/AD5934 Registers */
>>> +#define AD5933_REG_CONTROL_HB                0x80    /* R/W, 2 bytes */
>>> +#define AD5933_REG_CONTROL_LB                0x81    /* R/W, 2 bytes */
>>> +#define AD5933_REG_FREQ_START                0x82    /* R/W, 3 bytes */
>>> +#define AD5933_REG_FREQ_INC          0x85    /* R/W, 3 bytes */
>>> +#define AD5933_REG_INC_NUM           0x88    /* R/W, 2 bytes, 9 bit */
>>> +#define AD5933_REG_SETTLING_CYCLES   0x8A    /* R/W, 2 bytes */
>>> +#define AD5933_REG_STATUS            0x8F    /* R, 1 byte */
>>> +#define AD5933_REG_TEMP_DATA         0x92    /* R, 2 bytes*/
>>> +#define AD5933_REG_REAL_DATA         0x94    /* R, 2 bytes*/
>>> +#define AD5933_REG_IMAG_DATA         0x96    /* R, 2 bytes*/
>>> +
>>> +/* AD5933_REG_CONTROL_HB Bits */
>>> +#define AD5933_CTRL_INIT_START_FREQ  (0x1<<  4)
>>> +#define AD5933_CTRL_START_SWEEP              (0x2<<  4)
>>> +#define AD5933_CTRL_INC_FREQ         (0x3<<  4)
>>> +#define AD5933_CTRL_REPEAT_FREQ              (0x4<<  4)
>>> +#define AD5933_CTRL_MEASURE_TEMP     (0x9<<  4)
>>> +#define AD5933_CTRL_POWER_DOWN               (0xA<<  4)
>>> +#define AD5933_CTRL_STANDBY          (0xB<<  4)
>>> +
>>> +#define AD5933_CTRL_RANGE_2000mVpp   (0x0<<  1)
>>> +#define AD5933_CTRL_RANGE_200mVpp    (0x1<<  1)
>>> +#define AD5933_CTRL_RANGE_400mVpp    (0x2<<  1)
>>> +#define AD5933_CTRL_RANGE_1000mVpp   (0x3<<  1)
>>> +#define AD5933_CTRL_RANGE(x)         ((x)<<  1)
>>> +
>>> +#define AD5933_CTRL_PGA_GAIN_1               (0x1<<  0)
>>> +#define AD5933_CTRL_PGA_GAIN_5               (0x0<<  0)
>>> +
>>> +/* AD5933_REG_CONTROL_LB Bits */
>>> +#define AD5933_CTRL_RESET            (0x1<<  4)
>>> +#define AD5933_CTRL_INT_SYSCLK               (0x0<<  3)
>>> +#define AD5933_CTRL_EXT_SYSCLK               (0x1<<  3)
>>> +
>>> +/* AD5933_REG_STATUS Bits */
>>> +#define AD5933_STAT_TEMP_VALID               (0x1<<  0)
>>> +#define AD5933_STAT_DATA_VALID               (0x1<<  1)
>>> +#define AD5933_STAT_SWEEP_DONE               (0x1<<  2)
>>> +
>>> +/* I2C Commands */
>> What are these?
> Those are special I2C block commands, but they didn't work
> as detailed in the datasheet. I therefore switched to
> single byte transfers. I can remove these defines.
Cool.  Or leave them and state they don't work. Might save
someone else some time in the future ;)
> 
>>> +#define AD5933_I2C_BLOCK_WRITE               0xA0
>>> +#define AD5933_I2C_BLOCK_READ                0xA1
>>> +#define AD5933_I2C_ADDR_POINTER              0xB0
>>> +
>>> +/* Device Specs */
>>> +#define AD5933_INT_OSC_FREQ_Hz               16776000
>>> +#define AD5933_MAX_OUTPUT_FREQ_Hz    100000
>>> +#define AD5933_MAX_RETRIES           100
>>> +
>>> +#define AD5933_OUT_RANGE             1
>>> +#define AD5933_OUT_RANGE_AVAIL               2
>>> +#define AD5933_OUT_SETTLING_CYCLES   3
>>> +#define AD5933_IN_PGA_GAIN           4
>>> +#define AD5933_IN_PGA_GAIN_AVAIL     5
>>> +#define AD5933_FREQ_POINTS           6
>>> +
>>> +#define AD5933_POLL_TIME_ms          10
>>> +#define AD5933_INIT_EXCITATION_TIME_ms       100
>>> +
>>> +struct ad5933_state {
>>> +     struct i2c_client               *client;
>>> +     struct regulator                *reg;
>>> +     struct ad5933_platform_data     *pdata;
>>> +     struct delayed_work             work;
>>> +     unsigned long                   mclk_hz;
>>> +     unsigned char                   ctrl_hb;
>>> +     unsigned char                   ctrl_lb;
>>> +     unsigned                        range_avail[4];
>>> +     unsigned short                  vref_mv;
>>> +     unsigned short                  settling_cycles;
>>> +     unsigned short                  freq_points;
>>> +     unsigned                        freq_start;
>>> +     unsigned                        freq_inc;
>>> +     unsigned                        state;
>>> +     unsigned                        poll_time_jiffies;
>>> +};
>>> +
>>> +struct ad5933_platform_data ad5933_default_pdata  = {
>>> +     .vref_mv = 3300,
>>> +};
>>> +
>>> +static struct iio_chan_spec ad5933_channels[] = {
>>> +     IIO_CHAN(IIO_TEMP, 0, 1, 1, NULL, 0, 0, 0,
>>> +              0, AD5933_REG_TEMP_DATA, IIO_ST('s', 14, 16, 0), 0),
>>> +     /* Ring Channels */
>>> +     IIO_CHAN(IIO_IN, 0, 1, 0, "real_raw", 0, 0,
>>> +              (1<<  IIO_CHAN_INFO_SCALE_SEPARATE),
>>> +              AD5933_REG_REAL_DATA, 0, IIO_ST('s', 16, 16, 0), 0),
>>> +     IIO_CHAN(IIO_IN, 0, 1, 0, "imag_raw", 0, 0,
>>> +              (1<<  IIO_CHAN_INFO_SCALE_SEPARATE),
>>> +              AD5933_REG_IMAG_DATA, 1, IIO_ST('s', 16, 16, 0), 0),
>>> +};
>> If those SCALE_SEPARATE elements aren't causing files to be created
>> and reads into the read_raw function then something nasty is going wrong...
> 
>      indio_dev->channels = ad5933_channels;
>      indio_dev->num_channels = 1;
> 
> :-)
Nasty.  Please add a comment here so people don't have to notice that!
> 
> 
>>> +
>>> +static int ad5933_i2c_write(struct i2c_client *client,
>>> +                           u8 reg, u8 len, u8 *data)
>>> +{
>>> +     int ret;
>>> +
>>> +     while (len--) {
>>> +             ret = i2c_smbus_write_byte_data(client, reg++, *data++);
>>> +             if (ret<  0) {
>>> +                     dev_err(&client->dev, "I2C write error\n");
>>> +                     return ret;
>>> +             }
>>> +     }
>>> +     return 0;
>>> +}
>>> +
>>> +static int ad5933_i2c_read(struct i2c_client *client,
>>> +                           u8 reg, u8 len, u8 *data)
>>> +{
>>> +     int ret;
>>> +
>>> +     while (len--) {
>>> +             ret = i2c_smbus_read_byte_data(client, reg++);
>>> +             if (ret<  0) {
>>> +                     dev_err(&client->dev, "I2C read error\n");
>>> +                     return ret;
>>> +             }
>>> +             *data++ = ret;
>>> +     }
>>> +     return 0;
>>> +}
>>> +
>>> +static int ad5933_cmd(struct ad5933_state *st, unsigned char cmd)
>>> +{
>>> +     unsigned char dat = st->ctrl_hb | cmd;
>>> +
>>> +     return ad5933_i2c_write(st->client,
>>> +                     AD5933_REG_CONTROL_HB, 1,&dat);
>>> +}
>>> +
>>> +static int ad5933_reset(struct ad5933_state *st)
>>> +{
>>> +     unsigned char dat = st->ctrl_lb | AD5933_CTRL_RESET;
>>> +     return ad5933_i2c_write(st->client,
>>> +                     AD5933_REG_CONTROL_LB, 1,&dat);
>>> +}
>>> +
>>> +static int ad5933_wait_busy(struct ad5933_state *st, unsigned char event)
>>> +{
>>> +     unsigned char val, timeout = AD5933_MAX_RETRIES;
>>> +     int ret;
>>> +
>>> +     while (timeout--) {
>>> +             ret =  ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1,&val);
>>> +             if (ret<  0)
>>> +                     return ret;
>>> +             if (val&  event)
>>> +                     return val;
>>> +             cpu_relax();
>>> +             mdelay(1);
>>> +     }
>>> +
>>> +     return -EAGAIN;
>>> +}
>>> +
>>> +static int ad5933_set_freq(struct ad5933_state *st,
>>> +                        unsigned reg, unsigned long freq)
>>> +{
>>> +     unsigned long long freqreg;
>>> +     u8 dat[3];
>>> +
>>> +     freqreg = (u64) freq * (u64) (1<<  27);
>>> +     do_div(freqreg, st->mclk_hz / 4);
>>> +
>>> +     switch (reg) {
>>> +     case AD5933_REG_FREQ_START:
>>> +             st->freq_start = freq;
>>> +             break;
>>> +     case AD5933_REG_FREQ_INC:
>>> +             st->freq_inc = freq;
>>> +             break;
>>> +     default:
>>> +             return -EINVAL;
>>> +     }
>>> +
>>> +     dat[0] = freqreg>>  16;
>>> +     dat[1] = freqreg>>  8;
>>> +     dat[2] = freqreg&  0xFF;
>>> +
>>> +     return ad5933_i2c_write(st->client, reg, 3, dat);
>>> +}
>>> +
>>> +static int ad5933_setup(struct ad5933_state *st)
>>> +{
>>> +     u8 dat[2];
>>> +     int ret;
>>> +
>>> +     ret = ad5933_reset(st);
>>> +     if (ret<  0)
>>> +             return ret;
>>> +
>>> +     ret = ad5933_set_freq(st, AD5933_REG_FREQ_START, 10000);
>>> +     if (ret<  0)
>>> +             return ret;
>>> +
>>> +     ret = ad5933_set_freq(st, AD5933_REG_FREQ_INC, 200);
>>> +     if (ret<  0)
>>> +             return ret;
>>> +
>>> +     st->settling_cycles = 10;
>>> +     dat[0] = st->settling_cycles>>  8;
>>> +     dat[1] = st->settling_cycles;
>>> +
>>> +     ret = ad5933_i2c_write(st->client,
>>> +                     AD5933_REG_SETTLING_CYCLES, 2, dat);
>>> +     if (ret<  0)
>>> +             return ret;
>>> +
>>> +     st->freq_points = 100;
>>> +     dat[0] = st->freq_points>>  8;
>>> +     dat[1] = st->freq_points;
>>> +
>>> +     return ad5933_i2c_write(st->client, AD5933_REG_INC_NUM, 2, dat);
>>> +}
>>> +
>>> +static void ad5933_calc_out_ranges(struct ad5933_state *st)
>>> +{
>>> +     int i;
>>> +     unsigned normalized_3v3[4] = {1980, 198, 383, 970};
>>> +
>>> +     for (i = 0; i<  4; i++)
>>> +             st->range_avail[i] = normalized_3v3[i] * st->vref_mv / 3300;
>>> +
>>> +}
>>> +
>>> +/*
>>> + * handles: AD5933_REG_FREQ_START and AD5933_REG_FREQ_INC
>>> + */
>>> +
>>> +static ssize_t ad5933_show_frequency(struct device *dev,
>>> +                                     struct device_attribute *attr,
>>> +                                     char *buf)
>>> +{
>>> +     struct iio_dev *dev_info = dev_get_drvdata(dev);
>>> +     struct ad5933_state *st = iio_priv(dev_info);
>>> +     struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
>>> +     int ret;
>>> +     unsigned long long freqreg;
>>> +     u8 dat[3];
>>> +
>>> +     mutex_lock(&dev_info->mlock);
>>> +     ret = ad5933_i2c_read(st->client, this_attr->address, 3, dat);
>>> +     mutex_unlock(&dev_info->mlock);
>>> +     if (ret<  0)
>>> +             return ret;
>>> +
>>> +     freqreg = dat[0]<<  16 | dat[1]<<  8 | dat[2];
>>> +
>>> +     freqreg = (u64) freqreg * (u64) (st->mclk_hz / 4);
>>> +     do_div(freqreg, 1<<  27);
>>> +
>>> +     return sprintf(buf, "%d\n", (int) freqreg);
>>> +}
>>> +
>>> +static ssize_t ad5933_store_frequency(struct device *dev,
>>> +                                      struct device_attribute *attr,
>>> +                                      const char *buf,
>>> +                                      size_t len)
>>> +{
>>> +     struct iio_dev *dev_info = dev_get_drvdata(dev);
>>> +     struct ad5933_state *st = iio_priv(dev_info);
>>> +     struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
>>> +     long val;
>>> +     int ret;
>>> +
>>> +     ret = strict_strtoul(buf, 10,&val);
>>> +     if (ret)
>>> +             return ret;
>>> +
>>> +     if (val>  AD5933_MAX_OUTPUT_FREQ_Hz)
>>> +             return -EINVAL;
>>> +
>>> +     mutex_lock(&dev_info->mlock);
>>> +     ret = ad5933_set_freq(st, this_attr->address, val);
>>> +     mutex_unlock(&dev_info->mlock);
>>> +
>>> +     return ret ? ret : len;
>>> +}
>>> +
>>> +static IIO_DEVICE_ATTR(out0_freq_start, S_IRUGO | S_IWUSR,
>>> +                     ad5933_show_frequency,
>>> +                     ad5933_store_frequency,
>>> +                     AD5933_REG_FREQ_START);
>>> +
>>> +static IIO_DEVICE_ATTR(out0_freq_increment, S_IRUGO | S_IWUSR,
>>> +                     ad5933_show_frequency,
>>> +                     ad5933_store_frequency,
>>> +                     AD5933_REG_FREQ_INC);
>>> +
>>> +static ssize_t ad5933_show(struct device *dev,
>>> +                                     struct device_attribute *attr,
>>> +                                     char *buf)
>>> +{
>>> +     struct iio_dev *dev_info = dev_get_drvdata(dev);
>>> +     struct ad5933_state *st = iio_priv(dev_info);
>>> +     struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
>>> +     int ret = 0, len = 0;
>>> +
>>> +     mutex_lock(&dev_info->mlock);
>>> +     switch (this_attr->address) {
>>> +     case AD5933_OUT_RANGE:
>>> +             len = sprintf(buf, "%d\n",
>>> +                           st->range_avail[(st->ctrl_hb>>  1)&  0x3]);
>>> +             break;
>>> +     case AD5933_OUT_RANGE_AVAIL:
>>> +             len = sprintf(buf, "%d %d %d %d\n", st->range_avail[0],
>>> +                           st->range_avail[3], st->range_avail[2],
>>> +                           st->range_avail[1]);
>>> +             break;
>>> +     case AD5933_OUT_SETTLING_CYCLES:
>>> +             len = sprintf(buf, "%d\n", st->settling_cycles);
>>> +             break;
>>> +     case AD5933_IN_PGA_GAIN:
>>> +             len = sprintf(buf, "%s\n",
>>> +                           (st->ctrl_hb&  AD5933_CTRL_PGA_GAIN_1) ?
>>> +                           "1" : "0.2");
>>> +             break;
>>> +     case AD5933_IN_PGA_GAIN_AVAIL:
>>> +             len = sprintf(buf, "1 0.2\n");
>>> +             break;
>>> +     case AD5933_FREQ_POINTS:
>>> +             len = sprintf(buf, "%d\n", st->freq_points);
>>> +             break;
>>> +     default:
>>> +             ret = -EINVAL;
>>> +     }
>>> +
>>> +     mutex_unlock(&dev_info->mlock);
>>> +     return ret ? ret : len;
>>> +}
>>> +
>>> +static ssize_t ad5933_store(struct device *dev,
>>> +                                      struct device_attribute *attr,
>>> +                                      const char *buf,
>>> +                                      size_t len)
>>> +{
>>> +     struct iio_dev *dev_info = dev_get_drvdata(dev);
>>> +     struct ad5933_state *st = iio_priv(dev_info);
>>> +     struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
>>> +     long val;
>>> +     int i, ret = 0;
>>> +     unsigned char dat[2];
>>> +
>>> +     if (this_attr->address != AD5933_IN_PGA_GAIN) {
>>> +             ret = strict_strtol(buf, 10,&val);
>>> +             if (ret)
>>> +                     return ret;
>>> +     }
>>> +
>>> +     mutex_lock(&dev_info->mlock);
>>> +     switch (this_attr->address) {
>>> +     case AD5933_OUT_RANGE:
>>> +             for (i = 0; i<  4; i++)
>>> +                     if (val == st->range_avail[i]) {
>>> +                             st->ctrl_hb&= ~AD5933_CTRL_RANGE(0x3);
>>> +                             st->ctrl_hb |= AD5933_CTRL_RANGE(i);
>>> +                             ret = ad5933_cmd(st, 0);
>>> +                             break;
>>> +                     }
>>> +             ret = -EINVAL;
>>> +             break;
>>> +     case AD5933_IN_PGA_GAIN:
>>> +             if (sysfs_streq(buf, "1")) {
>>> +                     st->ctrl_hb |= AD5933_CTRL_PGA_GAIN_1;
>>> +             } else if (sysfs_streq(buf, "0.2")) {
>>> +                     st->ctrl_hb&= ~AD5933_CTRL_PGA_GAIN_1;
>>> +             } else {
>>> +                     ret = -EINVAL;
>>> +                     break;
>>> +             }
>>> +             ret = ad5933_cmd(st, 0);
>>> +             break;
>>> +     case AD5933_OUT_SETTLING_CYCLES:
>>> +             val = clamp(val, 0L, 0x7FFL);
>>> +             st->settling_cycles = val;
>>> +
>>> +             /* 2x, 4x handling, see datasheet */
>>> +             if (val>  511)
>>> +                     val = (val>>  1) | (1<<  9);
>>> +             else if (val>  1022)
>>> +                     val = (val>>  2) | (3<<  9);
>>> +
>>> +             dat[0] = val>>  8;
>>> +             dat[1] = val;
>>> +
>>> +             ret = ad5933_i2c_write(st->client,
>>> +                             AD5933_REG_SETTLING_CYCLES, 2, dat);
>>> +             break;
>>> +     case AD5933_FREQ_POINTS:
>>> +             val = clamp(val, 0L, 511L);
>>> +             st->freq_points = val;
>>> +
>> Looks like an endian conversion to me.  Can we do this any slicker?
> Sure
>>> +             dat[0] = val>>  8;
>>> +             dat[1] = val;
>>> +
>>> +             ret = ad5933_i2c_write(st->client, AD5933_REG_INC_NUM, 2, dat);
>>> +             break;
>>> +     default:
>>> +             ret = -EINVAL;
>>> +     }
>>> +
>>> +     mutex_unlock(&dev_info->mlock);
>>> +     return ret ? ret : len;
>>> +}
>>> +
>>> +static IIO_DEVICE_ATTR(out0_scale, S_IRUGO | S_IWUSR,
>>> +                     ad5933_show,
>>> +                     ad5933_store,
>>> +                     AD5933_OUT_RANGE);
>>> +
>>> +static IIO_DEVICE_ATTR(out0_scale_available, S_IRUGO,
>>> +                     ad5933_show,
>>> +                     NULL,
>>> +                     AD5933_OUT_RANGE_AVAIL);
>>> +
>>> +static IIO_DEVICE_ATTR(in0_scale, S_IRUGO | S_IWUSR,
>>> +                     ad5933_show,
>>> +                     ad5933_store,
>>> +                     AD5933_IN_PGA_GAIN);
>>> +
>>> +static IIO_DEVICE_ATTR(in0_scale_available, S_IRUGO,
>>> +                     ad5933_show,
>>> +                     NULL,
>>> +                     AD5933_IN_PGA_GAIN_AVAIL);
>>> +
>>> +static IIO_DEVICE_ATTR(out0_freq_points, S_IRUGO | S_IWUSR,
>>> +                     ad5933_show,
>>> +                     ad5933_store,
>>> +                     AD5933_FREQ_POINTS);
>>> +
>>> +static IIO_DEVICE_ATTR(out0_settling_cycles, S_IRUGO | S_IWUSR,
>>> +                     ad5933_show,
>>> +                     ad5933_store,
>>> +                     AD5933_OUT_SETTLING_CYCLES);
>>> +
>>> +static struct attribute *ad5933_attributes[] = {
>>> +&iio_dev_attr_out0_scale.dev_attr.attr,
>>> +&iio_dev_attr_out0_scale_available.dev_attr.attr,
>>> +&iio_dev_attr_out0_freq_start.dev_attr.attr,
>>> +&iio_dev_attr_out0_freq_increment.dev_attr.attr,
>>> +&iio_dev_attr_out0_freq_points.dev_attr.attr,
>>> +&iio_dev_attr_out0_settling_cycles.dev_attr.attr,
>>> +&iio_dev_attr_in0_scale.dev_attr.attr,
>> Should be able to do the scale attributes via the chan_spec. Could also
>> add scale_available to that given it's pretty common.  The others
>> are one offs for now so probably best to leave them here.  Depends if you
>> have lots more of these drivers queued up!
>>> +&iio_dev_attr_in0_scale_available.dev_attr.attr,
>>> +     NULL
>>> +};
>>> +
>>> +static const struct attribute_group ad5933_attribute_group = {
>>> +     .attrs = ad5933_attributes,
>>> +};
>>> +
>>> +static int ad5933_read_raw(struct iio_dev *dev_info,
>>> +                        struct iio_chan_spec const *chan,
>>> +                        int *val,
>>> +                        int *val2,
>>> +                        long m)
>>> +{
>>> +     struct ad5933_state *st = iio_priv(dev_info);
>>> +     unsigned char dat[2];
>>> +     int ret = -EINVAL;
>>> +
>>> +     mutex_lock(&dev_info->mlock);
>>> +     switch (m) {
>>> +     case 0:
>>> +             if (iio_ring_enabled(dev_info)) {
>>> +                     ret = -EBUSY;
>>> +                     goto out;
>>> +             }
>>> +             ret = ad5933_cmd(st, AD5933_CTRL_MEASURE_TEMP);
>>> +             if (ret<  0)
>>> +                     goto out;
>>> +             ret = ad5933_wait_busy(st, AD5933_STAT_TEMP_VALID);
>>> +             if (ret<  0)
>>> +                     goto out;
>>> +
>>> +             ret = ad5933_i2c_read(st->client,
>>> +                             AD5933_REG_TEMP_DATA, 2,
>>> +                             dat);
>>> +             if (ret<  0)
>>> +                     goto out;
>>> +             mutex_unlock(&dev_info->mlock);
>>> +
>>> +             ret = dat[0]<<  8 | dat[1];
>>> +             /* Temp in Milli degrees Celsius */
>>> +             if (ret<  8192)
>>> +                     *val = ret * 1000 / 32;
>>> +             else
>>> +                     *val = (ret - 16384) * 1000 / 32;
>>> +
>>> +             return IIO_VAL_INT;
>>> +     }
>>> +
>>> +out:
>>> +     mutex_unlock(&dev_info->mlock);
>>> +     return ret;
>>> +}
>>> +
>>> +static const struct iio_info ad5933_info = {
>>> +     .read_raw =&ad5933_read_raw,
>>> +     .attrs =&ad5933_attribute_group,
>>> +     .driver_module = THIS_MODULE,
>>> +};
>>> +
>>> +static int ad5933_ring_preenable(struct iio_dev *indio_dev)
>>> +{
>>> +     struct ad5933_state *st = iio_priv(indio_dev);
>>> +     struct iio_ring_buffer *ring = indio_dev->ring;
>>> +     size_t d_size;
>>> +     int ret;
>>> +
>>> +     if (!ring->scan_count)
>>> +             return -EINVAL;
>>> +
>>> +     d_size = ring->scan_count *
>>> +              ad5933_channels[1].scan_type.storagebits / 8;
>>> +
>>> +     if (indio_dev->ring->access->set_bytes_per_datum)
>>> +             indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring,
>>> +                                                          d_size);
>>> +
>>> +     ret = ad5933_reset(st);
>>> +     if (ret<  0)
>>> +             return ret;
>>> +
>>> +     ret = ad5933_cmd(st, AD5933_CTRL_STANDBY);
>>> +     if (ret<  0)
>>> +             return ret;
>>> +
>>> +     ret = ad5933_cmd(st, AD5933_CTRL_INIT_START_FREQ);
>>> +     if (ret<  0)
>>> +             return ret;
>>> +
>>> +     st->state = AD5933_CTRL_INIT_START_FREQ;
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +static int ad5933_ring_postenable(struct iio_dev *indio_dev)
>>> +{
>>> +     struct ad5933_state *st = iio_priv(indio_dev);
>>> +
>>> +     /* AD5933_CTRL_INIT_START_FREQ:
>>> +      * High Q complex circuits require a long time to reach steady state.
>>> +      * To facilitate the measurement of such impedances, this mode allows
>>> +      * the user full control of the settling time requirement before
>>> +      * entering start frequency sweep mode where the impedance measurement
>>> +      * takes place. In this mode the impedance is excited with the
>>> +      * programmed start frequency (ad5933_ring_preenable),
>>> +      * but no measurement takes place.
>>> +      */
>>> +
>>> +     schedule_delayed_work(&st->work,
>>> +                           msecs_to_jiffies(AD5933_INIT_EXCITATION_TIME_ms));
>>> +     return 0;
>>> +}
>>> +
>>> +static int ad5933_ring_postdisable(struct iio_dev *indio_dev)
>>> +{
>>> +     struct ad5933_state *st = iio_priv(indio_dev);
>>> +
>>> +     cancel_delayed_work_sync(&st->work);
>>> +     return ad5933_cmd(st, AD5933_CTRL_POWER_DOWN);
>>> +}
>>> +
>>> +static const struct iio_ring_setup_ops ad5933_ring_setup_ops = {
>>> +     .preenable =&ad5933_ring_preenable,
>>> +     .postenable =&ad5933_ring_postenable,
>>> +     .postdisable =&ad5933_ring_postdisable,
>>> +};
>>> +
>>> +static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev)
>>> +{
>>> +     indio_dev->ring = iio_sw_rb_allocate(indio_dev);
>>> +     if (!indio_dev->ring)
>>> +             return -ENOMEM;
>>> +
>>> +     /* Effectively select the ring buffer implementation */
>>> +     indio_dev->ring->access =&ring_sw_access_funcs;
>>> +
>>> +     /* Ring buffer functions - here trigger setup related */
>>> +     indio_dev->ring->setup_ops =&ad5933_ring_setup_ops;
>>> +
>>> +     indio_dev->modes |= INDIO_RING_HARDWARE_BUFFER;
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +static void ad5933_work(struct work_struct *work)
>>> +{
>>> +     struct ad5933_state *st = container_of(work,
>>> +             struct ad5933_state, work.work);
>>> +     struct iio_dev *indio_dev = i2c_get_clientdata(st->client);
>>> +     struct iio_ring_buffer *ring = indio_dev->ring;
>>> +     signed short buf[2];
>>> +     unsigned char status;
>>> +
>>> +     mutex_lock(&indio_dev->mlock);
>>> +     if (st->state == AD5933_CTRL_INIT_START_FREQ) {
>>> +             /* start sweep */
>>> +             ad5933_cmd(st, AD5933_CTRL_START_SWEEP);
>>> +             st->state = AD5933_CTRL_START_SWEEP;
>>> +             schedule_delayed_work(&st->work, st->poll_time_jiffies);
>>> +             mutex_unlock(&indio_dev->mlock);
>>> +             return;
>>> +     }
>>> +
>>> +     ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1,&status);
>>> +
>>> +     if (status&  AD5933_STAT_DATA_VALID) {
>>> +             ad5933_i2c_read(st->client,
>> This will fall foul of the change to bitmap for these, but I'll fix that
>> up if this goes in first.
>>
>>> +                             (ring->scan_mask&  (1<<  0)) ?
>>> +                             AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA,
>>> +                             ring->scan_count * 2, (u8 *)buf);
>>> +
>>> +             if (ring->scan_count == 2) {
>>> +                     buf[0] = be16_to_cpu(buf[0]);
>>> +                     buf[1] = be16_to_cpu(buf[1]);
>>> +             } else {
>>> +                     buf[0] = be16_to_cpu(buf[0]);
>>> +             }
>>> +             /* save datum to the ring */
>>> +             ring->access->store_to(ring, (u8 *)buf, iio_get_time_ns());
>>> +     } else {
>>> +             /* no data available - try again later */
>>> +             schedule_delayed_work(&st->work, st->poll_time_jiffies);
>>> +             mutex_unlock(&indio_dev->mlock);
>>> +             return;
>>> +     }
>>> +
>>> +     if (status&  AD5933_STAT_SWEEP_DONE) {
>>> +             /* last sample received - power down do nothing until
>>> +              * the ring enable is toggled */
>>> +             ad5933_cmd(st, AD5933_CTRL_POWER_DOWN);
>>> +     } else {
>>> +             /* we just received a valid datum, move on to the next */
>>> +             ad5933_cmd(st, AD5933_CTRL_INC_FREQ);
>> Use st->poll_time_jiffies?  If not, please comment why not.
> Good catch.
>>> +             schedule_delayed_work(&st->work, msecs_to_jiffies(10));
>>> +     }
>>> +
>>> +     mutex_unlock(&indio_dev->mlock);
>>> +}
>>> +
>>> +static int __devinit ad5933_probe(struct i2c_client *client,
>>> +                                const struct i2c_device_id *id)
>>> +{
>>> +     int ret, regdone = 0, voltage_uv = 0;
>>> +     struct ad5933_platform_data *pdata = client->dev.platform_data;
>>> +     struct ad5933_state *st;
>>> +     struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));
>>> +     if (indio_dev == NULL)
>>> +             return -ENOMEM;
>>> +
>>> +     st = iio_priv(indio_dev);
>>> +     i2c_set_clientdata(client, indio_dev);
>>> +     st->client = client;
>>> +
>>> +     if (!pdata)
>>> +             st->pdata =&ad5933_default_pdata;
>>> +     else
>>> +             st->pdata = pdata;
>>> +
>>> +     st->reg = regulator_get(&client->dev, "vcc");
>>> +     if (!IS_ERR(st->reg)) {
>>> +             ret = regulator_enable(st->reg);
>>> +             if (ret)
>>> +                     goto error_put_reg;
>>> +             voltage_uv = regulator_get_voltage(st->reg);
>>> +     }
>>> +
>>> +     if (voltage_uv)
>>> +             st->vref_mv = voltage_uv / 1000;
>>> +     else
>>> +             st->vref_mv = st->pdata->vref_mv;
>>> +
>>> +     if (st->pdata->ext_clk_Hz) {
>>> +             st->mclk_hz = st->pdata->ext_clk_Hz;
>>> +             st->ctrl_lb = AD5933_CTRL_EXT_SYSCLK;
>>> +     } else {
>>> +             st->mclk_hz = AD5933_INT_OSC_FREQ_Hz;
>>> +             st->ctrl_lb = AD5933_CTRL_INT_SYSCLK;
>>> +     }
>>> +
>>> +     ad5933_calc_out_ranges(st);
>>> +     INIT_DELAYED_WORK(&st->work, ad5933_work);
>>> +     st->poll_time_jiffies = msecs_to_jiffies(AD5933_POLL_TIME_ms);
>>> +
>>> +     indio_dev->dev.parent =&client->dev;
>>> +     indio_dev->info =&ad5933_info;
>>> +     indio_dev->name = id->name;
>>> +     indio_dev->modes = INDIO_DIRECT_MODE;
>>> +     indio_dev->channels = ad5933_channels;
>>> +     indio_dev->num_channels = 1;
>>> +
>>> +     ret = ad5933_register_ring_funcs_and_init(indio_dev);
>>> +     if (ret)
>>> +             goto error_disable_reg;
>>> +
>>> +     ret = iio_device_register(indio_dev);
>>> +     if (ret)
>>> +             goto error_unreg_ring;
>>> +     regdone = 1;
>>> +
>>> +     ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
>>> +&ad5933_channels[1],
>>> +                                       2);
>>> +     if (ret)
>>> +             goto error_unreg_ring;
>>> +
>>> +     /* enable both REAL and IMAG channels by default */
>>> +     iio_scan_mask_set(indio_dev->ring, 0);
>>> +     iio_scan_mask_set(indio_dev->ring, 1);
>>> +
>>> +     ret = ad5933_setup(st);
>>> +     if (ret)
>>> +             goto error_uninitialize_ring;
>>> +
>>> +     return 0;
>>> +
>>> +error_uninitialize_ring:
>>> +     iio_ring_buffer_unregister(indio_dev->ring);
>>> +error_unreg_ring:
>>> +     iio_sw_rb_free(indio_dev->ring);
>>> +error_disable_reg:
>>> +     if (!IS_ERR(st->reg))
>>> +             regulator_disable(st->reg);
>>> +error_put_reg:
>>> +     if (!IS_ERR(st->reg))
>>> +             regulator_put(st->reg);
>>> +
>>> +     if (regdone)
>>> +             iio_device_unregister(indio_dev);
>>> +     else
>>> +             iio_free_device(indio_dev);
>>> +
>>> +     return ret;
>>> +}
>>> +
>>> +static __devexit int ad5933_remove(struct i2c_client *client)
>>> +{
>>> +     struct iio_dev *indio_dev = i2c_get_clientdata(client);
>>> +     struct ad5933_state *st = iio_priv(indio_dev);
>>> +
>>> +     iio_ring_buffer_unregister(indio_dev->ring);
>>> +     iio_sw_rb_free(indio_dev->ring);
>>> +     if (!IS_ERR(st->reg)) {
>>> +             regulator_disable(st->reg);
>>> +             regulator_put(st->reg);
>>> +     }
>>> +     iio_device_unregister(indio_dev);
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +static const struct i2c_device_id ad5933_id[] = {
>>> +     { "ad5933", 0 },
>>> +     { "ad5934", 0 },
>>> +     {}
>>> +};
>>> +
>>> +MODULE_DEVICE_TABLE(i2c, ad5933_id);
>>> +
>>> +static struct i2c_driver ad5933_driver = {
>>> +     .driver = {
>>> +             .name = "ad5933",
>>> +     },
>>> +     .probe = ad5933_probe,
>>> +     .remove = __devexit_p(ad5933_remove),
>>> +     .id_table = ad5933_id,
>>> +};
>>> +
>>> +static __init int ad5933_init(void)
>>> +{
>>> +     return i2c_add_driver(&ad5933_driver);
>>> +}
>>> +module_init(ad5933_init);
>>> +
>>> +static __exit void ad5933_exit(void)
>>> +{
>>> +     i2c_del_driver(&ad5933_driver);
>>> +}
>>> +module_exit(ad5933_exit);
>>> +
>>> +MODULE_AUTHOR("Michael Hennerich<hennerich@xxxxxxxxxxxxxxxxxxxx>");
>>> +MODULE_DESCRIPTION("Analog Devices AD5933 Impedance Conv. Network Analyzer");
>>> +MODULE_LICENSE("GPL v2");
>>> diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.h b/drivers/staging/iio/impedance-analyzer/ad5933.h
>>> new file mode 100644
>>> index 0000000..b140e42
>>> --- /dev/null
>>> +++ b/drivers/staging/iio/impedance-analyzer/ad5933.h
>>> @@ -0,0 +1,28 @@
>>> +/*
>>> + * AD5933 AD5934 Impedance Converter, Network Analyzer
>>> + *
>>> + * Copyright 2011 Analog Devices Inc.
>>> + *
>>> + * Licensed under the GPL-2.
>>> + */
>>> +
>>> +#ifndef IIO_ADC_AD5933_H_
>>> +#define IIO_ADC_AD5933_H_
>>> +
>>> +/*
>>> + * TODO: struct ad5933_platform_data needs to go into include/linux/iio
>>> + */
>>> +
>>> +/**
>>> + * struct ad5933_platform_data - platform specific data
>>> + * @ext_clk_Hz:              the external clock frequency in Hz, if not set
>>> + *                   the driver uses the internal clock (16.776 MHz)
>>> + * @vref_mv:         the external reference voltage in millivolt
>>> + */
>>> +
>>> +struct ad5933_platform_data {
>>> +     unsigned long                   ext_clk_Hz;
>>> +     unsigned short                  vref_mv;
>>> +};
>>> +
>>> +#endif /* IIO_ADC_AD5933_H_ */
>>
> 
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[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